@opencode/ai 2.0.23 → 2.0.24

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 CHANGED
@@ -1283,7 +1283,7 @@ const gateway = CloudflareAIGateway.configure({
1283
1283
  }).model("workers-ai/@cf/meta/llama-3.1-8b-instruct")
1284
1284
  ```
1285
1285
 
1286
- Included LLM providers: OpenAI, Anthropic, Google (Gemini), Google Vertex, Amazon Bedrock, Azure OpenAI, Baseten, Cerebras, Cohere, Cloudflare AI Gateway, Cloudflare Workers AI, DeepInfra, DeepSeek, Fireworks, Groq, Mistral, OpenRouter, TogetherAI, and xAI. Z.ai currently exposes image generation. Generic Chat Completions, Responses, and Anthropic Messages-compatible entrypoints support custom endpoints.
1286
+ Included LLM providers: OpenAI, Anthropic, Google (Gemini), Google Vertex, Amazon Bedrock, Azure OpenAI, Baseten, Cerebras, Cohere, Cloudflare AI Gateway, Cloudflare Workers AI, DeepInfra, DeepSeek, Fireworks, Groq, Mistral, OpenRouter, TogetherAI, Vercel AI Gateway, and xAI. Z.ai currently exposes image generation. Generic Chat Completions, Responses, and Anthropic Messages-compatible entrypoints support custom endpoints.
1287
1287
 
1288
1288
  Each named provider owns its module, endpoint, authentication, and route setup. Providers with the same wire format compose the shared protocol directly:
1289
1289
 
@@ -46,21 +46,22 @@ const RESPECTS_INLINE_HINTS = new Set([
46
46
  "meta-messages",
47
47
  "minimax-messages",
48
48
  "moonshot-messages",
49
+ "vercel-ai-gateway-messages",
49
50
  "zai-coding-messages",
50
51
  "bedrock-converse",
51
52
  "openrouter",
52
53
  "digitalocean",
53
54
  ]);
54
- // OpenRouter upstreams other than Anthropic and Alibaba Qwen cache without breakpoints. Gemini uses only the last
55
- // breakpoint, so a conversation-tail breakpoint writes a new cache every step and costs more than none. Qwen ignores
56
- // breakpoints on tool definitions and caches tools with the system prompt.
55
+ // OpenRouter and Vercel AI Gateway upstreams other than Anthropic and Alibaba Qwen cache without breakpoints.
56
+ // Gemini uses only the last breakpoint, so a conversation-tail breakpoint writes a new cache every step and costs
57
+ // more than none. Qwen ignores breakpoints on tool definitions and caches tools with the system prompt.
57
58
  const QWEN = { system: true, messages: { tail: 1 } };
58
- const openRouterPolicy = (modelID) => {
59
+ const gatewayPolicy = (modelID) => {
59
60
  // `~anthropic/claude-sonnet-latest` style IDs are OpenRouter aliases for the latest model in a family.
60
61
  const id = modelID.replace(/^~/, "");
61
62
  if (id.startsWith("anthropic/"))
62
63
  return AUTO;
63
- if (id.startsWith("qwen/"))
64
+ if (id.startsWith("qwen/") || id.startsWith("alibaba/qwen"))
64
65
  return QWEN;
65
66
  return NONE;
66
67
  };
@@ -142,11 +143,13 @@ const countHints = (request) => countToolHints(request.tools) +
142
143
  request.messages.reduce((count, message) => count +
143
144
  message.content.reduce((contentCount, part) => contentCount + ("cache" in part && part.cache !== undefined ? 1 : 0), 0), 0);
144
145
  export const applyCachePolicy = (request) => {
145
- if (!RESPECTS_INLINE_HINTS.has(request.model.route.id))
146
+ const route = request.model.route.id;
147
+ if (!RESPECTS_INLINE_HINTS.has(route))
146
148
  return request;
147
- const policy = request.model.route.id === "openrouter" && (request.cache === undefined || request.cache === "auto")
148
- ? openRouterPolicy(request.model.id)
149
- : request.model.route.id === "alibaba-chat" && (request.cache === undefined || request.cache === "auto")
149
+ const policy = (route === "openrouter" || route === "vercel-ai-gateway-messages") &&
150
+ (request.cache === undefined || request.cache === "auto")
151
+ ? gatewayPolicy(request.model.id)
152
+ : route === "alibaba-chat" && (request.cache === undefined || request.cache === "auto")
150
153
  ? request.model.id.toLowerCase().startsWith("qwen")
151
154
  ? QWEN
152
155
  : NONE
@@ -272,8 +272,10 @@ export declare const protocol: Protocol<{
272
272
  readonly top_k?: number | undefined;
273
273
  readonly stop_sequences?: readonly string[] | undefined;
274
274
  }, string, {
275
+ readonly [x: string]: unknown;
275
276
  readonly type: string;
276
277
  readonly message?: {
278
+ readonly [x: string]: unknown;
277
279
  readonly usage?: {
278
280
  readonly [x: string]: unknown;
279
281
  readonly input_tokens?: number | null | undefined;
@@ -306,6 +308,7 @@ export declare const protocol: Protocol<{
306
308
  } | undefined;
307
309
  } | undefined;
308
310
  readonly error?: {
311
+ readonly [x: string]: unknown;
309
312
  readonly type?: string | undefined;
310
313
  readonly message?: string | undefined;
311
314
  } | undefined;
@@ -213,13 +213,16 @@ export declare const protocol: Protocol<{
213
213
  }[] | undefined;
214
214
  readonly error?: unknown;
215
215
  readonly usage?: {
216
+ readonly [x: string]: unknown;
216
217
  readonly input_tokens?: number | undefined;
217
218
  readonly output_tokens?: number | undefined;
218
219
  readonly output_tokens_details?: {
220
+ readonly [x: string]: unknown;
219
221
  readonly reasoning_tokens?: number | undefined;
220
222
  } | null | undefined;
221
223
  readonly total_tokens?: number | undefined;
222
224
  readonly input_tokens_details?: {
225
+ readonly [x: string]: unknown;
223
226
  readonly cached_tokens?: number | undefined;
224
227
  readonly cache_write_tokens?: number | undefined;
225
228
  } | null | undefined;
@@ -684,8 +684,10 @@ export declare const protocol: Protocol<{
684
684
  readonly top_k?: number | undefined;
685
685
  readonly stop_sequences?: readonly string[] | undefined;
686
686
  }, string, {
687
+ readonly [x: string]: unknown;
687
688
  readonly type: string;
688
689
  readonly message?: {
690
+ readonly [x: string]: unknown;
689
691
  readonly usage?: {
690
692
  readonly [x: string]: unknown;
691
693
  readonly input_tokens?: number | null | undefined;
@@ -718,6 +720,7 @@ export declare const protocol: Protocol<{
718
720
  } | undefined;
719
721
  } | undefined;
720
722
  readonly error?: {
723
+ readonly [x: string]: unknown;
721
724
  readonly type?: string | undefined;
722
725
  readonly message?: string | undefined;
723
726
  } | undefined;
@@ -332,7 +332,7 @@ const AnthropicUsage = Schema.StructWithRest(Schema.Struct({
332
332
  ...AnthropicIterationUsage.schema.fields,
333
333
  iterations: Schema.optional(Schema.Array(AnthropicIterationUsage)),
334
334
  }), [JsonObject]);
335
- const AnthropicStreamBlock = Schema.Struct({
335
+ const AnthropicStreamBlock = Schema.StructWithRest(Schema.Struct({
336
336
  type: Schema.String,
337
337
  id: Schema.optional(Schema.String),
338
338
  name: Schema.optional(Schema.String),
@@ -348,9 +348,9 @@ const AnthropicStreamBlock = Schema.Struct({
348
348
  // server_tool_use id in `tool_use_id`.
349
349
  tool_use_id: Schema.optional(Schema.String),
350
350
  content: Schema.optional(Schema.Unknown),
351
- });
351
+ }), [JsonObject]);
352
352
  const decodeAnthropicStreamBlock = Schema.decodeUnknownOption(AnthropicStreamBlock);
353
- const AnthropicStreamDelta = Schema.Struct({
353
+ const AnthropicStreamDelta = Schema.StructWithRest(Schema.Struct({
354
354
  content: optionalNull(Schema.String),
355
355
  type: Schema.optional(Schema.String),
356
356
  text: Schema.optional(Schema.String),
@@ -359,13 +359,13 @@ const AnthropicStreamDelta = Schema.Struct({
359
359
  signature: Schema.optional(Schema.String),
360
360
  stop_reason: optionalNull(Schema.String),
361
361
  stop_sequence: optionalNull(Schema.String),
362
- stop_details: optionalNull(Schema.Struct({ category: optionalNull(Schema.String), explanation: optionalNull(Schema.String) })),
363
- });
362
+ stop_details: optionalNull(Schema.StructWithRest(Schema.Struct({ category: optionalNull(Schema.String), explanation: optionalNull(Schema.String) }), [JsonObject])),
363
+ }), [JsonObject]);
364
364
  const decodeAnthropicStreamDelta = Schema.decodeUnknownOption(AnthropicStreamDelta);
365
- const AnthropicEvent = Schema.Struct({
365
+ const AnthropicEvent = Schema.StructWithRest(Schema.Struct({
366
366
  type: Schema.String,
367
367
  index: Schema.optional(Schema.Number),
368
- message: Schema.optional(Schema.Struct({ usage: Schema.optional(AnthropicUsage) })),
368
+ message: Schema.optional(Schema.StructWithRest(Schema.Struct({ usage: Schema.optional(AnthropicUsage) }), [JsonObject])),
369
369
  content_block: Schema.optional(Schema.Unknown),
370
370
  delta: Schema.optional(Schema.Unknown),
371
371
  usage: Schema.optional(AnthropicUsage),
@@ -373,8 +373,8 @@ const AnthropicEvent = Schema.Struct({
373
373
  // OpenAI-compatible proxies and gateway translations occasionally drop one
374
374
  // or the other; mark them optional so a partial payload still parses and
375
375
  // the parser can fall back to whichever field is populated.
376
- error: Schema.optional(Schema.Struct({ type: Schema.optional(Schema.String), message: Schema.optional(Schema.String) })),
377
- });
376
+ error: Schema.optional(Schema.StructWithRest(Schema.Struct({ type: Schema.optional(Schema.String), message: Schema.optional(Schema.String) }), [JsonObject])),
377
+ }), [JsonObject]);
378
378
  const invalid = ProviderShared.invalidRequest;
379
379
  // =============================================================================
380
380
  // Request Lowering
@@ -282,8 +282,10 @@ export declare const protocol: Protocol<{
282
282
  readonly top_k?: number | undefined;
283
283
  readonly stop_sequences?: readonly string[] | undefined;
284
284
  }, string, {
285
+ readonly [x: string]: unknown;
285
286
  readonly type: string;
286
287
  readonly message?: {
288
+ readonly [x: string]: unknown;
287
289
  readonly usage?: {
288
290
  readonly [x: string]: unknown;
289
291
  readonly input_tokens?: number | null | undefined;
@@ -316,6 +318,7 @@ export declare const protocol: Protocol<{
316
318
  } | undefined;
317
319
  } | undefined;
318
320
  readonly error?: {
321
+ readonly [x: string]: unknown;
319
322
  readonly type?: string | undefined;
320
323
  readonly message?: string | undefined;
321
324
  } | undefined;
@@ -224,13 +224,16 @@ export declare const protocol: Protocol<{
224
224
  }[] | undefined;
225
225
  readonly error?: unknown;
226
226
  readonly usage?: {
227
+ readonly [x: string]: unknown;
227
228
  readonly input_tokens?: number | undefined;
228
229
  readonly output_tokens?: number | undefined;
229
230
  readonly output_tokens_details?: {
231
+ readonly [x: string]: unknown;
230
232
  readonly reasoning_tokens?: number | undefined;
231
233
  } | null | undefined;
232
234
  readonly total_tokens?: number | undefined;
233
235
  readonly input_tokens_details?: {
236
+ readonly [x: string]: unknown;
234
237
  readonly cached_tokens?: number | undefined;
235
238
  readonly cache_write_tokens?: number | undefined;
236
239
  } | null | undefined;
@@ -559,18 +559,18 @@ export declare const OpenResponsesBody: Schema.Struct<{
559
559
  readonly frequency_penalty: Schema.optional<Schema.Number>;
560
560
  }>;
561
561
  export type OpenResponsesBody = Schema.Schema.Type<typeof OpenResponsesBody>;
562
- export declare const OpenResponsesUsage: Schema.Struct<{
562
+ export declare const OpenResponsesUsage: Schema.StructWithRest<Schema.Struct<{
563
563
  readonly input_tokens: Schema.optional<Schema.Number>;
564
- readonly input_tokens_details: Schema.optional<Schema.NullOr<Schema.Struct<{
564
+ readonly input_tokens_details: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
565
565
  readonly cached_tokens: Schema.optional<Schema.Number>;
566
566
  readonly cache_write_tokens: Schema.optional<Schema.Number>;
567
- }>>>;
567
+ }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
568
568
  readonly output_tokens: Schema.optional<Schema.Number>;
569
- readonly output_tokens_details: Schema.optional<Schema.NullOr<Schema.Struct<{
569
+ readonly output_tokens_details: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
570
570
  readonly reasoning_tokens: Schema.optional<Schema.Number>;
571
- }>>>;
571
+ }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
572
572
  readonly total_tokens: Schema.optional<Schema.Number>;
573
- }>;
573
+ }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>;
574
574
  type OpenResponsesUsage = Schema.Schema.Type<typeof OpenResponsesUsage>;
575
575
  export declare const StreamItem: Schema.StructWithRest<Schema.Struct<{
576
576
  readonly type: Schema.String;
@@ -617,18 +617,18 @@ export declare const Event: Schema.StructWithRest<Schema.Struct<{
617
617
  readonly arguments: Schema.optional<Schema.String>;
618
618
  readonly encrypted_content: Schema.optional<Schema.NullOr<Schema.String>>;
619
619
  }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
620
- readonly usage: Schema.optional<Schema.NullOr<Schema.Struct<{
620
+ readonly usage: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
621
621
  readonly input_tokens: Schema.optional<Schema.Number>;
622
- readonly input_tokens_details: Schema.optional<Schema.NullOr<Schema.Struct<{
622
+ readonly input_tokens_details: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
623
623
  readonly cached_tokens: Schema.optional<Schema.Number>;
624
624
  readonly cache_write_tokens: Schema.optional<Schema.Number>;
625
- }>>>;
625
+ }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
626
626
  readonly output_tokens: Schema.optional<Schema.Number>;
627
- readonly output_tokens_details: Schema.optional<Schema.NullOr<Schema.Struct<{
627
+ readonly output_tokens_details: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
628
628
  readonly reasoning_tokens: Schema.optional<Schema.Number>;
629
- }>>>;
629
+ }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
630
630
  readonly total_tokens: Schema.optional<Schema.Number>;
631
- }>>>;
631
+ }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
632
632
  readonly error: Schema.optional<Schema.Unknown>;
633
633
  }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>;
634
634
  readonly code: Schema.optional<Schema.Unknown>;
@@ -669,13 +669,16 @@ export declare const decodeChannelEvent: (frame: string) => Effect.Effect<{
669
669
  }[] | undefined;
670
670
  readonly error?: unknown;
671
671
  readonly usage?: {
672
+ readonly [x: string]: unknown;
672
673
  readonly input_tokens?: number | undefined;
673
674
  readonly output_tokens?: number | undefined;
674
675
  readonly output_tokens_details?: {
676
+ readonly [x: string]: unknown;
675
677
  readonly reasoning_tokens?: number | undefined;
676
678
  } | null | undefined;
677
679
  readonly total_tokens?: number | undefined;
678
680
  readonly input_tokens_details?: {
681
+ readonly [x: string]: unknown;
679
682
  readonly cached_tokens?: number | undefined;
680
683
  readonly cache_write_tokens?: number | undefined;
681
684
  } | null | undefined;
@@ -1721,13 +1724,16 @@ export declare const protocol: Protocol<{
1721
1724
  }[] | undefined;
1722
1725
  readonly error?: unknown;
1723
1726
  readonly usage?: {
1727
+ readonly [x: string]: unknown;
1724
1728
  readonly input_tokens?: number | undefined;
1725
1729
  readonly output_tokens?: number | undefined;
1726
1730
  readonly output_tokens_details?: {
1731
+ readonly [x: string]: unknown;
1727
1732
  readonly reasoning_tokens?: number | undefined;
1728
1733
  } | null | undefined;
1729
1734
  readonly total_tokens?: number | undefined;
1730
1735
  readonly input_tokens_details?: {
1736
+ readonly [x: string]: unknown;
1731
1737
  readonly cached_tokens?: number | undefined;
1732
1738
  readonly cache_write_tokens?: number | undefined;
1733
1739
  } | null | undefined;
@@ -221,16 +221,16 @@ export const OpenResponsesBody = Schema.Struct({
221
221
  ...coreFields,
222
222
  stream: Schema.Literal(true),
223
223
  });
224
- export const OpenResponsesUsage = Schema.Struct({
224
+ export const OpenResponsesUsage = Schema.StructWithRest(Schema.Struct({
225
225
  input_tokens: Schema.optional(Schema.Number),
226
- input_tokens_details: optionalNull(Schema.Struct({
226
+ input_tokens_details: optionalNull(Schema.StructWithRest(Schema.Struct({
227
227
  cached_tokens: Schema.optional(Schema.Number),
228
228
  cache_write_tokens: Schema.optional(Schema.Number),
229
- })),
229
+ }), [JsonObject])),
230
230
  output_tokens: Schema.optional(Schema.Number),
231
- output_tokens_details: optionalNull(Schema.Struct({ reasoning_tokens: Schema.optional(Schema.Number) })),
231
+ output_tokens_details: optionalNull(Schema.StructWithRest(Schema.Struct({ reasoning_tokens: Schema.optional(Schema.Number) }), [JsonObject])),
232
232
  total_tokens: Schema.optional(Schema.Number),
233
- });
233
+ }), [JsonObject]);
234
234
  // The spec requires `id` on every output item, but some gateways drop it from
235
235
  // later item events (Bedrock Mantle renames it to `item_id` on
236
236
  // `output_item.done` and `response.completed.output`). Decode it as optional
@@ -429,13 +429,16 @@ export declare const protocol: Protocol<{
429
429
  }[] | undefined;
430
430
  readonly error?: unknown;
431
431
  readonly usage?: {
432
+ readonly [x: string]: unknown;
432
433
  readonly input_tokens?: number | undefined;
433
434
  readonly output_tokens?: number | undefined;
434
435
  readonly output_tokens_details?: {
436
+ readonly [x: string]: unknown;
435
437
  readonly reasoning_tokens?: number | undefined;
436
438
  } | null | undefined;
437
439
  readonly total_tokens?: number | undefined;
438
440
  readonly input_tokens_details?: {
441
+ readonly [x: string]: unknown;
439
442
  readonly cached_tokens?: number | undefined;
440
443
  readonly cache_write_tokens?: number | undefined;
441
444
  } | null | undefined;
@@ -0,0 +1,17 @@
1
+ import { Effect } from "effect";
2
+ import { Protocol } from "../../route/protocol.js";
3
+ import { type AIError, type LLMRequest } from "../../schema/index.js";
4
+ interface ParserState<Inner> {
5
+ readonly inner: Inner;
6
+ readonly gateway?: Record<string, unknown>;
7
+ }
8
+ export declare function gatewayProtocol<Body, Event, State>(protocol: Protocol<Body, string, Event, State>, input: {
9
+ readonly id: string;
10
+ readonly prepare: (request: LLMRequest) => Effect.Effect<{
11
+ readonly request: LLMRequest;
12
+ readonly body: Record<string, unknown>;
13
+ }, AIError>;
14
+ }): Protocol<{
15
+ readonly [x: string]: unknown;
16
+ }, string, Event, ParserState<State>>;
17
+ export {};
@@ -0,0 +1,57 @@
1
+ import { Effect, Option, Schema } from "effect";
2
+ import { Protocol } from "../../route/protocol.js";
3
+ import { LLMEvent, mergeJsonRecords } from "../../schema/index.js";
4
+ import { JsonObject, lenient } from "../shared.js";
5
+ const GatewayHolder = Schema.Struct({
6
+ provider_metadata: lenient(Schema.Struct({
7
+ gateway: lenient(JsonObject),
8
+ })),
9
+ });
10
+ const GatewayEvent = Schema.Struct({
11
+ ...GatewayHolder.fields,
12
+ response: lenient(GatewayHolder),
13
+ choices: lenient(Schema.Array(Schema.Struct({
14
+ delta: lenient(GatewayHolder),
15
+ }))),
16
+ });
17
+ const decodeGatewayEvent = Schema.decodeUnknownOption(GatewayEvent);
18
+ function attachGatewayMetadata(events, gateway) {
19
+ if (!gateway || !events.some(LLMEvent.is.finish))
20
+ return events;
21
+ return events.map((event) => LLMEvent.is.finish(event) ? { ...event, providerMetadata: { ...event.providerMetadata, gateway } } : event);
22
+ }
23
+ export function gatewayProtocol(protocol, input) {
24
+ const initial = (request) => ({
25
+ inner: protocol.stream.initial(request),
26
+ });
27
+ const onHalt = protocol.stream.onHalt;
28
+ return Protocol.make({
29
+ id: input.id,
30
+ body: {
31
+ schema: JsonObject,
32
+ from: Effect.fnUntraced(function* (request) {
33
+ const prepared = yield* input.prepare(request);
34
+ const body = yield* protocol.body.from(prepared.request);
35
+ return { ...body, ...prepared.body };
36
+ }),
37
+ },
38
+ supportsEffortUpdates: protocol.supportsEffortUpdates,
39
+ sanitizer: protocol.sanitizer,
40
+ stream: {
41
+ event: protocol.stream.event,
42
+ initial,
43
+ step: Effect.fnUntraced(function* (state, event) {
44
+ const decoded = Option.getOrUndefined(decodeGatewayEvent(event));
45
+ const gateway = decoded
46
+ ? mergeJsonRecords(state.gateway, decoded.provider_metadata?.gateway, decoded.response?.provider_metadata?.gateway, ...(decoded.choices ?? []).map((choice) => choice.delta?.provider_metadata?.gateway))
47
+ : state.gateway;
48
+ const [inner, events] = yield* protocol.stream.step(state.inner, event);
49
+ return [{ inner, gateway }, attachGatewayMetadata(events, gateway)];
50
+ }),
51
+ terminal: protocol.stream.terminal,
52
+ onHalt: onHalt
53
+ ? (state) => onHalt(state.inner).pipe(Effect.map((events) => attachGatewayMetadata(events, state.gateway)))
54
+ : undefined,
55
+ },
56
+ });
57
+ }
@@ -200,13 +200,16 @@ export declare const protocol: Protocol<{
200
200
  }[] | undefined;
201
201
  readonly error?: unknown;
202
202
  readonly usage?: {
203
+ readonly [x: string]: unknown;
203
204
  readonly input_tokens?: number | undefined;
204
205
  readonly output_tokens?: number | undefined;
205
206
  readonly output_tokens_details?: {
207
+ readonly [x: string]: unknown;
206
208
  readonly reasoning_tokens?: number | undefined;
207
209
  } | null | undefined;
208
210
  readonly total_tokens?: number | undefined;
209
211
  readonly input_tokens_details?: {
212
+ readonly [x: string]: unknown;
210
213
  readonly cached_tokens?: number | undefined;
211
214
  readonly cache_write_tokens?: number | undefined;
212
215
  } | null | undefined;
@@ -266,8 +266,10 @@ export declare const protocol: Protocol<{
266
266
  readonly top_k?: number | undefined;
267
267
  readonly stop_sequences?: readonly string[] | undefined;
268
268
  }, string, {
269
+ readonly [x: string]: unknown;
269
270
  readonly type: string;
270
271
  readonly message?: {
272
+ readonly [x: string]: unknown;
271
273
  readonly usage?: {
272
274
  readonly [x: string]: unknown;
273
275
  readonly input_tokens?: number | null | undefined;
@@ -300,6 +302,7 @@ export declare const protocol: Protocol<{
300
302
  } | undefined;
301
303
  } | undefined;
302
304
  readonly error?: {
305
+ readonly [x: string]: unknown;
303
306
  readonly type?: string | undefined;
304
307
  readonly message?: string | undefined;
305
308
  } | undefined;
@@ -26,6 +26,7 @@ const route = Route.make({
26
26
  }))),
27
27
  },
28
28
  stream: AnthropicMessages.protocol.stream,
29
+ supportsEffortUpdates: AnthropicMessages.protocol.supportsEffortUpdates,
29
30
  }),
30
31
  endpoint: Endpoint.path(({ request }) => `/${request.model.id}:streamRawPredict`),
31
32
  auth: Auth.none,
@@ -0,0 +1,2 @@
1
+ export { chatModel as model } from "../vercel-ai-gateway.js";
2
+ export type { Settings } from "../vercel-ai-gateway.js";
@@ -0,0 +1 @@
1
+ export { chatModel as model } from "../vercel-ai-gateway.js";
@@ -0,0 +1,2 @@
1
+ export { messagesModel as model } from "../vercel-ai-gateway.js";
2
+ export type { Settings } from "../vercel-ai-gateway.js";
@@ -0,0 +1 @@
1
+ export { messagesModel as model } from "../vercel-ai-gateway.js";
@@ -0,0 +1,2 @@
1
+ export { responsesModel as model } from "../vercel-ai-gateway.js";
2
+ export type { Settings } from "../vercel-ai-gateway.js";
@@ -0,0 +1 @@
1
+ export { responsesModel as model } from "../vercel-ai-gateway.js";
@@ -1,22 +1,89 @@
1
1
  import { EvaluationModel } from "../experimental/evaluation.js";
2
+ import { AnthropicMessages } from "../protocols/anthropic-messages.js";
3
+ import type { ProviderPackage } from "../provider-package.js";
2
4
  import { type ProviderAuthOption } from "../route/auth-options.js";
3
- import { HttpOptions, ModelID } from "../schema/index.js";
5
+ import { Route, type RouteDefaultsInput } from "../route/client.js";
6
+ import { ModelID } from "../schema/index.js";
7
+ import type { OpenResponsesProviderOptionsInput } from "./open-responses-options.js";
4
8
  export declare const id: string & import("effect/Brand").Brand<"AI.ProviderID">;
5
- export interface EvaluationOptions {
9
+ export interface GatewayOptions {
10
+ /** Service-owned options added by the Gateway without requiring an SDK update. */
6
11
  readonly [key: string]: unknown;
7
- readonly gateway?: Readonly<{
12
+ /** Enables Gateway automatic prompt-cache breakpoint injection (`"auto"`). */
13
+ readonly caching?: "auto" | (string & {});
14
+ /** Provider slugs that are the only ones allowed to serve the request (e.g. `["anthropic", "vertex"]`). */
15
+ readonly only?: ReadonlyArray<string>;
16
+ /** Provider slugs specifying the order in which providers are tried (e.g. `["bedrock", "anthropic"]`). */
17
+ readonly order?: ReadonlyArray<string>;
18
+ /** Sort candidate providers by cost (`"cost"`), throughput (`"tps"`), or time-to-first-token (`"ttft"`). */
19
+ readonly sort?: "cost" | "tps" | "ttft" | (string & {});
20
+ /** Fallback models to try in order, or a conditional `{ model, when }` entry on evaluation requests. */
21
+ readonly models?: ReadonlyArray<string | Readonly<Record<string, unknown>>>;
22
+ /** Restrict routing to providers with zero data retention agreements. */
23
+ readonly zeroDataRetention?: boolean;
24
+ /** Restrict routing to providers that do not train on prompt data. */
25
+ readonly disallowPromptTraining?: boolean;
26
+ /**
27
+ * Restrict routing to provider models that satisfy every entry: capability
28
+ * tags (`"implicit-caching"`, `"reasoning"`, `"structured-output"`,
29
+ * `"tool-use"`, `"vision"`) or weight-format filters (`"quantization:fp8"`,
30
+ * `"!quantization:fp8"`).
31
+ */
32
+ readonly has?: ReadonlyArray<"implicit-caching" | "reasoning" | "structured-output" | "tool-use" | "vision" | `quantization:${string}` | `!quantization:${string}` | (string & {})>;
33
+ /** Entity identifier against which Gateway quota is tracked. */
34
+ readonly quotaEntityId?: string;
35
+ /** Unified service tier intent (`"flex"` or `"priority"`). */
36
+ readonly serviceTier?: "flex" | "priority" | (string & {});
37
+ /** End-user identifier for spend tracking and attribution. */
38
+ readonly user?: string;
39
+ /** User-specified tags for reporting and filtering usage. */
40
+ readonly tags?: ReadonlyArray<string>;
41
+ /** Request-scoped BYOK credentials keyed by provider slug, used instead of cached workspace credentials. */
42
+ readonly byok?: Readonly<Record<string, ReadonlyArray<Readonly<Record<string, unknown>>>>>;
43
+ /** Preferred inference region for upstream provider routing. */
44
+ readonly inferenceRegion?: string;
45
+ /** Per-provider timeouts in milliseconds (e.g. `{ byok: { anthropic: 3000 } }`). */
46
+ readonly providerTimeouts?: {
8
47
  readonly [key: string]: unknown;
9
- readonly zeroDataRetention?: boolean;
10
- readonly only?: ReadonlyArray<string>;
11
- }>;
48
+ readonly byok?: Readonly<Record<string, number>>;
49
+ };
50
+ }
51
+ export type ProviderOptionsInput = OpenResponsesProviderOptionsInput & Omit<AnthropicMessages.OptionsInput, "thinking"> & {
52
+ /** Reasoning configuration for Messages (`thinking`) or Chat (`reasoning.enabled` + `reasoning.max_tokens`). */
53
+ readonly thinking?: AnthropicMessages.OptionsInput["thinking"] | {
54
+ readonly type: "enabled" | "adaptive" | "disabled" | (string & {});
55
+ readonly budgetTokens?: number;
56
+ readonly budget_tokens?: number;
57
+ };
58
+ /** Gateway routing, fallback, BYOK, compliance, and attribution options sent under `body.providerOptions.gateway`. */
59
+ readonly gateway?: GatewayOptions;
60
+ /** Provider-specific options forwarded under their upstream namespace in `body.providerOptions` (e.g. `{ anthropic: { ... } }`). */
61
+ readonly upstream?: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
62
+ /** Responses API automatic-cache lifetime (`"5m"` or `"1h"`), sent as top-level `cache_ttl`. */
63
+ readonly cacheTTL?: "5m" | "1h" | (string & {});
64
+ /** Responses API count of stable input items to anchor for caching, sent as top-level `cache_anchor_items`. */
65
+ readonly cacheAnchorItems?: number;
66
+ };
67
+ export interface EvaluationOptions {
68
+ readonly [key: string]: unknown;
69
+ readonly gateway?: GatewayOptions;
12
70
  }
13
- export type Options = ProviderAuthOption<"optional"> & {
71
+ export type Options = Omit<RouteDefaultsInput, "providerOptions"> & ProviderAuthOption<"optional"> & {
14
72
  readonly baseURL?: string;
15
- readonly headers?: Record<string, string>;
16
- readonly http?: HttpOptions.Input;
73
+ readonly providerOptions?: ProviderOptionsInput;
74
+ };
75
+ export type Settings = ProviderPackage.Settings & ProviderOptionsInput & {
76
+ readonly apiKey?: string;
17
77
  };
78
+ export declare const routes: Route<{
79
+ readonly [x: string]: unknown;
80
+ }, import("../route/transport/http.js").HttpPrepared<string>, import("../route/client.js").CompactionOperations | undefined>[];
18
81
  export declare const configure: (input?: Options) => {
19
82
  id: string & import("effect/Brand").Brand<"AI.ProviderID">;
83
+ model: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
84
+ messages: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
85
+ responses: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
86
+ chat: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
20
87
  experimental: {
21
88
  evaluation: (modelID: string | ModelID) => EvaluationModel<EvaluationOptions>;
22
89
  };
@@ -24,11 +91,19 @@ export declare const configure: (input?: Options) => {
24
91
  };
25
92
  export declare const provider: {
26
93
  id: string & import("effect/Brand").Brand<"AI.ProviderID">;
94
+ model: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
95
+ messages: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
96
+ responses: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
97
+ chat: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
27
98
  experimental: {
28
99
  evaluation: (modelID: string | ModelID) => EvaluationModel<EvaluationOptions>;
29
100
  };
30
101
  configure: (input?: Options) => {
31
102
  id: string & import("effect/Brand").Brand<"AI.ProviderID">;
103
+ model: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
104
+ messages: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
105
+ responses: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
106
+ chat: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
32
107
  experimental: {
33
108
  evaluation: (modelID: string | ModelID) => EvaluationModel<EvaluationOptions>;
34
109
  };
@@ -38,4 +113,11 @@ export declare const provider: {
38
113
  export declare const experimental: {
39
114
  evaluation: (modelID: string | ModelID) => EvaluationModel<EvaluationOptions>;
40
115
  };
116
+ export declare const messages: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
117
+ export declare const responses: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
118
+ export declare const chat: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<ProviderOptionsInput, import("../route/client.js").CompactionOperations | undefined>;
119
+ export declare const model: ProviderPackage.Definition<Settings, ProviderOptionsInput>["model"];
120
+ export declare const messagesModel: ProviderPackage.Definition<Settings, ProviderOptionsInput>["model"];
121
+ export declare const responsesModel: ProviderPackage.Definition<Settings, ProviderOptionsInput>["model"];
122
+ export declare const chatModel: ProviderPackage.Definition<Settings, ProviderOptionsInput>["model"];
41
123
  export * as VercelAIGateway from "./vercel-ai-gateway.js";
@@ -1,11 +1,111 @@
1
1
  import { Effect, Schema } from "effect";
2
2
  import { Headers, HttpClientRequest } from "effect/unstable/http";
3
3
  import { EvaluationAnswer, EvaluationInput, EvaluationModel, EvaluationQuestion, EvaluationResponse, EvaluationRounding, } from "../experimental/evaluation.js";
4
+ import { AnthropicMessages } from "../protocols/anthropic-messages.js";
5
+ import { OpenAIChat } from "../protocols/openai-chat.js";
6
+ import { OpenResponses } from "../protocols/open-responses.js";
7
+ import { optionalNull, ProviderShared } from "../protocols/shared.js";
8
+ import { gatewayProtocol } from "../protocols/utils/gateway-protocol.js";
4
9
  import { Auth } from "../route/auth.js";
5
10
  import { AuthOptions } from "../route/auth-options.js";
6
- import { AIError, HttpContext, HttpOptions, InvalidProviderOutputError, InvalidRequestError, ModelID, ProviderID, ProviderMetadata, Usage, } from "../schema/index.js";
11
+ import { Route } from "../route/client.js";
12
+ import { Endpoint } from "../route/endpoint.js";
13
+ import { Framing } from "../route/framing.js";
14
+ import { AIError, HttpContext, HttpOptions, InvalidProviderOutputError, InvalidRequestError, LLMRequest, ModelID, ProviderID, ProviderMetadata, ReasoningEffort, Usage, } from "../schema/index.js";
7
15
  export const id = ProviderID.make("vercel-ai-gateway");
8
16
  const baseURL = "https://ai-gateway.vercel.sh/v1";
17
+ const GatewayOptionsSchema = Schema.Struct({
18
+ gateway: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
19
+ upstream: Schema.optional(Schema.Record(Schema.String, Schema.Record(Schema.String, Schema.Unknown))),
20
+ reasoningEffort: Schema.optional(ReasoningEffort),
21
+ thinking: Schema.optional(Schema.Struct({
22
+ type: Schema.String,
23
+ budgetTokens: Schema.optional(Schema.Number),
24
+ budget_tokens: Schema.optional(Schema.Number),
25
+ })),
26
+ cacheTTL: Schema.optional(Schema.String),
27
+ cacheAnchorItems: Schema.optional(Schema.Number),
28
+ });
29
+ const decodeOptions = ProviderShared.validateWith(Schema.decodeUnknownEffect(GatewayOptionsSchema));
30
+ const prepare = (api) => Effect.fnUntraced(function* (request) {
31
+ const options = yield* decodeOptions(request.providerOptions ?? {});
32
+ const providerOptions = (() => {
33
+ if (!options.upstream && !options.gateway)
34
+ return undefined;
35
+ if (!options.gateway)
36
+ return options.upstream;
37
+ return { ...options.upstream, gateway: options.gateway };
38
+ })();
39
+ switch (api) {
40
+ case "messages": {
41
+ const effort = options.reasoningEffort;
42
+ if (effort === undefined)
43
+ return { request, body: { providerOptions } };
44
+ const enabled = effort !== "none";
45
+ const thinking = request.providerOptions?.thinking ?? { type: enabled ? "adaptive" : "disabled" };
46
+ const next = LLMRequest.update(request, {
47
+ providerOptions: {
48
+ ...request.providerOptions,
49
+ effort: enabled ? effort : undefined,
50
+ thinking,
51
+ },
52
+ });
53
+ return { request: next, body: { providerOptions } };
54
+ }
55
+ case "responses":
56
+ return {
57
+ request,
58
+ body: {
59
+ providerOptions,
60
+ cache_ttl: options.cacheTTL,
61
+ cache_anchor_items: options.cacheAnchorItems,
62
+ },
63
+ };
64
+ case "chat": {
65
+ if (!options.thinking)
66
+ return { request, body: { providerOptions } };
67
+ const reasoning = {
68
+ enabled: options.thinking.type !== "disabled",
69
+ max_tokens: options.thinking.budgetTokens ?? options.thinking.budget_tokens,
70
+ };
71
+ return { request, body: { providerOptions, reasoning } };
72
+ }
73
+ }
74
+ });
75
+ const route = (input) => Route.make({
76
+ id: input.id,
77
+ provider: id,
78
+ providerMetadataKey: id,
79
+ protocol: gatewayProtocol(input.protocol, { id: input.id, prepare: prepare(input.api) }),
80
+ endpoint: Endpoint.path(input.path, { baseURL }),
81
+ framing: input.framing,
82
+ headers: ({ request }) => request.promptCacheKey ? { "x-session-affinity": request.promptCacheKey } : {},
83
+ defaults: input.defaults,
84
+ });
85
+ const messagesRoute = route({
86
+ id: "vercel-ai-gateway-messages",
87
+ protocol: AnthropicMessages.protocol,
88
+ api: "messages",
89
+ path: "/messages",
90
+ framing: AnthropicMessages.framing,
91
+ defaults: { headers: { "anthropic-version": "2023-06-01" } },
92
+ });
93
+ const responsesRoute = route({
94
+ id: "vercel-ai-gateway-responses",
95
+ protocol: OpenResponses.protocol,
96
+ api: "responses",
97
+ path: "/responses",
98
+ framing: Framing.sse,
99
+ defaults: { providerOptions: { store: false, include: ["reasoning.encrypted_content"] } },
100
+ });
101
+ const chatRoute = route({
102
+ id: "vercel-ai-gateway-chat",
103
+ protocol: OpenAIChat.protocol,
104
+ api: "chat",
105
+ path: "/chat/completions",
106
+ framing: OpenAIChat.framing,
107
+ });
108
+ export const routes = [messagesRoute, responsesRoute, chatRoute];
9
109
  const Request = Schema.StructWithRest(Schema.Struct({
10
110
  model: Schema.String,
11
111
  state: EvaluationInput,
@@ -13,16 +113,39 @@ const Request = Schema.StructWithRest(Schema.Struct({
13
113
  providerOptions: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
14
114
  }), [Schema.Record(Schema.String, Schema.Any)]);
15
115
  const Response = Schema.Struct({
16
- model: Schema.optional(Schema.String),
116
+ model: optionalNull(Schema.String),
17
117
  answers: Schema.Record(Schema.String, EvaluationAnswer),
18
- usage: Schema.optional(Schema.Struct({
19
- inputTokens: Schema.optional(Schema.Number),
20
- outputTokens: Schema.optional(Schema.Number),
118
+ usage: optionalNull(Schema.Struct({
119
+ inputTokens: optionalNull(Schema.Number),
120
+ outputTokens: optionalNull(Schema.Number),
21
121
  })),
22
- rounding: Schema.optional(EvaluationRounding),
23
- providerMetadata: Schema.optional(ProviderMetadata),
122
+ rounding: optionalNull(EvaluationRounding),
123
+ providerMetadata: optionalNull(ProviderMetadata),
24
124
  });
25
125
  export const configure = (input = {}) => {
126
+ const { apiKey: _apiKey, auth: _auth, baseURL: endpoint, ...defaults } = input;
127
+ const configured = {
128
+ ...defaults,
129
+ endpoint: { baseURL: endpoint ?? baseURL },
130
+ auth: AuthOptions.bearer(input, ["AI_GATEWAY_API_KEY", "VERCEL_OIDC_TOKEN"]),
131
+ };
132
+ const messages = (modelID) => messagesRoute.with(configured).model({
133
+ id: modelID,
134
+ // Recorded Gateway translations for non-Claude models return thinking with empty signatures.
135
+ compatibility: { requireSignature: modelID.startsWith("anthropic/") },
136
+ });
137
+ const responses = (modelID) => responsesRoute.with(configured).model({ id: modelID });
138
+ const chat = (modelID) => chatRoute
139
+ .with(configured)
140
+ .model({ id: modelID, compatibility: { reasoningField: "reasoning" } });
141
+ // Each family uses the API whose Gateway translation carries its reasoning state across turns.
142
+ const model = (modelID) => {
143
+ if (/^(openai\/gpt-|spacexai\/grok-)/.test(modelID))
144
+ return responses(modelID);
145
+ if (modelID.startsWith("meta/muse-"))
146
+ return chat(modelID);
147
+ return messages(modelID);
148
+ };
26
149
  const evaluation = (modelID) => EvaluationModel.make({
27
150
  id: modelID,
28
151
  provider: id,
@@ -39,7 +162,7 @@ export const configure = (input = {}) => {
39
162
  questions: req.questions,
40
163
  providerOptions: req.options,
41
164
  }).pipe(Effect.mapError((cause) => new AIError({ reason: new InvalidRequestError({ message: cause.message, cause }) })));
42
- const headers = yield* Auth.toEffect(AuthOptions.bearer(input, ["AI_GATEWAY_API_KEY", "VERCEL_OIDC_TOKEN"]))({
165
+ const headers = yield* Auth.toEffect(configured.auth)({
43
166
  request: req,
44
167
  method: "POST",
45
168
  url: url.toString(),
@@ -59,27 +182,44 @@ export const configure = (input = {}) => {
59
182
  });
60
183
  const text = yield* res.text.pipe(Effect.mapError((cause) => fail("Failed to read the Vercel AI Gateway evaluation response", cause)));
61
184
  const data = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(Response))(text).pipe(Effect.mapError((cause) => fail("Vercel AI Gateway returned an invalid evaluation response", cause, text)));
185
+ const inputTokens = data.usage?.inputTokens ?? undefined;
186
+ const outputTokens = data.usage?.outputTokens ?? undefined;
187
+ const usage = data.usage
188
+ ? new Usage({
189
+ inputTokens,
190
+ outputTokens,
191
+ totalTokens: ProviderShared.totalTokens(inputTokens, outputTokens, undefined),
192
+ providerMetadata: { gateway: data.usage },
193
+ })
194
+ : undefined;
62
195
  return new EvaluationResponse({
63
196
  model: ModelID.make(data.model ?? req.model.id),
64
197
  answers: data.answers,
65
- usage: data.usage
66
- ? new Usage({
67
- inputTokens: data.usage.inputTokens,
68
- outputTokens: data.usage.outputTokens,
69
- totalTokens: data.usage.inputTokens === undefined && data.usage.outputTokens === undefined
70
- ? undefined
71
- : (data.usage.inputTokens ?? 0) + (data.usage.outputTokens ?? 0),
72
- providerMetadata: { gateway: data.usage },
73
- })
74
- : undefined,
75
- rounding: data.rounding,
76
- providerMetadata: data.providerMetadata,
198
+ usage,
199
+ rounding: data.rounding ?? undefined,
200
+ providerMetadata: data.providerMetadata ?? undefined,
77
201
  });
78
202
  }),
79
203
  },
80
204
  });
81
- return { id, experimental: { evaluation }, configure };
205
+ return { id, model, messages, responses, chat, experimental: { evaluation }, configure };
82
206
  };
83
207
  export const provider = configure();
84
208
  export const experimental = provider.experimental;
209
+ export const messages = provider.messages;
210
+ export const responses = provider.responses;
211
+ export const chat = provider.chat;
212
+ export const model = (modelID, settings) => fromSettings(settings).model(modelID);
213
+ export const messagesModel = (modelID, settings) => fromSettings(settings).messages(modelID);
214
+ export const responsesModel = (modelID, settings) => fromSettings(settings).responses(modelID);
215
+ export const chatModel = (modelID, settings) => fromSettings(settings).chat(modelID);
216
+ function fromSettings({ apiKey, baseURL, headers, body, ...providerOptions }) {
217
+ return configure({
218
+ apiKey,
219
+ baseURL,
220
+ headers,
221
+ http: body === undefined ? undefined : { body: { ...body } },
222
+ providerOptions,
223
+ });
224
+ }
85
225
  export * as VercelAIGateway from "./vercel-ai-gateway.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "2.0.23",
3
+ "version": "2.0.24",
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.23",
37
+ "@opencode/http-recorder": "2.0.24",
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.23",
47
+ "@opencode/schema": "2.0.24",
48
48
  "aws4fetch": "1.0.20",
49
49
  "effect": "4.0.0-rc.112",
50
50
  "google-auth-library": "10.5.0"