adhdev 0.8.75 → 0.8.77
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/index.js +764 -182
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +742 -160
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1546,6 +1546,67 @@ var init_host_memory = __esm({
|
|
|
1546
1546
|
}
|
|
1547
1547
|
});
|
|
1548
1548
|
|
|
1549
|
+
// ../../oss/packages/daemon-core/src/session-host/runtime-surface.ts
|
|
1550
|
+
function isSessionHostLiveRuntime(record2) {
|
|
1551
|
+
const lifecycle = String(record2?.lifecycle || "").trim();
|
|
1552
|
+
return LIVE_LIFECYCLES.has(lifecycle);
|
|
1553
|
+
}
|
|
1554
|
+
function getSessionHostRecoveryLabel(meta3) {
|
|
1555
|
+
const recoveryState = typeof meta3?.runtimeRecoveryState === "string" ? String(meta3.runtimeRecoveryState).trim() : "";
|
|
1556
|
+
if (!recoveryState) return null;
|
|
1557
|
+
if (recoveryState === "auto_resumed") return "restored after restart";
|
|
1558
|
+
if (recoveryState === "resume_failed") return "restore failed";
|
|
1559
|
+
if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
|
|
1560
|
+
if (recoveryState === "orphan_snapshot") return "snapshot recovered";
|
|
1561
|
+
return recoveryState.replace(/_/g, " ");
|
|
1562
|
+
}
|
|
1563
|
+
function isSessionHostRecoverySnapshot(record2) {
|
|
1564
|
+
if (!record2) return false;
|
|
1565
|
+
if (isSessionHostLiveRuntime(record2)) return false;
|
|
1566
|
+
const lifecycle = String(record2.lifecycle || "").trim();
|
|
1567
|
+
if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
|
|
1568
|
+
return false;
|
|
1569
|
+
}
|
|
1570
|
+
const meta3 = record2.meta || void 0;
|
|
1571
|
+
if (meta3?.restoredFromStorage === true) return true;
|
|
1572
|
+
return getSessionHostRecoveryLabel(meta3) !== null;
|
|
1573
|
+
}
|
|
1574
|
+
function getSessionHostSurfaceKind(record2) {
|
|
1575
|
+
if (isSessionHostLiveRuntime(record2)) return "live_runtime";
|
|
1576
|
+
if (isSessionHostRecoverySnapshot(record2)) return "recovery_snapshot";
|
|
1577
|
+
return "inactive_record";
|
|
1578
|
+
}
|
|
1579
|
+
function partitionSessionHostRecords(records) {
|
|
1580
|
+
const liveRuntimes = [];
|
|
1581
|
+
const recoverySnapshots = [];
|
|
1582
|
+
const inactiveRecords = [];
|
|
1583
|
+
for (const record2 of records) {
|
|
1584
|
+
const kind = getSessionHostSurfaceKind(record2);
|
|
1585
|
+
if (kind === "live_runtime") {
|
|
1586
|
+
liveRuntimes.push(record2);
|
|
1587
|
+
} else if (kind === "recovery_snapshot") {
|
|
1588
|
+
recoverySnapshots.push(record2);
|
|
1589
|
+
} else {
|
|
1590
|
+
inactiveRecords.push(record2);
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
return {
|
|
1594
|
+
liveRuntimes,
|
|
1595
|
+
recoverySnapshots,
|
|
1596
|
+
inactiveRecords
|
|
1597
|
+
};
|
|
1598
|
+
}
|
|
1599
|
+
function partitionSessionHostDiagnosticsSessions(records) {
|
|
1600
|
+
return partitionSessionHostRecords(records || []);
|
|
1601
|
+
}
|
|
1602
|
+
var LIVE_LIFECYCLES;
|
|
1603
|
+
var init_runtime_surface = __esm({
|
|
1604
|
+
"../../oss/packages/daemon-core/src/session-host/runtime-surface.ts"() {
|
|
1605
|
+
"use strict";
|
|
1606
|
+
LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
1607
|
+
}
|
|
1608
|
+
});
|
|
1609
|
+
|
|
1549
1610
|
// ../../oss/packages/daemon-core/src/status/chat-tail-hot-sessions.ts
|
|
1550
1611
|
function parseMessageTimestamp(value) {
|
|
1551
1612
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
@@ -1555,6 +1616,23 @@ function parseMessageTimestamp(value) {
|
|
|
1555
1616
|
}
|
|
1556
1617
|
return 0;
|
|
1557
1618
|
}
|
|
1619
|
+
function isDefinitelyNonLiveRuntimeSession(session) {
|
|
1620
|
+
const surfaceKind = String(session?.runtimeSurfaceKind || "").trim();
|
|
1621
|
+
if (surfaceKind === "live_runtime") return false;
|
|
1622
|
+
if (surfaceKind === "recovery_snapshot") return true;
|
|
1623
|
+
if (surfaceKind === "inactive_record") return false;
|
|
1624
|
+
const lifecycle = String(session?.runtimeLifecycle || "").trim();
|
|
1625
|
+
if (lifecycle && LIVE_RUNTIME_LIFECYCLES.has(lifecycle)) return false;
|
|
1626
|
+
const inferredSurfaceKind = getSessionHostSurfaceKind({
|
|
1627
|
+
lifecycle: lifecycle || null,
|
|
1628
|
+
meta: {
|
|
1629
|
+
restoredFromStorage: session?.runtimeRestoredFromStorage === true,
|
|
1630
|
+
...session?.runtimeRecoveryState ? { runtimeRecoveryState: session.runtimeRecoveryState } : {}
|
|
1631
|
+
}
|
|
1632
|
+
});
|
|
1633
|
+
if (inferredSurfaceKind === "recovery_snapshot") return true;
|
|
1634
|
+
return false;
|
|
1635
|
+
}
|
|
1558
1636
|
function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessionIds, options = {}) {
|
|
1559
1637
|
const now = options.now ?? Date.now();
|
|
1560
1638
|
const recentMessageGraceMs = Math.max(
|
|
@@ -1563,9 +1641,14 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
|
|
|
1563
1641
|
);
|
|
1564
1642
|
const activeStatuses = options.activeStatuses ?? DEFAULT_ACTIVE_CHAT_POLL_STATUSES;
|
|
1565
1643
|
const active = /* @__PURE__ */ new Set();
|
|
1644
|
+
const excluded = /* @__PURE__ */ new Set();
|
|
1566
1645
|
for (const session of sessions) {
|
|
1567
1646
|
const sessionId = typeof session?.id === "string" ? session.id : "";
|
|
1568
1647
|
if (!sessionId) continue;
|
|
1648
|
+
if (isDefinitelyNonLiveRuntimeSession(session)) {
|
|
1649
|
+
excluded.add(sessionId);
|
|
1650
|
+
continue;
|
|
1651
|
+
}
|
|
1569
1652
|
const status = String(session?.status || "").toLowerCase();
|
|
1570
1653
|
const lastMessageAt = parseMessageTimestamp(session?.lastMessageAt);
|
|
1571
1654
|
const recentlyUpdated = lastMessageAt > 0 && now - lastMessageAt <= recentMessageGraceMs;
|
|
@@ -1574,20 +1657,22 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
|
|
|
1574
1657
|
}
|
|
1575
1658
|
}
|
|
1576
1659
|
const finalizing = new Set(
|
|
1577
|
-
Array.from(previousHotSessionIds).filter((sessionId) => !active.has(sessionId))
|
|
1660
|
+
Array.from(previousHotSessionIds).filter((sessionId) => !active.has(sessionId) && !excluded.has(sessionId))
|
|
1578
1661
|
);
|
|
1579
1662
|
return { active, finalizing };
|
|
1580
1663
|
}
|
|
1581
|
-
var DEFAULT_ACTIVE_CHAT_POLL_STATUSES, DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS;
|
|
1664
|
+
var DEFAULT_ACTIVE_CHAT_POLL_STATUSES, DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS, LIVE_RUNTIME_LIFECYCLES;
|
|
1582
1665
|
var init_chat_tail_hot_sessions = __esm({
|
|
1583
1666
|
"../../oss/packages/daemon-core/src/status/chat-tail-hot-sessions.ts"() {
|
|
1584
1667
|
"use strict";
|
|
1668
|
+
init_runtime_surface();
|
|
1585
1669
|
DEFAULT_ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
|
|
1586
1670
|
"generating",
|
|
1587
1671
|
"waiting_approval",
|
|
1588
1672
|
"starting"
|
|
1589
1673
|
]);
|
|
1590
1674
|
DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS = 8e3;
|
|
1675
|
+
LIVE_RUNTIME_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
1591
1676
|
}
|
|
1592
1677
|
});
|
|
1593
1678
|
|
|
@@ -1807,6 +1892,32 @@ var init_logger = __esm({
|
|
|
1807
1892
|
});
|
|
1808
1893
|
|
|
1809
1894
|
// ../../oss/packages/daemon-core/src/cdp/manager.ts
|
|
1895
|
+
function normalizeTitle(value) {
|
|
1896
|
+
return String(value || "").trim().replace(/\s+/g, " ").toLowerCase();
|
|
1897
|
+
}
|
|
1898
|
+
function titlesMatch(lhs, rhs) {
|
|
1899
|
+
const a = normalizeTitle(lhs);
|
|
1900
|
+
const b = normalizeTitle(rhs);
|
|
1901
|
+
if (!a || !b) return false;
|
|
1902
|
+
return a === b || a.includes(b) || b.includes(a);
|
|
1903
|
+
}
|
|
1904
|
+
function resolveCdpPageTarget(params) {
|
|
1905
|
+
const { pages, pinnedTargetId, previousPageTitle } = params;
|
|
1906
|
+
if (pages.length === 0) return { target: null, retargeted: false };
|
|
1907
|
+
if (!pinnedTargetId) {
|
|
1908
|
+
return { target: pages[0] || null, retargeted: false };
|
|
1909
|
+
}
|
|
1910
|
+
const exact = pages.find((page) => page.id === pinnedTargetId);
|
|
1911
|
+
if (exact) return { target: exact, retargeted: false };
|
|
1912
|
+
const titleMatchesList = pages.filter((page) => titlesMatch(page.title, previousPageTitle));
|
|
1913
|
+
if (titleMatchesList.length === 1) {
|
|
1914
|
+
return { target: titleMatchesList[0], retargeted: true };
|
|
1915
|
+
}
|
|
1916
|
+
if (pages.length === 1) {
|
|
1917
|
+
return { target: pages[0], retargeted: true };
|
|
1918
|
+
}
|
|
1919
|
+
return { target: null, retargeted: false };
|
|
1920
|
+
}
|
|
1810
1921
|
var import_ws, http, DaemonCdpManager;
|
|
1811
1922
|
var init_manager = __esm({
|
|
1812
1923
|
"../../oss/packages/daemon-core/src/cdp/manager.ts"() {
|
|
@@ -1974,18 +2085,28 @@ var init_manager = __esm({
|
|
|
1974
2085
|
resolve17(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
1975
2086
|
return;
|
|
1976
2087
|
}
|
|
1977
|
-
const
|
|
1978
|
-
const
|
|
2088
|
+
const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
2089
|
+
const mainPages = titleFilteredPages.filter((t) => this.isMainPageUrl(t.url));
|
|
2090
|
+
const list = mainPages.length > 0 ? mainPages : titleFilteredPages.length > 0 ? titleFilteredPages : pages;
|
|
1979
2091
|
this.log(`[CDP] pages(${list.length}): ${list.map((t) => `"${t.title}"`).join(", ")}`);
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
2092
|
+
const previousTargetId = this._targetId;
|
|
2093
|
+
const selected = resolveCdpPageTarget({
|
|
2094
|
+
pages: list,
|
|
2095
|
+
pinnedTargetId: previousTargetId,
|
|
2096
|
+
previousPageTitle: this._pageTitle
|
|
2097
|
+
});
|
|
2098
|
+
if (selected.target) {
|
|
2099
|
+
if (selected.retargeted && previousTargetId && previousTargetId !== selected.target.id) {
|
|
2100
|
+
this.log(`[CDP] Target ${previousTargetId} rekeyed to ${selected.target.id}`);
|
|
2101
|
+
this._targetId = selected.target.id;
|
|
1988
2102
|
}
|
|
2103
|
+
this._pageTitle = selected.target.title || "";
|
|
2104
|
+
resolve17(selected.target);
|
|
2105
|
+
return;
|
|
2106
|
+
}
|
|
2107
|
+
if (previousTargetId) {
|
|
2108
|
+
this.log(`[CDP] Target ${previousTargetId} not found in page list`);
|
|
2109
|
+
resolve17(null);
|
|
1989
2110
|
return;
|
|
1990
2111
|
}
|
|
1991
2112
|
this._pageTitle = list[0]?.title || "";
|
|
@@ -3862,6 +3983,68 @@ function sanitizeHistoryMessage(agentType, message) {
|
|
|
3862
3983
|
content
|
|
3863
3984
|
};
|
|
3864
3985
|
}
|
|
3986
|
+
function sortSavedHistorySessionSummaries(summaries) {
|
|
3987
|
+
return summaries.slice().sort((a, b) => b.lastMessageAt - a.lastMessageAt);
|
|
3988
|
+
}
|
|
3989
|
+
function buildSavedHistorySessionSummaryMapFromEntries(entries) {
|
|
3990
|
+
const summaries = /* @__PURE__ */ new Map();
|
|
3991
|
+
for (const entry of Array.from(entries.values())) {
|
|
3992
|
+
const fileSummary = entry.summary;
|
|
3993
|
+
if (!fileSummary || fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) continue;
|
|
3994
|
+
const existing = summaries.get(fileSummary.historySessionId);
|
|
3995
|
+
if (!existing) {
|
|
3996
|
+
summaries.set(fileSummary.historySessionId, {
|
|
3997
|
+
historySessionId: fileSummary.historySessionId,
|
|
3998
|
+
sessionTitle: fileSummary.sessionTitle,
|
|
3999
|
+
messageCount: fileSummary.messageCount,
|
|
4000
|
+
firstMessageAt: fileSummary.firstMessageAt,
|
|
4001
|
+
lastMessageAt: fileSummary.lastMessageAt,
|
|
4002
|
+
preview: fileSummary.preview,
|
|
4003
|
+
workspace: fileSummary.workspace
|
|
4004
|
+
});
|
|
4005
|
+
continue;
|
|
4006
|
+
}
|
|
4007
|
+
existing.messageCount += fileSummary.messageCount;
|
|
4008
|
+
if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
|
|
4009
|
+
existing.firstMessageAt = fileSummary.firstMessageAt;
|
|
4010
|
+
}
|
|
4011
|
+
if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
|
|
4012
|
+
existing.lastMessageAt = fileSummary.lastMessageAt;
|
|
4013
|
+
if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
|
|
4014
|
+
if (fileSummary.preview) existing.preview = fileSummary.preview;
|
|
4015
|
+
}
|
|
4016
|
+
if (!existing.workspace && fileSummary.workspace) {
|
|
4017
|
+
existing.workspace = fileSummary.workspace;
|
|
4018
|
+
}
|
|
4019
|
+
}
|
|
4020
|
+
return Object.fromEntries(sortSavedHistorySessionSummaries(Array.from(summaries.values())).map((summary) => [summary.historySessionId, summary]));
|
|
4021
|
+
}
|
|
4022
|
+
function readPersistedSavedHistorySessionSummaries(dir) {
|
|
4023
|
+
try {
|
|
4024
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
4025
|
+
if (!fs3.existsSync(filePath)) return null;
|
|
4026
|
+
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
4027
|
+
if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.sessions || typeof raw.sessions !== "object") {
|
|
4028
|
+
return null;
|
|
4029
|
+
}
|
|
4030
|
+
return sortSavedHistorySessionSummaries(
|
|
4031
|
+
Object.values(raw.sessions).filter((summary) => !!summary && typeof summary.historySessionId === "string" && summary.messageCount > 0 && summary.lastMessageAt > 0).map((summary) => ({
|
|
4032
|
+
historySessionId: summary.historySessionId,
|
|
4033
|
+
sessionTitle: summary.sessionTitle,
|
|
4034
|
+
messageCount: summary.messageCount,
|
|
4035
|
+
firstMessageAt: summary.firstMessageAt,
|
|
4036
|
+
lastMessageAt: summary.lastMessageAt,
|
|
4037
|
+
preview: summary.preview,
|
|
4038
|
+
workspace: summary.workspace
|
|
4039
|
+
}))
|
|
4040
|
+
);
|
|
4041
|
+
} catch {
|
|
4042
|
+
return null;
|
|
4043
|
+
}
|
|
4044
|
+
}
|
|
4045
|
+
function shouldScheduleSavedHistoryRollup(totalBytes) {
|
|
4046
|
+
return Number.isFinite(totalBytes) && totalBytes >= SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES;
|
|
4047
|
+
}
|
|
3865
4048
|
function sanitizeHistoryFileSegment(value) {
|
|
3866
4049
|
return String(value || "").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3867
4050
|
}
|
|
@@ -3875,71 +4058,386 @@ function listHistoryFiles(dir, historySessionId) {
|
|
|
3875
4058
|
return true;
|
|
3876
4059
|
}).sort().reverse();
|
|
3877
4060
|
}
|
|
3878
|
-
function
|
|
3879
|
-
|
|
4061
|
+
function normalizeSavedHistorySessionId(agentType, historySessionId) {
|
|
4062
|
+
const normalizedId = String(historySessionId || "").trim();
|
|
4063
|
+
if (!normalizedId) return "";
|
|
4064
|
+
const strictProviderId = normalizeProviderSessionId(agentType, normalizedId);
|
|
4065
|
+
if (strictProviderId) return strictProviderId;
|
|
4066
|
+
return agentType === "hermes-cli" ? "" : normalizedId;
|
|
4067
|
+
}
|
|
4068
|
+
function extractSavedHistorySessionIdFromFile(agentType, file2) {
|
|
4069
|
+
const match = file2.match(/^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/);
|
|
4070
|
+
return normalizeSavedHistorySessionId(agentType, match?.[1] || "");
|
|
4071
|
+
}
|
|
4072
|
+
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
4073
|
+
return new Map(files.map((file2) => {
|
|
3880
4074
|
try {
|
|
3881
4075
|
const stat4 = fs3.statSync(path7.join(dir, file2));
|
|
3882
|
-
return `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}
|
|
4076
|
+
return [file2, `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`];
|
|
3883
4077
|
} catch {
|
|
3884
|
-
return `${file2}:missing
|
|
3885
|
-
}
|
|
3886
|
-
})
|
|
3887
|
-
}
|
|
3888
|
-
function
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
4078
|
+
return [file2, `${file2}:missing`];
|
|
4079
|
+
}
|
|
4080
|
+
}));
|
|
4081
|
+
}
|
|
4082
|
+
function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
4083
|
+
return files.map((file2) => fileSignatures.get(file2) || `${file2}:missing`).join("|");
|
|
4084
|
+
}
|
|
4085
|
+
function getSavedHistoryIndexFilePath(dir) {
|
|
4086
|
+
return path7.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
4087
|
+
}
|
|
4088
|
+
function getSavedHistoryIndexLockPath(dir) {
|
|
4089
|
+
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
4090
|
+
}
|
|
4091
|
+
function sleepBlocking(ms) {
|
|
4092
|
+
if (ms <= 0) return;
|
|
4093
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
4094
|
+
}
|
|
4095
|
+
function loadPersistedSavedHistoryIndexFromFile(dir) {
|
|
4096
|
+
try {
|
|
4097
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
4098
|
+
if (!fs3.existsSync(filePath)) return /* @__PURE__ */ new Map();
|
|
4099
|
+
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
4100
|
+
if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.files || typeof raw.files !== "object") {
|
|
4101
|
+
return /* @__PURE__ */ new Map();
|
|
4102
|
+
}
|
|
4103
|
+
return new Map(
|
|
4104
|
+
Object.entries(raw.files).filter(([file2, entry]) => !!file2 && !!entry && typeof entry.signature === "string").map(([file2, entry]) => [file2, {
|
|
4105
|
+
signature: entry.signature,
|
|
4106
|
+
summary: entry.summary || null
|
|
4107
|
+
}])
|
|
4108
|
+
);
|
|
4109
|
+
} catch {
|
|
4110
|
+
return /* @__PURE__ */ new Map();
|
|
4111
|
+
}
|
|
4112
|
+
}
|
|
4113
|
+
function writePersistedSavedHistoryIndexFile(dir, entries) {
|
|
4114
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
4115
|
+
const tempPath = `${filePath}.tmp`;
|
|
4116
|
+
const payload = {
|
|
4117
|
+
version: SAVED_HISTORY_INDEX_VERSION,
|
|
4118
|
+
files: Object.fromEntries(entries.entries()),
|
|
4119
|
+
sessions: buildSavedHistorySessionSummaryMapFromEntries(entries)
|
|
4120
|
+
};
|
|
4121
|
+
fs3.writeFileSync(tempPath, JSON.stringify(payload), "utf-8");
|
|
4122
|
+
fs3.renameSync(tempPath, filePath);
|
|
4123
|
+
}
|
|
4124
|
+
function acquireSavedHistoryIndexLock(dir) {
|
|
4125
|
+
const lockPath = getSavedHistoryIndexLockPath(dir);
|
|
4126
|
+
const deadline = Date.now() + SAVED_HISTORY_INDEX_LOCK_WAIT_MS;
|
|
4127
|
+
while (Date.now() <= deadline) {
|
|
4128
|
+
try {
|
|
4129
|
+
fs3.mkdirSync(lockPath);
|
|
4130
|
+
return () => {
|
|
3913
4131
|
try {
|
|
3914
|
-
|
|
4132
|
+
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
3915
4133
|
} catch {
|
|
3916
|
-
parsed = null;
|
|
3917
4134
|
}
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
4135
|
+
};
|
|
4136
|
+
} catch (error48) {
|
|
4137
|
+
if (error48?.code !== "EEXIST") return null;
|
|
4138
|
+
try {
|
|
4139
|
+
const stat4 = fs3.statSync(lockPath);
|
|
4140
|
+
if (Date.now() - stat4.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
|
|
4141
|
+
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
3921
4142
|
continue;
|
|
3922
4143
|
}
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
4144
|
+
} catch {
|
|
4145
|
+
continue;
|
|
4146
|
+
}
|
|
4147
|
+
sleepBlocking(SAVED_HISTORY_INDEX_LOCK_POLL_MS);
|
|
4148
|
+
}
|
|
4149
|
+
}
|
|
4150
|
+
return null;
|
|
4151
|
+
}
|
|
4152
|
+
function withLockedPersistedSavedHistoryIndex(dir, callback) {
|
|
4153
|
+
const release2 = acquireSavedHistoryIndexLock(dir);
|
|
4154
|
+
if (!release2) return null;
|
|
4155
|
+
try {
|
|
4156
|
+
const entries = loadPersistedSavedHistoryIndexFromFile(dir);
|
|
4157
|
+
const result = callback(entries);
|
|
4158
|
+
writePersistedSavedHistoryIndexFile(dir, entries);
|
|
4159
|
+
return result;
|
|
4160
|
+
} catch {
|
|
4161
|
+
return null;
|
|
4162
|
+
} finally {
|
|
4163
|
+
release2();
|
|
3940
4164
|
}
|
|
3941
|
-
|
|
3942
|
-
|
|
4165
|
+
}
|
|
4166
|
+
function loadPersistedSavedHistoryIndex(dir) {
|
|
4167
|
+
return loadPersistedSavedHistoryIndexFromFile(dir);
|
|
4168
|
+
}
|
|
4169
|
+
function savePersistedSavedHistoryIndex(dir, entries) {
|
|
4170
|
+
withLockedPersistedSavedHistoryIndex(dir, (currentEntries) => {
|
|
4171
|
+
const incomingFiles = new Set(Array.from(entries.keys()));
|
|
4172
|
+
for (const [file2, entry] of Array.from(entries.entries())) {
|
|
4173
|
+
const liveSignature = buildSavedHistoryFileSignature(dir, file2);
|
|
4174
|
+
const existingEntry = currentEntries.get(file2);
|
|
4175
|
+
if (existingEntry && existingEntry.signature !== liveSignature && entry.signature !== liveSignature) {
|
|
4176
|
+
continue;
|
|
4177
|
+
}
|
|
4178
|
+
if (entry.signature !== liveSignature && (!existingEntry || existingEntry.signature !== liveSignature)) {
|
|
4179
|
+
continue;
|
|
4180
|
+
}
|
|
4181
|
+
currentEntries.set(file2, entry.signature === liveSignature ? entry : {
|
|
4182
|
+
signature: liveSignature,
|
|
4183
|
+
summary: existingEntry?.summary || entry.summary
|
|
4184
|
+
});
|
|
4185
|
+
}
|
|
4186
|
+
for (const file2 of Array.from(currentEntries.keys())) {
|
|
4187
|
+
if (incomingFiles.has(file2)) continue;
|
|
4188
|
+
if (!fs3.existsSync(path7.join(dir, file2))) {
|
|
4189
|
+
currentEntries.delete(file2);
|
|
4190
|
+
}
|
|
4191
|
+
}
|
|
4192
|
+
});
|
|
4193
|
+
}
|
|
4194
|
+
function invalidatePersistedSavedHistoryIndex(agentType, dir) {
|
|
4195
|
+
try {
|
|
4196
|
+
fs3.rmSync(getSavedHistoryIndexFilePath(dir), { force: true });
|
|
4197
|
+
} catch {
|
|
4198
|
+
}
|
|
4199
|
+
savedHistorySessionCache.delete(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"));
|
|
4200
|
+
}
|
|
4201
|
+
function buildSavedHistoryIndexFileSignature(dir) {
|
|
4202
|
+
try {
|
|
4203
|
+
const stat4 = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
4204
|
+
return `index:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
|
|
4205
|
+
} catch {
|
|
4206
|
+
return "index:missing";
|
|
4207
|
+
}
|
|
4208
|
+
}
|
|
4209
|
+
function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
4210
|
+
try {
|
|
4211
|
+
const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
4212
|
+
const files = listHistoryFiles(dir);
|
|
4213
|
+
for (const file2 of files) {
|
|
4214
|
+
const stat4 = fs3.statSync(path7.join(dir, file2));
|
|
4215
|
+
if (stat4.mtimeMs > indexStat.mtimeMs) return true;
|
|
4216
|
+
}
|
|
4217
|
+
return false;
|
|
4218
|
+
} catch {
|
|
4219
|
+
return true;
|
|
4220
|
+
}
|
|
4221
|
+
}
|
|
4222
|
+
function buildSavedHistoryFileSignature(dir, file2) {
|
|
4223
|
+
try {
|
|
4224
|
+
const stat4 = fs3.statSync(path7.join(dir, file2));
|
|
4225
|
+
return `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
|
|
4226
|
+
} catch {
|
|
4227
|
+
return `${file2}:missing`;
|
|
4228
|
+
}
|
|
4229
|
+
}
|
|
4230
|
+
function persistSavedHistoryFileSummaryEntry(agentType, dir, file2, updater) {
|
|
4231
|
+
const filePath = path7.join(dir, file2);
|
|
4232
|
+
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
4233
|
+
const currentEntry = entries.get(file2) || null;
|
|
4234
|
+
const nextSummary = updater(currentEntry?.summary || null);
|
|
4235
|
+
const nextEntry = {
|
|
4236
|
+
signature: buildSavedHistoryFileSignature(dir, file2),
|
|
4237
|
+
summary: nextSummary
|
|
4238
|
+
};
|
|
4239
|
+
entries.set(file2, nextEntry);
|
|
4240
|
+
savedHistoryFileSummaryCache.set(filePath, nextEntry);
|
|
4241
|
+
return nextEntry;
|
|
4242
|
+
});
|
|
4243
|
+
if (!result) return;
|
|
4244
|
+
if (result.summary?.historySessionId && shouldScheduleSavedHistoryRollupForSignature(result.signature)) {
|
|
4245
|
+
scheduleSavedHistoryRollup(agentType, result.summary.historySessionId);
|
|
4246
|
+
}
|
|
4247
|
+
}
|
|
4248
|
+
function updateSavedHistoryIndexForSessionStart(agentType, dir, file2, historySessionId, workspace) {
|
|
4249
|
+
const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId);
|
|
4250
|
+
const normalizedWorkspace = String(workspace || "").trim();
|
|
4251
|
+
if (!normalizedSessionId || !normalizedWorkspace) return;
|
|
4252
|
+
persistSavedHistoryFileSummaryEntry(agentType, dir, file2, (currentSummary) => ({
|
|
4253
|
+
file: file2,
|
|
4254
|
+
historySessionId: normalizedSessionId,
|
|
4255
|
+
messageCount: currentSummary?.messageCount || 0,
|
|
4256
|
+
firstMessageAt: currentSummary?.firstMessageAt || 0,
|
|
4257
|
+
lastMessageAt: currentSummary?.lastMessageAt || 0,
|
|
4258
|
+
sessionTitle: currentSummary?.sessionTitle,
|
|
4259
|
+
preview: currentSummary?.preview,
|
|
4260
|
+
workspace: normalizedWorkspace
|
|
4261
|
+
}));
|
|
4262
|
+
}
|
|
4263
|
+
function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file2, historySessionId, messages) {
|
|
4264
|
+
const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId || "");
|
|
4265
|
+
if (!normalizedSessionId || messages.length === 0) return;
|
|
4266
|
+
persistSavedHistoryFileSummaryEntry(agentType, dir, file2, (currentSummary) => {
|
|
4267
|
+
const nextSummary = {
|
|
4268
|
+
file: file2,
|
|
4269
|
+
historySessionId: normalizedSessionId,
|
|
4270
|
+
messageCount: currentSummary?.messageCount || 0,
|
|
4271
|
+
firstMessageAt: currentSummary?.firstMessageAt || 0,
|
|
4272
|
+
lastMessageAt: currentSummary?.lastMessageAt || 0,
|
|
4273
|
+
sessionTitle: currentSummary?.sessionTitle,
|
|
4274
|
+
preview: currentSummary?.preview,
|
|
4275
|
+
workspace: currentSummary?.workspace
|
|
4276
|
+
};
|
|
4277
|
+
for (const message of messages) {
|
|
4278
|
+
if (!message || message.historySessionId !== historySessionId) continue;
|
|
4279
|
+
if (message.kind === "session_start") {
|
|
4280
|
+
if (message.workspace) nextSummary.workspace = message.workspace;
|
|
4281
|
+
continue;
|
|
4282
|
+
}
|
|
4283
|
+
nextSummary.messageCount += 1;
|
|
4284
|
+
if (!nextSummary.firstMessageAt || message.receivedAt < nextSummary.firstMessageAt) {
|
|
4285
|
+
nextSummary.firstMessageAt = message.receivedAt;
|
|
4286
|
+
}
|
|
4287
|
+
if (!nextSummary.lastMessageAt || message.receivedAt >= nextSummary.lastMessageAt) {
|
|
4288
|
+
nextSummary.lastMessageAt = message.receivedAt;
|
|
4289
|
+
if (message.sessionTitle) nextSummary.sessionTitle = message.sessionTitle;
|
|
4290
|
+
if (message.role !== "system" && message.content.trim()) nextSummary.preview = message.content.trim();
|
|
4291
|
+
} else if (message.sessionTitle) {
|
|
4292
|
+
nextSummary.sessionTitle = message.sessionTitle;
|
|
4293
|
+
}
|
|
4294
|
+
if (!nextSummary.preview && message.role !== "system" && message.content.trim()) {
|
|
4295
|
+
nextSummary.preview = message.content.trim();
|
|
4296
|
+
}
|
|
4297
|
+
}
|
|
4298
|
+
return nextSummary;
|
|
4299
|
+
});
|
|
4300
|
+
}
|
|
4301
|
+
function computeSavedHistoryFileSummary(agentType, dir, file2) {
|
|
4302
|
+
const historySessionId = extractSavedHistorySessionIdFromFile(agentType, file2);
|
|
4303
|
+
if (!historySessionId) return null;
|
|
4304
|
+
const filePath = path7.join(dir, file2);
|
|
4305
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
4306
|
+
const lines = content.split("\n").filter(Boolean);
|
|
4307
|
+
let messageCount = 0;
|
|
4308
|
+
let firstMessageAt = 0;
|
|
4309
|
+
let lastMessageAt = 0;
|
|
4310
|
+
let sessionTitle = "";
|
|
4311
|
+
let preview = "";
|
|
4312
|
+
let workspace = "";
|
|
4313
|
+
for (const line of lines) {
|
|
4314
|
+
let parsed = null;
|
|
4315
|
+
try {
|
|
4316
|
+
parsed = JSON.parse(line);
|
|
4317
|
+
} catch {
|
|
4318
|
+
parsed = null;
|
|
4319
|
+
}
|
|
4320
|
+
if (!parsed || parsed.historySessionId !== historySessionId) continue;
|
|
4321
|
+
if (parsed.kind === "session_start") {
|
|
4322
|
+
if (!workspace && parsed.workspace) workspace = parsed.workspace;
|
|
4323
|
+
continue;
|
|
4324
|
+
}
|
|
4325
|
+
messageCount += 1;
|
|
4326
|
+
if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
|
|
4327
|
+
if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
|
|
4328
|
+
if (parsed.sessionTitle) sessionTitle = parsed.sessionTitle;
|
|
4329
|
+
if (parsed.role !== "system" && parsed.content.trim()) preview = parsed.content.trim();
|
|
4330
|
+
}
|
|
4331
|
+
if (messageCount === 0 || !lastMessageAt) return null;
|
|
4332
|
+
return {
|
|
4333
|
+
file: file2,
|
|
4334
|
+
historySessionId,
|
|
4335
|
+
messageCount,
|
|
4336
|
+
firstMessageAt,
|
|
4337
|
+
lastMessageAt,
|
|
4338
|
+
sessionTitle: sessionTitle || void 0,
|
|
4339
|
+
preview: preview || void 0,
|
|
4340
|
+
workspace: workspace || void 0
|
|
4341
|
+
};
|
|
4342
|
+
}
|
|
4343
|
+
function shouldScheduleSavedHistoryRollupForSignature(signature) {
|
|
4344
|
+
const parts = String(signature || "").split(":");
|
|
4345
|
+
const size = Number(parts[1] || 0);
|
|
4346
|
+
return shouldScheduleSavedHistoryRollup(size);
|
|
4347
|
+
}
|
|
4348
|
+
function scheduleSavedHistoryRollup(agentType, historySessionId) {
|
|
4349
|
+
const key = `${agentType}:${historySessionId}`;
|
|
4350
|
+
if (!historySessionId || savedHistoryRollupInFlight.has(key)) return;
|
|
4351
|
+
savedHistoryRollupInFlight.add(key);
|
|
4352
|
+
setTimeout(() => {
|
|
4353
|
+
try {
|
|
4354
|
+
new ChatHistoryWriter().compactHistorySession(agentType, historySessionId);
|
|
4355
|
+
} finally {
|
|
4356
|
+
savedHistoryRollupInFlight.delete(key);
|
|
4357
|
+
}
|
|
4358
|
+
}, 0);
|
|
4359
|
+
}
|
|
4360
|
+
function scheduleSavedHistoryBackgroundRefresh(agentType, dir) {
|
|
4361
|
+
const key = `${agentType}:${dir}`;
|
|
4362
|
+
if (savedHistoryBackgroundRefresh.has(key)) return;
|
|
4363
|
+
savedHistoryBackgroundRefresh.add(key);
|
|
4364
|
+
setTimeout(() => {
|
|
4365
|
+
try {
|
|
4366
|
+
if (!fs3.existsSync(dir)) return;
|
|
4367
|
+
const files = listHistoryFiles(dir);
|
|
4368
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
4369
|
+
const persistedEntries = loadPersistedSavedHistoryIndex(dir);
|
|
4370
|
+
const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
|
|
4371
|
+
savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
|
|
4372
|
+
const refreshedIndexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
4373
|
+
savedHistorySessionCache.set(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"), {
|
|
4374
|
+
signature: refreshedIndexSignature,
|
|
4375
|
+
summaries: computed.summaries || []
|
|
4376
|
+
});
|
|
4377
|
+
for (const [file2, entry] of Array.from(computed.persistedEntries.entries())) {
|
|
4378
|
+
if (!entry?.summary || !shouldScheduleSavedHistoryRollupForSignature(entry.signature)) continue;
|
|
4379
|
+
scheduleSavedHistoryRollup(agentType, entry.summary.historySessionId);
|
|
4380
|
+
}
|
|
4381
|
+
} catch {
|
|
4382
|
+
} finally {
|
|
4383
|
+
savedHistoryBackgroundRefresh.delete(key);
|
|
4384
|
+
}
|
|
4385
|
+
}, 0);
|
|
4386
|
+
}
|
|
4387
|
+
function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries) {
|
|
4388
|
+
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
4389
|
+
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
4390
|
+
for (const file2 of files.slice().sort()) {
|
|
4391
|
+
const filePath = path7.join(dir, file2);
|
|
4392
|
+
const signature = fileSignatures.get(file2) || `${file2}:missing`;
|
|
4393
|
+
const cached2 = savedHistoryFileSummaryCache.get(filePath);
|
|
4394
|
+
const persisted = persistedEntries.get(file2);
|
|
4395
|
+
const reusableEntry = cached2?.signature === signature ? cached2 : persisted?.signature === signature ? persisted : null;
|
|
4396
|
+
const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(agentType, dir, file2);
|
|
4397
|
+
const nextEntry = reusableEntry || {
|
|
4398
|
+
signature,
|
|
4399
|
+
summary: fileSummary
|
|
4400
|
+
};
|
|
4401
|
+
if (!reusableEntry) {
|
|
4402
|
+
nextEntry.signature = signature;
|
|
4403
|
+
nextEntry.summary = fileSummary;
|
|
4404
|
+
}
|
|
4405
|
+
savedHistoryFileSummaryCache.set(filePath, nextEntry);
|
|
4406
|
+
nextPersistedEntries.set(file2, nextEntry);
|
|
4407
|
+
if (!fileSummary) continue;
|
|
4408
|
+
const existing = summaryBySessionId.get(fileSummary.historySessionId);
|
|
4409
|
+
if (fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) {
|
|
4410
|
+
continue;
|
|
4411
|
+
}
|
|
4412
|
+
if (!existing) {
|
|
4413
|
+
summaryBySessionId.set(fileSummary.historySessionId, {
|
|
4414
|
+
historySessionId: fileSummary.historySessionId,
|
|
4415
|
+
sessionTitle: fileSummary.sessionTitle,
|
|
4416
|
+
messageCount: fileSummary.messageCount,
|
|
4417
|
+
firstMessageAt: fileSummary.firstMessageAt,
|
|
4418
|
+
lastMessageAt: fileSummary.lastMessageAt,
|
|
4419
|
+
preview: fileSummary.preview,
|
|
4420
|
+
workspace: fileSummary.workspace
|
|
4421
|
+
});
|
|
4422
|
+
continue;
|
|
4423
|
+
}
|
|
4424
|
+
existing.messageCount += fileSummary.messageCount;
|
|
4425
|
+
if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
|
|
4426
|
+
existing.firstMessageAt = fileSummary.firstMessageAt;
|
|
4427
|
+
}
|
|
4428
|
+
if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
|
|
4429
|
+
existing.lastMessageAt = fileSummary.lastMessageAt;
|
|
4430
|
+
if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
|
|
4431
|
+
if (fileSummary.preview) existing.preview = fileSummary.preview;
|
|
4432
|
+
}
|
|
4433
|
+
if (!existing.workspace && fileSummary.workspace) {
|
|
4434
|
+
existing.workspace = fileSummary.workspace;
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4437
|
+
return {
|
|
4438
|
+
summaries: Array.from(summaryBySessionId.values()).sort((a, b) => b.lastMessageAt - a.lastMessageAt),
|
|
4439
|
+
persistedEntries: nextPersistedEntries
|
|
4440
|
+
};
|
|
3943
4441
|
}
|
|
3944
4442
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0) {
|
|
3945
4443
|
try {
|
|
@@ -3997,18 +4495,51 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
3997
4495
|
savedHistorySessionCache.delete(sanitized);
|
|
3998
4496
|
return { sessions: [], hasMore: false };
|
|
3999
4497
|
}
|
|
4000
|
-
const files = listHistoryFiles(dir);
|
|
4001
|
-
const signature = buildSavedHistoryCacheSignature(dir, files);
|
|
4002
4498
|
const cached2 = savedHistorySessionCache.get(sanitized);
|
|
4003
|
-
const
|
|
4004
|
-
|
|
4499
|
+
const offset = Math.max(0, options.offset || 0);
|
|
4500
|
+
const limit = Math.max(1, options.limit || 30);
|
|
4501
|
+
const indexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
4502
|
+
let cacheWasInvalidated = false;
|
|
4503
|
+
if (cached2) {
|
|
4504
|
+
const cacheLooksPersisted = cached2.signature.startsWith("index:");
|
|
4505
|
+
const cacheStillValid = cacheLooksPersisted ? cached2.signature === indexSignature : (() => {
|
|
4506
|
+
const files2 = listHistoryFiles(dir);
|
|
4507
|
+
const fileSignatures2 = buildSavedHistoryFileSignatureMap(dir, files2);
|
|
4508
|
+
return cached2.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
|
|
4509
|
+
})();
|
|
4510
|
+
if (cacheStillValid) {
|
|
4511
|
+
const sliced2 = cached2.summaries.slice(offset, offset + limit);
|
|
4512
|
+
return {
|
|
4513
|
+
sessions: sliced2,
|
|
4514
|
+
hasMore: cached2.summaries.length > offset + limit
|
|
4515
|
+
};
|
|
4516
|
+
}
|
|
4517
|
+
cacheWasInvalidated = true;
|
|
4518
|
+
}
|
|
4519
|
+
const persistedSessions = readPersistedSavedHistorySessionSummaries(dir);
|
|
4520
|
+
if (!cacheWasInvalidated && persistedSessions?.length && !historyDirectoryHasFilesNewerThanIndex(dir)) {
|
|
4005
4521
|
savedHistorySessionCache.set(sanitized, {
|
|
4006
|
-
signature,
|
|
4007
|
-
summaries
|
|
4522
|
+
signature: indexSignature,
|
|
4523
|
+
summaries: persistedSessions
|
|
4008
4524
|
});
|
|
4525
|
+
scheduleSavedHistoryBackgroundRefresh(agentType, dir);
|
|
4526
|
+
const sliced2 = persistedSessions.slice(offset, offset + limit);
|
|
4527
|
+
return {
|
|
4528
|
+
sessions: sliced2,
|
|
4529
|
+
hasMore: persistedSessions.length > offset + limit
|
|
4530
|
+
};
|
|
4009
4531
|
}
|
|
4010
|
-
const
|
|
4011
|
-
const
|
|
4532
|
+
const files = listHistoryFiles(dir);
|
|
4533
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
4534
|
+
const signature = buildSavedHistoryCacheSignature(files, fileSignatures);
|
|
4535
|
+
const persistedEntries = loadPersistedSavedHistoryIndex(dir);
|
|
4536
|
+
const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
|
|
4537
|
+
const summaries = computed.summaries || [];
|
|
4538
|
+
savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
|
|
4539
|
+
savedHistorySessionCache.set(sanitized, {
|
|
4540
|
+
signature,
|
|
4541
|
+
summaries
|
|
4542
|
+
});
|
|
4012
4543
|
const sliced = summaries.slice(offset, offset + limit);
|
|
4013
4544
|
return {
|
|
4014
4545
|
sessions: sliced,
|
|
@@ -4018,7 +4549,7 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
4018
4549
|
return { sessions: [], hasMore: false };
|
|
4019
4550
|
}
|
|
4020
4551
|
}
|
|
4021
|
-
var fs3, path7, os6, HISTORY_DIR, RETAIN_DAYS, savedHistorySessionCache, CODEX_STARTER_PROMPT_RE, ChatHistoryWriter;
|
|
4552
|
+
var fs3, path7, os6, HISTORY_DIR, RETAIN_DAYS, SAVED_HISTORY_INDEX_VERSION, SAVED_HISTORY_INDEX_FILE, SAVED_HISTORY_INDEX_LOCK_SUFFIX, SAVED_HISTORY_INDEX_LOCK_WAIT_MS, SAVED_HISTORY_INDEX_LOCK_STALE_MS, SAVED_HISTORY_INDEX_LOCK_POLL_MS, SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES, savedHistorySessionCache, savedHistoryFileSummaryCache, savedHistoryBackgroundRefresh, savedHistoryRollupInFlight, CODEX_STARTER_PROMPT_RE, ChatHistoryWriter;
|
|
4022
4553
|
var init_chat_history = __esm({
|
|
4023
4554
|
"../../oss/packages/daemon-core/src/config/chat-history.ts"() {
|
|
4024
4555
|
"use strict";
|
|
@@ -4026,9 +4557,20 @@ var init_chat_history = __esm({
|
|
|
4026
4557
|
path7 = __toESM(require("path"));
|
|
4027
4558
|
os6 = __toESM(require("os"));
|
|
4028
4559
|
init_chat_message_normalization();
|
|
4560
|
+
init_provider_session_id();
|
|
4029
4561
|
HISTORY_DIR = path7.join(os6.homedir(), ".adhdev", "history");
|
|
4030
4562
|
RETAIN_DAYS = 30;
|
|
4563
|
+
SAVED_HISTORY_INDEX_VERSION = 1;
|
|
4564
|
+
SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
4565
|
+
SAVED_HISTORY_INDEX_LOCK_SUFFIX = ".lock";
|
|
4566
|
+
SAVED_HISTORY_INDEX_LOCK_WAIT_MS = 1500;
|
|
4567
|
+
SAVED_HISTORY_INDEX_LOCK_STALE_MS = 15e3;
|
|
4568
|
+
SAVED_HISTORY_INDEX_LOCK_POLL_MS = 25;
|
|
4569
|
+
SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES = 16 * 1024 * 1024;
|
|
4031
4570
|
savedHistorySessionCache = /* @__PURE__ */ new Map();
|
|
4571
|
+
savedHistoryFileSummaryCache = /* @__PURE__ */ new Map();
|
|
4572
|
+
savedHistoryBackgroundRefresh = /* @__PURE__ */ new Set();
|
|
4573
|
+
savedHistoryRollupInFlight = /* @__PURE__ */ new Set();
|
|
4032
4574
|
CODEX_STARTER_PROMPT_RE = /^(?:[›❯]\s*)?(?:Find and fix a bug in @filename|Improve documentation in @filename|Write tests for @filename|Explain this codebase|Summarize recent commits|Implement \{feature\}|Use \/skills(?: to list available skills)?|Run \/review on my current changes)$/i;
|
|
4033
4575
|
ChatHistoryWriter = class {
|
|
4034
4576
|
/** Last seen message count per agent (deduplication) */
|
|
@@ -4103,9 +4645,11 @@ var init_chat_history = __esm({
|
|
|
4103
4645
|
fs3.mkdirSync(dir, { recursive: true });
|
|
4104
4646
|
const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4105
4647
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
4106
|
-
const
|
|
4648
|
+
const fileName = `${filePrefix}${date5}.jsonl`;
|
|
4649
|
+
const filePath = path7.join(dir, fileName);
|
|
4107
4650
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
4108
4651
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
4652
|
+
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
4109
4653
|
const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
|
|
4110
4654
|
if (!historySessionId && messages.length < prevCount * 0.5 && prevCount > 3) {
|
|
4111
4655
|
seenHashes.clear();
|
|
@@ -4196,7 +4740,8 @@ var init_chat_history = __esm({
|
|
|
4196
4740
|
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
4197
4741
|
fs3.mkdirSync(dir, { recursive: true });
|
|
4198
4742
|
const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4199
|
-
const
|
|
4743
|
+
const fileName = `${this.sanitize(id)}_${date5}.jsonl`;
|
|
4744
|
+
const filePath = path7.join(dir, fileName);
|
|
4200
4745
|
const record2 = {
|
|
4201
4746
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4202
4747
|
receivedAt: Date.now(),
|
|
@@ -4209,6 +4754,7 @@ var init_chat_history = __esm({
|
|
|
4209
4754
|
workspace: ws
|
|
4210
4755
|
};
|
|
4211
4756
|
fs3.appendFileSync(filePath, JSON.stringify(record2) + "\n", "utf-8");
|
|
4757
|
+
updateSavedHistoryIndexForSessionStart(agentType, dir, fileName, id, ws);
|
|
4212
4758
|
} catch {
|
|
4213
4759
|
}
|
|
4214
4760
|
}
|
|
@@ -4274,6 +4820,7 @@ var init_chat_history = __esm({
|
|
|
4274
4820
|
}
|
|
4275
4821
|
fs3.unlinkSync(sourcePath);
|
|
4276
4822
|
}
|
|
4823
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
4277
4824
|
} catch {
|
|
4278
4825
|
}
|
|
4279
4826
|
}
|
|
@@ -4323,6 +4870,7 @@ var init_chat_history = __esm({
|
|
|
4323
4870
|
fs3.writeFileSync(filePath, `${collapsed.map((entry) => JSON.stringify(entry)).join("\n")}
|
|
4324
4871
|
`, "utf-8");
|
|
4325
4872
|
}
|
|
4873
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
4326
4874
|
} catch {
|
|
4327
4875
|
}
|
|
4328
4876
|
}
|
|
@@ -4342,13 +4890,18 @@ var init_chat_history = __esm({
|
|
|
4342
4890
|
for (const dir of agentDirs) {
|
|
4343
4891
|
const dirPath = path7.join(HISTORY_DIR, dir.name);
|
|
4344
4892
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
4893
|
+
let removedAny = false;
|
|
4345
4894
|
for (const file2 of files) {
|
|
4346
4895
|
const filePath = path7.join(dirPath, file2);
|
|
4347
4896
|
const stat4 = fs3.statSync(filePath);
|
|
4348
4897
|
if (stat4.mtimeMs < cutoff) {
|
|
4349
4898
|
fs3.unlinkSync(filePath);
|
|
4899
|
+
removedAny = true;
|
|
4350
4900
|
}
|
|
4351
4901
|
}
|
|
4902
|
+
if (removedAny) {
|
|
4903
|
+
invalidatePersistedSavedHistoryIndex(dir.name, dirPath);
|
|
4904
|
+
}
|
|
4352
4905
|
}
|
|
4353
4906
|
} catch {
|
|
4354
4907
|
}
|
|
@@ -6183,7 +6736,7 @@ function shouldIncludeSessionMetadata(profile) {
|
|
|
6183
6736
|
return profile !== "live";
|
|
6184
6737
|
}
|
|
6185
6738
|
function shouldIncludeRuntimeMetadata(profile) {
|
|
6186
|
-
return
|
|
6739
|
+
return true;
|
|
6187
6740
|
}
|
|
6188
6741
|
function findCdpManager(cdpManagers, key) {
|
|
6189
6742
|
const exact = cdpManagers.get(key);
|
|
@@ -6275,6 +6828,21 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
6275
6828
|
lastUpdated: ext.lastUpdated
|
|
6276
6829
|
};
|
|
6277
6830
|
}
|
|
6831
|
+
function shouldIncludeExtensionSession(ext) {
|
|
6832
|
+
const status = String(ext.status || "").trim().toLowerCase();
|
|
6833
|
+
const hasActiveChat = !!ext.activeChat;
|
|
6834
|
+
const hasMessages = Array.isArray(ext.activeChat?.messages) && ext.activeChat.messages.length > 0;
|
|
6835
|
+
const hasModal = !!ext.activeChat?.activeModal;
|
|
6836
|
+
const hasStreams = Array.isArray(ext.agentStreams) && ext.agentStreams.length > 0;
|
|
6837
|
+
const hasProviderSessionId = typeof ext.providerSessionId === "string" && ext.providerSessionId.trim().length > 0;
|
|
6838
|
+
const hasControlValues = !!(ext.controlValues && Object.keys(ext.controlValues).length > 0);
|
|
6839
|
+
const hasProviderControls = Array.isArray(ext.providerControls) && ext.providerControls.length > 0;
|
|
6840
|
+
const hasOpenPanelCapability = Array.isArray(ext.sessionCapabilities) && ext.sessionCapabilities.includes("open_panel");
|
|
6841
|
+
const hasSummaryMetadata = !!ext.summaryMetadata;
|
|
6842
|
+
const hasError = typeof ext.errorMessage === "string" && ext.errorMessage.trim().length > 0;
|
|
6843
|
+
const hasInterestingStatus = !!status && !["idle", "panel_hidden", "disconnected", "not_monitored"].includes(status);
|
|
6844
|
+
return hasActiveChat || hasMessages || hasModal || hasStreams || hasProviderSessionId || hasControlValues || hasProviderControls || hasOpenPanelCapability || hasSummaryMetadata || hasError || hasInterestingStatus;
|
|
6845
|
+
}
|
|
6278
6846
|
function buildCliSession(state, options) {
|
|
6279
6847
|
const profile = options.profile || "full";
|
|
6280
6848
|
const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
|
|
@@ -6300,8 +6868,12 @@ function buildCliSession(state, options) {
|
|
|
6300
6868
|
runtimeKey: state.runtime?.runtimeKey,
|
|
6301
6869
|
runtimeDisplayName: state.runtime?.displayName,
|
|
6302
6870
|
runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
|
|
6871
|
+
runtimeLifecycle: state.runtime?.lifecycle ?? null,
|
|
6872
|
+
runtimeSurfaceKind: state.runtime?.surfaceKind,
|
|
6303
6873
|
runtimeWriteOwner: state.runtime?.writeOwner || null,
|
|
6304
|
-
runtimeAttachedClients: state.runtime?.attachedClients || []
|
|
6874
|
+
runtimeAttachedClients: state.runtime?.attachedClients || [],
|
|
6875
|
+
runtimeRestoredFromStorage: state.runtime?.restoredFromStorage === true,
|
|
6876
|
+
runtimeRecoveryState: state.runtime?.recoveryState ?? null
|
|
6305
6877
|
},
|
|
6306
6878
|
mode: state.mode,
|
|
6307
6879
|
resume: state.resume,
|
|
@@ -6358,6 +6930,7 @@ function buildSessionEntries(allStates, cdpManagers, options = {}) {
|
|
|
6358
6930
|
for (const state of ideStates) {
|
|
6359
6931
|
sessions.push(buildIdeWorkspaceSession(state, cdpManagers, options));
|
|
6360
6932
|
for (const ext of state.extensions) {
|
|
6933
|
+
if (!shouldIncludeExtensionSession(ext)) continue;
|
|
6361
6934
|
sessions.push(buildExtensionAgentSession(state, ext, options));
|
|
6362
6935
|
}
|
|
6363
6936
|
}
|
|
@@ -8610,7 +9183,9 @@ function applyProviderPatch(h, args, payload) {
|
|
|
8610
9183
|
});
|
|
8611
9184
|
}
|
|
8612
9185
|
async function executeProviderScript(h, args, scriptName) {
|
|
8613
|
-
const
|
|
9186
|
+
const explicitTargetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
9187
|
+
const targetSession = explicitTargetSessionId ? h.ctx.sessionRegistry?.get(explicitTargetSessionId) : void 0;
|
|
9188
|
+
const resolvedProviderType = targetSession?.providerType || h.currentSession?.providerType || h.currentProviderType || args?.agentType || args?.providerType;
|
|
8614
9189
|
if (!resolvedProviderType) return { success: false, error: "targetSessionId or providerType is required" };
|
|
8615
9190
|
const loader = h.ctx.providerLoader;
|
|
8616
9191
|
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
@@ -8653,16 +9228,16 @@ async function executeProviderScript(h, args, scriptName) {
|
|
|
8653
9228
|
const scriptFn = provider.scripts[actualScriptName];
|
|
8654
9229
|
const scriptCode = scriptFn(normalizedArgs);
|
|
8655
9230
|
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
8656
|
-
const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : h.currentSession?.cdpManagerKey || h.currentManagerKey;
|
|
9231
|
+
const cdpKey = provider.category === "ide" ? targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey;
|
|
8657
9232
|
LOG.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
|
|
8658
9233
|
const cdp = h.getCdp(cdpKey);
|
|
8659
9234
|
if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
|
|
8660
9235
|
try {
|
|
8661
9236
|
let result;
|
|
8662
9237
|
if (provider.category === "extension") {
|
|
8663
|
-
const runtimeSessionId = h.currentSession?.sessionId
|
|
9238
|
+
const runtimeSessionId = explicitTargetSessionId || h.currentSession?.sessionId;
|
|
8664
9239
|
if (!runtimeSessionId) return { success: false, error: `No target session found for ${resolvedProviderType}` };
|
|
8665
|
-
const parentSessionId = h.currentSession?.parentSessionId;
|
|
9240
|
+
const parentSessionId = targetSession?.parentSessionId || h.currentSession?.parentSessionId;
|
|
8666
9241
|
if (parentSessionId) {
|
|
8667
9242
|
await h.agentStream?.setActiveSession(cdp, parentSessionId, runtimeSessionId);
|
|
8668
9243
|
await h.agentStream?.syncActiveSession(cdp, parentSessionId);
|
|
@@ -10208,11 +10783,11 @@ __export(dist_exports, {
|
|
|
10208
10783
|
ensureNodePtySpawnHelperPermissions: () => ensureNodePtySpawnHelperPermissions,
|
|
10209
10784
|
formatRuntimeOwner: () => formatRuntimeOwner,
|
|
10210
10785
|
getDefaultSessionHostEndpoint: () => getDefaultSessionHostEndpoint,
|
|
10211
|
-
getSessionHostRecoveryLabel: () =>
|
|
10212
|
-
getSessionHostSurfaceKind: () =>
|
|
10786
|
+
getSessionHostRecoveryLabel: () => getSessionHostRecoveryLabel2,
|
|
10787
|
+
getSessionHostSurfaceKind: () => getSessionHostSurfaceKind2,
|
|
10213
10788
|
getWorkspaceLabel: () => getWorkspaceLabel,
|
|
10214
|
-
isSessionHostLiveRuntime: () =>
|
|
10215
|
-
isSessionHostRecoverySnapshot: () =>
|
|
10789
|
+
isSessionHostLiveRuntime: () => isSessionHostLiveRuntime2,
|
|
10790
|
+
isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot2,
|
|
10216
10791
|
resolveAttachableRuntimeRecord: () => resolveAttachableRuntimeRecord,
|
|
10217
10792
|
resolveRuntimeRecord: () => resolveRuntimeRecord,
|
|
10218
10793
|
sanitizeSpawnEnv: () => sanitizeSpawnEnv,
|
|
@@ -10252,14 +10827,14 @@ function buildRuntimeKey(payload, existingKeys) {
|
|
|
10252
10827
|
}
|
|
10253
10828
|
return candidate;
|
|
10254
10829
|
}
|
|
10255
|
-
function
|
|
10830
|
+
function isSessionHostLiveRuntime2(record2) {
|
|
10256
10831
|
if (!record2) return false;
|
|
10257
10832
|
if (record2.surfaceKind === "live_runtime") return true;
|
|
10258
10833
|
if (record2.surfaceKind === "recovery_snapshot" || record2.surfaceKind === "inactive_record") return false;
|
|
10259
10834
|
const lifecycle = String(record2.lifecycle || "").trim();
|
|
10260
|
-
return
|
|
10835
|
+
return LIVE_LIFECYCLES2.has(lifecycle);
|
|
10261
10836
|
}
|
|
10262
|
-
function
|
|
10837
|
+
function getSessionHostRecoveryLabel2(meta3) {
|
|
10263
10838
|
const recoveryState = typeof meta3?.runtimeRecoveryState === "string" ? String(meta3.runtimeRecoveryState).trim() : "";
|
|
10264
10839
|
if (!recoveryState) return null;
|
|
10265
10840
|
if (recoveryState === "auto_resumed") return "restored after restart";
|
|
@@ -10268,30 +10843,30 @@ function getSessionHostRecoveryLabel(meta3) {
|
|
|
10268
10843
|
if (recoveryState === "orphan_snapshot") return "snapshot recovered";
|
|
10269
10844
|
return recoveryState.replace(/_/g, " ");
|
|
10270
10845
|
}
|
|
10271
|
-
function
|
|
10846
|
+
function isSessionHostRecoverySnapshot2(record2) {
|
|
10272
10847
|
if (!record2) return false;
|
|
10273
10848
|
if (record2.surfaceKind === "recovery_snapshot") return true;
|
|
10274
10849
|
if (record2.surfaceKind === "live_runtime" || record2.surfaceKind === "inactive_record") return false;
|
|
10275
|
-
if (
|
|
10850
|
+
if (isSessionHostLiveRuntime2(record2)) return false;
|
|
10276
10851
|
const lifecycle = String(record2.lifecycle || "").trim();
|
|
10277
10852
|
if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
|
|
10278
10853
|
return false;
|
|
10279
10854
|
}
|
|
10280
10855
|
const meta3 = record2.meta || void 0;
|
|
10281
10856
|
if (meta3?.restoredFromStorage === true) return true;
|
|
10282
|
-
return
|
|
10857
|
+
return getSessionHostRecoveryLabel2(meta3) !== null;
|
|
10283
10858
|
}
|
|
10284
|
-
function
|
|
10859
|
+
function getSessionHostSurfaceKind2(record2) {
|
|
10285
10860
|
if (record2?.surfaceKind === "live_runtime" || record2?.surfaceKind === "recovery_snapshot" || record2?.surfaceKind === "inactive_record") {
|
|
10286
10861
|
return record2.surfaceKind;
|
|
10287
10862
|
}
|
|
10288
|
-
if (
|
|
10289
|
-
if (
|
|
10863
|
+
if (isSessionHostLiveRuntime2(record2)) return "live_runtime";
|
|
10864
|
+
if (isSessionHostRecoverySnapshot2(record2)) return "recovery_snapshot";
|
|
10290
10865
|
return "inactive_record";
|
|
10291
10866
|
}
|
|
10292
10867
|
function resolveAttachableRuntimeRecord(records, identifier) {
|
|
10293
10868
|
const record2 = resolveRuntimeRecord(records, identifier);
|
|
10294
|
-
const surfaceKind =
|
|
10869
|
+
const surfaceKind = getSessionHostSurfaceKind2(record2);
|
|
10295
10870
|
if (surfaceKind === "live_runtime") {
|
|
10296
10871
|
return record2;
|
|
10297
10872
|
}
|
|
@@ -10414,7 +10989,7 @@ function ensureNodePtySpawnHelperPermissions(logFn) {
|
|
|
10414
10989
|
} catch {
|
|
10415
10990
|
}
|
|
10416
10991
|
}
|
|
10417
|
-
var import_crypto3, path9, os9, path22, net, import_crypto4, os22, path32, __require, SessionRingBuffer,
|
|
10992
|
+
var import_crypto3, path9, os9, path22, net, import_crypto4, os22, path32, __require, SessionRingBuffer, LIVE_LIFECYCLES2, SessionHostRegistry, SessionHostClient;
|
|
10418
10993
|
var init_dist = __esm({
|
|
10419
10994
|
"../../oss/packages/session-host-core/dist/index.mjs"() {
|
|
10420
10995
|
"use strict";
|
|
@@ -10492,7 +11067,7 @@ var init_dist = __esm({
|
|
|
10492
11067
|
}
|
|
10493
11068
|
}
|
|
10494
11069
|
};
|
|
10495
|
-
|
|
11070
|
+
LIVE_LIFECYCLES2 = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
10496
11071
|
SessionHostRegistry = class {
|
|
10497
11072
|
sessions = /* @__PURE__ */ new Map();
|
|
10498
11073
|
createSession(payload) {
|
|
@@ -13433,8 +14008,12 @@ var init_cli_provider_instance = __esm({
|
|
|
13433
14008
|
runtimeKey: runtime.runtimeKey,
|
|
13434
14009
|
displayName: runtime.displayName,
|
|
13435
14010
|
workspaceLabel: runtime.workspaceLabel,
|
|
14011
|
+
lifecycle: runtime.lifecycle ?? null,
|
|
14012
|
+
surfaceKind: runtime.surfaceKind,
|
|
13436
14013
|
writeOwner: runtime.writeOwner || null,
|
|
13437
|
-
attachedClients: runtime.attachedClients || []
|
|
14014
|
+
attachedClients: runtime.attachedClients || [],
|
|
14015
|
+
restoredFromStorage: runtime.restoredFromStorage === true,
|
|
14016
|
+
recoveryState: runtime.recoveryState ?? null
|
|
13438
14017
|
} : void 0,
|
|
13439
14018
|
resume: this.provider.resume,
|
|
13440
14019
|
controlValues: surface.controlValues,
|
|
@@ -35845,67 +36424,6 @@ var init_command_log = __esm({
|
|
|
35845
36424
|
}
|
|
35846
36425
|
});
|
|
35847
36426
|
|
|
35848
|
-
// ../../oss/packages/daemon-core/src/session-host/runtime-surface.ts
|
|
35849
|
-
function isSessionHostLiveRuntime2(record2) {
|
|
35850
|
-
const lifecycle = String(record2?.lifecycle || "").trim();
|
|
35851
|
-
return LIVE_LIFECYCLES2.has(lifecycle);
|
|
35852
|
-
}
|
|
35853
|
-
function getSessionHostRecoveryLabel2(meta3) {
|
|
35854
|
-
const recoveryState = typeof meta3?.runtimeRecoveryState === "string" ? String(meta3.runtimeRecoveryState).trim() : "";
|
|
35855
|
-
if (!recoveryState) return null;
|
|
35856
|
-
if (recoveryState === "auto_resumed") return "restored after restart";
|
|
35857
|
-
if (recoveryState === "resume_failed") return "restore failed";
|
|
35858
|
-
if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
|
|
35859
|
-
if (recoveryState === "orphan_snapshot") return "snapshot recovered";
|
|
35860
|
-
return recoveryState.replace(/_/g, " ");
|
|
35861
|
-
}
|
|
35862
|
-
function isSessionHostRecoverySnapshot2(record2) {
|
|
35863
|
-
if (!record2) return false;
|
|
35864
|
-
if (isSessionHostLiveRuntime2(record2)) return false;
|
|
35865
|
-
const lifecycle = String(record2.lifecycle || "").trim();
|
|
35866
|
-
if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
|
|
35867
|
-
return false;
|
|
35868
|
-
}
|
|
35869
|
-
const meta3 = record2.meta || void 0;
|
|
35870
|
-
if (meta3?.restoredFromStorage === true) return true;
|
|
35871
|
-
return getSessionHostRecoveryLabel2(meta3) !== null;
|
|
35872
|
-
}
|
|
35873
|
-
function getSessionHostSurfaceKind2(record2) {
|
|
35874
|
-
if (isSessionHostLiveRuntime2(record2)) return "live_runtime";
|
|
35875
|
-
if (isSessionHostRecoverySnapshot2(record2)) return "recovery_snapshot";
|
|
35876
|
-
return "inactive_record";
|
|
35877
|
-
}
|
|
35878
|
-
function partitionSessionHostRecords(records) {
|
|
35879
|
-
const liveRuntimes = [];
|
|
35880
|
-
const recoverySnapshots = [];
|
|
35881
|
-
const inactiveRecords = [];
|
|
35882
|
-
for (const record2 of records) {
|
|
35883
|
-
const kind = getSessionHostSurfaceKind2(record2);
|
|
35884
|
-
if (kind === "live_runtime") {
|
|
35885
|
-
liveRuntimes.push(record2);
|
|
35886
|
-
} else if (kind === "recovery_snapshot") {
|
|
35887
|
-
recoverySnapshots.push(record2);
|
|
35888
|
-
} else {
|
|
35889
|
-
inactiveRecords.push(record2);
|
|
35890
|
-
}
|
|
35891
|
-
}
|
|
35892
|
-
return {
|
|
35893
|
-
liveRuntimes,
|
|
35894
|
-
recoverySnapshots,
|
|
35895
|
-
inactiveRecords
|
|
35896
|
-
};
|
|
35897
|
-
}
|
|
35898
|
-
function partitionSessionHostDiagnosticsSessions(records) {
|
|
35899
|
-
return partitionSessionHostRecords(records || []);
|
|
35900
|
-
}
|
|
35901
|
-
var LIVE_LIFECYCLES2;
|
|
35902
|
-
var init_runtime_surface = __esm({
|
|
35903
|
-
"../../oss/packages/daemon-core/src/session-host/runtime-surface.ts"() {
|
|
35904
|
-
"use strict";
|
|
35905
|
-
LIVE_LIFECYCLES2 = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
35906
|
-
}
|
|
35907
|
-
});
|
|
35908
|
-
|
|
35909
36427
|
// ../../oss/packages/daemon-core/src/status/snapshot.ts
|
|
35910
36428
|
function buildRecentReadDebugSignature(snapshot) {
|
|
35911
36429
|
return [
|
|
@@ -36441,7 +36959,7 @@ function summarizeSessionHostRecord(result) {
|
|
|
36441
36959
|
return {
|
|
36442
36960
|
runtimeKey: typeof record2.runtimeKey === "string" ? record2.runtimeKey : void 0,
|
|
36443
36961
|
lifecycle: typeof record2.lifecycle === "string" ? record2.lifecycle : void 0,
|
|
36444
|
-
surfaceKind:
|
|
36962
|
+
surfaceKind: getSessionHostSurfaceKind(record2),
|
|
36445
36963
|
attachedClientCount: Array.isArray(record2.attachedClients) ? record2.attachedClients.length : void 0,
|
|
36446
36964
|
hasWriteOwner: !!record2.writeOwner,
|
|
36447
36965
|
writeOwnerClientId: typeof record2.writeOwner?.clientId === "string" ? record2.writeOwner.clientId : void 0
|
|
@@ -37523,6 +38041,28 @@ var init_subscription_updates = __esm({
|
|
|
37523
38041
|
}
|
|
37524
38042
|
});
|
|
37525
38043
|
|
|
38044
|
+
// ../../oss/packages/daemon-core/src/chat/async-batch.ts
|
|
38045
|
+
async function runAsyncBatch(items, worker, options = {}) {
|
|
38046
|
+
const list = Array.from(items);
|
|
38047
|
+
if (list.length === 0) return;
|
|
38048
|
+
const concurrency = Math.max(1, Math.min(list.length, Math.floor(options.concurrency || 1)));
|
|
38049
|
+
let nextIndex = 0;
|
|
38050
|
+
const runners = Array.from({ length: concurrency }, async () => {
|
|
38051
|
+
while (true) {
|
|
38052
|
+
const currentIndex = nextIndex;
|
|
38053
|
+
nextIndex += 1;
|
|
38054
|
+
if (currentIndex >= list.length) return;
|
|
38055
|
+
await worker(list[currentIndex], currentIndex);
|
|
38056
|
+
}
|
|
38057
|
+
});
|
|
38058
|
+
await Promise.all(runners);
|
|
38059
|
+
}
|
|
38060
|
+
var init_async_batch = __esm({
|
|
38061
|
+
"../../oss/packages/daemon-core/src/chat/async-batch.ts"() {
|
|
38062
|
+
"use strict";
|
|
38063
|
+
}
|
|
38064
|
+
});
|
|
38065
|
+
|
|
37526
38066
|
// ../../oss/packages/daemon-core/src/agent-stream/provider-adapter.ts
|
|
37527
38067
|
var ProviderStreamAdapter;
|
|
37528
38068
|
var init_provider_adapter = __esm({
|
|
@@ -38004,10 +38544,12 @@ var init_manager2 = __esm({
|
|
|
38004
38544
|
}
|
|
38005
38545
|
}
|
|
38006
38546
|
/** Collect active extension session state */
|
|
38007
|
-
async collectActiveSession(cdp, parentSessionId) {
|
|
38547
|
+
async collectActiveSession(cdp, parentSessionId, attemptedSessionIds = /* @__PURE__ */ new Set(), originSessionId) {
|
|
38008
38548
|
if (!this.enabled) return null;
|
|
38009
38549
|
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
38010
38550
|
if (!activeSessionId) return null;
|
|
38551
|
+
const resolvedOriginSessionId = originSessionId || activeSessionId;
|
|
38552
|
+
attemptedSessionIds.add(activeSessionId);
|
|
38011
38553
|
let agent = this.managedBySessionId.get(activeSessionId);
|
|
38012
38554
|
if (!agent) {
|
|
38013
38555
|
agent = await this.connectManagedSession(cdp, parentSessionId, activeSessionId) || void 0;
|
|
@@ -38020,18 +38562,44 @@ var init_manager2 = __esm({
|
|
|
38020
38562
|
try {
|
|
38021
38563
|
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
38022
38564
|
const state = await agent.adapter.readChat(evaluate);
|
|
38023
|
-
const
|
|
38024
|
-
const
|
|
38025
|
-
|
|
38026
|
-
|
|
38565
|
+
const resolvedProviderSessionId = typeof state.providerSessionId === "string" && state.providerSessionId.trim() ? state.providerSessionId.trim() : typeof state.sessionId === "string" && state.sessionId.trim() && state.sessionId !== agent.runtimeSessionId ? state.sessionId.trim() : void 0;
|
|
38566
|
+
const normalizedState = {
|
|
38567
|
+
...state,
|
|
38568
|
+
sessionId: agent.runtimeSessionId,
|
|
38569
|
+
...resolvedProviderSessionId ? { providerSessionId: resolvedProviderSessionId } : {}
|
|
38570
|
+
};
|
|
38571
|
+
const stateError = this.getStateError(normalizedState);
|
|
38572
|
+
const selectedModelValue = typeof normalizedState.controlValues?.model === "string" ? normalizedState.controlValues.model : "";
|
|
38573
|
+
LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${normalizedState.status} msgs=${normalizedState.messages?.length || 0} model=${selectedModelValue}${normalizedState.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
|
|
38574
|
+
if (normalizedState.status === "error" && this.isRecoverableSessionError(stateError)) {
|
|
38027
38575
|
throw new Error(stateError);
|
|
38028
38576
|
}
|
|
38029
|
-
agent.lastState =
|
|
38577
|
+
agent.lastState = normalizedState;
|
|
38030
38578
|
agent.lastError = null;
|
|
38031
|
-
if (
|
|
38579
|
+
if (normalizedState.status === "panel_hidden") {
|
|
38580
|
+
const discovered = await cdp.discoverAgentWebviews().catch(() => []);
|
|
38581
|
+
const fallbackTarget = discovered.find((entry) => {
|
|
38582
|
+
if (entry.agentType === type) return false;
|
|
38583
|
+
const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, entry.agentType);
|
|
38584
|
+
return !!fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId);
|
|
38585
|
+
});
|
|
38586
|
+
if (fallbackTarget) {
|
|
38587
|
+
const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, fallbackTarget.agentType);
|
|
38588
|
+
if (fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId)) {
|
|
38589
|
+
this.logFn(`[AgentStream] Active session ${type} is hidden; switching to visible agent ${fallbackTarget.agentType} (${parentSessionId})`);
|
|
38590
|
+
await this.setActiveSession(cdp, parentSessionId, fallbackSessionId);
|
|
38591
|
+
await this.syncActiveSession(cdp, parentSessionId);
|
|
38592
|
+
const fallbackState = await this.collectActiveSession(cdp, parentSessionId, attemptedSessionIds, resolvedOriginSessionId);
|
|
38593
|
+
if (fallbackState?.status === "panel_hidden" && resolvedOriginSessionId !== fallbackSessionId) {
|
|
38594
|
+
await this.setActiveSession(cdp, parentSessionId, resolvedOriginSessionId);
|
|
38595
|
+
await this.syncActiveSession(cdp, parentSessionId);
|
|
38596
|
+
}
|
|
38597
|
+
return fallbackState;
|
|
38598
|
+
}
|
|
38599
|
+
}
|
|
38032
38600
|
agent.lastHiddenCheckTime = Date.now();
|
|
38033
38601
|
}
|
|
38034
|
-
return
|
|
38602
|
+
return normalizedState;
|
|
38035
38603
|
} catch (e) {
|
|
38036
38604
|
const errorMsg = e?.message || String(e);
|
|
38037
38605
|
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
@@ -38343,6 +38911,7 @@ var init_poller = __esm({
|
|
|
38343
38911
|
try {
|
|
38344
38912
|
await agentStreamManager.syncActiveSession(cdp, parentSessionId);
|
|
38345
38913
|
let stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
|
|
38914
|
+
resolvedActiveSessionId = stream?.sessionId || agentStreamManager.getActiveSessionId(parentSessionId) || resolvedActiveSessionId;
|
|
38346
38915
|
if (stream?.status === "waiting_approval") {
|
|
38347
38916
|
const autoApprove = providerLoader.getSettings(stream.agentType).autoApprove !== false;
|
|
38348
38917
|
if (autoApprove && resolvedActiveSessionId) {
|
|
@@ -44385,6 +44954,8 @@ var init_session_host_transport = __esm({
|
|
|
44385
44954
|
runtimeKey: record2.runtimeKey,
|
|
44386
44955
|
displayName: record2.displayName,
|
|
44387
44956
|
workspaceLabel: record2.workspaceLabel,
|
|
44957
|
+
lifecycle: typeof record2.lifecycle === "string" ? record2.lifecycle : null,
|
|
44958
|
+
surfaceKind: record2.surfaceKind,
|
|
44388
44959
|
writeOwner: record2.writeOwner ? {
|
|
44389
44960
|
clientId: record2.writeOwner.clientId,
|
|
44390
44961
|
ownerType: record2.writeOwner.ownerType
|
|
@@ -45112,8 +45683,8 @@ __export(src_exports, {
|
|
|
45112
45683
|
getRecentDebugTrace: () => getRecentDebugTrace,
|
|
45113
45684
|
getRecentLogs: () => getRecentLogs,
|
|
45114
45685
|
getSavedProviderSessions: () => getSavedProviderSessions,
|
|
45115
|
-
getSessionHostRecoveryLabel: () =>
|
|
45116
|
-
getSessionHostSurfaceKind: () =>
|
|
45686
|
+
getSessionHostRecoveryLabel: () => getSessionHostRecoveryLabel,
|
|
45687
|
+
getSessionHostSurfaceKind: () => getSessionHostSurfaceKind,
|
|
45117
45688
|
getWorkspaceState: () => getWorkspaceState,
|
|
45118
45689
|
hasCdpManager: () => hasCdpManager,
|
|
45119
45690
|
hashSignatureParts: () => hashSignatureParts,
|
|
@@ -45126,8 +45697,8 @@ __export(src_exports, {
|
|
|
45126
45697
|
isIdeRunning: () => isIdeRunning,
|
|
45127
45698
|
isManagedStatusWaiting: () => isManagedStatusWaiting,
|
|
45128
45699
|
isManagedStatusWorking: () => isManagedStatusWorking,
|
|
45129
|
-
isSessionHostLiveRuntime: () =>
|
|
45130
|
-
isSessionHostRecoverySnapshot: () =>
|
|
45700
|
+
isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
|
|
45701
|
+
isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot,
|
|
45131
45702
|
isSetupComplete: () => isSetupComplete,
|
|
45132
45703
|
killIdeProcess: () => killIdeProcess,
|
|
45133
45704
|
launchIDE: () => launchIDE,
|
|
@@ -45162,6 +45733,7 @@ __export(src_exports, {
|
|
|
45162
45733
|
resolveChatMessageKind: () => resolveChatMessageKind,
|
|
45163
45734
|
resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
|
|
45164
45735
|
resolveSessionHostAppName: () => resolveSessionHostAppName,
|
|
45736
|
+
runAsyncBatch: () => runAsyncBatch,
|
|
45165
45737
|
saveConfig: () => saveConfig,
|
|
45166
45738
|
saveState: () => saveState,
|
|
45167
45739
|
setDebugRuntimeConfig: () => setDebugRuntimeConfig,
|
|
@@ -45209,6 +45781,7 @@ var init_src = __esm({
|
|
|
45209
45781
|
init_chat_history();
|
|
45210
45782
|
init_chat_signatures();
|
|
45211
45783
|
init_subscription_updates();
|
|
45784
|
+
init_async_batch();
|
|
45212
45785
|
init_agent_stream();
|
|
45213
45786
|
init_agent_stream();
|
|
45214
45787
|
init_forward();
|
|
@@ -77527,6 +78100,7 @@ var init_daemon_p2p = __esm({
|
|
|
77527
78100
|
fs20 = __toESM(require("fs"));
|
|
77528
78101
|
path26 = __toESM(require("path"));
|
|
77529
78102
|
import_node_module2 = require("module");
|
|
78103
|
+
init_src();
|
|
77530
78104
|
init_data_channel_router();
|
|
77531
78105
|
init_screenshot_sender();
|
|
77532
78106
|
init_peer_connection_manager();
|
|
@@ -77776,14 +78350,22 @@ ${e?.stack || ""}`);
|
|
|
77776
78350
|
return false;
|
|
77777
78351
|
}
|
|
77778
78352
|
async flushChatSubscriptions(builder) {
|
|
78353
|
+
const tasks = [];
|
|
77779
78354
|
for (const peer of this.peers.values()) {
|
|
77780
78355
|
if (peer.state !== "connected" || !peer.chatSubscriptions || peer.chatSubscriptions.size === 0) continue;
|
|
77781
78356
|
for (const subscription of peer.chatSubscriptions.values()) {
|
|
78357
|
+
tasks.push({ peer, subscription });
|
|
78358
|
+
}
|
|
78359
|
+
}
|
|
78360
|
+
await runAsyncBatch(tasks, async ({ peer, subscription }) => {
|
|
78361
|
+
try {
|
|
77782
78362
|
const update = await builder(subscription);
|
|
77783
|
-
if (!update)
|
|
78363
|
+
if (!update) return;
|
|
77784
78364
|
this.screenshotSender.sendTopicUpdateToPeer(peer, update);
|
|
78365
|
+
} catch (error48) {
|
|
78366
|
+
log(`chat_tail flush skipped: peer=${peer.peerId} session=${subscription.params.targetSessionId} error=${error48?.message || error48}`);
|
|
77785
78367
|
}
|
|
77786
|
-
}
|
|
78368
|
+
}, { concurrency: 4 });
|
|
77787
78369
|
}
|
|
77788
78370
|
async flushMachineRuntimeSubscriptions(builder) {
|
|
77789
78371
|
for (const peer of this.peers.values()) {
|
|
@@ -85267,7 +85849,7 @@ var init_adhdev_daemon = __esm({
|
|
|
85267
85849
|
init_source();
|
|
85268
85850
|
init_version();
|
|
85269
85851
|
init_src();
|
|
85270
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.
|
|
85852
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.77" });
|
|
85271
85853
|
AdhdevDaemon = class _AdhdevDaemon {
|
|
85272
85854
|
localHttpServer = null;
|
|
85273
85855
|
localWss = null;
|
|
@@ -85681,7 +86263,7 @@ ${err?.stack || ""}`);
|
|
|
85681
86263
|
}),
|
|
85682
86264
|
onStatusChange: () => {
|
|
85683
86265
|
this.statusReporter?.onStatusChange();
|
|
85684
|
-
void this.flushP2PChatSubscriptions({ onlyActive:
|
|
86266
|
+
void this.flushP2PChatSubscriptions({ onlyActive: true });
|
|
85685
86267
|
},
|
|
85686
86268
|
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
|
|
85687
86269
|
hostedRuntimeManagerTag: "adhdev-cloud",
|
|
@@ -85710,7 +86292,7 @@ ${err?.stack || ""}`);
|
|
|
85710
86292
|
statusVersion: pkgVersion,
|
|
85711
86293
|
onStatusChange: () => {
|
|
85712
86294
|
this.statusReporter?.onStatusChange();
|
|
85713
|
-
void this.flushP2PChatSubscriptions({ onlyActive:
|
|
86295
|
+
void this.flushP2PChatSubscriptions({ onlyActive: true });
|
|
85714
86296
|
},
|
|
85715
86297
|
onPostChatCommand: () => {
|
|
85716
86298
|
setTimeout(() => this.statusReporter?.throttledReport(), 1e3);
|
|
@@ -86736,7 +87318,7 @@ async function buildRuntimeTargetResolutionTrace(records, target, options) {
|
|
|
86736
87318
|
runtimeKey: record2.runtimeKey,
|
|
86737
87319
|
displayName: record2.displayName,
|
|
86738
87320
|
lifecycle: record2.lifecycle,
|
|
86739
|
-
surfaceKind:
|
|
87321
|
+
surfaceKind: getSessionHostSurfaceKind2(record2),
|
|
86740
87322
|
attachedClientCount: Array.isArray(record2.attachedClients) ? record2.attachedClients.length : 0,
|
|
86741
87323
|
writeOwnerClientId: record2.writeOwner?.clientId
|
|
86742
87324
|
};
|