cogpit-memory 0.3.0 → 0.4.1

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.js CHANGED
@@ -54,10 +54,39 @@ var import_better_sqlite3 = __toESM(require("better-sqlite3"));
54
54
  var Database = import_better_sqlite3.default;
55
55
 
56
56
  // src/lib/search-index.ts
57
- var import_node_fs2 = require("node:fs");
57
+ var import_node_fs3 = require("node:fs");
58
58
 
59
59
  // src/lib/types.ts
60
- var AGENT_KINDS = ["codex", "copilot", "claude"];
60
+ var AGENT_KINDS = ["acp", "codex", "copilot", "claude"];
61
+
62
+ // src/lib/instances.ts
63
+ function instanceSessionId(instanceId, nativeId) {
64
+ if (instanceId === "default") return nativeId;
65
+ const bytes = new TextEncoder().encode(nativeId);
66
+ const encoded = btoa(Array.from(bytes, (byte) => String.fromCharCode(byte)).join("")).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
67
+ return `i-${instanceId}__${encoded}`;
68
+ }
69
+ function splitInstanceSessionId(id) {
70
+ const match = /^i-([A-Za-z0-9-]+)__([A-Za-z0-9_-]+)$/.exec(id);
71
+ if (!match) return { instanceId: "default", nativeId: id };
72
+ try {
73
+ const bytes = Uint8Array.from(atob(match[2].replace(/-/g, "+").replace(/_/g, "/")), (character) => character.charCodeAt(0));
74
+ return { instanceId: match[1], nativeId: new TextDecoder("utf-8", { fatal: true }).decode(bytes) };
75
+ } catch {
76
+ throw new Error("Invalid instance session ID");
77
+ }
78
+ }
79
+ function instanceDirName(instanceId, nativeDirName) {
80
+ return instanceId === "default" ? nativeDirName : `instance__${instanceId}__${nativeDirName}`;
81
+ }
82
+ function splitInstanceDirName(dirName) {
83
+ const match = /^instance__([A-Za-z0-9-]+)__(.+)$/.exec(dirName ?? "");
84
+ return match ? { instanceId: match[1], nativeDirName: match[2] } : { instanceId: "default", nativeDirName: dirName ?? "" };
85
+ }
86
+ function scopeParsedSession(session, instanceId) {
87
+ if (instanceId === "default") return session;
88
+ return { ...session, instanceId, sessionId: instanceSessionId(instanceId, splitInstanceSessionId(session.sessionId).nativeId), ...session.branchedFrom ? { branchedFrom: { ...session.branchedFrom, sessionId: instanceSessionId(instanceId, splitInstanceSessionId(session.branchedFrom.sessionId).nativeId) } } : {} };
89
+ }
61
90
 
62
91
  // src/lib/agent-descriptors.ts
63
92
  var SESSION_UUID = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
@@ -84,14 +113,26 @@ function base64DirNameCodec(prefix) {
84
113
  return {
85
114
  lossy: false,
86
115
  owns: (dirName) => typeof dirName === "string" && dirName.startsWith(prefix),
116
+ recognizes: (dirName) => {
117
+ const cwd = decodeBase64DirName(prefix, dirName);
118
+ return cwd !== null && cwd !== "" && encodeBase64DirName(prefix, cwd) === dirName;
119
+ },
87
120
  encode: (cwd) => encodeBase64DirName(prefix, cwd),
88
121
  decode: (dirName) => decodeBase64DirName(prefix, dirName)
89
122
  };
90
123
  }
91
124
  function sessionIdFromJsonlName(fileName) {
92
- const match = new RegExp(`(${SESSION_UUID})\\.jsonl$`, "i").exec(fileName);
125
+ const match = new RegExp(`(${SESSION_UUID})\\.jsonl(?:\\.zst)?$`, "i").exec(fileName);
93
126
  return match ? match[1] : null;
94
127
  }
128
+ function ownTranscriptRoot(sessionId) {
129
+ return sessionId ? { rootSessionId: sessionId.toLowerCase(), isRootTranscript: true } : null;
130
+ }
131
+ function plainPathSegments(relativePath) {
132
+ const segments = relativePath.split("/");
133
+ const plain = segments.every((segment) => segment !== "" && segment !== "." && segment !== ".." && !segment.includes("\\"));
134
+ return plain ? segments : null;
135
+ }
95
136
  var jsonlPathUrlCodec = {
96
137
  urlId: (fileName) => fileName.replace(/\.jsonl$/, ""),
97
138
  fileNameFromUrlId: (urlId) => urlId.endsWith(".jsonl") ? urlId : `${urlId}.jsonl`
@@ -109,6 +150,17 @@ var ARGV_SESSION_ID = "[0-9a-f-]{36}";
109
150
  var CODEX_DIR_PREFIX = "codex__";
110
151
  var COPILOT_DIR_PREFIX = "copilot__";
111
152
  var CLAUDE_PERMISSION_MODES = /* @__PURE__ */ new Set(["default", "plan", "acceptEdits", "dontAsk", "auto"]);
153
+ var CLAUDE_SESSION_CHILD_DIRS = /* @__PURE__ */ new Set(["subagents", "workflows"]);
154
+ function claudeTranscriptRoot(relativePath) {
155
+ const segments = plainPathSegments(relativePath);
156
+ if (!segments) return null;
157
+ const [root, childDir] = segments;
158
+ if (segments.length === 1) {
159
+ const sessionId = root.replace(/\.jsonl$/, "");
160
+ return sessionId !== root && isSessionUuid(sessionId) ? ownTranscriptRoot(sessionId) : null;
161
+ }
162
+ return segments.length > 2 && CLAUDE_SESSION_CHILD_DIRS.has(childDir) && isSessionUuid(root) ? { rootSessionId: root.toLowerCase(), isRootTranscript: false } : null;
163
+ }
112
164
  var claude = {
113
165
  kind: "claude",
114
166
  displayName: "Claude Code",
@@ -119,6 +171,8 @@ var claude = {
119
171
  // registry checks the prefixed agents first, so this is only ever reached
120
172
  // as the terminal arm.
121
173
  owns: (dirName) => typeof dirName === "string" && !dirName.startsWith(CODEX_DIR_PREFIX) && !dirName.startsWith(COPILOT_DIR_PREFIX),
174
+ // An absolute path starts with `/` or `\` (`-`) or a drive (`C:\` → `C--`); a drive root alone is `C-`.
175
+ recognizes: (dirName) => /^(?:(?:-|[A-Za-z]--)[A-Za-z0-9-]*|[A-Za-z]-)$/.test(dirName),
122
176
  /**
123
177
  * Claude Code's own convention: every character outside `[A-Za-z0-9]`
124
178
  * becomes `-`, so `/Users/x/proj` and `C:\Users\x\proj` both collapse into a
@@ -136,10 +190,12 @@ var claude = {
136
190
  return "/" + dirName.replace(/^-/, "").replace(/-/g, "/");
137
191
  }
138
192
  },
193
+ projectWorktreeDir: ".claude/worktrees",
139
194
  sessionFile: {
140
195
  name: (sessionId) => `${sessionId}.jsonl`,
141
196
  sessionId: sessionIdFromJsonlName,
142
- ...jsonlPathUrlCodec
197
+ ...jsonlPathUrlCodec,
198
+ transcriptRoot: claudeTranscriptRoot
143
199
  },
144
200
  metadataFromHead: true,
145
201
  resume: {
@@ -174,6 +230,7 @@ var claude = {
174
230
  bundledBySdk: true,
175
231
  homeDirName: ".claude",
176
232
  homeEnvVar: null,
233
+ sdkHomeEnvVar: "CLAUDE_CONFIG_DIR",
177
234
  installMarker: "projects",
178
235
  homeIsDiscoverable: false,
179
236
  process: {
@@ -185,7 +242,8 @@ var claude = {
185
242
  rootDirName: ".claude",
186
243
  instructions: [
187
244
  { in: "scope", path: "CLAUDE.md", scopes: ["global", "project"] },
188
- { in: "root", path: "CLAUDE.md", label: ".claude/CLAUDE.md", scopes: ["project"] }
245
+ { in: "root", path: "CLAUDE.md", label: ".claude/CLAUDE.md", scopes: ["project"] },
246
+ { in: "scope", path: "AGENTS.md", scopes: ["project"], fallback: true }
189
247
  ],
190
248
  settings: [
191
249
  { in: "root", path: "settings.json", scopes: ["global"] },
@@ -230,9 +288,12 @@ var claude = {
230
288
  nativeRewind: false,
231
289
  fileCheckpoints: true,
232
290
  reasoningEffort: true,
291
+ configurableContextWindow: false,
233
292
  fastTier: true,
293
+ lowPriorityInTerminal: true,
234
294
  imageInput: true,
235
- midTurnSteering: false,
295
+ midTurnSteering: true,
296
+ activeNotifications: true,
236
297
  stopSession: true,
237
298
  ultracode: true,
238
299
  contextWindow: true,
@@ -240,6 +301,7 @@ var claude = {
240
301
  accountSwitching: true,
241
302
  modelFallbackNotices: true,
242
303
  autoPermissionMode: "per-model",
304
+ toolPermissionRules: true,
243
305
  settingsApply: "live",
244
306
  turnLiveness: "transcript",
245
307
  tokenStreaming: true,
@@ -256,6 +318,7 @@ var codex = {
256
318
  displayName: "Codex",
257
319
  binName: "codex",
258
320
  dirName: base64DirNameCodec(CODEX_DIR_PREFIX),
321
+ projectWorktreeDir: null,
259
322
  sessionFile: {
260
323
  /**
261
324
  * Codex nests rollouts by local date:
@@ -272,7 +335,9 @@ var codex = {
272
335
  },
273
336
  sessionId: sessionIdFromJsonlName,
274
337
  // The date nesting is unrecoverable from the id, so the URL keeps the path.
275
- ...jsonlPathUrlCodec
338
+ ...jsonlPathUrlCodec,
339
+ // A sub-agent is a rollout of its own, linked to its parent only in its header.
340
+ transcriptRoot: (relativePath) => plainPathSegments(relativePath) ? ownTranscriptRoot(sessionIdFromJsonlName(relativePath)) : null
276
341
  },
277
342
  // A rollout's header carries no turn count and no last user message; both
278
343
  // only settle at the end of the file.
@@ -285,6 +350,7 @@ var codex = {
285
350
  permissions: (permissions) => {
286
351
  const mode = permissions?.mode || "default";
287
352
  if (mode === "bypassPermissions") return ["--dangerously-bypass-approvals-and-sandbox"];
353
+ if (mode === "auto") return ["--approve-for-me"];
288
354
  return [
289
355
  "--sandbox",
290
356
  mode === "plan" ? "read-only" : "workspace-write",
@@ -313,6 +379,7 @@ var codex = {
313
379
  bundledBySdk: false,
314
380
  homeDirName: ".codex",
315
381
  homeEnvVar: "CODEX_HOME",
382
+ sessionIdEnvVar: "CODEX_THREAD_ID",
316
383
  installMarker: "",
317
384
  homeIsDiscoverable: true,
318
385
  process: {
@@ -344,7 +411,7 @@ var codex = {
344
411
  extendedContext: null
345
412
  },
346
413
  capabilities: {
347
- worktrees: false,
414
+ worktrees: true,
348
415
  mcp: false,
349
416
  slashCommands: false,
350
417
  workflows: false,
@@ -358,16 +425,20 @@ var codex = {
358
425
  nativeRewind: false,
359
426
  fileCheckpoints: false,
360
427
  reasoningEffort: true,
428
+ configurableContextWindow: true,
361
429
  fastTier: true,
430
+ lowPriorityInTerminal: false,
362
431
  imageInput: true,
363
432
  midTurnSteering: true,
433
+ activeNotifications: true,
364
434
  stopSession: false,
365
435
  ultracode: false,
366
436
  contextWindow: false,
367
437
  externalProcesses: false,
368
438
  accountSwitching: false,
369
439
  modelFallbackNotices: false,
370
- autoPermissionMode: "never",
440
+ autoPermissionMode: "always",
441
+ toolPermissionRules: true,
371
442
  settingsApply: "next-turn",
372
443
  turnLiveness: "runtime",
373
444
  tokenStreaming: true,
@@ -376,24 +447,25 @@ var codex = {
376
447
  namedSessions: false
377
448
  }
378
449
  };
450
+ function copilotSessionId(fileName) {
451
+ const match = new RegExp(`^(${SESSION_UUID})/events\\.jsonl$`, "i").exec(fileName);
452
+ return match ? match[1] : null;
453
+ }
379
454
  var copilot = {
380
455
  kind: "copilot",
381
456
  displayName: "GitHub Copilot CLI",
382
457
  binName: "copilot",
383
458
  dirName: base64DirNameCodec(COPILOT_DIR_PREFIX),
459
+ projectWorktreeDir: null,
384
460
  sessionFile: {
385
461
  /** Copilot keeps one directory per session: `<uuid>/events.jsonl`. */
386
462
  name: (sessionId) => `${sessionId}/events.jsonl`,
387
- sessionId: (fileName) => {
388
- const match = new RegExp(`^(${SESSION_UUID})/events\\.jsonl$`, "i").exec(fileName);
389
- return match ? match[1] : null;
390
- },
463
+ sessionId: copilotSessionId,
391
464
  // `<id>/events.jsonl` rebuilds from the id, so URLs stay short.
392
- urlId: (fileName) => {
393
- const match = new RegExp(`^(${SESSION_UUID})/events\\.jsonl$`, "i").exec(fileName);
394
- return match ? match[1] : fileName.replace(/\.jsonl$/, "");
395
- },
396
- fileNameFromUrlId: (urlId) => urlId.endsWith(".jsonl") ? urlId : `${urlId}/events.jsonl`
465
+ urlId: (fileName) => copilotSessionId(fileName) ?? fileName.replace(/\.jsonl$/, ""),
466
+ fileNameFromUrlId: (urlId) => urlId.endsWith(".jsonl") ? urlId : `${urlId}/events.jsonl`,
467
+ // Sub-agents are events inside the parent transcript, so every file is a root.
468
+ transcriptRoot: (relativePath) => ownTranscriptRoot(copilotSessionId(relativePath))
397
469
  },
398
470
  metadataFromHead: true,
399
471
  resume: {
@@ -475,9 +547,12 @@ var copilot = {
475
547
  fileCheckpoints: false,
476
548
  // Effort is only offered for models whose catalog entry advertises it.
477
549
  reasoningEffort: false,
550
+ configurableContextWindow: false,
478
551
  fastTier: false,
552
+ lowPriorityInTerminal: false,
479
553
  imageInput: false,
480
554
  midTurnSteering: true,
555
+ activeNotifications: true,
481
556
  stopSession: true,
482
557
  ultracode: false,
483
558
  contextWindow: false,
@@ -485,6 +560,7 @@ var copilot = {
485
560
  accountSwitching: false,
486
561
  modelFallbackNotices: false,
487
562
  autoPermissionMode: "always",
563
+ toolPermissionRules: true,
488
564
  settingsApply: "next-turn",
489
565
  turnLiveness: "runtime",
490
566
  tokenStreaming: false,
@@ -492,21 +568,56 @@ var copilot = {
492
568
  namedSessions: true
493
569
  }
494
570
  };
571
+ var acp = {
572
+ ...copilot,
573
+ kind: "acp",
574
+ displayName: "ACP agent",
575
+ binName: "acp",
576
+ dirName: base64DirNameCodec("acp__"),
577
+ sessionFile: { name: (id) => `${id}.jsonl`, sessionId: sessionIdFromJsonlName, ...jsonlPathUrlCodec, transcriptRoot: (path) => {
578
+ const segments = plainPathSegments(path);
579
+ return segments?.length === 1 ? ownTranscriptRoot(sessionIdFromJsonlName(path)) : null;
580
+ } },
581
+ resume: { command: () => "Resume this session in Cogpit", args: () => [] },
582
+ launchArgs: { permissions: () => [], model: () => [], effort: () => [], fastTier: () => [] },
583
+ cli: { ...copilot.cli, packageName: "", homebrew: null, wingetId: null, selfUpdate: null, requiresConfiguration: true, homeDirName: ".cogpit-acp", homeEnvVar: "COGPIT_ACP_HOME", homeIsDiscoverable: true, installMarker: "projects" },
584
+ config: { ...copilot.config, rootDirName: ".cogpit-acp", instructions: [], settings: [], skillsDir: null },
585
+ capabilities: { ...copilot.capabilities, undo: false, redo: false, nativeRewind: false, nativeFork: false, midTurnSteering: false, activeNotifications: false, externalProcesses: false, autoPermissionMode: "never", toolPermissionRules: false, namedSessions: false }
586
+ };
495
587
  var DESCRIPTORS = Object.freeze({
496
588
  claude,
497
589
  codex,
498
- copilot
590
+ copilot,
591
+ acp
499
592
  });
500
593
  function descriptorFor(kind) {
501
594
  return DESCRIPTORS[kind];
502
595
  }
503
596
  function descriptorForDirName(dirName) {
597
+ const scoped = splitInstanceDirName(dirName);
598
+ if (scoped.instanceId !== "default") {
599
+ const descriptor = descriptorForDirName(scoped.nativeDirName);
600
+ return {
601
+ ...descriptor,
602
+ dirName: { ...descriptor.dirName, encode: (cwd) => instanceDirName(scoped.instanceId, descriptor.dirName.encode(cwd)), decode: (name) => descriptor.dirName.decode(splitInstanceDirName(name).nativeDirName) },
603
+ sessionFile: { ...descriptor.sessionFile, name: (id) => descriptor.sessionFile.name(splitInstanceSessionId(id).nativeId), sessionId: (file) => {
604
+ const nativeId = descriptor.sessionFile.sessionId(file);
605
+ return nativeId ? instanceSessionId(scoped.instanceId, nativeId) : null;
606
+ }, transcriptRoot: (file) => {
607
+ const root = descriptor.sessionFile.transcriptRoot(file);
608
+ return root ? { ...root, rootSessionId: instanceSessionId(scoped.instanceId, root.rootSessionId) } : null;
609
+ } }
610
+ };
611
+ }
504
612
  for (const kind of AGENT_KINDS) {
505
613
  if (kind === "claude") continue;
506
614
  if (DESCRIPTORS[kind].dirName.owns(dirName)) return DESCRIPTORS[kind];
507
615
  }
508
616
  return claude;
509
617
  }
618
+ function isSessionUuid(value) {
619
+ return SESSION_UUID_RE.test(value);
620
+ }
510
621
 
511
622
  // src/lib/codex-exec.ts
512
623
  var JS_SIMPLE_ESCAPES = {
@@ -575,6 +686,27 @@ function readJsStringLiteral(source, startIndex) {
575
686
  return null;
576
687
  }
577
688
 
689
+ // src/lib/backgroundAgents.ts
690
+ function awaitingAgentsStatus(launches, pendingQueue = 0) {
691
+ if (!launches.some((launch) => launch.endedAt === void 0)) return null;
692
+ const ordered = [...launches].sort((a, b) => a.launchedAt - b.launchedAt);
693
+ let batchStart = 0;
694
+ let busyUntil = -Infinity;
695
+ ordered.forEach((launch, index) => {
696
+ if (busyUntil < launch.launchedAt) batchStart = index;
697
+ busyUntil = Math.max(busyUntil, launch.endedAt ?? Infinity);
698
+ });
699
+ const batch = ordered.slice(batchStart).map(({ agent, endedAt }) => ({ ...agent, done: endedAt !== void 0 }));
700
+ const running = batch.filter((agent) => !agent.done);
701
+ return {
702
+ status: "awaiting_agents",
703
+ pendingQueue,
704
+ pendingAgents: running.length,
705
+ pendingAgentDescriptions: running.map((agent) => agent.description).filter((description) => description.length > 0),
706
+ backgroundAgents: batch
707
+ };
708
+ }
709
+
578
710
  // src/lib/messageTypeGuards.ts
579
711
  function isUserMessage(msg) {
580
712
  return msg.type === "user";
@@ -682,6 +814,36 @@ function parseAgentEnvelope(text) {
682
814
  return { sender, matched, body: matched ? unwrapped.trim() : text };
683
815
  }
684
816
 
817
+ // src/lib/toolResults.ts
818
+ function record(value) {
819
+ return value && typeof value === "object" ? value : {};
820
+ }
821
+ function toolResultMetadata(name, value) {
822
+ const result = record(value);
823
+ if (name === "Edit" || name === "Write") {
824
+ return result.staged === true ? { awaitingReview: true } : {};
825
+ }
826
+ if (name !== "Bash") return {};
827
+ const diff = record(result.bashEditDiff);
828
+ if (!Array.isArray(diff.files)) return {};
829
+ const files = [];
830
+ for (const raw of diff.files) {
831
+ const file = record(raw);
832
+ if (typeof file.filePath !== "string" || !file.filePath || !Array.isArray(file.hunks)) continue;
833
+ const hunks = [];
834
+ for (const rawHunk of file.hunks) {
835
+ const hunk = record(rawHunk);
836
+ const { oldStart, oldLines, newStart, newLines, lines } = hunk;
837
+ if (![oldStart, oldLines, newStart, newLines].every((n) => typeof n === "number" && Number.isInteger(n) && n >= 0)) continue;
838
+ if (!Array.isArray(lines) || !lines.every((line) => typeof line === "string" && /^[ +\\-]/.test(line))) continue;
839
+ hunks.push({ oldStart, oldLines, newStart, newLines, lines });
840
+ }
841
+ if (hunks.length) files.push({ filePath: file.filePath, hunks });
842
+ }
843
+ const more = typeof diff.moreFiles === "number" && Number.isInteger(diff.moreFiles) && diff.moreFiles > 0 ? diff.moreFiles : 0;
844
+ return { fileDiffs: files, ...more ? { additionalFileDiffs: more } : {} };
845
+ }
846
+
685
847
  // src/lib/turnBuilder.ts
686
848
  function extractTextFromContent(content) {
687
849
  if (typeof content === "string") return content;
@@ -709,6 +871,17 @@ function isTaskNotificationRecord(msg) {
709
871
  if (!text.includes("<task-notification>")) return false;
710
872
  return text.replace(TASK_NOTIFICATION_BLOCK_RE, "").replace(ANY_TAG_RE, "").trim() === "";
711
873
  }
874
+ function isTaskToolName(name) {
875
+ return name === "Task" || name === "Agent";
876
+ }
877
+ function readTaskMeta(input) {
878
+ const effort = input.effort;
879
+ return {
880
+ name: typeof input.name === "string" ? input.name : null,
881
+ subagentType: typeof input.subagent_type === "string" ? input.subagent_type : null,
882
+ effort: typeof effort === "string" || typeof effort === "number" ? String(effort) : null
883
+ };
884
+ }
712
885
  function queuedCommandPrompt(msg) {
713
886
  if (!isAttachmentMessage(msg)) return null;
714
887
  const attachment = msg.attachment;
@@ -1049,6 +1222,16 @@ function buildTurnsWithStarts(messages) {
1049
1222
  pendingRecap = { content: msg.content, timestamp: msg.timestamp };
1050
1223
  continue;
1051
1224
  }
1225
+ if (isSystemMessage(msg) && msg.subtype === "local_command" && msg.content) {
1226
+ current?.contentBlocks.push({
1227
+ kind: "local_command",
1228
+ content: msg.content,
1229
+ timestamp: msg.timestamp,
1230
+ ...msg.contextUsage ? { contextUsage: msg.contextUsage } : {},
1231
+ ...msg.usageReport ? { usageReport: msg.usageReport } : {}
1232
+ });
1233
+ continue;
1234
+ }
1052
1235
  if (isQueueOperationMessage(msg)) {
1053
1236
  if (current && msg.operation === "enqueue" && isVisibleQueuedPrompt(msg.content)) {
1054
1237
  const parsed = parseAgentEnvelope(msg.content);
@@ -1100,6 +1283,8 @@ function buildTurnsWithStarts(messages) {
1100
1283
  if (pending) {
1101
1284
  pending.turn.toolCalls[pending.index].result = extractToolResultText(block.content);
1102
1285
  pending.turn.toolCalls[pending.index].isError = block.is_error === true;
1286
+ const call = pending.turn.toolCalls[pending.index];
1287
+ Object.assign(call, toolResultMetadata(call.name, msg.toolUseResult));
1103
1288
  pendingToolUses.delete(block.tool_use_id);
1104
1289
  }
1105
1290
  }
@@ -1120,6 +1305,7 @@ function buildTurnsWithStarts(messages) {
1120
1305
  parentToolUseId: toolUseId || void 0,
1121
1306
  agentName: taskMeta?.name ?? null,
1122
1307
  subagentType: taskMeta?.subagentType ?? null,
1308
+ ...taskMeta?.effort ? { effort: taskMeta.effort } : {},
1123
1309
  type: "assistant",
1124
1310
  content: toolUseResult.content,
1125
1311
  toolCalls: [],
@@ -1258,15 +1444,12 @@ function buildTurnsWithStarts(messages) {
1258
1444
  current.toolCalls.push(tc);
1259
1445
  msgToolCalls.push(tc);
1260
1446
  pendingToolUses.set(block.id, { turn: current, index: idx });
1261
- if (block.name === "Task" || block.name === "Agent") {
1447
+ if (isTaskToolName(block.name)) {
1262
1448
  const input = block.input;
1263
1449
  if (input.run_in_background === true) {
1264
1450
  backgroundAgentParentIds.add(block.id);
1265
1451
  }
1266
- taskMetaMap.set(block.id, {
1267
- name: input.name ?? null,
1268
- subagentType: input.subagent_type ?? null
1269
- });
1452
+ taskMetaMap.set(block.id, readTaskMeta(input));
1270
1453
  }
1271
1454
  }
1272
1455
  }
@@ -1277,6 +1460,7 @@ function buildTurnsWithStarts(messages) {
1277
1460
  if (isProgressMessage(msg) && msg.data.type === "agent_progress") {
1278
1461
  const data = msg.data;
1279
1462
  const parentId = msg.parentToolUseID ?? "";
1463
+ const ownToolUseId = data.toolUseId ?? parentId;
1280
1464
  let subAgentUsage = null;
1281
1465
  if (data.message.type === "assistant") {
1282
1466
  const innerMsg = data.message.message;
@@ -1293,12 +1477,14 @@ function buildTurnsWithStarts(messages) {
1293
1477
  }
1294
1478
  }
1295
1479
  const innerModel = data.message.type === "assistant" ? data.message.message.model ?? null : null;
1296
- const taskMeta = taskMetaMap.get(parentId);
1480
+ const taskMeta = taskMetaMap.get(ownToolUseId);
1297
1481
  const agentMsg = {
1298
1482
  agentId: data.agentId,
1299
- parentToolUseId: parentId || void 0,
1483
+ parentToolUseId: ownToolUseId || void 0,
1484
+ ...data.parentAgentId ? { parentAgentId: data.parentAgentId } : {},
1485
+ ...taskMeta?.effort ? { effort: taskMeta.effort } : {},
1300
1486
  agentName: taskMeta?.name ?? null,
1301
- subagentType: taskMeta?.subagentType ?? null,
1487
+ subagentType: taskMeta?.subagentType ?? data.subagentType ?? null,
1302
1488
  type: data.message.type,
1303
1489
  content: data.message.message.content,
1304
1490
  toolCalls: [],
@@ -1318,6 +1504,7 @@ function buildTurnsWithStarts(messages) {
1318
1504
  } else if (block.type === "text") {
1319
1505
  agentMsg.text.push(block.text);
1320
1506
  } else if (block.type === "tool_use") {
1507
+ if (isTaskToolName(block.name)) taskMetaMap.set(block.id, readTaskMeta(block.input));
1321
1508
  agentMsg.toolCalls.push({
1322
1509
  id: block.id,
1323
1510
  name: block.name,
@@ -1410,11 +1597,19 @@ function buildTurns(messages) {
1410
1597
  function isClaudeSessionText() {
1411
1598
  return true;
1412
1599
  }
1600
+ var API_REQUEST_TYPE = '"type":"api-request';
1601
+ var RECORD_TYPE_WINDOW = 256;
1602
+ function isClaudeNoiseLine(line) {
1603
+ if (line.startsWith(`{${API_REQUEST_TYPE}`)) return true;
1604
+ const head = line.slice(0, RECORD_TYPE_WINDOW);
1605
+ const at = head.indexOf(API_REQUEST_TYPE);
1606
+ return at > 0 && head.lastIndexOf("{", at) === 0;
1607
+ }
1413
1608
  function parseRecords(lines) {
1414
1609
  const messages = [];
1415
1610
  for (const line of lines) {
1416
1611
  const trimmed = line.trim();
1417
- if (!trimmed) continue;
1612
+ if (!trimmed || isClaudeNoiseLine(trimmed)) continue;
1418
1613
  try {
1419
1614
  messages.push(JSON.parse(trimmed));
1420
1615
  } catch {
@@ -1519,21 +1714,24 @@ function userMessageTexts(msg) {
1519
1714
  }
1520
1715
  function collectClaudeBackgroundWork(rawMessages) {
1521
1716
  const launches = [];
1522
- const resolved = /* @__PURE__ */ new Set();
1717
+ const resolvedAt = /* @__PURE__ */ new Map();
1523
1718
  const queuedIds = /* @__PURE__ */ new Set();
1524
1719
  const deliveredIds = /* @__PURE__ */ new Set();
1525
- function noteNotifications(text, sink) {
1720
+ function resolve2(id, index) {
1721
+ if (!resolvedAt.has(id)) resolvedAt.set(id, index);
1722
+ }
1723
+ function noteNotifications(text, index, sink) {
1526
1724
  if (!text.includes(TASK_NOTIFICATION_MARKER)) return;
1527
1725
  for (const match of text.matchAll(TASK_ID_RE)) {
1528
- resolved.add(match[1]);
1726
+ resolve2(match[1], index);
1529
1727
  sink?.add(match[1]);
1530
1728
  }
1531
1729
  for (const match of text.matchAll(TOOL_USE_ID_RE)) {
1532
- resolved.add(match[1]);
1730
+ resolve2(match[1], index);
1533
1731
  sink?.add(match[1]);
1534
1732
  }
1535
1733
  }
1536
- for (const msg of rawMessages) {
1734
+ for (const [index, msg] of rawMessages.entries()) {
1537
1735
  if (msg.type === "user") {
1538
1736
  const toolUseResult = isObject(msg.toolUseResult) ? msg.toolUseResult : null;
1539
1737
  if (toolUseResult?.status === "async_launched") {
@@ -1542,9 +1740,11 @@ function collectClaudeBackgroundWork(rawMessages) {
1542
1740
  const toolUseIds = blocks.filter((block) => isObject(block) && block.type === "tool_result").map((block) => block.tool_use_id);
1543
1741
  const ids = [toolUseResult.agentId, toolUseResult.taskId, ...toolUseIds].filter((id) => typeof id === "string" && id.length > 0);
1544
1742
  const description = [toolUseResult.description, toolUseResult.workflowName, toolUseResult.summary].find((value) => typeof value === "string" && value.length > 0) ?? "";
1545
- if (ids.length > 0) launches.push({ ids, description });
1743
+ const toolUseId = toolUseIds.find((id) => typeof id === "string" && id.length > 0);
1744
+ const startedAt = typeof msg.timestamp === "string" ? msg.timestamp : void 0;
1745
+ if (ids.length > 0) launches.push({ ids, launch: { agent: { description, startedAt, toolUseId }, launchedAt: index } });
1546
1746
  }
1547
- for (const text of userMessageTexts(msg)) noteNotifications(text, deliveredIds);
1747
+ for (const text of userMessageTexts(msg)) noteNotifications(text, index, deliveredIds);
1548
1748
  continue;
1549
1749
  }
1550
1750
  if (msg.type === "assistant") {
@@ -1554,33 +1754,28 @@ function collectClaudeBackgroundWork(rawMessages) {
1554
1754
  if (!isObject(block) || block.type !== "tool_use" || block.name !== "TaskStop") continue;
1555
1755
  const input = isObject(block.input) ? block.input : null;
1556
1756
  const taskId = input?.task_id ?? input?.shell_id;
1557
- if (typeof taskId === "string") resolved.add(taskId);
1757
+ if (typeof taskId === "string") resolve2(taskId, index);
1558
1758
  }
1559
1759
  continue;
1560
1760
  }
1561
1761
  if (msg.type === "attachment") {
1562
1762
  const attachment = isObject(msg.attachment) ? msg.attachment : null;
1563
- if (typeof attachment?.prompt === "string") noteNotifications(attachment.prompt, deliveredIds);
1763
+ if (typeof attachment?.prompt === "string") noteNotifications(attachment.prompt, index, deliveredIds);
1564
1764
  continue;
1565
1765
  }
1566
1766
  if (msg.type === "queue-operation" && typeof msg.content === "string") {
1567
1767
  const op = msg.operation;
1568
- noteNotifications(msg.content, op === "enqueue" ? queuedIds : deliveredIds);
1768
+ noteNotifications(msg.content, index, op === "enqueue" ? queuedIds : deliveredIds);
1569
1769
  }
1570
1770
  }
1571
1771
  return {
1572
- pendingDescriptions: launches.filter((launch) => !launch.ids.some((id) => resolved.has(id))).map((launch) => launch.description),
1772
+ launches: launches.map(({ ids, launch }) => {
1773
+ const ends = ids.flatMap((id) => resolvedAt.get(id) ?? []);
1774
+ return ends.length > 0 ? { ...launch, endedAt: Math.min(...ends) } : launch;
1775
+ }),
1573
1776
  undeliveredNotifications: [...queuedIds].filter((id) => !deliveredIds.has(id)).length
1574
1777
  };
1575
1778
  }
1576
- function awaitingAgentsResult(pendingDescriptions, pendingQueue) {
1577
- return {
1578
- status: "awaiting_agents",
1579
- pendingQueue,
1580
- pendingAgents: pendingDescriptions.length,
1581
- pendingAgentDescriptions: pendingDescriptions.filter((description) => description.length > 0)
1582
- };
1583
- }
1584
1779
  function deriveClaudeSessionStatus(rawMessages) {
1585
1780
  let pendingEnqueues = 0;
1586
1781
  let backgroundWork = null;
@@ -1626,9 +1821,8 @@ function deriveClaudeSessionStatus(rawMessages) {
1626
1821
  if (stopReason === "end_turn") {
1627
1822
  const work = getBackgroundWork();
1628
1823
  if (deliveringNotification || work.undeliveredNotifications > 0) return result("processing");
1629
- if (work.pendingDescriptions.length > 0) {
1630
- return awaitingAgentsResult(work.pendingDescriptions, Math.max(0, pendingEnqueues));
1631
- }
1824
+ const awaiting = awaitingAgentsStatus(work.launches, Math.max(0, pendingEnqueues));
1825
+ if (awaiting) return awaiting;
1632
1826
  let hasActivity = false;
1633
1827
  for (let j = i - 1; j >= 0; j--) {
1634
1828
  const m = rawMessages[j];
@@ -2016,9 +2210,60 @@ function safeParseLine(line) {
2016
2210
  function isObject3(value) {
2017
2211
  return typeof value === "object" && value !== null;
2018
2212
  }
2019
- function isCodexRecord(record) {
2020
- if (!record || typeof record.type !== "string") return false;
2021
- return record.type === "session_meta" || record.type === "turn_context" || record.type === "event_msg" || record.type === "response_item" || record.type === "inter_agent_communication_metadata" || record.type === "compacted" || record.type === "world_state";
2213
+ function codexParentId(payload) {
2214
+ const source = isObject3(payload.source) ? payload.source : null;
2215
+ const subagent = source && isObject3(source.subagent) ? source.subagent : null;
2216
+ const threadSpawn = subagent && isObject3(subagent.thread_spawn) ? subagent.thread_spawn : null;
2217
+ for (const candidate of [payload.forked_from_id, payload.parent_thread_id, threadSpawn?.parent_thread_id]) {
2218
+ if (typeof candidate === "string" && candidate) return candidate;
2219
+ }
2220
+ return null;
2221
+ }
2222
+ function inheritedHistoryFilter(records) {
2223
+ const meta = records.find((record2) => record2?.type === "session_meta");
2224
+ const start = meta?.payload?.subagent_history_start_ordinal;
2225
+ if (typeof start !== "number") return null;
2226
+ const reachesPast = (ordinal) => typeof ordinal === "number" && ordinal >= start;
2227
+ if (!reachesPast(meta?.rolloutLastOrdinal) && !records.some((record2) => reachesPast(record2?.ordinal))) return null;
2228
+ return (record2) => typeof record2.ordinal === "number" && record2.ordinal > 0 && record2.ordinal < start;
2229
+ }
2230
+ async function codexPageHeaderLine(firstLine, lastLines) {
2231
+ if (!firstLine.includes('"subagent_history_start_ordinal"')) return firstLine;
2232
+ const meta = safeParseLine(firstLine);
2233
+ if (meta?.type !== "session_meta") return firstLine;
2234
+ const lines = await lastLines();
2235
+ for (let index = lines.length - 1; index >= 0; index--) {
2236
+ const ordinal = safeParseLine(lines[index])?.ordinal;
2237
+ if (typeof ordinal === "number") return JSON.stringify({ ...meta, rolloutLastOrdinal: ordinal });
2238
+ }
2239
+ return firstLine;
2240
+ }
2241
+ function subAgentActivitySource(record2) {
2242
+ const payload = record2.payload;
2243
+ if (record2.type !== "event_msg" || !isObject3(payload)) return null;
2244
+ if (payload.type === "sub_agent_activity") return payload;
2245
+ if (payload.type === "item_completed" && isObject3(payload.item) && payload.item.type === "SubAgentActivity") return payload.item;
2246
+ return null;
2247
+ }
2248
+ function readSubAgentActivity(record2) {
2249
+ const source = subAgentActivitySource(record2);
2250
+ if (!source || typeof source.agent_thread_id !== "string" || typeof source.agent_path !== "string") return null;
2251
+ return {
2252
+ agentId: source.agent_thread_id,
2253
+ agentPath: source.agent_path,
2254
+ kind: typeof source.kind === "string" ? source.kind : "started",
2255
+ eventId: findString(source.event_id, source.id) ?? "",
2256
+ model: findString(source.model) || null,
2257
+ effort: findString(source.reasoning_effort) || null
2258
+ };
2259
+ }
2260
+ function turnErrorMessage(payload) {
2261
+ if (payload.type !== "task_complete" || !isObject3(payload.error)) return "";
2262
+ return typeof payload.error.message === "string" ? payload.error.message.trim() : "";
2263
+ }
2264
+ function isCodexRecord(record2) {
2265
+ if (!record2 || typeof record2.type !== "string") return false;
2266
+ return record2.type === "session_meta" || record2.type === "turn_context" || record2.type === "event_msg" || record2.type === "response_item" || record2.type === "inter_agent_communication_metadata" || record2.type === "compacted" || record2.type === "world_state";
2022
2267
  }
2023
2268
  function extractMessageText(payload, blockType) {
2024
2269
  const content = payload?.content;
@@ -2213,22 +2458,39 @@ function createTurn2(turnId, timestamp, model) {
2213
2458
  model
2214
2459
  };
2215
2460
  }
2216
- function extractPromptFromRecord(record) {
2217
- if (record.type === "event_msg" && isObject3(record.payload) && record.payload.type === "user_message" && typeof record.payload.message === "string") {
2218
- return normalizePromptText(record.payload.message);
2461
+ function codexPromptText(record2) {
2462
+ const payload = isObject3(record2.payload) ? record2.payload : null;
2463
+ if (record2.type === "event_msg" && payload?.type === "user_message" && typeof payload.message === "string") {
2464
+ return normalizePromptText(payload.message);
2219
2465
  }
2220
- if (record.type === "response_item" && isObject3(record.payload) && record.payload.type === "message" && record.payload.role === "user") {
2221
- return normalizePromptText(extractMessageText(record.payload, "input_text"));
2466
+ if (record2.type === "response_item" && payload?.type === "message" && payload.role === "user") {
2467
+ return normalizePromptText(extractMessageText(payload, "input_text"));
2222
2468
  }
2223
2469
  return "";
2224
2470
  }
2225
- function recordOpensTurn(record, payload) {
2226
- if (record.type === "session_meta") return false;
2227
- if (record.type === "event_msg" && payload?.type === "task_started") return false;
2228
- if (record.type === "response_item" && payload?.type === "message") {
2471
+ function createCodexPromptReader() {
2472
+ let echoPending = false;
2473
+ return (record2) => {
2474
+ const payload = isObject3(record2.payload) ? record2.payload : null;
2475
+ if (record2.type === "event_msg" && payload?.type === "user_message") {
2476
+ const isEcho = echoPending;
2477
+ echoPending = false;
2478
+ return isEcho ? "" : codexPromptText(record2);
2479
+ }
2480
+ if (record2.type !== "response_item") return "";
2481
+ const prompt = codexPromptText(record2);
2482
+ if (prompt) echoPending = true;
2483
+ else if (payload?.type !== "message" || payload.role !== "user") echoPending = false;
2484
+ return prompt;
2485
+ };
2486
+ }
2487
+ function recordOpensTurn(record2, payload) {
2488
+ if (record2.type === "session_meta") return false;
2489
+ if (record2.type === "event_msg" && payload?.type === "task_started") return false;
2490
+ if (record2.type === "response_item" && payload?.type === "message") {
2229
2491
  if (payload.role === "developer" || payload.role === "system") return false;
2230
2492
  if (payload.role === "user") {
2231
- return extractPromptFromRecord(record) !== "" || extractResponseMessageImages(payload).length > 0 || extractResponseMessageAudio(payload).length > 0;
2493
+ return codexPromptText(record2) !== "" || extractResponseMessageImages(payload).length > 0 || extractResponseMessageAudio(payload).length > 0;
2232
2494
  }
2233
2495
  }
2234
2496
  return true;
@@ -2248,23 +2510,24 @@ function extractMetadataFromRecords(records) {
2248
2510
  let isSubagent = false;
2249
2511
  let parentSessionId = null;
2250
2512
  let agentPath = "/root";
2251
- let previousPrompt = "";
2252
- for (const record of records) {
2253
- if (!isObject3(record.payload)) continue;
2254
- if (record.type === "session_meta") {
2255
- sessionId ||= typeof record.payload.id === "string" ? record.payload.id : "";
2256
- version ||= typeof record.payload.cli_version === "string" ? record.payload.cli_version : "";
2257
- cwd ||= typeof record.payload.cwd === "string" ? record.payload.cwd : "";
2258
- if (!branchedFrom && isObject3(record.payload.branchedFrom)) {
2259
- const sourceId = typeof record.payload.branchedFrom.sessionId === "string" ? record.payload.branchedFrom.sessionId : "";
2513
+ const readPrompt = createCodexPromptReader();
2514
+ const isInherited = inheritedHistoryFilter(records);
2515
+ for (const record2 of records) {
2516
+ if (!isObject3(record2.payload) || isInherited?.(record2)) continue;
2517
+ if (record2.type === "session_meta") {
2518
+ sessionId ||= typeof record2.payload.id === "string" ? record2.payload.id : "";
2519
+ version ||= typeof record2.payload.cli_version === "string" ? record2.payload.cli_version : "";
2520
+ cwd ||= typeof record2.payload.cwd === "string" ? record2.payload.cwd : "";
2521
+ if (!branchedFrom && isObject3(record2.payload.branchedFrom)) {
2522
+ const sourceId = typeof record2.payload.branchedFrom.sessionId === "string" ? record2.payload.branchedFrom.sessionId : "";
2260
2523
  if (sourceId) {
2261
2524
  branchedFrom = {
2262
2525
  sessionId: sourceId,
2263
- turnIndex: typeof record.payload.branchedFrom.turnIndex === "number" ? record.payload.branchedFrom.turnIndex : null
2526
+ turnIndex: typeof record2.payload.branchedFrom.turnIndex === "number" ? record2.payload.branchedFrom.turnIndex : null
2264
2527
  };
2265
2528
  }
2266
2529
  }
2267
- const source = isObject3(record.payload.source) ? record.payload.source : null;
2530
+ const source = isObject3(record2.payload.source) ? record2.payload.source : null;
2268
2531
  if (source && isObject3(source.subagent)) {
2269
2532
  isSubagent = true;
2270
2533
  const threadSpawn = isObject3(source.subagent.thread_spawn) ? source.subagent.thread_spawn : null;
@@ -2272,25 +2535,21 @@ function extractMetadataFromRecords(records) {
2272
2535
  agentPath = threadSpawn.agent_path;
2273
2536
  }
2274
2537
  }
2275
- if (typeof record.payload.forked_from_id === "string" && record.payload.forked_from_id) {
2276
- parentSessionId = record.payload.forked_from_id;
2277
- }
2278
- const git = isObject3(record.payload.git) ? record.payload.git : null;
2538
+ parentSessionId = codexParentId(record2.payload) ?? parentSessionId;
2539
+ const git = isObject3(record2.payload.git) ? record2.payload.git : null;
2279
2540
  gitBranch ||= git && typeof git.branch === "string" ? git.branch : "";
2280
2541
  }
2281
- if (record.type === "turn_context") {
2282
- model ||= typeof record.payload.model === "string" ? record.payload.model : "";
2283
- cwd ||= typeof record.payload.cwd === "string" ? record.payload.cwd : "";
2542
+ if (record2.type === "turn_context") {
2543
+ model ||= typeof record2.payload.model === "string" ? record2.payload.model : "";
2544
+ cwd ||= typeof record2.payload.cwd === "string" ? record2.payload.cwd : "";
2284
2545
  }
2285
- const prompt = extractPromptFromRecord(record);
2546
+ const prompt = readPrompt(record2);
2286
2547
  if (!prompt) continue;
2287
- if (prompt === previousPrompt) continue;
2288
2548
  if (!firstUserMessage) firstUserMessage = prompt;
2289
2549
  lastUserMessage = prompt;
2290
- previousPrompt = prompt;
2291
2550
  turnCount++;
2292
- if (!timestamp) timestamp = record.timestamp ?? "";
2293
- lastTimestamp = record.timestamp ?? lastTimestamp;
2551
+ if (!timestamp) timestamp = record2.timestamp ?? "";
2552
+ lastTimestamp = record2.timestamp ?? lastTimestamp;
2294
2553
  }
2295
2554
  if (lastTimestamp === "") lastTimestamp = timestamp;
2296
2555
  return {
@@ -2357,6 +2616,7 @@ function walkCodexRecords(records, options) {
2357
2616
  timestamp: info?.timestamp ?? eventTimestamp2,
2358
2617
  tokenUsage: null,
2359
2618
  model: info?.model ?? null,
2619
+ ...info?.effort ? { effort: info.effort } : {},
2360
2620
  isBackground: false,
2361
2621
  prompt: info?.message || void 0,
2362
2622
  status: update.status ?? "running"
@@ -2377,6 +2637,7 @@ function walkCodexRecords(records, options) {
2377
2637
  agentMessage.agentName = info.nickname ?? (info.agentPath ? agentNameFromPath(info.agentPath) : agentMessage.agentName);
2378
2638
  agentMessage.subagentType = info.agentType;
2379
2639
  agentMessage.model = info.model;
2640
+ if (info.effort) agentMessage.effort = info.effort;
2380
2641
  agentMessage.prompt = info.message || agentMessage.prompt;
2381
2642
  }
2382
2643
  if (update.text && !agentMessage.text.includes(update.text)) {
@@ -2447,20 +2708,21 @@ function walkCodexRecords(records, options) {
2447
2708
  webSearchCalls.set(id, toolCall);
2448
2709
  appendToolCall(targetTurn, toolCall, timestamp);
2449
2710
  }
2711
+ const isInherited = inheritedHistoryFilter(records);
2450
2712
  for (let index = 0; index < records.length; index++) {
2451
- const record = records[index];
2452
- if (!isCodexRecord(record)) continue;
2713
+ const record2 = records[index];
2714
+ if (!isCodexRecord(record2) || isInherited?.(record2)) continue;
2453
2715
  recordIndex = index;
2454
- const payload = isObject3(record.payload) ? record.payload : void 0;
2455
- const timestamp = record.timestamp ?? "";
2456
- if (record.type === "compacted") {
2716
+ const payload = isObject3(record2.payload) ? record2.payload : void 0;
2717
+ const timestamp = record2.timestamp ?? "";
2718
+ if (record2.type === "compacted") {
2457
2719
  current = commitTurn(current);
2458
2720
  pendingCompaction = "Conversation compacted";
2459
2721
  lastTurnTimestamp = timestamp;
2460
2722
  continue;
2461
2723
  }
2462
- if (record.type === "world_state") continue;
2463
- if (record.type === "turn_context") {
2724
+ if (record2.type === "world_state") continue;
2725
+ if (record2.type === "turn_context") {
2464
2726
  current = commitTurn(current);
2465
2727
  pendingContextIndex = index;
2466
2728
  currentTurnId = typeof payload?.turn_id === "string" ? payload.turn_id : null;
@@ -2469,7 +2731,7 @@ function walkCodexRecords(records, options) {
2469
2731
  sawTurnStart = true;
2470
2732
  continue;
2471
2733
  }
2472
- if (record.type === "event_msg" && payload?.type === "user_message" && typeof payload.message === "string") {
2734
+ if (record2.type === "event_msg" && payload?.type === "user_message" && typeof payload.message === "string") {
2473
2735
  if (current && (current.assistantText.length > 0 || current.toolCalls.length > 0 || current.thinking.length > 0)) {
2474
2736
  current = commitTurn(current);
2475
2737
  }
@@ -2493,12 +2755,12 @@ function walkCodexRecords(records, options) {
2493
2755
  lastTurnTimestamp = timestamp;
2494
2756
  continue;
2495
2757
  }
2496
- if (!current && !recordOpensTurn(record, payload)) continue;
2758
+ if (!current && !recordOpensTurn(record2, payload)) continue;
2497
2759
  current ??= createActiveTurn(currentTurnId, timestamp, currentModel);
2498
2760
  if (!current.model && currentModel) current.model = currentModel;
2499
2761
  if (!current.timestamp) current.timestamp = timestamp;
2500
2762
  if (timestamp) lastTurnTimestamp = timestamp;
2501
- if (record.type === "event_msg" && payload?.type === "token_count") {
2763
+ if (record2.type === "event_msg" && payload?.type === "token_count") {
2502
2764
  const info = isObject3(payload.info) ? payload.info : null;
2503
2765
  const lastUsage = info ? parseTokenUsage(info.last_token_usage) : null;
2504
2766
  if (lastUsage) {
@@ -2506,14 +2768,14 @@ function walkCodexRecords(records, options) {
2506
2768
  }
2507
2769
  continue;
2508
2770
  }
2509
- if (record.type === "event_msg" && payload?.type === "web_search_end" && typeof payload.call_id === "string") {
2771
+ if (record2.type === "event_msg" && payload?.type === "web_search_end" && typeof payload.call_id === "string") {
2510
2772
  const input = {};
2511
2773
  if (typeof payload.query === "string" && payload.query) input.query = payload.query;
2512
2774
  if (isObject3(payload.action)) input.action = payload.action;
2513
2775
  upsertWebSearchCall(current, payload.call_id, input, "completed", timestamp);
2514
2776
  continue;
2515
2777
  }
2516
- if (record.type === "event_msg" && payload?.type === "mcp_tool_call_end" && typeof payload.call_id === "string" && isObject3(payload.invocation)) {
2778
+ if (record2.type === "event_msg" && payload?.type === "mcp_tool_call_end" && typeof payload.call_id === "string" && isObject3(payload.invocation)) {
2517
2779
  const invocation = payload.invocation;
2518
2780
  const server = typeof invocation.server === "string" ? invocation.server : "mcp";
2519
2781
  const tool = typeof invocation.tool === "string" ? invocation.tool : "tool";
@@ -2538,12 +2800,18 @@ function walkCodexRecords(records, options) {
2538
2800
  }
2539
2801
  continue;
2540
2802
  }
2541
- if (record.type === "event_msg" && payload?.type === "sub_agent_activity" && typeof payload.agent_thread_id === "string" && typeof payload.agent_path === "string") {
2542
- const agentId = payload.agent_thread_id;
2543
- const eventId2 = typeof payload.event_id === "string" ? payload.event_id : "";
2544
- const kind = typeof payload.kind === "string" ? payload.kind : "started";
2803
+ if (record2.type === "event_msg" && payload) {
2804
+ const turnError = turnErrorMessage(payload);
2805
+ if (turnError) {
2806
+ appendAssistantText(current, turnError, timestamp);
2807
+ continue;
2808
+ }
2809
+ }
2810
+ const activity = readSubAgentActivity(record2);
2811
+ if (activity) {
2812
+ const { agentId, agentPath, eventId: eventId2, kind } = activity;
2545
2813
  const spawnInfo = eventId2 ? spawnAgentCalls.get(eventId2) : void 0;
2546
- const existingId = agentIdByPath.get(payload.agent_path);
2814
+ const existingId = agentIdByPath.get(agentPath);
2547
2815
  const existing = agentRegistry.get(agentId) ?? (existingId ? agentRegistry.get(existingId) : void 0);
2548
2816
  if (kind !== "started" && !existing && !spawnInfo) continue;
2549
2817
  if (existingId && existingId !== agentId && !agentMessages.has(agentId)) {
@@ -2557,22 +2825,23 @@ function walkCodexRecords(records, options) {
2557
2825
  }
2558
2826
  const info = {
2559
2827
  agentId,
2560
- nickname: existing?.nickname ?? agentNameFromPath(payload.agent_path) ?? spawnInfo?.taskName ?? null,
2561
- agentPath: payload.agent_path,
2828
+ nickname: existing?.nickname ?? agentNameFromPath(agentPath) ?? spawnInfo?.taskName ?? null,
2829
+ agentPath,
2562
2830
  message: existing?.message ?? spawnInfo?.message ?? "",
2563
- model: existing?.model ?? spawnInfo?.model ?? null,
2831
+ model: activity.model ?? existing?.model ?? spawnInfo?.model ?? null,
2832
+ effort: activity.effort ?? existing?.effort ?? null,
2564
2833
  agentType: existing?.agentType ?? spawnInfo?.agentType ?? null,
2565
2834
  timestamp: existing?.timestamp ?? (timestamp || spawnInfo?.timestamp || ""),
2566
2835
  parentToolCallId: existing?.parentToolCallId ?? eventId2
2567
2836
  };
2568
2837
  agentRegistry.set(agentId, info);
2569
- agentIdByPath.set(payload.agent_path, agentId);
2838
+ agentIdByPath.set(agentPath, agentId);
2570
2839
  if (eventId2 && (kind === "started" || spawnInfo)) agentIdBySpawnCall.set(eventId2, agentId);
2571
- const status = kind === "interrupted" ? "interrupted" : "running";
2840
+ const status = kind === "interrupted" || kind === "completed" ? kind : "running";
2572
2841
  upsertAgentMessage(agentId, current, timestamp, { status });
2573
2842
  continue;
2574
2843
  }
2575
- if (record.type !== "response_item" || !payload) continue;
2844
+ if (record2.type !== "response_item" || !payload) continue;
2576
2845
  if (payload.type === "reasoning") {
2577
2846
  const summary = Array.isArray(payload.summary) ? payload.summary.filter((item) => typeof item === "string").join("\n") : "";
2578
2847
  appendThinking(current, summary.trim(), timestamp);
@@ -2724,6 +2993,7 @@ function walkCodexRecords(records, options) {
2724
2993
  agentPath: agentPath ?? existing?.agentPath ?? null,
2725
2994
  message: existing?.message ?? spawnInfo?.message ?? "",
2726
2995
  model: existing?.model ?? spawnInfo?.model ?? null,
2996
+ effort: existing?.effort ?? null,
2727
2997
  agentType: existing?.agentType ?? spawnInfo?.agentType ?? null,
2728
2998
  timestamp: existing?.timestamp ?? spawnInfo?.timestamp ?? timestamp,
2729
2999
  parentToolCallId: existing?.parentToolCallId ?? toolCall.id
@@ -2842,14 +3112,16 @@ function walkCodexRecords(records, options) {
2842
3112
  }
2843
3113
  function parseCodexSession(jsonlText, options) {
2844
3114
  const records = jsonlText.split("\n").map((line) => line.trim()).filter(Boolean).map(safeParseLine).filter(isCodexRecord);
3115
+ const isInherited = inheritedHistoryFilter(records);
3116
+ const ownRecords = isInherited ? records.filter((record2) => !isInherited(record2)) : records;
2845
3117
  const { turnStartIndices: _starts, ...session } = walkCodexRecords(
2846
- records,
3118
+ ownRecords,
2847
3119
  options
2848
3120
  );
2849
3121
  return session;
2850
3122
  }
2851
3123
  function appendCodexSession(existing, newJsonlText) {
2852
- const prefix = existing.rawMessages.map((record) => JSON.stringify(record)).join("\n");
3124
+ const prefix = existing.rawMessages.map((record2) => JSON.stringify(record2)).join("\n");
2853
3125
  return parseCodexSession(prefix ? `${prefix}
2854
3126
  ${newJsonlText}` : newJsonlText);
2855
3127
  }
@@ -2868,40 +3140,48 @@ function parseJsonObject(value) {
2868
3140
  return null;
2869
3141
  }
2870
3142
  }
2871
- function collectCodexPendingAgents(rawMessages) {
2872
- const alive = /* @__PURE__ */ new Map();
2873
- const done = /* @__PURE__ */ new Set();
3143
+ function collectCodexBackgroundAgents(rawMessages) {
3144
+ const launched = /* @__PURE__ */ new Map();
3145
+ const alive = /* @__PURE__ */ new Set();
3146
+ const endedAt = /* @__PURE__ */ new Map();
2874
3147
  const agentIdByPath = /* @__PURE__ */ new Map();
2875
3148
  const spawnCalls = /* @__PURE__ */ new Map();
2876
3149
  const waitCalls = /* @__PURE__ */ new Set();
2877
3150
  const interruptCalls = /* @__PURE__ */ new Map();
2878
- function markAlive(agentId, description) {
2879
- if (!done.has(agentId)) alive.set(agentId, alive.get(agentId) || description);
2880
- }
2881
- for (const msg of rawMessages) {
3151
+ function markAlive(agentId, description, index, startedAt) {
3152
+ if (endedAt.has(agentId)) return;
3153
+ alive.add(agentId);
3154
+ const launch = launched.get(agentId);
3155
+ if (!launch) launched.set(agentId, { launchedAt: index, description, startedAt });
3156
+ else if (!launch.description) launch.description = description;
3157
+ }
3158
+ function markEnded(agentId, index) {
3159
+ if (!endedAt.has(agentId)) endedAt.set(agentId, index);
3160
+ alive.delete(agentId);
3161
+ }
3162
+ for (const [index, msg] of rawMessages.entries()) {
2882
3163
  const payload = isObject3(msg.payload) ? msg.payload : null;
2883
3164
  if (!payload) continue;
2884
- if (msg.type === "event_msg" && payload.type === "sub_agent_activity" && typeof payload.agent_thread_id === "string" && typeof payload.agent_path === "string") {
2885
- const agentId = payload.agent_thread_id;
2886
- const kind = typeof payload.kind === "string" ? payload.kind : "started";
2887
- const eventId2 = typeof payload.event_id === "string" ? payload.event_id : "";
2888
- const existingId = agentIdByPath.get(payload.agent_path);
2889
- const known = alive.has(agentId) || done.has(agentId) || existingId !== void 0 || spawnCalls.has(eventId2);
3165
+ const timestamp = typeof msg.timestamp === "string" ? msg.timestamp : void 0;
3166
+ const activity = readSubAgentActivity(msg);
3167
+ if (activity) {
3168
+ const { agentId, agentPath, kind, eventId: eventId2 } = activity;
3169
+ const existingId = agentIdByPath.get(agentPath);
3170
+ const known = alive.has(agentId) || endedAt.has(agentId) || existingId !== void 0 || spawnCalls.has(eventId2);
2890
3171
  if (kind !== "started" && !known) continue;
2891
3172
  if (existingId && existingId !== agentId) {
2892
- if (alive.has(existingId)) {
2893
- markAlive(agentId, alive.get(existingId) ?? "");
2894
- alive.delete(existingId);
2895
- }
2896
- if (done.has(existingId)) done.add(agentId);
2897
- }
2898
- agentIdByPath.set(payload.agent_path, agentId);
2899
- if (kind === "interrupted") {
2900
- done.add(agentId);
2901
- alive.delete(agentId);
2902
- } else {
2903
- markAlive(agentId, spawnCalls.get(eventId2) ?? "");
3173
+ const prior = launched.get(existingId);
3174
+ launched.delete(existingId);
3175
+ const current = launched.get(agentId);
3176
+ if (prior && !current) launched.set(agentId, prior);
3177
+ else if (prior && current && !current.description) current.description = prior.description;
3178
+ if (alive.delete(existingId)) markAlive(agentId, "", index, timestamp);
3179
+ const priorEnd = endedAt.get(existingId);
3180
+ if (priorEnd !== void 0) markEnded(agentId, priorEnd);
2904
3181
  }
3182
+ agentIdByPath.set(agentPath, agentId);
3183
+ if (kind === "interrupted" || kind === "completed") markEnded(agentId, index);
3184
+ else markAlive(agentId, spawnCalls.get(eventId2) ?? "", index, timestamp);
2905
3185
  continue;
2906
3186
  }
2907
3187
  if (msg.type !== "response_item") continue;
@@ -2925,7 +3205,7 @@ function collectCodexPendingAgents(rawMessages) {
2925
3205
  const output = parseJsonObject(payload.output);
2926
3206
  const agentId = typeof output?.agent_id === "string" ? output.agent_id : "";
2927
3207
  if (agentId) {
2928
- markAlive(agentId, spawnCalls.get(callId) ?? "");
3208
+ markAlive(agentId, spawnCalls.get(callId) ?? "", index, timestamp);
2929
3209
  const agentPath = typeof output?.task_name === "string" ? output.task_name : "";
2930
3210
  if (agentPath && !agentIdByPath.has(agentPath)) agentIdByPath.set(agentPath, agentId);
2931
3211
  }
@@ -2936,16 +3216,10 @@ function collectCodexPendingAgents(rawMessages) {
2936
3216
  const statusValue = isObject3(status) ? status : {};
2937
3217
  const lifecycle = typeof statusValue.status === "string" ? statusValue.status : "";
2938
3218
  const isTerminal = typeof statusValue.completed === "string" || typeof statusValue.failed === "string" || typeof statusValue.error === "string" || typeof statusValue.interrupted === "string" || lifecycle === "completed" || lifecycle === "failed" || lifecycle === "interrupted";
2939
- if (isTerminal) {
2940
- done.add(agentId);
2941
- alive.delete(agentId);
2942
- }
3219
+ if (isTerminal) markEnded(agentId, index);
2943
3220
  }
2944
3221
  } else if (interruptCalls.has(callId)) {
2945
- for (const agentId of interruptCalls.get(callId) ?? []) {
2946
- done.add(agentId);
2947
- alive.delete(agentId);
2948
- }
3222
+ for (const agentId of interruptCalls.get(callId) ?? []) markEnded(agentId, index);
2949
3223
  }
2950
3224
  continue;
2951
3225
  }
@@ -2953,12 +3227,14 @@ function collectCodexPendingAgents(rawMessages) {
2953
3227
  const text = codexPayloadText(payload);
2954
3228
  const messageType = text.match(/^Message Type:\s*([^\r\n]+)/)?.[1]?.trim().toUpperCase() ?? "";
2955
3229
  if (!TERMINAL_INTER_AGENT_TYPES.has(messageType)) continue;
2956
- const agentId = agentIdByPath.get(payload.author) ?? payload.author;
2957
- done.add(agentId);
2958
- alive.delete(agentId);
3230
+ markEnded(agentIdByPath.get(payload.author) ?? payload.author, index);
2959
3231
  }
2960
3232
  }
2961
- return [...alive.entries()].filter(([agentId]) => !done.has(agentId)).map(([, description]) => description);
3233
+ return [...launched.entries()].map(([agentId, { description, startedAt, launchedAt }]) => ({
3234
+ agent: { description, startedAt },
3235
+ launchedAt,
3236
+ endedAt: alive.has(agentId) ? void 0 : endedAt.get(agentId) ?? launchedAt
3237
+ }));
2962
3238
  }
2963
3239
  function deriveCodexSessionStatus(rawMessages) {
2964
3240
  for (let i = rawMessages.length - 1; i >= 0; i--) {
@@ -2967,16 +3243,7 @@ function deriveCodexSessionStatus(rawMessages) {
2967
3243
  const payload = msg.payload;
2968
3244
  switch (payload?.type) {
2969
3245
  case "task_complete": {
2970
- const pending = collectCodexPendingAgents(rawMessages);
2971
- if (pending.length > 0) {
2972
- return {
2973
- status: "awaiting_agents",
2974
- pendingQueue: 0,
2975
- pendingAgents: pending.length,
2976
- pendingAgentDescriptions: pending.filter((description) => description.length > 0)
2977
- };
2978
- }
2979
- return { status: "completed" };
3246
+ return awaitingAgentsStatus(collectCodexBackgroundAgents(rawMessages)) ?? { status: "completed" };
2980
3247
  }
2981
3248
  case "task_started":
2982
3249
  return { status: "processing" };
@@ -3000,11 +3267,11 @@ function deriveCodexSessionStatus(rawMessages) {
3000
3267
  }
3001
3268
  return { status: "idle" };
3002
3269
  }
3003
- function brandCodexBranch(firstRecord, sessionId, turnIndex) {
3270
+ function brandCodexBranch(firstRecord, sessionId, turnIndex, branchedAt) {
3004
3271
  const payload = isObject3(firstRecord.payload) ? { ...firstRecord.payload } : {};
3005
3272
  const originalId = typeof payload.id === "string" ? payload.id : "";
3006
3273
  payload.id = sessionId;
3007
- payload.branchedFrom = { sessionId: originalId, turnIndex };
3274
+ payload.branchedFrom = { sessionId: originalId, turnIndex, at: new Date(branchedAt).toISOString() };
3008
3275
  return { record: { ...firstRecord, payload }, originalId };
3009
3276
  }
3010
3277
  function codexTurnBoundaries(records) {
@@ -3766,7 +4033,7 @@ function parseCopilotSession(jsonlText, options) {
3766
4033
  };
3767
4034
  }
3768
4035
  function appendCopilotSession(existing, newJsonlText) {
3769
- const prefix = existing.rawMessages.map((record) => JSON.stringify(record)).join("\n");
4036
+ const prefix = existing.rawMessages.map((record2) => JSON.stringify(record2)).join("\n");
3770
4037
  return parseCopilotSession(prefix ? `${prefix}
3771
4038
  ${newJsonlText}` : newJsonlText);
3772
4039
  }
@@ -3774,33 +4041,32 @@ function isCopilotEventType(type) {
3774
4041
  return typeof type === "string" && (type === "abort" || type === "binary_asset" || type === "user.message" || type.startsWith("assistant.") || type.startsWith("permission.") || type.startsWith("session.") || type.startsWith("subagent.") || type.startsWith("tool.") || type.startsWith("user_input."));
3775
4042
  }
3776
4043
  function deriveCopilotSessionStatus(rawMessages) {
3777
- const pendingAgents = /* @__PURE__ */ new Map();
3778
- for (const event of rawMessages) {
4044
+ const agents = /* @__PURE__ */ new Map();
4045
+ for (const [index, event] of rawMessages.entries()) {
3779
4046
  const agentId = typeof event.agentId === "string" ? event.agentId : "";
3780
4047
  if (!agentId && (event.type === "abort" || event.type === "session.shutdown" || event.type === "session.error")) {
3781
- pendingAgents.clear();
4048
+ agents.clear();
3782
4049
  continue;
3783
4050
  }
3784
4051
  if (!agentId || !event.type.startsWith("subagent.")) continue;
3785
4052
  const data = isObject4(event.data) ? event.data : {};
4053
+ const launch = agents.get(agentId);
3786
4054
  if (event.type === "subagent.completed" || event.type === "subagent.failed") {
3787
- pendingAgents.delete(agentId);
4055
+ if (launch) launch.endedAt ??= index;
3788
4056
  continue;
3789
4057
  }
3790
4058
  if (event.type === "subagent.started" || event.type === "subagent.configured") {
3791
4059
  const description = [data.agentDisplayName, data.description, data.agentName].find((value) => typeof value === "string") ?? "";
3792
- pendingAgents.set(agentId, description || pendingAgents.get(agentId) || "");
4060
+ if (!launch || launch.endedAt !== void 0) {
4061
+ const startedAt = typeof event.timestamp === "string" ? event.timestamp : void 0;
4062
+ agents.set(agentId, { agent: { description, startedAt }, launchedAt: index });
4063
+ } else if (description) {
4064
+ launch.agent.description = description;
4065
+ }
3793
4066
  }
3794
4067
  }
3795
- if (pendingAgents.size > 0) {
3796
- const descriptions = [...pendingAgents.values()];
3797
- return {
3798
- status: "awaiting_agents",
3799
- pendingQueue: 0,
3800
- pendingAgents: descriptions.length,
3801
- pendingAgentDescriptions: descriptions.filter((description) => description.length > 0)
3802
- };
3803
- }
4068
+ const awaiting = awaitingAgentsStatus([...agents.values()]);
4069
+ if (awaiting) return awaiting;
3804
4070
  let sawUserActivity = false;
3805
4071
  const completedPermissionRequests = /* @__PURE__ */ new Set();
3806
4072
  for (let i = rawMessages.length - 1; i >= 0; i--) {
@@ -3874,11 +4140,11 @@ function brandCopilotBranch() {
3874
4140
  function copilotTurnBoundaries(records) {
3875
4141
  const boundaries = [];
3876
4142
  for (let index = 0; index < records.length; index++) {
3877
- const record = records[index];
3878
- if (record.type !== "user.message" || typeof record.agentId === "string") continue;
3879
- const data = record.data;
4143
+ const record2 = records[index];
4144
+ if (record2.type !== "user.message" || typeof record2.agentId === "string") continue;
4145
+ const data = record2.data;
3880
4146
  if (!data || typeof data !== "object" || Array.isArray(data)) continue;
3881
- if (typeof record.id !== "string" || !record.id) continue;
4147
+ if (typeof record2.id !== "string" || !record2.id) continue;
3882
4148
  boundaries.push(index);
3883
4149
  }
3884
4150
  return boundaries;
@@ -3886,6 +4152,7 @@ function copilotTurnBoundaries(records) {
3886
4152
 
3887
4153
  // src/lib/agents.ts
3888
4154
  var TERMINAL_AGENT_KIND = AGENT_KINDS[AGENT_KINDS.length - 1];
4155
+ var hasNoNoiseLines = () => false;
3889
4156
  var codexFormat = {
3890
4157
  kind: "codex",
3891
4158
  descriptor: descriptorFor("codex"),
@@ -3895,6 +4162,8 @@ var codexFormat = {
3895
4162
  append: appendCodexSession,
3896
4163
  metadataFromLines: extractCodexMetadataFromLines,
3897
4164
  status: deriveCodexSessionStatus,
4165
+ isNoiseLine: hasNoNoiseLines,
4166
+ pageHeaderLine: codexPageHeaderLine,
3898
4167
  brandBranch: brandCodexBranch,
3899
4168
  turnBoundaries: codexTurnBoundaries
3900
4169
  };
@@ -3907,6 +4176,7 @@ var copilotFormat = {
3907
4176
  append: appendCopilotSession,
3908
4177
  metadataFromLines: extractCopilotMetadataFromLines,
3909
4178
  status: deriveCopilotSessionStatus,
4179
+ isNoiseLine: hasNoNoiseLines,
3910
4180
  brandBranch: brandCopilotBranch,
3911
4181
  turnBoundaries: copilotTurnBoundaries
3912
4182
  };
@@ -3920,10 +4190,20 @@ var claudeFormat = {
3920
4190
  append: appendClaudeSession,
3921
4191
  metadataFromLines: extractClaudeMetadataFromLines,
3922
4192
  status: deriveClaudeSessionStatus,
4193
+ isNoiseLine: isClaudeNoiseLine,
3923
4194
  brandBranch: brandClaudeBranch,
3924
4195
  turnBoundaries: claudeTurnBoundaries
3925
4196
  };
3926
4197
  var FORMATS = Object.freeze({
4198
+ acp: {
4199
+ ...claudeFormat,
4200
+ kind: "acp",
4201
+ descriptor: descriptorFor("acp"),
4202
+ detectsText: (text) => text.split("\n", 1)[0]?.includes('"type":"acp_session"') ?? false,
4203
+ detectsRecords: (records) => records[0]?.type === "acp_session",
4204
+ parse: (text, options) => ({ ...parseClaudeSession(text, options), agentKind: "acp" }),
4205
+ append: (session, text) => ({ ...appendClaudeSession(session, text), agentKind: "acp" })
4206
+ },
3927
4207
  claude: claudeFormat,
3928
4208
  codex: codexFormat,
3929
4209
  copilot: copilotFormat
@@ -3940,6 +4220,9 @@ function formatForText(jsonlText) {
3940
4220
  function formatForRecords(records) {
3941
4221
  return firstMatch((format) => format.detectsRecords(records));
3942
4222
  }
4223
+ function isAnyAgentNoiseLine(line) {
4224
+ return AGENT_KINDS.some((kind) => FORMATS[kind].isNoiseLine(line));
4225
+ }
3943
4226
 
3944
4227
  // src/lib/parser.ts
3945
4228
  function extractTextFromContent2(content) {
@@ -3952,7 +4235,8 @@ function parseSession(jsonlText, options) {
3952
4235
  function parseSessionAppend(existing, newJsonlText) {
3953
4236
  const byRecords = formatForRecords(existing.rawMessages);
3954
4237
  const format = byRecords.kind === TERMINAL_AGENT_KIND ? formatForText(newJsonlText) : byRecords;
3955
- return format.append(existing, newJsonlText);
4238
+ const appended = format.append(existing, newJsonlText);
4239
+ return existing.instanceId ? scopeParsedSession(appended, existing.instanceId) : appended;
3956
4240
  }
3957
4241
  function getUserMessageText(content) {
3958
4242
  if (content === null) return "";
@@ -3964,16 +4248,63 @@ function getUserMessageImages(content) {
3964
4248
  return content.filter((b) => b.type === "image");
3965
4249
  }
3966
4250
 
3967
- // src/lib/stores.ts
4251
+ // src/lib/transcriptFile.ts
3968
4252
  var import_node_fs = require("node:fs");
4253
+ var import_promises = require("node:fs/promises");
4254
+ var zlib = __toESM(require("node:zlib"));
4255
+ var COMPRESSED_SUFFIX = ".zst";
4256
+ var canReadCompressedTranscripts = typeof zlib.zstdDecompressSync === "function";
4257
+ function isCompressedTranscript(filePath) {
4258
+ return filePath.endsWith(COMPRESSED_SUFFIX);
4259
+ }
4260
+ function uncompressedTranscriptName(fileName) {
4261
+ return isCompressedTranscript(fileName) ? fileName.slice(0, -COMPRESSED_SUFFIX.length) : fileName;
4262
+ }
4263
+ function isListableTranscript(name, siblings) {
4264
+ const plainName = uncompressedTranscriptName(name);
4265
+ if (!plainName.endsWith(".jsonl")) return false;
4266
+ if (plainName === name) return true;
4267
+ return canReadCompressedTranscripts && !siblings.has(plainName);
4268
+ }
4269
+ function inflate(data) {
4270
+ if (!canReadCompressedTranscripts) {
4271
+ throw new Error("Reading a .jsonl.zst transcript needs Node.js 22.15 or newer, or Bun");
4272
+ }
4273
+ return zlib.zstdDecompressSync(data);
4274
+ }
4275
+ function readTranscriptTextSync(filePath) {
4276
+ const data = (0, import_node_fs.readFileSync)(filePath);
4277
+ return (isCompressedTranscript(filePath) ? inflate(data) : data).toString("utf-8");
4278
+ }
4279
+ async function readTranscriptText(filePath) {
4280
+ const data = await (0, import_promises.readFile)(filePath);
4281
+ return (isCompressedTranscript(filePath) ? inflate(data) : data).toString("utf-8");
4282
+ }
4283
+ async function openTranscript(filePath) {
4284
+ if (!isCompressedTranscript(filePath)) return (0, import_promises.open)(filePath, "r");
4285
+ const [fileStat, compressed] = await Promise.all([(0, import_promises.stat)(filePath), (0, import_promises.readFile)(filePath)]);
4286
+ const data = inflate(compressed);
4287
+ return {
4288
+ async read(buffer, offset, length, position) {
4289
+ const start = Math.min(Math.max(position, 0), data.length);
4290
+ return { bytesRead: data.copy(buffer, offset, start, Math.min(start + length, data.length)) };
4291
+ },
4292
+ stat: async () => ({ size: data.length, mtimeMs: fileStat.mtimeMs }),
4293
+ close: async () => {
4294
+ }
4295
+ };
4296
+ }
4297
+
4298
+ // src/lib/stores.ts
4299
+ var import_node_fs2 = require("node:fs");
3969
4300
  var import_node_path2 = require("node:path");
3970
4301
 
3971
4302
  // src/lib/dirs.ts
3972
4303
  var import_node_path = require("node:path");
3973
4304
  var import_node_os = require("node:os");
3974
4305
  function agentHomeDir(kind, env = process.env, homeDirectory = (0, import_node_os.homedir)()) {
3975
- const { homeEnvVar, homeDirName } = descriptorFor(kind).cli;
3976
- const override = homeEnvVar ? env[homeEnvVar] : void 0;
4306
+ const { homeEnvVar, homeDirName, sdkHomeEnvVar } = descriptorFor(kind).cli;
4307
+ const override = env[homeEnvVar ?? sdkHomeEnvVar ?? ""];
3977
4308
  return override || (0, import_node_path.join)(homeDirectory, homeDirName);
3978
4309
  }
3979
4310
  var dirs = {
@@ -3981,7 +4312,8 @@ var dirs = {
3981
4312
  TEAMS_DIR: (0, import_node_path.join)(agentHomeDir("claude"), "teams"),
3982
4313
  TASKS_DIR: (0, import_node_path.join)(agentHomeDir("claude"), "tasks"),
3983
4314
  CODEX_SESSIONS_DIR: (0, import_node_path.join)(agentHomeDir("codex"), "sessions"),
3984
- COPILOT_SESSIONS_DIR: (0, import_node_path.join)(agentHomeDir("copilot"), "session-state")
4315
+ COPILOT_SESSIONS_DIR: (0, import_node_path.join)(agentHomeDir("copilot"), "session-state"),
4316
+ ACP_PROJECTS_DIR: (0, import_node_path.join)(agentHomeDir("acp"), "projects")
3985
4317
  };
3986
4318
  var DEFAULT_DB_PATH = (0, import_node_path.join)(agentHomeDir("claude"), "cogpit-memory", "search-index.db");
3987
4319
 
@@ -3991,14 +4323,14 @@ var MAX_WALK_DEPTH = 4;
3991
4323
  var SUBAGENTS_DIR = "subagents";
3992
4324
  function mtimeOf(filePath) {
3993
4325
  try {
3994
- return (0, import_node_fs.statSync)(filePath).mtimeMs;
4326
+ return (0, import_node_fs2.statSync)(filePath).mtimeMs;
3995
4327
  } catch {
3996
4328
  return null;
3997
4329
  }
3998
4330
  }
3999
4331
  function readDirSafe(dir) {
4000
4332
  try {
4001
- return (0, import_node_fs.readdirSync)(dir, { withFileTypes: true });
4333
+ return (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true });
4002
4334
  } catch {
4003
4335
  return [];
4004
4336
  }
@@ -4009,8 +4341,8 @@ function isWithin(root, target) {
4009
4341
  }
4010
4342
  function canonicalWithinRoot(root, filePath) {
4011
4343
  try {
4012
- const realRoot = (0, import_node_fs.realpathSync)(root);
4013
- const real = (0, import_node_fs.realpathSync)(filePath);
4344
+ const realRoot = (0, import_node_fs2.realpathSync)(root);
4345
+ const real = (0, import_node_fs2.realpathSync)(filePath);
4014
4346
  return isWithin(realRoot, real) ? real : null;
4015
4347
  } catch {
4016
4348
  return null;
@@ -4076,13 +4408,15 @@ function walkClaude(root, cutoffMs) {
4076
4408
  function walkCodex(root, cutoffMs, dir = root, depth = 0) {
4077
4409
  if (depth > MAX_WALK_DEPTH) return [];
4078
4410
  const found = [];
4079
- for (const entry of readDirSafe(dir)) {
4411
+ const entries = readDirSafe(dir);
4412
+ const names = new Set(entries.map((entry) => entry.name));
4413
+ for (const entry of entries) {
4080
4414
  const filePath = (0, import_node_path2.join)(dir, entry.name);
4081
4415
  if (entry.isDirectory()) {
4082
4416
  found.push(...walkCodex(root, cutoffMs, filePath, depth + 1));
4083
4417
  continue;
4084
4418
  }
4085
- if (!entry.name.endsWith(".jsonl")) continue;
4419
+ if (!isListableTranscript(entry.name, names)) continue;
4086
4420
  const mtimeMs = mtimeOf(filePath);
4087
4421
  if (mtimeMs === null || mtimeMs < cutoffMs) continue;
4088
4422
  found.push({
@@ -4143,14 +4477,18 @@ var WALKERS = {
4143
4477
  find(root, sessionId) {
4144
4478
  const walk = (dir, depth) => {
4145
4479
  if (depth > MAX_WALK_DEPTH) return null;
4146
- for (const entry of readDirSafe(dir)) {
4480
+ const entries = readDirSafe(dir);
4481
+ const names = new Set(entries.map((entry) => entry.name));
4482
+ for (const entry of entries) {
4147
4483
  const filePath = (0, import_node_path2.join)(dir, entry.name);
4148
4484
  if (entry.isDirectory()) {
4149
4485
  const match = walk(filePath, depth + 1);
4150
4486
  if (match) return match;
4151
4487
  continue;
4152
4488
  }
4153
- if (entry.name.endsWith(`${sessionId}.jsonl`)) return filePath;
4489
+ if (uncompressedTranscriptName(entry.name).endsWith(`${sessionId}.jsonl`) && isListableTranscript(entry.name, names)) {
4490
+ return filePath;
4491
+ }
4154
4492
  }
4155
4493
  return null;
4156
4494
  };
@@ -4169,24 +4507,48 @@ var WALKERS = {
4169
4507
  const candidate = copilotTranscript(root, sessionId);
4170
4508
  return mtimeOf(candidate) === null ? null : candidate;
4171
4509
  }
4510
+ },
4511
+ acp: {
4512
+ root: () => dirs.ACP_PROJECTS_DIR,
4513
+ list: walkClaude,
4514
+ identify: claudeIdentify,
4515
+ find: (root, id) => WALKERS.claude.find(root, id)
4172
4516
  }
4173
4517
  };
4174
- function makeStore(kind) {
4518
+ function makeStore(kind, home, configuredId) {
4175
4519
  const walker = WALKERS[kind];
4520
+ const instanceId = configuredId ?? (process.env.COGPIT_WORKER_AGENT === kind ? process.env.COGPIT_AGENT_INSTANCE_ID : void 0) ?? "default";
4521
+ const root = home ? () => (0, import_node_path2.join)(home, kind === "codex" ? "sessions" : kind === "copilot" ? "session-state" : "projects") : walker.root;
4522
+ const identify = (filePath, directory = root()) => {
4523
+ const identity = walker.identify(filePath, directory);
4524
+ return { ...identity, sessionId: instanceSessionId(instanceId, identity.sessionId), parentSessionId: identity.parentSessionId ? instanceSessionId(instanceId, identity.parentSessionId) : null };
4525
+ };
4176
4526
  return {
4177
4527
  kind,
4528
+ instanceId,
4178
4529
  descriptor: descriptorFor(kind),
4179
- root: walker.root,
4180
- ownsPath: (filePath) => isWithin((0, import_node_path2.resolve)(walker.root()), (0, import_node_path2.resolve)(filePath)),
4181
- identify: (filePath, root = walker.root()) => walker.identify(filePath, root),
4182
- list: (cutoffMs, root = walker.root()) => walker.list(root, cutoffMs),
4183
- find: (sessionId) => walker.find(walker.root(), sessionId)
4530
+ root,
4531
+ ownsPath: (filePath) => {
4532
+ if (isWithin((0, import_node_path2.resolve)(root()), (0, import_node_path2.resolve)(filePath))) return true;
4533
+ try {
4534
+ return isWithin((0, import_node_fs2.realpathSync)(root()), (0, import_node_fs2.realpathSync)(filePath));
4535
+ } catch {
4536
+ return false;
4537
+ }
4538
+ },
4539
+ identify,
4540
+ list: (cutoffMs, directory = root()) => walker.list(directory, cutoffMs).map((file) => ({ ...file, ...identify(file.path, directory) })),
4541
+ find: (sessionId) => {
4542
+ const parts = splitInstanceSessionId(sessionId);
4543
+ return parts.instanceId === instanceId ? walker.find(root(), parts.nativeId) : null;
4544
+ }
4184
4545
  };
4185
4546
  }
4186
4547
  var STORES = {
4187
4548
  claude: makeStore("claude"),
4188
4549
  codex: makeStore("codex"),
4189
- copilot: makeStore("copilot")
4550
+ copilot: makeStore("copilot"),
4551
+ acp: makeStore("acp")
4190
4552
  };
4191
4553
  function storeFor(kind) {
4192
4554
  return STORES[kind];
@@ -4195,7 +4557,20 @@ function defaultStore() {
4195
4557
  return storeFor(descriptorForDirName(null).kind);
4196
4558
  }
4197
4559
  function allStores() {
4198
- return AGENT_KINDS.map((kind) => STORES[kind]);
4560
+ if (process.env.COGPIT_AGENT_INSTANCE_ID && AGENT_KINDS.includes(process.env.COGPIT_WORKER_AGENT)) return [STORES[process.env.COGPIT_WORKER_AGENT]];
4561
+ const stores = AGENT_KINDS.map((kind) => STORES[kind]);
4562
+ const root = process.env.COGPIT_ORCHESTRATION_ROOT;
4563
+ if (!root) return stores;
4564
+ for (const entry of readDirSafe((0, import_node_path2.join)(root, "provider-instances"))) {
4565
+ if (!entry.isDirectory()) continue;
4566
+ const home = (0, import_node_path2.join)(root, "provider-instances", entry.name);
4567
+ try {
4568
+ const config = JSON.parse((0, import_node_fs2.readFileSync)((0, import_node_path2.join)(home, "config.json"), "utf8"));
4569
+ if (config.providerInstance?.id === entry.name && config.providerInstance.agent && AGENT_KINDS.includes(config.providerInstance.agent)) stores.push(makeStore(config.providerInstance.agent, home, entry.name));
4570
+ } catch {
4571
+ }
4572
+ }
4573
+ return stores;
4199
4574
  }
4200
4575
  function storeForPath(filePath) {
4201
4576
  return allStores().find((store) => store.ownsPath(filePath)) ?? null;
@@ -4265,7 +4640,7 @@ var SearchIndex = class {
4265
4640
  const { count: totalRows } = this.db.prepare("SELECT COUNT(*) as count FROM search_content").get();
4266
4641
  let dbSizeBytes = 0;
4267
4642
  try {
4268
- dbSizeBytes = (0, import_node_fs2.statSync)(this.dbPath).size;
4643
+ dbSizeBytes = (0, import_node_fs3.statSync)(this.dbPath).size;
4269
4644
  } catch {
4270
4645
  }
4271
4646
  return {
@@ -4338,9 +4713,9 @@ var SearchIndex = class {
4338
4713
  indexFile(filePath, sessionId, mtimeMs, opts) {
4339
4714
  const resolvedSessionId = sessionId ?? identifyTranscript(filePath).sessionId;
4340
4715
  if (mtimeMs == null) {
4341
- mtimeMs = (0, import_node_fs2.statSync)(filePath).mtimeMs;
4716
+ mtimeMs = (0, import_node_fs3.statSync)(filePath).mtimeMs;
4342
4717
  }
4343
- const content = (0, import_node_fs2.readFileSync)(filePath, "utf-8");
4718
+ const content = readTranscriptTextSync(filePath);
4344
4719
  const session = parseSession(content, { skipStats: true });
4345
4720
  const isSubagent = opts?.isSubagent ? 1 : 0;
4346
4721
  const parentSessionId = opts?.parentSessionId ?? null;
@@ -4369,7 +4744,7 @@ var SearchIndex = class {
4369
4744
  const files = this.db.prepare("SELECT file_path FROM indexed_files").all();
4370
4745
  const missing = files.filter(({ file_path }) => {
4371
4746
  try {
4372
- (0, import_node_fs2.statSync)(file_path);
4747
+ (0, import_node_fs3.statSync)(file_path);
4373
4748
  return false;
4374
4749
  } catch (error) {
4375
4750
  const code = error.code;
@@ -4486,7 +4861,7 @@ var SearchIndex = class {
4486
4861
  this.db.close();
4487
4862
  for (const suffix of ["", "-wal", "-shm"]) {
4488
4863
  try {
4489
- (0, import_node_fs2.unlinkSync)(this.dbPath + suffix);
4864
+ (0, import_node_fs3.unlinkSync)(this.dbPath + suffix);
4490
4865
  } catch {
4491
4866
  }
4492
4867
  }
@@ -4510,7 +4885,7 @@ var SearchIndex = class {
4510
4885
  const txn = this.db.transaction(() => {
4511
4886
  for (const file of files) {
4512
4887
  try {
4513
- const content = (0, import_node_fs2.readFileSync)(file.path, "utf-8");
4888
+ const content = readTranscriptTextSync(file.path);
4514
4889
  const session = parseSession(content, { skipStats: true });
4515
4890
  this.insertSessionContent(insert, file.sessionId, file.path, session);
4516
4891
  insertFile.run(file.path, file.mtimeMs, file.sessionId, file.isSubagent ? 1 : 0, file.parentSessionId);
@@ -4572,8 +4947,8 @@ var SearchIndex = class {
4572
4947
  };
4573
4948
 
4574
4949
  // src/commands/search.ts
4575
- var import_node_fs3 = require("node:fs");
4576
- var import_promises = require("node:fs/promises");
4950
+ var import_node_fs4 = require("node:fs");
4951
+ var import_promises2 = require("node:fs/promises");
4577
4952
  var import_node_path3 = require("node:path");
4578
4953
 
4579
4954
  // src/lib/response.ts
@@ -4594,6 +4969,11 @@ function parseMaxAge(raw) {
4594
4969
  }
4595
4970
  }
4596
4971
 
4972
+ // src/lib/read-session.ts
4973
+ function parseTranscript(content, filePath) {
4974
+ return scopeParsedSession(parseSession(content), storeForPath(filePath)?.instanceId ?? "default");
4975
+ }
4976
+
4597
4977
  // src/commands/search.ts
4598
4978
  async function searchSessions(query, opts, searchIndex) {
4599
4979
  if (!query || query.length < 2) {
@@ -4606,9 +4986,9 @@ async function searchSessions(query, opts, searchIndex) {
4606
4986
  let ownedIndex = false;
4607
4987
  if (!index && searchIndex === void 0) {
4608
4988
  try {
4609
- const dbExists = (0, import_node_fs3.existsSync)(DEFAULT_DB_PATH);
4989
+ const dbExists = (0, import_node_fs4.existsSync)(DEFAULT_DB_PATH);
4610
4990
  if (!dbExists) {
4611
- (0, import_node_fs3.mkdirSync)((0, import_node_path3.dirname)(DEFAULT_DB_PATH), { recursive: true });
4991
+ (0, import_node_fs4.mkdirSync)((0, import_node_path3.dirname)(DEFAULT_DB_PATH), { recursive: true });
4612
4992
  }
4613
4993
  index = new SearchIndex(DEFAULT_DB_PATH);
4614
4994
  ownedIndex = true;
@@ -4682,7 +5062,7 @@ async function cwdFromFilePath(filePath) {
4682
5062
  const cached = cwdCache.get(filePath);
4683
5063
  if (cached !== void 0) return cached;
4684
5064
  try {
4685
- const fh = await (0, import_promises.open)(filePath, "r");
5065
+ const fh = await openTranscript(filePath);
4686
5066
  try {
4687
5067
  const buf = Buffer.alloc(CWD_READ_BYTES);
4688
5068
  const { bytesRead } = await fh.read(buf, 0, CWD_READ_BYTES, 0);
@@ -4740,7 +5120,7 @@ function searchField(text, location, query, caseSensitive, extras) {
4740
5120
  async function discoverSingleSession(sessionId) {
4741
5121
  const jsonlPath = await findSessionFile(sessionId);
4742
5122
  if (!jsonlPath) return [];
4743
- const s = await (0, import_promises.stat)(jsonlPath);
5123
+ const s = await (0, import_promises2.stat)(jsonlPath);
4744
5124
  return [{ path: jsonlPath, mtimeMs: s.mtimeMs, sessionId }];
4745
5125
  }
4746
5126
  function discoverAllSessions(maxAgeMs) {
@@ -4748,7 +5128,7 @@ function discoverAllSessions(maxAgeMs) {
4748
5128
  }
4749
5129
  async function rawTextMatch(filePath, query, caseSensitive) {
4750
5130
  try {
4751
- const content = await (0, import_promises.readFile)(filePath, "utf-8");
5131
+ const content = await readTranscriptText(filePath);
4752
5132
  const haystack = caseSensitive ? content : content.toLowerCase();
4753
5133
  const needle = caseSensitive ? query : query.toLowerCase();
4754
5134
  if (haystack.includes(needle)) return content;
@@ -4823,7 +5203,7 @@ async function walkSubagentFiles(parentJsonlPath, query, caseSensitive, currentD
4823
5203
  const subDir = parentJsonlPath.replace(/\.jsonl$/, "") + "/subagents";
4824
5204
  let files;
4825
5205
  try {
4826
- files = await (0, import_promises.readdir)(subDir);
5206
+ files = await (0, import_promises2.readdir)(subDir);
4827
5207
  } catch {
4828
5208
  return [];
4829
5209
  }
@@ -4840,7 +5220,7 @@ async function walkSubagentFiles(parentJsonlPath, query, caseSensitive, currentD
4840
5220
  );
4841
5221
  const hitArrays = await Promise.all(
4842
5222
  matched.filter((m) => m.rawContent).map(async ({ agentId, filePath, rawContent }) => {
4843
- const subSession = parseSession(rawContent);
5223
+ const subSession = parseTranscript(rawContent, filePath);
4844
5224
  const subHits = walkSession(subSession, query, caseSensitive, `agent/${agentId}/`);
4845
5225
  const nestedHits = await walkSubagentFiles(filePath, query, caseSensitive, currentDepth + 1, maxDepth);
4846
5226
  return [...subHits, ...nestedHits];
@@ -4861,7 +5241,7 @@ async function rawScanSearch(query, sessionId, maxAgeMs, limit, caseSensitive, e
4861
5241
  const rawContent = await rawTextMatch(file.path, query, caseSensitive);
4862
5242
  sessionsSearched++;
4863
5243
  if (!rawContent) continue;
4864
- const session = parseSession(rawContent);
5244
+ const session = parseTranscript(rawContent, file.path);
4865
5245
  const sessionHits = walkSession(session, query, caseSensitive);
4866
5246
  const subagentHits = await walkSubagentFiles(file.path, query, caseSensitive, 0, MAX_SUBAGENT_DEPTH);
4867
5247
  const allHits = [...sessionHits, ...subagentHits];
@@ -4901,14 +5281,14 @@ async function rawScanSearch(query, sessionId, maxAgeMs, limit, caseSensitive, e
4901
5281
  }
4902
5282
 
4903
5283
  // src/commands/context.ts
4904
- var import_promises3 = require("node:fs/promises");
5284
+ var import_promises4 = require("node:fs/promises");
4905
5285
  var import_node_path5 = require("node:path");
4906
5286
 
4907
5287
  // src/lib/helpers.ts
4908
- var import_promises2 = require("node:fs/promises");
5288
+ var import_promises3 = require("node:fs/promises");
4909
5289
  var import_node_path4 = require("node:path");
4910
5290
  async function matchSubagentToMember(leadSessionId, subagentFileName, members) {
4911
- const entries = await (0, import_promises2.readdir)(dirs.PROJECTS_DIR, { withFileTypes: true });
5291
+ const entries = await (0, import_promises3.readdir)(dirs.PROJECTS_DIR, { withFileTypes: true });
4912
5292
  for (const entry of entries) {
4913
5293
  if (!entry.isDirectory() || entry.name === "memory") continue;
4914
5294
  const filePath = (0, import_node_path4.join)(
@@ -4919,7 +5299,7 @@ async function matchSubagentToMember(leadSessionId, subagentFileName, members) {
4919
5299
  subagentFileName
4920
5300
  );
4921
5301
  try {
4922
- const fh = await (0, import_promises2.open)(filePath, "r");
5302
+ const fh = await (0, import_promises3.open)(filePath, "r");
4923
5303
  try {
4924
5304
  const buf = Buffer.alloc(16384);
4925
5305
  const { bytesRead } = await fh.read(buf, 0, 16384, 0);
@@ -5113,6 +5493,14 @@ function mapContentBlock(block) {
5113
5493
  return { kind: "recap", content: block.content, timestamp: block.timestamp ?? null };
5114
5494
  case "task_notification":
5115
5495
  return { kind: "task_notification", content: block.content, timestamp: block.timestamp ?? null };
5496
+ case "local_command":
5497
+ return {
5498
+ kind: "local_command",
5499
+ content: block.content,
5500
+ timestamp: block.timestamp ?? null,
5501
+ ...block.contextUsage ? { contextUsage: block.contextUsage } : {},
5502
+ ...block.usageReport ? { usageReport: block.usageReport } : {}
5503
+ };
5116
5504
  default: {
5117
5505
  const exhaustive = block;
5118
5506
  return exhaustive;
@@ -5122,7 +5510,7 @@ function mapContentBlock(block) {
5122
5510
  async function findSubagentFile(parentJsonlPath, agentId) {
5123
5511
  const subagentsDir = parentJsonlPath.replace(/\.jsonl$/, "") + "/subagents";
5124
5512
  try {
5125
- const files = await (0, import_promises3.readdir)(subagentsDir);
5513
+ const files = await (0, import_promises4.readdir)(subagentsDir);
5126
5514
  for (const f of files) {
5127
5515
  if (!f.startsWith("agent-") || !f.endsWith(".jsonl")) continue;
5128
5516
  const fileAgentId = f.replace("agent-", "").replace(".jsonl", "");
@@ -5136,12 +5524,12 @@ async function findSubagentFile(parentJsonlPath, agentId) {
5136
5524
  }
5137
5525
  async function findTeamContext(sessionId, subagentFileName) {
5138
5526
  try {
5139
- const teamEntries = await (0, import_promises3.readdir)(dirs.TEAMS_DIR, { withFileTypes: true });
5527
+ const teamEntries = await (0, import_promises4.readdir)(dirs.TEAMS_DIR, { withFileTypes: true });
5140
5528
  for (const entry of teamEntries) {
5141
5529
  if (!entry.isDirectory()) continue;
5142
5530
  const configPath = (0, import_node_path5.join)(dirs.TEAMS_DIR, entry.name, "config.json");
5143
5531
  try {
5144
- const raw = await (0, import_promises3.readFile)(configPath, "utf-8");
5532
+ const raw = await (0, import_promises4.readFile)(configPath, "utf-8");
5145
5533
  const config = JSON.parse(raw);
5146
5534
  if (config.leadSessionId !== sessionId) continue;
5147
5535
  const members = config.members ?? [];
@@ -5150,10 +5538,10 @@ async function findTeamContext(sessionId, subagentFileName) {
5150
5538
  let currentTask = null;
5151
5539
  try {
5152
5540
  const taskDir = (0, import_node_path5.join)(dirs.TASKS_DIR, entry.name);
5153
- const taskFiles = await (0, import_promises3.readdir)(taskDir);
5541
+ const taskFiles = await (0, import_promises4.readdir)(taskDir);
5154
5542
  for (const tf of taskFiles) {
5155
5543
  if (!tf.endsWith(".json")) continue;
5156
- const taskRaw = await (0, import_promises3.readFile)((0, import_node_path5.join)(taskDir, tf), "utf-8");
5544
+ const taskRaw = await (0, import_promises4.readFile)((0, import_node_path5.join)(taskDir, tf), "utf-8");
5157
5545
  const task = JSON.parse(taskRaw);
5158
5546
  if (task.owner === memberName && task.status === "in_progress") {
5159
5547
  currentTask = { id: task.id, subject: task.subject, status: task.status };
@@ -5201,27 +5589,27 @@ function findAgentMetadata(session, agentId) {
5201
5589
  async function getSessionOverview(sessionId) {
5202
5590
  const jsonlPath = await findSessionFile(sessionId);
5203
5591
  if (!jsonlPath) return { error: "Session not found" };
5204
- const content = await (0, import_promises3.readFile)(jsonlPath, "utf-8");
5205
- const session = parseSession(content);
5592
+ const content = await readTranscriptText(jsonlPath);
5593
+ const session = parseTranscript(content, jsonlPath);
5206
5594
  return mapSessionToOverview(session);
5207
5595
  }
5208
5596
  async function getTurnDetail(sessionId, turnIndex) {
5209
5597
  const jsonlPath = await findSessionFile(sessionId);
5210
5598
  if (!jsonlPath) return { error: "Session not found" };
5211
- const content = await (0, import_promises3.readFile)(jsonlPath, "utf-8");
5212
- const session = parseSession(content);
5599
+ const content = await readTranscriptText(jsonlPath);
5600
+ const session = parseTranscript(content, jsonlPath);
5213
5601
  if (turnIndex < 0 || turnIndex >= session.turns.length) return { error: "Turn not found" };
5214
5602
  return mapTurnToDetail(session, turnIndex);
5215
5603
  }
5216
5604
  async function getAgentOverview(sessionId, agentId) {
5217
5605
  const jsonlPath = await findSessionFile(sessionId);
5218
5606
  if (!jsonlPath) return { error: "Session not found" };
5219
- const content = await (0, import_promises3.readFile)(jsonlPath, "utf-8");
5220
- const session = parseSession(content);
5607
+ const content = await readTranscriptText(jsonlPath);
5608
+ const session = parseTranscript(content, jsonlPath);
5221
5609
  const subagentFile = await findSubagentFile(jsonlPath, agentId);
5222
5610
  if (!subagentFile) return { error: "Agent not found" };
5223
- const subagentContent = await (0, import_promises3.readFile)(subagentFile.filePath, "utf-8");
5224
- const subagentSession = parseSession(subagentContent);
5611
+ const subagentContent = await readTranscriptText(subagentFile.filePath);
5612
+ const subagentSession = parseTranscript(subagentContent, subagentFile.filePath);
5225
5613
  const metadata = findAgentMetadata(session, agentId);
5226
5614
  const parentToolCallId = findParentToolCallId(session, agentId);
5227
5615
  const teamContext = await findTeamContext(sessionId, subagentFile.fileName);
@@ -5241,8 +5629,8 @@ async function getAgentTurnDetail(sessionId, agentId, turnIndex) {
5241
5629
  if (!jsonlPath) return { error: "Session not found" };
5242
5630
  const subagentFile = await findSubagentFile(jsonlPath, agentId);
5243
5631
  if (!subagentFile) return { error: "Agent not found" };
5244
- const subagentContent = await (0, import_promises3.readFile)(subagentFile.filePath, "utf-8");
5245
- const subagentSession = parseSession(subagentContent);
5632
+ const subagentContent = await readTranscriptText(subagentFile.filePath);
5633
+ const subagentSession = parseTranscript(subagentContent, subagentFile.filePath);
5246
5634
  if (turnIndex < 0 || turnIndex >= subagentSession.turns.length) return { error: "Turn not found" };
5247
5635
  return mapTurnToDetail(subagentSession, turnIndex);
5248
5636
  }
@@ -5251,7 +5639,7 @@ async function getAgentTurnDetail(sessionId, agentId, turnIndex) {
5251
5639
  var import_node_path6 = require("node:path");
5252
5640
 
5253
5641
  // src/lib/metadata.ts
5254
- var import_promises4 = require("node:fs/promises");
5642
+ var import_promises5 = require("node:fs/promises");
5255
5643
 
5256
5644
  // src/lib/sessionStatus.ts
5257
5645
  function deriveSessionStatus(rawMessages) {
@@ -5276,15 +5664,16 @@ function scanClaudeMessages(lines) {
5276
5664
  turnCount: 0
5277
5665
  };
5278
5666
  for (const line of lines) {
5279
- let record;
5667
+ if (isAnyAgentNoiseLine(line)) continue;
5668
+ let record2;
5280
5669
  try {
5281
- record = JSON.parse(line);
5670
+ record2 = JSON.parse(line);
5282
5671
  } catch {
5283
5672
  continue;
5284
5673
  }
5285
- if (record.type !== "user" || record.isMeta) continue;
5286
- if (!meta.timestamp) meta.timestamp = record.timestamp || "";
5287
- const content = record.message?.content;
5674
+ if (record2.type !== "user" || record2.isMeta) continue;
5675
+ if (!meta.timestamp) meta.timestamp = record2.timestamp || "";
5676
+ const content = record2.message?.content;
5288
5677
  let extracted = "";
5289
5678
  if (typeof content === "string") {
5290
5679
  extracted = cleanUserText(content);
@@ -5304,11 +5693,11 @@ function scanClaudeMessages(lines) {
5304
5693
  return meta;
5305
5694
  }
5306
5695
  async function readLines(filePath, size) {
5307
- if (size <= FULL_READ_LIMIT) {
5308
- const content = await (0, import_promises4.readFile)(filePath, "utf-8");
5696
+ if (size <= FULL_READ_LIMIT || isCompressedTranscript(filePath)) {
5697
+ const content = await readTranscriptText(filePath);
5309
5698
  return { lines: content.split("\n").filter(Boolean), isPartialRead: false };
5310
5699
  }
5311
- const handle = await (0, import_promises4.open)(filePath, "r");
5700
+ const handle = await (0, import_promises5.open)(filePath, "r");
5312
5701
  try {
5313
5702
  const buffer = Buffer.alloc(HEAD_READ_BYTES);
5314
5703
  const { bytesRead } = await handle.read(buffer, 0, HEAD_READ_BYTES, 0);
@@ -5323,14 +5712,15 @@ async function readLines(filePath, size) {
5323
5712
  }
5324
5713
  }
5325
5714
  async function getSessionMeta(filePath) {
5326
- const fileStat = await (0, import_promises4.stat)(filePath);
5715
+ const fileStat = await (0, import_promises5.stat)(filePath);
5327
5716
  let { lines, isPartialRead } = await readLines(filePath, fileStat.size);
5328
5717
  const format = formatForText(lines.join("\n"));
5329
5718
  if (isPartialRead && !format.descriptor.metadataFromHead) {
5330
- lines = (await (0, import_promises4.readFile)(filePath, "utf-8")).split("\n").filter(Boolean);
5719
+ lines = (await (0, import_promises5.readFile)(filePath, "utf-8")).split("\n").filter(Boolean);
5331
5720
  isPartialRead = false;
5332
5721
  }
5333
5722
  const header = readHeader(format, lines);
5723
+ const instanceId = storeForPath(filePath)?.instanceId ?? "default";
5334
5724
  const conversation = header.turnCount === void 0 ? scanClaudeMessages(lines) : {
5335
5725
  firstUserMessage: header.firstUserMessage ?? "",
5336
5726
  lastUserMessage: header.lastUserMessage ?? "",
@@ -5338,7 +5728,7 @@ async function getSessionMeta(filePath) {
5338
5728
  turnCount: header.turnCount
5339
5729
  };
5340
5730
  return {
5341
- sessionId: header.sessionId,
5731
+ sessionId: instanceSessionId(instanceId, header.sessionId),
5342
5732
  version: header.version,
5343
5733
  gitBranch: header.gitBranch,
5344
5734
  model: header.model,
@@ -5348,17 +5738,17 @@ async function getSessionMeta(filePath) {
5348
5738
  // A head read saw a known number of lines in a known number of bytes;
5349
5739
  // scaling that by the file size is the only estimate available.
5350
5740
  lineCount: isPartialRead ? Math.round(fileStat.size / (HEAD_READ_BYTES / lines.length)) : lines.length,
5351
- branchedFrom: header.branchedFrom
5741
+ branchedFrom: header.branchedFrom ? { ...header.branchedFrom, sessionId: instanceSessionId(instanceId, header.branchedFrom.sessionId) } : void 0
5352
5742
  };
5353
5743
  }
5354
5744
  async function getSessionStatus(filePath) {
5355
5745
  const CHUNK = 4096;
5356
5746
  const MAX_CHUNKS = 64;
5357
5747
  try {
5358
- const fileStat = await (0, import_promises4.stat)(filePath);
5359
- if (fileStat.size === 0) return { status: "idle" };
5360
- const fh = await (0, import_promises4.open)(filePath, "r");
5748
+ const fh = await openTranscript(filePath);
5361
5749
  try {
5750
+ const fileStat = await fh.stat();
5751
+ if (fileStat.size === 0) return { status: "idle" };
5362
5752
  const meaningful = [];
5363
5753
  let cursor = fileStat.size;
5364
5754
  let leftover = "";
@@ -5374,7 +5764,7 @@ async function getSessionStatus(filePath) {
5374
5764
  const startIdx = cursor > 0 ? 1 : 0;
5375
5765
  for (let i = lines.length - 1; i >= startIdx; i--) {
5376
5766
  const line = lines[i];
5377
- if (!line) continue;
5767
+ if (!line || isAnyAgentNoiseLine(line)) continue;
5378
5768
  let obj;
5379
5769
  try {
5380
5770
  obj = JSON.parse(line);
@@ -5443,7 +5833,7 @@ async function getSessionStatus(filePath) {
5443
5833
  // src/commands/sessions.ts
5444
5834
  function toSessionSummary(file, meta, status) {
5445
5835
  return {
5446
- sessionId: meta.sessionId,
5836
+ sessionId: file.sessionId || meta.sessionId,
5447
5837
  filePath: file.path,
5448
5838
  timestamp: meta.timestamp,
5449
5839
  model: meta.model,
@@ -5505,11 +5895,11 @@ async function currentSession(cwd) {
5505
5895
  }
5506
5896
 
5507
5897
  // src/commands/index-cmd.ts
5508
- var import_node_fs4 = require("node:fs");
5898
+ var import_node_fs5 = require("node:fs");
5509
5899
  var import_node_path7 = require("node:path");
5510
5900
  async function indexStats(dbPath) {
5511
5901
  const path = dbPath ?? DEFAULT_DB_PATH;
5512
- if (!(0, import_node_fs4.existsSync)(path)) {
5902
+ if (!(0, import_node_fs5.existsSync)(path)) {
5513
5903
  return { error: `Database not found at ${path}. Run 'cogpit-memory index rebuild' to create it.` };
5514
5904
  }
5515
5905
  const index = new SearchIndex(path);
@@ -5519,7 +5909,7 @@ async function indexStats(dbPath) {
5519
5909
  }
5520
5910
  async function indexRebuild(dbPath) {
5521
5911
  const path = dbPath ?? DEFAULT_DB_PATH;
5522
- (0, import_node_fs4.mkdirSync)((0, import_node_path7.dirname)(path), { recursive: true });
5912
+ (0, import_node_fs5.mkdirSync)((0, import_node_path7.dirname)(path), { recursive: true });
5523
5913
  const index = new SearchIndex(path);
5524
5914
  index.buildFull();
5525
5915
  const stats = index.getStats();