@ellipsis-dev/sdk 0.35.0 → 0.37.0
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/index.d.ts +56 -175
- package/dist/index.js +38 -82
- package/dist/store/index.d.ts +14 -25
- package/dist/store/index.js +228 -284
- package/dist/stream/index.d.ts +2 -3
- package/dist/stream/index.js +11 -22
- package/dist/{types-BrLpRRde.d.ts → types-BXbnHOQe.d.ts} +844 -1555
- package/package.json +1 -1
- package/schema/collection_frames.schema.json +87 -211
- package/schema/frames.schema.json +842 -1496
- package/schema/lifecycle.schema.json +389 -150
- package/schema/openapi.v1.json +761 -1619
package/dist/store/index.js
CHANGED
|
@@ -47,6 +47,42 @@ function claudePayload(record) {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// src/store/codexAppServer.ts
|
|
50
|
+
function codexSubagentThreads(records) {
|
|
51
|
+
const threads = /* @__PURE__ */ new Set();
|
|
52
|
+
for (const record of records) addCodexSubagentThreads(threads, record);
|
|
53
|
+
return threads;
|
|
54
|
+
}
|
|
55
|
+
function addCodexSubagentThreads(threads, record) {
|
|
56
|
+
if (record.kind !== "codex_app_server") return false;
|
|
57
|
+
const event = record.payload;
|
|
58
|
+
if (event.method !== "item/started" && event.method !== "item/completed") {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
const item = event.params.item;
|
|
62
|
+
if (item.type === "subAgentActivity") {
|
|
63
|
+
threads.add(item.agentThreadId);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
if (item.type === "collabAgentToolCall") {
|
|
67
|
+
for (const thread of item.receiverThreadIds) threads.add(thread);
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
function isCodexSubagentSpawn(record) {
|
|
73
|
+
if (record.kind !== "codex_app_server") return false;
|
|
74
|
+
const event = record.payload;
|
|
75
|
+
if (event.method !== "item/started" && event.method !== "item/completed") {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const item = event.params.item;
|
|
79
|
+
return item.type === "subAgentActivity" && item.kind === "started";
|
|
80
|
+
}
|
|
81
|
+
function isCodexSubagentRecord(threads, record) {
|
|
82
|
+
if (record.kind !== "codex_app_server") return false;
|
|
83
|
+
const params = record.payload.params;
|
|
84
|
+
return "threadId" in params && typeof params.threadId === "string" && threads.has(params.threadId);
|
|
85
|
+
}
|
|
50
86
|
function codexAppServerContent(event) {
|
|
51
87
|
if (event.method === "turn/completed") {
|
|
52
88
|
return { kind: "end", isError: event.params.turn.status !== "completed" };
|
|
@@ -86,6 +122,15 @@ function codexAppServerContent(event) {
|
|
|
86
122
|
result: item.changes.map((change) => change.diff).join("\n"),
|
|
87
123
|
isError: item.status === "failed" || item.status === "declined"
|
|
88
124
|
};
|
|
125
|
+
case "subAgentActivity":
|
|
126
|
+
return {
|
|
127
|
+
kind: "tool",
|
|
128
|
+
name: "Agent",
|
|
129
|
+
input: { agentPath: item.agentPath ?? null, kind: item.kind },
|
|
130
|
+
summary: item.agentPath ?? item.agentThreadId,
|
|
131
|
+
result: item.kind,
|
|
132
|
+
isError: false
|
|
133
|
+
};
|
|
89
134
|
case "webSearch":
|
|
90
135
|
return {
|
|
91
136
|
kind: "tool",
|
|
@@ -101,16 +146,19 @@ function codexAppServerContent(event) {
|
|
|
101
146
|
}
|
|
102
147
|
|
|
103
148
|
// src/store/lifecycle.ts
|
|
104
|
-
function environmentOutputStep(
|
|
149
|
+
function environmentOutputStep(source) {
|
|
150
|
+
const payload = source;
|
|
105
151
|
if (typeof payload.step === "string" && payload.step) return payload.step;
|
|
106
152
|
return typeof payload.phase === "string" ? payload.phase : "setup";
|
|
107
153
|
}
|
|
108
|
-
function environmentOutputLines(
|
|
154
|
+
function environmentOutputLines(source) {
|
|
155
|
+
const payload = source;
|
|
109
156
|
return Array.isArray(payload.lines) ? payload.lines.filter(
|
|
110
157
|
(l) => typeof l === "string" && l.trim().length > 0
|
|
111
158
|
) : [];
|
|
112
159
|
}
|
|
113
|
-
function environmentOutputLine(
|
|
160
|
+
function environmentOutputLine(source) {
|
|
161
|
+
const payload = source;
|
|
114
162
|
const lines = environmentOutputLines(payload);
|
|
115
163
|
return lines.length ? lines[lines.length - 1].trim() : null;
|
|
116
164
|
}
|
|
@@ -170,13 +218,16 @@ function environmentPhaseText(payload) {
|
|
|
170
218
|
return label;
|
|
171
219
|
}
|
|
172
220
|
}
|
|
173
|
-
function
|
|
221
|
+
function messageEndedText(source) {
|
|
222
|
+
const payload = source;
|
|
174
223
|
const status = typeof payload.status === "string" ? payload.status : "";
|
|
175
224
|
if (!status || status === "completed") return null;
|
|
176
|
-
const
|
|
177
|
-
|
|
225
|
+
const error = payload.error && typeof payload.error === "object" ? payload.error : {};
|
|
226
|
+
const detail = typeof error.detail === "string" ? error.detail.trim() : "";
|
|
227
|
+
return detail || `Message ${status}`;
|
|
178
228
|
}
|
|
179
|
-
function lifecycleText(recordType,
|
|
229
|
+
function lifecycleText(recordType, source) {
|
|
230
|
+
const payload = source;
|
|
180
231
|
switch (recordType) {
|
|
181
232
|
case "environment_phase":
|
|
182
233
|
return environmentPhaseText(payload);
|
|
@@ -194,12 +245,12 @@ function lifecycleText(recordType, payload) {
|
|
|
194
245
|
if (duration) parts.push(duration);
|
|
195
246
|
return parts.join(", ");
|
|
196
247
|
}
|
|
197
|
-
case "
|
|
248
|
+
case "message_queued":
|
|
198
249
|
return typeof payload.limit === "number" ? `Waiting because ${payload.limit} sessions are already alive on this account` : null;
|
|
199
|
-
case "
|
|
200
|
-
return
|
|
250
|
+
case "message_ended":
|
|
251
|
+
return messageEndedText(payload);
|
|
201
252
|
case "session_closed":
|
|
202
|
-
return "
|
|
253
|
+
return "Session closed";
|
|
203
254
|
default:
|
|
204
255
|
return null;
|
|
205
256
|
}
|
|
@@ -689,97 +740,74 @@ function geminiStreamContent(event) {
|
|
|
689
740
|
// src/store/progress.ts
|
|
690
741
|
function messageProgress(records) {
|
|
691
742
|
const messages = /* @__PURE__ */ new Map();
|
|
692
|
-
const pending = /* @__PURE__ */ new
|
|
693
|
-
const turns = /* @__PURE__ */ new Map();
|
|
743
|
+
const pending = /* @__PURE__ */ new Set();
|
|
694
744
|
let ready = false;
|
|
695
|
-
const
|
|
696
|
-
let
|
|
697
|
-
if (!
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
messages: /* @__PURE__ */ new Set()
|
|
745
|
+
const get = (id) => {
|
|
746
|
+
let message = messages.get(id);
|
|
747
|
+
if (!message) {
|
|
748
|
+
message = {
|
|
749
|
+
phase: "queued",
|
|
750
|
+
timing: { startedAt: null, completedAt: null }
|
|
702
751
|
};
|
|
703
|
-
|
|
752
|
+
messages.set(id, message);
|
|
704
753
|
}
|
|
705
|
-
return
|
|
754
|
+
return message;
|
|
706
755
|
};
|
|
707
|
-
const
|
|
708
|
-
const
|
|
709
|
-
|
|
710
|
-
const turn = getTurn(turnId);
|
|
711
|
-
if (!turn.messages.has(messageId)) {
|
|
712
|
-
turn.messages.add(messageId);
|
|
713
|
-
message.turns.push(turn.timing);
|
|
714
|
-
}
|
|
715
|
-
pending.delete(messageId);
|
|
716
|
-
message.phase = turn.phase;
|
|
717
|
-
};
|
|
718
|
-
const setPending = (turnId, phase) => {
|
|
719
|
-
for (const [id, turn] of pending) {
|
|
720
|
-
if (turnId == null || turn == null || turn === turnId)
|
|
721
|
-
messages.get(id).phase = phase;
|
|
756
|
+
const setPending = (messageId, phase) => {
|
|
757
|
+
for (const id of pending) {
|
|
758
|
+
if (messageId == null || messageId === id) get(id).phase = phase;
|
|
722
759
|
}
|
|
723
760
|
};
|
|
724
761
|
for (const record of records) {
|
|
762
|
+
const recordMessageId = record.message_id ?? null;
|
|
725
763
|
if (record.kind === "platform") {
|
|
726
|
-
const p = record.payload;
|
|
727
|
-
const messageId = typeof p.message_id === "string" ? p.message_id :
|
|
728
|
-
const turnId = typeof p.turn_id === "string" ? p.turn_id : record.turn_id;
|
|
764
|
+
const p = { ...record.payload };
|
|
765
|
+
const messageId = typeof p.message_id === "string" ? p.message_id : typeof p.id === "string" && record.record_type === "message" ? p.id : recordMessageId;
|
|
729
766
|
switch (record.record_type) {
|
|
730
|
-
case "
|
|
767
|
+
case "message":
|
|
731
768
|
if (messageId && !messages.has(messageId)) {
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
else pending.set(messageId, turnId ?? null);
|
|
769
|
+
get(messageId);
|
|
770
|
+
pending.add(messageId);
|
|
735
771
|
}
|
|
736
772
|
break;
|
|
737
|
-
case "message_delivered":
|
|
738
|
-
if (messageId && turnId) attach(messageId, turnId);
|
|
739
|
-
break;
|
|
740
773
|
case "message_requeued":
|
|
741
774
|
if (messageId && messages.has(messageId)) {
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
775
|
+
pending.add(messageId);
|
|
776
|
+
const message = get(messageId);
|
|
777
|
+
message.phase = "queued";
|
|
778
|
+
message.timing.startedAt = null;
|
|
779
|
+
message.timing.completedAt = null;
|
|
745
780
|
}
|
|
746
781
|
break;
|
|
747
782
|
case "environment_phase":
|
|
748
783
|
case "environment_output":
|
|
749
784
|
ready = false;
|
|
750
|
-
setPending(
|
|
785
|
+
setPending(recordMessageId, "preparing");
|
|
751
786
|
break;
|
|
752
787
|
case "environment_ready":
|
|
753
788
|
ready = false;
|
|
754
|
-
setPending(
|
|
789
|
+
setPending(recordMessageId, "starting");
|
|
755
790
|
break;
|
|
756
|
-
case "
|
|
757
|
-
if (
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
791
|
+
case "message_started":
|
|
792
|
+
if (messageId) {
|
|
793
|
+
const message = get(messageId);
|
|
794
|
+
message.timing.startedAt = record.created_at;
|
|
795
|
+
message.phase = ready ? "working" : "starting";
|
|
796
|
+
pending.delete(messageId);
|
|
762
797
|
}
|
|
763
798
|
break;
|
|
764
|
-
case "
|
|
765
|
-
if (
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
if (!pending.has(id)) messages.get(id).phase = null;
|
|
771
|
-
}
|
|
772
|
-
for (const [id, pendingTurn] of pending) {
|
|
773
|
-
if (pendingTurn === turnId) {
|
|
774
|
-
pending.delete(id);
|
|
775
|
-
messages.get(id).phase = null;
|
|
776
|
-
}
|
|
777
|
-
}
|
|
799
|
+
case "message_ended":
|
|
800
|
+
if (messageId) {
|
|
801
|
+
const message = get(messageId);
|
|
802
|
+
message.timing.completedAt = record.created_at;
|
|
803
|
+
message.phase = null;
|
|
804
|
+
pending.delete(messageId);
|
|
778
805
|
}
|
|
779
806
|
break;
|
|
780
807
|
case "session_closed":
|
|
781
808
|
ready = false;
|
|
782
|
-
for (const id of pending
|
|
809
|
+
for (const id of pending) get(id).phase = null;
|
|
810
|
+
pending.clear();
|
|
783
811
|
break;
|
|
784
812
|
}
|
|
785
813
|
continue;
|
|
@@ -788,18 +816,15 @@ function messageProgress(records) {
|
|
|
788
816
|
const agentStarted = record.kind === "codex_app_server" && record.payload.method === "turn/started" || record.kind === "codex" && record.payload.type === "turn.started" || record.kind === "gemini" && record.payload.type === "init" || claude != null && (claude.kind === "assistant" || claude.kind === "user" || claude.kind === "system" && claude.subtype === "init");
|
|
789
817
|
if (agentStarted) {
|
|
790
818
|
ready = true;
|
|
791
|
-
if (
|
|
792
|
-
const
|
|
793
|
-
if (
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
819
|
+
if (recordMessageId) {
|
|
820
|
+
const message = get(recordMessageId);
|
|
821
|
+
if (message.timing.completedAt == null) {
|
|
822
|
+
message.timing.startedAt ??= record.created_at;
|
|
823
|
+
message.phase = "working";
|
|
824
|
+
pending.delete(recordMessageId);
|
|
797
825
|
}
|
|
798
826
|
}
|
|
799
827
|
}
|
|
800
|
-
if (record.session_message_id && record.turn_id) {
|
|
801
|
-
attach(record.session_message_id, record.turn_id);
|
|
802
|
-
}
|
|
803
828
|
}
|
|
804
829
|
return messages;
|
|
805
830
|
}
|
|
@@ -815,10 +840,9 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
815
840
|
const turns = [];
|
|
816
841
|
const toolNodeByUseId = /* @__PURE__ */ new Map();
|
|
817
842
|
const openGeminiTools = /* @__PURE__ */ new Map();
|
|
843
|
+
const codexSubagentThreads2 = /* @__PURE__ */ new Set();
|
|
818
844
|
const userTurnByMessageId = /* @__PURE__ */ new Map();
|
|
819
|
-
const
|
|
820
|
-
const unansweredTurnIds = /* @__PURE__ */ new Set();
|
|
821
|
-
const activeMessageByTurnId = /* @__PURE__ */ new Map();
|
|
845
|
+
const unansweredMessageIds = /* @__PURE__ */ new Set();
|
|
822
846
|
let lastDeliveredMessageId;
|
|
823
847
|
let seq = 0;
|
|
824
848
|
const nextKey = (base) => `${base}:${seq++}`;
|
|
@@ -826,15 +850,14 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
826
850
|
let initCount = 0;
|
|
827
851
|
let pendingResume = false;
|
|
828
852
|
const openSessionTurn = (record) => {
|
|
829
|
-
const messageId =
|
|
830
|
-
if (openIdx >= 0 &&
|
|
853
|
+
const messageId = record.message_id ?? lastDeliveredMessageId;
|
|
854
|
+
if (openIdx >= 0 && turns[openIdx].messageId !== messageId) {
|
|
831
855
|
openIdx = -1;
|
|
832
856
|
}
|
|
833
857
|
if (openIdx < 0) {
|
|
834
858
|
turns.push({
|
|
835
859
|
key: nextKey(record.id),
|
|
836
860
|
messageId,
|
|
837
|
-
turnId: record.turn_id ?? void 0,
|
|
838
861
|
role: "assistant",
|
|
839
862
|
nodes: [],
|
|
840
863
|
startedAt: record.created_at,
|
|
@@ -850,13 +873,26 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
850
873
|
}
|
|
851
874
|
return turns[openIdx];
|
|
852
875
|
};
|
|
876
|
+
const subagentTurn = (record) => {
|
|
877
|
+
for (let i = turns.length - 1; i >= 0; i--) {
|
|
878
|
+
const turn = turns[i];
|
|
879
|
+
if (turn.role === "assistant" && turn.messageId === (record.message_id ?? void 0))
|
|
880
|
+
return turn;
|
|
881
|
+
}
|
|
882
|
+
return null;
|
|
883
|
+
};
|
|
884
|
+
const newestAssistantTurn = () => {
|
|
885
|
+
for (let i = turns.length - 1; i >= 0; i--) {
|
|
886
|
+
if (turns[i].role === "assistant") return turns[i];
|
|
887
|
+
}
|
|
888
|
+
return null;
|
|
889
|
+
};
|
|
853
890
|
for (const record of records) {
|
|
854
891
|
if (record.kind === "platform") {
|
|
855
|
-
const
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
const body = typeof record.payload.body === "string" ? record.payload.body : "";
|
|
892
|
+
const payload = { ...record.payload };
|
|
893
|
+
const messageId = typeof payload.message_id === "string" ? payload.message_id : record.record_type === "message" && typeof payload.id === "string" ? payload.id : null;
|
|
894
|
+
if (record.record_type === "message" && messageId) {
|
|
895
|
+
const body = typeof payload.body === "string" ? payload.body : "";
|
|
860
896
|
if (!body.trim() || userTurnByMessageId.has(messageId)) continue;
|
|
861
897
|
const turn2 = {
|
|
862
898
|
resumed: false,
|
|
@@ -875,29 +911,23 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
875
911
|
turns.push(turn2);
|
|
876
912
|
continue;
|
|
877
913
|
}
|
|
878
|
-
if (record.record_type === "
|
|
879
|
-
|
|
880
|
-
turnByMessageId.set(messageId, record.payload.turn_id);
|
|
881
|
-
activeMessageByTurnId.set(record.payload.turn_id, messageId);
|
|
882
|
-
lastDeliveredMessageId = messageId;
|
|
883
|
-
}
|
|
914
|
+
if (record.record_type === "message_started" && messageId) {
|
|
915
|
+
lastDeliveredMessageId = messageId;
|
|
884
916
|
continue;
|
|
885
917
|
}
|
|
886
918
|
if (record.record_type === "message_requeued" && messageId) {
|
|
887
|
-
|
|
888
|
-
turnByMessageId.set(messageId, record.payload.requeued_turn_id);
|
|
889
|
-
else turnByMessageId.delete(messageId);
|
|
919
|
+
unansweredMessageIds.delete(messageId);
|
|
890
920
|
continue;
|
|
891
921
|
}
|
|
892
|
-
if (record.record_type === "
|
|
893
|
-
|
|
894
|
-
const text2 = lifecycleText(record.record_type,
|
|
922
|
+
if (record.record_type === "message_ended" && messageId && payload.status !== "completed")
|
|
923
|
+
unansweredMessageIds.add(messageId);
|
|
924
|
+
const text2 = lifecycleText(record.record_type, payload);
|
|
895
925
|
if (!text2) continue;
|
|
896
926
|
const isEnvironment = ENVIRONMENT_RECORD_TYPES.has(record.record_type);
|
|
897
927
|
const isOutput = record.record_type === "environment_output";
|
|
898
|
-
const step = isOutput ? environmentOutputStep(
|
|
899
|
-
const lines = isOutput ? environmentOutputLines(
|
|
900
|
-
const
|
|
928
|
+
const step = isOutput ? environmentOutputStep(payload) : void 0;
|
|
929
|
+
const lines = isOutput ? environmentOutputLines(payload) : void 0;
|
|
930
|
+
const messageKey = record.message_id ?? void 0;
|
|
901
931
|
let foldTarget = null;
|
|
902
932
|
if (isEnvironment) {
|
|
903
933
|
for (let i = turns.length - 1; i >= 0; i--) {
|
|
@@ -906,7 +936,7 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
906
936
|
if (candidate.nodes.some(
|
|
907
937
|
(n) => n.kind === "lifecycle" && ENVIRONMENT_RECORD_TYPES.has(n.recordType)
|
|
908
938
|
)) {
|
|
909
|
-
if (candidate.
|
|
939
|
+
if (candidate.messageId === messageKey) foldTarget = candidate;
|
|
910
940
|
break;
|
|
911
941
|
}
|
|
912
942
|
}
|
|
@@ -924,7 +954,7 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
924
954
|
recordType: record.record_type,
|
|
925
955
|
step,
|
|
926
956
|
lines,
|
|
927
|
-
payload
|
|
957
|
+
payload
|
|
928
958
|
});
|
|
929
959
|
}
|
|
930
960
|
foldTarget.completedAt = record.created_at;
|
|
@@ -932,7 +962,7 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
932
962
|
}
|
|
933
963
|
turns.push({
|
|
934
964
|
key: nextKey(record.id),
|
|
935
|
-
|
|
965
|
+
messageId: messageKey,
|
|
936
966
|
role: "lifecycle",
|
|
937
967
|
nodes: [
|
|
938
968
|
{
|
|
@@ -942,7 +972,7 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
942
972
|
recordType: record.record_type,
|
|
943
973
|
step,
|
|
944
974
|
lines,
|
|
945
|
-
payload
|
|
975
|
+
payload
|
|
946
976
|
}
|
|
947
977
|
],
|
|
948
978
|
startedAt: record.created_at,
|
|
@@ -955,11 +985,7 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
955
985
|
});
|
|
956
986
|
continue;
|
|
957
987
|
}
|
|
958
|
-
if (record.
|
|
959
|
-
lastDeliveredMessageId = record.session_message_id;
|
|
960
|
-
if (record.turn_id)
|
|
961
|
-
activeMessageByTurnId.set(record.turn_id, record.session_message_id);
|
|
962
|
-
}
|
|
988
|
+
if (record.message_id) lastDeliveredMessageId = record.message_id;
|
|
963
989
|
if (record.kind === "codex") {
|
|
964
990
|
codexEventIntoTurns(record, record.payload, {
|
|
965
991
|
openSessionTurn,
|
|
@@ -1018,16 +1044,31 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
1018
1044
|
continue;
|
|
1019
1045
|
}
|
|
1020
1046
|
if (record.kind === "codex_app_server") {
|
|
1047
|
+
const fromSubagent = isCodexSubagentRecord(codexSubagentThreads2, record);
|
|
1048
|
+
const announces = addCodexSubagentThreads(codexSubagentThreads2, record);
|
|
1021
1049
|
const content = codexAppServerContent(record.payload);
|
|
1022
1050
|
if (!content) continue;
|
|
1051
|
+
const late = fromSubagent || announces && !isCodexSubagentSpawn(record);
|
|
1052
|
+
const turnFor = () => {
|
|
1053
|
+
if (!late) return openSessionTurn(record);
|
|
1054
|
+
const open = openIdx >= 0 ? turns[openIdx] : null;
|
|
1055
|
+
if (open !== null && open.messageId === (record.message_id ?? void 0)) {
|
|
1056
|
+
return open;
|
|
1057
|
+
}
|
|
1058
|
+
if (record.message_id == null) {
|
|
1059
|
+
return open ?? newestAssistantTurn() ?? openSessionTurn(record);
|
|
1060
|
+
}
|
|
1061
|
+
return subagentTurn(record) ?? openSessionTurn(record);
|
|
1062
|
+
};
|
|
1023
1063
|
if (content.kind === "end") {
|
|
1064
|
+
if (fromSubagent) continue;
|
|
1024
1065
|
if (openIdx >= 0) {
|
|
1025
1066
|
turns[openIdx].completedAt = record.created_at;
|
|
1026
1067
|
if (content.isError) turns[openIdx].isError = true;
|
|
1027
1068
|
openIdx = -1;
|
|
1028
1069
|
}
|
|
1029
1070
|
} else if (content.kind === "tool") {
|
|
1030
|
-
|
|
1071
|
+
turnFor().nodes.push({
|
|
1031
1072
|
key: nextKey(record.id),
|
|
1032
1073
|
kind: "tool",
|
|
1033
1074
|
name: content.name,
|
|
@@ -1039,8 +1080,8 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
1039
1080
|
completedAt: record.created_at
|
|
1040
1081
|
});
|
|
1041
1082
|
} else if (content.text.trim()) {
|
|
1042
|
-
const turn2 =
|
|
1043
|
-
if (content.kind === "error") turn2.isError = true;
|
|
1083
|
+
const turn2 = turnFor();
|
|
1084
|
+
if (content.kind === "error" && !fromSubagent) turn2.isError = true;
|
|
1044
1085
|
turn2.nodes.push({
|
|
1045
1086
|
key: nextKey(record.id),
|
|
1046
1087
|
kind: content.kind === "error" ? "assistant" : content.kind,
|
|
@@ -1077,7 +1118,7 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
1077
1118
|
if (typeof content === "string") {
|
|
1078
1119
|
if (content.trim()) {
|
|
1079
1120
|
openIdx = -1;
|
|
1080
|
-
if (record.
|
|
1121
|
+
if (record.message_id != null && userTurnByMessageId.has(record.message_id))
|
|
1081
1122
|
continue;
|
|
1082
1123
|
turns.push({
|
|
1083
1124
|
resumed: false,
|
|
@@ -1162,27 +1203,19 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
1162
1203
|
}
|
|
1163
1204
|
}
|
|
1164
1205
|
}
|
|
1165
|
-
for (const [messageId,
|
|
1166
|
-
|
|
1167
|
-
if (turn) turn.isError = unansweredTurnIds.has(turnId);
|
|
1206
|
+
for (const [messageId, turn] of userTurnByMessageId) {
|
|
1207
|
+
turn.isError = unansweredMessageIds.has(messageId);
|
|
1168
1208
|
}
|
|
1169
1209
|
for (const [messageId, progress] of messageProgress(records)) {
|
|
1170
1210
|
const turn = userTurnByMessageId.get(messageId);
|
|
1171
1211
|
if (turn) turn.progress = progress;
|
|
1172
1212
|
}
|
|
1173
|
-
const
|
|
1174
|
-
(r) => r.kind === "platform" && r.record_type === "
|
|
1175
|
-
);
|
|
1176
|
-
const openingTurnId = initialTurn?.turn_id ?? initialTurn?.payload.turn_id ?? (session?.turn?.index === 0 ? session.turn.id : void 0);
|
|
1177
|
-
const initialReceived = openingTurnId == null ? void 0 : records.find(
|
|
1178
|
-
(r) => r.kind === "platform" && r.record_type === "message_received" && (r.turn_id === openingTurnId || r.payload.turn_id === openingTurnId)
|
|
1213
|
+
const initialMessage = records.find(
|
|
1214
|
+
(r) => r.kind === "platform" && r.record_type === "message" && r.payload.index === 0
|
|
1179
1215
|
);
|
|
1180
|
-
const
|
|
1181
|
-
(r) => r.kind === "platform" && r.record_type === "message_delivered" && r.payload.turn_id === openingTurnId
|
|
1182
|
-
);
|
|
1183
|
-
const initialId = (initialReceived ?? initialDelivery)?.payload.message_id;
|
|
1216
|
+
const initialId = initialMessage?.payload.id;
|
|
1184
1217
|
const opening = initialId ? userTurnByMessageId.get(initialId) : void 0;
|
|
1185
|
-
const includesStart = records.length === 0 ||
|
|
1218
|
+
const includesStart = records.length === 0 || initialMessage != null;
|
|
1186
1219
|
const prompt = (session?.claude_code ?? session?.codex)?.prompt;
|
|
1187
1220
|
if (prompt?.trim() && session && (opening || includesStart)) {
|
|
1188
1221
|
const first = opening ?? {
|
|
@@ -1196,7 +1229,10 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
1196
1229
|
tokens: null,
|
|
1197
1230
|
resumed: false,
|
|
1198
1231
|
isError: false,
|
|
1199
|
-
progress: {
|
|
1232
|
+
progress: {
|
|
1233
|
+
phase: "preparing",
|
|
1234
|
+
timing: { startedAt: null, completedAt: null }
|
|
1235
|
+
}
|
|
1200
1236
|
};
|
|
1201
1237
|
if (opening) turns.splice(turns.indexOf(opening), 1);
|
|
1202
1238
|
first.key = "prompt";
|
|
@@ -1204,7 +1240,7 @@ function groupRecordsToChatTurns(records, session) {
|
|
|
1204
1240
|
turns.unshift(first);
|
|
1205
1241
|
if (!opening) {
|
|
1206
1242
|
for (const turn of turns) {
|
|
1207
|
-
if (turn !== first && turn.role === "user" && turn.progress &&
|
|
1243
|
+
if (turn !== first && turn.role === "user" && turn.progress && turn.progress.timing.startedAt == null) {
|
|
1208
1244
|
turn.progress.phase = turn.progress.phase === null ? null : "queued";
|
|
1209
1245
|
}
|
|
1210
1246
|
}
|
|
@@ -1318,9 +1354,9 @@ function codexEventIntoTurns(record, event, ops) {
|
|
|
1318
1354
|
function recordSlice(records) {
|
|
1319
1355
|
return records;
|
|
1320
1356
|
}
|
|
1321
|
-
function
|
|
1322
|
-
if (record.
|
|
1323
|
-
return typeof record.payload.
|
|
1357
|
+
function messageOf(record) {
|
|
1358
|
+
if (record.message_id != null) return record.message_id;
|
|
1359
|
+
return typeof record.payload.message_id === "string" ? record.payload.message_id : null;
|
|
1324
1360
|
}
|
|
1325
1361
|
function humanDuration(seconds) {
|
|
1326
1362
|
const clamped = Math.max(0, seconds);
|
|
@@ -1342,10 +1378,10 @@ function humanDuration(seconds) {
|
|
|
1342
1378
|
}
|
|
1343
1379
|
function sessionLogText(recordType, payload) {
|
|
1344
1380
|
switch (recordType) {
|
|
1345
|
-
case "
|
|
1346
|
-
return
|
|
1381
|
+
case "message_ended":
|
|
1382
|
+
return messageEndedText(payload);
|
|
1347
1383
|
case "session_closed":
|
|
1348
|
-
return "
|
|
1384
|
+
return "Session closed";
|
|
1349
1385
|
default:
|
|
1350
1386
|
return null;
|
|
1351
1387
|
}
|
|
@@ -1359,10 +1395,10 @@ function awaitingAgentPhase(records) {
|
|
|
1359
1395
|
continue;
|
|
1360
1396
|
}
|
|
1361
1397
|
switch (r.record_type) {
|
|
1362
|
-
case "
|
|
1398
|
+
case "message_started":
|
|
1363
1399
|
inFlight = true;
|
|
1364
1400
|
break;
|
|
1365
|
-
case "
|
|
1401
|
+
case "message_ended":
|
|
1366
1402
|
inFlight = false;
|
|
1367
1403
|
break;
|
|
1368
1404
|
case "environment_phase":
|
|
@@ -1377,37 +1413,34 @@ function awaitingAgentPhase(records) {
|
|
|
1377
1413
|
}
|
|
1378
1414
|
function deliveredUnechoedSends(records) {
|
|
1379
1415
|
const received = /* @__PURE__ */ new Map();
|
|
1380
|
-
const
|
|
1416
|
+
const started = /* @__PURE__ */ new Set();
|
|
1381
1417
|
const unanswered = /* @__PURE__ */ new Set();
|
|
1382
1418
|
const echoed = /* @__PURE__ */ new Set();
|
|
1383
1419
|
for (const r of records) {
|
|
1384
|
-
if (r.
|
|
1385
|
-
|
|
1386
|
-
if (r.record_type === "turn_ended") {
|
|
1387
|
-
if (typeof r.payload.turn_id === "string" && r.payload.status !== "completed")
|
|
1388
|
-
unanswered.add(r.payload.turn_id);
|
|
1420
|
+
if (r.source !== "lifecycle") {
|
|
1421
|
+
if (r.message_id != null) echoed.add(r.message_id);
|
|
1389
1422
|
continue;
|
|
1390
1423
|
}
|
|
1391
|
-
const id = typeof r.payload.
|
|
1424
|
+
const id = messageOf(r) ?? (typeof r.payload.id === "string" ? r.payload.id : null);
|
|
1392
1425
|
if (!id) continue;
|
|
1393
|
-
if (r.record_type === "
|
|
1426
|
+
if (r.record_type === "message") {
|
|
1394
1427
|
if (!received.has(id))
|
|
1395
1428
|
received.set(
|
|
1396
1429
|
id,
|
|
1397
1430
|
typeof r.payload.body === "string" ? r.payload.body : ""
|
|
1398
1431
|
);
|
|
1399
|
-
} else if (r.record_type === "
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1432
|
+
} else if (r.record_type === "message_started") {
|
|
1433
|
+
started.add(id);
|
|
1434
|
+
} else if (r.record_type === "message_requeued") {
|
|
1435
|
+
started.delete(id);
|
|
1436
|
+
} else if (r.record_type === "message_ended") {
|
|
1437
|
+
if (r.payload.status !== "completed") unanswered.add(id);
|
|
1438
|
+
}
|
|
1405
1439
|
}
|
|
1406
1440
|
const out = [];
|
|
1407
1441
|
for (const [id, body] of received) {
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
out.push({ id, body, cancelled: unanswered.has(turnId) });
|
|
1442
|
+
if (!started.has(id) || echoed.has(id)) continue;
|
|
1443
|
+
out.push({ id, body, cancelled: unanswered.has(id) });
|
|
1411
1444
|
}
|
|
1412
1445
|
return out;
|
|
1413
1446
|
}
|
|
@@ -1457,22 +1490,22 @@ function deriveEnvironmentState(records, minFeedSeq) {
|
|
|
1457
1490
|
let readySeconds = null;
|
|
1458
1491
|
let log = [];
|
|
1459
1492
|
let open = /* @__PURE__ */ new Map();
|
|
1460
|
-
let
|
|
1493
|
+
let storyMessage = null;
|
|
1461
1494
|
const push = (record, kind, text2) => {
|
|
1462
1495
|
const entry = { key: `${record.feed_seq}:${log.length}`, kind, text: text2 };
|
|
1463
1496
|
log.push(entry);
|
|
1464
1497
|
return entry;
|
|
1465
1498
|
};
|
|
1466
1499
|
const begin = (record) => {
|
|
1467
|
-
const
|
|
1468
|
-
if (seen &&
|
|
1500
|
+
const message = messageOf(record);
|
|
1501
|
+
if (seen && message !== storyMessage) {
|
|
1469
1502
|
log = [];
|
|
1470
1503
|
open = /* @__PURE__ */ new Map();
|
|
1471
1504
|
done = false;
|
|
1472
1505
|
readySeconds = null;
|
|
1473
1506
|
}
|
|
1474
1507
|
seen = true;
|
|
1475
|
-
|
|
1508
|
+
storyMessage = message;
|
|
1476
1509
|
};
|
|
1477
1510
|
for (const record of records) {
|
|
1478
1511
|
if (record.feed_seq <= minFeedSeq || record.source !== "lifecycle")
|
|
@@ -1528,9 +1561,9 @@ function deriveEnvironmentState(records, minFeedSeq) {
|
|
|
1528
1561
|
done = true;
|
|
1529
1562
|
break;
|
|
1530
1563
|
}
|
|
1531
|
-
case "
|
|
1532
|
-
case "
|
|
1533
|
-
if (seen &&
|
|
1564
|
+
case "message_started":
|
|
1565
|
+
case "message_ended":
|
|
1566
|
+
if (seen && messageOf(record) === storyMessage) done = true;
|
|
1534
1567
|
break;
|
|
1535
1568
|
case "session_closed":
|
|
1536
1569
|
if (seen) done = true;
|
|
@@ -1730,12 +1763,10 @@ function splitLedger(turns) {
|
|
|
1730
1763
|
return { preamble, entries };
|
|
1731
1764
|
}
|
|
1732
1765
|
function entrySeconds(entry, now) {
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
return ms2 + Math.max(0, end - Date.parse(turn.startedAt));
|
|
1738
|
-
}, 0) / 1e3;
|
|
1766
|
+
const timing = entry.progress?.timing;
|
|
1767
|
+
if (timing?.startedAt != null) {
|
|
1768
|
+
const end = timing.completedAt == null ? now : Date.parse(timing.completedAt);
|
|
1769
|
+
return Math.max(0, end - Date.parse(timing.startedAt)) / 1e3;
|
|
1739
1770
|
}
|
|
1740
1771
|
let ms = 0;
|
|
1741
1772
|
for (const turn of entry.turns) {
|
|
@@ -1811,7 +1842,7 @@ function entryBody(entry, {
|
|
|
1811
1842
|
const items = [];
|
|
1812
1843
|
const work = [];
|
|
1813
1844
|
const phase = entry.progress?.phase;
|
|
1814
|
-
const seconds = entry.progress &&
|
|
1845
|
+
const seconds = entry.progress && entry.progress.timing.startedAt == null ? null : entrySeconds(entry, now);
|
|
1815
1846
|
const key = `work:${entry.key}`;
|
|
1816
1847
|
const header = {
|
|
1817
1848
|
key,
|
|
@@ -1981,25 +2012,17 @@ function activitySummary(activities) {
|
|
|
1981
2012
|
|
|
1982
2013
|
// src/store/index.ts
|
|
1983
2014
|
function isConversationOver(session) {
|
|
1984
|
-
return session.
|
|
2015
|
+
return session.status === "closed";
|
|
1985
2016
|
}
|
|
1986
2017
|
function seedTranscriptStore(store, seed) {
|
|
1987
|
-
store.ingest({
|
|
1988
|
-
type: "snapshot",
|
|
1989
|
-
earliest_feed_seq: seed.earliestFeedSeq ?? null,
|
|
1990
|
-
session: seed.session,
|
|
1991
|
-
messages: [...seed.messages ?? []]
|
|
1992
|
-
});
|
|
2018
|
+
store.ingest({ type: "session", session: seed.session });
|
|
1993
2019
|
const ordered = [...seed.records].sort((a, b) => a.feed_seq - b.feed_seq);
|
|
1994
|
-
if (ordered.length)
|
|
1995
|
-
store.ingest({ type: "records_append", records: ordered });
|
|
2020
|
+
if (ordered.length) store.ingest({ type: "records", records: ordered });
|
|
1996
2021
|
}
|
|
1997
2022
|
var EMPTY_SNAPSHOT = {
|
|
1998
2023
|
session: null,
|
|
1999
2024
|
records: [],
|
|
2000
|
-
messages: [],
|
|
2001
2025
|
acknowledgedMessageIds: /* @__PURE__ */ new Set(),
|
|
2002
|
-
historyTruncated: false,
|
|
2003
2026
|
liveText: "",
|
|
2004
2027
|
liveSummary: "",
|
|
2005
2028
|
liveOutputTokens: null,
|
|
@@ -2013,21 +2036,16 @@ var SessionTranscriptStore = class {
|
|
|
2013
2036
|
snapshot = EMPTY_SNAPSHOT;
|
|
2014
2037
|
listeners = /* @__PURE__ */ new Set();
|
|
2015
2038
|
acknowledged = /* @__PURE__ */ new Set();
|
|
2016
|
-
// The
|
|
2017
|
-
//
|
|
2018
|
-
//
|
|
2019
|
-
//
|
|
2020
|
-
inbox = /* @__PURE__ */ new Map();
|
|
2021
|
-
// The resume cursor: the highest feed_seq received via records_append. Only
|
|
2022
|
-
// records advance it — never messages/session frames. streamSession
|
|
2023
|
-
// tracks its own copy; this one seeds a NEW streamSession call (e.g. a
|
|
2024
|
-
// page-level reconnect after unmount) from already-held state.
|
|
2039
|
+
// The resume cursor: the highest feed_seq received via records frames. Only
|
|
2040
|
+
// records advance it — never session frames. streamSession tracks its own
|
|
2041
|
+
// copy; this one seeds a NEW streamSession call (e.g. a page-level
|
|
2042
|
+
// reconnect after unmount) from already-held state.
|
|
2025
2043
|
cursorSeq = 0;
|
|
2026
2044
|
// Derived-turn cache, keyed on the records array identity.
|
|
2027
2045
|
turnsFor = null;
|
|
2028
2046
|
turnsSession = null;
|
|
2029
2047
|
turnsCache = [];
|
|
2030
|
-
|
|
2048
|
+
summaryMessageId = null;
|
|
2031
2049
|
get cursor() {
|
|
2032
2050
|
return this.cursorSeq;
|
|
2033
2051
|
}
|
|
@@ -2049,59 +2067,6 @@ var SessionTranscriptStore = class {
|
|
|
2049
2067
|
}
|
|
2050
2068
|
return this.turnsCache;
|
|
2051
2069
|
};
|
|
2052
|
-
// The current pending set, in feed order — what queued chips render.
|
|
2053
|
-
pendingMessages = () => [...this.inbox.values()].filter((m) => m.status === "pending").sort((a, b) => (a.feed_seq ?? 0) - (b.feed_seq ?? 0));
|
|
2054
|
-
// Fold one lifecycle record into the inbox projection; returns whether the
|
|
2055
|
-
// pending view changed. Unknown fields/types are ignored.
|
|
2056
|
-
applyMessageRecord = (record) => {
|
|
2057
|
-
if (record.kind !== "platform") return false;
|
|
2058
|
-
const payload = record.payload;
|
|
2059
|
-
const messageId = typeof payload.message_id === "string" ? payload.message_id : null;
|
|
2060
|
-
switch (record.record_type) {
|
|
2061
|
-
case "message_received": {
|
|
2062
|
-
if (messageId == null || this.inbox.has(messageId)) return false;
|
|
2063
|
-
this.inbox.set(messageId, {
|
|
2064
|
-
id: messageId,
|
|
2065
|
-
session_id: record.session_id,
|
|
2066
|
-
feed_seq: record.feed_seq,
|
|
2067
|
-
status: "pending",
|
|
2068
|
-
body: typeof payload.body === "string" ? payload.body : "",
|
|
2069
|
-
author: typeof payload.author === "string" ? payload.author : null,
|
|
2070
|
-
sender_attribution_type: typeof payload.sender_attribution_type === "string" ? payload.sender_attribution_type : null,
|
|
2071
|
-
sender_attribution_id: typeof payload.sender_attribution_id === "string" ? payload.sender_attribution_id : null,
|
|
2072
|
-
created_at: record.created_at,
|
|
2073
|
-
delivered_at: null,
|
|
2074
|
-
images: [],
|
|
2075
|
-
turn_id: typeof payload.turn_id === "string" ? payload.turn_id : null
|
|
2076
|
-
});
|
|
2077
|
-
return true;
|
|
2078
|
-
}
|
|
2079
|
-
case "message_delivered": {
|
|
2080
|
-
const existing = messageId != null ? this.inbox.get(messageId) : null;
|
|
2081
|
-
if (!existing || existing.status !== "pending") return false;
|
|
2082
|
-
this.inbox.set(messageId, {
|
|
2083
|
-
...existing,
|
|
2084
|
-
status: "delivered",
|
|
2085
|
-
delivered_at: record.created_at,
|
|
2086
|
-
turn_id: typeof payload.turn_id === "string" ? payload.turn_id : existing.turn_id
|
|
2087
|
-
});
|
|
2088
|
-
return true;
|
|
2089
|
-
}
|
|
2090
|
-
case "message_requeued": {
|
|
2091
|
-
const existing = messageId != null ? this.inbox.get(messageId) : null;
|
|
2092
|
-
if (!existing || existing.status === "pending") return false;
|
|
2093
|
-
this.inbox.set(messageId, {
|
|
2094
|
-
...existing,
|
|
2095
|
-
status: "pending",
|
|
2096
|
-
delivered_at: null,
|
|
2097
|
-
turn_id: typeof payload.requeued_turn_id === "string" ? payload.requeued_turn_id : null
|
|
2098
|
-
});
|
|
2099
|
-
return true;
|
|
2100
|
-
}
|
|
2101
|
-
default:
|
|
2102
|
-
return false;
|
|
2103
|
-
}
|
|
2104
|
-
};
|
|
2105
2070
|
// Ingest one frame from the stream client. Unknown frame types stamp
|
|
2106
2071
|
// liveness and change nothing else.
|
|
2107
2072
|
ingest = (rawFrame) => {
|
|
@@ -2112,45 +2077,29 @@ var SessionTranscriptStore = class {
|
|
|
2112
2077
|
};
|
|
2113
2078
|
const frame = rawFrame;
|
|
2114
2079
|
switch (frame.type) {
|
|
2115
|
-
case "
|
|
2116
|
-
next.liveSummary = "";
|
|
2117
|
-
next.session = frame.session;
|
|
2118
|
-
for (const message of frame.messages) {
|
|
2119
|
-
this.inbox.set(message.id, message);
|
|
2120
|
-
this.acknowledged.add(message.id);
|
|
2121
|
-
}
|
|
2122
|
-
next.messages = this.pendingMessages();
|
|
2123
|
-
next.acknowledgedMessageIds = new Set(this.acknowledged);
|
|
2124
|
-
next.conversationOver = isConversationOver(frame.session);
|
|
2125
|
-
next.historyTruncated = frame.earliest_feed_seq != null && this.cursorSeq < frame.earliest_feed_seq - 1;
|
|
2126
|
-
break;
|
|
2127
|
-
}
|
|
2128
|
-
case "records_append": {
|
|
2080
|
+
case "records": {
|
|
2129
2081
|
const fresh = frame.records.filter((r) => r.feed_seq > this.cursorSeq);
|
|
2130
2082
|
if (fresh.length === 0) break;
|
|
2131
2083
|
this.cursorSeq = fresh[fresh.length - 1].feed_seq;
|
|
2132
2084
|
next.records = [...prev.records, ...fresh];
|
|
2133
2085
|
let acknowledgedNew = false;
|
|
2134
|
-
let inboxChanged = false;
|
|
2135
2086
|
for (const record of fresh) {
|
|
2136
|
-
if (record.
|
|
2137
|
-
this.acknowledged.add(record.
|
|
2087
|
+
if (record.message_id != null) {
|
|
2088
|
+
this.acknowledged.add(record.message_id);
|
|
2138
2089
|
acknowledgedNew = true;
|
|
2139
2090
|
}
|
|
2140
2091
|
if (record.source === "lifecycle") {
|
|
2141
|
-
if (record.record_type === "
|
|
2092
|
+
if (record.record_type === "message_started" && record.message_id !== this.summaryMessageId || record.record_type === "message_ended" && record.message_id === this.summaryMessageId)
|
|
2142
2093
|
next.liveSummary = "";
|
|
2143
|
-
|
|
2144
|
-
if (record.record_type === "message_received" || record.record_type === "message_delivered") {
|
|
2094
|
+
if (record.record_type === "message") {
|
|
2145
2095
|
const payload = record.payload;
|
|
2146
|
-
if (typeof payload.
|
|
2147
|
-
this.acknowledged.add(payload.
|
|
2096
|
+
if (typeof payload.id === "string") {
|
|
2097
|
+
this.acknowledged.add(payload.id);
|
|
2148
2098
|
acknowledgedNew = true;
|
|
2149
2099
|
}
|
|
2150
2100
|
}
|
|
2151
2101
|
}
|
|
2152
2102
|
}
|
|
2153
|
-
if (inboxChanged) next.messages = this.pendingMessages();
|
|
2154
2103
|
if (acknowledgedNew) {
|
|
2155
2104
|
next.acknowledgedMessageIds = new Set(this.acknowledged);
|
|
2156
2105
|
}
|
|
@@ -2161,15 +2110,13 @@ var SessionTranscriptStore = class {
|
|
|
2161
2110
|
case "session": {
|
|
2162
2111
|
next.session = frame.session;
|
|
2163
2112
|
next.conversationOver = isConversationOver(frame.session);
|
|
2164
|
-
if (
|
|
2165
|
-
next.liveSummary = "";
|
|
2166
|
-
}
|
|
2113
|
+
if (frame.session.status !== "running") next.liveSummary = "";
|
|
2167
2114
|
break;
|
|
2168
2115
|
}
|
|
2169
2116
|
case "delta": {
|
|
2170
2117
|
if (frame.kind === "thinking") {
|
|
2171
2118
|
if (next.conversationOver) break;
|
|
2172
|
-
this.
|
|
2119
|
+
this.summaryMessageId = frame.message_id;
|
|
2173
2120
|
if (frame.text != null) next.liveSummary = frame.text;
|
|
2174
2121
|
break;
|
|
2175
2122
|
}
|
|
@@ -2182,11 +2129,6 @@ var SessionTranscriptStore = class {
|
|
|
2182
2129
|
next.liveOutputTokens = frame.output_tokens;
|
|
2183
2130
|
break;
|
|
2184
2131
|
}
|
|
2185
|
-
case "done": {
|
|
2186
|
-
next.conversationOver = true;
|
|
2187
|
-
next.liveSummary = "";
|
|
2188
|
-
break;
|
|
2189
|
-
}
|
|
2190
2132
|
case "error": {
|
|
2191
2133
|
next.liveSummary = "";
|
|
2192
2134
|
break;
|
|
@@ -2212,6 +2154,7 @@ export {
|
|
|
2212
2154
|
codexChangedPaths,
|
|
2213
2155
|
codexEventToItems,
|
|
2214
2156
|
codexMcpToolName,
|
|
2157
|
+
codexSubagentThreads,
|
|
2215
2158
|
collapseToolRuns,
|
|
2216
2159
|
deliveredUnechoedSends,
|
|
2217
2160
|
deriveEnvironmentState,
|
|
@@ -2232,6 +2175,7 @@ export {
|
|
|
2232
2175
|
gutterFor,
|
|
2233
2176
|
hookPhrase,
|
|
2234
2177
|
humanDuration,
|
|
2178
|
+
isCodexSubagentRecord,
|
|
2235
2179
|
isConnectVisibleRecord,
|
|
2236
2180
|
isConversationOver,
|
|
2237
2181
|
isFoldable,
|
|
@@ -2241,6 +2185,7 @@ export {
|
|
|
2241
2185
|
lastLines,
|
|
2242
2186
|
layOutItems,
|
|
2243
2187
|
lifecycleText,
|
|
2188
|
+
messageEndedText,
|
|
2244
2189
|
oneLine,
|
|
2245
2190
|
pendingToolCalls,
|
|
2246
2191
|
reasoningSummaryTitle,
|
|
@@ -2257,6 +2202,5 @@ export {
|
|
|
2257
2202
|
tailLines,
|
|
2258
2203
|
toolActivities,
|
|
2259
2204
|
toolResultText,
|
|
2260
|
-
toolRunMembers
|
|
2261
|
-
turnEndedText
|
|
2205
|
+
toolRunMembers
|
|
2262
2206
|
};
|