@opencode/ai 2.0.15 → 2.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +441 -99
- package/dist/ai-client.d.ts +8 -0
- package/dist/ai-client.js +12 -0
- package/dist/experimental/evaluation-client.d.ts +3 -3
- package/dist/experimental/evaluation-client.js +1 -1
- package/dist/experimental/evaluation.js +1 -1
- package/dist/generation.d.ts +39 -29
- package/dist/generation.js +62 -36
- package/dist/image-client.d.ts +59 -17
- package/dist/image-client.js +16 -24
- package/dist/image.d.ts +394 -55
- package/dist/image.js +48 -57
- package/dist/index.d.ts +15 -2
- package/dist/index.js +10 -0
- package/dist/llm.d.ts +7 -5
- package/dist/llm.js +10 -4
- package/dist/media-client.d.ts +30 -0
- package/dist/media-client.js +51 -0
- package/dist/media-model.d.ts +43 -0
- package/dist/media-model.js +47 -0
- package/dist/media.d.ts +10 -9
- package/dist/media.js +11 -12
- package/dist/promise.d.ts +473 -15
- package/dist/promise.js +71 -13
- package/dist/protocols/alibaba-chat.d.ts +12 -0
- package/dist/protocols/alibaba-chat.js +4 -1
- package/dist/protocols/alibaba-messages.d.ts +1 -1
- package/dist/protocols/alibaba-messages.js +6 -4
- package/dist/protocols/alibaba-responses.d.ts +2 -2
- package/dist/protocols/anthropic-messages.d.ts +34 -34
- package/dist/protocols/anthropic-messages.js +14 -9
- package/dist/protocols/assemblyai-transcription.d.ts +41 -0
- package/dist/protocols/assemblyai-transcription.js +136 -0
- package/dist/protocols/bedrock-converse.d.ts +7 -0
- package/dist/protocols/bedrock-converse.js +39 -19
- package/dist/protocols/bfl-images.d.ts +38 -0
- package/dist/protocols/bfl-images.js +153 -0
- package/dist/protocols/cartesia-speech.d.ts +143 -0
- package/dist/protocols/cartesia-speech.js +120 -0
- package/dist/protocols/deepgram-speech.d.ts +135 -0
- package/dist/protocols/deepgram-speech.js +91 -0
- package/dist/protocols/deepgram-transcription.d.ts +26 -0
- package/dist/protocols/deepgram-transcription.js +125 -0
- package/dist/protocols/elevenlabs-speech.d.ts +138 -0
- package/dist/protocols/elevenlabs-speech.js +111 -0
- package/dist/protocols/fal-images.d.ts +25 -0
- package/dist/protocols/fal-images.js +104 -0
- package/dist/protocols/fal-video.d.ts +29 -0
- package/dist/protocols/fal-video.js +73 -0
- package/dist/protocols/gemini.d.ts +22 -22
- package/dist/protocols/gemini.js +19 -36
- package/dist/protocols/google-images.d.ts +3 -3
- package/dist/protocols/google-images.js +12 -34
- package/dist/protocols/google-speech.d.ts +146 -0
- package/dist/protocols/google-speech.js +88 -0
- package/dist/protocols/google-transcription.d.ts +174 -0
- package/dist/protocols/google-transcription.js +126 -0
- package/dist/protocols/google-video.d.ts +26 -0
- package/dist/protocols/google-video.js +142 -0
- package/dist/protocols/meta-images.d.ts +3 -4
- package/dist/protocols/meta-images.js +13 -29
- package/dist/protocols/meta-messages.d.ts +5 -5
- package/dist/protocols/meta-responses.d.ts +4 -4
- package/dist/protocols/meta-responses.js +6 -4
- package/dist/protocols/open-responses.d.ts +10 -9
- package/dist/protocols/open-responses.js +4 -9
- package/dist/protocols/openai-chat.d.ts +84 -0
- package/dist/protocols/openai-chat.js +28 -17
- package/dist/protocols/openai-compatible-chat.d.ts +12 -0
- package/dist/protocols/openai-compatible-responses.d.ts +2 -2
- package/dist/protocols/openai-images.d.ts +130 -7
- package/dist/protocols/openai-images.js +143 -91
- package/dist/protocols/openai-responses.d.ts +20 -20
- package/dist/protocols/openai-responses.js +31 -31
- package/dist/protocols/openai-speech.d.ts +136 -0
- package/dist/protocols/openai-speech.js +97 -0
- package/dist/protocols/openai-transcription.d.ts +211 -0
- package/dist/protocols/openai-transcription.js +202 -0
- package/dist/protocols/replicate-images.d.ts +28 -0
- package/dist/protocols/replicate-images.js +127 -0
- package/dist/protocols/runway-video.d.ts +38 -0
- package/dist/protocols/runway-video.js +140 -0
- package/dist/protocols/shared.d.ts +21 -17
- package/dist/protocols/shared.js +27 -36
- package/dist/protocols/stability-images.d.ts +39 -0
- package/dist/protocols/stability-images.js +136 -0
- package/dist/protocols/utils/fal-queue.d.ts +26 -0
- package/dist/protocols/utils/fal-queue.js +67 -0
- package/dist/protocols/utils/gemini-generate-content.d.ts +65 -0
- package/dist/protocols/utils/gemini-generate-content.js +65 -0
- package/dist/protocols/utils/gemini-json-schema.d.ts +3 -0
- package/dist/protocols/utils/gemini-json-schema.js +76 -0
- package/dist/protocols/utils/media-input.d.ts +23 -1
- package/dist/protocols/utils/media-input.js +40 -0
- package/dist/protocols/utils/responses-checkpoint.js +3 -7
- package/dist/protocols/utils/responses-compaction.d.ts +3 -1
- package/dist/protocols/utils/responses-compaction.js +16 -3
- package/dist/protocols/utils/speech-stream.d.ts +49 -0
- package/dist/protocols/utils/speech-stream.js +64 -0
- package/dist/protocols/utils/tool-schema.d.ts +2 -2
- package/dist/protocols/utils/tool-schema.js +62 -19
- package/dist/protocols/xai-images.d.ts +4 -4
- package/dist/protocols/xai-images.js +14 -40
- package/dist/protocols/xai-responses.d.ts +2 -2
- package/dist/protocols/xai-responses.js +1 -1
- package/dist/protocols/xai-video.d.ts +34 -0
- package/dist/protocols/xai-video.js +141 -0
- package/dist/protocols/zai-chat.d.ts +13 -1
- package/dist/protocols/zai-images.d.ts +2 -2
- package/dist/protocols/zai-images.js +11 -14
- package/dist/protocols/zai-messages.d.ts +1 -1
- package/dist/provider-error.js +10 -1
- package/dist/providers/alibaba.d.ts +15 -3
- package/dist/providers/amazon-bedrock-mantle.d.ts +14 -2
- package/dist/providers/amazon-bedrock.d.ts +2 -0
- package/dist/providers/amazon-bedrock.js +1 -0
- package/dist/providers/anthropic-compatible.d.ts +5 -5
- package/dist/providers/anthropic.d.ts +5 -5
- package/dist/providers/assemblyai.d.ts +25 -0
- package/dist/providers/assemblyai.js +24 -0
- package/dist/providers/azure.d.ts +20 -8
- package/dist/providers/azure.js +2 -2
- package/dist/providers/baseten.d.ts +24 -0
- package/dist/providers/black-forest-labs.d.ts +25 -0
- package/dist/providers/black-forest-labs.js +23 -0
- package/dist/providers/cartesia.d.ts +24 -0
- package/dist/providers/cartesia.js +17 -0
- package/dist/providers/cerebras.d.ts +24 -0
- package/dist/providers/cloudflare-ai-gateway.d.ts +42 -18
- package/dist/providers/cloudflare-workers-ai.d.ts +24 -0
- package/dist/providers/deepgram.d.ts +29 -0
- package/dist/providers/deepgram.js +25 -0
- package/dist/providers/deepinfra.d.ts +24 -0
- package/dist/providers/deepseek.d.ts +24 -0
- package/dist/providers/elevenlabs.d.ts +24 -0
- package/dist/providers/elevenlabs.js +23 -0
- package/dist/providers/fal.d.ts +29 -0
- package/dist/providers/fal.js +26 -0
- package/dist/providers/fireworks.d.ts +24 -0
- package/dist/providers/google-vertex-chat.d.ts +12 -0
- package/dist/providers/google-vertex-messages.d.ts +5 -5
- package/dist/providers/google-vertex-responses.d.ts +2 -2
- package/dist/providers/google-vertex.d.ts +6 -6
- package/dist/providers/google.d.ts +21 -6
- package/dist/providers/google.js +13 -9
- package/dist/providers/groq.d.ts +24 -0
- package/dist/providers/index.d.ts +9 -0
- package/dist/providers/index.js +9 -0
- package/dist/providers/meta.d.ts +22 -10
- package/dist/providers/meta.js +4 -8
- package/dist/providers/minimax.d.ts +19 -7
- package/dist/providers/moonshot.d.ts +19 -7
- package/dist/providers/moonshot.js +3 -3
- package/dist/providers/openai-compatible-responses.d.ts +2 -2
- package/dist/providers/openai-compatible.d.ts +12 -0
- package/dist/providers/openai-options.d.ts +3 -9
- package/dist/providers/openai-options.js +4 -7
- package/dist/providers/openai.d.ts +33 -12
- package/dist/providers/openai.js +17 -9
- package/dist/providers/opencode-zen.js +1 -1
- package/dist/providers/openrouter.d.ts +54 -7
- package/dist/providers/openrouter.js +10 -5
- package/dist/providers/replicate.d.ts +25 -0
- package/dist/providers/replicate.js +17 -0
- package/dist/providers/runway.d.ts +24 -0
- package/dist/providers/runway.js +17 -0
- package/dist/providers/stability.d.ts +28 -0
- package/dist/providers/stability.js +18 -0
- package/dist/providers/togetherai.d.ts +24 -0
- package/dist/providers/typesafe-ai.js +1 -1
- package/dist/providers/vercel-ai-gateway.js +1 -1
- package/dist/providers/xai.d.ts +17 -0
- package/dist/providers/xai.js +7 -9
- package/dist/providers/zai-coding-plan.d.ts +16 -4
- package/dist/providers/zai.d.ts +13 -1
- package/dist/providers/zai.js +4 -8
- package/dist/route/auth.d.ts +5 -2
- package/dist/route/auth.js +20 -13
- package/dist/route/client.d.ts +9 -7
- package/dist/route/client.js +6 -8
- package/dist/route/endpoint.d.ts +1 -0
- package/dist/route/endpoint.js +2 -2
- package/dist/route/executor-service.d.ts +4 -2
- package/dist/route/executor-service.js +2 -1
- package/dist/route/executor.d.ts +3 -1
- package/dist/route/executor.js +7 -0
- package/dist/route/framing.d.ts +15 -2
- package/dist/route/framing.js +53 -4
- package/dist/route/index.d.ts +1 -1
- package/dist/route/media-protocol.d.ts +145 -18
- package/dist/route/media-protocol.js +96 -28
- package/dist/route/media.d.ts +54 -9
- package/dist/route/media.js +194 -38
- package/dist/route/protocol.d.ts +3 -1
- package/dist/schema/events.d.ts +0 -6
- package/dist/schema/messages.d.ts +0 -3
- package/dist/schema/options.d.ts +10 -6
- package/dist/schema/options.js +10 -5
- package/dist/speech-client.d.ts +66 -0
- package/dist/speech-client.js +21 -0
- package/dist/speech.d.ts +1307 -0
- package/dist/speech.js +124 -0
- package/dist/testing.d.ts +2 -2
- package/dist/transcription-client.d.ts +82 -0
- package/dist/transcription-client.js +13 -0
- package/dist/transcription.d.ts +1492 -0
- package/dist/transcription.js +127 -0
- package/dist/utils/bytes.d.ts +1 -0
- package/dist/utils/bytes.js +10 -0
- package/dist/utils/json.d.ts +4 -0
- package/dist/utils/json.js +4 -0
- package/dist/utils/media-type.d.ts +3 -1
- package/dist/utils/media-type.js +25 -2
- package/dist/video-client.d.ts +59 -0
- package/dist/video-client.js +20 -0
- package/dist/video.d.ts +1351 -0
- package/dist/video.js +118 -0
- package/package.json +3 -3
- package/dist/protocols/utils/gemini-tool-schema.d.ts +0 -2
- package/dist/protocols/utils/gemini-tool-schema.js +0 -103
- package/dist/protocols/utils/meta-image.d.ts +0 -2
- package/dist/protocols/utils/meta-image.js +0 -13
- package/dist/protocols/utils/openai-image.d.ts +0 -5
- package/dist/protocols/utils/openai-image.js +0 -18
|
@@ -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";
|
|
@@ -364,8 +364,8 @@ export declare const protocol: Protocol<{
|
|
|
364
364
|
readonly type: "image_generation_call";
|
|
365
365
|
readonly status?: string | undefined;
|
|
366
366
|
readonly result?: string | null | undefined;
|
|
367
|
-
readonly revised_prompt?: string | null | undefined;
|
|
368
367
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
368
|
+
readonly revised_prompt?: string | null | undefined;
|
|
369
369
|
})[];
|
|
370
370
|
readonly model: string;
|
|
371
371
|
readonly stream: true;
|
|
@@ -392,9 +392,9 @@ export declare const protocol: Protocol<{
|
|
|
392
392
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
393
393
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
394
394
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
395
|
+
readonly partial_images?: number | 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";
|
|
@@ -647,8 +647,8 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
647
647
|
readonly type: "image_generation_call";
|
|
648
648
|
readonly status?: string | undefined;
|
|
649
649
|
readonly result?: string | null | undefined;
|
|
650
|
-
readonly revised_prompt?: string | null | undefined;
|
|
651
650
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
651
|
+
readonly revised_prompt?: string | null | undefined;
|
|
652
652
|
})[];
|
|
653
653
|
readonly model: string;
|
|
654
654
|
readonly stream: true;
|
|
@@ -675,9 +675,9 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
675
675
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
676
676
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
677
677
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
678
|
+
readonly partial_images?: number | 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";
|
|
@@ -875,8 +875,8 @@ export declare const channelTransport: (options: import("./open-responses-channe
|
|
|
875
875
|
readonly type: "image_generation_call";
|
|
876
876
|
readonly status?: string | undefined;
|
|
877
877
|
readonly result?: string | null | undefined;
|
|
878
|
-
readonly revised_prompt?: string | null | undefined;
|
|
879
878
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
879
|
+
readonly revised_prompt?: string | null | undefined;
|
|
880
880
|
})[];
|
|
881
881
|
readonly model: string;
|
|
882
882
|
readonly stream: true;
|
|
@@ -903,9 +903,9 @@ export declare const channelTransport: (options: import("./open-responses-channe
|
|
|
903
903
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
904
904
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
905
905
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
906
|
+
readonly partial_images?: number | 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";
|
|
@@ -1103,8 +1103,8 @@ export declare const transport: import("../route/transport/index.js").Transport<
|
|
|
1103
1103
|
readonly type: "image_generation_call";
|
|
1104
1104
|
readonly status?: string | undefined;
|
|
1105
1105
|
readonly result?: string | null | undefined;
|
|
1106
|
-
readonly revised_prompt?: string | null | undefined;
|
|
1107
1106
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
1107
|
+
readonly revised_prompt?: string | null | undefined;
|
|
1108
1108
|
})[];
|
|
1109
1109
|
readonly model: string;
|
|
1110
1110
|
readonly stream: true;
|
|
@@ -1131,9 +1131,9 @@ export declare const transport: import("../route/transport/index.js").Transport<
|
|
|
1131
1131
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
1132
1132
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
1133
1133
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
1134
|
+
readonly partial_images?: number | 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";
|
|
@@ -1331,8 +1331,8 @@ export declare const route: Route<{
|
|
|
1331
1331
|
readonly type: "image_generation_call";
|
|
1332
1332
|
readonly status?: string | undefined;
|
|
1333
1333
|
readonly result?: string | null | undefined;
|
|
1334
|
-
readonly revised_prompt?: string | null | undefined;
|
|
1335
1334
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
1335
|
+
readonly revised_prompt?: string | null | undefined;
|
|
1336
1336
|
})[];
|
|
1337
1337
|
readonly model: string;
|
|
1338
1338
|
readonly stream: true;
|
|
@@ -1359,9 +1359,9 @@ export declare const route: Route<{
|
|
|
1359
1359
|
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
1360
1360
|
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
1361
1361
|
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
1362
|
+
readonly partial_images?: number | 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,14 +5,12 @@ 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
|
|
8
|
+
import { LLMRequest } 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";
|
|
12
12
|
import { JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js";
|
|
13
|
-
import { OpenAIImage } from "./utils/openai-image.js";
|
|
14
13
|
import { ResponsesHostedTools } from "./utils/responses-hosted-tools.js";
|
|
15
|
-
import { ToolSchemaProjection } from "./utils/tool-schema.js";
|
|
16
14
|
import { OpenResponsesChannel } from "./open-responses-channel.js";
|
|
17
15
|
import { ResponsesCompaction } from "./utils/responses-compaction.js";
|
|
18
16
|
import { ResponsesCheckpoint } from "./utils/responses-checkpoint.js";
|
|
@@ -35,7 +33,14 @@ const OpenAIResponsesImageGenerationTool = Schema.Struct({
|
|
|
35
33
|
output_format: Schema.optional(Schema.Literals(["png", "jpeg", "webp"])),
|
|
36
34
|
partial_images: Schema.optional(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),
|
|
37
35
|
quality: Schema.optional(Schema.Literals(["auto", "low", "medium", "high"])),
|
|
38
|
-
size: Schema.optional(
|
|
36
|
+
size: Schema.optional(Schema.String.check(Schema.makeFilter((value) => {
|
|
37
|
+
if (value === "auto")
|
|
38
|
+
return undefined;
|
|
39
|
+
const match = /^(\d+)x(\d+)$/.exec(value);
|
|
40
|
+
if (!match)
|
|
41
|
+
return "image size must be `auto` or `{width}x{height}`";
|
|
42
|
+
return Number(match[1]) > 0 && Number(match[2]) > 0 ? undefined : "image dimensions must be positive integers";
|
|
43
|
+
}))),
|
|
39
44
|
});
|
|
40
45
|
const OpenAIResponsesHostedToolItem = Schema.Union([
|
|
41
46
|
Schema.StructWithRest(Schema.Struct({
|
|
@@ -100,23 +105,23 @@ export const CompactionTrigger = Schema.Struct({ type: Schema.Literal("compactio
|
|
|
100
105
|
const CheckpointBody = Schema.Struct({
|
|
101
106
|
...OpenAIResponsesBody.fields,
|
|
102
107
|
input: Schema.Array(Schema.Union([OpenAIResponsesInputItem, CompactionTrigger])),
|
|
103
|
-
store: Schema.Literal(false),
|
|
104
|
-
prompt_cache_retention: optionalNull(Schema.String),
|
|
105
|
-
prompt_cache_options: optionalNull(Schema.Struct({ mode: Schema.optional(Schema.String), ttl: Schema.optional(Schema.String) })),
|
|
106
108
|
});
|
|
107
109
|
const adapter = {
|
|
108
110
|
id: ADAPTER,
|
|
109
111
|
name: NAME,
|
|
110
112
|
restoreHostedToolItem: (item) => (Schema.is(OpenAIResponsesHostedToolItem)(item) ? item : undefined),
|
|
111
113
|
};
|
|
112
|
-
//
|
|
114
|
+
// GPT-6 Astra, Sol, and Luna accept `configuration_update` only in standard mode (not `reasoning.mode: "pro"` or
|
|
115
|
+
// `-pro` slugs), and never alongside automatic `context_management` compaction.
|
|
113
116
|
const supportsEffortUpdates = (request) => {
|
|
114
117
|
if (request.providerOptions?.contextManagement !== undefined)
|
|
115
118
|
return false;
|
|
119
|
+
if (Schema.is(Schema.Struct({ mode: Schema.Literal("pro") }))(request.http?.body?.reasoning))
|
|
120
|
+
return false;
|
|
116
121
|
const override = request.model.compatibility?.supportsEffortUpdates;
|
|
117
122
|
if (override !== undefined)
|
|
118
123
|
return override;
|
|
119
|
-
return /(?:^|\/)gpt-6-astra$/i.test(request.model.id);
|
|
124
|
+
return /(?:^|\/)gpt-6-(?:astra|sol|luna)$/i.test(request.model.id);
|
|
120
125
|
};
|
|
121
126
|
const nativeImageToolInput = (tool) => {
|
|
122
127
|
const native = tool.native?.openai;
|
|
@@ -126,29 +131,30 @@ const nativeImageTool = (tool) => {
|
|
|
126
131
|
const native = nativeImageToolInput(tool);
|
|
127
132
|
return Schema.is(OpenAIResponsesImageGenerationTool)(native) ? native : undefined;
|
|
128
133
|
};
|
|
129
|
-
const lowerTool = Effect.fn("OpenAIResponses.lowerTool")(function* (tool
|
|
134
|
+
const lowerTool = Effect.fn("OpenAIResponses.lowerTool")(function* (tool) {
|
|
130
135
|
const native = nativeImageToolInput(tool);
|
|
131
136
|
if (native !== undefined) {
|
|
132
137
|
if (Schema.is(OpenAIResponsesImageGenerationTool)(native))
|
|
133
138
|
return native;
|
|
134
139
|
return yield* ProviderShared.invalidRequest("OpenAI Responses image generation tool options are invalid");
|
|
135
140
|
}
|
|
136
|
-
return yield* OpenResponses.lowerTool(NAME, tool
|
|
141
|
+
return yield* OpenResponses.lowerTool(NAME, tool);
|
|
137
142
|
});
|
|
138
143
|
// Native namespaces hold only function tools, so deeper levels flatten into
|
|
139
144
|
// the leaf names the same way non-native protocols flatten the whole tree.
|
|
140
|
-
const lowerToolEntry = Effect.fn("OpenAIResponses.lowerToolEntry")(function* (tool
|
|
145
|
+
const lowerToolEntry = Effect.fn("OpenAIResponses.lowerToolEntry")(function* (tool) {
|
|
141
146
|
if (tool.type === "tool")
|
|
142
|
-
return yield* lowerTool(tool
|
|
147
|
+
return yield* lowerTool(tool);
|
|
143
148
|
// OpenAI requires a namespace description; fall back to a generic one so a
|
|
144
149
|
// missing description never blocks the request.
|
|
145
150
|
return {
|
|
146
151
|
type: "namespace",
|
|
147
152
|
name: tool.name,
|
|
148
153
|
description: tool.description ?? `Tools in the ${tool.name} namespace.`,
|
|
149
|
-
tools: yield* Effect.forEach(ProviderShared.flattenTools(tool.tools), (leaf) => OpenResponses.lowerTool(NAME, leaf
|
|
154
|
+
tools: yield* Effect.forEach(ProviderShared.flattenTools(tool.tools), (leaf) => OpenResponses.lowerTool(NAME, leaf)),
|
|
150
155
|
};
|
|
151
156
|
});
|
|
157
|
+
const lowerTools = (request) => Effect.forEach(request.tools, lowerToolEntry);
|
|
152
158
|
const lowerToolChoice = (toolChoice, tools) => ProviderShared.matchToolChoice(NAME, toolChoice, {
|
|
153
159
|
auto: () => "auto",
|
|
154
160
|
none: () => "none",
|
|
@@ -162,14 +168,11 @@ const fromRequest = Effect.fn("OpenAIResponses.fromRequest")(function* (request)
|
|
|
162
168
|
const management = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Schema.UndefinedOr(ContextManagement)))(request.providerOptions?.contextManagement);
|
|
163
169
|
const options = OpenResponsesOptions.resolve(request);
|
|
164
170
|
const updates = resolveEffortUpdates(request, options.reasoningEffort);
|
|
165
|
-
const toolSchemaCompatibility = request.model.compatibility?.toolSchema;
|
|
166
171
|
return yield* decodeBody({
|
|
167
172
|
...(yield* OpenResponses.lowerConversation(updates.request, adapter)),
|
|
168
173
|
...OpenResponses.lowerGeneration(request, { ...options, reasoningEffort: updates.effort }),
|
|
169
174
|
context_management: management?.map((edit) => ({ type: edit.type, compact_threshold: edit.compactThreshold })),
|
|
170
|
-
tools: request.tools.length === 0
|
|
171
|
-
? undefined
|
|
172
|
-
: yield* Effect.forEach(request.tools, (tool) => lowerToolEntry(tool, toolSchemaCompatibility)),
|
|
175
|
+
tools: request.tools.length === 0 ? undefined : yield* lowerTools(request),
|
|
173
176
|
tool_choice: request.tools.length === 0
|
|
174
177
|
? undefined
|
|
175
178
|
: (OpenResponses.allowedToolChoice(request) ??
|
|
@@ -179,25 +182,19 @@ const fromRequest = Effect.fn("OpenAIResponses.fromRequest")(function* (request)
|
|
|
179
182
|
const checkpointBody = {
|
|
180
183
|
schema: CheckpointBody,
|
|
181
184
|
from: Effect.fn("OpenAIResponses.checkpointBody")(function* (request) {
|
|
182
|
-
const native = yield* fromRequest(LLMRequest.update(request, { toolChoice: undefined }));
|
|
183
185
|
const overlay = request.http?.body;
|
|
184
186
|
// Complete history is required for stateless replay and SSE recovery. Raw input overrides bypass that contract.
|
|
185
187
|
if (overlay?.input !== undefined ||
|
|
186
188
|
overlay?.previous_response_id !== undefined ||
|
|
187
189
|
overlay?.conversation !== undefined)
|
|
188
190
|
return yield* ProviderShared.invalidRequest("Trigger compaction requires complete canonical history, not an input or continuation override");
|
|
189
|
-
|
|
190
|
-
|
|
191
|
+
if (overlay?.stream !== undefined && overlay.stream !== true)
|
|
192
|
+
return yield* ProviderShared.invalidRequest("Trigger compaction requires a streamed response");
|
|
193
|
+
const native = yield* fromRequest(request);
|
|
194
|
+
return {
|
|
195
|
+
...native,
|
|
191
196
|
input: [...native.input, { type: "compaction_trigger" }],
|
|
192
|
-
|
|
193
|
-
store: false,
|
|
194
|
-
parallel_tool_calls: true,
|
|
195
|
-
tool_choice: undefined,
|
|
196
|
-
context_management: undefined,
|
|
197
|
-
text: undefined,
|
|
198
|
-
max_output_tokens: undefined,
|
|
199
|
-
max_tool_calls: undefined,
|
|
200
|
-
});
|
|
197
|
+
};
|
|
201
198
|
}),
|
|
202
199
|
};
|
|
203
200
|
const hostedToolResult = Effect.fn("OpenAIResponses.hostedToolResult")(function* (item) {
|
|
@@ -268,7 +265,10 @@ export const transport = channelTransport({
|
|
|
268
265
|
headers: (headers) => Headers.set(headers, "openai-beta", headers["openai-beta"] ?? WEBSOCKET_PROTOCOL_HEADER),
|
|
269
266
|
});
|
|
270
267
|
export const route = Route.make({
|
|
271
|
-
compact: {
|
|
268
|
+
compact: {
|
|
269
|
+
endpoint: ResponsesCompaction.make(adapter, lowerTools),
|
|
270
|
+
trigger: ResponsesCheckpoint.make(checkpointBody),
|
|
271
|
+
},
|
|
272
272
|
id: ADAPTER,
|
|
273
273
|
provider: "openai",
|
|
274
274
|
providerMetadataKey: "openai",
|
|
@@ -0,0 +1,136 @@
|
|
|
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
|
+
/** `voice`, `instructions`, `speed`, and `format` are common request fields; other native body fields pass through. */
|
|
9
|
+
export type OpenAISpeechOptions = {
|
|
10
|
+
/** Defaults to `"sse"` in `stream` mode on models that support it; the merged value selects the response framing. */
|
|
11
|
+
readonly stream_format?: "sse" | "audio";
|
|
12
|
+
} & Record<string, unknown>;
|
|
13
|
+
export type Request = SpeechRequestFor<OpenAISpeechOptions>;
|
|
14
|
+
interface State extends SpeechStream.Audio {
|
|
15
|
+
readonly done: boolean;
|
|
16
|
+
readonly usage?: MediaUsage;
|
|
17
|
+
}
|
|
18
|
+
export declare const protocol: MediaProtocol.Streamed<Request, {
|
|
19
|
+
readonly id: string;
|
|
20
|
+
readonly type: "generation-queued";
|
|
21
|
+
readonly position?: number | undefined;
|
|
22
|
+
} | {
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly type: "generation-progress";
|
|
25
|
+
readonly progress?: number | undefined;
|
|
26
|
+
} | {
|
|
27
|
+
readonly type: "audio-delta";
|
|
28
|
+
readonly chunk: Uint8Array<ArrayBufferLike>;
|
|
29
|
+
} | {
|
|
30
|
+
readonly type: "timestamps";
|
|
31
|
+
readonly items: readonly {
|
|
32
|
+
readonly text: string;
|
|
33
|
+
readonly startSeconds: number;
|
|
34
|
+
readonly endSeconds: number;
|
|
35
|
+
}[];
|
|
36
|
+
} | {
|
|
37
|
+
readonly type: "finish";
|
|
38
|
+
readonly audio: import("../media.js").Asset;
|
|
39
|
+
readonly providerMetadata?: {
|
|
40
|
+
readonly [x: string]: {
|
|
41
|
+
readonly [x: string]: unknown;
|
|
42
|
+
};
|
|
43
|
+
} | undefined;
|
|
44
|
+
readonly usage?: {
|
|
45
|
+
readonly type: "tokens";
|
|
46
|
+
readonly input?: number | undefined;
|
|
47
|
+
readonly output?: number | undefined;
|
|
48
|
+
readonly total?: number | undefined;
|
|
49
|
+
readonly details?: {
|
|
50
|
+
readonly [x: string]: unknown;
|
|
51
|
+
} | undefined;
|
|
52
|
+
} | {
|
|
53
|
+
readonly type: "seconds";
|
|
54
|
+
readonly seconds: number;
|
|
55
|
+
} | {
|
|
56
|
+
readonly type: "characters";
|
|
57
|
+
readonly characters: number;
|
|
58
|
+
} | {
|
|
59
|
+
readonly type: "credits";
|
|
60
|
+
readonly credits: number;
|
|
61
|
+
} | {
|
|
62
|
+
readonly type: "compute";
|
|
63
|
+
readonly seconds: number;
|
|
64
|
+
} | undefined;
|
|
65
|
+
readonly notices?: readonly {
|
|
66
|
+
readonly type: "other" | "moderated" | "filtered";
|
|
67
|
+
readonly message: string;
|
|
68
|
+
readonly providerMetadata?: {
|
|
69
|
+
readonly [x: string]: {
|
|
70
|
+
readonly [x: string]: unknown;
|
|
71
|
+
};
|
|
72
|
+
} | undefined;
|
|
73
|
+
}[] | undefined;
|
|
74
|
+
}, string | Uint8Array<ArrayBufferLike>, State>;
|
|
75
|
+
export declare const model: (input: MediaRoute.ModelInput) => SpeechModel<OpenAISpeechOptions>;
|
|
76
|
+
export declare const OpenAISpeech: {
|
|
77
|
+
readonly protocol: MediaProtocol.Streamed<Request, {
|
|
78
|
+
readonly id: string;
|
|
79
|
+
readonly type: "generation-queued";
|
|
80
|
+
readonly position?: number | undefined;
|
|
81
|
+
} | {
|
|
82
|
+
readonly id: string;
|
|
83
|
+
readonly type: "generation-progress";
|
|
84
|
+
readonly progress?: number | undefined;
|
|
85
|
+
} | {
|
|
86
|
+
readonly type: "audio-delta";
|
|
87
|
+
readonly chunk: Uint8Array<ArrayBufferLike>;
|
|
88
|
+
} | {
|
|
89
|
+
readonly type: "timestamps";
|
|
90
|
+
readonly items: readonly {
|
|
91
|
+
readonly text: string;
|
|
92
|
+
readonly startSeconds: number;
|
|
93
|
+
readonly endSeconds: number;
|
|
94
|
+
}[];
|
|
95
|
+
} | {
|
|
96
|
+
readonly type: "finish";
|
|
97
|
+
readonly audio: import("../media.js").Asset;
|
|
98
|
+
readonly providerMetadata?: {
|
|
99
|
+
readonly [x: string]: {
|
|
100
|
+
readonly [x: string]: unknown;
|
|
101
|
+
};
|
|
102
|
+
} | undefined;
|
|
103
|
+
readonly usage?: {
|
|
104
|
+
readonly type: "tokens";
|
|
105
|
+
readonly input?: number | undefined;
|
|
106
|
+
readonly output?: number | undefined;
|
|
107
|
+
readonly total?: number | undefined;
|
|
108
|
+
readonly details?: {
|
|
109
|
+
readonly [x: string]: unknown;
|
|
110
|
+
} | undefined;
|
|
111
|
+
} | {
|
|
112
|
+
readonly type: "seconds";
|
|
113
|
+
readonly seconds: number;
|
|
114
|
+
} | {
|
|
115
|
+
readonly type: "characters";
|
|
116
|
+
readonly characters: number;
|
|
117
|
+
} | {
|
|
118
|
+
readonly type: "credits";
|
|
119
|
+
readonly credits: number;
|
|
120
|
+
} | {
|
|
121
|
+
readonly type: "compute";
|
|
122
|
+
readonly seconds: number;
|
|
123
|
+
} | undefined;
|
|
124
|
+
readonly notices?: readonly {
|
|
125
|
+
readonly type: "other" | "moderated" | "filtered";
|
|
126
|
+
readonly message: string;
|
|
127
|
+
readonly providerMetadata?: {
|
|
128
|
+
readonly [x: string]: {
|
|
129
|
+
readonly [x: string]: unknown;
|
|
130
|
+
};
|
|
131
|
+
} | undefined;
|
|
132
|
+
}[] | undefined;
|
|
133
|
+
}, string | Uint8Array<ArrayBufferLike>, State>;
|
|
134
|
+
readonly model: (input: MediaRoute.ModelInput) => SpeechModel<OpenAISpeechOptions>;
|
|
135
|
+
};
|
|
136
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
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 { mergeJsonRecords } from "../schema/index.js";
|
|
6
|
+
import { SpeechModel } from "../speech.js";
|
|
7
|
+
import { SpeechStream } from "./utils/speech-stream.js";
|
|
8
|
+
const route = MediaProtocol.identity({ id: "openai-speech", name: "OpenAI Speech", provider: "openai" });
|
|
9
|
+
export const DEFAULT_BASE_URL = "https://api.openai.com/v1";
|
|
10
|
+
export const PATH = "/audio/speech";
|
|
11
|
+
/** `pcm` is raw 24 kHz, 16-bit signed little-endian mono samples without a header. */
|
|
12
|
+
const PCM_SAMPLE_RATE = 24000;
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// 3. Streaming event schema
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
const SpeechStreamEvent = Schema.Union([
|
|
17
|
+
Schema.Struct({ type: Schema.Literal("speech.audio.delta"), audio: Schema.Uint8ArrayFromBase64 }),
|
|
18
|
+
Schema.Struct({
|
|
19
|
+
type: Schema.Literal("speech.audio.done"),
|
|
20
|
+
usage: Schema.optional(Schema.Struct({
|
|
21
|
+
input_tokens: Schema.optional(Schema.Number),
|
|
22
|
+
output_tokens: Schema.optional(Schema.Number),
|
|
23
|
+
total_tokens: Schema.optional(Schema.Number),
|
|
24
|
+
})),
|
|
25
|
+
}),
|
|
26
|
+
]);
|
|
27
|
+
const decodeEvent = route.decodeFrame(SpeechStreamEvent);
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// 5. Request body construction
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// `sse` is not supported for `tts-1` or `tts-1-hd`; those models stream the raw audio body instead.
|
|
32
|
+
const supportsSse = (model) => !/^tts-1(-hd)?(-|$)/.test(model);
|
|
33
|
+
const fromRequest = Effect.fn("OpenAISpeech.fromRequest")(function* (request) {
|
|
34
|
+
// Not in `unsupported`: that list would also reject `timestamps: false`, which asks for nothing.
|
|
35
|
+
if (request.timestamps === true)
|
|
36
|
+
return yield* route.unsupported("media.timestamps", `${route.name} does not return timestamps`);
|
|
37
|
+
return MediaProtocol.json(mergeJsonRecords({
|
|
38
|
+
model: request.model.id,
|
|
39
|
+
input: request.text,
|
|
40
|
+
voice: request.voice,
|
|
41
|
+
instructions: request.instructions,
|
|
42
|
+
response_format: request.format,
|
|
43
|
+
speed: request.speed,
|
|
44
|
+
stream_format: request.mode === "stream" && supportsSse(request.model.id) ? "sse" : undefined,
|
|
45
|
+
}, request.providerOptions, request.http?.body) ?? {});
|
|
46
|
+
});
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// 6. Stream parsing
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
const isSse = (body) => body.type === "json" && body.value.stream_format === "sse";
|
|
51
|
+
const onEvent = Effect.fn("OpenAISpeech.onEvent")(function* (state, frame) {
|
|
52
|
+
const event = yield* decodeEvent(frame);
|
|
53
|
+
if (event.type === "speech.audio.delta")
|
|
54
|
+
return SpeechStream.delta(state, event.audio);
|
|
55
|
+
const usage = event.usage;
|
|
56
|
+
return [
|
|
57
|
+
{
|
|
58
|
+
...state,
|
|
59
|
+
done: true,
|
|
60
|
+
usage: usage === undefined
|
|
61
|
+
? undefined
|
|
62
|
+
: {
|
|
63
|
+
type: "tokens",
|
|
64
|
+
input: usage.input_tokens,
|
|
65
|
+
output: usage.output_tokens,
|
|
66
|
+
total: usage.total_tokens,
|
|
67
|
+
details: { openai: usage },
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
[],
|
|
71
|
+
];
|
|
72
|
+
});
|
|
73
|
+
const finish = (state, context) => {
|
|
74
|
+
if (isSse(context.body) && !state.done)
|
|
75
|
+
return Effect.fail(route.incomplete());
|
|
76
|
+
const format = context.request.format ?? "mp3";
|
|
77
|
+
return SpeechStream.finish(route, state, {
|
|
78
|
+
...(format === "pcm" ? SpeechStream.pcm("pcm_s16le", PCM_SAMPLE_RATE) : SpeechStream.container(format)),
|
|
79
|
+
usage: state.usage,
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
// 7. Protocol and route
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
export const protocol = MediaProtocol.stream(route, {
|
|
86
|
+
unsupported: ["language"],
|
|
87
|
+
body: { from: fromRequest },
|
|
88
|
+
frames: (bytes, context) => (isSse(context.body) ? Framing.sse.frame(bytes) : bytes),
|
|
89
|
+
initial: () => ({ chunks: [], done: false }),
|
|
90
|
+
step: SpeechStream.step(onEvent),
|
|
91
|
+
finish,
|
|
92
|
+
});
|
|
93
|
+
export const model = (input) => SpeechModel.fromRoute({ protocol, baseURL: DEFAULT_BASE_URL, path: PATH }, input);
|
|
94
|
+
export const OpenAISpeech = {
|
|
95
|
+
protocol,
|
|
96
|
+
model,
|
|
97
|
+
};
|