@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
@@ -1,10 +1,11 @@
1
1
  import { Schema } from "effect";
2
2
  import { LLM } from "@opencode/schema/llm";
3
3
  import { ContentBlockID, ToolCallID } from "./ids.js";
4
- import { Message, CompactionPart, ProviderMetadata, ToolCallPart, ToolOutput, ToolResultPart, ToolResultValue, } from "./messages.js";
4
+ import { Message, CompactionPart, ToolCallPart, ToolOutput, ToolResultPart, ToolResultValue, } from "./messages.js";
5
+ import { ProviderMetadata } from "./options.js";
5
6
  import { ProviderFailureClassification } from "./errors.js";
7
+ import { Media } from "../media.js";
6
8
  export const FinishReason = LLM.FinishReason;
7
- export { ProviderMetadata } from "./messages.js";
8
9
  /**
9
10
  * Token usage reported by an LLM provider.
10
11
  *
@@ -75,6 +76,25 @@ export class Usage extends Schema.Class("AI.Usage")({
75
76
  return input instanceof Usage ? input : new Usage(input);
76
77
  }
77
78
  }
79
+ /**
80
+ * Usage reported by media routes. Providers bill images, video, speech, and transcription in different units, so
81
+ * each response carries the unit it was actually metered in instead of forcing everything into tokens.
82
+ */
83
+ export const MediaUsage = Schema.Union([
84
+ Schema.Struct({
85
+ type: Schema.Literal("tokens"),
86
+ input: Schema.optional(Schema.Number),
87
+ output: Schema.optional(Schema.Number),
88
+ total: Schema.optional(Schema.Number),
89
+ details: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
90
+ }),
91
+ Schema.Struct({ type: Schema.Literal("seconds"), seconds: Schema.Number }),
92
+ Schema.Struct({ type: Schema.Literal("characters"), characters: Schema.Number }),
93
+ Schema.Struct({ type: Schema.Literal("credits"), credits: Schema.Number }),
94
+ Schema.Struct({ type: Schema.Literal("compute"), seconds: Schema.Number }),
95
+ ])
96
+ .pipe(Schema.toTaggedUnion("type"))
97
+ .annotate({ identifier: "AI.MediaUsage" });
78
98
  /** A replacement context window, not an assistant message to append to prior history. */
79
99
  export class CompactionResponse extends Schema.Class("LLM.CompactionResponse")({
80
100
  replacement: Schema.Array(Message),
@@ -205,6 +225,12 @@ export const Finish = Schema.Struct({
205
225
  usage: Schema.optional(Usage),
206
226
  providerMetadata: Schema.optional(ProviderMetadata),
207
227
  }).annotate({ identifier: "LLM.Event.Finish" });
228
+ /** A generated media asset (image, audio, …) emitted by the model as first-class output rather than a tool result. */
229
+ export const MediaEvent = Schema.Struct({
230
+ type: Schema.tag("media"),
231
+ media: Media.AssetSchema,
232
+ providerMetadata: Schema.optional(ProviderMetadata),
233
+ }).annotate({ identifier: "LLM.Event.Media" });
208
234
  export const ProviderErrorEvent = Schema.Struct({
209
235
  type: Schema.tag("provider-error"),
210
236
  message: Schema.String,
@@ -227,6 +253,7 @@ const llmEventTagged = Schema.Union([
227
253
  ToolCall,
228
254
  ToolResult,
229
255
  ToolError,
256
+ MediaEvent,
230
257
  StepFinish,
231
258
  Finish,
232
259
  ProviderErrorEvent,
@@ -258,6 +285,7 @@ export const LLMEvent = Object.assign(llmEventTagged, {
258
285
  output: input.output === undefined ? undefined : ToolOutput.make(input.output.structured, input.output.content),
259
286
  }),
260
287
  toolError: (input) => ToolError.make({ ...input, id: toolCallID(input.id) }),
288
+ media: MediaEvent.make,
261
289
  stepFinish: (input) => StepFinish.make({
262
290
  ...input,
263
291
  usage: input.usage === undefined ? undefined : Usage.from(input.usage),
@@ -283,6 +311,7 @@ export const LLMEvent = Object.assign(llmEventTagged, {
283
311
  toolCall: llmEventTagged.guards["tool-call"],
284
312
  toolResult: llmEventTagged.guards["tool-result"],
285
313
  toolError: llmEventTagged.guards["tool-error"],
314
+ media: llmEventTagged.guards.media,
286
315
  stepFinish: llmEventTagged.guards["step-finish"],
287
316
  finish: llmEventTagged.guards.finish,
288
317
  providerError: llmEventTagged.guards["provider-error"],
@@ -500,6 +529,10 @@ const reduceResponseState = (state, event) => {
500
529
  return reduceToolCall(next, event);
501
530
  case "tool-result":
502
531
  return appendContent(next, toolResultContent(event));
532
+ case "media":
533
+ return appendContent(next, event.providerMetadata === undefined
534
+ ? { type: "media", media: event.media }
535
+ : { type: "media", media: event.media, providerMetadata: event.providerMetadata });
503
536
  default:
504
537
  return next;
505
538
  }
@@ -1,10 +1,9 @@
1
1
  import { Schema } from "effect";
2
2
  import { Tool } from "@opencode/schema/tool";
3
3
  import { CacheHint, GenerationOptions, HttpOptions, type LanguageModel, ReasoningEffort } from "./options.js";
4
+ import { Media } from "../media.js";
4
5
  export declare const MessageRole: Schema.Literals<readonly ["system", "user", "assistant", "tool"]>;
5
6
  export type MessageRole = Schema.Schema.Type<typeof MessageRole>;
6
- export declare const ProviderMetadata: Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>;
7
- export type ProviderMetadata = Schema.Schema.Type<typeof ProviderMetadata>;
8
7
  declare const systemPartSchema: Schema.Struct<{
9
8
  readonly type: Schema.Literal<"text">;
10
9
  readonly text: Schema.String;
@@ -31,8 +30,37 @@ export declare const TextPart: Schema.Struct<{
31
30
  export type TextPart = Schema.Schema.Type<typeof TextPart>;
32
31
  export declare const MediaPart: Schema.Struct<{
33
32
  readonly type: Schema.Literal<"media">;
34
- readonly mediaType: Schema.String;
35
- readonly data: Schema.Union<readonly [Schema.String, Schema.Uint8Array]>;
33
+ readonly media: Schema.decodeTo<Schema.declare<Media.Asset, Media.Asset>, Schema.Struct<{
34
+ readonly source: Schema.Union<readonly [Schema.Struct<{
35
+ readonly type: Schema.Literal<"bytes">;
36
+ readonly data: Schema.Uint8Array;
37
+ readonly mediaType: Schema.String;
38
+ }>, Schema.Struct<{
39
+ readonly type: Schema.Literal<"base64">;
40
+ readonly data: Schema.String;
41
+ readonly mediaType: Schema.String;
42
+ }>, Schema.Struct<{
43
+ readonly type: Schema.Literal<"url">;
44
+ readonly url: Schema.String;
45
+ readonly mediaType: Schema.optional<Schema.String>;
46
+ readonly expiresAt: Schema.optional<Schema.Number>;
47
+ }>, Schema.Struct<{
48
+ readonly type: Schema.Literal<"ref">;
49
+ readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
50
+ readonly id: Schema.String;
51
+ readonly mediaType: Schema.optional<Schema.String>;
52
+ }>]>;
53
+ readonly info: Schema.optional<Schema.Struct<{
54
+ readonly width: Schema.optional<Schema.Number>;
55
+ readonly height: Schema.optional<Schema.Number>;
56
+ readonly durationSeconds: Schema.optional<Schema.Number>;
57
+ readonly sampleRate: Schema.optional<Schema.Number>;
58
+ readonly channels: Schema.optional<Schema.Number>;
59
+ readonly encoding: Schema.optional<Schema.String>;
60
+ readonly format: Schema.optional<Schema.String>;
61
+ }>>;
62
+ readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
63
+ }>, never, never>;
36
64
  readonly filename: Schema.optional<Schema.String>;
37
65
  readonly cache: Schema.optional<typeof CacheHint>;
38
66
  readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
@@ -262,8 +290,37 @@ export declare const ContentPart: Schema.toTaggedUnion<"type", readonly [Schema.
262
290
  readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
263
291
  }>, Schema.Struct<{
264
292
  readonly type: Schema.Literal<"media">;
265
- readonly mediaType: Schema.String;
266
- readonly data: Schema.Union<readonly [Schema.String, Schema.Uint8Array]>;
293
+ readonly media: Schema.decodeTo<Schema.declare<Media.Asset, Media.Asset>, Schema.Struct<{
294
+ readonly source: Schema.Union<readonly [Schema.Struct<{
295
+ readonly type: Schema.Literal<"bytes">;
296
+ readonly data: Schema.Uint8Array;
297
+ readonly mediaType: Schema.String;
298
+ }>, Schema.Struct<{
299
+ readonly type: Schema.Literal<"base64">;
300
+ readonly data: Schema.String;
301
+ readonly mediaType: Schema.String;
302
+ }>, Schema.Struct<{
303
+ readonly type: Schema.Literal<"url">;
304
+ readonly url: Schema.String;
305
+ readonly mediaType: Schema.optional<Schema.String>;
306
+ readonly expiresAt: Schema.optional<Schema.Number>;
307
+ }>, Schema.Struct<{
308
+ readonly type: Schema.Literal<"ref">;
309
+ readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
310
+ readonly id: Schema.String;
311
+ readonly mediaType: Schema.optional<Schema.String>;
312
+ }>]>;
313
+ readonly info: Schema.optional<Schema.Struct<{
314
+ readonly width: Schema.optional<Schema.Number>;
315
+ readonly height: Schema.optional<Schema.Number>;
316
+ readonly durationSeconds: Schema.optional<Schema.Number>;
317
+ readonly sampleRate: Schema.optional<Schema.Number>;
318
+ readonly channels: Schema.optional<Schema.Number>;
319
+ readonly encoding: Schema.optional<Schema.String>;
320
+ readonly format: Schema.optional<Schema.String>;
321
+ }>>;
322
+ readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
323
+ }>, never, never>;
267
324
  readonly filename: Schema.optional<Schema.String>;
268
325
  readonly cache: Schema.optional<typeof CacheHint>;
269
326
  readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
@@ -377,8 +434,37 @@ declare const Message_base: Schema.Class<Message, Schema.Struct<{
377
434
  readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
378
435
  }>, Schema.Struct<{
379
436
  readonly type: Schema.Literal<"media">;
380
- readonly mediaType: Schema.String;
381
- readonly data: Schema.Union<readonly [Schema.String, Schema.Uint8Array]>;
437
+ readonly media: Schema.decodeTo<Schema.declare<Media.Asset, Media.Asset>, Schema.Struct<{
438
+ readonly source: Schema.Union<readonly [Schema.Struct<{
439
+ readonly type: Schema.Literal<"bytes">;
440
+ readonly data: Schema.Uint8Array;
441
+ readonly mediaType: Schema.String;
442
+ }>, Schema.Struct<{
443
+ readonly type: Schema.Literal<"base64">;
444
+ readonly data: Schema.String;
445
+ readonly mediaType: Schema.String;
446
+ }>, Schema.Struct<{
447
+ readonly type: Schema.Literal<"url">;
448
+ readonly url: Schema.String;
449
+ readonly mediaType: Schema.optional<Schema.String>;
450
+ readonly expiresAt: Schema.optional<Schema.Number>;
451
+ }>, Schema.Struct<{
452
+ readonly type: Schema.Literal<"ref">;
453
+ readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
454
+ readonly id: Schema.String;
455
+ readonly mediaType: Schema.optional<Schema.String>;
456
+ }>]>;
457
+ readonly info: Schema.optional<Schema.Struct<{
458
+ readonly width: Schema.optional<Schema.Number>;
459
+ readonly height: Schema.optional<Schema.Number>;
460
+ readonly durationSeconds: Schema.optional<Schema.Number>;
461
+ readonly sampleRate: Schema.optional<Schema.Number>;
462
+ readonly channels: Schema.optional<Schema.Number>;
463
+ readonly encoding: Schema.optional<Schema.String>;
464
+ readonly format: Schema.optional<Schema.String>;
465
+ }>>;
466
+ readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
467
+ }>, never, never>;
382
468
  readonly filename: Schema.optional<Schema.String>;
383
469
  readonly cache: Schema.optional<typeof CacheHint>;
384
470
  readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
@@ -493,6 +579,7 @@ export declare namespace Message {
493
579
  readonly content: ContentInput;
494
580
  };
495
581
  const text: (value: string) => ContentPart;
582
+ const media: (asset: Media.Asset, options?: Omit<MediaPart, "type" | "media">) => MediaPart;
496
583
  const content: (input: ContentInput) => any[];
497
584
  const make: (input: Message | Input) => Message;
498
585
  const user: (content: ContentInput) => Message;
@@ -1,11 +1,9 @@
1
1
  import { Schema } from "effect";
2
2
  import { Tool } from "@opencode/schema/tool";
3
- import { CacheHint, CachePolicy, GenerationOptions, HttpOptions, JsonSchema, LanguageModelSchema, ProviderOptions, ReasoningEffort, } from "./options.js";
3
+ import { CacheHint, CachePolicy, GenerationOptions, HttpOptions, JsonSchema, LanguageModelSchema, ProviderMetadata, ProviderOptions, ReasoningEffort, } from "./options.js";
4
4
  import { ProviderID } from "./ids.js";
5
+ import { Media } from "../media.js";
5
6
  export const MessageRole = Schema.Literals(["system", "user", "assistant", "tool"]);
6
- export const ProviderMetadata = Schema.Record(Schema.String, Schema.Record(Schema.String, Schema.Unknown)).annotate({
7
- identifier: "LLM.ProviderMetadata",
8
- });
9
7
  const systemPartSchema = Schema.Struct({
10
8
  type: Schema.Literal("text"),
11
9
  text: Schema.String,
@@ -30,8 +28,7 @@ export const TextPart = Schema.Struct({
30
28
  }).annotate({ identifier: "LLM.Content.Text" });
31
29
  export const MediaPart = Schema.Struct({
32
30
  type: Schema.Literal("media"),
33
- mediaType: Schema.String,
34
- data: Schema.Union([Schema.String, Schema.Uint8Array]),
31
+ media: Media.AssetSchema,
35
32
  filename: Schema.optional(Schema.String),
36
33
  cache: Schema.optional(CacheHint),
37
34
  metadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
@@ -184,6 +181,11 @@ export class Message extends Schema.Class("LLM.Message")({
184
181
  }
185
182
  (function (Message) {
186
183
  Message.text = (value) => ({ type: "text", text: value });
184
+ Message.media = (asset, options) => ({
185
+ type: "media",
186
+ media: asset,
187
+ ...options,
188
+ });
187
189
  Message.content = (input) => typeof input === "string" ? [Message.text(input)] : Array.isArray(input) ? [...input] : [input];
188
190
  Message.make = (input) => {
189
191
  if (input instanceof Message)
@@ -6,6 +6,8 @@ export type JsonSchema = Schema.Schema.Type<typeof JsonSchema>;
6
6
  export declare const mergeJsonRecords: (...items: ReadonlyArray<Record<string, unknown> | undefined>) => Record<string, unknown> | undefined;
7
7
  export declare const ProviderOptions: Schema.$Record<Schema.String, Schema.Unknown>;
8
8
  export type ProviderOptions = Schema.Schema.Type<typeof ProviderOptions>;
9
+ export declare const ProviderMetadata: Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>;
10
+ export type ProviderMetadata = Schema.Schema.Type<typeof ProviderMetadata>;
9
11
  export declare const mergeProviderOptions: (...items: ReadonlyArray<ProviderOptions | undefined>) => ProviderOptions | undefined;
10
12
  declare const HttpOptions_base: Schema.Class<HttpOptions, Schema.Struct<{
11
13
  readonly body: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
@@ -68,12 +70,13 @@ export declare namespace LanguageModelDefaults {
68
70
  export declare const ReasoningEfforts: readonly ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
69
71
  export type ReasoningEffort = (typeof ReasoningEfforts)[number] | (string & {});
70
72
  export declare const ReasoningEffort: Schema.declare<ReasoningEffort, ReasoningEffort>;
71
- export declare const LanguageModelToolSchemaCompatibility: Schema.Literals<readonly ["gemini", "moonshot"]>;
72
- export type LanguageModelToolSchemaCompatibility = Schema.Schema.Type<typeof LanguageModelToolSchemaCompatibility>;
73
+ /** Tool schema sanitizer for a model family. `none` opts out of the protocol and model-name defaults. */
74
+ export declare const LanguageModelSanitizerCompatibility: Schema.Literals<readonly ["gemini", "moonshot", "none"]>;
75
+ export type LanguageModelSanitizerCompatibility = Schema.Schema.Type<typeof LanguageModelSanitizerCompatibility>;
73
76
  export declare const LanguageModelMaxTokensFieldCompatibility: Schema.Literals<readonly ["max_completion_tokens", "max_tokens"]>;
74
77
  export type LanguageModelMaxTokensFieldCompatibility = Schema.Schema.Type<typeof LanguageModelMaxTokensFieldCompatibility>;
75
78
  declare const LanguageModelCompatibility_base: Schema.Class<LanguageModelCompatibility, Schema.Struct<{
76
- readonly toolSchema: Schema.optional<Schema.Literals<readonly ["gemini", "moonshot"]>>;
79
+ readonly sanitizer: Schema.optional<Schema.Literals<readonly ["gemini", "moonshot", "none"]>>;
77
80
  readonly reasoningField: Schema.optional<Schema.String>;
78
81
  /** Require every assistant message to include its reasoning field, even when empty. */
79
82
  readonly requireReasoning: Schema.optional<Schema.Boolean>;
@@ -28,6 +28,9 @@ const mergeStringRecords = (...items) => {
28
28
  return Object.keys(result).length === 0 ? undefined : result;
29
29
  };
30
30
  export const ProviderOptions = Schema.Record(Schema.String, Schema.Unknown);
31
+ export const ProviderMetadata = Schema.Record(Schema.String, Schema.Record(Schema.String, Schema.Unknown)).annotate({
32
+ identifier: "LLM.ProviderMetadata",
33
+ });
31
34
  export const mergeProviderOptions = (...items) => mergeJsonRecords(...items);
32
35
  export class HttpOptions extends Schema.Class("AI.HttpOptions")({
33
36
  body: Schema.optional(JsonSchema),
@@ -96,10 +99,11 @@ export class LanguageModelDefaults extends Schema.Class("LLM.LanguageModelDefaul
96
99
  })(LanguageModelDefaults || (LanguageModelDefaults = {}));
97
100
  export const ReasoningEfforts = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
98
101
  export const ReasoningEffort = Schema.declare((value) => typeof value === "string", { title: "ReasoningEffort" });
99
- export const LanguageModelToolSchemaCompatibility = Schema.Literals(["gemini", "moonshot"]);
102
+ /** Tool schema sanitizer for a model family. `none` opts out of the protocol and model-name defaults. */
103
+ export const LanguageModelSanitizerCompatibility = Schema.Literals(["gemini", "moonshot", "none"]);
100
104
  export const LanguageModelMaxTokensFieldCompatibility = Schema.Literals(["max_completion_tokens", "max_tokens"]);
101
105
  export class LanguageModelCompatibility extends Schema.Class("LLM.LanguageModelCompatibility")({
102
- toolSchema: Schema.optional(LanguageModelToolSchemaCompatibility),
106
+ sanitizer: Schema.optional(LanguageModelSanitizerCompatibility),
103
107
  reasoningField: Schema.optional(Schema.String),
104
108
  /** Require every assistant message to include its reasoning field, even when empty. */
105
109
  requireReasoning: Schema.optional(Schema.Boolean),
@@ -0,0 +1,21 @@
1
+ import { Context, Effect, Layer, Stream } from "effect";
2
+ import { RequestExecutor } from "./route/executor.js";
3
+ import type { AIError } from "./schema/index.js";
4
+ import type { SpeechEvent, SpeechOptions, SpeechRequestFor, SpeechResponse } from "./speech.js";
5
+ export interface Interface {
6
+ readonly generate: <Options extends SpeechOptions>(request: SpeechRequestFor<Options>) => Effect.Effect<SpeechResponse, AIError>;
7
+ readonly stream: <Options extends SpeechOptions>(request: SpeechRequestFor<Options>) => Stream.Stream<SpeechEvent, AIError>;
8
+ }
9
+ declare const Service_base: Context.ServiceClass<Service, "@opencode/SpeechClient", Interface>;
10
+ export declare class Service extends Service_base {
11
+ }
12
+ export declare const generate: <Options extends SpeechOptions>(request: SpeechRequestFor<Options>) => Effect.Effect<SpeechResponse, AIError, Service>;
13
+ export declare const stream: <Options extends SpeechOptions>(request: SpeechRequestFor<Options>) => Stream.Stream<SpeechEvent, AIError, Service>;
14
+ export declare const layer: Layer.Layer<Service, never, RequestExecutor.Service>;
15
+ export declare const SpeechClient: {
16
+ readonly Service: typeof Service;
17
+ readonly layer: Layer.Layer<Service, never, RequestExecutor.Service>;
18
+ readonly generate: <Options extends SpeechOptions>(request: SpeechRequestFor<Options>) => Effect.Effect<SpeechResponse, AIError, Service>;
19
+ readonly stream: <Options extends SpeechOptions>(request: SpeechRequestFor<Options>) => Stream.Stream<SpeechEvent, AIError, Service>;
20
+ };
21
+ export {};
@@ -0,0 +1,25 @@
1
+ import { Context, Effect, Layer, Stream } from "effect";
2
+ import { RequestExecutor } from "./route/executor.js";
3
+ export class Service extends Context.Service()("@opencode/SpeechClient") {
4
+ }
5
+ export const generate = (request) => Effect.gen(function* () {
6
+ const client = yield* Service;
7
+ return yield* client.generate(request);
8
+ });
9
+ export const stream = (request) => Stream.unwrap(Effect.gen(function* () {
10
+ const client = yield* Service;
11
+ return client.stream(request);
12
+ }));
13
+ export const layer = Layer.effect(Service, Effect.gen(function* () {
14
+ const executor = yield* RequestExecutor.Service;
15
+ return Service.of({
16
+ generate: (request) => request.model.route.generate(request, executor.execute),
17
+ stream: (request) => request.model.route.stream(request, executor.execute),
18
+ });
19
+ }));
20
+ export const SpeechClient = {
21
+ Service,
22
+ layer,
23
+ generate,
24
+ stream,
25
+ };