@ai-sdk/workflow 2.0.69 → 2.0.71
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 +37 -0
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +273 -67
- package/dist/index.js.map +1 -1
- package/dist/{workflow-chat-transport-DwOgX7dK.d.ts → workflow-chat-transport-Bw-K44A5.d.ts} +2 -1
- package/dist/workflow-chat-transport-Bw-K44A5.d.ts.map +1 -0
- package/dist/{workflow-chat-transport-Bduf4ZDx.js → workflow-chat-transport-Dj1poviu.js} +3 -1
- package/dist/workflow-chat-transport-Dj1poviu.js.map +1 -0
- package/package.json +8 -5
- package/src/build-model-step-result.ts +3 -2
- package/src/do-generate-step.ts +87 -24
- package/src/do-stream-step.ts +53 -21
- package/src/language-model-prompt-to-model-messages.ts +28 -0
- package/src/model-call-iterator.ts +38 -26
- package/src/model-call-telemetry.ts +177 -0
- package/src/model-call.ts +21 -1
- package/src/serializable-schema.ts +26 -2
- package/src/test/telemetry-workflows.ts +42 -0
- package/src/workflow-agent.ts +14 -8
- package/src/workflow-chat-transport.ts +6 -1
- package/dist/workflow-chat-transport-Bduf4ZDx.js.map +0 -1
- package/dist/workflow-chat-transport-DwOgX7dK.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { n as normalizeUIMessageStreamParts, t as WorkflowChatTransport } from "./workflow-chat-transport-
|
|
2
|
-
import { asArray, asSchema, convertUint8ArrayToBase64, generateId, getErrorMessage, isAbortError, jsonSchema, validateTypes, withUserAgentSuffix } from "@ai-sdk/provider-utils";
|
|
1
|
+
import { n as normalizeUIMessageStreamParts, t as WorkflowChatTransport } from "./workflow-chat-transport-Dj1poviu.js";
|
|
2
|
+
import { asArray, asSchema, convertUint8ArrayToBase64, createIdGenerator, generateId, getErrorMessage, isAbortError, jsonSchema, validateTypes, withUserAgentSuffix } from "@ai-sdk/provider-utils";
|
|
3
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";
|
|
4
|
+
import { DefaultGenerateTextResult, DefaultStepResult, addLanguageModelUsage, asLanguageModelUsage, calculateTokensPerSecond, collectToolApprovals, convertLanguageModelContent, convertToLanguageModelPrompt, createDefaultDownloadFunction, createNullLanguageModelUsage, createRestrictedTelemetryDispatcher, createTelemetryDispatcher, createToolModelOutput, createToolSearchState, downloadAssets, isOutputChunk, 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
|
import Ajv2020 from "ajv/dist/2020.js";
|
|
@@ -182,7 +182,7 @@ async function buildModelStepResult(raw, toolCalls, finish, providerExecutedTool
|
|
|
182
182
|
durationMs: duration
|
|
183
183
|
});
|
|
184
184
|
return new DefaultStepResult({
|
|
185
|
-
callId: "workflow-agent",
|
|
185
|
+
callId: opts.callId ?? "workflow-agent",
|
|
186
186
|
stepNumber: opts.stepNumber,
|
|
187
187
|
provider: raw.generation.provider,
|
|
188
188
|
modelId: raw.generation.modelId,
|
|
@@ -311,7 +311,7 @@ async function buildModelStepResult(raw, toolCalls, finish, providerExecutedTool
|
|
|
311
311
|
}
|
|
312
312
|
const toolResults = content.filter((part) => part.type === "tool-result");
|
|
313
313
|
return {
|
|
314
|
-
callId: "workflow-agent",
|
|
314
|
+
callId: opts.callId ?? "workflow-agent",
|
|
315
315
|
stepNumber: opts.stepNumber,
|
|
316
316
|
model: {
|
|
317
317
|
provider: responseMetadata?.modelId?.split(":")[0] ?? "unknown",
|
|
@@ -382,6 +382,26 @@ async function buildModelStepResult(raw, toolCalls, finish, providerExecutedTool
|
|
|
382
382
|
};
|
|
383
383
|
}
|
|
384
384
|
//#endregion
|
|
385
|
+
//#region src/language-model-prompt-to-model-messages.ts
|
|
386
|
+
/**
|
|
387
|
+
* Prepares a workflow-side `LanguageModelV4Prompt` for a second, model-aware
|
|
388
|
+
* `convertToLanguageModelPrompt` pass inside a model step.
|
|
389
|
+
*
|
|
390
|
+
* The workflow-side conversion preserves URLs (it cannot download them) and
|
|
391
|
+
* filters out approval responses for tools that are not provider-executed.
|
|
392
|
+
* The remaining approval responses are restored with the `providerExecuted`
|
|
393
|
+
* marker that the second conversion expects.
|
|
394
|
+
*/
|
|
395
|
+
function languageModelPromptToModelMessages(prompt) {
|
|
396
|
+
return prompt.map((message) => message.role !== "tool" ? message : {
|
|
397
|
+
...message,
|
|
398
|
+
content: message.content.map((part) => part.type === "tool-approval-response" ? {
|
|
399
|
+
...part,
|
|
400
|
+
providerExecuted: true
|
|
401
|
+
} : part)
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
//#endregion
|
|
385
405
|
//#region src/serializable-schema.ts
|
|
386
406
|
/**
|
|
387
407
|
* Converts a ToolSet (with Zod/standard schemas and execute functions) to a
|
|
@@ -424,6 +444,16 @@ function resolveToolDescription({ tool, toolName, toolsContext, experimental_san
|
|
|
424
444
|
experimental_sandbox: sandbox
|
|
425
445
|
});
|
|
426
446
|
}
|
|
447
|
+
function formatAjvError(error) {
|
|
448
|
+
const path = `data${error.instancePath}`;
|
|
449
|
+
switch (error.keyword) {
|
|
450
|
+
case "enum": return `${path} must be one of ${error.params.allowedValues.map((value) => JSON.stringify(value)).join(", ")}`;
|
|
451
|
+
case "additionalProperties": return `${path} has unexpected property ${JSON.stringify(error.params.additionalProperty)}`;
|
|
452
|
+
case "const": return `${path} must equal ${JSON.stringify(error.params.allowedValue)}`;
|
|
453
|
+
case "required": return `${path} is missing required property ${JSON.stringify(error.params.missingProperty)}`;
|
|
454
|
+
default: return `${path} ${error.message ?? "is invalid"}`;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
427
457
|
/**
|
|
428
458
|
* Reconstructs tool objects from serializable tool definitions inside a step.
|
|
429
459
|
*
|
|
@@ -433,14 +463,14 @@ function resolveToolDescription({ tool, toolName, toolsContext, experimental_san
|
|
|
433
463
|
*/
|
|
434
464
|
function resolveSerializableTools(tools) {
|
|
435
465
|
const ajvOptions = {
|
|
466
|
+
allErrors: true,
|
|
436
467
|
strict: false,
|
|
437
468
|
validateFormats: false
|
|
438
469
|
};
|
|
439
470
|
const ajv = new Ajv(ajvOptions);
|
|
440
471
|
const ajv2020 = new Ajv2020(ajvOptions);
|
|
441
472
|
const createValidatedInputSchema = (inputSchema) => {
|
|
442
|
-
const
|
|
443
|
-
const validateFn = schemaAjv.compile(inputSchema);
|
|
473
|
+
const validateFn = ((typeof inputSchema.$schema === "string" ? inputSchema.$schema.replace(/#$/, "") : void 0) === "https://json-schema.org/draft/2020-12/schema" ? ajv2020 : ajv).compile(inputSchema);
|
|
444
474
|
return jsonSchema(inputSchema, { validate: (value) => {
|
|
445
475
|
if (validateFn(value)) return {
|
|
446
476
|
success: true,
|
|
@@ -448,7 +478,7 @@ function resolveSerializableTools(tools) {
|
|
|
448
478
|
};
|
|
449
479
|
return {
|
|
450
480
|
success: false,
|
|
451
|
-
error: new Error(
|
|
481
|
+
error: new Error(validateFn.errors.map(formatAjvError).join(", "))
|
|
452
482
|
};
|
|
453
483
|
} });
|
|
454
484
|
};
|
|
@@ -494,31 +524,164 @@ function resolveSerializableTools(tools) {
|
|
|
494
524
|
}));
|
|
495
525
|
}
|
|
496
526
|
//#endregion
|
|
527
|
+
//#region src/model-call-telemetry.ts
|
|
528
|
+
const generateCallId = createIdGenerator({
|
|
529
|
+
prefix: "call",
|
|
530
|
+
size: 24
|
|
531
|
+
});
|
|
532
|
+
/**
|
|
533
|
+
* Global telemetry integrations are not visible in the workflow VM, so the
|
|
534
|
+
* workflow body sends a serializable descriptor and the model step, which
|
|
535
|
+
* runs in Node, dispatches the model call lifecycle itself.
|
|
536
|
+
*
|
|
537
|
+
* Each model call is reported as its own operation with a unique `callId`.
|
|
538
|
+
*/
|
|
539
|
+
function shouldDispatchModelCallTelemetryInStep(telemetry) {
|
|
540
|
+
return telemetry?.isEnabled !== false && telemetry?.integrations == null && globalThis.AI_SDK_TELEMETRY_INTEGRATIONS == null;
|
|
541
|
+
}
|
|
542
|
+
async function runModelCallWithTelemetry({ telemetry, modelInit, prompt, serializedTools, options, execute }) {
|
|
543
|
+
if (telemetry == null) return execute(void 0);
|
|
544
|
+
const dispatcher = createTelemetryDispatcher({ telemetry });
|
|
545
|
+
const callId = generateCallId();
|
|
546
|
+
const { provider, modelId } = typeof modelInit === "string" ? {
|
|
547
|
+
provider: "gateway",
|
|
548
|
+
modelId: modelInit
|
|
549
|
+
} : modelInit;
|
|
550
|
+
const tools = serializedTools == null ? void 0 : resolveSerializableTools(serializedTools);
|
|
551
|
+
const messages = prompt;
|
|
552
|
+
await dispatcher.onStart?.({
|
|
553
|
+
callId,
|
|
554
|
+
operationId: "ai.workflowAgent.stream",
|
|
555
|
+
provider,
|
|
556
|
+
modelId,
|
|
557
|
+
system: void 0,
|
|
558
|
+
messages,
|
|
559
|
+
tools,
|
|
560
|
+
toolChoice: options?.toolChoice,
|
|
561
|
+
activeTools: void 0,
|
|
562
|
+
maxOutputTokens: options?.maxOutputTokens,
|
|
563
|
+
temperature: options?.temperature,
|
|
564
|
+
topP: options?.topP,
|
|
565
|
+
topK: options?.topK,
|
|
566
|
+
presencePenalty: options?.presencePenalty,
|
|
567
|
+
frequencyPenalty: options?.frequencyPenalty,
|
|
568
|
+
stopSequences: options?.stopSequences,
|
|
569
|
+
seed: options?.seed,
|
|
570
|
+
maxRetries: options?.maxRetries ?? 2,
|
|
571
|
+
timeout: void 0,
|
|
572
|
+
headers: options?.headers,
|
|
573
|
+
reasoning: options?.reasoning,
|
|
574
|
+
providerOptions: options?.providerOptions,
|
|
575
|
+
output: void 0,
|
|
576
|
+
runtimeContext: {},
|
|
577
|
+
toolsContext: {}
|
|
578
|
+
});
|
|
579
|
+
await dispatcher.onStepStart?.({
|
|
580
|
+
callId,
|
|
581
|
+
provider,
|
|
582
|
+
modelId,
|
|
583
|
+
stepNumber: telemetry.stepNumber,
|
|
584
|
+
system: void 0,
|
|
585
|
+
messages,
|
|
586
|
+
tools,
|
|
587
|
+
toolChoice: options?.toolChoice,
|
|
588
|
+
activeTools: void 0,
|
|
589
|
+
steps: [],
|
|
590
|
+
providerOptions: options?.providerOptions,
|
|
591
|
+
output: void 0,
|
|
592
|
+
runtimeContext: {},
|
|
593
|
+
toolsContext: {}
|
|
594
|
+
});
|
|
595
|
+
let result;
|
|
596
|
+
try {
|
|
597
|
+
result = await execute({
|
|
598
|
+
callId,
|
|
599
|
+
onLanguageModelCallStart: dispatcher.onLanguageModelCallStart,
|
|
600
|
+
onLanguageModelCallEnd: dispatcher.onLanguageModelCallEnd,
|
|
601
|
+
executeLanguageModelCallInTelemetryContext: dispatcher.executeLanguageModelCall
|
|
602
|
+
});
|
|
603
|
+
} catch (error) {
|
|
604
|
+
await dispatcher.onError?.({
|
|
605
|
+
callId,
|
|
606
|
+
error
|
|
607
|
+
});
|
|
608
|
+
throw error;
|
|
609
|
+
}
|
|
610
|
+
if (result.aborted) {
|
|
611
|
+
await dispatcher.onAbort?.({
|
|
612
|
+
callId,
|
|
613
|
+
steps: []
|
|
614
|
+
});
|
|
615
|
+
return result;
|
|
616
|
+
}
|
|
617
|
+
if ("terminalError" in result) {
|
|
618
|
+
await dispatcher.onError?.({
|
|
619
|
+
callId,
|
|
620
|
+
error: result.terminalError
|
|
621
|
+
});
|
|
622
|
+
return result;
|
|
623
|
+
}
|
|
624
|
+
const step = await buildModelStepResult(result.raw, result.toolCalls, result.finish, result.providerExecutedToolResults, {
|
|
625
|
+
callId,
|
|
626
|
+
tools,
|
|
627
|
+
stepNumber: telemetry.stepNumber,
|
|
628
|
+
runtimeContext: {},
|
|
629
|
+
toolsContext: {}
|
|
630
|
+
});
|
|
631
|
+
await dispatcher.onStepEnd?.(step);
|
|
632
|
+
await dispatcher.onEnd?.(Object.assign(Object.create(Object.getPrototypeOf(step)), step, {
|
|
633
|
+
finalStep: step,
|
|
634
|
+
steps: [step],
|
|
635
|
+
usage: step.usage,
|
|
636
|
+
totalUsage: step.usage
|
|
637
|
+
}));
|
|
638
|
+
return result;
|
|
639
|
+
}
|
|
640
|
+
//#endregion
|
|
497
641
|
//#region src/do-generate-step.ts
|
|
498
642
|
/** A single durable provider call; orchestration and callbacks stay in the workflow. */
|
|
499
643
|
async function doGenerateStep(prompt, modelInit, serializedTools, options = {}) {
|
|
500
644
|
"use step";
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
645
|
+
return runModelCallWithTelemetry({
|
|
646
|
+
telemetry: options.telemetry,
|
|
647
|
+
modelInit,
|
|
648
|
+
prompt,
|
|
649
|
+
serializedTools,
|
|
650
|
+
options,
|
|
651
|
+
execute: async (languageModelCallTelemetry) => {
|
|
652
|
+
try {
|
|
653
|
+
return await generateModelCall(prompt, modelInit, serializedTools, options, languageModelCallTelemetry);
|
|
654
|
+
} catch (error) {
|
|
655
|
+
return {
|
|
656
|
+
toolCalls: [],
|
|
657
|
+
finish: void 0,
|
|
658
|
+
raw: {
|
|
659
|
+
content: [],
|
|
660
|
+
reasoning: []
|
|
661
|
+
},
|
|
662
|
+
providerExecutedToolResults: /* @__PURE__ */ new Map(),
|
|
663
|
+
terminalError: error
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
});
|
|
515
668
|
}
|
|
516
|
-
async function generateModelCall(prompt, modelInit, serializedTools, options) {
|
|
669
|
+
async function generateModelCall(prompt, modelInit, serializedTools, options, languageModelCallTelemetry) {
|
|
517
670
|
const remaining = options.timeoutAt == null ? void 0 : options.timeoutAt - Date.now();
|
|
518
671
|
options.abortSignal?.throwIfAborted();
|
|
519
672
|
if (remaining != null && remaining <= 0) throw new DOMException("The generation deadline expired.", "TimeoutError");
|
|
520
673
|
const abortSignal = remaining == null ? options.abortSignal : AbortSignal.any([...options.abortSignal == null ? [] : [options.abortSignal], AbortSignal.timeout(remaining)]);
|
|
521
674
|
const model = resolveLanguageModel(modelInit);
|
|
675
|
+
const modelPrompt = await convertToLanguageModelPrompt({
|
|
676
|
+
prompt: {
|
|
677
|
+
instructions: void 0,
|
|
678
|
+
messages: languageModelPromptToModelMessages(prompt)
|
|
679
|
+
},
|
|
680
|
+
supportedUrls: await model.supportedUrls,
|
|
681
|
+
download: options.download,
|
|
682
|
+
abortSignal,
|
|
683
|
+
provider: model.provider.split(".")[0]
|
|
684
|
+
});
|
|
522
685
|
const tools = resolveSerializableTools(serializedTools);
|
|
523
686
|
const toolChoice = prepareToolChoice({ toolChoice: options.toolChoice });
|
|
524
687
|
const modelTools = await prepareTools({ tools });
|
|
@@ -527,28 +690,54 @@ async function generateModelCall(prompt, modelInit, serializedTools, options) {
|
|
|
527
690
|
maxRetries: options.maxRetries,
|
|
528
691
|
abortSignal
|
|
529
692
|
});
|
|
693
|
+
const callId = languageModelCallTelemetry?.callId;
|
|
694
|
+
const executeLanguageModelCall = languageModelCallTelemetry?.executeLanguageModelCallInTelemetryContext ?? (({ execute }) => execute());
|
|
695
|
+
await languageModelCallTelemetry?.onLanguageModelCallStart?.({
|
|
696
|
+
callId,
|
|
697
|
+
provider: model.provider,
|
|
698
|
+
modelId: model.modelId,
|
|
699
|
+
messages: prompt,
|
|
700
|
+
tools: modelTools,
|
|
701
|
+
...settings,
|
|
702
|
+
providerOptions: options.providerOptions,
|
|
703
|
+
headers: options.headers
|
|
704
|
+
});
|
|
530
705
|
const start = Date.now();
|
|
531
706
|
const response = await retry(async () => {
|
|
532
707
|
abortSignal?.throwIfAborted();
|
|
533
708
|
if (options.timeoutAt != null && options.timeoutAt <= Date.now()) throw new DOMException("The generation deadline expired.", "TimeoutError");
|
|
534
|
-
return
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
709
|
+
return executeLanguageModelCall({
|
|
710
|
+
callId: callId ?? "",
|
|
711
|
+
execute: () => model.doGenerate({
|
|
712
|
+
...settings,
|
|
713
|
+
prompt: modelPrompt,
|
|
714
|
+
tools: modelTools,
|
|
715
|
+
toolChoice,
|
|
716
|
+
responseFormat: options.responseFormat,
|
|
717
|
+
providerOptions: options.providerOptions,
|
|
718
|
+
headers: options.headers,
|
|
719
|
+
abortSignal
|
|
720
|
+
})
|
|
543
721
|
});
|
|
544
722
|
});
|
|
545
|
-
abortSignal?.throwIfAborted();
|
|
546
723
|
const responseTimeMs = Date.now() - start;
|
|
724
|
+
await languageModelCallTelemetry?.onLanguageModelCallEnd?.({
|
|
725
|
+
callId,
|
|
726
|
+
provider: model.provider,
|
|
727
|
+
modelId: response.response?.modelId ?? model.modelId,
|
|
728
|
+
finishReason: response.finishReason.unified,
|
|
729
|
+
usage: asLanguageModelUsage(response.usage),
|
|
730
|
+
content: response.content,
|
|
731
|
+
responseId: response.response?.id,
|
|
732
|
+
...response.providerMetadata != null ? { providerMetadata: response.providerMetadata } : {},
|
|
733
|
+
performance: { responseTimeMs }
|
|
734
|
+
});
|
|
735
|
+
abortSignal?.throwIfAborted();
|
|
547
736
|
const toolCalls = await Promise.all(response.content.filter((part) => part.type === "tool-call").map((toolCall) => parseToolCall({
|
|
548
737
|
toolCall,
|
|
549
738
|
tools,
|
|
550
739
|
repairToolCall: options.repairToolCall,
|
|
551
|
-
instructions:
|
|
740
|
+
instructions: modelPrompt.filter((message) => message.role === "system").map((message) => message.content).join("\n") || void 0,
|
|
552
741
|
messages: prompt.filter((message) => message.role !== "system")
|
|
553
742
|
})));
|
|
554
743
|
if ((toolChoice.type === "required" || toolChoice.type === "tool") && !toolCalls.some((call) => toolChoice.type === "required" || call.toolName === toolChoice.toolName)) throw new ToolChoiceViolationError({
|
|
@@ -627,6 +816,17 @@ doGenerateStep.maxRetries = 0;
|
|
|
627
816
|
//#region src/do-stream-step.ts
|
|
628
817
|
async function doStreamStep(conversationPrompt, modelInit, writable, serializedTools, options) {
|
|
629
818
|
"use step";
|
|
819
|
+
return runModelCallWithTelemetry({
|
|
820
|
+
telemetry: options?.telemetry,
|
|
821
|
+
modelInit,
|
|
822
|
+
prompt: conversationPrompt,
|
|
823
|
+
serializedTools,
|
|
824
|
+
options,
|
|
825
|
+
execute: (languageModelCallTelemetry) => streamModelStep(conversationPrompt, modelInit, writable, serializedTools, options, languageModelCallTelemetry)
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
doStreamStep.maxRetries = 0;
|
|
829
|
+
async function streamModelStep(conversationPrompt, modelInit, writable, serializedTools, options, languageModelCallTelemetry) {
|
|
630
830
|
const timeout = options?.timeoutAt == null ? void 0 : options.timeoutAt - Date.now();
|
|
631
831
|
if (options?.abortSignal?.aborted || timeout != null && timeout <= 0) return { aborted: true };
|
|
632
832
|
const abortSignal = timeout == null ? options?.abortSignal : options?.abortSignal == null ? AbortSignal.timeout(timeout) : AbortSignal.any([options.abortSignal, AbortSignal.timeout(timeout)]);
|
|
@@ -667,13 +867,7 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
|
|
|
667
867
|
try {
|
|
668
868
|
const { stream } = await retry(() => experimental_streamLanguageModelCall({
|
|
669
869
|
model: modelWithTransforms,
|
|
670
|
-
messages: conversationPrompt
|
|
671
|
-
...message,
|
|
672
|
-
content: message.content.map((part) => part.type === "tool-approval-response" ? {
|
|
673
|
-
...part,
|
|
674
|
-
providerExecuted: true
|
|
675
|
-
} : part)
|
|
676
|
-
}),
|
|
870
|
+
messages: languageModelPromptToModelMessages(conversationPrompt),
|
|
677
871
|
allowSystemInMessages: true,
|
|
678
872
|
tools,
|
|
679
873
|
toolChoice: options?.toolChoice,
|
|
@@ -691,7 +885,9 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
|
|
|
691
885
|
frequencyPenalty: options?.frequencyPenalty,
|
|
692
886
|
stopSequences: options?.stopSequences,
|
|
693
887
|
seed: options?.seed,
|
|
694
|
-
repairToolCall: options?.repairToolCall
|
|
888
|
+
repairToolCall: options?.repairToolCall,
|
|
889
|
+
download: options?.download,
|
|
890
|
+
...languageModelCallTelemetry
|
|
695
891
|
}));
|
|
696
892
|
return stream;
|
|
697
893
|
} catch (error) {
|
|
@@ -712,11 +908,13 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
|
|
|
712
908
|
let performance;
|
|
713
909
|
let terminalError;
|
|
714
910
|
let hasTerminalError = false;
|
|
911
|
+
let hasReceivedOutputChunk = false;
|
|
715
912
|
const ongoingToolCallToolNames = /* @__PURE__ */ new Map();
|
|
716
913
|
const writer = writable?.getWriter();
|
|
717
914
|
try {
|
|
718
915
|
await writer?.write({ type: "reset-step" });
|
|
719
916
|
for await (const part of modelStream) {
|
|
917
|
+
if (isOutputChunk(part)) hasReceivedOutputChunk = true;
|
|
720
918
|
switch (part.type) {
|
|
721
919
|
case "tool-input-start":
|
|
722
920
|
ongoingToolCallToolNames.set(part.id, part.toolName);
|
|
@@ -902,6 +1100,10 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
|
|
|
902
1100
|
writer?.releaseLock();
|
|
903
1101
|
}
|
|
904
1102
|
if (abortSignal?.aborted || options?.timeoutAt != null && options.timeoutAt <= Date.now()) return { aborted: true };
|
|
1103
|
+
if (finish == null && !hasReceivedOutputChunk && !hasTerminalError) {
|
|
1104
|
+
terminalError = new NoOutputGeneratedError({ message: "No output generated. The model stream ended without a finish chunk." });
|
|
1105
|
+
hasTerminalError = true;
|
|
1106
|
+
}
|
|
905
1107
|
return {
|
|
906
1108
|
toolCalls,
|
|
907
1109
|
finish,
|
|
@@ -917,7 +1119,6 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
|
|
|
917
1119
|
...hasTerminalError ? { terminalError } : {}
|
|
918
1120
|
};
|
|
919
1121
|
}
|
|
920
|
-
doStreamStep.maxRetries = 0;
|
|
921
1122
|
function applyStreamTransforms({ stream, transforms, tools }) {
|
|
922
1123
|
const sourceReader = stream.getReader();
|
|
923
1124
|
let stopped = false;
|
|
@@ -1006,7 +1207,7 @@ function mergePrepareStepGenerationSettings(current, overrides) {
|
|
|
1006
1207
|
...definedOverrides
|
|
1007
1208
|
};
|
|
1008
1209
|
}
|
|
1009
|
-
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 }) {
|
|
1210
|
+
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, download, responseFormat, experimental_transform, experimental_sandbox: sandbox }) {
|
|
1010
1211
|
let conversationPrompt = [...prompt];
|
|
1011
1212
|
let currentModel = model;
|
|
1012
1213
|
let currentGenerationSettings = generationSettings ?? {};
|
|
@@ -1032,6 +1233,7 @@ async function* modelCallIterator({ prompt, mode = "stream", include, initialIns
|
|
|
1032
1233
|
includeRuntimeContext: telemetry?.includeRuntimeContext,
|
|
1033
1234
|
includeToolsContext: telemetry?.includeToolsContext
|
|
1034
1235
|
});
|
|
1236
|
+
const dispatchTelemetryInStep = shouldDispatchModelCallTelemetryInStep(telemetry);
|
|
1035
1237
|
while (!done) {
|
|
1036
1238
|
if (currentGenerationSettings.abortSignal?.aborted) {
|
|
1037
1239
|
if (mode === "generate") currentGenerationSettings.abortSignal.throwIfAborted();
|
|
@@ -1133,9 +1335,16 @@ async function* modelCallIterator({ prompt, mode = "stream", include, initialIns
|
|
|
1133
1335
|
includeRawChunks,
|
|
1134
1336
|
timeoutAt,
|
|
1135
1337
|
repairToolCall,
|
|
1338
|
+
download,
|
|
1136
1339
|
responseFormat,
|
|
1137
1340
|
include,
|
|
1138
|
-
experimental_transform
|
|
1341
|
+
experimental_transform,
|
|
1342
|
+
telemetry: dispatchTelemetryInStep ? {
|
|
1343
|
+
functionId: telemetry?.functionId,
|
|
1344
|
+
recordInputs: telemetry?.recordInputs,
|
|
1345
|
+
recordOutputs: telemetry?.recordOutputs,
|
|
1346
|
+
stepNumber
|
|
1347
|
+
} : void 0
|
|
1139
1348
|
};
|
|
1140
1349
|
const modelCallResult = mode === "generate" ? await doGenerateStep(conversationPrompt, currentModel, serializedTools, callOptions) : await doStreamStep(conversationPrompt, currentModel, writable, serializedTools, callOptions);
|
|
1141
1350
|
if (modelCallResult.aborted) {
|
|
@@ -1182,10 +1391,10 @@ async function* modelCallIterator({ prompt, mode = "stream", include, initialIns
|
|
|
1182
1391
|
const isToolExecutionAllowed = finishReason === "tool-calls" || finishReason === "stop";
|
|
1183
1392
|
for (const toolCall of toolCalls) if (toolCall.providerExecuted && serializedTools[toolCall.toolName]?.supportsDeferredResults && !providerExecutedToolResults.has(toolCall.toolCallId)) pendingDeferredToolCallIds.add(toolCall.toolCallId);
|
|
1184
1393
|
for (const toolCallId of providerExecutedToolResults.keys()) pendingDeferredToolCallIds.delete(toolCallId);
|
|
1185
|
-
const shouldProcessTools = isToolExecutionAllowed && (toolCalls.length > 0 || providerExecutedToolResults.size > 0);
|
|
1186
|
-
if (hasTerminalError
|
|
1187
|
-
else if (shouldProcessTools) {
|
|
1394
|
+
const shouldProcessTools = isToolExecutionAllowed && (toolCalls.length > 0 || providerExecutedToolResults.size > 0) || finishReason === "length" && providerExecutedToolResults.size > 0;
|
|
1395
|
+
if (!hasTerminalError && shouldProcessTools) {
|
|
1188
1396
|
lastStepWasYielded = true;
|
|
1397
|
+
const processableToolCalls = isToolExecutionAllowed ? toolCalls : toolCalls.filter((toolCall) => !toolCall.providerExecuted && toolCall.invalid || toolCall.providerExecuted && providerExecutedToolResults.has(toolCall.toolCallId));
|
|
1189
1398
|
const { content: assistantContent, providerExecutedToolResultPositions } = getAssistantMessageContent(step, mode);
|
|
1190
1399
|
const includedToolCallIds = new Set(assistantContent.flatMap((part) => part.type === "tool-call" ? [part.toolCallId] : []));
|
|
1191
1400
|
conversationPrompt.push({
|
|
@@ -1193,7 +1402,7 @@ async function* modelCallIterator({ prompt, mode = "stream", include, initialIns
|
|
|
1193
1402
|
content: [...assistantContent, ...toolCalls.filter((toolCall) => !includedToolCallIds.has(toolCall.toolCallId)).map(toAssistantToolCallContent)]
|
|
1194
1403
|
});
|
|
1195
1404
|
const toolResults = yield {
|
|
1196
|
-
toolCalls,
|
|
1405
|
+
toolCalls: processableToolCalls,
|
|
1197
1406
|
tools: effectiveTools,
|
|
1198
1407
|
messages: conversationPrompt,
|
|
1199
1408
|
step,
|
|
@@ -1206,14 +1415,14 @@ async function* modelCallIterator({ prompt, mode = "stream", include, initialIns
|
|
|
1206
1415
|
const responseMessages = addToolResultsToConversation({
|
|
1207
1416
|
messages: conversationPrompt,
|
|
1208
1417
|
toolResults,
|
|
1209
|
-
providerExecutedToolCallIds: /* @__PURE__ */ new Set([...
|
|
1418
|
+
providerExecutedToolCallIds: /* @__PURE__ */ new Set([...processableToolCalls.flatMap((toolCall) => toolCall.providerExecuted ? [toolCall.toolCallId] : []), ...providerExecutedToolResults.keys()]),
|
|
1210
1419
|
providerExecutedToolResultPositions
|
|
1211
1420
|
});
|
|
1212
1421
|
step.response.messages.push(...mode === "generate" ? toModelResponseMessages(responseMessages) : responseMessages);
|
|
1213
1422
|
const stopConditionMet = (stopConditions == null ? [] : Array.isArray(stopConditions) ? stopConditions : [stopConditions]).some((test) => test({ steps }));
|
|
1214
1423
|
const hasClientToolCalls = toolCalls.some((toolCall) => !toolCall.providerExecuted);
|
|
1215
|
-
done = stopConditionMet || !hasClientToolCalls && pendingDeferredToolCallIds.size === 0;
|
|
1216
|
-
} else if (mode === "generate" || finishReason === "stop" || finishReason === "tool-calls" || finishReason === "length") {
|
|
1424
|
+
done = !isToolExecutionAllowed || stopConditionMet || !hasClientToolCalls && pendingDeferredToolCallIds.size === 0;
|
|
1425
|
+
} else if (hasTerminalError || mode === "generate" || finishReason === "stop" || finishReason === "tool-calls" || finishReason === "length" || finishReason === "content-filter" || finishReason === "error" || finishReason === "other" || finishReason === "unknown" || !finishReason) {
|
|
1217
1426
|
const { content: assistantContent } = getAssistantMessageContent(step, mode);
|
|
1218
1427
|
if (assistantContent.length > 0) {
|
|
1219
1428
|
const assistantMessage = {
|
|
@@ -1224,12 +1433,7 @@ async function* modelCallIterator({ prompt, mode = "stream", include, initialIns
|
|
|
1224
1433
|
step.response.messages.push(...mode === "generate" ? toModelResponseMessages([assistantMessage]) : [assistantMessage]);
|
|
1225
1434
|
}
|
|
1226
1435
|
done = true;
|
|
1227
|
-
} else
|
|
1228
|
-
else if (finishReason === "error") done = true;
|
|
1229
|
-
else if (finishReason === "other") done = true;
|
|
1230
|
-
else if (finishReason === "unknown") done = true;
|
|
1231
|
-
else if (!finishReason) done = true;
|
|
1232
|
-
else throw new Error(`Unexpected finish reason: ${typeof finish?.finishReason === "object" ? JSON.stringify(finish?.finishReason) : finish?.finishReason}`);
|
|
1436
|
+
} else throw new Error(`Unexpected finish reason: ${typeof finish?.finishReason === "object" ? JSON.stringify(finish?.finishReason) : finish?.finishReason}`);
|
|
1233
1437
|
const resolvedOnStepEnd = onStepEnd ?? onStepFinish;
|
|
1234
1438
|
if (resolvedOnStepEnd) await resolvedOnStepEnd(step);
|
|
1235
1439
|
await telemetryDispatcher.onStepEnd?.(normalizeStepForTelemetry$1(step));
|
|
@@ -1617,7 +1821,7 @@ var WorkflowAgent = class {
|
|
|
1617
1821
|
allowSystemInMessages: this.allowSystemInMessages,
|
|
1618
1822
|
...effectivePrompt != null ? { prompt: effectivePrompt } : { messages: effectiveMessages }
|
|
1619
1823
|
});
|
|
1620
|
-
const
|
|
1824
|
+
const workflowDownload = async (requests) => requests.map(() => null);
|
|
1621
1825
|
const sandbox = options.experimental_sandbox ?? this.experimentalSandbox;
|
|
1622
1826
|
const abortSignalTimeout = isInWorkflow() ? void 0 : options.timeout;
|
|
1623
1827
|
const effectiveAbortSignal = mergeAbortSignals(options.abortSignal ?? effectiveGenerationSettings.abortSignal, abortSignalTimeout);
|
|
@@ -1638,7 +1842,8 @@ var WorkflowAgent = class {
|
|
|
1638
1842
|
effectiveTelemetry,
|
|
1639
1843
|
telemetryDispatcher,
|
|
1640
1844
|
prompt,
|
|
1641
|
-
download,
|
|
1845
|
+
download: effectiveDownloadFromPrepare,
|
|
1846
|
+
workflowDownload,
|
|
1642
1847
|
sandbox,
|
|
1643
1848
|
effectiveAbortSignal,
|
|
1644
1849
|
timeoutAt,
|
|
@@ -1647,7 +1852,7 @@ var WorkflowAgent = class {
|
|
|
1647
1852
|
};
|
|
1648
1853
|
}
|
|
1649
1854
|
async execute(options, mode = "stream") {
|
|
1650
|
-
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);
|
|
1855
|
+
const { onEnd, effectiveModel, effectiveInstructions, effectiveGenerationSettings, effectiveRuntimeContext, effectiveToolsContext, effectiveToolChoiceFromPrepare, effectiveStopWhenFromPrepare, effectiveActiveToolsFromPrepare, effectiveToolApprovalSecret, effectiveTelemetry, telemetryDispatcher, prompt, download, workflowDownload, sandbox, effectiveAbortSignal, timeoutAt, mergedOnToolExecutionStart, mergedOnToolExecutionEnd } = await this.prepareInvocation(options, mode);
|
|
1651
1856
|
const initialResponseMessages = [];
|
|
1652
1857
|
const abortReason = () => effectiveAbortSignal?.reason === void 0 ? void 0 : { value: effectiveAbortSignal.reason };
|
|
1653
1858
|
const collectedApprovals = collectToolApprovals({ messages: prompt.messages });
|
|
@@ -1689,7 +1894,7 @@ var WorkflowAgent = class {
|
|
|
1689
1894
|
tool,
|
|
1690
1895
|
errorMode: "text",
|
|
1691
1896
|
supportedUrls: {},
|
|
1692
|
-
download
|
|
1897
|
+
download: workflowDownload
|
|
1693
1898
|
})
|
|
1694
1899
|
});
|
|
1695
1900
|
continue;
|
|
@@ -1730,7 +1935,7 @@ var WorkflowAgent = class {
|
|
|
1730
1935
|
tool,
|
|
1731
1936
|
errorMode: "text",
|
|
1732
1937
|
supportedUrls: {},
|
|
1733
|
-
download
|
|
1938
|
+
download: workflowDownload
|
|
1734
1939
|
})
|
|
1735
1940
|
});
|
|
1736
1941
|
continue;
|
|
@@ -1797,7 +2002,7 @@ var WorkflowAgent = class {
|
|
|
1797
2002
|
const modelPrompt = await convertToLanguageModelPrompt({
|
|
1798
2003
|
prompt,
|
|
1799
2004
|
supportedUrls: {},
|
|
1800
|
-
download
|
|
2005
|
+
download: workflowDownload
|
|
1801
2006
|
});
|
|
1802
2007
|
const mergedGenerationSettings = {
|
|
1803
2008
|
...effectiveGenerationSettings,
|
|
@@ -1894,7 +2099,7 @@ var WorkflowAgent = class {
|
|
|
1894
2099
|
const startTime = Date.now();
|
|
1895
2100
|
let result;
|
|
1896
2101
|
try {
|
|
1897
|
-
const execute = () => executeTool(toolCall, tools, messages, resolvedContext, effectiveAbortSignal,
|
|
2102
|
+
const execute = () => executeTool(toolCall, tools, messages, resolvedContext, effectiveAbortSignal, workflowDownload, stepSandbox);
|
|
1898
2103
|
result = telemetryDispatcher.executeTool != null ? await telemetryDispatcher.executeTool({
|
|
1899
2104
|
callId: "workflow-agent",
|
|
1900
2105
|
toolCallId: toolCall.toolCallId,
|
|
@@ -2029,6 +2234,7 @@ var WorkflowAgent = class {
|
|
|
2029
2234
|
includeRawChunks: options.includeRawChunks ?? false,
|
|
2030
2235
|
timeoutAt,
|
|
2031
2236
|
repairToolCall: options.repairToolCall ?? options.experimental_repairToolCall ?? this.repairToolCall,
|
|
2237
|
+
download,
|
|
2032
2238
|
responseFormat: await (options.output ?? this.output)?.responseFormat,
|
|
2033
2239
|
experimental_transform: options.experimental_transform,
|
|
2034
2240
|
experimental_sandbox: sandbox
|
|
@@ -2106,7 +2312,7 @@ var WorkflowAgent = class {
|
|
|
2106
2312
|
const executableResults = await Promise.all(executableToolCalls.map((toolCall) => executeToolWithCallbacks(toolCall, stepTools, iterMessages, toolsContext, currentStepNumber, toolExecutionSandbox)));
|
|
2107
2313
|
const providerResultEntries = await Promise.all(providerToolCallsForResults.filter((call) => !providerApprovalRequests.some((request) => request.toolCall.toolCallId === call.toolCallId)).map(async (toolCall) => ({
|
|
2108
2314
|
toolCall,
|
|
2109
|
-
result: await resolveProviderToolResult(toolCall, capturedProviderToolResults, stepTools,
|
|
2315
|
+
result: await resolveProviderToolResult(toolCall, capturedProviderToolResults, stepTools, workflowDownload)
|
|
2110
2316
|
})));
|
|
2111
2317
|
await Promise.all(providerResultEntries.flatMap(({ toolCall, result }) => result == null ? [] : [recordProviderExecutedToolTelemetry(toolCall, result, iterMessages, currentStepNumber)]));
|
|
2112
2318
|
const providerResults = providerResultEntries.flatMap(({ result }) => result == null ? [] : [result]);
|
|
@@ -2204,7 +2410,7 @@ var WorkflowAgent = class {
|
|
|
2204
2410
|
const clientToolResults = await Promise.all(nonProviderToolCalls.map((toolCall) => executeToolWithCallbacks(toolCall, stepTools, iterMessages, toolsContext, currentStepNumber, toolExecutionSandbox)));
|
|
2205
2411
|
const providerToolResultEntries = await Promise.all(providerToolCallsForResults.map(async (toolCall) => ({
|
|
2206
2412
|
toolCall,
|
|
2207
|
-
result: await resolveProviderToolResult(toolCall, capturedProviderToolResults, stepTools,
|
|
2413
|
+
result: await resolveProviderToolResult(toolCall, capturedProviderToolResults, stepTools, workflowDownload)
|
|
2208
2414
|
})));
|
|
2209
2415
|
await Promise.all(providerToolResultEntries.flatMap(({ toolCall, result }) => result == null ? [] : [recordProviderExecutedToolTelemetry(toolCall, result, iterMessages, currentStepNumber)]));
|
|
2210
2416
|
const providerToolResults = providerToolResultEntries.flatMap(({ result }) => result == null ? [] : [result]);
|