MCPcopy Create free account
hub / github.com/Zoo-Code-Org/Zoo-Code / backoffAndAnnounce

Method backoffAndAnnounce

src/core/task/Task.ts:4386–4458  ·  view source on GitHub ↗
(retryAttempt: number, error: any)

Source from the content-addressed store, hash-verified

4384
4385 // Shared exponential backoff for retries (first-chunk and mid-stream)
4386 private async backoffAndAnnounce(retryAttempt: number, error: any): Promise<void> {
4387 try {
4388 const state = await this.providerRef.deref()?.getState()
4389 const baseDelay = state?.requestDelaySeconds || 5
4390
4391 let exponentialDelay = Math.min(
4392 Math.ceil(baseDelay * Math.pow(2, retryAttempt)),
4393 MAX_EXPONENTIAL_BACKOFF_SECONDS,
4394 )
4395
4396 // Respect provider rate limit window
4397 let rateLimitDelay = 0
4398 const rateLimit = (state?.apiConfiguration ?? this.apiConfiguration)?.rateLimitSeconds || 0
4399 const lastRequestTime = this.rateLimitClock.getLastRequestTime()
4400 if (lastRequestTime && rateLimit > 0) {
4401 const elapsed = performance.now() - lastRequestTime
4402 rateLimitDelay = Math.ceil(Math.min(rateLimit, Math.max(0, rateLimit * 1000 - elapsed) / 1000))
4403 }
4404
4405 // Prefer RetryInfo on 429 if present
4406 if (error?.status === 429) {
4407 const retryInfo = error?.errorDetails?.find(
4408 (d: any) => d["@type"] === "type.googleapis.com/google.rpc.RetryInfo",
4409 )
4410 const match = retryInfo?.retryDelay?.match?.(/^(\d+)s$/)
4411 if (match) {
4412 exponentialDelay = Number(match[1]) + 1
4413 }
4414 }
4415
4416 const finalDelay = Math.max(exponentialDelay, rateLimitDelay)
4417 if (finalDelay <= 0) {
4418 return
4419 }
4420
4421 // Build header text; fall back to error message if none provided
4422 let headerText
4423 if (error.status) {
4424 // Include both status code (for ChatRow parsing) and detailed message (for error details)
4425 // Format: "<status>\n<message>" allows ChatRow to extract status via parseInt(text.substring(0,3))
4426 // while preserving the full error message in errorDetails for debugging
4427 const errorMessage = error?.message || "Unknown error"
4428 headerText = `${error.status}\n${errorMessage}`
4429 } else if (error?.message) {
4430 headerText = error.message
4431 } else {
4432 headerText = "Unknown error"
4433 }
4434
4435 headerText = headerText ? `${headerText}\n` : ""
4436
4437 // Show countdown timer with exponential backoff
4438 for (let i = finalDelay; i > 0; i--) {
4439 // Check abort flag during countdown to allow early exit
4440 if (this.abort) {
4441 throw new Error(`[Task#${this.taskId}] Aborted during retry countdown`)
4442 }
4443

Callers 2

attemptApiRequestMethod · 0.95

Calls 5

sayMethod · 0.95
getLastRequestTimeMethod · 0.80
getStateMethod · 0.65
errorMethod · 0.65
StringInterface · 0.50

Tested by

no test coverage detected