cogpit-memory 0.4.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,7 +54,7 @@ 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
60
  var AGENT_KINDS = ["acp", "codex", "copilot", "claude"];
@@ -122,7 +122,7 @@ function base64DirNameCodec(prefix) {
122
122
  };
123
123
  }
124
124
  function sessionIdFromJsonlName(fileName) {
125
- const match = new RegExp(`(${SESSION_UUID})\\.jsonl$`, "i").exec(fileName);
125
+ const match = new RegExp(`(${SESSION_UUID})\\.jsonl(?:\\.zst)?$`, "i").exec(fileName);
126
126
  return match ? match[1] : null;
127
127
  }
128
128
  function ownTranscriptRoot(sessionId) {
@@ -292,7 +292,8 @@ var claude = {
292
292
  fastTier: true,
293
293
  lowPriorityInTerminal: true,
294
294
  imageInput: true,
295
- midTurnSteering: false,
295
+ midTurnSteering: true,
296
+ activeNotifications: true,
296
297
  stopSession: true,
297
298
  ultracode: true,
298
299
  contextWindow: true,
@@ -378,6 +379,7 @@ var codex = {
378
379
  bundledBySdk: false,
379
380
  homeDirName: ".codex",
380
381
  homeEnvVar: "CODEX_HOME",
382
+ sessionIdEnvVar: "CODEX_THREAD_ID",
381
383
  installMarker: "",
382
384
  homeIsDiscoverable: true,
383
385
  process: {
@@ -428,6 +430,7 @@ var codex = {
428
430
  lowPriorityInTerminal: false,
429
431
  imageInput: true,
430
432
  midTurnSteering: true,
433
+ activeNotifications: true,
431
434
  stopSession: false,
432
435
  ultracode: false,
433
436
  contextWindow: false,
@@ -549,6 +552,7 @@ var copilot = {
549
552
  lowPriorityInTerminal: false,
550
553
  imageInput: false,
551
554
  midTurnSteering: true,
555
+ activeNotifications: true,
552
556
  stopSession: true,
553
557
  ultracode: false,
554
558
  contextWindow: false,
@@ -578,7 +582,7 @@ var acp = {
578
582
  launchArgs: { permissions: () => [], model: () => [], effort: () => [], fastTier: () => [] },
579
583
  cli: { ...copilot.cli, packageName: "", homebrew: null, wingetId: null, selfUpdate: null, requiresConfiguration: true, homeDirName: ".cogpit-acp", homeEnvVar: "COGPIT_ACP_HOME", homeIsDiscoverable: true, installMarker: "projects" },
580
584
  config: { ...copilot.config, rootDirName: ".cogpit-acp", instructions: [], settings: [], skillsDir: null },
581
- capabilities: { ...copilot.capabilities, undo: false, redo: false, nativeRewind: false, nativeFork: false, midTurnSteering: false, externalProcesses: false, autoPermissionMode: "never", toolPermissionRules: false, namedSessions: false }
585
+ capabilities: { ...copilot.capabilities, undo: false, redo: false, nativeRewind: false, nativeFork: false, midTurnSteering: false, activeNotifications: false, externalProcesses: false, autoPermissionMode: "never", toolPermissionRules: false, namedSessions: false }
582
586
  };
583
587
  var DESCRIPTORS = Object.freeze({
584
588
  claude,
@@ -682,6 +686,27 @@ function readJsStringLiteral(source, startIndex) {
682
686
  return null;
683
687
  }
684
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
+
685
710
  // src/lib/messageTypeGuards.ts
686
711
  function isUserMessage(msg) {
687
712
  return msg.type === "user";
@@ -846,6 +871,17 @@ function isTaskNotificationRecord(msg) {
846
871
  if (!text.includes("<task-notification>")) return false;
847
872
  return text.replace(TASK_NOTIFICATION_BLOCK_RE, "").replace(ANY_TAG_RE, "").trim() === "";
848
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
+ }
849
885
  function queuedCommandPrompt(msg) {
850
886
  if (!isAttachmentMessage(msg)) return null;
851
887
  const attachment = msg.attachment;
@@ -1187,7 +1223,13 @@ function buildTurnsWithStarts(messages) {
1187
1223
  continue;
1188
1224
  }
1189
1225
  if (isSystemMessage(msg) && msg.subtype === "local_command" && msg.content) {
1190
- current?.contentBlocks.push({ kind: "local_command", content: msg.content, timestamp: msg.timestamp });
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
+ });
1191
1233
  continue;
1192
1234
  }
1193
1235
  if (isQueueOperationMessage(msg)) {
@@ -1263,6 +1305,7 @@ function buildTurnsWithStarts(messages) {
1263
1305
  parentToolUseId: toolUseId || void 0,
1264
1306
  agentName: taskMeta?.name ?? null,
1265
1307
  subagentType: taskMeta?.subagentType ?? null,
1308
+ ...taskMeta?.effort ? { effort: taskMeta.effort } : {},
1266
1309
  type: "assistant",
1267
1310
  content: toolUseResult.content,
1268
1311
  toolCalls: [],
@@ -1401,15 +1444,12 @@ function buildTurnsWithStarts(messages) {
1401
1444
  current.toolCalls.push(tc);
1402
1445
  msgToolCalls.push(tc);
1403
1446
  pendingToolUses.set(block.id, { turn: current, index: idx });
1404
- if (block.name === "Task" || block.name === "Agent") {
1447
+ if (isTaskToolName(block.name)) {
1405
1448
  const input = block.input;
1406
1449
  if (input.run_in_background === true) {
1407
1450
  backgroundAgentParentIds.add(block.id);
1408
1451
  }
1409
- taskMetaMap.set(block.id, {
1410
- name: input.name ?? null,
1411
- subagentType: input.subagent_type ?? null
1412
- });
1452
+ taskMetaMap.set(block.id, readTaskMeta(input));
1413
1453
  }
1414
1454
  }
1415
1455
  }
@@ -1420,6 +1460,7 @@ function buildTurnsWithStarts(messages) {
1420
1460
  if (isProgressMessage(msg) && msg.data.type === "agent_progress") {
1421
1461
  const data = msg.data;
1422
1462
  const parentId = msg.parentToolUseID ?? "";
1463
+ const ownToolUseId = data.toolUseId ?? parentId;
1423
1464
  let subAgentUsage = null;
1424
1465
  if (data.message.type === "assistant") {
1425
1466
  const innerMsg = data.message.message;
@@ -1436,12 +1477,14 @@ function buildTurnsWithStarts(messages) {
1436
1477
  }
1437
1478
  }
1438
1479
  const innerModel = data.message.type === "assistant" ? data.message.message.model ?? null : null;
1439
- const taskMeta = taskMetaMap.get(parentId);
1480
+ const taskMeta = taskMetaMap.get(ownToolUseId);
1440
1481
  const agentMsg = {
1441
1482
  agentId: data.agentId,
1442
- parentToolUseId: parentId || void 0,
1483
+ parentToolUseId: ownToolUseId || void 0,
1484
+ ...data.parentAgentId ? { parentAgentId: data.parentAgentId } : {},
1485
+ ...taskMeta?.effort ? { effort: taskMeta.effort } : {},
1443
1486
  agentName: taskMeta?.name ?? null,
1444
- subagentType: taskMeta?.subagentType ?? null,
1487
+ subagentType: taskMeta?.subagentType ?? data.subagentType ?? null,
1445
1488
  type: data.message.type,
1446
1489
  content: data.message.message.content,
1447
1490
  toolCalls: [],
@@ -1461,6 +1504,7 @@ function buildTurnsWithStarts(messages) {
1461
1504
  } else if (block.type === "text") {
1462
1505
  agentMsg.text.push(block.text);
1463
1506
  } else if (block.type === "tool_use") {
1507
+ if (isTaskToolName(block.name)) taskMetaMap.set(block.id, readTaskMeta(block.input));
1464
1508
  agentMsg.toolCalls.push({
1465
1509
  id: block.id,
1466
1510
  name: block.name,
@@ -1553,11 +1597,19 @@ function buildTurns(messages) {
1553
1597
  function isClaudeSessionText() {
1554
1598
  return true;
1555
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
+ }
1556
1608
  function parseRecords(lines) {
1557
1609
  const messages = [];
1558
1610
  for (const line of lines) {
1559
1611
  const trimmed = line.trim();
1560
- if (!trimmed) continue;
1612
+ if (!trimmed || isClaudeNoiseLine(trimmed)) continue;
1561
1613
  try {
1562
1614
  messages.push(JSON.parse(trimmed));
1563
1615
  } catch {
@@ -1662,21 +1714,24 @@ function userMessageTexts(msg) {
1662
1714
  }
1663
1715
  function collectClaudeBackgroundWork(rawMessages) {
1664
1716
  const launches = [];
1665
- const resolved = /* @__PURE__ */ new Set();
1717
+ const resolvedAt = /* @__PURE__ */ new Map();
1666
1718
  const queuedIds = /* @__PURE__ */ new Set();
1667
1719
  const deliveredIds = /* @__PURE__ */ new Set();
1668
- 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) {
1669
1724
  if (!text.includes(TASK_NOTIFICATION_MARKER)) return;
1670
1725
  for (const match of text.matchAll(TASK_ID_RE)) {
1671
- resolved.add(match[1]);
1726
+ resolve2(match[1], index);
1672
1727
  sink?.add(match[1]);
1673
1728
  }
1674
1729
  for (const match of text.matchAll(TOOL_USE_ID_RE)) {
1675
- resolved.add(match[1]);
1730
+ resolve2(match[1], index);
1676
1731
  sink?.add(match[1]);
1677
1732
  }
1678
1733
  }
1679
- for (const msg of rawMessages) {
1734
+ for (const [index, msg] of rawMessages.entries()) {
1680
1735
  if (msg.type === "user") {
1681
1736
  const toolUseResult = isObject(msg.toolUseResult) ? msg.toolUseResult : null;
1682
1737
  if (toolUseResult?.status === "async_launched") {
@@ -1685,9 +1740,11 @@ function collectClaudeBackgroundWork(rawMessages) {
1685
1740
  const toolUseIds = blocks.filter((block) => isObject(block) && block.type === "tool_result").map((block) => block.tool_use_id);
1686
1741
  const ids = [toolUseResult.agentId, toolUseResult.taskId, ...toolUseIds].filter((id) => typeof id === "string" && id.length > 0);
1687
1742
  const description = [toolUseResult.description, toolUseResult.workflowName, toolUseResult.summary].find((value) => typeof value === "string" && value.length > 0) ?? "";
1688
- 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 } });
1689
1746
  }
1690
- for (const text of userMessageTexts(msg)) noteNotifications(text, deliveredIds);
1747
+ for (const text of userMessageTexts(msg)) noteNotifications(text, index, deliveredIds);
1691
1748
  continue;
1692
1749
  }
1693
1750
  if (msg.type === "assistant") {
@@ -1697,33 +1754,28 @@ function collectClaudeBackgroundWork(rawMessages) {
1697
1754
  if (!isObject(block) || block.type !== "tool_use" || block.name !== "TaskStop") continue;
1698
1755
  const input = isObject(block.input) ? block.input : null;
1699
1756
  const taskId = input?.task_id ?? input?.shell_id;
1700
- if (typeof taskId === "string") resolved.add(taskId);
1757
+ if (typeof taskId === "string") resolve2(taskId, index);
1701
1758
  }
1702
1759
  continue;
1703
1760
  }
1704
1761
  if (msg.type === "attachment") {
1705
1762
  const attachment = isObject(msg.attachment) ? msg.attachment : null;
1706
- if (typeof attachment?.prompt === "string") noteNotifications(attachment.prompt, deliveredIds);
1763
+ if (typeof attachment?.prompt === "string") noteNotifications(attachment.prompt, index, deliveredIds);
1707
1764
  continue;
1708
1765
  }
1709
1766
  if (msg.type === "queue-operation" && typeof msg.content === "string") {
1710
1767
  const op = msg.operation;
1711
- noteNotifications(msg.content, op === "enqueue" ? queuedIds : deliveredIds);
1768
+ noteNotifications(msg.content, index, op === "enqueue" ? queuedIds : deliveredIds);
1712
1769
  }
1713
1770
  }
1714
1771
  return {
1715
- 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
+ }),
1716
1776
  undeliveredNotifications: [...queuedIds].filter((id) => !deliveredIds.has(id)).length
1717
1777
  };
1718
1778
  }
1719
- function awaitingAgentsResult(pendingDescriptions, pendingQueue) {
1720
- return {
1721
- status: "awaiting_agents",
1722
- pendingQueue,
1723
- pendingAgents: pendingDescriptions.length,
1724
- pendingAgentDescriptions: pendingDescriptions.filter((description) => description.length > 0)
1725
- };
1726
- }
1727
1779
  function deriveClaudeSessionStatus(rawMessages) {
1728
1780
  let pendingEnqueues = 0;
1729
1781
  let backgroundWork = null;
@@ -1769,9 +1821,8 @@ function deriveClaudeSessionStatus(rawMessages) {
1769
1821
  if (stopReason === "end_turn") {
1770
1822
  const work = getBackgroundWork();
1771
1823
  if (deliveringNotification || work.undeliveredNotifications > 0) return result("processing");
1772
- if (work.pendingDescriptions.length > 0) {
1773
- return awaitingAgentsResult(work.pendingDescriptions, Math.max(0, pendingEnqueues));
1774
- }
1824
+ const awaiting = awaitingAgentsStatus(work.launches, Math.max(0, pendingEnqueues));
1825
+ if (awaiting) return awaiting;
1775
1826
  let hasActivity = false;
1776
1827
  for (let j = i - 1; j >= 0; j--) {
1777
1828
  const m = rawMessages[j];
@@ -2168,6 +2219,48 @@ function codexParentId(payload) {
2168
2219
  }
2169
2220
  return null;
2170
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
+ }
2171
2264
  function isCodexRecord(record2) {
2172
2265
  if (!record2 || typeof record2.type !== "string") return false;
2173
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";
@@ -2365,22 +2458,39 @@ function createTurn2(turnId, timestamp, model) {
2365
2458
  model
2366
2459
  };
2367
2460
  }
2368
- function extractPromptFromRecord(record2) {
2369
- if (record2.type === "event_msg" && isObject3(record2.payload) && record2.payload.type === "user_message" && typeof record2.payload.message === "string") {
2370
- return normalizePromptText(record2.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);
2371
2465
  }
2372
- if (record2.type === "response_item" && isObject3(record2.payload) && record2.payload.type === "message" && record2.payload.role === "user") {
2373
- return normalizePromptText(extractMessageText(record2.payload, "input_text"));
2466
+ if (record2.type === "response_item" && payload?.type === "message" && payload.role === "user") {
2467
+ return normalizePromptText(extractMessageText(payload, "input_text"));
2374
2468
  }
2375
2469
  return "";
2376
2470
  }
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
+ }
2377
2487
  function recordOpensTurn(record2, payload) {
2378
2488
  if (record2.type === "session_meta") return false;
2379
2489
  if (record2.type === "event_msg" && payload?.type === "task_started") return false;
2380
2490
  if (record2.type === "response_item" && payload?.type === "message") {
2381
2491
  if (payload.role === "developer" || payload.role === "system") return false;
2382
2492
  if (payload.role === "user") {
2383
- return extractPromptFromRecord(record2) !== "" || extractResponseMessageImages(payload).length > 0 || extractResponseMessageAudio(payload).length > 0;
2493
+ return codexPromptText(record2) !== "" || extractResponseMessageImages(payload).length > 0 || extractResponseMessageAudio(payload).length > 0;
2384
2494
  }
2385
2495
  }
2386
2496
  return true;
@@ -2400,9 +2510,10 @@ function extractMetadataFromRecords(records) {
2400
2510
  let isSubagent = false;
2401
2511
  let parentSessionId = null;
2402
2512
  let agentPath = "/root";
2403
- let previousPrompt = "";
2513
+ const readPrompt = createCodexPromptReader();
2514
+ const isInherited = inheritedHistoryFilter(records);
2404
2515
  for (const record2 of records) {
2405
- if (!isObject3(record2.payload)) continue;
2516
+ if (!isObject3(record2.payload) || isInherited?.(record2)) continue;
2406
2517
  if (record2.type === "session_meta") {
2407
2518
  sessionId ||= typeof record2.payload.id === "string" ? record2.payload.id : "";
2408
2519
  version ||= typeof record2.payload.cli_version === "string" ? record2.payload.cli_version : "";
@@ -2432,12 +2543,10 @@ function extractMetadataFromRecords(records) {
2432
2543
  model ||= typeof record2.payload.model === "string" ? record2.payload.model : "";
2433
2544
  cwd ||= typeof record2.payload.cwd === "string" ? record2.payload.cwd : "";
2434
2545
  }
2435
- const prompt = extractPromptFromRecord(record2);
2546
+ const prompt = readPrompt(record2);
2436
2547
  if (!prompt) continue;
2437
- if (prompt === previousPrompt) continue;
2438
2548
  if (!firstUserMessage) firstUserMessage = prompt;
2439
2549
  lastUserMessage = prompt;
2440
- previousPrompt = prompt;
2441
2550
  turnCount++;
2442
2551
  if (!timestamp) timestamp = record2.timestamp ?? "";
2443
2552
  lastTimestamp = record2.timestamp ?? lastTimestamp;
@@ -2507,6 +2616,7 @@ function walkCodexRecords(records, options) {
2507
2616
  timestamp: info?.timestamp ?? eventTimestamp2,
2508
2617
  tokenUsage: null,
2509
2618
  model: info?.model ?? null,
2619
+ ...info?.effort ? { effort: info.effort } : {},
2510
2620
  isBackground: false,
2511
2621
  prompt: info?.message || void 0,
2512
2622
  status: update.status ?? "running"
@@ -2527,6 +2637,7 @@ function walkCodexRecords(records, options) {
2527
2637
  agentMessage.agentName = info.nickname ?? (info.agentPath ? agentNameFromPath(info.agentPath) : agentMessage.agentName);
2528
2638
  agentMessage.subagentType = info.agentType;
2529
2639
  agentMessage.model = info.model;
2640
+ if (info.effort) agentMessage.effort = info.effort;
2530
2641
  agentMessage.prompt = info.message || agentMessage.prompt;
2531
2642
  }
2532
2643
  if (update.text && !agentMessage.text.includes(update.text)) {
@@ -2597,9 +2708,10 @@ function walkCodexRecords(records, options) {
2597
2708
  webSearchCalls.set(id, toolCall);
2598
2709
  appendToolCall(targetTurn, toolCall, timestamp);
2599
2710
  }
2711
+ const isInherited = inheritedHistoryFilter(records);
2600
2712
  for (let index = 0; index < records.length; index++) {
2601
2713
  const record2 = records[index];
2602
- if (!isCodexRecord(record2)) continue;
2714
+ if (!isCodexRecord(record2) || isInherited?.(record2)) continue;
2603
2715
  recordIndex = index;
2604
2716
  const payload = isObject3(record2.payload) ? record2.payload : void 0;
2605
2717
  const timestamp = record2.timestamp ?? "";
@@ -2688,12 +2800,18 @@ function walkCodexRecords(records, options) {
2688
2800
  }
2689
2801
  continue;
2690
2802
  }
2691
- if (record2.type === "event_msg" && payload?.type === "sub_agent_activity" && typeof payload.agent_thread_id === "string" && typeof payload.agent_path === "string") {
2692
- const agentId = payload.agent_thread_id;
2693
- const eventId2 = typeof payload.event_id === "string" ? payload.event_id : "";
2694
- 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;
2695
2813
  const spawnInfo = eventId2 ? spawnAgentCalls.get(eventId2) : void 0;
2696
- const existingId = agentIdByPath.get(payload.agent_path);
2814
+ const existingId = agentIdByPath.get(agentPath);
2697
2815
  const existing = agentRegistry.get(agentId) ?? (existingId ? agentRegistry.get(existingId) : void 0);
2698
2816
  if (kind !== "started" && !existing && !spawnInfo) continue;
2699
2817
  if (existingId && existingId !== agentId && !agentMessages.has(agentId)) {
@@ -2707,18 +2825,19 @@ function walkCodexRecords(records, options) {
2707
2825
  }
2708
2826
  const info = {
2709
2827
  agentId,
2710
- nickname: existing?.nickname ?? agentNameFromPath(payload.agent_path) ?? spawnInfo?.taskName ?? null,
2711
- agentPath: payload.agent_path,
2828
+ nickname: existing?.nickname ?? agentNameFromPath(agentPath) ?? spawnInfo?.taskName ?? null,
2829
+ agentPath,
2712
2830
  message: existing?.message ?? spawnInfo?.message ?? "",
2713
- model: existing?.model ?? spawnInfo?.model ?? null,
2831
+ model: activity.model ?? existing?.model ?? spawnInfo?.model ?? null,
2832
+ effort: activity.effort ?? existing?.effort ?? null,
2714
2833
  agentType: existing?.agentType ?? spawnInfo?.agentType ?? null,
2715
2834
  timestamp: existing?.timestamp ?? (timestamp || spawnInfo?.timestamp || ""),
2716
2835
  parentToolCallId: existing?.parentToolCallId ?? eventId2
2717
2836
  };
2718
2837
  agentRegistry.set(agentId, info);
2719
- agentIdByPath.set(payload.agent_path, agentId);
2838
+ agentIdByPath.set(agentPath, agentId);
2720
2839
  if (eventId2 && (kind === "started" || spawnInfo)) agentIdBySpawnCall.set(eventId2, agentId);
2721
- const status = kind === "interrupted" ? "interrupted" : "running";
2840
+ const status = kind === "interrupted" || kind === "completed" ? kind : "running";
2722
2841
  upsertAgentMessage(agentId, current, timestamp, { status });
2723
2842
  continue;
2724
2843
  }
@@ -2874,6 +2993,7 @@ function walkCodexRecords(records, options) {
2874
2993
  agentPath: agentPath ?? existing?.agentPath ?? null,
2875
2994
  message: existing?.message ?? spawnInfo?.message ?? "",
2876
2995
  model: existing?.model ?? spawnInfo?.model ?? null,
2996
+ effort: existing?.effort ?? null,
2877
2997
  agentType: existing?.agentType ?? spawnInfo?.agentType ?? null,
2878
2998
  timestamp: existing?.timestamp ?? spawnInfo?.timestamp ?? timestamp,
2879
2999
  parentToolCallId: existing?.parentToolCallId ?? toolCall.id
@@ -2992,8 +3112,10 @@ function walkCodexRecords(records, options) {
2992
3112
  }
2993
3113
  function parseCodexSession(jsonlText, options) {
2994
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;
2995
3117
  const { turnStartIndices: _starts, ...session } = walkCodexRecords(
2996
- records,
3118
+ ownRecords,
2997
3119
  options
2998
3120
  );
2999
3121
  return session;
@@ -3018,40 +3140,48 @@ function parseJsonObject(value) {
3018
3140
  return null;
3019
3141
  }
3020
3142
  }
3021
- function collectCodexPendingAgents(rawMessages) {
3022
- const alive = /* @__PURE__ */ new Map();
3023
- 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();
3024
3147
  const agentIdByPath = /* @__PURE__ */ new Map();
3025
3148
  const spawnCalls = /* @__PURE__ */ new Map();
3026
3149
  const waitCalls = /* @__PURE__ */ new Set();
3027
3150
  const interruptCalls = /* @__PURE__ */ new Map();
3028
- function markAlive(agentId, description) {
3029
- if (!done.has(agentId)) alive.set(agentId, alive.get(agentId) || description);
3030
- }
3031
- 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()) {
3032
3163
  const payload = isObject3(msg.payload) ? msg.payload : null;
3033
3164
  if (!payload) continue;
3034
- if (msg.type === "event_msg" && payload.type === "sub_agent_activity" && typeof payload.agent_thread_id === "string" && typeof payload.agent_path === "string") {
3035
- const agentId = payload.agent_thread_id;
3036
- const kind = typeof payload.kind === "string" ? payload.kind : "started";
3037
- const eventId2 = typeof payload.event_id === "string" ? payload.event_id : "";
3038
- const existingId = agentIdByPath.get(payload.agent_path);
3039
- 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);
3040
3171
  if (kind !== "started" && !known) continue;
3041
3172
  if (existingId && existingId !== agentId) {
3042
- if (alive.has(existingId)) {
3043
- markAlive(agentId, alive.get(existingId) ?? "");
3044
- alive.delete(existingId);
3045
- }
3046
- if (done.has(existingId)) done.add(agentId);
3047
- }
3048
- agentIdByPath.set(payload.agent_path, agentId);
3049
- if (kind === "interrupted") {
3050
- done.add(agentId);
3051
- alive.delete(agentId);
3052
- } else {
3053
- 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);
3054
3181
  }
3182
+ agentIdByPath.set(agentPath, agentId);
3183
+ if (kind === "interrupted" || kind === "completed") markEnded(agentId, index);
3184
+ else markAlive(agentId, spawnCalls.get(eventId2) ?? "", index, timestamp);
3055
3185
  continue;
3056
3186
  }
3057
3187
  if (msg.type !== "response_item") continue;
@@ -3075,7 +3205,7 @@ function collectCodexPendingAgents(rawMessages) {
3075
3205
  const output = parseJsonObject(payload.output);
3076
3206
  const agentId = typeof output?.agent_id === "string" ? output.agent_id : "";
3077
3207
  if (agentId) {
3078
- markAlive(agentId, spawnCalls.get(callId) ?? "");
3208
+ markAlive(agentId, spawnCalls.get(callId) ?? "", index, timestamp);
3079
3209
  const agentPath = typeof output?.task_name === "string" ? output.task_name : "";
3080
3210
  if (agentPath && !agentIdByPath.has(agentPath)) agentIdByPath.set(agentPath, agentId);
3081
3211
  }
@@ -3086,16 +3216,10 @@ function collectCodexPendingAgents(rawMessages) {
3086
3216
  const statusValue = isObject3(status) ? status : {};
3087
3217
  const lifecycle = typeof statusValue.status === "string" ? statusValue.status : "";
3088
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";
3089
- if (isTerminal) {
3090
- done.add(agentId);
3091
- alive.delete(agentId);
3092
- }
3219
+ if (isTerminal) markEnded(agentId, index);
3093
3220
  }
3094
3221
  } else if (interruptCalls.has(callId)) {
3095
- for (const agentId of interruptCalls.get(callId) ?? []) {
3096
- done.add(agentId);
3097
- alive.delete(agentId);
3098
- }
3222
+ for (const agentId of interruptCalls.get(callId) ?? []) markEnded(agentId, index);
3099
3223
  }
3100
3224
  continue;
3101
3225
  }
@@ -3103,12 +3227,14 @@ function collectCodexPendingAgents(rawMessages) {
3103
3227
  const text = codexPayloadText(payload);
3104
3228
  const messageType = text.match(/^Message Type:\s*([^\r\n]+)/)?.[1]?.trim().toUpperCase() ?? "";
3105
3229
  if (!TERMINAL_INTER_AGENT_TYPES.has(messageType)) continue;
3106
- const agentId = agentIdByPath.get(payload.author) ?? payload.author;
3107
- done.add(agentId);
3108
- alive.delete(agentId);
3230
+ markEnded(agentIdByPath.get(payload.author) ?? payload.author, index);
3109
3231
  }
3110
3232
  }
3111
- 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
+ }));
3112
3238
  }
3113
3239
  function deriveCodexSessionStatus(rawMessages) {
3114
3240
  for (let i = rawMessages.length - 1; i >= 0; i--) {
@@ -3117,16 +3243,7 @@ function deriveCodexSessionStatus(rawMessages) {
3117
3243
  const payload = msg.payload;
3118
3244
  switch (payload?.type) {
3119
3245
  case "task_complete": {
3120
- const pending = collectCodexPendingAgents(rawMessages);
3121
- if (pending.length > 0) {
3122
- return {
3123
- status: "awaiting_agents",
3124
- pendingQueue: 0,
3125
- pendingAgents: pending.length,
3126
- pendingAgentDescriptions: pending.filter((description) => description.length > 0)
3127
- };
3128
- }
3129
- return { status: "completed" };
3246
+ return awaitingAgentsStatus(collectCodexBackgroundAgents(rawMessages)) ?? { status: "completed" };
3130
3247
  }
3131
3248
  case "task_started":
3132
3249
  return { status: "processing" };
@@ -3924,33 +4041,32 @@ function isCopilotEventType(type) {
3924
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."));
3925
4042
  }
3926
4043
  function deriveCopilotSessionStatus(rawMessages) {
3927
- const pendingAgents = /* @__PURE__ */ new Map();
3928
- for (const event of rawMessages) {
4044
+ const agents = /* @__PURE__ */ new Map();
4045
+ for (const [index, event] of rawMessages.entries()) {
3929
4046
  const agentId = typeof event.agentId === "string" ? event.agentId : "";
3930
4047
  if (!agentId && (event.type === "abort" || event.type === "session.shutdown" || event.type === "session.error")) {
3931
- pendingAgents.clear();
4048
+ agents.clear();
3932
4049
  continue;
3933
4050
  }
3934
4051
  if (!agentId || !event.type.startsWith("subagent.")) continue;
3935
4052
  const data = isObject4(event.data) ? event.data : {};
4053
+ const launch = agents.get(agentId);
3936
4054
  if (event.type === "subagent.completed" || event.type === "subagent.failed") {
3937
- pendingAgents.delete(agentId);
4055
+ if (launch) launch.endedAt ??= index;
3938
4056
  continue;
3939
4057
  }
3940
4058
  if (event.type === "subagent.started" || event.type === "subagent.configured") {
3941
4059
  const description = [data.agentDisplayName, data.description, data.agentName].find((value) => typeof value === "string") ?? "";
3942
- 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
+ }
3943
4066
  }
3944
4067
  }
3945
- if (pendingAgents.size > 0) {
3946
- const descriptions = [...pendingAgents.values()];
3947
- return {
3948
- status: "awaiting_agents",
3949
- pendingQueue: 0,
3950
- pendingAgents: descriptions.length,
3951
- pendingAgentDescriptions: descriptions.filter((description) => description.length > 0)
3952
- };
3953
- }
4068
+ const awaiting = awaitingAgentsStatus([...agents.values()]);
4069
+ if (awaiting) return awaiting;
3954
4070
  let sawUserActivity = false;
3955
4071
  const completedPermissionRequests = /* @__PURE__ */ new Set();
3956
4072
  for (let i = rawMessages.length - 1; i >= 0; i--) {
@@ -4036,6 +4152,7 @@ function copilotTurnBoundaries(records) {
4036
4152
 
4037
4153
  // src/lib/agents.ts
4038
4154
  var TERMINAL_AGENT_KIND = AGENT_KINDS[AGENT_KINDS.length - 1];
4155
+ var hasNoNoiseLines = () => false;
4039
4156
  var codexFormat = {
4040
4157
  kind: "codex",
4041
4158
  descriptor: descriptorFor("codex"),
@@ -4045,6 +4162,8 @@ var codexFormat = {
4045
4162
  append: appendCodexSession,
4046
4163
  metadataFromLines: extractCodexMetadataFromLines,
4047
4164
  status: deriveCodexSessionStatus,
4165
+ isNoiseLine: hasNoNoiseLines,
4166
+ pageHeaderLine: codexPageHeaderLine,
4048
4167
  brandBranch: brandCodexBranch,
4049
4168
  turnBoundaries: codexTurnBoundaries
4050
4169
  };
@@ -4057,6 +4176,7 @@ var copilotFormat = {
4057
4176
  append: appendCopilotSession,
4058
4177
  metadataFromLines: extractCopilotMetadataFromLines,
4059
4178
  status: deriveCopilotSessionStatus,
4179
+ isNoiseLine: hasNoNoiseLines,
4060
4180
  brandBranch: brandCopilotBranch,
4061
4181
  turnBoundaries: copilotTurnBoundaries
4062
4182
  };
@@ -4070,6 +4190,7 @@ var claudeFormat = {
4070
4190
  append: appendClaudeSession,
4071
4191
  metadataFromLines: extractClaudeMetadataFromLines,
4072
4192
  status: deriveClaudeSessionStatus,
4193
+ isNoiseLine: isClaudeNoiseLine,
4073
4194
  brandBranch: brandClaudeBranch,
4074
4195
  turnBoundaries: claudeTurnBoundaries
4075
4196
  };
@@ -4099,6 +4220,9 @@ function formatForText(jsonlText) {
4099
4220
  function formatForRecords(records) {
4100
4221
  return firstMatch((format) => format.detectsRecords(records));
4101
4222
  }
4223
+ function isAnyAgentNoiseLine(line) {
4224
+ return AGENT_KINDS.some((kind) => FORMATS[kind].isNoiseLine(line));
4225
+ }
4102
4226
 
4103
4227
  // src/lib/parser.ts
4104
4228
  function extractTextFromContent2(content) {
@@ -4124,8 +4248,55 @@ function getUserMessageImages(content) {
4124
4248
  return content.filter((b) => b.type === "image");
4125
4249
  }
4126
4250
 
4127
- // src/lib/stores.ts
4251
+ // src/lib/transcriptFile.ts
4128
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");
4129
4300
  var import_node_path2 = require("node:path");
4130
4301
 
4131
4302
  // src/lib/dirs.ts
@@ -4152,14 +4323,14 @@ var MAX_WALK_DEPTH = 4;
4152
4323
  var SUBAGENTS_DIR = "subagents";
4153
4324
  function mtimeOf(filePath) {
4154
4325
  try {
4155
- return (0, import_node_fs.statSync)(filePath).mtimeMs;
4326
+ return (0, import_node_fs2.statSync)(filePath).mtimeMs;
4156
4327
  } catch {
4157
4328
  return null;
4158
4329
  }
4159
4330
  }
4160
4331
  function readDirSafe(dir) {
4161
4332
  try {
4162
- return (0, import_node_fs.readdirSync)(dir, { withFileTypes: true });
4333
+ return (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true });
4163
4334
  } catch {
4164
4335
  return [];
4165
4336
  }
@@ -4170,8 +4341,8 @@ function isWithin(root, target) {
4170
4341
  }
4171
4342
  function canonicalWithinRoot(root, filePath) {
4172
4343
  try {
4173
- const realRoot = (0, import_node_fs.realpathSync)(root);
4174
- 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);
4175
4346
  return isWithin(realRoot, real) ? real : null;
4176
4347
  } catch {
4177
4348
  return null;
@@ -4237,13 +4408,15 @@ function walkClaude(root, cutoffMs) {
4237
4408
  function walkCodex(root, cutoffMs, dir = root, depth = 0) {
4238
4409
  if (depth > MAX_WALK_DEPTH) return [];
4239
4410
  const found = [];
4240
- 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) {
4241
4414
  const filePath = (0, import_node_path2.join)(dir, entry.name);
4242
4415
  if (entry.isDirectory()) {
4243
4416
  found.push(...walkCodex(root, cutoffMs, filePath, depth + 1));
4244
4417
  continue;
4245
4418
  }
4246
- if (!entry.name.endsWith(".jsonl")) continue;
4419
+ if (!isListableTranscript(entry.name, names)) continue;
4247
4420
  const mtimeMs = mtimeOf(filePath);
4248
4421
  if (mtimeMs === null || mtimeMs < cutoffMs) continue;
4249
4422
  found.push({
@@ -4304,14 +4477,18 @@ var WALKERS = {
4304
4477
  find(root, sessionId) {
4305
4478
  const walk = (dir, depth) => {
4306
4479
  if (depth > MAX_WALK_DEPTH) return null;
4307
- 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) {
4308
4483
  const filePath = (0, import_node_path2.join)(dir, entry.name);
4309
4484
  if (entry.isDirectory()) {
4310
4485
  const match = walk(filePath, depth + 1);
4311
4486
  if (match) return match;
4312
4487
  continue;
4313
4488
  }
4314
- if (entry.name.endsWith(`${sessionId}.jsonl`)) return filePath;
4489
+ if (uncompressedTranscriptName(entry.name).endsWith(`${sessionId}.jsonl`) && isListableTranscript(entry.name, names)) {
4490
+ return filePath;
4491
+ }
4315
4492
  }
4316
4493
  return null;
4317
4494
  };
@@ -4354,7 +4531,7 @@ function makeStore(kind, home, configuredId) {
4354
4531
  ownsPath: (filePath) => {
4355
4532
  if (isWithin((0, import_node_path2.resolve)(root()), (0, import_node_path2.resolve)(filePath))) return true;
4356
4533
  try {
4357
- return isWithin((0, import_node_fs.realpathSync)(root()), (0, import_node_fs.realpathSync)(filePath));
4534
+ return isWithin((0, import_node_fs2.realpathSync)(root()), (0, import_node_fs2.realpathSync)(filePath));
4358
4535
  } catch {
4359
4536
  return false;
4360
4537
  }
@@ -4388,7 +4565,7 @@ function allStores() {
4388
4565
  if (!entry.isDirectory()) continue;
4389
4566
  const home = (0, import_node_path2.join)(root, "provider-instances", entry.name);
4390
4567
  try {
4391
- const config = JSON.parse((0, import_node_fs.readFileSync)((0, import_node_path2.join)(home, "config.json"), "utf8"));
4568
+ const config = JSON.parse((0, import_node_fs2.readFileSync)((0, import_node_path2.join)(home, "config.json"), "utf8"));
4392
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));
4393
4570
  } catch {
4394
4571
  }
@@ -4463,7 +4640,7 @@ var SearchIndex = class {
4463
4640
  const { count: totalRows } = this.db.prepare("SELECT COUNT(*) as count FROM search_content").get();
4464
4641
  let dbSizeBytes = 0;
4465
4642
  try {
4466
- dbSizeBytes = (0, import_node_fs2.statSync)(this.dbPath).size;
4643
+ dbSizeBytes = (0, import_node_fs3.statSync)(this.dbPath).size;
4467
4644
  } catch {
4468
4645
  }
4469
4646
  return {
@@ -4536,9 +4713,9 @@ var SearchIndex = class {
4536
4713
  indexFile(filePath, sessionId, mtimeMs, opts) {
4537
4714
  const resolvedSessionId = sessionId ?? identifyTranscript(filePath).sessionId;
4538
4715
  if (mtimeMs == null) {
4539
- mtimeMs = (0, import_node_fs2.statSync)(filePath).mtimeMs;
4716
+ mtimeMs = (0, import_node_fs3.statSync)(filePath).mtimeMs;
4540
4717
  }
4541
- const content = (0, import_node_fs2.readFileSync)(filePath, "utf-8");
4718
+ const content = readTranscriptTextSync(filePath);
4542
4719
  const session = parseSession(content, { skipStats: true });
4543
4720
  const isSubagent = opts?.isSubagent ? 1 : 0;
4544
4721
  const parentSessionId = opts?.parentSessionId ?? null;
@@ -4567,7 +4744,7 @@ var SearchIndex = class {
4567
4744
  const files = this.db.prepare("SELECT file_path FROM indexed_files").all();
4568
4745
  const missing = files.filter(({ file_path }) => {
4569
4746
  try {
4570
- (0, import_node_fs2.statSync)(file_path);
4747
+ (0, import_node_fs3.statSync)(file_path);
4571
4748
  return false;
4572
4749
  } catch (error) {
4573
4750
  const code = error.code;
@@ -4684,7 +4861,7 @@ var SearchIndex = class {
4684
4861
  this.db.close();
4685
4862
  for (const suffix of ["", "-wal", "-shm"]) {
4686
4863
  try {
4687
- (0, import_node_fs2.unlinkSync)(this.dbPath + suffix);
4864
+ (0, import_node_fs3.unlinkSync)(this.dbPath + suffix);
4688
4865
  } catch {
4689
4866
  }
4690
4867
  }
@@ -4708,7 +4885,7 @@ var SearchIndex = class {
4708
4885
  const txn = this.db.transaction(() => {
4709
4886
  for (const file of files) {
4710
4887
  try {
4711
- const content = (0, import_node_fs2.readFileSync)(file.path, "utf-8");
4888
+ const content = readTranscriptTextSync(file.path);
4712
4889
  const session = parseSession(content, { skipStats: true });
4713
4890
  this.insertSessionContent(insert, file.sessionId, file.path, session);
4714
4891
  insertFile.run(file.path, file.mtimeMs, file.sessionId, file.isSubagent ? 1 : 0, file.parentSessionId);
@@ -4770,8 +4947,8 @@ var SearchIndex = class {
4770
4947
  };
4771
4948
 
4772
4949
  // src/commands/search.ts
4773
- var import_node_fs3 = require("node:fs");
4774
- var import_promises = require("node:fs/promises");
4950
+ var import_node_fs4 = require("node:fs");
4951
+ var import_promises2 = require("node:fs/promises");
4775
4952
  var import_node_path3 = require("node:path");
4776
4953
 
4777
4954
  // src/lib/response.ts
@@ -4809,9 +4986,9 @@ async function searchSessions(query, opts, searchIndex) {
4809
4986
  let ownedIndex = false;
4810
4987
  if (!index && searchIndex === void 0) {
4811
4988
  try {
4812
- const dbExists = (0, import_node_fs3.existsSync)(DEFAULT_DB_PATH);
4989
+ const dbExists = (0, import_node_fs4.existsSync)(DEFAULT_DB_PATH);
4813
4990
  if (!dbExists) {
4814
- (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 });
4815
4992
  }
4816
4993
  index = new SearchIndex(DEFAULT_DB_PATH);
4817
4994
  ownedIndex = true;
@@ -4885,7 +5062,7 @@ async function cwdFromFilePath(filePath) {
4885
5062
  const cached = cwdCache.get(filePath);
4886
5063
  if (cached !== void 0) return cached;
4887
5064
  try {
4888
- const fh = await (0, import_promises.open)(filePath, "r");
5065
+ const fh = await openTranscript(filePath);
4889
5066
  try {
4890
5067
  const buf = Buffer.alloc(CWD_READ_BYTES);
4891
5068
  const { bytesRead } = await fh.read(buf, 0, CWD_READ_BYTES, 0);
@@ -4943,7 +5120,7 @@ function searchField(text, location, query, caseSensitive, extras) {
4943
5120
  async function discoverSingleSession(sessionId) {
4944
5121
  const jsonlPath = await findSessionFile(sessionId);
4945
5122
  if (!jsonlPath) return [];
4946
- const s = await (0, import_promises.stat)(jsonlPath);
5123
+ const s = await (0, import_promises2.stat)(jsonlPath);
4947
5124
  return [{ path: jsonlPath, mtimeMs: s.mtimeMs, sessionId }];
4948
5125
  }
4949
5126
  function discoverAllSessions(maxAgeMs) {
@@ -4951,7 +5128,7 @@ function discoverAllSessions(maxAgeMs) {
4951
5128
  }
4952
5129
  async function rawTextMatch(filePath, query, caseSensitive) {
4953
5130
  try {
4954
- const content = await (0, import_promises.readFile)(filePath, "utf-8");
5131
+ const content = await readTranscriptText(filePath);
4955
5132
  const haystack = caseSensitive ? content : content.toLowerCase();
4956
5133
  const needle = caseSensitive ? query : query.toLowerCase();
4957
5134
  if (haystack.includes(needle)) return content;
@@ -5026,7 +5203,7 @@ async function walkSubagentFiles(parentJsonlPath, query, caseSensitive, currentD
5026
5203
  const subDir = parentJsonlPath.replace(/\.jsonl$/, "") + "/subagents";
5027
5204
  let files;
5028
5205
  try {
5029
- files = await (0, import_promises.readdir)(subDir);
5206
+ files = await (0, import_promises2.readdir)(subDir);
5030
5207
  } catch {
5031
5208
  return [];
5032
5209
  }
@@ -5104,14 +5281,14 @@ async function rawScanSearch(query, sessionId, maxAgeMs, limit, caseSensitive, e
5104
5281
  }
5105
5282
 
5106
5283
  // src/commands/context.ts
5107
- var import_promises3 = require("node:fs/promises");
5284
+ var import_promises4 = require("node:fs/promises");
5108
5285
  var import_node_path5 = require("node:path");
5109
5286
 
5110
5287
  // src/lib/helpers.ts
5111
- var import_promises2 = require("node:fs/promises");
5288
+ var import_promises3 = require("node:fs/promises");
5112
5289
  var import_node_path4 = require("node:path");
5113
5290
  async function matchSubagentToMember(leadSessionId, subagentFileName, members) {
5114
- 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 });
5115
5292
  for (const entry of entries) {
5116
5293
  if (!entry.isDirectory() || entry.name === "memory") continue;
5117
5294
  const filePath = (0, import_node_path4.join)(
@@ -5122,7 +5299,7 @@ async function matchSubagentToMember(leadSessionId, subagentFileName, members) {
5122
5299
  subagentFileName
5123
5300
  );
5124
5301
  try {
5125
- const fh = await (0, import_promises2.open)(filePath, "r");
5302
+ const fh = await (0, import_promises3.open)(filePath, "r");
5126
5303
  try {
5127
5304
  const buf = Buffer.alloc(16384);
5128
5305
  const { bytesRead } = await fh.read(buf, 0, 16384, 0);
@@ -5317,7 +5494,13 @@ function mapContentBlock(block) {
5317
5494
  case "task_notification":
5318
5495
  return { kind: "task_notification", content: block.content, timestamp: block.timestamp ?? null };
5319
5496
  case "local_command":
5320
- return { kind: "local_command", content: block.content, timestamp: block.timestamp ?? null };
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
+ };
5321
5504
  default: {
5322
5505
  const exhaustive = block;
5323
5506
  return exhaustive;
@@ -5327,7 +5510,7 @@ function mapContentBlock(block) {
5327
5510
  async function findSubagentFile(parentJsonlPath, agentId) {
5328
5511
  const subagentsDir = parentJsonlPath.replace(/\.jsonl$/, "") + "/subagents";
5329
5512
  try {
5330
- const files = await (0, import_promises3.readdir)(subagentsDir);
5513
+ const files = await (0, import_promises4.readdir)(subagentsDir);
5331
5514
  for (const f of files) {
5332
5515
  if (!f.startsWith("agent-") || !f.endsWith(".jsonl")) continue;
5333
5516
  const fileAgentId = f.replace("agent-", "").replace(".jsonl", "");
@@ -5341,12 +5524,12 @@ async function findSubagentFile(parentJsonlPath, agentId) {
5341
5524
  }
5342
5525
  async function findTeamContext(sessionId, subagentFileName) {
5343
5526
  try {
5344
- 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 });
5345
5528
  for (const entry of teamEntries) {
5346
5529
  if (!entry.isDirectory()) continue;
5347
5530
  const configPath = (0, import_node_path5.join)(dirs.TEAMS_DIR, entry.name, "config.json");
5348
5531
  try {
5349
- const raw = await (0, import_promises3.readFile)(configPath, "utf-8");
5532
+ const raw = await (0, import_promises4.readFile)(configPath, "utf-8");
5350
5533
  const config = JSON.parse(raw);
5351
5534
  if (config.leadSessionId !== sessionId) continue;
5352
5535
  const members = config.members ?? [];
@@ -5355,10 +5538,10 @@ async function findTeamContext(sessionId, subagentFileName) {
5355
5538
  let currentTask = null;
5356
5539
  try {
5357
5540
  const taskDir = (0, import_node_path5.join)(dirs.TASKS_DIR, entry.name);
5358
- const taskFiles = await (0, import_promises3.readdir)(taskDir);
5541
+ const taskFiles = await (0, import_promises4.readdir)(taskDir);
5359
5542
  for (const tf of taskFiles) {
5360
5543
  if (!tf.endsWith(".json")) continue;
5361
- 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");
5362
5545
  const task = JSON.parse(taskRaw);
5363
5546
  if (task.owner === memberName && task.status === "in_progress") {
5364
5547
  currentTask = { id: task.id, subject: task.subject, status: task.status };
@@ -5406,14 +5589,14 @@ function findAgentMetadata(session, agentId) {
5406
5589
  async function getSessionOverview(sessionId) {
5407
5590
  const jsonlPath = await findSessionFile(sessionId);
5408
5591
  if (!jsonlPath) return { error: "Session not found" };
5409
- const content = await (0, import_promises3.readFile)(jsonlPath, "utf-8");
5592
+ const content = await readTranscriptText(jsonlPath);
5410
5593
  const session = parseTranscript(content, jsonlPath);
5411
5594
  return mapSessionToOverview(session);
5412
5595
  }
5413
5596
  async function getTurnDetail(sessionId, turnIndex) {
5414
5597
  const jsonlPath = await findSessionFile(sessionId);
5415
5598
  if (!jsonlPath) return { error: "Session not found" };
5416
- const content = await (0, import_promises3.readFile)(jsonlPath, "utf-8");
5599
+ const content = await readTranscriptText(jsonlPath);
5417
5600
  const session = parseTranscript(content, jsonlPath);
5418
5601
  if (turnIndex < 0 || turnIndex >= session.turns.length) return { error: "Turn not found" };
5419
5602
  return mapTurnToDetail(session, turnIndex);
@@ -5421,11 +5604,11 @@ async function getTurnDetail(sessionId, turnIndex) {
5421
5604
  async function getAgentOverview(sessionId, agentId) {
5422
5605
  const jsonlPath = await findSessionFile(sessionId);
5423
5606
  if (!jsonlPath) return { error: "Session not found" };
5424
- const content = await (0, import_promises3.readFile)(jsonlPath, "utf-8");
5607
+ const content = await readTranscriptText(jsonlPath);
5425
5608
  const session = parseTranscript(content, jsonlPath);
5426
5609
  const subagentFile = await findSubagentFile(jsonlPath, agentId);
5427
5610
  if (!subagentFile) return { error: "Agent not found" };
5428
- const subagentContent = await (0, import_promises3.readFile)(subagentFile.filePath, "utf-8");
5611
+ const subagentContent = await readTranscriptText(subagentFile.filePath);
5429
5612
  const subagentSession = parseTranscript(subagentContent, subagentFile.filePath);
5430
5613
  const metadata = findAgentMetadata(session, agentId);
5431
5614
  const parentToolCallId = findParentToolCallId(session, agentId);
@@ -5446,7 +5629,7 @@ async function getAgentTurnDetail(sessionId, agentId, turnIndex) {
5446
5629
  if (!jsonlPath) return { error: "Session not found" };
5447
5630
  const subagentFile = await findSubagentFile(jsonlPath, agentId);
5448
5631
  if (!subagentFile) return { error: "Agent not found" };
5449
- const subagentContent = await (0, import_promises3.readFile)(subagentFile.filePath, "utf-8");
5632
+ const subagentContent = await readTranscriptText(subagentFile.filePath);
5450
5633
  const subagentSession = parseTranscript(subagentContent, subagentFile.filePath);
5451
5634
  if (turnIndex < 0 || turnIndex >= subagentSession.turns.length) return { error: "Turn not found" };
5452
5635
  return mapTurnToDetail(subagentSession, turnIndex);
@@ -5456,7 +5639,7 @@ async function getAgentTurnDetail(sessionId, agentId, turnIndex) {
5456
5639
  var import_node_path6 = require("node:path");
5457
5640
 
5458
5641
  // src/lib/metadata.ts
5459
- var import_promises4 = require("node:fs/promises");
5642
+ var import_promises5 = require("node:fs/promises");
5460
5643
 
5461
5644
  // src/lib/sessionStatus.ts
5462
5645
  function deriveSessionStatus(rawMessages) {
@@ -5481,6 +5664,7 @@ function scanClaudeMessages(lines) {
5481
5664
  turnCount: 0
5482
5665
  };
5483
5666
  for (const line of lines) {
5667
+ if (isAnyAgentNoiseLine(line)) continue;
5484
5668
  let record2;
5485
5669
  try {
5486
5670
  record2 = JSON.parse(line);
@@ -5509,11 +5693,11 @@ function scanClaudeMessages(lines) {
5509
5693
  return meta;
5510
5694
  }
5511
5695
  async function readLines(filePath, size) {
5512
- if (size <= FULL_READ_LIMIT) {
5513
- const content = await (0, import_promises4.readFile)(filePath, "utf-8");
5696
+ if (size <= FULL_READ_LIMIT || isCompressedTranscript(filePath)) {
5697
+ const content = await readTranscriptText(filePath);
5514
5698
  return { lines: content.split("\n").filter(Boolean), isPartialRead: false };
5515
5699
  }
5516
- const handle = await (0, import_promises4.open)(filePath, "r");
5700
+ const handle = await (0, import_promises5.open)(filePath, "r");
5517
5701
  try {
5518
5702
  const buffer = Buffer.alloc(HEAD_READ_BYTES);
5519
5703
  const { bytesRead } = await handle.read(buffer, 0, HEAD_READ_BYTES, 0);
@@ -5528,11 +5712,11 @@ async function readLines(filePath, size) {
5528
5712
  }
5529
5713
  }
5530
5714
  async function getSessionMeta(filePath) {
5531
- const fileStat = await (0, import_promises4.stat)(filePath);
5715
+ const fileStat = await (0, import_promises5.stat)(filePath);
5532
5716
  let { lines, isPartialRead } = await readLines(filePath, fileStat.size);
5533
5717
  const format = formatForText(lines.join("\n"));
5534
5718
  if (isPartialRead && !format.descriptor.metadataFromHead) {
5535
- 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);
5536
5720
  isPartialRead = false;
5537
5721
  }
5538
5722
  const header = readHeader(format, lines);
@@ -5561,10 +5745,10 @@ async function getSessionStatus(filePath) {
5561
5745
  const CHUNK = 4096;
5562
5746
  const MAX_CHUNKS = 64;
5563
5747
  try {
5564
- const fileStat = await (0, import_promises4.stat)(filePath);
5565
- if (fileStat.size === 0) return { status: "idle" };
5566
- const fh = await (0, import_promises4.open)(filePath, "r");
5748
+ const fh = await openTranscript(filePath);
5567
5749
  try {
5750
+ const fileStat = await fh.stat();
5751
+ if (fileStat.size === 0) return { status: "idle" };
5568
5752
  const meaningful = [];
5569
5753
  let cursor = fileStat.size;
5570
5754
  let leftover = "";
@@ -5580,7 +5764,7 @@ async function getSessionStatus(filePath) {
5580
5764
  const startIdx = cursor > 0 ? 1 : 0;
5581
5765
  for (let i = lines.length - 1; i >= startIdx; i--) {
5582
5766
  const line = lines[i];
5583
- if (!line) continue;
5767
+ if (!line || isAnyAgentNoiseLine(line)) continue;
5584
5768
  let obj;
5585
5769
  try {
5586
5770
  obj = JSON.parse(line);
@@ -5711,11 +5895,11 @@ async function currentSession(cwd) {
5711
5895
  }
5712
5896
 
5713
5897
  // src/commands/index-cmd.ts
5714
- var import_node_fs4 = require("node:fs");
5898
+ var import_node_fs5 = require("node:fs");
5715
5899
  var import_node_path7 = require("node:path");
5716
5900
  async function indexStats(dbPath) {
5717
5901
  const path = dbPath ?? DEFAULT_DB_PATH;
5718
- if (!(0, import_node_fs4.existsSync)(path)) {
5902
+ if (!(0, import_node_fs5.existsSync)(path)) {
5719
5903
  return { error: `Database not found at ${path}. Run 'cogpit-memory index rebuild' to create it.` };
5720
5904
  }
5721
5905
  const index = new SearchIndex(path);
@@ -5725,7 +5909,7 @@ async function indexStats(dbPath) {
5725
5909
  }
5726
5910
  async function indexRebuild(dbPath) {
5727
5911
  const path = dbPath ?? DEFAULT_DB_PATH;
5728
- (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 });
5729
5913
  const index = new SearchIndex(path);
5730
5914
  index.buildFull();
5731
5915
  const stats = index.getStats();