@opencode/ai 2.0.21 → 2.0.23

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.
Files changed (113) hide show
  1. package/README.md +61 -1
  2. package/dist/cache-policy.js +10 -2
  3. package/dist/llm.d.ts +4 -0
  4. package/dist/promise.d.ts +8 -0
  5. package/dist/protocols/alibaba-chat.d.ts +7 -3
  6. package/dist/protocols/alibaba-chat.js +2 -1
  7. package/dist/protocols/alibaba-responses.d.ts +16 -12
  8. package/dist/protocols/alibaba-responses.js +3 -5
  9. package/dist/protocols/anthropic-messages.js +58 -51
  10. package/dist/protocols/bedrock-converse.js +33 -4
  11. package/dist/protocols/cartesia-speech.js +3 -3
  12. package/dist/protocols/cohere-chat.d.ts +178 -0
  13. package/dist/protocols/cohere-chat.js +299 -0
  14. package/dist/protocols/elevenlabs-speech.js +3 -3
  15. package/dist/protocols/gemini.d.ts +2 -2
  16. package/dist/protocols/gemini.js +3 -3
  17. package/dist/protocols/google-interactions.d.ts +236 -0
  18. package/dist/protocols/google-interactions.js +478 -0
  19. package/dist/protocols/google-speech.js +1 -1
  20. package/dist/protocols/google-transcription.js +1 -1
  21. package/dist/protocols/index.d.ts +2 -0
  22. package/dist/protocols/index.js +2 -0
  23. package/dist/protocols/meta-responses.d.ts +31 -58
  24. package/dist/protocols/meta-responses.js +8 -27
  25. package/dist/protocols/mistral-chat.d.ts +24 -9
  26. package/dist/protocols/mistral-chat.js +22 -10
  27. package/dist/protocols/open-responses.d.ts +410 -91
  28. package/dist/protocols/open-responses.js +25 -15
  29. package/dist/protocols/openai-chat.d.ts +409 -5
  30. package/dist/protocols/openai-chat.js +27 -26
  31. package/dist/protocols/openai-compatible-chat.d.ts +1 -1
  32. package/dist/protocols/openai-compatible-responses.d.ts +16 -4
  33. package/dist/protocols/openai-images.js +2 -2
  34. package/dist/protocols/openai-responses.d.ts +87 -223
  35. package/dist/protocols/openai-responses.js +10 -16
  36. package/dist/protocols/openai-speech.js +1 -1
  37. package/dist/protocols/openai-transcription.js +1 -1
  38. package/dist/protocols/shared.js +2 -2
  39. package/dist/protocols/stability-images.js +1 -1
  40. package/dist/protocols/utils/bedrock-media.js +2 -2
  41. package/dist/protocols/utils/cache.d.ts +5 -0
  42. package/dist/protocols/utils/cache.js +9 -1
  43. package/dist/protocols/utils/responses-checkpoint.js +2 -2
  44. package/dist/protocols/utils/responses-hosted-tools.js +1 -1
  45. package/dist/protocols/utils/tool-stream.d.ts +12 -0
  46. package/dist/protocols/utils/tool-stream.js +15 -7
  47. package/dist/protocols/venice-chat.d.ts +280 -0
  48. package/dist/protocols/venice-chat.js +283 -0
  49. package/dist/protocols/xai-responses.d.ts +18 -21
  50. package/dist/protocols/xai-responses.js +2 -8
  51. package/dist/protocols/zai-chat.d.ts +7 -3
  52. package/dist/protocols/zai-chat.js +6 -3
  53. package/dist/provider-error.js +27 -7
  54. package/dist/providers/alibaba.d.ts +17 -13
  55. package/dist/providers/amazon-bedrock/mantle/messages.d.ts +2 -0
  56. package/dist/providers/amazon-bedrock/mantle/messages.js +1 -0
  57. package/dist/providers/amazon-bedrock-mantle.d.ts +301 -9
  58. package/dist/providers/amazon-bedrock-mantle.js +28 -3
  59. package/dist/providers/azure.d.ts +13 -61
  60. package/dist/providers/baseten.d.ts +2 -2
  61. package/dist/providers/cerebras.d.ts +2 -2
  62. package/dist/providers/cloudflare-ai-gateway.d.ts +14 -62
  63. package/dist/providers/cloudflare-workers-ai.d.ts +2 -2
  64. package/dist/providers/cohere/chat.d.ts +4 -0
  65. package/dist/providers/cohere/chat.js +8 -0
  66. package/dist/providers/cohere.d.ts +395 -0
  67. package/dist/providers/cohere.js +48 -0
  68. package/dist/providers/deepinfra.d.ts +2 -2
  69. package/dist/providers/deepseek.d.ts +2 -2
  70. package/dist/providers/digitalocean.d.ts +469 -0
  71. package/dist/providers/digitalocean.js +53 -0
  72. package/dist/providers/fireworks.d.ts +2 -2
  73. package/dist/providers/google/interactions.d.ts +7 -0
  74. package/dist/providers/google/interactions.js +8 -0
  75. package/dist/providers/google-vertex-chat.d.ts +1 -1
  76. package/dist/providers/google-vertex-messages.js +1 -1
  77. package/dist/providers/google-vertex-responses.d.ts +16 -4
  78. package/dist/providers/google-vertex.d.ts +1 -1
  79. package/dist/providers/google.d.ts +95 -4
  80. package/dist/providers/google.js +8 -1
  81. package/dist/providers/groq.d.ts +8 -4
  82. package/dist/providers/groq.js +1 -1
  83. package/dist/providers/index.d.ts +3 -0
  84. package/dist/providers/index.js +3 -0
  85. package/dist/providers/meta.d.ts +15 -28
  86. package/dist/providers/minimax.d.ts +17 -5
  87. package/dist/providers/mistral.d.ts +10 -4
  88. package/dist/providers/moonshot.d.ts +17 -5
  89. package/dist/providers/openai-compatible-responses.d.ts +16 -4
  90. package/dist/providers/openai-compatible.d.ts +1 -1
  91. package/dist/providers/openai-options.d.ts +1 -1
  92. package/dist/providers/openai.d.ts +7 -31
  93. package/dist/providers/openrouter.d.ts +9 -5
  94. package/dist/providers/openrouter.js +1 -13
  95. package/dist/providers/togetherai.d.ts +2 -2
  96. package/dist/providers/venice.d.ts +183 -0
  97. package/dist/providers/venice.js +38 -0
  98. package/dist/providers/xai.d.ts +1 -1
  99. package/dist/providers/zai-coding-plan.d.ts +17 -5
  100. package/dist/providers/zai.d.ts +1 -1
  101. package/dist/route/client.d.ts +4 -0
  102. package/dist/route/client.js +2 -5
  103. package/dist/route/executor.js +13 -6
  104. package/dist/route/framing.js +23 -23
  105. package/dist/route/transport/http.d.ts +2 -1
  106. package/dist/route/transport/http.js +28 -6
  107. package/dist/schema/events.d.ts +176 -0
  108. package/dist/schema/events.js +4 -0
  109. package/dist/schema/options.d.ts +11 -0
  110. package/dist/schema/options.js +15 -2
  111. package/dist/testing.d.ts +32 -0
  112. package/dist/tool-history.js +17 -3
  113. package/package.json +3 -3
@@ -0,0 +1,283 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { Protocol } from "../route/protocol.js";
3
+ import { AIError, LLMEvent } from "../schema/index.js";
4
+ import { classifyProviderFailure } from "../provider-error.js";
5
+ import { OpenAIChat } from "./openai-chat.js";
6
+ import { JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js";
7
+ import { cacheControl } from "./utils/cache.js";
8
+ const Parameters = Schema.Struct({
9
+ enableWebSearch: Schema.optional(Schema.String),
10
+ enableWebScraping: Schema.optional(Schema.Boolean),
11
+ enableWebCitations: Schema.optional(Schema.Boolean),
12
+ enableXSearch: Schema.optional(Schema.Boolean),
13
+ stripThinkingResponse: Schema.optional(Schema.Boolean),
14
+ disableThinking: Schema.optional(Schema.Boolean),
15
+ includeVeniceSystemPrompt: Schema.optional(Schema.Boolean),
16
+ characterSlug: Schema.optional(Schema.String),
17
+ includeSearchResultsInStream: Schema.optional(Schema.Boolean),
18
+ returnSearchResultsAsDocuments: Schema.optional(Schema.Boolean),
19
+ });
20
+ const Reasoning = Schema.Struct({
21
+ effort: Schema.optional(Schema.String),
22
+ enabled: Schema.optional(Schema.Boolean),
23
+ summary: Schema.optional(Schema.String),
24
+ });
25
+ const Options = Schema.Struct({
26
+ reasoningEffort: Schema.optional(Schema.String),
27
+ reasoning: Schema.optional(Reasoning),
28
+ veniceParameters: Schema.optional(Parameters),
29
+ promptCacheKey: Schema.optional(Schema.String),
30
+ promptCacheRetention: Schema.optional(Schema.String),
31
+ parallelToolCalls: Schema.optional(Schema.Boolean),
32
+ maxCompletionTokens: Schema.optional(Schema.Number),
33
+ maxTokens: Schema.optional(Schema.Number),
34
+ minP: Schema.optional(Schema.Number),
35
+ repetitionPenalty: Schema.optional(Schema.Number),
36
+ stopTokenIds: Schema.optional(Schema.Array(Schema.Number)),
37
+ logprobs: Schema.optional(Schema.Boolean),
38
+ topLogprobs: Schema.optional(Schema.Number),
39
+ maxTemp: Schema.optional(Schema.Number),
40
+ minTemp: Schema.optional(Schema.Number),
41
+ responseFormat: Schema.optional(JsonObject),
42
+ user: Schema.optional(Schema.String),
43
+ });
44
+ const ToolCall = Schema.Struct({
45
+ ...OpenAIChat.OpenAIChatAssistantToolCall.fields,
46
+ thought_signature: Schema.optional(Schema.String),
47
+ });
48
+ const Assistant = Schema.StructWithRest(Schema.Struct({
49
+ ...OpenAIChat.OpenAIChatMessage.cases.assistant.schema.fields,
50
+ tool_calls: optionalArray(ToolCall),
51
+ thought_signature: Schema.optional(Schema.String),
52
+ }), [Schema.Record(Schema.String, Schema.Unknown)]);
53
+ const Messages = Schema.Array(Schema.Union([
54
+ OpenAIChat.OpenAIChatMessage.cases.system,
55
+ OpenAIChat.OpenAIChatMessage.cases.user,
56
+ Assistant,
57
+ OpenAIChat.OpenAIChatMessage.cases.tool,
58
+ ]));
59
+ const Body = Schema.Struct({
60
+ ...OpenAIChat.bodyFields,
61
+ messages: Messages,
62
+ reasoning: Schema.optional(Reasoning),
63
+ venice_parameters: Schema.Record(Schema.String, Schema.Union([Schema.String, Schema.Boolean])),
64
+ prompt_cache_retention: Options.fields.promptCacheRetention,
65
+ parallel_tool_calls: Options.fields.parallelToolCalls,
66
+ min_p: Options.fields.minP,
67
+ top_k: Schema.optional(Schema.Number),
68
+ repetition_penalty: Options.fields.repetitionPenalty,
69
+ stop_token_ids: Options.fields.stopTokenIds,
70
+ logprobs: Options.fields.logprobs,
71
+ top_logprobs: Options.fields.topLogprobs,
72
+ max_temp: Options.fields.maxTemp,
73
+ min_temp: Options.fields.minTemp,
74
+ response_format: Options.fields.responseFormat,
75
+ user: Options.fields.user,
76
+ });
77
+ // ---------------------------------------------------------------------------
78
+ // Streaming schemas and state
79
+ // ---------------------------------------------------------------------------
80
+ const ToolDelta = Schema.Struct({
81
+ ...OpenAIChat.OpenAIChatToolCallDelta.fields,
82
+ thought_signature: optionalNull(Schema.String),
83
+ });
84
+ const Delta = Schema.StructWithRest(Schema.Struct({
85
+ ...OpenAIChat.OpenAIChatDelta.schema.fields,
86
+ tool_calls: optionalNull(Schema.Array(ToolDelta)),
87
+ thought_signature: optionalNull(Schema.String),
88
+ }), [Schema.Record(Schema.String, Schema.Unknown)]);
89
+ const Choice = Schema.StructWithRest(Schema.Struct({ ...OpenAIChat.OpenAIChatChoice.schema.fields, delta: optionalNull(Delta) }), [Schema.Record(Schema.String, Schema.Unknown)]);
90
+ const Usage = Schema.StructWithRest(Schema.Struct({
91
+ ...OpenAIChat.OpenAIChatUsage.schema.fields,
92
+ prompt_tokens_details: optionalNull(Schema.StructWithRest(Schema.Struct({
93
+ cached_tokens: optionalNull(Schema.Number),
94
+ cache_write_tokens: optionalNull(Schema.Number),
95
+ cache_creation_input_tokens: optionalNull(Schema.Number),
96
+ }), [Schema.Record(Schema.String, Schema.Unknown)])),
97
+ }), [Schema.Record(Schema.String, Schema.Unknown)]);
98
+ const Event = Schema.StructWithRest(Schema.Struct({
99
+ ...OpenAIChat.OpenAIChatEvent.schema.fields,
100
+ choices: optionalNull(Schema.Array(Choice)),
101
+ usage: optionalNull(Usage),
102
+ error: optionalNull(Schema.Union([Schema.String, OpenAIChat.OpenAIChatEvent.schema.fields.error.schema])),
103
+ issues: optionalArray(Schema.Struct({
104
+ message: Schema.String,
105
+ path: Schema.optional(Schema.Array(Schema.Union([Schema.String, Schema.Number]))),
106
+ })),
107
+ }), [Schema.Record(Schema.String, Schema.Unknown)]);
108
+ const MARKER = "__ENCRYPTED_REASONING__";
109
+ // ---------------------------------------------------------------------------
110
+ // Request lowering
111
+ // ---------------------------------------------------------------------------
112
+ const fromRequest = Effect.fn("VeniceChat.fromRequest")(function* (request) {
113
+ const options = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Options))(request.providerOptions ?? {});
114
+ const body = yield* OpenAIChat.fromRequest(request, {
115
+ cacheControl: cacheControl(),
116
+ assistant: (source, message) => {
117
+ if (message.role !== "assistant")
118
+ return message;
119
+ const parts = source.content.filter((part) => part.type === "text" || part.type === "reasoning" || part.type === "tool-call");
120
+ const calls = source.content.filter((part) => part.type === "tool-call");
121
+ const signature = parts
122
+ .map((part) => part.providerMetadata?.venice?.messageThoughtSignature)
123
+ .find((value) => typeof value === "string");
124
+ const raw = parts
125
+ .map((part) => part.providerMetadata?.venice?.encryptedReasoningContent)
126
+ .find((value) => typeof value === "string");
127
+ return {
128
+ ...message,
129
+ ...(signature === undefined ? {} : { thought_signature: signature }),
130
+ ...(raw === undefined ? {} : { reasoning_content: raw }),
131
+ tool_calls: message.tool_calls?.map((call, index) => {
132
+ const signature = calls[index]?.providerMetadata?.venice?.thoughtSignature;
133
+ return { ...call, ...(typeof signature === "string" ? { thought_signature: signature } : {}) };
134
+ }),
135
+ };
136
+ },
137
+ });
138
+ return {
139
+ ...body,
140
+ max_completion_tokens: options.maxCompletionTokens ?? options.maxTokens ?? request.generation?.maxTokens,
141
+ reasoning_effort: undefined,
142
+ reasoning: options.reasoningEffort === undefined
143
+ ? options.reasoning
144
+ : { ...options.reasoning, effort: options.reasoningEffort },
145
+ // Match the previous Venice SDK default, not the gateway's added prompt.
146
+ venice_parameters: Object.fromEntries(Object.entries({
147
+ ...options.veniceParameters,
148
+ includeVeniceSystemPrompt: options.veniceParameters?.includeVeniceSystemPrompt ?? false,
149
+ })
150
+ .filter(([, value]) => value !== undefined)
151
+ .map(([key, value]) => [key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`), value])),
152
+ prompt_cache_retention: options.promptCacheRetention,
153
+ parallel_tool_calls: options.parallelToolCalls,
154
+ min_p: options.minP,
155
+ top_k: request.generation?.topK,
156
+ repetition_penalty: options.repetitionPenalty,
157
+ stop_token_ids: options.stopTokenIds,
158
+ logprobs: options.logprobs,
159
+ top_logprobs: options.topLogprobs,
160
+ max_temp: options.maxTemp,
161
+ min_temp: options.minTemp,
162
+ response_format: options.responseFormat,
163
+ user: options.user,
164
+ };
165
+ });
166
+ // ---------------------------------------------------------------------------
167
+ // Venice normalization around the shared Chat state machine
168
+ // ---------------------------------------------------------------------------
169
+ const step = Effect.fn("VeniceChat.step")(function* (state, event) {
170
+ if (typeof event.error === "string")
171
+ return yield* new AIError({
172
+ reason: classifyProviderFailure({
173
+ message: [
174
+ event.error,
175
+ ...(event.issues ?? []).map((issue) => `${issue.path?.length ? `${issue.path.join(".")}: ` : ""}${issue.message}`),
176
+ ].join("; "),
177
+ rawBody: ProviderShared.encodeJson(event),
178
+ }),
179
+ });
180
+ const delta = event.choices?.[0]?.delta;
181
+ const scalar = delta?.reasoning_content ?? "";
182
+ const text = state.pending + scalar;
183
+ const marker = text.indexOf(MARKER);
184
+ const pending = marker >= 0 || state.encrypted
185
+ ? 0
186
+ : (Array.from({ length: Math.min(text.length, MARKER.length - 1) }, (_, index) => index + 1)
187
+ .filter((length) => text.endsWith(MARKER.slice(0, length)))
188
+ .at(-1) ?? 0);
189
+ const visible = state.encrypted ? "" : marker >= 0 ? text.slice(0, marker) : text.slice(0, text.length - pending);
190
+ const result = yield* OpenAIChat.protocol.stream.step(state.shared, {
191
+ ...event,
192
+ error: event.error,
193
+ usage: event.usage
194
+ ? {
195
+ ...event.usage,
196
+ prompt_tokens_details: event.usage.prompt_tokens_details
197
+ ? {
198
+ ...event.usage.prompt_tokens_details,
199
+ cache_write_tokens: event.usage.prompt_tokens_details.cache_write_tokens ??
200
+ event.usage.prompt_tokens_details.cache_creation_input_tokens,
201
+ }
202
+ : event.usage.prompt_tokens_details,
203
+ }
204
+ : event.usage,
205
+ choices: event.choices?.map((choice, index) => index === 0 && choice.delta
206
+ ? {
207
+ ...choice,
208
+ delta: {
209
+ ...choice.delta,
210
+ reasoning_content: visible || undefined,
211
+ // Opaque-only scalar reasoning still needs a canonical part for replay.
212
+ reasoning_details: choice.delta.reasoning_details ?? (marker >= 0 ? [] : undefined),
213
+ },
214
+ }
215
+ : choice),
216
+ });
217
+ const tools = { ...state.tools };
218
+ for (const call of delta?.tool_calls ?? []) {
219
+ if (!call.thought_signature)
220
+ continue;
221
+ const index = call.index ?? result[0].latestToolIndex;
222
+ const id = call.id ?? (index === undefined ? undefined : (result[0].tools[index]?.id ?? result[0].pendingTools[index]?.id));
223
+ if (id)
224
+ tools[id] = call.thought_signature;
225
+ }
226
+ return [
227
+ {
228
+ shared: result[0],
229
+ pending: pending ? text.slice(-pending) : "",
230
+ reasoning: state.reasoning + scalar,
231
+ encrypted: state.encrypted || marker >= 0,
232
+ signature: delta?.thought_signature ?? state.signature,
233
+ tools,
234
+ },
235
+ result[1],
236
+ ];
237
+ });
238
+ const onHalt = Effect.fn("VeniceChat.onHalt")(function* (state) {
239
+ const events = yield* OpenAIChat.finishEvents(state.shared);
240
+ return events.flatMap((event) => {
241
+ if (event.type !== "reasoning-end" &&
242
+ event.type !== "text-end" &&
243
+ event.type !== "tool-call" &&
244
+ event.type !== "tool-input-end")
245
+ return [event];
246
+ const signature = event.type === "tool-call" || event.type === "tool-input-end" ? state.tools[event.id] : undefined;
247
+ const providerMetadata = {
248
+ ...event.providerMetadata,
249
+ venice: {
250
+ ...event.providerMetadata?.venice,
251
+ ...(state.signature ? { messageThoughtSignature: state.signature } : {}),
252
+ ...(signature ? { thoughtSignature: signature } : {}),
253
+ ...(event.type === "reasoning-end" && state.encrypted ? { encryptedReasoningContent: state.reasoning } : {}),
254
+ },
255
+ };
256
+ if (event.type === "reasoning-end" && state.pending)
257
+ return [LLMEvent.reasoningDelta({ id: event.id, text: state.pending }), { ...event, providerMetadata }];
258
+ return [{ ...event, providerMetadata }];
259
+ });
260
+ });
261
+ export const compatibility = {
262
+ maxTokensField: "max_completion_tokens",
263
+ supportsStore: false,
264
+ supportsPromptCacheKey: true,
265
+ };
266
+ export const protocol = Protocol.make({
267
+ id: "venice-chat",
268
+ body: { schema: Body, from: fromRequest },
269
+ stream: {
270
+ event: Schema.Union([Schema.Literal("[DONE]"), Protocol.jsonEvent(Event)]),
271
+ initial: (request) => ({
272
+ shared: OpenAIChat.protocol.stream.initial(request),
273
+ pending: "",
274
+ reasoning: "",
275
+ encrypted: false,
276
+ tools: {},
277
+ }),
278
+ step: (state, event) => (event === "[DONE]" ? Effect.succeed([state, []]) : step(state, event)),
279
+ terminal: (event) => event === "[DONE]",
280
+ onHalt,
281
+ },
282
+ });
283
+ export * as VeniceChat from "./venice-chat.js";
@@ -38,6 +38,15 @@ export declare const protocol: Protocol<{
38
38
  readonly error?: unknown;
39
39
  readonly arguments?: string | undefined;
40
40
  readonly server_label?: string | undefined;
41
+ } | {
42
+ readonly type: "configuration_update";
43
+ readonly reasoning: {
44
+ readonly effort: import("../schema/options.js").ReasoningEffort;
45
+ };
46
+ } | {
47
+ readonly [x: string]: unknown;
48
+ readonly type: string;
49
+ readonly id: string;
41
50
  } | {
42
51
  readonly type: "reasoning";
43
52
  readonly summary: readonly {
@@ -114,21 +123,6 @@ export declare const protocol: Protocol<{
114
123
  readonly type: "input_video";
115
124
  readonly video_url: string;
116
125
  })[];
117
- } | {
118
- readonly [x: string]: unknown;
119
- readonly id: string;
120
- readonly type: "x_search_call";
121
- readonly status?: string | undefined;
122
- readonly action?: {
123
- readonly [x: string]: unknown;
124
- } | null | undefined;
125
- } | {
126
- readonly [x: string]: unknown;
127
- readonly id: string;
128
- readonly type: "image_generation_call";
129
- readonly status?: string | undefined;
130
- readonly error?: unknown;
131
- readonly result?: unknown;
132
126
  })[];
133
127
  readonly model: string;
134
128
  readonly stream: true;
@@ -140,7 +134,10 @@ export declare const protocol: Protocol<{
140
134
  readonly summary?: "auto" | "concise" | "detailed" | undefined;
141
135
  readonly effort?: import("../schema/options.js").ReasoningEffort | undefined;
142
136
  } | undefined;
143
- readonly tools?: readonly {
137
+ readonly tools?: readonly ({
138
+ readonly [x: string]: unknown;
139
+ readonly type: string;
140
+ } | {
144
141
  readonly type: "function";
145
142
  readonly description: string;
146
143
  readonly name: string;
@@ -148,7 +145,7 @@ export declare const protocol: Protocol<{
148
145
  readonly [x: string]: unknown;
149
146
  };
150
147
  readonly strict?: boolean | undefined;
151
- }[] | undefined;
148
+ })[] | undefined;
152
149
  readonly text?: {
153
150
  readonly verbosity?: import("./utils/open-responses-options.js").TextVerbosity | undefined;
154
151
  } | undefined;
@@ -168,9 +165,10 @@ export declare const protocol: Protocol<{
168
165
  readonly top_p?: number | undefined;
169
166
  readonly frequency_penalty?: number | undefined;
170
167
  readonly presence_penalty?: number | undefined;
168
+ readonly store?: boolean | undefined;
169
+ readonly max_output_tokens?: number | undefined;
171
170
  readonly prompt_cache_key?: string | undefined;
172
171
  readonly parallel_tool_calls?: boolean | undefined;
173
- readonly store?: boolean | undefined;
174
172
  readonly include?: readonly import("./utils/open-responses-options.js").ResponseIncludable[] | undefined;
175
173
  readonly truncation?: "auto" | "disabled" | undefined;
176
174
  readonly stream_options?: {
@@ -178,7 +176,6 @@ export declare const protocol: Protocol<{
178
176
  } | undefined;
179
177
  readonly safety_identifier?: string | undefined;
180
178
  readonly top_logprobs?: number | undefined;
181
- readonly max_output_tokens?: number | undefined;
182
179
  readonly max_tool_calls?: number | undefined;
183
180
  }, string, {
184
181
  readonly [x: string]: unknown;
@@ -198,8 +195,8 @@ export declare const protocol: Protocol<{
198
195
  readonly name?: string | undefined;
199
196
  readonly namespace?: string | undefined;
200
197
  readonly arguments?: string | undefined;
201
- readonly encrypted_content?: string | null | undefined;
202
198
  readonly call_id?: string | undefined;
199
+ readonly encrypted_content?: string | null | undefined;
203
200
  }[] | undefined;
204
201
  readonly error?: unknown;
205
202
  readonly usage?: {
@@ -226,8 +223,8 @@ export declare const protocol: Protocol<{
226
223
  readonly name?: string | undefined;
227
224
  readonly namespace?: string | undefined;
228
225
  readonly arguments?: string | undefined;
229
- readonly encrypted_content?: string | null | undefined;
230
226
  readonly call_id?: string | undefined;
227
+ readonly encrypted_content?: string | null | undefined;
231
228
  } | null | undefined;
232
229
  readonly delta?: string | undefined;
233
230
  readonly arguments?: string | undefined;
@@ -21,17 +21,11 @@ const XAIResponsesHostedToolItem = Schema.Union([
21
21
  error: Schema.optional(Schema.Unknown),
22
22
  }), [JsonObject]),
23
23
  ]);
24
- const XAIResponsesBody = Schema.Struct({
25
- ...OpenResponses.coreFields,
26
- input: Schema.Array(Schema.Union([OpenResponses.InputItem, XAIResponsesHostedToolItem])),
27
- stream: Schema.Literal(true),
28
- });
29
24
  const adapter = {
30
25
  id: ADAPTER,
31
26
  name: NAME,
32
27
  restoreHostedToolItem: (item) => (Schema.is(XAIResponsesHostedToolItem)(item) ? item : undefined),
33
28
  };
34
- const decodeBody = ProviderShared.validateWith(Schema.decodeUnknownEffect(XAIResponsesBody));
35
29
  const fromRequest = Effect.fn("XAIResponses.fromRequest")(function* (request) {
36
30
  if (request.providerOptions?.contextManagement !== undefined)
37
31
  return yield* ProviderShared.unsupportedOperation({
@@ -40,7 +34,7 @@ const fromRequest = Effect.fn("XAIResponses.fromRequest")(function* (request) {
40
34
  route: request.model.route.id,
41
35
  message: "xAI requires explicit compaction through LLMClient.compact; automatic context management is not supported",
42
36
  });
43
- return yield* decodeBody(yield* OpenResponses.fromRequestWithAdapter(request, adapter));
37
+ return yield* OpenResponses.fromRequestWithAdapter(request, adapter);
44
38
  });
45
39
  const HOSTED_TOOLS = {
46
40
  web_search_call: { name: "web_search", input: (item) => item.action ?? {} },
@@ -67,7 +61,7 @@ const step = (state, input) => {
67
61
  export const protocol = Protocol.make({
68
62
  id: ADAPTER,
69
63
  body: {
70
- schema: XAIResponsesBody,
64
+ schema: OpenResponses.OpenResponsesBody,
71
65
  from: fromRequest,
72
66
  },
73
67
  stream: {
@@ -142,9 +142,9 @@ export declare const protocol: Protocol<{
142
142
  readonly top_p?: number | undefined;
143
143
  readonly frequency_penalty?: number | undefined;
144
144
  readonly presence_penalty?: number | undefined;
145
+ readonly store?: boolean | undefined;
145
146
  readonly prompt_cache_key?: string | undefined;
146
147
  readonly reasoning_effort?: import("../schema/options.js").ReasoningEffort | undefined;
147
- readonly store?: boolean | undefined;
148
148
  readonly stream_options?: {
149
149
  readonly include_usage: boolean;
150
150
  } | undefined;
@@ -163,16 +163,18 @@ export declare const protocol: Protocol<{
163
163
  } | null | undefined;
164
164
  readonly usage?: {
165
165
  readonly [x: string]: unknown;
166
+ readonly cache_read_input_tokens?: number | null | undefined;
166
167
  readonly cached_tokens?: number | null | undefined;
168
+ readonly total_tokens?: number | null | undefined;
167
169
  readonly prompt_tokens?: number | null | undefined;
168
170
  readonly completion_tokens?: number | null | undefined;
169
- readonly total_tokens?: number | null | undefined;
170
171
  readonly prompt_tokens_details?: {
171
172
  readonly [x: string]: unknown;
172
173
  readonly cached_tokens?: number | null | undefined;
173
174
  readonly cache_write_tokens?: number | null | undefined;
174
175
  } | null | undefined;
175
176
  readonly prompt_cache_hit_tokens?: number | null | undefined;
177
+ readonly cache_created_input_tokens?: number | null | undefined;
176
178
  readonly completion_tokens_details?: {
177
179
  readonly [x: string]: unknown;
178
180
  readonly reasoning_tokens?: number | null | undefined;
@@ -202,16 +204,18 @@ export declare const protocol: Protocol<{
202
204
  } | null | undefined;
203
205
  readonly usage?: {
204
206
  readonly [x: string]: unknown;
207
+ readonly cache_read_input_tokens?: number | null | undefined;
205
208
  readonly cached_tokens?: number | null | undefined;
209
+ readonly total_tokens?: number | null | undefined;
206
210
  readonly prompt_tokens?: number | null | undefined;
207
211
  readonly completion_tokens?: number | null | undefined;
208
- readonly total_tokens?: number | null | undefined;
209
212
  readonly prompt_tokens_details?: {
210
213
  readonly [x: string]: unknown;
211
214
  readonly cached_tokens?: number | null | undefined;
212
215
  readonly cache_write_tokens?: number | null | undefined;
213
216
  } | null | undefined;
214
217
  readonly prompt_cache_hit_tokens?: number | null | undefined;
218
+ readonly cache_created_input_tokens?: number | null | undefined;
215
219
  readonly completion_tokens_details?: {
216
220
  readonly [x: string]: unknown;
217
221
  readonly reasoning_tokens?: number | null | undefined;
@@ -19,15 +19,18 @@ const Body = Schema.Struct({
19
19
  request_id: Options.fields.requestID,
20
20
  user_id: Options.fields.userID,
21
21
  });
22
+ // Tool streaming was introduced in GLM-4.6; later versions inherit support.
23
+ const supportsToolStreaming = (modelID) => {
24
+ const match = /(?:^|\/)glm-(\d+)(?:\.(\d+))?(?:-|$)/i.exec(modelID);
25
+ return match !== null && (Number(match[1]) > 4 || (Number(match[1]) === 4 && Number(match[2] ?? 0) >= 6));
26
+ };
22
27
  const fromRequest = Effect.fn("ZAIChat.fromRequest")(function* (request) {
23
28
  const options = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Options))(request.providerOptions ?? {});
24
29
  const body = yield* OpenAIChat.protocol.body.from(request);
25
30
  return {
26
31
  ...body,
27
32
  thinking: options.thinking,
28
- // Tool streaming was introduced in GLM-4.6; older models must not receive the opt-in.
29
- tool_stream: options.toolStream ??
30
- (body.tools?.length && /^glm-(?:4\.[67]|5(?:[.-]|$))/i.test(request.model.id) ? true : undefined),
33
+ tool_stream: options.toolStream ?? (body.tools?.length && supportsToolStreaming(request.model.id) ? true : undefined),
31
34
  do_sample: options.doSample,
32
35
  response_format: options.responseFormat,
33
36
  request_id: options.requestID,
@@ -13,18 +13,24 @@ const patterns = [
13
13
  /tokens in request more than max tokens allowed/i,
14
14
  /maximum prompt length is \d+/i,
15
15
  /reduce the length of the messages/i,
16
+ // DeepInfra
17
+ /requested input length \d+ exceeds maximum input length/i,
16
18
  /maximum context length is \d+ tokens/i,
17
19
  /exceeds (?:the )?maximum allowed input length of [\d,]+ tokens?/i,
18
- /input \(\d+ tokens\) is longer than the model'?s context length \(\d+ tokens\)/i,
20
+ // Novita omits the token counts.
21
+ /input(?: \(\d+ tokens\))? is longer than the model'?s context length/i,
19
22
  /exceeds the limit of \d+/i,
20
23
  /exceeds the available context size/i,
21
24
  /greater than the context length/i,
25
+ // Hugging Face Text Generation Inference, e.g. Together
26
+ /`inputs` tokens \+ `max_new_tokens` must be <= \d+/i,
22
27
  /context window exceeds limit/i,
23
28
  /exceeded model token limit/i,
24
29
  /context[_ ]length[_ ]exceeded/i,
25
30
  /context length is only \d+ tokens/i,
26
31
  /input length.*exceeds.*context length/i,
27
- /prompt too long; exceeded (?:max )?context length/i,
32
+ // Z.ai code 1261 arrives as `Prompt too long` or `Prompt 超长`.
33
+ /prompt (?:too long|超长)/i,
28
34
  /too large for model with \d+ maximum context length/i,
29
35
  /prompt has [\d,]+ tokens?, but the configured context size is [\d,]+ tokens?/i,
30
36
  /model_context_window_exceeded/i,
@@ -34,7 +40,13 @@ const patterns = [
34
40
  /request_too_large/i,
35
41
  ];
36
42
  const payloadPatterns = [/request entity too large/i, /payload too large/i, /request too large/i];
37
- const exclusions = [/^(throttling error|service unavailable):/i, /rate limit/i, /too many requests/i];
43
+ const exclusions = [
44
+ /^(throttling error|service unavailable):/i,
45
+ /rate limit/i,
46
+ /too many requests/i,
47
+ // Cohere reports an output limit above the model maximum as "too many tokens"; compaction cannot fix it.
48
+ /max[_ ]tokens must be less than/i,
49
+ ];
38
50
  export const isContextOverflow = (message) => !exclusions.some((pattern) => pattern.test(message)) &&
39
51
  (patterns.some((pattern) => pattern.test(message)) || /^4(?:00|13)\s*(status code)?\s*\(no body\)/i.test(message));
40
52
  export const isPayloadTooLarge = (message) => payloadPatterns.some((pattern) => pattern.test(message));
@@ -92,7 +104,8 @@ const QUOTA_CODES = new Set([
92
104
  "creditlimitexceeded",
93
105
  ]);
94
106
  // Google reports an invalid API key as HTTP 400 INVALID_ARGUMENT with this `details[].reason`.
95
- const AUTH_CODES = new Set(["authentication_error", "permission_error", "api_key_invalid"]);
107
+ // Z.ai's Responses API reports account and plan rejections mid-stream as `permission_denied`.
108
+ const AUTH_CODES = new Set(["authentication_error", "permission_error", "permission_denied", "api_key_invalid"]);
96
109
  const SERVER_CODES = new Set([
97
110
  "api_error",
98
111
  "internal_error",
@@ -106,6 +119,7 @@ const SERVER_CODES = new Set([
106
119
  ]);
107
120
  // `invalid_request` is the Vercel AI Gateway's code for an upstream request rejection.
108
121
  const INVALID_REQUEST_CODES = new Set([
122
+ "model_not_found",
109
123
  "invalid_prompt",
110
124
  "invalid_request",
111
125
  "invalid_request_error",
@@ -125,14 +139,17 @@ const CONTENT_POLICY_CODES = new Set([
125
139
  // OpenCode Zen replaces upstream codes outside its allow-list but keeps the original
126
140
  // as a `[code]` label at the start of the rewritten message.
127
141
  const GATEWAY_CODE_LABEL = /^[^:\n]+: \[([A-Za-z0-9_.-]+)\]/;
142
+ // xAI reports an invalid API key as HTTP 400 with the generic `invalid-argument` code.
143
+ const AUTH_TEXT = /incorrect api key provided/i;
128
144
  const RATE_LIMIT_TEXT = /rate increased too quickly|rate[-_\s]?limit|too[_\s]?many[_\s]?requests/i;
129
145
  // Only consulted on 429, where throttles and account caps share a status.
130
- const QUOTA_TEXT = /insufficient[-_\s]?quota|quota[-_\s]?exceeded|budget exceeded|usage limit/i;
146
+ // Z.ai reports balance, plan expiry, plan limits, and plan model access on 429.
147
+ const QUOTA_TEXT = /insufficient[-_\s]?(?:quota|balance)|quota[-_\s]?exceeded|budget exceeded|usage limit|limit exhausted|package has expired|plan does not yet include/i;
131
148
  // Policy rejections without a dedicated code, matched against the provider's own
132
149
  // explanation only. OpenAI reuses `invalid_prompt` for usage-policy rejections while
133
150
  // Bedrock Mantle reuses it for schema validation; Anthropic reports blocked output
134
151
  // under `invalid_request_error`.
135
- const CONTENT_POLICY_TEXT = /violating our usage policy|blocked by content filtering policy|content[-_\s]?policy|rejected as a result of our safety system/i;
152
+ const CONTENT_POLICY_TEXT = /violating our usage policy|blocked by content filtering policy|content[-_\s]?policy|rejected as a result of our safety system|detected potentially unsafe or sensitive content/i;
136
153
  const SERVER_ERROR_TEXT = /\b(?:try again|(?:please |you can )?retry (?:the |this |your )?request|try (?:the |this |your )?request again|(?:currently |temporarily )?at capacity|overloaded|temporarily unavailable|service[-_\s]?unavailable|(?:server|internal)[-_\s]?error|server (?:is )?busy|provider returned (?:an )?error|resource[-_\s]?exhausted|upstream (?:connect|connection|request)|request buffer limit while retrying upstream)\b/i;
137
154
  const Message = Schema.String.check(Schema.isPattern(/\S/));
138
155
  const messageAt = (fields, message) => Schema.Struct(fields).pipe(Schema.decodeTo(Schema.String, {
@@ -185,7 +202,10 @@ export function classifyProviderFailure(input) {
185
202
  codes.some((code) => QUOTA_CODES.has(code)) ||
186
203
  (input.status === 429 && QUOTA_TEXT.test(text)))
187
204
  return new QuotaExceededError(details);
188
- if (input.status === 401 || input.status === 403 || codes.some((code) => AUTH_CODES.has(code)))
205
+ if (input.status === 401 ||
206
+ input.status === 403 ||
207
+ codes.some((code) => AUTH_CODES.has(code)) ||
208
+ (input.status === 400 && AUTH_TEXT.test(text)))
189
209
  return new AuthenticationError(details);
190
210
  if (input.status === 429 ||
191
211
  codes.some((code) => code.includes("rate_limit") || code === "too_many_requests" || code === "throttlingexception") ||