@ai-sdk/provider-utils 5.0.0-beta.26 → 5.0.0-beta.28
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 +19 -0
- package/dist/index.d.ts +103 -18
- package/dist/index.js +52 -24
- package/dist/index.js.map +1 -1
- package/dist/test/index.d.ts +2 -1
- package/dist/test/index.js +15 -1
- package/dist/test/index.js.map +1 -1
- package/package.json +7 -5
- package/src/index.ts +9 -5
- package/src/maybe-promise-like.ts +3 -0
- package/src/{provider-tool-factory.ts → provider-defined-tool-factory.ts} +12 -20
- package/src/provider-executed-tool-factory.ts +70 -0
- package/src/streaming-tool-call-tracker.ts +34 -36
- package/src/test/is-node-version.ts +22 -1
- package/src/types/index.ts +1 -0
- package/src/types/sensitive-context.ts +9 -0
- package/src/types/tool-approval-request.ts +7 -0
- package/src/types/tool.ts +58 -3
package/dist/test/index.d.ts
CHANGED
|
@@ -9,9 +9,10 @@ declare function convertReadableStreamToArray<T>(stream: ReadableStream<T>): Pro
|
|
|
9
9
|
declare function convertResponseStreamToArray(response: Response): Promise<string[]>;
|
|
10
10
|
|
|
11
11
|
declare function isNodeVersion(version: number): boolean;
|
|
12
|
+
declare function isNodeVersionAtLeast(major: number, minor?: number, patch?: number): boolean;
|
|
12
13
|
|
|
13
14
|
declare function mockId({ prefix, }?: {
|
|
14
15
|
prefix?: string;
|
|
15
16
|
}): () => string;
|
|
16
17
|
|
|
17
|
-
export { convertArrayToAsyncIterable, convertArrayToReadableStream, convertAsyncIterableToArray, convertReadableStreamToArray, convertResponseStreamToArray, isNodeVersion, mockId };
|
|
18
|
+
export { convertArrayToAsyncIterable, convertArrayToReadableStream, convertAsyncIterableToArray, convertReadableStreamToArray, convertResponseStreamToArray, isNodeVersion, isNodeVersionAtLeast, mockId };
|
package/dist/test/index.js
CHANGED
|
@@ -53,10 +53,23 @@ async function convertResponseStreamToArray(response) {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
// src/test/is-node-version.ts
|
|
56
|
+
function getNodeVersionParts() {
|
|
57
|
+
return process.versions.node.split(".").map((version) => Number.parseInt(version, 10));
|
|
58
|
+
}
|
|
56
59
|
function isNodeVersion(version) {
|
|
57
|
-
const nodeMajorVersion =
|
|
60
|
+
const [nodeMajorVersion] = getNodeVersionParts();
|
|
58
61
|
return nodeMajorVersion === version;
|
|
59
62
|
}
|
|
63
|
+
function isNodeVersionAtLeast(major, minor = 0, patch = 0) {
|
|
64
|
+
const [nodeMajorVersion, nodeMinorVersion, nodePatchVersion] = getNodeVersionParts();
|
|
65
|
+
if (nodeMajorVersion !== major) {
|
|
66
|
+
return nodeMajorVersion > major;
|
|
67
|
+
}
|
|
68
|
+
if (nodeMinorVersion !== minor) {
|
|
69
|
+
return nodeMinorVersion > minor;
|
|
70
|
+
}
|
|
71
|
+
return nodePatchVersion >= patch;
|
|
72
|
+
}
|
|
60
73
|
|
|
61
74
|
// src/test/mock-id.ts
|
|
62
75
|
function mockId({
|
|
@@ -72,6 +85,7 @@ export {
|
|
|
72
85
|
convertReadableStreamToArray,
|
|
73
86
|
convertResponseStreamToArray,
|
|
74
87
|
isNodeVersion,
|
|
88
|
+
isNodeVersionAtLeast,
|
|
75
89
|
mockId
|
|
76
90
|
};
|
|
77
91
|
//# sourceMappingURL=index.js.map
|
package/dist/test/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/test/convert-array-to-async-iterable.ts","../../src/test/convert-array-to-readable-stream.ts","../../src/test/convert-async-iterable-to-array.ts","../../src/test/convert-readable-stream-to-array.ts","../../src/test/convert-response-stream-to-array.ts","../../src/test/is-node-version.ts","../../src/test/mock-id.ts"],"sourcesContent":["export function convertArrayToAsyncIterable<T>(values: T[]): AsyncIterable<T> {\n return {\n async *[Symbol.asyncIterator]() {\n for (const value of values) {\n yield value;\n }\n },\n };\n}\n","export function convertArrayToReadableStream<T>(\n values: T[],\n): ReadableStream<T> {\n return new ReadableStream({\n start(controller) {\n try {\n for (const value of values) {\n controller.enqueue(value);\n }\n } finally {\n controller.close();\n }\n },\n });\n}\n","export async function convertAsyncIterableToArray<T>(\n iterable: AsyncIterable<T>,\n): Promise<T[]> {\n const result: T[] = [];\n for await (const item of iterable) {\n result.push(item);\n }\n return result;\n}\n","export async function convertReadableStreamToArray<T>(\n stream: ReadableStream<T>,\n): Promise<T[]> {\n const reader = stream.getReader();\n const result: T[] = [];\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n result.push(value);\n }\n\n return result;\n}\n","import { convertReadableStreamToArray } from './convert-readable-stream-to-array';\n\nexport async function convertResponseStreamToArray(\n response: Response,\n): Promise<string[]> {\n return await convertReadableStreamToArray(\n response.body!.pipeThrough(new TextDecoderStream()),\n );\n}\n","
|
|
1
|
+
{"version":3,"sources":["../../src/test/convert-array-to-async-iterable.ts","../../src/test/convert-array-to-readable-stream.ts","../../src/test/convert-async-iterable-to-array.ts","../../src/test/convert-readable-stream-to-array.ts","../../src/test/convert-response-stream-to-array.ts","../../src/test/is-node-version.ts","../../src/test/mock-id.ts"],"sourcesContent":["export function convertArrayToAsyncIterable<T>(values: T[]): AsyncIterable<T> {\n return {\n async *[Symbol.asyncIterator]() {\n for (const value of values) {\n yield value;\n }\n },\n };\n}\n","export function convertArrayToReadableStream<T>(\n values: T[],\n): ReadableStream<T> {\n return new ReadableStream({\n start(controller) {\n try {\n for (const value of values) {\n controller.enqueue(value);\n }\n } finally {\n controller.close();\n }\n },\n });\n}\n","export async function convertAsyncIterableToArray<T>(\n iterable: AsyncIterable<T>,\n): Promise<T[]> {\n const result: T[] = [];\n for await (const item of iterable) {\n result.push(item);\n }\n return result;\n}\n","export async function convertReadableStreamToArray<T>(\n stream: ReadableStream<T>,\n): Promise<T[]> {\n const reader = stream.getReader();\n const result: T[] = [];\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n result.push(value);\n }\n\n return result;\n}\n","import { convertReadableStreamToArray } from './convert-readable-stream-to-array';\n\nexport async function convertResponseStreamToArray(\n response: Response,\n): Promise<string[]> {\n return await convertReadableStreamToArray(\n response.body!.pipeThrough(new TextDecoderStream()),\n );\n}\n","function getNodeVersionParts() {\n return process.versions.node\n .split('.')\n .map(version => Number.parseInt(version, 10));\n}\n\nexport function isNodeVersion(version: number) {\n const [nodeMajorVersion] = getNodeVersionParts();\n return nodeMajorVersion === version;\n}\n\nexport function isNodeVersionAtLeast(major: number, minor = 0, patch = 0) {\n const [nodeMajorVersion, nodeMinorVersion, nodePatchVersion] =\n getNodeVersionParts();\n\n if (nodeMajorVersion !== major) {\n return nodeMajorVersion > major;\n }\n\n if (nodeMinorVersion !== minor) {\n return nodeMinorVersion > minor;\n }\n\n return nodePatchVersion >= patch;\n}\n","export function mockId({\n prefix = 'id',\n}: {\n prefix?: string;\n} = {}): () => string {\n let counter = 0;\n return () => `${prefix}-${counter++}`;\n}\n"],"mappings":";AAAO,SAAS,4BAA+B,QAA+B;AAC5E,SAAO;AAAA,IACL,QAAQ,OAAO,aAAa,IAAI;AAC9B,iBAAW,SAAS,QAAQ;AAC1B,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;;;ACRO,SAAS,6BACd,QACmB;AACnB,SAAO,IAAI,eAAe;AAAA,IACxB,MAAM,YAAY;AAChB,UAAI;AACF,mBAAW,SAAS,QAAQ;AAC1B,qBAAW,QAAQ,KAAK;AAAA,QAC1B;AAAA,MACF,UAAE;AACA,mBAAW,MAAM;AAAA,MACnB;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;ACdA,eAAsB,4BACpB,UACc;AACd,QAAM,SAAc,CAAC;AACrB,mBAAiB,QAAQ,UAAU;AACjC,WAAO,KAAK,IAAI;AAAA,EAClB;AACA,SAAO;AACT;;;ACRA,eAAsB,6BACpB,QACc;AACd,QAAM,SAAS,OAAO,UAAU;AAChC,QAAM,SAAc,CAAC;AAErB,SAAO,MAAM;AACX,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,QAAI,KAAM;AACV,WAAO,KAAK,KAAK;AAAA,EACnB;AAEA,SAAO;AACT;;;ACXA,eAAsB,6BACpB,UACmB;AACnB,SAAO,MAAM;AAAA,IACX,SAAS,KAAM,YAAY,IAAI,kBAAkB,CAAC;AAAA,EACpD;AACF;;;ACRA,SAAS,sBAAsB;AAC7B,SAAO,QAAQ,SAAS,KACrB,MAAM,GAAG,EACT,IAAI,aAAW,OAAO,SAAS,SAAS,EAAE,CAAC;AAChD;AAEO,SAAS,cAAc,SAAiB;AAC7C,QAAM,CAAC,gBAAgB,IAAI,oBAAoB;AAC/C,SAAO,qBAAqB;AAC9B;AAEO,SAAS,qBAAqB,OAAe,QAAQ,GAAG,QAAQ,GAAG;AACxE,QAAM,CAAC,kBAAkB,kBAAkB,gBAAgB,IACzD,oBAAoB;AAEtB,MAAI,qBAAqB,OAAO;AAC9B,WAAO,mBAAmB;AAAA,EAC5B;AAEA,MAAI,qBAAqB,OAAO;AAC9B,WAAO,mBAAmB;AAAA,EAC5B;AAEA,SAAO,oBAAoB;AAC7B;;;ACxBO,SAAS,OAAO;AAAA,EACrB,SAAS;AACX,IAEI,CAAC,GAAiB;AACpB,MAAI,UAAU;AACd,SAAO,MAAM,GAAG,MAAM,IAAI,SAAS;AACrC;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/provider-utils",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.28",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@standard-schema/spec": "^1.1.0",
|
|
36
36
|
"@workflow/serde": "4.1.0",
|
|
37
|
-
"eventsource-parser": "^3.0.
|
|
38
|
-
"@ai-sdk/provider": "4.0.0-beta.
|
|
37
|
+
"eventsource-parser": "^3.0.8",
|
|
38
|
+
"@ai-sdk/provider": "4.0.0-beta.13"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "20.17.24",
|
|
@@ -52,12 +52,14 @@
|
|
|
52
52
|
"node": ">=18"
|
|
53
53
|
},
|
|
54
54
|
"publishConfig": {
|
|
55
|
-
"access": "public"
|
|
55
|
+
"access": "public",
|
|
56
|
+
"provenance": true
|
|
56
57
|
},
|
|
57
58
|
"homepage": "https://ai-sdk.dev/docs",
|
|
58
59
|
"repository": {
|
|
59
60
|
"type": "git",
|
|
60
|
-
"url": "
|
|
61
|
+
"url": "https://github.com/vercel/ai",
|
|
62
|
+
"directory": "packages/provider-utils"
|
|
61
63
|
},
|
|
62
64
|
"bugs": {
|
|
63
65
|
"url": "https://github.com/vercel/ai/issues"
|
package/src/index.ts
CHANGED
|
@@ -41,11 +41,15 @@ export { parseJsonEventStream } from './parse-json-event-stream';
|
|
|
41
41
|
export { parseProviderOptions } from './parse-provider-options';
|
|
42
42
|
export * from './post-to-api';
|
|
43
43
|
export {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
type
|
|
47
|
-
type
|
|
48
|
-
} from './provider-tool-factory';
|
|
44
|
+
createProviderDefinedToolFactory,
|
|
45
|
+
createProviderDefinedToolFactoryWithOutputSchema,
|
|
46
|
+
type ProviderDefinedToolFactory,
|
|
47
|
+
type ProviderDefinedToolFactoryWithOutputSchema,
|
|
48
|
+
} from './provider-defined-tool-factory';
|
|
49
|
+
export {
|
|
50
|
+
createProviderExecutedToolFactory,
|
|
51
|
+
type ProviderExecutedToolFactory,
|
|
52
|
+
} from './provider-executed-tool-factory';
|
|
49
53
|
export {
|
|
50
54
|
DEFAULT_MAX_DOWNLOAD_SIZE,
|
|
51
55
|
readResponseWithSizeLimit,
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { tool, Tool, ToolExecuteFunction } from './types/tool';
|
|
2
2
|
import { FlexibleSchema } from './schema';
|
|
3
3
|
import { Context } from './types/context';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* A provider-defined tool is a tool for which the provider defines the input
|
|
6
|
+
* and output schemas, but does not execute the tool.
|
|
7
|
+
*/
|
|
8
|
+
export type ProviderDefinedToolFactory<
|
|
6
9
|
INPUT,
|
|
7
10
|
ARGS extends object,
|
|
8
11
|
CONTEXT extends Context = {},
|
|
@@ -17,7 +20,7 @@ export type ProviderToolFactory<
|
|
|
17
20
|
},
|
|
18
21
|
) => Tool<INPUT, OUTPUT, CONTEXT>;
|
|
19
22
|
|
|
20
|
-
export function
|
|
23
|
+
export function createProviderDefinedToolFactory<
|
|
21
24
|
INPUT,
|
|
22
25
|
ARGS extends object,
|
|
23
26
|
CONTEXT extends Context = {},
|
|
@@ -27,7 +30,7 @@ export function createProviderToolFactory<
|
|
|
27
30
|
}: {
|
|
28
31
|
id: `${string}.${string}`;
|
|
29
32
|
inputSchema: FlexibleSchema<INPUT>;
|
|
30
|
-
}):
|
|
33
|
+
}): ProviderDefinedToolFactory<INPUT, ARGS, CONTEXT> {
|
|
31
34
|
return <OUTPUT>({
|
|
32
35
|
execute,
|
|
33
36
|
outputSchema,
|
|
@@ -48,6 +51,7 @@ export function createProviderToolFactory<
|
|
|
48
51
|
}): Tool<INPUT, OUTPUT, CONTEXT> =>
|
|
49
52
|
tool({
|
|
50
53
|
type: 'provider',
|
|
54
|
+
isProviderExecuted: false,
|
|
51
55
|
id,
|
|
52
56
|
args,
|
|
53
57
|
inputSchema,
|
|
@@ -61,7 +65,7 @@ export function createProviderToolFactory<
|
|
|
61
65
|
});
|
|
62
66
|
}
|
|
63
67
|
|
|
64
|
-
export type
|
|
68
|
+
export type ProviderDefinedToolFactoryWithOutputSchema<
|
|
65
69
|
INPUT,
|
|
66
70
|
OUTPUT,
|
|
67
71
|
ARGS extends object,
|
|
@@ -77,7 +81,7 @@ export type ProviderToolFactoryWithOutputSchema<
|
|
|
77
81
|
},
|
|
78
82
|
) => Tool<INPUT, OUTPUT, CONTEXT>;
|
|
79
83
|
|
|
80
|
-
export function
|
|
84
|
+
export function createProviderDefinedToolFactoryWithOutputSchema<
|
|
81
85
|
INPUT,
|
|
82
86
|
OUTPUT,
|
|
83
87
|
ARGS extends object,
|
|
@@ -86,23 +90,11 @@ export function createProviderToolFactoryWithOutputSchema<
|
|
|
86
90
|
id,
|
|
87
91
|
inputSchema,
|
|
88
92
|
outputSchema,
|
|
89
|
-
supportsDeferredResults,
|
|
90
93
|
}: {
|
|
91
94
|
id: `${string}.${string}`;
|
|
92
95
|
inputSchema: FlexibleSchema<INPUT>;
|
|
93
96
|
outputSchema: FlexibleSchema<OUTPUT>;
|
|
94
|
-
|
|
95
|
-
* Whether this provider-executed tool supports deferred results.
|
|
96
|
-
*
|
|
97
|
-
* When true, the tool result may not be returned in the same turn as the
|
|
98
|
-
* tool call (e.g., when using programmatic tool calling where a server tool
|
|
99
|
-
* triggers a client-executed tool, and the server tool's result is deferred
|
|
100
|
-
* until the client tool is resolved).
|
|
101
|
-
*
|
|
102
|
-
* @default false
|
|
103
|
-
*/
|
|
104
|
-
supportsDeferredResults?: boolean;
|
|
105
|
-
}): ProviderToolFactoryWithOutputSchema<INPUT, OUTPUT, ARGS, CONTEXT> {
|
|
97
|
+
}): ProviderDefinedToolFactoryWithOutputSchema<INPUT, OUTPUT, ARGS, CONTEXT> {
|
|
106
98
|
return ({
|
|
107
99
|
execute,
|
|
108
100
|
needsApproval,
|
|
@@ -121,6 +113,7 @@ export function createProviderToolFactoryWithOutputSchema<
|
|
|
121
113
|
}): Tool<INPUT, OUTPUT, CONTEXT> =>
|
|
122
114
|
tool({
|
|
123
115
|
type: 'provider',
|
|
116
|
+
isProviderExecuted: false,
|
|
124
117
|
id,
|
|
125
118
|
args,
|
|
126
119
|
inputSchema,
|
|
@@ -131,6 +124,5 @@ export function createProviderToolFactoryWithOutputSchema<
|
|
|
131
124
|
onInputStart,
|
|
132
125
|
onInputDelta,
|
|
133
126
|
onInputAvailable,
|
|
134
|
-
supportsDeferredResults,
|
|
135
127
|
});
|
|
136
128
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { FlexibleSchema } from './schema';
|
|
2
|
+
import { Context } from './types/context';
|
|
3
|
+
import { tool, Tool } from './types/tool';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A provider-executed tool is a tool for which the provider executes the tool.
|
|
7
|
+
*/
|
|
8
|
+
export type ProviderExecutedToolFactory<
|
|
9
|
+
INPUT,
|
|
10
|
+
OUTPUT,
|
|
11
|
+
ARGS extends object,
|
|
12
|
+
CONTEXT extends Context = {},
|
|
13
|
+
> = (
|
|
14
|
+
options: ARGS & {
|
|
15
|
+
onInputStart?: Tool<INPUT, OUTPUT, CONTEXT>['onInputStart'];
|
|
16
|
+
onInputDelta?: Tool<INPUT, OUTPUT, CONTEXT>['onInputDelta'];
|
|
17
|
+
onInputAvailable?: Tool<INPUT, OUTPUT, CONTEXT>['onInputAvailable'];
|
|
18
|
+
},
|
|
19
|
+
) => Tool<INPUT, OUTPUT, CONTEXT>;
|
|
20
|
+
|
|
21
|
+
export function createProviderExecutedToolFactory<
|
|
22
|
+
INPUT,
|
|
23
|
+
OUTPUT,
|
|
24
|
+
ARGS extends object,
|
|
25
|
+
CONTEXT extends Context = {},
|
|
26
|
+
>({
|
|
27
|
+
id,
|
|
28
|
+
inputSchema,
|
|
29
|
+
outputSchema,
|
|
30
|
+
supportsDeferredResults,
|
|
31
|
+
}: {
|
|
32
|
+
id: `${string}.${string}`;
|
|
33
|
+
inputSchema: FlexibleSchema<INPUT>;
|
|
34
|
+
outputSchema: FlexibleSchema<OUTPUT>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Whether this provider-executed tool supports deferred results.
|
|
38
|
+
*
|
|
39
|
+
* When true, the tool result may not be returned in the same turn as the
|
|
40
|
+
* tool call (e.g., when using programmatic tool calling where a server tool
|
|
41
|
+
* triggers a client-executed tool, and the server tool's result is deferred
|
|
42
|
+
* until the client tool is resolved).
|
|
43
|
+
*
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
supportsDeferredResults?: boolean;
|
|
47
|
+
}): ProviderExecutedToolFactory<INPUT, OUTPUT, ARGS, CONTEXT> {
|
|
48
|
+
return ({
|
|
49
|
+
onInputStart,
|
|
50
|
+
onInputDelta,
|
|
51
|
+
onInputAvailable,
|
|
52
|
+
...args
|
|
53
|
+
}: ARGS & {
|
|
54
|
+
onInputStart?: Tool<INPUT, OUTPUT, CONTEXT>['onInputStart'];
|
|
55
|
+
onInputDelta?: Tool<INPUT, OUTPUT, CONTEXT>['onInputDelta'];
|
|
56
|
+
onInputAvailable?: Tool<INPUT, OUTPUT, CONTEXT>['onInputAvailable'];
|
|
57
|
+
}): Tool<INPUT, OUTPUT, CONTEXT> =>
|
|
58
|
+
tool({
|
|
59
|
+
type: 'provider',
|
|
60
|
+
isProviderExecuted: true,
|
|
61
|
+
id,
|
|
62
|
+
args,
|
|
63
|
+
inputSchema,
|
|
64
|
+
outputSchema,
|
|
65
|
+
onInputStart,
|
|
66
|
+
onInputDelta,
|
|
67
|
+
onInputAvailable,
|
|
68
|
+
supportsDeferredResults,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
@@ -19,7 +19,9 @@ export interface StreamingToolCallDelta {
|
|
|
19
19
|
} | null;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export interface StreamingToolCallTrackerOptions
|
|
22
|
+
export interface StreamingToolCallTrackerOptions<
|
|
23
|
+
DELTA extends StreamingToolCallDelta = StreamingToolCallDelta,
|
|
24
|
+
> {
|
|
23
25
|
/**
|
|
24
26
|
* ID generator function for tool call IDs.
|
|
25
27
|
* Defaults to the standard generateId.
|
|
@@ -40,9 +42,7 @@ export interface StreamingToolCallTrackerOptions {
|
|
|
40
42
|
* The returned metadata is stored on the tool call and passed to
|
|
41
43
|
* `buildToolCallProviderMetadata` when the tool call is finalized.
|
|
42
44
|
*/
|
|
43
|
-
extractMetadata?: (
|
|
44
|
-
delta: StreamingToolCallDelta,
|
|
45
|
-
) => SharedV4ProviderMetadata | undefined;
|
|
45
|
+
extractMetadata?: (delta: DELTA) => SharedV4ProviderMetadata | undefined;
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* Build the `providerMetadata` object for a `tool-call` event.
|
|
@@ -62,6 +62,11 @@ interface TrackedToolCall {
|
|
|
62
62
|
metadata?: SharedV4ProviderMetadata;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
type StreamingToolCallTrackerController = Pick<
|
|
66
|
+
TransformStreamDefaultController<LanguageModelV4StreamPart>,
|
|
67
|
+
'enqueue'
|
|
68
|
+
>;
|
|
69
|
+
|
|
65
70
|
/**
|
|
66
71
|
* Tracks streaming tool call state across multiple deltas from an
|
|
67
72
|
* OpenAI-compatible chat completion stream. Handles argument accumulation,
|
|
@@ -70,18 +75,25 @@ interface TrackedToolCall {
|
|
|
70
75
|
*
|
|
71
76
|
* Used by openai, openai-compatible, groq, deepseek, and alibaba providers.
|
|
72
77
|
*/
|
|
73
|
-
export class StreamingToolCallTracker
|
|
78
|
+
export class StreamingToolCallTracker<
|
|
79
|
+
DELTA extends StreamingToolCallDelta = StreamingToolCallDelta,
|
|
80
|
+
> {
|
|
74
81
|
private toolCalls: TrackedToolCall[] = [];
|
|
82
|
+
private readonly controller: StreamingToolCallTrackerController;
|
|
75
83
|
private readonly _generateId: () => string;
|
|
76
84
|
private readonly typeValidation: 'none' | 'if-present' | 'required';
|
|
77
85
|
private readonly extractMetadata?: (
|
|
78
|
-
delta:
|
|
86
|
+
delta: DELTA,
|
|
79
87
|
) => SharedV4ProviderMetadata | undefined;
|
|
80
88
|
private readonly buildToolCallProviderMetadata?: (
|
|
81
89
|
metadata: SharedV4ProviderMetadata | undefined,
|
|
82
90
|
) => SharedV4ProviderMetadata | undefined;
|
|
83
91
|
|
|
84
|
-
constructor(
|
|
92
|
+
constructor(
|
|
93
|
+
controller: StreamingToolCallTrackerController,
|
|
94
|
+
options: StreamingToolCallTrackerOptions<DELTA> = {},
|
|
95
|
+
) {
|
|
96
|
+
this.controller = controller;
|
|
85
97
|
this._generateId = options.generateId ?? defaultGenerateId;
|
|
86
98
|
this.typeValidation = options.typeValidation ?? 'none';
|
|
87
99
|
this.extractMetadata = options.extractMetadata;
|
|
@@ -93,16 +105,13 @@ export class StreamingToolCallTracker {
|
|
|
93
105
|
* Emits tool-input-start, tool-input-delta, tool-input-end, and tool-call
|
|
94
106
|
* events as appropriate.
|
|
95
107
|
*/
|
|
96
|
-
processDelta(
|
|
97
|
-
toolCallDelta: StreamingToolCallDelta,
|
|
98
|
-
enqueue: (part: LanguageModelV4StreamPart) => void,
|
|
99
|
-
): void {
|
|
108
|
+
processDelta(toolCallDelta: DELTA): void {
|
|
100
109
|
const index = toolCallDelta.index ?? this.toolCalls.length;
|
|
101
110
|
|
|
102
111
|
if (this.toolCalls[index] == null) {
|
|
103
|
-
this.processNewToolCall(index, toolCallDelta
|
|
112
|
+
this.processNewToolCall(index, toolCallDelta);
|
|
104
113
|
} else {
|
|
105
|
-
this.processExistingToolCall(index, toolCallDelta
|
|
114
|
+
this.processExistingToolCall(index, toolCallDelta);
|
|
106
115
|
}
|
|
107
116
|
}
|
|
108
117
|
|
|
@@ -110,19 +119,15 @@ export class StreamingToolCallTracker {
|
|
|
110
119
|
* Finalize any unfinished tool calls. Should be called during the stream's
|
|
111
120
|
* flush handler to ensure all tool calls are properly completed.
|
|
112
121
|
*/
|
|
113
|
-
flush(
|
|
122
|
+
flush(): void {
|
|
114
123
|
for (const toolCall of this.toolCalls) {
|
|
115
124
|
if (!toolCall.hasFinished) {
|
|
116
|
-
this.finishToolCall(toolCall
|
|
125
|
+
this.finishToolCall(toolCall);
|
|
117
126
|
}
|
|
118
127
|
}
|
|
119
128
|
}
|
|
120
129
|
|
|
121
|
-
private processNewToolCall(
|
|
122
|
-
index: number,
|
|
123
|
-
toolCallDelta: StreamingToolCallDelta,
|
|
124
|
-
enqueue: (part: LanguageModelV4StreamPart) => void,
|
|
125
|
-
): void {
|
|
130
|
+
private processNewToolCall(index: number, toolCallDelta: DELTA): void {
|
|
126
131
|
if (this.typeValidation === 'required') {
|
|
127
132
|
if (toolCallDelta.type !== 'function') {
|
|
128
133
|
throw new InvalidResponseDataError({
|
|
@@ -153,7 +158,7 @@ export class StreamingToolCallTracker {
|
|
|
153
158
|
});
|
|
154
159
|
}
|
|
155
160
|
|
|
156
|
-
enqueue({
|
|
161
|
+
this.controller.enqueue({
|
|
157
162
|
type: 'tool-input-start',
|
|
158
163
|
id: toolCallDelta.id,
|
|
159
164
|
toolName: toolCallDelta.function.name,
|
|
@@ -176,7 +181,7 @@ export class StreamingToolCallTracker {
|
|
|
176
181
|
|
|
177
182
|
// Emit initial delta if arguments already present
|
|
178
183
|
if (toolCall.function.arguments.length > 0) {
|
|
179
|
-
enqueue({
|
|
184
|
+
this.controller.enqueue({
|
|
180
185
|
type: 'tool-input-delta',
|
|
181
186
|
id: toolCall.id,
|
|
182
187
|
delta: toolCall.function.arguments,
|
|
@@ -186,15 +191,11 @@ export class StreamingToolCallTracker {
|
|
|
186
191
|
// Check if tool call is complete
|
|
187
192
|
// (some providers send the full tool call in one chunk)
|
|
188
193
|
if (isParsableJson(toolCall.function.arguments)) {
|
|
189
|
-
this.finishToolCall(toolCall
|
|
194
|
+
this.finishToolCall(toolCall);
|
|
190
195
|
}
|
|
191
196
|
}
|
|
192
197
|
|
|
193
|
-
private processExistingToolCall(
|
|
194
|
-
index: number,
|
|
195
|
-
toolCallDelta: StreamingToolCallDelta,
|
|
196
|
-
enqueue: (part: LanguageModelV4StreamPart) => void,
|
|
197
|
-
): void {
|
|
198
|
+
private processExistingToolCall(index: number, toolCallDelta: DELTA): void {
|
|
198
199
|
const toolCall = this.toolCalls[index];
|
|
199
200
|
|
|
200
201
|
if (toolCall.hasFinished) {
|
|
@@ -204,7 +205,7 @@ export class StreamingToolCallTracker {
|
|
|
204
205
|
if (toolCallDelta.function?.arguments != null) {
|
|
205
206
|
toolCall.function.arguments += toolCallDelta.function.arguments;
|
|
206
207
|
|
|
207
|
-
enqueue({
|
|
208
|
+
this.controller.enqueue({
|
|
208
209
|
type: 'tool-input-delta',
|
|
209
210
|
id: toolCall.id,
|
|
210
211
|
delta: toolCallDelta.function.arguments,
|
|
@@ -213,15 +214,12 @@ export class StreamingToolCallTracker {
|
|
|
213
214
|
|
|
214
215
|
// Check if tool call is complete
|
|
215
216
|
if (isParsableJson(toolCall.function.arguments)) {
|
|
216
|
-
this.finishToolCall(toolCall
|
|
217
|
+
this.finishToolCall(toolCall);
|
|
217
218
|
}
|
|
218
219
|
}
|
|
219
220
|
|
|
220
|
-
private finishToolCall(
|
|
221
|
-
|
|
222
|
-
enqueue: (part: LanguageModelV4StreamPart) => void,
|
|
223
|
-
): void {
|
|
224
|
-
enqueue({
|
|
221
|
+
private finishToolCall(toolCall: TrackedToolCall): void {
|
|
222
|
+
this.controller.enqueue({
|
|
225
223
|
type: 'tool-input-end',
|
|
226
224
|
id: toolCall.id,
|
|
227
225
|
});
|
|
@@ -230,7 +228,7 @@ export class StreamingToolCallTracker {
|
|
|
230
228
|
toolCall.metadata,
|
|
231
229
|
);
|
|
232
230
|
|
|
233
|
-
enqueue({
|
|
231
|
+
this.controller.enqueue({
|
|
234
232
|
type: 'tool-call',
|
|
235
233
|
toolCallId: toolCall.id ?? this._generateId(),
|
|
236
234
|
toolName: toolCall.function.name,
|
|
@@ -1,4 +1,25 @@
|
|
|
1
|
+
function getNodeVersionParts() {
|
|
2
|
+
return process.versions.node
|
|
3
|
+
.split('.')
|
|
4
|
+
.map(version => Number.parseInt(version, 10));
|
|
5
|
+
}
|
|
6
|
+
|
|
1
7
|
export function isNodeVersion(version: number) {
|
|
2
|
-
const nodeMajorVersion =
|
|
8
|
+
const [nodeMajorVersion] = getNodeVersionParts();
|
|
3
9
|
return nodeMajorVersion === version;
|
|
4
10
|
}
|
|
11
|
+
|
|
12
|
+
export function isNodeVersionAtLeast(major: number, minor = 0, patch = 0) {
|
|
13
|
+
const [nodeMajorVersion, nodeMinorVersion, nodePatchVersion] =
|
|
14
|
+
getNodeVersionParts();
|
|
15
|
+
|
|
16
|
+
if (nodeMajorVersion !== major) {
|
|
17
|
+
return nodeMajorVersion > major;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (nodeMinorVersion !== minor) {
|
|
21
|
+
return nodeMinorVersion > minor;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return nodePatchVersion >= patch;
|
|
25
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -24,6 +24,7 @@ export type { InferToolSetContext } from './infer-tool-set-context';
|
|
|
24
24
|
export type { ModelMessage } from './model-message';
|
|
25
25
|
export type { ProviderOptions } from './provider-options';
|
|
26
26
|
export type { ProviderReference } from './provider-reference';
|
|
27
|
+
export type { SensitiveContext } from './sensitive-context';
|
|
27
28
|
export type { SystemModelMessage } from './system-model-message';
|
|
28
29
|
export {
|
|
29
30
|
dynamicTool,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Context } from './context';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Top-level context properties that contain sensitive data and should be
|
|
5
|
+
* excluded from telemetry.
|
|
6
|
+
*/
|
|
7
|
+
export type SensitiveContext<CONTEXT extends Context | unknown | never> =
|
|
8
|
+
| { [KEY in keyof CONTEXT]?: boolean }
|
|
9
|
+
| undefined;
|
|
@@ -13,4 +13,11 @@ export type ToolApprovalRequest = {
|
|
|
13
13
|
* ID of the tool call that the approval request is for.
|
|
14
14
|
*/
|
|
15
15
|
toolCallId: string;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Flag indicating whether the tool was automatically approved or denied.
|
|
19
|
+
*
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
isAutomatic?: boolean;
|
|
16
23
|
};
|
package/src/types/tool.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { JSONValue } from '@ai-sdk/provider';
|
|
2
2
|
import { FlexibleSchema } from '../schema';
|
|
3
3
|
import { ToolResultOutput } from './content-part';
|
|
4
|
+
import { Context } from './context';
|
|
4
5
|
import { ModelMessage } from './model-message';
|
|
5
6
|
import { ProviderOptions } from './provider-options';
|
|
6
|
-
import {
|
|
7
|
+
import { SensitiveContext } from './sensitive-context';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Additional options that are sent into each tool execution.
|
|
@@ -28,7 +29,8 @@ export interface ToolExecutionOptions<
|
|
|
28
29
|
abortSignal?: AbortSignal;
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
|
-
*
|
|
32
|
+
* Tool context as defined by the tool's context schema.
|
|
33
|
+
* The tool context is specific to the tool and is passed to the tool execution.
|
|
32
34
|
*
|
|
33
35
|
* Treat the context object as immutable inside tools.
|
|
34
36
|
* Mutating the context object can lead to race conditions and unexpected results
|
|
@@ -42,6 +44,8 @@ export interface ToolExecutionOptions<
|
|
|
42
44
|
|
|
43
45
|
/**
|
|
44
46
|
* Function that is called to determine if the tool needs approval before it can be executed.
|
|
47
|
+
*
|
|
48
|
+
* @deprecated Tool approval is handled on a `generateText` / `streamText` level now.
|
|
45
49
|
*/
|
|
46
50
|
export type ToolNeedsApprovalFunction<
|
|
47
51
|
INPUT,
|
|
@@ -61,7 +65,8 @@ export type ToolNeedsApprovalFunction<
|
|
|
61
65
|
messages: ModelMessage[];
|
|
62
66
|
|
|
63
67
|
/**
|
|
64
|
-
*
|
|
68
|
+
* Tool context as defined by the tool's context schema.
|
|
69
|
+
* The tool context is specific to the tool and is passed to the tool execution.
|
|
65
70
|
*
|
|
66
71
|
* Treat the context object as immutable inside tools.
|
|
67
72
|
* Mutating the context object can lead to race conditions and unexpected results
|
|
@@ -113,9 +118,15 @@ type ToolOutputProperties<
|
|
|
113
118
|
*/
|
|
114
119
|
execute: ToolExecuteFunction<INPUT, OUTPUT, CONTEXT>;
|
|
115
120
|
|
|
121
|
+
/**
|
|
122
|
+
* The schema of the output that the tool produces.
|
|
123
|
+
*/
|
|
116
124
|
outputSchema?: FlexibleSchema<OUTPUT>;
|
|
117
125
|
}
|
|
118
126
|
| {
|
|
127
|
+
/**
|
|
128
|
+
* The schema of the output that the tool produces.
|
|
129
|
+
*/
|
|
119
130
|
outputSchema: FlexibleSchema<OUTPUT>;
|
|
120
131
|
|
|
121
132
|
execute?: never;
|
|
@@ -174,8 +185,16 @@ export type Tool<
|
|
|
174
185
|
*/
|
|
175
186
|
contextSchema?: FlexibleSchema<CONTEXT>;
|
|
176
187
|
|
|
188
|
+
/**
|
|
189
|
+
* Marks top-level context properties that contain sensitive data and should be excluded from telemetry.
|
|
190
|
+
* Properties marked as `true` are omitted from telemetry integrations.
|
|
191
|
+
*/
|
|
192
|
+
sensitiveContext?: SensitiveContext<CONTEXT>;
|
|
193
|
+
|
|
177
194
|
/**
|
|
178
195
|
* Whether the tool needs approval before it can be executed.
|
|
196
|
+
*
|
|
197
|
+
* @deprecated Tool approval is handled on a `generateText` / `streamText` level now.
|
|
179
198
|
*/
|
|
180
199
|
needsApproval?:
|
|
181
200
|
| boolean
|
|
@@ -273,6 +292,11 @@ export type Tool<
|
|
|
273
292
|
*/
|
|
274
293
|
id: `${string}.${string}`;
|
|
275
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Flag that indicates whether the tool is executed by the provider.
|
|
297
|
+
*/
|
|
298
|
+
isProviderExecuted: boolean;
|
|
299
|
+
|
|
276
300
|
/**
|
|
277
301
|
* The arguments for configuring the tool. Must match the expected arguments defined by the provider for this tool.
|
|
278
302
|
*/
|
|
@@ -319,10 +343,41 @@ export function tool(tool: any): any {
|
|
|
319
343
|
* Defines a dynamic tool.
|
|
320
344
|
*/
|
|
321
345
|
export function dynamicTool(tool: {
|
|
346
|
+
/**
|
|
347
|
+
* An optional description of what the tool does.
|
|
348
|
+
* Will be used by the language model to decide whether to use the tool.
|
|
349
|
+
* Not used for provider-defined tools.
|
|
350
|
+
*/
|
|
322
351
|
description?: string;
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* An optional title of the tool.
|
|
355
|
+
*/
|
|
323
356
|
title?: string;
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Additional provider-specific metadata. They are passed through
|
|
360
|
+
* to the provider from the AI SDK and enable provider-specific
|
|
361
|
+
* functionality that can be fully encapsulated in the provider.
|
|
362
|
+
*/
|
|
324
363
|
providerOptions?: ProviderOptions;
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* The schema of the input that the tool expects.
|
|
367
|
+
* The language model will use this to generate the input.
|
|
368
|
+
* It is also used to validate the output of the language model.
|
|
369
|
+
*
|
|
370
|
+
* You can use descriptions on the schema properties to make the input understandable for the language model.
|
|
371
|
+
*/
|
|
325
372
|
inputSchema: FlexibleSchema<unknown>;
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* An async function that is called with the arguments from the tool call and produces a result.
|
|
376
|
+
* If not provided, the tool will not be executed automatically.
|
|
377
|
+
*
|
|
378
|
+
* @args is the input of the tool call.
|
|
379
|
+
* @options.abortSignal is a signal that can be used to abort the tool call.
|
|
380
|
+
*/
|
|
326
381
|
execute: ToolExecuteFunction<unknown, unknown, Context>;
|
|
327
382
|
|
|
328
383
|
/**
|