ai 7.0.41 → 7.0.43
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 +25 -0
- package/dist/index.d.ts +35 -9
- package/dist/index.js +175 -12
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +2 -1
- package/dist/internal/index.js +1 -1
- package/dist/internal/index.js.map +1 -1
- package/docs/03-agents/02-building-agents.mdx +4 -0
- package/docs/03-agents/04-loop-control.mdx +40 -0
- package/docs/03-ai-sdk-core/18-code-mode.mdx +246 -0
- package/docs/03-ai-sdk-core/36-transcription.mdx +1 -0
- package/docs/03-ai-sdk-core/65-devtools.mdx +47 -1
- package/docs/03-ai-sdk-core/index.mdx +6 -0
- package/docs/06-advanced/11-secure-url-fetching.mdx +18 -24
- package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +75 -3
- package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +64 -1
- package/docs/07-reference/01-ai-sdk-core/16-tool-loop-agent.mdx +1 -1
- package/docs/07-reference/01-ai-sdk-core/23-create-mcp-client.mdx +7 -0
- package/package.json +4 -4
- package/src/generate-text/generate-text-result.ts +3 -1
- package/src/generate-text/generate-text.ts +40 -9
- package/src/generate-text/index.ts +4 -0
- package/src/generate-text/prepare-step-call-settings.ts +31 -0
- package/src/generate-text/prepare-step.ts +8 -3
- package/src/generate-text/step-result.ts +2 -1
- package/src/generate-text/stream-text.ts +16 -2
- package/src/generate-text/tool-caller-configuration.ts +186 -0
- package/src/index.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.43",
|
|
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.33",
|
|
46
46
|
"@ai-sdk/provider": "4.0.4",
|
|
47
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
47
|
+
"@ai-sdk/provider-utils": "5.0.16"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@edge-runtime/vm": "^5.0.0",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"tsx": "^4.22.0",
|
|
56
56
|
"typescript": "5.8.3",
|
|
57
57
|
"zod": "3.25.76",
|
|
58
|
-
"@ai-sdk/test-server": "2.0.
|
|
58
|
+
"@ai-sdk/test-server": "2.0.1",
|
|
59
59
|
"@vercel/ai-tsconfig": "0.0.0"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
@@ -40,7 +40,9 @@ export interface GenerateTextResult<
|
|
|
40
40
|
readonly content: Array<ContentPart<TOOLS>>;
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* The text
|
|
43
|
+
* The concatenation of all text parts generated in the final step.
|
|
44
|
+
* It is an empty string if the final step contains no text parts.
|
|
45
|
+
* Inspect `finalStep.content` to distinguish that case.
|
|
44
46
|
*/
|
|
45
47
|
readonly text: string;
|
|
46
48
|
|
|
@@ -84,6 +84,7 @@ import { text, type Output } from './output';
|
|
|
84
84
|
import type { InferCompleteOutput } from './output-utils';
|
|
85
85
|
import { parseToolCall } from './parse-tool-call';
|
|
86
86
|
import type { PrepareStepFunction } from './prepare-step';
|
|
87
|
+
import { prepareStepCallSettings } from './prepare-step-call-settings';
|
|
87
88
|
import { convertToReasoningOutputs } from './reasoning-output';
|
|
88
89
|
import { resolveToolApproval } from './resolve-tool-approval';
|
|
89
90
|
import type { ResponseMessage } from './response-message';
|
|
@@ -103,6 +104,11 @@ import { toResponseMessages } from './to-response-messages';
|
|
|
103
104
|
import type { ToolApprovalConfiguration } from './tool-approval-configuration';
|
|
104
105
|
import type { ToolApprovalRequestOutput } from './tool-approval-request-output';
|
|
105
106
|
import type { ToolApprovalResponseOutput } from './tool-approval-response-output';
|
|
107
|
+
import {
|
|
108
|
+
prepareToolsForToolCallers,
|
|
109
|
+
resolveToolCallerConfiguration,
|
|
110
|
+
type Experimental_ToolCallers,
|
|
111
|
+
} from './tool-caller-configuration';
|
|
106
112
|
import type { TypedToolCall } from './tool-call';
|
|
107
113
|
import type { ToolCallRepairFunction } from './tool-call-repair-function';
|
|
108
114
|
import type { TypedToolError } from './tool-error';
|
|
@@ -241,6 +247,7 @@ export async function generateText<
|
|
|
241
247
|
experimental_sandbox: sandbox,
|
|
242
248
|
output,
|
|
243
249
|
toolApproval,
|
|
250
|
+
experimental_toolCallers,
|
|
244
251
|
experimental_toolApprovalSecret,
|
|
245
252
|
experimental_telemetry,
|
|
246
253
|
telemetry = experimental_telemetry,
|
|
@@ -357,6 +364,11 @@ export async function generateText<
|
|
|
357
364
|
*/
|
|
358
365
|
toolApproval?: ToolApprovalConfiguration<TOOLS, RUNTIME_CONTEXT>;
|
|
359
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Configures which caller tools may invoke each tool.
|
|
369
|
+
*/
|
|
370
|
+
experimental_toolCallers?: Experimental_ToolCallers<NoInfer<TOOLS>>;
|
|
371
|
+
|
|
360
372
|
/**
|
|
361
373
|
* Secret for HMAC-signing tool approval requests. When set, the server
|
|
362
374
|
* signs each approval request at issuance and verifies the signature when
|
|
@@ -559,6 +571,10 @@ export async function generateText<
|
|
|
559
571
|
};
|
|
560
572
|
|
|
561
573
|
const model = resolveLanguageModel(modelArg);
|
|
574
|
+
const resolvedToolCallers = resolveToolCallerConfiguration({
|
|
575
|
+
tools,
|
|
576
|
+
toolCallers: experimental_toolCallers,
|
|
577
|
+
});
|
|
562
578
|
const stopConditions = asArray(stopWhen);
|
|
563
579
|
const resolvedOnStart = onStart ?? experimental_onStart;
|
|
564
580
|
const resolvedOnStepStart = onStepStart ?? experimental_onStepStart;
|
|
@@ -862,10 +878,20 @@ export async function generateText<
|
|
|
862
878
|
tools,
|
|
863
879
|
activeTools: prepareStepResult?.activeTools ?? activeTools,
|
|
864
880
|
});
|
|
881
|
+
const {
|
|
882
|
+
executionTools: stepExecutionTools,
|
|
883
|
+
modelTools: stepModelTools,
|
|
884
|
+
} = prepareToolsForToolCallers({
|
|
885
|
+
tools: stepActiveTools,
|
|
886
|
+
toolCallers: resolvedToolCallers,
|
|
887
|
+
});
|
|
865
888
|
const stepToolOrder = prepareStepResult?.toolOrder ?? toolOrder;
|
|
866
889
|
|
|
867
890
|
const stepTools = await prepareTools({
|
|
868
|
-
tools:
|
|
891
|
+
tools: stepModelTools as ActiveToolSubset<
|
|
892
|
+
TOOLS,
|
|
893
|
+
ActiveTools<NoInfer<TOOLS>>
|
|
894
|
+
>,
|
|
869
895
|
toolOrder: stepToolOrder as ToolOrder<
|
|
870
896
|
ActiveToolSubset<TOOLS, ActiveTools<NoInfer<TOOLS>>>
|
|
871
897
|
>,
|
|
@@ -888,6 +914,11 @@ export async function generateText<
|
|
|
888
914
|
prepareStepResult?.providerOptions,
|
|
889
915
|
);
|
|
890
916
|
|
|
917
|
+
const stepCallSettings = prepareStepCallSettings({
|
|
918
|
+
callSettings,
|
|
919
|
+
stepSettings: prepareStepResult,
|
|
920
|
+
});
|
|
921
|
+
|
|
891
922
|
await notify({
|
|
892
923
|
event: {
|
|
893
924
|
callId,
|
|
@@ -921,7 +952,7 @@ export async function generateText<
|
|
|
921
952
|
instructions: stepInstructions,
|
|
922
953
|
messages: stepMessages,
|
|
923
954
|
tools: stepTools,
|
|
924
|
-
...
|
|
955
|
+
...stepCallSettings,
|
|
925
956
|
};
|
|
926
957
|
const languageModelCallStartEvent = {
|
|
927
958
|
callId,
|
|
@@ -951,7 +982,7 @@ export async function generateText<
|
|
|
951
982
|
...languageModelCallStartEvent,
|
|
952
983
|
execute: async () =>
|
|
953
984
|
await stepModel.doGenerate({
|
|
954
|
-
...
|
|
985
|
+
...stepCallSettings,
|
|
955
986
|
tools: stepTools,
|
|
956
987
|
toolChoice: stepToolChoice,
|
|
957
988
|
responseFormat: await output?.responseFormat,
|
|
@@ -988,7 +1019,7 @@ export async function generateText<
|
|
|
988
1019
|
.map(toolCall =>
|
|
989
1020
|
parseToolCall({
|
|
990
1021
|
toolCall,
|
|
991
|
-
tools,
|
|
1022
|
+
tools: stepExecutionTools as TOOLS,
|
|
992
1023
|
repairToolCall,
|
|
993
1024
|
refineToolInput,
|
|
994
1025
|
instructions: stepInstructions,
|
|
@@ -1056,7 +1087,7 @@ export async function generateText<
|
|
|
1056
1087
|
continue; // ignore invalid tool calls
|
|
1057
1088
|
}
|
|
1058
1089
|
|
|
1059
|
-
const tool = getOwn(
|
|
1090
|
+
const tool = getOwn(stepExecutionTools, toolCall.toolName);
|
|
1060
1091
|
|
|
1061
1092
|
if (tool == null) {
|
|
1062
1093
|
// ignore tool calls for tools that are not available,
|
|
@@ -1084,7 +1115,7 @@ export async function generateText<
|
|
|
1084
1115
|
}
|
|
1085
1116
|
|
|
1086
1117
|
const toolApprovalStatus = await resolveToolApproval({
|
|
1087
|
-
tools,
|
|
1118
|
+
tools: stepExecutionTools as TOOLS,
|
|
1088
1119
|
toolApproval,
|
|
1089
1120
|
toolCall,
|
|
1090
1121
|
messages: stepMessages,
|
|
@@ -1193,14 +1224,14 @@ export async function generateText<
|
|
|
1193
1224
|
);
|
|
1194
1225
|
const toolExecutionMs: Record<string, number> = {};
|
|
1195
1226
|
|
|
1196
|
-
if (
|
|
1227
|
+
if (stepExecutionTools != null) {
|
|
1197
1228
|
const toolExecutionResults = await executeTools({
|
|
1198
1229
|
toolCalls: clientToolCalls.filter(
|
|
1199
1230
|
toolCall =>
|
|
1200
1231
|
!toolCall.invalid &&
|
|
1201
1232
|
!blockedToolCallIds.has(toolCall.toolCallId),
|
|
1202
1233
|
),
|
|
1203
|
-
tools,
|
|
1234
|
+
tools: stepExecutionTools as TOOLS,
|
|
1204
1235
|
callId,
|
|
1205
1236
|
messages: stepMessages,
|
|
1206
1237
|
abortSignal: mergedAbortSignal,
|
|
@@ -1262,7 +1293,7 @@ export async function generateText<
|
|
|
1262
1293
|
// the client tool's result is sent back.
|
|
1263
1294
|
for (const toolCall of stepToolCalls) {
|
|
1264
1295
|
if (!toolCall.providerExecuted) continue;
|
|
1265
|
-
const tool = getOwn(
|
|
1296
|
+
const tool = getOwn(stepExecutionTools, toolCall.toolName);
|
|
1266
1297
|
if (tool?.type === 'provider' && tool.supportsDeferredResults) {
|
|
1267
1298
|
// Check if this tool call already has a result in the current response
|
|
1268
1299
|
const hasResultInResponse = currentModelResponse.content.some(
|
|
@@ -80,6 +80,10 @@ export type {
|
|
|
80
80
|
ToolApprovalConfiguration,
|
|
81
81
|
ToolApprovalStatus,
|
|
82
82
|
} from './tool-approval-configuration';
|
|
83
|
+
export type {
|
|
84
|
+
Experimental_ToolCallerReference,
|
|
85
|
+
Experimental_ToolCallers,
|
|
86
|
+
} from './tool-caller-configuration';
|
|
83
87
|
export { detectToolDrift, fingerprintTools } from './tool-fingerprint';
|
|
84
88
|
export type { ToolApprovalRequestOutput } from './tool-approval-request-output';
|
|
85
89
|
export type { ToolApprovalResponseOutput } from './tool-approval-response-output';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { LanguageModelCallOptions } from '../prompt/language-model-call-options';
|
|
2
|
+
import { prepareLanguageModelCallOptions } from '../prompt/prepare-language-model-call-options';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Resolves model call settings for a single step.
|
|
6
|
+
*
|
|
7
|
+
* Undefined step settings intentionally fall back to the outer call settings,
|
|
8
|
+
* while defined falsy values such as `temperature: 0` and `seed: 0` are kept.
|
|
9
|
+
*/
|
|
10
|
+
export function prepareStepCallSettings({
|
|
11
|
+
callSettings,
|
|
12
|
+
stepSettings,
|
|
13
|
+
}: {
|
|
14
|
+
callSettings: LanguageModelCallOptions;
|
|
15
|
+
stepSettings: LanguageModelCallOptions | undefined;
|
|
16
|
+
}): LanguageModelCallOptions {
|
|
17
|
+
return prepareLanguageModelCallOptions({
|
|
18
|
+
maxOutputTokens:
|
|
19
|
+
stepSettings?.maxOutputTokens ?? callSettings.maxOutputTokens,
|
|
20
|
+
temperature: stepSettings?.temperature ?? callSettings.temperature,
|
|
21
|
+
topP: stepSettings?.topP ?? callSettings.topP,
|
|
22
|
+
topK: stepSettings?.topK ?? callSettings.topK,
|
|
23
|
+
presencePenalty:
|
|
24
|
+
stepSettings?.presencePenalty ?? callSettings.presencePenalty,
|
|
25
|
+
frequencyPenalty:
|
|
26
|
+
stepSettings?.frequencyPenalty ?? callSettings.frequencyPenalty,
|
|
27
|
+
stopSequences: stepSettings?.stopSequences ?? callSettings.stopSequences,
|
|
28
|
+
seed: stepSettings?.seed ?? callSettings.seed,
|
|
29
|
+
reasoning: stepSettings?.reasoning ?? callSettings.reasoning,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
ToolSet,
|
|
8
8
|
} from '@ai-sdk/provider-utils';
|
|
9
9
|
import type { Instructions } from '../prompt';
|
|
10
|
+
import type { LanguageModelCallOptions } from '../prompt/language-model-call-options';
|
|
10
11
|
import type { LanguageModel, ToolChoice } from '../types/language-model';
|
|
11
12
|
import type { ActiveTools } from './active-tools';
|
|
12
13
|
import type { ResponseMessage } from './response-message';
|
|
@@ -95,13 +96,17 @@ export type PrepareStepFunction<
|
|
|
95
96
|
|
|
96
97
|
/**
|
|
97
98
|
* The result type returned by a {@link PrepareStepFunction},
|
|
98
|
-
* allowing per-step overrides of model,
|
|
99
|
+
* allowing per-step overrides of model call settings, model, tools,
|
|
100
|
+
* instructions, or messages.
|
|
101
|
+
*
|
|
102
|
+
* Model call setting overrides apply only to the current step. Undefined
|
|
103
|
+
* settings fall back to the outer call settings.
|
|
99
104
|
*/
|
|
100
105
|
export type PrepareStepResult<
|
|
101
106
|
TOOLS extends ToolSet,
|
|
102
107
|
RUNTIME_CONTEXT extends Context = Context,
|
|
103
108
|
> =
|
|
104
|
-
| {
|
|
109
|
+
| ({
|
|
105
110
|
/**
|
|
106
111
|
* Optionally override which LanguageModel instance is used for this step.
|
|
107
112
|
*/
|
|
@@ -175,5 +180,5 @@ export type PrepareStepResult<
|
|
|
175
180
|
* container IDs for Anthropic's code execution.
|
|
176
181
|
*/
|
|
177
182
|
providerOptions?: ProviderOptions;
|
|
178
|
-
}
|
|
183
|
+
} & LanguageModelCallOptions)
|
|
179
184
|
| undefined;
|
|
@@ -176,7 +176,8 @@ export type StepResult<
|
|
|
176
176
|
readonly content: Array<ContentPart<TOOLS>>;
|
|
177
177
|
|
|
178
178
|
/**
|
|
179
|
-
* The
|
|
179
|
+
* The concatenation of all text parts generated in this step.
|
|
180
|
+
* It is an empty string if the step contains no text parts.
|
|
180
181
|
*/
|
|
181
182
|
readonly text: string;
|
|
182
183
|
|
|
@@ -113,6 +113,7 @@ import type {
|
|
|
113
113
|
InferPartialOutput,
|
|
114
114
|
} from './output-utils';
|
|
115
115
|
import type { PrepareStepFunction } from './prepare-step';
|
|
116
|
+
import { prepareStepCallSettings } from './prepare-step-call-settings';
|
|
116
117
|
import { convertToReasoningOutputs } from './reasoning-output';
|
|
117
118
|
import type { ResponseMessage } from './response-message';
|
|
118
119
|
import { createRestrictedTelemetryDispatcher } from './restricted-telemetry-dispatcher';
|
|
@@ -915,6 +916,11 @@ function createOutputTransformStream<
|
|
|
915
916
|
textChunk += chunk.text;
|
|
916
917
|
textProviderMetadata = chunk.providerMetadata ?? textProviderMetadata;
|
|
917
918
|
|
|
919
|
+
if (chunk.text.length === 0 && chunk.providerMetadata != null) {
|
|
920
|
+
controller.enqueue({ part: chunk, partialOutput: undefined });
|
|
921
|
+
return;
|
|
922
|
+
}
|
|
923
|
+
|
|
918
924
|
// only publish if partial json can be parsed:
|
|
919
925
|
const result = await output.parsePartialOutput({ text });
|
|
920
926
|
|
|
@@ -1963,6 +1969,11 @@ class DefaultStreamTextResult<
|
|
|
1963
1969
|
prepareStepResult?.providerOptions,
|
|
1964
1970
|
);
|
|
1965
1971
|
|
|
1972
|
+
const stepCallSettings = prepareStepCallSettings({
|
|
1973
|
+
callSettings,
|
|
1974
|
+
stepSettings: prepareStepResult,
|
|
1975
|
+
});
|
|
1976
|
+
|
|
1966
1977
|
const stepStartTimestampMs = now();
|
|
1967
1978
|
|
|
1968
1979
|
const { retry } = prepareRetries({ maxRetries, abortSignal });
|
|
@@ -2035,7 +2046,7 @@ class DefaultStreamTextResult<
|
|
|
2035
2046
|
_internal: {
|
|
2036
2047
|
now,
|
|
2037
2048
|
},
|
|
2038
|
-
...
|
|
2049
|
+
...stepCallSettings,
|
|
2039
2050
|
}),
|
|
2040
2051
|
),
|
|
2041
2052
|
);
|
|
@@ -2198,7 +2209,10 @@ class DefaultStreamTextResult<
|
|
|
2198
2209
|
}
|
|
2199
2210
|
|
|
2200
2211
|
case 'text-delta': {
|
|
2201
|
-
if (
|
|
2212
|
+
if (
|
|
2213
|
+
chunk.text.length > 0 ||
|
|
2214
|
+
chunk.providerMetadata != null
|
|
2215
|
+
) {
|
|
2202
2216
|
controller.enqueue(chunk);
|
|
2203
2217
|
}
|
|
2204
2218
|
break;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import {
|
|
2
|
+
experimental_getToolCaller,
|
|
3
|
+
type Experimental_ToolCallerTool,
|
|
4
|
+
type Tool,
|
|
5
|
+
type ToolSet,
|
|
6
|
+
} from '@ai-sdk/provider-utils';
|
|
7
|
+
import { InvalidArgumentError } from '../error/invalid-argument-error';
|
|
8
|
+
|
|
9
|
+
export interface Experimental_ToolCallerReference<
|
|
10
|
+
NAME extends string = string,
|
|
11
|
+
> {
|
|
12
|
+
readonly toolName: NAME;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type ToolCallerName<TOOLS extends ToolSet> = {
|
|
16
|
+
[NAME in keyof TOOLS]: TOOLS[NAME] extends Experimental_ToolCallerTool
|
|
17
|
+
? NAME
|
|
18
|
+
: never;
|
|
19
|
+
}[keyof TOOLS] &
|
|
20
|
+
string;
|
|
21
|
+
|
|
22
|
+
type ToolCallerReferenceUnion<TOOLS extends ToolSet> = {
|
|
23
|
+
[NAME in ToolCallerName<TOOLS>]: Experimental_ToolCallerReference<NAME>;
|
|
24
|
+
}[ToolCallerName<TOOLS>];
|
|
25
|
+
|
|
26
|
+
export type Experimental_ToolCallers<TOOLS extends ToolSet> = (callers: {
|
|
27
|
+
[NAME in ToolCallerName<TOOLS>]: Experimental_ToolCallerReference<NAME>;
|
|
28
|
+
}) => {
|
|
29
|
+
[NAME in keyof TOOLS]?: ReadonlyArray<
|
|
30
|
+
'direct' | ToolCallerReferenceUnion<TOOLS>
|
|
31
|
+
>;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type ResolvedToolCallers = Record<
|
|
35
|
+
string,
|
|
36
|
+
ReadonlyArray<'direct' | string>
|
|
37
|
+
>;
|
|
38
|
+
|
|
39
|
+
export function resolveToolCallerConfiguration<TOOLS extends ToolSet>({
|
|
40
|
+
tools,
|
|
41
|
+
toolCallers,
|
|
42
|
+
}: {
|
|
43
|
+
tools: TOOLS | undefined;
|
|
44
|
+
toolCallers: Experimental_ToolCallers<TOOLS> | undefined;
|
|
45
|
+
}): ResolvedToolCallers | undefined {
|
|
46
|
+
if (tools == null || toolCallers == null) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const namesByReference = new WeakMap<object, string>();
|
|
51
|
+
const callerReferences: Record<string, Experimental_ToolCallerReference> = {};
|
|
52
|
+
|
|
53
|
+
for (const [toolName, tool] of Object.entries(tools)) {
|
|
54
|
+
if (experimental_getToolCaller(tool) == null) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const reference = Object.freeze({ toolName });
|
|
59
|
+
namesByReference.set(reference, toolName);
|
|
60
|
+
callerReferences[toolName] = reference;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const configuration = toolCallers(callerReferences as never);
|
|
64
|
+
const resolved: ResolvedToolCallers = {};
|
|
65
|
+
|
|
66
|
+
for (const [toolName, callers] of Object.entries(configuration)) {
|
|
67
|
+
if (!Object.prototype.hasOwnProperty.call(tools, toolName)) {
|
|
68
|
+
throw new InvalidArgumentError({
|
|
69
|
+
parameter: 'experimental_toolCallers',
|
|
70
|
+
value: configuration,
|
|
71
|
+
message: `unknown tool "${toolName}".`,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!Array.isArray(callers)) {
|
|
76
|
+
throw new InvalidArgumentError({
|
|
77
|
+
parameter: 'experimental_toolCallers',
|
|
78
|
+
value: configuration,
|
|
79
|
+
message: `callers for tool "${toolName}" must be an array.`,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
resolved[toolName] = callers.map(caller => {
|
|
84
|
+
if (caller === 'direct') {
|
|
85
|
+
return caller;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const callerName =
|
|
89
|
+
caller != null && typeof caller === 'object'
|
|
90
|
+
? namesByReference.get(caller)
|
|
91
|
+
: undefined;
|
|
92
|
+
|
|
93
|
+
if (callerName == null) {
|
|
94
|
+
throw new InvalidArgumentError({
|
|
95
|
+
parameter: 'experimental_toolCallers',
|
|
96
|
+
value: configuration,
|
|
97
|
+
message: `tool "${toolName}" contains an invalid caller reference.`,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return callerName;
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return resolved;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function prepareToolsForToolCallers({
|
|
109
|
+
tools,
|
|
110
|
+
toolCallers,
|
|
111
|
+
}: {
|
|
112
|
+
tools: ToolSet | undefined;
|
|
113
|
+
toolCallers: ResolvedToolCallers | undefined;
|
|
114
|
+
}): {
|
|
115
|
+
executionTools: ToolSet | undefined;
|
|
116
|
+
modelTools: ToolSet | undefined;
|
|
117
|
+
} {
|
|
118
|
+
if (tools == null || toolCallers == null) {
|
|
119
|
+
return { executionTools: tools, modelTools: tools };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const executionTools: ToolSet = { ...tools };
|
|
123
|
+
const modelTools: ToolSet = { ...tools };
|
|
124
|
+
const localToolsByCaller = new Map<string, ToolSet>();
|
|
125
|
+
|
|
126
|
+
for (const [toolName, callerNames] of Object.entries(toolCallers)) {
|
|
127
|
+
const tool = executionTools[toolName];
|
|
128
|
+
if (tool == null) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
let availableDirectly = false;
|
|
133
|
+
let availableToProvider = false;
|
|
134
|
+
let preparedTool: Tool = tool;
|
|
135
|
+
|
|
136
|
+
for (const callerName of callerNames) {
|
|
137
|
+
if (callerName === 'direct') {
|
|
138
|
+
availableDirectly = true;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const caller = experimental_getToolCaller(executionTools[callerName]);
|
|
143
|
+
if (caller == null) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (caller.type === 'provider') {
|
|
148
|
+
availableToProvider = true;
|
|
149
|
+
preparedTool = {
|
|
150
|
+
...preparedTool,
|
|
151
|
+
providerOptions: caller.prepareProviderOptions(
|
|
152
|
+
preparedTool.providerOptions,
|
|
153
|
+
),
|
|
154
|
+
} as Tool;
|
|
155
|
+
} else {
|
|
156
|
+
const localTools = localToolsByCaller.get(callerName) ?? {};
|
|
157
|
+
localTools[toolName] = preparedTool;
|
|
158
|
+
localToolsByCaller.set(callerName, localTools);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
executionTools[toolName] = preparedTool;
|
|
163
|
+
|
|
164
|
+
if (availableDirectly || availableToProvider) {
|
|
165
|
+
modelTools[toolName] = preparedTool;
|
|
166
|
+
} else {
|
|
167
|
+
delete modelTools[toolName];
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
for (const [callerName, callerTool] of Object.entries(executionTools)) {
|
|
172
|
+
const caller = experimental_getToolCaller(callerTool);
|
|
173
|
+
if (caller?.type !== 'local') {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const boundCaller = caller.bind(localToolsByCaller.get(callerName) ?? {});
|
|
178
|
+
executionTools[callerName] = boundCaller;
|
|
179
|
+
|
|
180
|
+
if (Object.prototype.hasOwnProperty.call(modelTools, callerName)) {
|
|
181
|
+
modelTools[callerName] = boundCaller;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return { executionTools, modelTools };
|
|
186
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ export {
|
|
|
7
7
|
asSchema,
|
|
8
8
|
createIdGenerator,
|
|
9
9
|
dynamicTool,
|
|
10
|
+
experimental_toolCaller,
|
|
10
11
|
generateId,
|
|
11
12
|
jsonSchema,
|
|
12
13
|
parseJsonEventStream,
|
|
@@ -19,6 +20,7 @@ export {
|
|
|
19
20
|
type InferToolOutput,
|
|
20
21
|
type Experimental_SandboxSession,
|
|
21
22
|
type Experimental_SandboxProcess,
|
|
23
|
+
type Experimental_ToolCallerTool,
|
|
22
24
|
type Schema,
|
|
23
25
|
type Tool,
|
|
24
26
|
type ToolApprovalRequest,
|