ai 7.0.3 → 7.0.5
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 +26 -11
- package/dist/index.js.map +1 -1
- package/dist/internal/index.js +1 -1
- package/docs/03-ai-sdk-core/16-mcp-tools.mdx +46 -0
- package/docs/07-reference/01-ai-sdk-core/23-create-mcp-client.mdx +42 -0
- package/package.json +3 -3
- package/src/generate-text/prune-messages.ts +45 -16
package/dist/internal/index.js
CHANGED
|
@@ -360,6 +360,52 @@ Resource templates are dynamic URI patterns that allow flexible queries. List al
|
|
|
360
360
|
const templates = await mcpClient.listResourceTemplates();
|
|
361
361
|
```
|
|
362
362
|
|
|
363
|
+
## Using MCP Completions
|
|
364
|
+
|
|
365
|
+
MCP servers can provide autocompletion suggestions for prompt arguments and
|
|
366
|
+
resource template variables when they advertise the `completions` capability.
|
|
367
|
+
Use `complete` to ask the server for suggestions based on the current partial
|
|
368
|
+
argument value:
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
const completion = await mcpClient.complete({
|
|
372
|
+
ref: {
|
|
373
|
+
type: 'ref/resource',
|
|
374
|
+
uri: 'file:///{path}',
|
|
375
|
+
},
|
|
376
|
+
argument: {
|
|
377
|
+
name: 'path',
|
|
378
|
+
value: 'doc',
|
|
379
|
+
},
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
console.log(completion.completion.values);
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
For resource templates or prompts with multiple arguments, pass already resolved
|
|
386
|
+
values through `context.arguments`:
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
const completion = await mcpClient.complete({
|
|
390
|
+
ref: {
|
|
391
|
+
type: 'ref/resource',
|
|
392
|
+
uri: 'kubernetes://namespaced/{plural}/{namespace}',
|
|
393
|
+
},
|
|
394
|
+
argument: {
|
|
395
|
+
name: 'namespace',
|
|
396
|
+
value: 'auth',
|
|
397
|
+
},
|
|
398
|
+
context: {
|
|
399
|
+
arguments: {
|
|
400
|
+
plural: 'deployments',
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
});
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
If the connected server does not advertise `capabilities.completions`, the
|
|
407
|
+
client throws an `MCPClientError`.
|
|
408
|
+
|
|
363
409
|
## Using MCP Prompts
|
|
364
410
|
|
|
365
411
|
<Note type="warning">
|
|
@@ -10,6 +10,7 @@ Creates a lightweight Model Context Protocol (MCP) client that connects to an MC
|
|
|
10
10
|
- **Tools**: Automatic conversion between MCP tools and AI SDK tools
|
|
11
11
|
- **Resources**: Methods to list, read, and discover resource templates from MCP servers
|
|
12
12
|
- **Prompts**: Methods to list available prompts and retrieve prompt messages
|
|
13
|
+
- **Completions**: Methods to request autocompletion suggestions for prompt arguments and resource template variables
|
|
13
14
|
- **Elicitation**: Support for handling server requests for additional input during tool execution
|
|
14
15
|
|
|
15
16
|
It currently does not support accepting notifications from an MCP server, and custom configuration of the client.
|
|
@@ -440,6 +441,47 @@ Returns a Promise that resolves to an `MCPClient` with the following properties
|
|
|
440
441
|
},
|
|
441
442
|
],
|
|
442
443
|
},
|
|
444
|
+
{
|
|
445
|
+
name: 'complete',
|
|
446
|
+
type: `async (args: CompleteRequestParams & {
|
|
447
|
+
options?: RequestOptions;
|
|
448
|
+
}) => Promise<CompleteResult>`,
|
|
449
|
+
description:
|
|
450
|
+
'Requests autocompletion suggestions for a prompt argument or resource template variable. The server must advertise the completions capability.',
|
|
451
|
+
properties: [
|
|
452
|
+
{
|
|
453
|
+
type: 'args',
|
|
454
|
+
parameters: [
|
|
455
|
+
{
|
|
456
|
+
name: 'ref',
|
|
457
|
+
type: "{ type: 'ref/prompt'; name: string } | { type: 'ref/resource'; uri: string }",
|
|
458
|
+
description:
|
|
459
|
+
'Reference to the prompt or resource template being completed.',
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
name: 'argument',
|
|
463
|
+
type: '{ name: string; value: string }',
|
|
464
|
+
description:
|
|
465
|
+
'Argument name and current partial value to complete.',
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
name: 'context',
|
|
469
|
+
type: '{ arguments: Record<string, string> }',
|
|
470
|
+
isOptional: true,
|
|
471
|
+
description:
|
|
472
|
+
'Previously resolved argument values used to provide context for multi-argument prompts or resource templates.',
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
name: 'options',
|
|
476
|
+
type: 'RequestOptions',
|
|
477
|
+
isOptional: true,
|
|
478
|
+
description:
|
|
479
|
+
'Optional request options including signal and timeout.',
|
|
480
|
+
},
|
|
481
|
+
],
|
|
482
|
+
},
|
|
483
|
+
],
|
|
484
|
+
},
|
|
443
485
|
{
|
|
444
486
|
name: 'experimental_listPrompts',
|
|
445
487
|
type: `async (options?: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.5",
|
|
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,9 +42,9 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@ai-sdk/gateway": "4.0.
|
|
45
|
+
"@ai-sdk/gateway": "4.0.4",
|
|
46
46
|
"@ai-sdk/provider": "4.0.0",
|
|
47
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
47
|
+
"@ai-sdk/provider-utils": "5.0.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@edge-runtime/vm": "^5.0.0",
|
|
@@ -100,6 +100,44 @@ export function pruneMessages({
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
// Build global maps from tool call id and approval id to tool name.
|
|
104
|
+
// These must be global (not per-message) because a `tool-approval-response`
|
|
105
|
+
// lives in a separate `tool` message from its `tool-approval-request`
|
|
106
|
+
// (assistant message), so the tool name of a response can only be resolved
|
|
107
|
+
// by looking across messages. Resolving names per-message left responses
|
|
108
|
+
// unresolved, which caused them to be kept while their request was pruned,
|
|
109
|
+
// producing orphaned approval responses.
|
|
110
|
+
const toolCallIdToToolName = new Map<string, string>();
|
|
111
|
+
for (const message of messages) {
|
|
112
|
+
if (
|
|
113
|
+
(message.role === 'assistant' || message.role === 'tool') &&
|
|
114
|
+
typeof message.content !== 'string'
|
|
115
|
+
) {
|
|
116
|
+
for (const part of message.content) {
|
|
117
|
+
if (part.type === 'tool-call' || part.type === 'tool-result') {
|
|
118
|
+
toolCallIdToToolName.set(part.toolCallId, part.toolName);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const approvalIdToToolName = new Map<string, string>();
|
|
125
|
+
for (const message of messages) {
|
|
126
|
+
if (
|
|
127
|
+
(message.role === 'assistant' || message.role === 'tool') &&
|
|
128
|
+
typeof message.content !== 'string'
|
|
129
|
+
) {
|
|
130
|
+
for (const part of message.content) {
|
|
131
|
+
if (part.type === 'tool-approval-request') {
|
|
132
|
+
const toolName = toolCallIdToToolName.get(part.toolCallId);
|
|
133
|
+
if (toolName != null) {
|
|
134
|
+
approvalIdToToolName.set(part.approvalId, toolName);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
103
141
|
messages = messages.map((message, messageIndex) => {
|
|
104
142
|
if (
|
|
105
143
|
(message.role !== 'assistant' && message.role !== 'tool') ||
|
|
@@ -110,9 +148,6 @@ export function pruneMessages({
|
|
|
110
148
|
return message;
|
|
111
149
|
}
|
|
112
150
|
|
|
113
|
-
const toolCallIdToToolName: Record<string, string> = {};
|
|
114
|
-
const approvalIdToToolName: Record<string, string> = {};
|
|
115
|
-
|
|
116
151
|
return {
|
|
117
152
|
...message,
|
|
118
153
|
content: message.content.filter(part => {
|
|
@@ -126,14 +161,6 @@ export function pruneMessages({
|
|
|
126
161
|
return true;
|
|
127
162
|
}
|
|
128
163
|
|
|
129
|
-
// track tool calls and approvals:
|
|
130
|
-
if (part.type === 'tool-call') {
|
|
131
|
-
toolCallIdToToolName[part.toolCallId] = part.toolName;
|
|
132
|
-
} else if (part.type === 'tool-approval-request') {
|
|
133
|
-
approvalIdToToolName[part.approvalId] =
|
|
134
|
-
toolCallIdToToolName[part.toolCallId];
|
|
135
|
-
}
|
|
136
|
-
|
|
137
164
|
// keep parts that are associated with a tool call or approval that needs to be kept:
|
|
138
165
|
if (
|
|
139
166
|
((part.type === 'tool-call' || part.type === 'tool-result') &&
|
|
@@ -146,13 +173,15 @@ export function pruneMessages({
|
|
|
146
173
|
}
|
|
147
174
|
|
|
148
175
|
// keep parts that are not associated with a tool that should be removed:
|
|
176
|
+
const partToolName =
|
|
177
|
+
part.type === 'tool-call' || part.type === 'tool-result'
|
|
178
|
+
? part.toolName
|
|
179
|
+
: approvalIdToToolName.get(part.approvalId);
|
|
180
|
+
|
|
149
181
|
return (
|
|
150
182
|
toolCall.tools != null &&
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
? part.toolName
|
|
154
|
-
: approvalIdToToolName[part.approvalId],
|
|
155
|
-
)
|
|
183
|
+
partToolName != null &&
|
|
184
|
+
!toolCall.tools.includes(partToolName)
|
|
156
185
|
);
|
|
157
186
|
}),
|
|
158
187
|
} as AssistantModelMessage | ToolModelMessage;
|