@ai-sdk/workflow 2.0.68 → 2.0.70
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 +32 -0
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +227 -49
- 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 +74 -23
- package/src/do-stream-step.ts +50 -5
- package/src/model-call-iterator.ts +35 -26
- package/src/model-call-telemetry.ts +177 -0
- package/src/model-call.ts +15 -0
- package/src/serializable-schema.ts +26 -2
- package/src/test/telemetry-workflows.ts +42 -0
- 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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @ai-sdk/workflow
|
|
2
2
|
|
|
3
|
+
## 2.0.70
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 1506ee1: Fix `WorkflowChatTransport` retrying indefinitely when successful reconnect responses contain no UI message chunks. Empty streams now count toward `maxConsecutiveErrors`, while streams that receive chunks continue to advance the resume cursor and reset the error count.
|
|
8
|
+
- 7400215: fix(workflow): retain streamed terminal assistant responses in conversation messages
|
|
9
|
+
- 9aef724: fix(workflow): report incomplete no-output model streams as errors
|
|
10
|
+
- 507cd9d: fix(workflow): include actionable details in tool input validation errors
|
|
11
|
+
- a155baa: fix(workflow): dispatch WorkflowAgent model call telemetry to globally registered integrations from the model step
|
|
12
|
+
- 7c0410d: fix(workflow): preserve provider-executed tool results and invalid local tool call error results on length completion
|
|
13
|
+
- Updated dependencies [eab278a]
|
|
14
|
+
- Updated dependencies [26d64e9]
|
|
15
|
+
- Updated dependencies [9667bf2]
|
|
16
|
+
- Updated dependencies [75b3ea2]
|
|
17
|
+
- Updated dependencies [69f4b82]
|
|
18
|
+
- Updated dependencies [e57803c]
|
|
19
|
+
- Updated dependencies [4c705d9]
|
|
20
|
+
- Updated dependencies [81663cc]
|
|
21
|
+
- Updated dependencies [5150d50]
|
|
22
|
+
- Updated dependencies [9aef724]
|
|
23
|
+
- Updated dependencies [7d0458b]
|
|
24
|
+
- ai@7.0.138
|
|
25
|
+
- @ai-sdk/provider-utils@5.0.59
|
|
26
|
+
- @ai-sdk/provider@4.0.27
|
|
27
|
+
|
|
28
|
+
## 2.0.69
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [e27cc64]
|
|
33
|
+
- ai@7.0.137
|
|
34
|
+
|
|
3
35
|
## 2.0.68
|
|
4
36
|
|
|
5
37
|
### Patch Changes
|
package/dist/client.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as WorkflowChatTransportOptions, n as SendMessagesOptions, r as WorkflowChatTransport, t as ReconnectToStreamOptions } from "./workflow-chat-transport-
|
|
1
|
+
import { i as WorkflowChatTransportOptions, n as SendMessagesOptions, r as WorkflowChatTransport, t as ReconnectToStreamOptions } from "./workflow-chat-transport-Bw-K44A5.js";
|
|
2
2
|
export { type ReconnectToStreamOptions, type SendMessagesOptions, WorkflowChatTransport, type WorkflowChatTransportOptions };
|
package/dist/client.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as WorkflowChatTransport } from "./workflow-chat-transport-
|
|
1
|
+
import { t as WorkflowChatTransport } from "./workflow-chat-transport-Dj1poviu.js";
|
|
2
2
|
export { WorkflowChatTransport };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as WorkflowChatTransportOptions, n as SendMessagesOptions, r as WorkflowChatTransport, t as ReconnectToStreamOptions } from "./workflow-chat-transport-
|
|
1
|
+
import { i as WorkflowChatTransportOptions, n as SendMessagesOptions, r as WorkflowChatTransport, t as ReconnectToStreamOptions } from "./workflow-chat-transport-Bw-K44A5.js";
|
|
2
2
|
import { Context, HasRequiredKey, InferToolContext, InferToolInput, InferToolOutput, InferToolSetContext } from "@ai-sdk/provider-utils";
|
|
3
3
|
import { ActiveTools, Experimental_LanguageModelStreamPart, Experimental_SandboxSession, FinishReason, GenerateTextOnStepEndCallback, GenerateTextResult, InferUITools, Instructions, LanguageModel, LanguageModelResponseMetadata, LanguageModelUsage, ModelMessage, Output, StepResult, StopCondition, TelemetryOptions as TelemetryOptions$1, ToolCallRepairFunction, ToolCallRepairFunction as ToolCallRepairFunction$1, ToolChoice, ToolSet, UIMessage, UIMessageChunk } from "ai";
|
|
4
4
|
import { LanguageModelV4, LanguageModelV4CallOptions, LanguageModelV4Prompt, LanguageModelV4StreamPart, SharedV4ProviderOptions } from "@ai-sdk/provider";
|
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",
|
|
@@ -424,6 +424,16 @@ function resolveToolDescription({ tool, toolName, toolsContext, experimental_san
|
|
|
424
424
|
experimental_sandbox: sandbox
|
|
425
425
|
});
|
|
426
426
|
}
|
|
427
|
+
function formatAjvError(error) {
|
|
428
|
+
const path = `data${error.instancePath}`;
|
|
429
|
+
switch (error.keyword) {
|
|
430
|
+
case "enum": return `${path} must be one of ${error.params.allowedValues.map((value) => JSON.stringify(value)).join(", ")}`;
|
|
431
|
+
case "additionalProperties": return `${path} has unexpected property ${JSON.stringify(error.params.additionalProperty)}`;
|
|
432
|
+
case "const": return `${path} must equal ${JSON.stringify(error.params.allowedValue)}`;
|
|
433
|
+
case "required": return `${path} is missing required property ${JSON.stringify(error.params.missingProperty)}`;
|
|
434
|
+
default: return `${path} ${error.message ?? "is invalid"}`;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
427
437
|
/**
|
|
428
438
|
* Reconstructs tool objects from serializable tool definitions inside a step.
|
|
429
439
|
*
|
|
@@ -433,14 +443,14 @@ function resolveToolDescription({ tool, toolName, toolsContext, experimental_san
|
|
|
433
443
|
*/
|
|
434
444
|
function resolveSerializableTools(tools) {
|
|
435
445
|
const ajvOptions = {
|
|
446
|
+
allErrors: true,
|
|
436
447
|
strict: false,
|
|
437
448
|
validateFormats: false
|
|
438
449
|
};
|
|
439
450
|
const ajv = new Ajv(ajvOptions);
|
|
440
451
|
const ajv2020 = new Ajv2020(ajvOptions);
|
|
441
452
|
const createValidatedInputSchema = (inputSchema) => {
|
|
442
|
-
const
|
|
443
|
-
const validateFn = schemaAjv.compile(inputSchema);
|
|
453
|
+
const validateFn = ((typeof inputSchema.$schema === "string" ? inputSchema.$schema.replace(/#$/, "") : void 0) === "https://json-schema.org/draft/2020-12/schema" ? ajv2020 : ajv).compile(inputSchema);
|
|
444
454
|
return jsonSchema(inputSchema, { validate: (value) => {
|
|
445
455
|
if (validateFn(value)) return {
|
|
446
456
|
success: true,
|
|
@@ -448,7 +458,7 @@ function resolveSerializableTools(tools) {
|
|
|
448
458
|
};
|
|
449
459
|
return {
|
|
450
460
|
success: false,
|
|
451
|
-
error: new Error(
|
|
461
|
+
error: new Error(validateFn.errors.map(formatAjvError).join(", "))
|
|
452
462
|
};
|
|
453
463
|
} });
|
|
454
464
|
};
|
|
@@ -494,26 +504,149 @@ function resolveSerializableTools(tools) {
|
|
|
494
504
|
}));
|
|
495
505
|
}
|
|
496
506
|
//#endregion
|
|
507
|
+
//#region src/model-call-telemetry.ts
|
|
508
|
+
const generateCallId = createIdGenerator({
|
|
509
|
+
prefix: "call",
|
|
510
|
+
size: 24
|
|
511
|
+
});
|
|
512
|
+
/**
|
|
513
|
+
* Global telemetry integrations are not visible in the workflow VM, so the
|
|
514
|
+
* workflow body sends a serializable descriptor and the model step, which
|
|
515
|
+
* runs in Node, dispatches the model call lifecycle itself.
|
|
516
|
+
*
|
|
517
|
+
* Each model call is reported as its own operation with a unique `callId`.
|
|
518
|
+
*/
|
|
519
|
+
function shouldDispatchModelCallTelemetryInStep(telemetry) {
|
|
520
|
+
return telemetry?.isEnabled !== false && telemetry?.integrations == null && globalThis.AI_SDK_TELEMETRY_INTEGRATIONS == null;
|
|
521
|
+
}
|
|
522
|
+
async function runModelCallWithTelemetry({ telemetry, modelInit, prompt, serializedTools, options, execute }) {
|
|
523
|
+
if (telemetry == null) return execute(void 0);
|
|
524
|
+
const dispatcher = createTelemetryDispatcher({ telemetry });
|
|
525
|
+
const callId = generateCallId();
|
|
526
|
+
const { provider, modelId } = typeof modelInit === "string" ? {
|
|
527
|
+
provider: "gateway",
|
|
528
|
+
modelId: modelInit
|
|
529
|
+
} : modelInit;
|
|
530
|
+
const tools = serializedTools == null ? void 0 : resolveSerializableTools(serializedTools);
|
|
531
|
+
const messages = prompt;
|
|
532
|
+
await dispatcher.onStart?.({
|
|
533
|
+
callId,
|
|
534
|
+
operationId: "ai.workflowAgent.stream",
|
|
535
|
+
provider,
|
|
536
|
+
modelId,
|
|
537
|
+
system: void 0,
|
|
538
|
+
messages,
|
|
539
|
+
tools,
|
|
540
|
+
toolChoice: options?.toolChoice,
|
|
541
|
+
activeTools: void 0,
|
|
542
|
+
maxOutputTokens: options?.maxOutputTokens,
|
|
543
|
+
temperature: options?.temperature,
|
|
544
|
+
topP: options?.topP,
|
|
545
|
+
topK: options?.topK,
|
|
546
|
+
presencePenalty: options?.presencePenalty,
|
|
547
|
+
frequencyPenalty: options?.frequencyPenalty,
|
|
548
|
+
stopSequences: options?.stopSequences,
|
|
549
|
+
seed: options?.seed,
|
|
550
|
+
maxRetries: options?.maxRetries ?? 2,
|
|
551
|
+
timeout: void 0,
|
|
552
|
+
headers: options?.headers,
|
|
553
|
+
reasoning: options?.reasoning,
|
|
554
|
+
providerOptions: options?.providerOptions,
|
|
555
|
+
output: void 0,
|
|
556
|
+
runtimeContext: {},
|
|
557
|
+
toolsContext: {}
|
|
558
|
+
});
|
|
559
|
+
await dispatcher.onStepStart?.({
|
|
560
|
+
callId,
|
|
561
|
+
provider,
|
|
562
|
+
modelId,
|
|
563
|
+
stepNumber: telemetry.stepNumber,
|
|
564
|
+
system: void 0,
|
|
565
|
+
messages,
|
|
566
|
+
tools,
|
|
567
|
+
toolChoice: options?.toolChoice,
|
|
568
|
+
activeTools: void 0,
|
|
569
|
+
steps: [],
|
|
570
|
+
providerOptions: options?.providerOptions,
|
|
571
|
+
output: void 0,
|
|
572
|
+
runtimeContext: {},
|
|
573
|
+
toolsContext: {}
|
|
574
|
+
});
|
|
575
|
+
let result;
|
|
576
|
+
try {
|
|
577
|
+
result = await execute({
|
|
578
|
+
callId,
|
|
579
|
+
onLanguageModelCallStart: dispatcher.onLanguageModelCallStart,
|
|
580
|
+
onLanguageModelCallEnd: dispatcher.onLanguageModelCallEnd,
|
|
581
|
+
executeLanguageModelCallInTelemetryContext: dispatcher.executeLanguageModelCall
|
|
582
|
+
});
|
|
583
|
+
} catch (error) {
|
|
584
|
+
await dispatcher.onError?.({
|
|
585
|
+
callId,
|
|
586
|
+
error
|
|
587
|
+
});
|
|
588
|
+
throw error;
|
|
589
|
+
}
|
|
590
|
+
if (result.aborted) {
|
|
591
|
+
await dispatcher.onAbort?.({
|
|
592
|
+
callId,
|
|
593
|
+
steps: []
|
|
594
|
+
});
|
|
595
|
+
return result;
|
|
596
|
+
}
|
|
597
|
+
if ("terminalError" in result) {
|
|
598
|
+
await dispatcher.onError?.({
|
|
599
|
+
callId,
|
|
600
|
+
error: result.terminalError
|
|
601
|
+
});
|
|
602
|
+
return result;
|
|
603
|
+
}
|
|
604
|
+
const step = await buildModelStepResult(result.raw, result.toolCalls, result.finish, result.providerExecutedToolResults, {
|
|
605
|
+
callId,
|
|
606
|
+
tools,
|
|
607
|
+
stepNumber: telemetry.stepNumber,
|
|
608
|
+
runtimeContext: {},
|
|
609
|
+
toolsContext: {}
|
|
610
|
+
});
|
|
611
|
+
await dispatcher.onStepEnd?.(step);
|
|
612
|
+
await dispatcher.onEnd?.(Object.assign(Object.create(Object.getPrototypeOf(step)), step, {
|
|
613
|
+
finalStep: step,
|
|
614
|
+
steps: [step],
|
|
615
|
+
usage: step.usage,
|
|
616
|
+
totalUsage: step.usage
|
|
617
|
+
}));
|
|
618
|
+
return result;
|
|
619
|
+
}
|
|
620
|
+
//#endregion
|
|
497
621
|
//#region src/do-generate-step.ts
|
|
498
622
|
/** A single durable provider call; orchestration and callbacks stay in the workflow. */
|
|
499
623
|
async function doGenerateStep(prompt, modelInit, serializedTools, options = {}) {
|
|
500
624
|
"use step";
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
625
|
+
return runModelCallWithTelemetry({
|
|
626
|
+
telemetry: options.telemetry,
|
|
627
|
+
modelInit,
|
|
628
|
+
prompt,
|
|
629
|
+
serializedTools,
|
|
630
|
+
options,
|
|
631
|
+
execute: async (languageModelCallTelemetry) => {
|
|
632
|
+
try {
|
|
633
|
+
return await generateModelCall(prompt, modelInit, serializedTools, options, languageModelCallTelemetry);
|
|
634
|
+
} catch (error) {
|
|
635
|
+
return {
|
|
636
|
+
toolCalls: [],
|
|
637
|
+
finish: void 0,
|
|
638
|
+
raw: {
|
|
639
|
+
content: [],
|
|
640
|
+
reasoning: []
|
|
641
|
+
},
|
|
642
|
+
providerExecutedToolResults: /* @__PURE__ */ new Map(),
|
|
643
|
+
terminalError: error
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
});
|
|
515
648
|
}
|
|
516
|
-
async function generateModelCall(prompt, modelInit, serializedTools, options) {
|
|
649
|
+
async function generateModelCall(prompt, modelInit, serializedTools, options, languageModelCallTelemetry) {
|
|
517
650
|
const remaining = options.timeoutAt == null ? void 0 : options.timeoutAt - Date.now();
|
|
518
651
|
options.abortSignal?.throwIfAborted();
|
|
519
652
|
if (remaining != null && remaining <= 0) throw new DOMException("The generation deadline expired.", "TimeoutError");
|
|
@@ -527,23 +660,49 @@ async function generateModelCall(prompt, modelInit, serializedTools, options) {
|
|
|
527
660
|
maxRetries: options.maxRetries,
|
|
528
661
|
abortSignal
|
|
529
662
|
});
|
|
663
|
+
const callId = languageModelCallTelemetry?.callId;
|
|
664
|
+
const executeLanguageModelCall = languageModelCallTelemetry?.executeLanguageModelCallInTelemetryContext ?? (({ execute }) => execute());
|
|
665
|
+
await languageModelCallTelemetry?.onLanguageModelCallStart?.({
|
|
666
|
+
callId,
|
|
667
|
+
provider: model.provider,
|
|
668
|
+
modelId: model.modelId,
|
|
669
|
+
messages: prompt,
|
|
670
|
+
tools: modelTools,
|
|
671
|
+
...settings,
|
|
672
|
+
providerOptions: options.providerOptions,
|
|
673
|
+
headers: options.headers
|
|
674
|
+
});
|
|
530
675
|
const start = Date.now();
|
|
531
676
|
const response = await retry(async () => {
|
|
532
677
|
abortSignal?.throwIfAborted();
|
|
533
678
|
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
|
-
|
|
679
|
+
return executeLanguageModelCall({
|
|
680
|
+
callId: callId ?? "",
|
|
681
|
+
execute: () => model.doGenerate({
|
|
682
|
+
...settings,
|
|
683
|
+
prompt: [...prompt],
|
|
684
|
+
tools: modelTools,
|
|
685
|
+
toolChoice,
|
|
686
|
+
responseFormat: options.responseFormat,
|
|
687
|
+
providerOptions: options.providerOptions,
|
|
688
|
+
headers: options.headers,
|
|
689
|
+
abortSignal
|
|
690
|
+
})
|
|
543
691
|
});
|
|
544
692
|
});
|
|
545
|
-
abortSignal?.throwIfAborted();
|
|
546
693
|
const responseTimeMs = Date.now() - start;
|
|
694
|
+
await languageModelCallTelemetry?.onLanguageModelCallEnd?.({
|
|
695
|
+
callId,
|
|
696
|
+
provider: model.provider,
|
|
697
|
+
modelId: response.response?.modelId ?? model.modelId,
|
|
698
|
+
finishReason: response.finishReason.unified,
|
|
699
|
+
usage: asLanguageModelUsage(response.usage),
|
|
700
|
+
content: response.content,
|
|
701
|
+
responseId: response.response?.id,
|
|
702
|
+
...response.providerMetadata != null ? { providerMetadata: response.providerMetadata } : {},
|
|
703
|
+
performance: { responseTimeMs }
|
|
704
|
+
});
|
|
705
|
+
abortSignal?.throwIfAborted();
|
|
547
706
|
const toolCalls = await Promise.all(response.content.filter((part) => part.type === "tool-call").map((toolCall) => parseToolCall({
|
|
548
707
|
toolCall,
|
|
549
708
|
tools,
|
|
@@ -627,6 +786,17 @@ doGenerateStep.maxRetries = 0;
|
|
|
627
786
|
//#region src/do-stream-step.ts
|
|
628
787
|
async function doStreamStep(conversationPrompt, modelInit, writable, serializedTools, options) {
|
|
629
788
|
"use step";
|
|
789
|
+
return runModelCallWithTelemetry({
|
|
790
|
+
telemetry: options?.telemetry,
|
|
791
|
+
modelInit,
|
|
792
|
+
prompt: conversationPrompt,
|
|
793
|
+
serializedTools,
|
|
794
|
+
options,
|
|
795
|
+
execute: (languageModelCallTelemetry) => streamModelStep(conversationPrompt, modelInit, writable, serializedTools, options, languageModelCallTelemetry)
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
doStreamStep.maxRetries = 0;
|
|
799
|
+
async function streamModelStep(conversationPrompt, modelInit, writable, serializedTools, options, languageModelCallTelemetry) {
|
|
630
800
|
const timeout = options?.timeoutAt == null ? void 0 : options.timeoutAt - Date.now();
|
|
631
801
|
if (options?.abortSignal?.aborted || timeout != null && timeout <= 0) return { aborted: true };
|
|
632
802
|
const abortSignal = timeout == null ? options?.abortSignal : options?.abortSignal == null ? AbortSignal.timeout(timeout) : AbortSignal.any([options.abortSignal, AbortSignal.timeout(timeout)]);
|
|
@@ -691,7 +861,8 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
|
|
|
691
861
|
frequencyPenalty: options?.frequencyPenalty,
|
|
692
862
|
stopSequences: options?.stopSequences,
|
|
693
863
|
seed: options?.seed,
|
|
694
|
-
repairToolCall: options?.repairToolCall
|
|
864
|
+
repairToolCall: options?.repairToolCall,
|
|
865
|
+
...languageModelCallTelemetry
|
|
695
866
|
}));
|
|
696
867
|
return stream;
|
|
697
868
|
} catch (error) {
|
|
@@ -712,11 +883,13 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
|
|
|
712
883
|
let performance;
|
|
713
884
|
let terminalError;
|
|
714
885
|
let hasTerminalError = false;
|
|
886
|
+
let hasReceivedOutputChunk = false;
|
|
715
887
|
const ongoingToolCallToolNames = /* @__PURE__ */ new Map();
|
|
716
888
|
const writer = writable?.getWriter();
|
|
717
889
|
try {
|
|
718
890
|
await writer?.write({ type: "reset-step" });
|
|
719
891
|
for await (const part of modelStream) {
|
|
892
|
+
if (isOutputChunk(part)) hasReceivedOutputChunk = true;
|
|
720
893
|
switch (part.type) {
|
|
721
894
|
case "tool-input-start":
|
|
722
895
|
ongoingToolCallToolNames.set(part.id, part.toolName);
|
|
@@ -902,6 +1075,10 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
|
|
|
902
1075
|
writer?.releaseLock();
|
|
903
1076
|
}
|
|
904
1077
|
if (abortSignal?.aborted || options?.timeoutAt != null && options.timeoutAt <= Date.now()) return { aborted: true };
|
|
1078
|
+
if (finish == null && !hasReceivedOutputChunk && !hasTerminalError) {
|
|
1079
|
+
terminalError = new NoOutputGeneratedError({ message: "No output generated. The model stream ended without a finish chunk." });
|
|
1080
|
+
hasTerminalError = true;
|
|
1081
|
+
}
|
|
905
1082
|
return {
|
|
906
1083
|
toolCalls,
|
|
907
1084
|
finish,
|
|
@@ -917,7 +1094,6 @@ async function doStreamStep(conversationPrompt, modelInit, writable, serializedT
|
|
|
917
1094
|
...hasTerminalError ? { terminalError } : {}
|
|
918
1095
|
};
|
|
919
1096
|
}
|
|
920
|
-
doStreamStep.maxRetries = 0;
|
|
921
1097
|
function applyStreamTransforms({ stream, transforms, tools }) {
|
|
922
1098
|
const sourceReader = stream.getReader();
|
|
923
1099
|
let stopped = false;
|
|
@@ -1032,6 +1208,7 @@ async function* modelCallIterator({ prompt, mode = "stream", include, initialIns
|
|
|
1032
1208
|
includeRuntimeContext: telemetry?.includeRuntimeContext,
|
|
1033
1209
|
includeToolsContext: telemetry?.includeToolsContext
|
|
1034
1210
|
});
|
|
1211
|
+
const dispatchTelemetryInStep = shouldDispatchModelCallTelemetryInStep(telemetry);
|
|
1035
1212
|
while (!done) {
|
|
1036
1213
|
if (currentGenerationSettings.abortSignal?.aborted) {
|
|
1037
1214
|
if (mode === "generate") currentGenerationSettings.abortSignal.throwIfAborted();
|
|
@@ -1135,7 +1312,13 @@ async function* modelCallIterator({ prompt, mode = "stream", include, initialIns
|
|
|
1135
1312
|
repairToolCall,
|
|
1136
1313
|
responseFormat,
|
|
1137
1314
|
include,
|
|
1138
|
-
experimental_transform
|
|
1315
|
+
experimental_transform,
|
|
1316
|
+
telemetry: dispatchTelemetryInStep ? {
|
|
1317
|
+
functionId: telemetry?.functionId,
|
|
1318
|
+
recordInputs: telemetry?.recordInputs,
|
|
1319
|
+
recordOutputs: telemetry?.recordOutputs,
|
|
1320
|
+
stepNumber
|
|
1321
|
+
} : void 0
|
|
1139
1322
|
};
|
|
1140
1323
|
const modelCallResult = mode === "generate" ? await doGenerateStep(conversationPrompt, currentModel, serializedTools, callOptions) : await doStreamStep(conversationPrompt, currentModel, writable, serializedTools, callOptions);
|
|
1141
1324
|
if (modelCallResult.aborted) {
|
|
@@ -1182,10 +1365,10 @@ async function* modelCallIterator({ prompt, mode = "stream", include, initialIns
|
|
|
1182
1365
|
const isToolExecutionAllowed = finishReason === "tool-calls" || finishReason === "stop";
|
|
1183
1366
|
for (const toolCall of toolCalls) if (toolCall.providerExecuted && serializedTools[toolCall.toolName]?.supportsDeferredResults && !providerExecutedToolResults.has(toolCall.toolCallId)) pendingDeferredToolCallIds.add(toolCall.toolCallId);
|
|
1184
1367
|
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) {
|
|
1368
|
+
const shouldProcessTools = isToolExecutionAllowed && (toolCalls.length > 0 || providerExecutedToolResults.size > 0) || finishReason === "length" && providerExecutedToolResults.size > 0;
|
|
1369
|
+
if (!hasTerminalError && shouldProcessTools) {
|
|
1188
1370
|
lastStepWasYielded = true;
|
|
1371
|
+
const processableToolCalls = isToolExecutionAllowed ? toolCalls : toolCalls.filter((toolCall) => !toolCall.providerExecuted && toolCall.invalid || toolCall.providerExecuted && providerExecutedToolResults.has(toolCall.toolCallId));
|
|
1189
1372
|
const { content: assistantContent, providerExecutedToolResultPositions } = getAssistantMessageContent(step, mode);
|
|
1190
1373
|
const includedToolCallIds = new Set(assistantContent.flatMap((part) => part.type === "tool-call" ? [part.toolCallId] : []));
|
|
1191
1374
|
conversationPrompt.push({
|
|
@@ -1193,7 +1376,7 @@ async function* modelCallIterator({ prompt, mode = "stream", include, initialIns
|
|
|
1193
1376
|
content: [...assistantContent, ...toolCalls.filter((toolCall) => !includedToolCallIds.has(toolCall.toolCallId)).map(toAssistantToolCallContent)]
|
|
1194
1377
|
});
|
|
1195
1378
|
const toolResults = yield {
|
|
1196
|
-
toolCalls,
|
|
1379
|
+
toolCalls: processableToolCalls,
|
|
1197
1380
|
tools: effectiveTools,
|
|
1198
1381
|
messages: conversationPrompt,
|
|
1199
1382
|
step,
|
|
@@ -1206,14 +1389,14 @@ async function* modelCallIterator({ prompt, mode = "stream", include, initialIns
|
|
|
1206
1389
|
const responseMessages = addToolResultsToConversation({
|
|
1207
1390
|
messages: conversationPrompt,
|
|
1208
1391
|
toolResults,
|
|
1209
|
-
providerExecutedToolCallIds: /* @__PURE__ */ new Set([...
|
|
1392
|
+
providerExecutedToolCallIds: /* @__PURE__ */ new Set([...processableToolCalls.flatMap((toolCall) => toolCall.providerExecuted ? [toolCall.toolCallId] : []), ...providerExecutedToolResults.keys()]),
|
|
1210
1393
|
providerExecutedToolResultPositions
|
|
1211
1394
|
});
|
|
1212
1395
|
step.response.messages.push(...mode === "generate" ? toModelResponseMessages(responseMessages) : responseMessages);
|
|
1213
1396
|
const stopConditionMet = (stopConditions == null ? [] : Array.isArray(stopConditions) ? stopConditions : [stopConditions]).some((test) => test({ steps }));
|
|
1214
1397
|
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") {
|
|
1398
|
+
done = !isToolExecutionAllowed || stopConditionMet || !hasClientToolCalls && pendingDeferredToolCallIds.size === 0;
|
|
1399
|
+
} else if (hasTerminalError || mode === "generate" || finishReason === "stop" || finishReason === "tool-calls" || finishReason === "length" || finishReason === "content-filter" || finishReason === "error" || finishReason === "other" || finishReason === "unknown" || !finishReason) {
|
|
1217
1400
|
const { content: assistantContent } = getAssistantMessageContent(step, mode);
|
|
1218
1401
|
if (assistantContent.length > 0) {
|
|
1219
1402
|
const assistantMessage = {
|
|
@@ -1224,12 +1407,7 @@ async function* modelCallIterator({ prompt, mode = "stream", include, initialIns
|
|
|
1224
1407
|
step.response.messages.push(...mode === "generate" ? toModelResponseMessages([assistantMessage]) : [assistantMessage]);
|
|
1225
1408
|
}
|
|
1226
1409
|
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}`);
|
|
1410
|
+
} else throw new Error(`Unexpected finish reason: ${typeof finish?.finishReason === "object" ? JSON.stringify(finish?.finishReason) : finish?.finishReason}`);
|
|
1233
1411
|
const resolvedOnStepEnd = onStepEnd ?? onStepFinish;
|
|
1234
1412
|
if (resolvedOnStepEnd) await resolvedOnStepEnd(step);
|
|
1235
1413
|
await telemetryDispatcher.onStepEnd?.(normalizeStepForTelemetry$1(step));
|