@ai-sdk/harness-deepagents 1.0.38 → 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 +19 -0
- package/dist/bridge/index.mjs +246 -173
- 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,24 @@
|
|
|
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
|
+
|
|
14
|
+
## 1.0.39
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Updated dependencies [59a2306]
|
|
19
|
+
- Updated dependencies [5f65e61]
|
|
20
|
+
- @ai-sdk/harness@1.0.40
|
|
21
|
+
|
|
3
22
|
## 1.0.38
|
|
4
23
|
|
|
5
24
|
### 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
|
|
@@ -57,6 +57,7 @@ async function runBridge(options) {
|
|
|
57
57
|
let currentBoundPort = 0;
|
|
58
58
|
let currentTurnState = "init";
|
|
59
59
|
let activeSocket;
|
|
60
|
+
let activeSocketReadyForLiveEvents = false;
|
|
60
61
|
let isFirstTurn = true;
|
|
61
62
|
let turnAbort;
|
|
62
63
|
let currentUserMessages;
|
|
@@ -156,7 +157,7 @@ async function runBridge(options) {
|
|
|
156
157
|
diskBuffer += `${line}
|
|
157
158
|
`;
|
|
158
159
|
scheduleEventFlush();
|
|
159
|
-
if (activeSocket?.readyState === WS_OPEN) {
|
|
160
|
+
if (activeSocketReadyForLiveEvents && activeSocket?.readyState === WS_OPEN) {
|
|
160
161
|
try {
|
|
161
162
|
activeSocket.send(line);
|
|
162
163
|
} catch {
|
|
@@ -259,6 +260,8 @@ async function runBridge(options) {
|
|
|
259
260
|
const handleInbound = async (msg, ws) => {
|
|
260
261
|
switch (msg.type) {
|
|
261
262
|
case "start": {
|
|
263
|
+
if (activeSocket !== ws) return;
|
|
264
|
+
activeSocketReadyForLiveEvents = true;
|
|
262
265
|
const firstTurn = isFirstTurn;
|
|
263
266
|
isFirstTurn = false;
|
|
264
267
|
eventLog = [];
|
|
@@ -361,7 +364,9 @@ async function runBridge(options) {
|
|
|
361
364
|
}
|
|
362
365
|
return;
|
|
363
366
|
case "resume":
|
|
367
|
+
if (activeSocket !== ws) return;
|
|
364
368
|
replay(ws, msg.lastSeenEventId);
|
|
369
|
+
activeSocketReadyForLiveEvents = true;
|
|
365
370
|
return;
|
|
366
371
|
case "shutdown":
|
|
367
372
|
currentTurnState = "done";
|
|
@@ -426,6 +431,7 @@ async function runBridge(options) {
|
|
|
426
431
|
return;
|
|
427
432
|
}
|
|
428
433
|
activeSocket = ws;
|
|
434
|
+
activeSocketReadyForLiveEvents = false;
|
|
429
435
|
sendControl({
|
|
430
436
|
type: "bridge-hello",
|
|
431
437
|
state: currentTurnState,
|
|
@@ -448,6 +454,7 @@ async function runBridge(options) {
|
|
|
448
454
|
ws.on("close", () => {
|
|
449
455
|
if (activeSocket === ws) {
|
|
450
456
|
activeSocket = void 0;
|
|
457
|
+
activeSocketReadyForLiveEvents = false;
|
|
451
458
|
}
|
|
452
459
|
});
|
|
453
460
|
ws.on("error", () => {
|
|
@@ -541,6 +548,222 @@ function collectActionRequests(interrupts) {
|
|
|
541
548
|
return out;
|
|
542
549
|
}
|
|
543
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
|
+
|
|
544
767
|
// src/bridge/json-schema-to-zod.ts
|
|
545
768
|
import { z } from "zod/v4";
|
|
546
769
|
function jsonSchemaToZodObject(input) {
|
|
@@ -685,16 +908,7 @@ function createBuiltinToolFilteringMiddleware(input) {
|
|
|
685
908
|
}
|
|
686
909
|
|
|
687
910
|
// src/bridge/index.ts
|
|
688
|
-
var NATIVE_TO_COMMON2 = {
|
|
689
|
-
read_file: "read",
|
|
690
|
-
write_file: "write",
|
|
691
|
-
edit_file: "edit",
|
|
692
|
-
execute: "bash"
|
|
693
|
-
};
|
|
694
911
|
var HARNESS_CLIENT_APP = procEnv2.AI_SDK_HARNESS_CLIENT_APP;
|
|
695
|
-
function toCommonName2(nativeName) {
|
|
696
|
-
return NATIVE_TO_COMMON2[nativeName] ?? nativeName;
|
|
697
|
-
}
|
|
698
912
|
function parseArgs(rawArgs) {
|
|
699
913
|
const out = {};
|
|
700
914
|
for (let i = 0; i < rawArgs.length; i++) {
|
|
@@ -725,13 +939,6 @@ function buildModel(rawModel) {
|
|
|
725
939
|
} : {}
|
|
726
940
|
});
|
|
727
941
|
}
|
|
728
|
-
function toToolCallInput(raw) {
|
|
729
|
-
if (raw && typeof raw === "object" && !Array.isArray(raw) && Object.keys(raw).length === 1 && typeof raw.input === "string") {
|
|
730
|
-
const inner = raw.input;
|
|
731
|
-
if (/^\s*[[{]/.test(inner)) return inner;
|
|
732
|
-
}
|
|
733
|
-
return JSON.stringify(raw ?? {});
|
|
734
|
-
}
|
|
735
942
|
var args = parseArgs(argv.slice(2));
|
|
736
943
|
var workdir = args.workdir;
|
|
737
944
|
var bridgeStateDir = args.bridgeStateDir;
|
|
@@ -747,7 +954,7 @@ function buildHostTools(toolSchemas) {
|
|
|
747
954
|
async (input) => {
|
|
748
955
|
const turn = currentTurn;
|
|
749
956
|
if (!turn) throw new Error("no active turn");
|
|
750
|
-
const toolCallId = `${schema.name}-${
|
|
957
|
+
const toolCallId = `${schema.name}-${randomUUID2()}`;
|
|
751
958
|
turn.emit({
|
|
752
959
|
type: "tool-call",
|
|
753
960
|
toolCallId,
|
|
@@ -800,67 +1007,18 @@ async function runTurn(start, turn) {
|
|
|
800
1007
|
checkpointer: new MemorySaver()
|
|
801
1008
|
});
|
|
802
1009
|
}
|
|
803
|
-
emit({
|
|
804
|
-
type: "stream-start",
|
|
805
|
-
...start.model ? { modelId: start.model } : {}
|
|
806
|
-
});
|
|
807
1010
|
const hostToolNames = new Set((start.tools ?? []).map((t) => t.name));
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
const approvedToolQueue = /* @__PURE__ */ new Map();
|
|
816
|
-
const approvedRunIds = /* @__PURE__ */ new Map();
|
|
817
|
-
const ensureTextBlock = () => {
|
|
818
|
-
if (!textBlockId) {
|
|
819
|
-
textBlockId = `text-${randomUUID()}`;
|
|
820
|
-
emit({ type: "text-start", id: textBlockId });
|
|
821
|
-
}
|
|
822
|
-
return textBlockId;
|
|
823
|
-
};
|
|
824
|
-
const endTextBlock = () => {
|
|
825
|
-
if (textBlockId) {
|
|
826
|
-
emit({ type: "text-end", id: textBlockId });
|
|
827
|
-
textBlockId = void 0;
|
|
828
|
-
}
|
|
829
|
-
};
|
|
830
|
-
const endReasoningBlock = () => {
|
|
831
|
-
if (reasoningBlockId) {
|
|
832
|
-
emit({ type: "reasoning-end", id: reasoningBlockId });
|
|
833
|
-
reasoningBlockId = void 0;
|
|
834
|
-
}
|
|
835
|
-
};
|
|
836
|
-
const emitText = (delta) => {
|
|
837
|
-
endReasoningBlock();
|
|
838
|
-
emit({ type: "text-delta", id: ensureTextBlock(), delta });
|
|
839
|
-
};
|
|
840
|
-
const emitReasoning = (delta) => {
|
|
841
|
-
endTextBlock();
|
|
842
|
-
if (!reasoningBlockId) {
|
|
843
|
-
reasoningBlockId = `reasoning-${randomUUID()}`;
|
|
844
|
-
emit({ type: "reasoning-start", id: reasoningBlockId });
|
|
845
|
-
}
|
|
846
|
-
emit({ type: "reasoning-delta", id: reasoningBlockId, delta });
|
|
847
|
-
};
|
|
848
|
-
const flushStep = () => {
|
|
849
|
-
if (!pendingStep) return;
|
|
850
|
-
emit({
|
|
851
|
-
type: "finish-step",
|
|
852
|
-
finishReason: { unified: "stop" },
|
|
853
|
-
usage: {
|
|
854
|
-
inputTokens: { total: pendingStep.input },
|
|
855
|
-
outputTokens: { total: pendingStep.output }
|
|
856
|
-
}
|
|
857
|
-
});
|
|
858
|
-
pendingStep = void 0;
|
|
859
|
-
};
|
|
1011
|
+
const streamEventState = createDeepAgentsStreamEventState();
|
|
1012
|
+
const emitStreamEvent = createEmitStreamEvent({
|
|
1013
|
+
state: streamEventState,
|
|
1014
|
+
configuredModel: start.model,
|
|
1015
|
+
hostToolNames,
|
|
1016
|
+
emit
|
|
1017
|
+
});
|
|
860
1018
|
const config = {
|
|
861
1019
|
version: "v2",
|
|
862
1020
|
configurable: { thread_id: "bridge-session" },
|
|
863
|
-
recursionLimit: start.recursionLimit
|
|
1021
|
+
...start.recursionLimit != null ? { recursionLimit: start.recursionLimit } : {},
|
|
864
1022
|
signal: turn.abortSignal
|
|
865
1023
|
};
|
|
866
1024
|
const readPendingApprovals = async () => {
|
|
@@ -881,100 +1039,15 @@ async function runTurn(start, turn) {
|
|
|
881
1039
|
while (true) {
|
|
882
1040
|
const stream = await agent.streamEvents(resumeInput, config);
|
|
883
1041
|
for await (const event of stream) {
|
|
884
|
-
|
|
885
|
-
const data = event.data ?? {};
|
|
886
|
-
const ns = event.metadata?.langgraph_checkpoint_ns ?? "";
|
|
887
|
-
const nested = ns.includes("|");
|
|
888
|
-
if (kind === "on_chat_model_start") {
|
|
889
|
-
if (!nested) flushStep();
|
|
890
|
-
} else if (kind === "on_chat_model_stream") {
|
|
891
|
-
if (nested) continue;
|
|
892
|
-
const chunk = data.chunk;
|
|
893
|
-
if (!chunk) continue;
|
|
894
|
-
const content = chunk.content;
|
|
895
|
-
if (typeof content === "string" && content) {
|
|
896
|
-
emitText(content);
|
|
897
|
-
} else if (Array.isArray(content)) {
|
|
898
|
-
for (const block of content) {
|
|
899
|
-
if (block && typeof block === "object") {
|
|
900
|
-
const b = block;
|
|
901
|
-
if (b.type === "text" && b.text) emitText(b.text);
|
|
902
|
-
else if (b.type === "thinking" && b.thinking)
|
|
903
|
-
emitReasoning(b.thinking);
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
const usage = chunk.usage_metadata;
|
|
908
|
-
if (usage) {
|
|
909
|
-
streamedStepInput = Math.max(
|
|
910
|
-
streamedStepInput,
|
|
911
|
-
usage.input_tokens ?? 0
|
|
912
|
-
);
|
|
913
|
-
streamedStepOutput = Math.max(
|
|
914
|
-
streamedStepOutput,
|
|
915
|
-
usage.output_tokens ?? 0
|
|
916
|
-
);
|
|
917
|
-
}
|
|
918
|
-
} else if (kind === "on_chat_model_end") {
|
|
919
|
-
const output = data.output;
|
|
920
|
-
const usage = output?.usage_metadata;
|
|
921
|
-
const stepInput = usage?.input_tokens ?? streamedStepInput;
|
|
922
|
-
const stepOutput = usage?.output_tokens ?? streamedStepOutput;
|
|
923
|
-
inputTokens += stepInput;
|
|
924
|
-
outputTokens += stepOutput;
|
|
925
|
-
streamedStepInput = 0;
|
|
926
|
-
streamedStepOutput = 0;
|
|
927
|
-
if (!nested) {
|
|
928
|
-
endTextBlock();
|
|
929
|
-
endReasoningBlock();
|
|
930
|
-
pendingStep = { input: stepInput, output: stepOutput };
|
|
931
|
-
}
|
|
932
|
-
} else if (kind === "on_tool_start") {
|
|
933
|
-
const toolName = event.name ?? "unknown";
|
|
934
|
-
const runId = event.run_id ?? "";
|
|
935
|
-
if (!nested && !hostToolNames.has(toolName)) {
|
|
936
|
-
const queued = approvedToolQueue.get(toolName);
|
|
937
|
-
if (queued && queued.length > 0) {
|
|
938
|
-
const approvalId = queued.shift();
|
|
939
|
-
if (runId) approvedRunIds.set(runId, approvalId);
|
|
940
|
-
} else {
|
|
941
|
-
endTextBlock();
|
|
942
|
-
endReasoningBlock();
|
|
943
|
-
emit({
|
|
944
|
-
type: "tool-call",
|
|
945
|
-
toolCallId: runId,
|
|
946
|
-
toolName: toCommonName2(toolName),
|
|
947
|
-
input: toToolCallInput(data.input),
|
|
948
|
-
providerExecuted: true,
|
|
949
|
-
nativeName: toolName
|
|
950
|
-
});
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
} else if (kind === "on_tool_end") {
|
|
954
|
-
const toolName = event.name ?? "unknown";
|
|
955
|
-
const runId = event.run_id ?? "";
|
|
956
|
-
if (!nested && !hostToolNames.has(toolName)) {
|
|
957
|
-
let output = data.output ?? "";
|
|
958
|
-
if (output && typeof output === "object" && "content" in output) {
|
|
959
|
-
output = output.content;
|
|
960
|
-
}
|
|
961
|
-
emit({
|
|
962
|
-
type: "tool-result",
|
|
963
|
-
toolCallId: approvedRunIds.get(runId) ?? runId,
|
|
964
|
-
toolName: toCommonName2(toolName),
|
|
965
|
-
result: output ?? null
|
|
966
|
-
});
|
|
967
|
-
approvedRunIds.delete(runId);
|
|
968
|
-
}
|
|
969
|
-
}
|
|
1042
|
+
emitStreamEvent(event);
|
|
970
1043
|
}
|
|
971
1044
|
const actionRequests = await readPendingApprovals();
|
|
972
1045
|
if (actionRequests.length === 0) break;
|
|
973
1046
|
const decisions = [];
|
|
974
1047
|
for (const action of actionRequests) {
|
|
975
|
-
const approvalId = `approval-${
|
|
976
|
-
endTextBlock();
|
|
977
|
-
endReasoningBlock();
|
|
1048
|
+
const approvalId = `approval-${randomUUID2()}`;
|
|
1049
|
+
endTextBlock({ state: streamEventState, emit });
|
|
1050
|
+
endReasoningBlock({ state: streamEventState, emit });
|
|
978
1051
|
emit({
|
|
979
1052
|
type: "tool-call",
|
|
980
1053
|
toolCallId: approvalId,
|
|
@@ -988,12 +1061,12 @@ async function runTurn(start, turn) {
|
|
|
988
1061
|
approvalId,
|
|
989
1062
|
toolCallId: approvalId
|
|
990
1063
|
});
|
|
991
|
-
flushStep();
|
|
1064
|
+
flushStep({ state: streamEventState, emit });
|
|
992
1065
|
const decision = await turn.requestToolApproval(approvalId);
|
|
993
1066
|
if (decision.approved) {
|
|
994
|
-
const queue = approvedToolQueue.get(action.name) ?? [];
|
|
1067
|
+
const queue = streamEventState.approvedToolQueue.get(action.name) ?? [];
|
|
995
1068
|
queue.push(approvalId);
|
|
996
|
-
approvedToolQueue.set(action.name, queue);
|
|
1069
|
+
streamEventState.approvedToolQueue.set(action.name, queue);
|
|
997
1070
|
decisions.push({ type: "approve" });
|
|
998
1071
|
} else {
|
|
999
1072
|
emit({
|
|
@@ -1010,15 +1083,15 @@ async function runTurn(start, turn) {
|
|
|
1010
1083
|
}
|
|
1011
1084
|
resumeInput = new Command({ resume: { decisions } });
|
|
1012
1085
|
}
|
|
1013
|
-
endTextBlock();
|
|
1014
|
-
endReasoningBlock();
|
|
1015
|
-
flushStep();
|
|
1086
|
+
endTextBlock({ state: streamEventState, emit });
|
|
1087
|
+
endReasoningBlock({ state: streamEventState, emit });
|
|
1088
|
+
flushStep({ state: streamEventState, emit });
|
|
1016
1089
|
emit({
|
|
1017
1090
|
type: "finish",
|
|
1018
1091
|
finishReason: { unified: "stop" },
|
|
1019
1092
|
totalUsage: {
|
|
1020
|
-
inputTokens: { total: inputTokens },
|
|
1021
|
-
outputTokens: { total: outputTokens }
|
|
1093
|
+
inputTokens: { total: streamEventState.inputTokens },
|
|
1094
|
+
outputTokens: { total: streamEventState.outputTokens }
|
|
1022
1095
|
}
|
|
1023
1096
|
});
|
|
1024
1097
|
}
|