ai 7.0.148 → 7.0.150
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 +35 -0
- package/dist/index.d.ts +168 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +325 -35
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +2 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +4 -1
- package/dist/internal/index.js.map +1 -1
- package/dist/test/index.d.ts +17 -2
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +12 -1
- package/dist/test/index.js.map +1 -1
- package/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +7 -0
- package/docs/03-ai-sdk-core/18-code-mode.mdx +3 -1
- package/docs/03-ai-sdk-core/36-transcription.mdx +40 -39
- package/docs/03-ai-sdk-core/37-speech.mdx +66 -0
- package/docs/03-ai-sdk-core/60-telemetry.mdx +25 -2
- package/docs/03-ai-sdk-harnesses/05-harness-adapters.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +4 -4
- package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +7 -7
- package/docs/07-reference/01-ai-sdk-core/12-stream-speech.mdx +195 -0
- package/docs/07-reference/01-ai-sdk-core/index.mdx +5 -0
- package/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx +1 -1
- package/docs/07-reference/02-ai-sdk-ui/40-create-ui-message-stream.mdx +1 -1
- package/docs/07-reference/03-ai-sdk-rsc/01-stream-ui.mdx +1 -1
- package/docs/07-reference/05-ai-sdk-errors/ai-tool-choice-violation-error.mdx +12 -7
- package/package.json +12 -12
- package/src/error/no-speech-generated-error.ts +5 -1
- package/src/error/tool-choice-violation-error.ts +6 -4
- package/src/generate-speech/index.ts +7 -0
- package/src/generate-speech/is-streaming-speech-model.ts +17 -0
- package/src/generate-speech/stream-speech-result.ts +95 -0
- package/src/generate-speech/stream-speech.ts +569 -0
- package/src/generate-text/collect-tool-approvals.ts +10 -0
- package/src/generate-text/generate-text.ts +24 -12
- package/src/generate-text/stream-language-model-call.ts +37 -12
- package/src/generate-text/stream-text.ts +4 -1
- package/src/test/mock-streaming-speech-model-v4.ts +28 -0
- package/src/types/language-model.ts +2 -0
- package/src/ui/chat.ts +40 -12
- package/src/ui-message-stream/ui-message-chunks.ts +1 -0
|
@@ -1411,7 +1411,7 @@ retain the content their contracts require.
|
|
|
1411
1411
|
},
|
|
1412
1412
|
{
|
|
1413
1413
|
name: 'finishReason',
|
|
1414
|
-
type: '"stop" | "length" | "content-filter" | "tool-calls" | "error" | "other"',
|
|
1414
|
+
type: '"stop" | "length" | "content-filter" | "tool-calls" | "error" | "interrupted" | "other"',
|
|
1415
1415
|
description:
|
|
1416
1416
|
'The unified finish reason why the generation finished.',
|
|
1417
1417
|
},
|
|
@@ -1746,7 +1746,7 @@ retain the content their contracts require.
|
|
|
1746
1746
|
parameters: [
|
|
1747
1747
|
{
|
|
1748
1748
|
name: 'finishReason',
|
|
1749
|
-
type: '"stop" | "length" | "content-filter" | "tool-calls" | "error" | "other"',
|
|
1749
|
+
type: '"stop" | "length" | "content-filter" | "tool-calls" | "error" | "interrupted" | "other"',
|
|
1750
1750
|
description:
|
|
1751
1751
|
'The unified finish reason why the generation finished.',
|
|
1752
1752
|
},
|
|
@@ -2674,9 +2674,9 @@ retain the content their contracts require.
|
|
|
2674
2674
|
},
|
|
2675
2675
|
{
|
|
2676
2676
|
name: 'finishReason',
|
|
2677
|
-
type: "PromiseLike<'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'>",
|
|
2677
|
+
type: "PromiseLike<'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'interrupted' | 'other'>",
|
|
2678
2678
|
description:
|
|
2679
|
-
'The reason why the generation finished. Automatically consumes the stream.',
|
|
2679
|
+
'The reason why the generation finished. A stream that ends cleanly without its provider completion signal can report "interrupted". Partial output is preserved; interruption alone does not emit an error. Streams that produce no output and no finish chunk still reject with NoOutputGeneratedError. OpenAI-compatible retains its existing error behavior. Automatically consumes the stream.',
|
|
2680
2680
|
},
|
|
2681
2681
|
{
|
|
2682
2682
|
name: 'rawFinishReason',
|
|
@@ -3165,7 +3165,7 @@ retain the content their contracts require.
|
|
|
3165
3165
|
},
|
|
3166
3166
|
{
|
|
3167
3167
|
name: 'finishReason',
|
|
3168
|
-
type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'",
|
|
3168
|
+
type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'interrupted' | 'other'",
|
|
3169
3169
|
description: 'The reason the model finished generating the text.',
|
|
3170
3170
|
},
|
|
3171
3171
|
{
|
|
@@ -3873,7 +3873,7 @@ retain the content their contracts require.
|
|
|
3873
3873
|
},
|
|
3874
3874
|
{
|
|
3875
3875
|
name: 'finishReason',
|
|
3876
|
-
type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'",
|
|
3876
|
+
type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'interrupted' | 'other'",
|
|
3877
3877
|
description: 'The reason the model finished generating the text.',
|
|
3878
3878
|
},
|
|
3879
3879
|
{
|
|
@@ -3911,7 +3911,7 @@ retain the content their contracts require.
|
|
|
3911
3911
|
},
|
|
3912
3912
|
{
|
|
3913
3913
|
name: 'finishReason',
|
|
3914
|
-
type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'",
|
|
3914
|
+
type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'interrupted' | 'other'",
|
|
3915
3915
|
description: 'The reason the model finished generating the text.',
|
|
3916
3916
|
},
|
|
3917
3917
|
{
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: experimental_streamSpeech
|
|
3
|
+
description: API Reference for experimental_streamSpeech.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `experimental_streamSpeech()`
|
|
7
|
+
|
|
8
|
+
<Note type="warning">
|
|
9
|
+
`experimental_streamSpeech` is an experimental feature.
|
|
10
|
+
</Note>
|
|
11
|
+
|
|
12
|
+
Streams speech audio from text, or from an array or stream of text deltas and
|
|
13
|
+
text parts, using a speech model with streaming support.
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { experimental_streamSpeech as streamSpeech } from 'ai';
|
|
17
|
+
import { elevenLabs } from '@ai-sdk/elevenlabs';
|
|
18
|
+
|
|
19
|
+
const result = streamSpeech({
|
|
20
|
+
model: elevenLabs.speech('eleven_flash_v2_5'),
|
|
21
|
+
text: 'Hello, world!',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
for await (const chunk of result.audioStream) {
|
|
25
|
+
// Uint8Array audio bytes
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Import
|
|
30
|
+
|
|
31
|
+
<Snippet
|
|
32
|
+
text={`import { experimental_streamSpeech as streamSpeech } from "ai"`}
|
|
33
|
+
prompt={false}
|
|
34
|
+
/>
|
|
35
|
+
|
|
36
|
+
## API Signature
|
|
37
|
+
|
|
38
|
+
### Parameters
|
|
39
|
+
|
|
40
|
+
<PropertiesTable
|
|
41
|
+
content={[
|
|
42
|
+
{
|
|
43
|
+
name: 'model',
|
|
44
|
+
type: 'SpeechModel',
|
|
45
|
+
description:
|
|
46
|
+
'The speech model to use. The model must implement the experimental streaming speech extension (`Experimental_StreamingSpeechModelV4`).',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: 'text',
|
|
50
|
+
type: 'string | Iterable<string | Experimental_SpeechTextPart> | AsyncIterable<string | Experimental_SpeechTextPart> | ReadableStream<string | Experimental_SpeechTextPart>',
|
|
51
|
+
description:
|
|
52
|
+
"The text to convert to speech: a complete string, or an array, iterable, or stream of text deltas (e.g. the `textStream` of `streamText`) and/or text parts `{ type: 'text', text, voice?, providerOptions? }`. A part's `voice` selects its speaker on providers that support several voices per stream; single-voice providers error the stream when a part's voice differs from the call's voice. The end of the stream ends the input.",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'voice',
|
|
56
|
+
type: 'string',
|
|
57
|
+
isOptional: true,
|
|
58
|
+
description: 'The voice to use for speech generation.',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'outputFormat',
|
|
62
|
+
type: '{ type: string; rate?: number }',
|
|
63
|
+
isOptional: true,
|
|
64
|
+
description:
|
|
65
|
+
"The format of the output audio chunks, e.g. `{ type: 'audio/pcm', rate: 24000 }` or `{ type: 'audio/mpeg' }`. Supported formats are provider-specific.",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: 'instructions',
|
|
69
|
+
type: 'string',
|
|
70
|
+
isOptional: true,
|
|
71
|
+
description: 'Instructions for the speech generation.',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'speed',
|
|
75
|
+
type: 'number',
|
|
76
|
+
isOptional: true,
|
|
77
|
+
description: 'The speed of the speech generation.',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: 'language',
|
|
81
|
+
type: 'string',
|
|
82
|
+
isOptional: true,
|
|
83
|
+
description:
|
|
84
|
+
'The language for speech generation (ISO 639-1 code), or "auto". Provider support varies.',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'providerOptions',
|
|
88
|
+
type: 'Record<string, JSONObject>',
|
|
89
|
+
isOptional: true,
|
|
90
|
+
description: 'Additional provider-specific options.',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'abortSignal',
|
|
94
|
+
type: 'AbortSignal',
|
|
95
|
+
isOptional: true,
|
|
96
|
+
description: 'An optional abort signal to cancel the call.',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'headers',
|
|
100
|
+
type: 'Record<string, string>',
|
|
101
|
+
isOptional: true,
|
|
102
|
+
description:
|
|
103
|
+
'Additional HTTP/WebSocket headers, if supported by the provider.',
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'includeRawChunks',
|
|
107
|
+
type: 'boolean',
|
|
108
|
+
isOptional: true,
|
|
109
|
+
description:
|
|
110
|
+
'When true, the provider includes raw provider chunks in `fullStream` as `raw` parts.',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'onError',
|
|
114
|
+
type: '(event: { error: unknown }) => void | PromiseLike<void>',
|
|
115
|
+
isOptional: true,
|
|
116
|
+
description:
|
|
117
|
+
'Called for each `error` part the provider reports. Defaults to `console.error`.',
|
|
118
|
+
},
|
|
119
|
+
]}
|
|
120
|
+
/>
|
|
121
|
+
|
|
122
|
+
### Returns
|
|
123
|
+
|
|
124
|
+
<PropertiesTable
|
|
125
|
+
content={[
|
|
126
|
+
{
|
|
127
|
+
name: 'audioStream',
|
|
128
|
+
type: 'AsyncIterableStream<Uint8Array>',
|
|
129
|
+
description:
|
|
130
|
+
'Audio bytes in generation order. Shares one live stream with `fullStream`: only one of them can be accessed, once, before any result promise. `error` parts are skipped (they are reported via `onError`); the stream errors only when the speech stream itself fails.',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'fullStream',
|
|
134
|
+
type: 'AsyncIterableStream<Experimental_SpeechStreamPart>',
|
|
135
|
+
description:
|
|
136
|
+
'A single-consumer live stream of `audio` (with `audio: Uint8Array` and `audioFormat`), `raw`, and `error` parts. Error parts are not fatal; the stream continues after them.',
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: 'usage',
|
|
140
|
+
type: 'Promise<{ inputCharacters?: number; inputTokens?: number; outputTokens?: number; raw?: JSONObject }>',
|
|
141
|
+
description: 'Usage information for the call, if known.',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
name: 'warnings',
|
|
145
|
+
type: 'Promise<Warning[]>',
|
|
146
|
+
description:
|
|
147
|
+
'Warnings for the call, e.g. unsupported settings. Resolves when the provider emits the stream start.',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: 'responses',
|
|
151
|
+
type: 'Promise<Array<SpeechModelResponseMetadata>>',
|
|
152
|
+
description: 'Response metadata (timestamp, model ID, headers, body).',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
name: 'providerMetadata',
|
|
156
|
+
type: 'Promise<Record<string, JSONObject>>',
|
|
157
|
+
description: 'Additional provider-specific metadata.',
|
|
158
|
+
},
|
|
159
|
+
]}
|
|
160
|
+
/>
|
|
161
|
+
|
|
162
|
+
<Note>
|
|
163
|
+
The result promises settle as the stream is consumed. If you cancel the stream
|
|
164
|
+
early (for example by breaking out of a `for await` loop) or abort the call,
|
|
165
|
+
pending result promises reject immediately and the provider is signalled to
|
|
166
|
+
close its connection. A stream that is not read stalls under backpressure and
|
|
167
|
+
keeps the provider call open.
|
|
168
|
+
</Note>
|
|
169
|
+
|
|
170
|
+
## Errors
|
|
171
|
+
|
|
172
|
+
- `UnsupportedFunctionalityError` is thrown synchronously when the model does
|
|
173
|
+
not support streaming speech.
|
|
174
|
+
- `InvalidArgumentError` is thrown synchronously when `text` is not a string,
|
|
175
|
+
an iterable or async iterable, or a readable stream.
|
|
176
|
+
- Provider `error` parts are not fatal. They appear in `fullStream`, are
|
|
177
|
+
skipped by `audioStream`, and are passed to `onError`.
|
|
178
|
+
- If the stream ends without audio, the result rejects with
|
|
179
|
+
`NoSpeechGeneratedError`, whose `cause` is the last provider error part.
|
|
180
|
+
- If the stream stops after audio but before it finished, the result rejects
|
|
181
|
+
with the last provider error part, or with a `StreamProviderError`.
|
|
182
|
+
- If the provider call fails (for example an authentication error), the result
|
|
183
|
+
rejects with that error. Cancelling or aborting rejects with the
|
|
184
|
+
cancellation or abort reason.
|
|
185
|
+
|
|
186
|
+
## Wire format (experimental)
|
|
187
|
+
|
|
188
|
+
Streaming speech over WebSocket is serialized with the experimental
|
|
189
|
+
speech-stream envelope defined in `@ai-sdk/provider-utils`
|
|
190
|
+
(`experimental_parseSpeechStreamClientFrame`,
|
|
191
|
+
`experimental_serializeSpeechStreamPart`, `experimental_parseSpeechStreamPart`):
|
|
192
|
+
the client sends one `speech-stream.start` TEXT frame, input text as
|
|
193
|
+
`speech-stream.text-delta` TEXT frames (each carrying its text part's `voice`
|
|
194
|
+
and `providerOptions`), and a `speech-stream.text-done` TEXT frame; each server TEXT frame is one JSON-serialized speech stream part with
|
|
195
|
+
base64 audio. AI Gateway implements the server side of this envelope.
|
|
@@ -98,6 +98,11 @@ AI SDK Core contains the following main functions:
|
|
|
98
98
|
description: 'Generate speech audio from text.',
|
|
99
99
|
href: '/docs/reference/ai-sdk-core/generate-speech',
|
|
100
100
|
},
|
|
101
|
+
{
|
|
102
|
+
title: 'experimental_streamSpeech()',
|
|
103
|
+
description: 'Stream speech audio from text or a text stream.',
|
|
104
|
+
href: '/docs/reference/ai-sdk-core/stream-speech',
|
|
105
|
+
},
|
|
101
106
|
{
|
|
102
107
|
title: 'uploadFile()',
|
|
103
108
|
description: 'Upload a file to a provider and get a provider reference.',
|
|
@@ -317,7 +317,7 @@ Allows you to easily create a conversational user interface for your chatbot app
|
|
|
317
317
|
},
|
|
318
318
|
{
|
|
319
319
|
name: 'finishReason',
|
|
320
|
-
type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'",
|
|
320
|
+
type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'interrupted' | 'other'",
|
|
321
321
|
isOptional: true,
|
|
322
322
|
description:
|
|
323
323
|
'The reason why the model finished generating the response. Undefined if the finish reason was not provided by the model.',
|
|
@@ -179,7 +179,7 @@ outcomes and call `setOutcome` once.
|
|
|
179
179
|
name: 'finishReason',
|
|
180
180
|
type: 'FinishReason | undefined',
|
|
181
181
|
description:
|
|
182
|
-
"The reason why the generation finished. One of: 'stop', 'length', 'content-filter', 'tool-calls', 'error', or 'other'.",
|
|
182
|
+
"The reason why the generation finished. One of: 'stop', 'length', 'content-filter', 'tool-calls', 'error', 'interrupted', or 'other'.",
|
|
183
183
|
},
|
|
184
184
|
],
|
|
185
185
|
},
|
|
@@ -649,7 +649,7 @@ To see `streamUI` in action, check out [these examples](#examples).
|
|
|
649
649
|
},
|
|
650
650
|
{
|
|
651
651
|
name: 'finishReason',
|
|
652
|
-
type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'",
|
|
652
|
+
type: "'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'interrupted' | 'other'",
|
|
653
653
|
description: 'The reason the model finished generating the text.',
|
|
654
654
|
},
|
|
655
655
|
{
|
|
@@ -5,14 +5,16 @@ description: Learn how to fix AI SDK ToolChoiceViolationError
|
|
|
5
5
|
|
|
6
6
|
# ToolChoiceViolationError
|
|
7
7
|
|
|
8
|
-
This error occurs when a `generateText` response does not satisfy
|
|
9
|
-
tool choice. It is thrown when `toolChoice` is set to `'
|
|
10
|
-
response contains
|
|
11
|
-
was not called.
|
|
8
|
+
This error occurs when a `generateText` or `streamText` response does not satisfy
|
|
9
|
+
an enforced tool choice. It is thrown when `toolChoice` is set to `'none'` but
|
|
10
|
+
the response contains a tool call, when `'required'` produces no structured tool
|
|
11
|
+
call, or when a specifically selected tool was not called. With `streamText`,
|
|
12
|
+
the error is emitted in the stream. Tool calls returned while `'none'` is selected
|
|
13
|
+
are not executed.
|
|
12
14
|
|
|
13
15
|
The error does not automatically interpret text or reasoning as an executable
|
|
14
|
-
tool call.
|
|
15
|
-
schema validation before executing any recovered call.
|
|
16
|
+
tool call. When tool calls are allowed, you can inspect `content` to implement
|
|
17
|
+
opt-in recovery, including schema validation before executing any recovered call.
|
|
16
18
|
|
|
17
19
|
## Properties
|
|
18
20
|
|
|
@@ -30,7 +32,10 @@ You can check if an error is an instance of `ToolChoiceViolationError` using:
|
|
|
30
32
|
```typescript
|
|
31
33
|
import { ToolChoiceViolationError } from 'ai';
|
|
32
34
|
|
|
33
|
-
if (
|
|
35
|
+
if (
|
|
36
|
+
ToolChoiceViolationError.isInstance(error) &&
|
|
37
|
+
error.toolChoice.type !== 'none'
|
|
38
|
+
) {
|
|
34
39
|
const serializedCall = error.content.find(part => part.type === 'text')?.text;
|
|
35
40
|
|
|
36
41
|
// Parse and validate serializedCall before treating it as a tool call.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.150",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -42,20 +42,20 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@ai-sdk/gateway": "4.0.
|
|
46
|
-
"@ai-sdk/provider": "4.0.
|
|
47
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
45
|
+
"@ai-sdk/gateway": "4.0.123",
|
|
46
|
+
"@ai-sdk/provider": "4.0.33",
|
|
47
|
+
"@ai-sdk/provider-utils": "5.0.67"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@ai-sdk/amazon-bedrock": "5.0.
|
|
51
|
-
"@ai-sdk/deepseek": "3.0.
|
|
52
|
-
"@ai-sdk/google": "4.0.
|
|
53
|
-
"@ai-sdk/groq": "4.0.
|
|
54
|
-
"@ai-sdk/huggingface": "2.0.
|
|
55
|
-
"@ai-sdk/moonshotai": "3.0.
|
|
56
|
-
"@ai-sdk/openai": "4.0.
|
|
50
|
+
"@ai-sdk/amazon-bedrock": "5.0.123",
|
|
51
|
+
"@ai-sdk/deepseek": "3.0.72",
|
|
52
|
+
"@ai-sdk/google": "4.0.104",
|
|
53
|
+
"@ai-sdk/groq": "4.0.69",
|
|
54
|
+
"@ai-sdk/huggingface": "2.0.77",
|
|
55
|
+
"@ai-sdk/moonshotai": "3.0.76",
|
|
56
|
+
"@ai-sdk/openai": "4.0.101",
|
|
57
57
|
"@ai-sdk/test-server": "2.0.4",
|
|
58
|
-
"@ai-sdk/xai": "5.0.
|
|
58
|
+
"@ai-sdk/xai": "5.0.29",
|
|
59
59
|
"@edge-runtime/vm": "^5.0.0",
|
|
60
60
|
"@smithy/eventstream-codec": "^4.3.3",
|
|
61
61
|
"@smithy/util-utf8": "^4.3.3",
|
|
@@ -13,10 +13,14 @@ export class NoSpeechGeneratedError extends AISDKError {
|
|
|
13
13
|
|
|
14
14
|
readonly responses: Array<SpeechModelResponseMetadata>;
|
|
15
15
|
|
|
16
|
-
constructor(options: {
|
|
16
|
+
constructor(options: {
|
|
17
|
+
responses: Array<SpeechModelResponseMetadata>;
|
|
18
|
+
cause?: unknown;
|
|
19
|
+
}) {
|
|
17
20
|
super({
|
|
18
21
|
name,
|
|
19
22
|
message: 'No speech audio generated.',
|
|
23
|
+
...(options.cause !== undefined && { cause: options.cause }),
|
|
20
24
|
});
|
|
21
25
|
|
|
22
26
|
this.responses = options.responses;
|
|
@@ -11,7 +11,7 @@ const symbol = Symbol.for(marker);
|
|
|
11
11
|
|
|
12
12
|
type EnforcedToolChoice = Extract<
|
|
13
13
|
LanguageModelV4ToolChoice,
|
|
14
|
-
{ type: 'required' } | { type: 'tool' }
|
|
14
|
+
{ type: 'none' } | { type: 'required' } | { type: 'tool' }
|
|
15
15
|
>;
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -54,9 +54,11 @@ export class ToolChoiceViolationError extends AISDKError {
|
|
|
54
54
|
provider,
|
|
55
55
|
modelId,
|
|
56
56
|
content,
|
|
57
|
-
message = toolChoice.type === '
|
|
58
|
-
? 'Model response
|
|
59
|
-
:
|
|
57
|
+
message = toolChoice.type === 'none'
|
|
58
|
+
? 'Model response contained a tool call even though tool choice was none.'
|
|
59
|
+
: toolChoice.type === 'required'
|
|
60
|
+
? 'Model response did not contain a tool call even though tool choice was required.'
|
|
61
|
+
: `Model response did not contain a call to the required tool '${toolChoice.toolName}'.`,
|
|
60
62
|
}: {
|
|
61
63
|
toolChoice: EnforcedToolChoice;
|
|
62
64
|
finishReason: FinishReason;
|
|
@@ -3,6 +3,13 @@ import { generateSpeech } from './generate-speech';
|
|
|
3
3
|
import { logWarnings } from '../logger/log-warnings';
|
|
4
4
|
|
|
5
5
|
export { generateSpeech } from './generate-speech';
|
|
6
|
+
export { streamSpeech as experimental_streamSpeech } from './stream-speech';
|
|
7
|
+
export type {
|
|
8
|
+
SpeechStreamPart as Experimental_SpeechStreamPart,
|
|
9
|
+
SpeechStreamUsage as Experimental_SpeechStreamUsage,
|
|
10
|
+
SpeechTextPart as Experimental_SpeechTextPart,
|
|
11
|
+
StreamSpeechResult as Experimental_StreamSpeechResult,
|
|
12
|
+
} from './stream-speech-result';
|
|
6
13
|
export type { SpeechResult } from './generate-speech-result';
|
|
7
14
|
export type { GeneratedAudioFile } from './generated-audio-file';
|
|
8
15
|
export type {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Experimental_StreamingSpeechModelV4,
|
|
3
|
+
SpeechModelV4,
|
|
4
|
+
} from '@ai-sdk/provider';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Whether a resolved speech model implements the experimental streaming
|
|
8
|
+
* speech extension (`Experimental_StreamingSpeechModelV4`).
|
|
9
|
+
*/
|
|
10
|
+
export function isStreamingSpeechModel(
|
|
11
|
+
model: SpeechModelV4,
|
|
12
|
+
): model is Experimental_StreamingSpeechModelV4 {
|
|
13
|
+
return (
|
|
14
|
+
typeof (model as Partial<Experimental_StreamingSpeechModelV4>).doStream ===
|
|
15
|
+
'function'
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Experimental_SpeechModelV4StreamUsage,
|
|
3
|
+
JSONObject,
|
|
4
|
+
SharedV4AudioFormat,
|
|
5
|
+
SharedV4ProviderMetadata,
|
|
6
|
+
} from '@ai-sdk/provider';
|
|
7
|
+
import type { ProviderOptions } from '@ai-sdk/provider-utils';
|
|
8
|
+
import type { SpeechModelResponseMetadata } from '../types/speech-model-response-metadata';
|
|
9
|
+
import type { Warning } from '../types/warning';
|
|
10
|
+
import type { AsyncIterableStream } from '../util/async-iterable-stream';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A piece of text to synthesize. Pass a stream of these (or mix them with
|
|
14
|
+
* plain strings) to give parts their own voice, e.g. for dialogue.
|
|
15
|
+
*/
|
|
16
|
+
export type SpeechTextPart = {
|
|
17
|
+
type: 'text';
|
|
18
|
+
text: string;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The voice that speaks this part (provider-specific, like the call's
|
|
22
|
+
* `voice`). Single-voice providers reject a voice that differs from the
|
|
23
|
+
* call's voice.
|
|
24
|
+
*/
|
|
25
|
+
voice?: string;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Additional provider-specific options for this part.
|
|
29
|
+
*/
|
|
30
|
+
providerOptions?: ProviderOptions;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type SpeechStreamPart =
|
|
34
|
+
| {
|
|
35
|
+
/**
|
|
36
|
+
* Audio chunk in generation order. Chunks are not necessarily
|
|
37
|
+
* standalone files; concatenate them to reconstruct the audio. A chunk
|
|
38
|
+
* is empty only when it carries `providerMetadata` (e.g. a turn marker).
|
|
39
|
+
*/
|
|
40
|
+
type: 'audio';
|
|
41
|
+
id?: string;
|
|
42
|
+
audio: Uint8Array;
|
|
43
|
+
audioFormat: SharedV4AudioFormat;
|
|
44
|
+
providerMetadata?: SharedV4ProviderMetadata;
|
|
45
|
+
}
|
|
46
|
+
| {
|
|
47
|
+
type: 'raw';
|
|
48
|
+
rawValue: unknown;
|
|
49
|
+
}
|
|
50
|
+
| {
|
|
51
|
+
type: 'error';
|
|
52
|
+
error: unknown;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export type SpeechStreamUsage = Experimental_SpeechModelV4StreamUsage;
|
|
56
|
+
|
|
57
|
+
export interface StreamSpeechResult {
|
|
58
|
+
/**
|
|
59
|
+
* Usage information reported for the call, if available.
|
|
60
|
+
*/
|
|
61
|
+
readonly usage: PromiseLike<SpeechStreamUsage>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Warnings for the call, e.g. unsupported settings.
|
|
65
|
+
*/
|
|
66
|
+
readonly warnings: PromiseLike<Array<Warning>>;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Response metadata.
|
|
70
|
+
*/
|
|
71
|
+
readonly responses: PromiseLike<Array<SpeechModelResponseMetadata>>;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Additional provider-specific metadata.
|
|
75
|
+
*/
|
|
76
|
+
readonly providerMetadata: PromiseLike<Record<string, JSONObject>>;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Stream of audio bytes in generation order.
|
|
80
|
+
*
|
|
81
|
+
* `audioStream` and `fullStream` share one live stream: only one of them
|
|
82
|
+
* can be accessed, and only once. Access it before any result promise;
|
|
83
|
+
* accessing a result promise first consumes the stream internally.
|
|
84
|
+
*/
|
|
85
|
+
readonly audioStream: AsyncIterableStream<Uint8Array>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Full stream of speech parts (audio, raw, and error parts).
|
|
89
|
+
*
|
|
90
|
+
* `audioStream` and `fullStream` share one live stream: only one of them
|
|
91
|
+
* can be accessed, and only once. Access it before any result promise;
|
|
92
|
+
* accessing a result promise first consumes the stream internally.
|
|
93
|
+
*/
|
|
94
|
+
readonly fullStream: AsyncIterableStream<SpeechStreamPart>;
|
|
95
|
+
}
|