ccpanel 0.1.5 → 0.1.6
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 +101 -31
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1508,6 +1508,18 @@ function blocksFromContent(content) {
|
|
|
1508
1508
|
}
|
|
1509
1509
|
return out;
|
|
1510
1510
|
}
|
|
1511
|
+
function outputText(output) {
|
|
1512
|
+
if (typeof output === "string") return output;
|
|
1513
|
+
return textFromContent(output);
|
|
1514
|
+
}
|
|
1515
|
+
function summaryText(summary) {
|
|
1516
|
+
if (!Array.isArray(summary)) return "";
|
|
1517
|
+
return summary.map((raw) => {
|
|
1518
|
+
if (!raw || typeof raw !== "object") return "";
|
|
1519
|
+
const s = raw;
|
|
1520
|
+
return typeof s.text === "string" ? s.text : "";
|
|
1521
|
+
}).filter(Boolean).join("\n");
|
|
1522
|
+
}
|
|
1511
1523
|
function parseFunctionArguments(args) {
|
|
1512
1524
|
if (typeof args !== "string") return JSON.stringify(args ?? {}, null, 2);
|
|
1513
1525
|
try {
|
|
@@ -1523,7 +1535,9 @@ var CodexSessionService = class {
|
|
|
1523
1535
|
this.readIndex(paths)
|
|
1524
1536
|
]);
|
|
1525
1537
|
const project = normalizeProjectPath(projectPath);
|
|
1526
|
-
return rollouts.filter(
|
|
1538
|
+
return rollouts.filter(
|
|
1539
|
+
(r) => normalizeProjectPath(r.cwd) === project && r.threadSource !== "subagent"
|
|
1540
|
+
).map((r) => {
|
|
1527
1541
|
const idx = index.get(r.id);
|
|
1528
1542
|
const mtime = idx?.updatedAt ? Date.parse(idx.updatedAt) : r.mtime;
|
|
1529
1543
|
return {
|
|
@@ -1538,12 +1552,38 @@ var CodexSessionService = class {
|
|
|
1538
1552
|
async read(paths, projectPath, id) {
|
|
1539
1553
|
assertSafeId2(id);
|
|
1540
1554
|
const project = normalizeProjectPath(projectPath);
|
|
1541
|
-
const
|
|
1555
|
+
const rollouts = await this.scanRollouts(paths);
|
|
1556
|
+
const found = rollouts.find(
|
|
1542
1557
|
(r) => r.id === id && normalizeProjectPath(r.cwd) === project
|
|
1543
1558
|
);
|
|
1544
1559
|
if (!found) throw new Error(`\u672A\u627E\u5230\u4F1A\u8BDD\uFF1A${id}`);
|
|
1545
1560
|
const parsed = this.parseDetail(await readFile9(found.file, "utf8"));
|
|
1546
|
-
|
|
1561
|
+
const subagents = await this.readSubagents(rollouts, parsed.subagentRefs);
|
|
1562
|
+
return { messages: parsed.messages, subagents, skippedRecords: parsed.skipped };
|
|
1563
|
+
}
|
|
1564
|
+
// 按 sub_agent_activity(started) 引用加载子会话;文件缺失或解析失败均跳过,
|
|
1565
|
+
// 不影响主会话展示。只嵌套一层:子会话内部的 subagentRefs 不再展开。
|
|
1566
|
+
async readSubagents(rollouts, refs) {
|
|
1567
|
+
const out = [];
|
|
1568
|
+
for (const ref of refs) {
|
|
1569
|
+
const rollout = rollouts.find((r) => r.id === ref.threadId);
|
|
1570
|
+
if (!rollout) continue;
|
|
1571
|
+
let parsed;
|
|
1572
|
+
try {
|
|
1573
|
+
parsed = this.parseDetail(await readFile9(rollout.file, "utf8"));
|
|
1574
|
+
} catch {
|
|
1575
|
+
continue;
|
|
1576
|
+
}
|
|
1577
|
+
const firstUser = parsed.messages.find((m) => m.type === "user");
|
|
1578
|
+
out.push({
|
|
1579
|
+
toolUseId: ref.toolUseId,
|
|
1580
|
+
agentId: ref.threadId,
|
|
1581
|
+
agentType: ref.agentPath.split("/").filter(Boolean).pop() ?? "subagent",
|
|
1582
|
+
description: (firstUser?.blocks[0]?.text ?? "").replace(/\s+/g, " ").trim().slice(0, 200),
|
|
1583
|
+
messages: parsed.messages
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
return out;
|
|
1547
1587
|
}
|
|
1548
1588
|
async scanRollouts(paths) {
|
|
1549
1589
|
const files = await this.rolloutFiles(paths.codexSessionsDir);
|
|
@@ -1580,6 +1620,7 @@ var CodexSessionService = class {
|
|
|
1580
1620
|
let cwd = "";
|
|
1581
1621
|
let firstPrompt = "";
|
|
1582
1622
|
let messageCount = 0;
|
|
1623
|
+
let threadSource;
|
|
1583
1624
|
for (const line of raw.split("\n")) {
|
|
1584
1625
|
if (!line.trim()) continue;
|
|
1585
1626
|
let obj;
|
|
@@ -1592,6 +1633,7 @@ var CodexSessionService = class {
|
|
|
1592
1633
|
if (obj.type === "session_meta" || payload.type === "session_meta") {
|
|
1593
1634
|
id = String(payload.id ?? id);
|
|
1594
1635
|
cwd = String(payload.cwd ?? cwd);
|
|
1636
|
+
if (payload.thread_source) threadSource = String(payload.thread_source);
|
|
1595
1637
|
continue;
|
|
1596
1638
|
}
|
|
1597
1639
|
if (payload.type === "message") {
|
|
@@ -1607,7 +1649,16 @@ var CodexSessionService = class {
|
|
|
1607
1649
|
id = m?.[1] ?? "";
|
|
1608
1650
|
}
|
|
1609
1651
|
if (!id || !cwd) return void 0;
|
|
1610
|
-
return {
|
|
1652
|
+
return {
|
|
1653
|
+
id,
|
|
1654
|
+
file,
|
|
1655
|
+
cwd,
|
|
1656
|
+
mtime: st.mtimeMs,
|
|
1657
|
+
size: st.size,
|
|
1658
|
+
firstPrompt,
|
|
1659
|
+
messageCount,
|
|
1660
|
+
threadSource
|
|
1661
|
+
};
|
|
1611
1662
|
}
|
|
1612
1663
|
async readIndex(paths) {
|
|
1613
1664
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -1637,8 +1688,22 @@ var CodexSessionService = class {
|
|
|
1637
1688
|
}
|
|
1638
1689
|
parseDetail(raw) {
|
|
1639
1690
|
const messages = [];
|
|
1691
|
+
const subagentRefs = [];
|
|
1640
1692
|
let skipped = 0;
|
|
1641
1693
|
let currentAssistant;
|
|
1694
|
+
let pendingReasoning = "";
|
|
1695
|
+
const ensureAssistant = (timestamp) => {
|
|
1696
|
+
if (!currentAssistant) {
|
|
1697
|
+
currentAssistant = {
|
|
1698
|
+
type: "assistant",
|
|
1699
|
+
role: "assistant",
|
|
1700
|
+
timestamp: timestamp ? String(timestamp) : void 0,
|
|
1701
|
+
blocks: []
|
|
1702
|
+
};
|
|
1703
|
+
messages.push(currentAssistant);
|
|
1704
|
+
}
|
|
1705
|
+
return currentAssistant;
|
|
1706
|
+
};
|
|
1642
1707
|
for (const line of raw.split("\n")) {
|
|
1643
1708
|
if (!line.trim()) continue;
|
|
1644
1709
|
let obj;
|
|
@@ -1649,6 +1714,30 @@ var CodexSessionService = class {
|
|
|
1649
1714
|
continue;
|
|
1650
1715
|
}
|
|
1651
1716
|
const payload = payloadOf(obj);
|
|
1717
|
+
if (payload.type === "agent_reasoning") {
|
|
1718
|
+
const text = String(payload.text ?? "").trim();
|
|
1719
|
+
if (text) pendingReasoning = text;
|
|
1720
|
+
continue;
|
|
1721
|
+
}
|
|
1722
|
+
if (payload.type === "reasoning") {
|
|
1723
|
+
const text = pendingReasoning || summaryText(payload.summary);
|
|
1724
|
+
pendingReasoning = "";
|
|
1725
|
+
ensureAssistant(obj.timestamp).blocks.push({
|
|
1726
|
+
kind: "thinking",
|
|
1727
|
+
text: truncate2(text)
|
|
1728
|
+
});
|
|
1729
|
+
continue;
|
|
1730
|
+
}
|
|
1731
|
+
if (payload.type === "sub_agent_activity") {
|
|
1732
|
+
if (payload.kind === "started" && payload.event_id && payload.agent_thread_id) {
|
|
1733
|
+
subagentRefs.push({
|
|
1734
|
+
toolUseId: String(payload.event_id),
|
|
1735
|
+
threadId: String(payload.agent_thread_id),
|
|
1736
|
+
agentPath: String(payload.agent_path ?? "")
|
|
1737
|
+
});
|
|
1738
|
+
}
|
|
1739
|
+
continue;
|
|
1740
|
+
}
|
|
1652
1741
|
if (payload.type === "message") {
|
|
1653
1742
|
const role = String(payload.role ?? "");
|
|
1654
1743
|
if (role !== "user" && role !== "assistant") continue;
|
|
@@ -1663,45 +1752,26 @@ var CodexSessionService = class {
|
|
|
1663
1752
|
currentAssistant = role === "assistant" ? msg : void 0;
|
|
1664
1753
|
continue;
|
|
1665
1754
|
}
|
|
1666
|
-
if (payload.type === "function_call") {
|
|
1667
|
-
const
|
|
1668
|
-
|
|
1669
|
-
role: "assistant",
|
|
1670
|
-
timestamp: obj.timestamp ? String(obj.timestamp) : void 0,
|
|
1671
|
-
blocks: []
|
|
1672
|
-
};
|
|
1673
|
-
if (!currentAssistant) {
|
|
1674
|
-
messages.push(target);
|
|
1675
|
-
currentAssistant = target;
|
|
1676
|
-
}
|
|
1677
|
-
target.blocks.push({
|
|
1755
|
+
if (payload.type === "function_call" || payload.type === "custom_tool_call") {
|
|
1756
|
+
const args = payload.type === "custom_tool_call" ? payload.input : payload.arguments;
|
|
1757
|
+
ensureAssistant(obj.timestamp).blocks.push({
|
|
1678
1758
|
kind: "tool_use",
|
|
1679
1759
|
name: String(payload.name ?? "tool"),
|
|
1680
|
-
text: truncate2(parseFunctionArguments(
|
|
1760
|
+
text: truncate2(parseFunctionArguments(args)),
|
|
1681
1761
|
toolUseId: payload.call_id ? String(payload.call_id) : void 0
|
|
1682
1762
|
});
|
|
1683
1763
|
continue;
|
|
1684
1764
|
}
|
|
1685
|
-
if (payload.type === "function_call_output") {
|
|
1686
|
-
|
|
1687
|
-
type: "assistant",
|
|
1688
|
-
role: "assistant",
|
|
1689
|
-
timestamp: obj.timestamp ? String(obj.timestamp) : void 0,
|
|
1690
|
-
blocks: []
|
|
1691
|
-
};
|
|
1692
|
-
if (!currentAssistant) {
|
|
1693
|
-
messages.push(target);
|
|
1694
|
-
currentAssistant = target;
|
|
1695
|
-
}
|
|
1696
|
-
target.blocks.push({
|
|
1765
|
+
if (payload.type === "function_call_output" || payload.type === "custom_tool_call_output") {
|
|
1766
|
+
ensureAssistant(obj.timestamp).blocks.push({
|
|
1697
1767
|
kind: "tool_result",
|
|
1698
|
-
text: truncate2(
|
|
1768
|
+
text: truncate2(outputText(payload.output)),
|
|
1699
1769
|
isError: payload.is_error === true,
|
|
1700
1770
|
toolUseId: payload.call_id ? String(payload.call_id) : void 0
|
|
1701
1771
|
});
|
|
1702
1772
|
}
|
|
1703
1773
|
}
|
|
1704
|
-
return { messages, skipped };
|
|
1774
|
+
return { messages, skipped, subagentRefs };
|
|
1705
1775
|
}
|
|
1706
1776
|
};
|
|
1707
1777
|
|