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/cli.js +363 -179
- package/dist/index.js +358 -174
- package/dist/lib/agent-descriptors.d.ts +4 -0
- package/dist/lib/agents.d.ts +14 -0
- package/dist/lib/backgroundAgents.d.ts +16 -0
- package/dist/lib/claude.d.ts +10 -0
- package/dist/lib/codex.d.ts +25 -0
- package/dist/lib/transcriptFile.d.ts +22 -0
- package/dist/lib/types.d.ts +118 -2
- package/package.json +1 -1
- package/skill/SKILL.md +26 -346
package/dist/cli.js
CHANGED
|
@@ -36,8 +36,8 @@ __export(cli_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(cli_exports);
|
|
37
37
|
|
|
38
38
|
// src/commands/search.ts
|
|
39
|
-
var
|
|
40
|
-
var
|
|
39
|
+
var import_node_fs4 = require("node:fs");
|
|
40
|
+
var import_promises2 = require("node:fs/promises");
|
|
41
41
|
var import_node_path3 = require("node:path");
|
|
42
42
|
|
|
43
43
|
// src/lib/sqlite-node-shim.ts
|
|
@@ -45,7 +45,7 @@ var import_better_sqlite3 = __toESM(require("better-sqlite3"));
|
|
|
45
45
|
var Database = import_better_sqlite3.default;
|
|
46
46
|
|
|
47
47
|
// src/lib/search-index.ts
|
|
48
|
-
var
|
|
48
|
+
var import_node_fs3 = require("node:fs");
|
|
49
49
|
|
|
50
50
|
// src/lib/types.ts
|
|
51
51
|
var AGENT_KINDS = ["acp", "codex", "copilot", "claude"];
|
|
@@ -113,7 +113,7 @@ function base64DirNameCodec(prefix) {
|
|
|
113
113
|
};
|
|
114
114
|
}
|
|
115
115
|
function sessionIdFromJsonlName(fileName) {
|
|
116
|
-
const match = new RegExp(`(${SESSION_UUID})\\.jsonl
|
|
116
|
+
const match = new RegExp(`(${SESSION_UUID})\\.jsonl(?:\\.zst)?$`, "i").exec(fileName);
|
|
117
117
|
return match ? match[1] : null;
|
|
118
118
|
}
|
|
119
119
|
function ownTranscriptRoot(sessionId) {
|
|
@@ -283,7 +283,8 @@ var claude = {
|
|
|
283
283
|
fastTier: true,
|
|
284
284
|
lowPriorityInTerminal: true,
|
|
285
285
|
imageInput: true,
|
|
286
|
-
midTurnSteering:
|
|
286
|
+
midTurnSteering: true,
|
|
287
|
+
activeNotifications: true,
|
|
287
288
|
stopSession: true,
|
|
288
289
|
ultracode: true,
|
|
289
290
|
contextWindow: true,
|
|
@@ -369,6 +370,7 @@ var codex = {
|
|
|
369
370
|
bundledBySdk: false,
|
|
370
371
|
homeDirName: ".codex",
|
|
371
372
|
homeEnvVar: "CODEX_HOME",
|
|
373
|
+
sessionIdEnvVar: "CODEX_THREAD_ID",
|
|
372
374
|
installMarker: "",
|
|
373
375
|
homeIsDiscoverable: true,
|
|
374
376
|
process: {
|
|
@@ -419,6 +421,7 @@ var codex = {
|
|
|
419
421
|
lowPriorityInTerminal: false,
|
|
420
422
|
imageInput: true,
|
|
421
423
|
midTurnSteering: true,
|
|
424
|
+
activeNotifications: true,
|
|
422
425
|
stopSession: false,
|
|
423
426
|
ultracode: false,
|
|
424
427
|
contextWindow: false,
|
|
@@ -540,6 +543,7 @@ var copilot = {
|
|
|
540
543
|
lowPriorityInTerminal: false,
|
|
541
544
|
imageInput: false,
|
|
542
545
|
midTurnSteering: true,
|
|
546
|
+
activeNotifications: true,
|
|
543
547
|
stopSession: true,
|
|
544
548
|
ultracode: false,
|
|
545
549
|
contextWindow: false,
|
|
@@ -569,7 +573,7 @@ var acp = {
|
|
|
569
573
|
launchArgs: { permissions: () => [], model: () => [], effort: () => [], fastTier: () => [] },
|
|
570
574
|
cli: { ...copilot.cli, packageName: "", homebrew: null, wingetId: null, selfUpdate: null, requiresConfiguration: true, homeDirName: ".cogpit-acp", homeEnvVar: "COGPIT_ACP_HOME", homeIsDiscoverable: true, installMarker: "projects" },
|
|
571
575
|
config: { ...copilot.config, rootDirName: ".cogpit-acp", instructions: [], settings: [], skillsDir: null },
|
|
572
|
-
capabilities: { ...copilot.capabilities, undo: false, redo: false, nativeRewind: false, nativeFork: false, midTurnSteering: false, externalProcesses: false, autoPermissionMode: "never", toolPermissionRules: false, namedSessions: false }
|
|
576
|
+
capabilities: { ...copilot.capabilities, undo: false, redo: false, nativeRewind: false, nativeFork: false, midTurnSteering: false, activeNotifications: false, externalProcesses: false, autoPermissionMode: "never", toolPermissionRules: false, namedSessions: false }
|
|
573
577
|
};
|
|
574
578
|
var DESCRIPTORS = Object.freeze({
|
|
575
579
|
claude,
|
|
@@ -673,6 +677,27 @@ function readJsStringLiteral(source, startIndex) {
|
|
|
673
677
|
return null;
|
|
674
678
|
}
|
|
675
679
|
|
|
680
|
+
// src/lib/backgroundAgents.ts
|
|
681
|
+
function awaitingAgentsStatus(launches, pendingQueue = 0) {
|
|
682
|
+
if (!launches.some((launch) => launch.endedAt === void 0)) return null;
|
|
683
|
+
const ordered = [...launches].sort((a, b) => a.launchedAt - b.launchedAt);
|
|
684
|
+
let batchStart = 0;
|
|
685
|
+
let busyUntil = -Infinity;
|
|
686
|
+
ordered.forEach((launch, index) => {
|
|
687
|
+
if (busyUntil < launch.launchedAt) batchStart = index;
|
|
688
|
+
busyUntil = Math.max(busyUntil, launch.endedAt ?? Infinity);
|
|
689
|
+
});
|
|
690
|
+
const batch = ordered.slice(batchStart).map(({ agent, endedAt }) => ({ ...agent, done: endedAt !== void 0 }));
|
|
691
|
+
const running = batch.filter((agent) => !agent.done);
|
|
692
|
+
return {
|
|
693
|
+
status: "awaiting_agents",
|
|
694
|
+
pendingQueue,
|
|
695
|
+
pendingAgents: running.length,
|
|
696
|
+
pendingAgentDescriptions: running.map((agent) => agent.description).filter((description) => description.length > 0),
|
|
697
|
+
backgroundAgents: batch
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
|
|
676
701
|
// src/lib/messageTypeGuards.ts
|
|
677
702
|
function isUserMessage(msg) {
|
|
678
703
|
return msg.type === "user";
|
|
@@ -837,6 +862,17 @@ function isTaskNotificationRecord(msg) {
|
|
|
837
862
|
if (!text.includes("<task-notification>")) return false;
|
|
838
863
|
return text.replace(TASK_NOTIFICATION_BLOCK_RE, "").replace(ANY_TAG_RE, "").trim() === "";
|
|
839
864
|
}
|
|
865
|
+
function isTaskToolName(name) {
|
|
866
|
+
return name === "Task" || name === "Agent";
|
|
867
|
+
}
|
|
868
|
+
function readTaskMeta(input) {
|
|
869
|
+
const effort = input.effort;
|
|
870
|
+
return {
|
|
871
|
+
name: typeof input.name === "string" ? input.name : null,
|
|
872
|
+
subagentType: typeof input.subagent_type === "string" ? input.subagent_type : null,
|
|
873
|
+
effort: typeof effort === "string" || typeof effort === "number" ? String(effort) : null
|
|
874
|
+
};
|
|
875
|
+
}
|
|
840
876
|
function queuedCommandPrompt(msg) {
|
|
841
877
|
if (!isAttachmentMessage(msg)) return null;
|
|
842
878
|
const attachment = msg.attachment;
|
|
@@ -1178,7 +1214,13 @@ function buildTurnsWithStarts(messages) {
|
|
|
1178
1214
|
continue;
|
|
1179
1215
|
}
|
|
1180
1216
|
if (isSystemMessage(msg) && msg.subtype === "local_command" && msg.content) {
|
|
1181
|
-
current?.contentBlocks.push({
|
|
1217
|
+
current?.contentBlocks.push({
|
|
1218
|
+
kind: "local_command",
|
|
1219
|
+
content: msg.content,
|
|
1220
|
+
timestamp: msg.timestamp,
|
|
1221
|
+
...msg.contextUsage ? { contextUsage: msg.contextUsage } : {},
|
|
1222
|
+
...msg.usageReport ? { usageReport: msg.usageReport } : {}
|
|
1223
|
+
});
|
|
1182
1224
|
continue;
|
|
1183
1225
|
}
|
|
1184
1226
|
if (isQueueOperationMessage(msg)) {
|
|
@@ -1254,6 +1296,7 @@ function buildTurnsWithStarts(messages) {
|
|
|
1254
1296
|
parentToolUseId: toolUseId || void 0,
|
|
1255
1297
|
agentName: taskMeta?.name ?? null,
|
|
1256
1298
|
subagentType: taskMeta?.subagentType ?? null,
|
|
1299
|
+
...taskMeta?.effort ? { effort: taskMeta.effort } : {},
|
|
1257
1300
|
type: "assistant",
|
|
1258
1301
|
content: toolUseResult.content,
|
|
1259
1302
|
toolCalls: [],
|
|
@@ -1392,15 +1435,12 @@ function buildTurnsWithStarts(messages) {
|
|
|
1392
1435
|
current.toolCalls.push(tc);
|
|
1393
1436
|
msgToolCalls.push(tc);
|
|
1394
1437
|
pendingToolUses.set(block.id, { turn: current, index: idx });
|
|
1395
|
-
if (block.name
|
|
1438
|
+
if (isTaskToolName(block.name)) {
|
|
1396
1439
|
const input = block.input;
|
|
1397
1440
|
if (input.run_in_background === true) {
|
|
1398
1441
|
backgroundAgentParentIds.add(block.id);
|
|
1399
1442
|
}
|
|
1400
|
-
taskMetaMap.set(block.id,
|
|
1401
|
-
name: input.name ?? null,
|
|
1402
|
-
subagentType: input.subagent_type ?? null
|
|
1403
|
-
});
|
|
1443
|
+
taskMetaMap.set(block.id, readTaskMeta(input));
|
|
1404
1444
|
}
|
|
1405
1445
|
}
|
|
1406
1446
|
}
|
|
@@ -1411,6 +1451,7 @@ function buildTurnsWithStarts(messages) {
|
|
|
1411
1451
|
if (isProgressMessage(msg) && msg.data.type === "agent_progress") {
|
|
1412
1452
|
const data = msg.data;
|
|
1413
1453
|
const parentId = msg.parentToolUseID ?? "";
|
|
1454
|
+
const ownToolUseId = data.toolUseId ?? parentId;
|
|
1414
1455
|
let subAgentUsage = null;
|
|
1415
1456
|
if (data.message.type === "assistant") {
|
|
1416
1457
|
const innerMsg = data.message.message;
|
|
@@ -1427,12 +1468,14 @@ function buildTurnsWithStarts(messages) {
|
|
|
1427
1468
|
}
|
|
1428
1469
|
}
|
|
1429
1470
|
const innerModel = data.message.type === "assistant" ? data.message.message.model ?? null : null;
|
|
1430
|
-
const taskMeta = taskMetaMap.get(
|
|
1471
|
+
const taskMeta = taskMetaMap.get(ownToolUseId);
|
|
1431
1472
|
const agentMsg = {
|
|
1432
1473
|
agentId: data.agentId,
|
|
1433
|
-
parentToolUseId:
|
|
1474
|
+
parentToolUseId: ownToolUseId || void 0,
|
|
1475
|
+
...data.parentAgentId ? { parentAgentId: data.parentAgentId } : {},
|
|
1476
|
+
...taskMeta?.effort ? { effort: taskMeta.effort } : {},
|
|
1434
1477
|
agentName: taskMeta?.name ?? null,
|
|
1435
|
-
subagentType: taskMeta?.subagentType ?? null,
|
|
1478
|
+
subagentType: taskMeta?.subagentType ?? data.subagentType ?? null,
|
|
1436
1479
|
type: data.message.type,
|
|
1437
1480
|
content: data.message.message.content,
|
|
1438
1481
|
toolCalls: [],
|
|
@@ -1452,6 +1495,7 @@ function buildTurnsWithStarts(messages) {
|
|
|
1452
1495
|
} else if (block.type === "text") {
|
|
1453
1496
|
agentMsg.text.push(block.text);
|
|
1454
1497
|
} else if (block.type === "tool_use") {
|
|
1498
|
+
if (isTaskToolName(block.name)) taskMetaMap.set(block.id, readTaskMeta(block.input));
|
|
1455
1499
|
agentMsg.toolCalls.push({
|
|
1456
1500
|
id: block.id,
|
|
1457
1501
|
name: block.name,
|
|
@@ -1544,11 +1588,19 @@ function buildTurns(messages) {
|
|
|
1544
1588
|
function isClaudeSessionText() {
|
|
1545
1589
|
return true;
|
|
1546
1590
|
}
|
|
1591
|
+
var API_REQUEST_TYPE = '"type":"api-request';
|
|
1592
|
+
var RECORD_TYPE_WINDOW = 256;
|
|
1593
|
+
function isClaudeNoiseLine(line) {
|
|
1594
|
+
if (line.startsWith(`{${API_REQUEST_TYPE}`)) return true;
|
|
1595
|
+
const head = line.slice(0, RECORD_TYPE_WINDOW);
|
|
1596
|
+
const at = head.indexOf(API_REQUEST_TYPE);
|
|
1597
|
+
return at > 0 && head.lastIndexOf("{", at) === 0;
|
|
1598
|
+
}
|
|
1547
1599
|
function parseRecords(lines) {
|
|
1548
1600
|
const messages = [];
|
|
1549
1601
|
for (const line of lines) {
|
|
1550
1602
|
const trimmed = line.trim();
|
|
1551
|
-
if (!trimmed) continue;
|
|
1603
|
+
if (!trimmed || isClaudeNoiseLine(trimmed)) continue;
|
|
1552
1604
|
try {
|
|
1553
1605
|
messages.push(JSON.parse(trimmed));
|
|
1554
1606
|
} catch {
|
|
@@ -1653,21 +1705,24 @@ function userMessageTexts(msg) {
|
|
|
1653
1705
|
}
|
|
1654
1706
|
function collectClaudeBackgroundWork(rawMessages) {
|
|
1655
1707
|
const launches = [];
|
|
1656
|
-
const
|
|
1708
|
+
const resolvedAt = /* @__PURE__ */ new Map();
|
|
1657
1709
|
const queuedIds = /* @__PURE__ */ new Set();
|
|
1658
1710
|
const deliveredIds = /* @__PURE__ */ new Set();
|
|
1659
|
-
function
|
|
1711
|
+
function resolve2(id, index) {
|
|
1712
|
+
if (!resolvedAt.has(id)) resolvedAt.set(id, index);
|
|
1713
|
+
}
|
|
1714
|
+
function noteNotifications(text, index, sink) {
|
|
1660
1715
|
if (!text.includes(TASK_NOTIFICATION_MARKER)) return;
|
|
1661
1716
|
for (const match of text.matchAll(TASK_ID_RE)) {
|
|
1662
|
-
|
|
1717
|
+
resolve2(match[1], index);
|
|
1663
1718
|
sink?.add(match[1]);
|
|
1664
1719
|
}
|
|
1665
1720
|
for (const match of text.matchAll(TOOL_USE_ID_RE)) {
|
|
1666
|
-
|
|
1721
|
+
resolve2(match[1], index);
|
|
1667
1722
|
sink?.add(match[1]);
|
|
1668
1723
|
}
|
|
1669
1724
|
}
|
|
1670
|
-
for (const msg of rawMessages) {
|
|
1725
|
+
for (const [index, msg] of rawMessages.entries()) {
|
|
1671
1726
|
if (msg.type === "user") {
|
|
1672
1727
|
const toolUseResult = isObject(msg.toolUseResult) ? msg.toolUseResult : null;
|
|
1673
1728
|
if (toolUseResult?.status === "async_launched") {
|
|
@@ -1676,9 +1731,11 @@ function collectClaudeBackgroundWork(rawMessages) {
|
|
|
1676
1731
|
const toolUseIds = blocks.filter((block) => isObject(block) && block.type === "tool_result").map((block) => block.tool_use_id);
|
|
1677
1732
|
const ids = [toolUseResult.agentId, toolUseResult.taskId, ...toolUseIds].filter((id) => typeof id === "string" && id.length > 0);
|
|
1678
1733
|
const description = [toolUseResult.description, toolUseResult.workflowName, toolUseResult.summary].find((value) => typeof value === "string" && value.length > 0) ?? "";
|
|
1679
|
-
|
|
1734
|
+
const toolUseId = toolUseIds.find((id) => typeof id === "string" && id.length > 0);
|
|
1735
|
+
const startedAt = typeof msg.timestamp === "string" ? msg.timestamp : void 0;
|
|
1736
|
+
if (ids.length > 0) launches.push({ ids, launch: { agent: { description, startedAt, toolUseId }, launchedAt: index } });
|
|
1680
1737
|
}
|
|
1681
|
-
for (const text of userMessageTexts(msg)) noteNotifications(text, deliveredIds);
|
|
1738
|
+
for (const text of userMessageTexts(msg)) noteNotifications(text, index, deliveredIds);
|
|
1682
1739
|
continue;
|
|
1683
1740
|
}
|
|
1684
1741
|
if (msg.type === "assistant") {
|
|
@@ -1688,33 +1745,28 @@ function collectClaudeBackgroundWork(rawMessages) {
|
|
|
1688
1745
|
if (!isObject(block) || block.type !== "tool_use" || block.name !== "TaskStop") continue;
|
|
1689
1746
|
const input = isObject(block.input) ? block.input : null;
|
|
1690
1747
|
const taskId = input?.task_id ?? input?.shell_id;
|
|
1691
|
-
if (typeof taskId === "string")
|
|
1748
|
+
if (typeof taskId === "string") resolve2(taskId, index);
|
|
1692
1749
|
}
|
|
1693
1750
|
continue;
|
|
1694
1751
|
}
|
|
1695
1752
|
if (msg.type === "attachment") {
|
|
1696
1753
|
const attachment = isObject(msg.attachment) ? msg.attachment : null;
|
|
1697
|
-
if (typeof attachment?.prompt === "string") noteNotifications(attachment.prompt, deliveredIds);
|
|
1754
|
+
if (typeof attachment?.prompt === "string") noteNotifications(attachment.prompt, index, deliveredIds);
|
|
1698
1755
|
continue;
|
|
1699
1756
|
}
|
|
1700
1757
|
if (msg.type === "queue-operation" && typeof msg.content === "string") {
|
|
1701
1758
|
const op = msg.operation;
|
|
1702
|
-
noteNotifications(msg.content, op === "enqueue" ? queuedIds : deliveredIds);
|
|
1759
|
+
noteNotifications(msg.content, index, op === "enqueue" ? queuedIds : deliveredIds);
|
|
1703
1760
|
}
|
|
1704
1761
|
}
|
|
1705
1762
|
return {
|
|
1706
|
-
|
|
1763
|
+
launches: launches.map(({ ids, launch }) => {
|
|
1764
|
+
const ends = ids.flatMap((id) => resolvedAt.get(id) ?? []);
|
|
1765
|
+
return ends.length > 0 ? { ...launch, endedAt: Math.min(...ends) } : launch;
|
|
1766
|
+
}),
|
|
1707
1767
|
undeliveredNotifications: [...queuedIds].filter((id) => !deliveredIds.has(id)).length
|
|
1708
1768
|
};
|
|
1709
1769
|
}
|
|
1710
|
-
function awaitingAgentsResult(pendingDescriptions, pendingQueue) {
|
|
1711
|
-
return {
|
|
1712
|
-
status: "awaiting_agents",
|
|
1713
|
-
pendingQueue,
|
|
1714
|
-
pendingAgents: pendingDescriptions.length,
|
|
1715
|
-
pendingAgentDescriptions: pendingDescriptions.filter((description) => description.length > 0)
|
|
1716
|
-
};
|
|
1717
|
-
}
|
|
1718
1770
|
function deriveClaudeSessionStatus(rawMessages) {
|
|
1719
1771
|
let pendingEnqueues = 0;
|
|
1720
1772
|
let backgroundWork = null;
|
|
@@ -1760,9 +1812,8 @@ function deriveClaudeSessionStatus(rawMessages) {
|
|
|
1760
1812
|
if (stopReason === "end_turn") {
|
|
1761
1813
|
const work = getBackgroundWork();
|
|
1762
1814
|
if (deliveringNotification || work.undeliveredNotifications > 0) return result("processing");
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
}
|
|
1815
|
+
const awaiting = awaitingAgentsStatus(work.launches, Math.max(0, pendingEnqueues));
|
|
1816
|
+
if (awaiting) return awaiting;
|
|
1766
1817
|
let hasActivity = false;
|
|
1767
1818
|
for (let j = i - 1; j >= 0; j--) {
|
|
1768
1819
|
const m = rawMessages[j];
|
|
@@ -2159,6 +2210,48 @@ function codexParentId(payload) {
|
|
|
2159
2210
|
}
|
|
2160
2211
|
return null;
|
|
2161
2212
|
}
|
|
2213
|
+
function inheritedHistoryFilter(records) {
|
|
2214
|
+
const meta = records.find((record2) => record2?.type === "session_meta");
|
|
2215
|
+
const start = meta?.payload?.subagent_history_start_ordinal;
|
|
2216
|
+
if (typeof start !== "number") return null;
|
|
2217
|
+
const reachesPast = (ordinal) => typeof ordinal === "number" && ordinal >= start;
|
|
2218
|
+
if (!reachesPast(meta?.rolloutLastOrdinal) && !records.some((record2) => reachesPast(record2?.ordinal))) return null;
|
|
2219
|
+
return (record2) => typeof record2.ordinal === "number" && record2.ordinal > 0 && record2.ordinal < start;
|
|
2220
|
+
}
|
|
2221
|
+
async function codexPageHeaderLine(firstLine, lastLines) {
|
|
2222
|
+
if (!firstLine.includes('"subagent_history_start_ordinal"')) return firstLine;
|
|
2223
|
+
const meta = safeParseLine(firstLine);
|
|
2224
|
+
if (meta?.type !== "session_meta") return firstLine;
|
|
2225
|
+
const lines = await lastLines();
|
|
2226
|
+
for (let index = lines.length - 1; index >= 0; index--) {
|
|
2227
|
+
const ordinal = safeParseLine(lines[index])?.ordinal;
|
|
2228
|
+
if (typeof ordinal === "number") return JSON.stringify({ ...meta, rolloutLastOrdinal: ordinal });
|
|
2229
|
+
}
|
|
2230
|
+
return firstLine;
|
|
2231
|
+
}
|
|
2232
|
+
function subAgentActivitySource(record2) {
|
|
2233
|
+
const payload = record2.payload;
|
|
2234
|
+
if (record2.type !== "event_msg" || !isObject3(payload)) return null;
|
|
2235
|
+
if (payload.type === "sub_agent_activity") return payload;
|
|
2236
|
+
if (payload.type === "item_completed" && isObject3(payload.item) && payload.item.type === "SubAgentActivity") return payload.item;
|
|
2237
|
+
return null;
|
|
2238
|
+
}
|
|
2239
|
+
function readSubAgentActivity(record2) {
|
|
2240
|
+
const source = subAgentActivitySource(record2);
|
|
2241
|
+
if (!source || typeof source.agent_thread_id !== "string" || typeof source.agent_path !== "string") return null;
|
|
2242
|
+
return {
|
|
2243
|
+
agentId: source.agent_thread_id,
|
|
2244
|
+
agentPath: source.agent_path,
|
|
2245
|
+
kind: typeof source.kind === "string" ? source.kind : "started",
|
|
2246
|
+
eventId: findString(source.event_id, source.id) ?? "",
|
|
2247
|
+
model: findString(source.model) || null,
|
|
2248
|
+
effort: findString(source.reasoning_effort) || null
|
|
2249
|
+
};
|
|
2250
|
+
}
|
|
2251
|
+
function turnErrorMessage(payload) {
|
|
2252
|
+
if (payload.type !== "task_complete" || !isObject3(payload.error)) return "";
|
|
2253
|
+
return typeof payload.error.message === "string" ? payload.error.message.trim() : "";
|
|
2254
|
+
}
|
|
2162
2255
|
function isCodexRecord(record2) {
|
|
2163
2256
|
if (!record2 || typeof record2.type !== "string") return false;
|
|
2164
2257
|
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";
|
|
@@ -2356,22 +2449,39 @@ function createTurn2(turnId, timestamp, model) {
|
|
|
2356
2449
|
model
|
|
2357
2450
|
};
|
|
2358
2451
|
}
|
|
2359
|
-
function
|
|
2360
|
-
|
|
2361
|
-
|
|
2452
|
+
function codexPromptText(record2) {
|
|
2453
|
+
const payload = isObject3(record2.payload) ? record2.payload : null;
|
|
2454
|
+
if (record2.type === "event_msg" && payload?.type === "user_message" && typeof payload.message === "string") {
|
|
2455
|
+
return normalizePromptText(payload.message);
|
|
2362
2456
|
}
|
|
2363
|
-
if (record2.type === "response_item" &&
|
|
2364
|
-
return normalizePromptText(extractMessageText(
|
|
2457
|
+
if (record2.type === "response_item" && payload?.type === "message" && payload.role === "user") {
|
|
2458
|
+
return normalizePromptText(extractMessageText(payload, "input_text"));
|
|
2365
2459
|
}
|
|
2366
2460
|
return "";
|
|
2367
2461
|
}
|
|
2462
|
+
function createCodexPromptReader() {
|
|
2463
|
+
let echoPending = false;
|
|
2464
|
+
return (record2) => {
|
|
2465
|
+
const payload = isObject3(record2.payload) ? record2.payload : null;
|
|
2466
|
+
if (record2.type === "event_msg" && payload?.type === "user_message") {
|
|
2467
|
+
const isEcho = echoPending;
|
|
2468
|
+
echoPending = false;
|
|
2469
|
+
return isEcho ? "" : codexPromptText(record2);
|
|
2470
|
+
}
|
|
2471
|
+
if (record2.type !== "response_item") return "";
|
|
2472
|
+
const prompt = codexPromptText(record2);
|
|
2473
|
+
if (prompt) echoPending = true;
|
|
2474
|
+
else if (payload?.type !== "message" || payload.role !== "user") echoPending = false;
|
|
2475
|
+
return prompt;
|
|
2476
|
+
};
|
|
2477
|
+
}
|
|
2368
2478
|
function recordOpensTurn(record2, payload) {
|
|
2369
2479
|
if (record2.type === "session_meta") return false;
|
|
2370
2480
|
if (record2.type === "event_msg" && payload?.type === "task_started") return false;
|
|
2371
2481
|
if (record2.type === "response_item" && payload?.type === "message") {
|
|
2372
2482
|
if (payload.role === "developer" || payload.role === "system") return false;
|
|
2373
2483
|
if (payload.role === "user") {
|
|
2374
|
-
return
|
|
2484
|
+
return codexPromptText(record2) !== "" || extractResponseMessageImages(payload).length > 0 || extractResponseMessageAudio(payload).length > 0;
|
|
2375
2485
|
}
|
|
2376
2486
|
}
|
|
2377
2487
|
return true;
|
|
@@ -2391,9 +2501,10 @@ function extractMetadataFromRecords(records) {
|
|
|
2391
2501
|
let isSubagent = false;
|
|
2392
2502
|
let parentSessionId = null;
|
|
2393
2503
|
let agentPath = "/root";
|
|
2394
|
-
|
|
2504
|
+
const readPrompt = createCodexPromptReader();
|
|
2505
|
+
const isInherited = inheritedHistoryFilter(records);
|
|
2395
2506
|
for (const record2 of records) {
|
|
2396
|
-
if (!isObject3(record2.payload)) continue;
|
|
2507
|
+
if (!isObject3(record2.payload) || isInherited?.(record2)) continue;
|
|
2397
2508
|
if (record2.type === "session_meta") {
|
|
2398
2509
|
sessionId ||= typeof record2.payload.id === "string" ? record2.payload.id : "";
|
|
2399
2510
|
version ||= typeof record2.payload.cli_version === "string" ? record2.payload.cli_version : "";
|
|
@@ -2423,12 +2534,10 @@ function extractMetadataFromRecords(records) {
|
|
|
2423
2534
|
model ||= typeof record2.payload.model === "string" ? record2.payload.model : "";
|
|
2424
2535
|
cwd ||= typeof record2.payload.cwd === "string" ? record2.payload.cwd : "";
|
|
2425
2536
|
}
|
|
2426
|
-
const prompt =
|
|
2537
|
+
const prompt = readPrompt(record2);
|
|
2427
2538
|
if (!prompt) continue;
|
|
2428
|
-
if (prompt === previousPrompt) continue;
|
|
2429
2539
|
if (!firstUserMessage) firstUserMessage = prompt;
|
|
2430
2540
|
lastUserMessage = prompt;
|
|
2431
|
-
previousPrompt = prompt;
|
|
2432
2541
|
turnCount++;
|
|
2433
2542
|
if (!timestamp) timestamp = record2.timestamp ?? "";
|
|
2434
2543
|
lastTimestamp = record2.timestamp ?? lastTimestamp;
|
|
@@ -2498,6 +2607,7 @@ function walkCodexRecords(records, options) {
|
|
|
2498
2607
|
timestamp: info?.timestamp ?? eventTimestamp2,
|
|
2499
2608
|
tokenUsage: null,
|
|
2500
2609
|
model: info?.model ?? null,
|
|
2610
|
+
...info?.effort ? { effort: info.effort } : {},
|
|
2501
2611
|
isBackground: false,
|
|
2502
2612
|
prompt: info?.message || void 0,
|
|
2503
2613
|
status: update.status ?? "running"
|
|
@@ -2518,6 +2628,7 @@ function walkCodexRecords(records, options) {
|
|
|
2518
2628
|
agentMessage.agentName = info.nickname ?? (info.agentPath ? agentNameFromPath(info.agentPath) : agentMessage.agentName);
|
|
2519
2629
|
agentMessage.subagentType = info.agentType;
|
|
2520
2630
|
agentMessage.model = info.model;
|
|
2631
|
+
if (info.effort) agentMessage.effort = info.effort;
|
|
2521
2632
|
agentMessage.prompt = info.message || agentMessage.prompt;
|
|
2522
2633
|
}
|
|
2523
2634
|
if (update.text && !agentMessage.text.includes(update.text)) {
|
|
@@ -2588,9 +2699,10 @@ function walkCodexRecords(records, options) {
|
|
|
2588
2699
|
webSearchCalls.set(id, toolCall);
|
|
2589
2700
|
appendToolCall(targetTurn, toolCall, timestamp);
|
|
2590
2701
|
}
|
|
2702
|
+
const isInherited = inheritedHistoryFilter(records);
|
|
2591
2703
|
for (let index = 0; index < records.length; index++) {
|
|
2592
2704
|
const record2 = records[index];
|
|
2593
|
-
if (!isCodexRecord(record2)) continue;
|
|
2705
|
+
if (!isCodexRecord(record2) || isInherited?.(record2)) continue;
|
|
2594
2706
|
recordIndex = index;
|
|
2595
2707
|
const payload = isObject3(record2.payload) ? record2.payload : void 0;
|
|
2596
2708
|
const timestamp = record2.timestamp ?? "";
|
|
@@ -2679,12 +2791,18 @@ function walkCodexRecords(records, options) {
|
|
|
2679
2791
|
}
|
|
2680
2792
|
continue;
|
|
2681
2793
|
}
|
|
2682
|
-
if (record2.type === "event_msg" && payload
|
|
2683
|
-
const
|
|
2684
|
-
|
|
2685
|
-
|
|
2794
|
+
if (record2.type === "event_msg" && payload) {
|
|
2795
|
+
const turnError = turnErrorMessage(payload);
|
|
2796
|
+
if (turnError) {
|
|
2797
|
+
appendAssistantText(current, turnError, timestamp);
|
|
2798
|
+
continue;
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
const activity = readSubAgentActivity(record2);
|
|
2802
|
+
if (activity) {
|
|
2803
|
+
const { agentId, agentPath, eventId: eventId2, kind } = activity;
|
|
2686
2804
|
const spawnInfo = eventId2 ? spawnAgentCalls.get(eventId2) : void 0;
|
|
2687
|
-
const existingId = agentIdByPath.get(
|
|
2805
|
+
const existingId = agentIdByPath.get(agentPath);
|
|
2688
2806
|
const existing = agentRegistry.get(agentId) ?? (existingId ? agentRegistry.get(existingId) : void 0);
|
|
2689
2807
|
if (kind !== "started" && !existing && !spawnInfo) continue;
|
|
2690
2808
|
if (existingId && existingId !== agentId && !agentMessages.has(agentId)) {
|
|
@@ -2698,18 +2816,19 @@ function walkCodexRecords(records, options) {
|
|
|
2698
2816
|
}
|
|
2699
2817
|
const info = {
|
|
2700
2818
|
agentId,
|
|
2701
|
-
nickname: existing?.nickname ?? agentNameFromPath(
|
|
2702
|
-
agentPath
|
|
2819
|
+
nickname: existing?.nickname ?? agentNameFromPath(agentPath) ?? spawnInfo?.taskName ?? null,
|
|
2820
|
+
agentPath,
|
|
2703
2821
|
message: existing?.message ?? spawnInfo?.message ?? "",
|
|
2704
|
-
model: existing?.model ?? spawnInfo?.model ?? null,
|
|
2822
|
+
model: activity.model ?? existing?.model ?? spawnInfo?.model ?? null,
|
|
2823
|
+
effort: activity.effort ?? existing?.effort ?? null,
|
|
2705
2824
|
agentType: existing?.agentType ?? spawnInfo?.agentType ?? null,
|
|
2706
2825
|
timestamp: existing?.timestamp ?? (timestamp || spawnInfo?.timestamp || ""),
|
|
2707
2826
|
parentToolCallId: existing?.parentToolCallId ?? eventId2
|
|
2708
2827
|
};
|
|
2709
2828
|
agentRegistry.set(agentId, info);
|
|
2710
|
-
agentIdByPath.set(
|
|
2829
|
+
agentIdByPath.set(agentPath, agentId);
|
|
2711
2830
|
if (eventId2 && (kind === "started" || spawnInfo)) agentIdBySpawnCall.set(eventId2, agentId);
|
|
2712
|
-
const status = kind === "interrupted"
|
|
2831
|
+
const status = kind === "interrupted" || kind === "completed" ? kind : "running";
|
|
2713
2832
|
upsertAgentMessage(agentId, current, timestamp, { status });
|
|
2714
2833
|
continue;
|
|
2715
2834
|
}
|
|
@@ -2865,6 +2984,7 @@ function walkCodexRecords(records, options) {
|
|
|
2865
2984
|
agentPath: agentPath ?? existing?.agentPath ?? null,
|
|
2866
2985
|
message: existing?.message ?? spawnInfo?.message ?? "",
|
|
2867
2986
|
model: existing?.model ?? spawnInfo?.model ?? null,
|
|
2987
|
+
effort: existing?.effort ?? null,
|
|
2868
2988
|
agentType: existing?.agentType ?? spawnInfo?.agentType ?? null,
|
|
2869
2989
|
timestamp: existing?.timestamp ?? spawnInfo?.timestamp ?? timestamp,
|
|
2870
2990
|
parentToolCallId: existing?.parentToolCallId ?? toolCall.id
|
|
@@ -2983,8 +3103,10 @@ function walkCodexRecords(records, options) {
|
|
|
2983
3103
|
}
|
|
2984
3104
|
function parseCodexSession(jsonlText, options) {
|
|
2985
3105
|
const records = jsonlText.split("\n").map((line) => line.trim()).filter(Boolean).map(safeParseLine).filter(isCodexRecord);
|
|
3106
|
+
const isInherited = inheritedHistoryFilter(records);
|
|
3107
|
+
const ownRecords = isInherited ? records.filter((record2) => !isInherited(record2)) : records;
|
|
2986
3108
|
const { turnStartIndices: _starts, ...session } = walkCodexRecords(
|
|
2987
|
-
|
|
3109
|
+
ownRecords,
|
|
2988
3110
|
options
|
|
2989
3111
|
);
|
|
2990
3112
|
return session;
|
|
@@ -3009,40 +3131,48 @@ function parseJsonObject(value) {
|
|
|
3009
3131
|
return null;
|
|
3010
3132
|
}
|
|
3011
3133
|
}
|
|
3012
|
-
function
|
|
3013
|
-
const
|
|
3014
|
-
const
|
|
3134
|
+
function collectCodexBackgroundAgents(rawMessages) {
|
|
3135
|
+
const launched = /* @__PURE__ */ new Map();
|
|
3136
|
+
const alive = /* @__PURE__ */ new Set();
|
|
3137
|
+
const endedAt = /* @__PURE__ */ new Map();
|
|
3015
3138
|
const agentIdByPath = /* @__PURE__ */ new Map();
|
|
3016
3139
|
const spawnCalls = /* @__PURE__ */ new Map();
|
|
3017
3140
|
const waitCalls = /* @__PURE__ */ new Set();
|
|
3018
3141
|
const interruptCalls = /* @__PURE__ */ new Map();
|
|
3019
|
-
function markAlive(agentId, description) {
|
|
3020
|
-
if (
|
|
3021
|
-
|
|
3022
|
-
|
|
3142
|
+
function markAlive(agentId, description, index, startedAt) {
|
|
3143
|
+
if (endedAt.has(agentId)) return;
|
|
3144
|
+
alive.add(agentId);
|
|
3145
|
+
const launch = launched.get(agentId);
|
|
3146
|
+
if (!launch) launched.set(agentId, { launchedAt: index, description, startedAt });
|
|
3147
|
+
else if (!launch.description) launch.description = description;
|
|
3148
|
+
}
|
|
3149
|
+
function markEnded(agentId, index) {
|
|
3150
|
+
if (!endedAt.has(agentId)) endedAt.set(agentId, index);
|
|
3151
|
+
alive.delete(agentId);
|
|
3152
|
+
}
|
|
3153
|
+
for (const [index, msg] of rawMessages.entries()) {
|
|
3023
3154
|
const payload = isObject3(msg.payload) ? msg.payload : null;
|
|
3024
3155
|
if (!payload) continue;
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
const
|
|
3029
|
-
const existingId = agentIdByPath.get(
|
|
3030
|
-
const known = alive.has(agentId) ||
|
|
3156
|
+
const timestamp = typeof msg.timestamp === "string" ? msg.timestamp : void 0;
|
|
3157
|
+
const activity = readSubAgentActivity(msg);
|
|
3158
|
+
if (activity) {
|
|
3159
|
+
const { agentId, agentPath, kind, eventId: eventId2 } = activity;
|
|
3160
|
+
const existingId = agentIdByPath.get(agentPath);
|
|
3161
|
+
const known = alive.has(agentId) || endedAt.has(agentId) || existingId !== void 0 || spawnCalls.has(eventId2);
|
|
3031
3162
|
if (kind !== "started" && !known) continue;
|
|
3032
3163
|
if (existingId && existingId !== agentId) {
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
if (
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
done.add(agentId);
|
|
3042
|
-
alive.delete(agentId);
|
|
3043
|
-
} else {
|
|
3044
|
-
markAlive(agentId, spawnCalls.get(eventId2) ?? "");
|
|
3164
|
+
const prior = launched.get(existingId);
|
|
3165
|
+
launched.delete(existingId);
|
|
3166
|
+
const current = launched.get(agentId);
|
|
3167
|
+
if (prior && !current) launched.set(agentId, prior);
|
|
3168
|
+
else if (prior && current && !current.description) current.description = prior.description;
|
|
3169
|
+
if (alive.delete(existingId)) markAlive(agentId, "", index, timestamp);
|
|
3170
|
+
const priorEnd = endedAt.get(existingId);
|
|
3171
|
+
if (priorEnd !== void 0) markEnded(agentId, priorEnd);
|
|
3045
3172
|
}
|
|
3173
|
+
agentIdByPath.set(agentPath, agentId);
|
|
3174
|
+
if (kind === "interrupted" || kind === "completed") markEnded(agentId, index);
|
|
3175
|
+
else markAlive(agentId, spawnCalls.get(eventId2) ?? "", index, timestamp);
|
|
3046
3176
|
continue;
|
|
3047
3177
|
}
|
|
3048
3178
|
if (msg.type !== "response_item") continue;
|
|
@@ -3066,7 +3196,7 @@ function collectCodexPendingAgents(rawMessages) {
|
|
|
3066
3196
|
const output = parseJsonObject(payload.output);
|
|
3067
3197
|
const agentId = typeof output?.agent_id === "string" ? output.agent_id : "";
|
|
3068
3198
|
if (agentId) {
|
|
3069
|
-
markAlive(agentId, spawnCalls.get(callId) ?? "");
|
|
3199
|
+
markAlive(agentId, spawnCalls.get(callId) ?? "", index, timestamp);
|
|
3070
3200
|
const agentPath = typeof output?.task_name === "string" ? output.task_name : "";
|
|
3071
3201
|
if (agentPath && !agentIdByPath.has(agentPath)) agentIdByPath.set(agentPath, agentId);
|
|
3072
3202
|
}
|
|
@@ -3077,16 +3207,10 @@ function collectCodexPendingAgents(rawMessages) {
|
|
|
3077
3207
|
const statusValue = isObject3(status) ? status : {};
|
|
3078
3208
|
const lifecycle = typeof statusValue.status === "string" ? statusValue.status : "";
|
|
3079
3209
|
const isTerminal = typeof statusValue.completed === "string" || typeof statusValue.failed === "string" || typeof statusValue.error === "string" || typeof statusValue.interrupted === "string" || lifecycle === "completed" || lifecycle === "failed" || lifecycle === "interrupted";
|
|
3080
|
-
if (isTerminal)
|
|
3081
|
-
done.add(agentId);
|
|
3082
|
-
alive.delete(agentId);
|
|
3083
|
-
}
|
|
3210
|
+
if (isTerminal) markEnded(agentId, index);
|
|
3084
3211
|
}
|
|
3085
3212
|
} else if (interruptCalls.has(callId)) {
|
|
3086
|
-
for (const agentId of interruptCalls.get(callId) ?? [])
|
|
3087
|
-
done.add(agentId);
|
|
3088
|
-
alive.delete(agentId);
|
|
3089
|
-
}
|
|
3213
|
+
for (const agentId of interruptCalls.get(callId) ?? []) markEnded(agentId, index);
|
|
3090
3214
|
}
|
|
3091
3215
|
continue;
|
|
3092
3216
|
}
|
|
@@ -3094,12 +3218,14 @@ function collectCodexPendingAgents(rawMessages) {
|
|
|
3094
3218
|
const text = codexPayloadText(payload);
|
|
3095
3219
|
const messageType = text.match(/^Message Type:\s*([^\r\n]+)/)?.[1]?.trim().toUpperCase() ?? "";
|
|
3096
3220
|
if (!TERMINAL_INTER_AGENT_TYPES.has(messageType)) continue;
|
|
3097
|
-
|
|
3098
|
-
done.add(agentId);
|
|
3099
|
-
alive.delete(agentId);
|
|
3221
|
+
markEnded(agentIdByPath.get(payload.author) ?? payload.author, index);
|
|
3100
3222
|
}
|
|
3101
3223
|
}
|
|
3102
|
-
return [...
|
|
3224
|
+
return [...launched.entries()].map(([agentId, { description, startedAt, launchedAt }]) => ({
|
|
3225
|
+
agent: { description, startedAt },
|
|
3226
|
+
launchedAt,
|
|
3227
|
+
endedAt: alive.has(agentId) ? void 0 : endedAt.get(agentId) ?? launchedAt
|
|
3228
|
+
}));
|
|
3103
3229
|
}
|
|
3104
3230
|
function deriveCodexSessionStatus(rawMessages) {
|
|
3105
3231
|
for (let i = rawMessages.length - 1; i >= 0; i--) {
|
|
@@ -3108,16 +3234,7 @@ function deriveCodexSessionStatus(rawMessages) {
|
|
|
3108
3234
|
const payload = msg.payload;
|
|
3109
3235
|
switch (payload?.type) {
|
|
3110
3236
|
case "task_complete": {
|
|
3111
|
-
|
|
3112
|
-
if (pending.length > 0) {
|
|
3113
|
-
return {
|
|
3114
|
-
status: "awaiting_agents",
|
|
3115
|
-
pendingQueue: 0,
|
|
3116
|
-
pendingAgents: pending.length,
|
|
3117
|
-
pendingAgentDescriptions: pending.filter((description) => description.length > 0)
|
|
3118
|
-
};
|
|
3119
|
-
}
|
|
3120
|
-
return { status: "completed" };
|
|
3237
|
+
return awaitingAgentsStatus(collectCodexBackgroundAgents(rawMessages)) ?? { status: "completed" };
|
|
3121
3238
|
}
|
|
3122
3239
|
case "task_started":
|
|
3123
3240
|
return { status: "processing" };
|
|
@@ -3915,33 +4032,32 @@ function isCopilotEventType(type) {
|
|
|
3915
4032
|
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."));
|
|
3916
4033
|
}
|
|
3917
4034
|
function deriveCopilotSessionStatus(rawMessages) {
|
|
3918
|
-
const
|
|
3919
|
-
for (const event of rawMessages) {
|
|
4035
|
+
const agents = /* @__PURE__ */ new Map();
|
|
4036
|
+
for (const [index, event] of rawMessages.entries()) {
|
|
3920
4037
|
const agentId = typeof event.agentId === "string" ? event.agentId : "";
|
|
3921
4038
|
if (!agentId && (event.type === "abort" || event.type === "session.shutdown" || event.type === "session.error")) {
|
|
3922
|
-
|
|
4039
|
+
agents.clear();
|
|
3923
4040
|
continue;
|
|
3924
4041
|
}
|
|
3925
4042
|
if (!agentId || !event.type.startsWith("subagent.")) continue;
|
|
3926
4043
|
const data = isObject4(event.data) ? event.data : {};
|
|
4044
|
+
const launch = agents.get(agentId);
|
|
3927
4045
|
if (event.type === "subagent.completed" || event.type === "subagent.failed") {
|
|
3928
|
-
|
|
4046
|
+
if (launch) launch.endedAt ??= index;
|
|
3929
4047
|
continue;
|
|
3930
4048
|
}
|
|
3931
4049
|
if (event.type === "subagent.started" || event.type === "subagent.configured") {
|
|
3932
4050
|
const description = [data.agentDisplayName, data.description, data.agentName].find((value) => typeof value === "string") ?? "";
|
|
3933
|
-
|
|
4051
|
+
if (!launch || launch.endedAt !== void 0) {
|
|
4052
|
+
const startedAt = typeof event.timestamp === "string" ? event.timestamp : void 0;
|
|
4053
|
+
agents.set(agentId, { agent: { description, startedAt }, launchedAt: index });
|
|
4054
|
+
} else if (description) {
|
|
4055
|
+
launch.agent.description = description;
|
|
4056
|
+
}
|
|
3934
4057
|
}
|
|
3935
4058
|
}
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
return {
|
|
3939
|
-
status: "awaiting_agents",
|
|
3940
|
-
pendingQueue: 0,
|
|
3941
|
-
pendingAgents: descriptions.length,
|
|
3942
|
-
pendingAgentDescriptions: descriptions.filter((description) => description.length > 0)
|
|
3943
|
-
};
|
|
3944
|
-
}
|
|
4059
|
+
const awaiting = awaitingAgentsStatus([...agents.values()]);
|
|
4060
|
+
if (awaiting) return awaiting;
|
|
3945
4061
|
let sawUserActivity = false;
|
|
3946
4062
|
const completedPermissionRequests = /* @__PURE__ */ new Set();
|
|
3947
4063
|
for (let i = rawMessages.length - 1; i >= 0; i--) {
|
|
@@ -4027,6 +4143,7 @@ function copilotTurnBoundaries(records) {
|
|
|
4027
4143
|
|
|
4028
4144
|
// src/lib/agents.ts
|
|
4029
4145
|
var TERMINAL_AGENT_KIND = AGENT_KINDS[AGENT_KINDS.length - 1];
|
|
4146
|
+
var hasNoNoiseLines = () => false;
|
|
4030
4147
|
var codexFormat = {
|
|
4031
4148
|
kind: "codex",
|
|
4032
4149
|
descriptor: descriptorFor("codex"),
|
|
@@ -4036,6 +4153,8 @@ var codexFormat = {
|
|
|
4036
4153
|
append: appendCodexSession,
|
|
4037
4154
|
metadataFromLines: extractCodexMetadataFromLines,
|
|
4038
4155
|
status: deriveCodexSessionStatus,
|
|
4156
|
+
isNoiseLine: hasNoNoiseLines,
|
|
4157
|
+
pageHeaderLine: codexPageHeaderLine,
|
|
4039
4158
|
brandBranch: brandCodexBranch,
|
|
4040
4159
|
turnBoundaries: codexTurnBoundaries
|
|
4041
4160
|
};
|
|
@@ -4048,6 +4167,7 @@ var copilotFormat = {
|
|
|
4048
4167
|
append: appendCopilotSession,
|
|
4049
4168
|
metadataFromLines: extractCopilotMetadataFromLines,
|
|
4050
4169
|
status: deriveCopilotSessionStatus,
|
|
4170
|
+
isNoiseLine: hasNoNoiseLines,
|
|
4051
4171
|
brandBranch: brandCopilotBranch,
|
|
4052
4172
|
turnBoundaries: copilotTurnBoundaries
|
|
4053
4173
|
};
|
|
@@ -4061,6 +4181,7 @@ var claudeFormat = {
|
|
|
4061
4181
|
append: appendClaudeSession,
|
|
4062
4182
|
metadataFromLines: extractClaudeMetadataFromLines,
|
|
4063
4183
|
status: deriveClaudeSessionStatus,
|
|
4184
|
+
isNoiseLine: isClaudeNoiseLine,
|
|
4064
4185
|
brandBranch: brandClaudeBranch,
|
|
4065
4186
|
turnBoundaries: claudeTurnBoundaries
|
|
4066
4187
|
};
|
|
@@ -4090,6 +4211,9 @@ function formatForText(jsonlText) {
|
|
|
4090
4211
|
function formatForRecords(records) {
|
|
4091
4212
|
return firstMatch((format) => format.detectsRecords(records));
|
|
4092
4213
|
}
|
|
4214
|
+
function isAnyAgentNoiseLine(line) {
|
|
4215
|
+
return AGENT_KINDS.some((kind) => FORMATS[kind].isNoiseLine(line));
|
|
4216
|
+
}
|
|
4093
4217
|
|
|
4094
4218
|
// src/lib/parser.ts
|
|
4095
4219
|
function extractTextFromContent2(content) {
|
|
@@ -4105,8 +4229,55 @@ function getUserMessageText(content) {
|
|
|
4105
4229
|
return extractTextFromContent2(content);
|
|
4106
4230
|
}
|
|
4107
4231
|
|
|
4108
|
-
// src/lib/
|
|
4232
|
+
// src/lib/transcriptFile.ts
|
|
4109
4233
|
var import_node_fs = require("node:fs");
|
|
4234
|
+
var import_promises = require("node:fs/promises");
|
|
4235
|
+
var zlib = __toESM(require("node:zlib"));
|
|
4236
|
+
var COMPRESSED_SUFFIX = ".zst";
|
|
4237
|
+
var canReadCompressedTranscripts = typeof zlib.zstdDecompressSync === "function";
|
|
4238
|
+
function isCompressedTranscript(filePath) {
|
|
4239
|
+
return filePath.endsWith(COMPRESSED_SUFFIX);
|
|
4240
|
+
}
|
|
4241
|
+
function uncompressedTranscriptName(fileName) {
|
|
4242
|
+
return isCompressedTranscript(fileName) ? fileName.slice(0, -COMPRESSED_SUFFIX.length) : fileName;
|
|
4243
|
+
}
|
|
4244
|
+
function isListableTranscript(name, siblings) {
|
|
4245
|
+
const plainName = uncompressedTranscriptName(name);
|
|
4246
|
+
if (!plainName.endsWith(".jsonl")) return false;
|
|
4247
|
+
if (plainName === name) return true;
|
|
4248
|
+
return canReadCompressedTranscripts && !siblings.has(plainName);
|
|
4249
|
+
}
|
|
4250
|
+
function inflate(data) {
|
|
4251
|
+
if (!canReadCompressedTranscripts) {
|
|
4252
|
+
throw new Error("Reading a .jsonl.zst transcript needs Node.js 22.15 or newer, or Bun");
|
|
4253
|
+
}
|
|
4254
|
+
return zlib.zstdDecompressSync(data);
|
|
4255
|
+
}
|
|
4256
|
+
function readTranscriptTextSync(filePath) {
|
|
4257
|
+
const data = (0, import_node_fs.readFileSync)(filePath);
|
|
4258
|
+
return (isCompressedTranscript(filePath) ? inflate(data) : data).toString("utf-8");
|
|
4259
|
+
}
|
|
4260
|
+
async function readTranscriptText(filePath) {
|
|
4261
|
+
const data = await (0, import_promises.readFile)(filePath);
|
|
4262
|
+
return (isCompressedTranscript(filePath) ? inflate(data) : data).toString("utf-8");
|
|
4263
|
+
}
|
|
4264
|
+
async function openTranscript(filePath) {
|
|
4265
|
+
if (!isCompressedTranscript(filePath)) return (0, import_promises.open)(filePath, "r");
|
|
4266
|
+
const [fileStat, compressed] = await Promise.all([(0, import_promises.stat)(filePath), (0, import_promises.readFile)(filePath)]);
|
|
4267
|
+
const data = inflate(compressed);
|
|
4268
|
+
return {
|
|
4269
|
+
async read(buffer, offset, length, position) {
|
|
4270
|
+
const start = Math.min(Math.max(position, 0), data.length);
|
|
4271
|
+
return { bytesRead: data.copy(buffer, offset, start, Math.min(start + length, data.length)) };
|
|
4272
|
+
},
|
|
4273
|
+
stat: async () => ({ size: data.length, mtimeMs: fileStat.mtimeMs }),
|
|
4274
|
+
close: async () => {
|
|
4275
|
+
}
|
|
4276
|
+
};
|
|
4277
|
+
}
|
|
4278
|
+
|
|
4279
|
+
// src/lib/stores.ts
|
|
4280
|
+
var import_node_fs2 = require("node:fs");
|
|
4110
4281
|
var import_node_path2 = require("node:path");
|
|
4111
4282
|
|
|
4112
4283
|
// src/lib/dirs.ts
|
|
@@ -4133,14 +4304,14 @@ var MAX_WALK_DEPTH = 4;
|
|
|
4133
4304
|
var SUBAGENTS_DIR = "subagents";
|
|
4134
4305
|
function mtimeOf(filePath) {
|
|
4135
4306
|
try {
|
|
4136
|
-
return (0,
|
|
4307
|
+
return (0, import_node_fs2.statSync)(filePath).mtimeMs;
|
|
4137
4308
|
} catch {
|
|
4138
4309
|
return null;
|
|
4139
4310
|
}
|
|
4140
4311
|
}
|
|
4141
4312
|
function readDirSafe(dir) {
|
|
4142
4313
|
try {
|
|
4143
|
-
return (0,
|
|
4314
|
+
return (0, import_node_fs2.readdirSync)(dir, { withFileTypes: true });
|
|
4144
4315
|
} catch {
|
|
4145
4316
|
return [];
|
|
4146
4317
|
}
|
|
@@ -4151,8 +4322,8 @@ function isWithin(root, target) {
|
|
|
4151
4322
|
}
|
|
4152
4323
|
function canonicalWithinRoot(root, filePath) {
|
|
4153
4324
|
try {
|
|
4154
|
-
const realRoot = (0,
|
|
4155
|
-
const real = (0,
|
|
4325
|
+
const realRoot = (0, import_node_fs2.realpathSync)(root);
|
|
4326
|
+
const real = (0, import_node_fs2.realpathSync)(filePath);
|
|
4156
4327
|
return isWithin(realRoot, real) ? real : null;
|
|
4157
4328
|
} catch {
|
|
4158
4329
|
return null;
|
|
@@ -4218,13 +4389,15 @@ function walkClaude(root, cutoffMs) {
|
|
|
4218
4389
|
function walkCodex(root, cutoffMs, dir = root, depth = 0) {
|
|
4219
4390
|
if (depth > MAX_WALK_DEPTH) return [];
|
|
4220
4391
|
const found = [];
|
|
4221
|
-
|
|
4392
|
+
const entries = readDirSafe(dir);
|
|
4393
|
+
const names = new Set(entries.map((entry) => entry.name));
|
|
4394
|
+
for (const entry of entries) {
|
|
4222
4395
|
const filePath = (0, import_node_path2.join)(dir, entry.name);
|
|
4223
4396
|
if (entry.isDirectory()) {
|
|
4224
4397
|
found.push(...walkCodex(root, cutoffMs, filePath, depth + 1));
|
|
4225
4398
|
continue;
|
|
4226
4399
|
}
|
|
4227
|
-
if (!entry.name
|
|
4400
|
+
if (!isListableTranscript(entry.name, names)) continue;
|
|
4228
4401
|
const mtimeMs = mtimeOf(filePath);
|
|
4229
4402
|
if (mtimeMs === null || mtimeMs < cutoffMs) continue;
|
|
4230
4403
|
found.push({
|
|
@@ -4285,14 +4458,18 @@ var WALKERS = {
|
|
|
4285
4458
|
find(root, sessionId) {
|
|
4286
4459
|
const walk = (dir, depth) => {
|
|
4287
4460
|
if (depth > MAX_WALK_DEPTH) return null;
|
|
4288
|
-
|
|
4461
|
+
const entries = readDirSafe(dir);
|
|
4462
|
+
const names = new Set(entries.map((entry) => entry.name));
|
|
4463
|
+
for (const entry of entries) {
|
|
4289
4464
|
const filePath = (0, import_node_path2.join)(dir, entry.name);
|
|
4290
4465
|
if (entry.isDirectory()) {
|
|
4291
4466
|
const match = walk(filePath, depth + 1);
|
|
4292
4467
|
if (match) return match;
|
|
4293
4468
|
continue;
|
|
4294
4469
|
}
|
|
4295
|
-
if (entry.name.endsWith(`${sessionId}.jsonl`))
|
|
4470
|
+
if (uncompressedTranscriptName(entry.name).endsWith(`${sessionId}.jsonl`) && isListableTranscript(entry.name, names)) {
|
|
4471
|
+
return filePath;
|
|
4472
|
+
}
|
|
4296
4473
|
}
|
|
4297
4474
|
return null;
|
|
4298
4475
|
};
|
|
@@ -4335,7 +4512,7 @@ function makeStore(kind, home, configuredId) {
|
|
|
4335
4512
|
ownsPath: (filePath) => {
|
|
4336
4513
|
if (isWithin((0, import_node_path2.resolve)(root()), (0, import_node_path2.resolve)(filePath))) return true;
|
|
4337
4514
|
try {
|
|
4338
|
-
return isWithin((0,
|
|
4515
|
+
return isWithin((0, import_node_fs2.realpathSync)(root()), (0, import_node_fs2.realpathSync)(filePath));
|
|
4339
4516
|
} catch {
|
|
4340
4517
|
return false;
|
|
4341
4518
|
}
|
|
@@ -4369,7 +4546,7 @@ function allStores() {
|
|
|
4369
4546
|
if (!entry.isDirectory()) continue;
|
|
4370
4547
|
const home = (0, import_node_path2.join)(root, "provider-instances", entry.name);
|
|
4371
4548
|
try {
|
|
4372
|
-
const config = JSON.parse((0,
|
|
4549
|
+
const config = JSON.parse((0, import_node_fs2.readFileSync)((0, import_node_path2.join)(home, "config.json"), "utf8"));
|
|
4373
4550
|
if (config.providerInstance?.id === entry.name && config.providerInstance.agent && AGENT_KINDS.includes(config.providerInstance.agent)) stores.push(makeStore(config.providerInstance.agent, home, entry.name));
|
|
4374
4551
|
} catch {
|
|
4375
4552
|
}
|
|
@@ -4444,7 +4621,7 @@ var SearchIndex = class {
|
|
|
4444
4621
|
const { count: totalRows } = this.db.prepare("SELECT COUNT(*) as count FROM search_content").get();
|
|
4445
4622
|
let dbSizeBytes = 0;
|
|
4446
4623
|
try {
|
|
4447
|
-
dbSizeBytes = (0,
|
|
4624
|
+
dbSizeBytes = (0, import_node_fs3.statSync)(this.dbPath).size;
|
|
4448
4625
|
} catch {
|
|
4449
4626
|
}
|
|
4450
4627
|
return {
|
|
@@ -4517,9 +4694,9 @@ var SearchIndex = class {
|
|
|
4517
4694
|
indexFile(filePath, sessionId, mtimeMs, opts) {
|
|
4518
4695
|
const resolvedSessionId = sessionId ?? identifyTranscript(filePath).sessionId;
|
|
4519
4696
|
if (mtimeMs == null) {
|
|
4520
|
-
mtimeMs = (0,
|
|
4697
|
+
mtimeMs = (0, import_node_fs3.statSync)(filePath).mtimeMs;
|
|
4521
4698
|
}
|
|
4522
|
-
const content = (
|
|
4699
|
+
const content = readTranscriptTextSync(filePath);
|
|
4523
4700
|
const session = parseSession(content, { skipStats: true });
|
|
4524
4701
|
const isSubagent = opts?.isSubagent ? 1 : 0;
|
|
4525
4702
|
const parentSessionId = opts?.parentSessionId ?? null;
|
|
@@ -4548,7 +4725,7 @@ var SearchIndex = class {
|
|
|
4548
4725
|
const files = this.db.prepare("SELECT file_path FROM indexed_files").all();
|
|
4549
4726
|
const missing = files.filter(({ file_path }) => {
|
|
4550
4727
|
try {
|
|
4551
|
-
(0,
|
|
4728
|
+
(0, import_node_fs3.statSync)(file_path);
|
|
4552
4729
|
return false;
|
|
4553
4730
|
} catch (error) {
|
|
4554
4731
|
const code = error.code;
|
|
@@ -4665,7 +4842,7 @@ var SearchIndex = class {
|
|
|
4665
4842
|
this.db.close();
|
|
4666
4843
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
4667
4844
|
try {
|
|
4668
|
-
(0,
|
|
4845
|
+
(0, import_node_fs3.unlinkSync)(this.dbPath + suffix);
|
|
4669
4846
|
} catch {
|
|
4670
4847
|
}
|
|
4671
4848
|
}
|
|
@@ -4689,7 +4866,7 @@ var SearchIndex = class {
|
|
|
4689
4866
|
const txn = this.db.transaction(() => {
|
|
4690
4867
|
for (const file of files) {
|
|
4691
4868
|
try {
|
|
4692
|
-
const content = (
|
|
4869
|
+
const content = readTranscriptTextSync(file.path);
|
|
4693
4870
|
const session = parseSession(content, { skipStats: true });
|
|
4694
4871
|
this.insertSessionContent(insert, file.sessionId, file.path, session);
|
|
4695
4872
|
insertFile.run(file.path, file.mtimeMs, file.sessionId, file.isSubagent ? 1 : 0, file.parentSessionId);
|
|
@@ -4785,9 +4962,9 @@ async function searchSessions(query, opts, searchIndex) {
|
|
|
4785
4962
|
let ownedIndex = false;
|
|
4786
4963
|
if (!index && searchIndex === void 0) {
|
|
4787
4964
|
try {
|
|
4788
|
-
const dbExists = (0,
|
|
4965
|
+
const dbExists = (0, import_node_fs4.existsSync)(DEFAULT_DB_PATH);
|
|
4789
4966
|
if (!dbExists) {
|
|
4790
|
-
(0,
|
|
4967
|
+
(0, import_node_fs4.mkdirSync)((0, import_node_path3.dirname)(DEFAULT_DB_PATH), { recursive: true });
|
|
4791
4968
|
}
|
|
4792
4969
|
index = new SearchIndex(DEFAULT_DB_PATH);
|
|
4793
4970
|
ownedIndex = true;
|
|
@@ -4861,7 +5038,7 @@ async function cwdFromFilePath(filePath) {
|
|
|
4861
5038
|
const cached = cwdCache.get(filePath);
|
|
4862
5039
|
if (cached !== void 0) return cached;
|
|
4863
5040
|
try {
|
|
4864
|
-
const fh = await (
|
|
5041
|
+
const fh = await openTranscript(filePath);
|
|
4865
5042
|
try {
|
|
4866
5043
|
const buf = Buffer.alloc(CWD_READ_BYTES);
|
|
4867
5044
|
const { bytesRead } = await fh.read(buf, 0, CWD_READ_BYTES, 0);
|
|
@@ -4919,7 +5096,7 @@ function searchField(text, location, query, caseSensitive, extras) {
|
|
|
4919
5096
|
async function discoverSingleSession(sessionId) {
|
|
4920
5097
|
const jsonlPath = await findSessionFile(sessionId);
|
|
4921
5098
|
if (!jsonlPath) return [];
|
|
4922
|
-
const s = await (0,
|
|
5099
|
+
const s = await (0, import_promises2.stat)(jsonlPath);
|
|
4923
5100
|
return [{ path: jsonlPath, mtimeMs: s.mtimeMs, sessionId }];
|
|
4924
5101
|
}
|
|
4925
5102
|
function discoverAllSessions(maxAgeMs) {
|
|
@@ -4927,7 +5104,7 @@ function discoverAllSessions(maxAgeMs) {
|
|
|
4927
5104
|
}
|
|
4928
5105
|
async function rawTextMatch(filePath, query, caseSensitive) {
|
|
4929
5106
|
try {
|
|
4930
|
-
const content = await (
|
|
5107
|
+
const content = await readTranscriptText(filePath);
|
|
4931
5108
|
const haystack = caseSensitive ? content : content.toLowerCase();
|
|
4932
5109
|
const needle = caseSensitive ? query : query.toLowerCase();
|
|
4933
5110
|
if (haystack.includes(needle)) return content;
|
|
@@ -5002,7 +5179,7 @@ async function walkSubagentFiles(parentJsonlPath, query, caseSensitive, currentD
|
|
|
5002
5179
|
const subDir = parentJsonlPath.replace(/\.jsonl$/, "") + "/subagents";
|
|
5003
5180
|
let files;
|
|
5004
5181
|
try {
|
|
5005
|
-
files = await (0,
|
|
5182
|
+
files = await (0, import_promises2.readdir)(subDir);
|
|
5006
5183
|
} catch {
|
|
5007
5184
|
return [];
|
|
5008
5185
|
}
|
|
@@ -5080,14 +5257,14 @@ async function rawScanSearch(query, sessionId, maxAgeMs, limit, caseSensitive, e
|
|
|
5080
5257
|
}
|
|
5081
5258
|
|
|
5082
5259
|
// src/commands/context.ts
|
|
5083
|
-
var
|
|
5260
|
+
var import_promises4 = require("node:fs/promises");
|
|
5084
5261
|
var import_node_path5 = require("node:path");
|
|
5085
5262
|
|
|
5086
5263
|
// src/lib/helpers.ts
|
|
5087
|
-
var
|
|
5264
|
+
var import_promises3 = require("node:fs/promises");
|
|
5088
5265
|
var import_node_path4 = require("node:path");
|
|
5089
5266
|
async function matchSubagentToMember(leadSessionId, subagentFileName, members) {
|
|
5090
|
-
const entries = await (0,
|
|
5267
|
+
const entries = await (0, import_promises3.readdir)(dirs.PROJECTS_DIR, { withFileTypes: true });
|
|
5091
5268
|
for (const entry of entries) {
|
|
5092
5269
|
if (!entry.isDirectory() || entry.name === "memory") continue;
|
|
5093
5270
|
const filePath = (0, import_node_path4.join)(
|
|
@@ -5098,7 +5275,7 @@ async function matchSubagentToMember(leadSessionId, subagentFileName, members) {
|
|
|
5098
5275
|
subagentFileName
|
|
5099
5276
|
);
|
|
5100
5277
|
try {
|
|
5101
|
-
const fh = await (0,
|
|
5278
|
+
const fh = await (0, import_promises3.open)(filePath, "r");
|
|
5102
5279
|
try {
|
|
5103
5280
|
const buf = Buffer.alloc(16384);
|
|
5104
5281
|
const { bytesRead } = await fh.read(buf, 0, 16384, 0);
|
|
@@ -5293,7 +5470,13 @@ function mapContentBlock(block) {
|
|
|
5293
5470
|
case "task_notification":
|
|
5294
5471
|
return { kind: "task_notification", content: block.content, timestamp: block.timestamp ?? null };
|
|
5295
5472
|
case "local_command":
|
|
5296
|
-
return {
|
|
5473
|
+
return {
|
|
5474
|
+
kind: "local_command",
|
|
5475
|
+
content: block.content,
|
|
5476
|
+
timestamp: block.timestamp ?? null,
|
|
5477
|
+
...block.contextUsage ? { contextUsage: block.contextUsage } : {},
|
|
5478
|
+
...block.usageReport ? { usageReport: block.usageReport } : {}
|
|
5479
|
+
};
|
|
5297
5480
|
default: {
|
|
5298
5481
|
const exhaustive = block;
|
|
5299
5482
|
return exhaustive;
|
|
@@ -5303,7 +5486,7 @@ function mapContentBlock(block) {
|
|
|
5303
5486
|
async function findSubagentFile(parentJsonlPath, agentId) {
|
|
5304
5487
|
const subagentsDir = parentJsonlPath.replace(/\.jsonl$/, "") + "/subagents";
|
|
5305
5488
|
try {
|
|
5306
|
-
const files = await (0,
|
|
5489
|
+
const files = await (0, import_promises4.readdir)(subagentsDir);
|
|
5307
5490
|
for (const f of files) {
|
|
5308
5491
|
if (!f.startsWith("agent-") || !f.endsWith(".jsonl")) continue;
|
|
5309
5492
|
const fileAgentId = f.replace("agent-", "").replace(".jsonl", "");
|
|
@@ -5317,12 +5500,12 @@ async function findSubagentFile(parentJsonlPath, agentId) {
|
|
|
5317
5500
|
}
|
|
5318
5501
|
async function findTeamContext(sessionId, subagentFileName) {
|
|
5319
5502
|
try {
|
|
5320
|
-
const teamEntries = await (0,
|
|
5503
|
+
const teamEntries = await (0, import_promises4.readdir)(dirs.TEAMS_DIR, { withFileTypes: true });
|
|
5321
5504
|
for (const entry of teamEntries) {
|
|
5322
5505
|
if (!entry.isDirectory()) continue;
|
|
5323
5506
|
const configPath = (0, import_node_path5.join)(dirs.TEAMS_DIR, entry.name, "config.json");
|
|
5324
5507
|
try {
|
|
5325
|
-
const raw = await (0,
|
|
5508
|
+
const raw = await (0, import_promises4.readFile)(configPath, "utf-8");
|
|
5326
5509
|
const config = JSON.parse(raw);
|
|
5327
5510
|
if (config.leadSessionId !== sessionId) continue;
|
|
5328
5511
|
const members = config.members ?? [];
|
|
@@ -5331,10 +5514,10 @@ async function findTeamContext(sessionId, subagentFileName) {
|
|
|
5331
5514
|
let currentTask = null;
|
|
5332
5515
|
try {
|
|
5333
5516
|
const taskDir = (0, import_node_path5.join)(dirs.TASKS_DIR, entry.name);
|
|
5334
|
-
const taskFiles = await (0,
|
|
5517
|
+
const taskFiles = await (0, import_promises4.readdir)(taskDir);
|
|
5335
5518
|
for (const tf of taskFiles) {
|
|
5336
5519
|
if (!tf.endsWith(".json")) continue;
|
|
5337
|
-
const taskRaw = await (0,
|
|
5520
|
+
const taskRaw = await (0, import_promises4.readFile)((0, import_node_path5.join)(taskDir, tf), "utf-8");
|
|
5338
5521
|
const task = JSON.parse(taskRaw);
|
|
5339
5522
|
if (task.owner === memberName && task.status === "in_progress") {
|
|
5340
5523
|
currentTask = { id: task.id, subject: task.subject, status: task.status };
|
|
@@ -5382,14 +5565,14 @@ function findAgentMetadata(session, agentId) {
|
|
|
5382
5565
|
async function getSessionOverview(sessionId) {
|
|
5383
5566
|
const jsonlPath = await findSessionFile(sessionId);
|
|
5384
5567
|
if (!jsonlPath) return { error: "Session not found" };
|
|
5385
|
-
const content = await (
|
|
5568
|
+
const content = await readTranscriptText(jsonlPath);
|
|
5386
5569
|
const session = parseTranscript(content, jsonlPath);
|
|
5387
5570
|
return mapSessionToOverview(session);
|
|
5388
5571
|
}
|
|
5389
5572
|
async function getTurnDetail(sessionId, turnIndex) {
|
|
5390
5573
|
const jsonlPath = await findSessionFile(sessionId);
|
|
5391
5574
|
if (!jsonlPath) return { error: "Session not found" };
|
|
5392
|
-
const content = await (
|
|
5575
|
+
const content = await readTranscriptText(jsonlPath);
|
|
5393
5576
|
const session = parseTranscript(content, jsonlPath);
|
|
5394
5577
|
if (turnIndex < 0 || turnIndex >= session.turns.length) return { error: "Turn not found" };
|
|
5395
5578
|
return mapTurnToDetail(session, turnIndex);
|
|
@@ -5397,11 +5580,11 @@ async function getTurnDetail(sessionId, turnIndex) {
|
|
|
5397
5580
|
async function getAgentOverview(sessionId, agentId) {
|
|
5398
5581
|
const jsonlPath = await findSessionFile(sessionId);
|
|
5399
5582
|
if (!jsonlPath) return { error: "Session not found" };
|
|
5400
|
-
const content = await (
|
|
5583
|
+
const content = await readTranscriptText(jsonlPath);
|
|
5401
5584
|
const session = parseTranscript(content, jsonlPath);
|
|
5402
5585
|
const subagentFile = await findSubagentFile(jsonlPath, agentId);
|
|
5403
5586
|
if (!subagentFile) return { error: "Agent not found" };
|
|
5404
|
-
const subagentContent = await (
|
|
5587
|
+
const subagentContent = await readTranscriptText(subagentFile.filePath);
|
|
5405
5588
|
const subagentSession = parseTranscript(subagentContent, subagentFile.filePath);
|
|
5406
5589
|
const metadata = findAgentMetadata(session, agentId);
|
|
5407
5590
|
const parentToolCallId = findParentToolCallId(session, agentId);
|
|
@@ -5422,7 +5605,7 @@ async function getAgentTurnDetail(sessionId, agentId, turnIndex) {
|
|
|
5422
5605
|
if (!jsonlPath) return { error: "Session not found" };
|
|
5423
5606
|
const subagentFile = await findSubagentFile(jsonlPath, agentId);
|
|
5424
5607
|
if (!subagentFile) return { error: "Agent not found" };
|
|
5425
|
-
const subagentContent = await (
|
|
5608
|
+
const subagentContent = await readTranscriptText(subagentFile.filePath);
|
|
5426
5609
|
const subagentSession = parseTranscript(subagentContent, subagentFile.filePath);
|
|
5427
5610
|
if (turnIndex < 0 || turnIndex >= subagentSession.turns.length) return { error: "Turn not found" };
|
|
5428
5611
|
return mapTurnToDetail(subagentSession, turnIndex);
|
|
@@ -5432,7 +5615,7 @@ async function getAgentTurnDetail(sessionId, agentId, turnIndex) {
|
|
|
5432
5615
|
var import_node_path6 = require("node:path");
|
|
5433
5616
|
|
|
5434
5617
|
// src/lib/metadata.ts
|
|
5435
|
-
var
|
|
5618
|
+
var import_promises5 = require("node:fs/promises");
|
|
5436
5619
|
|
|
5437
5620
|
// src/lib/sessionStatus.ts
|
|
5438
5621
|
function deriveSessionStatus(rawMessages) {
|
|
@@ -5457,6 +5640,7 @@ function scanClaudeMessages(lines) {
|
|
|
5457
5640
|
turnCount: 0
|
|
5458
5641
|
};
|
|
5459
5642
|
for (const line of lines) {
|
|
5643
|
+
if (isAnyAgentNoiseLine(line)) continue;
|
|
5460
5644
|
let record2;
|
|
5461
5645
|
try {
|
|
5462
5646
|
record2 = JSON.parse(line);
|
|
@@ -5485,11 +5669,11 @@ function scanClaudeMessages(lines) {
|
|
|
5485
5669
|
return meta;
|
|
5486
5670
|
}
|
|
5487
5671
|
async function readLines(filePath, size) {
|
|
5488
|
-
if (size <= FULL_READ_LIMIT) {
|
|
5489
|
-
const content = await (
|
|
5672
|
+
if (size <= FULL_READ_LIMIT || isCompressedTranscript(filePath)) {
|
|
5673
|
+
const content = await readTranscriptText(filePath);
|
|
5490
5674
|
return { lines: content.split("\n").filter(Boolean), isPartialRead: false };
|
|
5491
5675
|
}
|
|
5492
|
-
const handle = await (0,
|
|
5676
|
+
const handle = await (0, import_promises5.open)(filePath, "r");
|
|
5493
5677
|
try {
|
|
5494
5678
|
const buffer = Buffer.alloc(HEAD_READ_BYTES);
|
|
5495
5679
|
const { bytesRead } = await handle.read(buffer, 0, HEAD_READ_BYTES, 0);
|
|
@@ -5504,11 +5688,11 @@ async function readLines(filePath, size) {
|
|
|
5504
5688
|
}
|
|
5505
5689
|
}
|
|
5506
5690
|
async function getSessionMeta(filePath) {
|
|
5507
|
-
const fileStat = await (0,
|
|
5691
|
+
const fileStat = await (0, import_promises5.stat)(filePath);
|
|
5508
5692
|
let { lines, isPartialRead } = await readLines(filePath, fileStat.size);
|
|
5509
5693
|
const format = formatForText(lines.join("\n"));
|
|
5510
5694
|
if (isPartialRead && !format.descriptor.metadataFromHead) {
|
|
5511
|
-
lines = (await (0,
|
|
5695
|
+
lines = (await (0, import_promises5.readFile)(filePath, "utf-8")).split("\n").filter(Boolean);
|
|
5512
5696
|
isPartialRead = false;
|
|
5513
5697
|
}
|
|
5514
5698
|
const header = readHeader(format, lines);
|
|
@@ -5537,10 +5721,10 @@ async function getSessionStatus(filePath) {
|
|
|
5537
5721
|
const CHUNK = 4096;
|
|
5538
5722
|
const MAX_CHUNKS = 64;
|
|
5539
5723
|
try {
|
|
5540
|
-
const
|
|
5541
|
-
if (fileStat.size === 0) return { status: "idle" };
|
|
5542
|
-
const fh = await (0, import_promises4.open)(filePath, "r");
|
|
5724
|
+
const fh = await openTranscript(filePath);
|
|
5543
5725
|
try {
|
|
5726
|
+
const fileStat = await fh.stat();
|
|
5727
|
+
if (fileStat.size === 0) return { status: "idle" };
|
|
5544
5728
|
const meaningful = [];
|
|
5545
5729
|
let cursor = fileStat.size;
|
|
5546
5730
|
let leftover = "";
|
|
@@ -5556,7 +5740,7 @@ async function getSessionStatus(filePath) {
|
|
|
5556
5740
|
const startIdx = cursor > 0 ? 1 : 0;
|
|
5557
5741
|
for (let i = lines.length - 1; i >= startIdx; i--) {
|
|
5558
5742
|
const line = lines[i];
|
|
5559
|
-
if (!line) continue;
|
|
5743
|
+
if (!line || isAnyAgentNoiseLine(line)) continue;
|
|
5560
5744
|
let obj;
|
|
5561
5745
|
try {
|
|
5562
5746
|
obj = JSON.parse(line);
|
|
@@ -5687,11 +5871,11 @@ async function currentSession(cwd) {
|
|
|
5687
5871
|
}
|
|
5688
5872
|
|
|
5689
5873
|
// src/commands/index-cmd.ts
|
|
5690
|
-
var
|
|
5874
|
+
var import_node_fs5 = require("node:fs");
|
|
5691
5875
|
var import_node_path7 = require("node:path");
|
|
5692
5876
|
async function indexStats(dbPath) {
|
|
5693
5877
|
const path = dbPath ?? DEFAULT_DB_PATH;
|
|
5694
|
-
if (!(0,
|
|
5878
|
+
if (!(0, import_node_fs5.existsSync)(path)) {
|
|
5695
5879
|
return { error: `Database not found at ${path}. Run 'cogpit-memory index rebuild' to create it.` };
|
|
5696
5880
|
}
|
|
5697
5881
|
const index = new SearchIndex(path);
|
|
@@ -5701,7 +5885,7 @@ async function indexStats(dbPath) {
|
|
|
5701
5885
|
}
|
|
5702
5886
|
async function indexRebuild(dbPath) {
|
|
5703
5887
|
const path = dbPath ?? DEFAULT_DB_PATH;
|
|
5704
|
-
(0,
|
|
5888
|
+
(0, import_node_fs5.mkdirSync)((0, import_node_path7.dirname)(path), { recursive: true });
|
|
5705
5889
|
const index = new SearchIndex(path);
|
|
5706
5890
|
index.buildFull();
|
|
5707
5891
|
const stats = index.getStats();
|
|
@@ -5710,7 +5894,7 @@ async function indexRebuild(dbPath) {
|
|
|
5710
5894
|
}
|
|
5711
5895
|
|
|
5712
5896
|
// src/commands/install-skill.ts
|
|
5713
|
-
var
|
|
5897
|
+
var import_node_fs6 = require("node:fs");
|
|
5714
5898
|
var import_node_path8 = require("node:path");
|
|
5715
5899
|
function findSkillContent() {
|
|
5716
5900
|
const candidates = [];
|
|
@@ -5720,8 +5904,8 @@ function findSkillContent() {
|
|
|
5720
5904
|
}
|
|
5721
5905
|
for (const candidate of candidates) {
|
|
5722
5906
|
try {
|
|
5723
|
-
if ((0,
|
|
5724
|
-
return (0,
|
|
5907
|
+
if ((0, import_node_fs6.existsSync)(candidate)) {
|
|
5908
|
+
return (0, import_node_fs6.readFileSync)(candidate, "utf-8");
|
|
5725
5909
|
}
|
|
5726
5910
|
} catch {
|
|
5727
5911
|
}
|
|
@@ -5731,10 +5915,10 @@ function findSkillContent() {
|
|
|
5731
5915
|
function installSkill(cwd, global) {
|
|
5732
5916
|
const root = global ? (0, import_node_path8.join)(process.env.HOME ?? process.env.USERPROFILE ?? "~", ".claude") : (0, import_node_path8.join)(cwd ?? process.cwd(), ".claude");
|
|
5733
5917
|
const skillDir = (0, import_node_path8.join)(root, "skills", "cogpit-memory");
|
|
5734
|
-
(0,
|
|
5918
|
+
(0, import_node_fs6.mkdirSync)(skillDir, { recursive: true });
|
|
5735
5919
|
const content = findSkillContent();
|
|
5736
5920
|
const dest = (0, import_node_path8.join)(skillDir, "SKILL.md");
|
|
5737
|
-
(0,
|
|
5921
|
+
(0, import_node_fs6.writeFileSync)(dest, content);
|
|
5738
5922
|
return { installed: true, path: skillDir };
|
|
5739
5923
|
}
|
|
5740
5924
|
|