@ai-sdk/workflow 2.0.27 → 2.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/index.js +291 -64
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/add-tool-results-to-conversation.ts +108 -0
- package/src/do-stream-step.ts +18 -0
- package/src/stream-text-iterator.ts +157 -34
- package/src/workflow-agent.ts +105 -39
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/workflow",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.29",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "WorkflowAgent for building AI agents with AI SDK",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ai-sdk/provider": "4.0.
|
|
35
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
36
|
-
"ai": "7.0.
|
|
34
|
+
"@ai-sdk/provider": "4.0.14",
|
|
35
|
+
"@ai-sdk/provider-utils": "5.0.40",
|
|
36
|
+
"ai": "7.0.98",
|
|
37
37
|
"ajv": "^8.20.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
LanguageModelV4Prompt,
|
|
3
|
+
LanguageModelV4ToolResultPart,
|
|
4
|
+
} from '@ai-sdk/provider';
|
|
5
|
+
|
|
6
|
+
export interface ProviderExecutedToolResultPosition {
|
|
7
|
+
toolCallId: string;
|
|
8
|
+
contentIndex: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function addToolResultsToConversation({
|
|
12
|
+
messages,
|
|
13
|
+
toolResults,
|
|
14
|
+
providerExecutedToolCallIds,
|
|
15
|
+
providerExecutedToolResultPositions = [],
|
|
16
|
+
}: {
|
|
17
|
+
messages: LanguageModelV4Prompt;
|
|
18
|
+
toolResults: LanguageModelV4ToolResultPart[];
|
|
19
|
+
providerExecutedToolCallIds: Set<string>;
|
|
20
|
+
providerExecutedToolResultPositions?: ProviderExecutedToolResultPosition[];
|
|
21
|
+
}) {
|
|
22
|
+
const providerResultIds = new Set([
|
|
23
|
+
...providerExecutedToolCallIds,
|
|
24
|
+
...providerExecutedToolResultPositions.map(position => position.toolCallId),
|
|
25
|
+
]);
|
|
26
|
+
const providerResults = new Map<string, LanguageModelV4ToolResultPart[]>();
|
|
27
|
+
const clientResults: LanguageModelV4ToolResultPart[] = [];
|
|
28
|
+
let assistantMessageIndex = -1;
|
|
29
|
+
let assistantMessage:
|
|
30
|
+
| Extract<LanguageModelV4Prompt[number], { role: 'assistant' }>
|
|
31
|
+
| undefined;
|
|
32
|
+
|
|
33
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
34
|
+
const message = messages[index];
|
|
35
|
+
if (message.role === 'assistant') {
|
|
36
|
+
assistantMessageIndex = index;
|
|
37
|
+
assistantMessage = message;
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (const toolResult of toolResults) {
|
|
43
|
+
if (providerResultIds.has(toolResult.toolCallId)) {
|
|
44
|
+
const results = providerResults.get(toolResult.toolCallId) ?? [];
|
|
45
|
+
results.push(toolResult);
|
|
46
|
+
providerResults.set(toolResult.toolCallId, results);
|
|
47
|
+
} else {
|
|
48
|
+
clientResults.push(toolResult);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (providerResults.size > 0) {
|
|
53
|
+
if (assistantMessage != null) {
|
|
54
|
+
let content = [...assistantMessage.content];
|
|
55
|
+
|
|
56
|
+
for (const position of [...providerExecutedToolResultPositions].sort(
|
|
57
|
+
(a, b) => a.contentIndex - b.contentIndex,
|
|
58
|
+
)) {
|
|
59
|
+
const results = providerResults.get(position.toolCallId);
|
|
60
|
+
if (results == null || results.length === 0) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const [result, ...remainingResults] = results;
|
|
65
|
+
content.splice(position.contentIndex, 0, result);
|
|
66
|
+
|
|
67
|
+
if (remainingResults.length === 0) {
|
|
68
|
+
providerResults.delete(position.toolCallId);
|
|
69
|
+
} else {
|
|
70
|
+
providerResults.set(position.toolCallId, remainingResults);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const contentWithFallbackResults: typeof assistantMessage.content = [];
|
|
75
|
+
|
|
76
|
+
for (const part of content) {
|
|
77
|
+
contentWithFallbackResults.push(part);
|
|
78
|
+
|
|
79
|
+
if (part.type !== 'tool-call') {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const results = providerResults.get(part.toolCallId);
|
|
84
|
+
if (results == null) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
providerResults.delete(part.toolCallId);
|
|
89
|
+
contentWithFallbackResults.push(...results);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (const results of providerResults.values()) {
|
|
93
|
+
contentWithFallbackResults.push(...results);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
assistantMessage.content = contentWithFallbackResults;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (clientResults.length > 0) {
|
|
101
|
+
messages.push({
|
|
102
|
+
role: 'tool',
|
|
103
|
+
content: clientResults,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return assistantMessageIndex < 0 ? [] : messages.slice(assistantMessageIndex);
|
|
108
|
+
}
|
package/src/do-stream-step.ts
CHANGED
|
@@ -46,6 +46,8 @@ export interface ProviderExecutedToolResult {
|
|
|
46
46
|
toolName: string;
|
|
47
47
|
result: unknown;
|
|
48
48
|
isError?: boolean;
|
|
49
|
+
dynamic?: boolean;
|
|
50
|
+
providerMetadata?: SharedV4ProviderMetadata;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
/**
|
|
@@ -115,6 +117,10 @@ export type DoStreamStepRawContentPart =
|
|
|
115
117
|
| {
|
|
116
118
|
type: 'tool-call';
|
|
117
119
|
toolCallIndex: number;
|
|
120
|
+
}
|
|
121
|
+
| {
|
|
122
|
+
type: 'provider-tool-result';
|
|
123
|
+
toolCallId: string;
|
|
118
124
|
};
|
|
119
125
|
|
|
120
126
|
/**
|
|
@@ -407,6 +413,12 @@ export async function doStreamStep(
|
|
|
407
413
|
toolName: part.toolName,
|
|
408
414
|
result: part.output,
|
|
409
415
|
isError: false,
|
|
416
|
+
dynamic: part.dynamic,
|
|
417
|
+
providerMetadata: part.providerMetadata,
|
|
418
|
+
});
|
|
419
|
+
content.push({
|
|
420
|
+
type: 'provider-tool-result',
|
|
421
|
+
toolCallId: part.toolCallId,
|
|
410
422
|
});
|
|
411
423
|
}
|
|
412
424
|
break;
|
|
@@ -420,6 +432,12 @@ export async function doStreamStep(
|
|
|
420
432
|
toolName: errorPart.toolName,
|
|
421
433
|
result: errorPart.error,
|
|
422
434
|
isError: true,
|
|
435
|
+
dynamic: errorPart.dynamic,
|
|
436
|
+
providerMetadata: errorPart.providerMetadata,
|
|
437
|
+
});
|
|
438
|
+
content.push({
|
|
439
|
+
type: 'provider-tool-result',
|
|
440
|
+
toolCallId: errorPart.toolCallId,
|
|
423
441
|
});
|
|
424
442
|
}
|
|
425
443
|
break;
|
|
@@ -30,6 +30,10 @@ import {
|
|
|
30
30
|
type StreamFinish,
|
|
31
31
|
type ToolInputLifecycleEvent,
|
|
32
32
|
} from './do-stream-step.js';
|
|
33
|
+
import {
|
|
34
|
+
addToolResultsToConversation,
|
|
35
|
+
type ProviderExecutedToolResultPosition,
|
|
36
|
+
} from './add-tool-results-to-conversation.js';
|
|
33
37
|
import { resolveToolContext } from './resolve-tool-context.js';
|
|
34
38
|
import { serializeToolSet } from './serializable-schema.js';
|
|
35
39
|
import type {
|
|
@@ -92,6 +96,8 @@ export interface StreamTextIteratorYieldValue {
|
|
|
92
96
|
toolsContext?: Record<string, Context | undefined>;
|
|
93
97
|
/** Provider-executed tool results (keyed by tool call ID) */
|
|
94
98
|
providerExecutedToolResults?: Map<string, ProviderExecutedToolResult>;
|
|
99
|
+
/** Original positions of provider-executed results in assistant content. */
|
|
100
|
+
providerExecutedToolResultPositions?: ProviderExecutedToolResultPosition[];
|
|
95
101
|
/** The sandbox selected for the current step. */
|
|
96
102
|
experimental_sandbox?: SandboxSession;
|
|
97
103
|
}
|
|
@@ -175,7 +181,8 @@ export async function* streamTextIterator({
|
|
|
175
181
|
let _isFirstIteration = true;
|
|
176
182
|
let stepNumber = 0;
|
|
177
183
|
let lastStep: StepResult<any, any> | undefined;
|
|
178
|
-
let
|
|
184
|
+
let lastStepWasYielded = false;
|
|
185
|
+
const pendingDeferredToolCallIds = new Set<string>();
|
|
179
186
|
let wasAborted = false;
|
|
180
187
|
let terminalError: unknown;
|
|
181
188
|
let hasTerminalError = false;
|
|
@@ -385,11 +392,17 @@ export async function* streamTextIterator({
|
|
|
385
392
|
// Reconstruct the full StepResult outside the step boundary so the
|
|
386
393
|
// durable event log doesn't carry StepResult's redundant copies (or the
|
|
387
394
|
// per-chunk snapshot the step used to return).
|
|
388
|
-
const step = buildStepResult(
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
395
|
+
const step = buildStepResult(
|
|
396
|
+
raw,
|
|
397
|
+
toolCalls,
|
|
398
|
+
finish,
|
|
399
|
+
providerExecutedToolResults,
|
|
400
|
+
{
|
|
401
|
+
stepNumber,
|
|
402
|
+
runtimeContext: currentRuntimeContext,
|
|
403
|
+
toolsContext: currentToolsContext,
|
|
404
|
+
},
|
|
405
|
+
);
|
|
393
406
|
|
|
394
407
|
await telemetryDispatcher.onLanguageModelCallEnd?.({
|
|
395
408
|
callId: step.callId,
|
|
@@ -408,19 +421,41 @@ export async function* streamTextIterator({
|
|
|
408
421
|
stepNumber++;
|
|
409
422
|
steps.push(step);
|
|
410
423
|
lastStep = step;
|
|
411
|
-
|
|
424
|
+
lastStepWasYielded = false;
|
|
412
425
|
|
|
413
426
|
const finishReason = finish?.finishReason;
|
|
427
|
+
const isToolExecutionAllowed =
|
|
428
|
+
finishReason === 'tool-calls' || finishReason === 'stop';
|
|
429
|
+
|
|
430
|
+
for (const toolCall of toolCalls) {
|
|
431
|
+
if (
|
|
432
|
+
toolCall.providerExecuted &&
|
|
433
|
+
serializedTools[toolCall.toolName]?.supportsDeferredResults &&
|
|
434
|
+
!providerExecutedToolResults.has(toolCall.toolCallId)
|
|
435
|
+
) {
|
|
436
|
+
pendingDeferredToolCallIds.add(toolCall.toolCallId);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
for (const toolCallId of providerExecutedToolResults.keys()) {
|
|
440
|
+
pendingDeferredToolCallIds.delete(toolCallId);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const shouldProcessTools =
|
|
444
|
+
isToolExecutionAllowed &&
|
|
445
|
+
(toolCalls.length > 0 || providerExecutedToolResults.size > 0);
|
|
414
446
|
|
|
415
447
|
if (hasTerminalError) {
|
|
416
448
|
// The error crossed the durable step boundary as data. End the loop
|
|
417
449
|
// without throwing so WorkflowAgent can preserve the existing
|
|
418
450
|
// resolved-result contract and expose the original value.
|
|
419
451
|
done = true;
|
|
420
|
-
} else if (
|
|
421
|
-
|
|
452
|
+
} else if (shouldProcessTools) {
|
|
453
|
+
lastStepWasYielded = true;
|
|
422
454
|
|
|
423
|
-
const
|
|
455
|
+
const {
|
|
456
|
+
content: assistantContent,
|
|
457
|
+
providerExecutedToolResultPositions,
|
|
458
|
+
} = getAssistantMessageContent(step);
|
|
424
459
|
const includedToolCallIds = new Set(
|
|
425
460
|
assistantContent.flatMap(part =>
|
|
426
461
|
part.type === 'tool-call' ? [part.toolCallId] : [],
|
|
@@ -455,30 +490,53 @@ export async function* streamTextIterator({
|
|
|
455
490
|
toolsContext: currentToolsContext,
|
|
456
491
|
experimental_sandbox: stepSandbox,
|
|
457
492
|
providerExecutedToolResults,
|
|
493
|
+
providerExecutedToolResultPositions,
|
|
458
494
|
};
|
|
459
495
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
496
|
+
const responseMessages = addToolResultsToConversation({
|
|
497
|
+
messages: conversationPrompt,
|
|
498
|
+
toolResults,
|
|
499
|
+
providerExecutedToolCallIds: new Set([
|
|
500
|
+
...toolCalls.flatMap(toolCall =>
|
|
501
|
+
toolCall.providerExecuted ? [toolCall.toolCallId] : [],
|
|
502
|
+
),
|
|
503
|
+
...providerExecutedToolResults.keys(),
|
|
504
|
+
]),
|
|
505
|
+
providerExecutedToolResultPositions,
|
|
463
506
|
});
|
|
507
|
+
step.response.messages.push(
|
|
508
|
+
...(responseMessages as unknown as typeof step.response.messages),
|
|
509
|
+
);
|
|
464
510
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
?
|
|
468
|
-
:
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
511
|
+
const stopConditionList =
|
|
512
|
+
stopConditions == null
|
|
513
|
+
? []
|
|
514
|
+
: Array.isArray(stopConditions)
|
|
515
|
+
? stopConditions
|
|
516
|
+
: [stopConditions];
|
|
517
|
+
const stopConditionMet = stopConditionList.some(test =>
|
|
518
|
+
test({ steps }),
|
|
519
|
+
);
|
|
520
|
+
const hasClientToolCalls = toolCalls.some(
|
|
521
|
+
toolCall => !toolCall.providerExecuted,
|
|
522
|
+
);
|
|
523
|
+
|
|
524
|
+
done =
|
|
525
|
+
stopConditionMet ||
|
|
526
|
+
(!hasClientToolCalls && pendingDeferredToolCallIds.size === 0);
|
|
527
|
+
} else if (finishReason === 'stop' || finishReason === 'tool-calls') {
|
|
474
528
|
// Add assistant response content to the conversation
|
|
475
|
-
const assistantContent = getAssistantMessageContent(step);
|
|
529
|
+
const { content: assistantContent } = getAssistantMessageContent(step);
|
|
476
530
|
|
|
477
531
|
if (assistantContent.length > 0) {
|
|
478
|
-
|
|
532
|
+
const assistantMessage = {
|
|
479
533
|
role: 'assistant',
|
|
480
534
|
content: assistantContent,
|
|
481
|
-
}
|
|
535
|
+
} as const;
|
|
536
|
+
conversationPrompt.push(assistantMessage);
|
|
537
|
+
step.response.messages.push(
|
|
538
|
+
assistantMessage as unknown as (typeof step.response.messages)[number],
|
|
539
|
+
);
|
|
482
540
|
}
|
|
483
541
|
|
|
484
542
|
done = true;
|
|
@@ -519,8 +577,8 @@ export async function* streamTextIterator({
|
|
|
519
577
|
}
|
|
520
578
|
}
|
|
521
579
|
|
|
522
|
-
// Yield the final step if it wasn't already yielded
|
|
523
|
-
if (lastStep && !
|
|
580
|
+
// Yield the final step if it wasn't already yielded inside the loop.
|
|
581
|
+
if (lastStep && !lastStepWasYielded) {
|
|
524
582
|
yield {
|
|
525
583
|
toolCalls: [],
|
|
526
584
|
messages: conversationPrompt,
|
|
@@ -653,6 +711,7 @@ function buildStepResult(
|
|
|
653
711
|
raw: DoStreamStepRawResult,
|
|
654
712
|
toolCalls: ParsedToolCall[],
|
|
655
713
|
finish: StreamFinish | undefined,
|
|
714
|
+
providerExecutedToolResults: Map<string, ProviderExecutedToolResult>,
|
|
656
715
|
opts: {
|
|
657
716
|
stepNumber: number;
|
|
658
717
|
runtimeContext: Context;
|
|
@@ -740,9 +799,53 @@ function buildStepResult(
|
|
|
740
799
|
}
|
|
741
800
|
break;
|
|
742
801
|
}
|
|
802
|
+
case 'provider-tool-result': {
|
|
803
|
+
const result = providerExecutedToolResults.get(part.toolCallId);
|
|
804
|
+
if (result == null) {
|
|
805
|
+
break;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
const toolCall = toolCalls.find(
|
|
809
|
+
toolCall => toolCall.toolCallId === result.toolCallId,
|
|
810
|
+
);
|
|
811
|
+
const common = {
|
|
812
|
+
toolCallId: result.toolCallId,
|
|
813
|
+
toolName: result.toolName,
|
|
814
|
+
input: toolCall?.input,
|
|
815
|
+
providerExecuted: true as const,
|
|
816
|
+
...(result.dynamic === true || toolCall?.dynamic === true
|
|
817
|
+
? { dynamic: true as const }
|
|
818
|
+
: {}),
|
|
819
|
+
...(result.providerMetadata != null
|
|
820
|
+
? { providerMetadata: result.providerMetadata }
|
|
821
|
+
: {}),
|
|
822
|
+
...(toolCall?.toolMetadata != null
|
|
823
|
+
? { toolMetadata: toolCall.toolMetadata }
|
|
824
|
+
: {}),
|
|
825
|
+
};
|
|
826
|
+
|
|
827
|
+
content.push(
|
|
828
|
+
result.isError
|
|
829
|
+
? {
|
|
830
|
+
type: 'tool-error',
|
|
831
|
+
...common,
|
|
832
|
+
error: result.result,
|
|
833
|
+
}
|
|
834
|
+
: {
|
|
835
|
+
type: 'tool-result',
|
|
836
|
+
...common,
|
|
837
|
+
output: result.result,
|
|
838
|
+
},
|
|
839
|
+
);
|
|
840
|
+
break;
|
|
841
|
+
}
|
|
743
842
|
}
|
|
744
843
|
}
|
|
745
844
|
|
|
845
|
+
const toolResults = content.filter(
|
|
846
|
+
part => part.type === 'tool-result',
|
|
847
|
+
) as StepResult<ToolSet, any>['toolResults'];
|
|
848
|
+
|
|
746
849
|
return {
|
|
747
850
|
callId: 'workflow-agent',
|
|
748
851
|
stepNumber: opts.stepNumber,
|
|
@@ -766,9 +869,9 @@ function buildStepResult(
|
|
|
766
869
|
toolCalls: validToolCalls,
|
|
767
870
|
staticToolCalls: validToolCalls.filter(tc => tc.dynamic !== true),
|
|
768
871
|
dynamicToolCalls: validToolCalls.filter(tc => tc.dynamic),
|
|
769
|
-
toolResults
|
|
770
|
-
staticToolResults:
|
|
771
|
-
dynamicToolResults:
|
|
872
|
+
toolResults,
|
|
873
|
+
staticToolResults: toolResults.filter(result => result.dynamic !== true),
|
|
874
|
+
dynamicToolResults: toolResults.filter(result => result.dynamic === true),
|
|
772
875
|
finishReason: finish?.finishReason ?? 'other',
|
|
773
876
|
rawFinishReason: finish?.rawFinishReason,
|
|
774
877
|
usage:
|
|
@@ -812,19 +915,27 @@ function buildStepResult(
|
|
|
812
915
|
} as StepResult<ToolSet, any>;
|
|
813
916
|
}
|
|
814
917
|
|
|
815
|
-
function getAssistantMessageContent(
|
|
816
|
-
|
|
817
|
-
|
|
918
|
+
function getAssistantMessageContent(step: StepResult<any, any>): {
|
|
919
|
+
content: Extract<
|
|
920
|
+
LanguageModelV4Prompt[number],
|
|
921
|
+
{ role: 'assistant' }
|
|
922
|
+
>['content'];
|
|
923
|
+
providerExecutedToolResultPositions: ProviderExecutedToolResultPosition[];
|
|
924
|
+
} {
|
|
818
925
|
const content: Extract<
|
|
819
926
|
LanguageModelV4Prompt[number],
|
|
820
927
|
{ role: 'assistant' }
|
|
821
928
|
>['content'] = [];
|
|
929
|
+
const providerExecutedToolResultPositions: ProviderExecutedToolResultPosition[] =
|
|
930
|
+
[];
|
|
931
|
+
let contentIndex = 0;
|
|
822
932
|
|
|
823
933
|
for (const part of step.content) {
|
|
824
934
|
switch (part.type) {
|
|
825
935
|
case 'text':
|
|
826
936
|
if (part.text.length > 0) {
|
|
827
937
|
content.push({ type: 'text', text: part.text });
|
|
938
|
+
contentIndex++;
|
|
828
939
|
}
|
|
829
940
|
break;
|
|
830
941
|
case 'file':
|
|
@@ -839,14 +950,26 @@ function getAssistantMessageContent(
|
|
|
839
950
|
}
|
|
840
951
|
: {}),
|
|
841
952
|
});
|
|
953
|
+
contentIndex++;
|
|
842
954
|
break;
|
|
843
955
|
case 'tool-call':
|
|
844
956
|
content.push(toAssistantToolCallContent(part));
|
|
957
|
+
contentIndex++;
|
|
958
|
+
break;
|
|
959
|
+
case 'tool-result':
|
|
960
|
+
case 'tool-error':
|
|
961
|
+
if (part.providerExecuted) {
|
|
962
|
+
providerExecutedToolResultPositions.push({
|
|
963
|
+
toolCallId: part.toolCallId,
|
|
964
|
+
contentIndex,
|
|
965
|
+
});
|
|
966
|
+
contentIndex++;
|
|
967
|
+
}
|
|
845
968
|
break;
|
|
846
969
|
}
|
|
847
970
|
}
|
|
848
971
|
|
|
849
|
-
return content;
|
|
972
|
+
return { content, providerExecutedToolResultPositions };
|
|
850
973
|
}
|
|
851
974
|
|
|
852
975
|
function toAssistantToolCallContent(toolCall: {
|