@ai-sdk/workflow 2.0.58 → 2.0.60
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 +27 -0
- package/dist/index.d.ts +61 -43
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +686 -305
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/build-model-step-result.ts +329 -0
- package/src/do-generate-step.ts +212 -0
- package/src/do-stream-step.ts +50 -179
- package/src/index.ts +3 -0
- package/src/{stream-text-iterator.ts → model-call-iterator.ts} +117 -297
- package/src/model-call.ts +196 -0
- package/src/providers/mock-function-wrapper.ts +32 -0
- package/src/test/agent-e2e-workflows.ts +60 -1
- package/src/test/approval-workflows.ts +105 -0
- package/src/test/generation-boundary-model.ts +115 -0
- package/src/test/generation-boundary-workflows.ts +106 -0
- package/src/test/model-call-payload-workflow.ts +132 -0
- package/src/to-model-response-messages.ts +28 -0
- package/src/workflow-agent.ts +521 -206
- package/src/workflow-execution-result.ts +55 -0
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as normalizeUIMessageStreamParts, t as WorkflowChatTransport } from "./workflow-chat-transport-Bduf4ZDx.js";
|
|
2
|
-
import { asArray, asSchema, getErrorMessage, isAbortError, jsonSchema, validateTypes, withUserAgentSuffix } from "@ai-sdk/provider-utils";
|
|
3
|
-
import { DefaultGeneratedFile, InvalidToolApprovalSignatureError, Output, dynamicTool, experimental_filterActiveTools, experimental_streamLanguageModelCall, gateway, tool, wrapLanguageModel } from "ai";
|
|
4
|
-
import { collectToolApprovals, convertToLanguageModelPrompt, createDefaultDownloadFunction, createRestrictedTelemetryDispatcher, createToolModelOutput, createToolSearchState, downloadAssets, mapToolResultOutput, mergeAbortSignals, mergeCallbacks, prepareRetries, signToolApproval, standardizePrompt, validateApprovedToolApprovals, verifyToolApprovalSignature } from "ai/internal";
|
|
2
|
+
import { asArray, asSchema, convertUint8ArrayToBase64, generateId, getErrorMessage, isAbortError, jsonSchema, validateTypes, withUserAgentSuffix } from "@ai-sdk/provider-utils";
|
|
3
|
+
import { DefaultGeneratedFile, InvalidToolApprovalSignatureError, NoOutputGeneratedError, Output, ToolChoiceViolationError, dynamicTool, experimental_filterActiveTools, experimental_streamLanguageModelCall, gateway, isStepCount, tool, wrapLanguageModel } from "ai";
|
|
4
|
+
import { DefaultGenerateTextResult, DefaultStepResult, addLanguageModelUsage, asLanguageModelUsage, calculateTokensPerSecond, collectToolApprovals, convertLanguageModelContent, convertToLanguageModelPrompt, createDefaultDownloadFunction, createNullLanguageModelUsage, createRestrictedTelemetryDispatcher, createToolModelOutput, createToolSearchState, downloadAssets, mapToolResultOutput, mergeAbortSignals, mergeCallbacks, parseToolCall, prepareLanguageModelCallOptions, prepareRetries, prepareToolChoice, prepareTools, resolveLanguageModel, signToolApproval, standardizePrompt, validateApprovedToolApprovals, verifyToolApprovalSignature } from "ai/internal";
|
|
5
5
|
import { getWorkflowMetadata } from "workflow";
|
|
6
6
|
import Ajv from "ajv";
|
|
7
7
|
//#region src/add-tool-results-to-conversation.ts
|
|
@@ -118,6 +118,265 @@ async function resolveToolContext({ toolName, tool, toolsContext }) {
|
|
|
118
118
|
});
|
|
119
119
|
}
|
|
120
120
|
//#endregion
|
|
121
|
+
//#region src/to-model-response-messages.ts
|
|
122
|
+
/** Convert provider file references back to public message data without re-running tool output hooks. */
|
|
123
|
+
function toModelResponseMessages(messages) {
|
|
124
|
+
return messages.map((message) => message.role !== "assistant" ? message : {
|
|
125
|
+
...message,
|
|
126
|
+
content: message.content.map((part) => {
|
|
127
|
+
if (part.type !== "file" && part.type !== "reasoning-file") return part;
|
|
128
|
+
return {
|
|
129
|
+
...part,
|
|
130
|
+
data: part.data.type === "data" ? part.data.data : part.data.type === "url" ? part.data.url : part.data
|
|
131
|
+
};
|
|
132
|
+
})
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region src/build-model-step-result.ts
|
|
137
|
+
async function buildModelStepResult(raw, toolCalls, finish, providerExecutedToolResults, opts) {
|
|
138
|
+
if (raw.generation != null && finish != null) {
|
|
139
|
+
const providerContent = [];
|
|
140
|
+
for (const part of raw.content) switch (part.type) {
|
|
141
|
+
case "reasoning":
|
|
142
|
+
if (!("reasoningIndex" in part)) providerContent.push(part);
|
|
143
|
+
break;
|
|
144
|
+
case "tool-call": {
|
|
145
|
+
const call = toolCalls[part.toolCallIndex];
|
|
146
|
+
providerContent.push({
|
|
147
|
+
...call,
|
|
148
|
+
input: "",
|
|
149
|
+
type: "tool-call"
|
|
150
|
+
});
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
case "provider-tool-result":
|
|
154
|
+
providerContent.push({
|
|
155
|
+
...providerExecutedToolResults.get(part.toolCallId),
|
|
156
|
+
type: "tool-result"
|
|
157
|
+
});
|
|
158
|
+
break;
|
|
159
|
+
case "file":
|
|
160
|
+
providerContent.push({
|
|
161
|
+
...part,
|
|
162
|
+
data: {
|
|
163
|
+
type: "data",
|
|
164
|
+
data: part.data
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
break;
|
|
168
|
+
default: providerContent.push(part);
|
|
169
|
+
}
|
|
170
|
+
const content = await convertLanguageModelContent({
|
|
171
|
+
content: providerContent,
|
|
172
|
+
toolCalls,
|
|
173
|
+
toolOutputs: [],
|
|
174
|
+
toolApprovalRequests: [],
|
|
175
|
+
toolApprovalResponses: [],
|
|
176
|
+
tools: opts.tools
|
|
177
|
+
});
|
|
178
|
+
const duration = raw.generation.responseTimeMs;
|
|
179
|
+
const rate = (tokens) => calculateTokensPerSecond({
|
|
180
|
+
tokens,
|
|
181
|
+
durationMs: duration
|
|
182
|
+
});
|
|
183
|
+
return new DefaultStepResult({
|
|
184
|
+
callId: "workflow-agent",
|
|
185
|
+
stepNumber: opts.stepNumber,
|
|
186
|
+
provider: raw.generation.provider,
|
|
187
|
+
modelId: raw.generation.modelId,
|
|
188
|
+
runtimeContext: opts.runtimeContext,
|
|
189
|
+
toolsContext: opts.toolsContext,
|
|
190
|
+
content,
|
|
191
|
+
finishReason: finish.finishReason,
|
|
192
|
+
rawFinishReason: finish.rawFinishReason,
|
|
193
|
+
usage: finish.usage,
|
|
194
|
+
warnings: raw.warnings,
|
|
195
|
+
request: {
|
|
196
|
+
...raw.generation.request,
|
|
197
|
+
messages: opts.requestMessages
|
|
198
|
+
},
|
|
199
|
+
response: {
|
|
200
|
+
...raw.responseMetadata,
|
|
201
|
+
messages: []
|
|
202
|
+
},
|
|
203
|
+
providerMetadata: finish.providerMetadata,
|
|
204
|
+
performance: {
|
|
205
|
+
responseTimeMs: duration,
|
|
206
|
+
stepTimeMs: duration,
|
|
207
|
+
toolExecutionMs: {},
|
|
208
|
+
effectiveOutputTokensPerSecond: rate(finish.usage.outputTokens),
|
|
209
|
+
effectiveTotalTokensPerSecond: rate(finish.usage.totalTokens),
|
|
210
|
+
outputTokensPerSecond: void 0,
|
|
211
|
+
inputTokensPerSecond: void 0,
|
|
212
|
+
timeToFirstOutputMs: void 0
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
const { content: rawContent, reasoning: reasoningParts, responseMetadata, warnings } = raw;
|
|
217
|
+
const reasoningText = reasoningParts.map((r) => r.text).join("") || void 0;
|
|
218
|
+
const validToolCallsByIndex = new Map(toolCalls.flatMap((tc, index) => tc.invalid ? [] : [[index, {
|
|
219
|
+
type: "tool-call",
|
|
220
|
+
toolCallId: tc.toolCallId,
|
|
221
|
+
toolName: tc.toolName,
|
|
222
|
+
input: tc.input,
|
|
223
|
+
...tc.providerExecuted != null ? { providerExecuted: tc.providerExecuted } : {},
|
|
224
|
+
...tc.title != null ? { title: tc.title } : {},
|
|
225
|
+
...tc.toolMetadata != null ? { toolMetadata: tc.toolMetadata } : {},
|
|
226
|
+
...tc.dynamic ? { dynamic: true } : {},
|
|
227
|
+
...tc.providerExecuted ? { providerExecuted: true } : {},
|
|
228
|
+
...tc.providerMetadata != null ? { providerMetadata: tc.providerMetadata } : {}
|
|
229
|
+
}]]));
|
|
230
|
+
const validToolCalls = [...validToolCallsByIndex.values()];
|
|
231
|
+
const content = [];
|
|
232
|
+
const files = [];
|
|
233
|
+
const sources = [];
|
|
234
|
+
let text = "";
|
|
235
|
+
for (const part of rawContent) switch (part.type) {
|
|
236
|
+
case "text":
|
|
237
|
+
text += part.text;
|
|
238
|
+
content.push({
|
|
239
|
+
type: "text",
|
|
240
|
+
text: part.text,
|
|
241
|
+
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
242
|
+
});
|
|
243
|
+
break;
|
|
244
|
+
case "reasoning":
|
|
245
|
+
if ("reasoningIndex" in part) {
|
|
246
|
+
const reasoningPart = reasoningParts[part.reasoningIndex];
|
|
247
|
+
if (reasoningPart != null) content.push({
|
|
248
|
+
type: "reasoning",
|
|
249
|
+
text: reasoningPart.text,
|
|
250
|
+
...reasoningPart.providerMetadata != null ? { providerMetadata: reasoningPart.providerMetadata } : {}
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
break;
|
|
254
|
+
case "file": {
|
|
255
|
+
const file = new DefaultGeneratedFile({
|
|
256
|
+
data: part.data,
|
|
257
|
+
mediaType: part.mediaType,
|
|
258
|
+
providerMetadata: part.providerMetadata
|
|
259
|
+
});
|
|
260
|
+
files.push(file);
|
|
261
|
+
content.push({
|
|
262
|
+
type: "file",
|
|
263
|
+
file,
|
|
264
|
+
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
265
|
+
});
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
case "source":
|
|
269
|
+
sources.push(part);
|
|
270
|
+
content.push(part);
|
|
271
|
+
break;
|
|
272
|
+
case "tool-approval-request": {
|
|
273
|
+
const toolCall = validToolCalls.find((call) => call.toolCallId === part.toolCallId);
|
|
274
|
+
if (toolCall != null) content.push({
|
|
275
|
+
type: "tool-approval-request",
|
|
276
|
+
approvalId: part.approvalId,
|
|
277
|
+
toolCall
|
|
278
|
+
});
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
case "tool-call": {
|
|
282
|
+
const toolCall = validToolCallsByIndex.get(part.toolCallIndex);
|
|
283
|
+
if (toolCall != null) content.push(toolCall);
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
case "provider-tool-result": {
|
|
287
|
+
const result = providerExecutedToolResults.get(part.toolCallId);
|
|
288
|
+
if (result == null) break;
|
|
289
|
+
const toolCall = toolCalls.find((toolCall) => toolCall.toolCallId === result.toolCallId);
|
|
290
|
+
const common = {
|
|
291
|
+
toolCallId: result.toolCallId,
|
|
292
|
+
toolName: result.toolName,
|
|
293
|
+
input: toolCall?.input,
|
|
294
|
+
providerExecuted: true,
|
|
295
|
+
...result.dynamic === true || toolCall?.dynamic === true ? { dynamic: true } : {},
|
|
296
|
+
...result.providerMetadata != null ? { providerMetadata: result.providerMetadata } : {},
|
|
297
|
+
...toolCall?.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
|
|
298
|
+
};
|
|
299
|
+
content.push(result.isError ? {
|
|
300
|
+
type: "tool-error",
|
|
301
|
+
...common,
|
|
302
|
+
error: result.result
|
|
303
|
+
} : {
|
|
304
|
+
type: "tool-result",
|
|
305
|
+
...common,
|
|
306
|
+
output: result.result
|
|
307
|
+
});
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
const toolResults = content.filter((part) => part.type === "tool-result");
|
|
312
|
+
return {
|
|
313
|
+
callId: "workflow-agent",
|
|
314
|
+
stepNumber: opts.stepNumber,
|
|
315
|
+
model: {
|
|
316
|
+
provider: responseMetadata?.modelId?.split(":")[0] ?? "unknown",
|
|
317
|
+
modelId: responseMetadata?.modelId ?? "unknown"
|
|
318
|
+
},
|
|
319
|
+
functionId: void 0,
|
|
320
|
+
metadata: void 0,
|
|
321
|
+
runtimeContext: opts.runtimeContext ?? {},
|
|
322
|
+
toolsContext: opts.toolsContext ?? {},
|
|
323
|
+
content,
|
|
324
|
+
text,
|
|
325
|
+
reasoning: reasoningParts.map((r) => ({
|
|
326
|
+
type: "reasoning",
|
|
327
|
+
text: r.text,
|
|
328
|
+
...r.providerMetadata != null ? { providerMetadata: r.providerMetadata } : {}
|
|
329
|
+
})),
|
|
330
|
+
reasoningText,
|
|
331
|
+
files,
|
|
332
|
+
sources,
|
|
333
|
+
toolCalls: validToolCalls,
|
|
334
|
+
staticToolCalls: validToolCalls.filter((tc) => tc.dynamic !== true),
|
|
335
|
+
dynamicToolCalls: validToolCalls.filter((tc) => tc.dynamic),
|
|
336
|
+
toolResults,
|
|
337
|
+
staticToolResults: toolResults.filter((result) => result.dynamic !== true),
|
|
338
|
+
dynamicToolResults: toolResults.filter((result) => result.dynamic === true),
|
|
339
|
+
finishReason: finish?.finishReason ?? "other",
|
|
340
|
+
rawFinishReason: finish?.rawFinishReason,
|
|
341
|
+
usage: finish?.usage ?? {
|
|
342
|
+
inputTokens: 0,
|
|
343
|
+
inputTokenDetails: {
|
|
344
|
+
noCacheTokens: void 0,
|
|
345
|
+
cacheReadTokens: void 0,
|
|
346
|
+
cacheWriteTokens: void 0
|
|
347
|
+
},
|
|
348
|
+
outputTokens: 0,
|
|
349
|
+
outputTokenDetails: {
|
|
350
|
+
textTokens: void 0,
|
|
351
|
+
reasoningTokens: void 0
|
|
352
|
+
},
|
|
353
|
+
totalTokens: 0
|
|
354
|
+
},
|
|
355
|
+
performance: {
|
|
356
|
+
effectiveOutputTokensPerSecond: 0,
|
|
357
|
+
outputTokensPerSecond: void 0,
|
|
358
|
+
inputTokensPerSecond: void 0,
|
|
359
|
+
effectiveTotalTokensPerSecond: 0,
|
|
360
|
+
stepTimeMs: 0,
|
|
361
|
+
responseTimeMs: 0,
|
|
362
|
+
toolExecutionMs: {},
|
|
363
|
+
timeToFirstOutputMs: void 0
|
|
364
|
+
},
|
|
365
|
+
warnings,
|
|
366
|
+
request: {
|
|
367
|
+
body: "",
|
|
368
|
+
messages: []
|
|
369
|
+
},
|
|
370
|
+
response: {
|
|
371
|
+
id: responseMetadata?.id ?? "unknown",
|
|
372
|
+
timestamp: responseMetadata?.timestamp ?? /* @__PURE__ */ new Date(),
|
|
373
|
+
modelId: responseMetadata?.modelId ?? "unknown",
|
|
374
|
+
messages: []
|
|
375
|
+
},
|
|
376
|
+
providerMetadata: finish?.providerMetadata ?? {}
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
//#endregion
|
|
121
380
|
//#region src/serializable-schema.ts
|
|
122
381
|
/**
|
|
123
382
|
* Converts a ToolSet (with Zod/standard schemas and execute functions) to a
|
|
@@ -233,6 +492,136 @@ function resolveSerializableTools(tools) {
|
|
|
233
492
|
}));
|
|
234
493
|
}
|
|
235
494
|
//#endregion
|
|
495
|
+
//#region src/do-generate-step.ts
|
|
496
|
+
/** A single durable provider call; orchestration and callbacks stay in the workflow. */
|
|
497
|
+
async function doGenerateStep(prompt, modelInit, serializedTools, options = {}) {
|
|
498
|
+
"use step";
|
|
499
|
+
try {
|
|
500
|
+
return await generateModelCall(prompt, modelInit, serializedTools, options);
|
|
501
|
+
} catch (error) {
|
|
502
|
+
return {
|
|
503
|
+
toolCalls: [],
|
|
504
|
+
finish: void 0,
|
|
505
|
+
raw: {
|
|
506
|
+
content: [],
|
|
507
|
+
reasoning: []
|
|
508
|
+
},
|
|
509
|
+
providerExecutedToolResults: /* @__PURE__ */ new Map(),
|
|
510
|
+
terminalError: error
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
async function generateModelCall(prompt, modelInit, serializedTools, options) {
|
|
515
|
+
const remaining = options.timeoutAt == null ? void 0 : options.timeoutAt - Date.now();
|
|
516
|
+
options.abortSignal?.throwIfAborted();
|
|
517
|
+
if (remaining != null && remaining <= 0) throw new DOMException("The generation deadline expired.", "TimeoutError");
|
|
518
|
+
const abortSignal = remaining == null ? options.abortSignal : AbortSignal.any([...options.abortSignal == null ? [] : [options.abortSignal], AbortSignal.timeout(remaining)]);
|
|
519
|
+
const model = resolveLanguageModel(modelInit);
|
|
520
|
+
const tools = resolveSerializableTools(serializedTools);
|
|
521
|
+
const toolChoice = prepareToolChoice({ toolChoice: options.toolChoice });
|
|
522
|
+
const modelTools = await prepareTools({ tools });
|
|
523
|
+
const settings = prepareLanguageModelCallOptions(options);
|
|
524
|
+
const { retry } = prepareRetries({
|
|
525
|
+
maxRetries: options.maxRetries,
|
|
526
|
+
abortSignal
|
|
527
|
+
});
|
|
528
|
+
const start = Date.now();
|
|
529
|
+
const response = await retry(async () => {
|
|
530
|
+
abortSignal?.throwIfAborted();
|
|
531
|
+
if (options.timeoutAt != null && options.timeoutAt <= Date.now()) throw new DOMException("The generation deadline expired.", "TimeoutError");
|
|
532
|
+
return model.doGenerate({
|
|
533
|
+
...settings,
|
|
534
|
+
prompt: [...prompt],
|
|
535
|
+
tools: modelTools,
|
|
536
|
+
toolChoice,
|
|
537
|
+
responseFormat: options.responseFormat,
|
|
538
|
+
providerOptions: options.providerOptions,
|
|
539
|
+
headers: options.headers,
|
|
540
|
+
abortSignal
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
abortSignal?.throwIfAborted();
|
|
544
|
+
const responseTimeMs = Date.now() - start;
|
|
545
|
+
const toolCalls = await Promise.all(response.content.filter((part) => part.type === "tool-call").map((toolCall) => parseToolCall({
|
|
546
|
+
toolCall,
|
|
547
|
+
tools,
|
|
548
|
+
repairToolCall: options.repairToolCall,
|
|
549
|
+
instructions: prompt.filter((message) => message.role === "system").map((message) => message.content).join("\n") || void 0,
|
|
550
|
+
messages: prompt.filter((message) => message.role !== "system")
|
|
551
|
+
})));
|
|
552
|
+
if ((toolChoice.type === "required" || toolChoice.type === "tool") && !toolCalls.some((call) => toolChoice.type === "required" || call.toolName === toolChoice.toolName)) throw new ToolChoiceViolationError({
|
|
553
|
+
toolChoice,
|
|
554
|
+
finishReason: response.finishReason.unified,
|
|
555
|
+
provider: model.provider,
|
|
556
|
+
modelId: model.modelId,
|
|
557
|
+
content: response.content
|
|
558
|
+
});
|
|
559
|
+
const providerExecutedToolResults = /* @__PURE__ */ new Map();
|
|
560
|
+
const content = response.content.map((part) => {
|
|
561
|
+
switch (part.type) {
|
|
562
|
+
case "tool-call": return {
|
|
563
|
+
type: "tool-call",
|
|
564
|
+
toolCallIndex: toolCalls.findIndex((call) => call.toolCallId === part.toolCallId)
|
|
565
|
+
};
|
|
566
|
+
case "tool-result":
|
|
567
|
+
providerExecutedToolResults.set(part.toolCallId, part);
|
|
568
|
+
return {
|
|
569
|
+
type: "provider-tool-result",
|
|
570
|
+
toolCallId: part.toolCallId
|
|
571
|
+
};
|
|
572
|
+
case "file": return {
|
|
573
|
+
type: "file",
|
|
574
|
+
data: part.data.type === "data" ? typeof part.data.data === "string" ? part.data.data : convertUint8ArrayToBase64(part.data.data) : part.data.url.toString(),
|
|
575
|
+
mediaType: part.mediaType,
|
|
576
|
+
providerMetadata: part.providerMetadata
|
|
577
|
+
};
|
|
578
|
+
default: return part;
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
const toolInputLifecycleEvents = toolCalls.flatMap((call) => {
|
|
582
|
+
const tool = serializedTools[call.toolName];
|
|
583
|
+
if (call.invalid || tool == null) return [];
|
|
584
|
+
const events = [];
|
|
585
|
+
if (tool.hasOnInputStart || tool.hasOnInputAvailable) events.push([
|
|
586
|
+
"start",
|
|
587
|
+
call.toolCallId,
|
|
588
|
+
call.toolName
|
|
589
|
+
]);
|
|
590
|
+
if (tool.hasOnInputAvailable) events.push(["available", call.toolCallId]);
|
|
591
|
+
return events;
|
|
592
|
+
});
|
|
593
|
+
return {
|
|
594
|
+
toolCalls,
|
|
595
|
+
finish: {
|
|
596
|
+
finishReason: response.finishReason.unified,
|
|
597
|
+
rawFinishReason: response.finishReason.raw,
|
|
598
|
+
usage: asLanguageModelUsage(response.usage),
|
|
599
|
+
providerMetadata: response.providerMetadata
|
|
600
|
+
},
|
|
601
|
+
raw: {
|
|
602
|
+
content,
|
|
603
|
+
reasoning: [],
|
|
604
|
+
warnings: response.warnings,
|
|
605
|
+
responseMetadata: {
|
|
606
|
+
id: response.response?.id ?? generateId(),
|
|
607
|
+
timestamp: response.response?.timestamp ?? /* @__PURE__ */ new Date(),
|
|
608
|
+
modelId: response.response?.modelId ?? model.modelId,
|
|
609
|
+
headers: response.response?.headers,
|
|
610
|
+
...options.include?.responseBody ? { body: response.response?.body } : {}
|
|
611
|
+
},
|
|
612
|
+
generation: {
|
|
613
|
+
provider: model.provider,
|
|
614
|
+
modelId: model.modelId,
|
|
615
|
+
responseTimeMs,
|
|
616
|
+
request: options.include?.requestBody ? response.request : void 0
|
|
617
|
+
}
|
|
618
|
+
},
|
|
619
|
+
providerExecutedToolResults,
|
|
620
|
+
toolInputLifecycleEvents
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
doGenerateStep.maxRetries = 0;
|
|
624
|
+
//#endregion
|
|
236
625
|
//#region src/do-stream-step.ts
|
|
237
626
|
async function doStreamStep(conversationPrompt, modelInit, writable, serializedTools, options) {
|
|
238
627
|
"use step";
|
|
@@ -276,7 +665,13 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
|
|
|
276
665
|
try {
|
|
277
666
|
const { stream } = await retry(() => experimental_streamLanguageModelCall({
|
|
278
667
|
model: modelWithTransforms,
|
|
279
|
-
messages: conversationPrompt
|
|
668
|
+
messages: conversationPrompt.map((message) => message.role !== "tool" ? message : {
|
|
669
|
+
...message,
|
|
670
|
+
content: message.content.map((part) => part.type === "tool-approval-response" ? {
|
|
671
|
+
...part,
|
|
672
|
+
providerExecuted: true
|
|
673
|
+
} : part)
|
|
674
|
+
}),
|
|
280
675
|
allowSystemInMessages: true,
|
|
281
676
|
tools,
|
|
282
677
|
toolChoice: options?.toolChoice,
|
|
@@ -403,6 +798,13 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
|
|
|
403
798
|
case "source":
|
|
404
799
|
content.push(part);
|
|
405
800
|
break;
|
|
801
|
+
case "tool-approval-request":
|
|
802
|
+
content.push({
|
|
803
|
+
type: "tool-approval-request",
|
|
804
|
+
approvalId: part.approvalId,
|
|
805
|
+
toolCallId: part.toolCall.toolCallId
|
|
806
|
+
});
|
|
807
|
+
break;
|
|
406
808
|
case "tool-call": {
|
|
407
809
|
const toolCallPart = part;
|
|
408
810
|
const toolCallIndex = toolCalls.length;
|
|
@@ -576,7 +978,7 @@ function upsertReasoningContentPart({ content, reasoningParts, reasoningPartInde
|
|
|
576
978
|
if (providerMetadata != null) part.providerMetadata = providerMetadata;
|
|
577
979
|
}
|
|
578
980
|
//#endregion
|
|
579
|
-
//#region src/
|
|
981
|
+
//#region src/model-call-iterator.ts
|
|
580
982
|
const prepareStepGenerationSettingKeys = [
|
|
581
983
|
"maxOutputTokens",
|
|
582
984
|
"temperature",
|
|
@@ -599,7 +1001,7 @@ function mergePrepareStepGenerationSettings(current, overrides) {
|
|
|
599
1001
|
...definedOverrides
|
|
600
1002
|
};
|
|
601
1003
|
}
|
|
602
|
-
async function*
|
|
1004
|
+
async function* modelCallIterator({ prompt, mode = "stream", include, initialInstructions, initialMessages = prompt, tools = {}, writable, model, stopConditions, onStepEnd, onStepFinish, onStepStart, onError, prepareStep, generationSettings, toolChoice, runtimeContext, toolsContext, telemetry, includeRawChunks = false, timeoutAt, repairToolCall, responseFormat, experimental_transform, experimental_sandbox: sandbox }) {
|
|
603
1005
|
let conversationPrompt = [...prompt];
|
|
604
1006
|
let currentModel = model;
|
|
605
1007
|
let currentGenerationSettings = generationSettings ?? {};
|
|
@@ -626,7 +1028,10 @@ async function* streamTextIterator({ prompt, initialInstructions, initialMessage
|
|
|
626
1028
|
includeToolsContext: telemetry?.includeToolsContext
|
|
627
1029
|
});
|
|
628
1030
|
while (!done) {
|
|
629
|
-
if (currentGenerationSettings.abortSignal?.aborted)
|
|
1031
|
+
if (currentGenerationSettings.abortSignal?.aborted) {
|
|
1032
|
+
if (mode === "generate") currentGenerationSettings.abortSignal.throwIfAborted();
|
|
1033
|
+
break;
|
|
1034
|
+
}
|
|
630
1035
|
let stepSandbox = sandbox;
|
|
631
1036
|
if (prepareStep) {
|
|
632
1037
|
const prepareResult = await prepareStep({
|
|
@@ -716,25 +1121,28 @@ async function* streamTextIterator({ prompt, initialInstructions, initialMessage
|
|
|
716
1121
|
providerOptions: currentGenerationSettings.providerOptions,
|
|
717
1122
|
headers: currentGenerationSettings.headers
|
|
718
1123
|
});
|
|
719
|
-
const stepInputMessages = conversationPrompt;
|
|
720
|
-
const
|
|
1124
|
+
const stepInputMessages = mode === "generate" ? [...conversationPrompt] : conversationPrompt;
|
|
1125
|
+
const callOptions = {
|
|
721
1126
|
...currentGenerationSettings,
|
|
722
1127
|
toolChoice: currentToolChoice,
|
|
723
1128
|
includeRawChunks,
|
|
724
1129
|
timeoutAt,
|
|
725
1130
|
repairToolCall,
|
|
726
1131
|
responseFormat,
|
|
1132
|
+
include,
|
|
727
1133
|
experimental_transform
|
|
728
|
-
}
|
|
729
|
-
|
|
1134
|
+
};
|
|
1135
|
+
const modelCallResult = mode === "generate" ? await doGenerateStep(conversationPrompt, currentModel, serializedTools, callOptions) : await doStreamStep(conversationPrompt, currentModel, writable, serializedTools, callOptions);
|
|
1136
|
+
if (modelCallResult.aborted) {
|
|
730
1137
|
wasAborted = true;
|
|
731
1138
|
break;
|
|
732
1139
|
}
|
|
733
|
-
if ("terminalError" in
|
|
734
|
-
|
|
1140
|
+
if ("terminalError" in modelCallResult) {
|
|
1141
|
+
if (mode === "generate") throw modelCallResult.terminalError;
|
|
1142
|
+
terminalError = modelCallResult.terminalError;
|
|
735
1143
|
hasTerminalError = true;
|
|
736
1144
|
}
|
|
737
|
-
const { toolCalls, finish, raw, providerExecutedToolResults, toolInputLifecycleEvents } =
|
|
1145
|
+
const { toolCalls, finish, raw, providerExecutedToolResults, toolInputLifecycleEvents } = modelCallResult;
|
|
738
1146
|
await invokeToolInputLifecycleCallbacks({
|
|
739
1147
|
events: toolInputLifecycleEvents ?? [],
|
|
740
1148
|
toolCalls,
|
|
@@ -744,7 +1152,9 @@ async function* streamTextIterator({ prompt, initialInstructions, initialMessage
|
|
|
744
1152
|
toolsContext: currentToolsContext,
|
|
745
1153
|
experimental_sandbox: stepSandbox
|
|
746
1154
|
});
|
|
747
|
-
const step =
|
|
1155
|
+
const step = await buildModelStepResult(raw, toolCalls, finish, providerExecutedToolResults, {
|
|
1156
|
+
tools: effectiveTools,
|
|
1157
|
+
requestMessages: mode === "generate" && include?.requestMessages ? stepInputMessages : void 0,
|
|
748
1158
|
stepNumber,
|
|
749
1159
|
runtimeContext: currentRuntimeContext,
|
|
750
1160
|
toolsContext: currentToolsContext
|
|
@@ -771,7 +1181,7 @@ async function* streamTextIterator({ prompt, initialInstructions, initialMessage
|
|
|
771
1181
|
if (hasTerminalError) done = true;
|
|
772
1182
|
else if (shouldProcessTools) {
|
|
773
1183
|
lastStepWasYielded = true;
|
|
774
|
-
const { content: assistantContent, providerExecutedToolResultPositions } = getAssistantMessageContent(step);
|
|
1184
|
+
const { content: assistantContent, providerExecutedToolResultPositions } = getAssistantMessageContent(step, mode);
|
|
775
1185
|
const includedToolCallIds = new Set(assistantContent.flatMap((part) => part.type === "tool-call" ? [part.toolCallId] : []));
|
|
776
1186
|
conversationPrompt.push({
|
|
777
1187
|
role: "assistant",
|
|
@@ -794,23 +1204,22 @@ async function* streamTextIterator({ prompt, initialInstructions, initialMessage
|
|
|
794
1204
|
providerExecutedToolCallIds: /* @__PURE__ */ new Set([...toolCalls.flatMap((toolCall) => toolCall.providerExecuted ? [toolCall.toolCallId] : []), ...providerExecutedToolResults.keys()]),
|
|
795
1205
|
providerExecutedToolResultPositions
|
|
796
1206
|
});
|
|
797
|
-
step.response.messages.push(...responseMessages);
|
|
1207
|
+
step.response.messages.push(...mode === "generate" ? toModelResponseMessages(responseMessages) : responseMessages);
|
|
798
1208
|
const stopConditionMet = (stopConditions == null ? [] : Array.isArray(stopConditions) ? stopConditions : [stopConditions]).some((test) => test({ steps }));
|
|
799
1209
|
const hasClientToolCalls = toolCalls.some((toolCall) => !toolCall.providerExecuted);
|
|
800
1210
|
done = stopConditionMet || !hasClientToolCalls && pendingDeferredToolCallIds.size === 0;
|
|
801
|
-
} else if (finishReason === "stop" || finishReason === "tool-calls") {
|
|
802
|
-
const { content: assistantContent } = getAssistantMessageContent(step);
|
|
1211
|
+
} else if (mode === "generate" || finishReason === "stop" || finishReason === "tool-calls" || finishReason === "length") {
|
|
1212
|
+
const { content: assistantContent } = getAssistantMessageContent(step, mode);
|
|
803
1213
|
if (assistantContent.length > 0) {
|
|
804
1214
|
const assistantMessage = {
|
|
805
1215
|
role: "assistant",
|
|
806
1216
|
content: assistantContent
|
|
807
1217
|
};
|
|
808
1218
|
conversationPrompt.push(assistantMessage);
|
|
809
|
-
step.response.messages.push(assistantMessage);
|
|
1219
|
+
step.response.messages.push(...mode === "generate" ? toModelResponseMessages([assistantMessage]) : [assistantMessage]);
|
|
810
1220
|
}
|
|
811
1221
|
done = true;
|
|
812
|
-
} else if (finishReason === "
|
|
813
|
-
else if (finishReason === "content-filter") done = true;
|
|
1222
|
+
} else if (finishReason === "content-filter") done = true;
|
|
814
1223
|
else if (finishReason === "error") done = true;
|
|
815
1224
|
else if (finishReason === "other") done = true;
|
|
816
1225
|
else if (finishReason === "unknown") done = true;
|
|
@@ -909,193 +1318,45 @@ function normalizeStepForTelemetry$1(step) {
|
|
|
909
1318
|
}
|
|
910
1319
|
};
|
|
911
1320
|
}
|
|
912
|
-
/**
|
|
913
|
-
|
|
914
|
-
* `doStreamStep`. Runs outside the step boundary so StepResult's redundant
|
|
915
|
-
* fields (duplicate tool-call lists, `text`, `files`, `sources`, and
|
|
916
|
-
* `reasoningText`) and the per-chunk snapshot don't cross it. Tool-result
|
|
917
|
-
* arrays are initialized here and populated after execution. The shape matches
|
|
918
|
-
* what the AI SDK's `streamText` exposes to callers.
|
|
919
|
-
*/
|
|
920
|
-
function buildStepResult(raw, toolCalls, finish, providerExecutedToolResults, opts) {
|
|
921
|
-
const { content: rawContent, reasoning: reasoningParts, responseMetadata, warnings } = raw;
|
|
922
|
-
const reasoningText = reasoningParts.map((r) => r.text).join("") || void 0;
|
|
923
|
-
const validToolCallsByIndex = new Map(toolCalls.flatMap((tc, index) => tc.invalid ? [] : [[index, {
|
|
924
|
-
type: "tool-call",
|
|
925
|
-
toolCallId: tc.toolCallId,
|
|
926
|
-
toolName: tc.toolName,
|
|
927
|
-
input: tc.input,
|
|
928
|
-
...tc.providerExecuted != null ? { providerExecuted: tc.providerExecuted } : {},
|
|
929
|
-
...tc.title != null ? { title: tc.title } : {},
|
|
930
|
-
...tc.toolMetadata != null ? { toolMetadata: tc.toolMetadata } : {},
|
|
931
|
-
...tc.dynamic ? { dynamic: true } : {},
|
|
932
|
-
...tc.providerExecuted ? { providerExecuted: true } : {},
|
|
933
|
-
...tc.providerMetadata != null ? { providerMetadata: tc.providerMetadata } : {}
|
|
934
|
-
}]]));
|
|
935
|
-
const validToolCalls = [...validToolCallsByIndex.values()];
|
|
936
|
-
const content = [];
|
|
937
|
-
const files = [];
|
|
938
|
-
const sources = [];
|
|
939
|
-
let text = "";
|
|
940
|
-
for (const part of rawContent) switch (part.type) {
|
|
941
|
-
case "text":
|
|
942
|
-
text += part.text;
|
|
943
|
-
content.push({
|
|
944
|
-
type: "text",
|
|
945
|
-
text: part.text,
|
|
946
|
-
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
947
|
-
});
|
|
948
|
-
break;
|
|
949
|
-
case "reasoning": {
|
|
950
|
-
const reasoningPart = reasoningParts[part.reasoningIndex];
|
|
951
|
-
if (reasoningPart != null) content.push({
|
|
952
|
-
type: "reasoning",
|
|
953
|
-
text: reasoningPart.text,
|
|
954
|
-
...reasoningPart.providerMetadata != null ? { providerMetadata: reasoningPart.providerMetadata } : {}
|
|
955
|
-
});
|
|
956
|
-
break;
|
|
957
|
-
}
|
|
958
|
-
case "file": {
|
|
959
|
-
const file = new DefaultGeneratedFile({
|
|
960
|
-
data: part.data,
|
|
961
|
-
mediaType: part.mediaType,
|
|
962
|
-
providerMetadata: part.providerMetadata
|
|
963
|
-
});
|
|
964
|
-
files.push(file);
|
|
965
|
-
content.push({
|
|
966
|
-
type: "file",
|
|
967
|
-
file,
|
|
968
|
-
...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
|
|
969
|
-
});
|
|
970
|
-
break;
|
|
971
|
-
}
|
|
972
|
-
case "source":
|
|
973
|
-
sources.push(part);
|
|
974
|
-
content.push(part);
|
|
975
|
-
break;
|
|
976
|
-
case "tool-call": {
|
|
977
|
-
const toolCall = validToolCallsByIndex.get(part.toolCallIndex);
|
|
978
|
-
if (toolCall != null) content.push(toolCall);
|
|
979
|
-
break;
|
|
980
|
-
}
|
|
981
|
-
case "provider-tool-result": {
|
|
982
|
-
const result = providerExecutedToolResults.get(part.toolCallId);
|
|
983
|
-
if (result == null) break;
|
|
984
|
-
const toolCall = toolCalls.find((toolCall) => toolCall.toolCallId === result.toolCallId);
|
|
985
|
-
const common = {
|
|
986
|
-
toolCallId: result.toolCallId,
|
|
987
|
-
toolName: result.toolName,
|
|
988
|
-
input: toolCall?.input,
|
|
989
|
-
providerExecuted: true,
|
|
990
|
-
...result.dynamic === true || toolCall?.dynamic === true ? { dynamic: true } : {},
|
|
991
|
-
...result.providerMetadata != null ? { providerMetadata: result.providerMetadata } : {},
|
|
992
|
-
...toolCall?.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
|
|
993
|
-
};
|
|
994
|
-
content.push(result.isError ? {
|
|
995
|
-
type: "tool-error",
|
|
996
|
-
...common,
|
|
997
|
-
error: result.result
|
|
998
|
-
} : {
|
|
999
|
-
type: "tool-result",
|
|
1000
|
-
...common,
|
|
1001
|
-
output: result.result
|
|
1002
|
-
});
|
|
1003
|
-
break;
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
const toolResults = content.filter((part) => part.type === "tool-result");
|
|
1007
|
-
return {
|
|
1008
|
-
callId: "workflow-agent",
|
|
1009
|
-
stepNumber: opts.stepNumber,
|
|
1010
|
-
model: {
|
|
1011
|
-
provider: responseMetadata?.modelId?.split(":")[0] ?? "unknown",
|
|
1012
|
-
modelId: responseMetadata?.modelId ?? "unknown"
|
|
1013
|
-
},
|
|
1014
|
-
functionId: void 0,
|
|
1015
|
-
metadata: void 0,
|
|
1016
|
-
runtimeContext: opts.runtimeContext ?? {},
|
|
1017
|
-
toolsContext: opts.toolsContext ?? {},
|
|
1018
|
-
content,
|
|
1019
|
-
text,
|
|
1020
|
-
reasoning: reasoningParts.map((r) => ({
|
|
1021
|
-
type: "reasoning",
|
|
1022
|
-
text: r.text,
|
|
1023
|
-
...r.providerMetadata != null ? { providerMetadata: r.providerMetadata } : {}
|
|
1024
|
-
})),
|
|
1025
|
-
reasoningText,
|
|
1026
|
-
files,
|
|
1027
|
-
sources,
|
|
1028
|
-
toolCalls: validToolCalls,
|
|
1029
|
-
staticToolCalls: validToolCalls.filter((tc) => tc.dynamic !== true),
|
|
1030
|
-
dynamicToolCalls: validToolCalls.filter((tc) => tc.dynamic),
|
|
1031
|
-
toolResults,
|
|
1032
|
-
staticToolResults: toolResults.filter((result) => result.dynamic !== true),
|
|
1033
|
-
dynamicToolResults: toolResults.filter((result) => result.dynamic === true),
|
|
1034
|
-
finishReason: finish?.finishReason ?? "other",
|
|
1035
|
-
rawFinishReason: finish?.rawFinishReason,
|
|
1036
|
-
usage: finish?.usage ?? {
|
|
1037
|
-
inputTokens: 0,
|
|
1038
|
-
inputTokenDetails: {
|
|
1039
|
-
noCacheTokens: void 0,
|
|
1040
|
-
cacheReadTokens: void 0,
|
|
1041
|
-
cacheWriteTokens: void 0
|
|
1042
|
-
},
|
|
1043
|
-
outputTokens: 0,
|
|
1044
|
-
outputTokenDetails: {
|
|
1045
|
-
textTokens: void 0,
|
|
1046
|
-
reasoningTokens: void 0
|
|
1047
|
-
},
|
|
1048
|
-
totalTokens: 0
|
|
1049
|
-
},
|
|
1050
|
-
performance: {
|
|
1051
|
-
effectiveOutputTokensPerSecond: 0,
|
|
1052
|
-
outputTokensPerSecond: void 0,
|
|
1053
|
-
inputTokensPerSecond: void 0,
|
|
1054
|
-
effectiveTotalTokensPerSecond: 0,
|
|
1055
|
-
stepTimeMs: 0,
|
|
1056
|
-
responseTimeMs: 0,
|
|
1057
|
-
toolExecutionMs: {},
|
|
1058
|
-
timeToFirstOutputMs: void 0
|
|
1059
|
-
},
|
|
1060
|
-
warnings,
|
|
1061
|
-
request: {
|
|
1062
|
-
body: "",
|
|
1063
|
-
messages: []
|
|
1064
|
-
},
|
|
1065
|
-
response: {
|
|
1066
|
-
id: responseMetadata?.id ?? "unknown",
|
|
1067
|
-
timestamp: responseMetadata?.timestamp ?? /* @__PURE__ */ new Date(),
|
|
1068
|
-
modelId: responseMetadata?.modelId ?? "unknown",
|
|
1069
|
-
messages: []
|
|
1070
|
-
},
|
|
1071
|
-
providerMetadata: finish?.providerMetadata ?? {}
|
|
1072
|
-
};
|
|
1073
|
-
}
|
|
1074
|
-
function getAssistantMessageContent(step) {
|
|
1321
|
+
/** Preserve assistant ordering and positions for provider-executed results. */
|
|
1322
|
+
function getAssistantMessageContent(step, mode) {
|
|
1075
1323
|
const content = [];
|
|
1076
1324
|
const providerExecutedToolResultPositions = [];
|
|
1077
1325
|
let contentIndex = 0;
|
|
1078
1326
|
for (const part of step.content) switch (part.type) {
|
|
1079
|
-
case "
|
|
1327
|
+
case "text":
|
|
1328
|
+
if (part.text.length > 0) {
|
|
1329
|
+
content.push({
|
|
1330
|
+
type: "text",
|
|
1331
|
+
text: part.text,
|
|
1332
|
+
...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
|
|
1333
|
+
});
|
|
1334
|
+
contentIndex++;
|
|
1335
|
+
}
|
|
1336
|
+
break;
|
|
1337
|
+
case "reasoning": {
|
|
1338
|
+
const { providerMetadata, ...messagePart } = part;
|
|
1080
1339
|
content.push({
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
|
|
1340
|
+
...messagePart,
|
|
1341
|
+
...providerMetadata != null ? { providerOptions: providerMetadata } : {}
|
|
1084
1342
|
});
|
|
1085
1343
|
contentIndex++;
|
|
1086
1344
|
break;
|
|
1087
|
-
|
|
1088
|
-
|
|
1345
|
+
}
|
|
1346
|
+
case "custom":
|
|
1347
|
+
if (mode === "generate") {
|
|
1348
|
+
const { providerMetadata, ...messagePart } = part;
|
|
1089
1349
|
content.push({
|
|
1090
|
-
|
|
1091
|
-
|
|
1350
|
+
...messagePart,
|
|
1351
|
+
providerOptions: providerMetadata
|
|
1092
1352
|
});
|
|
1093
1353
|
contentIndex++;
|
|
1094
1354
|
}
|
|
1095
1355
|
break;
|
|
1356
|
+
case "reasoning-file": if (mode !== "generate") break;
|
|
1096
1357
|
case "file":
|
|
1097
1358
|
content.push({
|
|
1098
|
-
type:
|
|
1359
|
+
type: part.type,
|
|
1099
1360
|
data: {
|
|
1100
1361
|
type: "data",
|
|
1101
1362
|
data: part.file.base64
|
|
@@ -1134,8 +1395,21 @@ function toAssistantToolCallContent(toolCall) {
|
|
|
1134
1395
|
};
|
|
1135
1396
|
}
|
|
1136
1397
|
//#endregion
|
|
1398
|
+
//#region src/workflow-execution-result.ts
|
|
1399
|
+
function resolveWorkflowStreamResult({ data, outcome }) {
|
|
1400
|
+
if (outcome.status === "failed") {
|
|
1401
|
+
if (outcome.source === "execution") throw outcome.error;
|
|
1402
|
+
return {
|
|
1403
|
+
...data,
|
|
1404
|
+
error: outcome.error
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
if (outcome.status === "aborted" && outcome.rejection != null) throw outcome.rejection.value;
|
|
1408
|
+
return data;
|
|
1409
|
+
}
|
|
1410
|
+
//#endregion
|
|
1137
1411
|
//#region src/workflow-agent.ts
|
|
1138
|
-
function addToolResultsToStep(step, executedResults) {
|
|
1412
|
+
function addToolResultsToStep(step, executedResults, mode = "stream") {
|
|
1139
1413
|
if (step == null || executedResults.length === 0) return;
|
|
1140
1414
|
const existingProviderResultIds = new Set(step.content.flatMap((part) => (part.type === "tool-result" || part.type === "tool-error") && part.providerExecuted ? [part.toolCallId] : []));
|
|
1141
1415
|
const toolOutputs = executedResults.flatMap((result) => {
|
|
@@ -1145,6 +1419,10 @@ function addToolResultsToStep(step, executedResults) {
|
|
|
1145
1419
|
toolCallId: result.modelResult.toolCallId,
|
|
1146
1420
|
toolName: result.modelResult.toolName,
|
|
1147
1421
|
input: toolCall?.input,
|
|
1422
|
+
...mode === "generate" ? {
|
|
1423
|
+
dynamic: toolCall?.dynamic === true,
|
|
1424
|
+
...toolCall?.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
|
|
1425
|
+
} : {},
|
|
1148
1426
|
...toolCall?.dynamic === true ? { dynamic: true } : {},
|
|
1149
1427
|
...toolCall?.providerExecuted === true ? { providerExecuted: true } : {}
|
|
1150
1428
|
};
|
|
@@ -1159,6 +1437,7 @@ function addToolResultsToStep(step, executedResults) {
|
|
|
1159
1437
|
}];
|
|
1160
1438
|
});
|
|
1161
1439
|
step.content.push(...toolOutputs);
|
|
1440
|
+
if (mode === "generate") return;
|
|
1162
1441
|
const toolResults = toolOutputs.filter((result) => result.type === "tool-result");
|
|
1163
1442
|
step.toolResults.push(...toolResults);
|
|
1164
1443
|
step.staticToolResults.push(...toolResults.filter((result) => result.dynamic !== true));
|
|
@@ -1234,10 +1513,34 @@ var WorkflowAgent = class {
|
|
|
1234
1513
|
providerOptions: options.providerOptions
|
|
1235
1514
|
};
|
|
1236
1515
|
}
|
|
1237
|
-
generate() {
|
|
1238
|
-
|
|
1516
|
+
async generate(options) {
|
|
1517
|
+
const { data, outcome, abortReason, initialResponseMessages = [] } = await this.execute(options, "generate");
|
|
1518
|
+
if (outcome.status === "failed") throw outcome.error;
|
|
1519
|
+
if (outcome.status === "aborted") {
|
|
1520
|
+
if (outcome.rejection != null) throw outcome.rejection.value;
|
|
1521
|
+
if (abortReason != null) throw abortReason.value;
|
|
1522
|
+
options.abortSignal?.throwIfAborted();
|
|
1523
|
+
throw new DOMException("Generation aborted.", "AbortError");
|
|
1524
|
+
}
|
|
1525
|
+
const lastStep = data.steps.at(-1);
|
|
1526
|
+
if (lastStep == null) throw new NoOutputGeneratedError();
|
|
1527
|
+
let output;
|
|
1528
|
+
if (lastStep.finishReason === "stop" || lastStep.finishReason !== "tool-calls" && lastStep.text.length > 0) output = await (options.output ?? this.output ?? Output.text()).parseCompleteOutput({ text: lastStep.text }, {
|
|
1529
|
+
response: lastStep.response,
|
|
1530
|
+
usage: lastStep.usage,
|
|
1531
|
+
finishReason: lastStep.finishReason
|
|
1532
|
+
});
|
|
1533
|
+
return new DefaultGenerateTextResult({
|
|
1534
|
+
initialResponseMessages,
|
|
1535
|
+
steps: data.steps,
|
|
1536
|
+
totalUsage: data.totalUsage,
|
|
1537
|
+
output
|
|
1538
|
+
});
|
|
1239
1539
|
}
|
|
1240
1540
|
async stream(options) {
|
|
1541
|
+
return resolveWorkflowStreamResult(await this.execute(options));
|
|
1542
|
+
}
|
|
1543
|
+
async prepareInvocation(options, mode = "stream") {
|
|
1241
1544
|
const { onFinish, onEnd = onFinish } = options;
|
|
1242
1545
|
let effectiveModel = this.model;
|
|
1243
1546
|
let effectiveInstructions = options.instructions ?? options.system ?? this.instructions;
|
|
@@ -1247,7 +1550,7 @@ var WorkflowAgent = class {
|
|
|
1247
1550
|
let effectiveRuntimeContext = options.runtimeContext ?? this.runtimeContext ?? {};
|
|
1248
1551
|
let effectiveToolsContext = options.toolsContext ?? this.toolsContext ?? {};
|
|
1249
1552
|
let effectiveToolChoiceFromPrepare = options.toolChoice ?? this.toolChoice;
|
|
1250
|
-
let effectiveStopWhenFromPrepare = options.stopWhen ?? this.stopWhen;
|
|
1553
|
+
let effectiveStopWhenFromPrepare = options.stopWhen ?? this.stopWhen ?? (mode === "generate" ? isStepCount(20) : void 0);
|
|
1251
1554
|
let effectiveActiveToolsFromPrepare = options.activeTools ?? this.activeTools;
|
|
1252
1555
|
let effectiveDownloadFromPrepare = options.experimental_download ?? this.experimentalDownload;
|
|
1253
1556
|
const effectiveToolApprovalSecret = options.experimental_toolApprovalSecret ?? this.experimentalToolApprovalSecret;
|
|
@@ -1316,6 +1619,32 @@ var WorkflowAgent = class {
|
|
|
1316
1619
|
const timeoutAt = options.timeout == null ? void 0 : Date.now() + options.timeout;
|
|
1317
1620
|
const mergedOnToolExecutionStart = mergeCallbacks(this.constructorOnToolExecutionStart, options.onToolExecutionStart);
|
|
1318
1621
|
const mergedOnToolExecutionEnd = mergeCallbacks(this.constructorOnToolExecutionEnd, options.onToolExecutionEnd);
|
|
1622
|
+
return {
|
|
1623
|
+
onEnd,
|
|
1624
|
+
effectiveModel,
|
|
1625
|
+
effectiveInstructions,
|
|
1626
|
+
effectiveGenerationSettings,
|
|
1627
|
+
effectiveRuntimeContext,
|
|
1628
|
+
effectiveToolsContext,
|
|
1629
|
+
effectiveToolChoiceFromPrepare,
|
|
1630
|
+
effectiveStopWhenFromPrepare,
|
|
1631
|
+
effectiveActiveToolsFromPrepare,
|
|
1632
|
+
effectiveToolApprovalSecret,
|
|
1633
|
+
effectiveTelemetry,
|
|
1634
|
+
telemetryDispatcher,
|
|
1635
|
+
prompt,
|
|
1636
|
+
download,
|
|
1637
|
+
sandbox,
|
|
1638
|
+
effectiveAbortSignal,
|
|
1639
|
+
timeoutAt,
|
|
1640
|
+
mergedOnToolExecutionStart,
|
|
1641
|
+
mergedOnToolExecutionEnd
|
|
1642
|
+
};
|
|
1643
|
+
}
|
|
1644
|
+
async execute(options, mode = "stream") {
|
|
1645
|
+
const { onEnd, effectiveModel, effectiveInstructions, effectiveGenerationSettings, effectiveRuntimeContext, effectiveToolsContext, effectiveToolChoiceFromPrepare, effectiveStopWhenFromPrepare, effectiveActiveToolsFromPrepare, effectiveToolApprovalSecret, effectiveTelemetry, telemetryDispatcher, prompt, download, sandbox, effectiveAbortSignal, timeoutAt, mergedOnToolExecutionStart, mergedOnToolExecutionEnd } = await this.prepareInvocation(options, mode);
|
|
1646
|
+
const initialResponseMessages = [];
|
|
1647
|
+
const abortReason = () => effectiveAbortSignal?.reason === void 0 ? void 0 : { value: effectiveAbortSignal.reason };
|
|
1319
1648
|
const collectedApprovals = collectToolApprovals({ messages: prompt.messages });
|
|
1320
1649
|
const approvedToolApprovals = collectedApprovals.approvedToolApprovals.map((collected) => ({
|
|
1321
1650
|
toolCallId: collected.toolCall.toolCallId,
|
|
@@ -1330,7 +1659,8 @@ var WorkflowAgent = class {
|
|
|
1330
1659
|
toolName: collected.toolCall.toolName,
|
|
1331
1660
|
input: collected.toolCall.input,
|
|
1332
1661
|
reason: collected.approvalResponse.reason,
|
|
1333
|
-
providerExecuted: collected.toolCall.providerExecuted === true
|
|
1662
|
+
providerExecuted: collected.toolCall.providerExecuted === true,
|
|
1663
|
+
existingToolResult: collected.existingToolResult
|
|
1334
1664
|
}));
|
|
1335
1665
|
const providerExecutedApprovalIds = new Set([...collectedApprovals.approvedToolApprovals, ...collectedApprovals.deniedToolApprovals].filter((collected) => collected.toolCall.providerExecuted === true).map((collected) => collected.approvalResponse.approvalId));
|
|
1336
1666
|
if (approvedToolApprovals.length > 0 || deniedToolApprovals.length > 0) {
|
|
@@ -1415,7 +1745,7 @@ var WorkflowAgent = class {
|
|
|
1415
1745
|
}
|
|
1416
1746
|
}
|
|
1417
1747
|
for (const denial of deniedToolApprovals) {
|
|
1418
|
-
if (denial.providerExecuted) continue;
|
|
1748
|
+
if (denial.providerExecuted || denial.existingToolResult !== void 0) continue;
|
|
1419
1749
|
toolResultContent.push({
|
|
1420
1750
|
type: "tool-result",
|
|
1421
1751
|
toolCallId: denial.toolCallId,
|
|
@@ -1447,15 +1777,17 @@ var WorkflowAgent = class {
|
|
|
1447
1777
|
content: filtered
|
|
1448
1778
|
});
|
|
1449
1779
|
} else cleanedMessages.push(msg);
|
|
1780
|
+
if (mode === "generate" && toolResultContent.length > 0) initialResponseMessages.push({
|
|
1781
|
+
role: "tool",
|
|
1782
|
+
content: toolResultContent
|
|
1783
|
+
});
|
|
1450
1784
|
if (toolResultContent.length > 0) cleanedMessages.push({
|
|
1451
1785
|
role: "tool",
|
|
1452
1786
|
content: toolResultContent
|
|
1453
1787
|
});
|
|
1454
1788
|
prompt.messages = cleanedMessages;
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
await writeApprovalToolResults(options.writable, approvedRawResults, deniedResults);
|
|
1458
|
-
}
|
|
1789
|
+
const deniedResults = deniedToolApprovals.filter((denial) => !denial.providerExecuted).map((denial) => ({ toolCallId: denial.toolCallId }));
|
|
1790
|
+
if (options.writable && (toolResultContent.length > 0 || deniedResults.length > 0)) await writeApprovalToolResults(options.writable, approvedRawResults, deniedResults);
|
|
1459
1791
|
}
|
|
1460
1792
|
const modelPrompt = await convertToLanguageModelPrompt({
|
|
1461
1793
|
prompt,
|
|
@@ -1658,16 +1990,22 @@ var WorkflowAgent = class {
|
|
|
1658
1990
|
if (mergedGenerationSettings.abortSignal?.aborted) {
|
|
1659
1991
|
if (options.onAbort) await options.onAbort({ steps });
|
|
1660
1992
|
return {
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1993
|
+
outcome: { status: "aborted" },
|
|
1994
|
+
abortReason: abortReason(),
|
|
1995
|
+
data: {
|
|
1996
|
+
messages: prompt.messages,
|
|
1997
|
+
steps,
|
|
1998
|
+
toolCalls: [],
|
|
1999
|
+
toolResults: [],
|
|
2000
|
+
finishReason: "other",
|
|
2001
|
+
totalUsage: aggregateExecutionUsage(steps, mode),
|
|
2002
|
+
output: void 0
|
|
2003
|
+
}
|
|
1668
2004
|
};
|
|
1669
2005
|
}
|
|
1670
|
-
const iterator =
|
|
2006
|
+
const iterator = modelCallIterator({
|
|
2007
|
+
mode,
|
|
2008
|
+
include: options.include,
|
|
1671
2009
|
model: effectiveModel,
|
|
1672
2010
|
tools: effectiveTools,
|
|
1673
2011
|
writable: options.writable,
|
|
@@ -1705,6 +2043,16 @@ var WorkflowAgent = class {
|
|
|
1705
2043
|
break;
|
|
1706
2044
|
}
|
|
1707
2045
|
const { toolCalls, tools: stepTools = effectiveTools, messages: iterMessages, step, runtimeContext: yieldedRuntimeContext, toolsContext: yieldedToolsContext, experimental_sandbox: stepSandbox, providerExecutedToolResults, providerExecutedToolResultPositions } = result.value;
|
|
2046
|
+
if (mode === "generate" && step != null) {
|
|
2047
|
+
for (const call of toolCalls) if (call.invalid && !call.providerExecuted) step.content.push({
|
|
2048
|
+
type: "tool-error",
|
|
2049
|
+
toolCallId: call.toolCallId,
|
|
2050
|
+
toolName: call.toolName,
|
|
2051
|
+
input: call.input,
|
|
2052
|
+
error: call.error,
|
|
2053
|
+
dynamic: true
|
|
2054
|
+
});
|
|
2055
|
+
}
|
|
1708
2056
|
const capturedProviderToolResults = providerExecutedToolResults ?? /* @__PURE__ */ new Map();
|
|
1709
2057
|
const toolExecutionSandbox = stepSandbox ?? sandbox;
|
|
1710
2058
|
const currentStepNumber = steps.length;
|
|
@@ -1748,9 +2096,10 @@ var WorkflowAgent = class {
|
|
|
1748
2096
|
const tool = stepTools[tc.toolName];
|
|
1749
2097
|
return tool && typeof tool.execute !== "function" || approvalNeeded[i];
|
|
1750
2098
|
});
|
|
1751
|
-
|
|
2099
|
+
const providerApprovalRequests = step?.content.filter((part) => part.type === "tool-approval-request").filter((part) => part.toolCall.providerExecuted) ?? [];
|
|
2100
|
+
if (pausedToolCalls.length > 0 || providerApprovalRequests.length > 0) {
|
|
1752
2101
|
const executableResults = await Promise.all(executableToolCalls.map((toolCall) => executeToolWithCallbacks(toolCall, stepTools, iterMessages, toolsContext, currentStepNumber, toolExecutionSandbox)));
|
|
1753
|
-
const providerResultEntries = await Promise.all(providerToolCallsForResults.map(async (toolCall) => ({
|
|
2102
|
+
const providerResultEntries = await Promise.all(providerToolCallsForResults.filter((call) => !providerApprovalRequests.some((request) => request.toolCall.toolCallId === call.toolCallId)).map(async (toolCall) => ({
|
|
1754
2103
|
toolCall,
|
|
1755
2104
|
result: await resolveProviderToolResult(toolCall, capturedProviderToolResults, stepTools, download)
|
|
1756
2105
|
})));
|
|
@@ -1776,39 +2125,60 @@ var WorkflowAgent = class {
|
|
|
1776
2125
|
input: toolCalls.find((tc) => tc.toolCallId === r.modelResult.toolCallId)?.input,
|
|
1777
2126
|
output: r.rawOutput
|
|
1778
2127
|
}));
|
|
1779
|
-
addToolResultsToStep(step, executedResults);
|
|
2128
|
+
addToolResultsToStep(step, executedResults, mode);
|
|
2129
|
+
const approvalToolCalls = pausedToolCalls.filter((tc) => approvalNeeded[nonProviderToolCalls.indexOf(tc)]);
|
|
2130
|
+
const approvalRequests = await Promise.all(approvalToolCalls.map(async (tc) => {
|
|
2131
|
+
const approvalId = `approval-${tc.toolCallId}`;
|
|
2132
|
+
const signature = effectiveToolApprovalSecret == null ? void 0 : await signWorkflowToolApproval({
|
|
2133
|
+
secret: effectiveToolApprovalSecret,
|
|
2134
|
+
approvalId,
|
|
2135
|
+
toolCallId: tc.toolCallId,
|
|
2136
|
+
toolName: tc.toolName,
|
|
2137
|
+
input: tc.input
|
|
2138
|
+
});
|
|
2139
|
+
return {
|
|
2140
|
+
type: "tool-approval-request",
|
|
2141
|
+
approvalId,
|
|
2142
|
+
toolCall: {
|
|
2143
|
+
...tc,
|
|
2144
|
+
type: "tool-call"
|
|
2145
|
+
},
|
|
2146
|
+
...signature != null ? { signature } : {}
|
|
2147
|
+
};
|
|
2148
|
+
}));
|
|
2149
|
+
step?.content.push(...approvalRequests);
|
|
2150
|
+
const approvalMessages = approvalRequests.map(({ toolCall, ...request }) => ({
|
|
2151
|
+
...request,
|
|
2152
|
+
toolCallId: toolCall.toolCallId
|
|
2153
|
+
}));
|
|
1780
2154
|
const responseMessages = addToolResultsToConversation({
|
|
1781
2155
|
messages: iterMessages,
|
|
1782
2156
|
toolResults: resolvedResults,
|
|
1783
2157
|
providerExecutedToolCallIds: new Set(providerToolCallsForResults.map((toolCall) => toolCall.toolCallId)),
|
|
1784
2158
|
providerExecutedToolResultPositions
|
|
1785
2159
|
});
|
|
1786
|
-
|
|
1787
|
-
|
|
2160
|
+
const publicResponseMessages = addApprovalRequestsToMessages(mode === "generate" ? toModelResponseMessages(responseMessages) : responseMessages, [...approvalMessages, ...providerApprovalRequests.map(({ toolCall, ...request }) => ({
|
|
2161
|
+
...request,
|
|
2162
|
+
toolCallId: toolCall.toolCallId
|
|
2163
|
+
}))]);
|
|
2164
|
+
step?.response.messages.push(...publicResponseMessages);
|
|
2165
|
+
const messages = publicResponseMessages === responseMessages ? iterMessages : [...iterMessages.slice(0, iterMessages.length - responseMessages.length), ...publicResponseMessages];
|
|
1788
2166
|
const lastStep = steps[steps.length - 1];
|
|
1789
|
-
const totalUsage =
|
|
1790
|
-
const
|
|
1791
|
-
if (mergedOnEnd && !wasAborted) await mergedOnEnd({
|
|
1792
|
-
steps,
|
|
2167
|
+
const totalUsage = aggregateExecutionUsage(steps, mode);
|
|
2168
|
+
const data = {
|
|
1793
2169
|
messages,
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
2170
|
+
steps,
|
|
2171
|
+
toolCalls: allToolCalls,
|
|
2172
|
+
toolResults: allToolResults,
|
|
2173
|
+
finishReason: lastStep?.finishReason ?? "other",
|
|
1797
2174
|
totalUsage,
|
|
1798
|
-
runtimeContext,
|
|
1799
|
-
toolsContext,
|
|
1800
2175
|
output: void 0
|
|
1801
|
-
}
|
|
1802
|
-
if (
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
await telemetryDispatcher.onEnd?.({
|
|
1806
|
-
...lastTelemetryStep,
|
|
1807
|
-
steps: telemetrySteps,
|
|
1808
|
-
usage: totalUsage,
|
|
1809
|
-
totalUsage
|
|
1810
|
-
});
|
|
2176
|
+
};
|
|
2177
|
+
if (mode === "generate" && step != null) {
|
|
2178
|
+
await mergedOnStepEnd?.(step);
|
|
2179
|
+
await telemetryDispatcher.onStepEnd?.(normalizeStepForTelemetry(step));
|
|
1811
2180
|
}
|
|
2181
|
+
await notifyEnd(data, wasAborted);
|
|
1812
2182
|
if (options.writable) {
|
|
1813
2183
|
if (allToolResults.length > 0) await writeToolResults(options.writable, executedResults.map((r) => ({
|
|
1814
2184
|
toolCallId: r.modelResult.toolCallId,
|
|
@@ -1817,42 +2187,13 @@ var WorkflowAgent = class {
|
|
|
1817
2187
|
output: r.rawOutput,
|
|
1818
2188
|
isError: r.isError
|
|
1819
2189
|
})));
|
|
1820
|
-
|
|
1821
|
-
const tcIndex = nonProviderToolCalls.indexOf(pausedToolCalls[i]);
|
|
1822
|
-
return approvalNeeded[tcIndex];
|
|
1823
|
-
});
|
|
1824
|
-
if (approvalToolCalls.length > 0) {
|
|
1825
|
-
const approvalRequests = await Promise.all(approvalToolCalls.map(async (tc) => {
|
|
1826
|
-
const approvalId = `approval-${tc.toolCallId}`;
|
|
1827
|
-
const signature = effectiveToolApprovalSecret == null ? void 0 : await signWorkflowToolApproval({
|
|
1828
|
-
secret: effectiveToolApprovalSecret,
|
|
1829
|
-
approvalId,
|
|
1830
|
-
toolCallId: tc.toolCallId,
|
|
1831
|
-
toolName: tc.toolName,
|
|
1832
|
-
input: tc.input
|
|
1833
|
-
});
|
|
1834
|
-
return {
|
|
1835
|
-
approvalId,
|
|
1836
|
-
toolCallId: tc.toolCallId,
|
|
1837
|
-
...signature != null ? { signature } : {}
|
|
1838
|
-
};
|
|
1839
|
-
}));
|
|
1840
|
-
await writeApprovalRequests(options.writable, approvalRequests);
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
|
-
if (options.writable) {
|
|
1844
|
-
const sendFinish = options.sendFinish ?? true;
|
|
1845
|
-
const preventClose = options.preventClose ?? false;
|
|
1846
|
-
if (sendFinish || !preventClose) await closeStream(options.writable, preventClose, sendFinish);
|
|
2190
|
+
if (approvalMessages.length > 0) await writeApprovalRequests(options.writable, approvalMessages);
|
|
1847
2191
|
}
|
|
2192
|
+
await closeOutput();
|
|
1848
2193
|
return {
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
toolResults: allToolResults,
|
|
1853
|
-
finishReason,
|
|
1854
|
-
totalUsage,
|
|
1855
|
-
output: void 0
|
|
2194
|
+
data,
|
|
2195
|
+
outcome: { status: "completed" },
|
|
2196
|
+
initialResponseMessages
|
|
1856
2197
|
};
|
|
1857
2198
|
}
|
|
1858
2199
|
const clientToolResults = await Promise.all(nonProviderToolCalls.map((toolCall) => executeToolWithCallbacks(toolCall, stepTools, iterMessages, toolsContext, currentStepNumber, toolExecutionSandbox)));
|
|
@@ -1900,7 +2241,7 @@ var WorkflowAgent = class {
|
|
|
1900
2241
|
input: toolCalls.find((tc) => tc.toolCallId === r.modelResult.toolCallId)?.input,
|
|
1901
2242
|
output: r.rawOutput
|
|
1902
2243
|
}));
|
|
1903
|
-
addToolResultsToStep(step, executedToolResults);
|
|
2244
|
+
addToolResultsToStep(step, executedToolResults, mode);
|
|
1904
2245
|
result = await iterator.next(continuationToolResults);
|
|
1905
2246
|
} else {
|
|
1906
2247
|
lastStepToolCalls = [];
|
|
@@ -1936,7 +2277,7 @@ var WorkflowAgent = class {
|
|
|
1936
2277
|
const messages = finalMessages ?? prompt.messages;
|
|
1937
2278
|
const effectiveOutput = options.output ?? this.output;
|
|
1938
2279
|
let experimentalOutput = void 0;
|
|
1939
|
-
if (effectiveOutput && steps.length > 0) {
|
|
2280
|
+
if (mode === "stream" && effectiveOutput && steps.length > 0) {
|
|
1940
2281
|
const lastStep = steps[steps.length - 1];
|
|
1941
2282
|
const text = lastStep.text;
|
|
1942
2283
|
if (text) try {
|
|
@@ -1953,52 +2294,67 @@ var WorkflowAgent = class {
|
|
|
1953
2294
|
}
|
|
1954
2295
|
}
|
|
1955
2296
|
const lastStep = steps[steps.length - 1];
|
|
1956
|
-
const totalUsage =
|
|
2297
|
+
const totalUsage = aggregateExecutionUsage(steps, mode);
|
|
1957
2298
|
const finishReason = lastStep?.finishReason ?? "other";
|
|
1958
|
-
|
|
1959
|
-
steps,
|
|
2299
|
+
const data = {
|
|
1960
2300
|
messages,
|
|
1961
|
-
|
|
2301
|
+
steps,
|
|
2302
|
+
toolCalls: lastStepToolCalls,
|
|
2303
|
+
toolResults: lastStepToolResults,
|
|
1962
2304
|
finishReason,
|
|
1963
|
-
usage: totalUsage,
|
|
1964
2305
|
totalUsage,
|
|
1965
|
-
runtimeContext,
|
|
1966
|
-
toolsContext,
|
|
1967
2306
|
output: experimentalOutput
|
|
1968
|
-
}
|
|
1969
|
-
if (!
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
2307
|
+
};
|
|
2308
|
+
if (mode === "stream" || !hasEncounteredError && !hasTerminalError) await notifyEnd(data, wasAborted);
|
|
2309
|
+
await closeOutput();
|
|
2310
|
+
const outcome = hasEncounteredError ? wasAborted ? {
|
|
2311
|
+
status: "aborted",
|
|
2312
|
+
rejection: { value: encounteredError }
|
|
2313
|
+
} : {
|
|
2314
|
+
status: "failed",
|
|
2315
|
+
source: "execution",
|
|
2316
|
+
error: encounteredError
|
|
2317
|
+
} : hasTerminalError ? {
|
|
2318
|
+
status: "failed",
|
|
2319
|
+
source: "model-stream",
|
|
2320
|
+
error: terminalError
|
|
2321
|
+
} : wasAborted ? { status: "aborted" } : { status: "completed" };
|
|
2322
|
+
return {
|
|
2323
|
+
data,
|
|
2324
|
+
outcome,
|
|
2325
|
+
initialResponseMessages,
|
|
2326
|
+
...outcome.status === "aborted" ? { abortReason: abortReason() } : {}
|
|
2327
|
+
};
|
|
2328
|
+
async function notifyEnd(data, aborted) {
|
|
2329
|
+
if (aborted) return;
|
|
2330
|
+
if (mergedOnEnd) await mergedOnEnd({
|
|
2331
|
+
steps: data.steps,
|
|
2332
|
+
messages: data.messages,
|
|
2333
|
+
text: data.steps.at(-1)?.text ?? "",
|
|
2334
|
+
finishReason: data.finishReason,
|
|
2335
|
+
usage: data.totalUsage,
|
|
2336
|
+
totalUsage: data.totalUsage,
|
|
2337
|
+
runtimeContext,
|
|
2338
|
+
toolsContext,
|
|
2339
|
+
output: data.output
|
|
1977
2340
|
});
|
|
2341
|
+
if (data.steps.length > 0) {
|
|
2342
|
+
const telemetrySteps = data.steps.map(normalizeStepForTelemetry);
|
|
2343
|
+
await telemetryDispatcher.onEnd?.({
|
|
2344
|
+
...telemetrySteps[telemetrySteps.length - 1],
|
|
2345
|
+
steps: telemetrySteps,
|
|
2346
|
+
usage: data.totalUsage,
|
|
2347
|
+
totalUsage: data.totalUsage
|
|
2348
|
+
});
|
|
2349
|
+
}
|
|
1978
2350
|
}
|
|
1979
|
-
|
|
2351
|
+
async function closeOutput() {
|
|
1980
2352
|
if (options.writable) {
|
|
1981
2353
|
const sendFinish = options.sendFinish ?? true;
|
|
1982
2354
|
const preventClose = options.preventClose ?? false;
|
|
1983
2355
|
if (sendFinish || !preventClose) await closeStream(options.writable, preventClose, sendFinish);
|
|
1984
2356
|
}
|
|
1985
|
-
throw encounteredError;
|
|
1986
|
-
}
|
|
1987
|
-
if (options.writable) {
|
|
1988
|
-
const sendFinish = options.sendFinish ?? true;
|
|
1989
|
-
const preventClose = options.preventClose ?? false;
|
|
1990
|
-
if (sendFinish || !preventClose) await closeStream(options.writable, preventClose, sendFinish);
|
|
1991
2357
|
}
|
|
1992
|
-
return {
|
|
1993
|
-
messages,
|
|
1994
|
-
steps,
|
|
1995
|
-
toolCalls: lastStepToolCalls,
|
|
1996
|
-
toolResults: lastStepToolResults,
|
|
1997
|
-
finishReason,
|
|
1998
|
-
totalUsage,
|
|
1999
|
-
output: experimentalOutput,
|
|
2000
|
-
...hasTerminalError ? { error: terminalError } : {}
|
|
2001
|
-
};
|
|
2002
2358
|
}
|
|
2003
2359
|
};
|
|
2004
2360
|
function getModelInfo(model) {
|
|
@@ -2287,6 +2643,31 @@ async function executeTool(toolCall, tools, messages, context, abortSignal, down
|
|
|
2287
2643
|
isError: false
|
|
2288
2644
|
};
|
|
2289
2645
|
}
|
|
2646
|
+
function aggregateExecutionUsage(steps, mode) {
|
|
2647
|
+
return mode === "stream" ? aggregateUsage(steps) : steps.reduce((usage, step) => addLanguageModelUsage(usage, step.usage), createNullLanguageModelUsage());
|
|
2648
|
+
}
|
|
2649
|
+
function addApprovalRequestsToMessages(messages, requests) {
|
|
2650
|
+
if (requests.length === 0) return messages;
|
|
2651
|
+
const result = [...messages];
|
|
2652
|
+
for (let index = result.length - 1; index >= 0; index--) {
|
|
2653
|
+
const message = result[index];
|
|
2654
|
+
if (message.role === "assistant") {
|
|
2655
|
+
result[index] = {
|
|
2656
|
+
...message,
|
|
2657
|
+
content: [...typeof message.content === "string" ? [{
|
|
2658
|
+
type: "text",
|
|
2659
|
+
text: message.content
|
|
2660
|
+
}] : message.content, ...requests]
|
|
2661
|
+
};
|
|
2662
|
+
return result;
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
result.unshift({
|
|
2666
|
+
role: "assistant",
|
|
2667
|
+
content: requests
|
|
2668
|
+
});
|
|
2669
|
+
return result;
|
|
2670
|
+
}
|
|
2290
2671
|
//#endregion
|
|
2291
2672
|
//#region src/to-ui-message-chunk.ts
|
|
2292
2673
|
/**
|