@opencode/ai 2.0.17 → 2.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -12
- package/dist/cache-policy.js +1 -0
- package/dist/experimental/evaluation.d.ts +7 -0
- package/dist/experimental/evaluation.js +2 -0
- package/dist/experimental/system-one.js +10 -7
- package/dist/generation.d.ts +1 -1
- package/dist/generation.js +23 -18
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/promise.d.ts +1 -1
- package/dist/promise.js +4 -3
- package/dist/protocols/alibaba-chat.d.ts +8 -2
- package/dist/protocols/deepgram-speech.js +9 -7
- package/dist/protocols/deepgram-transcription.js +4 -10
- package/dist/protocols/elevenlabs-transcription.d.ts +28 -0
- package/dist/protocols/elevenlabs-transcription.js +137 -0
- package/dist/protocols/gemini.js +1 -10
- package/dist/protocols/google-speech.js +9 -2
- package/dist/protocols/google-transcription.js +4 -0
- package/dist/protocols/google-video.js +11 -2
- package/dist/protocols/openai-chat.d.ts +53 -10
- package/dist/protocols/openai-chat.js +21 -8
- package/dist/protocols/openai-compatible-chat.d.ts +7 -2
- package/dist/protocols/openai-speech.js +6 -1
- package/dist/protocols/openai-transcription.js +1 -1
- package/dist/protocols/runway-video.js +2 -1
- package/dist/protocols/utils/gemini-generate-content.d.ts +6 -0
- package/dist/protocols/utils/gemini-generate-content.js +33 -0
- package/dist/protocols/utils/media-input.d.ts +4 -3
- package/dist/protocols/utils/media-input.js +5 -4
- package/dist/protocols/utils/speaker-turns.d.ts +3 -0
- package/dist/protocols/utils/speaker-turns.js +9 -0
- package/dist/protocols/utils/speech-stream.d.ts +1 -0
- package/dist/protocols/utils/speech-stream.js +1 -0
- package/dist/protocols/utils/tool-stream.d.ts +1 -0
- package/dist/protocols/utils/tool-stream.js +1 -1
- package/dist/protocols/xai-video.js +7 -1
- package/dist/protocols/zai-chat.d.ts +8 -2
- package/dist/provider-error.d.ts +5 -0
- package/dist/provider-error.js +46 -1
- package/dist/providers/alibaba.d.ts +7 -2
- package/dist/providers/amazon-bedrock-mantle.d.ts +7 -2
- package/dist/providers/anthropic-compatible.js +3 -2
- package/dist/providers/azure.d.ts +7 -2
- package/dist/providers/baseten.d.ts +14 -4
- package/dist/providers/cerebras.d.ts +14 -4
- package/dist/providers/cloudflare-ai-gateway.d.ts +14 -4
- package/dist/providers/cloudflare-workers-ai.d.ts +14 -4
- package/dist/providers/deepinfra.d.ts +14 -4
- package/dist/providers/deepseek.d.ts +14 -4
- package/dist/providers/elevenlabs.d.ts +5 -0
- package/dist/providers/elevenlabs.js +4 -0
- package/dist/providers/fireworks.d.ts +14 -4
- package/dist/providers/google-vertex-chat.d.ts +7 -2
- package/dist/providers/groq.d.ts +15 -4
- package/dist/providers/meta.d.ts +7 -2
- package/dist/providers/minimax.d.ts +7 -2
- package/dist/providers/moonshot.d.ts +7 -2
- package/dist/providers/openai-compatible.d.ts +7 -2
- package/dist/providers/openai.d.ts +7 -2
- package/dist/providers/openrouter.d.ts +27 -6
- package/dist/providers/togetherai.d.ts +14 -4
- package/dist/providers/xai.d.ts +7 -2
- package/dist/providers/xai.js +3 -3
- package/dist/providers/zai-coding-plan.d.ts +7 -2
- package/dist/providers/zai.d.ts +7 -2
- package/dist/route/media-protocol.d.ts +13 -3
- package/dist/route/media-protocol.js +16 -6
- package/dist/route/media.js +18 -4
- package/dist/transcription.d.ts +1 -1
- package/dist/transcription.js +1 -1
- package/package.json +3 -3
|
@@ -141,6 +141,11 @@ declare const OpenRouterBody: Schema.StructWithRest<Schema.Struct<{
|
|
|
141
141
|
readonly name: Schema.String;
|
|
142
142
|
readonly arguments: Schema.String;
|
|
143
143
|
}>;
|
|
144
|
+
readonly extra_content: Schema.optional<Schema.Struct<{
|
|
145
|
+
readonly google: Schema.Struct<{
|
|
146
|
+
readonly thought_signature: Schema.String;
|
|
147
|
+
}>;
|
|
148
|
+
}>>;
|
|
144
149
|
}>>>;
|
|
145
150
|
readonly reasoning_content: Schema.optional<Schema.String>;
|
|
146
151
|
readonly reasoning: Schema.optional<Schema.String>;
|
|
@@ -253,12 +258,17 @@ export declare const protocol: Protocol<{
|
|
|
253
258
|
readonly ttl?: string | undefined;
|
|
254
259
|
} | undefined;
|
|
255
260
|
readonly tool_calls?: readonly {
|
|
256
|
-
readonly id: string;
|
|
257
|
-
readonly type: "function";
|
|
258
261
|
readonly function: {
|
|
259
262
|
readonly name: string;
|
|
260
263
|
readonly arguments: string;
|
|
261
264
|
};
|
|
265
|
+
readonly id: string;
|
|
266
|
+
readonly type: "function";
|
|
267
|
+
readonly extra_content?: {
|
|
268
|
+
readonly google: {
|
|
269
|
+
readonly thought_signature: string;
|
|
270
|
+
};
|
|
271
|
+
} | undefined;
|
|
262
272
|
}[] | undefined;
|
|
263
273
|
readonly reasoning_details?: unknown;
|
|
264
274
|
} | {
|
|
@@ -349,6 +359,7 @@ export declare const protocol: Protocol<{
|
|
|
349
359
|
} | null | undefined;
|
|
350
360
|
readonly id?: string | null | undefined;
|
|
351
361
|
readonly index?: number | null | undefined;
|
|
362
|
+
readonly extra_content?: unknown;
|
|
352
363
|
}[] | null | undefined;
|
|
353
364
|
readonly reasoning_details?: unknown;
|
|
354
365
|
} | null | undefined;
|
|
@@ -432,12 +443,17 @@ export declare const route: Route<{
|
|
|
432
443
|
readonly ttl?: string | undefined;
|
|
433
444
|
} | undefined;
|
|
434
445
|
readonly tool_calls?: readonly {
|
|
435
|
-
readonly id: string;
|
|
436
|
-
readonly type: "function";
|
|
437
446
|
readonly function: {
|
|
438
447
|
readonly name: string;
|
|
439
448
|
readonly arguments: string;
|
|
440
449
|
};
|
|
450
|
+
readonly id: string;
|
|
451
|
+
readonly type: "function";
|
|
452
|
+
readonly extra_content?: {
|
|
453
|
+
readonly google: {
|
|
454
|
+
readonly thought_signature: string;
|
|
455
|
+
};
|
|
456
|
+
} | undefined;
|
|
441
457
|
}[] | undefined;
|
|
442
458
|
readonly reasoning_details?: unknown;
|
|
443
459
|
} | {
|
|
@@ -544,12 +560,17 @@ export declare const routes: Route<{
|
|
|
544
560
|
readonly ttl?: string | undefined;
|
|
545
561
|
} | undefined;
|
|
546
562
|
readonly tool_calls?: readonly {
|
|
547
|
-
readonly id: string;
|
|
548
|
-
readonly type: "function";
|
|
549
563
|
readonly function: {
|
|
550
564
|
readonly name: string;
|
|
551
565
|
readonly arguments: string;
|
|
552
566
|
};
|
|
567
|
+
readonly id: string;
|
|
568
|
+
readonly type: "function";
|
|
569
|
+
readonly extra_content?: {
|
|
570
|
+
readonly google: {
|
|
571
|
+
readonly thought_signature: string;
|
|
572
|
+
};
|
|
573
|
+
} | undefined;
|
|
553
574
|
}[] | undefined;
|
|
554
575
|
readonly reasoning_details?: unknown;
|
|
555
576
|
} | {
|
|
@@ -68,12 +68,17 @@ export declare const route: Route<{
|
|
|
68
68
|
readonly ttl?: string | undefined;
|
|
69
69
|
} | undefined;
|
|
70
70
|
readonly tool_calls?: readonly {
|
|
71
|
-
readonly id: string;
|
|
72
|
-
readonly type: "function";
|
|
73
71
|
readonly function: {
|
|
74
72
|
readonly name: string;
|
|
75
73
|
readonly arguments: string;
|
|
76
74
|
};
|
|
75
|
+
readonly id: string;
|
|
76
|
+
readonly type: "function";
|
|
77
|
+
readonly extra_content?: {
|
|
78
|
+
readonly google: {
|
|
79
|
+
readonly thought_signature: string;
|
|
80
|
+
};
|
|
81
|
+
} | undefined;
|
|
77
82
|
}[] | undefined;
|
|
78
83
|
readonly reasoning_details?: unknown;
|
|
79
84
|
} | {
|
|
@@ -179,12 +184,17 @@ export declare const routes: Route<{
|
|
|
179
184
|
readonly ttl?: string | undefined;
|
|
180
185
|
} | undefined;
|
|
181
186
|
readonly tool_calls?: readonly {
|
|
182
|
-
readonly id: string;
|
|
183
|
-
readonly type: "function";
|
|
184
187
|
readonly function: {
|
|
185
188
|
readonly name: string;
|
|
186
189
|
readonly arguments: string;
|
|
187
190
|
};
|
|
191
|
+
readonly id: string;
|
|
192
|
+
readonly type: "function";
|
|
193
|
+
readonly extra_content?: {
|
|
194
|
+
readonly google: {
|
|
195
|
+
readonly thought_signature: string;
|
|
196
|
+
};
|
|
197
|
+
} | undefined;
|
|
188
198
|
}[] | undefined;
|
|
189
199
|
readonly reasoning_details?: unknown;
|
|
190
200
|
} | {
|
package/dist/providers/xai.d.ts
CHANGED
|
@@ -76,12 +76,17 @@ export declare const routes: (Route<{
|
|
|
76
76
|
readonly ttl?: string | undefined;
|
|
77
77
|
} | undefined;
|
|
78
78
|
readonly tool_calls?: readonly {
|
|
79
|
-
readonly id: string;
|
|
80
|
-
readonly type: "function";
|
|
81
79
|
readonly function: {
|
|
82
80
|
readonly name: string;
|
|
83
81
|
readonly arguments: string;
|
|
84
82
|
};
|
|
83
|
+
readonly id: string;
|
|
84
|
+
readonly type: "function";
|
|
85
|
+
readonly extra_content?: {
|
|
86
|
+
readonly google: {
|
|
87
|
+
readonly thought_signature: string;
|
|
88
|
+
};
|
|
89
|
+
} | undefined;
|
|
85
90
|
}[] | undefined;
|
|
86
91
|
readonly reasoning_details?: unknown;
|
|
87
92
|
} | {
|
package/dist/providers/xai.js
CHANGED
|
@@ -13,13 +13,13 @@ const baseURL = "https://api.x.ai/v1";
|
|
|
13
13
|
const RESPONSES_WEBSOCKET_ROTATE_AFTER_MS = 24 * 60 * 1000;
|
|
14
14
|
const responsesRoute = Route.make({
|
|
15
15
|
compact: { endpoint: XAIResponses.compact },
|
|
16
|
-
id: "
|
|
16
|
+
id: "xai-responses",
|
|
17
17
|
provider: id,
|
|
18
18
|
providerMetadataKey: "xai",
|
|
19
19
|
protocol: XAIResponses.protocol,
|
|
20
20
|
endpoint: Endpoint.path("/responses", { baseURL }),
|
|
21
21
|
transport: OpenResponsesChannel.transport({
|
|
22
|
-
id: "
|
|
22
|
+
id: "xai-responses",
|
|
23
23
|
name: "xAI Responses",
|
|
24
24
|
rotateAfterMs: RESPONSES_WEBSOCKET_ROTATE_AFTER_MS,
|
|
25
25
|
// xAI continues a chain only from stored responses: with `store: false` (the route default) `previous_response_id`
|
|
@@ -30,7 +30,7 @@ const responsesRoute = Route.make({
|
|
|
30
30
|
defaults: { providerOptions: { store: false, include: ["reasoning.encrypted_content"] } },
|
|
31
31
|
});
|
|
32
32
|
const chatRoute = Route.make({
|
|
33
|
-
id: "
|
|
33
|
+
id: "xai-chat",
|
|
34
34
|
provider: id,
|
|
35
35
|
providerMetadataKey: "xai",
|
|
36
36
|
protocol: OpenAIChat.protocol,
|
|
@@ -240,12 +240,17 @@ export declare const routes: (Route<{
|
|
|
240
240
|
readonly ttl?: string | undefined;
|
|
241
241
|
} | undefined;
|
|
242
242
|
readonly tool_calls?: readonly {
|
|
243
|
-
readonly id: string;
|
|
244
|
-
readonly type: "function";
|
|
245
243
|
readonly function: {
|
|
246
244
|
readonly name: string;
|
|
247
245
|
readonly arguments: string;
|
|
248
246
|
};
|
|
247
|
+
readonly id: string;
|
|
248
|
+
readonly type: "function";
|
|
249
|
+
readonly extra_content?: {
|
|
250
|
+
readonly google: {
|
|
251
|
+
readonly thought_signature: string;
|
|
252
|
+
};
|
|
253
|
+
} | undefined;
|
|
249
254
|
}[] | undefined;
|
|
250
255
|
readonly reasoning_details?: unknown;
|
|
251
256
|
} | {
|
package/dist/providers/zai.d.ts
CHANGED
|
@@ -70,12 +70,17 @@ export declare const routes: Route<{
|
|
|
70
70
|
readonly ttl?: string | undefined;
|
|
71
71
|
} | undefined;
|
|
72
72
|
readonly tool_calls?: readonly {
|
|
73
|
-
readonly id: string;
|
|
74
|
-
readonly type: "function";
|
|
75
73
|
readonly function: {
|
|
76
74
|
readonly name: string;
|
|
77
75
|
readonly arguments: string;
|
|
78
76
|
};
|
|
77
|
+
readonly id: string;
|
|
78
|
+
readonly type: "function";
|
|
79
|
+
readonly extra_content?: {
|
|
80
|
+
readonly google: {
|
|
81
|
+
readonly thought_signature: string;
|
|
82
|
+
};
|
|
83
|
+
} | undefined;
|
|
79
84
|
}[] | undefined;
|
|
80
85
|
readonly reasoning_details?: unknown;
|
|
81
86
|
} | {
|
|
@@ -3,7 +3,7 @@ import { HttpClientResponse } from "effect/unstable/http";
|
|
|
3
3
|
import type { Snapshot, Status } from "../generation.js";
|
|
4
4
|
import { Media } from "../media.js";
|
|
5
5
|
import type { AuthInput } from "./auth.js";
|
|
6
|
-
import { AIError, HttpContext, ProviderID } from "../schema/index.js";
|
|
6
|
+
import { AIError, AuthenticationError, HttpContext, InvalidRequestError, ProviderID, ProviderInternalError, RateLimitError } from "../schema/index.js";
|
|
7
7
|
/** Array values become repeated parameters (`keyterm=a&keyterm=b`). */
|
|
8
8
|
export type Query = Readonly<Record<string, string | ReadonlyArray<string>>>;
|
|
9
9
|
/** `query` is appended to the endpoint URL before the route and caller `http.query` overlays. */
|
|
@@ -128,6 +128,14 @@ export interface Streamed<Request, Event, Frame, State> {
|
|
|
128
128
|
readonly finish: (state: State, context: ResponseContext<Request>) => Effect.Effect<ReadonlyArray<Event>, AIError>;
|
|
129
129
|
}
|
|
130
130
|
export declare const stream: <Request, Event, Frame, State>(route: Identity, input: Omit<Streamed<Request, Event, Frame, State>, "kind" | "id" | "provider">) => Streamed<Request, Event, Frame, State>;
|
|
131
|
+
/** Reasons a provider can report for a `failed` generation; anything it does not classify is `ProviderInternal`. */
|
|
132
|
+
declare const FAILURES: {
|
|
133
|
+
InvalidRequest: typeof InvalidRequestError;
|
|
134
|
+
Authentication: typeof AuthenticationError;
|
|
135
|
+
RateLimit: typeof RateLimitError;
|
|
136
|
+
ProviderInternal: typeof ProviderInternalError;
|
|
137
|
+
};
|
|
138
|
+
export type Failure = keyof typeof FAILURES;
|
|
131
139
|
/** One protocol's route id, display name, and provider, with the decoders and errors that carry them. */
|
|
132
140
|
export declare const identity: (input: {
|
|
133
141
|
readonly id: string;
|
|
@@ -141,7 +149,7 @@ export declare const identity: (input: {
|
|
|
141
149
|
body: string;
|
|
142
150
|
http: HttpContext;
|
|
143
151
|
invalid: (message: string, cause?: unknown) => AIError;
|
|
144
|
-
ended: (status: Exclude<Status, "queued" | "running" | "completed">, message: string) => AIError;
|
|
152
|
+
ended: (status: Exclude<Status, "queued" | "running" | "completed">, message: string, failure?: Failure) => AIError;
|
|
145
153
|
pending: (id: string) => AIError;
|
|
146
154
|
contentPolicy: (message: string) => AIError;
|
|
147
155
|
}, AIError, never>;
|
|
@@ -150,7 +158,7 @@ export declare const identity: (input: {
|
|
|
150
158
|
body: string;
|
|
151
159
|
http: HttpContext;
|
|
152
160
|
invalid: (message: string, cause?: unknown) => AIError;
|
|
153
|
-
ended: (status: Exclude<Status, "queued" | "running" | "completed">, message: string) => AIError;
|
|
161
|
+
ended: (status: Exclude<Status, "queued" | "running" | "completed">, message: string, failure?: Failure) => AIError;
|
|
154
162
|
pending: (id: string) => AIError;
|
|
155
163
|
contentPolicy: (message: string) => AIError;
|
|
156
164
|
}, AIError, never>;
|
|
@@ -167,6 +175,8 @@ export type Identity = ReturnType<typeof identity>;
|
|
|
167
175
|
export type Output = Effect.Success<ReturnType<Identity["text"]>>;
|
|
168
176
|
/** Map a provider status string through the protocol's table; unknown values are an invalid provider document. */
|
|
169
177
|
export declare const status: <Table extends Record<string, Status>>(table: Table, raw: string, output: Output) => Effect.Effect<Status, AIError>;
|
|
178
|
+
/** Map a provider error code through the protocol's table; missing or unmapped codes are `ProviderInternal`. */
|
|
179
|
+
export declare const failure: (table: Readonly<Record<string, Failure>>, code: string | number | undefined) => Failure;
|
|
170
180
|
/** A `url` asset whose provider-declared retention window starts now. */
|
|
171
181
|
export declare const expiringUrl: (url: string, retention: Duration.Duration, options?: Parameters<typeof Media.url>[1]) => Effect.Effect<Media.Asset, never, never>;
|
|
172
182
|
export * as MediaProtocol from "./media-protocol.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Clock, Duration, Effect, Schema } from "effect";
|
|
2
2
|
import { HttpClientResponse } from "effect/unstable/http";
|
|
3
3
|
import { Media } from "../media.js";
|
|
4
|
-
import { AIError, ContentPolicyError, HttpContext, InvalidProviderOutputError, InvalidRequestError, ProviderID, ProviderInternalError, UnsupportedOperationError, } from "../schema/index.js";
|
|
4
|
+
import { AIError, AuthenticationError, ContentPolicyError, HttpContext, InvalidProviderOutputError, InvalidRequestError, ProviderID, ProviderInternalError, RateLimitError, UnsupportedOperationError, } from "../schema/index.js";
|
|
5
5
|
export const json = (value, query) => ({
|
|
6
6
|
type: "json",
|
|
7
7
|
value,
|
|
@@ -20,6 +20,13 @@ export const stream = (route, input) => ({ kind: "stream", id: route.id, provide
|
|
|
20
20
|
// ---------------------------------------------------------------------------
|
|
21
21
|
// Response helpers
|
|
22
22
|
// ---------------------------------------------------------------------------
|
|
23
|
+
/** Reasons a provider can report for a `failed` generation; anything it does not classify is `ProviderInternal`. */
|
|
24
|
+
const FAILURES = {
|
|
25
|
+
InvalidRequest: InvalidRequestError,
|
|
26
|
+
Authentication: AuthenticationError,
|
|
27
|
+
RateLimit: RateLimitError,
|
|
28
|
+
ProviderInternal: ProviderInternalError,
|
|
29
|
+
};
|
|
23
30
|
const context = (response) => new HttpContext({ url: response.request.url, status: response.status, headers: response.headers });
|
|
24
31
|
/** One protocol's route id, display name, and provider, with the decoders and errors that carry them. */
|
|
25
32
|
export const identity = (input) => {
|
|
@@ -27,9 +34,10 @@ export const identity = (input) => {
|
|
|
27
34
|
const frameError = (message, body, cause) => new AIError({ reason: new InvalidProviderOutputError({ route: input.id, message, body, cause }) });
|
|
28
35
|
/**
|
|
29
36
|
* Read a text body while retaining the original payload and HTTP context on every downstream error. `invalid` is a
|
|
30
|
-
* malformed provider document; `ended` is a generation that reached a terminal status without output (`failed`
|
|
31
|
-
* provider
|
|
32
|
-
* generation finished, which is caller misuse;
|
|
37
|
+
* malformed provider document; `ended` is a generation that reached a terminal status without output (`failed`
|
|
38
|
+
* carries the provider's classification, defaulting to `ProviderInternal`; `cancelled`/`expired` mean the result
|
|
39
|
+
* will never exist); `pending` is a `result()` read before the generation finished, which is caller misuse;
|
|
40
|
+
* `contentPolicy` is a moderated result.
|
|
33
41
|
*/
|
|
34
42
|
const text = Effect.fn("MediaProtocol.text")(function* (response) {
|
|
35
43
|
const http = context(response);
|
|
@@ -45,9 +53,9 @@ export const identity = (input) => {
|
|
|
45
53
|
body,
|
|
46
54
|
http,
|
|
47
55
|
invalid: (message, cause) => new AIError({ reason: new InvalidProviderOutputError({ route: input.id, message, body, http, cause }) }),
|
|
48
|
-
ended: (status, message) => new AIError({
|
|
56
|
+
ended: (status, message, failure = "ProviderInternal") => new AIError({
|
|
49
57
|
reason: status === "failed"
|
|
50
|
-
? new
|
|
58
|
+
? new FAILURES[failure]({ message, body, http })
|
|
51
59
|
: new InvalidRequestError({ message, body, http }),
|
|
52
60
|
}),
|
|
53
61
|
pending: (id) => new AIError({
|
|
@@ -103,6 +111,8 @@ export const status = (table, raw, output) => {
|
|
|
103
111
|
return Effect.fail(output.invalid(`Unknown generation status "${raw}"`));
|
|
104
112
|
return Effect.succeed(table[raw]);
|
|
105
113
|
};
|
|
114
|
+
/** Map a provider error code through the protocol's table; missing or unmapped codes are `ProviderInternal`. */
|
|
115
|
+
export const failure = (table, code) => code !== undefined && Object.hasOwn(table, code) ? table[code] : "ProviderInternal";
|
|
106
116
|
/** A `url` asset whose provider-declared retention window starts now. */
|
|
107
117
|
export const expiringUrl = (url, retention, options) => Clock.currentTimeMillis.pipe(Effect.map((now) => Media.url(url, { ...options, expiresAt: now + Duration.toMillis(retention) })));
|
|
108
118
|
export * as MediaProtocol from "./media-protocol.js";
|
package/dist/route/media.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Effect, Schema, Stream } from "effect";
|
|
1
|
+
import { Duration, Effect, Schedule, Schema, Stream } from "effect";
|
|
2
2
|
import { Headers, HttpClientRequest } from "effect/unstable/http";
|
|
3
3
|
import { Auth } from "./auth.js";
|
|
4
4
|
import { Endpoint } from "./endpoint.js";
|
|
@@ -6,6 +6,7 @@ import { RequestExecutorService } from "./executor-service.js";
|
|
|
6
6
|
import { RequestExecutor } from "./executor.js";
|
|
7
7
|
import { MediaProtocol } from "./media-protocol.js";
|
|
8
8
|
import { Generation, isTerminal } from "../generation.js";
|
|
9
|
+
import { isRetryable } from "../provider-error.js";
|
|
9
10
|
import { AIError, AIErrorReason, HttpOptions, InvalidRequestError, ProviderID, UnsupportedOperationError, mergeHttpOptions, } from "../schema/index.js";
|
|
10
11
|
import { encodeJson } from "../utils/json.js";
|
|
11
12
|
import { sanitizeSurrogates } from "../utils/sanitize.js";
|
|
@@ -35,6 +36,19 @@ export const inline = (input) => {
|
|
|
35
36
|
}),
|
|
36
37
|
};
|
|
37
38
|
};
|
|
39
|
+
const READ_RETRY_MAX_DELAY = Duration.seconds(30);
|
|
40
|
+
/**
|
|
41
|
+
* Status and result reads retry transient failures; `start` and `cancel` never do. Gaps grow exponentially from 1s,
|
|
42
|
+
* jittered, up to 30s each, for at most 8 retries (about two minutes when every attempt fails), so a direct
|
|
43
|
+
* `Generation.result()` stays bounded; `await` and `events` also cut retries off at `poll.timeout`. A provider
|
|
44
|
+
* `retryAfterMs` raises the gap, still capped at 30s.
|
|
45
|
+
*/
|
|
46
|
+
const READ_RETRY = Schedule.max([
|
|
47
|
+
Schedule.min([Schedule.exponential("1 second"), Schedule.spaced(READ_RETRY_MAX_DELAY)]),
|
|
48
|
+
Schedule.recurs(8),
|
|
49
|
+
]).pipe(Schedule.jittered, Schedule.setInputType(), Schedule.modifyDelay(({ input, duration }) => Effect.succeed(Duration.min(input.reason._tag === "RateLimit" || input.reason._tag === "ProviderInternal"
|
|
50
|
+
? Duration.max(duration, Duration.millis(input.reason.retryAfterMs ?? 0))
|
|
51
|
+
: duration, READ_RETRY_MAX_DELAY))));
|
|
38
52
|
/**
|
|
39
53
|
* Compose a queued media protocol the same way, adding `start`/`resume` handles whose polls reuse the route's auth,
|
|
40
54
|
* deployment headers, and (for `start`) the request's `http` overlay. The token is decoded once at the boundary and
|
|
@@ -48,9 +62,9 @@ export const queued = (input) => {
|
|
|
48
62
|
const encodeToken = Schema.encodeSync(protocol.token);
|
|
49
63
|
const generationRoute = (token, http, execute) => {
|
|
50
64
|
const materialize = (asset) => asset.materialize().pipe(Effect.provideService(RequestExecutorService, { execute }));
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
65
|
+
// Only the GET exchange retries: a decoded terminal failure (`output.ended`) can be a `ProviderInternal` too, and
|
|
66
|
+
// re-reading it would spin until the caller's deadline.
|
|
67
|
+
const poll = (operation) => transport.call("GET", operation.path(token), http, execute).pipe(Effect.retry({ schedule: READ_RETRY, while: isRetryable }), Effect.flatMap((sent) => operation.decode(sent.response, { token, auth: sent.auth, materialize })));
|
|
54
68
|
const status = poll(protocol.status);
|
|
55
69
|
const cancel = protocol.cancel;
|
|
56
70
|
const send = cancel === undefined
|
package/dist/transcription.d.ts
CHANGED
|
@@ -72,7 +72,7 @@ export type TranscriptionRequestInput<Model extends TranscriptionModel = Transcr
|
|
|
72
72
|
readonly providerOptions?: NoInfer<TranscriptionModelOptions<Model>>;
|
|
73
73
|
readonly http?: HttpOptions.Input;
|
|
74
74
|
};
|
|
75
|
-
/** Speaker labels are provider-native (`A`, `0`, `spk:0`, or a known speaker name). */
|
|
75
|
+
/** Speaker labels are provider-native (`A`, `0`, `spk:0`, `speaker_0`, or a known speaker name). */
|
|
76
76
|
export declare const TranscriptionSegment: Schema.Struct<{
|
|
77
77
|
readonly text: Schema.String;
|
|
78
78
|
readonly startSeconds: Schema.Number;
|
package/dist/transcription.js
CHANGED
|
@@ -36,7 +36,7 @@ export class TranscriptionRequest extends Schema.Class("Transcription.Request")(
|
|
|
36
36
|
// ---------------------------------------------------------------------------
|
|
37
37
|
// Response and events
|
|
38
38
|
// ---------------------------------------------------------------------------
|
|
39
|
-
/** Speaker labels are provider-native (`A`, `0`, `spk:0`, or a known speaker name). */
|
|
39
|
+
/** Speaker labels are provider-native (`A`, `0`, `spk:0`, `speaker_0`, or a known speaker name). */
|
|
40
40
|
export const TranscriptionSegment = Schema.Struct({
|
|
41
41
|
text: Schema.String,
|
|
42
42
|
startSeconds: Schema.Number,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.19",
|
|
4
4
|
"name": "@opencode/ai",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@clack/prompts": "1.0.0-alpha.1",
|
|
36
36
|
"@effect/platform-node": "4.0.0-rc.112",
|
|
37
|
-
"@opencode/http-recorder": "2.0.
|
|
37
|
+
"@opencode/http-recorder": "2.0.19",
|
|
38
38
|
"@tsconfig/bun": "1.0.9",
|
|
39
39
|
"@types/bun": "1.4.0",
|
|
40
40
|
"@typescript/native-preview": "7.0.0-dev.20251207.1",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@aws-sdk/credential-providers": "3.1057.0",
|
|
45
45
|
"@smithy/eventstream-codec": "4.2.14",
|
|
46
46
|
"@smithy/util-utf8": "4.2.2",
|
|
47
|
-
"@opencode/schema": "2.0.
|
|
47
|
+
"@opencode/schema": "2.0.19",
|
|
48
48
|
"aws4fetch": "1.0.20",
|
|
49
49
|
"effect": "4.0.0-rc.112",
|
|
50
50
|
"google-auth-library": "10.5.0"
|