* Re-acquire a hosted key after upstream-429 retries have been exhausted. Calls * `acquireKey` (which now blocks on the per-workspace bucket) and re-injects the * fresh key into `params`. Returns false if no key could be obtained — caller * should re-throw the original upstream 429. * * Does no
( tool: ToolConfig, params: Record<string, unknown>, executionContext: ExecutionContext | undefined, requestId: string )
| 328 | * branch of `executeTool`, so BYOK has already been ruled out for this call. |
| 329 | */ |
| 330 | async function reacquireHostedKey( |
| 331 | tool: ToolConfig, |
| 332 | params: Record<string, unknown>, |
| 333 | executionContext: ExecutionContext | undefined, |
| 334 | requestId: string |
| 335 | ): Promise<string | null> { |
| 336 | if (!tool.hosting) return null |
| 337 | const { envKeyPrefix, apiKeyParam, byokProviderId, rateLimit } = tool.hosting |
| 338 | const { workspaceId } = resolveToolScope(params, executionContext) |
| 339 | if (!workspaceId) return null |
| 340 | |
| 341 | const provider = byokProviderId || tool.id |
| 342 | const acquireResult = await getHostedKeyRateLimiter().acquireKey( |
| 343 | provider, |
| 344 | envKeyPrefix, |
| 345 | rateLimit, |
| 346 | workspaceId, |
| 347 | executionContext?.abortSignal |
| 348 | ) |
| 349 | |
| 350 | if (!acquireResult.success || !acquireResult.key) { |
| 351 | logger.warn( |
| 352 | `[${requestId}] Re-acquire of hosted key for ${tool.id} failed: ${acquireResult.error ?? 'unknown'}` |
| 353 | ) |
| 354 | return null |
| 355 | } |
| 356 | |
| 357 | params[apiKeyParam] = acquireResult.key |
| 358 | logger.info( |
| 359 | `[${requestId}] Re-acquired hosted key for ${tool.id} (${acquireResult.envVarName}) after upstream throttling` |
| 360 | ) |
| 361 | return acquireResult.envVarName ?? 'unknown' |
| 362 | } |
| 363 | |
| 364 | /** |
| 365 | * Check if an error is a rate limit (throttling) or quota exhaustion error. |
no test coverage detected