MCPcopy Index your code
hub / github.com/anomalyco/opencode / retryable

Function retryable

packages/opencode/src/session/retry.ts:68–152  ·  view source on GitHub ↗
(error: Err, provider: string)

Source from the content-addressed store, hash-verified

66}
67
68export function retryable(error: Err, provider: string) {
69 // context overflow errors should not be retried
70 if (SessionV1.ContextOverflowError.isInstance(error)) return undefined
71 if (SessionV1.APIError.isInstance(error)) {
72 const status = error.data.statusCode
73 // 5xx errors are transient server failures and should always be retried,
74 // even when the provider SDK doesn't explicitly mark them as retryable.
75 if (!error.data.isRetryable && !(status !== undefined && status >= 500)) return undefined
76 if (error.data.responseBody?.includes("FreeUsageLimitError")) {
77 return {
78 message: GO_UPSELL_MESSAGE,
79 action: {
80 reason: "free_tier_limit",
81 provider,
82 title: "Free limit reached",
83 message: "Subscribe to OpenCode Go for reliable access to the best open-source models, starting at $5/month.",
84 label: "subscribe",
85 link: GO_UPSELL_URL,
86 },
87 }
88 }
89 if (error.data.responseBody?.includes("GoUsageLimitError")) {
90 const body = parseJSON(error.data.responseBody)
91 const workspace = str(body?.metadata?.workspace)
92 const limitName = str(body?.metadata?.limitName)
93 const retryAfter = num(error.data.responseHeaders?.["retry-after"])
94 const resetIn = iife(() => {
95 if (retryAfter === undefined) return ""
96 const seconds = Math.max(0, Math.ceil(retryAfter))
97 const days = Math.floor(seconds / 86_400)
98 const hours = Math.floor((seconds % 86_400) / 3_600)
99 const minutes = Math.ceil((seconds % 3_600) / 60)
100 const unit = (value: number, name: string) => `${value} ${name}${value === 1 ? "" : "s"}`
101
102 if (days > 0) return hours > 0 ? `${unit(days, "day")} ${unit(hours, "hour")}` : unit(days, "day")
103 if (hours > 0) return minutes > 0 ? `${unit(hours, "hour")} ${unit(minutes, "minute")}` : unit(hours, "hour")
104 return minutes > 0 ? unit(minutes, "minute") : "less than a minute"
105 })
106
107 const message = `${limitName ? `${limitName} usage limit` : "Usage limit"} reached. It will reset in ${resetIn}. To continue using this model now, enable usage from your available balance`
108
109 const link = `https://opencode.ai/workspace/${workspace}/go`
110 return {
111 message: `${message} - ${link}`,
112 action: {
113 reason: "account_rate_limit",
114 provider,
115 title: "Go limit reached",
116 message,
117 label: "open settings",
118 link,
119 },
120 }
121 }
122 return { message: error.data.message.includes("Overloaded") ? "Provider is overloaded" : error.data.message }
123 }
124
125 // Check for rate limit patterns in plain text error messages

Callers 1

policyFunction · 0.70

Calls 7

iifeFunction · 0.90
isRecordFunction · 0.90
parseJSONFunction · 0.85
strFunction · 0.85
unitFunction · 0.85
numFunction · 0.70
isInstanceMethod · 0.45

Tested by

no test coverage detected