@gkorepanov/ccodex 0.5.0-rc.2 → 0.5.0-rc.21

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 (93) hide show
  1. package/README.md +156 -157
  2. package/claude/chat-formatting.md +25 -0
  3. package/config/compatibility.json +1 -1
  4. package/dist/claude/commandActions.d.ts +2 -0
  5. package/dist/claude/commandActions.js +43 -24
  6. package/dist/claude/commandActions.js.map +1 -1
  7. package/dist/claude/delegation.d.ts +10 -0
  8. package/dist/claude/delegation.js +41 -0
  9. package/dist/claude/delegation.js.map +1 -0
  10. package/dist/claude/native/catalog.d.ts +14 -0
  11. package/dist/claude/native/catalog.js +52 -17
  12. package/dist/claude/native/catalog.js.map +1 -1
  13. package/dist/claude/native/history.d.ts +8 -1
  14. package/dist/claude/native/history.js +43 -19
  15. package/dist/claude/native/history.js.map +1 -1
  16. package/dist/claude/native/pages.d.ts +54 -0
  17. package/dist/claude/native/pages.js +271 -0
  18. package/dist/claude/native/pages.js.map +1 -0
  19. package/dist/claude/native/projector.d.ts +18 -2
  20. package/dist/claude/native/projector.js +104 -46
  21. package/dist/claude/native/projector.js.map +1 -1
  22. package/dist/claude/native/records.d.ts +2 -0
  23. package/dist/claude/native/records.js +35 -13
  24. package/dist/claude/native/records.js.map +1 -1
  25. package/dist/claude/native/search.d.ts +7 -0
  26. package/dist/claude/native/search.js +79 -0
  27. package/dist/claude/native/search.js.map +1 -0
  28. package/dist/claude/native/summary.d.ts +6 -1
  29. package/dist/claude/native/summary.js +24 -6
  30. package/dist/claude/native/summary.js.map +1 -1
  31. package/dist/claude/peers.d.ts +4 -0
  32. package/dist/claude/peers.js +19 -5
  33. package/dist/claude/peers.js.map +1 -1
  34. package/dist/claude/processes.d.ts +2 -0
  35. package/dist/claude/processes.js +15 -0
  36. package/dist/claude/processes.js.map +1 -1
  37. package/dist/claude/sdk.d.ts +8 -2
  38. package/dist/claude/sdk.js +23 -6
  39. package/dist/claude/sdk.js.map +1 -1
  40. package/dist/claude/session.d.ts +34 -7
  41. package/dist/claude/session.js +184 -72
  42. package/dist/claude/session.js.map +1 -1
  43. package/dist/claude/threads.d.ts +61 -3
  44. package/dist/claude/threads.js +408 -100
  45. package/dist/claude/threads.js.map +1 -1
  46. package/dist/claude/toolMapper.d.ts +23 -3
  47. package/dist/claude/toolMapper.js +50 -1
  48. package/dist/claude/toolMapper.js.map +1 -1
  49. package/dist/cli/args.js +2 -1
  50. package/dist/cli/args.js.map +1 -1
  51. package/dist/config.d.ts +1 -0
  52. package/dist/config.js +7 -3
  53. package/dist/config.js.map +1 -1
  54. package/dist/daemon/daemon.d.ts +3 -0
  55. package/dist/daemon/daemon.js +6 -3
  56. package/dist/daemon/daemon.js.map +1 -1
  57. package/dist/daemon/supervisor.d.ts +8 -0
  58. package/dist/daemon/supervisor.js +15 -7
  59. package/dist/daemon/supervisor.js.map +1 -1
  60. package/dist/desktop/stdioFrontend.js +1 -1
  61. package/dist/desktop/stdioFrontend.js.map +1 -1
  62. package/dist/gateway/catalog.js +35 -20
  63. package/dist/gateway/catalog.js.map +1 -1
  64. package/dist/gateway/connection.js +2 -2
  65. package/dist/gateway/connection.js.map +1 -1
  66. package/dist/gateway/lineage.d.ts +29 -1
  67. package/dist/gateway/lineage.js +260 -38
  68. package/dist/gateway/lineage.js.map +1 -1
  69. package/dist/gateway/remote.js +3 -8
  70. package/dist/gateway/remote.js.map +1 -1
  71. package/dist/gateway/server.d.ts +2 -1
  72. package/dist/gateway/server.js +26 -13
  73. package/dist/gateway/server.js.map +1 -1
  74. package/dist/gateway/status.d.ts +15 -5
  75. package/dist/gateway/status.js +142 -47
  76. package/dist/gateway/status.js.map +1 -1
  77. package/dist/gateway/stock.js +17 -2
  78. package/dist/gateway/stock.js.map +1 -1
  79. package/dist/management/commands.d.ts +2 -0
  80. package/dist/management/commands.js +66 -3
  81. package/dist/management/commands.js.map +1 -1
  82. package/dist/meta.d.ts +39 -11
  83. package/dist/meta.js +59 -28
  84. package/dist/meta.js.map +1 -1
  85. package/dist/protocol/codex.d.ts +1 -3
  86. package/dist/protocol/codex.js +1 -4
  87. package/dist/protocol/codex.js.map +1 -1
  88. package/dist/protocol/turnPagination.d.ts +35 -2
  89. package/dist/protocol/turnPagination.js +53 -28
  90. package/dist/protocol/turnPagination.js.map +1 -1
  91. package/examples/config.toml +2 -2
  92. package/package.json +5 -4
  93. package/scripts/migrate-0.4-to-0.5.mjs +31 -20
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Owns paged reads of a Claude transcript. History is projected from windows read back from the end of the file, as
3
+ * far as a page needs, never the whole file: Desktop pages a thread (`thread/turns/list`, `thread/items/list`) and
4
+ * a transcript grows to hundreds of megabytes.
5
+ */
6
+ import { open, stat } from "node:fs/promises";
7
+ import { backgroundEnds, projectTranscript } from "./projector.js";
8
+ import { parseTranscriptLine } from "./records.js";
9
+ const CHUNK_BYTES = 1 << 20;
10
+ /** Turns the live window keeps beyond what was asked: the next page of a scroll back needs no read. */
11
+ const KEPT_TURNS = 12;
12
+ /** Windows kept while the file stays as it is: Desktop asks each turn of a page for its items right after the page. */
13
+ const RECENT_WINDOWS = 4;
14
+ function emptyWindow(end) {
15
+ return { start: end, end, records: [], positions: [], offsets: new Map() };
16
+ }
17
+ async function readRange(path, from, to) {
18
+ const handle = await open(path, "r");
19
+ try {
20
+ const bytes = Buffer.alloc(to - from);
21
+ const { bytesRead } = await handle.read(bytes, 0, bytes.length, from);
22
+ return bytes.subarray(0, bytesRead);
23
+ }
24
+ finally {
25
+ await handle.close();
26
+ }
27
+ }
28
+ /** Complete lines of `bytes` (read at `at`) from `first` up to the last newline: records with their line offsets. */
29
+ function parseLines(bytes, at, first) {
30
+ const records = [];
31
+ const positions = [];
32
+ let line = first;
33
+ for (let newline = bytes.indexOf(0x0a, line); newline !== -1; newline = bytes.indexOf(0x0a, line)) {
34
+ const record = parseTranscriptLine(bytes.subarray(line, newline));
35
+ if (record) {
36
+ records.push(record);
37
+ positions.push(at + line);
38
+ }
39
+ line = newline + 1;
40
+ }
41
+ return { records, positions, end: at + line };
42
+ }
43
+ function uuidOf(record) {
44
+ return "uuid" in record && typeof record.uuid === "string" ? record.uuid : undefined;
45
+ }
46
+ /** Extends the window back by up to `chunk` bytes; false when no whole line fits in them (a longer chunk will). */
47
+ async function readBack(path, window, chunk, ends) {
48
+ const from = Math.max(0, window.start - chunk);
49
+ const bytes = await readRange(path, from, window.start);
50
+ const first = from === 0 ? 0 : bytes.indexOf(0x0a) + 1;
51
+ if (first === 0 && from > 0)
52
+ return false;
53
+ const parsed = parseLines(bytes, from, first);
54
+ // A window opened at the end of the file ends at its last whole line (Claude may be writing the next one).
55
+ if (window.start === window.end)
56
+ window.end = parsed.end;
57
+ else if (parsed.end !== window.start)
58
+ throw new Error(`${path}: a line runs past a window's start`);
59
+ window.start = from + first;
60
+ backgroundEnds(parsed.records, ends);
61
+ window.records.unshift(...parsed.records);
62
+ window.positions.unshift(...parsed.positions);
63
+ parsed.records.forEach((record, index) => {
64
+ const uuid = uuidOf(record);
65
+ if (uuid && !window.offsets.has(uuid))
66
+ window.offsets.set(uuid, parsed.positions[index]);
67
+ });
68
+ return true;
69
+ }
70
+ /** Appends what Claude wrote since the window's end. */
71
+ async function readForward(path, window, size, ends) {
72
+ if (size <= window.end || !window.records.length)
73
+ return;
74
+ const parsed = parseLines(await readRange(path, window.end, size), window.end, 0);
75
+ backgroundEnds(parsed.records, ends);
76
+ window.end = parsed.end;
77
+ window.records.push(...parsed.records);
78
+ window.positions.push(...parsed.positions);
79
+ parsed.records.forEach((record, index) => {
80
+ const uuid = uuidOf(record);
81
+ if (uuid)
82
+ window.offsets.set(uuid, parsed.positions[index]);
83
+ });
84
+ }
85
+ /** Where the line after `uuid`'s starts. */
86
+ function after(window, uuid) {
87
+ const offset = window.offsets.get(uuid);
88
+ let low = 0;
89
+ let high = window.positions.length;
90
+ while (low < high) {
91
+ const middle = (low + high) >> 1;
92
+ if (window.positions[middle] <= offset)
93
+ low = middle + 1;
94
+ else
95
+ high = middle;
96
+ }
97
+ return window.positions[low] ?? window.end;
98
+ }
99
+ /** Drops the window's records before `offset`. */
100
+ function trim(window, offset) {
101
+ const index = window.positions.findIndex((position) => position >= offset);
102
+ if (index <= 0)
103
+ return;
104
+ window.records.splice(0, index);
105
+ window.positions.splice(0, index);
106
+ window.start = window.positions[0];
107
+ for (const [uuid, position] of window.offsets)
108
+ if (position < window.start)
109
+ window.offsets.delete(uuid);
110
+ }
111
+ export class TranscriptPages {
112
+ chunkBytes;
113
+ /** The newest part of the file; follows Claude's writes. */
114
+ live;
115
+ places = new Map();
116
+ /**
117
+ * How background commands ended, from every part of the file read. A turn is read after the turns that follow it
118
+ * (pages go back from the end), so its commands' ends are known by then.
119
+ */
120
+ ends = new Map();
121
+ /** Windows projected lately, newest first, for the file as it was (`key`). */
122
+ recent = { key: "", windows: [] };
123
+ queue = Promise.resolve();
124
+ constructor(chunkBytes = CHUNK_BYTES) {
125
+ this.chunkBytes = chunkBytes;
126
+ }
127
+ /** The newest turns: at least `count` of them unless history is shorter. */
128
+ newest(source, count) {
129
+ return this.serial(() => this.liveWindow(source, (turns) => turns.length >= count, count));
130
+ }
131
+ /** The window of `turnId` (the last of its turns unless it is the newest) with at least `before` turns before it. */
132
+ around(source, turnId, before) {
133
+ return this.serial(async () => {
134
+ const reaches = (turns) => turns.findIndex((turn) => turn.id === turnId) >= before;
135
+ let place = this.places.get(turnId);
136
+ if (!place) {
137
+ // Not paged to yet (a cursor from before a restart): back from the end until it shows.
138
+ const found = await this.liveWindow(source, (turns) => turns.some((turn) => turn.id === turnId), 1);
139
+ if (!found.turns.some((turn) => turn.id === turnId))
140
+ throw new Error(`turn not found: ${turnId}`);
141
+ place = this.places.get(turnId);
142
+ }
143
+ if (place.end === undefined)
144
+ return this.liveWindow(source, reaches, 1);
145
+ const { physical, end, lastUuid } = place;
146
+ const { ino, size } = await stat(source.path);
147
+ // A turn alone (its items) reads the same in any window holding it whole; a page's turns before it do not: where
148
+ // history starts depends on where the window was read from (a compaction).
149
+ const known = before === 0 && this.recentWindows(source, ino, size).find((window) => reaches(window.turns));
150
+ if (known)
151
+ return known;
152
+ return this.remember(await this.fill(source, emptyWindow(end), lastUuid, true, reaches, physical));
153
+ });
154
+ }
155
+ /** The newest turns back to the one holding the record at `offset` (bytes into the file). */
156
+ reaching(source, offset) {
157
+ return this.serial(() => this.liveWindow(source, (_turns, start) => start !== undefined && start <= offset, 1));
158
+ }
159
+ /** The newest turns back to `turnId`. */
160
+ since(source, turnId) {
161
+ return this.serial(() => this.liveWindow(source, (turns) => turns.some((turn) => turn.id === turnId), 1));
162
+ }
163
+ /** The last record of the turn before `turnId` (of `turnId` itself when `inclusive`); null before the first turn. */
164
+ async boundary(source, turnId, inclusive) {
165
+ if (!this.places.has(turnId))
166
+ await this.around(source, turnId, 0);
167
+ const place = this.places.get(turnId);
168
+ return inclusive ? place.boundary : place.previousBoundary;
169
+ }
170
+ /** The windows projected lately, while the file is as it was then. */
171
+ recentWindows(source, ino, size) {
172
+ const key = `${ino}:${size}:${source.leafUuid ?? ""}:${source.peersVersion}`;
173
+ if (this.recent.key !== key)
174
+ this.recent = { key, windows: [] };
175
+ return this.recent.windows;
176
+ }
177
+ remember(window) {
178
+ this.recent.windows = [window, ...this.recent.windows.filter((entry) => entry !== window)].slice(0, RECENT_WINDOWS);
179
+ return window;
180
+ }
181
+ serial(work) {
182
+ const run = this.queue.then(work, work);
183
+ this.queue = run.catch(() => undefined);
184
+ return run;
185
+ }
186
+ async liveWindow(source, enough, keep) {
187
+ const { ino, size } = await stat(source.path);
188
+ if (!this.live || this.live.ino !== ino || size < this.live.end) {
189
+ this.live = { ...emptyWindow(size), ino };
190
+ this.places.clear();
191
+ this.ends.clear();
192
+ }
193
+ const live = this.live;
194
+ this.recentWindows(source, ino, size);
195
+ await readForward(source.path, live, size, this.ends);
196
+ const key = `${live.start}:${live.end}:${source.leafUuid ?? ""}:${source.peersVersion}`;
197
+ if (live.cache?.key === key && (!live.cache.window.older || enough(live.cache.window.turns)))
198
+ return this.remember(live.cache.window);
199
+ const window = this.remember(await this.fill(source, live, source.leafUuid, false, enough));
200
+ // The window stays a few pages long: it starts again at the turn before the kept ones (their context).
201
+ const kept = Math.max(keep, KEPT_TURNS);
202
+ const cut = window.projection.turnBoundaries.at(-kept - 1)?.firstUuid;
203
+ if (window.turns.length > 2 * kept && cut && enough(window.turns.slice(-kept)))
204
+ trim(live, live.offsets.get(cut));
205
+ else
206
+ live.cache = { key, window };
207
+ return window;
208
+ }
209
+ /** Reads the window back until its turns are `enough` or history starts in it. */
210
+ async fill(source, window, leafUuid, continues, enough, physical = false) {
211
+ for (let chunk = this.chunkBytes;; chunk *= 2) {
212
+ if (window.records.length && (!leafUuid || window.offsets.has(leafUuid))) {
213
+ const projection = await projectTranscript({
214
+ sessionId: source.sessionId, path: source.path, records: window.records, header: source.header,
215
+ peers: source.peers, continues, physical, backgroundEnds: this.ends, ...(leafUuid ? { leafUuid } : {}),
216
+ });
217
+ // Cut off from its start, the first turn lacks what came before it (a steer's queue, the prompt of the answer it
218
+ // goes on after): only the turns after it are whole.
219
+ const older = window.start > 0 && (projection.truncated || projection.selectedLeafUuid === null);
220
+ // A turn Claude goes on from mid-message: the window of the one before it holds the message's later blocks, the
221
+ // start of this turn only (past the leaf).
222
+ const leafAt = projection.selectedLeafUuid ? window.offsets.get(projection.selectedLeafUuid) : window.end;
223
+ const partial = projection.turnBoundaries.findIndex((bound) => window.offsets.get(bound.firstUuid) > leafAt);
224
+ const whole = partial < 0 ? projection.turns.length : partial;
225
+ const turns = projection.turns.slice(older ? 1 : 0, whole);
226
+ const first = projection.turnBoundaries[older ? 1 : 0];
227
+ if (!older || enough(turns, first && window.offsets.get(first.firstUuid)) && !projection.partialCompaction) {
228
+ this.index(window, projection, older, continues, physical, whole);
229
+ return { turns, older, projection };
230
+ }
231
+ }
232
+ else if (window.start === 0) {
233
+ if (!leafUuid)
234
+ return { turns: [], older: false, projection: await projectTranscript({ sessionId: source.sessionId, path: source.path, records: [], header: source.header }) };
235
+ throw new Error(`${source.path}: record ${leafUuid} not found`);
236
+ }
237
+ await readBack(source.path, window, chunk, this.ends);
238
+ }
239
+ }
240
+ index(window, projection, older, continues, physical, whole) {
241
+ const bounds = projection.turnBoundaries.slice(0, whole);
242
+ const order = new Map([...projection.selectedRecordUuids].map((uuid, index) => [uuid, index]));
243
+ const physicalFrom = projection.physicalFrom ? order.get(projection.physicalFrom) : -1;
244
+ // Where each record's API message ends: a turn Claude goes on from mid-message needs the message's later blocks.
245
+ const messageOf = new Map();
246
+ const messageEnds = new Map();
247
+ window.records.forEach((record, index) => {
248
+ if (record.type !== "assistant" || !record.message.id)
249
+ return;
250
+ messageOf.set(record.uuid, record.message.id);
251
+ messageEnds.set(record.message.id, window.positions[index + 1] ?? window.end);
252
+ });
253
+ bounds.forEach((bound, index) => {
254
+ if (older && index === 0)
255
+ return;
256
+ const next = bounds[index + 1];
257
+ this.places.set(bound.turnId, {
258
+ start: window.offsets.get(bound.firstUuid),
259
+ // Its records end where the next turn starts, unless Claude grouped a later one into it (one API message).
260
+ end: next
261
+ ? Math.max(window.offsets.get(next.firstUuid), after(window, bound.lastUuid), messageEnds.get(messageOf.get(bound.lastUuid)) ?? 0)
262
+ : continues ? window.end : undefined,
263
+ lastUuid: bound.lastUuid,
264
+ boundary: bound.messageUuid,
265
+ previousBoundary: bounds[index - 1]?.messageUuid ?? null,
266
+ physical: physical || order.get(bound.lastUuid) < physicalFrom,
267
+ });
268
+ });
269
+ }
270
+ }
271
+ //# sourceMappingURL=pages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pages.js","sourceRoot":"","sources":["../../../src/claude/native/pages.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAI9C,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAA6B,MAAM,gBAAgB,CAAC;AAC9F,OAAO,EAAE,mBAAmB,EAAyB,MAAM,cAAc,CAAC;AAG1E,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,CAAC;AAC5B,uGAAuG;AACvG,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,uHAAuH;AACvH,MAAM,cAAc,GAAG,CAAC,CAAC;AA2CzB,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;AAC7E,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,IAAY,EAAE,EAAU;IAC7D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;QACtC,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACtE,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACtC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC;AAED,qHAAqH;AACrH,SAAS,UAAU,CAAC,KAAa,EAAE,EAAU,EAAE,KAAa;IAC1D,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,KAAK,IAAI,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,CAAC,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QAClG,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAClE,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,GAAG,OAAO,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC;AAChD,CAAC;AAED,SAAS,MAAM,CAAC,MAAwB;IACtC,OAAO,MAAM,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACvF,CAAC;AAED,mHAAmH;AACnH,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAE,MAAc,EAAE,KAAa,EAAE,IAAgC;IACnG,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvD,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC9C,2GAA2G;IAC3G,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,GAAG;QAAE,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;SACpD,IAAI,MAAM,CAAC,GAAG,KAAK,MAAM,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,qCAAqC,CAAC,CAAC;IACpG,MAAM,CAAC,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC;IAC5B,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QACvC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,KAAK,CAAE,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wDAAwD;AACxD,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,MAAc,EAAE,IAAY,EAAE,IAAgC;IACrG,IAAI,IAAI,IAAI,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO;IACzD,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAClF,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrC,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IACxB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QACvC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,IAAI;YAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,KAAK,CAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,4CAA4C;AAC5C,SAAS,KAAK,CAAC,MAAc,EAAE,IAAY;IACzC,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;IACzC,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;IACnC,OAAO,GAAG,GAAG,IAAI,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAE,IAAI,MAAM;YAAE,GAAG,GAAG,MAAM,GAAG,CAAC,CAAC;;YACrD,IAAI,GAAG,MAAM,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC;AAC7C,CAAC;AAED,kDAAkD;AAClD,SAAS,IAAI,CAAC,MAAc,EAAE,MAAc;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,IAAI,MAAM,CAAC,CAAC;IAC3E,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO;IACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAChC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAClC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAE,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO;QAAE,IAAI,QAAQ,GAAG,MAAM,CAAC,KAAK;YAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC1G,CAAC;AAKD,MAAM,OAAO,eAAe;IAaU;IAZpC,4DAA4D;IACpD,IAAI,CAAoG;IAC/F,MAAM,GAAG,IAAI,GAAG,EAAqB,CAAC;IACvD;;;OAGG;IACc,IAAI,GAAG,IAAI,GAAG,EAAyB,CAAC;IACzD,8EAA8E;IACtE,MAAM,GAA2C,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC1E,KAAK,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAC;IAEpD,YAAoC,aAAa,WAAW;QAAxB,eAAU,GAAV,UAAU,CAAc;IAAG,CAAC;IAEhE,4EAA4E;IACrE,MAAM,CAAC,MAAkB,EAAE,KAAa;QAC7C,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAC7F,CAAC;IAED,qHAAqH;IAC9G,MAAM,CAAC,MAAkB,EAAE,MAAc,EAAE,MAAc;QAC9D,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;YAC5B,MAAM,OAAO,GAAG,CAAC,KAAsB,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC;YACpG,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,uFAAuF;gBACvF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;gBACpG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;gBAClG,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC;YACnC,CAAC;YACD,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YACxE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;YAC1C,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC9C,iHAAiH;YACjH,2EAA2E;YAC3E,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC5G,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC;YACxB,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;QACrG,CAAC,CAAC,CAAC;IACL,CAAC;IAED,6FAA6F;IACtF,QAAQ,CAAC,MAAkB,EAAE,MAAc;QAChD,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAClH,CAAC;IAED,yCAAyC;IAClC,KAAK,CAAC,MAAkB,EAAE,MAAc;QAC7C,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5G,CAAC;IAED,qHAAqH;IAC9G,KAAK,CAAC,QAAQ,CAAC,MAAkB,EAAE,MAAc,EAAE,SAAkB;QAC1E,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QACnE,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC;QACvC,OAAO,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC;IAC7D,CAAC;IAED,sEAAsE;IAC9D,aAAa,CAAC,MAAkB,EAAE,GAAW,EAAE,IAAY;QACjE,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,IAAI,EAAE,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QAC7E,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,KAAK,GAAG;YAAE,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;IAC7B,CAAC;IAEO,QAAQ,CAAC,MAAkB;QACjC,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QACpH,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,MAAM,CAAI,IAAsB;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACxC,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,KAAK,CAAC,UAAU,CAAC,MAAkB,EAAE,MAAc,EAAE,IAAY;QACvE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YAChE,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACvB,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACtD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,QAAQ,IAAI,EAAE,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxF,IAAI,IAAI,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACtI,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;QAC5F,uGAAuG;QACvG,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC;QACtE,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,IAAI,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;YAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,CAAC;;YAC9G,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;QAClC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,kFAAkF;IAC1E,KAAK,CAAC,IAAI,CAChB,MAAkB,EAClB,MAAc,EACd,QAA4B,EAC5B,SAAkB,EAClB,MAAc,EACd,QAAQ,GAAG,KAAK;QAEhB,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,GAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YAC/C,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;gBACzE,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC;oBACzC,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM;oBAC9F,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACvG,CAAC,CAAC;gBACH,iHAAiH;gBACjH,qDAAqD;gBACrD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,IAAI,UAAU,CAAC,gBAAgB,KAAK,IAAI,CAAC,CAAC;gBACjG,gHAAgH;gBAChH,2CAA2C;gBAC3C,MAAM,MAAM,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;gBAC3G,MAAM,OAAO,GAAG,UAAU,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAE,GAAG,MAAM,CAAC,CAAC;gBAC9G,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;gBAC9D,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBAC3D,MAAM,KAAK,GAAG,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACvD,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,EAAE,KAAK,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC;oBAC3G,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;oBAClE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;gBACtC,CAAC;YACH,CAAC;iBAAM,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;gBAC9B,IAAI,CAAC,QAAQ;oBAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;gBAC/K,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,CAAC,IAAI,YAAY,QAAQ,YAAY,CAAC,CAAC;YAClE,CAAC;YACD,MAAM,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,MAAc,EAAE,UAAgC,EAAE,KAAc,EAAE,SAAkB,EAAE,QAAiB,EAAE,KAAa;QAClI,MAAM,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/F,MAAM,YAAY,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,CAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxF,iHAAiH;QACjH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC5C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;YACvC,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;gBAAE,OAAO;YAC9D,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC9C,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAC9B,IAAI,KAAK,IAAI,KAAK,KAAK,CAAC;gBAAE,OAAO;YACjC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE;gBAC5B,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAE;gBAC3C,2GAA2G;gBAC3G,GAAG,EAAE,IAAI;oBACP,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAE,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAE,CAAC,IAAI,CAAC,CAAC;oBACpI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;gBACtC,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,QAAQ,EAAE,KAAK,CAAC,WAAW;gBAC3B,gBAAgB,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,WAAW,IAAI,IAAI;gBACxD,QAAQ,EAAE,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAE,GAAG,YAAY;aAChE,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -1,6 +1,6 @@
1
1
  import type { Thread, ThreadItem, TokenUsageBreakdown, Turn } from "../../protocol/codex.js";
2
2
  import { type PeerDirectory } from "../peers.js";
3
- import { type ActiveTool } from "../toolMapper.js";
3
+ import { type ActiveTool, type BackgroundEnd } from "../toolMapper.js";
4
4
  import { type SelectedHistory } from "./history.js";
5
5
  import { type ToolResultBlock, type TranscriptRecord, type UserRecord } from "./records.js";
6
6
  import { type TranscriptHeader } from "./summary.js";
@@ -19,11 +19,22 @@ export interface ProjectTranscriptInput {
19
19
  readonly nickname: string;
20
20
  readonly depth: number;
21
21
  };
22
+ /** The records end where a later turn starts (a page of history): their last turn is not the thread's last. */
23
+ readonly continues?: boolean;
24
+ /** The leaf lies past a later compaction: see `selectHistory`. */
25
+ readonly physical?: boolean;
26
+ /** How background commands ended further on in the transcript than `records` reach (a page of history). */
27
+ readonly backgroundEnds?: ReadonlyMap<string, BackgroundEnd>;
22
28
  }
23
- /** Last chain record of a projected turn; the native rollback anchor. */
29
+ /** How background commands ended, by task id: Claude's task notifications and its stops of them (TaskStop). */
30
+ export declare function backgroundEnds(records: readonly TranscriptRecord[], ends?: Map<string, BackgroundEnd>): Map<string, BackgroundEnd>;
31
+ /** Chain records bounding a projected turn: `messageUuid` is the native rollback anchor. */
24
32
  export interface TurnProviderBoundary {
25
33
  readonly turnId: string;
26
34
  readonly messageUuid: string;
35
+ readonly firstUuid: string;
36
+ /** The turn's last record: a trailing compaction included, unless the `/compact` turn next takes it. */
37
+ readonly lastUuid: string;
27
38
  }
28
39
  export interface TranscriptProjection {
29
40
  readonly thread: Thread;
@@ -38,6 +49,11 @@ export interface TranscriptProjection {
38
49
  readonly turnBoundaries: readonly TurnProviderBoundary[];
39
50
  readonly selectedLeafUuid: string | null;
40
51
  readonly selectedRecordUuids: ReadonlySet<string>;
52
+ /** Projected from a window of the transcript whose history goes on before it. */
53
+ readonly truncated: boolean;
54
+ /** A compaction in it keeps messages from before the window. */
55
+ readonly partialCompaction: boolean;
56
+ readonly physicalFrom: string | null;
41
57
  }
42
58
  export interface ToolCompletion {
43
59
  readonly record: Pick<UserRecord, "toolUseResult" | "toolDenialKind">;
@@ -1,13 +1,37 @@
1
1
  /** Owns pure projection of selected Claude transcript history into Codex protocol objects. */
2
2
  import { isAbsolute, resolve } from "node:path";
3
+ import { parseCommands } from "../commandActions.js";
3
4
  import { CODEX_MCP_TOOLS, codexMcpItems } from "../codexRollout.js";
4
5
  import { normalizeClaudeModelIdentifier } from "../modelSelection.js";
5
- import { NO_PEERS, peerMessageItem, peerOrigin, sentMessageItem } from "../peers.js";
6
- import { projectToolCompletion, startTool, } from "../toolMapper.js";
6
+ import { NO_PEERS, peerMessageItem, peerOrigin, sentMessageItem, subagentFiles } from "../peers.js";
7
+ import { endedBackground, killedCommand, projectToolCompletion, taskOutputFile, startTool, stoppedCommand, taskNotification, } from "../toolMapper.js";
7
8
  import { selectHistory } from "./history.js";
8
9
  import { ANSWER_CHARS, assistantBlockItemId, continuationTurnId } from "./ids.js";
9
10
  import { isCompactBoundary, readTranscriptRecords, } from "./records.js";
10
11
  import { slashCommand, startsTurn, summarizeTranscript, timestampSeconds, userText, } from "./summary.js";
12
+ /** How background commands ended, by task id: Claude's task notifications and its stops of them (TaskStop). */
13
+ export function backgroundEnds(records, ends = new Map()) {
14
+ for (const record of records) {
15
+ // A command Stop killed: Claude queues its notification but never sends it (a sent one, later, tells more).
16
+ const killed = record.type === "queue-operation" && record.operation === "enqueue"
17
+ ? taskNotification(record.content ?? "", Date.parse(record.timestamp ?? "")) : undefined;
18
+ if (killed) {
19
+ ends.set(killed.taskId, killed.end);
20
+ if (killed.toolUseId)
21
+ ends.set(killed.toolUseId, { ...killed.end, taskId: killed.taskId });
22
+ }
23
+ if (record.type !== "user")
24
+ continue;
25
+ const atMs = Date.parse(record.timestamp);
26
+ const notified = record.origin?.kind === "task-notification" ? taskNotification(userText(record), atMs) : undefined;
27
+ if (notified)
28
+ ends.set(notified.taskId, notified.end);
29
+ const stopped = stoppedCommand(record.toolUseResult);
30
+ if (stopped)
31
+ ends.set(stopped, { status: "stopped", summary: "", atMs });
32
+ }
33
+ return ends;
34
+ }
11
35
  /** Claude's token use over a history, and of its last request (Desktop's context meter). */
12
36
  function projectedUsage(records) {
13
37
  const total = {
@@ -86,6 +110,13 @@ function assistantBlocks(record) {
86
110
  return [];
87
111
  return record.message.content.filter((block) => block !== null && typeof block === "object");
88
112
  }
113
+ /** Claude Code's filler reply to a turn cut off mid-way, written when the session resumes; its own UI hides it. */
114
+ function resumeFiller(record) {
115
+ if (record.type !== "assistant" || record.isApiErrorMessage === true || record.message.model !== "<synthetic>")
116
+ return false;
117
+ const blocks = assistantBlocks(record);
118
+ return blocks.length === 1 && blocks[0].text === "No response requested.";
119
+ }
89
120
  function outputText(value) {
90
121
  if (typeof value === "string")
91
122
  return value;
@@ -167,14 +198,30 @@ function activeTool(index, block, cwd, threadId, timestamp) {
167
198
  }
168
199
  return startTool(index, block, cwd, threadId);
169
200
  }
170
- function projectTool(block, blockIndex, record, cwd, threadId, completions, peers) {
201
+ function projectTool(block, blockIndex, record, cwd, threadId, completions, peers, ends) {
171
202
  const started = activeTool(blockIndex, block, cwd, threadId, record.timestamp);
172
203
  const completion = completions.get(block.id);
173
204
  const result = completion?.record.toolUseResult;
174
205
  const item = sentMessageItem(started.item, started.state.input, result, peers);
175
206
  if (!completion)
176
207
  return item;
177
- return completedToolItem({ state: { ...started.state, startedAtMs: Date.parse(record.timestamp) }, item }, { ...completion, record: { ...completion.record, toolUseResult: { ...result, duration_ms: typeof result?.duration_ms === "number" ? result.duration_ms : 0 } } }, cwd);
208
+ // An MCP tool's result is its content (text or blocks), not an object of fields.
209
+ const fields = typeof result === "object" && !Array.isArray(result) ? result : undefined;
210
+ const startedAtMs = Date.parse(record.timestamp);
211
+ const completed = completedToolItem({ state: { ...started.state, startedAtMs }, item }, { ...completion, record: { ...completion.record, toolUseResult: { ...fields, duration_ms: typeof fields?.duration_ms === "number" ? fields.duration_ms : 0 } } }, cwd);
212
+ // A background command runs on past its turn: it ends as its task notification (or a stop) tells. With neither, its
213
+ // Claude process ended first (a running one shows live).
214
+ const taskId = typeof fields?.backgroundTaskId === "string" ? fields.backgroundTaskId : undefined;
215
+ const output = (end, task) => end.outputFile ?? taskOutputFile(cwd, record.sessionId, task);
216
+ const killed = taskId ? undefined : ends.get(block.id);
217
+ if (killed?.taskId)
218
+ return killedCommand(completed, output(killed, killed.taskId));
219
+ if (!taskId || completed.type !== "commandExecution")
220
+ return completed;
221
+ const background = { ...completed, processId: taskId };
222
+ const end = ends.get(taskId);
223
+ return end ? endedBackground(background, { ...end, outputFile: output(end, taskId) }, startedAtMs)
224
+ : { ...background, status: "failed", exitCode: null, aggregatedOutput: null };
178
225
  }
179
226
  /** A started tool item completed by its tool_result; shared by history projection and the live stream. */
180
227
  export function completedToolItem(started, completion, cwd) {
@@ -219,26 +266,27 @@ function responseHasTools(records) {
219
266
  }
220
267
  return result;
221
268
  }
269
+ /**
270
+ * A block's item id: its API message and block index. A record without the index (older Claude Code; 0.4's restored
271
+ * turns, whose messages all share one id) is named by its own uuid, a synthetic reply by its message id as live names it.
272
+ */
273
+ function blockItemId(record, position) {
274
+ if (record.apiBlockIndex !== undefined)
275
+ return assistantBlockItemId(record.message.id, record.apiBlockIndex + position);
276
+ return assistantBlockItemId(record.message.model === "<synthetic>" ? record.message.id : record.uuid, position);
277
+ }
222
278
  function responseBlocks(records) {
223
279
  const ordered = records
224
280
  .map((record, order) => ({ record, order }))
225
281
  .sort((left, right) => (left.record.apiBlockIndex ?? left.order) - (right.record.apiBlockIndex ?? right.order));
226
- let fallbackIndex = 0;
227
- return ordered.flatMap(({ record }) => assistantBlocks(record).map((block, blockIndex) => {
228
- const apiBlockIndex = record.apiBlockIndex === undefined
229
- ? fallbackIndex
230
- : record.apiBlockIndex + blockIndex;
231
- fallbackIndex = Math.max(fallbackIndex, apiBlockIndex + 1);
232
- return { record, block, apiBlockIndex };
233
- }));
282
+ return ordered.flatMap(({ record }) => assistantBlocks(record).map((block, position) => ({ record, block, index: (record.apiBlockIndex ?? 0) + position, id: blockItemId(record, position) })));
234
283
  }
235
- function assistantItems(records, cwd, threadId, completions, toolResponses, codexCalls, peers) {
284
+ function assistantItems(records, cwd, threadId, completions, toolResponses, codexCalls, peers, ends) {
236
285
  let reasoning;
237
- return responseBlocks(records).flatMap(({ record, block, apiBlockIndex }) => {
238
- const messageId = record.message.id;
286
+ return responseBlocks(records).flatMap(({ record, block, index, id }) => {
239
287
  if (block.type === "text" && typeof block.text === "string")
240
288
  return [{
241
- type: "agentMessage", id: assistantBlockItemId(messageId, apiBlockIndex), text: block.text,
289
+ type: "agentMessage", id, text: block.text,
242
290
  phase: record.message.id && toolResponses.has(record.message.id) ? "commentary" : "final_answer",
243
291
  memoryCitation: null, delivery: null, questions: null,
244
292
  }];
@@ -248,17 +296,21 @@ function assistantItems(records, cwd, threadId, completions, toolResponses, code
248
296
  return [];
249
297
  }
250
298
  const item = {
251
- type: "reasoning", id: assistantBlockItemId(messageId, apiBlockIndex), summary: [block.thinking], content: [],
299
+ type: "reasoning", id, summary: [block.thinking], content: [],
252
300
  };
253
301
  reasoning = item;
254
302
  return [item];
255
303
  }
256
304
  if (["tool_use", "server_tool_use", "mcp_tool_use"].includes(String(block.type))
257
305
  && typeof block.id === "string" && typeof block.name === "string") {
258
- const item = projectTool(block, apiBlockIndex, record, cwd, threadId, completions, peers);
306
+ const completion = completions.get(block.id);
307
+ // Stopping a background command shows on the command (stock's Ctrl-C), not as a call of its own.
308
+ if (stoppedCommand(completion?.record.toolUseResult))
309
+ return [];
310
+ const item = projectTool(block, index, record, cwd, threadId, completions, peers, ends);
259
311
  if (!CODEX_MCP_TOOLS.has(block.name))
260
312
  return [item];
261
- const result = completions.get(block.id)?.block.content;
313
+ const result = completion?.block.content;
262
314
  return [item, ...codexMcpItems(block.id, object(block.input) ?? {}, result === undefined ? undefined : outputText(result), codexCalls)];
263
315
  }
264
316
  return [];
@@ -267,7 +319,7 @@ function assistantItems(records, cwd, threadId, completions, toolResponses, code
267
319
  function turnStatus(records, hasFollowingTurn) {
268
320
  const failed = records.some((record) => record.type === "system" && record.subtype === "api_error"
269
321
  || record.type === "assistant" && (record.isApiErrorMessage === true || Boolean(record.error)));
270
- const interrupted = records.some((record) => record.type === "user" && (record.interruptedByShutdown === true
322
+ const interrupted = records.some((record) => resumeFiller(record) || record.type === "user" && (record.interruptedByShutdown === true
271
323
  || record.toolUseResult?.interrupted === true || /^\[Request interrupted by user(?: for tool use)?\]$/u.test(userText(record))));
272
324
  if (interrupted)
273
325
  return "interrupted";
@@ -348,7 +400,7 @@ function turnStarts(records, subagentPromptUuid, steered) {
348
400
  assistantBlocks(record).forEach((block, position) => {
349
401
  if (answer)
350
402
  goOn(index);
351
- lastBlock = assistantBlockItemId(record.message.id, (record.apiBlockIndex ?? 0) + position);
403
+ lastBlock = blockItemId(record, position);
352
404
  answer = block.type === "text" && typeof block.text === "string" && block.text.length >= ANSWER_CHARS;
353
405
  });
354
406
  }
@@ -373,22 +425,18 @@ function turnStarts(records, subagentPromptUuid, steered) {
373
425
  });
374
426
  return starts;
375
427
  }
376
- /** The session's sub-agents, from the results of the calls that started them. */
377
- function subagentIds(completions) {
378
- return new Set([...completions.values()].flatMap(({ record }) => string(record.toolUseResult?.agentId) ?? []));
379
- }
380
- function projectTurns(records, cwd, threadId, subagentPromptUuid, steered, directory) {
428
+ function projectTurns(records, cwd, threadId, subagentPromptUuid, steered, directory, continues, path, ends) {
381
429
  const starts = turnStarts(records, subagentPromptUuid, steered);
382
430
  const completions = toolCompletions(records);
383
- const peers = { directory, children: subagentIds(completions) };
431
+ // As live: a window of history lacks the calls that started earlier sub-agents.
432
+ const peers = { directory, children: subagentFiles(path) };
384
433
  const toolResponses = responseHasTools(records);
385
434
  const codexCalls = new Map();
386
435
  const turns = starts.map(({ index: start, id, prompt }, turnIndex) => {
387
436
  const end = starts[turnIndex + 1]?.index ?? records.length;
388
437
  const turnRecords = records.slice(start, end);
389
438
  const input = prompt ? userInputs(prompt) : [];
390
- const hiddenCommand = input.length === 1 && input[0]?.type === "text"
391
- && /^\/(?:compact(?:\s|$)|goal clear$)/u.test(input[0].text);
439
+ const hiddenCommand = input.length === 1 && input[0]?.type === "text" && /^\/compact(?:\s|$)/u.test(input[0].text);
392
440
  const peer = peerOrigin(prompt?.origin);
393
441
  const items = peer ? [peerMessageItem(prompt.uuid, peer, userText(prompt), peers)]
394
442
  : hiddenCommand || !prompt ? []
@@ -404,22 +452,26 @@ function projectTurns(records, cwd, threadId, subagentPromptUuid, steered, direc
404
452
  }
405
453
  const projectedResponses = new Set();
406
454
  for (const record of prompt ? turnRecords.slice(1) : turnRecords) {
455
+ if (resumeFiller(record))
456
+ continue;
407
457
  if (record.type === "assistant") {
408
458
  const messageId = record.message.id;
409
459
  if (projectedResponses.has(messageId))
410
460
  continue;
411
461
  projectedResponses.add(messageId);
412
- items.push(...assistantItems(responses.get(messageId), cwd, threadId, completions, toolResponses, codexCalls, peers));
462
+ items.push(...assistantItems(responses.get(messageId), cwd, threadId, completions, toolResponses, codexCalls, peers, ends));
413
463
  }
414
464
  else if (record.type === "user" && peerOrigin(record.origin)) {
415
465
  items.push(peerMessageItem(record.uuid, peerOrigin(record.origin), userText(record), peers));
416
466
  }
467
+ // A steer's id is the client's own (Desktop shows a message of a turn after its first only with it).
417
468
  else if (record.type === "user" && steered.has(record.uuid)) {
418
- items.push({ type: "userMessage", id: record.uuid, clientId: null, content: userInputs(record) });
469
+ items.push({ type: "userMessage", id: record.uuid, clientId: record.uuid, content: userInputs(record) });
419
470
  }
420
471
  else if (record.type === "system" && record.subtype === "local_command" && typeof record.content === "string") {
421
472
  const text = record.content.replace(/<\/?local-command-std(?:out|err)>/gu, "").trim();
422
- if (text)
473
+ // Claude's own word on `/goal` ("Goal set: …"): Codex clients show goals themselves.
474
+ if (text && record.commandRun?.command !== "goal")
423
475
  items.push({ type: "agentMessage", id: record.uuid, text, phase: "commentary", memoryCitation: null });
424
476
  }
425
477
  else if (isCompactBoundary(record))
@@ -431,19 +483,17 @@ function projectTurns(records, cwd, threadId, subagentPromptUuid, steered, direc
431
483
  if (attachment?.type === "queued_command" && peer) {
432
484
  items.push(peerMessageItem(string(attachment.source_uuid) ?? record.uuid, peer, string(attachment.prompt) ?? "", peers));
433
485
  }
434
- else if (attachment?.type === "queued_command" && attachment.commandMode === "prompt" && typeof attachment.prompt === "string") {
435
- items.push({
436
- type: "userMessage", id: string(attachment.source_uuid) ?? record.uuid, clientId: null,
437
- content: [{ type: "text", text: attachment.prompt, text_elements: [] }],
438
- });
486
+ else if (attachment?.type === "queued_command" && attachment.commandMode === "prompt" && (typeof attachment.prompt === "string" || Array.isArray(attachment.prompt))) {
487
+ const id = string(attachment.source_uuid) ?? record.uuid;
488
+ items.push({ type: "userMessage", id, clientId: id, content: userInputs({ message: { content: attachment.prompt } }) });
439
489
  }
440
490
  }
441
491
  }
442
- const status = turnStatus(turnRecords, turnIndex + 1 < starts.length);
492
+ const status = turnStatus(turnRecords, continues || turnIndex + 1 < starts.length);
443
493
  const startedAt = timestampSeconds(turnRecords[0].timestamp);
444
- // A later local command (a model switch) trails the turn in the transcript without extending it.
445
- const last = turnRecords.findLast((record) => record.type !== "user" || record === turnRecords[0]
446
- || record.isMeta !== true && !/^<(?:command-name|local-command-)/u.test(userText(record)));
494
+ // A later local command (a model switch) or compaction trails the turn in the transcript without extending it.
495
+ const last = turnRecords.findLast((record) => record === turnRecords[0] || !isCompactBoundary(record) && (record.type !== "user"
496
+ || record.isMeta !== true && record.isCompactSummary !== true && !/^<(?:command-name|local-command-)/u.test(userText(record))));
447
497
  const completedAt = status === "inProgress" ? null : timestampSeconds(last?.timestamp);
448
498
  return {
449
499
  id,
@@ -467,14 +517,16 @@ function projectTurns(records, cwd, threadId, subagentPromptUuid, steered, direc
467
517
  });
468
518
  return turns;
469
519
  }
470
- function projectTurnBoundaries(records, subagentPromptUuid, steered) {
520
+ function projectTurnBoundaries(records, subagentPromptUuid, steered, turns) {
471
521
  const starts = turnStarts(records, subagentPromptUuid, steered);
472
522
  return starts.map(({ index: start, id }, turnIndex) => {
473
523
  const range = records.slice(start + 1, starts[turnIndex + 1]?.index ?? records.length);
474
524
  // A compaction that ends the turn (the next turn is the `/compact`) is not part of it: forks stay uncompacted.
475
525
  const compaction = range.findLastIndex((record) => isCompactBoundary(record));
476
526
  const kept = compaction >= 0 && !range.slice(compaction).some((record) => record.type === "assistant") ? range.slice(0, compaction) : range;
477
- return { turnId: id, messageUuid: (kept.at(-1) ?? records[start]).uuid };
527
+ // A `/compact` turn next took the compaction (see `projectTurns`): this turn's records end before it.
528
+ const last = compaction >= 0 && turns[turnIndex + 1]?.items[0]?.id === range[compaction].uuid ? kept : range;
529
+ return { turnId: id, messageUuid: (kept.at(-1) ?? records[start]).uuid, firstUuid: records[start].uuid, lastUuid: (last.at(-1) ?? records[start]).uuid };
478
530
  });
479
531
  }
480
532
  /** The Codex thread for a native session header (list rows, reads, live responses). */
@@ -534,11 +586,14 @@ export async function projectTranscript(input) {
534
586
  skippedLines = reader.skippedLines;
535
587
  rawRecords = loaded;
536
588
  }
537
- const history = input.history ?? selectHistory(rawRecords, input.leafUuid);
589
+ const history = input.history ?? selectHistory(rawRecords, input.leafUuid, input.physical);
538
590
  const selected = history.records;
591
+ await parseCommands(selected.flatMap((record) => record.type === "assistant"
592
+ ? assistantBlocks(record).flatMap((block) => block.type === "tool_use" && block.name === "Bash" ? string(object(block.input)?.command) ?? [] : [])
593
+ : []));
539
594
  const header = input.header ?? summarizeTranscript(rawRecords, input.subagent?.promptRecordUuid);
540
595
  const steered = steeredPrompts(rawRecords);
541
- const turns = projectTurns(selected, header.cwd, input.sessionId, input.subagent?.promptRecordUuid, steered, input.peers ?? NO_PEERS.directory);
596
+ const turns = projectTurns(selected, header.cwd, input.sessionId, input.subagent?.promptRecordUuid, steered, input.peers ?? NO_PEERS.directory, input.continues ?? false, input.path, backgroundEnds(rawRecords, new Map(input.backgroundEnds)));
542
597
  const nickname = input.subagent?.nickname ?? null;
543
598
  const parentThreadId = input.parentThreadId ?? null;
544
599
  const status = turns.at(-1)?.status === "inProgress"
@@ -557,9 +612,12 @@ export async function projectTranscript(input) {
557
612
  tokenUsage: projectedUsage(selected),
558
613
  skippedLines,
559
614
  compactionBoundaries: history.compactionBoundaries,
560
- turnBoundaries: projectTurnBoundaries(selected, input.subagent?.promptRecordUuid, steered),
615
+ turnBoundaries: projectTurnBoundaries(selected, input.subagent?.promptRecordUuid, steered, turns),
561
616
  selectedLeafUuid: history.leafUuid,
562
617
  selectedRecordUuids: new Set(selected.map((record) => record.uuid)),
618
+ truncated: history.truncated,
619
+ partialCompaction: history.partialCompaction,
620
+ physicalFrom: history.physicalFrom,
563
621
  };
564
622
  }
565
623
  //# sourceMappingURL=projector.js.map