@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.mjs
CHANGED
|
@@ -4271,6 +4271,61 @@ function getHostMemorySnapshot() {
|
|
|
4271
4271
|
return { totalMem, freeMem, availableMem };
|
|
4272
4272
|
}
|
|
4273
4273
|
|
|
4274
|
+
// src/session-host/runtime-surface.ts
|
|
4275
|
+
var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
4276
|
+
function isSessionHostLiveRuntime(record) {
|
|
4277
|
+
const lifecycle = String(record?.lifecycle || "").trim();
|
|
4278
|
+
return LIVE_LIFECYCLES.has(lifecycle);
|
|
4279
|
+
}
|
|
4280
|
+
function getSessionHostRecoveryLabel(meta) {
|
|
4281
|
+
const recoveryState = typeof meta?.runtimeRecoveryState === "string" ? String(meta.runtimeRecoveryState).trim() : "";
|
|
4282
|
+
if (!recoveryState) return null;
|
|
4283
|
+
if (recoveryState === "auto_resumed") return "restored after restart";
|
|
4284
|
+
if (recoveryState === "resume_failed") return "restore failed";
|
|
4285
|
+
if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
|
|
4286
|
+
if (recoveryState === "orphan_snapshot") return "snapshot recovered";
|
|
4287
|
+
return recoveryState.replace(/_/g, " ");
|
|
4288
|
+
}
|
|
4289
|
+
function isSessionHostRecoverySnapshot(record) {
|
|
4290
|
+
if (!record) return false;
|
|
4291
|
+
if (isSessionHostLiveRuntime(record)) return false;
|
|
4292
|
+
const lifecycle = String(record.lifecycle || "").trim();
|
|
4293
|
+
if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
|
|
4294
|
+
return false;
|
|
4295
|
+
}
|
|
4296
|
+
const meta = record.meta || void 0;
|
|
4297
|
+
if (meta?.restoredFromStorage === true) return true;
|
|
4298
|
+
return getSessionHostRecoveryLabel(meta) !== null;
|
|
4299
|
+
}
|
|
4300
|
+
function getSessionHostSurfaceKind(record) {
|
|
4301
|
+
if (isSessionHostLiveRuntime(record)) return "live_runtime";
|
|
4302
|
+
if (isSessionHostRecoverySnapshot(record)) return "recovery_snapshot";
|
|
4303
|
+
return "inactive_record";
|
|
4304
|
+
}
|
|
4305
|
+
function partitionSessionHostRecords(records) {
|
|
4306
|
+
const liveRuntimes = [];
|
|
4307
|
+
const recoverySnapshots = [];
|
|
4308
|
+
const inactiveRecords = [];
|
|
4309
|
+
for (const record of records) {
|
|
4310
|
+
const kind = getSessionHostSurfaceKind(record);
|
|
4311
|
+
if (kind === "live_runtime") {
|
|
4312
|
+
liveRuntimes.push(record);
|
|
4313
|
+
} else if (kind === "recovery_snapshot") {
|
|
4314
|
+
recoverySnapshots.push(record);
|
|
4315
|
+
} else {
|
|
4316
|
+
inactiveRecords.push(record);
|
|
4317
|
+
}
|
|
4318
|
+
}
|
|
4319
|
+
return {
|
|
4320
|
+
liveRuntimes,
|
|
4321
|
+
recoverySnapshots,
|
|
4322
|
+
inactiveRecords
|
|
4323
|
+
};
|
|
4324
|
+
}
|
|
4325
|
+
function partitionSessionHostDiagnosticsSessions(records) {
|
|
4326
|
+
return partitionSessionHostRecords(records || []);
|
|
4327
|
+
}
|
|
4328
|
+
|
|
4274
4329
|
// src/status/chat-tail-hot-sessions.ts
|
|
4275
4330
|
var DEFAULT_ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
|
|
4276
4331
|
"generating",
|
|
@@ -4278,6 +4333,7 @@ var DEFAULT_ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
|
|
|
4278
4333
|
"starting"
|
|
4279
4334
|
]);
|
|
4280
4335
|
var DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS = 8e3;
|
|
4336
|
+
var LIVE_RUNTIME_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
4281
4337
|
function parseMessageTimestamp(value) {
|
|
4282
4338
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
4283
4339
|
if (typeof value === "string") {
|
|
@@ -4286,6 +4342,23 @@ function parseMessageTimestamp(value) {
|
|
|
4286
4342
|
}
|
|
4287
4343
|
return 0;
|
|
4288
4344
|
}
|
|
4345
|
+
function isDefinitelyNonLiveRuntimeSession(session) {
|
|
4346
|
+
const surfaceKind = String(session?.runtimeSurfaceKind || "").trim();
|
|
4347
|
+
if (surfaceKind === "live_runtime") return false;
|
|
4348
|
+
if (surfaceKind === "recovery_snapshot") return true;
|
|
4349
|
+
if (surfaceKind === "inactive_record") return false;
|
|
4350
|
+
const lifecycle = String(session?.runtimeLifecycle || "").trim();
|
|
4351
|
+
if (lifecycle && LIVE_RUNTIME_LIFECYCLES.has(lifecycle)) return false;
|
|
4352
|
+
const inferredSurfaceKind = getSessionHostSurfaceKind({
|
|
4353
|
+
lifecycle: lifecycle || null,
|
|
4354
|
+
meta: {
|
|
4355
|
+
restoredFromStorage: session?.runtimeRestoredFromStorage === true,
|
|
4356
|
+
...session?.runtimeRecoveryState ? { runtimeRecoveryState: session.runtimeRecoveryState } : {}
|
|
4357
|
+
}
|
|
4358
|
+
});
|
|
4359
|
+
if (inferredSurfaceKind === "recovery_snapshot") return true;
|
|
4360
|
+
return false;
|
|
4361
|
+
}
|
|
4289
4362
|
function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessionIds, options = {}) {
|
|
4290
4363
|
const now = options.now ?? Date.now();
|
|
4291
4364
|
const recentMessageGraceMs = Math.max(
|
|
@@ -4294,9 +4367,14 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
|
|
|
4294
4367
|
);
|
|
4295
4368
|
const activeStatuses = options.activeStatuses ?? DEFAULT_ACTIVE_CHAT_POLL_STATUSES;
|
|
4296
4369
|
const active = /* @__PURE__ */ new Set();
|
|
4370
|
+
const excluded = /* @__PURE__ */ new Set();
|
|
4297
4371
|
for (const session of sessions) {
|
|
4298
4372
|
const sessionId = typeof session?.id === "string" ? session.id : "";
|
|
4299
4373
|
if (!sessionId) continue;
|
|
4374
|
+
if (isDefinitelyNonLiveRuntimeSession(session)) {
|
|
4375
|
+
excluded.add(sessionId);
|
|
4376
|
+
continue;
|
|
4377
|
+
}
|
|
4300
4378
|
const status = String(session?.status || "").toLowerCase();
|
|
4301
4379
|
const lastMessageAt = parseMessageTimestamp(session?.lastMessageAt);
|
|
4302
4380
|
const recentlyUpdated = lastMessageAt > 0 && now - lastMessageAt <= recentMessageGraceMs;
|
|
@@ -4305,7 +4383,7 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
|
|
|
4305
4383
|
}
|
|
4306
4384
|
}
|
|
4307
4385
|
const finalizing = new Set(
|
|
4308
|
-
Array.from(previousHotSessionIds).filter((sessionId) => !active.has(sessionId))
|
|
4386
|
+
Array.from(previousHotSessionIds).filter((sessionId) => !active.has(sessionId) && !excluded.has(sessionId))
|
|
4309
4387
|
);
|
|
4310
4388
|
return { active, finalizing };
|
|
4311
4389
|
}
|
|
@@ -4314,6 +4392,32 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
|
|
|
4314
4392
|
init_logger();
|
|
4315
4393
|
import WebSocket from "ws";
|
|
4316
4394
|
import * as http from "http";
|
|
4395
|
+
function normalizeTitle(value) {
|
|
4396
|
+
return String(value || "").trim().replace(/\s+/g, " ").toLowerCase();
|
|
4397
|
+
}
|
|
4398
|
+
function titlesMatch(lhs, rhs) {
|
|
4399
|
+
const a = normalizeTitle(lhs);
|
|
4400
|
+
const b = normalizeTitle(rhs);
|
|
4401
|
+
if (!a || !b) return false;
|
|
4402
|
+
return a === b || a.includes(b) || b.includes(a);
|
|
4403
|
+
}
|
|
4404
|
+
function resolveCdpPageTarget(params) {
|
|
4405
|
+
const { pages, pinnedTargetId, previousPageTitle } = params;
|
|
4406
|
+
if (pages.length === 0) return { target: null, retargeted: false };
|
|
4407
|
+
if (!pinnedTargetId) {
|
|
4408
|
+
return { target: pages[0] || null, retargeted: false };
|
|
4409
|
+
}
|
|
4410
|
+
const exact = pages.find((page) => page.id === pinnedTargetId);
|
|
4411
|
+
if (exact) return { target: exact, retargeted: false };
|
|
4412
|
+
const titleMatchesList = pages.filter((page) => titlesMatch(page.title, previousPageTitle));
|
|
4413
|
+
if (titleMatchesList.length === 1) {
|
|
4414
|
+
return { target: titleMatchesList[0], retargeted: true };
|
|
4415
|
+
}
|
|
4416
|
+
if (pages.length === 1) {
|
|
4417
|
+
return { target: pages[0], retargeted: true };
|
|
4418
|
+
}
|
|
4419
|
+
return { target: null, retargeted: false };
|
|
4420
|
+
}
|
|
4317
4421
|
var DaemonCdpManager = class {
|
|
4318
4422
|
ws = null;
|
|
4319
4423
|
browserWs = null;
|
|
@@ -4474,18 +4578,28 @@ var DaemonCdpManager = class {
|
|
|
4474
4578
|
resolve11(targets.find((t) => t.webSocketDebuggerUrl) || null);
|
|
4475
4579
|
return;
|
|
4476
4580
|
}
|
|
4477
|
-
const
|
|
4478
|
-
const
|
|
4581
|
+
const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
|
|
4582
|
+
const mainPages = titleFilteredPages.filter((t) => this.isMainPageUrl(t.url));
|
|
4583
|
+
const list = mainPages.length > 0 ? mainPages : titleFilteredPages.length > 0 ? titleFilteredPages : pages;
|
|
4479
4584
|
this.log(`[CDP] pages(${list.length}): ${list.map((t) => `"${t.title}"`).join(", ")}`);
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4585
|
+
const previousTargetId = this._targetId;
|
|
4586
|
+
const selected = resolveCdpPageTarget({
|
|
4587
|
+
pages: list,
|
|
4588
|
+
pinnedTargetId: previousTargetId,
|
|
4589
|
+
previousPageTitle: this._pageTitle
|
|
4590
|
+
});
|
|
4591
|
+
if (selected.target) {
|
|
4592
|
+
if (selected.retargeted && previousTargetId && previousTargetId !== selected.target.id) {
|
|
4593
|
+
this.log(`[CDP] Target ${previousTargetId} rekeyed to ${selected.target.id}`);
|
|
4594
|
+
this._targetId = selected.target.id;
|
|
4488
4595
|
}
|
|
4596
|
+
this._pageTitle = selected.target.title || "";
|
|
4597
|
+
resolve11(selected.target);
|
|
4598
|
+
return;
|
|
4599
|
+
}
|
|
4600
|
+
if (previousTargetId) {
|
|
4601
|
+
this.log(`[CDP] Target ${previousTargetId} not found in page list`);
|
|
4602
|
+
resolve11(null);
|
|
4489
4603
|
return;
|
|
4490
4604
|
}
|
|
4491
4605
|
this._pageTitle = list[0]?.title || "";
|
|
@@ -5925,7 +6039,17 @@ import * as path7 from "path";
|
|
|
5925
6039
|
import * as os5 from "os";
|
|
5926
6040
|
var HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
|
|
5927
6041
|
var RETAIN_DAYS = 30;
|
|
6042
|
+
var SAVED_HISTORY_INDEX_VERSION = 1;
|
|
6043
|
+
var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
6044
|
+
var SAVED_HISTORY_INDEX_LOCK_SUFFIX = ".lock";
|
|
6045
|
+
var SAVED_HISTORY_INDEX_LOCK_WAIT_MS = 1500;
|
|
6046
|
+
var SAVED_HISTORY_INDEX_LOCK_STALE_MS = 15e3;
|
|
6047
|
+
var SAVED_HISTORY_INDEX_LOCK_POLL_MS = 25;
|
|
6048
|
+
var SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES = 16 * 1024 * 1024;
|
|
5928
6049
|
var savedHistorySessionCache = /* @__PURE__ */ new Map();
|
|
6050
|
+
var savedHistoryFileSummaryCache = /* @__PURE__ */ new Map();
|
|
6051
|
+
var savedHistoryBackgroundRefresh = /* @__PURE__ */ new Set();
|
|
6052
|
+
var savedHistoryRollupInFlight = /* @__PURE__ */ new Set();
|
|
5929
6053
|
var CODEX_STARTER_PROMPT_RE = /^(?:[›❯]\s*)?(?:Find and fix a bug in @filename|Improve documentation in @filename|Write tests for @filename|Explain this codebase|Summarize recent commits|Implement \{feature\}|Use \/skills(?: to list available skills)?|Run \/review on my current changes)$/i;
|
|
5930
6054
|
function normalizeHistoryComparable(text) {
|
|
5931
6055
|
return String(text || "").replace(/\s+/g, " ").trim();
|
|
@@ -5983,6 +6107,68 @@ function sanitizeHistoryMessage(agentType, message) {
|
|
|
5983
6107
|
content
|
|
5984
6108
|
};
|
|
5985
6109
|
}
|
|
6110
|
+
function sortSavedHistorySessionSummaries(summaries) {
|
|
6111
|
+
return summaries.slice().sort((a, b) => b.lastMessageAt - a.lastMessageAt);
|
|
6112
|
+
}
|
|
6113
|
+
function buildSavedHistorySessionSummaryMapFromEntries(entries) {
|
|
6114
|
+
const summaries = /* @__PURE__ */ new Map();
|
|
6115
|
+
for (const entry of Array.from(entries.values())) {
|
|
6116
|
+
const fileSummary = entry.summary;
|
|
6117
|
+
if (!fileSummary || fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) continue;
|
|
6118
|
+
const existing = summaries.get(fileSummary.historySessionId);
|
|
6119
|
+
if (!existing) {
|
|
6120
|
+
summaries.set(fileSummary.historySessionId, {
|
|
6121
|
+
historySessionId: fileSummary.historySessionId,
|
|
6122
|
+
sessionTitle: fileSummary.sessionTitle,
|
|
6123
|
+
messageCount: fileSummary.messageCount,
|
|
6124
|
+
firstMessageAt: fileSummary.firstMessageAt,
|
|
6125
|
+
lastMessageAt: fileSummary.lastMessageAt,
|
|
6126
|
+
preview: fileSummary.preview,
|
|
6127
|
+
workspace: fileSummary.workspace
|
|
6128
|
+
});
|
|
6129
|
+
continue;
|
|
6130
|
+
}
|
|
6131
|
+
existing.messageCount += fileSummary.messageCount;
|
|
6132
|
+
if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
|
|
6133
|
+
existing.firstMessageAt = fileSummary.firstMessageAt;
|
|
6134
|
+
}
|
|
6135
|
+
if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
|
|
6136
|
+
existing.lastMessageAt = fileSummary.lastMessageAt;
|
|
6137
|
+
if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
|
|
6138
|
+
if (fileSummary.preview) existing.preview = fileSummary.preview;
|
|
6139
|
+
}
|
|
6140
|
+
if (!existing.workspace && fileSummary.workspace) {
|
|
6141
|
+
existing.workspace = fileSummary.workspace;
|
|
6142
|
+
}
|
|
6143
|
+
}
|
|
6144
|
+
return Object.fromEntries(sortSavedHistorySessionSummaries(Array.from(summaries.values())).map((summary) => [summary.historySessionId, summary]));
|
|
6145
|
+
}
|
|
6146
|
+
function readPersistedSavedHistorySessionSummaries(dir) {
|
|
6147
|
+
try {
|
|
6148
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
6149
|
+
if (!fs3.existsSync(filePath)) return null;
|
|
6150
|
+
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
6151
|
+
if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.sessions || typeof raw.sessions !== "object") {
|
|
6152
|
+
return null;
|
|
6153
|
+
}
|
|
6154
|
+
return sortSavedHistorySessionSummaries(
|
|
6155
|
+
Object.values(raw.sessions).filter((summary) => !!summary && typeof summary.historySessionId === "string" && summary.messageCount > 0 && summary.lastMessageAt > 0).map((summary) => ({
|
|
6156
|
+
historySessionId: summary.historySessionId,
|
|
6157
|
+
sessionTitle: summary.sessionTitle,
|
|
6158
|
+
messageCount: summary.messageCount,
|
|
6159
|
+
firstMessageAt: summary.firstMessageAt,
|
|
6160
|
+
lastMessageAt: summary.lastMessageAt,
|
|
6161
|
+
preview: summary.preview,
|
|
6162
|
+
workspace: summary.workspace
|
|
6163
|
+
}))
|
|
6164
|
+
);
|
|
6165
|
+
} catch {
|
|
6166
|
+
return null;
|
|
6167
|
+
}
|
|
6168
|
+
}
|
|
6169
|
+
function shouldScheduleSavedHistoryRollup(totalBytes) {
|
|
6170
|
+
return Number.isFinite(totalBytes) && totalBytes >= SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES;
|
|
6171
|
+
}
|
|
5986
6172
|
function sanitizeHistoryFileSegment(value) {
|
|
5987
6173
|
return String(value || "").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
5988
6174
|
}
|
|
@@ -5996,71 +6182,386 @@ function listHistoryFiles(dir, historySessionId) {
|
|
|
5996
6182
|
return true;
|
|
5997
6183
|
}).sort().reverse();
|
|
5998
6184
|
}
|
|
5999
|
-
function
|
|
6000
|
-
|
|
6185
|
+
function normalizeSavedHistorySessionId(agentType, historySessionId) {
|
|
6186
|
+
const normalizedId = String(historySessionId || "").trim();
|
|
6187
|
+
if (!normalizedId) return "";
|
|
6188
|
+
const strictProviderId = normalizeProviderSessionId(agentType, normalizedId);
|
|
6189
|
+
if (strictProviderId) return strictProviderId;
|
|
6190
|
+
return agentType === "hermes-cli" ? "" : normalizedId;
|
|
6191
|
+
}
|
|
6192
|
+
function extractSavedHistorySessionIdFromFile(agentType, file) {
|
|
6193
|
+
const match = file.match(/^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/);
|
|
6194
|
+
return normalizeSavedHistorySessionId(agentType, match?.[1] || "");
|
|
6195
|
+
}
|
|
6196
|
+
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
6197
|
+
return new Map(files.map((file) => {
|
|
6001
6198
|
try {
|
|
6002
6199
|
const stat = fs3.statSync(path7.join(dir, file));
|
|
6003
|
-
return `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}
|
|
6200
|
+
return [file, `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}`];
|
|
6004
6201
|
} catch {
|
|
6005
|
-
return `${file}:missing
|
|
6006
|
-
}
|
|
6007
|
-
})
|
|
6008
|
-
}
|
|
6009
|
-
function
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6033
|
-
|
|
6202
|
+
return [file, `${file}:missing`];
|
|
6203
|
+
}
|
|
6204
|
+
}));
|
|
6205
|
+
}
|
|
6206
|
+
function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
6207
|
+
return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
|
|
6208
|
+
}
|
|
6209
|
+
function getSavedHistoryIndexFilePath(dir) {
|
|
6210
|
+
return path7.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
6211
|
+
}
|
|
6212
|
+
function getSavedHistoryIndexLockPath(dir) {
|
|
6213
|
+
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
6214
|
+
}
|
|
6215
|
+
function sleepBlocking(ms) {
|
|
6216
|
+
if (ms <= 0) return;
|
|
6217
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
6218
|
+
}
|
|
6219
|
+
function loadPersistedSavedHistoryIndexFromFile(dir) {
|
|
6220
|
+
try {
|
|
6221
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
6222
|
+
if (!fs3.existsSync(filePath)) return /* @__PURE__ */ new Map();
|
|
6223
|
+
const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
|
|
6224
|
+
if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.files || typeof raw.files !== "object") {
|
|
6225
|
+
return /* @__PURE__ */ new Map();
|
|
6226
|
+
}
|
|
6227
|
+
return new Map(
|
|
6228
|
+
Object.entries(raw.files).filter(([file, entry]) => !!file && !!entry && typeof entry.signature === "string").map(([file, entry]) => [file, {
|
|
6229
|
+
signature: entry.signature,
|
|
6230
|
+
summary: entry.summary || null
|
|
6231
|
+
}])
|
|
6232
|
+
);
|
|
6233
|
+
} catch {
|
|
6234
|
+
return /* @__PURE__ */ new Map();
|
|
6235
|
+
}
|
|
6236
|
+
}
|
|
6237
|
+
function writePersistedSavedHistoryIndexFile(dir, entries) {
|
|
6238
|
+
const filePath = getSavedHistoryIndexFilePath(dir);
|
|
6239
|
+
const tempPath = `${filePath}.tmp`;
|
|
6240
|
+
const payload = {
|
|
6241
|
+
version: SAVED_HISTORY_INDEX_VERSION,
|
|
6242
|
+
files: Object.fromEntries(entries.entries()),
|
|
6243
|
+
sessions: buildSavedHistorySessionSummaryMapFromEntries(entries)
|
|
6244
|
+
};
|
|
6245
|
+
fs3.writeFileSync(tempPath, JSON.stringify(payload), "utf-8");
|
|
6246
|
+
fs3.renameSync(tempPath, filePath);
|
|
6247
|
+
}
|
|
6248
|
+
function acquireSavedHistoryIndexLock(dir) {
|
|
6249
|
+
const lockPath = getSavedHistoryIndexLockPath(dir);
|
|
6250
|
+
const deadline = Date.now() + SAVED_HISTORY_INDEX_LOCK_WAIT_MS;
|
|
6251
|
+
while (Date.now() <= deadline) {
|
|
6252
|
+
try {
|
|
6253
|
+
fs3.mkdirSync(lockPath);
|
|
6254
|
+
return () => {
|
|
6034
6255
|
try {
|
|
6035
|
-
|
|
6256
|
+
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
6036
6257
|
} catch {
|
|
6037
|
-
parsed = null;
|
|
6038
6258
|
}
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6259
|
+
};
|
|
6260
|
+
} catch (error) {
|
|
6261
|
+
if (error?.code !== "EEXIST") return null;
|
|
6262
|
+
try {
|
|
6263
|
+
const stat = fs3.statSync(lockPath);
|
|
6264
|
+
if (Date.now() - stat.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
|
|
6265
|
+
fs3.rmSync(lockPath, { recursive: true, force: true });
|
|
6042
6266
|
continue;
|
|
6043
6267
|
}
|
|
6044
|
-
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6268
|
+
} catch {
|
|
6269
|
+
continue;
|
|
6270
|
+
}
|
|
6271
|
+
sleepBlocking(SAVED_HISTORY_INDEX_LOCK_POLL_MS);
|
|
6272
|
+
}
|
|
6273
|
+
}
|
|
6274
|
+
return null;
|
|
6275
|
+
}
|
|
6276
|
+
function withLockedPersistedSavedHistoryIndex(dir, callback) {
|
|
6277
|
+
const release2 = acquireSavedHistoryIndexLock(dir);
|
|
6278
|
+
if (!release2) return null;
|
|
6279
|
+
try {
|
|
6280
|
+
const entries = loadPersistedSavedHistoryIndexFromFile(dir);
|
|
6281
|
+
const result = callback(entries);
|
|
6282
|
+
writePersistedSavedHistoryIndexFile(dir, entries);
|
|
6283
|
+
return result;
|
|
6284
|
+
} catch {
|
|
6285
|
+
return null;
|
|
6286
|
+
} finally {
|
|
6287
|
+
release2();
|
|
6288
|
+
}
|
|
6289
|
+
}
|
|
6290
|
+
function loadPersistedSavedHistoryIndex(dir) {
|
|
6291
|
+
return loadPersistedSavedHistoryIndexFromFile(dir);
|
|
6292
|
+
}
|
|
6293
|
+
function savePersistedSavedHistoryIndex(dir, entries) {
|
|
6294
|
+
withLockedPersistedSavedHistoryIndex(dir, (currentEntries) => {
|
|
6295
|
+
const incomingFiles = new Set(Array.from(entries.keys()));
|
|
6296
|
+
for (const [file, entry] of Array.from(entries.entries())) {
|
|
6297
|
+
const liveSignature = buildSavedHistoryFileSignature(dir, file);
|
|
6298
|
+
const existingEntry = currentEntries.get(file);
|
|
6299
|
+
if (existingEntry && existingEntry.signature !== liveSignature && entry.signature !== liveSignature) {
|
|
6300
|
+
continue;
|
|
6301
|
+
}
|
|
6302
|
+
if (entry.signature !== liveSignature && (!existingEntry || existingEntry.signature !== liveSignature)) {
|
|
6303
|
+
continue;
|
|
6304
|
+
}
|
|
6305
|
+
currentEntries.set(file, entry.signature === liveSignature ? entry : {
|
|
6306
|
+
signature: liveSignature,
|
|
6307
|
+
summary: existingEntry?.summary || entry.summary
|
|
6308
|
+
});
|
|
6309
|
+
}
|
|
6310
|
+
for (const file of Array.from(currentEntries.keys())) {
|
|
6311
|
+
if (incomingFiles.has(file)) continue;
|
|
6312
|
+
if (!fs3.existsSync(path7.join(dir, file))) {
|
|
6313
|
+
currentEntries.delete(file);
|
|
6314
|
+
}
|
|
6315
|
+
}
|
|
6316
|
+
});
|
|
6317
|
+
}
|
|
6318
|
+
function invalidatePersistedSavedHistoryIndex(agentType, dir) {
|
|
6319
|
+
try {
|
|
6320
|
+
fs3.rmSync(getSavedHistoryIndexFilePath(dir), { force: true });
|
|
6321
|
+
} catch {
|
|
6322
|
+
}
|
|
6323
|
+
savedHistorySessionCache.delete(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"));
|
|
6324
|
+
}
|
|
6325
|
+
function buildSavedHistoryIndexFileSignature(dir) {
|
|
6326
|
+
try {
|
|
6327
|
+
const stat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
6328
|
+
return `index:${stat.size}:${Math.trunc(stat.mtimeMs)}`;
|
|
6329
|
+
} catch {
|
|
6330
|
+
return "index:missing";
|
|
6331
|
+
}
|
|
6332
|
+
}
|
|
6333
|
+
function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
6334
|
+
try {
|
|
6335
|
+
const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
6336
|
+
const files = listHistoryFiles(dir);
|
|
6337
|
+
for (const file of files) {
|
|
6338
|
+
const stat = fs3.statSync(path7.join(dir, file));
|
|
6339
|
+
if (stat.mtimeMs > indexStat.mtimeMs) return true;
|
|
6340
|
+
}
|
|
6341
|
+
return false;
|
|
6342
|
+
} catch {
|
|
6343
|
+
return true;
|
|
6344
|
+
}
|
|
6345
|
+
}
|
|
6346
|
+
function buildSavedHistoryFileSignature(dir, file) {
|
|
6347
|
+
try {
|
|
6348
|
+
const stat = fs3.statSync(path7.join(dir, file));
|
|
6349
|
+
return `${file}:${stat.size}:${Math.trunc(stat.mtimeMs)}`;
|
|
6350
|
+
} catch {
|
|
6351
|
+
return `${file}:missing`;
|
|
6352
|
+
}
|
|
6353
|
+
}
|
|
6354
|
+
function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
|
|
6355
|
+
const filePath = path7.join(dir, file);
|
|
6356
|
+
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
6357
|
+
const currentEntry = entries.get(file) || null;
|
|
6358
|
+
const nextSummary = updater(currentEntry?.summary || null);
|
|
6359
|
+
const nextEntry = {
|
|
6360
|
+
signature: buildSavedHistoryFileSignature(dir, file),
|
|
6361
|
+
summary: nextSummary
|
|
6362
|
+
};
|
|
6363
|
+
entries.set(file, nextEntry);
|
|
6364
|
+
savedHistoryFileSummaryCache.set(filePath, nextEntry);
|
|
6365
|
+
return nextEntry;
|
|
6366
|
+
});
|
|
6367
|
+
if (!result) return;
|
|
6368
|
+
if (result.summary?.historySessionId && shouldScheduleSavedHistoryRollupForSignature(result.signature)) {
|
|
6369
|
+
scheduleSavedHistoryRollup(agentType, result.summary.historySessionId);
|
|
6370
|
+
}
|
|
6371
|
+
}
|
|
6372
|
+
function updateSavedHistoryIndexForSessionStart(agentType, dir, file, historySessionId, workspace) {
|
|
6373
|
+
const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId);
|
|
6374
|
+
const normalizedWorkspace = String(workspace || "").trim();
|
|
6375
|
+
if (!normalizedSessionId || !normalizedWorkspace) return;
|
|
6376
|
+
persistSavedHistoryFileSummaryEntry(agentType, dir, file, (currentSummary) => ({
|
|
6377
|
+
file,
|
|
6378
|
+
historySessionId: normalizedSessionId,
|
|
6379
|
+
messageCount: currentSummary?.messageCount || 0,
|
|
6380
|
+
firstMessageAt: currentSummary?.firstMessageAt || 0,
|
|
6381
|
+
lastMessageAt: currentSummary?.lastMessageAt || 0,
|
|
6382
|
+
sessionTitle: currentSummary?.sessionTitle,
|
|
6383
|
+
preview: currentSummary?.preview,
|
|
6384
|
+
workspace: normalizedWorkspace
|
|
6385
|
+
}));
|
|
6386
|
+
}
|
|
6387
|
+
function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, historySessionId, messages) {
|
|
6388
|
+
const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId || "");
|
|
6389
|
+
if (!normalizedSessionId || messages.length === 0) return;
|
|
6390
|
+
persistSavedHistoryFileSummaryEntry(agentType, dir, file, (currentSummary) => {
|
|
6391
|
+
const nextSummary = {
|
|
6392
|
+
file,
|
|
6393
|
+
historySessionId: normalizedSessionId,
|
|
6394
|
+
messageCount: currentSummary?.messageCount || 0,
|
|
6395
|
+
firstMessageAt: currentSummary?.firstMessageAt || 0,
|
|
6396
|
+
lastMessageAt: currentSummary?.lastMessageAt || 0,
|
|
6397
|
+
sessionTitle: currentSummary?.sessionTitle,
|
|
6398
|
+
preview: currentSummary?.preview,
|
|
6399
|
+
workspace: currentSummary?.workspace
|
|
6400
|
+
};
|
|
6401
|
+
for (const message of messages) {
|
|
6402
|
+
if (!message || message.historySessionId !== historySessionId) continue;
|
|
6403
|
+
if (message.kind === "session_start") {
|
|
6404
|
+
if (message.workspace) nextSummary.workspace = message.workspace;
|
|
6405
|
+
continue;
|
|
6406
|
+
}
|
|
6407
|
+
nextSummary.messageCount += 1;
|
|
6408
|
+
if (!nextSummary.firstMessageAt || message.receivedAt < nextSummary.firstMessageAt) {
|
|
6409
|
+
nextSummary.firstMessageAt = message.receivedAt;
|
|
6410
|
+
}
|
|
6411
|
+
if (!nextSummary.lastMessageAt || message.receivedAt >= nextSummary.lastMessageAt) {
|
|
6412
|
+
nextSummary.lastMessageAt = message.receivedAt;
|
|
6413
|
+
if (message.sessionTitle) nextSummary.sessionTitle = message.sessionTitle;
|
|
6414
|
+
if (message.role !== "system" && message.content.trim()) nextSummary.preview = message.content.trim();
|
|
6415
|
+
} else if (message.sessionTitle) {
|
|
6416
|
+
nextSummary.sessionTitle = message.sessionTitle;
|
|
6417
|
+
}
|
|
6418
|
+
if (!nextSummary.preview && message.role !== "system" && message.content.trim()) {
|
|
6419
|
+
nextSummary.preview = message.content.trim();
|
|
6420
|
+
}
|
|
6421
|
+
}
|
|
6422
|
+
return nextSummary;
|
|
6423
|
+
});
|
|
6424
|
+
}
|
|
6425
|
+
function computeSavedHistoryFileSummary(agentType, dir, file) {
|
|
6426
|
+
const historySessionId = extractSavedHistorySessionIdFromFile(agentType, file);
|
|
6427
|
+
if (!historySessionId) return null;
|
|
6428
|
+
const filePath = path7.join(dir, file);
|
|
6429
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
6430
|
+
const lines = content.split("\n").filter(Boolean);
|
|
6431
|
+
let messageCount = 0;
|
|
6432
|
+
let firstMessageAt = 0;
|
|
6433
|
+
let lastMessageAt = 0;
|
|
6434
|
+
let sessionTitle = "";
|
|
6435
|
+
let preview = "";
|
|
6436
|
+
let workspace = "";
|
|
6437
|
+
for (const line of lines) {
|
|
6438
|
+
let parsed = null;
|
|
6439
|
+
try {
|
|
6440
|
+
parsed = JSON.parse(line);
|
|
6441
|
+
} catch {
|
|
6442
|
+
parsed = null;
|
|
6443
|
+
}
|
|
6444
|
+
if (!parsed || parsed.historySessionId !== historySessionId) continue;
|
|
6445
|
+
if (parsed.kind === "session_start") {
|
|
6446
|
+
if (!workspace && parsed.workspace) workspace = parsed.workspace;
|
|
6447
|
+
continue;
|
|
6448
|
+
}
|
|
6449
|
+
messageCount += 1;
|
|
6450
|
+
if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
|
|
6451
|
+
if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
|
|
6452
|
+
if (parsed.sessionTitle) sessionTitle = parsed.sessionTitle;
|
|
6453
|
+
if (parsed.role !== "system" && parsed.content.trim()) preview = parsed.content.trim();
|
|
6454
|
+
}
|
|
6455
|
+
if (messageCount === 0 || !lastMessageAt) return null;
|
|
6456
|
+
return {
|
|
6457
|
+
file,
|
|
6458
|
+
historySessionId,
|
|
6459
|
+
messageCount,
|
|
6460
|
+
firstMessageAt,
|
|
6461
|
+
lastMessageAt,
|
|
6462
|
+
sessionTitle: sessionTitle || void 0,
|
|
6463
|
+
preview: preview || void 0,
|
|
6464
|
+
workspace: workspace || void 0
|
|
6465
|
+
};
|
|
6466
|
+
}
|
|
6467
|
+
function shouldScheduleSavedHistoryRollupForSignature(signature) {
|
|
6468
|
+
const parts = String(signature || "").split(":");
|
|
6469
|
+
const size = Number(parts[1] || 0);
|
|
6470
|
+
return shouldScheduleSavedHistoryRollup(size);
|
|
6471
|
+
}
|
|
6472
|
+
function scheduleSavedHistoryRollup(agentType, historySessionId) {
|
|
6473
|
+
const key = `${agentType}:${historySessionId}`;
|
|
6474
|
+
if (!historySessionId || savedHistoryRollupInFlight.has(key)) return;
|
|
6475
|
+
savedHistoryRollupInFlight.add(key);
|
|
6476
|
+
setTimeout(() => {
|
|
6477
|
+
try {
|
|
6478
|
+
new ChatHistoryWriter().compactHistorySession(agentType, historySessionId);
|
|
6479
|
+
} finally {
|
|
6480
|
+
savedHistoryRollupInFlight.delete(key);
|
|
6481
|
+
}
|
|
6482
|
+
}, 0);
|
|
6483
|
+
}
|
|
6484
|
+
function scheduleSavedHistoryBackgroundRefresh(agentType, dir) {
|
|
6485
|
+
const key = `${agentType}:${dir}`;
|
|
6486
|
+
if (savedHistoryBackgroundRefresh.has(key)) return;
|
|
6487
|
+
savedHistoryBackgroundRefresh.add(key);
|
|
6488
|
+
setTimeout(() => {
|
|
6489
|
+
try {
|
|
6490
|
+
if (!fs3.existsSync(dir)) return;
|
|
6491
|
+
const files = listHistoryFiles(dir);
|
|
6492
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
6493
|
+
const persistedEntries = loadPersistedSavedHistoryIndex(dir);
|
|
6494
|
+
const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
|
|
6495
|
+
savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
|
|
6496
|
+
const refreshedIndexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
6497
|
+
savedHistorySessionCache.set(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"), {
|
|
6498
|
+
signature: refreshedIndexSignature,
|
|
6499
|
+
summaries: computed.summaries || []
|
|
6500
|
+
});
|
|
6501
|
+
for (const [file, entry] of Array.from(computed.persistedEntries.entries())) {
|
|
6502
|
+
if (!entry?.summary || !shouldScheduleSavedHistoryRollupForSignature(entry.signature)) continue;
|
|
6503
|
+
scheduleSavedHistoryRollup(agentType, entry.summary.historySessionId);
|
|
6504
|
+
}
|
|
6505
|
+
} catch {
|
|
6506
|
+
} finally {
|
|
6507
|
+
savedHistoryBackgroundRefresh.delete(key);
|
|
6508
|
+
}
|
|
6509
|
+
}, 0);
|
|
6510
|
+
}
|
|
6511
|
+
function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries) {
|
|
6512
|
+
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
6513
|
+
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
6514
|
+
for (const file of files.slice().sort()) {
|
|
6515
|
+
const filePath = path7.join(dir, file);
|
|
6516
|
+
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
6517
|
+
const cached = savedHistoryFileSummaryCache.get(filePath);
|
|
6518
|
+
const persisted = persistedEntries.get(file);
|
|
6519
|
+
const reusableEntry = cached?.signature === signature ? cached : persisted?.signature === signature ? persisted : null;
|
|
6520
|
+
const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(agentType, dir, file);
|
|
6521
|
+
const nextEntry = reusableEntry || {
|
|
6522
|
+
signature,
|
|
6523
|
+
summary: fileSummary
|
|
6524
|
+
};
|
|
6525
|
+
if (!reusableEntry) {
|
|
6526
|
+
nextEntry.signature = signature;
|
|
6527
|
+
nextEntry.summary = fileSummary;
|
|
6528
|
+
}
|
|
6529
|
+
savedHistoryFileSummaryCache.set(filePath, nextEntry);
|
|
6530
|
+
nextPersistedEntries.set(file, nextEntry);
|
|
6531
|
+
if (!fileSummary) continue;
|
|
6532
|
+
const existing = summaryBySessionId.get(fileSummary.historySessionId);
|
|
6533
|
+
if (fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) {
|
|
6534
|
+
continue;
|
|
6535
|
+
}
|
|
6536
|
+
if (!existing) {
|
|
6537
|
+
summaryBySessionId.set(fileSummary.historySessionId, {
|
|
6538
|
+
historySessionId: fileSummary.historySessionId,
|
|
6539
|
+
sessionTitle: fileSummary.sessionTitle,
|
|
6540
|
+
messageCount: fileSummary.messageCount,
|
|
6541
|
+
firstMessageAt: fileSummary.firstMessageAt,
|
|
6542
|
+
lastMessageAt: fileSummary.lastMessageAt,
|
|
6543
|
+
preview: fileSummary.preview,
|
|
6544
|
+
workspace: fileSummary.workspace
|
|
6545
|
+
});
|
|
6546
|
+
continue;
|
|
6547
|
+
}
|
|
6548
|
+
existing.messageCount += fileSummary.messageCount;
|
|
6549
|
+
if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
|
|
6550
|
+
existing.firstMessageAt = fileSummary.firstMessageAt;
|
|
6551
|
+
}
|
|
6552
|
+
if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
|
|
6553
|
+
existing.lastMessageAt = fileSummary.lastMessageAt;
|
|
6554
|
+
if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
|
|
6555
|
+
if (fileSummary.preview) existing.preview = fileSummary.preview;
|
|
6556
|
+
}
|
|
6557
|
+
if (!existing.workspace && fileSummary.workspace) {
|
|
6558
|
+
existing.workspace = fileSummary.workspace;
|
|
6559
|
+
}
|
|
6061
6560
|
}
|
|
6062
|
-
|
|
6063
|
-
|
|
6561
|
+
return {
|
|
6562
|
+
summaries: Array.from(summaryBySessionId.values()).sort((a, b) => b.lastMessageAt - a.lastMessageAt),
|
|
6563
|
+
persistedEntries: nextPersistedEntries
|
|
6564
|
+
};
|
|
6064
6565
|
}
|
|
6065
6566
|
var ChatHistoryWriter = class {
|
|
6066
6567
|
/** Last seen message count per agent (deduplication) */
|
|
@@ -6135,9 +6636,11 @@ var ChatHistoryWriter = class {
|
|
|
6135
6636
|
fs3.mkdirSync(dir, { recursive: true });
|
|
6136
6637
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
6137
6638
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
6138
|
-
const
|
|
6639
|
+
const fileName = `${filePrefix}${date}.jsonl`;
|
|
6640
|
+
const filePath = path7.join(dir, fileName);
|
|
6139
6641
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
6140
6642
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
6643
|
+
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
6141
6644
|
const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
|
|
6142
6645
|
if (!historySessionId && messages.length < prevCount * 0.5 && prevCount > 3) {
|
|
6143
6646
|
seenHashes.clear();
|
|
@@ -6228,7 +6731,8 @@ var ChatHistoryWriter = class {
|
|
|
6228
6731
|
const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
|
|
6229
6732
|
fs3.mkdirSync(dir, { recursive: true });
|
|
6230
6733
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
6231
|
-
const
|
|
6734
|
+
const fileName = `${this.sanitize(id)}_${date}.jsonl`;
|
|
6735
|
+
const filePath = path7.join(dir, fileName);
|
|
6232
6736
|
const record = {
|
|
6233
6737
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6234
6738
|
receivedAt: Date.now(),
|
|
@@ -6241,6 +6745,7 @@ var ChatHistoryWriter = class {
|
|
|
6241
6745
|
workspace: ws
|
|
6242
6746
|
};
|
|
6243
6747
|
fs3.appendFileSync(filePath, JSON.stringify(record) + "\n", "utf-8");
|
|
6748
|
+
updateSavedHistoryIndexForSessionStart(agentType, dir, fileName, id, ws);
|
|
6244
6749
|
} catch {
|
|
6245
6750
|
}
|
|
6246
6751
|
}
|
|
@@ -6306,6 +6811,7 @@ var ChatHistoryWriter = class {
|
|
|
6306
6811
|
}
|
|
6307
6812
|
fs3.unlinkSync(sourcePath);
|
|
6308
6813
|
}
|
|
6814
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
6309
6815
|
} catch {
|
|
6310
6816
|
}
|
|
6311
6817
|
}
|
|
@@ -6355,6 +6861,7 @@ var ChatHistoryWriter = class {
|
|
|
6355
6861
|
fs3.writeFileSync(filePath, `${collapsed.map((entry) => JSON.stringify(entry)).join("\n")}
|
|
6356
6862
|
`, "utf-8");
|
|
6357
6863
|
}
|
|
6864
|
+
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
6358
6865
|
} catch {
|
|
6359
6866
|
}
|
|
6360
6867
|
}
|
|
@@ -6374,13 +6881,18 @@ var ChatHistoryWriter = class {
|
|
|
6374
6881
|
for (const dir of agentDirs) {
|
|
6375
6882
|
const dirPath = path7.join(HISTORY_DIR, dir.name);
|
|
6376
6883
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
6884
|
+
let removedAny = false;
|
|
6377
6885
|
for (const file of files) {
|
|
6378
6886
|
const filePath = path7.join(dirPath, file);
|
|
6379
6887
|
const stat = fs3.statSync(filePath);
|
|
6380
6888
|
if (stat.mtimeMs < cutoff) {
|
|
6381
6889
|
fs3.unlinkSync(filePath);
|
|
6890
|
+
removedAny = true;
|
|
6382
6891
|
}
|
|
6383
6892
|
}
|
|
6893
|
+
if (removedAny) {
|
|
6894
|
+
invalidatePersistedSavedHistoryIndex(dir.name, dirPath);
|
|
6895
|
+
}
|
|
6384
6896
|
}
|
|
6385
6897
|
} catch {
|
|
6386
6898
|
}
|
|
@@ -6446,18 +6958,51 @@ function listSavedHistorySessions(agentType, options = {}) {
|
|
|
6446
6958
|
savedHistorySessionCache.delete(sanitized);
|
|
6447
6959
|
return { sessions: [], hasMore: false };
|
|
6448
6960
|
}
|
|
6449
|
-
const files = listHistoryFiles(dir);
|
|
6450
|
-
const signature = buildSavedHistoryCacheSignature(dir, files);
|
|
6451
6961
|
const cached = savedHistorySessionCache.get(sanitized);
|
|
6452
|
-
const
|
|
6453
|
-
|
|
6962
|
+
const offset = Math.max(0, options.offset || 0);
|
|
6963
|
+
const limit = Math.max(1, options.limit || 30);
|
|
6964
|
+
const indexSignature = buildSavedHistoryIndexFileSignature(dir);
|
|
6965
|
+
let cacheWasInvalidated = false;
|
|
6966
|
+
if (cached) {
|
|
6967
|
+
const cacheLooksPersisted = cached.signature.startsWith("index:");
|
|
6968
|
+
const cacheStillValid = cacheLooksPersisted ? cached.signature === indexSignature : (() => {
|
|
6969
|
+
const files2 = listHistoryFiles(dir);
|
|
6970
|
+
const fileSignatures2 = buildSavedHistoryFileSignatureMap(dir, files2);
|
|
6971
|
+
return cached.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
|
|
6972
|
+
})();
|
|
6973
|
+
if (cacheStillValid) {
|
|
6974
|
+
const sliced2 = cached.summaries.slice(offset, offset + limit);
|
|
6975
|
+
return {
|
|
6976
|
+
sessions: sliced2,
|
|
6977
|
+
hasMore: cached.summaries.length > offset + limit
|
|
6978
|
+
};
|
|
6979
|
+
}
|
|
6980
|
+
cacheWasInvalidated = true;
|
|
6981
|
+
}
|
|
6982
|
+
const persistedSessions = readPersistedSavedHistorySessionSummaries(dir);
|
|
6983
|
+
if (!cacheWasInvalidated && persistedSessions?.length && !historyDirectoryHasFilesNewerThanIndex(dir)) {
|
|
6454
6984
|
savedHistorySessionCache.set(sanitized, {
|
|
6455
|
-
signature,
|
|
6456
|
-
summaries
|
|
6985
|
+
signature: indexSignature,
|
|
6986
|
+
summaries: persistedSessions
|
|
6457
6987
|
});
|
|
6988
|
+
scheduleSavedHistoryBackgroundRefresh(agentType, dir);
|
|
6989
|
+
const sliced2 = persistedSessions.slice(offset, offset + limit);
|
|
6990
|
+
return {
|
|
6991
|
+
sessions: sliced2,
|
|
6992
|
+
hasMore: persistedSessions.length > offset + limit
|
|
6993
|
+
};
|
|
6458
6994
|
}
|
|
6459
|
-
const
|
|
6460
|
-
const
|
|
6995
|
+
const files = listHistoryFiles(dir);
|
|
6996
|
+
const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
|
|
6997
|
+
const signature = buildSavedHistoryCacheSignature(files, fileSignatures);
|
|
6998
|
+
const persistedEntries = loadPersistedSavedHistoryIndex(dir);
|
|
6999
|
+
const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
|
|
7000
|
+
const summaries = computed.summaries || [];
|
|
7001
|
+
savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
|
|
7002
|
+
savedHistorySessionCache.set(sanitized, {
|
|
7003
|
+
signature,
|
|
7004
|
+
summaries
|
|
7005
|
+
});
|
|
6461
7006
|
const sliced = summaries.slice(offset, offset + limit);
|
|
6462
7007
|
return {
|
|
6463
7008
|
sessions: sliced,
|
|
@@ -8095,7 +8640,7 @@ function shouldIncludeSessionMetadata(profile) {
|
|
|
8095
8640
|
return profile !== "live";
|
|
8096
8641
|
}
|
|
8097
8642
|
function shouldIncludeRuntimeMetadata(profile) {
|
|
8098
|
-
return
|
|
8643
|
+
return true;
|
|
8099
8644
|
}
|
|
8100
8645
|
function findCdpManager(cdpManagers, key) {
|
|
8101
8646
|
const exact = cdpManagers.get(key);
|
|
@@ -8210,6 +8755,21 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
8210
8755
|
lastUpdated: ext.lastUpdated
|
|
8211
8756
|
};
|
|
8212
8757
|
}
|
|
8758
|
+
function shouldIncludeExtensionSession(ext) {
|
|
8759
|
+
const status = String(ext.status || "").trim().toLowerCase();
|
|
8760
|
+
const hasActiveChat = !!ext.activeChat;
|
|
8761
|
+
const hasMessages = Array.isArray(ext.activeChat?.messages) && ext.activeChat.messages.length > 0;
|
|
8762
|
+
const hasModal = !!ext.activeChat?.activeModal;
|
|
8763
|
+
const hasStreams = Array.isArray(ext.agentStreams) && ext.agentStreams.length > 0;
|
|
8764
|
+
const hasProviderSessionId = typeof ext.providerSessionId === "string" && ext.providerSessionId.trim().length > 0;
|
|
8765
|
+
const hasControlValues = !!(ext.controlValues && Object.keys(ext.controlValues).length > 0);
|
|
8766
|
+
const hasProviderControls = Array.isArray(ext.providerControls) && ext.providerControls.length > 0;
|
|
8767
|
+
const hasOpenPanelCapability = Array.isArray(ext.sessionCapabilities) && ext.sessionCapabilities.includes("open_panel");
|
|
8768
|
+
const hasSummaryMetadata = !!ext.summaryMetadata;
|
|
8769
|
+
const hasError = typeof ext.errorMessage === "string" && ext.errorMessage.trim().length > 0;
|
|
8770
|
+
const hasInterestingStatus = !!status && !["idle", "panel_hidden", "disconnected", "not_monitored"].includes(status);
|
|
8771
|
+
return hasActiveChat || hasMessages || hasModal || hasStreams || hasProviderSessionId || hasControlValues || hasProviderControls || hasOpenPanelCapability || hasSummaryMetadata || hasError || hasInterestingStatus;
|
|
8772
|
+
}
|
|
8213
8773
|
function buildCliSession(state, options) {
|
|
8214
8774
|
const profile = options.profile || "full";
|
|
8215
8775
|
const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
|
|
@@ -8235,8 +8795,12 @@ function buildCliSession(state, options) {
|
|
|
8235
8795
|
runtimeKey: state.runtime?.runtimeKey,
|
|
8236
8796
|
runtimeDisplayName: state.runtime?.displayName,
|
|
8237
8797
|
runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
|
|
8798
|
+
runtimeLifecycle: state.runtime?.lifecycle ?? null,
|
|
8799
|
+
runtimeSurfaceKind: state.runtime?.surfaceKind,
|
|
8238
8800
|
runtimeWriteOwner: state.runtime?.writeOwner || null,
|
|
8239
|
-
runtimeAttachedClients: state.runtime?.attachedClients || []
|
|
8801
|
+
runtimeAttachedClients: state.runtime?.attachedClients || [],
|
|
8802
|
+
runtimeRestoredFromStorage: state.runtime?.restoredFromStorage === true,
|
|
8803
|
+
runtimeRecoveryState: state.runtime?.recoveryState ?? null
|
|
8240
8804
|
},
|
|
8241
8805
|
mode: state.mode,
|
|
8242
8806
|
resume: state.resume,
|
|
@@ -8293,6 +8857,7 @@ function buildSessionEntries(allStates, cdpManagers, options = {}) {
|
|
|
8293
8857
|
for (const state of ideStates) {
|
|
8294
8858
|
sessions.push(buildIdeWorkspaceSession(state, cdpManagers, options));
|
|
8295
8859
|
for (const ext of state.extensions) {
|
|
8860
|
+
if (!shouldIncludeExtensionSession(ext)) continue;
|
|
8296
8861
|
sessions.push(buildExtensionAgentSession(state, ext, options));
|
|
8297
8862
|
}
|
|
8298
8863
|
}
|
|
@@ -10463,7 +11028,9 @@ function applyProviderPatch(h, args, payload) {
|
|
|
10463
11028
|
});
|
|
10464
11029
|
}
|
|
10465
11030
|
async function executeProviderScript(h, args, scriptName) {
|
|
10466
|
-
const
|
|
11031
|
+
const explicitTargetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
|
|
11032
|
+
const targetSession = explicitTargetSessionId ? h.ctx.sessionRegistry?.get(explicitTargetSessionId) : void 0;
|
|
11033
|
+
const resolvedProviderType = targetSession?.providerType || h.currentSession?.providerType || h.currentProviderType || args?.agentType || args?.providerType;
|
|
10467
11034
|
if (!resolvedProviderType) return { success: false, error: "targetSessionId or providerType is required" };
|
|
10468
11035
|
const loader = h.ctx.providerLoader;
|
|
10469
11036
|
if (!loader) return { success: false, error: "ProviderLoader not initialized" };
|
|
@@ -10506,16 +11073,16 @@ async function executeProviderScript(h, args, scriptName) {
|
|
|
10506
11073
|
const scriptFn = provider.scripts[actualScriptName];
|
|
10507
11074
|
const scriptCode = scriptFn(normalizedArgs);
|
|
10508
11075
|
if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
|
|
10509
|
-
const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : h.currentSession?.cdpManagerKey || h.currentManagerKey;
|
|
11076
|
+
const cdpKey = provider.category === "ide" ? targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey;
|
|
10510
11077
|
LOG.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
|
|
10511
11078
|
const cdp = h.getCdp(cdpKey);
|
|
10512
11079
|
if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
|
|
10513
11080
|
try {
|
|
10514
11081
|
let result;
|
|
10515
11082
|
if (provider.category === "extension") {
|
|
10516
|
-
const runtimeSessionId = h.currentSession?.sessionId
|
|
11083
|
+
const runtimeSessionId = explicitTargetSessionId || h.currentSession?.sessionId;
|
|
10517
11084
|
if (!runtimeSessionId) return { success: false, error: `No target session found for ${resolvedProviderType}` };
|
|
10518
|
-
const parentSessionId = h.currentSession?.parentSessionId;
|
|
11085
|
+
const parentSessionId = targetSession?.parentSessionId || h.currentSession?.parentSessionId;
|
|
10519
11086
|
if (parentSessionId) {
|
|
10520
11087
|
await h.agentStream?.setActiveSession(cdp, parentSessionId, runtimeSessionId);
|
|
10521
11088
|
await h.agentStream?.syncActiveSession(cdp, parentSessionId);
|
|
@@ -11518,8 +12085,12 @@ var CliProviderInstance = class {
|
|
|
11518
12085
|
runtimeKey: runtime.runtimeKey,
|
|
11519
12086
|
displayName: runtime.displayName,
|
|
11520
12087
|
workspaceLabel: runtime.workspaceLabel,
|
|
12088
|
+
lifecycle: runtime.lifecycle ?? null,
|
|
12089
|
+
surfaceKind: runtime.surfaceKind,
|
|
11521
12090
|
writeOwner: runtime.writeOwner || null,
|
|
11522
|
-
attachedClients: runtime.attachedClients || []
|
|
12091
|
+
attachedClients: runtime.attachedClients || [],
|
|
12092
|
+
restoredFromStorage: runtime.restoredFromStorage === true,
|
|
12093
|
+
recoveryState: runtime.recoveryState ?? null
|
|
11523
12094
|
} : void 0,
|
|
11524
12095
|
resume: this.provider.resume,
|
|
11525
12096
|
controlValues: surface.controlValues,
|
|
@@ -15831,61 +16402,6 @@ cleanOldFiles();
|
|
|
15831
16402
|
// src/commands/router.ts
|
|
15832
16403
|
init_logger();
|
|
15833
16404
|
|
|
15834
|
-
// src/session-host/runtime-surface.ts
|
|
15835
|
-
var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
|
|
15836
|
-
function isSessionHostLiveRuntime(record) {
|
|
15837
|
-
const lifecycle = String(record?.lifecycle || "").trim();
|
|
15838
|
-
return LIVE_LIFECYCLES.has(lifecycle);
|
|
15839
|
-
}
|
|
15840
|
-
function getSessionHostRecoveryLabel(meta) {
|
|
15841
|
-
const recoveryState = typeof meta?.runtimeRecoveryState === "string" ? String(meta.runtimeRecoveryState).trim() : "";
|
|
15842
|
-
if (!recoveryState) return null;
|
|
15843
|
-
if (recoveryState === "auto_resumed") return "restored after restart";
|
|
15844
|
-
if (recoveryState === "resume_failed") return "restore failed";
|
|
15845
|
-
if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
|
|
15846
|
-
if (recoveryState === "orphan_snapshot") return "snapshot recovered";
|
|
15847
|
-
return recoveryState.replace(/_/g, " ");
|
|
15848
|
-
}
|
|
15849
|
-
function isSessionHostRecoverySnapshot(record) {
|
|
15850
|
-
if (!record) return false;
|
|
15851
|
-
if (isSessionHostLiveRuntime(record)) return false;
|
|
15852
|
-
const lifecycle = String(record.lifecycle || "").trim();
|
|
15853
|
-
if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
|
|
15854
|
-
return false;
|
|
15855
|
-
}
|
|
15856
|
-
const meta = record.meta || void 0;
|
|
15857
|
-
if (meta?.restoredFromStorage === true) return true;
|
|
15858
|
-
return getSessionHostRecoveryLabel(meta) !== null;
|
|
15859
|
-
}
|
|
15860
|
-
function getSessionHostSurfaceKind(record) {
|
|
15861
|
-
if (isSessionHostLiveRuntime(record)) return "live_runtime";
|
|
15862
|
-
if (isSessionHostRecoverySnapshot(record)) return "recovery_snapshot";
|
|
15863
|
-
return "inactive_record";
|
|
15864
|
-
}
|
|
15865
|
-
function partitionSessionHostRecords(records) {
|
|
15866
|
-
const liveRuntimes = [];
|
|
15867
|
-
const recoverySnapshots = [];
|
|
15868
|
-
const inactiveRecords = [];
|
|
15869
|
-
for (const record of records) {
|
|
15870
|
-
const kind = getSessionHostSurfaceKind(record);
|
|
15871
|
-
if (kind === "live_runtime") {
|
|
15872
|
-
liveRuntimes.push(record);
|
|
15873
|
-
} else if (kind === "recovery_snapshot") {
|
|
15874
|
-
recoverySnapshots.push(record);
|
|
15875
|
-
} else {
|
|
15876
|
-
inactiveRecords.push(record);
|
|
15877
|
-
}
|
|
15878
|
-
}
|
|
15879
|
-
return {
|
|
15880
|
-
liveRuntimes,
|
|
15881
|
-
recoverySnapshots,
|
|
15882
|
-
inactiveRecords
|
|
15883
|
-
};
|
|
15884
|
-
}
|
|
15885
|
-
function partitionSessionHostDiagnosticsSessions(records) {
|
|
15886
|
-
return partitionSessionHostRecords(records || []);
|
|
15887
|
-
}
|
|
15888
|
-
|
|
15889
16405
|
// src/status/snapshot.ts
|
|
15890
16406
|
init_config();
|
|
15891
16407
|
import * as os16 from "os";
|
|
@@ -17443,6 +17959,23 @@ function prepareSessionModalUpdate(input) {
|
|
|
17443
17959
|
};
|
|
17444
17960
|
}
|
|
17445
17961
|
|
|
17962
|
+
// src/chat/async-batch.ts
|
|
17963
|
+
async function runAsyncBatch(items, worker, options = {}) {
|
|
17964
|
+
const list = Array.from(items);
|
|
17965
|
+
if (list.length === 0) return;
|
|
17966
|
+
const concurrency = Math.max(1, Math.min(list.length, Math.floor(options.concurrency || 1)));
|
|
17967
|
+
let nextIndex = 0;
|
|
17968
|
+
const runners = Array.from({ length: concurrency }, async () => {
|
|
17969
|
+
while (true) {
|
|
17970
|
+
const currentIndex = nextIndex;
|
|
17971
|
+
nextIndex += 1;
|
|
17972
|
+
if (currentIndex >= list.length) return;
|
|
17973
|
+
await worker(list[currentIndex], currentIndex);
|
|
17974
|
+
}
|
|
17975
|
+
});
|
|
17976
|
+
await Promise.all(runners);
|
|
17977
|
+
}
|
|
17978
|
+
|
|
17446
17979
|
// src/agent-stream/provider-adapter.ts
|
|
17447
17980
|
init_read_chat_contract();
|
|
17448
17981
|
init_chat_message_normalization();
|
|
@@ -17911,10 +18444,12 @@ var DaemonAgentStreamManager = class {
|
|
|
17911
18444
|
}
|
|
17912
18445
|
}
|
|
17913
18446
|
/** Collect active extension session state */
|
|
17914
|
-
async collectActiveSession(cdp, parentSessionId) {
|
|
18447
|
+
async collectActiveSession(cdp, parentSessionId, attemptedSessionIds = /* @__PURE__ */ new Set(), originSessionId) {
|
|
17915
18448
|
if (!this.enabled) return null;
|
|
17916
18449
|
const activeSessionId = this.getActiveSessionId(parentSessionId);
|
|
17917
18450
|
if (!activeSessionId) return null;
|
|
18451
|
+
const resolvedOriginSessionId = originSessionId || activeSessionId;
|
|
18452
|
+
attemptedSessionIds.add(activeSessionId);
|
|
17918
18453
|
let agent = this.managedBySessionId.get(activeSessionId);
|
|
17919
18454
|
if (!agent) {
|
|
17920
18455
|
agent = await this.connectManagedSession(cdp, parentSessionId, activeSessionId) || void 0;
|
|
@@ -17927,18 +18462,44 @@ var DaemonAgentStreamManager = class {
|
|
|
17927
18462
|
try {
|
|
17928
18463
|
const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
|
|
17929
18464
|
const state = await agent.adapter.readChat(evaluate);
|
|
17930
|
-
const
|
|
17931
|
-
const
|
|
17932
|
-
|
|
17933
|
-
|
|
18465
|
+
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;
|
|
18466
|
+
const normalizedState = {
|
|
18467
|
+
...state,
|
|
18468
|
+
sessionId: agent.runtimeSessionId,
|
|
18469
|
+
...resolvedProviderSessionId ? { providerSessionId: resolvedProviderSessionId } : {}
|
|
18470
|
+
};
|
|
18471
|
+
const stateError = this.getStateError(normalizedState);
|
|
18472
|
+
const selectedModelValue = typeof normalizedState.controlValues?.model === "string" ? normalizedState.controlValues.model : "";
|
|
18473
|
+
LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${normalizedState.status} msgs=${normalizedState.messages?.length || 0} model=${selectedModelValue}${normalizedState.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
|
|
18474
|
+
if (normalizedState.status === "error" && this.isRecoverableSessionError(stateError)) {
|
|
17934
18475
|
throw new Error(stateError);
|
|
17935
18476
|
}
|
|
17936
|
-
agent.lastState =
|
|
18477
|
+
agent.lastState = normalizedState;
|
|
17937
18478
|
agent.lastError = null;
|
|
17938
|
-
if (
|
|
18479
|
+
if (normalizedState.status === "panel_hidden") {
|
|
18480
|
+
const discovered = await cdp.discoverAgentWebviews().catch(() => []);
|
|
18481
|
+
const fallbackTarget = discovered.find((entry) => {
|
|
18482
|
+
if (entry.agentType === type) return false;
|
|
18483
|
+
const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, entry.agentType);
|
|
18484
|
+
return !!fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId);
|
|
18485
|
+
});
|
|
18486
|
+
if (fallbackTarget) {
|
|
18487
|
+
const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, fallbackTarget.agentType);
|
|
18488
|
+
if (fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId)) {
|
|
18489
|
+
this.logFn(`[AgentStream] Active session ${type} is hidden; switching to visible agent ${fallbackTarget.agentType} (${parentSessionId})`);
|
|
18490
|
+
await this.setActiveSession(cdp, parentSessionId, fallbackSessionId);
|
|
18491
|
+
await this.syncActiveSession(cdp, parentSessionId);
|
|
18492
|
+
const fallbackState = await this.collectActiveSession(cdp, parentSessionId, attemptedSessionIds, resolvedOriginSessionId);
|
|
18493
|
+
if (fallbackState?.status === "panel_hidden" && resolvedOriginSessionId !== fallbackSessionId) {
|
|
18494
|
+
await this.setActiveSession(cdp, parentSessionId, resolvedOriginSessionId);
|
|
18495
|
+
await this.syncActiveSession(cdp, parentSessionId);
|
|
18496
|
+
}
|
|
18497
|
+
return fallbackState;
|
|
18498
|
+
}
|
|
18499
|
+
}
|
|
17939
18500
|
agent.lastHiddenCheckTime = Date.now();
|
|
17940
18501
|
}
|
|
17941
|
-
return
|
|
18502
|
+
return normalizedState;
|
|
17942
18503
|
} catch (e) {
|
|
17943
18504
|
const errorMsg = e?.message || String(e);
|
|
17944
18505
|
this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
|
|
@@ -18234,6 +18795,7 @@ var AgentStreamPoller = class {
|
|
|
18234
18795
|
try {
|
|
18235
18796
|
await agentStreamManager.syncActiveSession(cdp, parentSessionId);
|
|
18236
18797
|
let stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
|
|
18798
|
+
resolvedActiveSessionId = stream?.sessionId || agentStreamManager.getActiveSessionId(parentSessionId) || resolvedActiveSessionId;
|
|
18237
18799
|
if (stream?.status === "waiting_approval") {
|
|
18238
18800
|
const autoApprove = providerLoader.getSettings(stream.agentType).autoApprove !== false;
|
|
18239
18801
|
if (autoApprove && resolvedActiveSessionId) {
|
|
@@ -24216,6 +24778,8 @@ var SessionHostRuntimeTransport = class {
|
|
|
24216
24778
|
runtimeKey: record.runtimeKey,
|
|
24217
24779
|
displayName: record.displayName,
|
|
24218
24780
|
workspaceLabel: record.workspaceLabel,
|
|
24781
|
+
lifecycle: typeof record.lifecycle === "string" ? record.lifecycle : null,
|
|
24782
|
+
surfaceKind: record.surfaceKind,
|
|
24219
24783
|
writeOwner: record.writeOwner ? {
|
|
24220
24784
|
clientId: record.writeOwner.clientId,
|
|
24221
24785
|
ownerType: record.writeOwner.ownerType
|
|
@@ -24943,6 +25507,7 @@ export {
|
|
|
24943
25507
|
resolveChatMessageKind,
|
|
24944
25508
|
resolveDebugRuntimeConfig,
|
|
24945
25509
|
resolveSessionHostAppName,
|
|
25510
|
+
runAsyncBatch,
|
|
24946
25511
|
saveConfig,
|
|
24947
25512
|
saveState,
|
|
24948
25513
|
setDebugRuntimeConfig,
|