@adhdev/daemon-core 0.8.75 → 0.8.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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/cli-adapters/pty-transport.d.ts +2 -0
- package/dist/config/chat-history.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +713 -147
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +712 -147
- package/dist/index.mjs.map +1 -1
- package/dist/providers/provider-instance.d.ts +4 -0
- package/dist/shared-types.d.ts +4 -0
- package/dist/status/chat-tail-hot-sessions.d.ts +4 -0
- package/node_modules/@adhdev/session-host-core/package.json +2 -2
- package/package.json +2 -2
- 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/cli-adapters/pty-transport.ts +2 -0
- package/src/cli-adapters/session-host-transport.ts +2 -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/providers/cli-provider-instance.ts +4 -0
- package/src/providers/provider-instance.ts +4 -0
- package/src/shared-types.ts +4 -0
- package/src/status/builders.ts +33 -1
- package/src/status/chat-tail-hot-sessions.ts +35 -1
package/dist/index.js
CHANGED
|
@@ -3667,6 +3667,7 @@ __export(index_exports, {
|
|
|
3667
3667
|
resolveChatMessageKind: () => resolveChatMessageKind,
|
|
3668
3668
|
resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
|
|
3669
3669
|
resolveSessionHostAppName: () => resolveSessionHostAppName,
|
|
3670
|
+
runAsyncBatch: () => runAsyncBatch,
|
|
3670
3671
|
saveConfig: () => saveConfig,
|
|
3671
3672
|
saveState: () => saveState,
|
|
3672
3673
|
setDebugRuntimeConfig: () => setDebugRuntimeConfig,
|
|
@@ -4408,6 +4409,61 @@ function getHostMemorySnapshot() {
|
|
|
4408
4409
|
return { totalMem, freeMem, availableMem };
|
|
4409
4410
|
}
|
|
4410
4411
|
|
|
4412
|
+
// src/session-host/runtime-surface.ts
|
|
4413
|
+
var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
4414
|
+
function isSessionHostLiveRuntime(record) {
|
|
4415
|
+
const lifecycle = String(record?.lifecycle || "").trim();
|
|
4416
|
+
return LIVE_LIFECYCLES.has(lifecycle);
|
|
4417
|
+
}
|
|
4418
|
+
function getSessionHostRecoveryLabel(meta) {
|
|
4419
|
+
const recoveryState = typeof meta?.runtimeRecoveryState === "string" ? String(meta.runtimeRecoveryState).trim() : "";
|
|
4420
|
+
if (!recoveryState) return null;
|
|
4421
|
+
if (recoveryState === "auto_resumed") return "restored after restart";
|
|
4422
|
+
if (recoveryState === "resume_failed") return "restore failed";
|
|
4423
|
+
if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
|
|
4424
|
+
if (recoveryState === "orphan_snapshot") return "snapshot recovered";
|
|
4425
|
+
return recoveryState.replace(/_/g, " ");
|
|
4426
|
+
}
|
|
4427
|
+
function isSessionHostRecoverySnapshot(record) {
|
|
4428
|
+
if (!record) return false;
|
|
4429
|
+
if (isSessionHostLiveRuntime(record)) return false;
|
|
4430
|
+
const lifecycle = String(record.lifecycle || "").trim();
|
|
4431
|
+
if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
|
|
4432
|
+
return false;
|
|
4433
|
+
}
|
|
4434
|
+
const meta = record.meta || void 0;
|
|
4435
|
+
if (meta?.restoredFromStorage === true) return true;
|
|
4436
|
+
return getSessionHostRecoveryLabel(meta) !== null;
|
|
4437
|
+
}
|
|
4438
|
+
function getSessionHostSurfaceKind(record) {
|
|
4439
|
+
if (isSessionHostLiveRuntime(record)) return "live_runtime";
|
|
4440
|
+
if (isSessionHostRecoverySnapshot(record)) return "recovery_snapshot";
|
|
4441
|
+
return "inactive_record";
|
|
4442
|
+
}
|
|
4443
|
+
function partitionSessionHostRecords(records) {
|
|
4444
|
+
const liveRuntimes = [];
|
|
4445
|
+
const recoverySnapshots = [];
|
|
4446
|
+
const inactiveRecords = [];
|
|
4447
|
+
for (const record of records) {
|
|
4448
|
+
const kind = getSessionHostSurfaceKind(record);
|
|
4449
|
+
if (kind === "live_runtime") {
|
|
4450
|
+
liveRuntimes.push(record);
|
|
4451
|
+
} else if (kind === "recovery_snapshot") {
|
|
4452
|
+
recoverySnapshots.push(record);
|
|
4453
|
+
} else {
|
|
4454
|
+
inactiveRecords.push(record);
|
|
4455
|
+
}
|
|
4456
|
+
}
|
|
4457
|
+
return {
|
|
4458
|
+
liveRuntimes,
|
|
4459
|
+
recoverySnapshots,
|
|
4460
|
+
inactiveRecords
|
|
4461
|
+
};
|
|
4462
|
+
}
|
|
4463
|
+
function partitionSessionHostDiagnosticsSessions(records) {
|
|
4464
|
+
return partitionSessionHostRecords(records || []);
|
|
4465
|
+
}
|
|
4466
|
+
|
|
4411
4467
|
// src/status/chat-tail-hot-sessions.ts
|
|
4412
4468
|
var DEFAULT_ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
|
|
4413
4469
|
"generating",
|
|
@@ -4415,6 +4471,7 @@ var DEFAULT_ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
|
|
|
4415
4471
|
"starting"
|
|
4416
4472
|
]);
|
|
4417
4473
|
var DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS = 8e3;
|
|
4474
|
+
var LIVE_RUNTIME_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
4418
4475
|
function parseMessageTimestamp(value) {
|
|
4419
4476
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
4420
4477
|
if (typeof value === "string") {
|
|
@@ -4423,6 +4480,23 @@ function parseMessageTimestamp(value) {
|
|
|
4423
4480
|
}
|
|
4424
4481
|
return 0;
|
|
4425
4482
|
}
|
|
4483
|
+
function isDefinitelyNonLiveRuntimeSession(session) {
|
|
4484
|
+
const surfaceKind = String(session?.runtimeSurfaceKind || "").trim();
|
|
4485
|
+
if (surfaceKind === "live_runtime") return false;
|
|
4486
|
+
if (surfaceKind === "recovery_snapshot") return true;
|
|
4487
|
+
if (surfaceKind === "inactive_record") return false;
|
|
4488
|
+
const lifecycle = String(session?.runtimeLifecycle || "").trim();
|
|
4489
|
+
if (lifecycle && LIVE_RUNTIME_LIFECYCLES.has(lifecycle)) return false;
|
|
4490
|
+
const inferredSurfaceKind = getSessionHostSurfaceKind({
|
|
4491
|
+
lifecycle: lifecycle || null,
|
|
4492
|
+
meta: {
|
|
4493
|
+
restoredFromStorage: session?.runtimeRestoredFromStorage === true,
|
|
4494
|
+
...session?.runtimeRecoveryState ? { runtimeRecoveryState: session.runtimeRecoveryState } : {}
|
|
4495
|
+
}
|
|
4496
|
+
});
|
|
4497
|
+
if (inferredSurfaceKind === "recovery_snapshot") return true;
|
|
4498
|
+
return false;
|
|
4499
|
+
}
|
|
4426
4500
|
function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessionIds, options = {}) {
|
|
4427
4501
|
const now = options.now ?? Date.now();
|
|
4428
4502
|
const recentMessageGraceMs = Math.max(
|
|
@@ -4431,9 +4505,14 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
|
|
|
4431
4505
|
);
|
|
4432
4506
|
const activeStatuses = options.activeStatuses ?? DEFAULT_ACTIVE_CHAT_POLL_STATUSES;
|
|
4433
4507
|
const active = /* @__PURE__ */ new Set();
|
|
4508
|
+
const excluded = /* @__PURE__ */ new Set();
|
|
4434
4509
|
for (const session of sessions) {
|
|
4435
4510
|
const sessionId = typeof session?.id === "string" ? session.id : "";
|
|
4436
4511
|
if (!sessionId) continue;
|
|
4512
|
+
if (isDefinitelyNonLiveRuntimeSession(session)) {
|
|
4513
|
+
excluded.add(sessionId);
|
|
4514
|
+
continue;
|
|
4515
|
+
}
|
|
4437
4516
|
const status = String(session?.status || "").toLowerCase();
|
|
4438
4517
|
const lastMessageAt = parseMessageTimestamp(session?.lastMessageAt);
|
|
4439
4518
|
const recentlyUpdated = lastMessageAt > 0 && now - lastMessageAt <= recentMessageGraceMs;
|
|
@@ -4442,7 +4521,7 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
|
|
|
4442
4521
|
}
|
|
4443
4522
|
}
|
|
4444
4523
|
const finalizing = new Set(
|
|
4445
|
-
Array.from(previousHotSessionIds).filter((sessionId) => !active.has(sessionId))
|
|
4524
|
+
Array.from(previousHotSessionIds).filter((sessionId) => !active.has(sessionId) && !excluded.has(sessionId))
|
|
4446
4525
|
);
|
|
4447
4526
|
return { active, finalizing };
|
|
4448
4527
|
}
|
|
@@ -4451,6 +4530,32 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
|
|
|
4451
4530
|
var import_ws = __toESM(require("ws"));
|
|
4452
4531
|
var http = __toESM(require("http"));
|
|
4453
4532
|
init_logger();
|
|
4533
|
+
function normalizeTitle(value) {
|
|
4534
|
+
return String(value || "").trim().replace(/\s+/g, " ").toLowerCase();
|
|
4535
|
+
}
|
|
4536
|
+
function titlesMatch(lhs, rhs) {
|
|
4537
|
+
const a = normalizeTitle(lhs);
|
|
4538
|
+
const b = normalizeTitle(rhs);
|
|
4539
|
+
if (!a || !b) return false;
|
|
4540
|
+
return a === b || a.includes(b) || b.includes(a);
|
|
4541
|
+
}
|
|
4542
|
+
function resolveCdpPageTarget(params) {
|
|
4543
|
+
const { pages, pinnedTargetId, previousPageTitle } = params;
|
|
4544
|
+
if (pages.length === 0) return { target: null, retargeted: false };
|
|
4545
|
+
if (!pinnedTargetId) {
|
|
4546
|
+
return { target: pages[0] || null, retargeted: false };
|
|
4547
|
+
}
|
|
4548
|
+
const exact = pages.find((page) => page.id === pinnedTargetId);
|
|
4549
|
+
if (exact) return { target: exact, retargeted: false };
|
|
4550
|
+
const titleMatchesList = pages.filter((page) => titlesMatch(page.title, previousPageTitle));
|
|
4551
|
+
if (titleMatchesList.length === 1) {
|
|
4552
|
+
return { target: titleMatchesList[0], retargeted: true };
|
|
4553
|
+
}
|
|
4554
|
+
if (pages.length === 1) {
|
|
4555
|
+
return { target: pages[0], retargeted: true };
|
|
4556
|
+
}
|
|
4557
|
+
return { target: null, retargeted: false };
|
|
4558
|
+
}
|
|
4454
4559
|
var DaemonCdpManager = class {
|
|
4455
4560
|
ws = null;
|
|
4456
4561
|
browserWs = null;
|
|
@@ -4611,18 +4716,28 @@ var DaemonCdpManager = class {
|
|
|
4611
4716
|
resolve11(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
4612
4717
|
return;
|
|
4613
4718
|
}
|
|
4614
|
-
const
|
|
4615
|
-
const
|
|
4719
|
+
const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
4720
|
+
const mainPages = titleFilteredPages.filter((t) => this.isMainPageUrl(t.url));
|
|
4721
|
+
const list = mainPages.length > 0 ? mainPages : titleFilteredPages.length > 0 ? titleFilteredPages : pages;
|
|
4616
4722
|
this.log(`[CDP] pages(${list.length}): ${list.map((t) => `"${t.title}"`).join(", ")}`);
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4723
|
+
const previousTargetId = this._targetId;
|
|
4724
|
+
const selected = resolveCdpPageTarget({
|
|
4725
|
+
pages: list,
|
|
4726
|
+
pinnedTargetId: previousTargetId,
|
|
4727
|
+
previousPageTitle: this._pageTitle
|
|
4728
|
+
});
|
|
4729
|
+
if (selected.target) {
|
|
4730
|
+
if (selected.retargeted && previousTargetId && previousTargetId !== selected.target.id) {
|
|
4731
|
+
this.log(`[CDP] Target ${previousTargetId} rekeyed to ${selected.target.id}`);
|
|
4732
|
+
this._targetId = selected.target.id;
|
|
4625
4733
|
}
|
|
4734
|
+
this._pageTitle = selected.target.title || "";
|
|
4735
|
+
resolve11(selected.target);
|
|
4736
|
+
return;
|
|
4737
|
+
}
|
|
4738
|
+
if (previousTargetId) {
|
|
4739
|
+
this.log(`[CDP] Target ${previousTargetId} not found in page list`);
|
|
4740
|
+
resolve11(null);
|
|
4626
4741
|
return;
|
|
4627
4742
|
}
|
|
4628
4743
|
this._pageTitle = list[0]?.title || "";
|
|
@@ -6062,7 +6177,17 @@ var os5 = __toESM(require("os"));
|
|
|
6062
6177
|
init_chat_message_normalization();
|
|
6063
6178
|
var HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
|
|
6064
6179
|
var RETAIN_DAYS = 30;
|
|
6180
|
+
var SAVED_HISTORY_INDEX_VERSION = 1;
|
|
6181
|
+
var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
6182
|
+
var SAVED_HISTORY_INDEX_LOCK_SUFFIX = ".lock";
|
|
6183
|
+
var SAVED_HISTORY_INDEX_LOCK_WAIT_MS = 1500;
|
|
6184
|
+
var SAVED_HISTORY_INDEX_LOCK_STALE_MS = 15e3;
|
|
6185
|
+
var SAVED_HISTORY_INDEX_LOCK_POLL_MS = 25;
|
|
6186
|
+
var SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES = 16 * 1024 * 1024;
|
|
6065
6187
|
var savedHistorySessionCache = /* @__PURE__ */ new Map();
|
|
6188
|
+
var savedHistoryFileSummaryCache = /* @__PURE__ */ new Map();
|
|
6189
|
+
var savedHistoryBackgroundRefresh = /* @__PURE__ */ new Set();
|
|
6190
|
+
var savedHistoryRollupInFlight = /* @__PURE__ */ new Set();
|
|
6066
6191
|
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;
|
|
6067
6192
|
function normalizeHistoryComparable(text) {
|
|
6068
6193
|
return String(text || "").replace(/\s+/g, " ").trim();
|
|
@@ -6120,6 +6245,68 @@ function sanitizeHistoryMessage(agentType, message) {
|
|
|
6120
6245
|
content
|
|
6121
6246
|
};
|
|
6122
6247
|
}
|
|
6248
|
+
function sortSavedHistorySessionSummaries(summaries) {
|
|
6249
|
+
return summaries.slice().sort((a, b) => b.lastMessageAt - a.lastMessageAt);
|
|
6250
|
+
}
|
|
6251
|
+
function buildSavedHistorySessionSummaryMapFromEntries(entries) {
|
|
6252
|
+
const summaries = /* @__PURE__ */ new Map();
|
|
6253
|
+
for (const entry of Array.from(entries.values())) {
|
|
6254
|
+
const fileSummary = entry.summary;
|
|
6255
|
+
if (!fileSummary || fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) continue;
|
|
6256
|
+
const existing = summaries.get(fileSummary.historySessionId);
|
|
6257
|
+
if (!existing) {
|
|
6258
|
+
summaries.set(fileSummary.historySessionId, {
|
|
6259
|
+
historySessionId: fileSummary.historySessionId,
|
|
6260
|
+
sessionTitle: fileSummary.sessionTitle,
|
|
6261
|
+
messageCount: fileSummary.messageCount,
|
|
6262
|
+
firstMessageAt: fileSummary.firstMessageAt,
|
|
6263
|
+
lastMessageAt: fileSummary.lastMessageAt,
|
|
6264
|
+
preview: fileSummary.preview,
|
|
6265
|
+
workspace: fileSummary.workspace
|
|
6266
|
+
});
|
|
6267
|
+
continue;
|
|
6268
|
+
}
|
|
6269
|
+
existing.messageCount += fileSummary.messageCount;
|
|
6270
|
+
if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
|
|
6271
|
+
existing.firstMessageAt = fileSummary.firstMessageAt;
|
|
6272
|
+
}
|
|
6273
|
+
if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
|
|
6274
|
+
existing.lastMessageAt = fileSummary.lastMessageAt;
|
|
6275
|
+
if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
|
|
6276
|
+
if (fileSummary.preview) existing.preview = fileSummary.preview;
|
|
6277
|
+
}
|
|
6278
|
+
if (!existing.workspace && fileSummary.workspace) {
|
|
6279
|
+
existing.workspace = fileSummary.workspace;
|
|
6280
|
+
}
|
|
6281
|
+
}
|
|
6282
|
+
return Object.fromEntries(sortSavedHistorySessionSummaries(Array.from(summaries.values())).map((summary) => [summary.historySessionId, summary]));
|
|
6283
|
+
}
|
|
6284
|
+
function readPersistedSavedHistorySessionSummaries(dir) {
|
|
6285
|
+
try {
|
|
6286
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
6287
|
+
if (!fs3.existsSync(filePath)) return null;
|
|
6288
|
+
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
6289
|
+
if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.sessions || typeof raw.sessions !== "object") {
|
|
6290
|
+
return null;
|
|
6291
|
+
}
|
|
6292
|
+
return sortSavedHistorySessionSummaries(
|
|
6293
|
+
Object.values(raw.sessions).filter((summary) => !!summary && typeof summary.historySessionId === "string" && summary.messageCount > 0 && summary.lastMessageAt > 0).map((summary) => ({
|
|
6294
|
+
historySessionId: summary.historySessionId,
|
|
6295
|
+
sessionTitle: summary.sessionTitle,
|
|
6296
|
+
messageCount: summary.messageCount,
|
|
6297
|
+
firstMessageAt: summary.firstMessageAt,
|
|
6298
|
+
lastMessageAt: summary.lastMessageAt,
|
|
6299
|
+
preview: summary.preview,
|
|
6300
|
+
workspace: summary.workspace
|
|
6301
|
+
}))
|
|
6302
|
+
);
|
|
6303
|
+
} catch {
|
|
6304
|
+
return null;
|
|
6305
|
+
}
|
|
6306
|
+
}
|
|
6307
|
+
function shouldScheduleSavedHistoryRollup(totalBytes) {
|
|
6308
|
+
return Number.isFinite(totalBytes) && totalBytes >= SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES;
|
|
6309
|
+
}
|
|
6123
6310
|
function sanitizeHistoryFileSegment(value) {
|
|
6124
6311
|
return String(value || "").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
6125
6312
|
}
|
|
@@ -6133,71 +6320,386 @@ function listHistoryFiles(dir, historySessionId) {
|
|
|
6133
6320
|
return true;
|
|
6134
6321
|
}).sort().reverse();
|
|
6135
6322
|
}
|
|
6136
|
-
function
|
|
6137
|
-
|
|
6323
|
+
function normalizeSavedHistorySessionId(agentType, historySessionId) {
|
|
6324
|
+
const normalizedId = String(historySessionId || "").trim();
|
|
6325
|
+
if (!normalizedId) return "";
|
|
6326
|
+
const strictProviderId = normalizeProviderSessionId(agentType, normalizedId);
|
|
6327
|
+
if (strictProviderId) return strictProviderId;
|
|
6328
|
+
return agentType === "hermes-cli" ? "" : normalizedId;
|
|
6329
|
+
}
|
|
6330
|
+
function extractSavedHistorySessionIdFromFile(agentType, file) {
|
|
6331
|
+
const match = file.match(/^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/);
|
|
6332
|
+
return normalizeSavedHistorySessionId(agentType, match?.[1] || "");
|
|
6333
|
+
}
|
|
6334
|
+
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
6335
|
+
return new Map(files.map((file) => {
|
|
6138
6336
|
try {
|
|
6139
6337
|
const stat = fs3.statSync(path7.join(dir, file));
|
|
6140
|
-
return `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}
|
|
6338
|
+
return [file, `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}`];
|
|
6141
6339
|
} catch {
|
|
6142
|
-
return `${file}:missing
|
|
6143
|
-
}
|
|
6144
|
-
})
|
|
6145
|
-
}
|
|
6146
|
-
function
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6340
|
+
return [file, `${file}:missing`];
|
|
6341
|
+
}
|
|
6342
|
+
}));
|
|
6343
|
+
}
|
|
6344
|
+
function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
6345
|
+
return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
|
|
6346
|
+
}
|
|
6347
|
+
function getSavedHistoryIndexFilePath(dir) {
|
|
6348
|
+
return path7.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
6349
|
+
}
|
|
6350
|
+
function getSavedHistoryIndexLockPath(dir) {
|
|
6351
|
+
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
6352
|
+
}
|
|
6353
|
+
function sleepBlocking(ms) {
|
|
6354
|
+
if (ms <= 0) return;
|
|
6355
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
6356
|
+
}
|
|
6357
|
+
function loadPersistedSavedHistoryIndexFromFile(dir) {
|
|
6358
|
+
try {
|
|
6359
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
6360
|
+
if (!fs3.existsSync(filePath)) return /* @__PURE__ */ new Map();
|
|
6361
|
+
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
6362
|
+
if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.files || typeof raw.files !== "object") {
|
|
6363
|
+
return /* @__PURE__ */ new Map();
|
|
6364
|
+
}
|
|
6365
|
+
return new Map(
|
|
6366
|
+
Object.entries(raw.files).filter(([file, entry]) => !!file && !!entry && typeof entry.signature === "string").map(([file, entry]) => [file, {
|
|
6367
|
+
signature: entry.signature,
|
|
6368
|
+
summary: entry.summary || null
|
|
6369
|
+
}])
|
|
6370
|
+
);
|
|
6371
|
+
} catch {
|
|
6372
|
+
return /* @__PURE__ */ new Map();
|
|
6373
|
+
}
|
|
6374
|
+
}
|
|
6375
|
+
function writePersistedSavedHistoryIndexFile(dir, entries) {
|
|
6376
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
6377
|
+
const tempPath = `${filePath}.tmp`;
|
|
6378
|
+
const payload = {
|
|
6379
|
+
version: SAVED_HISTORY_INDEX_VERSION,
|
|
6380
|
+
files: Object.fromEntries(entries.entries()),
|
|
6381
|
+
sessions: buildSavedHistorySessionSummaryMapFromEntries(entries)
|
|
6382
|
+
};
|
|
6383
|
+
fs3.writeFileSync(tempPath, JSON.stringify(payload), "utf-8");
|
|
6384
|
+
fs3.renameSync(tempPath, filePath);
|
|
6385
|
+
}
|
|
6386
|
+
function acquireSavedHistoryIndexLock(dir) {
|
|
6387
|
+
const lockPath = getSavedHistoryIndexLockPath(dir);
|
|
6388
|
+
const deadline = Date.now() + SAVED_HISTORY_INDEX_LOCK_WAIT_MS;
|
|
6389
|
+
while (Date.now() <= deadline) {
|
|
6390
|
+
try {
|
|
6391
|
+
fs3.mkdirSync(lockPath);
|
|
6392
|
+
return () => {
|
|
6171
6393
|
try {
|
|
6172
|
-
|
|
6394
|
+
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
6173
6395
|
} catch {
|
|
6174
|
-
parsed = null;
|
|
6175
6396
|
}
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6397
|
+
};
|
|
6398
|
+
} catch (error) {
|
|
6399
|
+
if (error?.code !== "EEXIST") return null;
|
|
6400
|
+
try {
|
|
6401
|
+
const stat = fs3.statSync(lockPath);
|
|
6402
|
+
if (Date.now() - stat.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
|
|
6403
|
+
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
6179
6404
|
continue;
|
|
6180
6405
|
}
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6406
|
+
} catch {
|
|
6407
|
+
continue;
|
|
6408
|
+
}
|
|
6409
|
+
sleepBlocking(SAVED_HISTORY_INDEX_LOCK_POLL_MS);
|
|
6410
|
+
}
|
|
6411
|
+
}
|
|
6412
|
+
return null;
|
|
6413
|
+
}
|
|
6414
|
+
function withLockedPersistedSavedHistoryIndex(dir, callback) {
|
|
6415
|
+
const release2 = acquireSavedHistoryIndexLock(dir);
|
|
6416
|
+
if (!release2) return null;
|
|
6417
|
+
try {
|
|
6418
|
+
const entries = loadPersistedSavedHistoryIndexFromFile(dir);
|
|
6419
|
+
const result = callback(entries);
|
|
6420
|
+
writePersistedSavedHistoryIndexFile(dir, entries);
|
|
6421
|
+
return result;
|
|
6422
|
+
} catch {
|
|
6423
|
+
return null;
|
|
6424
|
+
} finally {
|
|
6425
|
+
release2();
|
|
6426
|
+
}
|
|
6427
|
+
}
|
|
6428
|
+
function loadPersistedSavedHistoryIndex(dir) {
|
|
6429
|
+
return loadPersistedSavedHistoryIndexFromFile(dir);
|
|
6430
|
+
}
|
|
6431
|
+
function savePersistedSavedHistoryIndex(dir, entries) {
|
|
6432
|
+
withLockedPersistedSavedHistoryIndex(dir, (currentEntries) => {
|
|
6433
|
+
const incomingFiles = new Set(Array.from(entries.keys()));
|
|
6434
|
+
for (const [file, entry] of Array.from(entries.entries())) {
|
|
6435
|
+
const liveSignature = buildSavedHistoryFileSignature(dir, file);
|
|
6436
|
+
const existingEntry = currentEntries.get(file);
|
|
6437
|
+
if (existingEntry && existingEntry.signature !== liveSignature && entry.signature !== liveSignature) {
|
|
6438
|
+
continue;
|
|
6439
|
+
}
|
|
6440
|
+
if (entry.signature !== liveSignature && (!existingEntry || existingEntry.signature !== liveSignature)) {
|
|
6441
|
+
continue;
|
|
6442
|
+
}
|
|
6443
|
+
currentEntries.set(file, entry.signature === liveSignature ? entry : {
|
|
6444
|
+
signature: liveSignature,
|
|
6445
|
+
summary: existingEntry?.summary || entry.summary
|
|
6446
|
+
});
|
|
6447
|
+
}
|
|
6448
|
+
for (const file of Array.from(currentEntries.keys())) {
|
|
6449
|
+
if (incomingFiles.has(file)) continue;
|
|
6450
|
+
if (!fs3.existsSync(path7.join(dir, file))) {
|
|
6451
|
+
currentEntries.delete(file);
|
|
6452
|
+
}
|
|
6453
|
+
}
|
|
6454
|
+
});
|
|
6455
|
+
}
|
|
6456
|
+
function invalidatePersistedSavedHistoryIndex(agentType, dir) {
|
|
6457
|
+
try {
|
|
6458
|
+
fs3.rmSync(getSavedHistoryIndexFilePath(dir), { force: true });
|
|
6459
|
+
} catch {
|
|
6460
|
+
}
|
|
6461
|
+
savedHistorySessionCache.delete(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"));
|
|
6462
|
+
}
|
|
6463
|
+
function buildSavedHistoryIndexFileSignature(dir) {
|
|
6464
|
+
try {
|
|
6465
|
+
const stat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
6466
|
+
return `index:${stat.size}:${Math.trunc(stat.mtimeMs)}`;
|
|
6467
|
+
} catch {
|
|
6468
|
+
return "index:missing";
|
|
6469
|
+
}
|
|
6470
|
+
}
|
|
6471
|
+
function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
6472
|
+
try {
|
|
6473
|
+
const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
6474
|
+
const files = listHistoryFiles(dir);
|
|
6475
|
+
for (const file of files) {
|
|
6476
|
+
const stat = fs3.statSync(path7.join(dir, file));
|
|
6477
|
+
if (stat.mtimeMs > indexStat.mtimeMs) return true;
|
|
6478
|
+
}
|
|
6479
|
+
return false;
|
|
6480
|
+
} catch {
|
|
6481
|
+
return true;
|
|
6482
|
+
}
|
|
6483
|
+
}
|
|
6484
|
+
function buildSavedHistoryFileSignature(dir, file) {
|
|
6485
|
+
try {
|
|
6486
|
+
const stat = fs3.statSync(path7.join(dir, file));
|
|
6487
|
+
return `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}`;
|
|
6488
|
+
} catch {
|
|
6489
|
+
return `${file}:missing`;
|
|
6490
|
+
}
|
|
6491
|
+
}
|
|
6492
|
+
function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
|
|
6493
|
+
const filePath = path7.join(dir, file);
|
|
6494
|
+
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
6495
|
+
const currentEntry = entries.get(file) || null;
|
|
6496
|
+
const nextSummary = updater(currentEntry?.summary || null);
|
|
6497
|
+
const nextEntry = {
|
|
6498
|
+
signature: buildSavedHistoryFileSignature(dir, file),
|
|
6499
|
+
summary: nextSummary
|
|
6500
|
+
};
|
|
6501
|
+
entries.set(file, nextEntry);
|
|
6502
|
+
savedHistoryFileSummaryCache.set(filePath, nextEntry);
|
|
6503
|
+
return nextEntry;
|
|
6504
|
+
});
|
|
6505
|
+
if (!result) return;
|
|
6506
|
+
if (result.summary?.historySessionId && shouldScheduleSavedHistoryRollupForSignature(result.signature)) {
|
|
6507
|
+
scheduleSavedHistoryRollup(agentType, result.summary.historySessionId);
|
|
6508
|
+
}
|
|
6509
|
+
}
|
|
6510
|
+
function updateSavedHistoryIndexForSessionStart(agentType, dir, file, historySessionId, workspace) {
|
|
6511
|
+
const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId);
|
|
6512
|
+
const normalizedWorkspace = String(workspace || "").trim();
|
|
6513
|
+
if (!normalizedSessionId || !normalizedWorkspace) return;
|
|
6514
|
+
persistSavedHistoryFileSummaryEntry(agentType, dir, file, (currentSummary) => ({
|
|
6515
|
+
file,
|
|
6516
|
+
historySessionId: normalizedSessionId,
|
|
6517
|
+
messageCount: currentSummary?.messageCount || 0,
|
|
6518
|
+
firstMessageAt: currentSummary?.firstMessageAt || 0,
|
|
6519
|
+
lastMessageAt: currentSummary?.lastMessageAt || 0,
|
|
6520
|
+
sessionTitle: currentSummary?.sessionTitle,
|
|
6521
|
+
preview: currentSummary?.preview,
|
|
6522
|
+
workspace: normalizedWorkspace
|
|
6523
|
+
}));
|
|
6524
|
+
}
|
|
6525
|
+
function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, historySessionId, messages) {
|
|
6526
|
+
const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId || "");
|
|
6527
|
+
if (!normalizedSessionId || messages.length === 0) return;
|
|
6528
|
+
persistSavedHistoryFileSummaryEntry(agentType, dir, file, (currentSummary) => {
|
|
6529
|
+
const nextSummary = {
|
|
6530
|
+
file,
|
|
6531
|
+
historySessionId: normalizedSessionId,
|
|
6532
|
+
messageCount: currentSummary?.messageCount || 0,
|
|
6533
|
+
firstMessageAt: currentSummary?.firstMessageAt || 0,
|
|
6534
|
+
lastMessageAt: currentSummary?.lastMessageAt || 0,
|
|
6535
|
+
sessionTitle: currentSummary?.sessionTitle,
|
|
6536
|
+
preview: currentSummary?.preview,
|
|
6537
|
+
workspace: currentSummary?.workspace
|
|
6538
|
+
};
|
|
6539
|
+
for (const message of messages) {
|
|
6540
|
+
if (!message || message.historySessionId !== historySessionId) continue;
|
|
6541
|
+
if (message.kind === "session_start") {
|
|
6542
|
+
if (message.workspace) nextSummary.workspace = message.workspace;
|
|
6543
|
+
continue;
|
|
6544
|
+
}
|
|
6545
|
+
nextSummary.messageCount += 1;
|
|
6546
|
+
if (!nextSummary.firstMessageAt || message.receivedAt < nextSummary.firstMessageAt) {
|
|
6547
|
+
nextSummary.firstMessageAt = message.receivedAt;
|
|
6548
|
+
}
|
|
6549
|
+
if (!nextSummary.lastMessageAt || message.receivedAt >= nextSummary.lastMessageAt) {
|
|
6550
|
+
nextSummary.lastMessageAt = message.receivedAt;
|
|
6551
|
+
if (message.sessionTitle) nextSummary.sessionTitle = message.sessionTitle;
|
|
6552
|
+
if (message.role !== "system" && message.content.trim()) nextSummary.preview = message.content.trim();
|
|
6553
|
+
} else if (message.sessionTitle) {
|
|
6554
|
+
nextSummary.sessionTitle = message.sessionTitle;
|
|
6555
|
+
}
|
|
6556
|
+
if (!nextSummary.preview && message.role !== "system" && message.content.trim()) {
|
|
6557
|
+
nextSummary.preview = message.content.trim();
|
|
6558
|
+
}
|
|
6559
|
+
}
|
|
6560
|
+
return nextSummary;
|
|
6561
|
+
});
|
|
6562
|
+
}
|
|
6563
|
+
function computeSavedHistoryFileSummary(agentType, dir, file) {
|
|
6564
|
+
const historySessionId = extractSavedHistorySessionIdFromFile(agentType, file);
|
|
6565
|
+
if (!historySessionId) return null;
|
|
6566
|
+
const filePath = path7.join(dir, file);
|
|
6567
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
6568
|
+
const lines = content.split("\n").filter(Boolean);
|
|
6569
|
+
let messageCount = 0;
|
|
6570
|
+
let firstMessageAt = 0;
|
|
6571
|
+
let lastMessageAt = 0;
|
|
6572
|
+
let sessionTitle = "";
|
|
6573
|
+
let preview = "";
|
|
6574
|
+
let workspace = "";
|
|
6575
|
+
for (const line of lines) {
|
|
6576
|
+
let parsed = null;
|
|
6577
|
+
try {
|
|
6578
|
+
parsed = JSON.parse(line);
|
|
6579
|
+
} catch {
|
|
6580
|
+
parsed = null;
|
|
6581
|
+
}
|
|
6582
|
+
if (!parsed || parsed.historySessionId !== historySessionId) continue;
|
|
6583
|
+
if (parsed.kind === "session_start") {
|
|
6584
|
+
if (!workspace && parsed.workspace) workspace = parsed.workspace;
|
|
6585
|
+
continue;
|
|
6586
|
+
}
|
|
6587
|
+
messageCount += 1;
|
|
6588
|
+
if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
|
|
6589
|
+
if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
|
|
6590
|
+
if (parsed.sessionTitle) sessionTitle = parsed.sessionTitle;
|
|
6591
|
+
if (parsed.role !== "system" && parsed.content.trim()) preview = parsed.content.trim();
|
|
6592
|
+
}
|
|
6593
|
+
if (messageCount === 0 || !lastMessageAt) return null;
|
|
6594
|
+
return {
|
|
6595
|
+
file,
|
|
6596
|
+
historySessionId,
|
|
6597
|
+
messageCount,
|
|
6598
|
+
firstMessageAt,
|
|
6599
|
+
lastMessageAt,
|
|
6600
|
+
sessionTitle: sessionTitle || void 0,
|
|
6601
|
+
preview: preview || void 0,
|
|
6602
|
+
workspace: workspace || void 0
|
|
6603
|
+
};
|
|
6604
|
+
}
|
|
6605
|
+
function shouldScheduleSavedHistoryRollupForSignature(signature) {
|
|
6606
|
+
const parts = String(signature || "").split(":");
|
|
6607
|
+
const size = Number(parts[1] || 0);
|
|
6608
|
+
return shouldScheduleSavedHistoryRollup(size);
|
|
6609
|
+
}
|
|
6610
|
+
function scheduleSavedHistoryRollup(agentType, historySessionId) {
|
|
6611
|
+
const key = `${agentType}:${historySessionId}`;
|
|
6612
|
+
if (!historySessionId || savedHistoryRollupInFlight.has(key)) return;
|
|
6613
|
+
savedHistoryRollupInFlight.add(key);
|
|
6614
|
+
setTimeout(() => {
|
|
6615
|
+
try {
|
|
6616
|
+
new ChatHistoryWriter().compactHistorySession(agentType, historySessionId);
|
|
6617
|
+
} finally {
|
|
6618
|
+
savedHistoryRollupInFlight.delete(key);
|
|
6619
|
+
}
|
|
6620
|
+
}, 0);
|
|
6621
|
+
}
|
|
6622
|
+
function scheduleSavedHistoryBackgroundRefresh(agentType, dir) {
|
|
6623
|
+
const key = `${agentType}:${dir}`;
|
|
6624
|
+
if (savedHistoryBackgroundRefresh.has(key)) return;
|
|
6625
|
+
savedHistoryBackgroundRefresh.add(key);
|
|
6626
|
+
setTimeout(() => {
|
|
6627
|
+
try {
|
|
6628
|
+
if (!fs3.existsSync(dir)) return;
|
|
6629
|
+
const files = listHistoryFiles(dir);
|
|
6630
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
6631
|
+
const persistedEntries = loadPersistedSavedHistoryIndex(dir);
|
|
6632
|
+
const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
|
|
6633
|
+
savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
|
|
6634
|
+
const refreshedIndexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
6635
|
+
savedHistorySessionCache.set(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"), {
|
|
6636
|
+
signature: refreshedIndexSignature,
|
|
6637
|
+
summaries: computed.summaries || []
|
|
6638
|
+
});
|
|
6639
|
+
for (const [file, entry] of Array.from(computed.persistedEntries.entries())) {
|
|
6640
|
+
if (!entry?.summary || !shouldScheduleSavedHistoryRollupForSignature(entry.signature)) continue;
|
|
6641
|
+
scheduleSavedHistoryRollup(agentType, entry.summary.historySessionId);
|
|
6642
|
+
}
|
|
6643
|
+
} catch {
|
|
6644
|
+
} finally {
|
|
6645
|
+
savedHistoryBackgroundRefresh.delete(key);
|
|
6646
|
+
}
|
|
6647
|
+
}, 0);
|
|
6648
|
+
}
|
|
6649
|
+
function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries) {
|
|
6650
|
+
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
6651
|
+
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
6652
|
+
for (const file of files.slice().sort()) {
|
|
6653
|
+
const filePath = path7.join(dir, file);
|
|
6654
|
+
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
6655
|
+
const cached = savedHistoryFileSummaryCache.get(filePath);
|
|
6656
|
+
const persisted = persistedEntries.get(file);
|
|
6657
|
+
const reusableEntry = cached?.signature === signature ? cached : persisted?.signature === signature ? persisted : null;
|
|
6658
|
+
const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(agentType, dir, file);
|
|
6659
|
+
const nextEntry = reusableEntry || {
|
|
6660
|
+
signature,
|
|
6661
|
+
summary: fileSummary
|
|
6662
|
+
};
|
|
6663
|
+
if (!reusableEntry) {
|
|
6664
|
+
nextEntry.signature = signature;
|
|
6665
|
+
nextEntry.summary = fileSummary;
|
|
6666
|
+
}
|
|
6667
|
+
savedHistoryFileSummaryCache.set(filePath, nextEntry);
|
|
6668
|
+
nextPersistedEntries.set(file, nextEntry);
|
|
6669
|
+
if (!fileSummary) continue;
|
|
6670
|
+
const existing = summaryBySessionId.get(fileSummary.historySessionId);
|
|
6671
|
+
if (fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) {
|
|
6672
|
+
continue;
|
|
6673
|
+
}
|
|
6674
|
+
if (!existing) {
|
|
6675
|
+
summaryBySessionId.set(fileSummary.historySessionId, {
|
|
6676
|
+
historySessionId: fileSummary.historySessionId,
|
|
6677
|
+
sessionTitle: fileSummary.sessionTitle,
|
|
6678
|
+
messageCount: fileSummary.messageCount,
|
|
6679
|
+
firstMessageAt: fileSummary.firstMessageAt,
|
|
6680
|
+
lastMessageAt: fileSummary.lastMessageAt,
|
|
6681
|
+
preview: fileSummary.preview,
|
|
6682
|
+
workspace: fileSummary.workspace
|
|
6683
|
+
});
|
|
6684
|
+
continue;
|
|
6685
|
+
}
|
|
6686
|
+
existing.messageCount += fileSummary.messageCount;
|
|
6687
|
+
if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
|
|
6688
|
+
existing.firstMessageAt = fileSummary.firstMessageAt;
|
|
6689
|
+
}
|
|
6690
|
+
if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
|
|
6691
|
+
existing.lastMessageAt = fileSummary.lastMessageAt;
|
|
6692
|
+
if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
|
|
6693
|
+
if (fileSummary.preview) existing.preview = fileSummary.preview;
|
|
6694
|
+
}
|
|
6695
|
+
if (!existing.workspace && fileSummary.workspace) {
|
|
6696
|
+
existing.workspace = fileSummary.workspace;
|
|
6697
|
+
}
|
|
6198
6698
|
}
|
|
6199
|
-
|
|
6200
|
-
|
|
6699
|
+
return {
|
|
6700
|
+
summaries: Array.from(summaryBySessionId.values()).sort((a, b) => b.lastMessageAt - a.lastMessageAt),
|
|
6701
|
+
persistedEntries: nextPersistedEntries
|
|
6702
|
+
};
|
|
6201
6703
|
}
|
|
6202
6704
|
var ChatHistoryWriter = class {
|
|
6203
6705
|
/** Last seen message count per agent (deduplication) */
|
|
@@ -6272,9 +6774,11 @@ var ChatHistoryWriter = class {
|
|
|
6272
6774
|
fs3.mkdirSync(dir, { recursive: true });
|
|
6273
6775
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
6274
6776
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
6275
|
-
const
|
|
6777
|
+
const fileName = `${filePrefix}${date}.jsonl`;
|
|
6778
|
+
const filePath = path7.join(dir, fileName);
|
|
6276
6779
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
6277
6780
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
6781
|
+
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
6278
6782
|
const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
|
|
6279
6783
|
if (!historySessionId && messages.length < prevCount * 0.5 && prevCount > 3) {
|
|
6280
6784
|
seenHashes.clear();
|
|
@@ -6365,7 +6869,8 @@ var ChatHistoryWriter = class {
|
|
|
6365
6869
|
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
6366
6870
|
fs3.mkdirSync(dir, { recursive: true });
|
|
6367
6871
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
6368
|
-
const
|
|
6872
|
+
const fileName = `${this.sanitize(id)}_${date}.jsonl`;
|
|
6873
|
+
const filePath = path7.join(dir, fileName);
|
|
6369
6874
|
const record = {
|
|
6370
6875
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6371
6876
|
receivedAt: Date.now(),
|
|
@@ -6378,6 +6883,7 @@ var ChatHistoryWriter = class {
|
|
|
6378
6883
|
workspace: ws
|
|
6379
6884
|
};
|
|
6380
6885
|
fs3.appendFileSync(filePath, JSON.stringify(record) + "\n", "utf-8");
|
|
6886
|
+
updateSavedHistoryIndexForSessionStart(agentType, dir, fileName, id, ws);
|
|
6381
6887
|
} catch {
|
|
6382
6888
|
}
|
|
6383
6889
|
}
|
|
@@ -6443,6 +6949,7 @@ var ChatHistoryWriter = class {
|
|
|
6443
6949
|
}
|
|
6444
6950
|
fs3.unlinkSync(sourcePath);
|
|
6445
6951
|
}
|
|
6952
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
6446
6953
|
} catch {
|
|
6447
6954
|
}
|
|
6448
6955
|
}
|
|
@@ -6492,6 +6999,7 @@ var ChatHistoryWriter = class {
|
|
|
6492
6999
|
fs3.writeFileSync(filePath, `${collapsed.map((entry) => JSON.stringify(entry)).join("\n")}
|
|
6493
7000
|
`, "utf-8");
|
|
6494
7001
|
}
|
|
7002
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
6495
7003
|
} catch {
|
|
6496
7004
|
}
|
|
6497
7005
|
}
|
|
@@ -6511,13 +7019,18 @@ var ChatHistoryWriter = class {
|
|
|
6511
7019
|
for (const dir of agentDirs) {
|
|
6512
7020
|
const dirPath = path7.join(HISTORY_DIR, dir.name);
|
|
6513
7021
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
7022
|
+
let removedAny = false;
|
|
6514
7023
|
for (const file of files) {
|
|
6515
7024
|
const filePath = path7.join(dirPath, file);
|
|
6516
7025
|
const stat = fs3.statSync(filePath);
|
|
6517
7026
|
if (stat.mtimeMs < cutoff) {
|
|
6518
7027
|
fs3.unlinkSync(filePath);
|
|
7028
|
+
removedAny = true;
|
|
6519
7029
|
}
|
|
6520
7030
|
}
|
|
7031
|
+
if (removedAny) {
|
|
7032
|
+
invalidatePersistedSavedHistoryIndex(dir.name, dirPath);
|
|
7033
|
+
}
|
|
6521
7034
|
}
|
|
6522
7035
|
} catch {
|
|
6523
7036
|
}
|
|
@@ -6583,18 +7096,51 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
6583
7096
|
savedHistorySessionCache.delete(sanitized);
|
|
6584
7097
|
return { sessions: [], hasMore: false };
|
|
6585
7098
|
}
|
|
6586
|
-
const files = listHistoryFiles(dir);
|
|
6587
|
-
const signature = buildSavedHistoryCacheSignature(dir, files);
|
|
6588
7099
|
const cached = savedHistorySessionCache.get(sanitized);
|
|
6589
|
-
const
|
|
6590
|
-
|
|
7100
|
+
const offset = Math.max(0, options.offset || 0);
|
|
7101
|
+
const limit = Math.max(1, options.limit || 30);
|
|
7102
|
+
const indexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
7103
|
+
let cacheWasInvalidated = false;
|
|
7104
|
+
if (cached) {
|
|
7105
|
+
const cacheLooksPersisted = cached.signature.startsWith("index:");
|
|
7106
|
+
const cacheStillValid = cacheLooksPersisted ? cached.signature === indexSignature : (() => {
|
|
7107
|
+
const files2 = listHistoryFiles(dir);
|
|
7108
|
+
const fileSignatures2 = buildSavedHistoryFileSignatureMap(dir, files2);
|
|
7109
|
+
return cached.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
|
|
7110
|
+
})();
|
|
7111
|
+
if (cacheStillValid) {
|
|
7112
|
+
const sliced2 = cached.summaries.slice(offset, offset + limit);
|
|
7113
|
+
return {
|
|
7114
|
+
sessions: sliced2,
|
|
7115
|
+
hasMore: cached.summaries.length > offset + limit
|
|
7116
|
+
};
|
|
7117
|
+
}
|
|
7118
|
+
cacheWasInvalidated = true;
|
|
7119
|
+
}
|
|
7120
|
+
const persistedSessions = readPersistedSavedHistorySessionSummaries(dir);
|
|
7121
|
+
if (!cacheWasInvalidated && persistedSessions?.length && !historyDirectoryHasFilesNewerThanIndex(dir)) {
|
|
6591
7122
|
savedHistorySessionCache.set(sanitized, {
|
|
6592
|
-
signature,
|
|
6593
|
-
summaries
|
|
7123
|
+
signature: indexSignature,
|
|
7124
|
+
summaries: persistedSessions
|
|
6594
7125
|
});
|
|
7126
|
+
scheduleSavedHistoryBackgroundRefresh(agentType, dir);
|
|
7127
|
+
const sliced2 = persistedSessions.slice(offset, offset + limit);
|
|
7128
|
+
return {
|
|
7129
|
+
sessions: sliced2,
|
|
7130
|
+
hasMore: persistedSessions.length > offset + limit
|
|
7131
|
+
};
|
|
6595
7132
|
}
|
|
6596
|
-
const
|
|
6597
|
-
const
|
|
7133
|
+
const files = listHistoryFiles(dir);
|
|
7134
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
7135
|
+
const signature = buildSavedHistoryCacheSignature(files, fileSignatures);
|
|
7136
|
+
const persistedEntries = loadPersistedSavedHistoryIndex(dir);
|
|
7137
|
+
const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
|
|
7138
|
+
const summaries = computed.summaries || [];
|
|
7139
|
+
savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
|
|
7140
|
+
savedHistorySessionCache.set(sanitized, {
|
|
7141
|
+
signature,
|
|
7142
|
+
summaries
|
|
7143
|
+
});
|
|
6598
7144
|
const sliced = summaries.slice(offset, offset + limit);
|
|
6599
7145
|
return {
|
|
6600
7146
|
sessions: sliced,
|
|
@@ -8232,7 +8778,7 @@ function shouldIncludeSessionMetadata(profile) {
|
|
|
8232
8778
|
return profile !== "live";
|
|
8233
8779
|
}
|
|
8234
8780
|
function shouldIncludeRuntimeMetadata(profile) {
|
|
8235
|
-
return
|
|
8781
|
+
return true;
|
|
8236
8782
|
}
|
|
8237
8783
|
function findCdpManager(cdpManagers, key) {
|
|
8238
8784
|
const exact = cdpManagers.get(key);
|
|
@@ -8347,6 +8893,21 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
8347
8893
|
lastUpdated: ext.lastUpdated
|
|
8348
8894
|
};
|
|
8349
8895
|
}
|
|
8896
|
+
function shouldIncludeExtensionSession(ext) {
|
|
8897
|
+
const status = String(ext.status || "").trim().toLowerCase();
|
|
8898
|
+
const hasActiveChat = !!ext.activeChat;
|
|
8899
|
+
const hasMessages = Array.isArray(ext.activeChat?.messages) && ext.activeChat.messages.length > 0;
|
|
8900
|
+
const hasModal = !!ext.activeChat?.activeModal;
|
|
8901
|
+
const hasStreams = Array.isArray(ext.agentStreams) && ext.agentStreams.length > 0;
|
|
8902
|
+
const hasProviderSessionId = typeof ext.providerSessionId === "string" && ext.providerSessionId.trim().length > 0;
|
|
8903
|
+
const hasControlValues = !!(ext.controlValues && Object.keys(ext.controlValues).length > 0);
|
|
8904
|
+
const hasProviderControls = Array.isArray(ext.providerControls) && ext.providerControls.length > 0;
|
|
8905
|
+
const hasOpenPanelCapability = Array.isArray(ext.sessionCapabilities) && ext.sessionCapabilities.includes("open_panel");
|
|
8906
|
+
const hasSummaryMetadata = !!ext.summaryMetadata;
|
|
8907
|
+
const hasError = typeof ext.errorMessage === "string" && ext.errorMessage.trim().length > 0;
|
|
8908
|
+
const hasInterestingStatus = !!status && !["idle", "panel_hidden", "disconnected", "not_monitored"].includes(status);
|
|
8909
|
+
return hasActiveChat || hasMessages || hasModal || hasStreams || hasProviderSessionId || hasControlValues || hasProviderControls || hasOpenPanelCapability || hasSummaryMetadata || hasError || hasInterestingStatus;
|
|
8910
|
+
}
|
|
8350
8911
|
function buildCliSession(state, options) {
|
|
8351
8912
|
const profile = options.profile || "full";
|
|
8352
8913
|
const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
|
|
@@ -8372,8 +8933,12 @@ function buildCliSession(state, options) {
|
|
|
8372
8933
|
runtimeKey: state.runtime?.runtimeKey,
|
|
8373
8934
|
runtimeDisplayName: state.runtime?.displayName,
|
|
8374
8935
|
runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
|
|
8936
|
+
runtimeLifecycle: state.runtime?.lifecycle ?? null,
|
|
8937
|
+
runtimeSurfaceKind: state.runtime?.surfaceKind,
|
|
8375
8938
|
runtimeWriteOwner: state.runtime?.writeOwner || null,
|
|
8376
|
-
runtimeAttachedClients: state.runtime?.attachedClients || []
|
|
8939
|
+
runtimeAttachedClients: state.runtime?.attachedClients || [],
|
|
8940
|
+
runtimeRestoredFromStorage: state.runtime?.restoredFromStorage === true,
|
|
8941
|
+
runtimeRecoveryState: state.runtime?.recoveryState ?? null
|
|
8377
8942
|
},
|
|
8378
8943
|
mode: state.mode,
|
|
8379
8944
|
resume: state.resume,
|
|
@@ -8430,6 +8995,7 @@ function buildSessionEntries(allStates, cdpManagers, options = {}) {
|
|
|
8430
8995
|
for (const state of ideStates) {
|
|
8431
8996
|
sessions.push(buildIdeWorkspaceSession(state, cdpManagers, options));
|
|
8432
8997
|
for (const ext of state.extensions) {
|
|
8998
|
+
if (!shouldIncludeExtensionSession(ext)) continue;
|
|
8433
8999
|
sessions.push(buildExtensionAgentSession(state, ext, options));
|
|
8434
9000
|
}
|
|
8435
9001
|
}
|
|
@@ -10600,7 +11166,9 @@ function applyProviderPatch(h, args, payload) {
|
|
|
10600
11166
|
});
|
|
10601
11167
|
}
|
|
10602
11168
|
async function executeProviderScript(h, args, scriptName) {
|
|
10603
|
-
const
|
|
11169
|
+
const explicitTargetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
11170
|
+
const targetSession = explicitTargetSessionId ? h.ctx.sessionRegistry?.get(explicitTargetSessionId) : void 0;
|
|
11171
|
+
const resolvedProviderType = targetSession?.providerType || h.currentSession?.providerType || h.currentProviderType || args?.agentType || args?.providerType;
|
|
10604
11172
|
if (!resolvedProviderType) return { success: false, error: "targetSessionId or providerType is required" };
|
|
10605
11173
|
const loader = h.ctx.providerLoader;
|
|
10606
11174
|
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
@@ -10643,16 +11211,16 @@ async function executeProviderScript(h, args, scriptName) {
|
|
|
10643
11211
|
const scriptFn = provider.scripts[actualScriptName];
|
|
10644
11212
|
const scriptCode = scriptFn(normalizedArgs);
|
|
10645
11213
|
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
10646
|
-
const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : h.currentSession?.cdpManagerKey || h.currentManagerKey;
|
|
11214
|
+
const cdpKey = provider.category === "ide" ? targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey;
|
|
10647
11215
|
LOG.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
|
|
10648
11216
|
const cdp = h.getCdp(cdpKey);
|
|
10649
11217
|
if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
|
|
10650
11218
|
try {
|
|
10651
11219
|
let result;
|
|
10652
11220
|
if (provider.category === "extension") {
|
|
10653
|
-
const runtimeSessionId = h.currentSession?.sessionId
|
|
11221
|
+
const runtimeSessionId = explicitTargetSessionId || h.currentSession?.sessionId;
|
|
10654
11222
|
if (!runtimeSessionId) return { success: false, error: `No target session found for ${resolvedProviderType}` };
|
|
10655
|
-
const parentSessionId = h.currentSession?.parentSessionId;
|
|
11223
|
+
const parentSessionId = targetSession?.parentSessionId || h.currentSession?.parentSessionId;
|
|
10656
11224
|
if (parentSessionId) {
|
|
10657
11225
|
await h.agentStream?.setActiveSession(cdp, parentSessionId, runtimeSessionId);
|
|
10658
11226
|
await h.agentStream?.syncActiveSession(cdp, parentSessionId);
|
|
@@ -11655,8 +12223,12 @@ var CliProviderInstance = class {
|
|
|
11655
12223
|
runtimeKey: runtime.runtimeKey,
|
|
11656
12224
|
displayName: runtime.displayName,
|
|
11657
12225
|
workspaceLabel: runtime.workspaceLabel,
|
|
12226
|
+
lifecycle: runtime.lifecycle ?? null,
|
|
12227
|
+
surfaceKind: runtime.surfaceKind,
|
|
11658
12228
|
writeOwner: runtime.writeOwner || null,
|
|
11659
|
-
attachedClients: runtime.attachedClients || []
|
|
12229
|
+
attachedClients: runtime.attachedClients || [],
|
|
12230
|
+
restoredFromStorage: runtime.restoredFromStorage === true,
|
|
12231
|
+
recoveryState: runtime.recoveryState ?? null
|
|
11660
12232
|
} : void 0,
|
|
11661
12233
|
resume: this.provider.resume,
|
|
11662
12234
|
controlValues: surface.controlValues,
|
|
@@ -15963,61 +16535,6 @@ cleanOldFiles();
|
|
|
15963
16535
|
// src/commands/router.ts
|
|
15964
16536
|
init_logger();
|
|
15965
16537
|
|
|
15966
|
-
// src/session-host/runtime-surface.ts
|
|
15967
|
-
var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
15968
|
-
function isSessionHostLiveRuntime(record) {
|
|
15969
|
-
const lifecycle = String(record?.lifecycle || "").trim();
|
|
15970
|
-
return LIVE_LIFECYCLES.has(lifecycle);
|
|
15971
|
-
}
|
|
15972
|
-
function getSessionHostRecoveryLabel(meta) {
|
|
15973
|
-
const recoveryState = typeof meta?.runtimeRecoveryState === "string" ? String(meta.runtimeRecoveryState).trim() : "";
|
|
15974
|
-
if (!recoveryState) return null;
|
|
15975
|
-
if (recoveryState === "auto_resumed") return "restored after restart";
|
|
15976
|
-
if (recoveryState === "resume_failed") return "restore failed";
|
|
15977
|
-
if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
|
|
15978
|
-
if (recoveryState === "orphan_snapshot") return "snapshot recovered";
|
|
15979
|
-
return recoveryState.replace(/_/g, " ");
|
|
15980
|
-
}
|
|
15981
|
-
function isSessionHostRecoverySnapshot(record) {
|
|
15982
|
-
if (!record) return false;
|
|
15983
|
-
if (isSessionHostLiveRuntime(record)) return false;
|
|
15984
|
-
const lifecycle = String(record.lifecycle || "").trim();
|
|
15985
|
-
if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
|
|
15986
|
-
return false;
|
|
15987
|
-
}
|
|
15988
|
-
const meta = record.meta || void 0;
|
|
15989
|
-
if (meta?.restoredFromStorage === true) return true;
|
|
15990
|
-
return getSessionHostRecoveryLabel(meta) !== null;
|
|
15991
|
-
}
|
|
15992
|
-
function getSessionHostSurfaceKind(record) {
|
|
15993
|
-
if (isSessionHostLiveRuntime(record)) return "live_runtime";
|
|
15994
|
-
if (isSessionHostRecoverySnapshot(record)) return "recovery_snapshot";
|
|
15995
|
-
return "inactive_record";
|
|
15996
|
-
}
|
|
15997
|
-
function partitionSessionHostRecords(records) {
|
|
15998
|
-
const liveRuntimes = [];
|
|
15999
|
-
const recoverySnapshots = [];
|
|
16000
|
-
const inactiveRecords = [];
|
|
16001
|
-
for (const record of records) {
|
|
16002
|
-
const kind = getSessionHostSurfaceKind(record);
|
|
16003
|
-
if (kind === "live_runtime") {
|
|
16004
|
-
liveRuntimes.push(record);
|
|
16005
|
-
} else if (kind === "recovery_snapshot") {
|
|
16006
|
-
recoverySnapshots.push(record);
|
|
16007
|
-
} else {
|
|
16008
|
-
inactiveRecords.push(record);
|
|
16009
|
-
}
|
|
16010
|
-
}
|
|
16011
|
-
return {
|
|
16012
|
-
liveRuntimes,
|
|
16013
|
-
recoverySnapshots,
|
|
16014
|
-
inactiveRecords
|
|
16015
|
-
};
|
|
16016
|
-
}
|
|
16017
|
-
function partitionSessionHostDiagnosticsSessions(records) {
|
|
16018
|
-
return partitionSessionHostRecords(records || []);
|
|
16019
|
-
}
|
|
16020
|
-
|
|
16021
16538
|
// src/status/snapshot.ts
|
|
16022
16539
|
var os16 = __toESM(require("os"));
|
|
16023
16540
|
init_config();
|
|
@@ -17575,6 +18092,23 @@ function prepareSessionModalUpdate(input) {
|
|
|
17575
18092
|
};
|
|
17576
18093
|
}
|
|
17577
18094
|
|
|
18095
|
+
// src/chat/async-batch.ts
|
|
18096
|
+
async function runAsyncBatch(items, worker, options = {}) {
|
|
18097
|
+
const list = Array.from(items);
|
|
18098
|
+
if (list.length === 0) return;
|
|
18099
|
+
const concurrency = Math.max(1, Math.min(list.length, Math.floor(options.concurrency || 1)));
|
|
18100
|
+
let nextIndex = 0;
|
|
18101
|
+
const runners = Array.from({ length: concurrency }, async () => {
|
|
18102
|
+
while (true) {
|
|
18103
|
+
const currentIndex = nextIndex;
|
|
18104
|
+
nextIndex += 1;
|
|
18105
|
+
if (currentIndex >= list.length) return;
|
|
18106
|
+
await worker(list[currentIndex], currentIndex);
|
|
18107
|
+
}
|
|
18108
|
+
});
|
|
18109
|
+
await Promise.all(runners);
|
|
18110
|
+
}
|
|
18111
|
+
|
|
17578
18112
|
// src/agent-stream/provider-adapter.ts
|
|
17579
18113
|
init_read_chat_contract();
|
|
17580
18114
|
init_chat_message_normalization();
|
|
@@ -18043,10 +18577,12 @@ var DaemonAgentStreamManager = class {
|
|
|
18043
18577
|
}
|
|
18044
18578
|
}
|
|
18045
18579
|
/** Collect active extension session state */
|
|
18046
|
-
async collectActiveSession(cdp, parentSessionId) {
|
|
18580
|
+
async collectActiveSession(cdp, parentSessionId, attemptedSessionIds = /* @__PURE__ */ new Set(), originSessionId) {
|
|
18047
18581
|
if (!this.enabled) return null;
|
|
18048
18582
|
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
18049
18583
|
if (!activeSessionId) return null;
|
|
18584
|
+
const resolvedOriginSessionId = originSessionId || activeSessionId;
|
|
18585
|
+
attemptedSessionIds.add(activeSessionId);
|
|
18050
18586
|
let agent = this.managedBySessionId.get(activeSessionId);
|
|
18051
18587
|
if (!agent) {
|
|
18052
18588
|
agent = await this.connectManagedSession(cdp, parentSessionId, activeSessionId) || void 0;
|
|
@@ -18059,18 +18595,44 @@ var DaemonAgentStreamManager = class {
|
|
|
18059
18595
|
try {
|
|
18060
18596
|
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
18061
18597
|
const state = await agent.adapter.readChat(evaluate);
|
|
18062
|
-
const
|
|
18063
|
-
const
|
|
18064
|
-
|
|
18065
|
-
|
|
18598
|
+
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;
|
|
18599
|
+
const normalizedState = {
|
|
18600
|
+
...state,
|
|
18601
|
+
sessionId: agent.runtimeSessionId,
|
|
18602
|
+
...resolvedProviderSessionId ? { providerSessionId: resolvedProviderSessionId } : {}
|
|
18603
|
+
};
|
|
18604
|
+
const stateError = this.getStateError(normalizedState);
|
|
18605
|
+
const selectedModelValue = typeof normalizedState.controlValues?.model === "string" ? normalizedState.controlValues.model : "";
|
|
18606
|
+
LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${normalizedState.status} msgs=${normalizedState.messages?.length || 0} model=${selectedModelValue}${normalizedState.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
|
|
18607
|
+
if (normalizedState.status === "error" && this.isRecoverableSessionError(stateError)) {
|
|
18066
18608
|
throw new Error(stateError);
|
|
18067
18609
|
}
|
|
18068
|
-
agent.lastState =
|
|
18610
|
+
agent.lastState = normalizedState;
|
|
18069
18611
|
agent.lastError = null;
|
|
18070
|
-
if (
|
|
18612
|
+
if (normalizedState.status === "panel_hidden") {
|
|
18613
|
+
const discovered = await cdp.discoverAgentWebviews().catch(() => []);
|
|
18614
|
+
const fallbackTarget = discovered.find((entry) => {
|
|
18615
|
+
if (entry.agentType === type) return false;
|
|
18616
|
+
const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, entry.agentType);
|
|
18617
|
+
return !!fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId);
|
|
18618
|
+
});
|
|
18619
|
+
if (fallbackTarget) {
|
|
18620
|
+
const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, fallbackTarget.agentType);
|
|
18621
|
+
if (fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId)) {
|
|
18622
|
+
this.logFn(`[AgentStream] Active session ${type} is hidden; switching to visible agent ${fallbackTarget.agentType} (${parentSessionId})`);
|
|
18623
|
+
await this.setActiveSession(cdp, parentSessionId, fallbackSessionId);
|
|
18624
|
+
await this.syncActiveSession(cdp, parentSessionId);
|
|
18625
|
+
const fallbackState = await this.collectActiveSession(cdp, parentSessionId, attemptedSessionIds, resolvedOriginSessionId);
|
|
18626
|
+
if (fallbackState?.status === "panel_hidden" && resolvedOriginSessionId !== fallbackSessionId) {
|
|
18627
|
+
await this.setActiveSession(cdp, parentSessionId, resolvedOriginSessionId);
|
|
18628
|
+
await this.syncActiveSession(cdp, parentSessionId);
|
|
18629
|
+
}
|
|
18630
|
+
return fallbackState;
|
|
18631
|
+
}
|
|
18632
|
+
}
|
|
18071
18633
|
agent.lastHiddenCheckTime = Date.now();
|
|
18072
18634
|
}
|
|
18073
|
-
return
|
|
18635
|
+
return normalizedState;
|
|
18074
18636
|
} catch (e) {
|
|
18075
18637
|
const errorMsg = e?.message || String(e);
|
|
18076
18638
|
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
@@ -18366,6 +18928,7 @@ var AgentStreamPoller = class {
|
|
|
18366
18928
|
try {
|
|
18367
18929
|
await agentStreamManager.syncActiveSession(cdp, parentSessionId);
|
|
18368
18930
|
let stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
|
|
18931
|
+
resolvedActiveSessionId = stream?.sessionId || agentStreamManager.getActiveSessionId(parentSessionId) || resolvedActiveSessionId;
|
|
18369
18932
|
if (stream?.status === "waiting_approval") {
|
|
18370
18933
|
const autoApprove = providerLoader.getSettings(stream.agentType).autoApprove !== false;
|
|
18371
18934
|
if (autoApprove && resolvedActiveSessionId) {
|
|
@@ -24346,6 +24909,8 @@ var SessionHostRuntimeTransport = class {
|
|
|
24346
24909
|
runtimeKey: record.runtimeKey,
|
|
24347
24910
|
displayName: record.displayName,
|
|
24348
24911
|
workspaceLabel: record.workspaceLabel,
|
|
24912
|
+
lifecycle: typeof record.lifecycle === "string" ? record.lifecycle : null,
|
|
24913
|
+
surfaceKind: record.surfaceKind,
|
|
24349
24914
|
writeOwner: record.writeOwner ? {
|
|
24350
24915
|
clientId: record.writeOwner.clientId,
|
|
24351
24916
|
ownerType: record.writeOwner.ownerType
|
|
@@ -25071,6 +25636,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
25071
25636
|
resolveChatMessageKind,
|
|
25072
25637
|
resolveDebugRuntimeConfig,
|
|
25073
25638
|
resolveSessionHostAppName,
|
|
25639
|
+
runAsyncBatch,
|
|
25074
25640
|
saveConfig,
|
|
25075
25641
|
saveState,
|
|
25076
25642
|
setDebugRuntimeConfig,
|