@ai-sdk/harness-deepagents 1.0.39 → 1.0.40
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 +11 -0
- package/dist/bridge/index.mjs +238 -172
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/bridge/create-emit-stream-event.ts +322 -0
- package/src/bridge/index.ts +30 -216
- package/src/deepagents-harness.ts +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @ai-sdk/harness-deepagents
|
|
2
2
|
|
|
3
|
+
## 1.0.40
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 07c977a: chore(harness): refactor bridge code to break out stream event emission from launcher to make it testable
|
|
8
|
+
- 8c96d41: fix(harness-deepagents): fix Deep Agents missing model ID in telemetry
|
|
9
|
+
- 5c1a6af: fix(harness-deepagents): fix overly limiting override of Deep Agents recursion limit default
|
|
10
|
+
- Updated dependencies [a94425b]
|
|
11
|
+
- Updated dependencies [2de0611]
|
|
12
|
+
- @ai-sdk/harness@1.0.41
|
|
13
|
+
|
|
3
14
|
## 1.0.39
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
package/dist/bridge/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/bridge/index.ts
|
|
2
|
-
import { randomUUID } from "crypto";
|
|
2
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
3
3
|
import { argv, env as procEnv2 } from "process";
|
|
4
4
|
|
|
5
5
|
// ../harness/dist/bridge/index.js
|
|
@@ -548,6 +548,222 @@ function collectActionRequests(interrupts) {
|
|
|
548
548
|
return out;
|
|
549
549
|
}
|
|
550
550
|
|
|
551
|
+
// src/bridge/create-emit-stream-event.ts
|
|
552
|
+
import { randomUUID } from "crypto";
|
|
553
|
+
function createDeepAgentsStreamEventState() {
|
|
554
|
+
return {
|
|
555
|
+
streamStarted: false,
|
|
556
|
+
textBlockId: void 0,
|
|
557
|
+
reasoningBlockId: void 0,
|
|
558
|
+
inputTokens: 0,
|
|
559
|
+
outputTokens: 0,
|
|
560
|
+
streamedStepInput: 0,
|
|
561
|
+
streamedStepOutput: 0,
|
|
562
|
+
pendingStep: void 0,
|
|
563
|
+
approvedToolQueue: /* @__PURE__ */ new Map(),
|
|
564
|
+
approvedRunIds: /* @__PURE__ */ new Map()
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
var NATIVE_TO_COMMON2 = {
|
|
568
|
+
read_file: "read",
|
|
569
|
+
write_file: "write",
|
|
570
|
+
edit_file: "edit",
|
|
571
|
+
execute: "bash"
|
|
572
|
+
};
|
|
573
|
+
function toCommonName2(nativeName) {
|
|
574
|
+
return NATIVE_TO_COMMON2[nativeName] ?? nativeName;
|
|
575
|
+
}
|
|
576
|
+
function createEmitStreamEvent({
|
|
577
|
+
state,
|
|
578
|
+
configuredModel,
|
|
579
|
+
hostToolNames,
|
|
580
|
+
emit
|
|
581
|
+
}) {
|
|
582
|
+
return (event) => {
|
|
583
|
+
const kind = event.event;
|
|
584
|
+
const data = event.data ?? {};
|
|
585
|
+
const ns = event.metadata?.langgraph_checkpoint_ns ?? "";
|
|
586
|
+
const nested = ns.includes("|");
|
|
587
|
+
if (kind === "on_chat_model_start") {
|
|
588
|
+
if (!nested) {
|
|
589
|
+
if (!state.streamStarted) {
|
|
590
|
+
state.streamStarted = true;
|
|
591
|
+
const modelId = resolveDeepAgentsModelId({
|
|
592
|
+
configuredModel,
|
|
593
|
+
metadata: event.metadata
|
|
594
|
+
});
|
|
595
|
+
emit({
|
|
596
|
+
type: "stream-start",
|
|
597
|
+
...modelId ? { modelId } : {}
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
flushStep({ state, emit });
|
|
601
|
+
}
|
|
602
|
+
} else if (kind === "on_chat_model_stream") {
|
|
603
|
+
if (nested) return;
|
|
604
|
+
const chunk = data.chunk;
|
|
605
|
+
if (!chunk) return;
|
|
606
|
+
const content = chunk.content;
|
|
607
|
+
if (typeof content === "string" && content) {
|
|
608
|
+
emitText({ state, emit, delta: content });
|
|
609
|
+
} else if (Array.isArray(content)) {
|
|
610
|
+
for (const block of content) {
|
|
611
|
+
if (block && typeof block === "object") {
|
|
612
|
+
const value = block;
|
|
613
|
+
if (value.type === "text" && value.text) {
|
|
614
|
+
emitText({ state, emit, delta: value.text });
|
|
615
|
+
} else if (value.type === "thinking" && value.thinking) {
|
|
616
|
+
emitReasoning({ state, emit, delta: value.thinking });
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
const usage = chunk.usage_metadata;
|
|
622
|
+
if (usage) {
|
|
623
|
+
state.streamedStepInput = Math.max(
|
|
624
|
+
state.streamedStepInput,
|
|
625
|
+
usage.input_tokens ?? 0
|
|
626
|
+
);
|
|
627
|
+
state.streamedStepOutput = Math.max(
|
|
628
|
+
state.streamedStepOutput,
|
|
629
|
+
usage.output_tokens ?? 0
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
} else if (kind === "on_chat_model_end") {
|
|
633
|
+
const output = data.output;
|
|
634
|
+
const usage = output?.usage_metadata;
|
|
635
|
+
const stepInput = usage?.input_tokens ?? state.streamedStepInput;
|
|
636
|
+
const stepOutput = usage?.output_tokens ?? state.streamedStepOutput;
|
|
637
|
+
state.inputTokens += stepInput;
|
|
638
|
+
state.outputTokens += stepOutput;
|
|
639
|
+
state.streamedStepInput = 0;
|
|
640
|
+
state.streamedStepOutput = 0;
|
|
641
|
+
if (!nested) {
|
|
642
|
+
endTextBlock({ state, emit });
|
|
643
|
+
endReasoningBlock({ state, emit });
|
|
644
|
+
state.pendingStep = { input: stepInput, output: stepOutput };
|
|
645
|
+
}
|
|
646
|
+
} else if (kind === "on_tool_start") {
|
|
647
|
+
const toolName = event.name ?? "unknown";
|
|
648
|
+
const runId = event.run_id ?? "";
|
|
649
|
+
if (!nested && !hostToolNames.has(toolName)) {
|
|
650
|
+
const queued = state.approvedToolQueue.get(toolName);
|
|
651
|
+
if (queued && queued.length > 0) {
|
|
652
|
+
const approvalId = queued.shift();
|
|
653
|
+
if (runId) state.approvedRunIds.set(runId, approvalId);
|
|
654
|
+
} else {
|
|
655
|
+
endTextBlock({ state, emit });
|
|
656
|
+
endReasoningBlock({ state, emit });
|
|
657
|
+
emit({
|
|
658
|
+
type: "tool-call",
|
|
659
|
+
toolCallId: runId,
|
|
660
|
+
toolName: toCommonName2(toolName),
|
|
661
|
+
input: toToolCallInput(data.input),
|
|
662
|
+
providerExecuted: true,
|
|
663
|
+
nativeName: toolName
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
} else if (kind === "on_tool_end") {
|
|
668
|
+
const toolName = event.name ?? "unknown";
|
|
669
|
+
const runId = event.run_id ?? "";
|
|
670
|
+
if (!nested && !hostToolNames.has(toolName)) {
|
|
671
|
+
let output = data.output ?? "";
|
|
672
|
+
if (output && typeof output === "object" && "content" in output) {
|
|
673
|
+
output = output.content;
|
|
674
|
+
}
|
|
675
|
+
emit({
|
|
676
|
+
type: "tool-result",
|
|
677
|
+
toolCallId: state.approvedRunIds.get(runId) ?? runId,
|
|
678
|
+
toolName: toCommonName2(toolName),
|
|
679
|
+
result: output ?? null
|
|
680
|
+
});
|
|
681
|
+
state.approvedRunIds.delete(runId);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
function endTextBlock({
|
|
687
|
+
state,
|
|
688
|
+
emit
|
|
689
|
+
}) {
|
|
690
|
+
if (state.textBlockId) {
|
|
691
|
+
emit({ type: "text-end", id: state.textBlockId });
|
|
692
|
+
state.textBlockId = void 0;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
function endReasoningBlock({
|
|
696
|
+
state,
|
|
697
|
+
emit
|
|
698
|
+
}) {
|
|
699
|
+
if (state.reasoningBlockId) {
|
|
700
|
+
emit({ type: "reasoning-end", id: state.reasoningBlockId });
|
|
701
|
+
state.reasoningBlockId = void 0;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
function flushStep({
|
|
705
|
+
state,
|
|
706
|
+
emit
|
|
707
|
+
}) {
|
|
708
|
+
if (!state.pendingStep) return;
|
|
709
|
+
emit({
|
|
710
|
+
type: "finish-step",
|
|
711
|
+
finishReason: { unified: "stop" },
|
|
712
|
+
usage: {
|
|
713
|
+
inputTokens: { total: state.pendingStep.input },
|
|
714
|
+
outputTokens: { total: state.pendingStep.output }
|
|
715
|
+
}
|
|
716
|
+
});
|
|
717
|
+
state.pendingStep = void 0;
|
|
718
|
+
}
|
|
719
|
+
function ensureTextBlock({
|
|
720
|
+
state,
|
|
721
|
+
emit
|
|
722
|
+
}) {
|
|
723
|
+
if (!state.textBlockId) {
|
|
724
|
+
state.textBlockId = `text-${randomUUID()}`;
|
|
725
|
+
emit({ type: "text-start", id: state.textBlockId });
|
|
726
|
+
}
|
|
727
|
+
return state.textBlockId;
|
|
728
|
+
}
|
|
729
|
+
function emitText({
|
|
730
|
+
state,
|
|
731
|
+
emit,
|
|
732
|
+
delta
|
|
733
|
+
}) {
|
|
734
|
+
endReasoningBlock({ state, emit });
|
|
735
|
+
emit({ type: "text-delta", id: ensureTextBlock({ state, emit }), delta });
|
|
736
|
+
}
|
|
737
|
+
function emitReasoning({
|
|
738
|
+
state,
|
|
739
|
+
emit,
|
|
740
|
+
delta
|
|
741
|
+
}) {
|
|
742
|
+
endTextBlock({ state, emit });
|
|
743
|
+
if (!state.reasoningBlockId) {
|
|
744
|
+
state.reasoningBlockId = `reasoning-${randomUUID()}`;
|
|
745
|
+
emit({ type: "reasoning-start", id: state.reasoningBlockId });
|
|
746
|
+
}
|
|
747
|
+
emit({ type: "reasoning-delta", id: state.reasoningBlockId, delta });
|
|
748
|
+
}
|
|
749
|
+
function resolveDeepAgentsModelId({
|
|
750
|
+
configuredModel,
|
|
751
|
+
metadata
|
|
752
|
+
}) {
|
|
753
|
+
if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
|
|
754
|
+
const modelId = metadata.ls_model_name;
|
|
755
|
+
if (typeof modelId === "string" && modelId.length > 0) return modelId;
|
|
756
|
+
}
|
|
757
|
+
return configuredModel;
|
|
758
|
+
}
|
|
759
|
+
function toToolCallInput(raw) {
|
|
760
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw) && Object.keys(raw).length === 1 && typeof raw.input === "string") {
|
|
761
|
+
const inner = raw.input;
|
|
762
|
+
if (/^\s*[[{]/.test(inner)) return inner;
|
|
763
|
+
}
|
|
764
|
+
return JSON.stringify(raw ?? {});
|
|
765
|
+
}
|
|
766
|
+
|
|
551
767
|
// src/bridge/json-schema-to-zod.ts
|
|
552
768
|
import { z } from "zod/v4";
|
|
553
769
|
function jsonSchemaToZodObject(input) {
|
|
@@ -692,16 +908,7 @@ function createBuiltinToolFilteringMiddleware(input) {
|
|
|
692
908
|
}
|
|
693
909
|
|
|
694
910
|
// src/bridge/index.ts
|
|
695
|
-
var NATIVE_TO_COMMON2 = {
|
|
696
|
-
read_file: "read",
|
|
697
|
-
write_file: "write",
|
|
698
|
-
edit_file: "edit",
|
|
699
|
-
execute: "bash"
|
|
700
|
-
};
|
|
701
911
|
var HARNESS_CLIENT_APP = procEnv2.AI_SDK_HARNESS_CLIENT_APP;
|
|
702
|
-
function toCommonName2(nativeName) {
|
|
703
|
-
return NATIVE_TO_COMMON2[nativeName] ?? nativeName;
|
|
704
|
-
}
|
|
705
912
|
function parseArgs(rawArgs) {
|
|
706
913
|
const out = {};
|
|
707
914
|
for (let i = 0; i < rawArgs.length; i++) {
|
|
@@ -732,13 +939,6 @@ function buildModel(rawModel) {
|
|
|
732
939
|
} : {}
|
|
733
940
|
});
|
|
734
941
|
}
|
|
735
|
-
function toToolCallInput(raw) {
|
|
736
|
-
if (raw && typeof raw === "object" && !Array.isArray(raw) && Object.keys(raw).length === 1 && typeof raw.input === "string") {
|
|
737
|
-
const inner = raw.input;
|
|
738
|
-
if (/^\s*[[{]/.test(inner)) return inner;
|
|
739
|
-
}
|
|
740
|
-
return JSON.stringify(raw ?? {});
|
|
741
|
-
}
|
|
742
942
|
var args = parseArgs(argv.slice(2));
|
|
743
943
|
var workdir = args.workdir;
|
|
744
944
|
var bridgeStateDir = args.bridgeStateDir;
|
|
@@ -754,7 +954,7 @@ function buildHostTools(toolSchemas) {
|
|
|
754
954
|
async (input) => {
|
|
755
955
|
const turn = currentTurn;
|
|
756
956
|
if (!turn) throw new Error("no active turn");
|
|
757
|
-
const toolCallId = `${schema.name}-${
|
|
957
|
+
const toolCallId = `${schema.name}-${randomUUID2()}`;
|
|
758
958
|
turn.emit({
|
|
759
959
|
type: "tool-call",
|
|
760
960
|
toolCallId,
|
|
@@ -807,67 +1007,18 @@ async function runTurn(start, turn) {
|
|
|
807
1007
|
checkpointer: new MemorySaver()
|
|
808
1008
|
});
|
|
809
1009
|
}
|
|
810
|
-
emit({
|
|
811
|
-
type: "stream-start",
|
|
812
|
-
...start.model ? { modelId: start.model } : {}
|
|
813
|
-
});
|
|
814
1010
|
const hostToolNames = new Set((start.tools ?? []).map((t) => t.name));
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
const approvedToolQueue = /* @__PURE__ */ new Map();
|
|
823
|
-
const approvedRunIds = /* @__PURE__ */ new Map();
|
|
824
|
-
const ensureTextBlock = () => {
|
|
825
|
-
if (!textBlockId) {
|
|
826
|
-
textBlockId = `text-${randomUUID()}`;
|
|
827
|
-
emit({ type: "text-start", id: textBlockId });
|
|
828
|
-
}
|
|
829
|
-
return textBlockId;
|
|
830
|
-
};
|
|
831
|
-
const endTextBlock = () => {
|
|
832
|
-
if (textBlockId) {
|
|
833
|
-
emit({ type: "text-end", id: textBlockId });
|
|
834
|
-
textBlockId = void 0;
|
|
835
|
-
}
|
|
836
|
-
};
|
|
837
|
-
const endReasoningBlock = () => {
|
|
838
|
-
if (reasoningBlockId) {
|
|
839
|
-
emit({ type: "reasoning-end", id: reasoningBlockId });
|
|
840
|
-
reasoningBlockId = void 0;
|
|
841
|
-
}
|
|
842
|
-
};
|
|
843
|
-
const emitText = (delta) => {
|
|
844
|
-
endReasoningBlock();
|
|
845
|
-
emit({ type: "text-delta", id: ensureTextBlock(), delta });
|
|
846
|
-
};
|
|
847
|
-
const emitReasoning = (delta) => {
|
|
848
|
-
endTextBlock();
|
|
849
|
-
if (!reasoningBlockId) {
|
|
850
|
-
reasoningBlockId = `reasoning-${randomUUID()}`;
|
|
851
|
-
emit({ type: "reasoning-start", id: reasoningBlockId });
|
|
852
|
-
}
|
|
853
|
-
emit({ type: "reasoning-delta", id: reasoningBlockId, delta });
|
|
854
|
-
};
|
|
855
|
-
const flushStep = () => {
|
|
856
|
-
if (!pendingStep) return;
|
|
857
|
-
emit({
|
|
858
|
-
type: "finish-step",
|
|
859
|
-
finishReason: { unified: "stop" },
|
|
860
|
-
usage: {
|
|
861
|
-
inputTokens: { total: pendingStep.input },
|
|
862
|
-
outputTokens: { total: pendingStep.output }
|
|
863
|
-
}
|
|
864
|
-
});
|
|
865
|
-
pendingStep = void 0;
|
|
866
|
-
};
|
|
1011
|
+
const streamEventState = createDeepAgentsStreamEventState();
|
|
1012
|
+
const emitStreamEvent = createEmitStreamEvent({
|
|
1013
|
+
state: streamEventState,
|
|
1014
|
+
configuredModel: start.model,
|
|
1015
|
+
hostToolNames,
|
|
1016
|
+
emit
|
|
1017
|
+
});
|
|
867
1018
|
const config = {
|
|
868
1019
|
version: "v2",
|
|
869
1020
|
configurable: { thread_id: "bridge-session" },
|
|
870
|
-
recursionLimit: start.recursionLimit
|
|
1021
|
+
...start.recursionLimit != null ? { recursionLimit: start.recursionLimit } : {},
|
|
871
1022
|
signal: turn.abortSignal
|
|
872
1023
|
};
|
|
873
1024
|
const readPendingApprovals = async () => {
|
|
@@ -888,100 +1039,15 @@ async function runTurn(start, turn) {
|
|
|
888
1039
|
while (true) {
|
|
889
1040
|
const stream = await agent.streamEvents(resumeInput, config);
|
|
890
1041
|
for await (const event of stream) {
|
|
891
|
-
|
|
892
|
-
const data = event.data ?? {};
|
|
893
|
-
const ns = event.metadata?.langgraph_checkpoint_ns ?? "";
|
|
894
|
-
const nested = ns.includes("|");
|
|
895
|
-
if (kind === "on_chat_model_start") {
|
|
896
|
-
if (!nested) flushStep();
|
|
897
|
-
} else if (kind === "on_chat_model_stream") {
|
|
898
|
-
if (nested) continue;
|
|
899
|
-
const chunk = data.chunk;
|
|
900
|
-
if (!chunk) continue;
|
|
901
|
-
const content = chunk.content;
|
|
902
|
-
if (typeof content === "string" && content) {
|
|
903
|
-
emitText(content);
|
|
904
|
-
} else if (Array.isArray(content)) {
|
|
905
|
-
for (const block of content) {
|
|
906
|
-
if (block && typeof block === "object") {
|
|
907
|
-
const b = block;
|
|
908
|
-
if (b.type === "text" && b.text) emitText(b.text);
|
|
909
|
-
else if (b.type === "thinking" && b.thinking)
|
|
910
|
-
emitReasoning(b.thinking);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
const usage = chunk.usage_metadata;
|
|
915
|
-
if (usage) {
|
|
916
|
-
streamedStepInput = Math.max(
|
|
917
|
-
streamedStepInput,
|
|
918
|
-
usage.input_tokens ?? 0
|
|
919
|
-
);
|
|
920
|
-
streamedStepOutput = Math.max(
|
|
921
|
-
streamedStepOutput,
|
|
922
|
-
usage.output_tokens ?? 0
|
|
923
|
-
);
|
|
924
|
-
}
|
|
925
|
-
} else if (kind === "on_chat_model_end") {
|
|
926
|
-
const output = data.output;
|
|
927
|
-
const usage = output?.usage_metadata;
|
|
928
|
-
const stepInput = usage?.input_tokens ?? streamedStepInput;
|
|
929
|
-
const stepOutput = usage?.output_tokens ?? streamedStepOutput;
|
|
930
|
-
inputTokens += stepInput;
|
|
931
|
-
outputTokens += stepOutput;
|
|
932
|
-
streamedStepInput = 0;
|
|
933
|
-
streamedStepOutput = 0;
|
|
934
|
-
if (!nested) {
|
|
935
|
-
endTextBlock();
|
|
936
|
-
endReasoningBlock();
|
|
937
|
-
pendingStep = { input: stepInput, output: stepOutput };
|
|
938
|
-
}
|
|
939
|
-
} else if (kind === "on_tool_start") {
|
|
940
|
-
const toolName = event.name ?? "unknown";
|
|
941
|
-
const runId = event.run_id ?? "";
|
|
942
|
-
if (!nested && !hostToolNames.has(toolName)) {
|
|
943
|
-
const queued = approvedToolQueue.get(toolName);
|
|
944
|
-
if (queued && queued.length > 0) {
|
|
945
|
-
const approvalId = queued.shift();
|
|
946
|
-
if (runId) approvedRunIds.set(runId, approvalId);
|
|
947
|
-
} else {
|
|
948
|
-
endTextBlock();
|
|
949
|
-
endReasoningBlock();
|
|
950
|
-
emit({
|
|
951
|
-
type: "tool-call",
|
|
952
|
-
toolCallId: runId,
|
|
953
|
-
toolName: toCommonName2(toolName),
|
|
954
|
-
input: toToolCallInput(data.input),
|
|
955
|
-
providerExecuted: true,
|
|
956
|
-
nativeName: toolName
|
|
957
|
-
});
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
} else if (kind === "on_tool_end") {
|
|
961
|
-
const toolName = event.name ?? "unknown";
|
|
962
|
-
const runId = event.run_id ?? "";
|
|
963
|
-
if (!nested && !hostToolNames.has(toolName)) {
|
|
964
|
-
let output = data.output ?? "";
|
|
965
|
-
if (output && typeof output === "object" && "content" in output) {
|
|
966
|
-
output = output.content;
|
|
967
|
-
}
|
|
968
|
-
emit({
|
|
969
|
-
type: "tool-result",
|
|
970
|
-
toolCallId: approvedRunIds.get(runId) ?? runId,
|
|
971
|
-
toolName: toCommonName2(toolName),
|
|
972
|
-
result: output ?? null
|
|
973
|
-
});
|
|
974
|
-
approvedRunIds.delete(runId);
|
|
975
|
-
}
|
|
976
|
-
}
|
|
1042
|
+
emitStreamEvent(event);
|
|
977
1043
|
}
|
|
978
1044
|
const actionRequests = await readPendingApprovals();
|
|
979
1045
|
if (actionRequests.length === 0) break;
|
|
980
1046
|
const decisions = [];
|
|
981
1047
|
for (const action of actionRequests) {
|
|
982
|
-
const approvalId = `approval-${
|
|
983
|
-
endTextBlock();
|
|
984
|
-
endReasoningBlock();
|
|
1048
|
+
const approvalId = `approval-${randomUUID2()}`;
|
|
1049
|
+
endTextBlock({ state: streamEventState, emit });
|
|
1050
|
+
endReasoningBlock({ state: streamEventState, emit });
|
|
985
1051
|
emit({
|
|
986
1052
|
type: "tool-call",
|
|
987
1053
|
toolCallId: approvalId,
|
|
@@ -995,12 +1061,12 @@ async function runTurn(start, turn) {
|
|
|
995
1061
|
approvalId,
|
|
996
1062
|
toolCallId: approvalId
|
|
997
1063
|
});
|
|
998
|
-
flushStep();
|
|
1064
|
+
flushStep({ state: streamEventState, emit });
|
|
999
1065
|
const decision = await turn.requestToolApproval(approvalId);
|
|
1000
1066
|
if (decision.approved) {
|
|
1001
|
-
const queue = approvedToolQueue.get(action.name) ?? [];
|
|
1067
|
+
const queue = streamEventState.approvedToolQueue.get(action.name) ?? [];
|
|
1002
1068
|
queue.push(approvalId);
|
|
1003
|
-
approvedToolQueue.set(action.name, queue);
|
|
1069
|
+
streamEventState.approvedToolQueue.set(action.name, queue);
|
|
1004
1070
|
decisions.push({ type: "approve" });
|
|
1005
1071
|
} else {
|
|
1006
1072
|
emit({
|
|
@@ -1017,15 +1083,15 @@ async function runTurn(start, turn) {
|
|
|
1017
1083
|
}
|
|
1018
1084
|
resumeInput = new Command({ resume: { decisions } });
|
|
1019
1085
|
}
|
|
1020
|
-
endTextBlock();
|
|
1021
|
-
endReasoningBlock();
|
|
1022
|
-
flushStep();
|
|
1086
|
+
endTextBlock({ state: streamEventState, emit });
|
|
1087
|
+
endReasoningBlock({ state: streamEventState, emit });
|
|
1088
|
+
flushStep({ state: streamEventState, emit });
|
|
1023
1089
|
emit({
|
|
1024
1090
|
type: "finish",
|
|
1025
1091
|
finishReason: { unified: "stop" },
|
|
1026
1092
|
totalUsage: {
|
|
1027
|
-
inputTokens: { total: inputTokens },
|
|
1028
|
-
outputTokens: { total: outputTokens }
|
|
1093
|
+
inputTokens: { total: streamEventState.inputTokens },
|
|
1094
|
+
outputTokens: { total: streamEventState.outputTokens }
|
|
1029
1095
|
}
|
|
1030
1096
|
});
|
|
1031
1097
|
}
|