Skip to content

Commit da38c3d

Browse files
chore(upstream): sync upstream dev
2 parents 773cc54 + 1f94d8a commit da38c3d

20 files changed

Lines changed: 46 additions & 151 deletions

File tree

packages/opencode/src/session/retry.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ export type Retryable = {
2525

2626
export const RETRY_INITIAL_DELAY = 2000
2727
export const RETRY_BACKOFF_FACTOR = 2
28+
export const RETRY_JITTER_FACTOR = 0.25
2829
export const RETRY_MAX_DELAY_NO_HEADERS = 30_000 // 30 seconds
2930
export const RETRY_MAX_DELAY = 2_147_483_647 // max 32-bit signed integer for setTimeout
31+
export const RETRY_MAX_RETRIES = 5
3032

3133
const RETRYABLE_MESSAGE_PATTERNS = [
3234
/429|500|502|503|504|524/i,
@@ -41,7 +43,7 @@ function cap(ms: number) {
4143
return Math.min(ms, RETRY_MAX_DELAY)
4244
}
4345

44-
export function delay(attempt: number, error?: SessionV1.APIError) {
46+
export function delay(attempt: number, error?: SessionV1.APIError, random = Math.random()) {
4547
if (error) {
4648
const headers = error.data.responseHeaders
4749
if (headers) {
@@ -67,11 +69,16 @@ export function delay(attempt: number, error?: SessionV1.APIError) {
6769
}
6870
}
6971

70-
return cap(RETRY_INITIAL_DELAY * Math.pow(RETRY_BACKOFF_FACTOR, attempt - 1))
72+
return cap(exponential(attempt, random))
7173
}
7274
}
7375

74-
return cap(Math.min(RETRY_INITIAL_DELAY * Math.pow(RETRY_BACKOFF_FACTOR, attempt - 1), RETRY_MAX_DELAY_NO_HEADERS))
76+
return cap(Math.min(exponential(attempt, random), RETRY_MAX_DELAY_NO_HEADERS))
77+
}
78+
79+
function exponential(attempt: number, random: number) {
80+
const base = RETRY_INITIAL_DELAY * Math.pow(RETRY_BACKOFF_FACTOR, attempt - 1)
81+
return Math.ceil(base + base * RETRY_JITTER_FACTOR * random)
7582
}
7683

7784
export function retryable(error: Err, provider: string) {
@@ -182,6 +189,7 @@ export function policy(opts: {
182189
const error = opts.parse(meta.input)
183190
const retry = retryable(error, opts.provider)
184191
if (!retry) return Cause.done(meta.attempt)
192+
if (meta.attempt > RETRY_MAX_RETRIES) return Cause.done(meta.attempt)
185193
return Effect.gen(function* () {
186194
const wait = delay(meta.attempt, SessionV1.APIError.isInstance(error) ? error : undefined)
187195
const now = yield* Clock.currentTimeMillis

packages/opencode/test/session/retry.test.ts

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,18 @@ function wrap(message: unknown): ReturnType<NamedError["toObject"]> {
3535
describe("session.retry.delay", () => {
3636
test("caps delay at 30 seconds when headers missing", () => {
3737
const error = apiError()
38-
const delays = Array.from({ length: 10 }, (_, index) => SessionRetry.delay(index + 1, error))
38+
const delays = Array.from({ length: 10 }, (_, index) => SessionRetry.delay(index + 1, error, 0))
3939
expect(delays).toStrictEqual([2000, 4000, 8000, 16000, 30000, 30000, 30000, 30000, 30000, 30000])
4040
})
4141

42+
test("adds jitter to exponential delays", () => {
43+
const error = apiError()
44+
expect(SessionRetry.delay(1, error, 0)).toBe(2000)
45+
expect(SessionRetry.delay(1, error, 1)).toBe(2500)
46+
expect(SessionRetry.delay(4, error, 1)).toBe(20000)
47+
expect(SessionRetry.delay(5, error, 1)).toBe(30000)
48+
})
49+
4250
test("prefers retry-after-ms when shorter than exponential", () => {
4351
const error = apiError({ "retry-after-ms": "1500" })
4452
expect(SessionRetry.delay(4, error)).toBe(1500)
@@ -59,18 +67,18 @@ describe("session.retry.delay", () => {
5967

6068
test("ignores invalid retry hints", () => {
6169
const error = apiError({ "retry-after": "not-a-number" })
62-
expect(SessionRetry.delay(1, error)).toBe(2000)
70+
expect(SessionRetry.delay(1, error, 0)).toBe(2000)
6371
})
6472

6573
test("ignores malformed date retry hints", () => {
6674
const error = apiError({ "retry-after": "Invalid Date String" })
67-
expect(SessionRetry.delay(1, error)).toBe(2000)
75+
expect(SessionRetry.delay(1, error, 0)).toBe(2000)
6876
})
6977

7078
test("ignores past date retry hints", () => {
7179
const pastDate = new Date(Date.now() - 5000).toUTCString()
7280
const error = apiError({ "retry-after": pastDate })
73-
expect(SessionRetry.delay(1, error)).toBe(2000)
81+
expect(SessionRetry.delay(1, error, 0)).toBe(2000)
7482
})
7583

7684
test("uses retry-after values even when exceeding 10 minutes with headers", () => {
@@ -115,6 +123,29 @@ describe("session.retry.delay", () => {
115123
})
116124
}),
117125
)
126+
127+
it.instance("policy stops after five retries", () =>
128+
Effect.gen(function* () {
129+
const attempts: number[] = []
130+
const error = apiError({ "retry-after-ms": "0" })
131+
const step = yield* Schedule.toStepWithMetadata(
132+
SessionRetry.policy({
133+
provider: "test",
134+
parse: Schema.decodeUnknownSync(SessionV1.APIError.Schema),
135+
set: (info) =>
136+
Effect.sync(() => {
137+
attempts.push(info.attempt)
138+
}),
139+
}),
140+
)
141+
142+
yield* Effect.forEach(Array.from({ length: SessionRetry.RETRY_MAX_RETRIES + 1 }), () =>
143+
Effect.ignore(step(error)),
144+
)
145+
146+
expect(attempts).toStrictEqual([1, 2, 3, 4, 5])
147+
}),
148+
)
118149
})
119150

120151
describe("session.retry.retryable", () => {

packages/web/src/content/docs/ar/zen.mdx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,6 @@ OpenCode Zen هي بوابة AI تتيح لك الوصول إلى هذه الن
113113
| Hy3 Free | hy3-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
114114
| Laguna S 2.1 Free | laguna-s-2.1-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
115115
| Ling-3.0-tiny Free | ling-3.0-tiny-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
116-
| LongCat-2.0 Free | longcat-2.0-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
117-
| North Mini Code Free | north-mini-code-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
118116
| Nemotron 3 Ultra Free | nemotron-3-ultra-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
119117
| Nemotron 3.5 Lightning Free | nemotron-3.5-lightning-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
120118
| DeepSeek V4 Flash Free | deepseek-v4-flash-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
@@ -145,8 +143,6 @@ https://opencode.ai/zen/v1/models
145143
| Hy3 Free | Free | Free | Free | - |
146144
| Laguna S 2.1 Free | Free | Free | Free | - |
147145
| Ling-3.0-tiny Free | Free | Free | Free | - |
148-
| LongCat-2.0 Free | Free | Free | Free | - |
149-
| North Mini Code Free | Free | Free | Free | - |
150146
| Nemotron 3 Ultra Free | Free | Free | Free | - |
151147
| Nemotron 3.5 Lightning Free | Free | Free | Free | - |
152148
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - |
@@ -224,8 +220,6 @@ https://opencode.ai/zen/v1/models
224220
- Hy3 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج.
225221
- Laguna S 2.1 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج.
226222
- Ling-3.0-tiny Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج.
227-
- LongCat-2.0 Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج.
228-
- North Mini Code Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج.
229223
- Nemotron 3 Ultra Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج.
230224
- Nemotron 3.5 Lightning Free متاح على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج.
231225
- Big Pickle نموذج خفي ومتاح مجانا على OpenCode لفترة محدودة. يستخدم الفريق هذه الفترة لجمع الملاحظات وتحسين النموذج.
@@ -285,8 +279,6 @@ https://opencode.ai/zen/v1/models
285279
- Hy3 Free: خلال فترته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج.
286280
- Laguna S 2.1 Free: خلال فترته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج.
287281
- Ling-3.0-tiny Free: خلال فترته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج.
288-
- LongCat-2.0 Free: خلال فترته المجانية، قد تُستخدم البيانات المجمعة لتحسين النموذج.
289-
- North Mini Code Free: خلال فترته المجانية، قد يُحتفَظ بالبيانات المُجمَّعة وتُستخدم لتحسين النموذج. لا تُرسل بيانات شخصية أو سرية. راجع [شروط الاستخدام](https://cohere.com/terms-of-use) و[سياسة الخصوصية](https://cohere.com/privacy).
290282
- Nemotron 3 Ultra Free (نقاط نهاية NVIDIA المجانية): للاستخدام التجريبي فقط — لا ترسل بيانات شخصية أو سرية. يُسجَّل استخدامك لأغراض أمنية ولتحسين منتجات وخدمات NVIDIA. بيانات الجلسة المُسجَّلة لأغراض التحسين غير مرتبطة بهويتك أو بأي مُعرِّف دائم. لمزيد من المعلومات حول ممارسات معالجة البيانات لدينا، راجع [سياسة الخصوصية](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf). بتفاعلك مع نقطة النهاية هذه، فإنك توافق على جمعنا لهذه المعلومات وتسجيلها واستخدامها وعلى [شروط خدمة النسخة التجريبية من واجهة NVIDIA API](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf).
291283
- Nemotron 3.5 Lightning Free (نقاط نهاية NVIDIA المجانية): للاستخدام التجريبي فقط — لا ترسل بيانات شخصية أو سرية. يُسجَّل استخدامك لأغراض أمنية ولتحسين منتجات وخدمات NVIDIA. بيانات الجلسة المُسجَّلة لأغراض التحسين غير مرتبطة بهويتك أو بأي مُعرِّف دائم. لمزيد من المعلومات حول ممارسات معالجة البيانات لدينا، راجع [سياسة الخصوصية](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf). بتفاعلك مع نقطة النهاية هذه، فإنك توافق على جمعنا لهذه المعلومات وتسجيلها واستخدامها وعلى [شروط خدمة النسخة التجريبية من واجهة NVIDIA API](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf).
292284
- OpenAI APIs: يتم الاحتفاظ بالطلبات لمدة 30 يوما وفقا لـ [OpenAI's Data Policies](https://platform.openai.com/docs/guides/your-data).

packages/web/src/content/docs/bs/zen.mdx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,6 @@ Našim modelima možete pristupiti i preko sljedećih API endpointa.
118118
| Hy3 Free | hy3-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
119119
| Laguna S 2.1 Free | laguna-s-2.1-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
120120
| Ling-3.0-tiny Free | ling-3.0-tiny-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
121-
| LongCat-2.0 Free | longcat-2.0-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
122-
| North Mini Code Free | north-mini-code-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
123121
| Nemotron 3 Ultra Free | nemotron-3-ultra-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
124122
| Nemotron 3.5 Lightning Free | nemotron-3.5-lightning-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
125123
| DeepSeek V4 Flash Free | deepseek-v4-flash-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
@@ -152,8 +150,6 @@ Podržavamo pay-as-you-go model. Ispod su cijene **po 1M tokena**.
152150
| Hy3 Free | Free | Free | Free | - |
153151
| Laguna S 2.1 Free | Free | Free | Free | - |
154152
| Ling-3.0-tiny Free | Free | Free | Free | - |
155-
| LongCat-2.0 Free | Free | Free | Free | - |
156-
| North Mini Code Free | Free | Free | Free | - |
157153
| Nemotron 3 Ultra Free | Free | Free | Free | - |
158154
| Nemotron 3.5 Lightning Free | Free | Free | Free | - |
159155
| MiniMax M3 | $0.30 | $1.20 | $0.06 | - |
@@ -231,8 +227,6 @@ Besplatni modeli:
231227
- Hy3 Free je dostupan na OpenCode ograničeno vrijeme. Tim koristi ovo vrijeme da prikupi povratne informacije i poboljša model.
232228
- Laguna S 2.1 Free je dostupan na OpenCode ograničeno vrijeme. Tim koristi ovo vrijeme da prikupi povratne informacije i poboljša model.
233229
- Ling-3.0-tiny Free je dostupan na OpenCode ograničeno vrijeme. Tim koristi ovo vrijeme da prikupi povratne informacije i poboljša model.
234-
- LongCat-2.0 Free je dostupan na OpenCode ograničeno vrijeme. Tim koristi ovo vrijeme da prikupi povratne informacije i poboljša model.
235-
- North Mini Code Free je dostupan na OpenCode ograničeno vrijeme. Tim koristi ovo vrijeme da prikupi povratne informacije i poboljša model.
236230
- Nemotron 3 Ultra Free je dostupan na OpenCode ograničeno vrijeme. Tim koristi ovo vrijeme da prikupi povratne informacije i poboljša model.
237231
- Nemotron 3.5 Lightning Free je dostupan na OpenCode ograničeno vrijeme. Tim koristi ovo vrijeme da prikupi povratne informacije i poboljša model.
238232
- Big Pickle je stealth model koji je besplatan na OpenCode ograničeno vrijeme. Tim koristi ovo vrijeme da prikupi povratne informacije i poboljša model.
@@ -297,8 +291,6 @@ i ne koriste vaše podatke za treniranje modela, uz sljedeće izuzetke:
297291
- Hy3 Free: Tokom besplatnog perioda, prikupljeni podaci mogu se koristiti za poboljšanje modela.
298292
- Laguna S 2.1 Free: Tokom besplatnog perioda, prikupljeni podaci mogu se koristiti za poboljšanje modela.
299293
- Ling-3.0-tiny Free: Tokom besplatnog perioda, prikupljeni podaci mogu se koristiti za poboljšanje modela.
300-
- LongCat-2.0 Free: Tokom besplatnog perioda, prikupljeni podaci mogu se koristiti za poboljšanje modela.
301-
- North Mini Code Free: Tokom besplatnog perioda, prikupljeni podaci mogu biti zadržani i korišteni za poboljšanje modela. Nemojte slati lične ili povjerljive podatke. Pogledajte naše [Uslove korištenja](https://cohere.com/terms-of-use) i [Politiku privatnosti](https://cohere.com/privacy).
302294
- Nemotron 3 Ultra Free (besplatni NVIDIA endpointi): Samo za probnu upotrebu — nemojte slati lične ili povjerljive podatke. Vaše korištenje se bilježi radi sigurnosti i poboljšanja NVIDIA proizvoda i usluga. Zabilježeni podaci sesije koji se koriste u svrhu poboljšanja nisu povezani s vašim identitetom niti bilo kojim trajnim identifikatorom. Za više informacija o našim praksama obrade podataka pogledajte našu [Politiku privatnosti](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf). Interakcijom s ovim endpointom pristajete na naše prikupljanje, bilježenje i korištenje takvih informacija te na [NVIDIA API Trial Terms of Service](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf).
303295
- Nemotron 3.5 Lightning Free (besplatni NVIDIA endpointi): Samo za probnu upotrebu — nemojte slati lične ili povjerljive podatke. Vaše korištenje se bilježi radi sigurnosti i poboljšanja NVIDIA proizvoda i usluga. Zabilježeni podaci sesije koji se koriste u svrhu poboljšanja nisu povezani s vašim identitetom niti bilo kojim trajnim identifikatorom. Za više informacija o našim praksama obrade podataka pogledajte našu [Politiku privatnosti](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf). Interakcijom s ovim endpointom pristajete na naše prikupljanje, bilježenje i korištenje takvih informacija te na [NVIDIA API Trial Terms of Service](https://assets.ngc.nvidia.com/products/api-catalog/legal/NVIDIA%20API%20Trial%20Terms%20of%20Service.pdf).
304296
- OpenAI APIs: Requests are retained for 30 days in accordance with [OpenAI's Data Policies](https://platform.openai.com/docs/guides/your-data).

0 commit comments

Comments
 (0)