@opencode-ai/ai 0.0.0-dev-18002 → 0.0.0-dev-18035

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.
@@ -15,6 +15,7 @@ export type ThinkingInput = {
15
15
  readonly type: "disabled";
16
16
  } | ({
17
17
  readonly type: "enabled";
18
+ readonly display?: "summarized" | "omitted";
18
19
  } & ({
19
20
  readonly budgetTokens: number;
20
21
  readonly budget_tokens?: number;
@@ -194,6 +195,7 @@ export declare const AnthropicMessagesBody: Schema.Struct<{
194
195
  thinking: Schema.optional<Schema.Union<readonly [Schema.Struct<{
195
196
  readonly type: Schema.tag<"enabled">;
196
197
  readonly budget_tokens: Schema.Number;
198
+ readonly display: Schema.optional<Schema.Literals<readonly ["summarized", "omitted"]>>;
197
199
  }>, Schema.Struct<{
198
200
  readonly type: Schema.tag<"adaptive">;
199
201
  readonly display: Schema.optional<Schema.Literals<readonly ["summarized", "omitted"]>>;
@@ -369,6 +371,7 @@ export declare const protocol: Protocol<{
369
371
  readonly thinking?: {
370
372
  readonly type: "enabled";
371
373
  readonly budget_tokens: number;
374
+ readonly display?: "summarized" | "omitted" | undefined;
372
375
  } | {
373
376
  readonly type: "adaptive";
374
377
  readonly display?: "summarized" | "omitted" | undefined;
@@ -611,6 +614,7 @@ export declare const route: Route<{
611
614
  readonly thinking?: {
612
615
  readonly type: "enabled";
613
616
  readonly budget_tokens: number;
617
+ readonly display?: "summarized" | "omitted" | undefined;
614
618
  } | {
615
619
  readonly type: "adaptive";
616
620
  readonly display?: "summarized" | "omitted" | undefined;
@@ -24,6 +24,7 @@ const SSE_EVENTS = new Set([
24
24
  "content_block_start",
25
25
  "content_block_delta",
26
26
  "content_block_stop",
27
+ "ping",
27
28
  "error",
28
29
  ]);
29
30
  export const framing = Framing.sseEvents(SSE_EVENTS);
@@ -145,6 +146,7 @@ const AnthropicThinking = Schema.Union([
145
146
  Schema.Struct({
146
147
  type: Schema.tag("enabled"),
147
148
  budget_tokens: Schema.Number,
149
+ display: Schema.optional(Schema.Literals(["summarized", "omitted"])),
148
150
  }),
149
151
  Schema.Struct({
150
152
  type: Schema.tag("adaptive"),
@@ -490,14 +492,11 @@ const resolveOptions = Effect.fn("AnthropicMessages.resolveOptions")(function* (
490
492
  const resolveThinking = Effect.fn("AnthropicMessages.resolveThinking")(function* (input) {
491
493
  if (!ProviderShared.isRecord(input))
492
494
  return undefined;
493
- if (input.type === "adaptive") {
494
- const display = input.display === "summarized"
495
- ? "summarized"
496
- : input.display === "omitted"
497
- ? "omitted"
498
- : undefined;
495
+ const display = input.display === "summarized" || input.display === "omitted"
496
+ ? input.display
497
+ : undefined;
498
+ if (input.type === "adaptive")
499
499
  return { type: "adaptive", ...(display === undefined ? {} : { display }) };
500
- }
501
500
  if (input.type === "disabled")
502
501
  return { type: "disabled" };
503
502
  if (input.type !== "enabled")
@@ -509,7 +508,7 @@ const resolveThinking = Effect.fn("AnthropicMessages.resolveThinking")(function*
509
508
  : undefined;
510
509
  if (budget === undefined)
511
510
  return yield* ProviderShared.invalidRequest("Anthropic thinking provider option requires budgetTokens");
512
- return { type: "enabled", budget_tokens: budget };
511
+ return { type: "enabled", budget_tokens: budget, ...(display === undefined ? {} : { display }) };
513
512
  });
514
513
  const fromRequest = Effect.fn("AnthropicMessages.fromRequest")(function* (request) {
515
514
  const generation = request.generation;
@@ -829,11 +828,11 @@ const providerErrorMessage = (event) => {
829
828
  return `${type}: ${message}`;
830
829
  return message || type || "Anthropic Messages stream error";
831
830
  };
832
- const onError = (event) => new AIError({
831
+ const onError = (event) => Effect.fail(new AIError({
833
832
  module: ADAPTER,
834
833
  method: "stream",
835
834
  reason: classifyProviderFailure({ message: providerErrorMessage(event), code: event.error?.type }),
836
- });
835
+ }));
837
836
  const step = (state, event) => {
838
837
  if (event.type === "message_start")
839
838
  return Effect.succeed(onMessageStart(state, event));
@@ -21,11 +21,11 @@ export type ProviderOptionsInput = OptionsInput;
21
21
  declare const GeminiBody: Schema.Struct<{
22
22
  cachedContent: Schema.optional<Schema.String>;
23
23
  contents: Schema.$Array<Schema.Struct<{
24
- readonly role: Schema.Literals<readonly ["user", "model"]>;
25
- readonly parts: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
24
+ readonly role: Schema.optional<Schema.NullOr<Schema.Literals<readonly ["user", "model"]>>>;
25
+ readonly parts: Schema.optional<Schema.NullOr<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
26
26
  readonly text: Schema.String;
27
- readonly thought: Schema.optional<Schema.Boolean>;
28
- readonly thoughtSignature: Schema.optional<Schema.String>;
27
+ readonly thought: Schema.optional<Schema.NullOr<Schema.Boolean>>;
28
+ readonly thoughtSignature: Schema.optional<Schema.NullOr<Schema.String>>;
29
29
  }>, Schema.Struct<{
30
30
  readonly inlineData: Schema.Struct<{
31
31
  readonly mimeType: Schema.String;
@@ -33,11 +33,11 @@ declare const GeminiBody: Schema.Struct<{
33
33
  }>;
34
34
  }>, Schema.Struct<{
35
35
  readonly functionCall: Schema.Struct<{
36
- readonly id: Schema.optional<Schema.String>;
36
+ readonly id: Schema.optional<Schema.NullOr<Schema.String>>;
37
37
  readonly name: Schema.String;
38
38
  readonly args: Schema.optional<Schema.Unknown>;
39
39
  }>;
40
- readonly thoughtSignature: Schema.optional<Schema.String>;
40
+ readonly thoughtSignature: Schema.optional<Schema.NullOr<Schema.String>>;
41
41
  }>, Schema.Struct<{
42
42
  readonly functionResponse: Schema.Struct<{
43
43
  readonly id: Schema.optional<Schema.String>;
@@ -50,7 +50,7 @@ declare const GeminiBody: Schema.Struct<{
50
50
  }>;
51
51
  }>>>;
52
52
  }>;
53
- }>]>>;
53
+ }>]>>>>;
54
54
  }>>;
55
55
  labels: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
56
56
  safetySettings: Schema.optional<Schema.$Array<Schema.Struct<{
@@ -99,23 +99,22 @@ export type GeminiBody = Schema.Schema.Type<typeof GeminiBody>;
99
99
  */
100
100
  export declare const protocol: Protocol<{
101
101
  readonly contents: readonly {
102
- readonly role: "model" | "user";
103
- readonly parts: readonly ({
102
+ readonly parts?: readonly ({
104
103
  readonly inlineData: {
105
104
  readonly mimeType: string;
106
105
  readonly data: string;
107
106
  };
108
107
  } | {
109
108
  readonly text: string;
110
- readonly thought?: boolean | undefined;
111
- readonly thoughtSignature?: string | undefined;
109
+ readonly thought?: boolean | null | undefined;
110
+ readonly thoughtSignature?: string | null | undefined;
112
111
  } | {
113
112
  readonly functionCall: {
114
113
  readonly name: string;
115
- readonly id?: string | undefined;
114
+ readonly id?: string | null | undefined;
116
115
  readonly args?: unknown;
117
116
  };
118
- readonly thoughtSignature?: string | undefined;
117
+ readonly thoughtSignature?: string | null | undefined;
119
118
  } | {
120
119
  readonly functionResponse: {
121
120
  readonly name: string;
@@ -128,7 +127,8 @@ export declare const protocol: Protocol<{
128
127
  };
129
128
  }[] | undefined;
130
129
  };
131
- })[];
130
+ })[] | null | undefined;
131
+ readonly role?: "model" | "user" | null | undefined;
132
132
  }[];
133
133
  readonly tools?: readonly {
134
134
  readonly functionDeclarations: readonly {
@@ -177,23 +177,22 @@ export declare const protocol: Protocol<{
177
177
  }, string, {
178
178
  readonly candidates?: readonly {
179
179
  readonly content?: {
180
- readonly role: "model" | "user";
181
- readonly parts: readonly ({
180
+ readonly parts?: readonly ({
182
181
  readonly inlineData: {
183
182
  readonly mimeType: string;
184
183
  readonly data: string;
185
184
  };
186
185
  } | {
187
186
  readonly text: string;
188
- readonly thought?: boolean | undefined;
189
- readonly thoughtSignature?: string | undefined;
187
+ readonly thought?: boolean | null | undefined;
188
+ readonly thoughtSignature?: string | null | undefined;
190
189
  } | {
191
190
  readonly functionCall: {
192
191
  readonly name: string;
193
- readonly id?: string | undefined;
192
+ readonly id?: string | null | undefined;
194
193
  readonly args?: unknown;
195
194
  };
196
- readonly thoughtSignature?: string | undefined;
195
+ readonly thoughtSignature?: string | null | undefined;
197
196
  } | {
198
197
  readonly functionResponse: {
199
198
  readonly name: string;
@@ -206,46 +205,46 @@ export declare const protocol: Protocol<{
206
205
  };
207
206
  }[] | undefined;
208
207
  };
209
- })[];
210
- } | undefined;
211
- readonly finishReason?: string | undefined;
212
- }[] | undefined;
208
+ })[] | null | undefined;
209
+ readonly role?: "model" | "user" | null | undefined;
210
+ } | null | undefined;
211
+ readonly finishReason?: string | null | undefined;
212
+ }[] | null | undefined;
213
213
  readonly promptFeedback?: {
214
214
  readonly [x: string]: unknown;
215
- readonly blockReason?: string | undefined;
216
- readonly blockReasonMessage?: string | undefined;
215
+ readonly blockReason?: string | null | undefined;
216
+ readonly blockReasonMessage?: string | null | undefined;
217
217
  readonly safetyRatings?: unknown;
218
- } | undefined;
218
+ } | null | undefined;
219
219
  readonly usageMetadata?: {
220
- readonly cachedContentTokenCount?: number | undefined;
221
- readonly thoughtsTokenCount?: number | undefined;
222
- readonly promptTokenCount?: number | undefined;
223
- readonly candidatesTokenCount?: number | undefined;
224
- readonly totalTokenCount?: number | undefined;
225
- } | undefined;
220
+ readonly cachedContentTokenCount?: number | null | undefined;
221
+ readonly thoughtsTokenCount?: number | null | undefined;
222
+ readonly promptTokenCount?: number | null | undefined;
223
+ readonly candidatesTokenCount?: number | null | undefined;
224
+ readonly totalTokenCount?: number | null | undefined;
225
+ } | null | undefined;
226
226
  }, {
227
227
  hasToolCalls: boolean;
228
228
  lifecycle: Lifecycle.State;
229
229
  }>;
230
230
  export declare const route: Route<{
231
231
  readonly contents: readonly {
232
- readonly role: "model" | "user";
233
- readonly parts: readonly ({
232
+ readonly parts?: readonly ({
234
233
  readonly inlineData: {
235
234
  readonly mimeType: string;
236
235
  readonly data: string;
237
236
  };
238
237
  } | {
239
238
  readonly text: string;
240
- readonly thought?: boolean | undefined;
241
- readonly thoughtSignature?: string | undefined;
239
+ readonly thought?: boolean | null | undefined;
240
+ readonly thoughtSignature?: string | null | undefined;
242
241
  } | {
243
242
  readonly functionCall: {
244
243
  readonly name: string;
245
- readonly id?: string | undefined;
244
+ readonly id?: string | null | undefined;
246
245
  readonly args?: unknown;
247
246
  };
248
- readonly thoughtSignature?: string | undefined;
247
+ readonly thoughtSignature?: string | null | undefined;
249
248
  } | {
250
249
  readonly functionResponse: {
251
250
  readonly name: string;
@@ -258,7 +257,8 @@ export declare const route: Route<{
258
257
  };
259
258
  }[] | undefined;
260
259
  };
261
- })[];
260
+ })[] | null | undefined;
261
+ readonly role?: "model" | "user" | null | undefined;
262
262
  }[];
263
263
  readonly tools?: readonly {
264
264
  readonly functionDeclarations: readonly {
@@ -6,7 +6,7 @@ import { Endpoint } from "../route/endpoint.js";
6
6
  import { Framing } from "../route/framing.js";
7
7
  import { Protocol } from "../route/protocol.js";
8
8
  import { LLMEvent, Usage, } from "../schema/index.js";
9
- import { JsonObject, optionalArray, ProviderShared } from "./shared.js";
9
+ import { JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js";
10
10
  import { GeminiToolSchema } from "./utils/gemini-tool-schema.js";
11
11
  import { Lifecycle } from "./utils/lifecycle.js";
12
12
  import { ToolSchemaProjection } from "./utils/tool-schema.js";
@@ -38,10 +38,15 @@ const omitsFunctionCallIds = (modelID) => {
38
38
  // =============================================================================
39
39
  // Request Body Schema
40
40
  // =============================================================================
41
+ // Gemini is known to send explicit `null` for optional streaming fields
42
+ // (usage counts, flags, whole subtrees), so every response-side optional uses
43
+ // `optionalNull` instead of bare `Schema.optional`. The same part/content
44
+ // schemas lower the outbound request body; encoding drops `undefined` keys,
45
+ // so the shared schemas stay safe there.
41
46
  const GeminiTextPart = Schema.Struct({
42
47
  text: Schema.String,
43
- thought: Schema.optional(Schema.Boolean),
44
- thoughtSignature: Schema.optional(Schema.String),
48
+ thought: optionalNull(Schema.Boolean),
49
+ thoughtSignature: optionalNull(Schema.String),
45
50
  });
46
51
  const GeminiInlineDataPart = Schema.Struct({
47
52
  inlineData: Schema.Struct({
@@ -51,11 +56,11 @@ const GeminiInlineDataPart = Schema.Struct({
51
56
  });
52
57
  const GeminiFunctionCallPart = Schema.Struct({
53
58
  functionCall: Schema.Struct({
54
- id: Schema.optional(Schema.String),
59
+ id: optionalNull(Schema.String),
55
60
  name: Schema.String,
56
61
  args: Schema.optional(Schema.Unknown),
57
62
  }),
58
- thoughtSignature: Schema.optional(Schema.String),
63
+ thoughtSignature: optionalNull(Schema.String),
59
64
  });
60
65
  const GeminiFunctionResponsePart = Schema.Struct({
61
66
  functionResponse: Schema.Struct({
@@ -72,8 +77,8 @@ const GeminiContentPart = Schema.Union([
72
77
  GeminiFunctionResponsePart,
73
78
  ]);
74
79
  const GeminiContent = Schema.Struct({
75
- role: Schema.Literals(["user", "model"]),
76
- parts: Schema.Array(GeminiContentPart),
80
+ role: optionalNull(Schema.Literals(["user", "model"])),
81
+ parts: optionalNull(Schema.Array(GeminiContentPart)),
77
82
  });
78
83
  const GeminiSystemInstruction = Schema.Struct({
79
84
  parts: Schema.Array(Schema.Struct({ text: Schema.String })),
@@ -125,25 +130,25 @@ const GeminiBodyFields = {
125
130
  };
126
131
  const GeminiBody = Schema.Struct(GeminiBodyFields);
127
132
  const GeminiUsage = Schema.Struct({
128
- cachedContentTokenCount: Schema.optional(Schema.Number),
129
- thoughtsTokenCount: Schema.optional(Schema.Number),
130
- promptTokenCount: Schema.optional(Schema.Number),
131
- candidatesTokenCount: Schema.optional(Schema.Number),
132
- totalTokenCount: Schema.optional(Schema.Number),
133
+ cachedContentTokenCount: optionalNull(Schema.Number),
134
+ thoughtsTokenCount: optionalNull(Schema.Number),
135
+ promptTokenCount: optionalNull(Schema.Number),
136
+ candidatesTokenCount: optionalNull(Schema.Number),
137
+ totalTokenCount: optionalNull(Schema.Number),
133
138
  });
134
139
  const GeminiCandidate = Schema.Struct({
135
- content: Schema.optional(GeminiContent),
136
- finishReason: Schema.optional(Schema.String),
140
+ content: optionalNull(GeminiContent),
141
+ finishReason: optionalNull(Schema.String),
137
142
  });
138
143
  const GeminiPromptFeedback = Schema.StructWithRest(Schema.Struct({
139
- blockReason: Schema.optional(Schema.String),
140
- blockReasonMessage: Schema.optional(Schema.String),
141
- safetyRatings: Schema.optional(Schema.Unknown),
144
+ blockReason: optionalNull(Schema.String),
145
+ blockReasonMessage: optionalNull(Schema.String),
146
+ safetyRatings: optionalNull(Schema.Unknown),
142
147
  }), [Schema.Record(Schema.String, Schema.Unknown)]);
143
148
  const GeminiEvent = Schema.Struct({
144
- candidates: optionalArray(GeminiCandidate),
145
- promptFeedback: Schema.optional(GeminiPromptFeedback),
146
- usageMetadata: Schema.optional(GeminiUsage),
149
+ candidates: optionalNull(Schema.Array(GeminiCandidate)),
150
+ promptFeedback: optionalNull(GeminiPromptFeedback),
151
+ usageMetadata: optionalNull(GeminiUsage),
147
152
  });
148
153
  // =============================================================================
149
154
  // Tool Schema Conversion
@@ -217,8 +222,8 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
217
222
  const previous = contents.at(-1);
218
223
  // Gemini rejects a continuation whose function-response turn carries extra
219
224
  // parts, so an update after a tool result starts its own user turn.
220
- if (previous?.role === "user" && !previous.parts.some((item) => "functionResponse" in item))
221
- contents[contents.length - 1] = { role: "user", parts: [...previous.parts, { text: part.text }] };
225
+ if (previous?.role === "user" && !(previous.parts ?? []).some((item) => "functionResponse" in item))
226
+ contents[contents.length - 1] = { role: "user", parts: [...(previous.parts ?? []), { text: part.text }] };
222
227
  else
223
228
  contents.push({ role: "user", parts: [{ text: part.text }] });
224
229
  continue;
@@ -309,8 +314,8 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
309
314
  // Gemini requires every response to a parallel call batch in one user turn,
310
315
  // so consecutive tool results join the open function-response turn.
311
316
  const previous = contents.at(-1);
312
- if (previous?.role === "user" && previous.parts.some((item) => "functionResponse" in item))
313
- contents[contents.length - 1] = { role: "user", parts: [...previous.parts, ...parts] };
317
+ if (previous?.role === "user" && (previous.parts ?? []).some((item) => "functionResponse" in item))
318
+ contents[contents.length - 1] = { role: "user", parts: [...(previous.parts ?? []), ...parts] };
314
319
  else
315
320
  contents.push({ role: "user", parts });
316
321
  }
@@ -389,20 +394,25 @@ const fromRequest = Effect.fn("Gemini.fromRequest")(function* (request) {
389
394
  const mapUsage = (usage) => {
390
395
  if (!usage)
391
396
  return undefined;
392
- const cached = usage.cachedContentTokenCount;
393
- const nonCached = ProviderShared.subtractTokens(usage.promptTokenCount, cached);
397
+ // Explicit provider nulls decode as `null`; normalize to `undefined` so the
398
+ // token arithmetic below treats them like absent counts.
399
+ const promptTokens = usage.promptTokenCount ?? undefined;
400
+ const cached = usage.cachedContentTokenCount ?? undefined;
401
+ const thoughts = usage.thoughtsTokenCount ?? undefined;
402
+ const visible = usage.candidatesTokenCount ?? undefined;
403
+ const nonCached = ProviderShared.subtractTokens(promptTokens, cached);
394
404
  // `candidatesTokenCount` is visible-only; sum with thoughts to produce the
395
405
  // inclusive `outputTokens` the contract expects. Only compute the total
396
406
  // when the visible component is reported — otherwise we'd fabricate an
397
407
  // inclusive number from a partial breakdown.
398
- const outputTokens = usage.candidatesTokenCount !== undefined ? usage.candidatesTokenCount + (usage.thoughtsTokenCount ?? 0) : undefined;
408
+ const outputTokens = visible !== undefined ? visible + (thoughts ?? 0) : undefined;
399
409
  return new Usage({
400
- inputTokens: usage.promptTokenCount,
410
+ inputTokens: promptTokens,
401
411
  outputTokens,
402
412
  nonCachedInputTokens: nonCached,
403
413
  cacheReadInputTokens: cached,
404
- reasoningTokens: usage.thoughtsTokenCount,
405
- totalTokens: ProviderShared.totalTokens(usage.promptTokenCount, outputTokens, usage.totalTokenCount),
414
+ reasoningTokens: thoughts,
415
+ totalTokens: ProviderShared.totalTokens(promptTokens, outputTokens, usage.totalTokenCount ?? undefined),
406
416
  providerMetadata: { google: usage },
407
417
  });
408
418
  };
@@ -434,7 +444,9 @@ const mapFinishReason = (finishReason, hasToolCalls) => {
434
444
  return "unknown";
435
445
  };
436
446
  const finish = (state) => {
437
- const promptBlockReason = state.finishReason === undefined ? state.promptFeedback?.blockReason : undefined;
447
+ // `?? undefined` normalizes an explicit `null` blockReason back to absent so
448
+ // the "nothing to finish" check below keeps its meaning.
449
+ const promptBlockReason = state.finishReason === undefined ? (state.promptFeedback?.blockReason ?? undefined) : undefined;
438
450
  const finishReason = state.finishReason ?? promptBlockReason;
439
451
  if (finishReason === undefined && state.usage === undefined)
440
452
  return [];
@@ -473,7 +485,7 @@ const step = (state, event) => {
473
485
  let textSignature = nextState.textSignature;
474
486
  // Supplier ids must be tracked across chunks of the same response, not just within one event's parts.
475
487
  const seenCallIds = new Set(nextState.seenCallIds);
476
- for (const part of candidate.content.parts) {
488
+ for (const part of candidate.content.parts ?? []) {
477
489
  const signature = "thoughtSignature" in part && part.thoughtSignature ? part.thoughtSignature : undefined;
478
490
  // Gemini attaches replay signatures to thought parts, visible text, or function calls;
479
491
  // each block kind must retain the signature attached to its own parts.
@@ -496,7 +508,8 @@ const step = (state, event) => {
496
508
  // Gemini 2.0+ supplies a unique function call ID on the part; when omitted (e.g. Gemini 1.5),
497
509
  // generate a globally unique ID rather than a per-request counter to prevent cross-request collisions in downstream registries.
498
510
  // A repeated supplier id would replay as two identical calls, so only the first occurrence keeps it.
499
- const supplied = part.functionCall.id;
511
+ // A `null` supplier id normalizes to absent so the generated-id fallback applies.
512
+ const supplied = part.functionCall.id ?? undefined;
500
513
  const duplicate = supplied !== undefined && seenCallIds.has(supplied);
501
514
  if (supplied !== undefined)
502
515
  seenCallIds.add(supplied);
@@ -507,7 +520,7 @@ const step = (state, event) => {
507
520
  id,
508
521
  name: part.functionCall.name,
509
522
  input,
510
- providerMetadata: part.thoughtSignature === undefined ? undefined : googleMetadata({ thoughtSignature: part.thoughtSignature }),
523
+ providerMetadata: part.thoughtSignature ? googleMetadata({ thoughtSignature: part.thoughtSignature }) : undefined,
511
524
  }));
512
525
  hasToolCalls = true;
513
526
  }
@@ -1,7 +1,7 @@
1
1
  import { Effect, Schema } from "effect";
2
2
  import { HttpTransport } from "../route/transport/index.js";
3
3
  import { Protocol } from "../route/protocol.js";
4
- import { AIError, LLMEvent, Usage, } from "../schema/index.js";
4
+ import { AIError, LLMEvent, ProviderInternalReason, Usage, } from "../schema/index.js";
5
5
  import { JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js";
6
6
  import { classifyProviderFailure } from "../provider-error.js";
7
7
  import { OpenResponsesOptions } from "./utils/open-responses-options.js";
@@ -234,7 +234,7 @@ export const lowerTool = Effect.fn("OpenResponses.lowerTool")(function* (protoco
234
234
  type: "function",
235
235
  name: tool.name,
236
236
  description: tool.description,
237
- parameters: ToolSchemaProjection.responses(inputSchema),
237
+ parameters: inputSchema,
238
238
  // The common tool definition does not currently express Responses strict-schema policy.
239
239
  strict: false,
240
240
  };
@@ -290,7 +290,7 @@ const lowerMedia = Effect.fn("OpenResponses.lowerMedia")(function* (part, reques
290
290
  return {
291
291
  type: "input_file",
292
292
  filename: part.filename ?? (media.mime === "application/pdf" ? "document.pdf" : "file"),
293
- ...(url ? { file_url: url } : { file_data: media.base64 }),
293
+ ...(url ? { file_url: url } : { file_data: media.dataUrl }),
294
294
  };
295
295
  }
296
296
  return { type: "input_image", image_url: url ?? media.dataUrl };
@@ -856,11 +856,18 @@ export const providerFailure = (id, event, fallback) => {
856
856
  : typeof event.status_code === "number"
857
857
  ? event.status_code
858
858
  : undefined;
859
+ const reason = event.type === "error" &&
860
+ event.error === undefined &&
861
+ event.response === undefined &&
862
+ summary === undefined &&
863
+ status === undefined
864
+ ? new ProviderInternalReason({ message })
865
+ : classifyProviderFailure({ message, code, status, rawBody: body });
859
866
  return new AIError({
860
867
  module: id,
861
868
  method: "stream",
862
869
  body,
863
- reason: classifyProviderFailure({ message, code, status, rawBody: body }),
870
+ reason,
864
871
  });
865
872
  };
866
873
  const providerError = (state, event, fallback) => providerFailure(state.id, event, fallback);
@@ -201,7 +201,7 @@ declare const OpenAIChatBody: Schema.Struct<{
201
201
  }>;
202
202
  export type OpenAIChatBody = Schema.Schema.Type<typeof OpenAIChatBody>;
203
203
  export declare const OpenAIChatEvent: Schema.Struct<{
204
- readonly choices: Schema.optional<Schema.NullOr<Schema.$Array<Schema.Struct<{
204
+ readonly choices: Schema.optional<Schema.NullOr<Schema.$Array<Schema.StructWithRest<Schema.Struct<{
205
205
  readonly delta: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
206
206
  readonly content: Schema.optional<Schema.NullOr<Schema.String>>;
207
207
  readonly refusal: Schema.optional<Schema.NullOr<Schema.String>>;
@@ -220,11 +220,29 @@ export declare const OpenAIChatEvent: Schema.Struct<{
220
220
  }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
221
221
  readonly finish_reason: Schema.optional<Schema.NullOr<Schema.String>>;
222
222
  readonly native_finish_reason: Schema.optional<Schema.NullOr<Schema.String>>;
223
- }>>>>;
223
+ readonly usage: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
224
+ readonly prompt_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
225
+ readonly completion_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
226
+ readonly total_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
227
+ readonly cached_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
228
+ readonly prompt_cache_hit_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
229
+ readonly prompt_tokens_details: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
230
+ readonly cached_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
231
+ readonly cache_write_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
232
+ }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
233
+ readonly completion_tokens_details: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
234
+ readonly reasoning_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
235
+ readonly accepted_prediction_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
236
+ readonly rejected_prediction_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
237
+ }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
238
+ }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
239
+ }>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>>;
224
240
  readonly usage: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
225
241
  readonly prompt_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
226
242
  readonly completion_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
227
243
  readonly total_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
244
+ readonly cached_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
245
+ readonly prompt_cache_hit_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
228
246
  readonly prompt_tokens_details: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
229
247
  readonly cached_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
230
248
  readonly cache_write_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
@@ -566,6 +584,8 @@ export declare const protocol: Protocol<{
566
584
  readonly prompt_tokens?: number | null | undefined;
567
585
  readonly completion_tokens?: number | null | undefined;
568
586
  readonly total_tokens?: number | null | undefined;
587
+ readonly cached_tokens?: number | null | undefined;
588
+ readonly prompt_cache_hit_tokens?: number | null | undefined;
569
589
  readonly prompt_tokens_details?: {
570
590
  readonly [x: string]: unknown;
571
591
  readonly cached_tokens?: number | null | undefined;
@@ -579,6 +599,7 @@ export declare const protocol: Protocol<{
579
599
  } | null | undefined;
580
600
  } | null | undefined;
581
601
  readonly choices?: readonly {
602
+ readonly [x: string]: unknown;
582
603
  readonly delta?: {
583
604
  readonly [x: string]: unknown;
584
605
  readonly reasoning?: string | null | undefined;
@@ -596,6 +617,25 @@ export declare const protocol: Protocol<{
596
617
  }[] | null | undefined;
597
618
  readonly reasoning_details?: unknown;
598
619
  } | null | undefined;
620
+ readonly usage?: {
621
+ readonly [x: string]: unknown;
622
+ readonly prompt_tokens?: number | null | undefined;
623
+ readonly completion_tokens?: number | null | undefined;
624
+ readonly total_tokens?: number | null | undefined;
625
+ readonly cached_tokens?: number | null | undefined;
626
+ readonly prompt_cache_hit_tokens?: number | null | undefined;
627
+ readonly prompt_tokens_details?: {
628
+ readonly [x: string]: unknown;
629
+ readonly cached_tokens?: number | null | undefined;
630
+ readonly cache_write_tokens?: number | null | undefined;
631
+ } | null | undefined;
632
+ readonly completion_tokens_details?: {
633
+ readonly [x: string]: unknown;
634
+ readonly reasoning_tokens?: number | null | undefined;
635
+ readonly accepted_prediction_tokens?: number | null | undefined;
636
+ readonly rejected_prediction_tokens?: number | null | undefined;
637
+ } | null | undefined;
638
+ } | null | undefined;
599
639
  readonly finish_reason?: string | null | undefined;
600
640
  readonly native_finish_reason?: string | null | undefined;
601
641
  }[] | null | undefined;
@@ -123,6 +123,9 @@ const OpenAIChatUsage = Schema.StructWithRest(Schema.Struct({
123
123
  prompt_tokens: optionalNull(Schema.Number),
124
124
  completion_tokens: optionalNull(Schema.Number),
125
125
  total_tokens: optionalNull(Schema.Number),
126
+ // Zai reports cache hits as top-level `cached_tokens`; DeepSeek uses `prompt_cache_hit_tokens`.
127
+ cached_tokens: optionalNull(Schema.Number),
128
+ prompt_cache_hit_tokens: optionalNull(Schema.Number),
126
129
  prompt_tokens_details: optionalNull(Schema.StructWithRest(Schema.Struct({
127
130
  cached_tokens: optionalNull(Schema.Number),
128
131
  cache_write_tokens: optionalNull(Schema.Number),
@@ -151,11 +154,13 @@ const OpenAIChatDelta = Schema.StructWithRest(Schema.Struct({
151
154
  reasoning_details: optionalNull(Schema.Unknown),
152
155
  tool_calls: optionalNull(Schema.Array(OpenAIChatToolCallDelta)),
153
156
  }), [Schema.Record(Schema.String, Schema.Unknown)]);
154
- const OpenAIChatChoice = Schema.Struct({
157
+ const OpenAIChatChoice = Schema.StructWithRest(Schema.Struct({
155
158
  delta: optionalNull(OpenAIChatDelta),
156
159
  finish_reason: optionalNull(Schema.String),
157
160
  native_finish_reason: optionalNull(Schema.String),
158
- });
161
+ // Moonshot streams usage on `choice.usage` instead of top-level `usage`.
162
+ usage: optionalNull(OpenAIChatUsage),
163
+ }), [Schema.Record(Schema.String, Schema.Unknown)]);
159
164
  const OpenAIChatError = Schema.Struct({
160
165
  code: optionalNull(Schema.Union([Schema.String, Schema.Number])),
161
166
  message: Schema.String,
@@ -170,7 +175,7 @@ const lowerTool = (tool, inputSchema, options) => ({
170
175
  function: {
171
176
  name: tool.name,
172
177
  description: tool.description,
173
- parameters: ToolSchemaProjection.openAI(inputSchema),
178
+ parameters: inputSchema,
174
179
  },
175
180
  cache_control: options.cacheControl?.(tool.cache),
176
181
  });
@@ -396,6 +401,18 @@ const lowerMessages = Effect.fn("OpenAIChat.lowerMessages")(function* (request,
396
401
  flushImages();
397
402
  return messages;
398
403
  });
404
+ // Anthropic via LiteLLM and Amazon Bedrock require `tools` to be present
405
+ // whenever the conversation history contains tool calls/results. Send an
406
+ // explicit empty array when we have history but no active tools.
407
+ const hasToolHistory = (messages) => {
408
+ for (const message of messages) {
409
+ if (message.role === "tool")
410
+ return true;
411
+ if (message.role === "assistant" && message.content.some((part) => part.type === "tool-call"))
412
+ return true;
413
+ }
414
+ return false;
415
+ };
399
416
  const lowerOptions = (request) => {
400
417
  const options = OpenAIOptions.resolve(request);
401
418
  return {
@@ -413,11 +430,14 @@ export const fromRequest = Effect.fn("OpenAIChat.fromRequest")(function* (reques
413
430
  const generation = request.generation;
414
431
  const toolSchemaCompatibility = request.model.compatibility?.toolSchema;
415
432
  const maxTokensField = request.model.compatibility?.maxTokensField ?? "max_tokens";
433
+ const hasHistory = hasToolHistory(request.messages);
416
434
  return {
417
435
  model: request.model.id,
418
436
  messages: yield* lowerMessages(request, options),
419
437
  tools: request.tools.length === 0
420
- ? undefined
438
+ ? hasHistory
439
+ ? []
440
+ : undefined
421
441
  : request.tools.map((tool) => lowerTool(tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, toolSchemaCompatibility), options)),
422
442
  tool_choice: request.toolChoice ? yield* lowerToolChoice(request.toolChoice) : undefined,
423
443
  stream: true,
@@ -458,12 +478,18 @@ const mapFinishReason = (reason) => {
458
478
  // total) with a `reasoning_tokens` subset. We pass the inclusive totals
459
479
  // through and derive the non-cached breakdown so the `AI.Usage` contract is
460
480
  // satisfied on both sides.
481
+ // Providers differ on cache-hit location: OpenAI uses
482
+ // `prompt_tokens_details.cached_tokens`, DeepSeek uses
483
+ // `prompt_cache_hit_tokens`, and Zai uses top-level `cached_tokens`.
461
484
  const mapUsage = (usage) => {
462
485
  if (!usage)
463
486
  return undefined;
464
487
  const input = usage.prompt_tokens ?? undefined;
465
488
  const output = usage.completion_tokens ?? undefined;
466
- const cached = usage.prompt_tokens_details?.cached_tokens ?? undefined;
489
+ const cached = (usage.prompt_tokens_details?.cached_tokens ??
490
+ usage.prompt_cache_hit_tokens ??
491
+ usage.cached_tokens ??
492
+ undefined);
467
493
  const cacheWrite = usage.prompt_tokens_details?.cache_write_tokens ?? undefined;
468
494
  const reasoning = usage.completion_tokens_details?.reasoning_tokens ?? undefined;
469
495
  const nonCached = ProviderShared.subtractTokens(input, ProviderShared.sumTokens(cached, cacheWrite));
@@ -554,8 +580,11 @@ const step = (state, event) => Effect.gen(function* () {
554
580
  }),
555
581
  });
556
582
  const events = [];
557
- const usage = mapUsage(event.usage) ?? state.usage;
558
583
  const choice = event.choices?.[0];
584
+ // Moonshot (and a few other OpenAI-compatible providers) attach usage to
585
+ // `choice.usage` instead of the top-level `usage` field.
586
+ const choiceUsage = choice?.usage;
587
+ const usage = mapUsage(event.usage) ?? (choiceUsage ? mapUsage(choiceUsage) : undefined) ?? state.usage;
559
588
  const rawFinishReason = choice?.finish_reason;
560
589
  const finishReason = rawFinishReason !== undefined && rawFinishReason !== null
561
590
  ? { normalized: mapFinishReason(rawFinishReason), raw: choice?.native_finish_reason ?? rawFinishReason }
@@ -115,7 +115,6 @@ const HOSTED_TOOLS = {
115
115
  name: "mcp",
116
116
  input: (item) => ({ server_label: item.server_label, name: item.name, arguments: item.arguments }),
117
117
  },
118
- local_shell_call: { name: "local_shell", input: (item) => item.action ?? {} },
119
118
  };
120
119
  const step = (state, event) => {
121
120
  if (event.type === "response.reasoning_text.delta" || event.type === "response.reasoning_summary.delta")
@@ -1,20 +1,5 @@
1
1
  import { isRecord } from "../../utils/record.js";
2
2
  import { GeminiToolSchema } from "./gemini-tool-schema.js";
3
- const removeNullSchemas = (value) => {
4
- if (Array.isArray(value))
5
- return value.map(removeNullSchemas);
6
- if (!isRecord(value))
7
- return value;
8
- const fields = Object.fromEntries(Object.entries(value)
9
- .filter(([key]) => key !== "anyOf")
10
- .map(([key, field]) => [key, removeNullSchemas(field)]));
11
- if (!Array.isArray(value.anyOf))
12
- return fields;
13
- const variants = value.anyOf.filter((variant) => !isRecord(variant) || variant.type !== "null").map(removeNullSchemas);
14
- if (variants.length === 1 && isRecord(variants[0]))
15
- return { ...fields, ...variants[0] };
16
- return { ...fields, anyOf: variants };
17
- };
18
3
  const tupleItemsSchema = (items) => {
19
4
  const projected = items.map(moonshotNode);
20
5
  if (projected.length === 0)
@@ -47,19 +32,7 @@ const moonshot = (schema) => {
47
32
  const projected = moonshotNode(schema);
48
33
  return isRecord(projected) ? projected : {};
49
34
  };
50
- const openAI = (schema) => {
51
- const variants = Array.isArray(schema.anyOf) ? schema.anyOf.filter(isRecord) : [];
52
- const flattened = variants.length === 0
53
- ? { ...schema, type: "object" }
54
- : {
55
- ...Object.fromEntries(Object.entries(schema).filter(([key]) => key !== "anyOf")),
56
- type: "object",
57
- properties: variants.reduce((properties, variant) => ({ ...(isRecord(variant.properties) ? variant.properties : {}), ...properties }), {}),
58
- additionalProperties: false,
59
- };
60
- const normalized = removeNullSchemas(flattened);
61
- return isRecord(normalized) ? normalized : { type: "object" };
62
- };
35
+ const openAI = (schema) => schema;
63
36
  const responses = openAI;
64
37
  const gemini = (schema) => GeminiToolSchema.convert(schema) ?? {};
65
38
  const modelCompatibility = (schema, compatibility) => {
@@ -182,6 +182,7 @@ export declare const routes: import("../route/client.js").Route<{
182
182
  readonly thinking?: {
183
183
  readonly type: "enabled";
184
184
  readonly budget_tokens: number;
185
+ readonly display?: "summarized" | "omitted" | undefined;
185
186
  } | {
186
187
  readonly type: "adaptive";
187
188
  readonly display?: "summarized" | "omitted" | undefined;
@@ -166,6 +166,7 @@ export declare const routes: import("../route/client.js").Route<{
166
166
  readonly thinking?: {
167
167
  readonly type: "enabled";
168
168
  readonly budget_tokens: number;
169
+ readonly display?: "summarized" | "omitted" | undefined;
169
170
  } | {
170
171
  readonly type: "adaptive";
171
172
  readonly display?: "summarized" | "omitted" | undefined;
@@ -180,6 +180,7 @@ export declare const routes: Route<{
180
180
  thinking?: {
181
181
  readonly type: "enabled";
182
182
  readonly budget_tokens: number;
183
+ readonly display?: "summarized" | "omitted" | undefined;
183
184
  } | {
184
185
  readonly type: "adaptive";
185
186
  readonly display?: "summarized" | "omitted" | undefined;
@@ -28,23 +28,22 @@ export type Settings = ProviderPackage.Settings & ({
28
28
  };
29
29
  export declare const routes: Route<{
30
30
  readonly contents: readonly {
31
- readonly role: "model" | "user";
32
- readonly parts: readonly ({
31
+ readonly parts?: readonly ({
33
32
  readonly inlineData: {
34
33
  readonly mimeType: string;
35
34
  readonly data: string;
36
35
  };
37
36
  } | {
38
37
  readonly text: string;
39
- readonly thought?: boolean | undefined;
40
- readonly thoughtSignature?: string | undefined;
38
+ readonly thought?: boolean | null | undefined;
39
+ readonly thoughtSignature?: string | null | undefined;
41
40
  } | {
42
41
  readonly functionCall: {
43
42
  readonly name: string;
44
- readonly id?: string | undefined;
43
+ readonly id?: string | null | undefined;
45
44
  readonly args?: unknown;
46
45
  };
47
- readonly thoughtSignature?: string | undefined;
46
+ readonly thoughtSignature?: string | null | undefined;
48
47
  } | {
49
48
  readonly functionResponse: {
50
49
  readonly name: string;
@@ -57,7 +56,8 @@ export declare const routes: Route<{
57
56
  };
58
57
  }[] | undefined;
59
58
  };
60
- })[];
59
+ })[] | null | undefined;
60
+ readonly role?: "model" | "user" | null | undefined;
61
61
  }[];
62
62
  readonly tools?: readonly {
63
63
  readonly functionDeclarations: readonly {
@@ -14,7 +14,7 @@ const fromRequest = Effect.fn("GoogleVertex.fromRequest")(function* (request) {
14
14
  // unlike AI Studio, so history minted there cannot be lowered verbatim.
15
15
  const contents = body.contents.map((content) => ({
16
16
  ...content,
17
- parts: content.parts.map((part) => {
17
+ parts: (content.parts ?? []).map((part) => {
18
18
  if ("functionCall" in part)
19
19
  return { ...part, functionCall: { ...part.functionCall, id: undefined } };
20
20
  if ("functionResponse" in part)
@@ -9,23 +9,22 @@ export type GeminiProviderOptionsInput = Gemini.ProviderOptionsInput;
9
9
  export declare const id: string & import("effect/Brand").Brand<"AI.ProviderID">;
10
10
  export declare const routes: import("../route/client.js").Route<{
11
11
  readonly contents: readonly {
12
- readonly role: "model" | "user";
13
- readonly parts: readonly ({
12
+ readonly parts?: readonly ({
14
13
  readonly inlineData: {
15
14
  readonly mimeType: string;
16
15
  readonly data: string;
17
16
  };
18
17
  } | {
19
18
  readonly text: string;
20
- readonly thought?: boolean | undefined;
21
- readonly thoughtSignature?: string | undefined;
19
+ readonly thought?: boolean | null | undefined;
20
+ readonly thoughtSignature?: string | null | undefined;
22
21
  } | {
23
22
  readonly functionCall: {
24
23
  readonly name: string;
25
- readonly id?: string | undefined;
24
+ readonly id?: string | null | undefined;
26
25
  readonly args?: unknown;
27
26
  };
28
- readonly thoughtSignature?: string | undefined;
27
+ readonly thoughtSignature?: string | null | undefined;
29
28
  } | {
30
29
  readonly functionResponse: {
31
30
  readonly name: string;
@@ -38,7 +37,8 @@ export declare const routes: import("../route/client.js").Route<{
38
37
  };
39
38
  }[] | undefined;
40
39
  };
41
- })[];
40
+ })[] | null | undefined;
41
+ readonly role?: "model" | "user" | null | undefined;
42
42
  }[];
43
43
  readonly tools?: readonly {
44
44
  readonly functionDeclarations: readonly {
@@ -288,6 +288,8 @@ export declare const protocol: Protocol<{
288
288
  readonly prompt_tokens?: number | null | undefined;
289
289
  readonly completion_tokens?: number | null | undefined;
290
290
  readonly total_tokens?: number | null | undefined;
291
+ readonly cached_tokens?: number | null | undefined;
292
+ readonly prompt_cache_hit_tokens?: number | null | undefined;
291
293
  readonly prompt_tokens_details?: {
292
294
  readonly [x: string]: unknown;
293
295
  readonly cached_tokens?: number | null | undefined;
@@ -301,6 +303,7 @@ export declare const protocol: Protocol<{
301
303
  } | null | undefined;
302
304
  } | null | undefined;
303
305
  readonly choices?: readonly {
306
+ readonly [x: string]: unknown;
304
307
  readonly delta?: {
305
308
  readonly [x: string]: unknown;
306
309
  readonly reasoning?: string | null | undefined;
@@ -318,6 +321,25 @@ export declare const protocol: Protocol<{
318
321
  }[] | null | undefined;
319
322
  readonly reasoning_details?: unknown;
320
323
  } | null | undefined;
324
+ readonly usage?: {
325
+ readonly [x: string]: unknown;
326
+ readonly prompt_tokens?: number | null | undefined;
327
+ readonly completion_tokens?: number | null | undefined;
328
+ readonly total_tokens?: number | null | undefined;
329
+ readonly cached_tokens?: number | null | undefined;
330
+ readonly prompt_cache_hit_tokens?: number | null | undefined;
331
+ readonly prompt_tokens_details?: {
332
+ readonly [x: string]: unknown;
333
+ readonly cached_tokens?: number | null | undefined;
334
+ readonly cache_write_tokens?: number | null | undefined;
335
+ } | null | undefined;
336
+ readonly completion_tokens_details?: {
337
+ readonly [x: string]: unknown;
338
+ readonly reasoning_tokens?: number | null | undefined;
339
+ readonly accepted_prediction_tokens?: number | null | undefined;
340
+ readonly rejected_prediction_tokens?: number | null | undefined;
341
+ } | null | undefined;
342
+ } | null | undefined;
321
343
  readonly finish_reason?: string | null | undefined;
322
344
  readonly native_finish_reason?: string | null | undefined;
323
345
  }[] | null | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "0.0.0-dev-18002",
3
+ "version": "0.0.0-dev-18035",
4
4
  "name": "@opencode-ai/ai",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -29,8 +29,8 @@
29
29
  },
30
30
  "devDependencies": {
31
31
  "@clack/prompts": "1.0.0-alpha.1",
32
- "@effect/platform-node": "4.0.0-rc.110",
33
- "@opencode-ai/http-recorder": "0.0.0-dev-18002",
32
+ "@effect/platform-node": "4.0.0-rc.111",
33
+ "@opencode-ai/http-recorder": "0.0.0-dev-18035",
34
34
  "@tsconfig/bun": "1.0.9",
35
35
  "@types/bun": "1.3.13",
36
36
  "@typescript/native-preview": "7.0.0-dev.20251207.1",
@@ -39,9 +39,9 @@
39
39
  "dependencies": {
40
40
  "@smithy/eventstream-codec": "4.2.14",
41
41
  "@smithy/util-utf8": "4.2.2",
42
- "@opencode-ai/schema": "0.0.0-dev-18002",
42
+ "@opencode-ai/schema": "0.0.0-dev-18035",
43
43
  "aws4fetch": "1.0.20",
44
- "effect": "4.0.0-rc.110",
44
+ "effect": "4.0.0-rc.111",
45
45
  "google-auth-library": "10.5.0"
46
46
  }
47
47
  }