@blade-hq/agent-kit 1.0.27 → 1.0.28
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/dist/{chunk-X2NJKKXR.js → chunk-BGNKHPCD.js} +213 -40
- package/dist/chunk-BGNKHPCD.js.map +1 -0
- package/dist/{chunk-M72OL7ZJ.js → chunk-HCQDDDOX.js} +2 -2
- package/dist/{chunk-TE6G6NVX.js → chunk-OGHUIKCY.js} +3 -3
- package/dist/{chunk-C2FKVGJU.js → chunk-PYYDXV2A.js} +2 -2
- package/dist/{chunk-JU5SL4HP.js → chunk-TVWC3PED.js} +2 -2
- package/dist/{chunk-SBASG3M2.js → chunk-UWNQ4PXK.js} +4 -1101
- package/dist/chunk-UWNQ4PXK.js.map +1 -0
- package/dist/{chunk-34GDDOWY.js → chunk-YJ6BX3FU.js} +1379 -31
- package/dist/chunk-YJ6BX3FU.js.map +1 -0
- package/dist/client/blade-client.d.ts +2 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js +3 -1
- package/dist/client/resources/app-dev-templates.d.ts +93 -0
- package/dist/client/resources/models.d.ts +3 -0
- package/dist/{react → client/shared}/projection/builder.d.ts +1 -1
- package/dist/{react → client/shared}/projection/helpers.d.ts +1 -1
- package/dist/client/shared/projection/history.d.ts +12 -0
- package/dist/{react → client/shared}/projection/index.d.ts +1 -0
- package/dist/{react → client/shared}/projection/state.d.ts +1 -1
- package/dist/client/types/index.d.ts +2 -2
- package/dist/client/types/rest.d.ts +1010 -29
- package/dist/client/types/socket-events.d.ts +18 -132
- package/dist/react/api/app-dev-templates.d.ts +5 -0
- package/dist/react/api/model-config.d.ts +68 -0
- package/dist/react/api/models.d.ts +2 -0
- package/dist/react/api/published-apps.js +3 -3
- package/dist/react/api/sessions.js +2 -2
- package/dist/react/components/chat/ChatView.d.ts +3 -1
- package/dist/react/components/chat/MessageList.d.ts +3 -1
- package/dist/react/components/chat/index.js +5 -5
- package/dist/react/components/chat/scroll-anchor.d.ts +8 -0
- package/dist/react/components/plan/index.js +4 -4
- package/dist/react/components/session/index.js +3 -3
- package/dist/react/components/workspace/index.js +3 -3
- package/dist/react/hooks/use-model-preferences.d.ts +1 -0
- package/dist/react/hooks/use-resolved-model.d.ts +1 -0
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.js +87 -7
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-34GDDOWY.js.map +0 -1
- package/dist/chunk-SBASG3M2.js.map +0 -1
- package/dist/chunk-X2NJKKXR.js.map +0 -1
- /package/dist/{chunk-M72OL7ZJ.js.map → chunk-HCQDDDOX.js.map} +0 -0
- /package/dist/{chunk-TE6G6NVX.js.map → chunk-OGHUIKCY.js.map} +0 -0
- /package/dist/{chunk-C2FKVGJU.js.map → chunk-PYYDXV2A.js.map} +0 -0
- /package/dist/{chunk-JU5SL4HP.js.map → chunk-TVWC3PED.js.map} +0 -0
|
@@ -2,8 +2,9 @@ import {
|
|
|
2
2
|
tapBridgeEvent
|
|
3
3
|
} from "./chunk-J3XVFPOV.js";
|
|
4
4
|
import {
|
|
5
|
-
BladeClient
|
|
6
|
-
|
|
5
|
+
BladeClient,
|
|
6
|
+
ClientProjectionBuilder
|
|
7
|
+
} from "./chunk-YJ6BX3FU.js";
|
|
7
8
|
import {
|
|
8
9
|
createClientActions,
|
|
9
10
|
useCardStateStore
|
|
@@ -618,1104 +619,6 @@ function isUiMeta(value) {
|
|
|
618
619
|
return true;
|
|
619
620
|
}
|
|
620
621
|
|
|
621
|
-
// src/react/projection/helpers.ts
|
|
622
|
-
function upsertToolCall(state, toolCallId, toolName, displayName, args) {
|
|
623
|
-
if (!toolCallId) return;
|
|
624
|
-
let found = false;
|
|
625
|
-
for (let i = 0; i < state.toolCalls.length; i++) {
|
|
626
|
-
if (state.toolCalls[i].id !== toolCallId) continue;
|
|
627
|
-
const tc = state.toolCalls[i];
|
|
628
|
-
state.toolCalls[i] = {
|
|
629
|
-
...tc,
|
|
630
|
-
tool_name: toolName || tc.tool_name,
|
|
631
|
-
display_name: displayName || tc.display_name,
|
|
632
|
-
arguments: args || tc.arguments
|
|
633
|
-
};
|
|
634
|
-
found = true;
|
|
635
|
-
break;
|
|
636
|
-
}
|
|
637
|
-
if (!found) {
|
|
638
|
-
state.toolCalls.push({
|
|
639
|
-
id: toolCallId,
|
|
640
|
-
tool_name: toolName,
|
|
641
|
-
display_name: displayName,
|
|
642
|
-
arguments: args,
|
|
643
|
-
status: "pending"
|
|
644
|
-
});
|
|
645
|
-
}
|
|
646
|
-
let blockFound = false;
|
|
647
|
-
for (let i = 0; i < state.blocks.length; i++) {
|
|
648
|
-
const b = state.blocks[i];
|
|
649
|
-
if (b.type !== "tool_use" || b.tool_call_id !== toolCallId) continue;
|
|
650
|
-
state.blocks[i] = {
|
|
651
|
-
...b,
|
|
652
|
-
content: args || b.content,
|
|
653
|
-
tool_name: toolName || b.tool_name,
|
|
654
|
-
display_name: displayName || b.display_name
|
|
655
|
-
};
|
|
656
|
-
blockFound = true;
|
|
657
|
-
break;
|
|
658
|
-
}
|
|
659
|
-
if (!blockFound) {
|
|
660
|
-
state.blocks.push({
|
|
661
|
-
type: "tool_use",
|
|
662
|
-
content: args,
|
|
663
|
-
tool_call_id: toolCallId,
|
|
664
|
-
tool_name: toolName || null,
|
|
665
|
-
display_name: displayName || null
|
|
666
|
-
});
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
function applyToolResult(state, toolCallId, result, status, durationMs, sourceLoop) {
|
|
670
|
-
let toolName = "";
|
|
671
|
-
let displayName = "";
|
|
672
|
-
let finalResult = result;
|
|
673
|
-
for (let i = 0; i < state.toolCalls.length; i++) {
|
|
674
|
-
const tc = state.toolCalls[i];
|
|
675
|
-
if (tc.id !== toolCallId) continue;
|
|
676
|
-
if (typeof result === "string") {
|
|
677
|
-
finalResult = maybeEnrichAskUserResult(tc.tool_name, result, sourceLoop);
|
|
678
|
-
}
|
|
679
|
-
const update = { status, result: finalResult };
|
|
680
|
-
if (durationMs != null) update.duration_ms = durationMs;
|
|
681
|
-
state.toolCalls[i] = { ...tc, ...update };
|
|
682
|
-
toolName = tc.tool_name;
|
|
683
|
-
displayName = tc.display_name;
|
|
684
|
-
break;
|
|
685
|
-
}
|
|
686
|
-
upsertToolResultBlock(state, toolCallId, finalResult, toolName, displayName);
|
|
687
|
-
}
|
|
688
|
-
function appendToolResultDelta(state, toolCallId, delta) {
|
|
689
|
-
if (!toolCallId || !delta) return;
|
|
690
|
-
let toolName = "";
|
|
691
|
-
let displayName = "";
|
|
692
|
-
let currentResult = "";
|
|
693
|
-
for (let i = 0; i < state.toolCalls.length; i++) {
|
|
694
|
-
const tc = state.toolCalls[i];
|
|
695
|
-
if (tc.id !== toolCallId) continue;
|
|
696
|
-
toolName = tc.tool_name;
|
|
697
|
-
displayName = tc.display_name;
|
|
698
|
-
if (typeof tc.result === "string") currentResult = tc.result;
|
|
699
|
-
state.toolCalls[i] = { ...tc, result: currentResult + delta };
|
|
700
|
-
break;
|
|
701
|
-
}
|
|
702
|
-
for (const block of state.blocks) {
|
|
703
|
-
if (block.type !== "tool_result" || block.tool_call_id !== toolCallId) continue;
|
|
704
|
-
if (typeof block.content === "string") currentResult = block.content;
|
|
705
|
-
break;
|
|
706
|
-
}
|
|
707
|
-
upsertToolResultBlock(state, toolCallId, currentResult + delta, toolName, displayName);
|
|
708
|
-
}
|
|
709
|
-
function upsertToolResultBlock(state, toolCallId, content, toolName, displayName) {
|
|
710
|
-
for (let i = 0; i < state.blocks.length; i++) {
|
|
711
|
-
const block = state.blocks[i];
|
|
712
|
-
if (block.type !== "tool_result" || block.tool_call_id !== toolCallId) continue;
|
|
713
|
-
state.blocks[i] = {
|
|
714
|
-
...block,
|
|
715
|
-
content,
|
|
716
|
-
tool_name: toolName || block.tool_name,
|
|
717
|
-
display_name: displayName || block.display_name
|
|
718
|
-
};
|
|
719
|
-
return;
|
|
720
|
-
}
|
|
721
|
-
state.blocks.push({
|
|
722
|
-
type: "tool_result",
|
|
723
|
-
content,
|
|
724
|
-
tool_call_id: toolCallId,
|
|
725
|
-
tool_name: toolName || null,
|
|
726
|
-
display_name: displayName || null
|
|
727
|
-
});
|
|
728
|
-
}
|
|
729
|
-
function appendTextBlock(state, blockType, content) {
|
|
730
|
-
if (content == null || content === "") return;
|
|
731
|
-
const text = String(content);
|
|
732
|
-
const lastBlock = state.blocks[state.blocks.length - 1];
|
|
733
|
-
if (lastBlock && lastBlock.type === blockType && typeof lastBlock.content === "string") {
|
|
734
|
-
state.blocks[state.blocks.length - 1] = {
|
|
735
|
-
...lastBlock,
|
|
736
|
-
content: lastBlock.content + text
|
|
737
|
-
};
|
|
738
|
-
return;
|
|
739
|
-
}
|
|
740
|
-
state.blocks.push({ type: blockType, content: text });
|
|
741
|
-
}
|
|
742
|
-
function appendToolCallArguments(state, toolCallId, delta) {
|
|
743
|
-
let newArgs = "";
|
|
744
|
-
for (let i = 0; i < state.toolCalls.length; i++) {
|
|
745
|
-
const tc = state.toolCalls[i];
|
|
746
|
-
if (tc.id === toolCallId) {
|
|
747
|
-
newArgs = tc.arguments + delta;
|
|
748
|
-
state.toolCalls[i] = { ...tc, arguments: newArgs };
|
|
749
|
-
break;
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
if (!newArgs) return;
|
|
753
|
-
for (let i = 0; i < state.blocks.length; i++) {
|
|
754
|
-
const b = state.blocks[i];
|
|
755
|
-
if (b.type === "tool_use" && b.tool_call_id === toolCallId) {
|
|
756
|
-
state.blocks[i] = { ...b, content: newArgs };
|
|
757
|
-
break;
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
function maybeEnrichAskUserResult(toolName, result, sourceLoop) {
|
|
762
|
-
if (!sourceLoop) return result;
|
|
763
|
-
const normalized = toolName.includes(":") ? toolName.split(":").pop() : toolName;
|
|
764
|
-
if (normalized !== "AskUserQuestion") return result;
|
|
765
|
-
try {
|
|
766
|
-
const payload = JSON.parse(result);
|
|
767
|
-
if (typeof payload !== "object" || payload === null) return result;
|
|
768
|
-
payload.source_loop = sourceLoop;
|
|
769
|
-
return JSON.stringify(payload);
|
|
770
|
-
} catch {
|
|
771
|
-
return result;
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
function buildSystemNotificationTurn(sequence, turnId, loopId, notificationType, status, title, detail, metadata) {
|
|
775
|
-
return {
|
|
776
|
-
id: turnId,
|
|
777
|
-
sequence,
|
|
778
|
-
turn_id: turnId,
|
|
779
|
-
loop_id: loopId,
|
|
780
|
-
kind: "message",
|
|
781
|
-
role: "system",
|
|
782
|
-
status: "completed",
|
|
783
|
-
blocks: [
|
|
784
|
-
{
|
|
785
|
-
type: "system_notification",
|
|
786
|
-
content: {
|
|
787
|
-
notification_type: notificationType,
|
|
788
|
-
status,
|
|
789
|
-
title,
|
|
790
|
-
detail,
|
|
791
|
-
metadata
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
],
|
|
795
|
-
tool_calls: [],
|
|
796
|
-
model: null,
|
|
797
|
-
usage: null,
|
|
798
|
-
duration_ms: 0
|
|
799
|
-
};
|
|
800
|
-
}
|
|
801
|
-
function buildSystemNotificationBlock(notificationType, status, title, detail, metadata) {
|
|
802
|
-
return {
|
|
803
|
-
type: "system_notification",
|
|
804
|
-
content: {
|
|
805
|
-
notification_type: notificationType,
|
|
806
|
-
status,
|
|
807
|
-
title,
|
|
808
|
-
detail,
|
|
809
|
-
metadata
|
|
810
|
-
}
|
|
811
|
-
};
|
|
812
|
-
}
|
|
813
|
-
function buildMarkerTurn(sequence, turnId, loopId, blockType, content) {
|
|
814
|
-
return {
|
|
815
|
-
id: turnId,
|
|
816
|
-
sequence,
|
|
817
|
-
turn_id: turnId,
|
|
818
|
-
loop_id: loopId,
|
|
819
|
-
kind: "message",
|
|
820
|
-
role: "assistant",
|
|
821
|
-
status: "completed",
|
|
822
|
-
blocks: [{ type: blockType, content }],
|
|
823
|
-
tool_calls: [],
|
|
824
|
-
model: null,
|
|
825
|
-
usage: null,
|
|
826
|
-
duration_ms: 0
|
|
827
|
-
};
|
|
828
|
-
}
|
|
829
|
-
function buildCompactionTurn(sequence, compactionId, loopId, status, data) {
|
|
830
|
-
const tokensBefore = asInt(data.tokens_before);
|
|
831
|
-
const tokensAfter = asInt(data.tokens_after);
|
|
832
|
-
let savedRatio = null;
|
|
833
|
-
if (tokensBefore && tokensBefore > 0 && tokensAfter != null) {
|
|
834
|
-
savedRatio = 1 - tokensAfter / tokensBefore;
|
|
835
|
-
} else {
|
|
836
|
-
savedRatio = asFloat(data.saved_ratio);
|
|
837
|
-
}
|
|
838
|
-
let archivedCount = asInt(data.archived_count);
|
|
839
|
-
if (archivedCount == null && Array.isArray(data.archived_files)) {
|
|
840
|
-
archivedCount = data.archived_files.length;
|
|
841
|
-
}
|
|
842
|
-
const content = data.content;
|
|
843
|
-
const summaryFull = compactionSummaryFull(content);
|
|
844
|
-
const summaryPreview = summaryFull ? summaryFull.split("\n").map((l) => l.trim()).filter(Boolean).join(" ").slice(0, 200) : null;
|
|
845
|
-
return {
|
|
846
|
-
id: `compaction:${compactionId}`,
|
|
847
|
-
sequence,
|
|
848
|
-
turn_id: `compaction:${compactionId}`,
|
|
849
|
-
loop_id: loopId,
|
|
850
|
-
kind: "compaction",
|
|
851
|
-
role: "system",
|
|
852
|
-
status,
|
|
853
|
-
blocks: [],
|
|
854
|
-
tool_calls: [],
|
|
855
|
-
model: null,
|
|
856
|
-
usage: null,
|
|
857
|
-
duration_ms: 0,
|
|
858
|
-
compaction_id: compactionId,
|
|
859
|
-
summary_preview: summaryPreview,
|
|
860
|
-
summary_full: summaryFull,
|
|
861
|
-
archived_count: archivedCount,
|
|
862
|
-
tokens_before: tokensBefore,
|
|
863
|
-
tokens_after: tokensAfter,
|
|
864
|
-
saved_ratio: savedRatio,
|
|
865
|
-
trigger: asTrigger(data.trigger),
|
|
866
|
-
failure_reason: typeof data.reason === "string" && data.reason ? data.reason : null,
|
|
867
|
-
fallback_applied: typeof data.fallback_applied === "boolean" ? data.fallback_applied : null
|
|
868
|
-
};
|
|
869
|
-
}
|
|
870
|
-
function compactionSummaryFull(content) {
|
|
871
|
-
const text = String(content ?? "");
|
|
872
|
-
if (!text) return null;
|
|
873
|
-
const cleaned = text.replace("<compaction-summary>", "").replace("</compaction-summary>", "").replace(/\r\n/g, "\n").replace(/\r/g, "\n").trim();
|
|
874
|
-
return cleaned || null;
|
|
875
|
-
}
|
|
876
|
-
function asInt(value) {
|
|
877
|
-
if (typeof value === "boolean") return null;
|
|
878
|
-
if (typeof value === "number") return Math.trunc(value);
|
|
879
|
-
return null;
|
|
880
|
-
}
|
|
881
|
-
function asFloat(value) {
|
|
882
|
-
if (typeof value === "boolean") return null;
|
|
883
|
-
if (typeof value === "number") return value;
|
|
884
|
-
return null;
|
|
885
|
-
}
|
|
886
|
-
function asTrigger(value) {
|
|
887
|
-
if (value === "auto" || value === "manual" || value === "forced_retry") return value;
|
|
888
|
-
return null;
|
|
889
|
-
}
|
|
890
|
-
function setToolCallStatus(turn, toolCallId, status, result, pendingQuestionRef) {
|
|
891
|
-
if (!turn || !toolCallId) return;
|
|
892
|
-
const toolCalls = "toolCalls" in turn ? turn.toolCalls : turn.tool_calls;
|
|
893
|
-
for (let i = 0; i < toolCalls.length; i++) {
|
|
894
|
-
if (toolCalls[i].id !== toolCallId) continue;
|
|
895
|
-
toolCalls[i] = {
|
|
896
|
-
...toolCalls[i],
|
|
897
|
-
status,
|
|
898
|
-
result,
|
|
899
|
-
pending_question_ref: pendingQuestionRef
|
|
900
|
-
};
|
|
901
|
-
return;
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
function applyAskUserPauseToTurn(turn, pauseToolData, toolCallId, childLoopName, description, displayNameResolver) {
|
|
905
|
-
if (!turn || !toolCallId) return;
|
|
906
|
-
const sourceLoop = childLoopName ? { loop_name: childLoopName, description } : null;
|
|
907
|
-
const toolName = String(pauseToolData.name ?? "AskUserQuestion");
|
|
908
|
-
const args = JSON.stringify(pauseToolData.arguments ?? {});
|
|
909
|
-
const result = askUserResultFromPausePayload(pauseToolData, sourceLoop);
|
|
910
|
-
const isTurnState = "toolCalls" in turn;
|
|
911
|
-
const toolCalls = isTurnState ? turn.toolCalls : turn.tool_calls;
|
|
912
|
-
const blocks = turn.blocks;
|
|
913
|
-
const displayName = displayNameResolver(toolName);
|
|
914
|
-
let found = false;
|
|
915
|
-
for (let i = 0; i < toolCalls.length; i++) {
|
|
916
|
-
if (toolCalls[i].id !== toolCallId) continue;
|
|
917
|
-
toolCalls[i] = {
|
|
918
|
-
...toolCalls[i],
|
|
919
|
-
tool_name: toolName || toolCalls[i].tool_name,
|
|
920
|
-
display_name: displayName || toolCalls[i].display_name,
|
|
921
|
-
arguments: args || toolCalls[i].arguments
|
|
922
|
-
};
|
|
923
|
-
found = true;
|
|
924
|
-
break;
|
|
925
|
-
}
|
|
926
|
-
if (!found) {
|
|
927
|
-
toolCalls.push({
|
|
928
|
-
id: toolCallId,
|
|
929
|
-
tool_name: toolName,
|
|
930
|
-
display_name: displayName,
|
|
931
|
-
arguments: args,
|
|
932
|
-
status: "pending"
|
|
933
|
-
});
|
|
934
|
-
}
|
|
935
|
-
let blockFound = false;
|
|
936
|
-
for (let i = 0; i < blocks.length; i++) {
|
|
937
|
-
if (blocks[i].type !== "tool_use" || blocks[i].tool_call_id !== toolCallId) continue;
|
|
938
|
-
blocks[i] = { ...blocks[i], content: args, tool_name: toolName, display_name: displayName };
|
|
939
|
-
blockFound = true;
|
|
940
|
-
break;
|
|
941
|
-
}
|
|
942
|
-
if (!blockFound) {
|
|
943
|
-
blocks.push({
|
|
944
|
-
type: "tool_use",
|
|
945
|
-
content: args,
|
|
946
|
-
tool_call_id: toolCallId,
|
|
947
|
-
tool_name: toolName,
|
|
948
|
-
display_name: displayName
|
|
949
|
-
});
|
|
950
|
-
}
|
|
951
|
-
setToolCallStatus(turn, toolCallId, "awaiting_answer", result, null);
|
|
952
|
-
let resultBlockFound = false;
|
|
953
|
-
for (let i = 0; i < blocks.length; i++) {
|
|
954
|
-
if (blocks[i].type !== "tool_result" || blocks[i].tool_call_id !== toolCallId) continue;
|
|
955
|
-
blocks[i] = { ...blocks[i], content: result };
|
|
956
|
-
resultBlockFound = true;
|
|
957
|
-
break;
|
|
958
|
-
}
|
|
959
|
-
if (!resultBlockFound) {
|
|
960
|
-
blocks.push({
|
|
961
|
-
type: "tool_result",
|
|
962
|
-
content: result,
|
|
963
|
-
tool_call_id: toolCallId,
|
|
964
|
-
tool_name: toolName,
|
|
965
|
-
display_name: displayName
|
|
966
|
-
});
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
function applyChildPauseToParent(parentTurn, parentToolCallId, childLoopName, childToolCallId, description, displayNameResolver) {
|
|
970
|
-
if (!parentTurn || !parentToolCallId) return;
|
|
971
|
-
const toolCalls = "toolCalls" in parentTurn ? parentTurn.toolCalls : parentTurn.tool_calls;
|
|
972
|
-
const blocks = parentTurn.blocks;
|
|
973
|
-
const displayName = displayNameResolver("Agent");
|
|
974
|
-
let found = false;
|
|
975
|
-
for (let i = 0; i < toolCalls.length; i++) {
|
|
976
|
-
if (toolCalls[i].id !== parentToolCallId) continue;
|
|
977
|
-
toolCalls[i] = {
|
|
978
|
-
...toolCalls[i],
|
|
979
|
-
tool_name: "Agent",
|
|
980
|
-
display_name: displayName || toolCalls[i].display_name
|
|
981
|
-
};
|
|
982
|
-
found = true;
|
|
983
|
-
break;
|
|
984
|
-
}
|
|
985
|
-
if (!found) {
|
|
986
|
-
toolCalls.push({
|
|
987
|
-
id: parentToolCallId,
|
|
988
|
-
tool_name: "Agent",
|
|
989
|
-
display_name: displayName,
|
|
990
|
-
arguments: "",
|
|
991
|
-
status: "pending"
|
|
992
|
-
});
|
|
993
|
-
}
|
|
994
|
-
let blockFound = false;
|
|
995
|
-
for (let i = 0; i < blocks.length; i++) {
|
|
996
|
-
if (blocks[i].type !== "tool_use" || blocks[i].tool_call_id !== parentToolCallId) continue;
|
|
997
|
-
blockFound = true;
|
|
998
|
-
break;
|
|
999
|
-
}
|
|
1000
|
-
if (!blockFound) {
|
|
1001
|
-
blocks.push({
|
|
1002
|
-
type: "tool_use",
|
|
1003
|
-
content: "",
|
|
1004
|
-
tool_call_id: parentToolCallId,
|
|
1005
|
-
tool_name: "Agent",
|
|
1006
|
-
display_name: displayName
|
|
1007
|
-
});
|
|
1008
|
-
}
|
|
1009
|
-
setToolCallStatus(parentTurn, parentToolCallId, "awaiting_answer", null, {
|
|
1010
|
-
child_loop_name: childLoopName,
|
|
1011
|
-
child_tool_call_id: childToolCallId,
|
|
1012
|
-
description: description || null
|
|
1013
|
-
});
|
|
1014
|
-
}
|
|
1015
|
-
function askUserResultFromPausePayload(pauseToolData, sourceLoop) {
|
|
1016
|
-
const args = typeof pauseToolData.arguments === "object" && pauseToolData.arguments !== null ? pauseToolData.arguments : {};
|
|
1017
|
-
const payload = { questions: args.questions ?? [] };
|
|
1018
|
-
if (sourceLoop) payload.source_loop = sourceLoop;
|
|
1019
|
-
return JSON.stringify(payload);
|
|
1020
|
-
}
|
|
1021
|
-
function sourceLoopFor(loopId, loopDescriptions) {
|
|
1022
|
-
if (loopId === "root") return null;
|
|
1023
|
-
const description = loopDescriptions.get(loopId);
|
|
1024
|
-
if (!description) return null;
|
|
1025
|
-
return { loop_name: loopId, description };
|
|
1026
|
-
}
|
|
1027
|
-
function normalizeChildPause(pausePayload) {
|
|
1028
|
-
const rawPtd = pausePayload.pause_tool_data;
|
|
1029
|
-
const pauseToolData = typeof rawPtd === "object" && rawPtd !== null ? { ...rawPtd } : { ...pausePayload };
|
|
1030
|
-
let sourceLoop = pauseToolData.source_loop;
|
|
1031
|
-
if (typeof sourceLoop !== "object" || sourceLoop === null) {
|
|
1032
|
-
sourceLoop = pausePayload.source_loop;
|
|
1033
|
-
}
|
|
1034
|
-
const childLoopName = String(pausePayload.child_loop_name ?? "") || (typeof sourceLoop === "object" && sourceLoop ? String(sourceLoop.name ?? "") : "");
|
|
1035
|
-
const childToolCallId = String(
|
|
1036
|
-
pausePayload.child_pause_tool_call_id ?? pauseToolData.tool_call_id ?? ""
|
|
1037
|
-
);
|
|
1038
|
-
const description = typeof sourceLoop === "object" && sourceLoop ? String(sourceLoop.description ?? "") : "";
|
|
1039
|
-
if (childLoopName && description) {
|
|
1040
|
-
pauseToolData.source_loop = { name: childLoopName, description };
|
|
1041
|
-
}
|
|
1042
|
-
return { pauseToolData, childLoopName, childToolCallId, description };
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
// src/react/schemas/message.ts
|
|
1046
|
-
function inferToolStatus(resultStr) {
|
|
1047
|
-
if (resultStr.includes('"Cancelled by user"')) return "cancelled";
|
|
1048
|
-
try {
|
|
1049
|
-
const parsed = JSON.parse(resultStr);
|
|
1050
|
-
if (typeof parsed === "object" && parsed !== null) {
|
|
1051
|
-
if ("error" in parsed && parsed.error) return "error";
|
|
1052
|
-
const nested = parsed.result;
|
|
1053
|
-
if (typeof nested === "object" && nested !== null && "error" in nested && nested.error) {
|
|
1054
|
-
return "error";
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
} catch {
|
|
1058
|
-
}
|
|
1059
|
-
return "done";
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
// src/react/projection/state.ts
|
|
1063
|
-
function createTurnState(turnId, loopId, opts = {}) {
|
|
1064
|
-
return {
|
|
1065
|
-
turnId,
|
|
1066
|
-
loopId,
|
|
1067
|
-
role: "assistant",
|
|
1068
|
-
model: opts.model ?? null,
|
|
1069
|
-
startedAt: Date.now(),
|
|
1070
|
-
contextWindow: opts.contextWindow ?? 0,
|
|
1071
|
-
blocks: [],
|
|
1072
|
-
toolCalls: [],
|
|
1073
|
-
usage: null,
|
|
1074
|
-
memoryRefs: opts.memoryRefs ?? null,
|
|
1075
|
-
parentForkToolCallId: null
|
|
1076
|
-
};
|
|
1077
|
-
}
|
|
1078
|
-
function snapshot(state, sequence, status) {
|
|
1079
|
-
return {
|
|
1080
|
-
id: state.turnId,
|
|
1081
|
-
sequence,
|
|
1082
|
-
turn_id: state.turnId,
|
|
1083
|
-
loop_id: state.loopId,
|
|
1084
|
-
kind: "message",
|
|
1085
|
-
role: state.role,
|
|
1086
|
-
status,
|
|
1087
|
-
blocks: [...state.blocks],
|
|
1088
|
-
tool_calls: [...state.toolCalls],
|
|
1089
|
-
model: state.model,
|
|
1090
|
-
usage: state.usage ? { ...state.usage } : null,
|
|
1091
|
-
duration_ms: Math.max(0, Date.now() - state.startedAt),
|
|
1092
|
-
started_at: new Date(state.startedAt).toISOString(),
|
|
1093
|
-
context_window: state.contextWindow,
|
|
1094
|
-
memory_refs: state.memoryRefs,
|
|
1095
|
-
parent_fork_tool_call_id: state.parentForkToolCallId
|
|
1096
|
-
};
|
|
1097
|
-
}
|
|
1098
|
-
var PAUSE_TOOL_NAMES = /* @__PURE__ */ new Set(["AskUserQuestion", "ExitPlanMode"]);
|
|
1099
|
-
function toolStatusFromResult(result) {
|
|
1100
|
-
const text = typeof result === "string" ? result : Array.isArray(result) ? result.filter(
|
|
1101
|
-
(p) => typeof p === "object" && p !== null && p.type === "text"
|
|
1102
|
-
).map((p) => p.text ?? "").join("\n") : String(result ?? "");
|
|
1103
|
-
return inferToolStatus(text);
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
// src/react/projection/builder.ts
|
|
1107
|
-
var ClientProjectionBuilder = class {
|
|
1108
|
-
activeTurns = /* @__PURE__ */ new Map();
|
|
1109
|
-
lastTurnIds = /* @__PURE__ */ new Map();
|
|
1110
|
-
latestTurns = /* @__PURE__ */ new Map();
|
|
1111
|
-
loopDescriptions = /* @__PURE__ */ new Map();
|
|
1112
|
-
pendingChildPauses = /* @__PURE__ */ new Map();
|
|
1113
|
-
pendingMemoryRefs = /* @__PURE__ */ new Map();
|
|
1114
|
-
activeCompactions = /* @__PURE__ */ new Map();
|
|
1115
|
-
seq = 0;
|
|
1116
|
-
syntheticCounter = 0;
|
|
1117
|
-
displayNameResolver;
|
|
1118
|
-
constructor(displayNameResolver) {
|
|
1119
|
-
this.displayNameResolver = displayNameResolver ?? ((n) => n);
|
|
1120
|
-
}
|
|
1121
|
-
processBatch(events) {
|
|
1122
|
-
const lastUpsertByTurn = /* @__PURE__ */ new Map();
|
|
1123
|
-
const nonUpserts = [];
|
|
1124
|
-
for (const event of events) {
|
|
1125
|
-
const updates = this.processEvent(event);
|
|
1126
|
-
if (!updates) continue;
|
|
1127
|
-
for (const u of updates) {
|
|
1128
|
-
if (u.kind === "upsert") {
|
|
1129
|
-
lastUpsertByTurn.set(u.turn.turn_id, u);
|
|
1130
|
-
} else {
|
|
1131
|
-
nonUpserts.push(u);
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
return [...nonUpserts, ...lastUpsertByTurn.values()];
|
|
1136
|
-
}
|
|
1137
|
-
processEvent(event) {
|
|
1138
|
-
const payload = event.payload;
|
|
1139
|
-
const loopId = String(payload.loop_name ?? "root");
|
|
1140
|
-
switch (event.type) {
|
|
1141
|
-
case "memory:inject:done":
|
|
1142
|
-
return this.onMemoryInject(loopId, payload);
|
|
1143
|
-
case "memory:inject:none":
|
|
1144
|
-
return null;
|
|
1145
|
-
case "loop:turn":
|
|
1146
|
-
return this.onLoopTurn(loopId, payload);
|
|
1147
|
-
case "mode:change":
|
|
1148
|
-
return this.onModeChange(loopId, payload);
|
|
1149
|
-
case "plan:status:update":
|
|
1150
|
-
return this.onPlanStatusUpdate(loopId, payload);
|
|
1151
|
-
case "workspace:changed":
|
|
1152
|
-
return this.onWorkspaceChanged(loopId, payload);
|
|
1153
|
-
case "agent:start":
|
|
1154
|
-
return this.onAgentStart(loopId, payload);
|
|
1155
|
-
case "bg:started":
|
|
1156
|
-
return this.onBgStarted(loopId, payload);
|
|
1157
|
-
case "bg:tasks_completed":
|
|
1158
|
-
return this.onBgTasksCompleted(loopId, payload);
|
|
1159
|
-
case "loop:ask_user_answer":
|
|
1160
|
-
return this.onAskUserAnswer(loopId, payload);
|
|
1161
|
-
case "user:message":
|
|
1162
|
-
return this.onUserMessage(loopId, payload);
|
|
1163
|
-
}
|
|
1164
|
-
if (event.type.startsWith("compaction:"))
|
|
1165
|
-
return this.onCompaction(event.type, loopId, payload);
|
|
1166
|
-
const state = this.activeTurns.get(loopId);
|
|
1167
|
-
if (!state) {
|
|
1168
|
-
if (event.type === "chat:end") {
|
|
1169
|
-
this.pendingMemoryRefs.delete(loopId);
|
|
1170
|
-
return null;
|
|
1171
|
-
}
|
|
1172
|
-
if (event.type === "agent:end") return this.onAgentEnd(null, loopId, payload);
|
|
1173
|
-
return null;
|
|
1174
|
-
}
|
|
1175
|
-
switch (event.type) {
|
|
1176
|
-
case "llm:thinking:delta":
|
|
1177
|
-
return this.onDelta(state, "thinking", "", String(payload.content ?? ""));
|
|
1178
|
-
case "llm:content:delta":
|
|
1179
|
-
return this.onDelta(state, "text", "", String(payload.content ?? ""));
|
|
1180
|
-
case "llm:tool_call:created":
|
|
1181
|
-
return this.onToolCallCreated(state, payload);
|
|
1182
|
-
case "llm:response:done":
|
|
1183
|
-
return this.onResponseDone(state, loopId, payload);
|
|
1184
|
-
case "tool:result:delta":
|
|
1185
|
-
return this.onToolResultDelta(state, payload);
|
|
1186
|
-
case "tool:result:done":
|
|
1187
|
-
return this.onToolResultDone(state, loopId, payload);
|
|
1188
|
-
case "loop:tool_ui":
|
|
1189
|
-
return this.onToolUi(state, payload);
|
|
1190
|
-
case "loop:tool_bridge":
|
|
1191
|
-
return this.onToolBridge(state, payload);
|
|
1192
|
-
case "tool:approval:required":
|
|
1193
|
-
return this.onToolApprovalRequired(state, payload);
|
|
1194
|
-
case "loop:child_pause":
|
|
1195
|
-
return this.onChildPause(state, loopId, payload);
|
|
1196
|
-
case "chat:end":
|
|
1197
|
-
return this.onChatEnd(state, loopId, payload);
|
|
1198
|
-
case "agent:end":
|
|
1199
|
-
return this.onAgentEnd(state, loopId, payload);
|
|
1200
|
-
default:
|
|
1201
|
-
return null;
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
|
-
reset() {
|
|
1205
|
-
this.activeTurns.clear();
|
|
1206
|
-
this.lastTurnIds.clear();
|
|
1207
|
-
this.latestTurns.clear();
|
|
1208
|
-
this.loopDescriptions.clear();
|
|
1209
|
-
this.pendingChildPauses.clear();
|
|
1210
|
-
this.pendingMemoryRefs.clear();
|
|
1211
|
-
this.activeCompactions.clear();
|
|
1212
|
-
this.seq = 0;
|
|
1213
|
-
this.syntheticCounter = 0;
|
|
1214
|
-
}
|
|
1215
|
-
seedSequence(maxSeq) {
|
|
1216
|
-
if (maxSeq > this.seq) {
|
|
1217
|
-
this.seq = maxSeq;
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
// --- Event handlers ---
|
|
1221
|
-
onMemoryInject(loopId, payload) {
|
|
1222
|
-
const refs = payload.memory_refs;
|
|
1223
|
-
const turnId = String(payload.turn_id ?? "");
|
|
1224
|
-
if (Array.isArray(refs) && refs.length > 0) {
|
|
1225
|
-
this.pendingMemoryRefs.set(loopId, {
|
|
1226
|
-
turnId,
|
|
1227
|
-
refs: refs.map((r4) => ({
|
|
1228
|
-
id: Number(r4.id),
|
|
1229
|
-
content_preview: String(r4.content_preview ?? ""),
|
|
1230
|
-
skill_name: r4.skill_name != null ? String(r4.skill_name) : null
|
|
1231
|
-
}))
|
|
1232
|
-
});
|
|
1233
|
-
}
|
|
1234
|
-
return null;
|
|
1235
|
-
}
|
|
1236
|
-
onLoopTurn(loopId, payload) {
|
|
1237
|
-
let turnId = String(payload.turn_id ?? this.nextTurnId(`turn:${loopId}`));
|
|
1238
|
-
let memoryRefs = null;
|
|
1239
|
-
const pending = this.pendingMemoryRefs.get(loopId);
|
|
1240
|
-
if (pending) {
|
|
1241
|
-
this.pendingMemoryRefs.delete(loopId);
|
|
1242
|
-
if (pending.turnId) turnId = pending.turnId;
|
|
1243
|
-
memoryRefs = pending.refs;
|
|
1244
|
-
}
|
|
1245
|
-
const rawCw = payload.context_window;
|
|
1246
|
-
const contextWindow = typeof rawCw === "number" && rawCw > 0 ? Math.trunc(rawCw) : 0;
|
|
1247
|
-
const state = createTurnState(turnId, loopId, {
|
|
1248
|
-
model: optStr(payload.model),
|
|
1249
|
-
contextWindow,
|
|
1250
|
-
memoryRefs
|
|
1251
|
-
});
|
|
1252
|
-
this.activeTurns.set(loopId, state);
|
|
1253
|
-
this.lastTurnIds.set(loopId, turnId);
|
|
1254
|
-
const turn = snapshot(state, this.nextSeq(), "streaming");
|
|
1255
|
-
this.latestTurns.set(loopId, turn);
|
|
1256
|
-
return [{ kind: "upsert", turn }];
|
|
1257
|
-
}
|
|
1258
|
-
onModeChange(loopId, payload) {
|
|
1259
|
-
const content = {};
|
|
1260
|
-
if (payload.from != null && payload.from !== "") content.from = String(payload.from);
|
|
1261
|
-
if (payload.to != null && payload.to !== "") content.to = String(payload.to);
|
|
1262
|
-
const turn = buildMarkerTurn(
|
|
1263
|
-
this.nextSeq(),
|
|
1264
|
-
this.nextTurnId("mode_change"),
|
|
1265
|
-
loopId,
|
|
1266
|
-
"mode_change",
|
|
1267
|
-
content
|
|
1268
|
-
);
|
|
1269
|
-
return [{ kind: "upsert", turn }];
|
|
1270
|
-
}
|
|
1271
|
-
onPlanStatusUpdate(loopId, payload) {
|
|
1272
|
-
let statuses = payload.statuses;
|
|
1273
|
-
if (typeof statuses !== "object" || statuses === null) {
|
|
1274
|
-
statuses = payload._statuses ?? {};
|
|
1275
|
-
}
|
|
1276
|
-
const turn = buildMarkerTurn(
|
|
1277
|
-
this.nextSeq(),
|
|
1278
|
-
this.nextTurnId("plan_status"),
|
|
1279
|
-
loopId,
|
|
1280
|
-
"plan_status",
|
|
1281
|
-
{ plan_yaml: payload.plan_yaml ?? "", statuses }
|
|
1282
|
-
);
|
|
1283
|
-
return [{ kind: "upsert", turn }];
|
|
1284
|
-
}
|
|
1285
|
-
onWorkspaceChanged(loopId, payload) {
|
|
1286
|
-
const updates = [
|
|
1287
|
-
{
|
|
1288
|
-
kind: "workspace_changed",
|
|
1289
|
-
loopId,
|
|
1290
|
-
toolCallId: optStr(payload.tool_call_id) ?? void 0,
|
|
1291
|
-
toolName: toolNameFromPayload(payload) ?? void 0
|
|
1292
|
-
}
|
|
1293
|
-
];
|
|
1294
|
-
const state = this.activeTurns.get(loopId);
|
|
1295
|
-
if (state) {
|
|
1296
|
-
const turn = snapshot(state, this.nextSeq(), "streaming");
|
|
1297
|
-
this.latestTurns.set(loopId, turn);
|
|
1298
|
-
this.lastTurnIds.set(loopId, turn.turn_id);
|
|
1299
|
-
updates.push({ kind: "upsert", turn });
|
|
1300
|
-
}
|
|
1301
|
-
return updates;
|
|
1302
|
-
}
|
|
1303
|
-
onAgentStart(loopId, payload) {
|
|
1304
|
-
const description = optStr(payload.description);
|
|
1305
|
-
if (description) this.loopDescriptions.set(loopId, description);
|
|
1306
|
-
const turn = buildSystemNotificationTurn(
|
|
1307
|
-
this.nextSeq(),
|
|
1308
|
-
this.nextTurnId("agent:start"),
|
|
1309
|
-
loopId,
|
|
1310
|
-
"agent:start",
|
|
1311
|
-
"running",
|
|
1312
|
-
`Agent: ${payload.description ?? payload.skill_id ?? "agent"}`,
|
|
1313
|
-
optStr(payload.prompt),
|
|
1314
|
-
{
|
|
1315
|
-
skill_id: optStr(payload.skill_id),
|
|
1316
|
-
description: optStr(payload.description),
|
|
1317
|
-
parent_fork_tool_call_id: optStr(payload.parent_fork_tool_call_id)
|
|
1318
|
-
}
|
|
1319
|
-
);
|
|
1320
|
-
return [{ kind: "upsert", turn }];
|
|
1321
|
-
}
|
|
1322
|
-
onBgStarted(loopId, payload) {
|
|
1323
|
-
const taskId = optStr(payload.task_id) ?? "";
|
|
1324
|
-
const command = optStr(payload.command);
|
|
1325
|
-
const description = optStr(payload.description);
|
|
1326
|
-
const turn = buildSystemNotificationTurn(
|
|
1327
|
-
this.nextSeq(),
|
|
1328
|
-
this.nextTurnId("bg:started"),
|
|
1329
|
-
loopId,
|
|
1330
|
-
"bg:started",
|
|
1331
|
-
"running",
|
|
1332
|
-
description ?? `Background: ${taskId || "task"}`,
|
|
1333
|
-
command,
|
|
1334
|
-
{ task_id: taskId, command, description }
|
|
1335
|
-
);
|
|
1336
|
-
return [{ kind: "upsert", turn }];
|
|
1337
|
-
}
|
|
1338
|
-
onBgTasksCompleted(loopId, payload) {
|
|
1339
|
-
const taskIds = Array.isArray(payload.task_ids) ? payload.task_ids : [];
|
|
1340
|
-
const count = typeof payload.count === "number" ? payload.count : taskIds.length;
|
|
1341
|
-
const detail = taskIds.map(String).join(", ");
|
|
1342
|
-
const turn = buildSystemNotificationTurn(
|
|
1343
|
-
this.nextSeq(),
|
|
1344
|
-
this.nextTurnId("bg:tasks_completed"),
|
|
1345
|
-
loopId,
|
|
1346
|
-
"bg:tasks_completed",
|
|
1347
|
-
"done",
|
|
1348
|
-
`Background tasks completed (${count})`,
|
|
1349
|
-
detail || null,
|
|
1350
|
-
{ task_ids: taskIds, count }
|
|
1351
|
-
);
|
|
1352
|
-
return [{ kind: "upsert", turn }];
|
|
1353
|
-
}
|
|
1354
|
-
onAskUserAnswer(loopId, payload) {
|
|
1355
|
-
const toolCallId = String(payload.tool_call_id ?? "");
|
|
1356
|
-
const pending = this.pendingChildPauses.get(toolCallId);
|
|
1357
|
-
const parentLoopId = pending?.parentLoopName;
|
|
1358
|
-
if (pending) {
|
|
1359
|
-
this.pendingChildPauses.delete(toolCallId);
|
|
1360
|
-
const childTurn = this.activeTurns.get(pending.childLoopName) ?? this.latestTurns.get(pending.childLoopName);
|
|
1361
|
-
setToolCallStatus(childTurn, pending.childToolCallId, "done", null, null);
|
|
1362
|
-
const parentTurn = this.activeTurns.get(pending.parentLoopName) ?? this.latestTurns.get(pending.parentLoopName);
|
|
1363
|
-
setToolCallStatus(parentTurn, pending.parentToolCallId, "done", null, null);
|
|
1364
|
-
}
|
|
1365
|
-
const directTurn = this.activeTurns.get(loopId) ?? this.latestTurns.get(loopId);
|
|
1366
|
-
setToolCallStatus(directTurn, toolCallId, "done", null, null);
|
|
1367
|
-
return this.collectLoopUpdates(loopId, parentLoopId);
|
|
1368
|
-
}
|
|
1369
|
-
onUserMessage(_loopId, payload) {
|
|
1370
|
-
const entryId = String(payload.entry_id ?? this.nextTurnId("user"));
|
|
1371
|
-
const displayContent = payload.display_content ?? payload.content ?? "";
|
|
1372
|
-
const turn = {
|
|
1373
|
-
id: entryId,
|
|
1374
|
-
sequence: this.nextSeq(),
|
|
1375
|
-
turn_id: entryId,
|
|
1376
|
-
loop_id: "root",
|
|
1377
|
-
kind: "message",
|
|
1378
|
-
role: "user",
|
|
1379
|
-
status: "completed",
|
|
1380
|
-
blocks: [{ type: "text", content: displayContent }],
|
|
1381
|
-
tool_calls: [],
|
|
1382
|
-
model: null,
|
|
1383
|
-
usage: null,
|
|
1384
|
-
duration_ms: 0
|
|
1385
|
-
};
|
|
1386
|
-
return [{ kind: "upsert", turn }];
|
|
1387
|
-
}
|
|
1388
|
-
// --- Delta / streaming events ---
|
|
1389
|
-
onDelta(state, blockType, _toolCallId, content) {
|
|
1390
|
-
if (!content) return null;
|
|
1391
|
-
appendTextBlock(state, blockType, content);
|
|
1392
|
-
return this.syncPatch(state);
|
|
1393
|
-
}
|
|
1394
|
-
onToolCallCreated(state, payload) {
|
|
1395
|
-
if ("arguments_delta" in payload) {
|
|
1396
|
-
const delta = String(payload.arguments_delta ?? "");
|
|
1397
|
-
const toolCallId2 = String(payload.id ?? "");
|
|
1398
|
-
if (delta && toolCallId2) {
|
|
1399
|
-
appendToolCallArguments(state, toolCallId2, delta);
|
|
1400
|
-
return this.syncPatch(state);
|
|
1401
|
-
}
|
|
1402
|
-
return null;
|
|
1403
|
-
}
|
|
1404
|
-
const toolCallId = String(payload.id ?? "");
|
|
1405
|
-
const toolName = toolNameFromPayload(payload);
|
|
1406
|
-
const displayName = String(payload.display_name ?? "") || this.displayNameResolver(toolName);
|
|
1407
|
-
const args = toolArgsFromPayload(payload);
|
|
1408
|
-
upsertToolCall(state, toolCallId, toolName, displayName, args);
|
|
1409
|
-
return this.syncPatch(state);
|
|
1410
|
-
}
|
|
1411
|
-
onResponseDone(state, loopId, payload) {
|
|
1412
|
-
const model = optStr(payload.model);
|
|
1413
|
-
if (model) state.model = model;
|
|
1414
|
-
if (typeof payload.usage === "object" && payload.usage !== null) {
|
|
1415
|
-
state.usage = { ...payload.usage };
|
|
1416
|
-
}
|
|
1417
|
-
const toolCalls = payload.tool_calls;
|
|
1418
|
-
if (Array.isArray(toolCalls)) {
|
|
1419
|
-
for (const raw of toolCalls) {
|
|
1420
|
-
if (typeof raw !== "object" || raw === null) continue;
|
|
1421
|
-
const tc = raw;
|
|
1422
|
-
const fn = tc.function ?? {};
|
|
1423
|
-
const toolName = String(fn.name ?? "");
|
|
1424
|
-
const displayName = String(tc.display_name ?? "") || this.displayNameResolver(toolName);
|
|
1425
|
-
upsertToolCall(
|
|
1426
|
-
state,
|
|
1427
|
-
String(tc.id ?? ""),
|
|
1428
|
-
toolName,
|
|
1429
|
-
displayName,
|
|
1430
|
-
String(fn.arguments ?? "")
|
|
1431
|
-
);
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
|
-
if (state.toolCalls.length === 0) {
|
|
1435
|
-
return this.finalize(loopId, "completed");
|
|
1436
|
-
}
|
|
1437
|
-
return this.syncPatch(state);
|
|
1438
|
-
}
|
|
1439
|
-
onToolResultDone(state, loopId, payload) {
|
|
1440
|
-
const toolCallId = String(payload.tool_call_id ?? "");
|
|
1441
|
-
const content = payload.content ?? "";
|
|
1442
|
-
const status = toolStatusFromResult(content);
|
|
1443
|
-
const rawDuration = payload.duration_ms;
|
|
1444
|
-
const durationMs = typeof rawDuration === "number" && rawDuration >= 0 ? Math.round(rawDuration) : null;
|
|
1445
|
-
const sl = sourceLoopFor(state.loopId, this.loopDescriptions);
|
|
1446
|
-
applyToolResult(state, toolCallId, content, status, durationMs, sl);
|
|
1447
|
-
if (this.shouldFinalizeAfterToolResults(state)) {
|
|
1448
|
-
return this.finalize(loopId, "completed");
|
|
1449
|
-
}
|
|
1450
|
-
return this.syncPatch(state);
|
|
1451
|
-
}
|
|
1452
|
-
onToolResultDelta(state, payload) {
|
|
1453
|
-
appendToolResultDelta(
|
|
1454
|
-
state,
|
|
1455
|
-
String(payload.tool_call_id ?? ""),
|
|
1456
|
-
String(payload.content ?? "")
|
|
1457
|
-
);
|
|
1458
|
-
return this.syncPatch(state);
|
|
1459
|
-
}
|
|
1460
|
-
onToolUi(state, payload) {
|
|
1461
|
-
const toolCallId = String(payload.tool_call_id ?? "");
|
|
1462
|
-
const ui = payload.ui;
|
|
1463
|
-
if (toolCallId && typeof ui === "object" && ui !== null) {
|
|
1464
|
-
state.blocks.push({
|
|
1465
|
-
type: "tool_ui",
|
|
1466
|
-
content: ui,
|
|
1467
|
-
tool_call_id: toolCallId
|
|
1468
|
-
});
|
|
1469
|
-
}
|
|
1470
|
-
return this.syncPatch(state);
|
|
1471
|
-
}
|
|
1472
|
-
onToolBridge(state, payload) {
|
|
1473
|
-
const bridge = payload.bridge;
|
|
1474
|
-
if (typeof bridge !== "object" || bridge === null) return null;
|
|
1475
|
-
state.blocks.push({
|
|
1476
|
-
type: "tool_bridge",
|
|
1477
|
-
content: bridge,
|
|
1478
|
-
tool_call_id: String(payload.tool_call_id ?? "") || null
|
|
1479
|
-
});
|
|
1480
|
-
return this.syncPatch(state);
|
|
1481
|
-
}
|
|
1482
|
-
onToolApprovalRequired(state, payload) {
|
|
1483
|
-
const toolCallId = String(payload.tool_call_id ?? "");
|
|
1484
|
-
const toolName = String(payload.tool_name ?? "");
|
|
1485
|
-
const displayName = this.displayNameResolver(toolName);
|
|
1486
|
-
upsertToolCall(state, toolCallId, toolName, displayName, "");
|
|
1487
|
-
return this.syncPatch(state);
|
|
1488
|
-
}
|
|
1489
|
-
onChildPause(state, loopId, payload) {
|
|
1490
|
-
const pauseToolData = payload.pause_tool_data;
|
|
1491
|
-
if (typeof pauseToolData !== "object" || pauseToolData === null)
|
|
1492
|
-
return this.syncPatch(state);
|
|
1493
|
-
const ptd = pauseToolData;
|
|
1494
|
-
const sourceLoop = ptd.source_loop;
|
|
1495
|
-
if (typeof sourceLoop === "object" && sourceLoop) {
|
|
1496
|
-
const slName = String(sourceLoop.name ?? "");
|
|
1497
|
-
const slDesc = optStr(sourceLoop.description);
|
|
1498
|
-
if (slName && slDesc) this.loopDescriptions.set(slName, slDesc);
|
|
1499
|
-
}
|
|
1500
|
-
const { childLoopName, childToolCallId, description } = normalizeChildPause(payload);
|
|
1501
|
-
if (!childToolCallId) return this.syncPatch(state);
|
|
1502
|
-
const existing = this.pendingChildPauses.get(childToolCallId);
|
|
1503
|
-
const parentLoopName = String(
|
|
1504
|
-
payload.parent_loop_name ?? existing?.parentLoopName ?? "root"
|
|
1505
|
-
);
|
|
1506
|
-
const parentToolCallId = String(
|
|
1507
|
-
payload.parent_fork_tool_call_id ?? existing?.parentToolCallId ?? ""
|
|
1508
|
-
);
|
|
1509
|
-
const resolvedChildLoopName = String(payload.child_loop_name ?? "") || existing?.childLoopName || childLoopName || loopId;
|
|
1510
|
-
this.pendingChildPauses.set(childToolCallId, {
|
|
1511
|
-
parentLoopName,
|
|
1512
|
-
parentToolCallId,
|
|
1513
|
-
childLoopName: resolvedChildLoopName,
|
|
1514
|
-
childToolCallId,
|
|
1515
|
-
description: description || existing?.description || ""
|
|
1516
|
-
});
|
|
1517
|
-
applyAskUserPauseToTurn(
|
|
1518
|
-
state,
|
|
1519
|
-
ptd,
|
|
1520
|
-
childToolCallId,
|
|
1521
|
-
resolvedChildLoopName,
|
|
1522
|
-
this.pendingChildPauses.get(childToolCallId).description,
|
|
1523
|
-
this.displayNameResolver
|
|
1524
|
-
);
|
|
1525
|
-
const parentTurn = this.activeTurns.get(parentLoopName) ?? this.latestTurns.get(parentLoopName);
|
|
1526
|
-
if (parentTurn) {
|
|
1527
|
-
applyChildPauseToParent(
|
|
1528
|
-
parentTurn,
|
|
1529
|
-
parentToolCallId,
|
|
1530
|
-
resolvedChildLoopName,
|
|
1531
|
-
childToolCallId,
|
|
1532
|
-
this.pendingChildPauses.get(childToolCallId).description,
|
|
1533
|
-
this.displayNameResolver
|
|
1534
|
-
);
|
|
1535
|
-
}
|
|
1536
|
-
return this.collectLoopUpdates(loopId, parentLoopName);
|
|
1537
|
-
}
|
|
1538
|
-
onChatEnd(state, loopId, payload) {
|
|
1539
|
-
const status = String(payload.status ?? "completed");
|
|
1540
|
-
const pauseToolData = payload.pause_tool_data;
|
|
1541
|
-
if (typeof pauseToolData === "object" && pauseToolData !== null) {
|
|
1542
|
-
const ptd = pauseToolData;
|
|
1543
|
-
const pauseToolName = String(ptd.name ?? "");
|
|
1544
|
-
const normalized = pauseToolName.includes(":") ? pauseToolName.split(":").pop() : pauseToolName;
|
|
1545
|
-
const sourceLoop = ptd.source_loop;
|
|
1546
|
-
if (typeof sourceLoop === "object" && sourceLoop) {
|
|
1547
|
-
const slName = String(sourceLoop.name ?? "");
|
|
1548
|
-
const slDesc = optStr(sourceLoop.description);
|
|
1549
|
-
if (slName && slDesc) this.loopDescriptions.set(slName, slDesc);
|
|
1550
|
-
if (status === "paused" && slName) {
|
|
1551
|
-
applyChildPauseToParent(
|
|
1552
|
-
state,
|
|
1553
|
-
String(ptd.parent_fork_tool_call_id ?? ""),
|
|
1554
|
-
slName,
|
|
1555
|
-
String(ptd.tool_call_id ?? ""),
|
|
1556
|
-
slDesc ?? "",
|
|
1557
|
-
this.displayNameResolver
|
|
1558
|
-
);
|
|
1559
|
-
const childTurn = this.activeTurns.get(slName);
|
|
1560
|
-
if (childTurn) {
|
|
1561
|
-
applyAskUserPauseToTurn(
|
|
1562
|
-
childTurn,
|
|
1563
|
-
ptd,
|
|
1564
|
-
String(ptd.tool_call_id ?? ""),
|
|
1565
|
-
slName,
|
|
1566
|
-
slDesc ?? "",
|
|
1567
|
-
this.displayNameResolver
|
|
1568
|
-
);
|
|
1569
|
-
}
|
|
1570
|
-
}
|
|
1571
|
-
} else if (status === "paused" && normalized === "AskUserQuestion") {
|
|
1572
|
-
applyAskUserPauseToTurn(
|
|
1573
|
-
state,
|
|
1574
|
-
ptd,
|
|
1575
|
-
String(ptd.tool_call_id ?? ""),
|
|
1576
|
-
"",
|
|
1577
|
-
"",
|
|
1578
|
-
this.displayNameResolver
|
|
1579
|
-
);
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
|
-
const finalStatus = { completed: "completed", paused: "paused", failed: "failed", interrupted: "interrupted" }[status];
|
|
1583
|
-
if (!finalStatus) return null;
|
|
1584
|
-
if (!this.activeTurns.has(loopId)) {
|
|
1585
|
-
this.pendingMemoryRefs.delete(loopId);
|
|
1586
|
-
}
|
|
1587
|
-
return this.finalize(loopId, finalStatus);
|
|
1588
|
-
}
|
|
1589
|
-
onAgentEnd(state, loopId, payload) {
|
|
1590
|
-
const ok = payload.ok !== false;
|
|
1591
|
-
const status = ok ? "done" : "error";
|
|
1592
|
-
const title = `Agent: ${payload.description ?? payload.skill_id ?? "agent"}`;
|
|
1593
|
-
const detail = optStr(payload.error);
|
|
1594
|
-
const metadata = {
|
|
1595
|
-
skill_id: optStr(payload.skill_id),
|
|
1596
|
-
description: optStr(payload.description),
|
|
1597
|
-
parent_fork_tool_call_id: optStr(payload.parent_fork_tool_call_id),
|
|
1598
|
-
ok
|
|
1599
|
-
};
|
|
1600
|
-
if (state) {
|
|
1601
|
-
state.blocks.push(buildSystemNotificationBlock("agent:end", status, title, detail, metadata));
|
|
1602
|
-
return this.finalize(loopId, ok ? "completed" : "failed");
|
|
1603
|
-
}
|
|
1604
|
-
const turn = buildSystemNotificationTurn(
|
|
1605
|
-
this.nextSeq(),
|
|
1606
|
-
this.nextTurnId("agent:end"),
|
|
1607
|
-
loopId,
|
|
1608
|
-
"agent:end",
|
|
1609
|
-
status,
|
|
1610
|
-
title,
|
|
1611
|
-
detail,
|
|
1612
|
-
metadata
|
|
1613
|
-
);
|
|
1614
|
-
return [{ kind: "upsert", turn }];
|
|
1615
|
-
}
|
|
1616
|
-
onCompaction(eventType, loopId, payload) {
|
|
1617
|
-
const compactionId = String(payload.compaction_id ?? "");
|
|
1618
|
-
if (!compactionId) return null;
|
|
1619
|
-
const current = {
|
|
1620
|
-
...this.activeCompactions.get(compactionId) ?? {},
|
|
1621
|
-
...payload,
|
|
1622
|
-
loop_id: loopId
|
|
1623
|
-
};
|
|
1624
|
-
let status;
|
|
1625
|
-
switch (eventType) {
|
|
1626
|
-
case "compaction:start":
|
|
1627
|
-
status = "streaming";
|
|
1628
|
-
this.activeCompactions.set(compactionId, current);
|
|
1629
|
-
break;
|
|
1630
|
-
case "compaction:end":
|
|
1631
|
-
status = "completed";
|
|
1632
|
-
this.activeCompactions.delete(compactionId);
|
|
1633
|
-
break;
|
|
1634
|
-
case "compaction:abort":
|
|
1635
|
-
status = "interrupted";
|
|
1636
|
-
this.activeCompactions.delete(compactionId);
|
|
1637
|
-
break;
|
|
1638
|
-
case "compaction:error":
|
|
1639
|
-
status = "failed";
|
|
1640
|
-
this.activeCompactions.delete(compactionId);
|
|
1641
|
-
break;
|
|
1642
|
-
default:
|
|
1643
|
-
status = "streaming";
|
|
1644
|
-
this.activeCompactions.set(compactionId, current);
|
|
1645
|
-
}
|
|
1646
|
-
const turn = buildCompactionTurn(this.nextSeq(), compactionId, loopId, status, current);
|
|
1647
|
-
return [{ kind: "upsert", turn }];
|
|
1648
|
-
}
|
|
1649
|
-
// --- Internal helpers ---
|
|
1650
|
-
syncPatch(state) {
|
|
1651
|
-
const turn = snapshot(state, this.nextSeq(), "streaming");
|
|
1652
|
-
this.latestTurns.set(state.loopId, turn);
|
|
1653
|
-
this.lastTurnIds.set(state.loopId, turn.turn_id);
|
|
1654
|
-
return [{ kind: "upsert", turn }];
|
|
1655
|
-
}
|
|
1656
|
-
finalize(loopId, status) {
|
|
1657
|
-
const state = this.activeTurns.get(loopId);
|
|
1658
|
-
if (!state) return null;
|
|
1659
|
-
this.activeTurns.delete(loopId);
|
|
1660
|
-
const turn = snapshot(state, this.nextSeq(), status);
|
|
1661
|
-
this.lastTurnIds.set(loopId, turn.turn_id);
|
|
1662
|
-
this.latestTurns.set(loopId, turn);
|
|
1663
|
-
return [{ kind: "upsert", turn }];
|
|
1664
|
-
}
|
|
1665
|
-
shouldFinalizeAfterToolResults(state) {
|
|
1666
|
-
if (state.toolCalls.length === 0) return true;
|
|
1667
|
-
if (state.toolCalls.some((tc) => tc.status === "pending")) return false;
|
|
1668
|
-
return !state.toolCalls.some((tc) => {
|
|
1669
|
-
const normalized = tc.tool_name.includes(":") ? tc.tool_name.split(":").pop() : tc.tool_name;
|
|
1670
|
-
return PAUSE_TOOL_NAMES.has(normalized);
|
|
1671
|
-
});
|
|
1672
|
-
}
|
|
1673
|
-
collectLoopUpdates(...loopIds) {
|
|
1674
|
-
const updates = [];
|
|
1675
|
-
for (const loopId of loopIds) {
|
|
1676
|
-
if (!loopId) continue;
|
|
1677
|
-
const state = this.activeTurns.get(loopId);
|
|
1678
|
-
if (state) {
|
|
1679
|
-
updates.push(...this.syncPatch(state));
|
|
1680
|
-
continue;
|
|
1681
|
-
}
|
|
1682
|
-
const proj = this.latestTurns.get(loopId);
|
|
1683
|
-
if (proj) {
|
|
1684
|
-
const updated = { ...proj, sequence: this.nextSeq() };
|
|
1685
|
-
this.latestTurns.set(loopId, updated);
|
|
1686
|
-
updates.push({ kind: "upsert", turn: updated });
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1689
|
-
return updates;
|
|
1690
|
-
}
|
|
1691
|
-
nextSeq() {
|
|
1692
|
-
return ++this.seq;
|
|
1693
|
-
}
|
|
1694
|
-
nextTurnId(prefix) {
|
|
1695
|
-
this.syntheticCounter++;
|
|
1696
|
-
const hex = Math.random().toString(16).slice(2, 10);
|
|
1697
|
-
return `${prefix}:${this.syntheticCounter}:${hex}`;
|
|
1698
|
-
}
|
|
1699
|
-
};
|
|
1700
|
-
function optStr(value) {
|
|
1701
|
-
if (value == null || value === "") return null;
|
|
1702
|
-
return String(value);
|
|
1703
|
-
}
|
|
1704
|
-
function toolNameFromPayload(payload) {
|
|
1705
|
-
const fn = payload.function;
|
|
1706
|
-
if (typeof fn === "object" && fn !== null) {
|
|
1707
|
-
return String(fn.name ?? "");
|
|
1708
|
-
}
|
|
1709
|
-
return String(payload.tool_name ?? "");
|
|
1710
|
-
}
|
|
1711
|
-
function toolArgsFromPayload(payload) {
|
|
1712
|
-
const fn = payload.function;
|
|
1713
|
-
if (typeof fn === "object" && fn !== null) {
|
|
1714
|
-
return String(fn.arguments ?? "");
|
|
1715
|
-
}
|
|
1716
|
-
return "";
|
|
1717
|
-
}
|
|
1718
|
-
|
|
1719
622
|
// src/react/stores/auth-store.ts
|
|
1720
623
|
import { create as create6 } from "zustand";
|
|
1721
624
|
import { createJSONStorage, persist } from "zustand/middleware";
|
|
@@ -4629,4 +3532,4 @@ export {
|
|
|
4629
3532
|
bootstrapBladeClient,
|
|
4630
3533
|
getBootstrappedClient
|
|
4631
3534
|
};
|
|
4632
|
-
//# sourceMappingURL=chunk-
|
|
3535
|
+
//# sourceMappingURL=chunk-UWNQ4PXK.js.map
|