@ai-sdk/provider-utils 5.0.0-beta.25 → 5.0.0-beta.27
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 +17 -0
- package/dist/index.d.ts +103 -18
- package/dist/index.js +55 -27
- package/dist/index.js.map +1 -1
- package/dist/test/index.d.ts +2 -1
- package/dist/test/index.js +16 -2
- package/dist/test/index.js.map +1 -1
- package/package.json +4 -3
- package/src/index.ts +9 -5
- package/src/maybe-promise-like.ts +3 -0
- package/src/parse-json.ts +1 -1
- package/src/post-to-api.ts +2 -2
- 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/convert-response-stream-to-array.ts +1 -1
- 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
|
@@ -47,16 +47,29 @@ async function convertReadableStreamToArray(stream) {
|
|
|
47
47
|
|
|
48
48
|
// src/test/convert-response-stream-to-array.ts
|
|
49
49
|
async function convertResponseStreamToArray(response) {
|
|
50
|
-
return convertReadableStreamToArray(
|
|
50
|
+
return await convertReadableStreamToArray(
|
|
51
51
|
response.body.pipeThrough(new TextDecoderStream())
|
|
52
52
|
);
|
|
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 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.27",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@standard-schema/spec": "^1.1.0",
|
|
36
36
|
"@workflow/serde": "4.1.0",
|
|
37
|
-
"eventsource-parser": "^3.0.
|
|
37
|
+
"eventsource-parser": "^3.0.8",
|
|
38
38
|
"@ai-sdk/provider": "4.0.0-beta.12"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
@@ -52,7 +52,8 @@
|
|
|
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": {
|
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,
|
package/src/parse-json.ts
CHANGED
package/src/post-to-api.ts
CHANGED
|
@@ -28,7 +28,7 @@ export const postJsonToApi = async <T>({
|
|
|
28
28
|
abortSignal?: AbortSignal;
|
|
29
29
|
fetch?: FetchFunction;
|
|
30
30
|
}) =>
|
|
31
|
-
postToApi({
|
|
31
|
+
await postToApi({
|
|
32
32
|
url,
|
|
33
33
|
headers: {
|
|
34
34
|
'Content-Type': 'application/json',
|
|
@@ -61,7 +61,7 @@ export const postFormDataToApi = async <T>({
|
|
|
61
61
|
abortSignal?: AbortSignal;
|
|
62
62
|
fetch?: FetchFunction;
|
|
63
63
|
}) =>
|
|
64
|
-
postToApi({
|
|
64
|
+
await postToApi({
|
|
65
65
|
url,
|
|
66
66
|
headers,
|
|
67
67
|
body: {
|
|
@@ -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,
|
|
@@ -3,7 +3,7 @@ import { convertReadableStreamToArray } from './convert-readable-stream-to-array
|
|
|
3
3
|
export async function convertResponseStreamToArray(
|
|
4
4
|
response: Response,
|
|
5
5
|
): Promise<string[]> {
|
|
6
|
-
return convertReadableStreamToArray(
|
|
6
|
+
return await convertReadableStreamToArray(
|
|
7
7
|
response.body!.pipeThrough(new TextDecoderStream()),
|
|
8
8
|
);
|
|
9
9
|
}
|
|
@@ -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
|
};
|