File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -28,6 +28,7 @@ import {
2828import {
2929 getUsageCollector ,
3030 initUsageCollector ,
31+ tryGetUsageCollector ,
3132 type UsageCollectorHealth ,
3233} from "./usage-collector" ;
3334
@@ -108,11 +109,11 @@ export function initProxy(getStorePayloads: () => boolean): void {
108109}
109110
110111export async function drainUsageCollector ( ) : Promise < void > {
111- return getUsageCollector ( ) . drain ( ) ;
112+ return tryGetUsageCollector ( ) ? .drain ( ) ?? Promise . resolve ( ) ;
112113}
113114
114115export function getUsageCollectorHealth ( ) : UsageCollectorHealth {
115- return getUsageCollector ( ) . getHealth ( ) ;
116+ return tryGetUsageCollector ( ) ? .getHealth ( ) ?? { state : "ready" } ;
116117}
117118
118119// ===== MAIN HANDLER =====
Original file line number Diff line number Diff line change @@ -262,13 +262,12 @@ export async function forwardToClient(
262262 *********************************************************************/
263263 if ( ! response . body ) {
264264 if ( shouldProcessRequest ) {
265- const endMsg : EndMessage = {
265+ fireAndForgetEnd ( {
266266 type : "end" ,
267267 requestId,
268268 responseBody : null ,
269269 success : isExpectedResponse ( path , response ) ,
270- } ;
271- void getUsageCollector ( ) . handleEnd ( endMsg ) ;
270+ } ) ;
272271 }
273272
274273 return response ;
@@ -281,24 +280,22 @@ export async function forwardToClient(
281280 onClose ( buffered ) {
282281 if ( ! shouldProcessRequest ) return ;
283282 const cappedBuf = combineChunks ( buffered ) ;
284- const endMsg : EndMessage = {
283+ fireAndForgetEnd ( {
285284 type : "end" ,
286285 requestId,
287286 responseBody :
288287 cappedBuf . byteLength > 0 ? cappedBuf . toString ( "base64" ) : null ,
289288 success : isExpectedResponse ( path , response ) ,
290- } ;
291- void getUsageCollector ( ) . handleEnd ( endMsg ) ;
289+ } ) ;
292290 } ,
293291 onError ( err ) {
294292 if ( ! shouldProcessRequest ) return ;
295- const endMsg : EndMessage = {
293+ fireAndForgetEnd ( {
296294 type : "end" ,
297295 requestId,
298296 success : false ,
299297 error : err . message ,
300- } ;
301- void getUsageCollector ( ) . handleEnd ( endMsg ) ;
298+ } ) ;
302299 } ,
303300 } ) ;
304301
Original file line number Diff line number Diff line change @@ -110,7 +110,8 @@ function extractProjectFromRequest(startMessage: StartMessage): string | null {
110110 const sanitizedPath = sanitizeProjectName ( pathMatch ?. [ 1 ] ) ;
111111 if ( sanitizedPath ) return sanitizedPath ;
112112
113- const headingMatch = systemPrompt . match ( / ^ # \s + ( .+ ?) $ / m) ;
113+ // Mirror of the regex in proxy.ts (both cap output via sanitizeProjectName)
114+ const headingMatch = systemPrompt . match ( / ^ # \s + ( [ ^ \n \r ] { 1 , 100 } ) / m) ;
114115 if ( headingMatch ) {
115116 const heading = sanitizeProjectName ( headingMatch [ 1 ] ) ;
116117 if ( heading && ! heading . toLowerCase ( ) . startsWith ( "claude" ) ) {
@@ -1045,3 +1046,11 @@ export function getUsageCollector(): UsageCollector {
10451046 }
10461047 return _usageCollector ;
10471048}
1049+
1050+ /**
1051+ * Returns the singleton or null if not yet initialized.
1052+ * Use in shutdown / health paths where a pre-init call must be a no-op.
1053+ */
1054+ export function tryGetUsageCollector ( ) : UsageCollector | null {
1055+ return _usageCollector ;
1056+ }
You can’t perform that action at this time.
0 commit comments