@ai-sdk/harness 1.0.39 → 1.0.41
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 +19 -0
- package/dist/agent/index.d.ts +19 -4
- package/dist/agent/index.js +200 -104
- package/dist/agent/index.js.map +1 -1
- package/dist/bridge/index.js +8 -1
- package/dist/bridge/index.js.map +1 -1
- package/dist/utils/index.d.ts +5 -1
- package/dist/utils/index.js +37 -5
- package/dist/utils/index.js.map +1 -1
- package/package.json +2 -2
- package/src/agent/harness-agent-session.ts +38 -8
- package/src/agent/harness-agent-settings.ts +25 -1
- package/src/agent/harness-agent.ts +17 -2
- package/src/agent/internal/run-prompt.ts +110 -38
- package/src/agent/internal/turn-telemetry.ts +60 -46
- package/src/bridge/index.ts +11 -1
- package/src/utils/sandbox-channel.ts +61 -3
|
@@ -9,10 +9,17 @@ import type {
|
|
|
9
9
|
HarnessAgentSkill,
|
|
10
10
|
} from './harness-agent-types';
|
|
11
11
|
import type {
|
|
12
|
+
Arrayable,
|
|
13
|
+
Context,
|
|
12
14
|
Experimental_SandboxSession as SandboxSession,
|
|
13
15
|
ToolSet,
|
|
14
16
|
} from '@ai-sdk/provider-utils';
|
|
15
|
-
import type {
|
|
17
|
+
import type {
|
|
18
|
+
ActiveTools,
|
|
19
|
+
StopCondition,
|
|
20
|
+
TelemetryOptions,
|
|
21
|
+
ToolApprovalStatus,
|
|
22
|
+
} from 'ai';
|
|
16
23
|
import type { HarnessAllTools } from './harness-agent-tool-types';
|
|
17
24
|
|
|
18
25
|
export type HarnessAgentToolApprovalConfiguration = Readonly<
|
|
@@ -91,6 +98,7 @@ type HarnessAgentToolFilteringSettings<TOOLS extends ToolSet> =
|
|
|
91
98
|
export type HarnessAgentSettings<
|
|
92
99
|
THarness extends HarnessAgentAdapter<any> = HarnessAgentAdapter,
|
|
93
100
|
TUserTools extends ToolSet = {},
|
|
101
|
+
RUNTIME_CONTEXT extends Context = Context,
|
|
94
102
|
> = {
|
|
95
103
|
/**
|
|
96
104
|
* The harness adapter driving the underlying agent runtime. Its
|
|
@@ -130,6 +138,22 @@ export type HarnessAgentSettings<
|
|
|
130
138
|
*/
|
|
131
139
|
readonly instructions?: string;
|
|
132
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Conditions that stop the current result after a completed harness tool
|
|
143
|
+
* step that can continue into another model step. The underlying turn remains
|
|
144
|
+
* unfinished and can be suspended and continued.
|
|
145
|
+
*
|
|
146
|
+
* A terminal text-only step finishes naturally and is not stopped early.
|
|
147
|
+
*
|
|
148
|
+
* When omitted, the harness runs until the turn naturally finishes or pauses.
|
|
149
|
+
*/
|
|
150
|
+
readonly stopWhen?: Arrayable<
|
|
151
|
+
StopCondition<
|
|
152
|
+
NoInfer<HarnessAllTools<THarness, TUserTools>>,
|
|
153
|
+
RUNTIME_CONTEXT
|
|
154
|
+
>
|
|
155
|
+
>;
|
|
156
|
+
|
|
133
157
|
/**
|
|
134
158
|
* Built-in tool permission mode. Defaults to `'allow-all'`, preserving the
|
|
135
159
|
* existing bypass-permissions behavior unless users opt in.
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
HarnessV1SandboxProvider,
|
|
7
7
|
} from '../v1';
|
|
8
8
|
import {
|
|
9
|
+
asArray,
|
|
9
10
|
asSchema,
|
|
10
11
|
generateId,
|
|
11
12
|
type Context,
|
|
@@ -19,6 +20,7 @@ import type {
|
|
|
19
20
|
GenerateTextResult,
|
|
20
21
|
ReasoningFileOutput,
|
|
21
22
|
ReasoningOutput,
|
|
23
|
+
StopCondition,
|
|
22
24
|
StreamTextResult,
|
|
23
25
|
} from 'ai';
|
|
24
26
|
import type {
|
|
@@ -133,7 +135,14 @@ export class HarnessAgent<
|
|
|
133
135
|
*/
|
|
134
136
|
readonly tools: HarnessAllTools<THarness, TUserTools>;
|
|
135
137
|
|
|
136
|
-
private readonly settings: HarnessAgentSettings<
|
|
138
|
+
private readonly settings: HarnessAgentSettings<
|
|
139
|
+
THarness,
|
|
140
|
+
TUserTools,
|
|
141
|
+
RUNTIME_CONTEXT
|
|
142
|
+
>;
|
|
143
|
+
private readonly stopConditions: Array<
|
|
144
|
+
StopCondition<HarnessAllTools<THarness, TUserTools>, RUNTIME_CONTEXT>
|
|
145
|
+
>;
|
|
137
146
|
private readonly sandboxConfig: HarnessAgentSandboxConfig;
|
|
138
147
|
private readonly activeUserTools: TUserTools;
|
|
139
148
|
private readonly builtinToolFiltering:
|
|
@@ -141,10 +150,14 @@ export class HarnessAgent<
|
|
|
141
150
|
| undefined;
|
|
142
151
|
private readonly permissionMode: HarnessAgentPermissionMode;
|
|
143
152
|
|
|
144
|
-
constructor(
|
|
153
|
+
constructor(
|
|
154
|
+
settings: HarnessAgentSettings<THarness, TUserTools, RUNTIME_CONTEXT>,
|
|
155
|
+
) {
|
|
145
156
|
const sandboxConfig = resolveSandboxConfig(settings);
|
|
146
157
|
validateSandboxBootstrapSettings(sandboxConfig);
|
|
147
158
|
this.settings = settings;
|
|
159
|
+
this.stopConditions =
|
|
160
|
+
settings.stopWhen == null ? [] : asArray(settings.stopWhen);
|
|
148
161
|
this.sandboxConfig = sandboxConfig;
|
|
149
162
|
this.id = settings.id;
|
|
150
163
|
const userTools = settings.tools ?? ({} as TUserTools);
|
|
@@ -528,6 +541,7 @@ export class HarnessAgent<
|
|
|
528
541
|
runtimeContext: input.runtimeContext,
|
|
529
542
|
abortSignal: input.abortSignal,
|
|
530
543
|
telemetry: this.settings.telemetry,
|
|
544
|
+
stopConditions: this.stopConditions,
|
|
531
545
|
toolApprovalContinuations: input.turnInput.toolApprovalContinuations,
|
|
532
546
|
toolResultContinuations: input.turnInput.toolResultContinuations,
|
|
533
547
|
});
|
|
@@ -546,6 +560,7 @@ export class HarnessAgent<
|
|
|
546
560
|
runtimeContext: input.runtimeContext,
|
|
547
561
|
abortSignal: input.abortSignal,
|
|
548
562
|
telemetry: this.settings.telemetry,
|
|
563
|
+
stopConditions: this.stopConditions,
|
|
549
564
|
});
|
|
550
565
|
}
|
|
551
566
|
|
|
@@ -32,6 +32,7 @@ import type {
|
|
|
32
32
|
ContentPart,
|
|
33
33
|
ProviderMetadata,
|
|
34
34
|
StepResult,
|
|
35
|
+
StopCondition,
|
|
35
36
|
TelemetryOptions,
|
|
36
37
|
TextStreamPart,
|
|
37
38
|
} from 'ai';
|
|
@@ -41,9 +42,14 @@ import type { HarnessAgentToolApprovalConfiguration } from '../harness-agent-set
|
|
|
41
42
|
import { HarnessStreamTextResult } from './harness-stream-text-result';
|
|
42
43
|
import { translateStreamPart } from './translate-stream-part';
|
|
43
44
|
import { stripWorkDir } from './strip-work-dir';
|
|
44
|
-
import {
|
|
45
|
+
import {
|
|
46
|
+
createTurnTelemetry,
|
|
47
|
+
type TurnContentPart,
|
|
48
|
+
type TurnTelemetry,
|
|
49
|
+
} from './turn-telemetry';
|
|
45
50
|
import { resolveCustomToolApproval } from './permission-mode';
|
|
46
51
|
import { logBridgeError } from '../../utils/bridge-diagnostics';
|
|
52
|
+
import { pinSandboxChannelEventCheckpoint } from '../../utils/sandbox-channel';
|
|
47
53
|
|
|
48
54
|
/**
|
|
49
55
|
* Drive one prompt turn end-to-end:
|
|
@@ -81,6 +87,7 @@ export function runPrompt<
|
|
|
81
87
|
runtimeContext: RUNTIME_CONTEXT;
|
|
82
88
|
abortSignal: AbortSignal | undefined;
|
|
83
89
|
telemetry?: TelemetryOptions | undefined;
|
|
90
|
+
stopConditions?: ReadonlyArray<StopCondition<TOOLS, RUNTIME_CONTEXT>>;
|
|
84
91
|
toolApproval?: HarnessAgentToolApprovalConfiguration | undefined;
|
|
85
92
|
pendingToolApprovals?: readonly HarnessV1PendingToolApproval[];
|
|
86
93
|
pendingToolResults?: readonly HarnessV1PendingToolResult[];
|
|
@@ -96,6 +103,7 @@ export function runPrompt<
|
|
|
96
103
|
onToolResultSettled?: (toolCallId: string) => void;
|
|
97
104
|
onTurnFinished?: () => void;
|
|
98
105
|
onTurnFailed?: () => void;
|
|
106
|
+
onStopConditionMet?: () => Promise<void>;
|
|
99
107
|
}): {
|
|
100
108
|
result: HarnessStreamTextResult<TOOLS, RUNTIME_CONTEXT>;
|
|
101
109
|
done: Promise<void>;
|
|
@@ -176,7 +184,7 @@ export function runPrompt<
|
|
|
176
184
|
},
|
|
177
185
|
});
|
|
178
186
|
} catch (err) {
|
|
179
|
-
telemetry.error(err);
|
|
187
|
+
await telemetry.error(err);
|
|
180
188
|
logBridgeError({
|
|
181
189
|
harnessId: input.harness.harnessId,
|
|
182
190
|
sessionId: input.session.sessionId,
|
|
@@ -220,9 +228,21 @@ export function runPrompt<
|
|
|
220
228
|
);
|
|
221
229
|
const settledHostToolCallIds = new Set<string>();
|
|
222
230
|
let closingResumedStep = false;
|
|
231
|
+
let pendingStopBoundary:
|
|
232
|
+
| {
|
|
233
|
+
finishReason: LanguageModelV4FinishReason;
|
|
234
|
+
usage: LanguageModelV4Usage;
|
|
235
|
+
releaseCheckpoint: (() => void) | undefined;
|
|
236
|
+
}
|
|
237
|
+
| undefined;
|
|
223
238
|
let finalFinish:
|
|
224
239
|
| Extract<HarnessV1StreamPart, { type: 'finish' }>
|
|
225
240
|
| undefined;
|
|
241
|
+
const completedSteps: Array<StepResult<TOOLS, RUNTIME_CONTEXT>> = [];
|
|
242
|
+
const releasePendingStopBoundary = (): void => {
|
|
243
|
+
pendingStopBoundary?.releaseCheckpoint?.();
|
|
244
|
+
pendingStopBoundary = undefined;
|
|
245
|
+
};
|
|
226
246
|
|
|
227
247
|
// Accumulate the model's output content per step so telemetry can record
|
|
228
248
|
// `gen_ai.output.messages` and reporters can log what was actually said.
|
|
@@ -258,36 +278,38 @@ export function runPrompt<
|
|
|
258
278
|
unified: 'tool-calls',
|
|
259
279
|
raw: undefined,
|
|
260
280
|
};
|
|
261
|
-
const completeStep = (input: {
|
|
281
|
+
const completeStep = async (input: {
|
|
262
282
|
finishReason: LanguageModelV4FinishReason;
|
|
263
283
|
usage: LanguageModelV4Usage;
|
|
264
284
|
providerMetadata: ProviderMetadata | undefined;
|
|
265
|
-
}): StepResult<TOOLS, RUNTIME_CONTEXT
|
|
266
|
-
telemetry.stepFinish({
|
|
285
|
+
}): Promise<StepResult<TOOLS, RUNTIME_CONTEXT>> => {
|
|
286
|
+
await telemetry.stepFinish({
|
|
267
287
|
finishReason: input.finishReason,
|
|
268
288
|
usage: input.usage,
|
|
269
289
|
providerMetadata: input.providerMetadata,
|
|
270
290
|
content: buildStepContent(),
|
|
271
291
|
});
|
|
272
292
|
resetStepContent();
|
|
273
|
-
|
|
293
|
+
const step = result.finishStep({
|
|
274
294
|
finishReason: input.finishReason,
|
|
275
295
|
usage: input.usage,
|
|
276
296
|
providerMetadata: input.providerMetadata,
|
|
277
297
|
warnings: [],
|
|
278
298
|
});
|
|
299
|
+
completedSteps.push(step);
|
|
300
|
+
return step;
|
|
279
301
|
};
|
|
280
302
|
const finishForHostInputPause = async (options: {
|
|
281
303
|
completeCurrentStep: boolean;
|
|
282
304
|
}): Promise<void> => {
|
|
283
305
|
if (options.completeCurrentStep) {
|
|
284
|
-
completeStep({
|
|
306
|
+
await completeStep({
|
|
285
307
|
finishReason: toolCallsFinishReason,
|
|
286
308
|
usage: zeroUsage,
|
|
287
309
|
providerMetadata: undefined,
|
|
288
310
|
});
|
|
289
311
|
}
|
|
290
|
-
telemetry.end({
|
|
312
|
+
await telemetry.end({
|
|
291
313
|
finishReason: toolCallsFinishReason,
|
|
292
314
|
usage: zeroUsage,
|
|
293
315
|
});
|
|
@@ -413,9 +435,16 @@ export function runPrompt<
|
|
|
413
435
|
input: approval.input,
|
|
414
436
|
} satisfies Extract<HarnessV1StreamPart, { type: 'tool-call' }>);
|
|
415
437
|
|
|
438
|
+
await telemetry.start(input.session.modelId);
|
|
439
|
+
await telemetry.toolStart({
|
|
440
|
+
toolCallId: rawToolCall.toolCallId,
|
|
441
|
+
toolName: rawToolCall.toolName,
|
|
442
|
+
input: rawToolCall.input,
|
|
443
|
+
});
|
|
416
444
|
const execution = await maybeExecuteHostTool({
|
|
417
445
|
event: rawToolCall,
|
|
418
446
|
tools: activeTools,
|
|
447
|
+
wrappedExecuteTool: telemetry.executeTool,
|
|
419
448
|
sandboxSession: input.sandboxSession,
|
|
420
449
|
abortSignal: input.abortSignal,
|
|
421
450
|
control,
|
|
@@ -447,7 +476,7 @@ export function runPrompt<
|
|
|
447
476
|
await finishForHostInputPause({ completeCurrentStep: false });
|
|
448
477
|
return 'awaiting-tool-result';
|
|
449
478
|
}
|
|
450
|
-
telemetry.toolEnd(rawToolCall.toolCallId, execution.outcome);
|
|
479
|
+
await telemetry.toolEnd(rawToolCall.toolCallId, execution.outcome);
|
|
451
480
|
return 'continued';
|
|
452
481
|
};
|
|
453
482
|
|
|
@@ -478,13 +507,39 @@ export function runPrompt<
|
|
|
478
507
|
|
|
479
508
|
while (true) {
|
|
480
509
|
const { value, done } = await reader.read();
|
|
481
|
-
if (done)
|
|
510
|
+
if (done) {
|
|
511
|
+
releasePendingStopBoundary();
|
|
512
|
+
break;
|
|
513
|
+
}
|
|
482
514
|
if (value == null) continue;
|
|
483
515
|
|
|
516
|
+
if (pendingStopBoundary != null) {
|
|
517
|
+
if (value.type === 'finish') {
|
|
518
|
+
releasePendingStopBoundary();
|
|
519
|
+
} else if (
|
|
520
|
+
(
|
|
521
|
+
await Promise.all(
|
|
522
|
+
input.stopConditions!.map(condition =>
|
|
523
|
+
condition({ steps: completedSteps }),
|
|
524
|
+
),
|
|
525
|
+
)
|
|
526
|
+
).some(Boolean)
|
|
527
|
+
) {
|
|
528
|
+
await input.onStopConditionMet?.();
|
|
529
|
+
const { finishReason, usage } = pendingStopBoundary;
|
|
530
|
+
releasePendingStopBoundary();
|
|
531
|
+
await telemetry.end({ finishReason, usage });
|
|
532
|
+
await result.finish();
|
|
533
|
+
return;
|
|
534
|
+
} else {
|
|
535
|
+
releasePendingStopBoundary();
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
484
539
|
// Begin the operation span on stream-start, using the runtime-resolved
|
|
485
540
|
// model the adapter reports (falling back to the session's model).
|
|
486
541
|
if (value.type === 'stream-start') {
|
|
487
|
-
telemetry.start(value.modelId ?? input.session.modelId);
|
|
542
|
+
await telemetry.start(value.modelId ?? input.session.modelId);
|
|
488
543
|
}
|
|
489
544
|
|
|
490
545
|
// Open a step span lazily before the first content of each step.
|
|
@@ -494,7 +549,7 @@ export function runPrompt<
|
|
|
494
549
|
value.type !== 'finish' &&
|
|
495
550
|
value.type !== 'error'
|
|
496
551
|
) {
|
|
497
|
-
telemetry.ensureStepOpen();
|
|
552
|
+
await telemetry.ensureStepOpen();
|
|
498
553
|
}
|
|
499
554
|
|
|
500
555
|
/*
|
|
@@ -565,7 +620,7 @@ export function runPrompt<
|
|
|
565
620
|
// Telemetry and stderr diagnostics keep the raw error (absolute
|
|
566
621
|
// paths help debugging); the consumer-facing settle uses the
|
|
567
622
|
// workDir-stripped one, like every other forwarded part.
|
|
568
|
-
telemetry.error(value.error);
|
|
623
|
+
await telemetry.error(value.error);
|
|
569
624
|
logBridgeError({
|
|
570
625
|
harnessId: input.harness.harnessId,
|
|
571
626
|
sessionId: input.session.sessionId,
|
|
@@ -609,7 +664,7 @@ export function runPrompt<
|
|
|
609
664
|
toolName: value.toolName,
|
|
610
665
|
input: value.input,
|
|
611
666
|
});
|
|
612
|
-
telemetry.toolStart({
|
|
667
|
+
await telemetry.toolStart({
|
|
613
668
|
toolCallId: value.toolCallId,
|
|
614
669
|
toolName: value.toolName,
|
|
615
670
|
input: value.input,
|
|
@@ -618,7 +673,7 @@ export function runPrompt<
|
|
|
618
673
|
|
|
619
674
|
// Telemetry: close a tool span when its provider-executed result lands.
|
|
620
675
|
if (value.type === 'tool-result') {
|
|
621
|
-
telemetry.toolEnd(
|
|
676
|
+
await telemetry.toolEnd(
|
|
622
677
|
value.toolCallId,
|
|
623
678
|
value.isError
|
|
624
679
|
? { ok: false, error: value.result }
|
|
@@ -681,16 +736,23 @@ export function runPrompt<
|
|
|
681
736
|
|
|
682
737
|
// Drive step boundaries.
|
|
683
738
|
if (value.type === 'finish-step') {
|
|
684
|
-
completeStep({
|
|
739
|
+
await completeStep({
|
|
685
740
|
finishReason: value.finishReason,
|
|
686
741
|
usage: value.usage,
|
|
687
742
|
providerMetadata: value.harnessMetadata,
|
|
688
743
|
});
|
|
744
|
+
if (input.stopConditions != null && input.stopConditions.length > 0) {
|
|
745
|
+
pendingStopBoundary = {
|
|
746
|
+
finishReason: value.finishReason,
|
|
747
|
+
usage: value.usage,
|
|
748
|
+
releaseCheckpoint: pinSandboxChannelEventCheckpoint(value),
|
|
749
|
+
};
|
|
750
|
+
}
|
|
689
751
|
}
|
|
690
752
|
|
|
691
753
|
if (value.type === 'finish') {
|
|
692
754
|
finalFinish = value;
|
|
693
|
-
telemetry.end({
|
|
755
|
+
await telemetry.end({
|
|
694
756
|
finishReason: value.finishReason,
|
|
695
757
|
usage: value.totalUsage,
|
|
696
758
|
});
|
|
@@ -716,7 +778,7 @@ export function runPrompt<
|
|
|
716
778
|
toolCallId: toolCall.toolCallId,
|
|
717
779
|
output,
|
|
718
780
|
});
|
|
719
|
-
telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
|
|
781
|
+
await telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
|
|
720
782
|
continue;
|
|
721
783
|
}
|
|
722
784
|
const customToolApprovalDecision = resolveCustomToolApproval({
|
|
@@ -745,7 +807,7 @@ export function runPrompt<
|
|
|
745
807
|
toolCallId: toolCall.toolCallId,
|
|
746
808
|
output,
|
|
747
809
|
});
|
|
748
|
-
telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
|
|
810
|
+
await telemetry.toolEnd(toolCall.toolCallId, { ok: true, output });
|
|
749
811
|
continue;
|
|
750
812
|
}
|
|
751
813
|
const pendingApproval =
|
|
@@ -803,6 +865,7 @@ export function runPrompt<
|
|
|
803
865
|
const execution = await maybeExecuteHostTool({
|
|
804
866
|
event: toolCall,
|
|
805
867
|
tools: activeTools,
|
|
868
|
+
wrappedExecuteTool: telemetry.executeTool,
|
|
806
869
|
sandboxSession: input.sandboxSession,
|
|
807
870
|
abortSignal: input.abortSignal,
|
|
808
871
|
control,
|
|
@@ -842,7 +905,7 @@ export function runPrompt<
|
|
|
842
905
|
await finishForHostInputPause({ completeCurrentStep: true });
|
|
843
906
|
return;
|
|
844
907
|
}
|
|
845
|
-
telemetry.toolEnd(toolCall.toolCallId, execution.outcome);
|
|
908
|
+
await telemetry.toolEnd(toolCall.toolCallId, execution.outcome);
|
|
846
909
|
}
|
|
847
910
|
}
|
|
848
911
|
if (finalFinish != null) {
|
|
@@ -860,7 +923,7 @@ export function runPrompt<
|
|
|
860
923
|
: undefined,
|
|
861
924
|
);
|
|
862
925
|
} catch (err) {
|
|
863
|
-
telemetry.error(err);
|
|
926
|
+
await telemetry.error(err);
|
|
864
927
|
logBridgeError({
|
|
865
928
|
harnessId: input.harness.harnessId,
|
|
866
929
|
sessionId: input.session.sessionId,
|
|
@@ -869,6 +932,7 @@ export function runPrompt<
|
|
|
869
932
|
});
|
|
870
933
|
settleFailure(err);
|
|
871
934
|
} finally {
|
|
935
|
+
releasePendingStopBoundary();
|
|
872
936
|
reader.releaseLock();
|
|
873
937
|
}
|
|
874
938
|
})();
|
|
@@ -921,6 +985,7 @@ function hasTool(input: { tools: ToolSet; toolName: string }): boolean {
|
|
|
921
985
|
async function maybeExecuteHostTool<TOOLS extends ToolSet>(input: {
|
|
922
986
|
event: { toolCallId: string; toolName: string; input: string };
|
|
923
987
|
tools: TOOLS;
|
|
988
|
+
wrappedExecuteTool: TurnTelemetry['executeTool'];
|
|
924
989
|
sandboxSession: SandboxSession;
|
|
925
990
|
abortSignal: AbortSignal | undefined;
|
|
926
991
|
control: HarnessV1PromptControl;
|
|
@@ -949,25 +1014,31 @@ async function maybeExecuteHostTool<TOOLS extends ToolSet>(input: {
|
|
|
949
1014
|
* back to the model — preliminary values are surfaced to the consumer
|
|
950
1015
|
* stream alone, matching how the AI SDK treats `onPreliminaryToolResult`.
|
|
951
1016
|
*/
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
1017
|
+
const output = await input.wrappedExecuteTool({
|
|
1018
|
+
toolCallId: input.event.toolCallId,
|
|
1019
|
+
execute: async () => {
|
|
1020
|
+
let output: unknown;
|
|
1021
|
+
const stream = executeTool({
|
|
1022
|
+
tool,
|
|
1023
|
+
input: args as never,
|
|
1024
|
+
options: {
|
|
1025
|
+
toolCallId: input.event.toolCallId,
|
|
1026
|
+
messages: [],
|
|
1027
|
+
abortSignal: input.abortSignal,
|
|
1028
|
+
context: undefined as never,
|
|
1029
|
+
experimental_sandbox: input.sandboxSession,
|
|
1030
|
+
},
|
|
1031
|
+
});
|
|
1032
|
+
for await (const part of stream) {
|
|
1033
|
+
if (part.type === 'preliminary') {
|
|
1034
|
+
input.onPreliminaryResult(part.output);
|
|
1035
|
+
} else {
|
|
1036
|
+
output = part.output;
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
return output;
|
|
962
1040
|
},
|
|
963
1041
|
});
|
|
964
|
-
for await (const part of stream) {
|
|
965
|
-
if (part.type === 'preliminary') {
|
|
966
|
-
input.onPreliminaryResult(part.output);
|
|
967
|
-
} else {
|
|
968
|
-
output = part.output;
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
1042
|
|
|
972
1043
|
await input.control.submitToolResult({
|
|
973
1044
|
toolCallId: input.event.toolCallId,
|
|
@@ -1009,6 +1080,7 @@ export async function validateToolCall<TOOLS extends ToolSet>(args: {
|
|
|
1009
1080
|
...(event.providerExecuted !== undefined
|
|
1010
1081
|
? { providerExecuted: event.providerExecuted }
|
|
1011
1082
|
: {}),
|
|
1083
|
+
...(event.dynamic !== undefined ? { dynamic: event.dynamic } : {}),
|
|
1012
1084
|
...(event.providerMetadata !== undefined
|
|
1013
1085
|
? { providerMetadata: event.providerMetadata }
|
|
1014
1086
|
: {}),
|