adhdev 0.8.74 → 0.8.76
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 +642 -94
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +642 -94
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1807,6 +1807,32 @@ var init_logger = __esm({
|
|
|
1807
1807
|
});
|
|
1808
1808
|
|
|
1809
1809
|
// ../../oss/packages/daemon-core/src/cdp/manager.ts
|
|
1810
|
+
function normalizeTitle(value) {
|
|
1811
|
+
return String(value || "").trim().replace(/\s+/g, " ").toLowerCase();
|
|
1812
|
+
}
|
|
1813
|
+
function titlesMatch(lhs, rhs) {
|
|
1814
|
+
const a = normalizeTitle(lhs);
|
|
1815
|
+
const b = normalizeTitle(rhs);
|
|
1816
|
+
if (!a || !b) return false;
|
|
1817
|
+
return a === b || a.includes(b) || b.includes(a);
|
|
1818
|
+
}
|
|
1819
|
+
function resolveCdpPageTarget(params) {
|
|
1820
|
+
const { pages, pinnedTargetId, previousPageTitle } = params;
|
|
1821
|
+
if (pages.length === 0) return { target: null, retargeted: false };
|
|
1822
|
+
if (!pinnedTargetId) {
|
|
1823
|
+
return { target: pages[0] || null, retargeted: false };
|
|
1824
|
+
}
|
|
1825
|
+
const exact = pages.find((page) => page.id === pinnedTargetId);
|
|
1826
|
+
if (exact) return { target: exact, retargeted: false };
|
|
1827
|
+
const titleMatchesList = pages.filter((page) => titlesMatch(page.title, previousPageTitle));
|
|
1828
|
+
if (titleMatchesList.length === 1) {
|
|
1829
|
+
return { target: titleMatchesList[0], retargeted: true };
|
|
1830
|
+
}
|
|
1831
|
+
if (pages.length === 1) {
|
|
1832
|
+
return { target: pages[0], retargeted: true };
|
|
1833
|
+
}
|
|
1834
|
+
return { target: null, retargeted: false };
|
|
1835
|
+
}
|
|
1810
1836
|
var import_ws, http, DaemonCdpManager;
|
|
1811
1837
|
var init_manager = __esm({
|
|
1812
1838
|
"../../oss/packages/daemon-core/src/cdp/manager.ts"() {
|
|
@@ -1974,18 +2000,28 @@ var init_manager = __esm({
|
|
|
1974
2000
|
resolve17(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
1975
2001
|
return;
|
|
1976
2002
|
}
|
|
1977
|
-
const
|
|
1978
|
-
const
|
|
2003
|
+
const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
2004
|
+
const mainPages = titleFilteredPages.filter((t) => this.isMainPageUrl(t.url));
|
|
2005
|
+
const list = mainPages.length > 0 ? mainPages : titleFilteredPages.length > 0 ? titleFilteredPages : pages;
|
|
1979
2006
|
this.log(`[CDP] pages(${list.length}): ${list.map((t) => `"${t.title}"`).join(", ")}`);
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
2007
|
+
const previousTargetId = this._targetId;
|
|
2008
|
+
const selected = resolveCdpPageTarget({
|
|
2009
|
+
pages: list,
|
|
2010
|
+
pinnedTargetId: previousTargetId,
|
|
2011
|
+
previousPageTitle: this._pageTitle
|
|
2012
|
+
});
|
|
2013
|
+
if (selected.target) {
|
|
2014
|
+
if (selected.retargeted && previousTargetId && previousTargetId !== selected.target.id) {
|
|
2015
|
+
this.log(`[CDP] Target ${previousTargetId} rekeyed to ${selected.target.id}`);
|
|
2016
|
+
this._targetId = selected.target.id;
|
|
1988
2017
|
}
|
|
2018
|
+
this._pageTitle = selected.target.title || "";
|
|
2019
|
+
resolve17(selected.target);
|
|
2020
|
+
return;
|
|
2021
|
+
}
|
|
2022
|
+
if (previousTargetId) {
|
|
2023
|
+
this.log(`[CDP] Target ${previousTargetId} not found in page list`);
|
|
2024
|
+
resolve17(null);
|
|
1989
2025
|
return;
|
|
1990
2026
|
}
|
|
1991
2027
|
this._pageTitle = list[0]?.title || "";
|
|
@@ -3862,6 +3898,68 @@ function sanitizeHistoryMessage(agentType, message) {
|
|
|
3862
3898
|
content
|
|
3863
3899
|
};
|
|
3864
3900
|
}
|
|
3901
|
+
function sortSavedHistorySessionSummaries(summaries) {
|
|
3902
|
+
return summaries.slice().sort((a, b) => b.lastMessageAt - a.lastMessageAt);
|
|
3903
|
+
}
|
|
3904
|
+
function buildSavedHistorySessionSummaryMapFromEntries(entries) {
|
|
3905
|
+
const summaries = /* @__PURE__ */ new Map();
|
|
3906
|
+
for (const entry of Array.from(entries.values())) {
|
|
3907
|
+
const fileSummary = entry.summary;
|
|
3908
|
+
if (!fileSummary || fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) continue;
|
|
3909
|
+
const existing = summaries.get(fileSummary.historySessionId);
|
|
3910
|
+
if (!existing) {
|
|
3911
|
+
summaries.set(fileSummary.historySessionId, {
|
|
3912
|
+
historySessionId: fileSummary.historySessionId,
|
|
3913
|
+
sessionTitle: fileSummary.sessionTitle,
|
|
3914
|
+
messageCount: fileSummary.messageCount,
|
|
3915
|
+
firstMessageAt: fileSummary.firstMessageAt,
|
|
3916
|
+
lastMessageAt: fileSummary.lastMessageAt,
|
|
3917
|
+
preview: fileSummary.preview,
|
|
3918
|
+
workspace: fileSummary.workspace
|
|
3919
|
+
});
|
|
3920
|
+
continue;
|
|
3921
|
+
}
|
|
3922
|
+
existing.messageCount += fileSummary.messageCount;
|
|
3923
|
+
if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
|
|
3924
|
+
existing.firstMessageAt = fileSummary.firstMessageAt;
|
|
3925
|
+
}
|
|
3926
|
+
if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
|
|
3927
|
+
existing.lastMessageAt = fileSummary.lastMessageAt;
|
|
3928
|
+
if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
|
|
3929
|
+
if (fileSummary.preview) existing.preview = fileSummary.preview;
|
|
3930
|
+
}
|
|
3931
|
+
if (!existing.workspace && fileSummary.workspace) {
|
|
3932
|
+
existing.workspace = fileSummary.workspace;
|
|
3933
|
+
}
|
|
3934
|
+
}
|
|
3935
|
+
return Object.fromEntries(sortSavedHistorySessionSummaries(Array.from(summaries.values())).map((summary) => [summary.historySessionId, summary]));
|
|
3936
|
+
}
|
|
3937
|
+
function readPersistedSavedHistorySessionSummaries(dir) {
|
|
3938
|
+
try {
|
|
3939
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
3940
|
+
if (!fs3.existsSync(filePath)) return null;
|
|
3941
|
+
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
3942
|
+
if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.sessions || typeof raw.sessions !== "object") {
|
|
3943
|
+
return null;
|
|
3944
|
+
}
|
|
3945
|
+
return sortSavedHistorySessionSummaries(
|
|
3946
|
+
Object.values(raw.sessions).filter((summary) => !!summary && typeof summary.historySessionId === "string" && summary.messageCount > 0 && summary.lastMessageAt > 0).map((summary) => ({
|
|
3947
|
+
historySessionId: summary.historySessionId,
|
|
3948
|
+
sessionTitle: summary.sessionTitle,
|
|
3949
|
+
messageCount: summary.messageCount,
|
|
3950
|
+
firstMessageAt: summary.firstMessageAt,
|
|
3951
|
+
lastMessageAt: summary.lastMessageAt,
|
|
3952
|
+
preview: summary.preview,
|
|
3953
|
+
workspace: summary.workspace
|
|
3954
|
+
}))
|
|
3955
|
+
);
|
|
3956
|
+
} catch {
|
|
3957
|
+
return null;
|
|
3958
|
+
}
|
|
3959
|
+
}
|
|
3960
|
+
function shouldScheduleSavedHistoryRollup(totalBytes) {
|
|
3961
|
+
return Number.isFinite(totalBytes) && totalBytes >= SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES;
|
|
3962
|
+
}
|
|
3865
3963
|
function sanitizeHistoryFileSegment(value) {
|
|
3866
3964
|
return String(value || "").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3867
3965
|
}
|
|
@@ -3875,71 +3973,386 @@ function listHistoryFiles(dir, historySessionId) {
|
|
|
3875
3973
|
return true;
|
|
3876
3974
|
}).sort().reverse();
|
|
3877
3975
|
}
|
|
3878
|
-
function
|
|
3879
|
-
|
|
3976
|
+
function normalizeSavedHistorySessionId(agentType, historySessionId) {
|
|
3977
|
+
const normalizedId = String(historySessionId || "").trim();
|
|
3978
|
+
if (!normalizedId) return "";
|
|
3979
|
+
const strictProviderId = normalizeProviderSessionId(agentType, normalizedId);
|
|
3980
|
+
if (strictProviderId) return strictProviderId;
|
|
3981
|
+
return agentType === "hermes-cli" ? "" : normalizedId;
|
|
3982
|
+
}
|
|
3983
|
+
function extractSavedHistorySessionIdFromFile(agentType, file2) {
|
|
3984
|
+
const match = file2.match(/^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/);
|
|
3985
|
+
return normalizeSavedHistorySessionId(agentType, match?.[1] || "");
|
|
3986
|
+
}
|
|
3987
|
+
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
3988
|
+
return new Map(files.map((file2) => {
|
|
3880
3989
|
try {
|
|
3881
3990
|
const stat4 = fs3.statSync(path7.join(dir, file2));
|
|
3882
|
-
return `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}
|
|
3991
|
+
return [file2, `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`];
|
|
3883
3992
|
} 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
|
-
|
|
3993
|
+
return [file2, `${file2}:missing`];
|
|
3994
|
+
}
|
|
3995
|
+
}));
|
|
3996
|
+
}
|
|
3997
|
+
function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
3998
|
+
return files.map((file2) => fileSignatures.get(file2) || `${file2}:missing`).join("|");
|
|
3999
|
+
}
|
|
4000
|
+
function getSavedHistoryIndexFilePath(dir) {
|
|
4001
|
+
return path7.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
4002
|
+
}
|
|
4003
|
+
function getSavedHistoryIndexLockPath(dir) {
|
|
4004
|
+
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
4005
|
+
}
|
|
4006
|
+
function sleepBlocking(ms) {
|
|
4007
|
+
if (ms <= 0) return;
|
|
4008
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
4009
|
+
}
|
|
4010
|
+
function loadPersistedSavedHistoryIndexFromFile(dir) {
|
|
4011
|
+
try {
|
|
4012
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
4013
|
+
if (!fs3.existsSync(filePath)) return /* @__PURE__ */ new Map();
|
|
4014
|
+
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
4015
|
+
if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.files || typeof raw.files !== "object") {
|
|
4016
|
+
return /* @__PURE__ */ new Map();
|
|
4017
|
+
}
|
|
4018
|
+
return new Map(
|
|
4019
|
+
Object.entries(raw.files).filter(([file2, entry]) => !!file2 && !!entry && typeof entry.signature === "string").map(([file2, entry]) => [file2, {
|
|
4020
|
+
signature: entry.signature,
|
|
4021
|
+
summary: entry.summary || null
|
|
4022
|
+
}])
|
|
4023
|
+
);
|
|
4024
|
+
} catch {
|
|
4025
|
+
return /* @__PURE__ */ new Map();
|
|
4026
|
+
}
|
|
4027
|
+
}
|
|
4028
|
+
function writePersistedSavedHistoryIndexFile(dir, entries) {
|
|
4029
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
4030
|
+
const tempPath = `${filePath}.tmp`;
|
|
4031
|
+
const payload = {
|
|
4032
|
+
version: SAVED_HISTORY_INDEX_VERSION,
|
|
4033
|
+
files: Object.fromEntries(entries.entries()),
|
|
4034
|
+
sessions: buildSavedHistorySessionSummaryMapFromEntries(entries)
|
|
4035
|
+
};
|
|
4036
|
+
fs3.writeFileSync(tempPath, JSON.stringify(payload), "utf-8");
|
|
4037
|
+
fs3.renameSync(tempPath, filePath);
|
|
4038
|
+
}
|
|
4039
|
+
function acquireSavedHistoryIndexLock(dir) {
|
|
4040
|
+
const lockPath = getSavedHistoryIndexLockPath(dir);
|
|
4041
|
+
const deadline = Date.now() + SAVED_HISTORY_INDEX_LOCK_WAIT_MS;
|
|
4042
|
+
while (Date.now() <= deadline) {
|
|
4043
|
+
try {
|
|
4044
|
+
fs3.mkdirSync(lockPath);
|
|
4045
|
+
return () => {
|
|
3913
4046
|
try {
|
|
3914
|
-
|
|
4047
|
+
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
3915
4048
|
} catch {
|
|
3916
|
-
parsed = null;
|
|
3917
4049
|
}
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
4050
|
+
};
|
|
4051
|
+
} catch (error48) {
|
|
4052
|
+
if (error48?.code !== "EEXIST") return null;
|
|
4053
|
+
try {
|
|
4054
|
+
const stat4 = fs3.statSync(lockPath);
|
|
4055
|
+
if (Date.now() - stat4.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
|
|
4056
|
+
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
3921
4057
|
continue;
|
|
3922
4058
|
}
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
4059
|
+
} catch {
|
|
4060
|
+
continue;
|
|
4061
|
+
}
|
|
4062
|
+
sleepBlocking(SAVED_HISTORY_INDEX_LOCK_POLL_MS);
|
|
4063
|
+
}
|
|
4064
|
+
}
|
|
4065
|
+
return null;
|
|
4066
|
+
}
|
|
4067
|
+
function withLockedPersistedSavedHistoryIndex(dir, callback) {
|
|
4068
|
+
const release2 = acquireSavedHistoryIndexLock(dir);
|
|
4069
|
+
if (!release2) return null;
|
|
4070
|
+
try {
|
|
4071
|
+
const entries = loadPersistedSavedHistoryIndexFromFile(dir);
|
|
4072
|
+
const result = callback(entries);
|
|
4073
|
+
writePersistedSavedHistoryIndexFile(dir, entries);
|
|
4074
|
+
return result;
|
|
4075
|
+
} catch {
|
|
4076
|
+
return null;
|
|
4077
|
+
} finally {
|
|
4078
|
+
release2();
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
function loadPersistedSavedHistoryIndex(dir) {
|
|
4082
|
+
return loadPersistedSavedHistoryIndexFromFile(dir);
|
|
4083
|
+
}
|
|
4084
|
+
function savePersistedSavedHistoryIndex(dir, entries) {
|
|
4085
|
+
withLockedPersistedSavedHistoryIndex(dir, (currentEntries) => {
|
|
4086
|
+
const incomingFiles = new Set(Array.from(entries.keys()));
|
|
4087
|
+
for (const [file2, entry] of Array.from(entries.entries())) {
|
|
4088
|
+
const liveSignature = buildSavedHistoryFileSignature(dir, file2);
|
|
4089
|
+
const existingEntry = currentEntries.get(file2);
|
|
4090
|
+
if (existingEntry && existingEntry.signature !== liveSignature && entry.signature !== liveSignature) {
|
|
4091
|
+
continue;
|
|
4092
|
+
}
|
|
4093
|
+
if (entry.signature !== liveSignature && (!existingEntry || existingEntry.signature !== liveSignature)) {
|
|
4094
|
+
continue;
|
|
4095
|
+
}
|
|
4096
|
+
currentEntries.set(file2, entry.signature === liveSignature ? entry : {
|
|
4097
|
+
signature: liveSignature,
|
|
4098
|
+
summary: existingEntry?.summary || entry.summary
|
|
4099
|
+
});
|
|
4100
|
+
}
|
|
4101
|
+
for (const file2 of Array.from(currentEntries.keys())) {
|
|
4102
|
+
if (incomingFiles.has(file2)) continue;
|
|
4103
|
+
if (!fs3.existsSync(path7.join(dir, file2))) {
|
|
4104
|
+
currentEntries.delete(file2);
|
|
4105
|
+
}
|
|
4106
|
+
}
|
|
4107
|
+
});
|
|
4108
|
+
}
|
|
4109
|
+
function invalidatePersistedSavedHistoryIndex(agentType, dir) {
|
|
4110
|
+
try {
|
|
4111
|
+
fs3.rmSync(getSavedHistoryIndexFilePath(dir), { force: true });
|
|
4112
|
+
} catch {
|
|
4113
|
+
}
|
|
4114
|
+
savedHistorySessionCache.delete(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"));
|
|
4115
|
+
}
|
|
4116
|
+
function buildSavedHistoryIndexFileSignature(dir) {
|
|
4117
|
+
try {
|
|
4118
|
+
const stat4 = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
4119
|
+
return `index:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
|
|
4120
|
+
} catch {
|
|
4121
|
+
return "index:missing";
|
|
4122
|
+
}
|
|
4123
|
+
}
|
|
4124
|
+
function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
4125
|
+
try {
|
|
4126
|
+
const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
4127
|
+
const files = listHistoryFiles(dir);
|
|
4128
|
+
for (const file2 of files) {
|
|
4129
|
+
const stat4 = fs3.statSync(path7.join(dir, file2));
|
|
4130
|
+
if (stat4.mtimeMs > indexStat.mtimeMs) return true;
|
|
4131
|
+
}
|
|
4132
|
+
return false;
|
|
4133
|
+
} catch {
|
|
4134
|
+
return true;
|
|
4135
|
+
}
|
|
4136
|
+
}
|
|
4137
|
+
function buildSavedHistoryFileSignature(dir, file2) {
|
|
4138
|
+
try {
|
|
4139
|
+
const stat4 = fs3.statSync(path7.join(dir, file2));
|
|
4140
|
+
return `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
|
|
4141
|
+
} catch {
|
|
4142
|
+
return `${file2}:missing`;
|
|
3940
4143
|
}
|
|
3941
|
-
|
|
3942
|
-
|
|
4144
|
+
}
|
|
4145
|
+
function persistSavedHistoryFileSummaryEntry(agentType, dir, file2, updater) {
|
|
4146
|
+
const filePath = path7.join(dir, file2);
|
|
4147
|
+
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
4148
|
+
const currentEntry = entries.get(file2) || null;
|
|
4149
|
+
const nextSummary = updater(currentEntry?.summary || null);
|
|
4150
|
+
const nextEntry = {
|
|
4151
|
+
signature: buildSavedHistoryFileSignature(dir, file2),
|
|
4152
|
+
summary: nextSummary
|
|
4153
|
+
};
|
|
4154
|
+
entries.set(file2, nextEntry);
|
|
4155
|
+
savedHistoryFileSummaryCache.set(filePath, nextEntry);
|
|
4156
|
+
return nextEntry;
|
|
4157
|
+
});
|
|
4158
|
+
if (!result) return;
|
|
4159
|
+
if (result.summary?.historySessionId && shouldScheduleSavedHistoryRollupForSignature(result.signature)) {
|
|
4160
|
+
scheduleSavedHistoryRollup(agentType, result.summary.historySessionId);
|
|
4161
|
+
}
|
|
4162
|
+
}
|
|
4163
|
+
function updateSavedHistoryIndexForSessionStart(agentType, dir, file2, historySessionId, workspace) {
|
|
4164
|
+
const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId);
|
|
4165
|
+
const normalizedWorkspace = String(workspace || "").trim();
|
|
4166
|
+
if (!normalizedSessionId || !normalizedWorkspace) return;
|
|
4167
|
+
persistSavedHistoryFileSummaryEntry(agentType, dir, file2, (currentSummary) => ({
|
|
4168
|
+
file: file2,
|
|
4169
|
+
historySessionId: normalizedSessionId,
|
|
4170
|
+
messageCount: currentSummary?.messageCount || 0,
|
|
4171
|
+
firstMessageAt: currentSummary?.firstMessageAt || 0,
|
|
4172
|
+
lastMessageAt: currentSummary?.lastMessageAt || 0,
|
|
4173
|
+
sessionTitle: currentSummary?.sessionTitle,
|
|
4174
|
+
preview: currentSummary?.preview,
|
|
4175
|
+
workspace: normalizedWorkspace
|
|
4176
|
+
}));
|
|
4177
|
+
}
|
|
4178
|
+
function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file2, historySessionId, messages) {
|
|
4179
|
+
const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId || "");
|
|
4180
|
+
if (!normalizedSessionId || messages.length === 0) return;
|
|
4181
|
+
persistSavedHistoryFileSummaryEntry(agentType, dir, file2, (currentSummary) => {
|
|
4182
|
+
const nextSummary = {
|
|
4183
|
+
file: file2,
|
|
4184
|
+
historySessionId: normalizedSessionId,
|
|
4185
|
+
messageCount: currentSummary?.messageCount || 0,
|
|
4186
|
+
firstMessageAt: currentSummary?.firstMessageAt || 0,
|
|
4187
|
+
lastMessageAt: currentSummary?.lastMessageAt || 0,
|
|
4188
|
+
sessionTitle: currentSummary?.sessionTitle,
|
|
4189
|
+
preview: currentSummary?.preview,
|
|
4190
|
+
workspace: currentSummary?.workspace
|
|
4191
|
+
};
|
|
4192
|
+
for (const message of messages) {
|
|
4193
|
+
if (!message || message.historySessionId !== historySessionId) continue;
|
|
4194
|
+
if (message.kind === "session_start") {
|
|
4195
|
+
if (message.workspace) nextSummary.workspace = message.workspace;
|
|
4196
|
+
continue;
|
|
4197
|
+
}
|
|
4198
|
+
nextSummary.messageCount += 1;
|
|
4199
|
+
if (!nextSummary.firstMessageAt || message.receivedAt < nextSummary.firstMessageAt) {
|
|
4200
|
+
nextSummary.firstMessageAt = message.receivedAt;
|
|
4201
|
+
}
|
|
4202
|
+
if (!nextSummary.lastMessageAt || message.receivedAt >= nextSummary.lastMessageAt) {
|
|
4203
|
+
nextSummary.lastMessageAt = message.receivedAt;
|
|
4204
|
+
if (message.sessionTitle) nextSummary.sessionTitle = message.sessionTitle;
|
|
4205
|
+
if (message.role !== "system" && message.content.trim()) nextSummary.preview = message.content.trim();
|
|
4206
|
+
} else if (message.sessionTitle) {
|
|
4207
|
+
nextSummary.sessionTitle = message.sessionTitle;
|
|
4208
|
+
}
|
|
4209
|
+
if (!nextSummary.preview && message.role !== "system" && message.content.trim()) {
|
|
4210
|
+
nextSummary.preview = message.content.trim();
|
|
4211
|
+
}
|
|
4212
|
+
}
|
|
4213
|
+
return nextSummary;
|
|
4214
|
+
});
|
|
4215
|
+
}
|
|
4216
|
+
function computeSavedHistoryFileSummary(agentType, dir, file2) {
|
|
4217
|
+
const historySessionId = extractSavedHistorySessionIdFromFile(agentType, file2);
|
|
4218
|
+
if (!historySessionId) return null;
|
|
4219
|
+
const filePath = path7.join(dir, file2);
|
|
4220
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
4221
|
+
const lines = content.split("\n").filter(Boolean);
|
|
4222
|
+
let messageCount = 0;
|
|
4223
|
+
let firstMessageAt = 0;
|
|
4224
|
+
let lastMessageAt = 0;
|
|
4225
|
+
let sessionTitle = "";
|
|
4226
|
+
let preview = "";
|
|
4227
|
+
let workspace = "";
|
|
4228
|
+
for (const line of lines) {
|
|
4229
|
+
let parsed = null;
|
|
4230
|
+
try {
|
|
4231
|
+
parsed = JSON.parse(line);
|
|
4232
|
+
} catch {
|
|
4233
|
+
parsed = null;
|
|
4234
|
+
}
|
|
4235
|
+
if (!parsed || parsed.historySessionId !== historySessionId) continue;
|
|
4236
|
+
if (parsed.kind === "session_start") {
|
|
4237
|
+
if (!workspace && parsed.workspace) workspace = parsed.workspace;
|
|
4238
|
+
continue;
|
|
4239
|
+
}
|
|
4240
|
+
messageCount += 1;
|
|
4241
|
+
if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
|
|
4242
|
+
if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
|
|
4243
|
+
if (parsed.sessionTitle) sessionTitle = parsed.sessionTitle;
|
|
4244
|
+
if (parsed.role !== "system" && parsed.content.trim()) preview = parsed.content.trim();
|
|
4245
|
+
}
|
|
4246
|
+
if (messageCount === 0 || !lastMessageAt) return null;
|
|
4247
|
+
return {
|
|
4248
|
+
file: file2,
|
|
4249
|
+
historySessionId,
|
|
4250
|
+
messageCount,
|
|
4251
|
+
firstMessageAt,
|
|
4252
|
+
lastMessageAt,
|
|
4253
|
+
sessionTitle: sessionTitle || void 0,
|
|
4254
|
+
preview: preview || void 0,
|
|
4255
|
+
workspace: workspace || void 0
|
|
4256
|
+
};
|
|
4257
|
+
}
|
|
4258
|
+
function shouldScheduleSavedHistoryRollupForSignature(signature) {
|
|
4259
|
+
const parts = String(signature || "").split(":");
|
|
4260
|
+
const size = Number(parts[1] || 0);
|
|
4261
|
+
return shouldScheduleSavedHistoryRollup(size);
|
|
4262
|
+
}
|
|
4263
|
+
function scheduleSavedHistoryRollup(agentType, historySessionId) {
|
|
4264
|
+
const key = `${agentType}:${historySessionId}`;
|
|
4265
|
+
if (!historySessionId || savedHistoryRollupInFlight.has(key)) return;
|
|
4266
|
+
savedHistoryRollupInFlight.add(key);
|
|
4267
|
+
setTimeout(() => {
|
|
4268
|
+
try {
|
|
4269
|
+
new ChatHistoryWriter().compactHistorySession(agentType, historySessionId);
|
|
4270
|
+
} finally {
|
|
4271
|
+
savedHistoryRollupInFlight.delete(key);
|
|
4272
|
+
}
|
|
4273
|
+
}, 0);
|
|
4274
|
+
}
|
|
4275
|
+
function scheduleSavedHistoryBackgroundRefresh(agentType, dir) {
|
|
4276
|
+
const key = `${agentType}:${dir}`;
|
|
4277
|
+
if (savedHistoryBackgroundRefresh.has(key)) return;
|
|
4278
|
+
savedHistoryBackgroundRefresh.add(key);
|
|
4279
|
+
setTimeout(() => {
|
|
4280
|
+
try {
|
|
4281
|
+
if (!fs3.existsSync(dir)) return;
|
|
4282
|
+
const files = listHistoryFiles(dir);
|
|
4283
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
4284
|
+
const persistedEntries = loadPersistedSavedHistoryIndex(dir);
|
|
4285
|
+
const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
|
|
4286
|
+
savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
|
|
4287
|
+
const refreshedIndexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
4288
|
+
savedHistorySessionCache.set(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"), {
|
|
4289
|
+
signature: refreshedIndexSignature,
|
|
4290
|
+
summaries: computed.summaries || []
|
|
4291
|
+
});
|
|
4292
|
+
for (const [file2, entry] of Array.from(computed.persistedEntries.entries())) {
|
|
4293
|
+
if (!entry?.summary || !shouldScheduleSavedHistoryRollupForSignature(entry.signature)) continue;
|
|
4294
|
+
scheduleSavedHistoryRollup(agentType, entry.summary.historySessionId);
|
|
4295
|
+
}
|
|
4296
|
+
} catch {
|
|
4297
|
+
} finally {
|
|
4298
|
+
savedHistoryBackgroundRefresh.delete(key);
|
|
4299
|
+
}
|
|
4300
|
+
}, 0);
|
|
4301
|
+
}
|
|
4302
|
+
function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries) {
|
|
4303
|
+
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
4304
|
+
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
4305
|
+
for (const file2 of files.slice().sort()) {
|
|
4306
|
+
const filePath = path7.join(dir, file2);
|
|
4307
|
+
const signature = fileSignatures.get(file2) || `${file2}:missing`;
|
|
4308
|
+
const cached2 = savedHistoryFileSummaryCache.get(filePath);
|
|
4309
|
+
const persisted = persistedEntries.get(file2);
|
|
4310
|
+
const reusableEntry = cached2?.signature === signature ? cached2 : persisted?.signature === signature ? persisted : null;
|
|
4311
|
+
const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(agentType, dir, file2);
|
|
4312
|
+
const nextEntry = reusableEntry || {
|
|
4313
|
+
signature,
|
|
4314
|
+
summary: fileSummary
|
|
4315
|
+
};
|
|
4316
|
+
if (!reusableEntry) {
|
|
4317
|
+
nextEntry.signature = signature;
|
|
4318
|
+
nextEntry.summary = fileSummary;
|
|
4319
|
+
}
|
|
4320
|
+
savedHistoryFileSummaryCache.set(filePath, nextEntry);
|
|
4321
|
+
nextPersistedEntries.set(file2, nextEntry);
|
|
4322
|
+
if (!fileSummary) continue;
|
|
4323
|
+
const existing = summaryBySessionId.get(fileSummary.historySessionId);
|
|
4324
|
+
if (fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) {
|
|
4325
|
+
continue;
|
|
4326
|
+
}
|
|
4327
|
+
if (!existing) {
|
|
4328
|
+
summaryBySessionId.set(fileSummary.historySessionId, {
|
|
4329
|
+
historySessionId: fileSummary.historySessionId,
|
|
4330
|
+
sessionTitle: fileSummary.sessionTitle,
|
|
4331
|
+
messageCount: fileSummary.messageCount,
|
|
4332
|
+
firstMessageAt: fileSummary.firstMessageAt,
|
|
4333
|
+
lastMessageAt: fileSummary.lastMessageAt,
|
|
4334
|
+
preview: fileSummary.preview,
|
|
4335
|
+
workspace: fileSummary.workspace
|
|
4336
|
+
});
|
|
4337
|
+
continue;
|
|
4338
|
+
}
|
|
4339
|
+
existing.messageCount += fileSummary.messageCount;
|
|
4340
|
+
if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
|
|
4341
|
+
existing.firstMessageAt = fileSummary.firstMessageAt;
|
|
4342
|
+
}
|
|
4343
|
+
if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
|
|
4344
|
+
existing.lastMessageAt = fileSummary.lastMessageAt;
|
|
4345
|
+
if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
|
|
4346
|
+
if (fileSummary.preview) existing.preview = fileSummary.preview;
|
|
4347
|
+
}
|
|
4348
|
+
if (!existing.workspace && fileSummary.workspace) {
|
|
4349
|
+
existing.workspace = fileSummary.workspace;
|
|
4350
|
+
}
|
|
4351
|
+
}
|
|
4352
|
+
return {
|
|
4353
|
+
summaries: Array.from(summaryBySessionId.values()).sort((a, b) => b.lastMessageAt - a.lastMessageAt),
|
|
4354
|
+
persistedEntries: nextPersistedEntries
|
|
4355
|
+
};
|
|
3943
4356
|
}
|
|
3944
4357
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0) {
|
|
3945
4358
|
try {
|
|
@@ -3997,18 +4410,51 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
3997
4410
|
savedHistorySessionCache.delete(sanitized);
|
|
3998
4411
|
return { sessions: [], hasMore: false };
|
|
3999
4412
|
}
|
|
4000
|
-
const files = listHistoryFiles(dir);
|
|
4001
|
-
const signature = buildSavedHistoryCacheSignature(dir, files);
|
|
4002
4413
|
const cached2 = savedHistorySessionCache.get(sanitized);
|
|
4003
|
-
const
|
|
4004
|
-
|
|
4414
|
+
const offset = Math.max(0, options.offset || 0);
|
|
4415
|
+
const limit = Math.max(1, options.limit || 30);
|
|
4416
|
+
const indexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
4417
|
+
let cacheWasInvalidated = false;
|
|
4418
|
+
if (cached2) {
|
|
4419
|
+
const cacheLooksPersisted = cached2.signature.startsWith("index:");
|
|
4420
|
+
const cacheStillValid = cacheLooksPersisted ? cached2.signature === indexSignature : (() => {
|
|
4421
|
+
const files2 = listHistoryFiles(dir);
|
|
4422
|
+
const fileSignatures2 = buildSavedHistoryFileSignatureMap(dir, files2);
|
|
4423
|
+
return cached2.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
|
|
4424
|
+
})();
|
|
4425
|
+
if (cacheStillValid) {
|
|
4426
|
+
const sliced2 = cached2.summaries.slice(offset, offset + limit);
|
|
4427
|
+
return {
|
|
4428
|
+
sessions: sliced2,
|
|
4429
|
+
hasMore: cached2.summaries.length > offset + limit
|
|
4430
|
+
};
|
|
4431
|
+
}
|
|
4432
|
+
cacheWasInvalidated = true;
|
|
4433
|
+
}
|
|
4434
|
+
const persistedSessions = readPersistedSavedHistorySessionSummaries(dir);
|
|
4435
|
+
if (!cacheWasInvalidated && persistedSessions?.length && !historyDirectoryHasFilesNewerThanIndex(dir)) {
|
|
4005
4436
|
savedHistorySessionCache.set(sanitized, {
|
|
4006
|
-
signature,
|
|
4007
|
-
summaries
|
|
4437
|
+
signature: indexSignature,
|
|
4438
|
+
summaries: persistedSessions
|
|
4008
4439
|
});
|
|
4440
|
+
scheduleSavedHistoryBackgroundRefresh(agentType, dir);
|
|
4441
|
+
const sliced2 = persistedSessions.slice(offset, offset + limit);
|
|
4442
|
+
return {
|
|
4443
|
+
sessions: sliced2,
|
|
4444
|
+
hasMore: persistedSessions.length > offset + limit
|
|
4445
|
+
};
|
|
4009
4446
|
}
|
|
4010
|
-
const
|
|
4011
|
-
const
|
|
4447
|
+
const files = listHistoryFiles(dir);
|
|
4448
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
4449
|
+
const signature = buildSavedHistoryCacheSignature(files, fileSignatures);
|
|
4450
|
+
const persistedEntries = loadPersistedSavedHistoryIndex(dir);
|
|
4451
|
+
const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
|
|
4452
|
+
const summaries = computed.summaries || [];
|
|
4453
|
+
savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
|
|
4454
|
+
savedHistorySessionCache.set(sanitized, {
|
|
4455
|
+
signature,
|
|
4456
|
+
summaries
|
|
4457
|
+
});
|
|
4012
4458
|
const sliced = summaries.slice(offset, offset + limit);
|
|
4013
4459
|
return {
|
|
4014
4460
|
sessions: sliced,
|
|
@@ -4018,7 +4464,7 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
4018
4464
|
return { sessions: [], hasMore: false };
|
|
4019
4465
|
}
|
|
4020
4466
|
}
|
|
4021
|
-
var fs3, path7, os6, HISTORY_DIR, RETAIN_DAYS, savedHistorySessionCache, CODEX_STARTER_PROMPT_RE, ChatHistoryWriter;
|
|
4467
|
+
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
4468
|
var init_chat_history = __esm({
|
|
4023
4469
|
"../../oss/packages/daemon-core/src/config/chat-history.ts"() {
|
|
4024
4470
|
"use strict";
|
|
@@ -4026,9 +4472,20 @@ var init_chat_history = __esm({
|
|
|
4026
4472
|
path7 = __toESM(require("path"));
|
|
4027
4473
|
os6 = __toESM(require("os"));
|
|
4028
4474
|
init_chat_message_normalization();
|
|
4475
|
+
init_provider_session_id();
|
|
4029
4476
|
HISTORY_DIR = path7.join(os6.homedir(), ".adhdev", "history");
|
|
4030
4477
|
RETAIN_DAYS = 30;
|
|
4478
|
+
SAVED_HISTORY_INDEX_VERSION = 1;
|
|
4479
|
+
SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
4480
|
+
SAVED_HISTORY_INDEX_LOCK_SUFFIX = ".lock";
|
|
4481
|
+
SAVED_HISTORY_INDEX_LOCK_WAIT_MS = 1500;
|
|
4482
|
+
SAVED_HISTORY_INDEX_LOCK_STALE_MS = 15e3;
|
|
4483
|
+
SAVED_HISTORY_INDEX_LOCK_POLL_MS = 25;
|
|
4484
|
+
SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES = 16 * 1024 * 1024;
|
|
4031
4485
|
savedHistorySessionCache = /* @__PURE__ */ new Map();
|
|
4486
|
+
savedHistoryFileSummaryCache = /* @__PURE__ */ new Map();
|
|
4487
|
+
savedHistoryBackgroundRefresh = /* @__PURE__ */ new Set();
|
|
4488
|
+
savedHistoryRollupInFlight = /* @__PURE__ */ new Set();
|
|
4032
4489
|
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
4490
|
ChatHistoryWriter = class {
|
|
4034
4491
|
/** Last seen message count per agent (deduplication) */
|
|
@@ -4103,9 +4560,11 @@ var init_chat_history = __esm({
|
|
|
4103
4560
|
fs3.mkdirSync(dir, { recursive: true });
|
|
4104
4561
|
const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4105
4562
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
4106
|
-
const
|
|
4563
|
+
const fileName = `${filePrefix}${date5}.jsonl`;
|
|
4564
|
+
const filePath = path7.join(dir, fileName);
|
|
4107
4565
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
4108
4566
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
4567
|
+
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
4109
4568
|
const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
|
|
4110
4569
|
if (!historySessionId && messages.length < prevCount * 0.5 && prevCount > 3) {
|
|
4111
4570
|
seenHashes.clear();
|
|
@@ -4196,7 +4655,8 @@ var init_chat_history = __esm({
|
|
|
4196
4655
|
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
4197
4656
|
fs3.mkdirSync(dir, { recursive: true });
|
|
4198
4657
|
const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4199
|
-
const
|
|
4658
|
+
const fileName = `${this.sanitize(id)}_${date5}.jsonl`;
|
|
4659
|
+
const filePath = path7.join(dir, fileName);
|
|
4200
4660
|
const record2 = {
|
|
4201
4661
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4202
4662
|
receivedAt: Date.now(),
|
|
@@ -4209,6 +4669,7 @@ var init_chat_history = __esm({
|
|
|
4209
4669
|
workspace: ws
|
|
4210
4670
|
};
|
|
4211
4671
|
fs3.appendFileSync(filePath, JSON.stringify(record2) + "\n", "utf-8");
|
|
4672
|
+
updateSavedHistoryIndexForSessionStart(agentType, dir, fileName, id, ws);
|
|
4212
4673
|
} catch {
|
|
4213
4674
|
}
|
|
4214
4675
|
}
|
|
@@ -4274,6 +4735,7 @@ var init_chat_history = __esm({
|
|
|
4274
4735
|
}
|
|
4275
4736
|
fs3.unlinkSync(sourcePath);
|
|
4276
4737
|
}
|
|
4738
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
4277
4739
|
} catch {
|
|
4278
4740
|
}
|
|
4279
4741
|
}
|
|
@@ -4323,6 +4785,7 @@ var init_chat_history = __esm({
|
|
|
4323
4785
|
fs3.writeFileSync(filePath, `${collapsed.map((entry) => JSON.stringify(entry)).join("\n")}
|
|
4324
4786
|
`, "utf-8");
|
|
4325
4787
|
}
|
|
4788
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
4326
4789
|
} catch {
|
|
4327
4790
|
}
|
|
4328
4791
|
}
|
|
@@ -4342,13 +4805,18 @@ var init_chat_history = __esm({
|
|
|
4342
4805
|
for (const dir of agentDirs) {
|
|
4343
4806
|
const dirPath = path7.join(HISTORY_DIR, dir.name);
|
|
4344
4807
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
4808
|
+
let removedAny = false;
|
|
4345
4809
|
for (const file2 of files) {
|
|
4346
4810
|
const filePath = path7.join(dirPath, file2);
|
|
4347
4811
|
const stat4 = fs3.statSync(filePath);
|
|
4348
4812
|
if (stat4.mtimeMs < cutoff) {
|
|
4349
4813
|
fs3.unlinkSync(filePath);
|
|
4814
|
+
removedAny = true;
|
|
4350
4815
|
}
|
|
4351
4816
|
}
|
|
4817
|
+
if (removedAny) {
|
|
4818
|
+
invalidatePersistedSavedHistoryIndex(dir.name, dirPath);
|
|
4819
|
+
}
|
|
4352
4820
|
}
|
|
4353
4821
|
} catch {
|
|
4354
4822
|
}
|
|
@@ -6275,6 +6743,21 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
6275
6743
|
lastUpdated: ext.lastUpdated
|
|
6276
6744
|
};
|
|
6277
6745
|
}
|
|
6746
|
+
function shouldIncludeExtensionSession(ext) {
|
|
6747
|
+
const status = String(ext.status || "").trim().toLowerCase();
|
|
6748
|
+
const hasActiveChat = !!ext.activeChat;
|
|
6749
|
+
const hasMessages = Array.isArray(ext.activeChat?.messages) && ext.activeChat.messages.length > 0;
|
|
6750
|
+
const hasModal = !!ext.activeChat?.activeModal;
|
|
6751
|
+
const hasStreams = Array.isArray(ext.agentStreams) && ext.agentStreams.length > 0;
|
|
6752
|
+
const hasProviderSessionId = typeof ext.providerSessionId === "string" && ext.providerSessionId.trim().length > 0;
|
|
6753
|
+
const hasControlValues = !!(ext.controlValues && Object.keys(ext.controlValues).length > 0);
|
|
6754
|
+
const hasProviderControls = Array.isArray(ext.providerControls) && ext.providerControls.length > 0;
|
|
6755
|
+
const hasOpenPanelCapability = Array.isArray(ext.sessionCapabilities) && ext.sessionCapabilities.includes("open_panel");
|
|
6756
|
+
const hasSummaryMetadata = !!ext.summaryMetadata;
|
|
6757
|
+
const hasError = typeof ext.errorMessage === "string" && ext.errorMessage.trim().length > 0;
|
|
6758
|
+
const hasInterestingStatus = !!status && !["idle", "panel_hidden", "disconnected", "not_monitored"].includes(status);
|
|
6759
|
+
return hasActiveChat || hasMessages || hasModal || hasStreams || hasProviderSessionId || hasControlValues || hasProviderControls || hasOpenPanelCapability || hasSummaryMetadata || hasError || hasInterestingStatus;
|
|
6760
|
+
}
|
|
6278
6761
|
function buildCliSession(state, options) {
|
|
6279
6762
|
const profile = options.profile || "full";
|
|
6280
6763
|
const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
|
|
@@ -6358,6 +6841,7 @@ function buildSessionEntries(allStates, cdpManagers, options = {}) {
|
|
|
6358
6841
|
for (const state of ideStates) {
|
|
6359
6842
|
sessions.push(buildIdeWorkspaceSession(state, cdpManagers, options));
|
|
6360
6843
|
for (const ext of state.extensions) {
|
|
6844
|
+
if (!shouldIncludeExtensionSession(ext)) continue;
|
|
6361
6845
|
sessions.push(buildExtensionAgentSession(state, ext, options));
|
|
6362
6846
|
}
|
|
6363
6847
|
}
|
|
@@ -8610,7 +9094,9 @@ function applyProviderPatch(h, args, payload) {
|
|
|
8610
9094
|
});
|
|
8611
9095
|
}
|
|
8612
9096
|
async function executeProviderScript(h, args, scriptName) {
|
|
8613
|
-
const
|
|
9097
|
+
const explicitTargetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
9098
|
+
const targetSession = explicitTargetSessionId ? h.ctx.sessionRegistry?.get(explicitTargetSessionId) : void 0;
|
|
9099
|
+
const resolvedProviderType = targetSession?.providerType || h.currentSession?.providerType || h.currentProviderType || args?.agentType || args?.providerType;
|
|
8614
9100
|
if (!resolvedProviderType) return { success: false, error: "targetSessionId or providerType is required" };
|
|
8615
9101
|
const loader = h.ctx.providerLoader;
|
|
8616
9102
|
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
@@ -8653,16 +9139,16 @@ async function executeProviderScript(h, args, scriptName) {
|
|
|
8653
9139
|
const scriptFn = provider.scripts[actualScriptName];
|
|
8654
9140
|
const scriptCode = scriptFn(normalizedArgs);
|
|
8655
9141
|
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;
|
|
9142
|
+
const cdpKey = provider.category === "ide" ? targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey;
|
|
8657
9143
|
LOG.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
|
|
8658
9144
|
const cdp = h.getCdp(cdpKey);
|
|
8659
9145
|
if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
|
|
8660
9146
|
try {
|
|
8661
9147
|
let result;
|
|
8662
9148
|
if (provider.category === "extension") {
|
|
8663
|
-
const runtimeSessionId = h.currentSession?.sessionId
|
|
9149
|
+
const runtimeSessionId = explicitTargetSessionId || h.currentSession?.sessionId;
|
|
8664
9150
|
if (!runtimeSessionId) return { success: false, error: `No target session found for ${resolvedProviderType}` };
|
|
8665
|
-
const parentSessionId = h.currentSession?.parentSessionId;
|
|
9151
|
+
const parentSessionId = targetSession?.parentSessionId || h.currentSession?.parentSessionId;
|
|
8666
9152
|
if (parentSessionId) {
|
|
8667
9153
|
await h.agentStream?.setActiveSession(cdp, parentSessionId, runtimeSessionId);
|
|
8668
9154
|
await h.agentStream?.syncActiveSession(cdp, parentSessionId);
|
|
@@ -37523,6 +38009,28 @@ var init_subscription_updates = __esm({
|
|
|
37523
38009
|
}
|
|
37524
38010
|
});
|
|
37525
38011
|
|
|
38012
|
+
// ../../oss/packages/daemon-core/src/chat/async-batch.ts
|
|
38013
|
+
async function runAsyncBatch(items, worker, options = {}) {
|
|
38014
|
+
const list = Array.from(items);
|
|
38015
|
+
if (list.length === 0) return;
|
|
38016
|
+
const concurrency = Math.max(1, Math.min(list.length, Math.floor(options.concurrency || 1)));
|
|
38017
|
+
let nextIndex = 0;
|
|
38018
|
+
const runners = Array.from({ length: concurrency }, async () => {
|
|
38019
|
+
while (true) {
|
|
38020
|
+
const currentIndex = nextIndex;
|
|
38021
|
+
nextIndex += 1;
|
|
38022
|
+
if (currentIndex >= list.length) return;
|
|
38023
|
+
await worker(list[currentIndex], currentIndex);
|
|
38024
|
+
}
|
|
38025
|
+
});
|
|
38026
|
+
await Promise.all(runners);
|
|
38027
|
+
}
|
|
38028
|
+
var init_async_batch = __esm({
|
|
38029
|
+
"../../oss/packages/daemon-core/src/chat/async-batch.ts"() {
|
|
38030
|
+
"use strict";
|
|
38031
|
+
}
|
|
38032
|
+
});
|
|
38033
|
+
|
|
37526
38034
|
// ../../oss/packages/daemon-core/src/agent-stream/provider-adapter.ts
|
|
37527
38035
|
var ProviderStreamAdapter;
|
|
37528
38036
|
var init_provider_adapter = __esm({
|
|
@@ -38004,10 +38512,12 @@ var init_manager2 = __esm({
|
|
|
38004
38512
|
}
|
|
38005
38513
|
}
|
|
38006
38514
|
/** Collect active extension session state */
|
|
38007
|
-
async collectActiveSession(cdp, parentSessionId) {
|
|
38515
|
+
async collectActiveSession(cdp, parentSessionId, attemptedSessionIds = /* @__PURE__ */ new Set(), originSessionId) {
|
|
38008
38516
|
if (!this.enabled) return null;
|
|
38009
38517
|
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
38010
38518
|
if (!activeSessionId) return null;
|
|
38519
|
+
const resolvedOriginSessionId = originSessionId || activeSessionId;
|
|
38520
|
+
attemptedSessionIds.add(activeSessionId);
|
|
38011
38521
|
let agent = this.managedBySessionId.get(activeSessionId);
|
|
38012
38522
|
if (!agent) {
|
|
38013
38523
|
agent = await this.connectManagedSession(cdp, parentSessionId, activeSessionId) || void 0;
|
|
@@ -38020,18 +38530,44 @@ var init_manager2 = __esm({
|
|
|
38020
38530
|
try {
|
|
38021
38531
|
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
38022
38532
|
const state = await agent.adapter.readChat(evaluate);
|
|
38023
|
-
const
|
|
38024
|
-
const
|
|
38025
|
-
|
|
38026
|
-
|
|
38533
|
+
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;
|
|
38534
|
+
const normalizedState = {
|
|
38535
|
+
...state,
|
|
38536
|
+
sessionId: agent.runtimeSessionId,
|
|
38537
|
+
...resolvedProviderSessionId ? { providerSessionId: resolvedProviderSessionId } : {}
|
|
38538
|
+
};
|
|
38539
|
+
const stateError = this.getStateError(normalizedState);
|
|
38540
|
+
const selectedModelValue = typeof normalizedState.controlValues?.model === "string" ? normalizedState.controlValues.model : "";
|
|
38541
|
+
LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${normalizedState.status} msgs=${normalizedState.messages?.length || 0} model=${selectedModelValue}${normalizedState.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
|
|
38542
|
+
if (normalizedState.status === "error" && this.isRecoverableSessionError(stateError)) {
|
|
38027
38543
|
throw new Error(stateError);
|
|
38028
38544
|
}
|
|
38029
|
-
agent.lastState =
|
|
38545
|
+
agent.lastState = normalizedState;
|
|
38030
38546
|
agent.lastError = null;
|
|
38031
|
-
if (
|
|
38547
|
+
if (normalizedState.status === "panel_hidden") {
|
|
38548
|
+
const discovered = await cdp.discoverAgentWebviews().catch(() => []);
|
|
38549
|
+
const fallbackTarget = discovered.find((entry) => {
|
|
38550
|
+
if (entry.agentType === type) return false;
|
|
38551
|
+
const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, entry.agentType);
|
|
38552
|
+
return !!fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId);
|
|
38553
|
+
});
|
|
38554
|
+
if (fallbackTarget) {
|
|
38555
|
+
const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, fallbackTarget.agentType);
|
|
38556
|
+
if (fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId)) {
|
|
38557
|
+
this.logFn(`[AgentStream] Active session ${type} is hidden; switching to visible agent ${fallbackTarget.agentType} (${parentSessionId})`);
|
|
38558
|
+
await this.setActiveSession(cdp, parentSessionId, fallbackSessionId);
|
|
38559
|
+
await this.syncActiveSession(cdp, parentSessionId);
|
|
38560
|
+
const fallbackState = await this.collectActiveSession(cdp, parentSessionId, attemptedSessionIds, resolvedOriginSessionId);
|
|
38561
|
+
if (fallbackState?.status === "panel_hidden" && resolvedOriginSessionId !== fallbackSessionId) {
|
|
38562
|
+
await this.setActiveSession(cdp, parentSessionId, resolvedOriginSessionId);
|
|
38563
|
+
await this.syncActiveSession(cdp, parentSessionId);
|
|
38564
|
+
}
|
|
38565
|
+
return fallbackState;
|
|
38566
|
+
}
|
|
38567
|
+
}
|
|
38032
38568
|
agent.lastHiddenCheckTime = Date.now();
|
|
38033
38569
|
}
|
|
38034
|
-
return
|
|
38570
|
+
return normalizedState;
|
|
38035
38571
|
} catch (e) {
|
|
38036
38572
|
const errorMsg = e?.message || String(e);
|
|
38037
38573
|
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
@@ -38343,6 +38879,7 @@ var init_poller = __esm({
|
|
|
38343
38879
|
try {
|
|
38344
38880
|
await agentStreamManager.syncActiveSession(cdp, parentSessionId);
|
|
38345
38881
|
let stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
|
|
38882
|
+
resolvedActiveSessionId = stream?.sessionId || agentStreamManager.getActiveSessionId(parentSessionId) || resolvedActiveSessionId;
|
|
38346
38883
|
if (stream?.status === "waiting_approval") {
|
|
38347
38884
|
const autoApprove = providerLoader.getSettings(stream.agentType).autoApprove !== false;
|
|
38348
38885
|
if (autoApprove && resolvedActiveSessionId) {
|
|
@@ -45162,6 +45699,7 @@ __export(src_exports, {
|
|
|
45162
45699
|
resolveChatMessageKind: () => resolveChatMessageKind,
|
|
45163
45700
|
resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
|
|
45164
45701
|
resolveSessionHostAppName: () => resolveSessionHostAppName,
|
|
45702
|
+
runAsyncBatch: () => runAsyncBatch,
|
|
45165
45703
|
saveConfig: () => saveConfig,
|
|
45166
45704
|
saveState: () => saveState,
|
|
45167
45705
|
setDebugRuntimeConfig: () => setDebugRuntimeConfig,
|
|
@@ -45209,6 +45747,7 @@ var init_src = __esm({
|
|
|
45209
45747
|
init_chat_history();
|
|
45210
45748
|
init_chat_signatures();
|
|
45211
45749
|
init_subscription_updates();
|
|
45750
|
+
init_async_batch();
|
|
45212
45751
|
init_agent_stream();
|
|
45213
45752
|
init_agent_stream();
|
|
45214
45753
|
init_forward();
|
|
@@ -77527,6 +78066,7 @@ var init_daemon_p2p = __esm({
|
|
|
77527
78066
|
fs20 = __toESM(require("fs"));
|
|
77528
78067
|
path26 = __toESM(require("path"));
|
|
77529
78068
|
import_node_module2 = require("module");
|
|
78069
|
+
init_src();
|
|
77530
78070
|
init_data_channel_router();
|
|
77531
78071
|
init_screenshot_sender();
|
|
77532
78072
|
init_peer_connection_manager();
|
|
@@ -77776,14 +78316,22 @@ ${e?.stack || ""}`);
|
|
|
77776
78316
|
return false;
|
|
77777
78317
|
}
|
|
77778
78318
|
async flushChatSubscriptions(builder) {
|
|
78319
|
+
const tasks = [];
|
|
77779
78320
|
for (const peer of this.peers.values()) {
|
|
77780
78321
|
if (peer.state !== "connected" || !peer.chatSubscriptions || peer.chatSubscriptions.size === 0) continue;
|
|
77781
78322
|
for (const subscription of peer.chatSubscriptions.values()) {
|
|
78323
|
+
tasks.push({ peer, subscription });
|
|
78324
|
+
}
|
|
78325
|
+
}
|
|
78326
|
+
await runAsyncBatch(tasks, async ({ peer, subscription }) => {
|
|
78327
|
+
try {
|
|
77782
78328
|
const update = await builder(subscription);
|
|
77783
|
-
if (!update)
|
|
78329
|
+
if (!update) return;
|
|
77784
78330
|
this.screenshotSender.sendTopicUpdateToPeer(peer, update);
|
|
78331
|
+
} catch (error48) {
|
|
78332
|
+
log(`chat_tail flush skipped: peer=${peer.peerId} session=${subscription.params.targetSessionId} error=${error48?.message || error48}`);
|
|
77785
78333
|
}
|
|
77786
|
-
}
|
|
78334
|
+
}, { concurrency: 4 });
|
|
77787
78335
|
}
|
|
77788
78336
|
async flushMachineRuntimeSubscriptions(builder) {
|
|
77789
78337
|
for (const peer of this.peers.values()) {
|
|
@@ -85267,7 +85815,7 @@ var init_adhdev_daemon = __esm({
|
|
|
85267
85815
|
init_source();
|
|
85268
85816
|
init_version();
|
|
85269
85817
|
init_src();
|
|
85270
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.
|
|
85818
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.76" });
|
|
85271
85819
|
AdhdevDaemon = class _AdhdevDaemon {
|
|
85272
85820
|
localHttpServer = null;
|
|
85273
85821
|
localWss = null;
|
|
@@ -85681,7 +86229,7 @@ ${err?.stack || ""}`);
|
|
|
85681
86229
|
}),
|
|
85682
86230
|
onStatusChange: () => {
|
|
85683
86231
|
this.statusReporter?.onStatusChange();
|
|
85684
|
-
void this.flushP2PChatSubscriptions({ onlyActive:
|
|
86232
|
+
void this.flushP2PChatSubscriptions({ onlyActive: true });
|
|
85685
86233
|
},
|
|
85686
86234
|
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
|
|
85687
86235
|
hostedRuntimeManagerTag: "adhdev-cloud",
|
|
@@ -85710,7 +86258,7 @@ ${err?.stack || ""}`);
|
|
|
85710
86258
|
statusVersion: pkgVersion,
|
|
85711
86259
|
onStatusChange: () => {
|
|
85712
86260
|
this.statusReporter?.onStatusChange();
|
|
85713
|
-
void this.flushP2PChatSubscriptions({ onlyActive:
|
|
86261
|
+
void this.flushP2PChatSubscriptions({ onlyActive: true });
|
|
85714
86262
|
},
|
|
85715
86263
|
onPostChatCommand: () => {
|
|
85716
86264
|
setTimeout(() => this.statusReporter?.throttledReport(), 1e3);
|