@ai-sdk/workflow 2.0.58 → 2.0.59
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 +21 -0
- package/dist/index.d.ts +61 -43
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +681 -299
- 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 +509 -201
- 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,
|
|
@@ -1447,6 +1776,10 @@ var WorkflowAgent = class {
|
|
|
1447
1776
|
content: filtered
|
|
1448
1777
|
});
|
|
1449
1778
|
} else cleanedMessages.push(msg);
|
|
1779
|
+
if (mode === "generate" && toolResultContent.length > 0) initialResponseMessages.push({
|
|
1780
|
+
role: "tool",
|
|
1781
|
+
content: toolResultContent
|
|
1782
|
+
});
|
|
1450
1783
|
if (toolResultContent.length > 0) cleanedMessages.push({
|
|
1451
1784
|
role: "tool",
|
|
1452
1785
|
content: toolResultContent
|
|
@@ -1658,16 +1991,22 @@ var WorkflowAgent = class {
|
|
|
1658
1991
|
if (mergedGenerationSettings.abortSignal?.aborted) {
|
|
1659
1992
|
if (options.onAbort) await options.onAbort({ steps });
|
|
1660
1993
|
return {
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1994
|
+
outcome: { status: "aborted" },
|
|
1995
|
+
abortReason: abortReason(),
|
|
1996
|
+
data: {
|
|
1997
|
+
messages: prompt.messages,
|
|
1998
|
+
steps,
|
|
1999
|
+
toolCalls: [],
|
|
2000
|
+
toolResults: [],
|
|
2001
|
+
finishReason: "other",
|
|
2002
|
+
totalUsage: aggregateExecutionUsage(steps, mode),
|
|
2003
|
+
output: void 0
|
|
2004
|
+
}
|
|
1668
2005
|
};
|
|
1669
2006
|
}
|
|
1670
|
-
const iterator =
|
|
2007
|
+
const iterator = modelCallIterator({
|
|
2008
|
+
mode,
|
|
2009
|
+
include: options.include,
|
|
1671
2010
|
model: effectiveModel,
|
|
1672
2011
|
tools: effectiveTools,
|
|
1673
2012
|
writable: options.writable,
|
|
@@ -1705,6 +2044,16 @@ var WorkflowAgent = class {
|
|
|
1705
2044
|
break;
|
|
1706
2045
|
}
|
|
1707
2046
|
const { toolCalls, tools: stepTools = effectiveTools, messages: iterMessages, step, runtimeContext: yieldedRuntimeContext, toolsContext: yieldedToolsContext, experimental_sandbox: stepSandbox, providerExecutedToolResults, providerExecutedToolResultPositions } = result.value;
|
|
2047
|
+
if (mode === "generate" && step != null) {
|
|
2048
|
+
for (const call of toolCalls) if (call.invalid && !call.providerExecuted) step.content.push({
|
|
2049
|
+
type: "tool-error",
|
|
2050
|
+
toolCallId: call.toolCallId,
|
|
2051
|
+
toolName: call.toolName,
|
|
2052
|
+
input: call.input,
|
|
2053
|
+
error: call.error,
|
|
2054
|
+
dynamic: true
|
|
2055
|
+
});
|
|
2056
|
+
}
|
|
1708
2057
|
const capturedProviderToolResults = providerExecutedToolResults ?? /* @__PURE__ */ new Map();
|
|
1709
2058
|
const toolExecutionSandbox = stepSandbox ?? sandbox;
|
|
1710
2059
|
const currentStepNumber = steps.length;
|
|
@@ -1748,9 +2097,10 @@ var WorkflowAgent = class {
|
|
|
1748
2097
|
const tool = stepTools[tc.toolName];
|
|
1749
2098
|
return tool && typeof tool.execute !== "function" || approvalNeeded[i];
|
|
1750
2099
|
});
|
|
1751
|
-
|
|
2100
|
+
const providerApprovalRequests = step?.content.filter((part) => part.type === "tool-approval-request").filter((part) => part.toolCall.providerExecuted) ?? [];
|
|
2101
|
+
if (pausedToolCalls.length > 0 || providerApprovalRequests.length > 0) {
|
|
1752
2102
|
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) => ({
|
|
2103
|
+
const providerResultEntries = await Promise.all(providerToolCallsForResults.filter((call) => !providerApprovalRequests.some((request) => request.toolCall.toolCallId === call.toolCallId)).map(async (toolCall) => ({
|
|
1754
2104
|
toolCall,
|
|
1755
2105
|
result: await resolveProviderToolResult(toolCall, capturedProviderToolResults, stepTools, download)
|
|
1756
2106
|
})));
|
|
@@ -1776,39 +2126,60 @@ var WorkflowAgent = class {
|
|
|
1776
2126
|
input: toolCalls.find((tc) => tc.toolCallId === r.modelResult.toolCallId)?.input,
|
|
1777
2127
|
output: r.rawOutput
|
|
1778
2128
|
}));
|
|
1779
|
-
addToolResultsToStep(step, executedResults);
|
|
2129
|
+
addToolResultsToStep(step, executedResults, mode);
|
|
2130
|
+
const approvalToolCalls = pausedToolCalls.filter((tc) => approvalNeeded[nonProviderToolCalls.indexOf(tc)]);
|
|
2131
|
+
const approvalRequests = await Promise.all(approvalToolCalls.map(async (tc) => {
|
|
2132
|
+
const approvalId = `approval-${tc.toolCallId}`;
|
|
2133
|
+
const signature = effectiveToolApprovalSecret == null ? void 0 : await signWorkflowToolApproval({
|
|
2134
|
+
secret: effectiveToolApprovalSecret,
|
|
2135
|
+
approvalId,
|
|
2136
|
+
toolCallId: tc.toolCallId,
|
|
2137
|
+
toolName: tc.toolName,
|
|
2138
|
+
input: tc.input
|
|
2139
|
+
});
|
|
2140
|
+
return {
|
|
2141
|
+
type: "tool-approval-request",
|
|
2142
|
+
approvalId,
|
|
2143
|
+
toolCall: {
|
|
2144
|
+
...tc,
|
|
2145
|
+
type: "tool-call"
|
|
2146
|
+
},
|
|
2147
|
+
...signature != null ? { signature } : {}
|
|
2148
|
+
};
|
|
2149
|
+
}));
|
|
2150
|
+
step?.content.push(...approvalRequests);
|
|
2151
|
+
const approvalMessages = approvalRequests.map(({ toolCall, ...request }) => ({
|
|
2152
|
+
...request,
|
|
2153
|
+
toolCallId: toolCall.toolCallId
|
|
2154
|
+
}));
|
|
1780
2155
|
const responseMessages = addToolResultsToConversation({
|
|
1781
2156
|
messages: iterMessages,
|
|
1782
2157
|
toolResults: resolvedResults,
|
|
1783
2158
|
providerExecutedToolCallIds: new Set(providerToolCallsForResults.map((toolCall) => toolCall.toolCallId)),
|
|
1784
2159
|
providerExecutedToolResultPositions
|
|
1785
2160
|
});
|
|
1786
|
-
|
|
1787
|
-
|
|
2161
|
+
const publicResponseMessages = addApprovalRequestsToMessages(mode === "generate" ? toModelResponseMessages(responseMessages) : responseMessages, [...approvalMessages, ...providerApprovalRequests.map(({ toolCall, ...request }) => ({
|
|
2162
|
+
...request,
|
|
2163
|
+
toolCallId: toolCall.toolCallId
|
|
2164
|
+
}))]);
|
|
2165
|
+
step?.response.messages.push(...publicResponseMessages);
|
|
2166
|
+
const messages = publicResponseMessages === responseMessages ? iterMessages : [...iterMessages.slice(0, iterMessages.length - responseMessages.length), ...publicResponseMessages];
|
|
1788
2167
|
const lastStep = steps[steps.length - 1];
|
|
1789
|
-
const totalUsage =
|
|
1790
|
-
const
|
|
1791
|
-
if (mergedOnEnd && !wasAborted) await mergedOnEnd({
|
|
1792
|
-
steps,
|
|
2168
|
+
const totalUsage = aggregateExecutionUsage(steps, mode);
|
|
2169
|
+
const data = {
|
|
1793
2170
|
messages,
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
2171
|
+
steps,
|
|
2172
|
+
toolCalls: allToolCalls,
|
|
2173
|
+
toolResults: allToolResults,
|
|
2174
|
+
finishReason: lastStep?.finishReason ?? "other",
|
|
1797
2175
|
totalUsage,
|
|
1798
|
-
runtimeContext,
|
|
1799
|
-
toolsContext,
|
|
1800
2176
|
output: void 0
|
|
1801
|
-
}
|
|
1802
|
-
if (
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
await telemetryDispatcher.onEnd?.({
|
|
1806
|
-
...lastTelemetryStep,
|
|
1807
|
-
steps: telemetrySteps,
|
|
1808
|
-
usage: totalUsage,
|
|
1809
|
-
totalUsage
|
|
1810
|
-
});
|
|
2177
|
+
};
|
|
2178
|
+
if (mode === "generate" && step != null) {
|
|
2179
|
+
await mergedOnStepEnd?.(step);
|
|
2180
|
+
await telemetryDispatcher.onStepEnd?.(normalizeStepForTelemetry(step));
|
|
1811
2181
|
}
|
|
2182
|
+
await notifyEnd(data, wasAborted);
|
|
1812
2183
|
if (options.writable) {
|
|
1813
2184
|
if (allToolResults.length > 0) await writeToolResults(options.writable, executedResults.map((r) => ({
|
|
1814
2185
|
toolCallId: r.modelResult.toolCallId,
|
|
@@ -1817,42 +2188,13 @@ var WorkflowAgent = class {
|
|
|
1817
2188
|
output: r.rawOutput,
|
|
1818
2189
|
isError: r.isError
|
|
1819
2190
|
})));
|
|
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);
|
|
2191
|
+
if (approvalMessages.length > 0) await writeApprovalRequests(options.writable, approvalMessages);
|
|
1847
2192
|
}
|
|
2193
|
+
await closeOutput();
|
|
1848
2194
|
return {
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
toolResults: allToolResults,
|
|
1853
|
-
finishReason,
|
|
1854
|
-
totalUsage,
|
|
1855
|
-
output: void 0
|
|
2195
|
+
data,
|
|
2196
|
+
outcome: { status: "completed" },
|
|
2197
|
+
initialResponseMessages
|
|
1856
2198
|
};
|
|
1857
2199
|
}
|
|
1858
2200
|
const clientToolResults = await Promise.all(nonProviderToolCalls.map((toolCall) => executeToolWithCallbacks(toolCall, stepTools, iterMessages, toolsContext, currentStepNumber, toolExecutionSandbox)));
|
|
@@ -1900,7 +2242,7 @@ var WorkflowAgent = class {
|
|
|
1900
2242
|
input: toolCalls.find((tc) => tc.toolCallId === r.modelResult.toolCallId)?.input,
|
|
1901
2243
|
output: r.rawOutput
|
|
1902
2244
|
}));
|
|
1903
|
-
addToolResultsToStep(step, executedToolResults);
|
|
2245
|
+
addToolResultsToStep(step, executedToolResults, mode);
|
|
1904
2246
|
result = await iterator.next(continuationToolResults);
|
|
1905
2247
|
} else {
|
|
1906
2248
|
lastStepToolCalls = [];
|
|
@@ -1936,7 +2278,7 @@ var WorkflowAgent = class {
|
|
|
1936
2278
|
const messages = finalMessages ?? prompt.messages;
|
|
1937
2279
|
const effectiveOutput = options.output ?? this.output;
|
|
1938
2280
|
let experimentalOutput = void 0;
|
|
1939
|
-
if (effectiveOutput && steps.length > 0) {
|
|
2281
|
+
if (mode === "stream" && effectiveOutput && steps.length > 0) {
|
|
1940
2282
|
const lastStep = steps[steps.length - 1];
|
|
1941
2283
|
const text = lastStep.text;
|
|
1942
2284
|
if (text) try {
|
|
@@ -1953,52 +2295,67 @@ var WorkflowAgent = class {
|
|
|
1953
2295
|
}
|
|
1954
2296
|
}
|
|
1955
2297
|
const lastStep = steps[steps.length - 1];
|
|
1956
|
-
const totalUsage =
|
|
2298
|
+
const totalUsage = aggregateExecutionUsage(steps, mode);
|
|
1957
2299
|
const finishReason = lastStep?.finishReason ?? "other";
|
|
1958
|
-
|
|
1959
|
-
steps,
|
|
2300
|
+
const data = {
|
|
1960
2301
|
messages,
|
|
1961
|
-
|
|
2302
|
+
steps,
|
|
2303
|
+
toolCalls: lastStepToolCalls,
|
|
2304
|
+
toolResults: lastStepToolResults,
|
|
1962
2305
|
finishReason,
|
|
1963
|
-
usage: totalUsage,
|
|
1964
2306
|
totalUsage,
|
|
1965
|
-
runtimeContext,
|
|
1966
|
-
toolsContext,
|
|
1967
2307
|
output: experimentalOutput
|
|
1968
|
-
}
|
|
1969
|
-
if (!
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
2308
|
+
};
|
|
2309
|
+
if (mode === "stream" || !hasEncounteredError && !hasTerminalError) await notifyEnd(data, wasAborted);
|
|
2310
|
+
await closeOutput();
|
|
2311
|
+
const outcome = hasEncounteredError ? wasAborted ? {
|
|
2312
|
+
status: "aborted",
|
|
2313
|
+
rejection: { value: encounteredError }
|
|
2314
|
+
} : {
|
|
2315
|
+
status: "failed",
|
|
2316
|
+
source: "execution",
|
|
2317
|
+
error: encounteredError
|
|
2318
|
+
} : hasTerminalError ? {
|
|
2319
|
+
status: "failed",
|
|
2320
|
+
source: "model-stream",
|
|
2321
|
+
error: terminalError
|
|
2322
|
+
} : wasAborted ? { status: "aborted" } : { status: "completed" };
|
|
2323
|
+
return {
|
|
2324
|
+
data,
|
|
2325
|
+
outcome,
|
|
2326
|
+
initialResponseMessages,
|
|
2327
|
+
...outcome.status === "aborted" ? { abortReason: abortReason() } : {}
|
|
2328
|
+
};
|
|
2329
|
+
async function notifyEnd(data, aborted) {
|
|
2330
|
+
if (aborted) return;
|
|
2331
|
+
if (mergedOnEnd) await mergedOnEnd({
|
|
2332
|
+
steps: data.steps,
|
|
2333
|
+
messages: data.messages,
|
|
2334
|
+
text: data.steps.at(-1)?.text ?? "",
|
|
2335
|
+
finishReason: data.finishReason,
|
|
2336
|
+
usage: data.totalUsage,
|
|
2337
|
+
totalUsage: data.totalUsage,
|
|
2338
|
+
runtimeContext,
|
|
2339
|
+
toolsContext,
|
|
2340
|
+
output: data.output
|
|
1977
2341
|
});
|
|
2342
|
+
if (data.steps.length > 0) {
|
|
2343
|
+
const telemetrySteps = data.steps.map(normalizeStepForTelemetry);
|
|
2344
|
+
await telemetryDispatcher.onEnd?.({
|
|
2345
|
+
...telemetrySteps[telemetrySteps.length - 1],
|
|
2346
|
+
steps: telemetrySteps,
|
|
2347
|
+
usage: data.totalUsage,
|
|
2348
|
+
totalUsage: data.totalUsage
|
|
2349
|
+
});
|
|
2350
|
+
}
|
|
1978
2351
|
}
|
|
1979
|
-
|
|
2352
|
+
async function closeOutput() {
|
|
1980
2353
|
if (options.writable) {
|
|
1981
2354
|
const sendFinish = options.sendFinish ?? true;
|
|
1982
2355
|
const preventClose = options.preventClose ?? false;
|
|
1983
2356
|
if (sendFinish || !preventClose) await closeStream(options.writable, preventClose, sendFinish);
|
|
1984
2357
|
}
|
|
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
2358
|
}
|
|
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
2359
|
}
|
|
2003
2360
|
};
|
|
2004
2361
|
function getModelInfo(model) {
|
|
@@ -2287,6 +2644,31 @@ async function executeTool(toolCall, tools, messages, context, abortSignal, down
|
|
|
2287
2644
|
isError: false
|
|
2288
2645
|
};
|
|
2289
2646
|
}
|
|
2647
|
+
function aggregateExecutionUsage(steps, mode) {
|
|
2648
|
+
return mode === "stream" ? aggregateUsage(steps) : steps.reduce((usage, step) => addLanguageModelUsage(usage, step.usage), createNullLanguageModelUsage());
|
|
2649
|
+
}
|
|
2650
|
+
function addApprovalRequestsToMessages(messages, requests) {
|
|
2651
|
+
if (requests.length === 0) return messages;
|
|
2652
|
+
const result = [...messages];
|
|
2653
|
+
for (let index = result.length - 1; index >= 0; index--) {
|
|
2654
|
+
const message = result[index];
|
|
2655
|
+
if (message.role === "assistant") {
|
|
2656
|
+
result[index] = {
|
|
2657
|
+
...message,
|
|
2658
|
+
content: [...typeof message.content === "string" ? [{
|
|
2659
|
+
type: "text",
|
|
2660
|
+
text: message.content
|
|
2661
|
+
}] : message.content, ...requests]
|
|
2662
|
+
};
|
|
2663
|
+
return result;
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
result.unshift({
|
|
2667
|
+
role: "assistant",
|
|
2668
|
+
content: requests
|
|
2669
|
+
});
|
|
2670
|
+
return result;
|
|
2671
|
+
}
|
|
2290
2672
|
//#endregion
|
|
2291
2673
|
//#region src/to-ui-message-chunk.ts
|
|
2292
2674
|
/**
|