ai 7.0.107 → 7.0.109
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 +23 -0
- package/dist/index.d.ts +14 -7
- package/dist/index.js +242 -59
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +38 -3
- package/dist/internal/index.js +201 -39
- package/dist/internal/index.js.map +1 -1
- package/docs/00-introduction/index.mdx +1 -1
- package/docs/02-getting-started/03-nextjs-pages-router.mdx +1 -1
- package/docs/02-getting-started/05-nuxt.mdx +1 -1
- package/docs/03-ai-sdk-core/16-mcp-tools.mdx +31 -0
- package/docs/03-ai-sdk-harnesses/02-harness-agent.mdx +7 -0
- package/docs/03-ai-sdk-harnesses/03-tools.mdx +46 -0
- package/docs/04-ai-sdk-ui/02-chatbot.mdx +26 -11
- package/docs/04-ai-sdk-ui/05-completion.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +7 -0
- package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +7 -0
- package/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx +1 -1
- package/package.json +6 -6
- package/src/generate-text/generate-text.ts +2 -1
- package/src/generate-text/parse-tool-call.ts +64 -12
- package/src/generate-text/stream-language-model-call.ts +32 -21
- package/src/generate-text/tool-call-repair-function.ts +2 -0
- package/src/generate-text/tools-context-parameter.ts +13 -7
- package/src/middleware/extract-reasoning-middleware.ts +29 -14
- package/src/model/as-language-model-v4.ts +166 -6
- package/src/ui/call-completion-api.ts +20 -7
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
LanguageModelV2,
|
|
3
|
-
LanguageModelV3,
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
type LanguageModelV2,
|
|
3
|
+
type LanguageModelV3,
|
|
4
|
+
type LanguageModelV3Content,
|
|
5
|
+
type LanguageModelV3DataContent,
|
|
6
|
+
type LanguageModelV3Prompt,
|
|
7
|
+
type LanguageModelV3StreamPart,
|
|
8
|
+
type LanguageModelV3ToolResultOutput,
|
|
9
|
+
type LanguageModelV4,
|
|
10
|
+
type LanguageModelV4CallOptions,
|
|
11
|
+
type LanguageModelV4Content,
|
|
12
|
+
type LanguageModelV4Prompt,
|
|
13
|
+
type LanguageModelV4StreamPart,
|
|
14
|
+
type LanguageModelV4ToolResultOutput,
|
|
15
|
+
type SharedV4FileData,
|
|
5
16
|
} from '@ai-sdk/provider';
|
|
17
|
+
import { convertUint8ArrayToBase64 } from '@ai-sdk/provider-utils';
|
|
6
18
|
import { asLanguageModelV3 } from './as-language-model-v3';
|
|
7
19
|
|
|
8
20
|
export function asLanguageModelV4(
|
|
@@ -18,8 +30,156 @@ export function asLanguageModelV4(
|
|
|
18
30
|
|
|
19
31
|
return new Proxy(v3Model, {
|
|
20
32
|
get(target, prop: keyof LanguageModelV3) {
|
|
21
|
-
|
|
22
|
-
|
|
33
|
+
switch (prop) {
|
|
34
|
+
case 'specificationVersion':
|
|
35
|
+
return 'v4';
|
|
36
|
+
case 'doGenerate':
|
|
37
|
+
return async (options: LanguageModelV4CallOptions) => {
|
|
38
|
+
const result = await target.doGenerate({
|
|
39
|
+
...options,
|
|
40
|
+
prompt: convertV4PromptToV3(options.prompt),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
...result,
|
|
45
|
+
content: result.content.map(convertV3ContentToV4),
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
case 'doStream':
|
|
49
|
+
return async (options: LanguageModelV4CallOptions) => {
|
|
50
|
+
const result = await target.doStream({
|
|
51
|
+
...options,
|
|
52
|
+
prompt: convertV4PromptToV3(options.prompt),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
...result,
|
|
57
|
+
stream: convertV3StreamToV4(result.stream),
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
default:
|
|
61
|
+
return target[prop];
|
|
62
|
+
}
|
|
23
63
|
},
|
|
24
64
|
}) as unknown as LanguageModelV4;
|
|
25
65
|
}
|
|
66
|
+
|
|
67
|
+
function convertV4PromptToV3(
|
|
68
|
+
prompt: LanguageModelV4Prompt,
|
|
69
|
+
): LanguageModelV3Prompt {
|
|
70
|
+
return prompt.map(message => {
|
|
71
|
+
if (message.role === 'system') {
|
|
72
|
+
return message;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
...message,
|
|
77
|
+
content: message.content.map(part => {
|
|
78
|
+
switch (part.type) {
|
|
79
|
+
case 'file':
|
|
80
|
+
return {
|
|
81
|
+
...part,
|
|
82
|
+
data: convertV4FileDataToV3(part.data),
|
|
83
|
+
};
|
|
84
|
+
case 'tool-result':
|
|
85
|
+
return {
|
|
86
|
+
...part,
|
|
87
|
+
output: convertV4ToolResultOutputToV3(part.output),
|
|
88
|
+
};
|
|
89
|
+
default:
|
|
90
|
+
return part;
|
|
91
|
+
}
|
|
92
|
+
}),
|
|
93
|
+
};
|
|
94
|
+
}) as LanguageModelV3Prompt;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function convertV4FileDataToV3(
|
|
98
|
+
data: SharedV4FileData,
|
|
99
|
+
): LanguageModelV3DataContent {
|
|
100
|
+
switch (data.type) {
|
|
101
|
+
case 'data':
|
|
102
|
+
return data.data;
|
|
103
|
+
case 'url':
|
|
104
|
+
return data.url;
|
|
105
|
+
case 'reference':
|
|
106
|
+
case 'text':
|
|
107
|
+
// pass through unsupported types as is
|
|
108
|
+
return data as unknown as LanguageModelV3DataContent;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function convertV4ToolResultOutputToV3(
|
|
113
|
+
output: LanguageModelV4ToolResultOutput,
|
|
114
|
+
): LanguageModelV3ToolResultOutput {
|
|
115
|
+
if (output.type !== 'content') {
|
|
116
|
+
return output;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
...output,
|
|
121
|
+
value: output.value.map(part => {
|
|
122
|
+
if (part.type !== 'file') {
|
|
123
|
+
return part;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
switch (part.data.type) {
|
|
127
|
+
case 'data':
|
|
128
|
+
return {
|
|
129
|
+
type: 'file-data' as const,
|
|
130
|
+
data:
|
|
131
|
+
typeof part.data.data === 'string'
|
|
132
|
+
? part.data.data
|
|
133
|
+
: convertUint8ArrayToBase64(part.data.data),
|
|
134
|
+
mediaType: part.mediaType,
|
|
135
|
+
filename: part.filename,
|
|
136
|
+
providerOptions: part.providerOptions,
|
|
137
|
+
};
|
|
138
|
+
case 'url':
|
|
139
|
+
return {
|
|
140
|
+
type: 'file-url' as const,
|
|
141
|
+
url: part.data.url.toString(),
|
|
142
|
+
providerOptions: part.providerOptions,
|
|
143
|
+
};
|
|
144
|
+
case 'reference':
|
|
145
|
+
return {
|
|
146
|
+
type: 'file-id' as const,
|
|
147
|
+
fileId: part.data.reference,
|
|
148
|
+
providerOptions: part.providerOptions,
|
|
149
|
+
};
|
|
150
|
+
case 'text':
|
|
151
|
+
return part;
|
|
152
|
+
}
|
|
153
|
+
}),
|
|
154
|
+
} as LanguageModelV3ToolResultOutput;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function convertV3ContentToV4(
|
|
158
|
+
content: LanguageModelV3Content,
|
|
159
|
+
): LanguageModelV4Content {
|
|
160
|
+
return content.type === 'file'
|
|
161
|
+
? {
|
|
162
|
+
...content,
|
|
163
|
+
data: { type: 'data', data: content.data },
|
|
164
|
+
}
|
|
165
|
+
: content;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function convertV3StreamToV4(
|
|
169
|
+
stream: ReadableStream<LanguageModelV3StreamPart>,
|
|
170
|
+
): ReadableStream<LanguageModelV4StreamPart> {
|
|
171
|
+
return stream.pipeThrough(
|
|
172
|
+
new TransformStream<LanguageModelV3StreamPart, LanguageModelV4StreamPart>({
|
|
173
|
+
transform(chunk, controller) {
|
|
174
|
+
controller.enqueue(
|
|
175
|
+
chunk.type === 'file'
|
|
176
|
+
? {
|
|
177
|
+
...chunk,
|
|
178
|
+
data: { type: 'data', data: chunk.data },
|
|
179
|
+
}
|
|
180
|
+
: chunk,
|
|
181
|
+
);
|
|
182
|
+
},
|
|
183
|
+
}),
|
|
184
|
+
);
|
|
185
|
+
}
|
|
@@ -30,6 +30,7 @@ export async function callCompletionApi({
|
|
|
30
30
|
setLoading,
|
|
31
31
|
setError,
|
|
32
32
|
setAbortController,
|
|
33
|
+
getAbortController,
|
|
33
34
|
onFinish,
|
|
34
35
|
onError,
|
|
35
36
|
fetch = getOriginalFetch(),
|
|
@@ -44,15 +45,19 @@ export async function callCompletionApi({
|
|
|
44
45
|
setLoading: (loading: boolean) => void;
|
|
45
46
|
setError: (error: Error | undefined) => void;
|
|
46
47
|
setAbortController: (abortController: AbortController | null) => void;
|
|
48
|
+
getAbortController?: () => AbortController | null | undefined;
|
|
47
49
|
onFinish: ((prompt: string, completion: string) => void) | undefined;
|
|
48
50
|
onError: ((error: Error) => void) | undefined;
|
|
49
51
|
fetch: ReturnType<typeof getOriginalFetch> | undefined;
|
|
50
52
|
}) {
|
|
53
|
+
const abortController = new AbortController();
|
|
54
|
+
const isCurrentRequest = () =>
|
|
55
|
+
getAbortController == null || getAbortController() === abortController;
|
|
56
|
+
|
|
51
57
|
try {
|
|
52
58
|
setLoading(true);
|
|
53
59
|
setError(undefined);
|
|
54
60
|
|
|
55
|
-
const abortController = new AbortController();
|
|
56
61
|
setAbortController(abortController);
|
|
57
62
|
|
|
58
63
|
// Empty the completion immediately.
|
|
@@ -100,7 +105,9 @@ export async function callCompletionApi({
|
|
|
100
105
|
stream: response.body,
|
|
101
106
|
onTextPart: chunk => {
|
|
102
107
|
result += chunk;
|
|
103
|
-
|
|
108
|
+
if (isCurrentRequest()) {
|
|
109
|
+
setCompletion(result);
|
|
110
|
+
}
|
|
104
111
|
},
|
|
105
112
|
});
|
|
106
113
|
break;
|
|
@@ -120,7 +127,9 @@ export async function callCompletionApi({
|
|
|
120
127
|
const streamPart = part.value;
|
|
121
128
|
if (streamPart.type === 'text-delta') {
|
|
122
129
|
result += streamPart.delta;
|
|
123
|
-
|
|
130
|
+
if (isCurrentRequest()) {
|
|
131
|
+
setCompletion(result);
|
|
132
|
+
}
|
|
124
133
|
} else if (streamPart.type === 'error') {
|
|
125
134
|
throw new UIMessageStreamError({
|
|
126
135
|
chunkType: 'error',
|
|
@@ -151,12 +160,10 @@ export async function callCompletionApi({
|
|
|
151
160
|
onFinish(prompt, result);
|
|
152
161
|
}
|
|
153
162
|
|
|
154
|
-
setAbortController(null);
|
|
155
163
|
return result;
|
|
156
164
|
} catch (err) {
|
|
157
165
|
// Ignore abort errors as they are expected.
|
|
158
166
|
if ((err as any).name === 'AbortError') {
|
|
159
|
-
setAbortController(null);
|
|
160
167
|
return null;
|
|
161
168
|
}
|
|
162
169
|
|
|
@@ -166,8 +173,14 @@ export async function callCompletionApi({
|
|
|
166
173
|
}
|
|
167
174
|
}
|
|
168
175
|
|
|
169
|
-
|
|
176
|
+
if (isCurrentRequest()) {
|
|
177
|
+
setError(err as Error);
|
|
178
|
+
}
|
|
170
179
|
} finally {
|
|
171
|
-
|
|
180
|
+
// A newer request may have started while this one was settling.
|
|
181
|
+
if (isCurrentRequest()) {
|
|
182
|
+
setAbortController(null);
|
|
183
|
+
setLoading(false);
|
|
184
|
+
}
|
|
172
185
|
}
|
|
173
186
|
}
|