@adhdev/daemon-core 0.8.75 → 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/agent-stream/manager.d.ts +1 -1
- package/dist/cdp/manager.d.ts +9 -2
- package/dist/chat/async-batch.d.ts +4 -0
- package/dist/config/chat-history.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +621 -88
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +620 -88
- package/dist/index.mjs.map +1 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/agent-stream/manager.ts +47 -8
- package/src/agent-stream/poller.ts +1 -0
- package/src/cdp/manager.ts +65 -13
- package/src/chat/async-batch.ts +26 -0
- package/src/commands/stream-commands.ts +8 -5
- package/src/config/chat-history.ts +596 -63
- package/src/index.ts +2 -0
- package/src/status/builders.ts +28 -0
package/dist/index.mjs
CHANGED
|
@@ -4314,6 +4314,32 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
|
|
|
4314
4314
|
init_logger();
|
|
4315
4315
|
import WebSocket from "ws";
|
|
4316
4316
|
import * as http from "http";
|
|
4317
|
+
function normalizeTitle(value) {
|
|
4318
|
+
return String(value || "").trim().replace(/\s+/g, " ").toLowerCase();
|
|
4319
|
+
}
|
|
4320
|
+
function titlesMatch(lhs, rhs) {
|
|
4321
|
+
const a = normalizeTitle(lhs);
|
|
4322
|
+
const b = normalizeTitle(rhs);
|
|
4323
|
+
if (!a || !b) return false;
|
|
4324
|
+
return a === b || a.includes(b) || b.includes(a);
|
|
4325
|
+
}
|
|
4326
|
+
function resolveCdpPageTarget(params) {
|
|
4327
|
+
const { pages, pinnedTargetId, previousPageTitle } = params;
|
|
4328
|
+
if (pages.length === 0) return { target: null, retargeted: false };
|
|
4329
|
+
if (!pinnedTargetId) {
|
|
4330
|
+
return { target: pages[0] || null, retargeted: false };
|
|
4331
|
+
}
|
|
4332
|
+
const exact = pages.find((page) => page.id === pinnedTargetId);
|
|
4333
|
+
if (exact) return { target: exact, retargeted: false };
|
|
4334
|
+
const titleMatchesList = pages.filter((page) => titlesMatch(page.title, previousPageTitle));
|
|
4335
|
+
if (titleMatchesList.length === 1) {
|
|
4336
|
+
return { target: titleMatchesList[0], retargeted: true };
|
|
4337
|
+
}
|
|
4338
|
+
if (pages.length === 1) {
|
|
4339
|
+
return { target: pages[0], retargeted: true };
|
|
4340
|
+
}
|
|
4341
|
+
return { target: null, retargeted: false };
|
|
4342
|
+
}
|
|
4317
4343
|
var DaemonCdpManager = class {
|
|
4318
4344
|
ws = null;
|
|
4319
4345
|
browserWs = null;
|
|
@@ -4474,18 +4500,28 @@ var DaemonCdpManager = class {
|
|
|
4474
4500
|
resolve11(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
4475
4501
|
return;
|
|
4476
4502
|
}
|
|
4477
|
-
const
|
|
4478
|
-
const
|
|
4503
|
+
const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
4504
|
+
const mainPages = titleFilteredPages.filter((t) => this.isMainPageUrl(t.url));
|
|
4505
|
+
const list = mainPages.length > 0 ? mainPages : titleFilteredPages.length > 0 ? titleFilteredPages : pages;
|
|
4479
4506
|
this.log(`[CDP] pages(${list.length}): ${list.map((t) => `"${t.title}"`).join(", ")}`);
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4507
|
+
const previousTargetId = this._targetId;
|
|
4508
|
+
const selected = resolveCdpPageTarget({
|
|
4509
|
+
pages: list,
|
|
4510
|
+
pinnedTargetId: previousTargetId,
|
|
4511
|
+
previousPageTitle: this._pageTitle
|
|
4512
|
+
});
|
|
4513
|
+
if (selected.target) {
|
|
4514
|
+
if (selected.retargeted && previousTargetId && previousTargetId !== selected.target.id) {
|
|
4515
|
+
this.log(`[CDP] Target ${previousTargetId} rekeyed to ${selected.target.id}`);
|
|
4516
|
+
this._targetId = selected.target.id;
|
|
4488
4517
|
}
|
|
4518
|
+
this._pageTitle = selected.target.title || "";
|
|
4519
|
+
resolve11(selected.target);
|
|
4520
|
+
return;
|
|
4521
|
+
}
|
|
4522
|
+
if (previousTargetId) {
|
|
4523
|
+
this.log(`[CDP] Target ${previousTargetId} not found in page list`);
|
|
4524
|
+
resolve11(null);
|
|
4489
4525
|
return;
|
|
4490
4526
|
}
|
|
4491
4527
|
this._pageTitle = list[0]?.title || "";
|
|
@@ -5925,7 +5961,17 @@ import * as path7 from "path";
|
|
|
5925
5961
|
import * as os5 from "os";
|
|
5926
5962
|
var HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
|
|
5927
5963
|
var RETAIN_DAYS = 30;
|
|
5964
|
+
var SAVED_HISTORY_INDEX_VERSION = 1;
|
|
5965
|
+
var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
5966
|
+
var SAVED_HISTORY_INDEX_LOCK_SUFFIX = ".lock";
|
|
5967
|
+
var SAVED_HISTORY_INDEX_LOCK_WAIT_MS = 1500;
|
|
5968
|
+
var SAVED_HISTORY_INDEX_LOCK_STALE_MS = 15e3;
|
|
5969
|
+
var SAVED_HISTORY_INDEX_LOCK_POLL_MS = 25;
|
|
5970
|
+
var SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES = 16 * 1024 * 1024;
|
|
5928
5971
|
var savedHistorySessionCache = /* @__PURE__ */ new Map();
|
|
5972
|
+
var savedHistoryFileSummaryCache = /* @__PURE__ */ new Map();
|
|
5973
|
+
var savedHistoryBackgroundRefresh = /* @__PURE__ */ new Set();
|
|
5974
|
+
var savedHistoryRollupInFlight = /* @__PURE__ */ new Set();
|
|
5929
5975
|
var 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;
|
|
5930
5976
|
function normalizeHistoryComparable(text) {
|
|
5931
5977
|
return String(text || "").replace(/\s+/g, " ").trim();
|
|
@@ -5983,6 +6029,68 @@ function sanitizeHistoryMessage(agentType, message) {
|
|
|
5983
6029
|
content
|
|
5984
6030
|
};
|
|
5985
6031
|
}
|
|
6032
|
+
function sortSavedHistorySessionSummaries(summaries) {
|
|
6033
|
+
return summaries.slice().sort((a, b) => b.lastMessageAt - a.lastMessageAt);
|
|
6034
|
+
}
|
|
6035
|
+
function buildSavedHistorySessionSummaryMapFromEntries(entries) {
|
|
6036
|
+
const summaries = /* @__PURE__ */ new Map();
|
|
6037
|
+
for (const entry of Array.from(entries.values())) {
|
|
6038
|
+
const fileSummary = entry.summary;
|
|
6039
|
+
if (!fileSummary || fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) continue;
|
|
6040
|
+
const existing = summaries.get(fileSummary.historySessionId);
|
|
6041
|
+
if (!existing) {
|
|
6042
|
+
summaries.set(fileSummary.historySessionId, {
|
|
6043
|
+
historySessionId: fileSummary.historySessionId,
|
|
6044
|
+
sessionTitle: fileSummary.sessionTitle,
|
|
6045
|
+
messageCount: fileSummary.messageCount,
|
|
6046
|
+
firstMessageAt: fileSummary.firstMessageAt,
|
|
6047
|
+
lastMessageAt: fileSummary.lastMessageAt,
|
|
6048
|
+
preview: fileSummary.preview,
|
|
6049
|
+
workspace: fileSummary.workspace
|
|
6050
|
+
});
|
|
6051
|
+
continue;
|
|
6052
|
+
}
|
|
6053
|
+
existing.messageCount += fileSummary.messageCount;
|
|
6054
|
+
if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
|
|
6055
|
+
existing.firstMessageAt = fileSummary.firstMessageAt;
|
|
6056
|
+
}
|
|
6057
|
+
if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
|
|
6058
|
+
existing.lastMessageAt = fileSummary.lastMessageAt;
|
|
6059
|
+
if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
|
|
6060
|
+
if (fileSummary.preview) existing.preview = fileSummary.preview;
|
|
6061
|
+
}
|
|
6062
|
+
if (!existing.workspace && fileSummary.workspace) {
|
|
6063
|
+
existing.workspace = fileSummary.workspace;
|
|
6064
|
+
}
|
|
6065
|
+
}
|
|
6066
|
+
return Object.fromEntries(sortSavedHistorySessionSummaries(Array.from(summaries.values())).map((summary) => [summary.historySessionId, summary]));
|
|
6067
|
+
}
|
|
6068
|
+
function readPersistedSavedHistorySessionSummaries(dir) {
|
|
6069
|
+
try {
|
|
6070
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
6071
|
+
if (!fs3.existsSync(filePath)) return null;
|
|
6072
|
+
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
6073
|
+
if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.sessions || typeof raw.sessions !== "object") {
|
|
6074
|
+
return null;
|
|
6075
|
+
}
|
|
6076
|
+
return sortSavedHistorySessionSummaries(
|
|
6077
|
+
Object.values(raw.sessions).filter((summary) => !!summary && typeof summary.historySessionId === "string" && summary.messageCount > 0 && summary.lastMessageAt > 0).map((summary) => ({
|
|
6078
|
+
historySessionId: summary.historySessionId,
|
|
6079
|
+
sessionTitle: summary.sessionTitle,
|
|
6080
|
+
messageCount: summary.messageCount,
|
|
6081
|
+
firstMessageAt: summary.firstMessageAt,
|
|
6082
|
+
lastMessageAt: summary.lastMessageAt,
|
|
6083
|
+
preview: summary.preview,
|
|
6084
|
+
workspace: summary.workspace
|
|
6085
|
+
}))
|
|
6086
|
+
);
|
|
6087
|
+
} catch {
|
|
6088
|
+
return null;
|
|
6089
|
+
}
|
|
6090
|
+
}
|
|
6091
|
+
function shouldScheduleSavedHistoryRollup(totalBytes) {
|
|
6092
|
+
return Number.isFinite(totalBytes) && totalBytes >= SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES;
|
|
6093
|
+
}
|
|
5986
6094
|
function sanitizeHistoryFileSegment(value) {
|
|
5987
6095
|
return String(value || "").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5988
6096
|
}
|
|
@@ -5996,71 +6104,386 @@ function listHistoryFiles(dir, historySessionId) {
|
|
|
5996
6104
|
return true;
|
|
5997
6105
|
}).sort().reverse();
|
|
5998
6106
|
}
|
|
5999
|
-
function
|
|
6000
|
-
|
|
6107
|
+
function normalizeSavedHistorySessionId(agentType, historySessionId) {
|
|
6108
|
+
const normalizedId = String(historySessionId || "").trim();
|
|
6109
|
+
if (!normalizedId) return "";
|
|
6110
|
+
const strictProviderId = normalizeProviderSessionId(agentType, normalizedId);
|
|
6111
|
+
if (strictProviderId) return strictProviderId;
|
|
6112
|
+
return agentType === "hermes-cli" ? "" : normalizedId;
|
|
6113
|
+
}
|
|
6114
|
+
function extractSavedHistorySessionIdFromFile(agentType, file) {
|
|
6115
|
+
const match = file.match(/^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/);
|
|
6116
|
+
return normalizeSavedHistorySessionId(agentType, match?.[1] || "");
|
|
6117
|
+
}
|
|
6118
|
+
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
6119
|
+
return new Map(files.map((file) => {
|
|
6001
6120
|
try {
|
|
6002
6121
|
const stat = fs3.statSync(path7.join(dir, file));
|
|
6003
|
-
return `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}
|
|
6122
|
+
return [file, `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}`];
|
|
6004
6123
|
} catch {
|
|
6005
|
-
return `${file}:missing
|
|
6006
|
-
}
|
|
6007
|
-
})
|
|
6008
|
-
}
|
|
6009
|
-
function
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6124
|
+
return [file, `${file}:missing`];
|
|
6125
|
+
}
|
|
6126
|
+
}));
|
|
6127
|
+
}
|
|
6128
|
+
function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
6129
|
+
return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
|
|
6130
|
+
}
|
|
6131
|
+
function getSavedHistoryIndexFilePath(dir) {
|
|
6132
|
+
return path7.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
6133
|
+
}
|
|
6134
|
+
function getSavedHistoryIndexLockPath(dir) {
|
|
6135
|
+
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
6136
|
+
}
|
|
6137
|
+
function sleepBlocking(ms) {
|
|
6138
|
+
if (ms <= 0) return;
|
|
6139
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
6140
|
+
}
|
|
6141
|
+
function loadPersistedSavedHistoryIndexFromFile(dir) {
|
|
6142
|
+
try {
|
|
6143
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
6144
|
+
if (!fs3.existsSync(filePath)) return /* @__PURE__ */ new Map();
|
|
6145
|
+
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
6146
|
+
if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.files || typeof raw.files !== "object") {
|
|
6147
|
+
return /* @__PURE__ */ new Map();
|
|
6148
|
+
}
|
|
6149
|
+
return new Map(
|
|
6150
|
+
Object.entries(raw.files).filter(([file, entry]) => !!file && !!entry && typeof entry.signature === "string").map(([file, entry]) => [file, {
|
|
6151
|
+
signature: entry.signature,
|
|
6152
|
+
summary: entry.summary || null
|
|
6153
|
+
}])
|
|
6154
|
+
);
|
|
6155
|
+
} catch {
|
|
6156
|
+
return /* @__PURE__ */ new Map();
|
|
6157
|
+
}
|
|
6158
|
+
}
|
|
6159
|
+
function writePersistedSavedHistoryIndexFile(dir, entries) {
|
|
6160
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
6161
|
+
const tempPath = `${filePath}.tmp`;
|
|
6162
|
+
const payload = {
|
|
6163
|
+
version: SAVED_HISTORY_INDEX_VERSION,
|
|
6164
|
+
files: Object.fromEntries(entries.entries()),
|
|
6165
|
+
sessions: buildSavedHistorySessionSummaryMapFromEntries(entries)
|
|
6166
|
+
};
|
|
6167
|
+
fs3.writeFileSync(tempPath, JSON.stringify(payload), "utf-8");
|
|
6168
|
+
fs3.renameSync(tempPath, filePath);
|
|
6169
|
+
}
|
|
6170
|
+
function acquireSavedHistoryIndexLock(dir) {
|
|
6171
|
+
const lockPath = getSavedHistoryIndexLockPath(dir);
|
|
6172
|
+
const deadline = Date.now() + SAVED_HISTORY_INDEX_LOCK_WAIT_MS;
|
|
6173
|
+
while (Date.now() <= deadline) {
|
|
6174
|
+
try {
|
|
6175
|
+
fs3.mkdirSync(lockPath);
|
|
6176
|
+
return () => {
|
|
6034
6177
|
try {
|
|
6035
|
-
|
|
6178
|
+
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
6036
6179
|
} catch {
|
|
6037
|
-
parsed = null;
|
|
6038
6180
|
}
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6181
|
+
};
|
|
6182
|
+
} catch (error) {
|
|
6183
|
+
if (error?.code !== "EEXIST") return null;
|
|
6184
|
+
try {
|
|
6185
|
+
const stat = fs3.statSync(lockPath);
|
|
6186
|
+
if (Date.now() - stat.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
|
|
6187
|
+
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
6042
6188
|
continue;
|
|
6043
6189
|
}
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6190
|
+
} catch {
|
|
6191
|
+
continue;
|
|
6192
|
+
}
|
|
6193
|
+
sleepBlocking(SAVED_HISTORY_INDEX_LOCK_POLL_MS);
|
|
6194
|
+
}
|
|
6195
|
+
}
|
|
6196
|
+
return null;
|
|
6197
|
+
}
|
|
6198
|
+
function withLockedPersistedSavedHistoryIndex(dir, callback) {
|
|
6199
|
+
const release2 = acquireSavedHistoryIndexLock(dir);
|
|
6200
|
+
if (!release2) return null;
|
|
6201
|
+
try {
|
|
6202
|
+
const entries = loadPersistedSavedHistoryIndexFromFile(dir);
|
|
6203
|
+
const result = callback(entries);
|
|
6204
|
+
writePersistedSavedHistoryIndexFile(dir, entries);
|
|
6205
|
+
return result;
|
|
6206
|
+
} catch {
|
|
6207
|
+
return null;
|
|
6208
|
+
} finally {
|
|
6209
|
+
release2();
|
|
6210
|
+
}
|
|
6211
|
+
}
|
|
6212
|
+
function loadPersistedSavedHistoryIndex(dir) {
|
|
6213
|
+
return loadPersistedSavedHistoryIndexFromFile(dir);
|
|
6214
|
+
}
|
|
6215
|
+
function savePersistedSavedHistoryIndex(dir, entries) {
|
|
6216
|
+
withLockedPersistedSavedHistoryIndex(dir, (currentEntries) => {
|
|
6217
|
+
const incomingFiles = new Set(Array.from(entries.keys()));
|
|
6218
|
+
for (const [file, entry] of Array.from(entries.entries())) {
|
|
6219
|
+
const liveSignature = buildSavedHistoryFileSignature(dir, file);
|
|
6220
|
+
const existingEntry = currentEntries.get(file);
|
|
6221
|
+
if (existingEntry && existingEntry.signature !== liveSignature && entry.signature !== liveSignature) {
|
|
6222
|
+
continue;
|
|
6223
|
+
}
|
|
6224
|
+
if (entry.signature !== liveSignature && (!existingEntry || existingEntry.signature !== liveSignature)) {
|
|
6225
|
+
continue;
|
|
6226
|
+
}
|
|
6227
|
+
currentEntries.set(file, entry.signature === liveSignature ? entry : {
|
|
6228
|
+
signature: liveSignature,
|
|
6229
|
+
summary: existingEntry?.summary || entry.summary
|
|
6230
|
+
});
|
|
6231
|
+
}
|
|
6232
|
+
for (const file of Array.from(currentEntries.keys())) {
|
|
6233
|
+
if (incomingFiles.has(file)) continue;
|
|
6234
|
+
if (!fs3.existsSync(path7.join(dir, file))) {
|
|
6235
|
+
currentEntries.delete(file);
|
|
6236
|
+
}
|
|
6237
|
+
}
|
|
6238
|
+
});
|
|
6239
|
+
}
|
|
6240
|
+
function invalidatePersistedSavedHistoryIndex(agentType, dir) {
|
|
6241
|
+
try {
|
|
6242
|
+
fs3.rmSync(getSavedHistoryIndexFilePath(dir), { force: true });
|
|
6243
|
+
} catch {
|
|
6244
|
+
}
|
|
6245
|
+
savedHistorySessionCache.delete(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"));
|
|
6246
|
+
}
|
|
6247
|
+
function buildSavedHistoryIndexFileSignature(dir) {
|
|
6248
|
+
try {
|
|
6249
|
+
const stat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
6250
|
+
return `index:${stat.size}:${Math.trunc(stat.mtimeMs)}`;
|
|
6251
|
+
} catch {
|
|
6252
|
+
return "index:missing";
|
|
6253
|
+
}
|
|
6254
|
+
}
|
|
6255
|
+
function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
6256
|
+
try {
|
|
6257
|
+
const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
6258
|
+
const files = listHistoryFiles(dir);
|
|
6259
|
+
for (const file of files) {
|
|
6260
|
+
const stat = fs3.statSync(path7.join(dir, file));
|
|
6261
|
+
if (stat.mtimeMs > indexStat.mtimeMs) return true;
|
|
6262
|
+
}
|
|
6263
|
+
return false;
|
|
6264
|
+
} catch {
|
|
6265
|
+
return true;
|
|
6266
|
+
}
|
|
6267
|
+
}
|
|
6268
|
+
function buildSavedHistoryFileSignature(dir, file) {
|
|
6269
|
+
try {
|
|
6270
|
+
const stat = fs3.statSync(path7.join(dir, file));
|
|
6271
|
+
return `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}`;
|
|
6272
|
+
} catch {
|
|
6273
|
+
return `${file}:missing`;
|
|
6274
|
+
}
|
|
6275
|
+
}
|
|
6276
|
+
function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
|
|
6277
|
+
const filePath = path7.join(dir, file);
|
|
6278
|
+
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
6279
|
+
const currentEntry = entries.get(file) || null;
|
|
6280
|
+
const nextSummary = updater(currentEntry?.summary || null);
|
|
6281
|
+
const nextEntry = {
|
|
6282
|
+
signature: buildSavedHistoryFileSignature(dir, file),
|
|
6283
|
+
summary: nextSummary
|
|
6284
|
+
};
|
|
6285
|
+
entries.set(file, nextEntry);
|
|
6286
|
+
savedHistoryFileSummaryCache.set(filePath, nextEntry);
|
|
6287
|
+
return nextEntry;
|
|
6288
|
+
});
|
|
6289
|
+
if (!result) return;
|
|
6290
|
+
if (result.summary?.historySessionId && shouldScheduleSavedHistoryRollupForSignature(result.signature)) {
|
|
6291
|
+
scheduleSavedHistoryRollup(agentType, result.summary.historySessionId);
|
|
6292
|
+
}
|
|
6293
|
+
}
|
|
6294
|
+
function updateSavedHistoryIndexForSessionStart(agentType, dir, file, historySessionId, workspace) {
|
|
6295
|
+
const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId);
|
|
6296
|
+
const normalizedWorkspace = String(workspace || "").trim();
|
|
6297
|
+
if (!normalizedSessionId || !normalizedWorkspace) return;
|
|
6298
|
+
persistSavedHistoryFileSummaryEntry(agentType, dir, file, (currentSummary) => ({
|
|
6299
|
+
file,
|
|
6300
|
+
historySessionId: normalizedSessionId,
|
|
6301
|
+
messageCount: currentSummary?.messageCount || 0,
|
|
6302
|
+
firstMessageAt: currentSummary?.firstMessageAt || 0,
|
|
6303
|
+
lastMessageAt: currentSummary?.lastMessageAt || 0,
|
|
6304
|
+
sessionTitle: currentSummary?.sessionTitle,
|
|
6305
|
+
preview: currentSummary?.preview,
|
|
6306
|
+
workspace: normalizedWorkspace
|
|
6307
|
+
}));
|
|
6308
|
+
}
|
|
6309
|
+
function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, historySessionId, messages) {
|
|
6310
|
+
const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId || "");
|
|
6311
|
+
if (!normalizedSessionId || messages.length === 0) return;
|
|
6312
|
+
persistSavedHistoryFileSummaryEntry(agentType, dir, file, (currentSummary) => {
|
|
6313
|
+
const nextSummary = {
|
|
6314
|
+
file,
|
|
6315
|
+
historySessionId: normalizedSessionId,
|
|
6316
|
+
messageCount: currentSummary?.messageCount || 0,
|
|
6317
|
+
firstMessageAt: currentSummary?.firstMessageAt || 0,
|
|
6318
|
+
lastMessageAt: currentSummary?.lastMessageAt || 0,
|
|
6319
|
+
sessionTitle: currentSummary?.sessionTitle,
|
|
6320
|
+
preview: currentSummary?.preview,
|
|
6321
|
+
workspace: currentSummary?.workspace
|
|
6322
|
+
};
|
|
6323
|
+
for (const message of messages) {
|
|
6324
|
+
if (!message || message.historySessionId !== historySessionId) continue;
|
|
6325
|
+
if (message.kind === "session_start") {
|
|
6326
|
+
if (message.workspace) nextSummary.workspace = message.workspace;
|
|
6327
|
+
continue;
|
|
6328
|
+
}
|
|
6329
|
+
nextSummary.messageCount += 1;
|
|
6330
|
+
if (!nextSummary.firstMessageAt || message.receivedAt < nextSummary.firstMessageAt) {
|
|
6331
|
+
nextSummary.firstMessageAt = message.receivedAt;
|
|
6332
|
+
}
|
|
6333
|
+
if (!nextSummary.lastMessageAt || message.receivedAt >= nextSummary.lastMessageAt) {
|
|
6334
|
+
nextSummary.lastMessageAt = message.receivedAt;
|
|
6335
|
+
if (message.sessionTitle) nextSummary.sessionTitle = message.sessionTitle;
|
|
6336
|
+
if (message.role !== "system" && message.content.trim()) nextSummary.preview = message.content.trim();
|
|
6337
|
+
} else if (message.sessionTitle) {
|
|
6338
|
+
nextSummary.sessionTitle = message.sessionTitle;
|
|
6339
|
+
}
|
|
6340
|
+
if (!nextSummary.preview && message.role !== "system" && message.content.trim()) {
|
|
6341
|
+
nextSummary.preview = message.content.trim();
|
|
6342
|
+
}
|
|
6343
|
+
}
|
|
6344
|
+
return nextSummary;
|
|
6345
|
+
});
|
|
6346
|
+
}
|
|
6347
|
+
function computeSavedHistoryFileSummary(agentType, dir, file) {
|
|
6348
|
+
const historySessionId = extractSavedHistorySessionIdFromFile(agentType, file);
|
|
6349
|
+
if (!historySessionId) return null;
|
|
6350
|
+
const filePath = path7.join(dir, file);
|
|
6351
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
6352
|
+
const lines = content.split("\n").filter(Boolean);
|
|
6353
|
+
let messageCount = 0;
|
|
6354
|
+
let firstMessageAt = 0;
|
|
6355
|
+
let lastMessageAt = 0;
|
|
6356
|
+
let sessionTitle = "";
|
|
6357
|
+
let preview = "";
|
|
6358
|
+
let workspace = "";
|
|
6359
|
+
for (const line of lines) {
|
|
6360
|
+
let parsed = null;
|
|
6361
|
+
try {
|
|
6362
|
+
parsed = JSON.parse(line);
|
|
6363
|
+
} catch {
|
|
6364
|
+
parsed = null;
|
|
6365
|
+
}
|
|
6366
|
+
if (!parsed || parsed.historySessionId !== historySessionId) continue;
|
|
6367
|
+
if (parsed.kind === "session_start") {
|
|
6368
|
+
if (!workspace && parsed.workspace) workspace = parsed.workspace;
|
|
6369
|
+
continue;
|
|
6370
|
+
}
|
|
6371
|
+
messageCount += 1;
|
|
6372
|
+
if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
|
|
6373
|
+
if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
|
|
6374
|
+
if (parsed.sessionTitle) sessionTitle = parsed.sessionTitle;
|
|
6375
|
+
if (parsed.role !== "system" && parsed.content.trim()) preview = parsed.content.trim();
|
|
6376
|
+
}
|
|
6377
|
+
if (messageCount === 0 || !lastMessageAt) return null;
|
|
6378
|
+
return {
|
|
6379
|
+
file,
|
|
6380
|
+
historySessionId,
|
|
6381
|
+
messageCount,
|
|
6382
|
+
firstMessageAt,
|
|
6383
|
+
lastMessageAt,
|
|
6384
|
+
sessionTitle: sessionTitle || void 0,
|
|
6385
|
+
preview: preview || void 0,
|
|
6386
|
+
workspace: workspace || void 0
|
|
6387
|
+
};
|
|
6388
|
+
}
|
|
6389
|
+
function shouldScheduleSavedHistoryRollupForSignature(signature) {
|
|
6390
|
+
const parts = String(signature || "").split(":");
|
|
6391
|
+
const size = Number(parts[1] || 0);
|
|
6392
|
+
return shouldScheduleSavedHistoryRollup(size);
|
|
6393
|
+
}
|
|
6394
|
+
function scheduleSavedHistoryRollup(agentType, historySessionId) {
|
|
6395
|
+
const key = `${agentType}:${historySessionId}`;
|
|
6396
|
+
if (!historySessionId || savedHistoryRollupInFlight.has(key)) return;
|
|
6397
|
+
savedHistoryRollupInFlight.add(key);
|
|
6398
|
+
setTimeout(() => {
|
|
6399
|
+
try {
|
|
6400
|
+
new ChatHistoryWriter().compactHistorySession(agentType, historySessionId);
|
|
6401
|
+
} finally {
|
|
6402
|
+
savedHistoryRollupInFlight.delete(key);
|
|
6403
|
+
}
|
|
6404
|
+
}, 0);
|
|
6405
|
+
}
|
|
6406
|
+
function scheduleSavedHistoryBackgroundRefresh(agentType, dir) {
|
|
6407
|
+
const key = `${agentType}:${dir}`;
|
|
6408
|
+
if (savedHistoryBackgroundRefresh.has(key)) return;
|
|
6409
|
+
savedHistoryBackgroundRefresh.add(key);
|
|
6410
|
+
setTimeout(() => {
|
|
6411
|
+
try {
|
|
6412
|
+
if (!fs3.existsSync(dir)) return;
|
|
6413
|
+
const files = listHistoryFiles(dir);
|
|
6414
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
6415
|
+
const persistedEntries = loadPersistedSavedHistoryIndex(dir);
|
|
6416
|
+
const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
|
|
6417
|
+
savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
|
|
6418
|
+
const refreshedIndexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
6419
|
+
savedHistorySessionCache.set(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"), {
|
|
6420
|
+
signature: refreshedIndexSignature,
|
|
6421
|
+
summaries: computed.summaries || []
|
|
6422
|
+
});
|
|
6423
|
+
for (const [file, entry] of Array.from(computed.persistedEntries.entries())) {
|
|
6424
|
+
if (!entry?.summary || !shouldScheduleSavedHistoryRollupForSignature(entry.signature)) continue;
|
|
6425
|
+
scheduleSavedHistoryRollup(agentType, entry.summary.historySessionId);
|
|
6426
|
+
}
|
|
6427
|
+
} catch {
|
|
6428
|
+
} finally {
|
|
6429
|
+
savedHistoryBackgroundRefresh.delete(key);
|
|
6430
|
+
}
|
|
6431
|
+
}, 0);
|
|
6432
|
+
}
|
|
6433
|
+
function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries) {
|
|
6434
|
+
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
6435
|
+
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
6436
|
+
for (const file of files.slice().sort()) {
|
|
6437
|
+
const filePath = path7.join(dir, file);
|
|
6438
|
+
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
6439
|
+
const cached = savedHistoryFileSummaryCache.get(filePath);
|
|
6440
|
+
const persisted = persistedEntries.get(file);
|
|
6441
|
+
const reusableEntry = cached?.signature === signature ? cached : persisted?.signature === signature ? persisted : null;
|
|
6442
|
+
const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(agentType, dir, file);
|
|
6443
|
+
const nextEntry = reusableEntry || {
|
|
6444
|
+
signature,
|
|
6445
|
+
summary: fileSummary
|
|
6446
|
+
};
|
|
6447
|
+
if (!reusableEntry) {
|
|
6448
|
+
nextEntry.signature = signature;
|
|
6449
|
+
nextEntry.summary = fileSummary;
|
|
6450
|
+
}
|
|
6451
|
+
savedHistoryFileSummaryCache.set(filePath, nextEntry);
|
|
6452
|
+
nextPersistedEntries.set(file, nextEntry);
|
|
6453
|
+
if (!fileSummary) continue;
|
|
6454
|
+
const existing = summaryBySessionId.get(fileSummary.historySessionId);
|
|
6455
|
+
if (fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) {
|
|
6456
|
+
continue;
|
|
6457
|
+
}
|
|
6458
|
+
if (!existing) {
|
|
6459
|
+
summaryBySessionId.set(fileSummary.historySessionId, {
|
|
6460
|
+
historySessionId: fileSummary.historySessionId,
|
|
6461
|
+
sessionTitle: fileSummary.sessionTitle,
|
|
6462
|
+
messageCount: fileSummary.messageCount,
|
|
6463
|
+
firstMessageAt: fileSummary.firstMessageAt,
|
|
6464
|
+
lastMessageAt: fileSummary.lastMessageAt,
|
|
6465
|
+
preview: fileSummary.preview,
|
|
6466
|
+
workspace: fileSummary.workspace
|
|
6467
|
+
});
|
|
6468
|
+
continue;
|
|
6469
|
+
}
|
|
6470
|
+
existing.messageCount += fileSummary.messageCount;
|
|
6471
|
+
if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
|
|
6472
|
+
existing.firstMessageAt = fileSummary.firstMessageAt;
|
|
6473
|
+
}
|
|
6474
|
+
if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
|
|
6475
|
+
existing.lastMessageAt = fileSummary.lastMessageAt;
|
|
6476
|
+
if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
|
|
6477
|
+
if (fileSummary.preview) existing.preview = fileSummary.preview;
|
|
6478
|
+
}
|
|
6479
|
+
if (!existing.workspace && fileSummary.workspace) {
|
|
6480
|
+
existing.workspace = fileSummary.workspace;
|
|
6481
|
+
}
|
|
6061
6482
|
}
|
|
6062
|
-
|
|
6063
|
-
|
|
6483
|
+
return {
|
|
6484
|
+
summaries: Array.from(summaryBySessionId.values()).sort((a, b) => b.lastMessageAt - a.lastMessageAt),
|
|
6485
|
+
persistedEntries: nextPersistedEntries
|
|
6486
|
+
};
|
|
6064
6487
|
}
|
|
6065
6488
|
var ChatHistoryWriter = class {
|
|
6066
6489
|
/** Last seen message count per agent (deduplication) */
|
|
@@ -6135,9 +6558,11 @@ var ChatHistoryWriter = class {
|
|
|
6135
6558
|
fs3.mkdirSync(dir, { recursive: true });
|
|
6136
6559
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
6137
6560
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
6138
|
-
const
|
|
6561
|
+
const fileName = `${filePrefix}${date}.jsonl`;
|
|
6562
|
+
const filePath = path7.join(dir, fileName);
|
|
6139
6563
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
6140
6564
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
6565
|
+
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
6141
6566
|
const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
|
|
6142
6567
|
if (!historySessionId && messages.length < prevCount * 0.5 && prevCount > 3) {
|
|
6143
6568
|
seenHashes.clear();
|
|
@@ -6228,7 +6653,8 @@ var ChatHistoryWriter = class {
|
|
|
6228
6653
|
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
6229
6654
|
fs3.mkdirSync(dir, { recursive: true });
|
|
6230
6655
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
6231
|
-
const
|
|
6656
|
+
const fileName = `${this.sanitize(id)}_${date}.jsonl`;
|
|
6657
|
+
const filePath = path7.join(dir, fileName);
|
|
6232
6658
|
const record = {
|
|
6233
6659
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6234
6660
|
receivedAt: Date.now(),
|
|
@@ -6241,6 +6667,7 @@ var ChatHistoryWriter = class {
|
|
|
6241
6667
|
workspace: ws
|
|
6242
6668
|
};
|
|
6243
6669
|
fs3.appendFileSync(filePath, JSON.stringify(record) + "\n", "utf-8");
|
|
6670
|
+
updateSavedHistoryIndexForSessionStart(agentType, dir, fileName, id, ws);
|
|
6244
6671
|
} catch {
|
|
6245
6672
|
}
|
|
6246
6673
|
}
|
|
@@ -6306,6 +6733,7 @@ var ChatHistoryWriter = class {
|
|
|
6306
6733
|
}
|
|
6307
6734
|
fs3.unlinkSync(sourcePath);
|
|
6308
6735
|
}
|
|
6736
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
6309
6737
|
} catch {
|
|
6310
6738
|
}
|
|
6311
6739
|
}
|
|
@@ -6355,6 +6783,7 @@ var ChatHistoryWriter = class {
|
|
|
6355
6783
|
fs3.writeFileSync(filePath, `${collapsed.map((entry) => JSON.stringify(entry)).join("\n")}
|
|
6356
6784
|
`, "utf-8");
|
|
6357
6785
|
}
|
|
6786
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
6358
6787
|
} catch {
|
|
6359
6788
|
}
|
|
6360
6789
|
}
|
|
@@ -6374,13 +6803,18 @@ var ChatHistoryWriter = class {
|
|
|
6374
6803
|
for (const dir of agentDirs) {
|
|
6375
6804
|
const dirPath = path7.join(HISTORY_DIR, dir.name);
|
|
6376
6805
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
6806
|
+
let removedAny = false;
|
|
6377
6807
|
for (const file of files) {
|
|
6378
6808
|
const filePath = path7.join(dirPath, file);
|
|
6379
6809
|
const stat = fs3.statSync(filePath);
|
|
6380
6810
|
if (stat.mtimeMs < cutoff) {
|
|
6381
6811
|
fs3.unlinkSync(filePath);
|
|
6812
|
+
removedAny = true;
|
|
6382
6813
|
}
|
|
6383
6814
|
}
|
|
6815
|
+
if (removedAny) {
|
|
6816
|
+
invalidatePersistedSavedHistoryIndex(dir.name, dirPath);
|
|
6817
|
+
}
|
|
6384
6818
|
}
|
|
6385
6819
|
} catch {
|
|
6386
6820
|
}
|
|
@@ -6446,18 +6880,51 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
6446
6880
|
savedHistorySessionCache.delete(sanitized);
|
|
6447
6881
|
return { sessions: [], hasMore: false };
|
|
6448
6882
|
}
|
|
6449
|
-
const files = listHistoryFiles(dir);
|
|
6450
|
-
const signature = buildSavedHistoryCacheSignature(dir, files);
|
|
6451
6883
|
const cached = savedHistorySessionCache.get(sanitized);
|
|
6452
|
-
const
|
|
6453
|
-
|
|
6884
|
+
const offset = Math.max(0, options.offset || 0);
|
|
6885
|
+
const limit = Math.max(1, options.limit || 30);
|
|
6886
|
+
const indexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
6887
|
+
let cacheWasInvalidated = false;
|
|
6888
|
+
if (cached) {
|
|
6889
|
+
const cacheLooksPersisted = cached.signature.startsWith("index:");
|
|
6890
|
+
const cacheStillValid = cacheLooksPersisted ? cached.signature === indexSignature : (() => {
|
|
6891
|
+
const files2 = listHistoryFiles(dir);
|
|
6892
|
+
const fileSignatures2 = buildSavedHistoryFileSignatureMap(dir, files2);
|
|
6893
|
+
return cached.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
|
|
6894
|
+
})();
|
|
6895
|
+
if (cacheStillValid) {
|
|
6896
|
+
const sliced2 = cached.summaries.slice(offset, offset + limit);
|
|
6897
|
+
return {
|
|
6898
|
+
sessions: sliced2,
|
|
6899
|
+
hasMore: cached.summaries.length > offset + limit
|
|
6900
|
+
};
|
|
6901
|
+
}
|
|
6902
|
+
cacheWasInvalidated = true;
|
|
6903
|
+
}
|
|
6904
|
+
const persistedSessions = readPersistedSavedHistorySessionSummaries(dir);
|
|
6905
|
+
if (!cacheWasInvalidated && persistedSessions?.length && !historyDirectoryHasFilesNewerThanIndex(dir)) {
|
|
6454
6906
|
savedHistorySessionCache.set(sanitized, {
|
|
6455
|
-
signature,
|
|
6456
|
-
summaries
|
|
6907
|
+
signature: indexSignature,
|
|
6908
|
+
summaries: persistedSessions
|
|
6457
6909
|
});
|
|
6910
|
+
scheduleSavedHistoryBackgroundRefresh(agentType, dir);
|
|
6911
|
+
const sliced2 = persistedSessions.slice(offset, offset + limit);
|
|
6912
|
+
return {
|
|
6913
|
+
sessions: sliced2,
|
|
6914
|
+
hasMore: persistedSessions.length > offset + limit
|
|
6915
|
+
};
|
|
6458
6916
|
}
|
|
6459
|
-
const
|
|
6460
|
-
const
|
|
6917
|
+
const files = listHistoryFiles(dir);
|
|
6918
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
6919
|
+
const signature = buildSavedHistoryCacheSignature(files, fileSignatures);
|
|
6920
|
+
const persistedEntries = loadPersistedSavedHistoryIndex(dir);
|
|
6921
|
+
const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
|
|
6922
|
+
const summaries = computed.summaries || [];
|
|
6923
|
+
savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
|
|
6924
|
+
savedHistorySessionCache.set(sanitized, {
|
|
6925
|
+
signature,
|
|
6926
|
+
summaries
|
|
6927
|
+
});
|
|
6461
6928
|
const sliced = summaries.slice(offset, offset + limit);
|
|
6462
6929
|
return {
|
|
6463
6930
|
sessions: sliced,
|
|
@@ -8210,6 +8677,21 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
8210
8677
|
lastUpdated: ext.lastUpdated
|
|
8211
8678
|
};
|
|
8212
8679
|
}
|
|
8680
|
+
function shouldIncludeExtensionSession(ext) {
|
|
8681
|
+
const status = String(ext.status || "").trim().toLowerCase();
|
|
8682
|
+
const hasActiveChat = !!ext.activeChat;
|
|
8683
|
+
const hasMessages = Array.isArray(ext.activeChat?.messages) && ext.activeChat.messages.length > 0;
|
|
8684
|
+
const hasModal = !!ext.activeChat?.activeModal;
|
|
8685
|
+
const hasStreams = Array.isArray(ext.agentStreams) && ext.agentStreams.length > 0;
|
|
8686
|
+
const hasProviderSessionId = typeof ext.providerSessionId === "string" && ext.providerSessionId.trim().length > 0;
|
|
8687
|
+
const hasControlValues = !!(ext.controlValues && Object.keys(ext.controlValues).length > 0);
|
|
8688
|
+
const hasProviderControls = Array.isArray(ext.providerControls) && ext.providerControls.length > 0;
|
|
8689
|
+
const hasOpenPanelCapability = Array.isArray(ext.sessionCapabilities) && ext.sessionCapabilities.includes("open_panel");
|
|
8690
|
+
const hasSummaryMetadata = !!ext.summaryMetadata;
|
|
8691
|
+
const hasError = typeof ext.errorMessage === "string" && ext.errorMessage.trim().length > 0;
|
|
8692
|
+
const hasInterestingStatus = !!status && !["idle", "panel_hidden", "disconnected", "not_monitored"].includes(status);
|
|
8693
|
+
return hasActiveChat || hasMessages || hasModal || hasStreams || hasProviderSessionId || hasControlValues || hasProviderControls || hasOpenPanelCapability || hasSummaryMetadata || hasError || hasInterestingStatus;
|
|
8694
|
+
}
|
|
8213
8695
|
function buildCliSession(state, options) {
|
|
8214
8696
|
const profile = options.profile || "full";
|
|
8215
8697
|
const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
|
|
@@ -8293,6 +8775,7 @@ function buildSessionEntries(allStates, cdpManagers, options = {}) {
|
|
|
8293
8775
|
for (const state of ideStates) {
|
|
8294
8776
|
sessions.push(buildIdeWorkspaceSession(state, cdpManagers, options));
|
|
8295
8777
|
for (const ext of state.extensions) {
|
|
8778
|
+
if (!shouldIncludeExtensionSession(ext)) continue;
|
|
8296
8779
|
sessions.push(buildExtensionAgentSession(state, ext, options));
|
|
8297
8780
|
}
|
|
8298
8781
|
}
|
|
@@ -10463,7 +10946,9 @@ function applyProviderPatch(h, args, payload) {
|
|
|
10463
10946
|
});
|
|
10464
10947
|
}
|
|
10465
10948
|
async function executeProviderScript(h, args, scriptName) {
|
|
10466
|
-
const
|
|
10949
|
+
const explicitTargetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
10950
|
+
const targetSession = explicitTargetSessionId ? h.ctx.sessionRegistry?.get(explicitTargetSessionId) : void 0;
|
|
10951
|
+
const resolvedProviderType = targetSession?.providerType || h.currentSession?.providerType || h.currentProviderType || args?.agentType || args?.providerType;
|
|
10467
10952
|
if (!resolvedProviderType) return { success: false, error: "targetSessionId or providerType is required" };
|
|
10468
10953
|
const loader = h.ctx.providerLoader;
|
|
10469
10954
|
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
@@ -10506,16 +10991,16 @@ async function executeProviderScript(h, args, scriptName) {
|
|
|
10506
10991
|
const scriptFn = provider.scripts[actualScriptName];
|
|
10507
10992
|
const scriptCode = scriptFn(normalizedArgs);
|
|
10508
10993
|
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
10509
|
-
const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : h.currentSession?.cdpManagerKey || h.currentManagerKey;
|
|
10994
|
+
const cdpKey = provider.category === "ide" ? targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey;
|
|
10510
10995
|
LOG.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
|
|
10511
10996
|
const cdp = h.getCdp(cdpKey);
|
|
10512
10997
|
if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
|
|
10513
10998
|
try {
|
|
10514
10999
|
let result;
|
|
10515
11000
|
if (provider.category === "extension") {
|
|
10516
|
-
const runtimeSessionId = h.currentSession?.sessionId
|
|
11001
|
+
const runtimeSessionId = explicitTargetSessionId || h.currentSession?.sessionId;
|
|
10517
11002
|
if (!runtimeSessionId) return { success: false, error: `No target session found for ${resolvedProviderType}` };
|
|
10518
|
-
const parentSessionId = h.currentSession?.parentSessionId;
|
|
11003
|
+
const parentSessionId = targetSession?.parentSessionId || h.currentSession?.parentSessionId;
|
|
10519
11004
|
if (parentSessionId) {
|
|
10520
11005
|
await h.agentStream?.setActiveSession(cdp, parentSessionId, runtimeSessionId);
|
|
10521
11006
|
await h.agentStream?.syncActiveSession(cdp, parentSessionId);
|
|
@@ -17443,6 +17928,23 @@ function prepareSessionModalUpdate(input) {
|
|
|
17443
17928
|
};
|
|
17444
17929
|
}
|
|
17445
17930
|
|
|
17931
|
+
// src/chat/async-batch.ts
|
|
17932
|
+
async function runAsyncBatch(items, worker, options = {}) {
|
|
17933
|
+
const list = Array.from(items);
|
|
17934
|
+
if (list.length === 0) return;
|
|
17935
|
+
const concurrency = Math.max(1, Math.min(list.length, Math.floor(options.concurrency || 1)));
|
|
17936
|
+
let nextIndex = 0;
|
|
17937
|
+
const runners = Array.from({ length: concurrency }, async () => {
|
|
17938
|
+
while (true) {
|
|
17939
|
+
const currentIndex = nextIndex;
|
|
17940
|
+
nextIndex += 1;
|
|
17941
|
+
if (currentIndex >= list.length) return;
|
|
17942
|
+
await worker(list[currentIndex], currentIndex);
|
|
17943
|
+
}
|
|
17944
|
+
});
|
|
17945
|
+
await Promise.all(runners);
|
|
17946
|
+
}
|
|
17947
|
+
|
|
17446
17948
|
// src/agent-stream/provider-adapter.ts
|
|
17447
17949
|
init_read_chat_contract();
|
|
17448
17950
|
init_chat_message_normalization();
|
|
@@ -17911,10 +18413,12 @@ var DaemonAgentStreamManager = class {
|
|
|
17911
18413
|
}
|
|
17912
18414
|
}
|
|
17913
18415
|
/** Collect active extension session state */
|
|
17914
|
-
async collectActiveSession(cdp, parentSessionId) {
|
|
18416
|
+
async collectActiveSession(cdp, parentSessionId, attemptedSessionIds = /* @__PURE__ */ new Set(), originSessionId) {
|
|
17915
18417
|
if (!this.enabled) return null;
|
|
17916
18418
|
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
17917
18419
|
if (!activeSessionId) return null;
|
|
18420
|
+
const resolvedOriginSessionId = originSessionId || activeSessionId;
|
|
18421
|
+
attemptedSessionIds.add(activeSessionId);
|
|
17918
18422
|
let agent = this.managedBySessionId.get(activeSessionId);
|
|
17919
18423
|
if (!agent) {
|
|
17920
18424
|
agent = await this.connectManagedSession(cdp, parentSessionId, activeSessionId) || void 0;
|
|
@@ -17927,18 +18431,44 @@ var DaemonAgentStreamManager = class {
|
|
|
17927
18431
|
try {
|
|
17928
18432
|
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
17929
18433
|
const state = await agent.adapter.readChat(evaluate);
|
|
17930
|
-
const
|
|
17931
|
-
const
|
|
17932
|
-
|
|
17933
|
-
|
|
18434
|
+
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;
|
|
18435
|
+
const normalizedState = {
|
|
18436
|
+
...state,
|
|
18437
|
+
sessionId: agent.runtimeSessionId,
|
|
18438
|
+
...resolvedProviderSessionId ? { providerSessionId: resolvedProviderSessionId } : {}
|
|
18439
|
+
};
|
|
18440
|
+
const stateError = this.getStateError(normalizedState);
|
|
18441
|
+
const selectedModelValue = typeof normalizedState.controlValues?.model === "string" ? normalizedState.controlValues.model : "";
|
|
18442
|
+
LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${normalizedState.status} msgs=${normalizedState.messages?.length || 0} model=${selectedModelValue}${normalizedState.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
|
|
18443
|
+
if (normalizedState.status === "error" && this.isRecoverableSessionError(stateError)) {
|
|
17934
18444
|
throw new Error(stateError);
|
|
17935
18445
|
}
|
|
17936
|
-
agent.lastState =
|
|
18446
|
+
agent.lastState = normalizedState;
|
|
17937
18447
|
agent.lastError = null;
|
|
17938
|
-
if (
|
|
18448
|
+
if (normalizedState.status === "panel_hidden") {
|
|
18449
|
+
const discovered = await cdp.discoverAgentWebviews().catch(() => []);
|
|
18450
|
+
const fallbackTarget = discovered.find((entry) => {
|
|
18451
|
+
if (entry.agentType === type) return false;
|
|
18452
|
+
const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, entry.agentType);
|
|
18453
|
+
return !!fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId);
|
|
18454
|
+
});
|
|
18455
|
+
if (fallbackTarget) {
|
|
18456
|
+
const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, fallbackTarget.agentType);
|
|
18457
|
+
if (fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId)) {
|
|
18458
|
+
this.logFn(`[AgentStream] Active session ${type} is hidden; switching to visible agent ${fallbackTarget.agentType} (${parentSessionId})`);
|
|
18459
|
+
await this.setActiveSession(cdp, parentSessionId, fallbackSessionId);
|
|
18460
|
+
await this.syncActiveSession(cdp, parentSessionId);
|
|
18461
|
+
const fallbackState = await this.collectActiveSession(cdp, parentSessionId, attemptedSessionIds, resolvedOriginSessionId);
|
|
18462
|
+
if (fallbackState?.status === "panel_hidden" && resolvedOriginSessionId !== fallbackSessionId) {
|
|
18463
|
+
await this.setActiveSession(cdp, parentSessionId, resolvedOriginSessionId);
|
|
18464
|
+
await this.syncActiveSession(cdp, parentSessionId);
|
|
18465
|
+
}
|
|
18466
|
+
return fallbackState;
|
|
18467
|
+
}
|
|
18468
|
+
}
|
|
17939
18469
|
agent.lastHiddenCheckTime = Date.now();
|
|
17940
18470
|
}
|
|
17941
|
-
return
|
|
18471
|
+
return normalizedState;
|
|
17942
18472
|
} catch (e) {
|
|
17943
18473
|
const errorMsg = e?.message || String(e);
|
|
17944
18474
|
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
@@ -18234,6 +18764,7 @@ var AgentStreamPoller = class {
|
|
|
18234
18764
|
try {
|
|
18235
18765
|
await agentStreamManager.syncActiveSession(cdp, parentSessionId);
|
|
18236
18766
|
let stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
|
|
18767
|
+
resolvedActiveSessionId = stream?.sessionId || agentStreamManager.getActiveSessionId(parentSessionId) || resolvedActiveSessionId;
|
|
18237
18768
|
if (stream?.status === "waiting_approval") {
|
|
18238
18769
|
const autoApprove = providerLoader.getSettings(stream.agentType).autoApprove !== false;
|
|
18239
18770
|
if (autoApprove && resolvedActiveSessionId) {
|
|
@@ -24943,6 +25474,7 @@ export {
|
|
|
24943
25474
|
resolveChatMessageKind,
|
|
24944
25475
|
resolveDebugRuntimeConfig,
|
|
24945
25476
|
resolveSessionHostAppName,
|
|
25477
|
+
runAsyncBatch,
|
|
24946
25478
|
saveConfig,
|
|
24947
25479
|
saveState,
|
|
24948
25480
|
setDebugRuntimeConfig,
|