@blade-hq/agent-kit 1.0.14 → 1.0.15

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.
Files changed (35) hide show
  1. package/dist/{SkillStatusBar-cYkuNAmR.d.ts → SkillStatusBar-DskumalP.d.ts} +19 -7
  2. package/dist/{blade-client-CGhtHnQN.d.ts → blade-client-KZiBuBHI.d.ts} +4 -1
  3. package/dist/{chunk-4K25SSZ4.js → chunk-J3PQU7BQ.js} +3 -3
  4. package/dist/{chunk-DXDLZXDP.js → chunk-JHUSL3JZ.js} +720 -626
  5. package/dist/chunk-JHUSL3JZ.js.map +1 -0
  6. package/dist/{chunk-CVCQSRVP.js → chunk-OMIVYL5D.js} +4 -4
  7. package/dist/chunk-OMIVYL5D.js.map +1 -0
  8. package/dist/{chunk-3UY7SD3P.js → chunk-QEYZZDLM.js} +1091 -11
  9. package/dist/chunk-QEYZZDLM.js.map +1 -0
  10. package/dist/{chunk-CM3H6ZNV.js → chunk-U4KVB5OB.js} +2 -2
  11. package/dist/{chunk-DN4CKDDQ.js → chunk-V74REX3Q.js} +2 -1
  12. package/dist/chunk-V74REX3Q.js.map +1 -0
  13. package/dist/client/index.d.ts +445 -2
  14. package/dist/client/index.js +1 -1
  15. package/dist/react/api/vibe-coding.d.ts +3 -3
  16. package/dist/react/api/vibe-coding.js +2 -2
  17. package/dist/react/components/chat/index.d.ts +4 -4
  18. package/dist/react/components/chat/index.js +7 -5
  19. package/dist/react/components/plan/index.js +4 -4
  20. package/dist/react/components/session/index.d.ts +1 -1
  21. package/dist/react/components/session/index.js +3 -3
  22. package/dist/react/components/workspace/index.d.ts +3 -3
  23. package/dist/react/components/workspace/index.js +3 -3
  24. package/dist/react/index.d.ts +22 -11
  25. package/dist/react/index.js +11 -6
  26. package/dist/react/index.js.map +1 -1
  27. package/dist/{session-o8bAQoXK.d.ts → session-CT8Y2KHr.d.ts} +2 -0
  28. package/dist/{sessions-BDau9Lk7.d.ts → sessions-BX8qHBN3.d.ts} +2 -2
  29. package/package.json +1 -1
  30. package/dist/chunk-3UY7SD3P.js.map +0 -1
  31. package/dist/chunk-CVCQSRVP.js.map +0 -1
  32. package/dist/chunk-DN4CKDDQ.js.map +0 -1
  33. package/dist/chunk-DXDLZXDP.js.map +0 -1
  34. /package/dist/{chunk-4K25SSZ4.js.map → chunk-J3PQU7BQ.js.map} +0 -0
  35. /package/dist/{chunk-CM3H6ZNV.js.map → chunk-U4KVB5OB.js.map} +0 -0
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-J3XVFPOV.js";
4
4
  import {
5
5
  BladeClient
6
- } from "./chunk-DN4CKDDQ.js";
6
+ } from "./chunk-V74REX3Q.js";
7
7
  import {
8
8
  createClientActions,
9
9
  useCardStateStore
@@ -571,6 +571,1059 @@ function isUiMeta(value) {
571
571
  return true;
572
572
  }
573
573
 
574
+ // src/react/projection/helpers.ts
575
+ function upsertToolCall(state, toolCallId, toolName, displayName, args) {
576
+ if (!toolCallId) return;
577
+ let found = false;
578
+ for (let i = 0; i < state.toolCalls.length; i++) {
579
+ if (state.toolCalls[i].id !== toolCallId) continue;
580
+ const tc = state.toolCalls[i];
581
+ state.toolCalls[i] = {
582
+ ...tc,
583
+ tool_name: toolName || tc.tool_name,
584
+ display_name: displayName || tc.display_name,
585
+ arguments: args || tc.arguments
586
+ };
587
+ found = true;
588
+ break;
589
+ }
590
+ if (!found) {
591
+ state.toolCalls.push({
592
+ id: toolCallId,
593
+ tool_name: toolName,
594
+ display_name: displayName,
595
+ arguments: args,
596
+ status: "pending"
597
+ });
598
+ }
599
+ let blockFound = false;
600
+ for (let i = 0; i < state.blocks.length; i++) {
601
+ const b = state.blocks[i];
602
+ if (b.type !== "tool_use" || b.tool_call_id !== toolCallId) continue;
603
+ state.blocks[i] = {
604
+ ...b,
605
+ content: args || b.content,
606
+ tool_name: toolName || b.tool_name,
607
+ display_name: displayName || b.display_name
608
+ };
609
+ blockFound = true;
610
+ break;
611
+ }
612
+ if (!blockFound) {
613
+ state.blocks.push({
614
+ type: "tool_use",
615
+ content: args,
616
+ tool_call_id: toolCallId,
617
+ tool_name: toolName || null,
618
+ display_name: displayName || null
619
+ });
620
+ }
621
+ }
622
+ function applyToolResult(state, toolCallId, result, status, durationMs, sourceLoop) {
623
+ let toolName = "";
624
+ let displayName = "";
625
+ let finalResult = result;
626
+ for (let i = 0; i < state.toolCalls.length; i++) {
627
+ const tc = state.toolCalls[i];
628
+ if (tc.id !== toolCallId) continue;
629
+ if (typeof result === "string") {
630
+ finalResult = maybeEnrichAskUserResult(tc.tool_name, result, sourceLoop);
631
+ }
632
+ const update = { status, result: finalResult };
633
+ if (durationMs != null) update.duration_ms = durationMs;
634
+ state.toolCalls[i] = { ...tc, ...update };
635
+ toolName = tc.tool_name;
636
+ displayName = tc.display_name;
637
+ break;
638
+ }
639
+ state.blocks.push({
640
+ type: "tool_result",
641
+ content: finalResult,
642
+ tool_call_id: toolCallId,
643
+ tool_name: toolName || null,
644
+ display_name: displayName || null
645
+ });
646
+ }
647
+ function appendTextBlock(state, blockType, content) {
648
+ if (content == null || content === "") return;
649
+ const text = String(content);
650
+ const lastBlock = state.blocks[state.blocks.length - 1];
651
+ if (lastBlock && lastBlock.type === blockType && typeof lastBlock.content === "string") {
652
+ state.blocks[state.blocks.length - 1] = {
653
+ ...lastBlock,
654
+ content: lastBlock.content + text
655
+ };
656
+ return;
657
+ }
658
+ state.blocks.push({ type: blockType, content: text });
659
+ }
660
+ function appendToolCallArguments(state, toolCallId, delta) {
661
+ let newArgs = "";
662
+ for (let i = 0; i < state.toolCalls.length; i++) {
663
+ const tc = state.toolCalls[i];
664
+ if (tc.id === toolCallId) {
665
+ newArgs = tc.arguments + delta;
666
+ state.toolCalls[i] = { ...tc, arguments: newArgs };
667
+ break;
668
+ }
669
+ }
670
+ if (!newArgs) return;
671
+ for (let i = 0; i < state.blocks.length; i++) {
672
+ const b = state.blocks[i];
673
+ if (b.type === "tool_use" && b.tool_call_id === toolCallId) {
674
+ state.blocks[i] = { ...b, content: newArgs };
675
+ break;
676
+ }
677
+ }
678
+ }
679
+ function maybeEnrichAskUserResult(toolName, result, sourceLoop) {
680
+ if (!sourceLoop) return result;
681
+ const normalized = toolName.includes(":") ? toolName.split(":").pop() : toolName;
682
+ if (normalized !== "AskUserQuestion") return result;
683
+ try {
684
+ const payload = JSON.parse(result);
685
+ if (typeof payload !== "object" || payload === null) return result;
686
+ payload.source_loop = sourceLoop;
687
+ return JSON.stringify(payload);
688
+ } catch {
689
+ return result;
690
+ }
691
+ }
692
+ function buildSystemNotificationTurn(sequence, turnId, loopId, notificationType, status, title, detail, metadata) {
693
+ return {
694
+ id: turnId,
695
+ sequence,
696
+ turn_id: turnId,
697
+ loop_id: loopId,
698
+ kind: "message",
699
+ role: "system",
700
+ status: "completed",
701
+ blocks: [
702
+ {
703
+ type: "system_notification",
704
+ content: {
705
+ notification_type: notificationType,
706
+ status,
707
+ title,
708
+ detail,
709
+ metadata
710
+ }
711
+ }
712
+ ],
713
+ tool_calls: [],
714
+ model: null,
715
+ usage: null,
716
+ duration_ms: 0
717
+ };
718
+ }
719
+ function buildSystemNotificationBlock(notificationType, status, title, detail, metadata) {
720
+ return {
721
+ type: "system_notification",
722
+ content: {
723
+ notification_type: notificationType,
724
+ status,
725
+ title,
726
+ detail,
727
+ metadata
728
+ }
729
+ };
730
+ }
731
+ function buildMarkerTurn(sequence, turnId, loopId, blockType, content) {
732
+ return {
733
+ id: turnId,
734
+ sequence,
735
+ turn_id: turnId,
736
+ loop_id: loopId,
737
+ kind: "message",
738
+ role: "assistant",
739
+ status: "completed",
740
+ blocks: [{ type: blockType, content }],
741
+ tool_calls: [],
742
+ model: null,
743
+ usage: null,
744
+ duration_ms: 0
745
+ };
746
+ }
747
+ function buildCompactionTurn(sequence, compactionId, loopId, status, data) {
748
+ const tokensBefore = asInt(data.tokens_before);
749
+ const tokensAfter = asInt(data.tokens_after);
750
+ let savedRatio = null;
751
+ if (tokensBefore && tokensBefore > 0 && tokensAfter != null) {
752
+ savedRatio = 1 - tokensAfter / tokensBefore;
753
+ } else {
754
+ savedRatio = asFloat(data.saved_ratio);
755
+ }
756
+ let archivedCount = asInt(data.archived_count);
757
+ if (archivedCount == null && Array.isArray(data.archived_files)) {
758
+ archivedCount = data.archived_files.length;
759
+ }
760
+ const content = data.content;
761
+ const summaryFull = compactionSummaryFull(content);
762
+ const summaryPreview = summaryFull ? summaryFull.split("\n").map((l) => l.trim()).filter(Boolean).join(" ").slice(0, 200) : null;
763
+ return {
764
+ id: `compaction:${compactionId}`,
765
+ sequence,
766
+ turn_id: `compaction:${compactionId}`,
767
+ loop_id: loopId,
768
+ kind: "compaction",
769
+ role: "system",
770
+ status,
771
+ blocks: [],
772
+ tool_calls: [],
773
+ model: null,
774
+ usage: null,
775
+ duration_ms: 0,
776
+ compaction_id: compactionId,
777
+ summary_preview: summaryPreview,
778
+ summary_full: summaryFull,
779
+ archived_count: archivedCount,
780
+ tokens_before: tokensBefore,
781
+ tokens_after: tokensAfter,
782
+ saved_ratio: savedRatio,
783
+ trigger: asTrigger(data.trigger),
784
+ failure_reason: typeof data.reason === "string" && data.reason ? data.reason : null,
785
+ fallback_applied: typeof data.fallback_applied === "boolean" ? data.fallback_applied : null
786
+ };
787
+ }
788
+ function compactionSummaryFull(content) {
789
+ const text = String(content ?? "");
790
+ if (!text) return null;
791
+ const cleaned = text.replace("<compaction-summary>", "").replace("</compaction-summary>", "").replace(/\r\n/g, "\n").replace(/\r/g, "\n").trim();
792
+ return cleaned || null;
793
+ }
794
+ function asInt(value) {
795
+ if (typeof value === "boolean") return null;
796
+ if (typeof value === "number") return Math.trunc(value);
797
+ return null;
798
+ }
799
+ function asFloat(value) {
800
+ if (typeof value === "boolean") return null;
801
+ if (typeof value === "number") return value;
802
+ return null;
803
+ }
804
+ function asTrigger(value) {
805
+ if (value === "auto" || value === "manual" || value === "forced_retry") return value;
806
+ return null;
807
+ }
808
+ function setToolCallStatus(turn, toolCallId, status, result, pendingQuestionRef) {
809
+ if (!turn || !toolCallId) return;
810
+ const toolCalls = "toolCalls" in turn ? turn.toolCalls : turn.tool_calls;
811
+ for (let i = 0; i < toolCalls.length; i++) {
812
+ if (toolCalls[i].id !== toolCallId) continue;
813
+ toolCalls[i] = {
814
+ ...toolCalls[i],
815
+ status,
816
+ result,
817
+ pending_question_ref: pendingQuestionRef
818
+ };
819
+ return;
820
+ }
821
+ }
822
+ function applyAskUserPauseToTurn(turn, pauseToolData, toolCallId, childLoopName, description, displayNameResolver) {
823
+ if (!turn || !toolCallId) return;
824
+ const sourceLoop = childLoopName ? { loop_name: childLoopName, description } : null;
825
+ const toolName = String(pauseToolData.name ?? "AskUserQuestion");
826
+ const args = JSON.stringify(pauseToolData.arguments ?? {});
827
+ const result = askUserResultFromPausePayload(pauseToolData, sourceLoop);
828
+ const isTurnState = "toolCalls" in turn;
829
+ const toolCalls = isTurnState ? turn.toolCalls : turn.tool_calls;
830
+ const blocks = turn.blocks;
831
+ const displayName = displayNameResolver(toolName);
832
+ let found = false;
833
+ for (let i = 0; i < toolCalls.length; i++) {
834
+ if (toolCalls[i].id !== toolCallId) continue;
835
+ toolCalls[i] = {
836
+ ...toolCalls[i],
837
+ tool_name: toolName || toolCalls[i].tool_name,
838
+ display_name: displayName || toolCalls[i].display_name,
839
+ arguments: args || toolCalls[i].arguments
840
+ };
841
+ found = true;
842
+ break;
843
+ }
844
+ if (!found) {
845
+ toolCalls.push({
846
+ id: toolCallId,
847
+ tool_name: toolName,
848
+ display_name: displayName,
849
+ arguments: args,
850
+ status: "pending"
851
+ });
852
+ }
853
+ let blockFound = false;
854
+ for (let i = 0; i < blocks.length; i++) {
855
+ if (blocks[i].type !== "tool_use" || blocks[i].tool_call_id !== toolCallId) continue;
856
+ blocks[i] = { ...blocks[i], content: args, tool_name: toolName, display_name: displayName };
857
+ blockFound = true;
858
+ break;
859
+ }
860
+ if (!blockFound) {
861
+ blocks.push({
862
+ type: "tool_use",
863
+ content: args,
864
+ tool_call_id: toolCallId,
865
+ tool_name: toolName,
866
+ display_name: displayName
867
+ });
868
+ }
869
+ setToolCallStatus(turn, toolCallId, "awaiting_answer", result, null);
870
+ let resultBlockFound = false;
871
+ for (let i = 0; i < blocks.length; i++) {
872
+ if (blocks[i].type !== "tool_result" || blocks[i].tool_call_id !== toolCallId) continue;
873
+ blocks[i] = { ...blocks[i], content: result };
874
+ resultBlockFound = true;
875
+ break;
876
+ }
877
+ if (!resultBlockFound) {
878
+ blocks.push({
879
+ type: "tool_result",
880
+ content: result,
881
+ tool_call_id: toolCallId,
882
+ tool_name: toolName,
883
+ display_name: displayName
884
+ });
885
+ }
886
+ }
887
+ function applyChildPauseToParent(parentTurn, parentToolCallId, childLoopName, childToolCallId, description, displayNameResolver) {
888
+ if (!parentTurn || !parentToolCallId) return;
889
+ const toolCalls = "toolCalls" in parentTurn ? parentTurn.toolCalls : parentTurn.tool_calls;
890
+ const blocks = parentTurn.blocks;
891
+ const displayName = displayNameResolver("Agent");
892
+ let found = false;
893
+ for (let i = 0; i < toolCalls.length; i++) {
894
+ if (toolCalls[i].id !== parentToolCallId) continue;
895
+ toolCalls[i] = {
896
+ ...toolCalls[i],
897
+ tool_name: "Agent",
898
+ display_name: displayName || toolCalls[i].display_name
899
+ };
900
+ found = true;
901
+ break;
902
+ }
903
+ if (!found) {
904
+ toolCalls.push({
905
+ id: parentToolCallId,
906
+ tool_name: "Agent",
907
+ display_name: displayName,
908
+ arguments: "",
909
+ status: "pending"
910
+ });
911
+ }
912
+ let blockFound = false;
913
+ for (let i = 0; i < blocks.length; i++) {
914
+ if (blocks[i].type !== "tool_use" || blocks[i].tool_call_id !== parentToolCallId) continue;
915
+ blockFound = true;
916
+ break;
917
+ }
918
+ if (!blockFound) {
919
+ blocks.push({
920
+ type: "tool_use",
921
+ content: "",
922
+ tool_call_id: parentToolCallId,
923
+ tool_name: "Agent",
924
+ display_name: displayName
925
+ });
926
+ }
927
+ setToolCallStatus(parentTurn, parentToolCallId, "awaiting_answer", null, {
928
+ child_loop_name: childLoopName,
929
+ child_tool_call_id: childToolCallId,
930
+ description: description || null
931
+ });
932
+ }
933
+ function askUserResultFromPausePayload(pauseToolData, sourceLoop) {
934
+ const args = typeof pauseToolData.arguments === "object" && pauseToolData.arguments !== null ? pauseToolData.arguments : {};
935
+ const payload = { questions: args.questions ?? [] };
936
+ if (sourceLoop) payload.source_loop = sourceLoop;
937
+ return JSON.stringify(payload);
938
+ }
939
+ function sourceLoopFor(loopId, loopDescriptions) {
940
+ if (loopId === "root") return null;
941
+ const description = loopDescriptions.get(loopId);
942
+ if (!description) return null;
943
+ return { loop_name: loopId, description };
944
+ }
945
+ function normalizeChildPause(pausePayload) {
946
+ const rawPtd = pausePayload.pause_tool_data;
947
+ const pauseToolData = typeof rawPtd === "object" && rawPtd !== null ? { ...rawPtd } : { ...pausePayload };
948
+ let sourceLoop = pauseToolData.source_loop;
949
+ if (typeof sourceLoop !== "object" || sourceLoop === null) {
950
+ sourceLoop = pausePayload.source_loop;
951
+ }
952
+ const childLoopName = String(pausePayload.child_loop_name ?? "") || (typeof sourceLoop === "object" && sourceLoop ? String(sourceLoop.name ?? "") : "");
953
+ const childToolCallId = String(
954
+ pausePayload.child_pause_tool_call_id ?? pauseToolData.tool_call_id ?? ""
955
+ );
956
+ const description = typeof sourceLoop === "object" && sourceLoop ? String(sourceLoop.description ?? "") : "";
957
+ if (childLoopName && description) {
958
+ pauseToolData.source_loop = { name: childLoopName, description };
959
+ }
960
+ return { pauseToolData, childLoopName, childToolCallId, description };
961
+ }
962
+
963
+ // src/react/schemas/message.ts
964
+ function inferToolStatus(resultStr) {
965
+ if (resultStr.includes('"Cancelled by user"')) return "cancelled";
966
+ try {
967
+ const parsed = JSON.parse(resultStr);
968
+ if (typeof parsed === "object" && parsed !== null) {
969
+ if ("error" in parsed && parsed.error) return "error";
970
+ const nested = parsed.result;
971
+ if (typeof nested === "object" && nested !== null && "error" in nested && nested.error) {
972
+ return "error";
973
+ }
974
+ }
975
+ } catch {
976
+ }
977
+ return "done";
978
+ }
979
+
980
+ // src/react/projection/state.ts
981
+ function createTurnState(turnId, loopId, opts = {}) {
982
+ return {
983
+ turnId,
984
+ loopId,
985
+ role: "assistant",
986
+ model: opts.model ?? null,
987
+ startedAt: Date.now(),
988
+ contextWindow: opts.contextWindow ?? 0,
989
+ blocks: [],
990
+ toolCalls: [],
991
+ usage: null,
992
+ memoryRefs: opts.memoryRefs ?? null,
993
+ parentForkToolCallId: null
994
+ };
995
+ }
996
+ function snapshot(state, sequence, status) {
997
+ return {
998
+ id: state.turnId,
999
+ sequence,
1000
+ turn_id: state.turnId,
1001
+ loop_id: state.loopId,
1002
+ kind: "message",
1003
+ role: state.role,
1004
+ status,
1005
+ blocks: [...state.blocks],
1006
+ tool_calls: [...state.toolCalls],
1007
+ model: state.model,
1008
+ usage: state.usage ? { ...state.usage } : null,
1009
+ duration_ms: Math.max(0, Date.now() - state.startedAt),
1010
+ started_at: new Date(state.startedAt).toISOString(),
1011
+ context_window: state.contextWindow,
1012
+ memory_refs: state.memoryRefs,
1013
+ parent_fork_tool_call_id: state.parentForkToolCallId
1014
+ };
1015
+ }
1016
+ var PAUSE_TOOL_NAMES = /* @__PURE__ */ new Set(["AskUserQuestion", "ExitPlanMode"]);
1017
+ function toolStatusFromResult(result) {
1018
+ const text = typeof result === "string" ? result : Array.isArray(result) ? result.filter(
1019
+ (p) => typeof p === "object" && p !== null && p.type === "text"
1020
+ ).map((p) => p.text ?? "").join("\n") : String(result ?? "");
1021
+ return inferToolStatus(text);
1022
+ }
1023
+
1024
+ // src/react/projection/builder.ts
1025
+ var ClientProjectionBuilder = class {
1026
+ activeTurns = /* @__PURE__ */ new Map();
1027
+ lastTurnIds = /* @__PURE__ */ new Map();
1028
+ latestTurns = /* @__PURE__ */ new Map();
1029
+ loopDescriptions = /* @__PURE__ */ new Map();
1030
+ pendingChildPauses = /* @__PURE__ */ new Map();
1031
+ pendingMemoryRefs = /* @__PURE__ */ new Map();
1032
+ activeCompactions = /* @__PURE__ */ new Map();
1033
+ seq = 0;
1034
+ syntheticCounter = 0;
1035
+ displayNameResolver;
1036
+ constructor(displayNameResolver) {
1037
+ this.displayNameResolver = displayNameResolver ?? ((n) => n);
1038
+ }
1039
+ processBatch(events) {
1040
+ const lastUpsertByTurn = /* @__PURE__ */ new Map();
1041
+ const nonUpserts = [];
1042
+ for (const event of events) {
1043
+ const updates = this.processEvent(event);
1044
+ if (!updates) continue;
1045
+ for (const u of updates) {
1046
+ if (u.kind === "upsert") {
1047
+ lastUpsertByTurn.set(u.turn.turn_id, u);
1048
+ } else {
1049
+ nonUpserts.push(u);
1050
+ }
1051
+ }
1052
+ }
1053
+ return [...nonUpserts, ...lastUpsertByTurn.values()];
1054
+ }
1055
+ processEvent(event) {
1056
+ const payload = event.payload;
1057
+ const loopId = String(payload.loop_name ?? "root");
1058
+ switch (event.type) {
1059
+ case "memory:inject:done":
1060
+ return this.onMemoryInject(loopId, payload);
1061
+ case "memory:inject:none":
1062
+ return null;
1063
+ case "loop:turn":
1064
+ return this.onLoopTurn(loopId, payload);
1065
+ case "mode:change":
1066
+ return this.onModeChange(loopId, payload);
1067
+ case "plan:status:update":
1068
+ return this.onPlanStatusUpdate(loopId, payload);
1069
+ case "workspace:changed":
1070
+ return this.onWorkspaceChanged(loopId, payload);
1071
+ case "agent:start":
1072
+ return this.onAgentStart(loopId, payload);
1073
+ case "bg:started":
1074
+ return this.onBgStarted(loopId, payload);
1075
+ case "bg:tasks_completed":
1076
+ return this.onBgTasksCompleted(loopId, payload);
1077
+ case "loop:ask_user_answer":
1078
+ return this.onAskUserAnswer(loopId, payload);
1079
+ case "user:message":
1080
+ return this.onUserMessage(loopId, payload);
1081
+ }
1082
+ if (event.type.startsWith("compaction:"))
1083
+ return this.onCompaction(event.type, loopId, payload);
1084
+ const state = this.activeTurns.get(loopId);
1085
+ if (!state) {
1086
+ if (event.type === "chat:end") {
1087
+ this.pendingMemoryRefs.delete(loopId);
1088
+ return null;
1089
+ }
1090
+ if (event.type === "agent:end") return this.onAgentEnd(null, loopId, payload);
1091
+ return null;
1092
+ }
1093
+ switch (event.type) {
1094
+ case "llm:thinking:delta":
1095
+ return this.onDelta(state, "thinking", "", String(payload.content ?? ""));
1096
+ case "llm:content:delta":
1097
+ return this.onDelta(state, "text", "", String(payload.content ?? ""));
1098
+ case "llm:tool_call:created":
1099
+ return this.onToolCallCreated(state, payload);
1100
+ case "llm:response:done":
1101
+ return this.onResponseDone(state, loopId, payload);
1102
+ case "tool:result:done":
1103
+ return this.onToolResultDone(state, loopId, payload);
1104
+ case "loop:tool_ui":
1105
+ return this.onToolUi(state, payload);
1106
+ case "loop:tool_bridge":
1107
+ return this.onToolBridge(state, payload);
1108
+ case "tool:approval:required":
1109
+ return this.onToolApprovalRequired(state, payload);
1110
+ case "loop:child_pause":
1111
+ return this.onChildPause(state, loopId, payload);
1112
+ case "chat:end":
1113
+ return this.onChatEnd(state, loopId, payload);
1114
+ case "agent:end":
1115
+ return this.onAgentEnd(state, loopId, payload);
1116
+ default:
1117
+ return null;
1118
+ }
1119
+ }
1120
+ reset() {
1121
+ this.activeTurns.clear();
1122
+ this.lastTurnIds.clear();
1123
+ this.latestTurns.clear();
1124
+ this.loopDescriptions.clear();
1125
+ this.pendingChildPauses.clear();
1126
+ this.pendingMemoryRefs.clear();
1127
+ this.activeCompactions.clear();
1128
+ this.seq = 0;
1129
+ this.syntheticCounter = 0;
1130
+ }
1131
+ seedSequence(maxSeq) {
1132
+ if (maxSeq > this.seq) {
1133
+ this.seq = maxSeq;
1134
+ }
1135
+ }
1136
+ // --- Event handlers ---
1137
+ onMemoryInject(loopId, payload) {
1138
+ const refs = payload.memory_refs;
1139
+ const turnId = String(payload.turn_id ?? "");
1140
+ if (Array.isArray(refs) && refs.length > 0) {
1141
+ this.pendingMemoryRefs.set(loopId, {
1142
+ turnId,
1143
+ refs: refs.map((r4) => ({
1144
+ id: Number(r4.id),
1145
+ content_preview: String(r4.content_preview ?? ""),
1146
+ skill_name: r4.skill_name != null ? String(r4.skill_name) : null
1147
+ }))
1148
+ });
1149
+ }
1150
+ return null;
1151
+ }
1152
+ onLoopTurn(loopId, payload) {
1153
+ let turnId = String(payload.turn_id ?? this.nextTurnId(`turn:${loopId}`));
1154
+ let memoryRefs = null;
1155
+ const pending = this.pendingMemoryRefs.get(loopId);
1156
+ if (pending) {
1157
+ this.pendingMemoryRefs.delete(loopId);
1158
+ if (pending.turnId) turnId = pending.turnId;
1159
+ memoryRefs = pending.refs;
1160
+ }
1161
+ const rawCw = payload.context_window;
1162
+ const contextWindow = typeof rawCw === "number" && rawCw > 0 ? Math.trunc(rawCw) : 0;
1163
+ const state = createTurnState(turnId, loopId, {
1164
+ model: optStr(payload.model),
1165
+ contextWindow,
1166
+ memoryRefs
1167
+ });
1168
+ this.activeTurns.set(loopId, state);
1169
+ this.lastTurnIds.set(loopId, turnId);
1170
+ const turn = snapshot(state, this.nextSeq(), "streaming");
1171
+ this.latestTurns.set(loopId, turn);
1172
+ return [{ kind: "upsert", turn }];
1173
+ }
1174
+ onModeChange(loopId, payload) {
1175
+ const content = {};
1176
+ if (payload.from != null && payload.from !== "") content.from = String(payload.from);
1177
+ if (payload.to != null && payload.to !== "") content.to = String(payload.to);
1178
+ const turn = buildMarkerTurn(
1179
+ this.nextSeq(),
1180
+ this.nextTurnId("mode_change"),
1181
+ loopId,
1182
+ "mode_change",
1183
+ content
1184
+ );
1185
+ return [{ kind: "upsert", turn }];
1186
+ }
1187
+ onPlanStatusUpdate(loopId, payload) {
1188
+ let statuses = payload.statuses;
1189
+ if (typeof statuses !== "object" || statuses === null) {
1190
+ statuses = payload._statuses ?? {};
1191
+ }
1192
+ const turn = buildMarkerTurn(
1193
+ this.nextSeq(),
1194
+ this.nextTurnId("plan_status"),
1195
+ loopId,
1196
+ "plan_status",
1197
+ { plan_yaml: payload.plan_yaml ?? "", statuses }
1198
+ );
1199
+ return [{ kind: "upsert", turn }];
1200
+ }
1201
+ onWorkspaceChanged(loopId, payload) {
1202
+ const updates = [
1203
+ {
1204
+ kind: "workspace_changed",
1205
+ loopId,
1206
+ toolCallId: optStr(payload.tool_call_id) ?? void 0,
1207
+ toolName: toolNameFromPayload(payload) ?? void 0
1208
+ }
1209
+ ];
1210
+ const state = this.activeTurns.get(loopId);
1211
+ if (state) {
1212
+ const turn = snapshot(state, this.nextSeq(), "streaming");
1213
+ this.latestTurns.set(loopId, turn);
1214
+ this.lastTurnIds.set(loopId, turn.turn_id);
1215
+ updates.push({ kind: "upsert", turn });
1216
+ }
1217
+ return updates;
1218
+ }
1219
+ onAgentStart(loopId, payload) {
1220
+ const description = optStr(payload.description);
1221
+ if (description) this.loopDescriptions.set(loopId, description);
1222
+ const turn = buildSystemNotificationTurn(
1223
+ this.nextSeq(),
1224
+ this.nextTurnId("agent:start"),
1225
+ loopId,
1226
+ "agent:start",
1227
+ "running",
1228
+ `Agent: ${payload.description ?? payload.skill_id ?? "agent"}`,
1229
+ optStr(payload.prompt),
1230
+ {
1231
+ skill_id: optStr(payload.skill_id),
1232
+ description: optStr(payload.description),
1233
+ parent_fork_tool_call_id: optStr(payload.parent_fork_tool_call_id)
1234
+ }
1235
+ );
1236
+ return [{ kind: "upsert", turn }];
1237
+ }
1238
+ onBgStarted(loopId, payload) {
1239
+ const taskId = optStr(payload.task_id) ?? "";
1240
+ const command = optStr(payload.command);
1241
+ const description = optStr(payload.description);
1242
+ const turn = buildSystemNotificationTurn(
1243
+ this.nextSeq(),
1244
+ this.nextTurnId("bg:started"),
1245
+ loopId,
1246
+ "bg:started",
1247
+ "running",
1248
+ description ?? `Background: ${taskId || "task"}`,
1249
+ command,
1250
+ { task_id: taskId, command, description }
1251
+ );
1252
+ return [{ kind: "upsert", turn }];
1253
+ }
1254
+ onBgTasksCompleted(loopId, payload) {
1255
+ const taskIds = Array.isArray(payload.task_ids) ? payload.task_ids : [];
1256
+ const count = typeof payload.count === "number" ? payload.count : taskIds.length;
1257
+ const detail = taskIds.map(String).join(", ");
1258
+ const turn = buildSystemNotificationTurn(
1259
+ this.nextSeq(),
1260
+ this.nextTurnId("bg:tasks_completed"),
1261
+ loopId,
1262
+ "bg:tasks_completed",
1263
+ "done",
1264
+ `Background tasks completed (${count})`,
1265
+ detail || null,
1266
+ { task_ids: taskIds, count }
1267
+ );
1268
+ return [{ kind: "upsert", turn }];
1269
+ }
1270
+ onAskUserAnswer(loopId, payload) {
1271
+ const toolCallId = String(payload.tool_call_id ?? "");
1272
+ const pending = this.pendingChildPauses.get(toolCallId);
1273
+ const parentLoopId = pending?.parentLoopName;
1274
+ if (pending) {
1275
+ this.pendingChildPauses.delete(toolCallId);
1276
+ const childTurn = this.activeTurns.get(pending.childLoopName) ?? this.latestTurns.get(pending.childLoopName);
1277
+ setToolCallStatus(childTurn, pending.childToolCallId, "done", null, null);
1278
+ const parentTurn = this.activeTurns.get(pending.parentLoopName) ?? this.latestTurns.get(pending.parentLoopName);
1279
+ setToolCallStatus(parentTurn, pending.parentToolCallId, "done", null, null);
1280
+ }
1281
+ const directTurn = this.activeTurns.get(loopId) ?? this.latestTurns.get(loopId);
1282
+ setToolCallStatus(directTurn, toolCallId, "done", null, null);
1283
+ return this.collectLoopUpdates(loopId, parentLoopId);
1284
+ }
1285
+ onUserMessage(_loopId, payload) {
1286
+ const entryId = String(payload.entry_id ?? this.nextTurnId("user"));
1287
+ const displayContent = payload.display_content ?? payload.content ?? "";
1288
+ const turn = {
1289
+ id: entryId,
1290
+ sequence: this.nextSeq(),
1291
+ turn_id: entryId,
1292
+ loop_id: "root",
1293
+ kind: "message",
1294
+ role: "user",
1295
+ status: "completed",
1296
+ blocks: [{ type: "text", content: displayContent }],
1297
+ tool_calls: [],
1298
+ model: null,
1299
+ usage: null,
1300
+ duration_ms: 0
1301
+ };
1302
+ return [{ kind: "upsert", turn }];
1303
+ }
1304
+ // --- Delta / streaming events ---
1305
+ onDelta(state, blockType, _toolCallId, content) {
1306
+ if (!content) return null;
1307
+ appendTextBlock(state, blockType, content);
1308
+ return this.syncPatch(state);
1309
+ }
1310
+ onToolCallCreated(state, payload) {
1311
+ if ("arguments_delta" in payload) {
1312
+ const delta = String(payload.arguments_delta ?? "");
1313
+ const toolCallId2 = String(payload.id ?? "");
1314
+ if (delta && toolCallId2) {
1315
+ appendToolCallArguments(state, toolCallId2, delta);
1316
+ return this.syncPatch(state);
1317
+ }
1318
+ return null;
1319
+ }
1320
+ const toolCallId = String(payload.id ?? "");
1321
+ const toolName = toolNameFromPayload(payload);
1322
+ const displayName = String(payload.display_name ?? "") || this.displayNameResolver(toolName);
1323
+ const args = toolArgsFromPayload(payload);
1324
+ upsertToolCall(state, toolCallId, toolName, displayName, args);
1325
+ return this.syncPatch(state);
1326
+ }
1327
+ onResponseDone(state, loopId, payload) {
1328
+ const model = optStr(payload.model);
1329
+ if (model) state.model = model;
1330
+ if (typeof payload.usage === "object" && payload.usage !== null) {
1331
+ state.usage = { ...payload.usage };
1332
+ }
1333
+ const toolCalls = payload.tool_calls;
1334
+ if (Array.isArray(toolCalls)) {
1335
+ for (const raw of toolCalls) {
1336
+ if (typeof raw !== "object" || raw === null) continue;
1337
+ const tc = raw;
1338
+ const fn = tc.function ?? {};
1339
+ const toolName = String(fn.name ?? "");
1340
+ const displayName = String(tc.display_name ?? "") || this.displayNameResolver(toolName);
1341
+ upsertToolCall(
1342
+ state,
1343
+ String(tc.id ?? ""),
1344
+ toolName,
1345
+ displayName,
1346
+ String(fn.arguments ?? "")
1347
+ );
1348
+ }
1349
+ }
1350
+ if (state.toolCalls.length === 0) {
1351
+ return this.finalize(loopId, "completed");
1352
+ }
1353
+ return this.syncPatch(state);
1354
+ }
1355
+ onToolResultDone(state, loopId, payload) {
1356
+ const toolCallId = String(payload.tool_call_id ?? "");
1357
+ const content = payload.content ?? "";
1358
+ const status = toolStatusFromResult(content);
1359
+ const rawDuration = payload.duration_ms;
1360
+ const durationMs = typeof rawDuration === "number" && rawDuration >= 0 ? Math.round(rawDuration) : null;
1361
+ const sl = sourceLoopFor(state.loopId, this.loopDescriptions);
1362
+ applyToolResult(state, toolCallId, content, status, durationMs, sl);
1363
+ if (this.shouldFinalizeAfterToolResults(state)) {
1364
+ return this.finalize(loopId, "completed");
1365
+ }
1366
+ return this.syncPatch(state);
1367
+ }
1368
+ onToolUi(state, payload) {
1369
+ const toolCallId = String(payload.tool_call_id ?? "");
1370
+ const ui = payload.ui;
1371
+ if (toolCallId && typeof ui === "object" && ui !== null) {
1372
+ state.blocks.push({
1373
+ type: "tool_ui",
1374
+ content: ui,
1375
+ tool_call_id: toolCallId
1376
+ });
1377
+ }
1378
+ return this.syncPatch(state);
1379
+ }
1380
+ onToolBridge(state, payload) {
1381
+ const bridge = payload.bridge;
1382
+ if (typeof bridge !== "object" || bridge === null) return null;
1383
+ state.blocks.push({
1384
+ type: "tool_bridge",
1385
+ content: bridge,
1386
+ tool_call_id: String(payload.tool_call_id ?? "") || null
1387
+ });
1388
+ return this.syncPatch(state);
1389
+ }
1390
+ onToolApprovalRequired(state, payload) {
1391
+ const toolCallId = String(payload.tool_call_id ?? "");
1392
+ const toolName = String(payload.tool_name ?? "");
1393
+ const displayName = this.displayNameResolver(toolName);
1394
+ upsertToolCall(state, toolCallId, toolName, displayName, "");
1395
+ return this.syncPatch(state);
1396
+ }
1397
+ onChildPause(state, loopId, payload) {
1398
+ const pauseToolData = payload.pause_tool_data;
1399
+ if (typeof pauseToolData !== "object" || pauseToolData === null)
1400
+ return this.syncPatch(state);
1401
+ const ptd = pauseToolData;
1402
+ const sourceLoop = ptd.source_loop;
1403
+ if (typeof sourceLoop === "object" && sourceLoop) {
1404
+ const slName = String(sourceLoop.name ?? "");
1405
+ const slDesc = optStr(sourceLoop.description);
1406
+ if (slName && slDesc) this.loopDescriptions.set(slName, slDesc);
1407
+ }
1408
+ const { childLoopName, childToolCallId, description } = normalizeChildPause(payload);
1409
+ if (!childToolCallId) return this.syncPatch(state);
1410
+ const existing = this.pendingChildPauses.get(childToolCallId);
1411
+ const parentLoopName = String(
1412
+ payload.parent_loop_name ?? existing?.parentLoopName ?? "root"
1413
+ );
1414
+ const parentToolCallId = String(
1415
+ payload.parent_fork_tool_call_id ?? existing?.parentToolCallId ?? ""
1416
+ );
1417
+ const resolvedChildLoopName = String(payload.child_loop_name ?? "") || existing?.childLoopName || childLoopName || loopId;
1418
+ this.pendingChildPauses.set(childToolCallId, {
1419
+ parentLoopName,
1420
+ parentToolCallId,
1421
+ childLoopName: resolvedChildLoopName,
1422
+ childToolCallId,
1423
+ description: description || existing?.description || ""
1424
+ });
1425
+ applyAskUserPauseToTurn(
1426
+ state,
1427
+ ptd,
1428
+ childToolCallId,
1429
+ resolvedChildLoopName,
1430
+ this.pendingChildPauses.get(childToolCallId).description,
1431
+ this.displayNameResolver
1432
+ );
1433
+ const parentTurn = this.activeTurns.get(parentLoopName) ?? this.latestTurns.get(parentLoopName);
1434
+ if (parentTurn) {
1435
+ applyChildPauseToParent(
1436
+ parentTurn,
1437
+ parentToolCallId,
1438
+ resolvedChildLoopName,
1439
+ childToolCallId,
1440
+ this.pendingChildPauses.get(childToolCallId).description,
1441
+ this.displayNameResolver
1442
+ );
1443
+ }
1444
+ return this.collectLoopUpdates(loopId, parentLoopName);
1445
+ }
1446
+ onChatEnd(state, loopId, payload) {
1447
+ const status = String(payload.status ?? "completed");
1448
+ const pauseToolData = payload.pause_tool_data;
1449
+ if (typeof pauseToolData === "object" && pauseToolData !== null) {
1450
+ const ptd = pauseToolData;
1451
+ const pauseToolName = String(ptd.name ?? "");
1452
+ const normalized = pauseToolName.includes(":") ? pauseToolName.split(":").pop() : pauseToolName;
1453
+ const sourceLoop = ptd.source_loop;
1454
+ if (typeof sourceLoop === "object" && sourceLoop) {
1455
+ const slName = String(sourceLoop.name ?? "");
1456
+ const slDesc = optStr(sourceLoop.description);
1457
+ if (slName && slDesc) this.loopDescriptions.set(slName, slDesc);
1458
+ if (status === "paused" && slName) {
1459
+ applyChildPauseToParent(
1460
+ state,
1461
+ String(ptd.parent_fork_tool_call_id ?? ""),
1462
+ slName,
1463
+ String(ptd.tool_call_id ?? ""),
1464
+ slDesc ?? "",
1465
+ this.displayNameResolver
1466
+ );
1467
+ const childTurn = this.activeTurns.get(slName);
1468
+ if (childTurn) {
1469
+ applyAskUserPauseToTurn(
1470
+ childTurn,
1471
+ ptd,
1472
+ String(ptd.tool_call_id ?? ""),
1473
+ slName,
1474
+ slDesc ?? "",
1475
+ this.displayNameResolver
1476
+ );
1477
+ }
1478
+ }
1479
+ } else if (status === "paused" && normalized === "AskUserQuestion") {
1480
+ applyAskUserPauseToTurn(
1481
+ state,
1482
+ ptd,
1483
+ String(ptd.tool_call_id ?? ""),
1484
+ "",
1485
+ "",
1486
+ this.displayNameResolver
1487
+ );
1488
+ }
1489
+ }
1490
+ const finalStatus = { completed: "completed", paused: "paused", failed: "failed", interrupted: "interrupted" }[status];
1491
+ if (!finalStatus) return null;
1492
+ if (!this.activeTurns.has(loopId)) {
1493
+ this.pendingMemoryRefs.delete(loopId);
1494
+ }
1495
+ return this.finalize(loopId, finalStatus);
1496
+ }
1497
+ onAgentEnd(state, loopId, payload) {
1498
+ const ok = payload.ok !== false;
1499
+ const status = ok ? "done" : "error";
1500
+ const title = `Agent: ${payload.description ?? payload.skill_id ?? "agent"}`;
1501
+ const detail = optStr(payload.error);
1502
+ const metadata = {
1503
+ skill_id: optStr(payload.skill_id),
1504
+ description: optStr(payload.description),
1505
+ parent_fork_tool_call_id: optStr(payload.parent_fork_tool_call_id),
1506
+ ok
1507
+ };
1508
+ if (state) {
1509
+ state.blocks.push(buildSystemNotificationBlock("agent:end", status, title, detail, metadata));
1510
+ return this.finalize(loopId, ok ? "completed" : "failed");
1511
+ }
1512
+ const turn = buildSystemNotificationTurn(
1513
+ this.nextSeq(),
1514
+ this.nextTurnId("agent:end"),
1515
+ loopId,
1516
+ "agent:end",
1517
+ status,
1518
+ title,
1519
+ detail,
1520
+ metadata
1521
+ );
1522
+ return [{ kind: "upsert", turn }];
1523
+ }
1524
+ onCompaction(eventType, loopId, payload) {
1525
+ const compactionId = String(payload.compaction_id ?? "");
1526
+ if (!compactionId) return null;
1527
+ const current = {
1528
+ ...this.activeCompactions.get(compactionId) ?? {},
1529
+ ...payload,
1530
+ loop_id: loopId
1531
+ };
1532
+ let status;
1533
+ switch (eventType) {
1534
+ case "compaction:start":
1535
+ status = "streaming";
1536
+ this.activeCompactions.set(compactionId, current);
1537
+ break;
1538
+ case "compaction:end":
1539
+ status = "completed";
1540
+ this.activeCompactions.delete(compactionId);
1541
+ break;
1542
+ case "compaction:abort":
1543
+ status = "interrupted";
1544
+ this.activeCompactions.delete(compactionId);
1545
+ break;
1546
+ case "compaction:error":
1547
+ status = "failed";
1548
+ this.activeCompactions.delete(compactionId);
1549
+ break;
1550
+ default:
1551
+ status = "streaming";
1552
+ this.activeCompactions.set(compactionId, current);
1553
+ }
1554
+ const turn = buildCompactionTurn(this.nextSeq(), compactionId, loopId, status, current);
1555
+ return [{ kind: "upsert", turn }];
1556
+ }
1557
+ // --- Internal helpers ---
1558
+ syncPatch(state) {
1559
+ const turn = snapshot(state, this.nextSeq(), "streaming");
1560
+ this.latestTurns.set(state.loopId, turn);
1561
+ this.lastTurnIds.set(state.loopId, turn.turn_id);
1562
+ return [{ kind: "upsert", turn }];
1563
+ }
1564
+ finalize(loopId, status) {
1565
+ const state = this.activeTurns.get(loopId);
1566
+ if (!state) return null;
1567
+ this.activeTurns.delete(loopId);
1568
+ const turn = snapshot(state, this.nextSeq(), status);
1569
+ this.lastTurnIds.set(loopId, turn.turn_id);
1570
+ this.latestTurns.set(loopId, turn);
1571
+ return [{ kind: "upsert", turn }];
1572
+ }
1573
+ shouldFinalizeAfterToolResults(state) {
1574
+ if (state.toolCalls.length === 0) return true;
1575
+ if (state.toolCalls.some((tc) => tc.status === "pending")) return false;
1576
+ return !state.toolCalls.some((tc) => {
1577
+ const normalized = tc.tool_name.includes(":") ? tc.tool_name.split(":").pop() : tc.tool_name;
1578
+ return PAUSE_TOOL_NAMES.has(normalized);
1579
+ });
1580
+ }
1581
+ collectLoopUpdates(...loopIds) {
1582
+ const updates = [];
1583
+ for (const loopId of loopIds) {
1584
+ if (!loopId) continue;
1585
+ const state = this.activeTurns.get(loopId);
1586
+ if (state) {
1587
+ updates.push(...this.syncPatch(state));
1588
+ continue;
1589
+ }
1590
+ const proj = this.latestTurns.get(loopId);
1591
+ if (proj) {
1592
+ const updated = { ...proj, sequence: this.nextSeq() };
1593
+ this.latestTurns.set(loopId, updated);
1594
+ updates.push({ kind: "upsert", turn: updated });
1595
+ }
1596
+ }
1597
+ return updates;
1598
+ }
1599
+ nextSeq() {
1600
+ return ++this.seq;
1601
+ }
1602
+ nextTurnId(prefix) {
1603
+ this.syntheticCounter++;
1604
+ const hex = Math.random().toString(16).slice(2, 10);
1605
+ return `${prefix}:${this.syntheticCounter}:${hex}`;
1606
+ }
1607
+ };
1608
+ function optStr(value) {
1609
+ if (value == null || value === "") return null;
1610
+ return String(value);
1611
+ }
1612
+ function toolNameFromPayload(payload) {
1613
+ const fn = payload.function;
1614
+ if (typeof fn === "object" && fn !== null) {
1615
+ return String(fn.name ?? "");
1616
+ }
1617
+ return String(payload.tool_name ?? "");
1618
+ }
1619
+ function toolArgsFromPayload(payload) {
1620
+ const fn = payload.function;
1621
+ if (typeof fn === "object" && fn !== null) {
1622
+ return String(fn.arguments ?? "");
1623
+ }
1624
+ return "";
1625
+ }
1626
+
574
1627
  // src/react/stores/auth-store.ts
575
1628
  import { create as create6 } from "zustand";
576
1629
  import { createJSONStorage, persist } from "zustand/middleware";
@@ -1624,7 +2677,7 @@ var useSessionStore = create5()((set, get) => ({
1624
2677
  rewindDrafts: {},
1625
2678
  errorMessages: {},
1626
2679
  _freshSessions: /* @__PURE__ */ new Set(),
1627
- fetchSessions: async () => {
2680
+ fetchAllSessions: async () => {
1628
2681
  set({ loading: true });
1629
2682
  try {
1630
2683
  const currentState = get();
@@ -1692,7 +2745,7 @@ var useSessionStore = create5()((set, get) => ({
1692
2745
  });
1693
2746
  get().setActiveSession(session_id);
1694
2747
  invalidateHomeSidebarSessions();
1695
- get().fetchSessions().catch(() => {
2748
+ get().fetchAllSessions().catch(() => {
1696
2749
  });
1697
2750
  return session_id;
1698
2751
  },
@@ -1762,7 +2815,7 @@ var useSessionStore = create5()((set, get) => ({
1762
2815
  await deleteSession(id);
1763
2816
  invalidateHomeSidebarSessions();
1764
2817
  const wasActive = get().activeSessionId === id;
1765
- await get().fetchSessions();
2818
+ await get().fetchAllSessions();
1766
2819
  if (!wasActive) {
1767
2820
  return;
1768
2821
  }
@@ -1907,8 +2960,6 @@ function finishAuth(set, payload) {
1907
2960
  error: null
1908
2961
  });
1909
2962
  agentSocket?.reconnect();
1910
- useSessionStore.getState().fetchSessions().catch(() => {
1911
- });
1912
2963
  }
1913
2964
  function finishCookieHydration(set, payload) {
1914
2965
  set({
@@ -1919,8 +2970,6 @@ function finishCookieHydration(set, payload) {
1919
2970
  error: null
1920
2971
  });
1921
2972
  agentSocket?.reconnect();
1922
- useSessionStore.getState().fetchSessions().catch(() => {
1923
- });
1924
2973
  }
1925
2974
  function toUser(info) {
1926
2975
  return {
@@ -2393,6 +3442,7 @@ var AgentSocket = class {
2393
3442
  boardProjectRefCounts = /* @__PURE__ */ new Map();
2394
3443
  patchFlushHandle = null;
2395
3444
  patchFlushCancel = null;
3445
+ projectionBuilder = new ClientProjectionBuilder();
2396
3446
  _ensureConnected() {
2397
3447
  if (this.socket.connected || this.socket.active) {
2398
3448
  return;
@@ -2499,6 +3549,33 @@ var AgentSocket = class {
2499
3549
  if (!sessionId) return;
2500
3550
  applyTurn(sessionId, data);
2501
3551
  });
3552
+ s.on("turn:events", (data) => {
3553
+ const sessionId = this._resolveSessionId(data);
3554
+ if (!sessionId || !data.events?.length) return;
3555
+ if (!useChatStore.getState().isStreaming[sessionId]) {
3556
+ useSessionStore.getState().updateSessionStatus(sessionId, "running");
3557
+ useChatStore.getState().setStreaming(sessionId, true);
3558
+ }
3559
+ const existingTurns = useChatStore.getState().turns[sessionId];
3560
+ if (existingTurns?.length) {
3561
+ this.projectionBuilder.seedSequence(
3562
+ Math.max(...existingTurns.map((t) => t.sequence))
3563
+ );
3564
+ }
3565
+ const updates = this.projectionBuilder.processBatch(data.events);
3566
+ for (const update of updates) {
3567
+ if (update.kind === "upsert") {
3568
+ useChatStore.getState().upsertTurn(sessionId, update.turn);
3569
+ const mode = extractModeFromBlocks3(update.turn.blocks);
3570
+ if (mode === "planning" || mode === "executing") {
3571
+ useSessionStore.getState().setMode(sessionId, mode);
3572
+ }
3573
+ this._applyProjectionSideEffects(sessionId, update.turn);
3574
+ } else if (update.kind === "workspace_changed") {
3575
+ notifyWorkspaceFilesChanged(sessionId);
3576
+ }
3577
+ }
3578
+ });
2502
3579
  s.on("chat:start", (data) => {
2503
3580
  const sessionId = this._resolveSessionId(data);
2504
3581
  if (!sessionId) return;
@@ -2599,6 +3676,7 @@ var AgentSocket = class {
2599
3676
  if (!sessionId) return;
2600
3677
  const patch = {};
2601
3678
  if (typeof data.intent === "string") patch.intent = data.intent;
3679
+ if (data.status) patch.status = data.status;
2602
3680
  if ("model" in data) patch.model = data.model;
2603
3681
  if ("bound_skill_id" in data) patch.bound_skill_id = data.bound_skill_id;
2604
3682
  if ("replay_state" in data) patch.replay_state = data.replay_state;
@@ -2917,6 +3995,7 @@ var AgentSocket = class {
2917
3995
  this.deliveredBridgeKeys.clear();
2918
3996
  useUiStore.getState().clearArtifacts();
2919
3997
  useCardStateStore.getState().clearAllStates();
3998
+ this.projectionBuilder.reset();
2920
3999
  }
2921
4000
  if (this.joinedSessions.has(sessionId)) {
2922
4001
  this._refreshRunningState(sessionId);
@@ -2955,9 +4034,9 @@ var AgentSocket = class {
2955
4034
  };
2956
4035
  }
2957
4036
  /**
2958
- * 订阅 session:updated(智能体意图等会话属性变更)。全局 handler 只会
4037
+ * 订阅 session:updated(智能体意图、状态等会话属性变更)。全局 handler 只会
2959
4038
  * patch 已在 useSessionStore 列表里的会话;看板任务这类不在列表里的
2960
- * 会话,由调用方通过本方法自行消费意图更新。
4039
+ * 会话,由调用方通过本方法自行消费属性更新。
2961
4040
  */
2962
4041
  onSessionUpdated(handler) {
2963
4042
  this.socket.on("session:updated", handler);
@@ -3087,6 +4166,7 @@ var AgentSocket = class {
3087
4166
  mode,
3088
4167
  askuser_answer: askuserAnswer,
3089
4168
  model: extras?.model,
4169
+ thinking_override: extras?.thinkingOverride,
3090
4170
  whatif: extras?.whatif,
3091
4171
  replay_decision: extras?.replay_decision
3092
4172
  };
@@ -3402,4 +4482,4 @@ export {
3402
4482
  bootstrapBladeClient,
3403
4483
  getBootstrappedClient
3404
4484
  };
3405
- //# sourceMappingURL=chunk-3UY7SD3P.js.map
4485
+ //# sourceMappingURL=chunk-QEYZZDLM.js.map