@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
@@ -291,8 +291,8 @@ export declare const protocol: Protocol<{
291
291
  } | {
292
292
  readonly type: "input_file";
293
293
  readonly filename: string;
294
- readonly detail?: string | undefined;
295
294
  readonly file_data?: string | undefined;
295
+ readonly detail?: string | undefined;
296
296
  readonly file_url?: string | undefined;
297
297
  } | {
298
298
  readonly type: "input_text";
@@ -328,8 +328,8 @@ export declare const protocol: Protocol<{
328
328
  } | {
329
329
  readonly type: "input_file";
330
330
  readonly filename: string;
331
- readonly detail?: string | undefined;
332
331
  readonly file_data?: string | undefined;
332
+ readonly detail?: string | undefined;
333
333
  readonly file_url?: string | undefined;
334
334
  } | {
335
335
  readonly type: "input_text";
@@ -390,11 +390,11 @@ export declare const protocol: Protocol<{
390
390
  readonly size?: string | undefined;
391
391
  readonly action?: "generate" | "auto" | "edit" | undefined;
392
392
  readonly output_format?: "png" | "jpeg" | "webp" | undefined;
393
+ readonly partial_images?: number | undefined;
393
394
  readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
394
395
  readonly background?: "auto" | "opaque" | "transparent" | undefined;
395
396
  readonly output_compression?: number | undefined;
396
397
  readonly input_fidelity?: "low" | "high" | undefined;
397
- readonly partial_images?: number | undefined;
398
398
  } | {
399
399
  readonly type: "namespace";
400
400
  readonly name: string;
@@ -574,8 +574,8 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
574
574
  } | {
575
575
  readonly type: "input_file";
576
576
  readonly filename: string;
577
- readonly detail?: string | undefined;
578
577
  readonly file_data?: string | undefined;
578
+ readonly detail?: string | undefined;
579
579
  readonly file_url?: string | undefined;
580
580
  } | {
581
581
  readonly type: "input_text";
@@ -611,8 +611,8 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
611
611
  } | {
612
612
  readonly type: "input_file";
613
613
  readonly filename: string;
614
- readonly detail?: string | undefined;
615
614
  readonly file_data?: string | undefined;
615
+ readonly detail?: string | undefined;
616
616
  readonly file_url?: string | undefined;
617
617
  } | {
618
618
  readonly type: "input_text";
@@ -673,11 +673,11 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
673
673
  readonly size?: string | undefined;
674
674
  readonly action?: "generate" | "auto" | "edit" | undefined;
675
675
  readonly output_format?: "png" | "jpeg" | "webp" | undefined;
676
+ readonly partial_images?: number | undefined;
676
677
  readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
677
678
  readonly background?: "auto" | "opaque" | "transparent" | undefined;
678
679
  readonly output_compression?: number | undefined;
679
680
  readonly input_fidelity?: "low" | "high" | undefined;
680
- readonly partial_images?: number | undefined;
681
681
  } | {
682
682
  readonly type: "namespace";
683
683
  readonly name: string;
@@ -802,8 +802,8 @@ export declare const channelTransport: (options: import("./open-responses-channe
802
802
  } | {
803
803
  readonly type: "input_file";
804
804
  readonly filename: string;
805
- readonly detail?: string | undefined;
806
805
  readonly file_data?: string | undefined;
806
+ readonly detail?: string | undefined;
807
807
  readonly file_url?: string | undefined;
808
808
  } | {
809
809
  readonly type: "input_text";
@@ -839,8 +839,8 @@ export declare const channelTransport: (options: import("./open-responses-channe
839
839
  } | {
840
840
  readonly type: "input_file";
841
841
  readonly filename: string;
842
- readonly detail?: string | undefined;
843
842
  readonly file_data?: string | undefined;
843
+ readonly detail?: string | undefined;
844
844
  readonly file_url?: string | undefined;
845
845
  } | {
846
846
  readonly type: "input_text";
@@ -901,11 +901,11 @@ export declare const channelTransport: (options: import("./open-responses-channe
901
901
  readonly size?: string | undefined;
902
902
  readonly action?: "generate" | "auto" | "edit" | undefined;
903
903
  readonly output_format?: "png" | "jpeg" | "webp" | undefined;
904
+ readonly partial_images?: number | undefined;
904
905
  readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
905
906
  readonly background?: "auto" | "opaque" | "transparent" | undefined;
906
907
  readonly output_compression?: number | undefined;
907
908
  readonly input_fidelity?: "low" | "high" | undefined;
908
- readonly partial_images?: number | undefined;
909
909
  } | {
910
910
  readonly type: "namespace";
911
911
  readonly name: string;
@@ -1030,8 +1030,8 @@ export declare const transport: import("../route/transport/index.js").Transport<
1030
1030
  } | {
1031
1031
  readonly type: "input_file";
1032
1032
  readonly filename: string;
1033
- readonly detail?: string | undefined;
1034
1033
  readonly file_data?: string | undefined;
1034
+ readonly detail?: string | undefined;
1035
1035
  readonly file_url?: string | undefined;
1036
1036
  } | {
1037
1037
  readonly type: "input_text";
@@ -1067,8 +1067,8 @@ export declare const transport: import("../route/transport/index.js").Transport<
1067
1067
  } | {
1068
1068
  readonly type: "input_file";
1069
1069
  readonly filename: string;
1070
- readonly detail?: string | undefined;
1071
1070
  readonly file_data?: string | undefined;
1071
+ readonly detail?: string | undefined;
1072
1072
  readonly file_url?: string | undefined;
1073
1073
  } | {
1074
1074
  readonly type: "input_text";
@@ -1129,11 +1129,11 @@ export declare const transport: import("../route/transport/index.js").Transport<
1129
1129
  readonly size?: string | undefined;
1130
1130
  readonly action?: "generate" | "auto" | "edit" | undefined;
1131
1131
  readonly output_format?: "png" | "jpeg" | "webp" | undefined;
1132
+ readonly partial_images?: number | undefined;
1132
1133
  readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
1133
1134
  readonly background?: "auto" | "opaque" | "transparent" | undefined;
1134
1135
  readonly output_compression?: number | undefined;
1135
1136
  readonly input_fidelity?: "low" | "high" | undefined;
1136
- readonly partial_images?: number | undefined;
1137
1137
  } | {
1138
1138
  readonly type: "namespace";
1139
1139
  readonly name: string;
@@ -1258,8 +1258,8 @@ export declare const route: Route<{
1258
1258
  } | {
1259
1259
  readonly type: "input_file";
1260
1260
  readonly filename: string;
1261
- readonly detail?: string | undefined;
1262
1261
  readonly file_data?: string | undefined;
1262
+ readonly detail?: string | undefined;
1263
1263
  readonly file_url?: string | undefined;
1264
1264
  } | {
1265
1265
  readonly type: "input_text";
@@ -1295,8 +1295,8 @@ export declare const route: Route<{
1295
1295
  } | {
1296
1296
  readonly type: "input_file";
1297
1297
  readonly filename: string;
1298
- readonly detail?: string | undefined;
1299
1298
  readonly file_data?: string | undefined;
1299
+ readonly detail?: string | undefined;
1300
1300
  readonly file_url?: string | undefined;
1301
1301
  } | {
1302
1302
  readonly type: "input_text";
@@ -1357,11 +1357,11 @@ export declare const route: Route<{
1357
1357
  readonly size?: string | undefined;
1358
1358
  readonly action?: "generate" | "auto" | "edit" | undefined;
1359
1359
  readonly output_format?: "png" | "jpeg" | "webp" | undefined;
1360
+ readonly partial_images?: number | undefined;
1360
1361
  readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
1361
1362
  readonly background?: "auto" | "opaque" | "transparent" | undefined;
1362
1363
  readonly output_compression?: number | undefined;
1363
1364
  readonly input_fidelity?: "low" | "high" | undefined;
1364
- readonly partial_images?: number | undefined;
1365
1365
  } | {
1366
1366
  readonly type: "namespace";
1367
1367
  readonly name: string;
@@ -5,7 +5,7 @@ import { Auth } from "../route/auth.js";
5
5
  import { Endpoint } from "../route/endpoint.js";
6
6
  import { Protocol } from "../route/protocol.js";
7
7
  import { HttpTransport } from "../route/transport/index.js";
8
- import { LLMRequest, mergeJsonRecords } from "../schema/index.js";
8
+ import { LLMRequest, mergeJsonRecords, } from "../schema/index.js";
9
9
  import { resolveEffortUpdates } from "../effort-updates.js";
10
10
  import { OpenResponses } from "./open-responses.js";
11
11
  import { OpenResponsesOptions } from "./utils/open-responses-options.js";
@@ -137,16 +137,16 @@ const lowerTool = Effect.fn("OpenAIResponses.lowerTool")(function* (tool, inputS
137
137
  });
138
138
  // Native namespaces hold only function tools, so deeper levels flatten into
139
139
  // the leaf names the same way non-native protocols flatten the whole tree.
140
- const lowerToolEntry = Effect.fn("OpenAIResponses.lowerToolEntry")(function* (tool, compatibility) {
140
+ const lowerToolEntry = Effect.fn("OpenAIResponses.lowerToolEntry")(function* (tool, model) {
141
141
  if (tool.type === "tool")
142
- return yield* lowerTool(tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, compatibility));
142
+ return yield* lowerTool(tool, ToolSchemaProjection.modelCompatibility(tool.inputSchema, model));
143
143
  // OpenAI requires a namespace description; fall back to a generic one so a
144
144
  // missing description never blocks the request.
145
145
  return {
146
146
  type: "namespace",
147
147
  name: tool.name,
148
148
  description: tool.description ?? `Tools in the ${tool.name} namespace.`,
149
- tools: yield* Effect.forEach(ProviderShared.flattenTools(tool.tools), (leaf) => OpenResponses.lowerTool(NAME, leaf, ToolSchemaProjection.modelCompatibility(leaf.inputSchema, compatibility))),
149
+ tools: yield* Effect.forEach(ProviderShared.flattenTools(tool.tools), (leaf) => OpenResponses.lowerTool(NAME, leaf, ToolSchemaProjection.modelCompatibility(leaf.inputSchema, model))),
150
150
  };
151
151
  });
152
152
  const lowerToolChoice = (toolChoice, tools) => ProviderShared.matchToolChoice(NAME, toolChoice, {
@@ -162,14 +162,13 @@ const fromRequest = Effect.fn("OpenAIResponses.fromRequest")(function* (request)
162
162
  const management = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Schema.UndefinedOr(ContextManagement)))(request.providerOptions?.contextManagement);
163
163
  const options = OpenResponsesOptions.resolve(request);
164
164
  const updates = resolveEffortUpdates(request, options.reasoningEffort);
165
- const toolSchemaCompatibility = request.model.compatibility?.toolSchema;
166
165
  return yield* decodeBody({
167
166
  ...(yield* OpenResponses.lowerConversation(updates.request, adapter)),
168
167
  ...OpenResponses.lowerGeneration(request, { ...options, reasoningEffort: updates.effort }),
169
168
  context_management: management?.map((edit) => ({ type: edit.type, compact_threshold: edit.compactThreshold })),
170
169
  tools: request.tools.length === 0
171
170
  ? undefined
172
- : yield* Effect.forEach(request.tools, (tool) => lowerToolEntry(tool, toolSchemaCompatibility)),
171
+ : yield* Effect.forEach(request.tools, (tool) => lowerToolEntry(tool, request.model)),
173
172
  tool_choice: request.tools.length === 0
174
173
  ? undefined
175
174
  : (OpenResponses.allowedToolChoice(request) ??
@@ -0,0 +1,116 @@
1
+ import { MediaProtocol } from "../route/media-protocol.js";
2
+ import { MediaRoute } from "../route/media.js";
3
+ import { type MediaUsage } from "../schema/index.js";
4
+ import { SpeechModel, type SpeechRequestFor } from "../speech.js";
5
+ import { SpeechStream } from "./utils/speech-stream.js";
6
+ export declare const DEFAULT_BASE_URL = "https://api.openai.com/v1";
7
+ export declare const PATH = "/audio/speech";
8
+ export type OpenAISpeechOptions = Record<string, unknown>;
9
+ export type Request = SpeechRequestFor<OpenAISpeechOptions>;
10
+ interface State extends SpeechStream.Audio {
11
+ readonly done: boolean;
12
+ readonly usage?: MediaUsage;
13
+ }
14
+ export declare const protocol: MediaProtocol.Streamed<Request, {
15
+ readonly type: "audio-delta";
16
+ readonly chunk: Uint8Array<ArrayBufferLike>;
17
+ } | {
18
+ readonly type: "timestamps";
19
+ readonly items: readonly {
20
+ readonly text: string;
21
+ readonly startSeconds: number;
22
+ readonly endSeconds: number;
23
+ }[];
24
+ } | {
25
+ readonly type: "finish";
26
+ readonly audio: import("../media.js").Asset;
27
+ readonly providerMetadata?: {
28
+ readonly [x: string]: {
29
+ readonly [x: string]: unknown;
30
+ };
31
+ } | undefined;
32
+ readonly usage?: {
33
+ readonly type: "tokens";
34
+ readonly input?: number | undefined;
35
+ readonly output?: number | undefined;
36
+ readonly total?: number | undefined;
37
+ readonly details?: {
38
+ readonly [x: string]: unknown;
39
+ } | undefined;
40
+ } | {
41
+ readonly type: "seconds";
42
+ readonly seconds: number;
43
+ } | {
44
+ readonly type: "characters";
45
+ readonly characters: number;
46
+ } | {
47
+ readonly type: "credits";
48
+ readonly credits: number;
49
+ } | {
50
+ readonly type: "compute";
51
+ readonly seconds: number;
52
+ } | undefined;
53
+ readonly notices?: readonly {
54
+ readonly type: "other" | "moderated" | "filtered";
55
+ readonly message: string;
56
+ readonly providerMetadata?: {
57
+ readonly [x: string]: {
58
+ readonly [x: string]: unknown;
59
+ };
60
+ } | undefined;
61
+ }[] | undefined;
62
+ }, string | Uint8Array<ArrayBufferLike>, State>;
63
+ export declare const model: (input: MediaRoute.ModelInput) => SpeechModel<OpenAISpeechOptions>;
64
+ export declare const OpenAISpeech: {
65
+ readonly protocol: MediaProtocol.Streamed<Request, {
66
+ readonly type: "audio-delta";
67
+ readonly chunk: Uint8Array<ArrayBufferLike>;
68
+ } | {
69
+ readonly type: "timestamps";
70
+ readonly items: readonly {
71
+ readonly text: string;
72
+ readonly startSeconds: number;
73
+ readonly endSeconds: number;
74
+ }[];
75
+ } | {
76
+ readonly type: "finish";
77
+ readonly audio: import("../media.js").Asset;
78
+ readonly providerMetadata?: {
79
+ readonly [x: string]: {
80
+ readonly [x: string]: unknown;
81
+ };
82
+ } | undefined;
83
+ readonly usage?: {
84
+ readonly type: "tokens";
85
+ readonly input?: number | undefined;
86
+ readonly output?: number | undefined;
87
+ readonly total?: number | undefined;
88
+ readonly details?: {
89
+ readonly [x: string]: unknown;
90
+ } | undefined;
91
+ } | {
92
+ readonly type: "seconds";
93
+ readonly seconds: number;
94
+ } | {
95
+ readonly type: "characters";
96
+ readonly characters: number;
97
+ } | {
98
+ readonly type: "credits";
99
+ readonly credits: number;
100
+ } | {
101
+ readonly type: "compute";
102
+ readonly seconds: number;
103
+ } | undefined;
104
+ readonly notices?: readonly {
105
+ readonly type: "other" | "moderated" | "filtered";
106
+ readonly message: string;
107
+ readonly providerMetadata?: {
108
+ readonly [x: string]: {
109
+ readonly [x: string]: unknown;
110
+ };
111
+ } | undefined;
112
+ }[] | undefined;
113
+ }, string | Uint8Array<ArrayBufferLike>, State>;
114
+ readonly model: (input: MediaRoute.ModelInput) => SpeechModel<OpenAISpeechOptions>;
115
+ };
116
+ export {};
@@ -0,0 +1,98 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { Framing } from "../route/framing.js";
3
+ import { MediaProtocol } from "../route/media-protocol.js";
4
+ import { MediaRoute } from "../route/media.js";
5
+ import { ProviderID, mergeJsonRecords } from "../schema/index.js";
6
+ import { SpeechModel } from "../speech.js";
7
+ import { SpeechStream } from "./utils/speech-stream.js";
8
+ const ADAPTER = "openai-speech";
9
+ const NAME = "OpenAI Speech";
10
+ const PROVIDER = ProviderID.make("openai");
11
+ export const DEFAULT_BASE_URL = "https://api.openai.com/v1";
12
+ export const PATH = "/audio/speech";
13
+ /** `pcm` is raw 24 kHz, 16-bit signed little-endian mono samples without a header. */
14
+ const PCM_SAMPLE_RATE = 24000;
15
+ // ---------------------------------------------------------------------------
16
+ // 3. Streaming event schema
17
+ // ---------------------------------------------------------------------------
18
+ const SpeechStreamEvent = Schema.Union([
19
+ Schema.Struct({ type: Schema.Literal("speech.audio.delta"), audio: Schema.Uint8ArrayFromBase64 }),
20
+ Schema.Struct({
21
+ type: Schema.Literal("speech.audio.done"),
22
+ usage: Schema.optional(Schema.Struct({
23
+ input_tokens: Schema.optional(Schema.Number),
24
+ output_tokens: Schema.optional(Schema.Number),
25
+ total_tokens: Schema.optional(Schema.Number),
26
+ })),
27
+ }),
28
+ ]);
29
+ const decodeEvent = MediaProtocol.decodeFrame(ADAPTER, NAME, SpeechStreamEvent);
30
+ // ---------------------------------------------------------------------------
31
+ // 5. Request body construction
32
+ // ---------------------------------------------------------------------------
33
+ // `sse` is not supported for `tts-1` or `tts-1-hd`; those models stream the raw audio body instead.
34
+ const supportsSse = (model) => !/^tts-1(-hd)?(-|$)/.test(model);
35
+ const fromRequest = Effect.fn("OpenAISpeech.fromRequest")(function* (request) {
36
+ return MediaProtocol.json(mergeJsonRecords({
37
+ model: request.model.id,
38
+ input: request.text,
39
+ voice: request.voice,
40
+ instructions: request.instructions,
41
+ response_format: request.format,
42
+ speed: request.speed,
43
+ stream_format: request.mode === "stream" && supportsSse(request.model.id) ? "sse" : undefined,
44
+ }, request.providerOptions, request.http?.body) ?? {});
45
+ });
46
+ // ---------------------------------------------------------------------------
47
+ // 6. Stream parsing
48
+ // ---------------------------------------------------------------------------
49
+ const isSse = (body) => body.type === "json" && body.value.stream_format === "sse";
50
+ const onEvent = Effect.fn("OpenAISpeech.onEvent")(function* (state, frame) {
51
+ const event = yield* decodeEvent(frame);
52
+ if (event.type === "speech.audio.delta")
53
+ return SpeechStream.delta(state, event.audio);
54
+ const usage = event.usage;
55
+ return [
56
+ {
57
+ ...state,
58
+ done: true,
59
+ usage: usage === undefined
60
+ ? undefined
61
+ : {
62
+ type: "tokens",
63
+ input: usage.input_tokens,
64
+ output: usage.output_tokens,
65
+ total: usage.total_tokens,
66
+ details: { openai: usage },
67
+ },
68
+ },
69
+ [],
70
+ ];
71
+ });
72
+ const finish = (state, context) => {
73
+ if (isSse(context.body) && !state.done)
74
+ return Effect.fail(MediaProtocol.incomplete(ADAPTER));
75
+ const format = context.request.format ?? "mp3";
76
+ return SpeechStream.finish(ADAPTER, state, {
77
+ ...(format === "pcm" ? SpeechStream.pcm("pcm_s16le", PCM_SAMPLE_RATE) : SpeechStream.container(format)),
78
+ usage: state.usage,
79
+ });
80
+ };
81
+ // ---------------------------------------------------------------------------
82
+ // 7. Protocol and route
83
+ // ---------------------------------------------------------------------------
84
+ export const protocol = MediaProtocol.stream({
85
+ id: ADAPTER,
86
+ name: NAME,
87
+ unsupported: ["language", "timestamps"],
88
+ body: { from: fromRequest },
89
+ frames: (bytes, context) => (isSse(context.body) ? Framing.sse.frame(bytes) : bytes),
90
+ initial: () => ({ chunks: [], done: false }),
91
+ step: SpeechStream.step(onEvent),
92
+ finish,
93
+ });
94
+ export const model = (input) => SpeechModel.fromRoute({ id: ADAPTER, provider: PROVIDER, protocol, baseURL: DEFAULT_BASE_URL, path: PATH }, input);
95
+ export const OpenAISpeech = {
96
+ protocol,
97
+ model,
98
+ };
@@ -0,0 +1,207 @@
1
+ import { Schema } from "effect";
2
+ import { MediaProtocol } from "../route/media-protocol.js";
3
+ import { MediaRoute } from "../route/media.js";
4
+ import { TranscriptionModel, type TranscriptionRequestFor, type TranscriptionSegment } from "../transcription.js";
5
+ export declare const DEFAULT_BASE_URL = "https://api.openai.com/v1";
6
+ export declare const PATH = "/audio/transcriptions";
7
+ export type OpenAITranscriptionOptions = {
8
+ readonly chunking_strategy?: "auto" | {
9
+ readonly type: "server_vad";
10
+ readonly prefix_padding_ms?: number;
11
+ readonly silence_duration_ms?: number;
12
+ readonly threshold?: number;
13
+ };
14
+ readonly include?: ReadonlyArray<"logprobs">;
15
+ readonly keywords?: ReadonlyArray<string>;
16
+ readonly known_speaker_names?: ReadonlyArray<string>;
17
+ readonly known_speaker_references?: ReadonlyArray<string>;
18
+ readonly temperature?: number;
19
+ } & Record<string, unknown>;
20
+ export type Request = TranscriptionRequestFor<OpenAITranscriptionOptions>;
21
+ declare const Transcript: Schema.Struct<{
22
+ text: Schema.String;
23
+ language: Schema.optional<Schema.String>;
24
+ languages: Schema.optional<Schema.$Array<Schema.Struct<{
25
+ readonly code: Schema.String;
26
+ }>>>;
27
+ duration: Schema.optional<Schema.Number>;
28
+ segments: Schema.optional<Schema.$Array<Schema.Struct<{
29
+ readonly text: Schema.String;
30
+ readonly start: Schema.Number;
31
+ readonly end: Schema.Number;
32
+ readonly speaker: Schema.optional<Schema.String>;
33
+ }>>>;
34
+ words: Schema.optional<Schema.$Array<Schema.Struct<{
35
+ readonly word: Schema.String;
36
+ readonly start: Schema.Number;
37
+ readonly end: Schema.Number;
38
+ }>>>;
39
+ usage: Schema.optional<Schema.Union<readonly [Schema.Struct<{
40
+ readonly type: Schema.Literal<"tokens">;
41
+ readonly input_tokens: Schema.optional<Schema.Number>;
42
+ readonly output_tokens: Schema.optional<Schema.Number>;
43
+ readonly total_tokens: Schema.optional<Schema.Number>;
44
+ }>, Schema.Struct<{
45
+ readonly type: Schema.Literal<"duration">;
46
+ readonly seconds: Schema.Number;
47
+ }>]>>;
48
+ }>;
49
+ type Transcript = Schema.Schema.Type<typeof Transcript>;
50
+ type Frame = string | {
51
+ readonly document: string;
52
+ };
53
+ interface State {
54
+ readonly segments: Array<TranscriptionSegment>;
55
+ readonly transcript?: Transcript;
56
+ }
57
+ export declare const protocol: MediaProtocol.Streamed<Request, {
58
+ readonly id: string;
59
+ readonly type: "generation-queued";
60
+ readonly position?: number | undefined;
61
+ } | {
62
+ readonly id: string;
63
+ readonly type: "generation-progress";
64
+ readonly progress?: number | undefined;
65
+ } | {
66
+ readonly type: "text-delta";
67
+ readonly delta: string;
68
+ } | {
69
+ readonly type: "segment";
70
+ readonly segment: {
71
+ readonly text: string;
72
+ readonly startSeconds: number;
73
+ readonly endSeconds: number;
74
+ readonly speaker?: string | undefined;
75
+ };
76
+ } | {
77
+ readonly type: "finish";
78
+ readonly text: string;
79
+ readonly durationSeconds?: number | undefined;
80
+ readonly providerMetadata?: {
81
+ readonly [x: string]: {
82
+ readonly [x: string]: unknown;
83
+ };
84
+ } | undefined;
85
+ readonly usage?: {
86
+ readonly type: "tokens";
87
+ readonly input?: number | undefined;
88
+ readonly output?: number | undefined;
89
+ readonly total?: number | undefined;
90
+ readonly details?: {
91
+ readonly [x: string]: unknown;
92
+ } | undefined;
93
+ } | {
94
+ readonly type: "seconds";
95
+ readonly seconds: number;
96
+ } | {
97
+ readonly type: "characters";
98
+ readonly characters: number;
99
+ } | {
100
+ readonly type: "credits";
101
+ readonly credits: number;
102
+ } | {
103
+ readonly type: "compute";
104
+ readonly seconds: number;
105
+ } | undefined;
106
+ readonly notices?: readonly {
107
+ readonly type: "other" | "moderated" | "filtered";
108
+ readonly message: string;
109
+ readonly providerMetadata?: {
110
+ readonly [x: string]: {
111
+ readonly [x: string]: unknown;
112
+ };
113
+ } | undefined;
114
+ }[] | undefined;
115
+ readonly language?: string | undefined;
116
+ readonly segments?: readonly {
117
+ readonly text: string;
118
+ readonly startSeconds: number;
119
+ readonly endSeconds: number;
120
+ readonly speaker?: string | undefined;
121
+ }[] | undefined;
122
+ readonly words?: readonly {
123
+ readonly text: string;
124
+ readonly startSeconds: number;
125
+ readonly endSeconds: number;
126
+ readonly speaker?: string | undefined;
127
+ readonly confidence?: number | undefined;
128
+ }[] | undefined;
129
+ }, Frame, State>;
130
+ export declare const model: (input: MediaRoute.ModelInput) => TranscriptionModel<OpenAITranscriptionOptions>;
131
+ export declare const OpenAITranscription: {
132
+ readonly protocol: MediaProtocol.Streamed<Request, {
133
+ readonly id: string;
134
+ readonly type: "generation-queued";
135
+ readonly position?: number | undefined;
136
+ } | {
137
+ readonly id: string;
138
+ readonly type: "generation-progress";
139
+ readonly progress?: number | undefined;
140
+ } | {
141
+ readonly type: "text-delta";
142
+ readonly delta: string;
143
+ } | {
144
+ readonly type: "segment";
145
+ readonly segment: {
146
+ readonly text: string;
147
+ readonly startSeconds: number;
148
+ readonly endSeconds: number;
149
+ readonly speaker?: string | undefined;
150
+ };
151
+ } | {
152
+ readonly type: "finish";
153
+ readonly text: string;
154
+ readonly durationSeconds?: number | undefined;
155
+ readonly providerMetadata?: {
156
+ readonly [x: string]: {
157
+ readonly [x: string]: unknown;
158
+ };
159
+ } | undefined;
160
+ readonly usage?: {
161
+ readonly type: "tokens";
162
+ readonly input?: number | undefined;
163
+ readonly output?: number | undefined;
164
+ readonly total?: number | undefined;
165
+ readonly details?: {
166
+ readonly [x: string]: unknown;
167
+ } | undefined;
168
+ } | {
169
+ readonly type: "seconds";
170
+ readonly seconds: number;
171
+ } | {
172
+ readonly type: "characters";
173
+ readonly characters: number;
174
+ } | {
175
+ readonly type: "credits";
176
+ readonly credits: number;
177
+ } | {
178
+ readonly type: "compute";
179
+ readonly seconds: number;
180
+ } | undefined;
181
+ readonly notices?: readonly {
182
+ readonly type: "other" | "moderated" | "filtered";
183
+ readonly message: string;
184
+ readonly providerMetadata?: {
185
+ readonly [x: string]: {
186
+ readonly [x: string]: unknown;
187
+ };
188
+ } | undefined;
189
+ }[] | undefined;
190
+ readonly language?: string | undefined;
191
+ readonly segments?: readonly {
192
+ readonly text: string;
193
+ readonly startSeconds: number;
194
+ readonly endSeconds: number;
195
+ readonly speaker?: string | undefined;
196
+ }[] | undefined;
197
+ readonly words?: readonly {
198
+ readonly text: string;
199
+ readonly startSeconds: number;
200
+ readonly endSeconds: number;
201
+ readonly speaker?: string | undefined;
202
+ readonly confidence?: number | undefined;
203
+ }[] | undefined;
204
+ }, Frame, State>;
205
+ readonly model: (input: MediaRoute.ModelInput) => TranscriptionModel<OpenAITranscriptionOptions>;
206
+ };
207
+ export {};