ai 7.0.124 → 7.0.127
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 +62 -24
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +101 -31
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +32 -12
- package/dist/internal/index.js.map +1 -1
- package/docs/03-ai-sdk-core/16-mcp-tools.mdx +25 -0
- package/docs/03-ai-sdk-core/19-tool-search.mdx +40 -4
- package/docs/03-ai-sdk-core/35-image-generation.mdx +5 -0
- package/docs/03-ai-sdk-core/36-transcription.mdx +42 -38
- package/docs/03-ai-sdk-core/37-speech.mdx +4 -0
- package/docs/04-ai-sdk-ui/02-chatbot.mdx +2 -1
- package/docs/07-reference/01-ai-sdk-core/17-create-agent-ui-stream.mdx +7 -0
- package/docs/07-reference/01-ai-sdk-core/18-create-agent-ui-stream-response.mdx +7 -0
- package/docs/07-reference/01-ai-sdk-core/18-pipe-agent-ui-stream-to-response.mdx +7 -0
- package/docs/07-reference/01-ai-sdk-core/23-tool-search.mdx +62 -6
- package/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx +13 -0
- package/docs/07-reference/04-ai-sdk-workflow/01-workflow-agent.mdx +60 -3
- package/package.json +4 -4
- package/src/agent/create-agent-ui-stream-response.ts +16 -4
- package/src/agent/create-agent-ui-stream.ts +16 -2
- package/src/agent/pipe-agent-ui-stream-to-response.ts +16 -4
- package/src/generate-text/validate-tool-approvals.ts +5 -1
- package/src/tool-search/prepare-tool-search.ts +49 -29
- package/src/tool-search/tool-search.ts +58 -4
- package/src/ui/chat.ts +36 -5
- package/src/ui-message-stream/create-ui-message-stream.ts +29 -4
package/dist/index.js
CHANGED
|
@@ -1102,7 +1102,7 @@ function cloneValue(value) {
|
|
|
1102
1102
|
}
|
|
1103
1103
|
//#endregion
|
|
1104
1104
|
//#region src/version.ts
|
|
1105
|
-
const VERSION = "7.0.
|
|
1105
|
+
const VERSION = "7.0.127";
|
|
1106
1106
|
//#endregion
|
|
1107
1107
|
//#region src/util/download/download.ts
|
|
1108
1108
|
/**
|
|
@@ -2949,14 +2949,21 @@ function appendToolCallerMessages({ messages, toolCallerMessages }) {
|
|
|
2949
2949
|
//#endregion
|
|
2950
2950
|
//#region src/tool-search/tool-search.ts
|
|
2951
2951
|
const toolSearchSymbol = Symbol.for("vercel.ai.toolSearch");
|
|
2952
|
+
const toolSearchFunctionSymbol = Symbol.for("vercel.ai.toolSearch.search");
|
|
2953
|
+
const toolSearchMaxResultsSymbol = Symbol.for("vercel.ai.toolSearch.maxResults");
|
|
2952
2954
|
/**
|
|
2953
2955
|
* Search deferred tools by name and description. The surrounding generation
|
|
2954
2956
|
* binds the search registry and makes matches available on the next step.
|
|
2955
2957
|
* Use directly or through code mode with `toolDiscovery: 'conversation'`.
|
|
2956
2958
|
*/
|
|
2957
|
-
function toolSearch() {
|
|
2959
|
+
function toolSearch({ search, maxResults = 5 } = {}) {
|
|
2960
|
+
if (!Number.isSafeInteger(maxResults) || maxResults < 1) throw new InvalidArgumentError({
|
|
2961
|
+
parameter: "maxResults",
|
|
2962
|
+
value: maxResults,
|
|
2963
|
+
message: "maxResults must be a positive safe integer."
|
|
2964
|
+
});
|
|
2958
2965
|
return Object.assign(tool$1({
|
|
2959
|
-
description: "Search for tools by keywords in their names and descriptions. Returns up to five matching tools. Matches become available on the next model step, after this execution finishes. Wait for their tool definitions before calling the discovered tools. If no tools match, try different keywords
|
|
2966
|
+
description: `${search == null ? "Search for tools by keywords in their names and descriptions." : "Search for tools matching a query."} Returns up to ${maxResults === 5 ? "five" : maxResults} matching tools. Matches become available on the next model step, after this execution finishes. Wait for their tool definitions before calling the discovered tools. If no tools match, try different keywords.`,
|
|
2960
2967
|
inputSchema: jsonSchema$1({
|
|
2961
2968
|
type: "object",
|
|
2962
2969
|
properties: { query: {
|
|
@@ -2988,9 +2995,17 @@ function toolSearch() {
|
|
|
2988
2995
|
}
|
|
2989
2996
|
}), {
|
|
2990
2997
|
type: "function",
|
|
2991
|
-
[toolSearchSymbol]: true
|
|
2998
|
+
[toolSearchSymbol]: true,
|
|
2999
|
+
[toolSearchFunctionSymbol]: search,
|
|
3000
|
+
[toolSearchMaxResultsSymbol]: maxResults
|
|
2992
3001
|
});
|
|
2993
3002
|
}
|
|
3003
|
+
function getToolSearchMaxResults(tool) {
|
|
3004
|
+
return tool[toolSearchMaxResultsSymbol] ?? 5;
|
|
3005
|
+
}
|
|
3006
|
+
function getToolSearchFunction(tool) {
|
|
3007
|
+
return tool[toolSearchFunctionSymbol];
|
|
3008
|
+
}
|
|
2994
3009
|
function isToolSearch(tool) {
|
|
2995
3010
|
return tool[toolSearchSymbol] === true;
|
|
2996
3011
|
}
|
|
@@ -3020,28 +3035,39 @@ function createToolSearchState({ tools, toolCallers }) {
|
|
|
3020
3035
|
const candidates = entries.filter(([name, candidate]) => candidate.deferLoading && !isToolSearch(candidate) && callers.some((caller) => getCallers(name).includes(caller)));
|
|
3021
3036
|
return [searchName, {
|
|
3022
3037
|
...tool,
|
|
3023
|
-
execute: ({ query }) => {
|
|
3024
|
-
const
|
|
3025
|
-
const matches = candidates.map(([name, candidate]) => {
|
|
3038
|
+
execute: async ({ query }) => {
|
|
3039
|
+
const availableTools = candidates.map(([name, candidate]) => {
|
|
3026
3040
|
const description = resolveToolDescription({
|
|
3027
3041
|
tool: candidate,
|
|
3028
3042
|
toolName: name,
|
|
3029
3043
|
toolsContext,
|
|
3030
3044
|
experimental_sandbox
|
|
3031
3045
|
});
|
|
3046
|
+
return {
|
|
3047
|
+
name,
|
|
3048
|
+
...description == null ? {} : { description }
|
|
3049
|
+
};
|
|
3050
|
+
});
|
|
3051
|
+
const toolsByName = new Map(availableTools.map((tool) => [tool.name, tool]));
|
|
3052
|
+
const customSearch = getToolSearchFunction(tool);
|
|
3053
|
+
const terms = [...new Set(tokenize(query))];
|
|
3054
|
+
const rankedNames = customSearch ? await customSearch({
|
|
3055
|
+
query,
|
|
3056
|
+
tools: availableTools.map((tool) => ({ ...tool }))
|
|
3057
|
+
}) : availableTools.map(({ name, description }) => {
|
|
3032
3058
|
const nameTerms = tokenize(name);
|
|
3033
3059
|
const descriptionTerms = tokenize(description ?? "");
|
|
3034
3060
|
return {
|
|
3035
3061
|
name,
|
|
3036
|
-
description,
|
|
3037
3062
|
score: terms.reduce((score, term) => score + (nameTerms.includes(term) ? 2 : 0) + (descriptionTerms.includes(term) ? 1 : 0), 0)
|
|
3038
3063
|
};
|
|
3039
|
-
}).filter((match) => match.score > 0).sort((a, b) => b.score - a.score).
|
|
3064
|
+
}).filter((match) => match.score > 0).sort((a, b) => b.score - a.score).map((match) => match.name);
|
|
3065
|
+
const matches = [...new Set(rankedNames)].flatMap((name) => {
|
|
3066
|
+
const match = toolsByName.get(name);
|
|
3067
|
+
return match == null ? [] : [match];
|
|
3068
|
+
}).slice(0, getToolSearchMaxResults(tool));
|
|
3040
3069
|
for (const { name } of matches) discovered.add(name);
|
|
3041
|
-
return { tools: matches
|
|
3042
|
-
name,
|
|
3043
|
-
...description == null ? {} : { description }
|
|
3044
|
-
})) };
|
|
3070
|
+
return { tools: matches };
|
|
3045
3071
|
}
|
|
3046
3072
|
}];
|
|
3047
3073
|
}));
|
|
@@ -4995,13 +5021,14 @@ async function validateApprovedToolApprovals({ approvedToolApprovals, tools, too
|
|
|
4995
5021
|
let validationError;
|
|
4996
5022
|
if (!validation.success) validationError = validation.error;
|
|
4997
5023
|
else try {
|
|
4998
|
-
|
|
5024
|
+
const revalidatedToolCall = await refineParsedToolCallInput({
|
|
4999
5025
|
toolCall: {
|
|
5000
5026
|
...toolCall,
|
|
5001
5027
|
input: validation.value
|
|
5002
5028
|
},
|
|
5003
5029
|
refineToolInput
|
|
5004
|
-
})
|
|
5030
|
+
});
|
|
5031
|
+
if (!isDeepEqualData(structuredClone(revalidatedToolCall.input), structuredClone(toolCall.input))) validationError = /* @__PURE__ */ new Error("Approved tool input does not match the validated schema output.");
|
|
5005
5032
|
} catch (error) {
|
|
5006
5033
|
validationError = error;
|
|
5007
5034
|
}
|
|
@@ -10331,10 +10358,20 @@ var ToolLoopAgent = class {
|
|
|
10331
10358
|
function createUIMessageStream({ execute, onError = () => "An error occurred.", originalMessages, onStepEnd, onStepFinish, onEnd, onFinish, generateId = generateId$1 }) {
|
|
10332
10359
|
let controller;
|
|
10333
10360
|
const ongoingStreamPromises = [];
|
|
10361
|
+
const activeReaders = /* @__PURE__ */ new Set();
|
|
10362
|
+
let isCancelled = false;
|
|
10363
|
+
let cancelReason;
|
|
10334
10364
|
let outcome = { status: "unknown" };
|
|
10335
|
-
const stream = new ReadableStream({
|
|
10336
|
-
|
|
10337
|
-
|
|
10365
|
+
const stream = new ReadableStream({
|
|
10366
|
+
start(controllerArg) {
|
|
10367
|
+
controller = controllerArg;
|
|
10368
|
+
},
|
|
10369
|
+
async cancel(reason) {
|
|
10370
|
+
isCancelled = true;
|
|
10371
|
+
cancelReason = reason;
|
|
10372
|
+
await Promise.all(Array.from(activeReaders, (reader) => reader.cancel(reason)));
|
|
10373
|
+
}
|
|
10374
|
+
});
|
|
10338
10375
|
function safeEnqueue(data) {
|
|
10339
10376
|
try {
|
|
10340
10377
|
controller.enqueue(data);
|
|
@@ -10375,12 +10412,22 @@ function createUIMessageStream({ execute, onError = () => "An error occurred.",
|
|
|
10375
10412
|
safeEnqueue(part);
|
|
10376
10413
|
},
|
|
10377
10414
|
merge(streamArg) {
|
|
10415
|
+
if (isCancelled) {
|
|
10416
|
+
streamArg.cancel(cancelReason).catch(() => {});
|
|
10417
|
+
return;
|
|
10418
|
+
}
|
|
10378
10419
|
ongoingStreamPromises.push((async () => {
|
|
10379
10420
|
const reader = streamArg.getReader();
|
|
10380
|
-
|
|
10381
|
-
|
|
10382
|
-
|
|
10383
|
-
|
|
10421
|
+
activeReaders.add(reader);
|
|
10422
|
+
try {
|
|
10423
|
+
while (true) {
|
|
10424
|
+
const { done, value } = await reader.read();
|
|
10425
|
+
if (done) break;
|
|
10426
|
+
safeEnqueue(value);
|
|
10427
|
+
}
|
|
10428
|
+
} finally {
|
|
10429
|
+
activeReaders.delete(reader);
|
|
10430
|
+
reader.releaseLock();
|
|
10384
10431
|
}
|
|
10385
10432
|
})().catch((error) => {
|
|
10386
10433
|
handleError(error);
|
|
@@ -11204,6 +11251,7 @@ async function validateUIMessagesForAgent(options) {
|
|
|
11204
11251
|
*
|
|
11205
11252
|
* @param agent - The agent to run.
|
|
11206
11253
|
* @param uiMessages - The input UI messages.
|
|
11254
|
+
* @param convertDataPart - Optional function to convert custom data parts to text or file model message parts.
|
|
11207
11255
|
* @param abortSignal - The abort signal. Optional.
|
|
11208
11256
|
* @param timeout - Timeout in milliseconds. Optional.
|
|
11209
11257
|
* @param experimental_sandbox - The sandbox environment that is passed through to tool execution. Optional.
|
|
@@ -11214,12 +11262,15 @@ async function validateUIMessagesForAgent(options) {
|
|
|
11214
11262
|
*
|
|
11215
11263
|
* @returns The UI message stream.
|
|
11216
11264
|
*/
|
|
11217
|
-
async function createAgentUIStream({ agent, uiMessages, options, abortSignal, timeout, experimental_sandbox: sandbox, experimental_transform, onStepEnd, onStepFinish, ...uiMessageStreamOptions }) {
|
|
11265
|
+
async function createAgentUIStream({ agent, uiMessages, convertDataPart, options, abortSignal, timeout, experimental_sandbox: sandbox, experimental_transform, onStepEnd, onStepFinish, ...uiMessageStreamOptions }) {
|
|
11218
11266
|
const validatedMessages = await validateUIMessagesForAgent({
|
|
11219
11267
|
messages: uiMessages,
|
|
11220
11268
|
tools: agent.tools
|
|
11221
11269
|
});
|
|
11222
|
-
const modelMessages = await convertToModelMessages(validatedMessages, {
|
|
11270
|
+
const modelMessages = await convertToModelMessages(validatedMessages, {
|
|
11271
|
+
tools: agent.tools,
|
|
11272
|
+
convertDataPart
|
|
11273
|
+
});
|
|
11223
11274
|
const result = await agent.stream({
|
|
11224
11275
|
prompt: modelMessages,
|
|
11225
11276
|
options,
|
|
@@ -11244,6 +11295,7 @@ async function createAgentUIStream({ agent, uiMessages, options, abortSignal, ti
|
|
|
11244
11295
|
*
|
|
11245
11296
|
* @param agent - The agent to run.
|
|
11246
11297
|
* @param uiMessages - The input UI messages.
|
|
11298
|
+
* @param convertDataPart - Optional function to convert custom data parts to text or file model message parts.
|
|
11247
11299
|
* @param abortSignal - Abort signal. Optional.
|
|
11248
11300
|
* @param timeout - Timeout in milliseconds. Optional.
|
|
11249
11301
|
* @param experimental_sandbox - The sandbox environment that is passed through to tool execution. Optional.
|
|
@@ -11277,6 +11329,7 @@ async function createAgentUIStreamResponse({ headers, status, statusText, keepAl
|
|
|
11277
11329
|
* @param response - The Node.js ServerResponse object to pipe to.
|
|
11278
11330
|
* @param agent - The agent to run.
|
|
11279
11331
|
* @param uiMessages - The input UI messages.
|
|
11332
|
+
* @param convertDataPart - Optional function to convert custom data parts to text or file model message parts.
|
|
11280
11333
|
* @param abortSignal - Abort signal. Optional.
|
|
11281
11334
|
* @param timeout - Timeout in milliseconds. Optional.
|
|
11282
11335
|
* @param experimental_sandbox - The sandbox environment that is passed through to tool execution. Optional.
|
|
@@ -19514,15 +19567,32 @@ var AbstractChat = class {
|
|
|
19514
19567
|
}
|
|
19515
19568
|
});
|
|
19516
19569
|
});
|
|
19517
|
-
this.addToolOutput = async ({ state
|
|
19570
|
+
this.addToolOutput = async ({ state, toolCallId, output, errorText, options }) => this.jobExecutor.run(async () => {
|
|
19518
19571
|
const messages = this.state.messages;
|
|
19519
19572
|
const lastMessage = messages[messages.length - 1];
|
|
19520
|
-
const updatePart = (part) =>
|
|
19521
|
-
|
|
19522
|
-
|
|
19523
|
-
|
|
19524
|
-
|
|
19525
|
-
|
|
19573
|
+
const updatePart = (part) => {
|
|
19574
|
+
if (!isToolUIPart(part) || part.toolCallId !== toolCallId) return part;
|
|
19575
|
+
const { approval: existingApproval, ...toolPart } = part;
|
|
19576
|
+
const approval = existingApproval?.approved === true ? { approval: {
|
|
19577
|
+
...existingApproval,
|
|
19578
|
+
approved: existingApproval.approved
|
|
19579
|
+
} } : {};
|
|
19580
|
+
return state === "output-error" ? {
|
|
19581
|
+
...toolPart,
|
|
19582
|
+
...approval,
|
|
19583
|
+
state,
|
|
19584
|
+
input: part.input,
|
|
19585
|
+
output: void 0,
|
|
19586
|
+
errorText
|
|
19587
|
+
} : {
|
|
19588
|
+
...toolPart,
|
|
19589
|
+
...approval,
|
|
19590
|
+
state: "output-available",
|
|
19591
|
+
input: part.input,
|
|
19592
|
+
output,
|
|
19593
|
+
errorText: void 0
|
|
19594
|
+
};
|
|
19595
|
+
};
|
|
19526
19596
|
this.state.replaceMessage(messages.length - 1, {
|
|
19527
19597
|
...lastMessage,
|
|
19528
19598
|
parts: lastMessage.parts.map(updatePart)
|