@@ -334,11 +334,11 @@ async function reacquireHostedKey(
334334 params : Record < string , unknown > ,
335335 executionContext : ExecutionContext | undefined ,
336336 requestId : string
337- ) : Promise < boolean > {
338- if ( ! tool . hosting ) return false
337+ ) : Promise < string | null > {
338+ if ( ! tool . hosting ) return null
339339 const { envKeyPrefix, apiKeyParam, byokProviderId, rateLimit } = tool . hosting
340340 const { workspaceId } = resolveToolScope ( params , executionContext )
341- if ( ! workspaceId ) return false
341+ if ( ! workspaceId ) return null
342342
343343 const provider = byokProviderId || tool . id
344344 const acquireResult = await getHostedKeyRateLimiter ( ) . acquireKey (
@@ -353,14 +353,14 @@ async function reacquireHostedKey(
353353 logger . warn (
354354 `[${ requestId } ] Re-acquire of hosted key for ${ tool . id } failed: ${ acquireResult . error ?? 'unknown' } `
355355 )
356- return false
356+ return null
357357 }
358358
359359 params [ apiKeyParam ] = acquireResult . key
360360 logger . info (
361361 `[${ requestId } ] Re-acquired hosted key for ${ tool . id } (${ acquireResult . envVarName } ) after upstream throttling`
362362 )
363- return true
363+ return acquireResult . envVarName ?? 'unknown'
364364}
365365
366366/**
@@ -383,11 +383,19 @@ function isRateLimitError(error: unknown): boolean {
383383 return false
384384}
385385
386- /** Map a thrown tool error to a hosted-key failure reason for metrics. */
386+ /**
387+ * Map a thrown tool error to a hosted-key failure reason for metrics. Mirrors
388+ * `isRateLimitError`: some providers signal quota/rate-limit via 401/403 with a
389+ * descriptive message, so those count as `rate_limited`, not `auth`.
390+ */
387391function classifyHostedKeyFailure ( error : unknown ) : 'rate_limited' | 'auth' | 'other' {
388392 const status = ( error as { status ?: number } | null ) ?. status
389393 if ( status === 429 || status === 503 ) return 'rate_limited'
390- if ( status === 401 || status === 403 ) return 'auth'
394+ if ( status === 401 || status === 403 ) {
395+ const message = ( ( error as { message ?: string } | null ) ?. message ?? '' ) . toLowerCase ( )
396+ if ( message . includes ( 'quota' ) || message . includes ( 'rate limit' ) ) return 'rate_limited'
397+ return 'auth'
398+ }
391399 return 'other'
392400}
393401
@@ -1178,6 +1186,8 @@ export async function executeTool(
11781186 requestId ,
11791187 hostedKeyInfo . envVarName
11801188 )
1189+ } else if ( hostedKeyForMetrics ) {
1190+ hostedKeyMetrics . recordFailed ( { ...hostedKeyForMetrics , reason : 'other' } )
11811191 }
11821192
11831193 const strippedOutput = postProcessToolOutput ( normalizedToolId , finalResult . output ?? { } )
@@ -1202,13 +1212,16 @@ export async function executeTool(
12021212 envVarName : hostedKeyInfo . envVarName ! ,
12031213 executionContext,
12041214 reacquireAfterRetriesExhausted : async ( ) => {
1205- const reacquired = await reacquireHostedKey (
1215+ const reacquiredEnvVar = await reacquireHostedKey (
12061216 tool ,
12071217 contextParams ,
12081218 executionContext ,
12091219 requestId
12101220 )
1211- if ( ! reacquired ) return null
1221+ if ( ! reacquiredEnvVar ) return null
1222+ // Re-point metric labels at the freshly acquired key.
1223+ hostedKeyInfo . envVarName = reacquiredEnvVar
1224+ if ( hostedKeyForMetrics ) hostedKeyForMetrics . key = reacquiredEnvVar
12121225 return ( ) => executeToolRequest ( toolId , tool , contextParams )
12131226 } ,
12141227 } )
@@ -1244,6 +1257,8 @@ export async function executeTool(
12441257 requestId ,
12451258 hostedKeyInfo . envVarName
12461259 )
1260+ } else if ( hostedKeyForMetrics ) {
1261+ hostedKeyMetrics . recordFailed ( { ...hostedKeyForMetrics , reason : 'other' } )
12471262 }
12481263
12491264 const strippedOutput = postProcessToolOutput ( normalizedToolId , finalResult . output ?? { } )
0 commit comments