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/index.js
CHANGED
|
@@ -1287,6 +1287,32 @@ var init_logger = __esm({
|
|
|
1287
1287
|
});
|
|
1288
1288
|
|
|
1289
1289
|
// ../../oss/packages/daemon-core/src/cdp/manager.ts
|
|
1290
|
+
function normalizeTitle(value) {
|
|
1291
|
+
return String(value || "").trim().replace(/\s+/g, " ").toLowerCase();
|
|
1292
|
+
}
|
|
1293
|
+
function titlesMatch(lhs, rhs) {
|
|
1294
|
+
const a = normalizeTitle(lhs);
|
|
1295
|
+
const b = normalizeTitle(rhs);
|
|
1296
|
+
if (!a || !b) return false;
|
|
1297
|
+
return a === b || a.includes(b) || b.includes(a);
|
|
1298
|
+
}
|
|
1299
|
+
function resolveCdpPageTarget(params) {
|
|
1300
|
+
const { pages, pinnedTargetId, previousPageTitle } = params;
|
|
1301
|
+
if (pages.length === 0) return { target: null, retargeted: false };
|
|
1302
|
+
if (!pinnedTargetId) {
|
|
1303
|
+
return { target: pages[0] || null, retargeted: false };
|
|
1304
|
+
}
|
|
1305
|
+
const exact = pages.find((page) => page.id === pinnedTargetId);
|
|
1306
|
+
if (exact) return { target: exact, retargeted: false };
|
|
1307
|
+
const titleMatchesList = pages.filter((page) => titlesMatch(page.title, previousPageTitle));
|
|
1308
|
+
if (titleMatchesList.length === 1) {
|
|
1309
|
+
return { target: titleMatchesList[0], retargeted: true };
|
|
1310
|
+
}
|
|
1311
|
+
if (pages.length === 1) {
|
|
1312
|
+
return { target: pages[0], retargeted: true };
|
|
1313
|
+
}
|
|
1314
|
+
return { target: null, retargeted: false };
|
|
1315
|
+
}
|
|
1290
1316
|
var import_ws, http, DaemonCdpManager;
|
|
1291
1317
|
var init_manager = __esm({
|
|
1292
1318
|
"../../oss/packages/daemon-core/src/cdp/manager.ts"() {
|
|
@@ -1454,18 +1480,28 @@ var init_manager = __esm({
|
|
|
1454
1480
|
resolve15(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
1455
1481
|
return;
|
|
1456
1482
|
}
|
|
1457
|
-
const
|
|
1458
|
-
const
|
|
1483
|
+
const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
1484
|
+
const mainPages = titleFilteredPages.filter((t) => this.isMainPageUrl(t.url));
|
|
1485
|
+
const list = mainPages.length > 0 ? mainPages : titleFilteredPages.length > 0 ? titleFilteredPages : pages;
|
|
1459
1486
|
this.log(`[CDP] pages(${list.length}): ${list.map((t) => `"${t.title}"`).join(", ")}`);
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1487
|
+
const previousTargetId = this._targetId;
|
|
1488
|
+
const selected = resolveCdpPageTarget({
|
|
1489
|
+
pages: list,
|
|
1490
|
+
pinnedTargetId: previousTargetId,
|
|
1491
|
+
previousPageTitle: this._pageTitle
|
|
1492
|
+
});
|
|
1493
|
+
if (selected.target) {
|
|
1494
|
+
if (selected.retargeted && previousTargetId && previousTargetId !== selected.target.id) {
|
|
1495
|
+
this.log(`[CDP] Target ${previousTargetId} rekeyed to ${selected.target.id}`);
|
|
1496
|
+
this._targetId = selected.target.id;
|
|
1468
1497
|
}
|
|
1498
|
+
this._pageTitle = selected.target.title || "";
|
|
1499
|
+
resolve15(selected.target);
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
if (previousTargetId) {
|
|
1503
|
+
this.log(`[CDP] Target ${previousTargetId} not found in page list`);
|
|
1504
|
+
resolve15(null);
|
|
1469
1505
|
return;
|
|
1470
1506
|
}
|
|
1471
1507
|
this._pageTitle = list[0]?.title || "";
|
|
@@ -3342,6 +3378,68 @@ function sanitizeHistoryMessage(agentType, message) {
|
|
|
3342
3378
|
content
|
|
3343
3379
|
};
|
|
3344
3380
|
}
|
|
3381
|
+
function sortSavedHistorySessionSummaries(summaries) {
|
|
3382
|
+
return summaries.slice().sort((a, b) => b.lastMessageAt - a.lastMessageAt);
|
|
3383
|
+
}
|
|
3384
|
+
function buildSavedHistorySessionSummaryMapFromEntries(entries) {
|
|
3385
|
+
const summaries = /* @__PURE__ */ new Map();
|
|
3386
|
+
for (const entry of Array.from(entries.values())) {
|
|
3387
|
+
const fileSummary = entry.summary;
|
|
3388
|
+
if (!fileSummary || fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) continue;
|
|
3389
|
+
const existing = summaries.get(fileSummary.historySessionId);
|
|
3390
|
+
if (!existing) {
|
|
3391
|
+
summaries.set(fileSummary.historySessionId, {
|
|
3392
|
+
historySessionId: fileSummary.historySessionId,
|
|
3393
|
+
sessionTitle: fileSummary.sessionTitle,
|
|
3394
|
+
messageCount: fileSummary.messageCount,
|
|
3395
|
+
firstMessageAt: fileSummary.firstMessageAt,
|
|
3396
|
+
lastMessageAt: fileSummary.lastMessageAt,
|
|
3397
|
+
preview: fileSummary.preview,
|
|
3398
|
+
workspace: fileSummary.workspace
|
|
3399
|
+
});
|
|
3400
|
+
continue;
|
|
3401
|
+
}
|
|
3402
|
+
existing.messageCount += fileSummary.messageCount;
|
|
3403
|
+
if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
|
|
3404
|
+
existing.firstMessageAt = fileSummary.firstMessageAt;
|
|
3405
|
+
}
|
|
3406
|
+
if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
|
|
3407
|
+
existing.lastMessageAt = fileSummary.lastMessageAt;
|
|
3408
|
+
if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
|
|
3409
|
+
if (fileSummary.preview) existing.preview = fileSummary.preview;
|
|
3410
|
+
}
|
|
3411
|
+
if (!existing.workspace && fileSummary.workspace) {
|
|
3412
|
+
existing.workspace = fileSummary.workspace;
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
return Object.fromEntries(sortSavedHistorySessionSummaries(Array.from(summaries.values())).map((summary) => [summary.historySessionId, summary]));
|
|
3416
|
+
}
|
|
3417
|
+
function readPersistedSavedHistorySessionSummaries(dir) {
|
|
3418
|
+
try {
|
|
3419
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
3420
|
+
if (!fs3.existsSync(filePath)) return null;
|
|
3421
|
+
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
3422
|
+
if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.sessions || typeof raw.sessions !== "object") {
|
|
3423
|
+
return null;
|
|
3424
|
+
}
|
|
3425
|
+
return sortSavedHistorySessionSummaries(
|
|
3426
|
+
Object.values(raw.sessions).filter((summary) => !!summary && typeof summary.historySessionId === "string" && summary.messageCount > 0 && summary.lastMessageAt > 0).map((summary) => ({
|
|
3427
|
+
historySessionId: summary.historySessionId,
|
|
3428
|
+
sessionTitle: summary.sessionTitle,
|
|
3429
|
+
messageCount: summary.messageCount,
|
|
3430
|
+
firstMessageAt: summary.firstMessageAt,
|
|
3431
|
+
lastMessageAt: summary.lastMessageAt,
|
|
3432
|
+
preview: summary.preview,
|
|
3433
|
+
workspace: summary.workspace
|
|
3434
|
+
}))
|
|
3435
|
+
);
|
|
3436
|
+
} catch {
|
|
3437
|
+
return null;
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
function shouldScheduleSavedHistoryRollup(totalBytes) {
|
|
3441
|
+
return Number.isFinite(totalBytes) && totalBytes >= SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES;
|
|
3442
|
+
}
|
|
3345
3443
|
function sanitizeHistoryFileSegment(value) {
|
|
3346
3444
|
return String(value || "").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3347
3445
|
}
|
|
@@ -3355,71 +3453,386 @@ function listHistoryFiles(dir, historySessionId) {
|
|
|
3355
3453
|
return true;
|
|
3356
3454
|
}).sort().reverse();
|
|
3357
3455
|
}
|
|
3358
|
-
function
|
|
3359
|
-
|
|
3456
|
+
function normalizeSavedHistorySessionId(agentType, historySessionId) {
|
|
3457
|
+
const normalizedId = String(historySessionId || "").trim();
|
|
3458
|
+
if (!normalizedId) return "";
|
|
3459
|
+
const strictProviderId = normalizeProviderSessionId(agentType, normalizedId);
|
|
3460
|
+
if (strictProviderId) return strictProviderId;
|
|
3461
|
+
return agentType === "hermes-cli" ? "" : normalizedId;
|
|
3462
|
+
}
|
|
3463
|
+
function extractSavedHistorySessionIdFromFile(agentType, file2) {
|
|
3464
|
+
const match = file2.match(/^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/);
|
|
3465
|
+
return normalizeSavedHistorySessionId(agentType, match?.[1] || "");
|
|
3466
|
+
}
|
|
3467
|
+
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
3468
|
+
return new Map(files.map((file2) => {
|
|
3360
3469
|
try {
|
|
3361
3470
|
const stat4 = fs3.statSync(path7.join(dir, file2));
|
|
3362
|
-
return `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}
|
|
3471
|
+
return [file2, `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`];
|
|
3363
3472
|
} catch {
|
|
3364
|
-
return `${file2}:missing
|
|
3365
|
-
}
|
|
3366
|
-
})
|
|
3367
|
-
}
|
|
3368
|
-
function
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3473
|
+
return [file2, `${file2}:missing`];
|
|
3474
|
+
}
|
|
3475
|
+
}));
|
|
3476
|
+
}
|
|
3477
|
+
function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
3478
|
+
return files.map((file2) => fileSignatures.get(file2) || `${file2}:missing`).join("|");
|
|
3479
|
+
}
|
|
3480
|
+
function getSavedHistoryIndexFilePath(dir) {
|
|
3481
|
+
return path7.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
3482
|
+
}
|
|
3483
|
+
function getSavedHistoryIndexLockPath(dir) {
|
|
3484
|
+
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
3485
|
+
}
|
|
3486
|
+
function sleepBlocking(ms) {
|
|
3487
|
+
if (ms <= 0) return;
|
|
3488
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
3489
|
+
}
|
|
3490
|
+
function loadPersistedSavedHistoryIndexFromFile(dir) {
|
|
3491
|
+
try {
|
|
3492
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
3493
|
+
if (!fs3.existsSync(filePath)) return /* @__PURE__ */ new Map();
|
|
3494
|
+
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
3495
|
+
if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.files || typeof raw.files !== "object") {
|
|
3496
|
+
return /* @__PURE__ */ new Map();
|
|
3497
|
+
}
|
|
3498
|
+
return new Map(
|
|
3499
|
+
Object.entries(raw.files).filter(([file2, entry]) => !!file2 && !!entry && typeof entry.signature === "string").map(([file2, entry]) => [file2, {
|
|
3500
|
+
signature: entry.signature,
|
|
3501
|
+
summary: entry.summary || null
|
|
3502
|
+
}])
|
|
3503
|
+
);
|
|
3504
|
+
} catch {
|
|
3505
|
+
return /* @__PURE__ */ new Map();
|
|
3506
|
+
}
|
|
3507
|
+
}
|
|
3508
|
+
function writePersistedSavedHistoryIndexFile(dir, entries) {
|
|
3509
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
3510
|
+
const tempPath = `${filePath}.tmp`;
|
|
3511
|
+
const payload = {
|
|
3512
|
+
version: SAVED_HISTORY_INDEX_VERSION,
|
|
3513
|
+
files: Object.fromEntries(entries.entries()),
|
|
3514
|
+
sessions: buildSavedHistorySessionSummaryMapFromEntries(entries)
|
|
3515
|
+
};
|
|
3516
|
+
fs3.writeFileSync(tempPath, JSON.stringify(payload), "utf-8");
|
|
3517
|
+
fs3.renameSync(tempPath, filePath);
|
|
3518
|
+
}
|
|
3519
|
+
function acquireSavedHistoryIndexLock(dir) {
|
|
3520
|
+
const lockPath = getSavedHistoryIndexLockPath(dir);
|
|
3521
|
+
const deadline = Date.now() + SAVED_HISTORY_INDEX_LOCK_WAIT_MS;
|
|
3522
|
+
while (Date.now() <= deadline) {
|
|
3523
|
+
try {
|
|
3524
|
+
fs3.mkdirSync(lockPath);
|
|
3525
|
+
return () => {
|
|
3393
3526
|
try {
|
|
3394
|
-
|
|
3527
|
+
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
3395
3528
|
} catch {
|
|
3396
|
-
parsed = null;
|
|
3397
3529
|
}
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3530
|
+
};
|
|
3531
|
+
} catch (error48) {
|
|
3532
|
+
if (error48?.code !== "EEXIST") return null;
|
|
3533
|
+
try {
|
|
3534
|
+
const stat4 = fs3.statSync(lockPath);
|
|
3535
|
+
if (Date.now() - stat4.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
|
|
3536
|
+
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
3401
3537
|
continue;
|
|
3402
3538
|
}
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3539
|
+
} catch {
|
|
3540
|
+
continue;
|
|
3541
|
+
}
|
|
3542
|
+
sleepBlocking(SAVED_HISTORY_INDEX_LOCK_POLL_MS);
|
|
3543
|
+
}
|
|
3544
|
+
}
|
|
3545
|
+
return null;
|
|
3546
|
+
}
|
|
3547
|
+
function withLockedPersistedSavedHistoryIndex(dir, callback) {
|
|
3548
|
+
const release2 = acquireSavedHistoryIndexLock(dir);
|
|
3549
|
+
if (!release2) return null;
|
|
3550
|
+
try {
|
|
3551
|
+
const entries = loadPersistedSavedHistoryIndexFromFile(dir);
|
|
3552
|
+
const result = callback(entries);
|
|
3553
|
+
writePersistedSavedHistoryIndexFile(dir, entries);
|
|
3554
|
+
return result;
|
|
3555
|
+
} catch {
|
|
3556
|
+
return null;
|
|
3557
|
+
} finally {
|
|
3558
|
+
release2();
|
|
3559
|
+
}
|
|
3560
|
+
}
|
|
3561
|
+
function loadPersistedSavedHistoryIndex(dir) {
|
|
3562
|
+
return loadPersistedSavedHistoryIndexFromFile(dir);
|
|
3563
|
+
}
|
|
3564
|
+
function savePersistedSavedHistoryIndex(dir, entries) {
|
|
3565
|
+
withLockedPersistedSavedHistoryIndex(dir, (currentEntries) => {
|
|
3566
|
+
const incomingFiles = new Set(Array.from(entries.keys()));
|
|
3567
|
+
for (const [file2, entry] of Array.from(entries.entries())) {
|
|
3568
|
+
const liveSignature = buildSavedHistoryFileSignature(dir, file2);
|
|
3569
|
+
const existingEntry = currentEntries.get(file2);
|
|
3570
|
+
if (existingEntry && existingEntry.signature !== liveSignature && entry.signature !== liveSignature) {
|
|
3571
|
+
continue;
|
|
3572
|
+
}
|
|
3573
|
+
if (entry.signature !== liveSignature && (!existingEntry || existingEntry.signature !== liveSignature)) {
|
|
3574
|
+
continue;
|
|
3575
|
+
}
|
|
3576
|
+
currentEntries.set(file2, entry.signature === liveSignature ? entry : {
|
|
3577
|
+
signature: liveSignature,
|
|
3578
|
+
summary: existingEntry?.summary || entry.summary
|
|
3579
|
+
});
|
|
3580
|
+
}
|
|
3581
|
+
for (const file2 of Array.from(currentEntries.keys())) {
|
|
3582
|
+
if (incomingFiles.has(file2)) continue;
|
|
3583
|
+
if (!fs3.existsSync(path7.join(dir, file2))) {
|
|
3584
|
+
currentEntries.delete(file2);
|
|
3585
|
+
}
|
|
3586
|
+
}
|
|
3587
|
+
});
|
|
3588
|
+
}
|
|
3589
|
+
function invalidatePersistedSavedHistoryIndex(agentType, dir) {
|
|
3590
|
+
try {
|
|
3591
|
+
fs3.rmSync(getSavedHistoryIndexFilePath(dir), { force: true });
|
|
3592
|
+
} catch {
|
|
3593
|
+
}
|
|
3594
|
+
savedHistorySessionCache.delete(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"));
|
|
3595
|
+
}
|
|
3596
|
+
function buildSavedHistoryIndexFileSignature(dir) {
|
|
3597
|
+
try {
|
|
3598
|
+
const stat4 = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
3599
|
+
return `index:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
|
|
3600
|
+
} catch {
|
|
3601
|
+
return "index:missing";
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3604
|
+
function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
3605
|
+
try {
|
|
3606
|
+
const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
3607
|
+
const files = listHistoryFiles(dir);
|
|
3608
|
+
for (const file2 of files) {
|
|
3609
|
+
const stat4 = fs3.statSync(path7.join(dir, file2));
|
|
3610
|
+
if (stat4.mtimeMs > indexStat.mtimeMs) return true;
|
|
3611
|
+
}
|
|
3612
|
+
return false;
|
|
3613
|
+
} catch {
|
|
3614
|
+
return true;
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3617
|
+
function buildSavedHistoryFileSignature(dir, file2) {
|
|
3618
|
+
try {
|
|
3619
|
+
const stat4 = fs3.statSync(path7.join(dir, file2));
|
|
3620
|
+
return `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
|
|
3621
|
+
} catch {
|
|
3622
|
+
return `${file2}:missing`;
|
|
3420
3623
|
}
|
|
3421
|
-
|
|
3422
|
-
|
|
3624
|
+
}
|
|
3625
|
+
function persistSavedHistoryFileSummaryEntry(agentType, dir, file2, updater) {
|
|
3626
|
+
const filePath = path7.join(dir, file2);
|
|
3627
|
+
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
3628
|
+
const currentEntry = entries.get(file2) || null;
|
|
3629
|
+
const nextSummary = updater(currentEntry?.summary || null);
|
|
3630
|
+
const nextEntry = {
|
|
3631
|
+
signature: buildSavedHistoryFileSignature(dir, file2),
|
|
3632
|
+
summary: nextSummary
|
|
3633
|
+
};
|
|
3634
|
+
entries.set(file2, nextEntry);
|
|
3635
|
+
savedHistoryFileSummaryCache.set(filePath, nextEntry);
|
|
3636
|
+
return nextEntry;
|
|
3637
|
+
});
|
|
3638
|
+
if (!result) return;
|
|
3639
|
+
if (result.summary?.historySessionId && shouldScheduleSavedHistoryRollupForSignature(result.signature)) {
|
|
3640
|
+
scheduleSavedHistoryRollup(agentType, result.summary.historySessionId);
|
|
3641
|
+
}
|
|
3642
|
+
}
|
|
3643
|
+
function updateSavedHistoryIndexForSessionStart(agentType, dir, file2, historySessionId, workspace) {
|
|
3644
|
+
const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId);
|
|
3645
|
+
const normalizedWorkspace = String(workspace || "").trim();
|
|
3646
|
+
if (!normalizedSessionId || !normalizedWorkspace) return;
|
|
3647
|
+
persistSavedHistoryFileSummaryEntry(agentType, dir, file2, (currentSummary) => ({
|
|
3648
|
+
file: file2,
|
|
3649
|
+
historySessionId: normalizedSessionId,
|
|
3650
|
+
messageCount: currentSummary?.messageCount || 0,
|
|
3651
|
+
firstMessageAt: currentSummary?.firstMessageAt || 0,
|
|
3652
|
+
lastMessageAt: currentSummary?.lastMessageAt || 0,
|
|
3653
|
+
sessionTitle: currentSummary?.sessionTitle,
|
|
3654
|
+
preview: currentSummary?.preview,
|
|
3655
|
+
workspace: normalizedWorkspace
|
|
3656
|
+
}));
|
|
3657
|
+
}
|
|
3658
|
+
function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file2, historySessionId, messages) {
|
|
3659
|
+
const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId || "");
|
|
3660
|
+
if (!normalizedSessionId || messages.length === 0) return;
|
|
3661
|
+
persistSavedHistoryFileSummaryEntry(agentType, dir, file2, (currentSummary) => {
|
|
3662
|
+
const nextSummary = {
|
|
3663
|
+
file: file2,
|
|
3664
|
+
historySessionId: normalizedSessionId,
|
|
3665
|
+
messageCount: currentSummary?.messageCount || 0,
|
|
3666
|
+
firstMessageAt: currentSummary?.firstMessageAt || 0,
|
|
3667
|
+
lastMessageAt: currentSummary?.lastMessageAt || 0,
|
|
3668
|
+
sessionTitle: currentSummary?.sessionTitle,
|
|
3669
|
+
preview: currentSummary?.preview,
|
|
3670
|
+
workspace: currentSummary?.workspace
|
|
3671
|
+
};
|
|
3672
|
+
for (const message of messages) {
|
|
3673
|
+
if (!message || message.historySessionId !== historySessionId) continue;
|
|
3674
|
+
if (message.kind === "session_start") {
|
|
3675
|
+
if (message.workspace) nextSummary.workspace = message.workspace;
|
|
3676
|
+
continue;
|
|
3677
|
+
}
|
|
3678
|
+
nextSummary.messageCount += 1;
|
|
3679
|
+
if (!nextSummary.firstMessageAt || message.receivedAt < nextSummary.firstMessageAt) {
|
|
3680
|
+
nextSummary.firstMessageAt = message.receivedAt;
|
|
3681
|
+
}
|
|
3682
|
+
if (!nextSummary.lastMessageAt || message.receivedAt >= nextSummary.lastMessageAt) {
|
|
3683
|
+
nextSummary.lastMessageAt = message.receivedAt;
|
|
3684
|
+
if (message.sessionTitle) nextSummary.sessionTitle = message.sessionTitle;
|
|
3685
|
+
if (message.role !== "system" && message.content.trim()) nextSummary.preview = message.content.trim();
|
|
3686
|
+
} else if (message.sessionTitle) {
|
|
3687
|
+
nextSummary.sessionTitle = message.sessionTitle;
|
|
3688
|
+
}
|
|
3689
|
+
if (!nextSummary.preview && message.role !== "system" && message.content.trim()) {
|
|
3690
|
+
nextSummary.preview = message.content.trim();
|
|
3691
|
+
}
|
|
3692
|
+
}
|
|
3693
|
+
return nextSummary;
|
|
3694
|
+
});
|
|
3695
|
+
}
|
|
3696
|
+
function computeSavedHistoryFileSummary(agentType, dir, file2) {
|
|
3697
|
+
const historySessionId = extractSavedHistorySessionIdFromFile(agentType, file2);
|
|
3698
|
+
if (!historySessionId) return null;
|
|
3699
|
+
const filePath = path7.join(dir, file2);
|
|
3700
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
3701
|
+
const lines = content.split("\n").filter(Boolean);
|
|
3702
|
+
let messageCount = 0;
|
|
3703
|
+
let firstMessageAt = 0;
|
|
3704
|
+
let lastMessageAt = 0;
|
|
3705
|
+
let sessionTitle = "";
|
|
3706
|
+
let preview = "";
|
|
3707
|
+
let workspace = "";
|
|
3708
|
+
for (const line of lines) {
|
|
3709
|
+
let parsed = null;
|
|
3710
|
+
try {
|
|
3711
|
+
parsed = JSON.parse(line);
|
|
3712
|
+
} catch {
|
|
3713
|
+
parsed = null;
|
|
3714
|
+
}
|
|
3715
|
+
if (!parsed || parsed.historySessionId !== historySessionId) continue;
|
|
3716
|
+
if (parsed.kind === "session_start") {
|
|
3717
|
+
if (!workspace && parsed.workspace) workspace = parsed.workspace;
|
|
3718
|
+
continue;
|
|
3719
|
+
}
|
|
3720
|
+
messageCount += 1;
|
|
3721
|
+
if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
|
|
3722
|
+
if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
|
|
3723
|
+
if (parsed.sessionTitle) sessionTitle = parsed.sessionTitle;
|
|
3724
|
+
if (parsed.role !== "system" && parsed.content.trim()) preview = parsed.content.trim();
|
|
3725
|
+
}
|
|
3726
|
+
if (messageCount === 0 || !lastMessageAt) return null;
|
|
3727
|
+
return {
|
|
3728
|
+
file: file2,
|
|
3729
|
+
historySessionId,
|
|
3730
|
+
messageCount,
|
|
3731
|
+
firstMessageAt,
|
|
3732
|
+
lastMessageAt,
|
|
3733
|
+
sessionTitle: sessionTitle || void 0,
|
|
3734
|
+
preview: preview || void 0,
|
|
3735
|
+
workspace: workspace || void 0
|
|
3736
|
+
};
|
|
3737
|
+
}
|
|
3738
|
+
function shouldScheduleSavedHistoryRollupForSignature(signature) {
|
|
3739
|
+
const parts = String(signature || "").split(":");
|
|
3740
|
+
const size = Number(parts[1] || 0);
|
|
3741
|
+
return shouldScheduleSavedHistoryRollup(size);
|
|
3742
|
+
}
|
|
3743
|
+
function scheduleSavedHistoryRollup(agentType, historySessionId) {
|
|
3744
|
+
const key = `${agentType}:${historySessionId}`;
|
|
3745
|
+
if (!historySessionId || savedHistoryRollupInFlight.has(key)) return;
|
|
3746
|
+
savedHistoryRollupInFlight.add(key);
|
|
3747
|
+
setTimeout(() => {
|
|
3748
|
+
try {
|
|
3749
|
+
new ChatHistoryWriter().compactHistorySession(agentType, historySessionId);
|
|
3750
|
+
} finally {
|
|
3751
|
+
savedHistoryRollupInFlight.delete(key);
|
|
3752
|
+
}
|
|
3753
|
+
}, 0);
|
|
3754
|
+
}
|
|
3755
|
+
function scheduleSavedHistoryBackgroundRefresh(agentType, dir) {
|
|
3756
|
+
const key = `${agentType}:${dir}`;
|
|
3757
|
+
if (savedHistoryBackgroundRefresh.has(key)) return;
|
|
3758
|
+
savedHistoryBackgroundRefresh.add(key);
|
|
3759
|
+
setTimeout(() => {
|
|
3760
|
+
try {
|
|
3761
|
+
if (!fs3.existsSync(dir)) return;
|
|
3762
|
+
const files = listHistoryFiles(dir);
|
|
3763
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
3764
|
+
const persistedEntries = loadPersistedSavedHistoryIndex(dir);
|
|
3765
|
+
const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
|
|
3766
|
+
savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
|
|
3767
|
+
const refreshedIndexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
3768
|
+
savedHistorySessionCache.set(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"), {
|
|
3769
|
+
signature: refreshedIndexSignature,
|
|
3770
|
+
summaries: computed.summaries || []
|
|
3771
|
+
});
|
|
3772
|
+
for (const [file2, entry] of Array.from(computed.persistedEntries.entries())) {
|
|
3773
|
+
if (!entry?.summary || !shouldScheduleSavedHistoryRollupForSignature(entry.signature)) continue;
|
|
3774
|
+
scheduleSavedHistoryRollup(agentType, entry.summary.historySessionId);
|
|
3775
|
+
}
|
|
3776
|
+
} catch {
|
|
3777
|
+
} finally {
|
|
3778
|
+
savedHistoryBackgroundRefresh.delete(key);
|
|
3779
|
+
}
|
|
3780
|
+
}, 0);
|
|
3781
|
+
}
|
|
3782
|
+
function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries) {
|
|
3783
|
+
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
3784
|
+
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
3785
|
+
for (const file2 of files.slice().sort()) {
|
|
3786
|
+
const filePath = path7.join(dir, file2);
|
|
3787
|
+
const signature = fileSignatures.get(file2) || `${file2}:missing`;
|
|
3788
|
+
const cached2 = savedHistoryFileSummaryCache.get(filePath);
|
|
3789
|
+
const persisted = persistedEntries.get(file2);
|
|
3790
|
+
const reusableEntry = cached2?.signature === signature ? cached2 : persisted?.signature === signature ? persisted : null;
|
|
3791
|
+
const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(agentType, dir, file2);
|
|
3792
|
+
const nextEntry = reusableEntry || {
|
|
3793
|
+
signature,
|
|
3794
|
+
summary: fileSummary
|
|
3795
|
+
};
|
|
3796
|
+
if (!reusableEntry) {
|
|
3797
|
+
nextEntry.signature = signature;
|
|
3798
|
+
nextEntry.summary = fileSummary;
|
|
3799
|
+
}
|
|
3800
|
+
savedHistoryFileSummaryCache.set(filePath, nextEntry);
|
|
3801
|
+
nextPersistedEntries.set(file2, nextEntry);
|
|
3802
|
+
if (!fileSummary) continue;
|
|
3803
|
+
const existing = summaryBySessionId.get(fileSummary.historySessionId);
|
|
3804
|
+
if (fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) {
|
|
3805
|
+
continue;
|
|
3806
|
+
}
|
|
3807
|
+
if (!existing) {
|
|
3808
|
+
summaryBySessionId.set(fileSummary.historySessionId, {
|
|
3809
|
+
historySessionId: fileSummary.historySessionId,
|
|
3810
|
+
sessionTitle: fileSummary.sessionTitle,
|
|
3811
|
+
messageCount: fileSummary.messageCount,
|
|
3812
|
+
firstMessageAt: fileSummary.firstMessageAt,
|
|
3813
|
+
lastMessageAt: fileSummary.lastMessageAt,
|
|
3814
|
+
preview: fileSummary.preview,
|
|
3815
|
+
workspace: fileSummary.workspace
|
|
3816
|
+
});
|
|
3817
|
+
continue;
|
|
3818
|
+
}
|
|
3819
|
+
existing.messageCount += fileSummary.messageCount;
|
|
3820
|
+
if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
|
|
3821
|
+
existing.firstMessageAt = fileSummary.firstMessageAt;
|
|
3822
|
+
}
|
|
3823
|
+
if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
|
|
3824
|
+
existing.lastMessageAt = fileSummary.lastMessageAt;
|
|
3825
|
+
if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
|
|
3826
|
+
if (fileSummary.preview) existing.preview = fileSummary.preview;
|
|
3827
|
+
}
|
|
3828
|
+
if (!existing.workspace && fileSummary.workspace) {
|
|
3829
|
+
existing.workspace = fileSummary.workspace;
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
return {
|
|
3833
|
+
summaries: Array.from(summaryBySessionId.values()).sort((a, b) => b.lastMessageAt - a.lastMessageAt),
|
|
3834
|
+
persistedEntries: nextPersistedEntries
|
|
3835
|
+
};
|
|
3423
3836
|
}
|
|
3424
3837
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0) {
|
|
3425
3838
|
try {
|
|
@@ -3477,18 +3890,51 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
3477
3890
|
savedHistorySessionCache.delete(sanitized);
|
|
3478
3891
|
return { sessions: [], hasMore: false };
|
|
3479
3892
|
}
|
|
3480
|
-
const files = listHistoryFiles(dir);
|
|
3481
|
-
const signature = buildSavedHistoryCacheSignature(dir, files);
|
|
3482
3893
|
const cached2 = savedHistorySessionCache.get(sanitized);
|
|
3483
|
-
const
|
|
3484
|
-
|
|
3894
|
+
const offset = Math.max(0, options.offset || 0);
|
|
3895
|
+
const limit = Math.max(1, options.limit || 30);
|
|
3896
|
+
const indexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
3897
|
+
let cacheWasInvalidated = false;
|
|
3898
|
+
if (cached2) {
|
|
3899
|
+
const cacheLooksPersisted = cached2.signature.startsWith("index:");
|
|
3900
|
+
const cacheStillValid = cacheLooksPersisted ? cached2.signature === indexSignature : (() => {
|
|
3901
|
+
const files2 = listHistoryFiles(dir);
|
|
3902
|
+
const fileSignatures2 = buildSavedHistoryFileSignatureMap(dir, files2);
|
|
3903
|
+
return cached2.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
|
|
3904
|
+
})();
|
|
3905
|
+
if (cacheStillValid) {
|
|
3906
|
+
const sliced2 = cached2.summaries.slice(offset, offset + limit);
|
|
3907
|
+
return {
|
|
3908
|
+
sessions: sliced2,
|
|
3909
|
+
hasMore: cached2.summaries.length > offset + limit
|
|
3910
|
+
};
|
|
3911
|
+
}
|
|
3912
|
+
cacheWasInvalidated = true;
|
|
3913
|
+
}
|
|
3914
|
+
const persistedSessions = readPersistedSavedHistorySessionSummaries(dir);
|
|
3915
|
+
if (!cacheWasInvalidated && persistedSessions?.length && !historyDirectoryHasFilesNewerThanIndex(dir)) {
|
|
3485
3916
|
savedHistorySessionCache.set(sanitized, {
|
|
3486
|
-
signature,
|
|
3487
|
-
summaries
|
|
3917
|
+
signature: indexSignature,
|
|
3918
|
+
summaries: persistedSessions
|
|
3488
3919
|
});
|
|
3920
|
+
scheduleSavedHistoryBackgroundRefresh(agentType, dir);
|
|
3921
|
+
const sliced2 = persistedSessions.slice(offset, offset + limit);
|
|
3922
|
+
return {
|
|
3923
|
+
sessions: sliced2,
|
|
3924
|
+
hasMore: persistedSessions.length > offset + limit
|
|
3925
|
+
};
|
|
3489
3926
|
}
|
|
3490
|
-
const
|
|
3491
|
-
const
|
|
3927
|
+
const files = listHistoryFiles(dir);
|
|
3928
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
3929
|
+
const signature = buildSavedHistoryCacheSignature(files, fileSignatures);
|
|
3930
|
+
const persistedEntries = loadPersistedSavedHistoryIndex(dir);
|
|
3931
|
+
const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
|
|
3932
|
+
const summaries = computed.summaries || [];
|
|
3933
|
+
savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
|
|
3934
|
+
savedHistorySessionCache.set(sanitized, {
|
|
3935
|
+
signature,
|
|
3936
|
+
summaries
|
|
3937
|
+
});
|
|
3492
3938
|
const sliced = summaries.slice(offset, offset + limit);
|
|
3493
3939
|
return {
|
|
3494
3940
|
sessions: sliced,
|
|
@@ -3498,7 +3944,7 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
3498
3944
|
return { sessions: [], hasMore: false };
|
|
3499
3945
|
}
|
|
3500
3946
|
}
|
|
3501
|
-
var fs3, path7, os5, HISTORY_DIR, RETAIN_DAYS, savedHistorySessionCache, CODEX_STARTER_PROMPT_RE, ChatHistoryWriter;
|
|
3947
|
+
var fs3, path7, os5, 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;
|
|
3502
3948
|
var init_chat_history = __esm({
|
|
3503
3949
|
"../../oss/packages/daemon-core/src/config/chat-history.ts"() {
|
|
3504
3950
|
"use strict";
|
|
@@ -3506,9 +3952,20 @@ var init_chat_history = __esm({
|
|
|
3506
3952
|
path7 = __toESM(require("path"));
|
|
3507
3953
|
os5 = __toESM(require("os"));
|
|
3508
3954
|
init_chat_message_normalization();
|
|
3955
|
+
init_provider_session_id();
|
|
3509
3956
|
HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
|
|
3510
3957
|
RETAIN_DAYS = 30;
|
|
3958
|
+
SAVED_HISTORY_INDEX_VERSION = 1;
|
|
3959
|
+
SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
3960
|
+
SAVED_HISTORY_INDEX_LOCK_SUFFIX = ".lock";
|
|
3961
|
+
SAVED_HISTORY_INDEX_LOCK_WAIT_MS = 1500;
|
|
3962
|
+
SAVED_HISTORY_INDEX_LOCK_STALE_MS = 15e3;
|
|
3963
|
+
SAVED_HISTORY_INDEX_LOCK_POLL_MS = 25;
|
|
3964
|
+
SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES = 16 * 1024 * 1024;
|
|
3511
3965
|
savedHistorySessionCache = /* @__PURE__ */ new Map();
|
|
3966
|
+
savedHistoryFileSummaryCache = /* @__PURE__ */ new Map();
|
|
3967
|
+
savedHistoryBackgroundRefresh = /* @__PURE__ */ new Set();
|
|
3968
|
+
savedHistoryRollupInFlight = /* @__PURE__ */ new Set();
|
|
3512
3969
|
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;
|
|
3513
3970
|
ChatHistoryWriter = class {
|
|
3514
3971
|
/** Last seen message count per agent (deduplication) */
|
|
@@ -3583,9 +4040,11 @@ var init_chat_history = __esm({
|
|
|
3583
4040
|
fs3.mkdirSync(dir, { recursive: true });
|
|
3584
4041
|
const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3585
4042
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
3586
|
-
const
|
|
4043
|
+
const fileName = `${filePrefix}${date5}.jsonl`;
|
|
4044
|
+
const filePath = path7.join(dir, fileName);
|
|
3587
4045
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
3588
4046
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
4047
|
+
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
3589
4048
|
const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
|
|
3590
4049
|
if (!historySessionId && messages.length < prevCount * 0.5 && prevCount > 3) {
|
|
3591
4050
|
seenHashes.clear();
|
|
@@ -3676,7 +4135,8 @@ var init_chat_history = __esm({
|
|
|
3676
4135
|
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
3677
4136
|
fs3.mkdirSync(dir, { recursive: true });
|
|
3678
4137
|
const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
3679
|
-
const
|
|
4138
|
+
const fileName = `${this.sanitize(id)}_${date5}.jsonl`;
|
|
4139
|
+
const filePath = path7.join(dir, fileName);
|
|
3680
4140
|
const record2 = {
|
|
3681
4141
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3682
4142
|
receivedAt: Date.now(),
|
|
@@ -3689,6 +4149,7 @@ var init_chat_history = __esm({
|
|
|
3689
4149
|
workspace: ws
|
|
3690
4150
|
};
|
|
3691
4151
|
fs3.appendFileSync(filePath, JSON.stringify(record2) + "\n", "utf-8");
|
|
4152
|
+
updateSavedHistoryIndexForSessionStart(agentType, dir, fileName, id, ws);
|
|
3692
4153
|
} catch {
|
|
3693
4154
|
}
|
|
3694
4155
|
}
|
|
@@ -3754,6 +4215,7 @@ var init_chat_history = __esm({
|
|
|
3754
4215
|
}
|
|
3755
4216
|
fs3.unlinkSync(sourcePath);
|
|
3756
4217
|
}
|
|
4218
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
3757
4219
|
} catch {
|
|
3758
4220
|
}
|
|
3759
4221
|
}
|
|
@@ -3803,6 +4265,7 @@ var init_chat_history = __esm({
|
|
|
3803
4265
|
fs3.writeFileSync(filePath, `${collapsed.map((entry) => JSON.stringify(entry)).join("\n")}
|
|
3804
4266
|
`, "utf-8");
|
|
3805
4267
|
}
|
|
4268
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
3806
4269
|
} catch {
|
|
3807
4270
|
}
|
|
3808
4271
|
}
|
|
@@ -3822,13 +4285,18 @@ var init_chat_history = __esm({
|
|
|
3822
4285
|
for (const dir of agentDirs) {
|
|
3823
4286
|
const dirPath = path7.join(HISTORY_DIR, dir.name);
|
|
3824
4287
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
4288
|
+
let removedAny = false;
|
|
3825
4289
|
for (const file2 of files) {
|
|
3826
4290
|
const filePath = path7.join(dirPath, file2);
|
|
3827
4291
|
const stat4 = fs3.statSync(filePath);
|
|
3828
4292
|
if (stat4.mtimeMs < cutoff) {
|
|
3829
4293
|
fs3.unlinkSync(filePath);
|
|
4294
|
+
removedAny = true;
|
|
3830
4295
|
}
|
|
3831
4296
|
}
|
|
4297
|
+
if (removedAny) {
|
|
4298
|
+
invalidatePersistedSavedHistoryIndex(dir.name, dirPath);
|
|
4299
|
+
}
|
|
3832
4300
|
}
|
|
3833
4301
|
} catch {
|
|
3834
4302
|
}
|
|
@@ -5755,6 +6223,21 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
5755
6223
|
lastUpdated: ext.lastUpdated
|
|
5756
6224
|
};
|
|
5757
6225
|
}
|
|
6226
|
+
function shouldIncludeExtensionSession(ext) {
|
|
6227
|
+
const status = String(ext.status || "").trim().toLowerCase();
|
|
6228
|
+
const hasActiveChat = !!ext.activeChat;
|
|
6229
|
+
const hasMessages = Array.isArray(ext.activeChat?.messages) && ext.activeChat.messages.length > 0;
|
|
6230
|
+
const hasModal = !!ext.activeChat?.activeModal;
|
|
6231
|
+
const hasStreams = Array.isArray(ext.agentStreams) && ext.agentStreams.length > 0;
|
|
6232
|
+
const hasProviderSessionId = typeof ext.providerSessionId === "string" && ext.providerSessionId.trim().length > 0;
|
|
6233
|
+
const hasControlValues = !!(ext.controlValues && Object.keys(ext.controlValues).length > 0);
|
|
6234
|
+
const hasProviderControls = Array.isArray(ext.providerControls) && ext.providerControls.length > 0;
|
|
6235
|
+
const hasOpenPanelCapability = Array.isArray(ext.sessionCapabilities) && ext.sessionCapabilities.includes("open_panel");
|
|
6236
|
+
const hasSummaryMetadata = !!ext.summaryMetadata;
|
|
6237
|
+
const hasError = typeof ext.errorMessage === "string" && ext.errorMessage.trim().length > 0;
|
|
6238
|
+
const hasInterestingStatus = !!status && !["idle", "panel_hidden", "disconnected", "not_monitored"].includes(status);
|
|
6239
|
+
return hasActiveChat || hasMessages || hasModal || hasStreams || hasProviderSessionId || hasControlValues || hasProviderControls || hasOpenPanelCapability || hasSummaryMetadata || hasError || hasInterestingStatus;
|
|
6240
|
+
}
|
|
5758
6241
|
function buildCliSession(state, options) {
|
|
5759
6242
|
const profile = options.profile || "full";
|
|
5760
6243
|
const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
|
|
@@ -5838,6 +6321,7 @@ function buildSessionEntries(allStates, cdpManagers, options = {}) {
|
|
|
5838
6321
|
for (const state of ideStates) {
|
|
5839
6322
|
sessions.push(buildIdeWorkspaceSession(state, cdpManagers, options));
|
|
5840
6323
|
for (const ext of state.extensions) {
|
|
6324
|
+
if (!shouldIncludeExtensionSession(ext)) continue;
|
|
5841
6325
|
sessions.push(buildExtensionAgentSession(state, ext, options));
|
|
5842
6326
|
}
|
|
5843
6327
|
}
|
|
@@ -8090,7 +8574,9 @@ function applyProviderPatch(h, args, payload) {
|
|
|
8090
8574
|
});
|
|
8091
8575
|
}
|
|
8092
8576
|
async function executeProviderScript(h, args, scriptName) {
|
|
8093
|
-
const
|
|
8577
|
+
const explicitTargetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
8578
|
+
const targetSession = explicitTargetSessionId ? h.ctx.sessionRegistry?.get(explicitTargetSessionId) : void 0;
|
|
8579
|
+
const resolvedProviderType = targetSession?.providerType || h.currentSession?.providerType || h.currentProviderType || args?.agentType || args?.providerType;
|
|
8094
8580
|
if (!resolvedProviderType) return { success: false, error: "targetSessionId or providerType is required" };
|
|
8095
8581
|
const loader = h.ctx.providerLoader;
|
|
8096
8582
|
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
@@ -8133,16 +8619,16 @@ async function executeProviderScript(h, args, scriptName) {
|
|
|
8133
8619
|
const scriptFn = provider.scripts[actualScriptName];
|
|
8134
8620
|
const scriptCode = scriptFn(normalizedArgs);
|
|
8135
8621
|
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
8136
|
-
const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : h.currentSession?.cdpManagerKey || h.currentManagerKey;
|
|
8622
|
+
const cdpKey = provider.category === "ide" ? targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey;
|
|
8137
8623
|
LOG.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
|
|
8138
8624
|
const cdp = h.getCdp(cdpKey);
|
|
8139
8625
|
if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
|
|
8140
8626
|
try {
|
|
8141
8627
|
let result;
|
|
8142
8628
|
if (provider.category === "extension") {
|
|
8143
|
-
const runtimeSessionId = h.currentSession?.sessionId
|
|
8629
|
+
const runtimeSessionId = explicitTargetSessionId || h.currentSession?.sessionId;
|
|
8144
8630
|
if (!runtimeSessionId) return { success: false, error: `No target session found for ${resolvedProviderType}` };
|
|
8145
|
-
const parentSessionId = h.currentSession?.parentSessionId;
|
|
8631
|
+
const parentSessionId = targetSession?.parentSessionId || h.currentSession?.parentSessionId;
|
|
8146
8632
|
if (parentSessionId) {
|
|
8147
8633
|
await h.agentStream?.setActiveSession(cdp, parentSessionId, runtimeSessionId);
|
|
8148
8634
|
await h.agentStream?.syncActiveSession(cdp, parentSessionId);
|
|
@@ -36582,6 +37068,28 @@ var init_subscription_updates = __esm({
|
|
|
36582
37068
|
}
|
|
36583
37069
|
});
|
|
36584
37070
|
|
|
37071
|
+
// ../../oss/packages/daemon-core/src/chat/async-batch.ts
|
|
37072
|
+
async function runAsyncBatch(items, worker, options = {}) {
|
|
37073
|
+
const list = Array.from(items);
|
|
37074
|
+
if (list.length === 0) return;
|
|
37075
|
+
const concurrency = Math.max(1, Math.min(list.length, Math.floor(options.concurrency || 1)));
|
|
37076
|
+
let nextIndex = 0;
|
|
37077
|
+
const runners = Array.from({ length: concurrency }, async () => {
|
|
37078
|
+
while (true) {
|
|
37079
|
+
const currentIndex = nextIndex;
|
|
37080
|
+
nextIndex += 1;
|
|
37081
|
+
if (currentIndex >= list.length) return;
|
|
37082
|
+
await worker(list[currentIndex], currentIndex);
|
|
37083
|
+
}
|
|
37084
|
+
});
|
|
37085
|
+
await Promise.all(runners);
|
|
37086
|
+
}
|
|
37087
|
+
var init_async_batch = __esm({
|
|
37088
|
+
"../../oss/packages/daemon-core/src/chat/async-batch.ts"() {
|
|
37089
|
+
"use strict";
|
|
37090
|
+
}
|
|
37091
|
+
});
|
|
37092
|
+
|
|
36585
37093
|
// ../../oss/packages/daemon-core/src/agent-stream/provider-adapter.ts
|
|
36586
37094
|
var ProviderStreamAdapter;
|
|
36587
37095
|
var init_provider_adapter = __esm({
|
|
@@ -37063,10 +37571,12 @@ var init_manager2 = __esm({
|
|
|
37063
37571
|
}
|
|
37064
37572
|
}
|
|
37065
37573
|
/** Collect active extension session state */
|
|
37066
|
-
async collectActiveSession(cdp, parentSessionId) {
|
|
37574
|
+
async collectActiveSession(cdp, parentSessionId, attemptedSessionIds = /* @__PURE__ */ new Set(), originSessionId) {
|
|
37067
37575
|
if (!this.enabled) return null;
|
|
37068
37576
|
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
37069
37577
|
if (!activeSessionId) return null;
|
|
37578
|
+
const resolvedOriginSessionId = originSessionId || activeSessionId;
|
|
37579
|
+
attemptedSessionIds.add(activeSessionId);
|
|
37070
37580
|
let agent = this.managedBySessionId.get(activeSessionId);
|
|
37071
37581
|
if (!agent) {
|
|
37072
37582
|
agent = await this.connectManagedSession(cdp, parentSessionId, activeSessionId) || void 0;
|
|
@@ -37079,18 +37589,44 @@ var init_manager2 = __esm({
|
|
|
37079
37589
|
try {
|
|
37080
37590
|
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
37081
37591
|
const state = await agent.adapter.readChat(evaluate);
|
|
37082
|
-
const
|
|
37083
|
-
const
|
|
37084
|
-
|
|
37085
|
-
|
|
37592
|
+
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;
|
|
37593
|
+
const normalizedState = {
|
|
37594
|
+
...state,
|
|
37595
|
+
sessionId: agent.runtimeSessionId,
|
|
37596
|
+
...resolvedProviderSessionId ? { providerSessionId: resolvedProviderSessionId } : {}
|
|
37597
|
+
};
|
|
37598
|
+
const stateError = this.getStateError(normalizedState);
|
|
37599
|
+
const selectedModelValue = typeof normalizedState.controlValues?.model === "string" ? normalizedState.controlValues.model : "";
|
|
37600
|
+
LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${normalizedState.status} msgs=${normalizedState.messages?.length || 0} model=${selectedModelValue}${normalizedState.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
|
|
37601
|
+
if (normalizedState.status === "error" && this.isRecoverableSessionError(stateError)) {
|
|
37086
37602
|
throw new Error(stateError);
|
|
37087
37603
|
}
|
|
37088
|
-
agent.lastState =
|
|
37604
|
+
agent.lastState = normalizedState;
|
|
37089
37605
|
agent.lastError = null;
|
|
37090
|
-
if (
|
|
37606
|
+
if (normalizedState.status === "panel_hidden") {
|
|
37607
|
+
const discovered = await cdp.discoverAgentWebviews().catch(() => []);
|
|
37608
|
+
const fallbackTarget = discovered.find((entry) => {
|
|
37609
|
+
if (entry.agentType === type) return false;
|
|
37610
|
+
const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, entry.agentType);
|
|
37611
|
+
return !!fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId);
|
|
37612
|
+
});
|
|
37613
|
+
if (fallbackTarget) {
|
|
37614
|
+
const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, fallbackTarget.agentType);
|
|
37615
|
+
if (fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId)) {
|
|
37616
|
+
this.logFn(`[AgentStream] Active session ${type} is hidden; switching to visible agent ${fallbackTarget.agentType} (${parentSessionId})`);
|
|
37617
|
+
await this.setActiveSession(cdp, parentSessionId, fallbackSessionId);
|
|
37618
|
+
await this.syncActiveSession(cdp, parentSessionId);
|
|
37619
|
+
const fallbackState = await this.collectActiveSession(cdp, parentSessionId, attemptedSessionIds, resolvedOriginSessionId);
|
|
37620
|
+
if (fallbackState?.status === "panel_hidden" && resolvedOriginSessionId !== fallbackSessionId) {
|
|
37621
|
+
await this.setActiveSession(cdp, parentSessionId, resolvedOriginSessionId);
|
|
37622
|
+
await this.syncActiveSession(cdp, parentSessionId);
|
|
37623
|
+
}
|
|
37624
|
+
return fallbackState;
|
|
37625
|
+
}
|
|
37626
|
+
}
|
|
37091
37627
|
agent.lastHiddenCheckTime = Date.now();
|
|
37092
37628
|
}
|
|
37093
|
-
return
|
|
37629
|
+
return normalizedState;
|
|
37094
37630
|
} catch (e) {
|
|
37095
37631
|
const errorMsg = e?.message || String(e);
|
|
37096
37632
|
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
@@ -37402,6 +37938,7 @@ var init_poller = __esm({
|
|
|
37402
37938
|
try {
|
|
37403
37939
|
await agentStreamManager.syncActiveSession(cdp, parentSessionId);
|
|
37404
37940
|
let stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
|
|
37941
|
+
resolvedActiveSessionId = stream?.sessionId || agentStreamManager.getActiveSessionId(parentSessionId) || resolvedActiveSessionId;
|
|
37405
37942
|
if (stream?.status === "waiting_approval") {
|
|
37406
37943
|
const autoApprove = providerLoader.getSettings(stream.agentType).autoApprove !== false;
|
|
37407
37944
|
if (autoApprove && resolvedActiveSessionId) {
|
|
@@ -44221,6 +44758,7 @@ __export(src_exports, {
|
|
|
44221
44758
|
resolveChatMessageKind: () => resolveChatMessageKind,
|
|
44222
44759
|
resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
|
|
44223
44760
|
resolveSessionHostAppName: () => resolveSessionHostAppName,
|
|
44761
|
+
runAsyncBatch: () => runAsyncBatch,
|
|
44224
44762
|
saveConfig: () => saveConfig,
|
|
44225
44763
|
saveState: () => saveState,
|
|
44226
44764
|
setDebugRuntimeConfig: () => setDebugRuntimeConfig,
|
|
@@ -44268,6 +44806,7 @@ var init_src = __esm({
|
|
|
44268
44806
|
init_chat_history();
|
|
44269
44807
|
init_chat_signatures();
|
|
44270
44808
|
init_subscription_updates();
|
|
44809
|
+
init_async_batch();
|
|
44271
44810
|
init_agent_stream();
|
|
44272
44811
|
init_agent_stream();
|
|
44273
44812
|
init_forward();
|
|
@@ -45356,6 +45895,7 @@ var init_daemon_p2p = __esm({
|
|
|
45356
45895
|
fs15 = __toESM(require("fs"));
|
|
45357
45896
|
path23 = __toESM(require("path"));
|
|
45358
45897
|
import_node_module2 = require("module");
|
|
45898
|
+
init_src();
|
|
45359
45899
|
init_data_channel_router();
|
|
45360
45900
|
init_screenshot_sender();
|
|
45361
45901
|
init_peer_connection_manager();
|
|
@@ -45605,14 +46145,22 @@ ${e?.stack || ""}`);
|
|
|
45605
46145
|
return false;
|
|
45606
46146
|
}
|
|
45607
46147
|
async flushChatSubscriptions(builder) {
|
|
46148
|
+
const tasks = [];
|
|
45608
46149
|
for (const peer of this.peers.values()) {
|
|
45609
46150
|
if (peer.state !== "connected" || !peer.chatSubscriptions || peer.chatSubscriptions.size === 0) continue;
|
|
45610
46151
|
for (const subscription of peer.chatSubscriptions.values()) {
|
|
46152
|
+
tasks.push({ peer, subscription });
|
|
46153
|
+
}
|
|
46154
|
+
}
|
|
46155
|
+
await runAsyncBatch(tasks, async ({ peer, subscription }) => {
|
|
46156
|
+
try {
|
|
45611
46157
|
const update = await builder(subscription);
|
|
45612
|
-
if (!update)
|
|
46158
|
+
if (!update) return;
|
|
45613
46159
|
this.screenshotSender.sendTopicUpdateToPeer(peer, update);
|
|
46160
|
+
} catch (error48) {
|
|
46161
|
+
log(`chat_tail flush skipped: peer=${peer.peerId} session=${subscription.params.targetSessionId} error=${error48?.message || error48}`);
|
|
45614
46162
|
}
|
|
45615
|
-
}
|
|
46163
|
+
}, { concurrency: 4 });
|
|
45616
46164
|
}
|
|
45617
46165
|
async flushMachineRuntimeSubscriptions(builder) {
|
|
45618
46166
|
for (const peer of this.peers.values()) {
|
|
@@ -53563,7 +54111,7 @@ var init_adhdev_daemon = __esm({
|
|
|
53563
54111
|
init_source2();
|
|
53564
54112
|
init_version();
|
|
53565
54113
|
init_src();
|
|
53566
|
-
pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.
|
|
54114
|
+
pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.76" });
|
|
53567
54115
|
AdhdevDaemon = class _AdhdevDaemon {
|
|
53568
54116
|
localHttpServer = null;
|
|
53569
54117
|
localWss = null;
|
|
@@ -53977,7 +54525,7 @@ ${err?.stack || ""}`);
|
|
|
53977
54525
|
}),
|
|
53978
54526
|
onStatusChange: () => {
|
|
53979
54527
|
this.statusReporter?.onStatusChange();
|
|
53980
|
-
void this.flushP2PChatSubscriptions({ onlyActive:
|
|
54528
|
+
void this.flushP2PChatSubscriptions({ onlyActive: true });
|
|
53981
54529
|
},
|
|
53982
54530
|
removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
|
|
53983
54531
|
hostedRuntimeManagerTag: "adhdev-cloud",
|
|
@@ -54006,7 +54554,7 @@ ${err?.stack || ""}`);
|
|
|
54006
54554
|
statusVersion: pkgVersion,
|
|
54007
54555
|
onStatusChange: () => {
|
|
54008
54556
|
this.statusReporter?.onStatusChange();
|
|
54009
|
-
void this.flushP2PChatSubscriptions({ onlyActive:
|
|
54557
|
+
void this.flushP2PChatSubscriptions({ onlyActive: true });
|
|
54010
54558
|
},
|
|
54011
54559
|
onPostChatCommand: () => {
|
|
54012
54560
|
setTimeout(() => this.statusReporter?.throttledReport(), 1e3);
|