@opencode/ai 2.0.14 → 2.0.16

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 (208) hide show
  1. package/README.md +399 -56
  2. package/dist/experimental/evaluation-client.d.ts +1 -1
  3. package/dist/experimental/evaluation-client.js +39 -3
  4. package/dist/experimental/evaluation.d.ts +4 -4
  5. package/dist/experimental/evaluation.js +2 -2
  6. package/dist/experimental/system-one.d.ts +3 -3
  7. package/dist/experimental/system-one.js +40 -51
  8. package/dist/generation.d.ts +83 -0
  9. package/dist/generation.js +113 -0
  10. package/dist/image-client.d.ts +16 -7
  11. package/dist/image-client.js +29 -13
  12. package/dist/image.d.ts +1410 -81
  13. package/dist/image.js +97 -67
  14. package/dist/index.d.ts +17 -2
  15. package/dist/index.js +12 -1
  16. package/dist/llm.d.ts +9 -1
  17. package/dist/media-model.d.ts +44 -0
  18. package/dist/media-model.js +49 -0
  19. package/dist/media.d.ts +213 -0
  20. package/dist/media.js +227 -0
  21. package/dist/promise.d.ts +974 -0
  22. package/dist/promise.js +81 -0
  23. package/dist/protocols/alibaba-chat.d.ts +12 -0
  24. package/dist/protocols/alibaba-responses.d.ts +2 -2
  25. package/dist/protocols/anthropic-messages.js +8 -19
  26. package/dist/protocols/assemblyai-transcription.d.ts +40 -0
  27. package/dist/protocols/assemblyai-transcription.js +138 -0
  28. package/dist/protocols/bedrock-converse.d.ts +4 -4
  29. package/dist/protocols/bedrock-converse.js +6 -17
  30. package/dist/protocols/bfl-images.d.ts +32 -0
  31. package/dist/protocols/bfl-images.js +153 -0
  32. package/dist/protocols/cartesia-speech.d.ts +127 -0
  33. package/dist/protocols/cartesia-speech.js +126 -0
  34. package/dist/protocols/deepgram-speech.d.ts +119 -0
  35. package/dist/protocols/deepgram-speech.js +92 -0
  36. package/dist/protocols/deepgram-transcription.d.ts +25 -0
  37. package/dist/protocols/deepgram-transcription.js +129 -0
  38. package/dist/protocols/elevenlabs-speech.d.ts +122 -0
  39. package/dist/protocols/elevenlabs-speech.js +115 -0
  40. package/dist/protocols/fal-images.d.ts +24 -0
  41. package/dist/protocols/fal-images.js +114 -0
  42. package/dist/protocols/fal-video.d.ts +29 -0
  43. package/dist/protocols/fal-video.js +88 -0
  44. package/dist/protocols/gemini.d.ts +30 -9
  45. package/dist/protocols/gemini.js +45 -35
  46. package/dist/protocols/google-images.d.ts +9 -21
  47. package/dist/protocols/google-images.js +158 -133
  48. package/dist/protocols/google-speech.d.ts +130 -0
  49. package/dist/protocols/google-speech.js +84 -0
  50. package/dist/protocols/google-transcription.d.ts +173 -0
  51. package/dist/protocols/google-transcription.js +138 -0
  52. package/dist/protocols/google-video.d.ts +26 -0
  53. package/dist/protocols/google-video.js +158 -0
  54. package/dist/protocols/meta-images.d.ts +7 -12
  55. package/dist/protocols/meta-images.js +85 -66
  56. package/dist/protocols/meta-responses.d.ts +4 -4
  57. package/dist/protocols/meta-responses.js +1 -1
  58. package/dist/protocols/mistral-chat.js +7 -6
  59. package/dist/protocols/open-responses.d.ts +17 -9
  60. package/dist/protocols/open-responses.js +24 -14
  61. package/dist/protocols/openai-chat.d.ts +118 -1
  62. package/dist/protocols/openai-chat.js +125 -44
  63. package/dist/protocols/openai-compatible-chat.d.ts +12 -0
  64. package/dist/protocols/openai-compatible-responses.d.ts +2 -2
  65. package/dist/protocols/openai-images.d.ts +128 -18
  66. package/dist/protocols/openai-images.js +177 -154
  67. package/dist/protocols/openai-responses.d.ts +15 -15
  68. package/dist/protocols/openai-responses.js +5 -6
  69. package/dist/protocols/openai-speech.d.ts +116 -0
  70. package/dist/protocols/openai-speech.js +98 -0
  71. package/dist/protocols/openai-transcription.d.ts +207 -0
  72. package/dist/protocols/openai-transcription.js +190 -0
  73. package/dist/protocols/replicate-images.d.ts +28 -0
  74. package/dist/protocols/replicate-images.js +133 -0
  75. package/dist/protocols/runway-video.d.ts +38 -0
  76. package/dist/protocols/runway-video.js +146 -0
  77. package/dist/protocols/shared.d.ts +27 -17
  78. package/dist/protocols/shared.js +52 -35
  79. package/dist/protocols/stability-images.d.ts +38 -0
  80. package/dist/protocols/stability-images.js +148 -0
  81. package/dist/protocols/utils/bedrock-media.d.ts +2 -3
  82. package/dist/protocols/utils/bedrock-media.js +4 -4
  83. package/dist/protocols/utils/fal-queue.d.ts +28 -0
  84. package/dist/protocols/utils/fal-queue.js +69 -0
  85. package/dist/protocols/utils/gemini-generate-content.d.ts +65 -0
  86. package/dist/protocols/utils/gemini-generate-content.js +65 -0
  87. package/dist/protocols/utils/gemini-json-schema.d.ts +3 -0
  88. package/dist/protocols/utils/gemini-json-schema.js +76 -0
  89. package/dist/protocols/utils/media-input.d.ts +18 -0
  90. package/dist/protocols/utils/media-input.js +35 -0
  91. package/dist/protocols/utils/responses-compaction.js +6 -5
  92. package/dist/protocols/utils/speech-stream.d.ts +49 -0
  93. package/dist/protocols/utils/speech-stream.js +67 -0
  94. package/dist/protocols/utils/tool-schema.d.ts +2 -2
  95. package/dist/protocols/utils/tool-schema.js +40 -17
  96. package/dist/protocols/utils/tool-stream.d.ts +27 -3
  97. package/dist/protocols/xai-images.d.ts +9 -15
  98. package/dist/protocols/xai-images.js +75 -84
  99. package/dist/protocols/xai-responses.d.ts +2 -2
  100. package/dist/protocols/xai-video.d.ts +34 -0
  101. package/dist/protocols/xai-video.js +147 -0
  102. package/dist/protocols/zai-chat.d.ts +13 -1
  103. package/dist/protocols/zai-images.d.ts +9 -13
  104. package/dist/protocols/zai-images.js +59 -57
  105. package/dist/provider-error.js +3 -0
  106. package/dist/providers/alibaba.d.ts +14 -2
  107. package/dist/providers/amazon-bedrock-mantle.d.ts +14 -2
  108. package/dist/providers/amazon-bedrock.d.ts +2 -2
  109. package/dist/providers/assemblyai.d.ts +25 -0
  110. package/dist/providers/assemblyai.js +29 -0
  111. package/dist/providers/azure.d.ts +18 -6
  112. package/dist/providers/baseten.d.ts +24 -0
  113. package/dist/providers/black-forest-labs.d.ts +25 -0
  114. package/dist/providers/black-forest-labs.js +28 -0
  115. package/dist/providers/cartesia.d.ts +24 -0
  116. package/dist/providers/cartesia.js +22 -0
  117. package/dist/providers/cerebras.d.ts +24 -0
  118. package/dist/providers/cerebras.js +6 -1
  119. package/dist/providers/cloudflare-ai-gateway.d.ts +30 -6
  120. package/dist/providers/cloudflare-workers-ai.d.ts +24 -0
  121. package/dist/providers/deepgram.d.ts +29 -0
  122. package/dist/providers/deepgram.js +31 -0
  123. package/dist/providers/deepinfra.d.ts +24 -0
  124. package/dist/providers/deepinfra.js +6 -1
  125. package/dist/providers/deepseek.d.ts +24 -0
  126. package/dist/providers/elevenlabs.d.ts +24 -0
  127. package/dist/providers/elevenlabs.js +28 -0
  128. package/dist/providers/fal.d.ts +29 -0
  129. package/dist/providers/fal.js +33 -0
  130. package/dist/providers/fireworks.d.ts +24 -0
  131. package/dist/providers/google-vertex-chat.d.ts +12 -0
  132. package/dist/providers/google-vertex-responses.d.ts +2 -2
  133. package/dist/providers/google-vertex.d.ts +10 -3
  134. package/dist/providers/google.d.ts +25 -3
  135. package/dist/providers/google.js +11 -2
  136. package/dist/providers/groq.d.ts +24 -0
  137. package/dist/providers/index.d.ts +10 -0
  138. package/dist/providers/index.js +10 -0
  139. package/dist/providers/meta.d.ts +14 -2
  140. package/dist/providers/minimax.d.ts +14 -2
  141. package/dist/providers/moonshot.d.ts +14 -2
  142. package/dist/providers/moonshot.js +3 -3
  143. package/dist/providers/openai-compatible-responses.d.ts +2 -2
  144. package/dist/providers/openai-compatible.d.ts +12 -0
  145. package/dist/providers/openai.d.ts +25 -3
  146. package/dist/providers/openai.js +10 -1
  147. package/dist/providers/openrouter.d.ts +67 -0
  148. package/dist/providers/openrouter.js +13 -1
  149. package/dist/providers/replicate.d.ts +25 -0
  150. package/dist/providers/replicate.js +22 -0
  151. package/dist/providers/runway.d.ts +24 -0
  152. package/dist/providers/runway.js +22 -0
  153. package/dist/providers/stability.d.ts +28 -0
  154. package/dist/providers/stability.js +23 -0
  155. package/dist/providers/togetherai.d.ts +24 -0
  156. package/dist/providers/vercel-ai-gateway.d.ts +41 -0
  157. package/dist/providers/vercel-ai-gateway.js +85 -0
  158. package/dist/providers/xai.d.ts +17 -0
  159. package/dist/providers/xai.js +5 -2
  160. package/dist/providers/zai-coding-plan.d.ts +15 -3
  161. package/dist/providers/zai.d.ts +13 -1
  162. package/dist/route/auth.d.ts +4 -1
  163. package/dist/route/auth.js +6 -0
  164. package/dist/route/client.d.ts +9 -1
  165. package/dist/route/endpoint.d.ts +10 -10
  166. package/dist/route/executor-service.d.ts +12 -0
  167. package/dist/route/executor-service.js +3 -0
  168. package/dist/route/executor.d.ts +4 -9
  169. package/dist/route/executor.js +3 -3
  170. package/dist/route/framing.d.ts +5 -1
  171. package/dist/route/framing.js +9 -0
  172. package/dist/route/index.d.ts +2 -0
  173. package/dist/route/index.js +2 -0
  174. package/dist/route/media-protocol.d.ts +158 -0
  175. package/dist/route/media-protocol.js +96 -0
  176. package/dist/route/media.d.ts +97 -0
  177. package/dist/route/media.js +236 -0
  178. package/dist/schema/errors.d.ts +13 -3
  179. package/dist/schema/errors.js +7 -0
  180. package/dist/schema/events.d.ts +557 -40
  181. package/dist/schema/events.js +35 -2
  182. package/dist/schema/messages.d.ts +95 -8
  183. package/dist/schema/messages.js +8 -6
  184. package/dist/schema/options.d.ts +6 -3
  185. package/dist/schema/options.js +6 -2
  186. package/dist/speech-client.d.ts +21 -0
  187. package/dist/speech-client.js +25 -0
  188. package/dist/speech.d.ts +1150 -0
  189. package/dist/speech.js +119 -0
  190. package/dist/testing.d.ts +72 -8
  191. package/dist/transcription-client.d.ts +28 -0
  192. package/dist/transcription-client.js +44 -0
  193. package/dist/transcription.d.ts +1504 -0
  194. package/dist/transcription.js +133 -0
  195. package/dist/utils/bytes.d.ts +1 -0
  196. package/dist/utils/bytes.js +10 -0
  197. package/dist/utils/media-type.d.ts +7 -0
  198. package/dist/utils/media-type.js +70 -0
  199. package/dist/utils/sanitize.js +3 -1
  200. package/dist/video-client.d.ts +28 -0
  201. package/dist/video-client.js +40 -0
  202. package/dist/video.d.ts +1359 -0
  203. package/dist/video.js +119 -0
  204. package/package.json +7 -3
  205. package/dist/protocols/utils/gemini-tool-schema.d.ts +0 -2
  206. package/dist/protocols/utils/gemini-tool-schema.js +0 -103
  207. package/dist/protocols/utils/image-input.d.ts +0 -21
  208. package/dist/protocols/utils/image-input.js +0 -20
@@ -33,6 +33,12 @@ declare const GeminiBody: Schema.Struct<{
33
33
  readonly mimeType: Schema.String;
34
34
  readonly data: Schema.String;
35
35
  }>;
36
+ readonly thoughtSignature: Schema.optional<Schema.NullOr<Schema.String>>;
37
+ }>, Schema.Struct<{
38
+ readonly fileData: Schema.Struct<{
39
+ readonly mimeType: Schema.String;
40
+ readonly fileUri: Schema.String;
41
+ }>;
36
42
  }>, Schema.Struct<{
37
43
  readonly functionCall: Schema.Struct<{
38
44
  readonly id: Schema.optional<Schema.NullOr<Schema.String>>;
@@ -50,6 +56,7 @@ declare const GeminiBody: Schema.Struct<{
50
56
  readonly mimeType: Schema.String;
51
57
  readonly data: Schema.String;
52
58
  }>;
59
+ readonly thoughtSignature: Schema.optional<Schema.NullOr<Schema.String>>;
53
60
  }>>>;
54
61
  }>;
55
62
  }>]>>>>;
@@ -69,7 +76,7 @@ declare const GeminiBody: Schema.Struct<{
69
76
  readonly functionDeclarations: Schema.$Array<Schema.Struct<{
70
77
  readonly name: Schema.String;
71
78
  readonly description: Schema.String;
72
- readonly parameters: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
79
+ readonly parametersJsonSchema: Schema.$Record<Schema.String, Schema.Unknown>;
73
80
  }>>;
74
81
  }>>>;
75
82
  toolConfig: Schema.optional<Schema.Struct<{
@@ -106,10 +113,16 @@ export declare const protocol: Protocol<{
106
113
  readonly mimeType: string;
107
114
  readonly data: string;
108
115
  };
116
+ readonly thoughtSignature?: string | null | undefined;
109
117
  } | {
110
118
  readonly text: string;
111
119
  readonly thought?: boolean | null | undefined;
112
120
  readonly thoughtSignature?: string | null | undefined;
121
+ } | {
122
+ readonly fileData: {
123
+ readonly mimeType: string;
124
+ readonly fileUri: string;
125
+ };
113
126
  } | {
114
127
  readonly functionCall: {
115
128
  readonly name: string;
@@ -127,6 +140,7 @@ export declare const protocol: Protocol<{
127
140
  readonly mimeType: string;
128
141
  readonly data: string;
129
142
  };
143
+ readonly thoughtSignature?: string | null | undefined;
130
144
  }[] | undefined;
131
145
  };
132
146
  })[] | null | undefined;
@@ -134,11 +148,11 @@ export declare const protocol: Protocol<{
134
148
  }[];
135
149
  readonly tools?: readonly {
136
150
  readonly functionDeclarations: readonly {
137
- readonly description: string;
138
151
  readonly name: string;
139
- readonly parameters?: {
152
+ readonly description: string;
153
+ readonly parametersJsonSchema: {
140
154
  readonly [x: string]: unknown;
141
- } | undefined;
155
+ };
142
156
  }[];
143
157
  }[] | undefined;
144
158
  readonly serviceTier?: string | undefined;
@@ -192,11 +206,11 @@ export declare const protocol: Protocol<{
192
206
  readonly safetyRatings?: unknown;
193
207
  } | null | undefined;
194
208
  readonly usageMetadata?: {
195
- readonly cachedContentTokenCount?: number | null | undefined;
196
- readonly thoughtsTokenCount?: number | null | undefined;
197
209
  readonly promptTokenCount?: number | null | undefined;
198
210
  readonly candidatesTokenCount?: number | null | undefined;
199
211
  readonly totalTokenCount?: number | null | undefined;
212
+ readonly cachedContentTokenCount?: number | null | undefined;
213
+ readonly thoughtsTokenCount?: number | null | undefined;
200
214
  } | null | undefined;
201
215
  }, {
202
216
  route: string;
@@ -213,10 +227,16 @@ export declare const route: Route<{
213
227
  readonly mimeType: string;
214
228
  readonly data: string;
215
229
  };
230
+ readonly thoughtSignature?: string | null | undefined;
216
231
  } | {
217
232
  readonly text: string;
218
233
  readonly thought?: boolean | null | undefined;
219
234
  readonly thoughtSignature?: string | null | undefined;
235
+ } | {
236
+ readonly fileData: {
237
+ readonly mimeType: string;
238
+ readonly fileUri: string;
239
+ };
220
240
  } | {
221
241
  readonly functionCall: {
222
242
  readonly name: string;
@@ -234,6 +254,7 @@ export declare const route: Route<{
234
254
  readonly mimeType: string;
235
255
  readonly data: string;
236
256
  };
257
+ readonly thoughtSignature?: string | null | undefined;
237
258
  }[] | undefined;
238
259
  };
239
260
  })[] | null | undefined;
@@ -241,11 +262,11 @@ export declare const route: Route<{
241
262
  }[];
242
263
  readonly tools?: readonly {
243
264
  readonly functionDeclarations: readonly {
244
- readonly description: string;
245
265
  readonly name: string;
246
- readonly parameters?: {
266
+ readonly description: string;
267
+ readonly parametersJsonSchema: {
247
268
  readonly [x: string]: unknown;
248
- } | undefined;
269
+ };
249
270
  }[];
250
271
  }[] | undefined;
251
272
  readonly serviceTier?: string | undefined;
@@ -7,8 +7,9 @@ import { Framing } from "../route/framing.js";
7
7
  import { Protocol } from "../route/protocol.js";
8
8
  import { AIError, LLMEvent, Usage, } from "../schema/index.js";
9
9
  import { classifyProviderFailure } from "../provider-error.js";
10
+ import { Media } from "../media.js";
10
11
  import { JsonObject, knownString, lenient, optionalArray, optionalNull, ProviderShared } from "./shared.js";
11
- import { GeminiToolSchema } from "./utils/gemini-tool-schema.js";
12
+ import { GeminiGenerateContent } from "./utils/gemini-generate-content.js";
12
13
  import { Lifecycle } from "./utils/lifecycle.js";
13
14
  import { ToolSchemaProjection } from "./utils/tool-schema.js";
14
15
  const ADAPTER = "gemini";
@@ -54,6 +55,14 @@ const GeminiInlineDataPart = Schema.Struct({
54
55
  mimeType: Schema.String,
55
56
  data: Schema.String,
56
57
  }),
58
+ thoughtSignature: optionalNull(Schema.String),
59
+ });
60
+ /** Gemini Files API reference; the only remote input Gemini accepts. */
61
+ const GeminiFileDataPart = Schema.Struct({
62
+ fileData: Schema.Struct({
63
+ mimeType: Schema.String,
64
+ fileUri: Schema.String,
65
+ }),
57
66
  });
58
67
  const GeminiFunctionCallPart = Schema.Struct({
59
68
  functionCall: Schema.Struct({
@@ -74,6 +83,7 @@ const GeminiFunctionResponsePart = Schema.Struct({
74
83
  const GeminiContentPart = Schema.Union([
75
84
  GeminiTextPart,
76
85
  GeminiInlineDataPart,
86
+ GeminiFileDataPart,
77
87
  GeminiFunctionCallPart,
78
88
  GeminiFunctionResponsePart,
79
89
  ]);
@@ -92,7 +102,7 @@ const GeminiSystemInstruction = Schema.Struct({
92
102
  const GeminiFunctionDeclaration = Schema.Struct({
93
103
  name: Schema.String,
94
104
  description: Schema.String,
95
- parameters: Schema.optional(JsonObject),
105
+ parametersJsonSchema: JsonObject,
96
106
  });
97
107
  const GeminiTool = Schema.Struct({
98
108
  functionDeclarations: Schema.Array(GeminiFunctionDeclaration),
@@ -176,34 +186,14 @@ const GeminiEvent = Schema.Struct({
176
186
  usageMetadata: optionalNull(GeminiUsage),
177
187
  });
178
188
  // =============================================================================
179
- // Tool Schema Conversion
180
- // =============================================================================
181
- // Tool-schema conversion has two distinct concerns:
182
- //
183
- // 1. Sanitize — fix common authoring mistakes Gemini rejects: integer/number
184
- // enums (must be strings), `required` entries that don't match a property,
185
- // untyped arrays (`items` must be present), and `properties`/`required`
186
- // keys on non-object scalars. Mirrors OpenCode's historical Gemini rules.
187
- //
188
- // 2. Project — lossy mapping from JSON Schema to Gemini's schema dialect:
189
- // drop empty root parameter schemas while preserving nested empty objects,
190
- // expand type arrays into `anyOf`, derive `nullable: true` from null members,
191
- // coerce `const` to `[const]` enum, recurse properties/items, and propagate
192
- // only an allowlisted set of keys (description, required, format, type,
193
- // nullable, enum, properties, items, allOf, anyOf, oneOf, minLength).
194
- // Anything outside the allowlist (e.g. `additionalProperties`, `$ref`) is
195
- // silently dropped.
196
- //
197
- // Sanitize runs first, then project. The implementation lives in
198
- // `utils/gemini-tool-schema` so this protocol keeps the same shape as the other
199
- // provider protocols.
200
- // =============================================================================
201
189
  // Request Lowering
202
190
  // =============================================================================
203
- const lowerTool = (tool, inputSchema) => ({
191
+ // Tool schemas go in `parametersJsonSchema`, which accepts standard JSON Schema. Gemini's schema
192
+ // rules are this API's default, including for tuned endpoints whose IDs do not name Gemini.
193
+ const lowerTool = (tool, model) => ({
204
194
  name: tool.name,
205
195
  description: tool.description,
206
- parameters: GeminiToolSchema.convert(inputSchema),
196
+ parametersJsonSchema: ToolSchemaProjection.modelCompatibility(tool.inputSchema, model, "gemini"),
207
197
  });
208
198
  const lowerToolConfig = (toolChoice) => ProviderShared.matchToolChoice("Gemini", toolChoice, {
209
199
  auto: () => ({ functionCallingConfig: { mode: "AUTO" } }),
@@ -211,11 +201,10 @@ const lowerToolConfig = (toolChoice) => ProviderShared.matchToolChoice("Gemini",
211
201
  required: () => ({ functionCallingConfig: { mode: "ANY" } }),
212
202
  tool: (name) => ({ functionCallingConfig: { mode: "ANY", allowedFunctionNames: [name] } }),
213
203
  });
214
- const lowerUserPart = Effect.fn("Gemini.lowerUserPart")(function* (part) {
204
+ const lowerContentPart = Effect.fn("Gemini.lowerContentPart")(function* (part) {
215
205
  if (part.type === "text")
216
206
  return { text: part.text };
217
- const media = ProviderShared.normalizeMedia(part);
218
- return { inlineData: { mimeType: media.mime, data: media.base64 } };
207
+ return yield* GeminiGenerateContent.mediaPart("Gemini", part.media);
219
208
  });
220
209
  const providerMetadata = (key, metadata) => ({ [key]: metadata });
221
210
  const thoughtSignature = (metadata, key) => {
@@ -259,7 +248,7 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
259
248
  for (const part of message.content) {
260
249
  if (!ProviderShared.supportsContent(part, ["text", "media"]))
261
250
  return yield* ProviderShared.unsupportedContent("Gemini", "user", ["text", "media"]);
262
- parts.push(yield* lowerUserPart(part));
251
+ parts.push(yield* lowerContentPart(part));
263
252
  }
264
253
  contents.push({ role: "user", parts });
265
254
  continue;
@@ -269,12 +258,23 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
269
258
  // Parallel Gemini 3 calls may carry one signature on the first call; unsigned sibling calls are valid.
270
259
  let hasSignedToolCall = false;
271
260
  for (const part of message.content) {
272
- if (!ProviderShared.supportsContent(part, ["text", "reasoning", "tool-call"]))
273
- return yield* ProviderShared.unsupportedContent("Gemini", "assistant", ["text", "reasoning", "tool-call"]);
261
+ if (!ProviderShared.supportsContent(part, ["text", "reasoning", "tool-call", "media"]))
262
+ return yield* ProviderShared.unsupportedContent("Gemini", "assistant", [
263
+ "text",
264
+ "reasoning",
265
+ "tool-call",
266
+ "media",
267
+ ]);
274
268
  if (part.type === "text") {
275
269
  parts.push({ text: part.text, thoughtSignature: thoughtSignature(part.providerMetadata, metadataKey) });
276
270
  continue;
277
271
  }
272
+ // Generated images replay as model-role inline data so multi-turn image editing keeps the prior output.
273
+ if (part.type === "media") {
274
+ const lowered = yield* lowerContentPart(part);
275
+ parts.push({ ...lowered, thoughtSignature: thoughtSignature(part.providerMetadata, metadataKey) });
276
+ continue;
277
+ }
278
278
  if (part.type === "reasoning") {
279
279
  parts.push({
280
280
  text: part.text,
@@ -324,7 +324,7 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
324
324
  for (const item of content) {
325
325
  if (item.type === "text")
326
326
  continue;
327
- const value = ProviderShared.normalizeToolFile(item);
327
+ const value = yield* ProviderShared.requireInlineMedia("Gemini", ProviderShared.toolFileMedia(item).media);
328
328
  media.push({ inlineData: { mimeType: value.mime, data: value.base64 } });
329
329
  }
330
330
  if (legacyToolMedia && media.length > 0)
@@ -357,7 +357,6 @@ const fromRequest = Effect.fn("Gemini.fromRequest")(function* (request) {
357
357
  const hasTools = flattened.tools.length > 0;
358
358
  const generation = request.generation;
359
359
  const options = yield* decodeOptions(request.providerOptions ?? {});
360
- const toolSchemaCompatibility = request.model.compatibility?.toolSchema;
361
360
  const generationConfig = {
362
361
  maxOutputTokens: generation?.maxTokens,
363
362
  temperature: generation?.temperature,
@@ -380,7 +379,7 @@ const fromRequest = Effect.fn("Gemini.fromRequest")(function* (request) {
380
379
  tools: hasTools
381
380
  ? [
382
381
  {
383
- functionDeclarations: flattened.tools.map((tool) => lowerTool(tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, toolSchemaCompatibility))),
382
+ functionDeclarations: flattened.tools.map((tool) => lowerTool(tool, request.model)),
384
383
  },
385
384
  ]
386
385
  : undefined,
@@ -539,6 +538,17 @@ const step = (state, event) => {
539
538
  reasoningSignature = signature;
540
539
  else if (signature !== undefined && "text" in part)
541
540
  textSignature = signature;
541
+ // Image-capable Gemini models return generated images as inline data parts; surface them as first-class output.
542
+ if ("inlineData" in part) {
543
+ lifecycle = Lifecycle.stepStart(lifecycle, events);
544
+ events.push(LLMEvent.media({
545
+ media: Media.base64(part.inlineData.data, part.inlineData.mimeType),
546
+ providerMetadata: signature
547
+ ? providerMetadata(state.providerMetadataKey, { thoughtSignature: signature })
548
+ : undefined,
549
+ }));
550
+ continue;
551
+ }
542
552
  if ("text" in part && part.text.length > 0) {
543
553
  if (part.thought) {
544
554
  if (textId !== undefined) {
@@ -1,30 +1,18 @@
1
- import { ImageModel } from "../image.js";
2
- import { type Definition as AuthDefinition } from "../route/auth.js";
3
- import { type HttpOptions } from "../schema/index.js";
1
+ import { ImageModel, ImageResponse, type ImageRequestFor } from "../image.js";
2
+ import { MediaProtocol } from "../route/media-protocol.js";
3
+ import { MediaRoute } from "../route/media.js";
4
4
  export declare const DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com/v1beta";
5
5
  export type GoogleImageString<Known extends string> = Known | (string & {});
6
+ /** Provider-native options. Common fields (`aspectRatio`, `seed`, `images`) live on the request. */
6
7
  export type GoogleImageOptions = {
7
- readonly aspectRatio?: GoogleImageString<"1:1" | "2:3" | "3:2" | "3:4" | "4:3" | "4:5" | "5:4" | "9:16" | "16:9" | "21:9">;
8
8
  readonly imageSize?: GoogleImageString<"1K" | "2K" | "4K">;
9
- readonly seed?: number;
10
9
  readonly thinkingLevel?: GoogleImageString<"MINIMAL" | "LOW" | "MEDIUM" | "HIGH">;
11
10
  readonly includeThoughts?: boolean;
12
11
  } & Record<string, unknown>;
13
- export type GoogleImageBody = Record<string, unknown> & {
14
- readonly contents: ReadonlyArray<{
15
- readonly role: "user";
16
- readonly parts: ReadonlyArray<Record<string, unknown>>;
17
- }>;
18
- readonly generationConfig: Record<string, unknown>;
19
- };
20
- export interface ModelInput {
21
- readonly id: string;
22
- readonly auth: AuthDefinition;
23
- readonly baseURL?: string;
24
- readonly headers?: Record<string, string>;
25
- readonly http?: HttpOptions;
26
- }
27
- export declare const model: (input: ModelInput) => ImageModel<GoogleImageOptions>;
12
+ export type Request = ImageRequestFor<GoogleImageOptions>;
13
+ export declare const protocol: MediaProtocol.Inline<Request, ImageResponse>;
14
+ export declare const model: (input: MediaRoute.ModelInput) => ImageModel<GoogleImageOptions>;
28
15
  export declare const GoogleImages: {
29
- readonly model: (input: ModelInput) => ImageModel<GoogleImageOptions>;
16
+ readonly protocol: MediaProtocol.Inline<Request, ImageResponse>;
17
+ readonly model: (input: MediaRoute.ModelInput) => ImageModel<GoogleImageOptions>;
30
18
  };