@ai-sdk/workflow 0.0.0-6b196531-20260710185421
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 +1145 -0
- package/LICENSE +13 -0
- package/README.md +62 -0
- package/dist/index.d.ts +1188 -0
- package/dist/index.js +2522 -0
- package/dist/index.js.map +1 -0
- package/package.json +80 -0
- package/src/create-language-model-tool-result-output.ts +85 -0
- package/src/do-stream-step.ts +265 -0
- package/src/index.ts +49 -0
- package/src/normalize-ui-message-stream.ts +164 -0
- package/src/providers/mock-function-wrapper.ts +11 -0
- package/src/providers/mock.ts +110 -0
- package/src/serializable-schema.ts +114 -0
- package/src/stream-text-iterator.ts +661 -0
- package/src/test/agent-e2e-workflows.ts +673 -0
- package/src/test/calculate-workflow.ts +19 -0
- package/src/test/test-sandbox.ts +26 -0
- package/src/to-ui-message-chunk.ts +238 -0
- package/src/types.ts +11 -0
- package/src/workflow-agent.ts +2930 -0
- package/src/workflow-chat-transport.ts +534 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2522 @@
|
|
|
1
|
+
// src/workflow-agent.ts
|
|
2
|
+
import {
|
|
3
|
+
getErrorMessage,
|
|
4
|
+
validateTypes,
|
|
5
|
+
withUserAgentSuffix
|
|
6
|
+
} from "@ai-sdk/provider-utils";
|
|
7
|
+
import {
|
|
8
|
+
Output,
|
|
9
|
+
experimental_filterActiveTools as filterActiveTools2
|
|
10
|
+
} from "ai";
|
|
11
|
+
import {
|
|
12
|
+
createRestrictedTelemetryDispatcher as createRestrictedTelemetryDispatcher2,
|
|
13
|
+
collectToolApprovals,
|
|
14
|
+
convertToLanguageModelPrompt,
|
|
15
|
+
mergeAbortSignals,
|
|
16
|
+
mergeCallbacks,
|
|
17
|
+
standardizePrompt,
|
|
18
|
+
validateApprovedToolApprovals
|
|
19
|
+
} from "ai/internal";
|
|
20
|
+
|
|
21
|
+
// src/create-language-model-tool-result-output.ts
|
|
22
|
+
import {
|
|
23
|
+
createDefaultDownloadFunction,
|
|
24
|
+
createToolModelOutput,
|
|
25
|
+
downloadAssets,
|
|
26
|
+
mapToolResultOutput
|
|
27
|
+
} from "ai/internal";
|
|
28
|
+
async function createLanguageModelToolResultOutput({
|
|
29
|
+
toolCallId,
|
|
30
|
+
toolName,
|
|
31
|
+
input,
|
|
32
|
+
output,
|
|
33
|
+
tool: tool2,
|
|
34
|
+
errorMode,
|
|
35
|
+
supportedUrls,
|
|
36
|
+
download = createDefaultDownloadFunction(),
|
|
37
|
+
provider
|
|
38
|
+
}) {
|
|
39
|
+
const modelOutput = await createToolModelOutput({
|
|
40
|
+
toolCallId,
|
|
41
|
+
input,
|
|
42
|
+
output,
|
|
43
|
+
tool: tool2,
|
|
44
|
+
errorMode
|
|
45
|
+
});
|
|
46
|
+
const downloadedAssets = modelOutput.type === "content" ? await downloadAssets(
|
|
47
|
+
[
|
|
48
|
+
{
|
|
49
|
+
role: "tool",
|
|
50
|
+
content: [
|
|
51
|
+
{
|
|
52
|
+
type: "tool-result",
|
|
53
|
+
toolCallId,
|
|
54
|
+
toolName,
|
|
55
|
+
output: modelOutput
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
download,
|
|
61
|
+
supportedUrls
|
|
62
|
+
) : {};
|
|
63
|
+
return mapToolResultOutput({
|
|
64
|
+
output: modelOutput,
|
|
65
|
+
provider,
|
|
66
|
+
downloadedAssets
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/stream-text-iterator.ts
|
|
71
|
+
import {
|
|
72
|
+
experimental_filterActiveTools as filterActiveTools
|
|
73
|
+
} from "ai";
|
|
74
|
+
import { createRestrictedTelemetryDispatcher } from "ai/internal";
|
|
75
|
+
|
|
76
|
+
// src/do-stream-step.ts
|
|
77
|
+
import {
|
|
78
|
+
experimental_streamLanguageModelCall as streamModelCall,
|
|
79
|
+
gateway
|
|
80
|
+
} from "ai";
|
|
81
|
+
|
|
82
|
+
// src/serializable-schema.ts
|
|
83
|
+
import { asSchema, jsonSchema } from "@ai-sdk/provider-utils";
|
|
84
|
+
import { tool } from "ai";
|
|
85
|
+
import Ajv from "ajv";
|
|
86
|
+
function serializeToolSet(tools) {
|
|
87
|
+
return Object.fromEntries(
|
|
88
|
+
Object.entries(tools).map(([name, t]) => {
|
|
89
|
+
var _a;
|
|
90
|
+
const def = {
|
|
91
|
+
description: t.description,
|
|
92
|
+
// TODO support tools with function descriptions
|
|
93
|
+
inputSchema: asSchema(t.inputSchema).jsonSchema
|
|
94
|
+
};
|
|
95
|
+
if (t.type === "provider") {
|
|
96
|
+
def.type = "provider";
|
|
97
|
+
def.isProviderExecuted = (_a = t.isProviderExecuted) != null ? _a : false;
|
|
98
|
+
def.id = t.id;
|
|
99
|
+
def.args = t.args;
|
|
100
|
+
}
|
|
101
|
+
return [name, def];
|
|
102
|
+
})
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
function resolveSerializableTools(tools) {
|
|
106
|
+
const ajv = new Ajv();
|
|
107
|
+
return Object.fromEntries(
|
|
108
|
+
Object.entries(tools).map(([name, t]) => {
|
|
109
|
+
var _a, _b;
|
|
110
|
+
if (t.type === "provider") {
|
|
111
|
+
return [
|
|
112
|
+
name,
|
|
113
|
+
tool({
|
|
114
|
+
type: "provider",
|
|
115
|
+
id: t.id,
|
|
116
|
+
args: (_a = t.args) != null ? _a : {},
|
|
117
|
+
isProviderExecuted: (_b = t.isProviderExecuted) != null ? _b : false,
|
|
118
|
+
inputSchema: jsonSchema(t.inputSchema)
|
|
119
|
+
})
|
|
120
|
+
];
|
|
121
|
+
}
|
|
122
|
+
const validateFn = ajv.compile(t.inputSchema);
|
|
123
|
+
return [
|
|
124
|
+
name,
|
|
125
|
+
tool({
|
|
126
|
+
description: t.description,
|
|
127
|
+
inputSchema: jsonSchema(t.inputSchema, {
|
|
128
|
+
validate: (value) => {
|
|
129
|
+
if (validateFn(value)) {
|
|
130
|
+
return { success: true, value };
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
success: false,
|
|
134
|
+
error: new Error(ajv.errorsText(validateFn.errors))
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
];
|
|
140
|
+
})
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/do-stream-step.ts
|
|
145
|
+
async function doStreamStep(conversationPrompt, modelInit, writable, serializedTools, options) {
|
|
146
|
+
"use step";
|
|
147
|
+
const model = typeof modelInit === "string" ? gateway.languageModel(modelInit) : modelInit;
|
|
148
|
+
const tools = serializedTools ? resolveSerializableTools(serializedTools) : void 0;
|
|
149
|
+
const { stream: modelStream } = await streamModelCall({
|
|
150
|
+
model,
|
|
151
|
+
// streamModelCall expects Prompt (ModelMessage[]) but we pass the
|
|
152
|
+
// pre-converted LanguageModelV4Prompt. standardizePrompt inside
|
|
153
|
+
// streamModelCall handles both formats.
|
|
154
|
+
messages: conversationPrompt,
|
|
155
|
+
allowSystemInMessages: true,
|
|
156
|
+
tools,
|
|
157
|
+
toolChoice: options == null ? void 0 : options.toolChoice,
|
|
158
|
+
includeRawChunks: options == null ? void 0 : options.includeRawChunks,
|
|
159
|
+
providerOptions: options == null ? void 0 : options.providerOptions,
|
|
160
|
+
abortSignal: options == null ? void 0 : options.abortSignal,
|
|
161
|
+
headers: options == null ? void 0 : options.headers,
|
|
162
|
+
reasoning: options == null ? void 0 : options.reasoning,
|
|
163
|
+
maxOutputTokens: options == null ? void 0 : options.maxOutputTokens,
|
|
164
|
+
temperature: options == null ? void 0 : options.temperature,
|
|
165
|
+
topP: options == null ? void 0 : options.topP,
|
|
166
|
+
topK: options == null ? void 0 : options.topK,
|
|
167
|
+
presencePenalty: options == null ? void 0 : options.presencePenalty,
|
|
168
|
+
frequencyPenalty: options == null ? void 0 : options.frequencyPenalty,
|
|
169
|
+
stopSequences: options == null ? void 0 : options.stopSequences,
|
|
170
|
+
seed: options == null ? void 0 : options.seed,
|
|
171
|
+
repairToolCall: options == null ? void 0 : options.repairToolCall
|
|
172
|
+
});
|
|
173
|
+
const toolCalls = [];
|
|
174
|
+
const providerExecutedToolResults = /* @__PURE__ */ new Map();
|
|
175
|
+
let finish;
|
|
176
|
+
let text = "";
|
|
177
|
+
const reasoningParts = [];
|
|
178
|
+
let responseMetadata;
|
|
179
|
+
let warnings;
|
|
180
|
+
const writer = writable == null ? void 0 : writable.getWriter();
|
|
181
|
+
try {
|
|
182
|
+
for await (const part of modelStream) {
|
|
183
|
+
switch (part.type) {
|
|
184
|
+
case "text-delta":
|
|
185
|
+
text += part.text;
|
|
186
|
+
break;
|
|
187
|
+
case "reasoning-delta":
|
|
188
|
+
reasoningParts.push({ text: part.text });
|
|
189
|
+
break;
|
|
190
|
+
case "tool-call": {
|
|
191
|
+
const toolCallPart = part;
|
|
192
|
+
toolCalls.push({
|
|
193
|
+
type: "tool-call",
|
|
194
|
+
toolCallId: toolCallPart.toolCallId,
|
|
195
|
+
toolName: toolCallPart.toolName,
|
|
196
|
+
input: toolCallPart.input,
|
|
197
|
+
providerExecuted: toolCallPart.providerExecuted,
|
|
198
|
+
providerMetadata: toolCallPart.providerMetadata,
|
|
199
|
+
dynamic: toolCallPart.dynamic,
|
|
200
|
+
invalid: toolCallPart.invalid,
|
|
201
|
+
error: toolCallPart.error
|
|
202
|
+
});
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
case "tool-result":
|
|
206
|
+
if (part.providerExecuted) {
|
|
207
|
+
providerExecutedToolResults.set(part.toolCallId, {
|
|
208
|
+
toolCallId: part.toolCallId,
|
|
209
|
+
toolName: part.toolName,
|
|
210
|
+
result: part.output,
|
|
211
|
+
isError: false
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
break;
|
|
215
|
+
case "tool-error": {
|
|
216
|
+
const errorPart = part;
|
|
217
|
+
if (errorPart.providerExecuted) {
|
|
218
|
+
providerExecutedToolResults.set(errorPart.toolCallId, {
|
|
219
|
+
toolCallId: errorPart.toolCallId,
|
|
220
|
+
toolName: errorPart.toolName,
|
|
221
|
+
result: errorPart.error,
|
|
222
|
+
isError: true
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
case "model-call-end":
|
|
228
|
+
finish = {
|
|
229
|
+
finishReason: part.finishReason,
|
|
230
|
+
rawFinishReason: part.rawFinishReason,
|
|
231
|
+
usage: part.usage,
|
|
232
|
+
providerMetadata: part.providerMetadata
|
|
233
|
+
};
|
|
234
|
+
break;
|
|
235
|
+
case "model-call-start":
|
|
236
|
+
warnings = part.warnings;
|
|
237
|
+
break;
|
|
238
|
+
case "model-call-response-metadata":
|
|
239
|
+
responseMetadata = part;
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
if (writer) {
|
|
243
|
+
await writer.write(part);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
} finally {
|
|
247
|
+
writer == null ? void 0 : writer.releaseLock();
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
toolCalls,
|
|
251
|
+
finish,
|
|
252
|
+
raw: {
|
|
253
|
+
text,
|
|
254
|
+
reasoning: reasoningParts,
|
|
255
|
+
responseMetadata,
|
|
256
|
+
warnings
|
|
257
|
+
},
|
|
258
|
+
providerExecutedToolResults
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// src/stream-text-iterator.ts
|
|
263
|
+
async function* streamTextIterator({
|
|
264
|
+
prompt,
|
|
265
|
+
tools = {},
|
|
266
|
+
writable,
|
|
267
|
+
model,
|
|
268
|
+
stopConditions,
|
|
269
|
+
onStepEnd,
|
|
270
|
+
onStepFinish,
|
|
271
|
+
onStepStart,
|
|
272
|
+
onError,
|
|
273
|
+
prepareStep,
|
|
274
|
+
generationSettings,
|
|
275
|
+
toolChoice,
|
|
276
|
+
runtimeContext,
|
|
277
|
+
toolsContext,
|
|
278
|
+
telemetry,
|
|
279
|
+
includeRawChunks = false,
|
|
280
|
+
repairToolCall,
|
|
281
|
+
responseFormat,
|
|
282
|
+
experimental_sandbox: sandbox
|
|
283
|
+
}) {
|
|
284
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
285
|
+
let conversationPrompt = [...prompt];
|
|
286
|
+
let currentModel = model;
|
|
287
|
+
let currentGenerationSettings = generationSettings != null ? generationSettings : {};
|
|
288
|
+
let currentToolChoice = toolChoice;
|
|
289
|
+
let currentRuntimeContext = runtimeContext != null ? runtimeContext : {};
|
|
290
|
+
let currentToolsContext = toolsContext != null ? toolsContext : {};
|
|
291
|
+
let currentActiveTools;
|
|
292
|
+
const steps = [];
|
|
293
|
+
let done = false;
|
|
294
|
+
let _isFirstIteration = true;
|
|
295
|
+
let stepNumber = 0;
|
|
296
|
+
let lastStep;
|
|
297
|
+
let lastStepWasToolCalls = false;
|
|
298
|
+
const telemetryDispatcher = createRestrictedTelemetryDispatcher({
|
|
299
|
+
telemetry,
|
|
300
|
+
includeRuntimeContext: telemetry == null ? void 0 : telemetry.includeRuntimeContext,
|
|
301
|
+
includeToolsContext: telemetry == null ? void 0 : telemetry.includeToolsContext
|
|
302
|
+
});
|
|
303
|
+
while (!done) {
|
|
304
|
+
if ((_a = currentGenerationSettings.abortSignal) == null ? void 0 : _a.aborted) {
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
let stepSandbox = sandbox;
|
|
308
|
+
if (prepareStep) {
|
|
309
|
+
const prepareResult = await prepareStep({
|
|
310
|
+
model: currentModel,
|
|
311
|
+
stepNumber,
|
|
312
|
+
steps,
|
|
313
|
+
messages: conversationPrompt,
|
|
314
|
+
runtimeContext: currentRuntimeContext,
|
|
315
|
+
toolsContext: currentToolsContext,
|
|
316
|
+
experimental_sandbox: sandbox
|
|
317
|
+
});
|
|
318
|
+
stepSandbox = (_b = prepareResult == null ? void 0 : prepareResult.experimental_sandbox) != null ? _b : sandbox;
|
|
319
|
+
if ((prepareResult == null ? void 0 : prepareResult.model) !== void 0) {
|
|
320
|
+
currentModel = prepareResult.model;
|
|
321
|
+
}
|
|
322
|
+
if ((prepareResult == null ? void 0 : prepareResult.messages) !== void 0) {
|
|
323
|
+
conversationPrompt = [...prepareResult.messages];
|
|
324
|
+
}
|
|
325
|
+
if ((prepareResult == null ? void 0 : prepareResult.system) !== void 0) {
|
|
326
|
+
if (conversationPrompt.length > 0 && conversationPrompt[0].role === "system") {
|
|
327
|
+
conversationPrompt[0] = {
|
|
328
|
+
role: "system",
|
|
329
|
+
content: prepareResult.system
|
|
330
|
+
};
|
|
331
|
+
} else {
|
|
332
|
+
conversationPrompt.unshift({
|
|
333
|
+
role: "system",
|
|
334
|
+
content: prepareResult.system
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
if ((prepareResult == null ? void 0 : prepareResult.runtimeContext) !== void 0) {
|
|
339
|
+
currentRuntimeContext = prepareResult.runtimeContext;
|
|
340
|
+
}
|
|
341
|
+
if ((prepareResult == null ? void 0 : prepareResult.toolsContext) !== void 0) {
|
|
342
|
+
currentToolsContext = prepareResult.toolsContext;
|
|
343
|
+
}
|
|
344
|
+
if ((prepareResult == null ? void 0 : prepareResult.activeTools) !== void 0) {
|
|
345
|
+
currentActiveTools = prepareResult.activeTools;
|
|
346
|
+
}
|
|
347
|
+
if ((prepareResult == null ? void 0 : prepareResult.maxOutputTokens) !== void 0) {
|
|
348
|
+
currentGenerationSettings = {
|
|
349
|
+
...currentGenerationSettings,
|
|
350
|
+
maxOutputTokens: prepareResult.maxOutputTokens
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
if ((prepareResult == null ? void 0 : prepareResult.temperature) !== void 0) {
|
|
354
|
+
currentGenerationSettings = {
|
|
355
|
+
...currentGenerationSettings,
|
|
356
|
+
temperature: prepareResult.temperature
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
if ((prepareResult == null ? void 0 : prepareResult.topP) !== void 0) {
|
|
360
|
+
currentGenerationSettings = {
|
|
361
|
+
...currentGenerationSettings,
|
|
362
|
+
topP: prepareResult.topP
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
if ((prepareResult == null ? void 0 : prepareResult.topK) !== void 0) {
|
|
366
|
+
currentGenerationSettings = {
|
|
367
|
+
...currentGenerationSettings,
|
|
368
|
+
topK: prepareResult.topK
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
if ((prepareResult == null ? void 0 : prepareResult.presencePenalty) !== void 0) {
|
|
372
|
+
currentGenerationSettings = {
|
|
373
|
+
...currentGenerationSettings,
|
|
374
|
+
presencePenalty: prepareResult.presencePenalty
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
if ((prepareResult == null ? void 0 : prepareResult.frequencyPenalty) !== void 0) {
|
|
378
|
+
currentGenerationSettings = {
|
|
379
|
+
...currentGenerationSettings,
|
|
380
|
+
frequencyPenalty: prepareResult.frequencyPenalty
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
if ((prepareResult == null ? void 0 : prepareResult.stopSequences) !== void 0) {
|
|
384
|
+
currentGenerationSettings = {
|
|
385
|
+
...currentGenerationSettings,
|
|
386
|
+
stopSequences: prepareResult.stopSequences
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
if ((prepareResult == null ? void 0 : prepareResult.seed) !== void 0) {
|
|
390
|
+
currentGenerationSettings = {
|
|
391
|
+
...currentGenerationSettings,
|
|
392
|
+
seed: prepareResult.seed
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
if ((prepareResult == null ? void 0 : prepareResult.maxRetries) !== void 0) {
|
|
396
|
+
currentGenerationSettings = {
|
|
397
|
+
...currentGenerationSettings,
|
|
398
|
+
maxRetries: prepareResult.maxRetries
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
if ((prepareResult == null ? void 0 : prepareResult.headers) !== void 0) {
|
|
402
|
+
currentGenerationSettings = {
|
|
403
|
+
...currentGenerationSettings,
|
|
404
|
+
headers: prepareResult.headers
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
if ((prepareResult == null ? void 0 : prepareResult.reasoning) !== void 0) {
|
|
408
|
+
currentGenerationSettings = {
|
|
409
|
+
...currentGenerationSettings,
|
|
410
|
+
reasoning: prepareResult.reasoning
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
if ((prepareResult == null ? void 0 : prepareResult.providerOptions) !== void 0) {
|
|
414
|
+
currentGenerationSettings = {
|
|
415
|
+
...currentGenerationSettings,
|
|
416
|
+
providerOptions: prepareResult.providerOptions
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
if ((prepareResult == null ? void 0 : prepareResult.toolChoice) !== void 0) {
|
|
420
|
+
currentToolChoice = prepareResult.toolChoice;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
if (onStepStart) {
|
|
424
|
+
await onStepStart({
|
|
425
|
+
stepNumber,
|
|
426
|
+
model: currentModel,
|
|
427
|
+
messages: conversationPrompt,
|
|
428
|
+
steps: [...steps],
|
|
429
|
+
runtimeContext: currentRuntimeContext,
|
|
430
|
+
toolsContext: currentToolsContext
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
const stepStartModelInfo = getModelInfo(currentModel);
|
|
434
|
+
await ((_c = telemetryDispatcher.onStepStart) == null ? void 0 : _c.call(telemetryDispatcher, {
|
|
435
|
+
callId: "workflow-agent",
|
|
436
|
+
provider: stepStartModelInfo.provider,
|
|
437
|
+
modelId: stepStartModelInfo.modelId,
|
|
438
|
+
stepNumber,
|
|
439
|
+
system: void 0,
|
|
440
|
+
messages: conversationPrompt,
|
|
441
|
+
tools,
|
|
442
|
+
toolChoice: currentToolChoice,
|
|
443
|
+
activeTools: currentActiveTools,
|
|
444
|
+
steps: steps.map(normalizeStepForTelemetry),
|
|
445
|
+
providerOptions: currentGenerationSettings.providerOptions,
|
|
446
|
+
output: void 0,
|
|
447
|
+
runtimeContext: currentRuntimeContext,
|
|
448
|
+
toolsContext: currentToolsContext
|
|
449
|
+
}));
|
|
450
|
+
try {
|
|
451
|
+
const effectiveTools = currentActiveTools && currentActiveTools.length > 0 ? (_d = filterActiveTools({
|
|
452
|
+
tools,
|
|
453
|
+
activeTools: currentActiveTools
|
|
454
|
+
})) != null ? _d : tools : tools;
|
|
455
|
+
const serializedTools = serializeToolSet(effectiveTools);
|
|
456
|
+
const modelCallInfo = getModelInfo(currentModel);
|
|
457
|
+
await ((_e = telemetryDispatcher.onLanguageModelCallStart) == null ? void 0 : _e.call(telemetryDispatcher, {
|
|
458
|
+
callId: "workflow-agent",
|
|
459
|
+
provider: modelCallInfo.provider,
|
|
460
|
+
modelId: modelCallInfo.modelId,
|
|
461
|
+
system: void 0,
|
|
462
|
+
messages: conversationPrompt,
|
|
463
|
+
tools: serializedTools == null ? void 0 : Object.values(serializedTools).map((tool2) => ({ ...tool2 })),
|
|
464
|
+
maxOutputTokens: currentGenerationSettings.maxOutputTokens,
|
|
465
|
+
temperature: currentGenerationSettings.temperature,
|
|
466
|
+
topP: currentGenerationSettings.topP,
|
|
467
|
+
topK: currentGenerationSettings.topK,
|
|
468
|
+
presencePenalty: currentGenerationSettings.presencePenalty,
|
|
469
|
+
frequencyPenalty: currentGenerationSettings.frequencyPenalty,
|
|
470
|
+
stopSequences: currentGenerationSettings.stopSequences,
|
|
471
|
+
seed: currentGenerationSettings.seed,
|
|
472
|
+
reasoning: currentGenerationSettings.reasoning,
|
|
473
|
+
providerOptions: currentGenerationSettings.providerOptions,
|
|
474
|
+
headers: currentGenerationSettings.headers
|
|
475
|
+
}));
|
|
476
|
+
const { toolCalls, finish, raw, providerExecutedToolResults } = await doStreamStep(
|
|
477
|
+
conversationPrompt,
|
|
478
|
+
currentModel,
|
|
479
|
+
writable,
|
|
480
|
+
serializedTools,
|
|
481
|
+
{
|
|
482
|
+
...currentGenerationSettings,
|
|
483
|
+
toolChoice: currentToolChoice,
|
|
484
|
+
includeRawChunks,
|
|
485
|
+
repairToolCall,
|
|
486
|
+
responseFormat
|
|
487
|
+
}
|
|
488
|
+
);
|
|
489
|
+
const step = buildStepResult(raw, toolCalls, finish, {
|
|
490
|
+
stepNumber,
|
|
491
|
+
runtimeContext: currentRuntimeContext,
|
|
492
|
+
toolsContext: currentToolsContext
|
|
493
|
+
});
|
|
494
|
+
await ((_j = telemetryDispatcher.onLanguageModelCallEnd) == null ? void 0 : _j.call(telemetryDispatcher, {
|
|
495
|
+
callId: step.callId,
|
|
496
|
+
provider: (_g = (_f = step.model) == null ? void 0 : _f.provider) != null ? _g : "unknown",
|
|
497
|
+
modelId: (_i = (_h = step.model) == null ? void 0 : _h.modelId) != null ? _i : "unknown",
|
|
498
|
+
finishReason: step.finishReason,
|
|
499
|
+
usage: step.usage,
|
|
500
|
+
content: step.content,
|
|
501
|
+
responseId: step.response.id
|
|
502
|
+
}));
|
|
503
|
+
_isFirstIteration = false;
|
|
504
|
+
stepNumber++;
|
|
505
|
+
steps.push(step);
|
|
506
|
+
lastStep = step;
|
|
507
|
+
lastStepWasToolCalls = false;
|
|
508
|
+
const finishReason = finish == null ? void 0 : finish.finishReason;
|
|
509
|
+
if (finishReason === "tool-calls") {
|
|
510
|
+
lastStepWasToolCalls = true;
|
|
511
|
+
conversationPrompt.push({
|
|
512
|
+
role: "assistant",
|
|
513
|
+
content: toolCalls.map((toolCall) => {
|
|
514
|
+
const sanitizedMetadata = sanitizeProviderMetadataForToolCall(
|
|
515
|
+
toolCall.providerMetadata
|
|
516
|
+
);
|
|
517
|
+
return {
|
|
518
|
+
type: "tool-call",
|
|
519
|
+
toolCallId: toolCall.toolCallId,
|
|
520
|
+
toolName: toolCall.toolName,
|
|
521
|
+
input: toolCall.input,
|
|
522
|
+
...sanitizedMetadata != null ? { providerOptions: sanitizedMetadata } : {}
|
|
523
|
+
};
|
|
524
|
+
})
|
|
525
|
+
});
|
|
526
|
+
const toolResults = yield {
|
|
527
|
+
toolCalls,
|
|
528
|
+
messages: conversationPrompt,
|
|
529
|
+
step,
|
|
530
|
+
runtimeContext: currentRuntimeContext,
|
|
531
|
+
toolsContext: currentToolsContext,
|
|
532
|
+
experimental_sandbox: stepSandbox,
|
|
533
|
+
providerExecutedToolResults
|
|
534
|
+
};
|
|
535
|
+
conversationPrompt.push({
|
|
536
|
+
role: "tool",
|
|
537
|
+
content: toolResults
|
|
538
|
+
});
|
|
539
|
+
if (stopConditions) {
|
|
540
|
+
const stopConditionList = Array.isArray(stopConditions) ? stopConditions : [stopConditions];
|
|
541
|
+
if (stopConditionList.some((test) => test({ steps }))) {
|
|
542
|
+
done = true;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
} else if (finishReason === "stop") {
|
|
546
|
+
const textContent = step.content.filter(
|
|
547
|
+
(item) => item.type === "text"
|
|
548
|
+
);
|
|
549
|
+
if (textContent.length > 0) {
|
|
550
|
+
conversationPrompt.push({
|
|
551
|
+
role: "assistant",
|
|
552
|
+
content: textContent
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
done = true;
|
|
556
|
+
} else if (finishReason === "length") {
|
|
557
|
+
done = true;
|
|
558
|
+
} else if (finishReason === "content-filter") {
|
|
559
|
+
done = true;
|
|
560
|
+
} else if (finishReason === "error") {
|
|
561
|
+
done = true;
|
|
562
|
+
} else if (finishReason === "other") {
|
|
563
|
+
done = true;
|
|
564
|
+
} else if (finishReason === "unknown") {
|
|
565
|
+
done = true;
|
|
566
|
+
} else if (!finishReason) {
|
|
567
|
+
done = true;
|
|
568
|
+
} else {
|
|
569
|
+
throw new Error(
|
|
570
|
+
`Unexpected finish reason: ${typeof (finish == null ? void 0 : finish.finishReason) === "object" ? JSON.stringify(finish == null ? void 0 : finish.finishReason) : finish == null ? void 0 : finish.finishReason}`
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
const resolvedOnStepEnd = onStepEnd != null ? onStepEnd : onStepFinish;
|
|
574
|
+
if (resolvedOnStepEnd) {
|
|
575
|
+
await resolvedOnStepEnd(step);
|
|
576
|
+
}
|
|
577
|
+
await ((_k = telemetryDispatcher.onStepEnd) == null ? void 0 : _k.call(telemetryDispatcher, normalizeStepForTelemetry(step)));
|
|
578
|
+
} catch (error) {
|
|
579
|
+
if (onError) {
|
|
580
|
+
await onError({ error });
|
|
581
|
+
}
|
|
582
|
+
throw error;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
if (lastStep && !lastStepWasToolCalls) {
|
|
586
|
+
yield {
|
|
587
|
+
toolCalls: [],
|
|
588
|
+
messages: conversationPrompt,
|
|
589
|
+
step: lastStep,
|
|
590
|
+
runtimeContext: currentRuntimeContext,
|
|
591
|
+
toolsContext: currentToolsContext,
|
|
592
|
+
experimental_sandbox: sandbox
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
return conversationPrompt;
|
|
596
|
+
}
|
|
597
|
+
function getModelInfo(model) {
|
|
598
|
+
var _a;
|
|
599
|
+
return typeof model === "string" ? { provider: (_a = model.split("/")[0]) != null ? _a : "gateway", modelId: model } : { provider: model.provider, modelId: model.modelId };
|
|
600
|
+
}
|
|
601
|
+
function normalizeStepForTelemetry(step) {
|
|
602
|
+
var _a;
|
|
603
|
+
return {
|
|
604
|
+
...step,
|
|
605
|
+
model: (_a = step.model) != null ? _a : { provider: "unknown", modelId: "unknown" }
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
function buildStepResult(raw, toolCalls, finish, opts) {
|
|
609
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
610
|
+
const { text, reasoning: reasoningParts, responseMetadata, warnings } = raw;
|
|
611
|
+
const reasoningText = reasoningParts.map((r) => r.text).join("") || void 0;
|
|
612
|
+
const validToolCalls = toolCalls.filter((tc) => !tc.invalid).map((tc) => ({
|
|
613
|
+
type: "tool-call",
|
|
614
|
+
toolCallId: tc.toolCallId,
|
|
615
|
+
toolName: tc.toolName,
|
|
616
|
+
input: tc.input,
|
|
617
|
+
...tc.dynamic ? { dynamic: true } : {}
|
|
618
|
+
}));
|
|
619
|
+
return {
|
|
620
|
+
callId: "workflow-agent",
|
|
621
|
+
stepNumber: opts.stepNumber,
|
|
622
|
+
model: {
|
|
623
|
+
provider: (_b = (_a = responseMetadata == null ? void 0 : responseMetadata.modelId) == null ? void 0 : _a.split(":")[0]) != null ? _b : "unknown",
|
|
624
|
+
modelId: (_c = responseMetadata == null ? void 0 : responseMetadata.modelId) != null ? _c : "unknown"
|
|
625
|
+
},
|
|
626
|
+
functionId: void 0,
|
|
627
|
+
metadata: void 0,
|
|
628
|
+
runtimeContext: (_d = opts.runtimeContext) != null ? _d : {},
|
|
629
|
+
toolsContext: (_e = opts.toolsContext) != null ? _e : {},
|
|
630
|
+
content: [
|
|
631
|
+
...text ? [{ type: "text", text }] : [],
|
|
632
|
+
...validToolCalls
|
|
633
|
+
],
|
|
634
|
+
text,
|
|
635
|
+
reasoning: reasoningParts.map((r) => ({
|
|
636
|
+
type: "reasoning",
|
|
637
|
+
text: r.text
|
|
638
|
+
})),
|
|
639
|
+
reasoningText,
|
|
640
|
+
files: [],
|
|
641
|
+
sources: [],
|
|
642
|
+
toolCalls: validToolCalls,
|
|
643
|
+
staticToolCalls: [],
|
|
644
|
+
dynamicToolCalls: validToolCalls.filter((tc) => tc.dynamic),
|
|
645
|
+
toolResults: [],
|
|
646
|
+
staticToolResults: [],
|
|
647
|
+
dynamicToolResults: [],
|
|
648
|
+
finishReason: (_f = finish == null ? void 0 : finish.finishReason) != null ? _f : "other",
|
|
649
|
+
rawFinishReason: finish == null ? void 0 : finish.rawFinishReason,
|
|
650
|
+
usage: (_g = finish == null ? void 0 : finish.usage) != null ? _g : {
|
|
651
|
+
inputTokens: 0,
|
|
652
|
+
inputTokenDetails: {
|
|
653
|
+
noCacheTokens: void 0,
|
|
654
|
+
cacheReadTokens: void 0,
|
|
655
|
+
cacheWriteTokens: void 0
|
|
656
|
+
},
|
|
657
|
+
outputTokens: 0,
|
|
658
|
+
outputTokenDetails: {
|
|
659
|
+
textTokens: void 0,
|
|
660
|
+
reasoningTokens: void 0
|
|
661
|
+
},
|
|
662
|
+
totalTokens: 0
|
|
663
|
+
},
|
|
664
|
+
performance: {
|
|
665
|
+
effectiveOutputTokensPerSecond: 0,
|
|
666
|
+
outputTokensPerSecond: void 0,
|
|
667
|
+
inputTokensPerSecond: void 0,
|
|
668
|
+
effectiveTotalTokensPerSecond: 0,
|
|
669
|
+
stepTimeMs: 0,
|
|
670
|
+
responseTimeMs: 0,
|
|
671
|
+
toolExecutionMs: {},
|
|
672
|
+
timeToFirstOutputMs: void 0
|
|
673
|
+
},
|
|
674
|
+
warnings,
|
|
675
|
+
request: {
|
|
676
|
+
body: "",
|
|
677
|
+
messages: []
|
|
678
|
+
// TODO implement step request messages
|
|
679
|
+
},
|
|
680
|
+
response: {
|
|
681
|
+
id: (_h = responseMetadata == null ? void 0 : responseMetadata.id) != null ? _h : "unknown",
|
|
682
|
+
timestamp: (_i = responseMetadata == null ? void 0 : responseMetadata.timestamp) != null ? _i : /* @__PURE__ */ new Date(),
|
|
683
|
+
modelId: (_j = responseMetadata == null ? void 0 : responseMetadata.modelId) != null ? _j : "unknown",
|
|
684
|
+
messages: []
|
|
685
|
+
},
|
|
686
|
+
providerMetadata: (_k = finish == null ? void 0 : finish.providerMetadata) != null ? _k : {}
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
function sanitizeProviderMetadataForToolCall(metadata) {
|
|
690
|
+
if (metadata == null) return void 0;
|
|
691
|
+
const meta = metadata;
|
|
692
|
+
if ("openai" in meta && meta.openai != null) {
|
|
693
|
+
const { openai, ...restProviders } = meta;
|
|
694
|
+
const openaiMeta = openai;
|
|
695
|
+
const { itemId: _itemId, ...restOpenai } = openaiMeta;
|
|
696
|
+
const hasOtherOpenaiFields = Object.keys(restOpenai).length > 0;
|
|
697
|
+
const hasOtherProviders = Object.keys(restProviders).length > 0;
|
|
698
|
+
if (hasOtherOpenaiFields && hasOtherProviders) {
|
|
699
|
+
return { ...restProviders, openai: restOpenai };
|
|
700
|
+
} else if (hasOtherOpenaiFields) {
|
|
701
|
+
return { openai: restOpenai };
|
|
702
|
+
} else if (hasOtherProviders) {
|
|
703
|
+
return restProviders;
|
|
704
|
+
}
|
|
705
|
+
return void 0;
|
|
706
|
+
}
|
|
707
|
+
return meta;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// src/workflow-agent.ts
|
|
711
|
+
var WorkflowAgent = class {
|
|
712
|
+
constructor(options) {
|
|
713
|
+
var _a, _b, _c, _d, _e;
|
|
714
|
+
this.id = options.id;
|
|
715
|
+
this.model = options.model;
|
|
716
|
+
this.tools = (_a = options.tools) != null ? _a : {};
|
|
717
|
+
this.instructions = (_b = options.instructions) != null ? _b : options.system;
|
|
718
|
+
this.toolChoice = options.toolChoice;
|
|
719
|
+
this.telemetry = options.telemetry;
|
|
720
|
+
this.runtimeContext = options.runtimeContext;
|
|
721
|
+
this.toolsContext = options.toolsContext;
|
|
722
|
+
this.stopWhen = options.stopWhen;
|
|
723
|
+
this.activeTools = options.activeTools;
|
|
724
|
+
this.output = options.output;
|
|
725
|
+
this.repairToolCall = (_c = options.repairToolCall) != null ? _c : options.experimental_repairToolCall;
|
|
726
|
+
this.experimentalDownload = options.experimental_download;
|
|
727
|
+
this.experimentalSandbox = options.experimental_sandbox;
|
|
728
|
+
this.prepareStep = options.prepareStep;
|
|
729
|
+
this.constructorOnStepEnd = (_d = options.onStepEnd) != null ? _d : options.onStepFinish;
|
|
730
|
+
const { onFinish, onEnd = onFinish } = options;
|
|
731
|
+
this.constructorOnEnd = onEnd;
|
|
732
|
+
this.constructorOnStart = options.experimental_onStart;
|
|
733
|
+
this.constructorOnStepStart = options.experimental_onStepStart;
|
|
734
|
+
this.constructorOnToolExecutionStart = options.onToolExecutionStart;
|
|
735
|
+
this.constructorOnToolExecutionEnd = options.onToolExecutionEnd;
|
|
736
|
+
this.prepareCall = options.prepareCall;
|
|
737
|
+
this.allowSystemInMessages = (_e = options.allowSystemInMessages) != null ? _e : false;
|
|
738
|
+
this.generationSettings = {
|
|
739
|
+
maxOutputTokens: options.maxOutputTokens,
|
|
740
|
+
temperature: options.temperature,
|
|
741
|
+
topP: options.topP,
|
|
742
|
+
topK: options.topK,
|
|
743
|
+
presencePenalty: options.presencePenalty,
|
|
744
|
+
frequencyPenalty: options.frequencyPenalty,
|
|
745
|
+
stopSequences: options.stopSequences,
|
|
746
|
+
seed: options.seed,
|
|
747
|
+
maxRetries: options.maxRetries,
|
|
748
|
+
abortSignal: options.abortSignal,
|
|
749
|
+
headers: options.headers,
|
|
750
|
+
reasoning: options.reasoning,
|
|
751
|
+
providerOptions: options.providerOptions
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
generate() {
|
|
755
|
+
throw new Error("Not implemented");
|
|
756
|
+
}
|
|
757
|
+
async stream(options) {
|
|
758
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S;
|
|
759
|
+
const { onFinish, onEnd = onFinish } = options;
|
|
760
|
+
let effectiveModel = this.model;
|
|
761
|
+
let effectiveInstructions = (_a = options.system) != null ? _a : this.instructions;
|
|
762
|
+
let effectivePrompt = options.prompt;
|
|
763
|
+
let effectiveMessages = options.messages;
|
|
764
|
+
let effectiveGenerationSettings = { ...this.generationSettings };
|
|
765
|
+
let effectiveRuntimeContext = (_c = (_b = options.runtimeContext) != null ? _b : this.runtimeContext) != null ? _c : {};
|
|
766
|
+
let effectiveToolsContext = (_e = (_d = options.toolsContext) != null ? _d : this.toolsContext) != null ? _e : {};
|
|
767
|
+
let effectiveToolChoiceFromPrepare = (_f = options.toolChoice) != null ? _f : this.toolChoice;
|
|
768
|
+
let effectiveTelemetryFromPrepare = (_g = options.telemetry) != null ? _g : this.telemetry;
|
|
769
|
+
const resolvedMessagesForPrepareCall = (_h = effectiveMessages != null ? effectiveMessages : typeof effectivePrompt === "string" ? [{ role: "user", content: effectivePrompt }] : effectivePrompt) != null ? _h : [];
|
|
770
|
+
if (this.prepareCall) {
|
|
771
|
+
const prepared = await this.prepareCall({
|
|
772
|
+
model: effectiveModel,
|
|
773
|
+
tools: this.tools,
|
|
774
|
+
instructions: effectiveInstructions,
|
|
775
|
+
toolChoice: effectiveToolChoiceFromPrepare,
|
|
776
|
+
telemetry: effectiveTelemetryFromPrepare,
|
|
777
|
+
runtimeContext: effectiveRuntimeContext,
|
|
778
|
+
toolsContext: effectiveToolsContext,
|
|
779
|
+
messages: resolvedMessagesForPrepareCall,
|
|
780
|
+
...effectiveGenerationSettings
|
|
781
|
+
});
|
|
782
|
+
if (prepared.model !== void 0) effectiveModel = prepared.model;
|
|
783
|
+
if (prepared.instructions !== void 0)
|
|
784
|
+
effectiveInstructions = prepared.instructions;
|
|
785
|
+
if (prepared.messages !== void 0) {
|
|
786
|
+
effectiveMessages = prepared.messages;
|
|
787
|
+
effectivePrompt = void 0;
|
|
788
|
+
}
|
|
789
|
+
if (prepared.runtimeContext !== void 0)
|
|
790
|
+
effectiveRuntimeContext = prepared.runtimeContext;
|
|
791
|
+
if (prepared.toolsContext !== void 0)
|
|
792
|
+
effectiveToolsContext = prepared.toolsContext;
|
|
793
|
+
if (prepared.toolChoice !== void 0)
|
|
794
|
+
effectiveToolChoiceFromPrepare = prepared.toolChoice;
|
|
795
|
+
if (prepared.telemetry !== void 0)
|
|
796
|
+
effectiveTelemetryFromPrepare = prepared.telemetry;
|
|
797
|
+
if (prepared.maxOutputTokens !== void 0)
|
|
798
|
+
effectiveGenerationSettings.maxOutputTokens = prepared.maxOutputTokens;
|
|
799
|
+
if (prepared.temperature !== void 0)
|
|
800
|
+
effectiveGenerationSettings.temperature = prepared.temperature;
|
|
801
|
+
if (prepared.topP !== void 0)
|
|
802
|
+
effectiveGenerationSettings.topP = prepared.topP;
|
|
803
|
+
if (prepared.topK !== void 0)
|
|
804
|
+
effectiveGenerationSettings.topK = prepared.topK;
|
|
805
|
+
if (prepared.presencePenalty !== void 0)
|
|
806
|
+
effectiveGenerationSettings.presencePenalty = prepared.presencePenalty;
|
|
807
|
+
if (prepared.frequencyPenalty !== void 0)
|
|
808
|
+
effectiveGenerationSettings.frequencyPenalty = prepared.frequencyPenalty;
|
|
809
|
+
if (prepared.stopSequences !== void 0)
|
|
810
|
+
effectiveGenerationSettings.stopSequences = prepared.stopSequences;
|
|
811
|
+
if (prepared.seed !== void 0)
|
|
812
|
+
effectiveGenerationSettings.seed = prepared.seed;
|
|
813
|
+
if (prepared.headers !== void 0)
|
|
814
|
+
effectiveGenerationSettings.headers = prepared.headers;
|
|
815
|
+
if (prepared.reasoning !== void 0)
|
|
816
|
+
effectiveGenerationSettings.reasoning = prepared.reasoning;
|
|
817
|
+
if (prepared.providerOptions !== void 0)
|
|
818
|
+
effectiveGenerationSettings.providerOptions = prepared.providerOptions;
|
|
819
|
+
}
|
|
820
|
+
const effectiveTelemetry = effectiveTelemetryFromPrepare;
|
|
821
|
+
const telemetryDispatcher = createRestrictedTelemetryDispatcher2({
|
|
822
|
+
telemetry: effectiveTelemetry,
|
|
823
|
+
includeRuntimeContext: effectiveTelemetry == null ? void 0 : effectiveTelemetry.includeRuntimeContext,
|
|
824
|
+
includeToolsContext: effectiveTelemetry == null ? void 0 : effectiveTelemetry.includeToolsContext
|
|
825
|
+
});
|
|
826
|
+
const prompt = await standardizePrompt({
|
|
827
|
+
system: effectiveInstructions,
|
|
828
|
+
allowSystemInMessages: this.allowSystemInMessages,
|
|
829
|
+
...effectivePrompt != null ? { prompt: effectivePrompt } : { messages: effectiveMessages }
|
|
830
|
+
});
|
|
831
|
+
const download = (_i = options.experimental_download) != null ? _i : this.experimentalDownload;
|
|
832
|
+
const sandbox = (_j = options.experimental_sandbox) != null ? _j : this.experimentalSandbox;
|
|
833
|
+
const collectedApprovals = collectToolApprovals({
|
|
834
|
+
messages: prompt.messages
|
|
835
|
+
});
|
|
836
|
+
const approvedToolApprovals = collectedApprovals.approvedToolApprovals.map(
|
|
837
|
+
(collected) => ({
|
|
838
|
+
toolCallId: collected.toolCall.toolCallId,
|
|
839
|
+
toolName: collected.toolCall.toolName,
|
|
840
|
+
input: collected.toolCall.input,
|
|
841
|
+
reason: collected.approvalResponse.reason,
|
|
842
|
+
providerExecuted: collected.toolCall.providerExecuted === true,
|
|
843
|
+
collected
|
|
844
|
+
})
|
|
845
|
+
);
|
|
846
|
+
const deniedToolApprovals = collectedApprovals.deniedToolApprovals.map(
|
|
847
|
+
(collected) => ({
|
|
848
|
+
toolCallId: collected.toolCall.toolCallId,
|
|
849
|
+
toolName: collected.toolCall.toolName,
|
|
850
|
+
input: collected.toolCall.input,
|
|
851
|
+
reason: collected.approvalResponse.reason,
|
|
852
|
+
providerExecuted: collected.toolCall.providerExecuted === true
|
|
853
|
+
})
|
|
854
|
+
);
|
|
855
|
+
const providerExecutedApprovalIds = new Set(
|
|
856
|
+
[
|
|
857
|
+
...collectedApprovals.approvedToolApprovals,
|
|
858
|
+
...collectedApprovals.deniedToolApprovals
|
|
859
|
+
].filter((collected) => collected.toolCall.providerExecuted === true).map((collected) => collected.approvalResponse.approvalId)
|
|
860
|
+
);
|
|
861
|
+
if (approvedToolApprovals.length > 0 || deniedToolApprovals.length > 0) {
|
|
862
|
+
const _toolResultMessages = [];
|
|
863
|
+
const toolResultContent = [];
|
|
864
|
+
const approvedRawResults = [];
|
|
865
|
+
for (const approval of approvedToolApprovals) {
|
|
866
|
+
if (approval.providerExecuted) {
|
|
867
|
+
continue;
|
|
868
|
+
}
|
|
869
|
+
const tool2 = this.tools[approval.toolName];
|
|
870
|
+
if (tool2 && typeof tool2.execute === "function") {
|
|
871
|
+
if (!tool2.needsApproval) {
|
|
872
|
+
const reason = `Tool "${approval.toolName}" does not require approval`;
|
|
873
|
+
toolResultContent.push({
|
|
874
|
+
type: "tool-result",
|
|
875
|
+
toolCallId: approval.toolCallId,
|
|
876
|
+
toolName: approval.toolName,
|
|
877
|
+
output: await createLanguageModelToolResultOutput({
|
|
878
|
+
toolCallId: approval.toolCallId,
|
|
879
|
+
toolName: approval.toolName,
|
|
880
|
+
input: approval.input,
|
|
881
|
+
output: reason,
|
|
882
|
+
tool: tool2,
|
|
883
|
+
errorMode: "text",
|
|
884
|
+
supportedUrls: {},
|
|
885
|
+
download
|
|
886
|
+
})
|
|
887
|
+
});
|
|
888
|
+
continue;
|
|
889
|
+
}
|
|
890
|
+
let revalidationReason;
|
|
891
|
+
try {
|
|
892
|
+
const { deniedToolApprovals: policyDenied } = await validateApprovedToolApprovals({
|
|
893
|
+
approvedToolApprovals: [approval.collected],
|
|
894
|
+
tools: this.tools,
|
|
895
|
+
toolApproval: void 0,
|
|
896
|
+
messages: prompt.messages,
|
|
897
|
+
toolsContext: effectiveToolsContext,
|
|
898
|
+
runtimeContext: effectiveRuntimeContext
|
|
899
|
+
});
|
|
900
|
+
if (policyDenied.length > 0) {
|
|
901
|
+
revalidationReason = (_k = policyDenied[0].approvalResponse.reason) != null ? _k : "Tool approval denied";
|
|
902
|
+
}
|
|
903
|
+
} catch (error) {
|
|
904
|
+
revalidationReason = getErrorMessage(error);
|
|
905
|
+
}
|
|
906
|
+
if (revalidationReason != null) {
|
|
907
|
+
toolResultContent.push({
|
|
908
|
+
type: "tool-result",
|
|
909
|
+
toolCallId: approval.toolCallId,
|
|
910
|
+
toolName: approval.toolName,
|
|
911
|
+
output: await createLanguageModelToolResultOutput({
|
|
912
|
+
toolCallId: approval.toolCallId,
|
|
913
|
+
toolName: approval.toolName,
|
|
914
|
+
input: approval.input,
|
|
915
|
+
output: revalidationReason,
|
|
916
|
+
tool: tool2,
|
|
917
|
+
errorMode: "text",
|
|
918
|
+
supportedUrls: {},
|
|
919
|
+
download
|
|
920
|
+
})
|
|
921
|
+
});
|
|
922
|
+
continue;
|
|
923
|
+
}
|
|
924
|
+
try {
|
|
925
|
+
const { execute } = tool2;
|
|
926
|
+
const resolvedContext = await resolveToolContext({
|
|
927
|
+
toolName: approval.toolName,
|
|
928
|
+
tool: tool2,
|
|
929
|
+
toolsContext: effectiveToolsContext
|
|
930
|
+
});
|
|
931
|
+
const toolCallEvent = {
|
|
932
|
+
type: "tool-call",
|
|
933
|
+
toolCallId: approval.toolCallId,
|
|
934
|
+
toolName: approval.toolName,
|
|
935
|
+
input: approval.input
|
|
936
|
+
};
|
|
937
|
+
const messages2 = prompt.messages;
|
|
938
|
+
await ((_l = telemetryDispatcher.onToolExecutionStart) == null ? void 0 : _l.call(telemetryDispatcher, {
|
|
939
|
+
toolCall: toolCallEvent,
|
|
940
|
+
stepNumber: 0,
|
|
941
|
+
messages: messages2,
|
|
942
|
+
toolContext: resolvedContext
|
|
943
|
+
}));
|
|
944
|
+
const startTime = Date.now();
|
|
945
|
+
const executeApprovedTool = () => execute(approval.input, {
|
|
946
|
+
toolCallId: approval.toolCallId,
|
|
947
|
+
messages: [],
|
|
948
|
+
context: resolvedContext,
|
|
949
|
+
experimental_sandbox: sandbox
|
|
950
|
+
});
|
|
951
|
+
const toolResult = telemetryDispatcher.executeTool != null ? await telemetryDispatcher.executeTool({
|
|
952
|
+
callId: "workflow-agent",
|
|
953
|
+
toolCallId: approval.toolCallId,
|
|
954
|
+
execute: executeApprovedTool
|
|
955
|
+
}) : await executeApprovedTool();
|
|
956
|
+
await ((_m = telemetryDispatcher.onToolExecutionEnd) == null ? void 0 : _m.call(telemetryDispatcher, {
|
|
957
|
+
toolCall: toolCallEvent,
|
|
958
|
+
stepNumber: 0,
|
|
959
|
+
durationMs: Date.now() - startTime,
|
|
960
|
+
messages: messages2,
|
|
961
|
+
toolContext: resolvedContext,
|
|
962
|
+
success: true,
|
|
963
|
+
output: toolResult
|
|
964
|
+
}));
|
|
965
|
+
toolResultContent.push({
|
|
966
|
+
type: "tool-result",
|
|
967
|
+
toolCallId: approval.toolCallId,
|
|
968
|
+
toolName: approval.toolName,
|
|
969
|
+
output: await createLanguageModelToolResultOutput({
|
|
970
|
+
toolCallId: approval.toolCallId,
|
|
971
|
+
toolName: approval.toolName,
|
|
972
|
+
input: approval.input,
|
|
973
|
+
output: toolResult,
|
|
974
|
+
tool: tool2,
|
|
975
|
+
errorMode: "none",
|
|
976
|
+
supportedUrls: {},
|
|
977
|
+
download
|
|
978
|
+
})
|
|
979
|
+
});
|
|
980
|
+
approvedRawResults.push({
|
|
981
|
+
toolCallId: approval.toolCallId,
|
|
982
|
+
toolName: approval.toolName,
|
|
983
|
+
input: approval.input,
|
|
984
|
+
output: toolResult
|
|
985
|
+
});
|
|
986
|
+
} catch (error) {
|
|
987
|
+
const errorMessage = getErrorMessage(error);
|
|
988
|
+
await ((_n = telemetryDispatcher.onToolExecutionEnd) == null ? void 0 : _n.call(telemetryDispatcher, {
|
|
989
|
+
toolCall: {
|
|
990
|
+
type: "tool-call",
|
|
991
|
+
toolCallId: approval.toolCallId,
|
|
992
|
+
toolName: approval.toolName,
|
|
993
|
+
input: approval.input
|
|
994
|
+
},
|
|
995
|
+
stepNumber: 0,
|
|
996
|
+
durationMs: 0,
|
|
997
|
+
messages: prompt.messages,
|
|
998
|
+
toolContext: void 0,
|
|
999
|
+
success: false,
|
|
1000
|
+
error
|
|
1001
|
+
}));
|
|
1002
|
+
toolResultContent.push({
|
|
1003
|
+
type: "tool-result",
|
|
1004
|
+
toolCallId: approval.toolCallId,
|
|
1005
|
+
toolName: approval.toolName,
|
|
1006
|
+
output: await createLanguageModelToolResultOutput({
|
|
1007
|
+
toolCallId: approval.toolCallId,
|
|
1008
|
+
toolName: approval.toolName,
|
|
1009
|
+
input: approval.input,
|
|
1010
|
+
output: errorMessage,
|
|
1011
|
+
tool: tool2,
|
|
1012
|
+
errorMode: "text",
|
|
1013
|
+
supportedUrls: {},
|
|
1014
|
+
download
|
|
1015
|
+
})
|
|
1016
|
+
});
|
|
1017
|
+
approvedRawResults.push({
|
|
1018
|
+
toolCallId: approval.toolCallId,
|
|
1019
|
+
toolName: approval.toolName,
|
|
1020
|
+
input: approval.input,
|
|
1021
|
+
output: errorMessage
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
for (const denial of deniedToolApprovals) {
|
|
1027
|
+
if (denial.providerExecuted) {
|
|
1028
|
+
continue;
|
|
1029
|
+
}
|
|
1030
|
+
toolResultContent.push({
|
|
1031
|
+
type: "tool-result",
|
|
1032
|
+
toolCallId: denial.toolCallId,
|
|
1033
|
+
toolName: denial.toolName,
|
|
1034
|
+
output: {
|
|
1035
|
+
type: "execution-denied",
|
|
1036
|
+
reason: denial.reason
|
|
1037
|
+
}
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
const cleanedMessages = [];
|
|
1041
|
+
for (const msg of prompt.messages) {
|
|
1042
|
+
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
|
1043
|
+
const filtered = msg.content.filter(
|
|
1044
|
+
(p) => p.type !== "tool-approval-request" || providerExecutedApprovalIds.has(p.approvalId)
|
|
1045
|
+
);
|
|
1046
|
+
if (filtered.length > 0) {
|
|
1047
|
+
cleanedMessages.push({ ...msg, content: filtered });
|
|
1048
|
+
}
|
|
1049
|
+
} else if (msg.role === "tool") {
|
|
1050
|
+
const filtered = msg.content.flatMap((p) => {
|
|
1051
|
+
if (p.type !== "tool-approval-response") {
|
|
1052
|
+
return [p];
|
|
1053
|
+
}
|
|
1054
|
+
if (!providerExecutedApprovalIds.has(p.approvalId)) {
|
|
1055
|
+
return [];
|
|
1056
|
+
}
|
|
1057
|
+
return [{ ...p, providerExecuted: true }];
|
|
1058
|
+
});
|
|
1059
|
+
if (filtered.length > 0) {
|
|
1060
|
+
cleanedMessages.push({ ...msg, content: filtered });
|
|
1061
|
+
}
|
|
1062
|
+
} else {
|
|
1063
|
+
cleanedMessages.push(msg);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
if (toolResultContent.length > 0) {
|
|
1067
|
+
cleanedMessages.push({
|
|
1068
|
+
role: "tool",
|
|
1069
|
+
content: toolResultContent
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
prompt.messages = cleanedMessages;
|
|
1073
|
+
if (options.writable && toolResultContent.length > 0) {
|
|
1074
|
+
const deniedResults = toolResultContent.filter((r) => r.output.type === "execution-denied").map((r) => ({ toolCallId: r.toolCallId }));
|
|
1075
|
+
await writeApprovalToolResults(
|
|
1076
|
+
options.writable,
|
|
1077
|
+
approvedRawResults,
|
|
1078
|
+
deniedResults
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
const modelPrompt = await convertToLanguageModelPrompt({
|
|
1083
|
+
prompt,
|
|
1084
|
+
supportedUrls: {},
|
|
1085
|
+
download
|
|
1086
|
+
});
|
|
1087
|
+
const effectiveAbortSignal = mergeAbortSignals(
|
|
1088
|
+
(_o = options.abortSignal) != null ? _o : effectiveGenerationSettings.abortSignal,
|
|
1089
|
+
options.timeout
|
|
1090
|
+
);
|
|
1091
|
+
const mergedGenerationSettings = {
|
|
1092
|
+
...effectiveGenerationSettings,
|
|
1093
|
+
...options.maxOutputTokens !== void 0 && {
|
|
1094
|
+
maxOutputTokens: options.maxOutputTokens
|
|
1095
|
+
},
|
|
1096
|
+
...options.temperature !== void 0 && {
|
|
1097
|
+
temperature: options.temperature
|
|
1098
|
+
},
|
|
1099
|
+
...options.topP !== void 0 && { topP: options.topP },
|
|
1100
|
+
...options.topK !== void 0 && { topK: options.topK },
|
|
1101
|
+
...options.presencePenalty !== void 0 && {
|
|
1102
|
+
presencePenalty: options.presencePenalty
|
|
1103
|
+
},
|
|
1104
|
+
...options.frequencyPenalty !== void 0 && {
|
|
1105
|
+
frequencyPenalty: options.frequencyPenalty
|
|
1106
|
+
},
|
|
1107
|
+
...options.stopSequences !== void 0 && {
|
|
1108
|
+
stopSequences: options.stopSequences
|
|
1109
|
+
},
|
|
1110
|
+
...options.seed !== void 0 && { seed: options.seed },
|
|
1111
|
+
...options.maxRetries !== void 0 && {
|
|
1112
|
+
maxRetries: options.maxRetries
|
|
1113
|
+
},
|
|
1114
|
+
...effectiveAbortSignal !== void 0 && {
|
|
1115
|
+
abortSignal: effectiveAbortSignal
|
|
1116
|
+
},
|
|
1117
|
+
...options.headers !== void 0 && { headers: options.headers },
|
|
1118
|
+
...options.reasoning !== void 0 && { reasoning: options.reasoning },
|
|
1119
|
+
...options.providerOptions !== void 0 && {
|
|
1120
|
+
providerOptions: options.providerOptions
|
|
1121
|
+
}
|
|
1122
|
+
};
|
|
1123
|
+
mergedGenerationSettings.headers = withUserAgentSuffix(
|
|
1124
|
+
(_p = mergedGenerationSettings.headers) != null ? _p : {},
|
|
1125
|
+
"ai-sdk-agent/workflow"
|
|
1126
|
+
);
|
|
1127
|
+
const mergedOnStepEnd = mergeCallbacks(
|
|
1128
|
+
this.constructorOnStepEnd,
|
|
1129
|
+
(_q = options.onStepEnd) != null ? _q : options.onStepFinish
|
|
1130
|
+
);
|
|
1131
|
+
const mergedOnEnd = mergeCallbacks(
|
|
1132
|
+
this.constructorOnEnd,
|
|
1133
|
+
onEnd
|
|
1134
|
+
);
|
|
1135
|
+
const mergedOnStart = mergeCallbacks(
|
|
1136
|
+
this.constructorOnStart,
|
|
1137
|
+
options.experimental_onStart
|
|
1138
|
+
);
|
|
1139
|
+
const mergedOnStepStart = mergeCallbacks(
|
|
1140
|
+
this.constructorOnStepStart,
|
|
1141
|
+
options.experimental_onStepStart
|
|
1142
|
+
);
|
|
1143
|
+
const mergedOnToolExecutionStart = mergeCallbacks(
|
|
1144
|
+
this.constructorOnToolExecutionStart,
|
|
1145
|
+
options.onToolExecutionStart
|
|
1146
|
+
);
|
|
1147
|
+
const mergedOnToolExecutionEnd = mergeCallbacks(
|
|
1148
|
+
this.constructorOnToolExecutionEnd,
|
|
1149
|
+
options.onToolExecutionEnd
|
|
1150
|
+
);
|
|
1151
|
+
const effectiveToolChoice = effectiveToolChoiceFromPrepare;
|
|
1152
|
+
const effectiveActiveTools = (_r = options.activeTools) != null ? _r : this.activeTools;
|
|
1153
|
+
const effectiveTools = effectiveActiveTools && effectiveActiveTools.length > 0 ? (_s = filterActiveTools2({
|
|
1154
|
+
tools: this.tools,
|
|
1155
|
+
activeTools: effectiveActiveTools
|
|
1156
|
+
})) != null ? _s : this.tools : this.tools;
|
|
1157
|
+
const effectiveModelInfo = getModelInfo2(effectiveModel);
|
|
1158
|
+
let runtimeContext = effectiveRuntimeContext;
|
|
1159
|
+
let toolsContext = effectiveToolsContext;
|
|
1160
|
+
const steps = [];
|
|
1161
|
+
let lastStepToolCalls = [];
|
|
1162
|
+
let lastStepToolResults = [];
|
|
1163
|
+
if (mergedOnStart) {
|
|
1164
|
+
await mergedOnStart({
|
|
1165
|
+
model: effectiveModel,
|
|
1166
|
+
messages: prompt.messages,
|
|
1167
|
+
runtimeContext,
|
|
1168
|
+
toolsContext
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
await ((_v = telemetryDispatcher.onStart) == null ? void 0 : _v.call(telemetryDispatcher, {
|
|
1172
|
+
callId: "workflow-agent",
|
|
1173
|
+
operationId: "ai.workflowAgent.stream",
|
|
1174
|
+
provider: effectiveModelInfo.provider,
|
|
1175
|
+
modelId: effectiveModelInfo.modelId,
|
|
1176
|
+
system: void 0,
|
|
1177
|
+
messages: prompt.messages,
|
|
1178
|
+
tools: effectiveTools,
|
|
1179
|
+
toolChoice: effectiveToolChoice,
|
|
1180
|
+
activeTools: effectiveActiveTools,
|
|
1181
|
+
maxOutputTokens: mergedGenerationSettings.maxOutputTokens,
|
|
1182
|
+
temperature: mergedGenerationSettings.temperature,
|
|
1183
|
+
topP: mergedGenerationSettings.topP,
|
|
1184
|
+
topK: mergedGenerationSettings.topK,
|
|
1185
|
+
presencePenalty: mergedGenerationSettings.presencePenalty,
|
|
1186
|
+
frequencyPenalty: mergedGenerationSettings.frequencyPenalty,
|
|
1187
|
+
stopSequences: mergedGenerationSettings.stopSequences,
|
|
1188
|
+
seed: mergedGenerationSettings.seed,
|
|
1189
|
+
maxRetries: (_t = mergedGenerationSettings.maxRetries) != null ? _t : 2,
|
|
1190
|
+
timeout: void 0,
|
|
1191
|
+
headers: mergedGenerationSettings.headers,
|
|
1192
|
+
reasoning: mergedGenerationSettings.reasoning,
|
|
1193
|
+
providerOptions: mergedGenerationSettings.providerOptions,
|
|
1194
|
+
output: (_u = options.output) != null ? _u : this.output,
|
|
1195
|
+
runtimeContext,
|
|
1196
|
+
toolsContext
|
|
1197
|
+
}));
|
|
1198
|
+
const executeToolWithCallbacks = async (toolCall, tools, messages2, perToolContexts, currentStepNumber = 0, stepSandbox) => {
|
|
1199
|
+
var _a2, _b2, _c2, _d2;
|
|
1200
|
+
const toolCallEvent = {
|
|
1201
|
+
type: "tool-call",
|
|
1202
|
+
toolCallId: toolCall.toolCallId,
|
|
1203
|
+
toolName: toolCall.toolName,
|
|
1204
|
+
input: toolCall.input
|
|
1205
|
+
};
|
|
1206
|
+
const tool2 = tools[toolCall.toolName];
|
|
1207
|
+
const resolvedContext = tool2 ? await resolveToolContext({
|
|
1208
|
+
toolName: toolCall.toolName,
|
|
1209
|
+
tool: tool2,
|
|
1210
|
+
toolsContext: perToolContexts
|
|
1211
|
+
}) : void 0;
|
|
1212
|
+
const modelMessages = getToolCallbackMessages(messages2);
|
|
1213
|
+
if (mergedOnToolExecutionStart) {
|
|
1214
|
+
await mergedOnToolExecutionStart({
|
|
1215
|
+
toolCall: toolCallEvent,
|
|
1216
|
+
stepNumber: currentStepNumber,
|
|
1217
|
+
messages: modelMessages,
|
|
1218
|
+
toolContext: resolvedContext
|
|
1219
|
+
});
|
|
1220
|
+
}
|
|
1221
|
+
await ((_a2 = telemetryDispatcher.onToolExecutionStart) == null ? void 0 : _a2.call(telemetryDispatcher, {
|
|
1222
|
+
toolCall: toolCallEvent,
|
|
1223
|
+
stepNumber: currentStepNumber,
|
|
1224
|
+
messages: modelMessages,
|
|
1225
|
+
toolContext: resolvedContext
|
|
1226
|
+
}));
|
|
1227
|
+
const startTime = Date.now();
|
|
1228
|
+
let result;
|
|
1229
|
+
try {
|
|
1230
|
+
const execute = () => executeTool(
|
|
1231
|
+
toolCall,
|
|
1232
|
+
tools,
|
|
1233
|
+
messages2,
|
|
1234
|
+
resolvedContext,
|
|
1235
|
+
download,
|
|
1236
|
+
stepSandbox
|
|
1237
|
+
);
|
|
1238
|
+
result = telemetryDispatcher.executeTool != null ? await telemetryDispatcher.executeTool({
|
|
1239
|
+
callId: "workflow-agent",
|
|
1240
|
+
toolCallId: toolCall.toolCallId,
|
|
1241
|
+
execute
|
|
1242
|
+
}) : await execute();
|
|
1243
|
+
} catch (err) {
|
|
1244
|
+
const durationMs2 = Date.now() - startTime;
|
|
1245
|
+
if (mergedOnToolExecutionEnd) {
|
|
1246
|
+
await mergedOnToolExecutionEnd({
|
|
1247
|
+
toolCall: toolCallEvent,
|
|
1248
|
+
stepNumber: currentStepNumber,
|
|
1249
|
+
durationMs: durationMs2,
|
|
1250
|
+
messages: modelMessages,
|
|
1251
|
+
toolContext: resolvedContext,
|
|
1252
|
+
success: false,
|
|
1253
|
+
error: err
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
await ((_b2 = telemetryDispatcher.onToolExecutionEnd) == null ? void 0 : _b2.call(telemetryDispatcher, {
|
|
1257
|
+
toolCall: toolCallEvent,
|
|
1258
|
+
stepNumber: currentStepNumber,
|
|
1259
|
+
durationMs: durationMs2,
|
|
1260
|
+
messages: modelMessages,
|
|
1261
|
+
toolContext: resolvedContext,
|
|
1262
|
+
success: false,
|
|
1263
|
+
error: err
|
|
1264
|
+
}));
|
|
1265
|
+
throw err;
|
|
1266
|
+
}
|
|
1267
|
+
const durationMs = Date.now() - startTime;
|
|
1268
|
+
if (mergedOnToolExecutionEnd) {
|
|
1269
|
+
if (result.isError) {
|
|
1270
|
+
await mergedOnToolExecutionEnd({
|
|
1271
|
+
toolCall: toolCallEvent,
|
|
1272
|
+
stepNumber: currentStepNumber,
|
|
1273
|
+
durationMs,
|
|
1274
|
+
messages: modelMessages,
|
|
1275
|
+
toolContext: resolvedContext,
|
|
1276
|
+
success: false,
|
|
1277
|
+
error: result.rawOutput
|
|
1278
|
+
});
|
|
1279
|
+
} else {
|
|
1280
|
+
await mergedOnToolExecutionEnd({
|
|
1281
|
+
toolCall: toolCallEvent,
|
|
1282
|
+
stepNumber: currentStepNumber,
|
|
1283
|
+
durationMs,
|
|
1284
|
+
messages: modelMessages,
|
|
1285
|
+
toolContext: resolvedContext,
|
|
1286
|
+
success: true,
|
|
1287
|
+
output: result.rawOutput
|
|
1288
|
+
});
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
if (result.isError) {
|
|
1292
|
+
await ((_c2 = telemetryDispatcher.onToolExecutionEnd) == null ? void 0 : _c2.call(telemetryDispatcher, {
|
|
1293
|
+
toolCall: toolCallEvent,
|
|
1294
|
+
stepNumber: currentStepNumber,
|
|
1295
|
+
durationMs,
|
|
1296
|
+
messages: modelMessages,
|
|
1297
|
+
toolContext: resolvedContext,
|
|
1298
|
+
success: false,
|
|
1299
|
+
error: result.rawOutput
|
|
1300
|
+
}));
|
|
1301
|
+
} else {
|
|
1302
|
+
await ((_d2 = telemetryDispatcher.onToolExecutionEnd) == null ? void 0 : _d2.call(telemetryDispatcher, {
|
|
1303
|
+
toolCall: toolCallEvent,
|
|
1304
|
+
stepNumber: currentStepNumber,
|
|
1305
|
+
durationMs,
|
|
1306
|
+
messages: modelMessages,
|
|
1307
|
+
toolContext: resolvedContext,
|
|
1308
|
+
success: true,
|
|
1309
|
+
output: result.rawOutput
|
|
1310
|
+
}));
|
|
1311
|
+
}
|
|
1312
|
+
return result;
|
|
1313
|
+
};
|
|
1314
|
+
const recordProviderExecutedToolTelemetry = async (toolCall, result, messages2, currentStepNumber) => {
|
|
1315
|
+
var _a2, _b2;
|
|
1316
|
+
const toolCallEvent = {
|
|
1317
|
+
type: "tool-call",
|
|
1318
|
+
toolCallId: toolCall.toolCallId,
|
|
1319
|
+
toolName: toolCall.toolName,
|
|
1320
|
+
input: toolCall.input
|
|
1321
|
+
};
|
|
1322
|
+
const modelMessages = getToolCallbackMessages(messages2);
|
|
1323
|
+
await ((_a2 = telemetryDispatcher.onToolExecutionStart) == null ? void 0 : _a2.call(telemetryDispatcher, {
|
|
1324
|
+
toolCall: toolCallEvent,
|
|
1325
|
+
stepNumber: currentStepNumber,
|
|
1326
|
+
messages: modelMessages,
|
|
1327
|
+
toolContext: void 0
|
|
1328
|
+
}));
|
|
1329
|
+
await ((_b2 = telemetryDispatcher.onToolExecutionEnd) == null ? void 0 : _b2.call(telemetryDispatcher, {
|
|
1330
|
+
toolCall: toolCallEvent,
|
|
1331
|
+
stepNumber: currentStepNumber,
|
|
1332
|
+
durationMs: 0,
|
|
1333
|
+
messages: modelMessages,
|
|
1334
|
+
toolContext: void 0,
|
|
1335
|
+
...result.isError ? {
|
|
1336
|
+
success: false,
|
|
1337
|
+
error: result.rawOutput
|
|
1338
|
+
} : {
|
|
1339
|
+
success: true,
|
|
1340
|
+
output: result.rawOutput
|
|
1341
|
+
}
|
|
1342
|
+
}));
|
|
1343
|
+
};
|
|
1344
|
+
if ((_w = mergedGenerationSettings.abortSignal) == null ? void 0 : _w.aborted) {
|
|
1345
|
+
if (options.onAbort) {
|
|
1346
|
+
await options.onAbort({ steps });
|
|
1347
|
+
}
|
|
1348
|
+
return {
|
|
1349
|
+
messages: prompt.messages,
|
|
1350
|
+
steps,
|
|
1351
|
+
toolCalls: [],
|
|
1352
|
+
toolResults: [],
|
|
1353
|
+
finishReason: "other",
|
|
1354
|
+
totalUsage: aggregateUsage(steps),
|
|
1355
|
+
output: void 0
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
const iterator = streamTextIterator({
|
|
1359
|
+
model: effectiveModel,
|
|
1360
|
+
tools: effectiveTools,
|
|
1361
|
+
writable: options.writable,
|
|
1362
|
+
prompt: modelPrompt,
|
|
1363
|
+
stopConditions: (_x = options.stopWhen) != null ? _x : this.stopWhen,
|
|
1364
|
+
onStepEnd: mergedOnStepEnd,
|
|
1365
|
+
onStepStart: mergedOnStepStart,
|
|
1366
|
+
onError: options.onError,
|
|
1367
|
+
prepareStep: (_y = options.prepareStep) != null ? _y : this.prepareStep,
|
|
1368
|
+
generationSettings: mergedGenerationSettings,
|
|
1369
|
+
toolChoice: effectiveToolChoice,
|
|
1370
|
+
runtimeContext,
|
|
1371
|
+
toolsContext,
|
|
1372
|
+
telemetry: effectiveTelemetry,
|
|
1373
|
+
includeRawChunks: (_z = options.includeRawChunks) != null ? _z : false,
|
|
1374
|
+
repairToolCall: (_B = (_A = options.repairToolCall) != null ? _A : options.experimental_repairToolCall) != null ? _B : this.repairToolCall,
|
|
1375
|
+
responseFormat: await ((_D = (_C = options.output) != null ? _C : this.output) == null ? void 0 : _D.responseFormat),
|
|
1376
|
+
experimental_sandbox: sandbox
|
|
1377
|
+
});
|
|
1378
|
+
let finalMessages;
|
|
1379
|
+
let encounteredError;
|
|
1380
|
+
let wasAborted = false;
|
|
1381
|
+
try {
|
|
1382
|
+
let result = await iterator.next();
|
|
1383
|
+
while (!result.done) {
|
|
1384
|
+
if ((_E = mergedGenerationSettings.abortSignal) == null ? void 0 : _E.aborted) {
|
|
1385
|
+
wasAborted = true;
|
|
1386
|
+
if (options.onAbort) {
|
|
1387
|
+
await options.onAbort({ steps });
|
|
1388
|
+
}
|
|
1389
|
+
break;
|
|
1390
|
+
}
|
|
1391
|
+
const {
|
|
1392
|
+
toolCalls,
|
|
1393
|
+
messages: iterMessages,
|
|
1394
|
+
step,
|
|
1395
|
+
runtimeContext: yieldedRuntimeContext,
|
|
1396
|
+
toolsContext: yieldedToolsContext,
|
|
1397
|
+
experimental_sandbox: stepSandbox,
|
|
1398
|
+
providerExecutedToolResults
|
|
1399
|
+
} = result.value;
|
|
1400
|
+
const toolExecutionSandbox = stepSandbox != null ? stepSandbox : sandbox;
|
|
1401
|
+
const currentStepNumber = steps.length;
|
|
1402
|
+
if (step) {
|
|
1403
|
+
steps.push(step);
|
|
1404
|
+
}
|
|
1405
|
+
if (yieldedRuntimeContext !== void 0) {
|
|
1406
|
+
runtimeContext = yieldedRuntimeContext;
|
|
1407
|
+
}
|
|
1408
|
+
if (yieldedToolsContext !== void 0) {
|
|
1409
|
+
toolsContext = yieldedToolsContext;
|
|
1410
|
+
}
|
|
1411
|
+
if (toolCalls.length > 0) {
|
|
1412
|
+
const invalidToolCalls = toolCalls.filter((tc) => tc.invalid === true);
|
|
1413
|
+
const validToolCalls = toolCalls.filter((tc) => tc.invalid !== true);
|
|
1414
|
+
const nonProviderToolCalls = validToolCalls.filter(
|
|
1415
|
+
(tc) => !tc.providerExecuted
|
|
1416
|
+
);
|
|
1417
|
+
const providerToolCalls = validToolCalls.filter(
|
|
1418
|
+
(tc) => tc.providerExecuted
|
|
1419
|
+
);
|
|
1420
|
+
const approvalNeeded = await Promise.all(
|
|
1421
|
+
nonProviderToolCalls.map(async (tc) => {
|
|
1422
|
+
const tool2 = effectiveTools[tc.toolName];
|
|
1423
|
+
if (!tool2) return false;
|
|
1424
|
+
if (tool2.needsApproval == null) return false;
|
|
1425
|
+
if (typeof tool2.needsApproval === "boolean")
|
|
1426
|
+
return tool2.needsApproval;
|
|
1427
|
+
const resolvedContext = await resolveToolContext({
|
|
1428
|
+
toolName: tc.toolName,
|
|
1429
|
+
tool: tool2,
|
|
1430
|
+
toolsContext
|
|
1431
|
+
});
|
|
1432
|
+
return tool2.needsApproval(tc.input, {
|
|
1433
|
+
toolCallId: tc.toolCallId,
|
|
1434
|
+
messages: iterMessages,
|
|
1435
|
+
context: resolvedContext
|
|
1436
|
+
});
|
|
1437
|
+
})
|
|
1438
|
+
);
|
|
1439
|
+
const executableToolCalls = nonProviderToolCalls.filter((tc, i) => {
|
|
1440
|
+
const tool2 = effectiveTools[tc.toolName];
|
|
1441
|
+
return (!tool2 || typeof tool2.execute === "function") && !approvalNeeded[i];
|
|
1442
|
+
});
|
|
1443
|
+
const pausedToolCalls = nonProviderToolCalls.filter((tc, i) => {
|
|
1444
|
+
const tool2 = effectiveTools[tc.toolName];
|
|
1445
|
+
return tool2 && typeof tool2.execute !== "function" || approvalNeeded[i];
|
|
1446
|
+
});
|
|
1447
|
+
if (pausedToolCalls.length > 0) {
|
|
1448
|
+
const executableResults = await Promise.all(
|
|
1449
|
+
executableToolCalls.map(
|
|
1450
|
+
(toolCall) => executeToolWithCallbacks(
|
|
1451
|
+
toolCall,
|
|
1452
|
+
effectiveTools,
|
|
1453
|
+
iterMessages,
|
|
1454
|
+
toolsContext,
|
|
1455
|
+
currentStepNumber,
|
|
1456
|
+
toolExecutionSandbox
|
|
1457
|
+
)
|
|
1458
|
+
)
|
|
1459
|
+
);
|
|
1460
|
+
const providerResults = await Promise.all(
|
|
1461
|
+
providerToolCalls.map(
|
|
1462
|
+
(toolCall) => resolveProviderToolResult(
|
|
1463
|
+
toolCall,
|
|
1464
|
+
providerExecutedToolResults,
|
|
1465
|
+
effectiveTools,
|
|
1466
|
+
download
|
|
1467
|
+
)
|
|
1468
|
+
)
|
|
1469
|
+
);
|
|
1470
|
+
await Promise.all(
|
|
1471
|
+
providerToolCalls.map(
|
|
1472
|
+
(toolCall, index) => recordProviderExecutedToolTelemetry(
|
|
1473
|
+
toolCall,
|
|
1474
|
+
providerResults[index],
|
|
1475
|
+
iterMessages,
|
|
1476
|
+
currentStepNumber
|
|
1477
|
+
)
|
|
1478
|
+
)
|
|
1479
|
+
);
|
|
1480
|
+
const continuationInvalidResults = invalidToolCalls.map(
|
|
1481
|
+
createInvalidToolResult
|
|
1482
|
+
);
|
|
1483
|
+
const resolvedResults = [
|
|
1484
|
+
...executableResults.map((result2) => result2.modelResult),
|
|
1485
|
+
...providerResults.map((result2) => result2.modelResult),
|
|
1486
|
+
...continuationInvalidResults
|
|
1487
|
+
];
|
|
1488
|
+
const executedResults = [...executableResults, ...providerResults];
|
|
1489
|
+
const allToolCalls = toolCalls.map((tc) => ({
|
|
1490
|
+
type: "tool-call",
|
|
1491
|
+
toolCallId: tc.toolCallId,
|
|
1492
|
+
toolName: tc.toolName,
|
|
1493
|
+
input: tc.input
|
|
1494
|
+
}));
|
|
1495
|
+
const allToolResults = executedResults.map((r) => {
|
|
1496
|
+
var _a2;
|
|
1497
|
+
return {
|
|
1498
|
+
type: "tool-result",
|
|
1499
|
+
toolCallId: r.modelResult.toolCallId,
|
|
1500
|
+
toolName: r.modelResult.toolName,
|
|
1501
|
+
input: (_a2 = toolCalls.find(
|
|
1502
|
+
(tc) => tc.toolCallId === r.modelResult.toolCallId
|
|
1503
|
+
)) == null ? void 0 : _a2.input,
|
|
1504
|
+
output: r.rawOutput
|
|
1505
|
+
};
|
|
1506
|
+
});
|
|
1507
|
+
if (resolvedResults.length > 0) {
|
|
1508
|
+
iterMessages.push({
|
|
1509
|
+
role: "tool",
|
|
1510
|
+
content: resolvedResults
|
|
1511
|
+
});
|
|
1512
|
+
}
|
|
1513
|
+
const messages2 = iterMessages;
|
|
1514
|
+
const lastStep2 = steps[steps.length - 1];
|
|
1515
|
+
const totalUsage2 = aggregateUsage(steps);
|
|
1516
|
+
const finishReason2 = (_F = lastStep2 == null ? void 0 : lastStep2.finishReason) != null ? _F : "other";
|
|
1517
|
+
if (mergedOnEnd && !wasAborted) {
|
|
1518
|
+
await mergedOnEnd({
|
|
1519
|
+
steps,
|
|
1520
|
+
messages: messages2,
|
|
1521
|
+
text: (_G = lastStep2 == null ? void 0 : lastStep2.text) != null ? _G : "",
|
|
1522
|
+
finishReason: finishReason2,
|
|
1523
|
+
usage: totalUsage2,
|
|
1524
|
+
totalUsage: totalUsage2,
|
|
1525
|
+
runtimeContext,
|
|
1526
|
+
toolsContext,
|
|
1527
|
+
output: void 0
|
|
1528
|
+
});
|
|
1529
|
+
}
|
|
1530
|
+
if (!wasAborted && steps.length > 0) {
|
|
1531
|
+
const telemetrySteps = steps.map(normalizeStepForTelemetry2);
|
|
1532
|
+
const lastTelemetryStep = telemetrySteps[telemetrySteps.length - 1];
|
|
1533
|
+
await ((_H = telemetryDispatcher.onEnd) == null ? void 0 : _H.call(telemetryDispatcher, {
|
|
1534
|
+
...lastTelemetryStep,
|
|
1535
|
+
steps: telemetrySteps,
|
|
1536
|
+
usage: totalUsage2,
|
|
1537
|
+
totalUsage: totalUsage2
|
|
1538
|
+
}));
|
|
1539
|
+
}
|
|
1540
|
+
if (options.writable) {
|
|
1541
|
+
const approvalToolCalls = pausedToolCalls.filter((_, i) => {
|
|
1542
|
+
const tcIndex = nonProviderToolCalls.indexOf(
|
|
1543
|
+
pausedToolCalls[i]
|
|
1544
|
+
);
|
|
1545
|
+
return approvalNeeded[tcIndex];
|
|
1546
|
+
});
|
|
1547
|
+
if (approvalToolCalls.length > 0) {
|
|
1548
|
+
await writeApprovalRequests(
|
|
1549
|
+
options.writable,
|
|
1550
|
+
approvalToolCalls.map((tc) => ({
|
|
1551
|
+
toolCallId: tc.toolCallId,
|
|
1552
|
+
toolName: tc.toolName
|
|
1553
|
+
}))
|
|
1554
|
+
);
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
if (options.writable) {
|
|
1558
|
+
const sendFinish = (_I = options.sendFinish) != null ? _I : true;
|
|
1559
|
+
const preventClose = (_J = options.preventClose) != null ? _J : false;
|
|
1560
|
+
if (sendFinish || !preventClose) {
|
|
1561
|
+
await closeStream(options.writable, preventClose, sendFinish);
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
return {
|
|
1565
|
+
messages: messages2,
|
|
1566
|
+
steps,
|
|
1567
|
+
toolCalls: allToolCalls,
|
|
1568
|
+
toolResults: allToolResults,
|
|
1569
|
+
finishReason: finishReason2,
|
|
1570
|
+
totalUsage: totalUsage2,
|
|
1571
|
+
output: void 0
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
const clientToolResults = await Promise.all(
|
|
1575
|
+
nonProviderToolCalls.map(
|
|
1576
|
+
(toolCall) => executeToolWithCallbacks(
|
|
1577
|
+
toolCall,
|
|
1578
|
+
effectiveTools,
|
|
1579
|
+
iterMessages,
|
|
1580
|
+
toolsContext,
|
|
1581
|
+
currentStepNumber,
|
|
1582
|
+
toolExecutionSandbox
|
|
1583
|
+
)
|
|
1584
|
+
)
|
|
1585
|
+
);
|
|
1586
|
+
const providerToolResults = await Promise.all(
|
|
1587
|
+
providerToolCalls.map(
|
|
1588
|
+
(toolCall) => resolveProviderToolResult(
|
|
1589
|
+
toolCall,
|
|
1590
|
+
providerExecutedToolResults,
|
|
1591
|
+
effectiveTools,
|
|
1592
|
+
download
|
|
1593
|
+
)
|
|
1594
|
+
)
|
|
1595
|
+
);
|
|
1596
|
+
await Promise.all(
|
|
1597
|
+
providerToolCalls.map(
|
|
1598
|
+
(toolCall, index) => recordProviderExecutedToolTelemetry(
|
|
1599
|
+
toolCall,
|
|
1600
|
+
providerToolResults[index],
|
|
1601
|
+
iterMessages,
|
|
1602
|
+
currentStepNumber
|
|
1603
|
+
)
|
|
1604
|
+
)
|
|
1605
|
+
);
|
|
1606
|
+
const continuationInvalidToolResults = invalidToolCalls.map(
|
|
1607
|
+
createInvalidToolResult
|
|
1608
|
+
);
|
|
1609
|
+
const executedToolResults = toolCalls.flatMap((tc) => {
|
|
1610
|
+
const clientResult = clientToolResults.find(
|
|
1611
|
+
(r) => r.modelResult.toolCallId === tc.toolCallId
|
|
1612
|
+
);
|
|
1613
|
+
if (clientResult) return [clientResult];
|
|
1614
|
+
const providerResult = providerToolResults.find(
|
|
1615
|
+
(r) => r.modelResult.toolCallId === tc.toolCallId
|
|
1616
|
+
);
|
|
1617
|
+
if (providerResult) return [providerResult];
|
|
1618
|
+
return [];
|
|
1619
|
+
});
|
|
1620
|
+
const continuationToolResults = toolCalls.flatMap((tc) => {
|
|
1621
|
+
const invalidResult = continuationInvalidToolResults.find(
|
|
1622
|
+
(r) => r.toolCallId === tc.toolCallId
|
|
1623
|
+
);
|
|
1624
|
+
if (invalidResult) return [invalidResult];
|
|
1625
|
+
const executedResult = executedToolResults.find(
|
|
1626
|
+
(r) => r.modelResult.toolCallId === tc.toolCallId
|
|
1627
|
+
);
|
|
1628
|
+
if (executedResult) return [executedResult.modelResult];
|
|
1629
|
+
return [];
|
|
1630
|
+
});
|
|
1631
|
+
if (options.writable) {
|
|
1632
|
+
await writeToolResultsWithStepBoundary(
|
|
1633
|
+
options.writable,
|
|
1634
|
+
executedToolResults.map((r) => {
|
|
1635
|
+
var _a2;
|
|
1636
|
+
return {
|
|
1637
|
+
toolCallId: r.modelResult.toolCallId,
|
|
1638
|
+
toolName: r.modelResult.toolName,
|
|
1639
|
+
input: (_a2 = toolCalls.find(
|
|
1640
|
+
(tc) => tc.toolCallId === r.modelResult.toolCallId
|
|
1641
|
+
)) == null ? void 0 : _a2.input,
|
|
1642
|
+
output: r.rawOutput
|
|
1643
|
+
};
|
|
1644
|
+
})
|
|
1645
|
+
);
|
|
1646
|
+
}
|
|
1647
|
+
lastStepToolCalls = toolCalls.map((tc) => ({
|
|
1648
|
+
type: "tool-call",
|
|
1649
|
+
toolCallId: tc.toolCallId,
|
|
1650
|
+
toolName: tc.toolName,
|
|
1651
|
+
input: tc.input
|
|
1652
|
+
}));
|
|
1653
|
+
lastStepToolResults = executedToolResults.map((r) => {
|
|
1654
|
+
var _a2;
|
|
1655
|
+
return {
|
|
1656
|
+
type: "tool-result",
|
|
1657
|
+
toolCallId: r.modelResult.toolCallId,
|
|
1658
|
+
toolName: r.modelResult.toolName,
|
|
1659
|
+
input: (_a2 = toolCalls.find(
|
|
1660
|
+
(tc) => tc.toolCallId === r.modelResult.toolCallId
|
|
1661
|
+
)) == null ? void 0 : _a2.input,
|
|
1662
|
+
output: r.rawOutput
|
|
1663
|
+
};
|
|
1664
|
+
});
|
|
1665
|
+
result = await iterator.next(continuationToolResults);
|
|
1666
|
+
} else {
|
|
1667
|
+
lastStepToolCalls = [];
|
|
1668
|
+
lastStepToolResults = [];
|
|
1669
|
+
result = await iterator.next([]);
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
if (result.done) {
|
|
1673
|
+
finalMessages = result.value;
|
|
1674
|
+
}
|
|
1675
|
+
} catch (error) {
|
|
1676
|
+
encounteredError = error;
|
|
1677
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
1678
|
+
wasAborted = true;
|
|
1679
|
+
if (options.onAbort) {
|
|
1680
|
+
await options.onAbort({ steps });
|
|
1681
|
+
}
|
|
1682
|
+
} else if (options.onError) {
|
|
1683
|
+
await options.onError({ error });
|
|
1684
|
+
}
|
|
1685
|
+
await ((_K = telemetryDispatcher.onError) == null ? void 0 : _K.call(telemetryDispatcher, error));
|
|
1686
|
+
}
|
|
1687
|
+
const messages = finalMessages != null ? finalMessages : prompt.messages;
|
|
1688
|
+
const effectiveOutput = (_L = options.output) != null ? _L : this.output;
|
|
1689
|
+
let experimentalOutput = void 0;
|
|
1690
|
+
if (effectiveOutput && steps.length > 0) {
|
|
1691
|
+
const lastStep2 = steps[steps.length - 1];
|
|
1692
|
+
const text = lastStep2.text;
|
|
1693
|
+
if (text) {
|
|
1694
|
+
try {
|
|
1695
|
+
experimentalOutput = await effectiveOutput.parseCompleteOutput(
|
|
1696
|
+
{ text },
|
|
1697
|
+
{
|
|
1698
|
+
response: lastStep2.response,
|
|
1699
|
+
usage: lastStep2.usage,
|
|
1700
|
+
finishReason: lastStep2.finishReason
|
|
1701
|
+
}
|
|
1702
|
+
);
|
|
1703
|
+
} catch (parseError) {
|
|
1704
|
+
if (!encounteredError) {
|
|
1705
|
+
encounteredError = parseError;
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
const lastStep = steps[steps.length - 1];
|
|
1711
|
+
const totalUsage = aggregateUsage(steps);
|
|
1712
|
+
const finishReason = (_M = lastStep == null ? void 0 : lastStep.finishReason) != null ? _M : "other";
|
|
1713
|
+
if (mergedOnEnd && !wasAborted) {
|
|
1714
|
+
await mergedOnEnd({
|
|
1715
|
+
steps,
|
|
1716
|
+
messages,
|
|
1717
|
+
text: (_N = lastStep == null ? void 0 : lastStep.text) != null ? _N : "",
|
|
1718
|
+
finishReason,
|
|
1719
|
+
usage: totalUsage,
|
|
1720
|
+
totalUsage,
|
|
1721
|
+
runtimeContext,
|
|
1722
|
+
toolsContext,
|
|
1723
|
+
output: experimentalOutput
|
|
1724
|
+
});
|
|
1725
|
+
}
|
|
1726
|
+
if (!wasAborted && steps.length > 0) {
|
|
1727
|
+
const telemetrySteps = steps.map(normalizeStepForTelemetry2);
|
|
1728
|
+
const lastTelemetryStep = telemetrySteps[telemetrySteps.length - 1];
|
|
1729
|
+
await ((_O = telemetryDispatcher.onEnd) == null ? void 0 : _O.call(telemetryDispatcher, {
|
|
1730
|
+
...lastTelemetryStep,
|
|
1731
|
+
steps: telemetrySteps,
|
|
1732
|
+
usage: totalUsage,
|
|
1733
|
+
totalUsage
|
|
1734
|
+
}));
|
|
1735
|
+
}
|
|
1736
|
+
if (encounteredError) {
|
|
1737
|
+
if (options.writable) {
|
|
1738
|
+
const sendFinish = (_P = options.sendFinish) != null ? _P : true;
|
|
1739
|
+
const preventClose = (_Q = options.preventClose) != null ? _Q : false;
|
|
1740
|
+
if (sendFinish || !preventClose) {
|
|
1741
|
+
await closeStream(options.writable, preventClose, sendFinish);
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
throw encounteredError;
|
|
1745
|
+
}
|
|
1746
|
+
if (options.writable) {
|
|
1747
|
+
const sendFinish = (_R = options.sendFinish) != null ? _R : true;
|
|
1748
|
+
const preventClose = (_S = options.preventClose) != null ? _S : false;
|
|
1749
|
+
if (sendFinish || !preventClose) {
|
|
1750
|
+
await closeStream(options.writable, preventClose, sendFinish);
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
return {
|
|
1754
|
+
messages,
|
|
1755
|
+
steps,
|
|
1756
|
+
toolCalls: lastStepToolCalls,
|
|
1757
|
+
toolResults: lastStepToolResults,
|
|
1758
|
+
finishReason,
|
|
1759
|
+
totalUsage,
|
|
1760
|
+
output: experimentalOutput
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
};
|
|
1764
|
+
function getModelInfo2(model) {
|
|
1765
|
+
var _a;
|
|
1766
|
+
return typeof model === "string" ? { provider: (_a = model.split("/")[0]) != null ? _a : "gateway", modelId: model } : { provider: model.provider, modelId: model.modelId };
|
|
1767
|
+
}
|
|
1768
|
+
function normalizeStepForTelemetry2(step) {
|
|
1769
|
+
var _a;
|
|
1770
|
+
return {
|
|
1771
|
+
...step,
|
|
1772
|
+
model: (_a = step.model) != null ? _a : { provider: "unknown", modelId: "unknown" }
|
|
1773
|
+
};
|
|
1774
|
+
}
|
|
1775
|
+
async function closeStream(writable, preventClose, sendFinish) {
|
|
1776
|
+
"use step";
|
|
1777
|
+
if (sendFinish) {
|
|
1778
|
+
const writer = writable.getWriter();
|
|
1779
|
+
try {
|
|
1780
|
+
await writer.write({ type: "finish" });
|
|
1781
|
+
} finally {
|
|
1782
|
+
writer.releaseLock();
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
if (!preventClose) {
|
|
1786
|
+
await writable.close();
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
async function writeApprovalRequests(writable, toolCalls) {
|
|
1790
|
+
"use step";
|
|
1791
|
+
const writer = writable.getWriter();
|
|
1792
|
+
try {
|
|
1793
|
+
for (const tc of toolCalls) {
|
|
1794
|
+
await writer.write({
|
|
1795
|
+
type: "tool-approval-request",
|
|
1796
|
+
approvalId: `approval-${tc.toolCallId}`,
|
|
1797
|
+
toolCallId: tc.toolCallId
|
|
1798
|
+
});
|
|
1799
|
+
}
|
|
1800
|
+
} finally {
|
|
1801
|
+
writer.releaseLock();
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
async function writeToolResultsWithStepBoundary(writable, results) {
|
|
1805
|
+
"use step";
|
|
1806
|
+
const writer = writable.getWriter();
|
|
1807
|
+
try {
|
|
1808
|
+
for (const r of results) {
|
|
1809
|
+
await writer.write({
|
|
1810
|
+
type: "tool-result",
|
|
1811
|
+
toolCallId: r.toolCallId,
|
|
1812
|
+
toolName: r.toolName,
|
|
1813
|
+
input: r.input,
|
|
1814
|
+
output: r.output
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1817
|
+
await writer.write({ type: "finish-step" });
|
|
1818
|
+
await writer.write({ type: "start-step" });
|
|
1819
|
+
} finally {
|
|
1820
|
+
writer.releaseLock();
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
async function writeApprovalToolResults(writable, approvedResults, deniedResults) {
|
|
1824
|
+
"use step";
|
|
1825
|
+
const writer = writable.getWriter();
|
|
1826
|
+
try {
|
|
1827
|
+
for (const r of approvedResults) {
|
|
1828
|
+
await writer.write({
|
|
1829
|
+
type: "tool-result",
|
|
1830
|
+
toolCallId: r.toolCallId,
|
|
1831
|
+
toolName: r.toolName,
|
|
1832
|
+
input: r.input,
|
|
1833
|
+
output: r.output
|
|
1834
|
+
});
|
|
1835
|
+
}
|
|
1836
|
+
for (const r of deniedResults) {
|
|
1837
|
+
await writer.write({
|
|
1838
|
+
type: "tool-output-denied",
|
|
1839
|
+
toolCallId: r.toolCallId
|
|
1840
|
+
});
|
|
1841
|
+
}
|
|
1842
|
+
await writer.write({ type: "finish-step" });
|
|
1843
|
+
await writer.write({ type: "start-step" });
|
|
1844
|
+
} finally {
|
|
1845
|
+
writer.releaseLock();
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
async function resolveToolContext({
|
|
1849
|
+
toolName,
|
|
1850
|
+
tool: tool2,
|
|
1851
|
+
toolsContext
|
|
1852
|
+
}) {
|
|
1853
|
+
const contextSchema = tool2.contextSchema;
|
|
1854
|
+
const entry = toolsContext == null ? void 0 : toolsContext[toolName];
|
|
1855
|
+
if (contextSchema == null) {
|
|
1856
|
+
return entry;
|
|
1857
|
+
}
|
|
1858
|
+
return await validateTypes({
|
|
1859
|
+
value: entry,
|
|
1860
|
+
schema: contextSchema,
|
|
1861
|
+
context: { field: "tool context", entityName: toolName }
|
|
1862
|
+
});
|
|
1863
|
+
}
|
|
1864
|
+
function aggregateUsage(steps) {
|
|
1865
|
+
var _a, _b, _c, _d;
|
|
1866
|
+
let inputTokens = 0;
|
|
1867
|
+
let outputTokens = 0;
|
|
1868
|
+
for (const step of steps) {
|
|
1869
|
+
inputTokens += (_b = (_a = step.usage) == null ? void 0 : _a.inputTokens) != null ? _b : 0;
|
|
1870
|
+
outputTokens += (_d = (_c = step.usage) == null ? void 0 : _c.outputTokens) != null ? _d : 0;
|
|
1871
|
+
}
|
|
1872
|
+
return {
|
|
1873
|
+
inputTokens,
|
|
1874
|
+
outputTokens,
|
|
1875
|
+
totalTokens: inputTokens + outputTokens
|
|
1876
|
+
};
|
|
1877
|
+
}
|
|
1878
|
+
async function resolveProviderToolResult(toolCall, providerExecutedToolResults, tools, download) {
|
|
1879
|
+
const streamResult = providerExecutedToolResults == null ? void 0 : providerExecutedToolResults.get(toolCall.toolCallId);
|
|
1880
|
+
if (!streamResult) {
|
|
1881
|
+
console.warn(
|
|
1882
|
+
`[WorkflowAgent] Provider-executed tool "${toolCall.toolName}" (${toolCall.toolCallId}) did not receive a result from the stream. This may indicate a provider issue.`
|
|
1883
|
+
);
|
|
1884
|
+
return {
|
|
1885
|
+
modelResult: {
|
|
1886
|
+
type: "tool-result",
|
|
1887
|
+
toolCallId: toolCall.toolCallId,
|
|
1888
|
+
toolName: toolCall.toolName,
|
|
1889
|
+
output: {
|
|
1890
|
+
type: "text",
|
|
1891
|
+
value: ""
|
|
1892
|
+
}
|
|
1893
|
+
},
|
|
1894
|
+
rawOutput: "",
|
|
1895
|
+
isError: false
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
const result = streamResult.result;
|
|
1899
|
+
const errorMode = streamResult.isError ? typeof result === "string" ? "text" : "json" : "none";
|
|
1900
|
+
return {
|
|
1901
|
+
modelResult: {
|
|
1902
|
+
type: "tool-result",
|
|
1903
|
+
toolCallId: toolCall.toolCallId,
|
|
1904
|
+
toolName: toolCall.toolName,
|
|
1905
|
+
output: await createLanguageModelToolResultOutput({
|
|
1906
|
+
toolCallId: toolCall.toolCallId,
|
|
1907
|
+
toolName: toolCall.toolName,
|
|
1908
|
+
input: toolCall.input,
|
|
1909
|
+
output: result,
|
|
1910
|
+
tool: tools == null ? void 0 : tools[toolCall.toolName],
|
|
1911
|
+
errorMode,
|
|
1912
|
+
supportedUrls: {},
|
|
1913
|
+
download
|
|
1914
|
+
})
|
|
1915
|
+
},
|
|
1916
|
+
rawOutput: result,
|
|
1917
|
+
isError: streamResult.isError === true
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1920
|
+
function createInvalidToolResult(toolCall) {
|
|
1921
|
+
return {
|
|
1922
|
+
type: "tool-result",
|
|
1923
|
+
toolCallId: toolCall.toolCallId,
|
|
1924
|
+
toolName: toolCall.toolName,
|
|
1925
|
+
output: {
|
|
1926
|
+
type: "error-text",
|
|
1927
|
+
value: getErrorMessage(toolCall.error)
|
|
1928
|
+
}
|
|
1929
|
+
};
|
|
1930
|
+
}
|
|
1931
|
+
function getToolCallbackMessages(messages) {
|
|
1932
|
+
var _a;
|
|
1933
|
+
const withoutAssistantToolCall = ((_a = messages.at(-1)) == null ? void 0 : _a.role) === "assistant" ? messages.slice(0, -1) : messages;
|
|
1934
|
+
return withoutAssistantToolCall;
|
|
1935
|
+
}
|
|
1936
|
+
async function executeTool(toolCall, tools, messages, context, download, sandbox) {
|
|
1937
|
+
const tool2 = tools[toolCall.toolName];
|
|
1938
|
+
if (!tool2) throw new Error(`Tool "${toolCall.toolName}" not found`);
|
|
1939
|
+
if (typeof tool2.execute !== "function") {
|
|
1940
|
+
throw new Error(
|
|
1941
|
+
`Tool "${toolCall.toolName}" does not have an execute function. Client-side tools should be filtered before calling executeTool.`
|
|
1942
|
+
);
|
|
1943
|
+
}
|
|
1944
|
+
const parsedInput = toolCall.input;
|
|
1945
|
+
let toolResult;
|
|
1946
|
+
try {
|
|
1947
|
+
const { execute } = tool2;
|
|
1948
|
+
toolResult = await execute(parsedInput, {
|
|
1949
|
+
toolCallId: toolCall.toolCallId,
|
|
1950
|
+
// Pass the conversation messages to the tool so it has context about the conversation
|
|
1951
|
+
messages,
|
|
1952
|
+
// Pass per-tool context to the tool (resolved from `toolsContext`)
|
|
1953
|
+
context,
|
|
1954
|
+
experimental_sandbox: sandbox
|
|
1955
|
+
});
|
|
1956
|
+
} catch (error) {
|
|
1957
|
+
const errorMessage = getErrorMessage(error);
|
|
1958
|
+
return {
|
|
1959
|
+
modelResult: {
|
|
1960
|
+
type: "tool-result",
|
|
1961
|
+
toolCallId: toolCall.toolCallId,
|
|
1962
|
+
toolName: toolCall.toolName,
|
|
1963
|
+
output: await createLanguageModelToolResultOutput({
|
|
1964
|
+
toolCallId: toolCall.toolCallId,
|
|
1965
|
+
toolName: toolCall.toolName,
|
|
1966
|
+
input: parsedInput,
|
|
1967
|
+
output: errorMessage,
|
|
1968
|
+
tool: tool2,
|
|
1969
|
+
errorMode: "text",
|
|
1970
|
+
supportedUrls: {},
|
|
1971
|
+
download
|
|
1972
|
+
})
|
|
1973
|
+
},
|
|
1974
|
+
rawOutput: errorMessage,
|
|
1975
|
+
isError: true
|
|
1976
|
+
};
|
|
1977
|
+
}
|
|
1978
|
+
return {
|
|
1979
|
+
modelResult: {
|
|
1980
|
+
type: "tool-result",
|
|
1981
|
+
toolCallId: toolCall.toolCallId,
|
|
1982
|
+
toolName: toolCall.toolName,
|
|
1983
|
+
output: await createLanguageModelToolResultOutput({
|
|
1984
|
+
toolCallId: toolCall.toolCallId,
|
|
1985
|
+
toolName: toolCall.toolName,
|
|
1986
|
+
input: parsedInput,
|
|
1987
|
+
output: toolResult,
|
|
1988
|
+
tool: tool2,
|
|
1989
|
+
errorMode: "none",
|
|
1990
|
+
supportedUrls: {},
|
|
1991
|
+
download
|
|
1992
|
+
})
|
|
1993
|
+
},
|
|
1994
|
+
rawOutput: toolResult,
|
|
1995
|
+
isError: false
|
|
1996
|
+
};
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
// src/to-ui-message-chunk.ts
|
|
2000
|
+
function toUIMessageChunk(part) {
|
|
2001
|
+
var _a;
|
|
2002
|
+
switch (part.type) {
|
|
2003
|
+
case "text-start":
|
|
2004
|
+
return {
|
|
2005
|
+
type: "text-start",
|
|
2006
|
+
id: part.id,
|
|
2007
|
+
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
2008
|
+
};
|
|
2009
|
+
case "text-delta":
|
|
2010
|
+
return {
|
|
2011
|
+
type: "text-delta",
|
|
2012
|
+
id: part.id,
|
|
2013
|
+
delta: part.text,
|
|
2014
|
+
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
2015
|
+
};
|
|
2016
|
+
case "text-end":
|
|
2017
|
+
return {
|
|
2018
|
+
type: "text-end",
|
|
2019
|
+
id: part.id,
|
|
2020
|
+
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
2021
|
+
};
|
|
2022
|
+
case "reasoning-start":
|
|
2023
|
+
return {
|
|
2024
|
+
type: "reasoning-start",
|
|
2025
|
+
id: part.id,
|
|
2026
|
+
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
2027
|
+
};
|
|
2028
|
+
case "reasoning-delta":
|
|
2029
|
+
return {
|
|
2030
|
+
type: "reasoning-delta",
|
|
2031
|
+
id: part.id,
|
|
2032
|
+
delta: part.text,
|
|
2033
|
+
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
2034
|
+
};
|
|
2035
|
+
case "reasoning-end":
|
|
2036
|
+
return {
|
|
2037
|
+
type: "reasoning-end",
|
|
2038
|
+
id: part.id,
|
|
2039
|
+
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
2040
|
+
};
|
|
2041
|
+
case "file": {
|
|
2042
|
+
const file = part.file;
|
|
2043
|
+
return {
|
|
2044
|
+
type: "file",
|
|
2045
|
+
mediaType: file.mediaType,
|
|
2046
|
+
url: `data:${file.mediaType};base64,${file.base64}`
|
|
2047
|
+
};
|
|
2048
|
+
}
|
|
2049
|
+
case "source": {
|
|
2050
|
+
if (part.sourceType === "url") {
|
|
2051
|
+
return {
|
|
2052
|
+
type: "source-url",
|
|
2053
|
+
sourceId: part.id,
|
|
2054
|
+
url: part.url,
|
|
2055
|
+
title: part.title,
|
|
2056
|
+
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
2057
|
+
};
|
|
2058
|
+
}
|
|
2059
|
+
if (part.sourceType === "document") {
|
|
2060
|
+
return {
|
|
2061
|
+
type: "source-document",
|
|
2062
|
+
sourceId: part.id,
|
|
2063
|
+
mediaType: part.mediaType,
|
|
2064
|
+
title: part.title,
|
|
2065
|
+
filename: part.filename,
|
|
2066
|
+
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
2067
|
+
};
|
|
2068
|
+
}
|
|
2069
|
+
return void 0;
|
|
2070
|
+
}
|
|
2071
|
+
case "tool-input-start":
|
|
2072
|
+
return {
|
|
2073
|
+
type: "tool-input-start",
|
|
2074
|
+
toolCallId: part.id,
|
|
2075
|
+
toolName: part.toolName,
|
|
2076
|
+
...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {}
|
|
2077
|
+
};
|
|
2078
|
+
case "tool-input-delta":
|
|
2079
|
+
return {
|
|
2080
|
+
type: "tool-input-delta",
|
|
2081
|
+
toolCallId: part.id,
|
|
2082
|
+
inputTextDelta: part.delta
|
|
2083
|
+
};
|
|
2084
|
+
case "tool-call": {
|
|
2085
|
+
const toolCallPart = part;
|
|
2086
|
+
if (toolCallPart.invalid) {
|
|
2087
|
+
return {
|
|
2088
|
+
type: "tool-input-error",
|
|
2089
|
+
toolCallId: toolCallPart.toolCallId,
|
|
2090
|
+
toolName: toolCallPart.toolName,
|
|
2091
|
+
input: toolCallPart.input,
|
|
2092
|
+
errorText: toolCallPart.error instanceof Error ? toolCallPart.error.message : String((_a = toolCallPart.error) != null ? _a : "Invalid tool call")
|
|
2093
|
+
};
|
|
2094
|
+
}
|
|
2095
|
+
return {
|
|
2096
|
+
type: "tool-input-available",
|
|
2097
|
+
toolCallId: part.toolCallId,
|
|
2098
|
+
toolName: part.toolName,
|
|
2099
|
+
input: part.input,
|
|
2100
|
+
...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
|
|
2101
|
+
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
2102
|
+
};
|
|
2103
|
+
}
|
|
2104
|
+
case "tool-result":
|
|
2105
|
+
return {
|
|
2106
|
+
type: "tool-output-available",
|
|
2107
|
+
toolCallId: part.toolCallId,
|
|
2108
|
+
output: part.output
|
|
2109
|
+
};
|
|
2110
|
+
case "tool-error":
|
|
2111
|
+
return {
|
|
2112
|
+
type: "tool-output-error",
|
|
2113
|
+
toolCallId: part.toolCallId,
|
|
2114
|
+
errorText: part.error instanceof Error ? part.error.message : String(part.error)
|
|
2115
|
+
};
|
|
2116
|
+
case "error": {
|
|
2117
|
+
const error = part.error;
|
|
2118
|
+
return {
|
|
2119
|
+
type: "error",
|
|
2120
|
+
errorText: error instanceof Error ? error.message : String(error)
|
|
2121
|
+
};
|
|
2122
|
+
}
|
|
2123
|
+
// These don't produce UI chunks
|
|
2124
|
+
case "tool-input-end":
|
|
2125
|
+
case "model-call-start":
|
|
2126
|
+
case "model-call-response-metadata":
|
|
2127
|
+
case "model-call-end":
|
|
2128
|
+
case "raw":
|
|
2129
|
+
return void 0;
|
|
2130
|
+
default: {
|
|
2131
|
+
const passthroughPart = part;
|
|
2132
|
+
if (passthroughPart.type === "tool-approval-request") {
|
|
2133
|
+
return {
|
|
2134
|
+
type: "tool-approval-request",
|
|
2135
|
+
approvalId: passthroughPart.approvalId,
|
|
2136
|
+
toolCallId: passthroughPart.toolCallId
|
|
2137
|
+
};
|
|
2138
|
+
}
|
|
2139
|
+
if (passthroughPart.type === "finish-step" || passthroughPart.type === "start-step" || passthroughPart.type === "tool-output-denied") {
|
|
2140
|
+
return passthroughPart;
|
|
2141
|
+
}
|
|
2142
|
+
return void 0;
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
function createModelCallToUIChunkTransform() {
|
|
2147
|
+
return new TransformStream({
|
|
2148
|
+
start: (controller) => {
|
|
2149
|
+
controller.enqueue({ type: "start" });
|
|
2150
|
+
controller.enqueue({ type: "start-step" });
|
|
2151
|
+
},
|
|
2152
|
+
flush: (controller) => {
|
|
2153
|
+
controller.enqueue({ type: "finish-step" });
|
|
2154
|
+
controller.enqueue({ type: "finish" });
|
|
2155
|
+
},
|
|
2156
|
+
transform: (part, controller) => {
|
|
2157
|
+
const uiChunk = toUIMessageChunk(part);
|
|
2158
|
+
if (uiChunk) {
|
|
2159
|
+
controller.enqueue(uiChunk);
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
// src/workflow-chat-transport.ts
|
|
2166
|
+
import {
|
|
2167
|
+
parseJsonEventStream,
|
|
2168
|
+
uiMessageChunkSchema
|
|
2169
|
+
} from "ai";
|
|
2170
|
+
import {
|
|
2171
|
+
convertAsyncIteratorToReadableStream,
|
|
2172
|
+
getErrorMessage as getErrorMessage2
|
|
2173
|
+
} from "@ai-sdk/provider-utils";
|
|
2174
|
+
import { createAsyncIterableStream } from "ai/internal";
|
|
2175
|
+
|
|
2176
|
+
// src/normalize-ui-message-stream.ts
|
|
2177
|
+
var newPartFrameState = () => ({
|
|
2178
|
+
open: /* @__PURE__ */ new Set(),
|
|
2179
|
+
ended: /* @__PURE__ */ new Set()
|
|
2180
|
+
});
|
|
2181
|
+
function* repairPart(kind, id, chunk, state, startType) {
|
|
2182
|
+
if (kind === "start") {
|
|
2183
|
+
if (state.open.has(id) || state.ended.has(id)) {
|
|
2184
|
+
return;
|
|
2185
|
+
}
|
|
2186
|
+
state.open.add(id);
|
|
2187
|
+
yield chunk;
|
|
2188
|
+
return;
|
|
2189
|
+
}
|
|
2190
|
+
if (state.ended.has(id)) {
|
|
2191
|
+
return;
|
|
2192
|
+
}
|
|
2193
|
+
if (!state.open.has(id)) {
|
|
2194
|
+
state.open.add(id);
|
|
2195
|
+
yield { type: startType, id };
|
|
2196
|
+
}
|
|
2197
|
+
if (kind === "end") {
|
|
2198
|
+
state.open.delete(id);
|
|
2199
|
+
state.ended.add(id);
|
|
2200
|
+
}
|
|
2201
|
+
yield chunk;
|
|
2202
|
+
}
|
|
2203
|
+
async function* normalizeUIMessageStreamParts(source) {
|
|
2204
|
+
const text = newPartFrameState();
|
|
2205
|
+
const reasoning = newPartFrameState();
|
|
2206
|
+
for await (const chunk of source) {
|
|
2207
|
+
switch (chunk.type) {
|
|
2208
|
+
case "finish-step":
|
|
2209
|
+
text.open.clear();
|
|
2210
|
+
text.ended.clear();
|
|
2211
|
+
reasoning.open.clear();
|
|
2212
|
+
reasoning.ended.clear();
|
|
2213
|
+
yield chunk;
|
|
2214
|
+
break;
|
|
2215
|
+
case "text-start":
|
|
2216
|
+
yield* repairPart("start", chunk.id, chunk, text, "text-start");
|
|
2217
|
+
break;
|
|
2218
|
+
case "text-delta":
|
|
2219
|
+
yield* repairPart("delta", chunk.id, chunk, text, "text-start");
|
|
2220
|
+
break;
|
|
2221
|
+
case "text-end":
|
|
2222
|
+
yield* repairPart("end", chunk.id, chunk, text, "text-start");
|
|
2223
|
+
break;
|
|
2224
|
+
case "reasoning-start":
|
|
2225
|
+
yield* repairPart(
|
|
2226
|
+
"start",
|
|
2227
|
+
chunk.id,
|
|
2228
|
+
chunk,
|
|
2229
|
+
reasoning,
|
|
2230
|
+
"reasoning-start"
|
|
2231
|
+
);
|
|
2232
|
+
break;
|
|
2233
|
+
case "reasoning-delta":
|
|
2234
|
+
yield* repairPart(
|
|
2235
|
+
"delta",
|
|
2236
|
+
chunk.id,
|
|
2237
|
+
chunk,
|
|
2238
|
+
reasoning,
|
|
2239
|
+
"reasoning-start"
|
|
2240
|
+
);
|
|
2241
|
+
break;
|
|
2242
|
+
case "reasoning-end":
|
|
2243
|
+
yield* repairPart("end", chunk.id, chunk, reasoning, "reasoning-start");
|
|
2244
|
+
break;
|
|
2245
|
+
default:
|
|
2246
|
+
yield chunk;
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
// src/workflow-chat-transport.ts
|
|
2252
|
+
function createOrphanFilter() {
|
|
2253
|
+
const seenStartedIds = /* @__PURE__ */ new Set();
|
|
2254
|
+
const seenStartedToolCallIds = /* @__PURE__ */ new Set();
|
|
2255
|
+
let warnedOnce = false;
|
|
2256
|
+
function warnOnce(orphanKind, orphanRef) {
|
|
2257
|
+
if (warnedOnce) return;
|
|
2258
|
+
warnedOnce = true;
|
|
2259
|
+
console.warn(
|
|
2260
|
+
`[WorkflowChatTransport] Dropping orphan UI chunk (${orphanKind} for id "${orphanRef}") on resume \u2014 the resume position landed mid-part. The dropped chunk(s) reference a part whose start chunk wasn't in the resumed window. To preserve the full message, configure your stream endpoint to rewind to a step boundary before returning the readable. See: https://workflow.dev/docs/ai/resumable-streams#mid-part-resumes`
|
|
2261
|
+
);
|
|
2262
|
+
}
|
|
2263
|
+
function shouldDrop(chunk) {
|
|
2264
|
+
switch (chunk.type) {
|
|
2265
|
+
case "text-start":
|
|
2266
|
+
case "reasoning-start":
|
|
2267
|
+
seenStartedIds.add(chunk.id);
|
|
2268
|
+
return false;
|
|
2269
|
+
case "tool-input-start":
|
|
2270
|
+
// `tool-input-available` / `tool-input-error` are self-contained: the
|
|
2271
|
+
// AI SDK creates the tool part from them directly (non-streamed tool
|
|
2272
|
+
// calls are emitted as a bare `tool-input-available`), so they must
|
|
2273
|
+
// never be dropped. They also carry the full input, so they recover a
|
|
2274
|
+
// tool call whose `tool-input-start` fell outside the resumed window.
|
|
2275
|
+
case "tool-input-available":
|
|
2276
|
+
case "tool-input-error":
|
|
2277
|
+
seenStartedToolCallIds.add(chunk.toolCallId);
|
|
2278
|
+
return false;
|
|
2279
|
+
case "text-delta":
|
|
2280
|
+
case "text-end":
|
|
2281
|
+
case "reasoning-delta":
|
|
2282
|
+
case "reasoning-end":
|
|
2283
|
+
if (seenStartedIds.has(chunk.id)) return false;
|
|
2284
|
+
warnOnce(chunk.type, chunk.id);
|
|
2285
|
+
return true;
|
|
2286
|
+
case "tool-input-delta":
|
|
2287
|
+
case "tool-approval-request":
|
|
2288
|
+
case "tool-output-available":
|
|
2289
|
+
case "tool-output-error":
|
|
2290
|
+
case "tool-output-denied":
|
|
2291
|
+
if (seenStartedToolCallIds.has(chunk.toolCallId)) return false;
|
|
2292
|
+
warnOnce(chunk.type, chunk.toolCallId);
|
|
2293
|
+
return true;
|
|
2294
|
+
default:
|
|
2295
|
+
return false;
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
return { shouldDrop };
|
|
2299
|
+
}
|
|
2300
|
+
var WorkflowChatTransport = class {
|
|
2301
|
+
/**
|
|
2302
|
+
* Creates a new WorkflowChatTransport instance.
|
|
2303
|
+
*
|
|
2304
|
+
* @param options - Configuration options for the transport
|
|
2305
|
+
* @param options.api - API endpoint for chat requests (defaults to '/api/chat')
|
|
2306
|
+
* @param options.fetch - Custom fetch implementation (defaults to global fetch)
|
|
2307
|
+
* @param options.onChatSendMessage - Callback after sending messages
|
|
2308
|
+
* @param options.onChatEnd - Callback when chat stream ends
|
|
2309
|
+
* @param options.maxConsecutiveErrors - Maximum consecutive errors for reconnection
|
|
2310
|
+
* @param options.prepareSendMessagesRequest - Function to prepare send messages request
|
|
2311
|
+
* @param options.prepareReconnectToStreamRequest - Function to prepare reconnect request
|
|
2312
|
+
*/
|
|
2313
|
+
constructor(options = {}) {
|
|
2314
|
+
var _a, _b, _c, _d;
|
|
2315
|
+
this.api = (_a = options.api) != null ? _a : "/api/chat";
|
|
2316
|
+
this.fetch = (_b = options.fetch) != null ? _b : fetch.bind(globalThis);
|
|
2317
|
+
this.onChatSendMessage = options.onChatSendMessage;
|
|
2318
|
+
this.onChatEnd = options.onChatEnd;
|
|
2319
|
+
this.maxConsecutiveErrors = (_c = options.maxConsecutiveErrors) != null ? _c : 3;
|
|
2320
|
+
this.initialStartIndex = (_d = options.initialStartIndex) != null ? _d : 0;
|
|
2321
|
+
this.prepareSendMessagesRequest = options.prepareSendMessagesRequest;
|
|
2322
|
+
this.prepareReconnectToStreamRequest = options.prepareReconnectToStreamRequest;
|
|
2323
|
+
}
|
|
2324
|
+
/**
|
|
2325
|
+
* Sends messages to the chat endpoint and returns a stream of response chunks.
|
|
2326
|
+
*
|
|
2327
|
+
* This method handles the entire chat lifecycle including:
|
|
2328
|
+
* - Sending messages to the /api/chat endpoint
|
|
2329
|
+
* - Streaming response chunks
|
|
2330
|
+
* - Automatic reconnection if the stream is interrupted
|
|
2331
|
+
*
|
|
2332
|
+
* @param options - Options for sending messages
|
|
2333
|
+
* @param options.trigger - The type of message submission ('submit-message' or 'regenerate-message')
|
|
2334
|
+
* @param options.chatId - Unique identifier for this chat session
|
|
2335
|
+
* @param options.messageId - Optional message ID for tracking specific messages
|
|
2336
|
+
* @param options.messages - Array of UI messages to send
|
|
2337
|
+
* @param options.abortSignal - Optional AbortSignal to cancel the request
|
|
2338
|
+
*
|
|
2339
|
+
* @returns A ReadableStream of UIMessageChunk objects containing the response
|
|
2340
|
+
* @throws Error if the fetch request fails or returns a non-OK status
|
|
2341
|
+
*/
|
|
2342
|
+
async sendMessages(options) {
|
|
2343
|
+
return convertAsyncIteratorToReadableStream(
|
|
2344
|
+
normalizeUIMessageStreamParts(this.sendMessagesIterator(options))
|
|
2345
|
+
);
|
|
2346
|
+
}
|
|
2347
|
+
async *sendMessagesIterator(options) {
|
|
2348
|
+
var _a, _b, _c;
|
|
2349
|
+
const { chatId, messages, abortSignal, trigger, messageId } = options;
|
|
2350
|
+
let gotFinish = false;
|
|
2351
|
+
let chunkIndex = 0;
|
|
2352
|
+
const requestConfig = this.prepareSendMessagesRequest ? await this.prepareSendMessagesRequest({
|
|
2353
|
+
id: chatId,
|
|
2354
|
+
messages,
|
|
2355
|
+
requestMetadata: options.metadata,
|
|
2356
|
+
body: options.body,
|
|
2357
|
+
credentials: void 0,
|
|
2358
|
+
headers: options.headers,
|
|
2359
|
+
api: this.api,
|
|
2360
|
+
trigger,
|
|
2361
|
+
messageId
|
|
2362
|
+
}) : void 0;
|
|
2363
|
+
const url = (_a = requestConfig == null ? void 0 : requestConfig.api) != null ? _a : this.api;
|
|
2364
|
+
const response = await this.fetch(url, {
|
|
2365
|
+
method: "POST",
|
|
2366
|
+
body: JSON.stringify(
|
|
2367
|
+
(_b = requestConfig == null ? void 0 : requestConfig.body) != null ? _b : { messages, ...options.body }
|
|
2368
|
+
),
|
|
2369
|
+
headers: requestConfig == null ? void 0 : requestConfig.headers,
|
|
2370
|
+
credentials: requestConfig == null ? void 0 : requestConfig.credentials,
|
|
2371
|
+
signal: abortSignal
|
|
2372
|
+
});
|
|
2373
|
+
if (!response.ok || !response.body) {
|
|
2374
|
+
throw new Error(
|
|
2375
|
+
`Failed to fetch chat: ${response.status} ${await response.text()}`
|
|
2376
|
+
);
|
|
2377
|
+
}
|
|
2378
|
+
const workflowRunId = response.headers.get("x-workflow-run-id");
|
|
2379
|
+
if (!workflowRunId) {
|
|
2380
|
+
throw new Error(
|
|
2381
|
+
'Workflow run ID not found in "x-workflow-run-id" response header'
|
|
2382
|
+
);
|
|
2383
|
+
}
|
|
2384
|
+
await ((_c = this.onChatSendMessage) == null ? void 0 : _c.call(this, response, options));
|
|
2385
|
+
try {
|
|
2386
|
+
const chunkStream = parseJsonEventStream({
|
|
2387
|
+
stream: response.body,
|
|
2388
|
+
schema: uiMessageChunkSchema
|
|
2389
|
+
});
|
|
2390
|
+
for await (const chunk of createAsyncIterableStream(chunkStream)) {
|
|
2391
|
+
if (!chunk.success) {
|
|
2392
|
+
throw chunk.error;
|
|
2393
|
+
}
|
|
2394
|
+
chunkIndex++;
|
|
2395
|
+
yield chunk.value;
|
|
2396
|
+
if (chunk.value.type === "finish") {
|
|
2397
|
+
gotFinish = true;
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
} catch (error) {
|
|
2401
|
+
console.error("Error in chat POST stream", error);
|
|
2402
|
+
}
|
|
2403
|
+
if (gotFinish) {
|
|
2404
|
+
await this.onFinish(gotFinish, { chatId, chunkIndex });
|
|
2405
|
+
} else {
|
|
2406
|
+
yield* this.reconnectToStreamIterator(options, workflowRunId, chunkIndex);
|
|
2407
|
+
}
|
|
2408
|
+
}
|
|
2409
|
+
/**
|
|
2410
|
+
* Reconnects to an existing chat stream that was previously interrupted.
|
|
2411
|
+
*
|
|
2412
|
+
* This method is useful for resuming a chat session after network issues,
|
|
2413
|
+
* page refreshes, or Vercel Function timeouts.
|
|
2414
|
+
*
|
|
2415
|
+
* @param options - Options for reconnecting to the stream
|
|
2416
|
+
* @param options.chatId - The chat ID to reconnect to
|
|
2417
|
+
*
|
|
2418
|
+
* @returns A ReadableStream of UIMessageChunk objects
|
|
2419
|
+
* @throws Error if the reconnection request fails or returns a non-OK status
|
|
2420
|
+
*/
|
|
2421
|
+
async reconnectToStream(options) {
|
|
2422
|
+
const reconnectIterator = normalizeUIMessageStreamParts(
|
|
2423
|
+
this.reconnectToStreamIterator(options)
|
|
2424
|
+
);
|
|
2425
|
+
return convertAsyncIteratorToReadableStream(reconnectIterator);
|
|
2426
|
+
}
|
|
2427
|
+
async *reconnectToStreamIterator(options, workflowRunId, initialChunkIndex = 0) {
|
|
2428
|
+
var _a, _b;
|
|
2429
|
+
let chunkIndex = initialChunkIndex;
|
|
2430
|
+
const explicitStartIndex = (_a = options.startIndex) != null ? _a : this.initialStartIndex;
|
|
2431
|
+
let useExplicitStartIndex = initialChunkIndex === 0 && explicitStartIndex !== 0;
|
|
2432
|
+
const defaultApi = `${this.api}/${encodeURIComponent(workflowRunId != null ? workflowRunId : options.chatId)}/stream`;
|
|
2433
|
+
const requestConfig = this.prepareReconnectToStreamRequest ? await this.prepareReconnectToStreamRequest({
|
|
2434
|
+
id: options.chatId,
|
|
2435
|
+
requestMetadata: options.metadata,
|
|
2436
|
+
body: void 0,
|
|
2437
|
+
credentials: void 0,
|
|
2438
|
+
headers: void 0,
|
|
2439
|
+
api: defaultApi
|
|
2440
|
+
}) : void 0;
|
|
2441
|
+
const baseUrl = (_b = requestConfig == null ? void 0 : requestConfig.api) != null ? _b : defaultApi;
|
|
2442
|
+
let gotFinish = false;
|
|
2443
|
+
let consecutiveErrors = 0;
|
|
2444
|
+
let replayFromStart = false;
|
|
2445
|
+
const orphanFilter = useExplicitStartIndex && explicitStartIndex < 0 ? createOrphanFilter() : null;
|
|
2446
|
+
while (!gotFinish) {
|
|
2447
|
+
const startIndex = useExplicitStartIndex ? explicitStartIndex : replayFromStart ? 0 : chunkIndex;
|
|
2448
|
+
const url = `${baseUrl}?startIndex=${startIndex}`;
|
|
2449
|
+
const response = await this.fetch(url, {
|
|
2450
|
+
headers: requestConfig == null ? void 0 : requestConfig.headers,
|
|
2451
|
+
credentials: requestConfig == null ? void 0 : requestConfig.credentials,
|
|
2452
|
+
signal: options.abortSignal
|
|
2453
|
+
});
|
|
2454
|
+
if (!response.ok || !response.body) {
|
|
2455
|
+
throw new Error(
|
|
2456
|
+
`Failed to fetch chat: ${response.status} ${await response.text()}`
|
|
2457
|
+
);
|
|
2458
|
+
}
|
|
2459
|
+
if (useExplicitStartIndex && explicitStartIndex > 0) {
|
|
2460
|
+
chunkIndex = explicitStartIndex;
|
|
2461
|
+
} else if (useExplicitStartIndex && explicitStartIndex < 0) {
|
|
2462
|
+
const tailIndexHeader = response.headers.get(
|
|
2463
|
+
"x-workflow-stream-tail-index"
|
|
2464
|
+
);
|
|
2465
|
+
const tailIndex = tailIndexHeader !== null ? parseInt(tailIndexHeader, 10) : NaN;
|
|
2466
|
+
if (!Number.isNaN(tailIndex)) {
|
|
2467
|
+
chunkIndex = Math.max(0, tailIndex + 1 + explicitStartIndex);
|
|
2468
|
+
} else {
|
|
2469
|
+
console.warn(
|
|
2470
|
+
`[WorkflowChatTransport] Negative initialStartIndex is configured (${explicitStartIndex}) but the reconnection endpoint did not return a valid "x-workflow-stream-tail-index" header. Retries will replay the stream from the beginning. See: https://workflow.dev/docs/ai/resumable-streams#resuming-from-the-end-of-the-stream`
|
|
2471
|
+
);
|
|
2472
|
+
replayFromStart = true;
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
useExplicitStartIndex = false;
|
|
2476
|
+
try {
|
|
2477
|
+
const chunkStream = parseJsonEventStream({
|
|
2478
|
+
stream: response.body,
|
|
2479
|
+
schema: uiMessageChunkSchema
|
|
2480
|
+
});
|
|
2481
|
+
for await (const chunk of createAsyncIterableStream(chunkStream)) {
|
|
2482
|
+
if (!chunk.success) {
|
|
2483
|
+
throw chunk.error;
|
|
2484
|
+
}
|
|
2485
|
+
chunkIndex++;
|
|
2486
|
+
if (orphanFilter == null ? void 0 : orphanFilter.shouldDrop(chunk.value)) continue;
|
|
2487
|
+
yield chunk.value;
|
|
2488
|
+
if (chunk.value.type === "finish") {
|
|
2489
|
+
gotFinish = true;
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
consecutiveErrors = 0;
|
|
2493
|
+
} catch (error) {
|
|
2494
|
+
console.error("Error in chat GET reconnectToStream", error);
|
|
2495
|
+
consecutiveErrors++;
|
|
2496
|
+
if (consecutiveErrors >= this.maxConsecutiveErrors) {
|
|
2497
|
+
throw new Error(
|
|
2498
|
+
`Failed to reconnect after ${this.maxConsecutiveErrors} consecutive errors. Last error: ${getErrorMessage2(error)}`
|
|
2499
|
+
);
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
await this.onFinish(gotFinish, { chatId: options.chatId, chunkIndex });
|
|
2504
|
+
}
|
|
2505
|
+
async onFinish(gotFinish, { chatId, chunkIndex }) {
|
|
2506
|
+
var _a;
|
|
2507
|
+
if (gotFinish) {
|
|
2508
|
+
await ((_a = this.onChatEnd) == null ? void 0 : _a.call(this, { chatId, chunkIndex }));
|
|
2509
|
+
} else {
|
|
2510
|
+
throw new Error("No finish chunk received");
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
};
|
|
2514
|
+
export {
|
|
2515
|
+
Output,
|
|
2516
|
+
WorkflowAgent,
|
|
2517
|
+
WorkflowChatTransport,
|
|
2518
|
+
createModelCallToUIChunkTransform,
|
|
2519
|
+
normalizeUIMessageStreamParts,
|
|
2520
|
+
toUIMessageChunk
|
|
2521
|
+
};
|
|
2522
|
+
//# sourceMappingURL=index.js.map
|