ai 6.0.32 → 6.0.34
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/CHANGELOG.md +16 -0
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +12 -2
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +1 -1
- package/dist/internal/index.mjs +1 -1
- package/docs/02-foundations/03-prompts.mdx +2 -2
- package/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/28-output.mdx +1 -1
- package/package.json +6 -4
- package/src/agent/agent.ts +116 -0
- package/src/agent/create-agent-ui-stream-response.test.ts +258 -0
- package/src/agent/create-agent-ui-stream-response.ts +50 -0
- package/src/agent/create-agent-ui-stream.ts +73 -0
- package/src/agent/index.ts +33 -0
- package/src/agent/infer-agent-tools.ts +7 -0
- package/src/agent/infer-agent-ui-message.test-d.ts +54 -0
- package/src/agent/infer-agent-ui-message.ts +11 -0
- package/src/agent/pipe-agent-ui-stream-to-response.ts +52 -0
- package/src/agent/tool-loop-agent-on-finish-callback.ts +31 -0
- package/src/agent/tool-loop-agent-on-step-finish-callback.ts +11 -0
- package/src/agent/tool-loop-agent-settings.ts +182 -0
- package/src/agent/tool-loop-agent.test-d.ts +114 -0
- package/src/agent/tool-loop-agent.test.ts +442 -0
- package/src/agent/tool-loop-agent.ts +114 -0
- package/src/embed/__snapshots__/embed-many.test.ts.snap +191 -0
- package/src/embed/__snapshots__/embed.test.ts.snap +81 -0
- package/src/embed/embed-many-result.ts +53 -0
- package/src/embed/embed-many.test.ts +653 -0
- package/src/embed/embed-many.ts +378 -0
- package/src/embed/embed-result.ts +50 -0
- package/src/embed/embed.test.ts +298 -0
- package/src/embed/embed.ts +211 -0
- package/src/embed/index.ts +4 -0
- package/src/error/index.ts +34 -0
- package/src/error/invalid-argument-error.ts +34 -0
- package/src/error/invalid-stream-part-error.ts +28 -0
- package/src/error/invalid-tool-approval-error.ts +26 -0
- package/src/error/invalid-tool-input-error.ts +33 -0
- package/src/error/no-image-generated-error.ts +39 -0
- package/src/error/no-object-generated-error.ts +70 -0
- package/src/error/no-output-generated-error.ts +26 -0
- package/src/error/no-speech-generated-error.ts +18 -0
- package/src/error/no-such-tool-error.ts +35 -0
- package/src/error/no-transcript-generated-error.ts +20 -0
- package/src/error/tool-call-not-found-for-approval-error.ts +32 -0
- package/src/error/tool-call-repair-error.ts +30 -0
- package/src/error/unsupported-model-version-error.ts +23 -0
- package/src/error/verify-no-object-generated-error.ts +27 -0
- package/src/generate-image/generate-image-result.ts +42 -0
- package/src/generate-image/generate-image.test.ts +1420 -0
- package/src/generate-image/generate-image.ts +360 -0
- package/src/generate-image/index.ts +18 -0
- package/src/generate-object/__snapshots__/generate-object.test.ts.snap +133 -0
- package/src/generate-object/__snapshots__/stream-object.test.ts.snap +297 -0
- package/src/generate-object/generate-object-result.ts +67 -0
- package/src/generate-object/generate-object.test-d.ts +49 -0
- package/src/generate-object/generate-object.test.ts +1191 -0
- package/src/generate-object/generate-object.ts +518 -0
- package/src/generate-object/index.ts +9 -0
- package/src/generate-object/inject-json-instruction.test.ts +181 -0
- package/src/generate-object/inject-json-instruction.ts +30 -0
- package/src/generate-object/output-strategy.ts +415 -0
- package/src/generate-object/parse-and-validate-object-result.ts +111 -0
- package/src/generate-object/repair-text.ts +12 -0
- package/src/generate-object/stream-object-result.ts +120 -0
- package/src/generate-object/stream-object.test-d.ts +74 -0
- package/src/generate-object/stream-object.test.ts +1950 -0
- package/src/generate-object/stream-object.ts +986 -0
- package/src/generate-object/validate-object-generation-input.ts +144 -0
- package/src/generate-speech/generate-speech-result.ts +30 -0
- package/src/generate-speech/generate-speech.test.ts +300 -0
- package/src/generate-speech/generate-speech.ts +190 -0
- package/src/generate-speech/generated-audio-file.ts +65 -0
- package/src/generate-speech/index.ts +3 -0
- package/src/generate-text/__snapshots__/generate-text.test.ts.snap +1872 -0
- package/src/generate-text/__snapshots__/stream-text.test.ts.snap +1255 -0
- package/src/generate-text/collect-tool-approvals.test.ts +553 -0
- package/src/generate-text/collect-tool-approvals.ts +116 -0
- package/src/generate-text/content-part.ts +25 -0
- package/src/generate-text/execute-tool-call.ts +129 -0
- package/src/generate-text/extract-reasoning-content.ts +17 -0
- package/src/generate-text/extract-text-content.ts +15 -0
- package/src/generate-text/generate-text-result.ts +168 -0
- package/src/generate-text/generate-text.test-d.ts +68 -0
- package/src/generate-text/generate-text.test.ts +7011 -0
- package/src/generate-text/generate-text.ts +1223 -0
- package/src/generate-text/generated-file.ts +70 -0
- package/src/generate-text/index.ts +57 -0
- package/src/generate-text/is-approval-needed.ts +29 -0
- package/src/generate-text/output-utils.ts +23 -0
- package/src/generate-text/output.test.ts +698 -0
- package/src/generate-text/output.ts +590 -0
- package/src/generate-text/parse-tool-call.test.ts +570 -0
- package/src/generate-text/parse-tool-call.ts +188 -0
- package/src/generate-text/prepare-step.ts +103 -0
- package/src/generate-text/prune-messages.test.ts +720 -0
- package/src/generate-text/prune-messages.ts +167 -0
- package/src/generate-text/reasoning-output.ts +20 -0
- package/src/generate-text/reasoning.ts +8 -0
- package/src/generate-text/response-message.ts +10 -0
- package/src/generate-text/run-tools-transformation.test.ts +1143 -0
- package/src/generate-text/run-tools-transformation.ts +420 -0
- package/src/generate-text/smooth-stream.test.ts +2101 -0
- package/src/generate-text/smooth-stream.ts +162 -0
- package/src/generate-text/step-result.ts +238 -0
- package/src/generate-text/stop-condition.ts +29 -0
- package/src/generate-text/stream-text-result.ts +463 -0
- package/src/generate-text/stream-text.test-d.ts +200 -0
- package/src/generate-text/stream-text.test.ts +19979 -0
- package/src/generate-text/stream-text.ts +2505 -0
- package/src/generate-text/to-response-messages.test.ts +922 -0
- package/src/generate-text/to-response-messages.ts +163 -0
- package/src/generate-text/tool-approval-request-output.ts +21 -0
- package/src/generate-text/tool-call-repair-function.ts +27 -0
- package/src/generate-text/tool-call.ts +47 -0
- package/src/generate-text/tool-error.ts +34 -0
- package/src/generate-text/tool-output-denied.ts +21 -0
- package/src/generate-text/tool-output.ts +7 -0
- package/src/generate-text/tool-result.ts +36 -0
- package/src/generate-text/tool-set.ts +14 -0
- package/src/global.ts +24 -0
- package/src/index.ts +50 -0
- package/src/logger/index.ts +6 -0
- package/src/logger/log-warnings.test.ts +351 -0
- package/src/logger/log-warnings.ts +119 -0
- package/src/middleware/__snapshots__/simulate-streaming-middleware.test.ts.snap +64 -0
- package/src/middleware/add-tool-input-examples-middleware.test.ts +476 -0
- package/src/middleware/add-tool-input-examples-middleware.ts +90 -0
- package/src/middleware/default-embedding-settings-middleware.test.ts +126 -0
- package/src/middleware/default-embedding-settings-middleware.ts +22 -0
- package/src/middleware/default-settings-middleware.test.ts +388 -0
- package/src/middleware/default-settings-middleware.ts +33 -0
- package/src/middleware/extract-json-middleware.test.ts +827 -0
- package/src/middleware/extract-json-middleware.ts +197 -0
- package/src/middleware/extract-reasoning-middleware.test.ts +1028 -0
- package/src/middleware/extract-reasoning-middleware.ts +238 -0
- package/src/middleware/index.ts +10 -0
- package/src/middleware/simulate-streaming-middleware.test.ts +911 -0
- package/src/middleware/simulate-streaming-middleware.ts +79 -0
- package/src/middleware/wrap-embedding-model.test.ts +358 -0
- package/src/middleware/wrap-embedding-model.ts +86 -0
- package/src/middleware/wrap-image-model.test.ts +423 -0
- package/src/middleware/wrap-image-model.ts +85 -0
- package/src/middleware/wrap-language-model.test.ts +518 -0
- package/src/middleware/wrap-language-model.ts +104 -0
- package/src/middleware/wrap-provider.test.ts +120 -0
- package/src/middleware/wrap-provider.ts +51 -0
- package/src/model/as-embedding-model-v3.test.ts +319 -0
- package/src/model/as-embedding-model-v3.ts +24 -0
- package/src/model/as-image-model-v3.test.ts +409 -0
- package/src/model/as-image-model-v3.ts +24 -0
- package/src/model/as-language-model-v3.test.ts +508 -0
- package/src/model/as-language-model-v3.ts +103 -0
- package/src/model/as-provider-v3.ts +36 -0
- package/src/model/as-speech-model-v3.test.ts +356 -0
- package/src/model/as-speech-model-v3.ts +24 -0
- package/src/model/as-transcription-model-v3.test.ts +529 -0
- package/src/model/as-transcription-model-v3.ts +24 -0
- package/src/model/resolve-model.test.ts +244 -0
- package/src/model/resolve-model.ts +126 -0
- package/src/prompt/call-settings.ts +148 -0
- package/src/prompt/content-part.ts +209 -0
- package/src/prompt/convert-to-language-model-prompt.test.ts +2018 -0
- package/src/prompt/convert-to-language-model-prompt.ts +442 -0
- package/src/prompt/create-tool-model-output.test.ts +508 -0
- package/src/prompt/create-tool-model-output.ts +34 -0
- package/src/prompt/data-content.test.ts +15 -0
- package/src/prompt/data-content.ts +134 -0
- package/src/prompt/index.ts +27 -0
- package/src/prompt/invalid-data-content-error.ts +29 -0
- package/src/prompt/invalid-message-role-error.ts +27 -0
- package/src/prompt/message-conversion-error.ts +28 -0
- package/src/prompt/message.ts +68 -0
- package/src/prompt/prepare-call-settings.test.ts +159 -0
- package/src/prompt/prepare-call-settings.ts +108 -0
- package/src/prompt/prepare-tools-and-tool-choice.test.ts +461 -0
- package/src/prompt/prepare-tools-and-tool-choice.ts +86 -0
- package/src/prompt/prompt.ts +43 -0
- package/src/prompt/split-data-url.ts +17 -0
- package/src/prompt/standardize-prompt.test.ts +82 -0
- package/src/prompt/standardize-prompt.ts +99 -0
- package/src/prompt/wrap-gateway-error.ts +29 -0
- package/src/registry/custom-provider.test.ts +211 -0
- package/src/registry/custom-provider.ts +155 -0
- package/src/registry/index.ts +7 -0
- package/src/registry/no-such-provider-error.ts +41 -0
- package/src/registry/provider-registry.test.ts +691 -0
- package/src/registry/provider-registry.ts +328 -0
- package/src/rerank/index.ts +2 -0
- package/src/rerank/rerank-result.ts +70 -0
- package/src/rerank/rerank.test.ts +516 -0
- package/src/rerank/rerank.ts +237 -0
- package/src/telemetry/assemble-operation-name.ts +21 -0
- package/src/telemetry/get-base-telemetry-attributes.ts +53 -0
- package/src/telemetry/get-tracer.ts +20 -0
- package/src/telemetry/noop-tracer.ts +69 -0
- package/src/telemetry/record-span.ts +63 -0
- package/src/telemetry/select-telemetry-attributes.ts +78 -0
- package/src/telemetry/select-temetry-attributes.test.ts +114 -0
- package/src/telemetry/stringify-for-telemetry.test.ts +114 -0
- package/src/telemetry/stringify-for-telemetry.ts +33 -0
- package/src/telemetry/telemetry-settings.ts +44 -0
- package/src/test/mock-embedding-model-v2.ts +35 -0
- package/src/test/mock-embedding-model-v3.ts +48 -0
- package/src/test/mock-image-model-v2.ts +28 -0
- package/src/test/mock-image-model-v3.ts +28 -0
- package/src/test/mock-language-model-v2.ts +72 -0
- package/src/test/mock-language-model-v3.ts +77 -0
- package/src/test/mock-provider-v2.ts +68 -0
- package/src/test/mock-provider-v3.ts +80 -0
- package/src/test/mock-reranking-model-v3.ts +25 -0
- package/src/test/mock-server-response.ts +69 -0
- package/src/test/mock-speech-model-v2.ts +24 -0
- package/src/test/mock-speech-model-v3.ts +24 -0
- package/src/test/mock-tracer.ts +156 -0
- package/src/test/mock-transcription-model-v2.ts +24 -0
- package/src/test/mock-transcription-model-v3.ts +24 -0
- package/src/test/mock-values.ts +4 -0
- package/src/test/not-implemented.ts +3 -0
- package/src/text-stream/create-text-stream-response.test.ts +38 -0
- package/src/text-stream/create-text-stream-response.ts +18 -0
- package/src/text-stream/index.ts +2 -0
- package/src/text-stream/pipe-text-stream-to-response.test.ts +38 -0
- package/src/text-stream/pipe-text-stream-to-response.ts +26 -0
- package/src/transcribe/index.ts +2 -0
- package/src/transcribe/transcribe-result.ts +60 -0
- package/src/transcribe/transcribe.test.ts +313 -0
- package/src/transcribe/transcribe.ts +173 -0
- package/src/types/embedding-model-middleware.ts +3 -0
- package/src/types/embedding-model.ts +18 -0
- package/src/types/image-model-middleware.ts +3 -0
- package/src/types/image-model-response-metadata.ts +16 -0
- package/src/types/image-model.ts +19 -0
- package/src/types/index.ts +29 -0
- package/src/types/json-value.ts +15 -0
- package/src/types/language-model-middleware.ts +3 -0
- package/src/types/language-model-request-metadata.ts +6 -0
- package/src/types/language-model-response-metadata.ts +21 -0
- package/src/types/language-model.ts +104 -0
- package/src/types/provider-metadata.ts +16 -0
- package/src/types/provider.ts +55 -0
- package/src/types/reranking-model.ts +6 -0
- package/src/types/speech-model-response-metadata.ts +21 -0
- package/src/types/speech-model.ts +6 -0
- package/src/types/transcription-model-response-metadata.ts +16 -0
- package/src/types/transcription-model.ts +9 -0
- package/src/types/usage.ts +200 -0
- package/src/types/warning.ts +7 -0
- package/src/ui/__snapshots__/append-response-messages.test.ts.snap +416 -0
- package/src/ui/__snapshots__/convert-to-model-messages.test.ts.snap +419 -0
- package/src/ui/__snapshots__/process-chat-text-response.test.ts.snap +142 -0
- package/src/ui/call-completion-api.ts +157 -0
- package/src/ui/chat-transport.ts +83 -0
- package/src/ui/chat.test-d.ts +233 -0
- package/src/ui/chat.test.ts +2695 -0
- package/src/ui/chat.ts +716 -0
- package/src/ui/convert-file-list-to-file-ui-parts.ts +36 -0
- package/src/ui/convert-to-model-messages.test.ts +2775 -0
- package/src/ui/convert-to-model-messages.ts +373 -0
- package/src/ui/default-chat-transport.ts +36 -0
- package/src/ui/direct-chat-transport.test.ts +446 -0
- package/src/ui/direct-chat-transport.ts +118 -0
- package/src/ui/http-chat-transport.test.ts +185 -0
- package/src/ui/http-chat-transport.ts +292 -0
- package/src/ui/index.ts +71 -0
- package/src/ui/last-assistant-message-is-complete-with-approval-responses.ts +44 -0
- package/src/ui/last-assistant-message-is-complete-with-tool-calls.test.ts +371 -0
- package/src/ui/last-assistant-message-is-complete-with-tool-calls.ts +39 -0
- package/src/ui/process-text-stream.test.ts +38 -0
- package/src/ui/process-text-stream.ts +16 -0
- package/src/ui/process-ui-message-stream.test.ts +8052 -0
- package/src/ui/process-ui-message-stream.ts +713 -0
- package/src/ui/text-stream-chat-transport.ts +23 -0
- package/src/ui/transform-text-to-ui-message-stream.test.ts +124 -0
- package/src/ui/transform-text-to-ui-message-stream.ts +27 -0
- package/src/ui/ui-messages.test.ts +48 -0
- package/src/ui/ui-messages.ts +534 -0
- package/src/ui/use-completion.ts +84 -0
- package/src/ui/validate-ui-messages.test.ts +1428 -0
- package/src/ui/validate-ui-messages.ts +476 -0
- package/src/ui-message-stream/create-ui-message-stream-response.test.ts +266 -0
- package/src/ui-message-stream/create-ui-message-stream-response.ts +32 -0
- package/src/ui-message-stream/create-ui-message-stream.test.ts +639 -0
- package/src/ui-message-stream/create-ui-message-stream.ts +124 -0
- package/src/ui-message-stream/get-response-ui-message-id.test.ts +55 -0
- package/src/ui-message-stream/get-response-ui-message-id.ts +24 -0
- package/src/ui-message-stream/handle-ui-message-stream-finish.test.ts +429 -0
- package/src/ui-message-stream/handle-ui-message-stream-finish.ts +135 -0
- package/src/ui-message-stream/index.ts +13 -0
- package/src/ui-message-stream/json-to-sse-transform-stream.ts +12 -0
- package/src/ui-message-stream/pipe-ui-message-stream-to-response.test.ts +90 -0
- package/src/ui-message-stream/pipe-ui-message-stream-to-response.ts +40 -0
- package/src/ui-message-stream/read-ui-message-stream.test.ts +122 -0
- package/src/ui-message-stream/read-ui-message-stream.ts +87 -0
- package/src/ui-message-stream/ui-message-chunks.test-d.ts +18 -0
- package/src/ui-message-stream/ui-message-chunks.ts +344 -0
- package/src/ui-message-stream/ui-message-stream-headers.ts +7 -0
- package/src/ui-message-stream/ui-message-stream-on-finish-callback.ts +32 -0
- package/src/ui-message-stream/ui-message-stream-response-init.ts +5 -0
- package/src/ui-message-stream/ui-message-stream-writer.ts +24 -0
- package/src/util/as-array.ts +3 -0
- package/src/util/async-iterable-stream.test.ts +241 -0
- package/src/util/async-iterable-stream.ts +94 -0
- package/src/util/consume-stream.ts +29 -0
- package/src/util/cosine-similarity.test.ts +57 -0
- package/src/util/cosine-similarity.ts +47 -0
- package/src/util/create-resolvable-promise.ts +30 -0
- package/src/util/create-stitchable-stream.test.ts +239 -0
- package/src/util/create-stitchable-stream.ts +112 -0
- package/src/util/data-url.ts +17 -0
- package/src/util/deep-partial.ts +84 -0
- package/src/util/detect-media-type.test.ts +670 -0
- package/src/util/detect-media-type.ts +184 -0
- package/src/util/download/download-function.ts +45 -0
- package/src/util/download/download.test.ts +69 -0
- package/src/util/download/download.ts +46 -0
- package/src/util/error-handler.ts +1 -0
- package/src/util/fix-json.test.ts +279 -0
- package/src/util/fix-json.ts +401 -0
- package/src/util/get-potential-start-index.test.ts +34 -0
- package/src/util/get-potential-start-index.ts +30 -0
- package/src/util/index.ts +11 -0
- package/src/util/is-deep-equal-data.test.ts +119 -0
- package/src/util/is-deep-equal-data.ts +48 -0
- package/src/util/is-non-empty-object.ts +5 -0
- package/src/util/job.ts +1 -0
- package/src/util/log-v2-compatibility-warning.ts +21 -0
- package/src/util/merge-abort-signals.test.ts +155 -0
- package/src/util/merge-abort-signals.ts +43 -0
- package/src/util/merge-objects.test.ts +118 -0
- package/src/util/merge-objects.ts +79 -0
- package/src/util/now.ts +4 -0
- package/src/util/parse-partial-json.test.ts +80 -0
- package/src/util/parse-partial-json.ts +30 -0
- package/src/util/prepare-headers.test.ts +51 -0
- package/src/util/prepare-headers.ts +14 -0
- package/src/util/prepare-retries.test.ts +10 -0
- package/src/util/prepare-retries.ts +47 -0
- package/src/util/retry-error.ts +41 -0
- package/src/util/retry-with-exponential-backoff.test.ts +446 -0
- package/src/util/retry-with-exponential-backoff.ts +154 -0
- package/src/util/serial-job-executor.test.ts +162 -0
- package/src/util/serial-job-executor.ts +36 -0
- package/src/util/simulate-readable-stream.test.ts +98 -0
- package/src/util/simulate-readable-stream.ts +39 -0
- package/src/util/split-array.test.ts +60 -0
- package/src/util/split-array.ts +20 -0
- package/src/util/value-of.ts +65 -0
- package/src/util/write-to-server-response.test.ts +266 -0
- package/src/util/write-to-server-response.ts +49 -0
- package/src/version.ts +5 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { FlexibleSchema } from '@ai-sdk/provider-utils';
|
|
2
|
+
import { InvalidArgumentError } from '../error/invalid-argument-error';
|
|
3
|
+
|
|
4
|
+
export function validateObjectGenerationInput({
|
|
5
|
+
output,
|
|
6
|
+
schema,
|
|
7
|
+
schemaName,
|
|
8
|
+
schemaDescription,
|
|
9
|
+
enumValues,
|
|
10
|
+
}: {
|
|
11
|
+
output?: 'object' | 'array' | 'enum' | 'no-schema';
|
|
12
|
+
schema?: FlexibleSchema<unknown>;
|
|
13
|
+
schemaName?: string;
|
|
14
|
+
schemaDescription?: string;
|
|
15
|
+
enumValues?: Array<unknown>;
|
|
16
|
+
}) {
|
|
17
|
+
if (
|
|
18
|
+
output != null &&
|
|
19
|
+
output !== 'object' &&
|
|
20
|
+
output !== 'array' &&
|
|
21
|
+
output !== 'enum' &&
|
|
22
|
+
output !== 'no-schema'
|
|
23
|
+
) {
|
|
24
|
+
throw new InvalidArgumentError({
|
|
25
|
+
parameter: 'output',
|
|
26
|
+
value: output,
|
|
27
|
+
message: 'Invalid output type.',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (output === 'no-schema') {
|
|
32
|
+
if (schema != null) {
|
|
33
|
+
throw new InvalidArgumentError({
|
|
34
|
+
parameter: 'schema',
|
|
35
|
+
value: schema,
|
|
36
|
+
message: 'Schema is not supported for no-schema output.',
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (schemaDescription != null) {
|
|
41
|
+
throw new InvalidArgumentError({
|
|
42
|
+
parameter: 'schemaDescription',
|
|
43
|
+
value: schemaDescription,
|
|
44
|
+
message: 'Schema description is not supported for no-schema output.',
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (schemaName != null) {
|
|
49
|
+
throw new InvalidArgumentError({
|
|
50
|
+
parameter: 'schemaName',
|
|
51
|
+
value: schemaName,
|
|
52
|
+
message: 'Schema name is not supported for no-schema output.',
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (enumValues != null) {
|
|
57
|
+
throw new InvalidArgumentError({
|
|
58
|
+
parameter: 'enumValues',
|
|
59
|
+
value: enumValues,
|
|
60
|
+
message: 'Enum values are not supported for no-schema output.',
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (output === 'object') {
|
|
66
|
+
if (schema == null) {
|
|
67
|
+
throw new InvalidArgumentError({
|
|
68
|
+
parameter: 'schema',
|
|
69
|
+
value: schema,
|
|
70
|
+
message: 'Schema is required for object output.',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (enumValues != null) {
|
|
75
|
+
throw new InvalidArgumentError({
|
|
76
|
+
parameter: 'enumValues',
|
|
77
|
+
value: enumValues,
|
|
78
|
+
message: 'Enum values are not supported for object output.',
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (output === 'array') {
|
|
84
|
+
if (schema == null) {
|
|
85
|
+
throw new InvalidArgumentError({
|
|
86
|
+
parameter: 'schema',
|
|
87
|
+
value: schema,
|
|
88
|
+
message: 'Element schema is required for array output.',
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (enumValues != null) {
|
|
93
|
+
throw new InvalidArgumentError({
|
|
94
|
+
parameter: 'enumValues',
|
|
95
|
+
value: enumValues,
|
|
96
|
+
message: 'Enum values are not supported for array output.',
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (output === 'enum') {
|
|
102
|
+
if (schema != null) {
|
|
103
|
+
throw new InvalidArgumentError({
|
|
104
|
+
parameter: 'schema',
|
|
105
|
+
value: schema,
|
|
106
|
+
message: 'Schema is not supported for enum output.',
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (schemaDescription != null) {
|
|
111
|
+
throw new InvalidArgumentError({
|
|
112
|
+
parameter: 'schemaDescription',
|
|
113
|
+
value: schemaDescription,
|
|
114
|
+
message: 'Schema description is not supported for enum output.',
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (schemaName != null) {
|
|
119
|
+
throw new InvalidArgumentError({
|
|
120
|
+
parameter: 'schemaName',
|
|
121
|
+
value: schemaName,
|
|
122
|
+
message: 'Schema name is not supported for enum output.',
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (enumValues == null) {
|
|
127
|
+
throw new InvalidArgumentError({
|
|
128
|
+
parameter: 'enumValues',
|
|
129
|
+
value: enumValues,
|
|
130
|
+
message: 'Enum values are required for enum output.',
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
for (const value of enumValues) {
|
|
135
|
+
if (typeof value !== 'string') {
|
|
136
|
+
throw new InvalidArgumentError({
|
|
137
|
+
parameter: 'enumValues',
|
|
138
|
+
value,
|
|
139
|
+
message: 'Enum values must be strings.',
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { JSONObject } from '@ai-sdk/provider';
|
|
2
|
+
import { SpeechModelResponseMetadata } from '../types/speech-model-response-metadata';
|
|
3
|
+
import { Warning } from '../types/warning';
|
|
4
|
+
import { GeneratedAudioFile } from './generated-audio-file';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
The result of a `generateSpeech` call.
|
|
8
|
+
It contains the audio data and additional information.
|
|
9
|
+
*/
|
|
10
|
+
export interface SpeechResult {
|
|
11
|
+
/**
|
|
12
|
+
* The audio data as a base64 encoded string or binary data.
|
|
13
|
+
*/
|
|
14
|
+
readonly audio: GeneratedAudioFile;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
Warnings for the call, e.g. unsupported settings.
|
|
18
|
+
*/
|
|
19
|
+
readonly warnings: Array<Warning>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
Response metadata from the provider. There may be multiple responses if we made multiple calls to the model.
|
|
23
|
+
*/
|
|
24
|
+
readonly responses: Array<SpeechModelResponseMetadata>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
Provider metadata from the provider.
|
|
28
|
+
*/
|
|
29
|
+
readonly providerMetadata: Record<string, JSONObject>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { JSONObject, SpeechModelV3 } from '@ai-sdk/provider';
|
|
2
|
+
import {
|
|
3
|
+
afterEach,
|
|
4
|
+
beforeEach,
|
|
5
|
+
describe,
|
|
6
|
+
expect,
|
|
7
|
+
it,
|
|
8
|
+
vi,
|
|
9
|
+
vitest,
|
|
10
|
+
} from 'vitest';
|
|
11
|
+
import * as logWarningsModule from '../logger/log-warnings';
|
|
12
|
+
import { MockSpeechModelV3 } from '../test/mock-speech-model-v3';
|
|
13
|
+
import { Warning } from '../types/warning';
|
|
14
|
+
import { generateSpeech } from './generate-speech';
|
|
15
|
+
import {
|
|
16
|
+
DefaultGeneratedAudioFile,
|
|
17
|
+
GeneratedAudioFile,
|
|
18
|
+
} from './generated-audio-file';
|
|
19
|
+
|
|
20
|
+
const audio = new Uint8Array([1, 2, 3, 4]); // Sample audio data
|
|
21
|
+
const testDate = new Date(2024, 0, 1);
|
|
22
|
+
const mockFile = new DefaultGeneratedAudioFile({
|
|
23
|
+
data: audio,
|
|
24
|
+
mediaType: 'audio/mp3',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const sampleText = 'This is a sample text to convert to speech.';
|
|
28
|
+
|
|
29
|
+
vi.mock('../version', () => {
|
|
30
|
+
return {
|
|
31
|
+
VERSION: '0.0.0-test',
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const createMockResponse = (options: {
|
|
36
|
+
audio: GeneratedAudioFile;
|
|
37
|
+
warnings?: Warning[];
|
|
38
|
+
timestamp?: Date;
|
|
39
|
+
modelId?: string;
|
|
40
|
+
headers?: Record<string, string>;
|
|
41
|
+
providerMetadata?: Record<string, JSONObject>;
|
|
42
|
+
}) => ({
|
|
43
|
+
audio: options.audio.uint8Array,
|
|
44
|
+
warnings: options.warnings ?? [],
|
|
45
|
+
response: {
|
|
46
|
+
timestamp: options.timestamp ?? new Date(),
|
|
47
|
+
modelId: options.modelId ?? 'test-model-id',
|
|
48
|
+
headers: options.headers ?? {},
|
|
49
|
+
},
|
|
50
|
+
providerMetadata: options.providerMetadata ?? {},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('generateSpeech', () => {
|
|
54
|
+
let logWarningsSpy: ReturnType<typeof vitest.spyOn>;
|
|
55
|
+
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
logWarningsSpy = vitest
|
|
58
|
+
.spyOn(logWarningsModule, 'logWarnings')
|
|
59
|
+
.mockImplementation(() => {});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
afterEach(() => {
|
|
63
|
+
logWarningsSpy.mockRestore();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should send args to doGenerate', async () => {
|
|
67
|
+
const abortController = new AbortController();
|
|
68
|
+
const abortSignal = abortController.signal;
|
|
69
|
+
|
|
70
|
+
let capturedArgs!: Parameters<SpeechModelV3['doGenerate']>[0];
|
|
71
|
+
|
|
72
|
+
await generateSpeech({
|
|
73
|
+
model: new MockSpeechModelV3({
|
|
74
|
+
doGenerate: async args => {
|
|
75
|
+
capturedArgs = args;
|
|
76
|
+
return createMockResponse({
|
|
77
|
+
audio: mockFile,
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
text: sampleText,
|
|
82
|
+
voice: 'test-voice',
|
|
83
|
+
headers: {
|
|
84
|
+
'custom-request-header': 'request-header-value',
|
|
85
|
+
},
|
|
86
|
+
abortSignal,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
expect(capturedArgs).toStrictEqual({
|
|
90
|
+
text: sampleText,
|
|
91
|
+
voice: 'test-voice',
|
|
92
|
+
headers: {
|
|
93
|
+
'custom-request-header': 'request-header-value',
|
|
94
|
+
'user-agent': 'ai/0.0.0-test',
|
|
95
|
+
},
|
|
96
|
+
abortSignal,
|
|
97
|
+
providerOptions: {},
|
|
98
|
+
outputFormat: undefined,
|
|
99
|
+
instructions: undefined,
|
|
100
|
+
speed: undefined,
|
|
101
|
+
language: undefined,
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should return warnings', async () => {
|
|
106
|
+
const result = await generateSpeech({
|
|
107
|
+
model: new MockSpeechModelV3({
|
|
108
|
+
doGenerate: async () =>
|
|
109
|
+
createMockResponse({
|
|
110
|
+
audio: mockFile,
|
|
111
|
+
warnings: [
|
|
112
|
+
{
|
|
113
|
+
type: 'other',
|
|
114
|
+
message: 'Setting is not supported',
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
providerMetadata: {
|
|
118
|
+
'test-provider': {
|
|
119
|
+
'test-key': 'test-value',
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
}),
|
|
123
|
+
}),
|
|
124
|
+
text: sampleText,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
expect(result.warnings).toStrictEqual([
|
|
128
|
+
{
|
|
129
|
+
type: 'other',
|
|
130
|
+
message: 'Setting is not supported',
|
|
131
|
+
},
|
|
132
|
+
]);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('should call logWarnings with the correct warnings', async () => {
|
|
136
|
+
const expectedWarnings: Warning[] = [
|
|
137
|
+
{
|
|
138
|
+
type: 'other',
|
|
139
|
+
message: 'Setting is not supported',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
type: 'unsupported',
|
|
143
|
+
feature: 'voice',
|
|
144
|
+
details: 'Voice parameter not supported',
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
await generateSpeech({
|
|
149
|
+
model: new MockSpeechModelV3({
|
|
150
|
+
doGenerate: async () =>
|
|
151
|
+
createMockResponse({
|
|
152
|
+
audio: mockFile,
|
|
153
|
+
warnings: expectedWarnings,
|
|
154
|
+
}),
|
|
155
|
+
}),
|
|
156
|
+
text: sampleText,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
expect(logWarningsSpy).toHaveBeenCalledOnce();
|
|
160
|
+
expect(logWarningsSpy).toHaveBeenCalledWith({
|
|
161
|
+
warnings: expectedWarnings,
|
|
162
|
+
provider: 'mock-provider',
|
|
163
|
+
model: 'mock-model-id',
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('should call logWarnings with empty array when no warnings are present', async () => {
|
|
168
|
+
await generateSpeech({
|
|
169
|
+
model: new MockSpeechModelV3({
|
|
170
|
+
doGenerate: async () =>
|
|
171
|
+
createMockResponse({
|
|
172
|
+
audio: mockFile,
|
|
173
|
+
warnings: [], // no warnings
|
|
174
|
+
}),
|
|
175
|
+
}),
|
|
176
|
+
text: sampleText,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
expect(logWarningsSpy).toHaveBeenCalledOnce();
|
|
180
|
+
expect(logWarningsSpy).toHaveBeenCalledWith({
|
|
181
|
+
warnings: [],
|
|
182
|
+
provider: 'mock-provider',
|
|
183
|
+
model: 'mock-model-id',
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('should return the audio data', async () => {
|
|
188
|
+
const result = await generateSpeech({
|
|
189
|
+
model: new MockSpeechModelV3({
|
|
190
|
+
doGenerate: async () =>
|
|
191
|
+
createMockResponse({
|
|
192
|
+
audio: mockFile,
|
|
193
|
+
}),
|
|
194
|
+
}),
|
|
195
|
+
text: sampleText,
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
expect(result).toEqual({
|
|
199
|
+
audio: mockFile,
|
|
200
|
+
warnings: [],
|
|
201
|
+
responses: [
|
|
202
|
+
{
|
|
203
|
+
timestamp: expect.any(Date),
|
|
204
|
+
modelId: 'test-model-id',
|
|
205
|
+
headers: {},
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
providerMetadata: {},
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
describe('error handling', () => {
|
|
213
|
+
it('should throw NoSpeechGeneratedError when no audio is returned', async () => {
|
|
214
|
+
await expect(
|
|
215
|
+
generateSpeech({
|
|
216
|
+
model: new MockSpeechModelV3({
|
|
217
|
+
doGenerate: async () =>
|
|
218
|
+
createMockResponse({
|
|
219
|
+
audio: new DefaultGeneratedAudioFile({
|
|
220
|
+
data: new Uint8Array(),
|
|
221
|
+
mediaType: 'audio/mp3',
|
|
222
|
+
}),
|
|
223
|
+
timestamp: testDate,
|
|
224
|
+
}),
|
|
225
|
+
}),
|
|
226
|
+
text: sampleText,
|
|
227
|
+
}),
|
|
228
|
+
).rejects.toMatchObject({
|
|
229
|
+
name: 'AI_NoSpeechGeneratedError',
|
|
230
|
+
message: 'No speech audio generated.',
|
|
231
|
+
responses: [
|
|
232
|
+
{
|
|
233
|
+
timestamp: testDate,
|
|
234
|
+
modelId: expect.any(String),
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('should include response headers in error when no audio generated', async () => {
|
|
241
|
+
await expect(
|
|
242
|
+
generateSpeech({
|
|
243
|
+
model: new MockSpeechModelV3({
|
|
244
|
+
doGenerate: async () =>
|
|
245
|
+
createMockResponse({
|
|
246
|
+
audio: new DefaultGeneratedAudioFile({
|
|
247
|
+
data: new Uint8Array(),
|
|
248
|
+
mediaType: 'audio/mp3',
|
|
249
|
+
}),
|
|
250
|
+
timestamp: testDate,
|
|
251
|
+
headers: {
|
|
252
|
+
'custom-response-header': 'response-header-value',
|
|
253
|
+
'user-agent': 'ai/0.0.0-test',
|
|
254
|
+
},
|
|
255
|
+
}),
|
|
256
|
+
}),
|
|
257
|
+
text: sampleText,
|
|
258
|
+
}),
|
|
259
|
+
).rejects.toMatchObject({
|
|
260
|
+
name: 'AI_NoSpeechGeneratedError',
|
|
261
|
+
message: 'No speech audio generated.',
|
|
262
|
+
responses: [
|
|
263
|
+
{
|
|
264
|
+
timestamp: testDate,
|
|
265
|
+
modelId: expect.any(String),
|
|
266
|
+
headers: {
|
|
267
|
+
'custom-response-header': 'response-header-value',
|
|
268
|
+
'user-agent': 'ai/0.0.0-test',
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
],
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it('should return response metadata', async () => {
|
|
277
|
+
const testHeaders = { 'x-test': 'value' };
|
|
278
|
+
|
|
279
|
+
const result = await generateSpeech({
|
|
280
|
+
model: new MockSpeechModelV3({
|
|
281
|
+
doGenerate: async () =>
|
|
282
|
+
createMockResponse({
|
|
283
|
+
audio: mockFile,
|
|
284
|
+
timestamp: testDate,
|
|
285
|
+
modelId: 'test-model',
|
|
286
|
+
headers: testHeaders,
|
|
287
|
+
}),
|
|
288
|
+
}),
|
|
289
|
+
text: sampleText,
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
expect(result.responses).toStrictEqual([
|
|
293
|
+
{
|
|
294
|
+
timestamp: testDate,
|
|
295
|
+
modelId: 'test-model',
|
|
296
|
+
headers: testHeaders,
|
|
297
|
+
},
|
|
298
|
+
]);
|
|
299
|
+
});
|
|
300
|
+
});
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { JSONObject } from '@ai-sdk/provider';
|
|
2
|
+
import { ProviderOptions, withUserAgentSuffix } from '@ai-sdk/provider-utils';
|
|
3
|
+
import { NoSpeechGeneratedError } from '../error/no-speech-generated-error';
|
|
4
|
+
import { logWarnings } from '../logger/log-warnings';
|
|
5
|
+
import { resolveSpeechModel } from '../model/resolve-model';
|
|
6
|
+
import { SpeechModel } from '../types/speech-model';
|
|
7
|
+
import { SpeechModelResponseMetadata } from '../types/speech-model-response-metadata';
|
|
8
|
+
import { Warning } from '../types/warning';
|
|
9
|
+
import {
|
|
10
|
+
audioMediaTypeSignatures,
|
|
11
|
+
detectMediaType,
|
|
12
|
+
} from '../util/detect-media-type';
|
|
13
|
+
import { prepareRetries } from '../util/prepare-retries';
|
|
14
|
+
import { VERSION } from '../version';
|
|
15
|
+
import { SpeechResult } from './generate-speech-result';
|
|
16
|
+
import {
|
|
17
|
+
DefaultGeneratedAudioFile,
|
|
18
|
+
GeneratedAudioFile,
|
|
19
|
+
} from './generated-audio-file';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
Generates speech audio using a speech model.
|
|
23
|
+
|
|
24
|
+
@param model - The speech model to use.
|
|
25
|
+
@param text - The text to convert to speech.
|
|
26
|
+
@param voice - The voice to use for speech generation.
|
|
27
|
+
@param outputFormat - The output format to use for speech generation e.g. "mp3", "wav", etc.
|
|
28
|
+
@param instructions - Instructions for the speech generation e.g. "Speak in a slow and steady tone".
|
|
29
|
+
@param speed - The speed of the speech generation.
|
|
30
|
+
@param providerOptions - Additional provider-specific options that are passed through to the provider
|
|
31
|
+
as body parameters.
|
|
32
|
+
@param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2.
|
|
33
|
+
@param abortSignal - An optional abort signal that can be used to cancel the call.
|
|
34
|
+
@param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
|
|
35
|
+
|
|
36
|
+
@returns A result object that contains the generated audio data.
|
|
37
|
+
*/
|
|
38
|
+
export async function generateSpeech({
|
|
39
|
+
model,
|
|
40
|
+
text,
|
|
41
|
+
voice,
|
|
42
|
+
outputFormat,
|
|
43
|
+
instructions,
|
|
44
|
+
speed,
|
|
45
|
+
language,
|
|
46
|
+
providerOptions = {},
|
|
47
|
+
maxRetries: maxRetriesArg,
|
|
48
|
+
abortSignal,
|
|
49
|
+
headers,
|
|
50
|
+
}: {
|
|
51
|
+
/**
|
|
52
|
+
The speech model to use.
|
|
53
|
+
*/
|
|
54
|
+
model: SpeechModel;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
The text to convert to speech.
|
|
58
|
+
*/
|
|
59
|
+
text: string;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
The voice to use for speech generation.
|
|
63
|
+
*/
|
|
64
|
+
voice?: string;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The desired output format for the audio e.g. "mp3", "wav", etc.
|
|
68
|
+
*/
|
|
69
|
+
outputFormat?: 'mp3' | 'wav' | (string & {});
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
Instructions for the speech generation e.g. "Speak in a slow and steady tone".
|
|
73
|
+
*/
|
|
74
|
+
instructions?: string;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
The speed of the speech generation.
|
|
78
|
+
*/
|
|
79
|
+
speed?: number;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
The language for speech generation. This should be an ISO 639-1 language code (e.g. "en", "es", "fr")
|
|
83
|
+
or "auto" for automatic language detection. Provider support varies.
|
|
84
|
+
*/
|
|
85
|
+
language?: string;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
Additional provider-specific options that are passed through to the provider
|
|
89
|
+
as body parameters.
|
|
90
|
+
|
|
91
|
+
The outer record is keyed by the provider name, and the inner
|
|
92
|
+
record is keyed by the provider-specific metadata key.
|
|
93
|
+
```ts
|
|
94
|
+
{
|
|
95
|
+
"openai": {}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
*/
|
|
99
|
+
providerOptions?: ProviderOptions;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
Maximum number of retries per speech model call. Set to 0 to disable retries.
|
|
103
|
+
|
|
104
|
+
@default 2
|
|
105
|
+
*/
|
|
106
|
+
maxRetries?: number;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
Abort signal.
|
|
110
|
+
*/
|
|
111
|
+
abortSignal?: AbortSignal;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
Additional headers to include in the request.
|
|
115
|
+
Only applicable for HTTP-based providers.
|
|
116
|
+
*/
|
|
117
|
+
headers?: Record<string, string>;
|
|
118
|
+
}): Promise<SpeechResult> {
|
|
119
|
+
const resolvedModel = resolveSpeechModel(model);
|
|
120
|
+
if (!resolvedModel) {
|
|
121
|
+
throw new Error('Model could not be resolved');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const headersWithUserAgent = withUserAgentSuffix(
|
|
125
|
+
headers ?? {},
|
|
126
|
+
`ai/${VERSION}`,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const { retry } = prepareRetries({
|
|
130
|
+
maxRetries: maxRetriesArg,
|
|
131
|
+
abortSignal,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const result = await retry(() =>
|
|
135
|
+
resolvedModel.doGenerate({
|
|
136
|
+
text,
|
|
137
|
+
voice,
|
|
138
|
+
outputFormat,
|
|
139
|
+
instructions,
|
|
140
|
+
speed,
|
|
141
|
+
language,
|
|
142
|
+
abortSignal,
|
|
143
|
+
headers: headersWithUserAgent,
|
|
144
|
+
providerOptions,
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
if (!result.audio || result.audio.length === 0) {
|
|
149
|
+
throw new NoSpeechGeneratedError({ responses: [result.response] });
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
logWarnings({
|
|
153
|
+
warnings: result.warnings,
|
|
154
|
+
provider: resolvedModel.provider,
|
|
155
|
+
model: resolvedModel.modelId,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
return new DefaultSpeechResult({
|
|
159
|
+
audio: new DefaultGeneratedAudioFile({
|
|
160
|
+
data: result.audio,
|
|
161
|
+
mediaType:
|
|
162
|
+
detectMediaType({
|
|
163
|
+
data: result.audio,
|
|
164
|
+
signatures: audioMediaTypeSignatures,
|
|
165
|
+
}) ?? 'audio/mp3',
|
|
166
|
+
}),
|
|
167
|
+
warnings: result.warnings,
|
|
168
|
+
responses: [result.response],
|
|
169
|
+
providerMetadata: result.providerMetadata,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
class DefaultSpeechResult implements SpeechResult {
|
|
174
|
+
readonly audio: GeneratedAudioFile;
|
|
175
|
+
readonly warnings: Array<Warning>;
|
|
176
|
+
readonly responses: Array<SpeechModelResponseMetadata>;
|
|
177
|
+
readonly providerMetadata: Record<string, JSONObject>;
|
|
178
|
+
|
|
179
|
+
constructor(options: {
|
|
180
|
+
audio: GeneratedAudioFile;
|
|
181
|
+
warnings: Array<Warning>;
|
|
182
|
+
responses: Array<SpeechModelResponseMetadata>;
|
|
183
|
+
providerMetadata: Record<string, JSONObject> | undefined;
|
|
184
|
+
}) {
|
|
185
|
+
this.audio = options.audio;
|
|
186
|
+
this.warnings = options.warnings;
|
|
187
|
+
this.responses = options.responses;
|
|
188
|
+
this.providerMetadata = options.providerMetadata ?? {};
|
|
189
|
+
}
|
|
190
|
+
}
|