adhdev 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/cli/index.js CHANGED
@@ -1546,6 +1546,67 @@ var init_host_memory = __esm({
1546
1546
  }
1547
1547
  });
1548
1548
 
1549
+ // ../../oss/packages/daemon-core/src/session-host/runtime-surface.ts
1550
+ function isSessionHostLiveRuntime(record2) {
1551
+ const lifecycle = String(record2?.lifecycle || "").trim();
1552
+ return LIVE_LIFECYCLES.has(lifecycle);
1553
+ }
1554
+ function getSessionHostRecoveryLabel(meta3) {
1555
+ const recoveryState = typeof meta3?.runtimeRecoveryState === "string" ? String(meta3.runtimeRecoveryState).trim() : "";
1556
+ if (!recoveryState) return null;
1557
+ if (recoveryState === "auto_resumed") return "restored after restart";
1558
+ if (recoveryState === "resume_failed") return "restore failed";
1559
+ if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
1560
+ if (recoveryState === "orphan_snapshot") return "snapshot recovered";
1561
+ return recoveryState.replace(/_/g, " ");
1562
+ }
1563
+ function isSessionHostRecoverySnapshot(record2) {
1564
+ if (!record2) return false;
1565
+ if (isSessionHostLiveRuntime(record2)) return false;
1566
+ const lifecycle = String(record2.lifecycle || "").trim();
1567
+ if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
1568
+ return false;
1569
+ }
1570
+ const meta3 = record2.meta || void 0;
1571
+ if (meta3?.restoredFromStorage === true) return true;
1572
+ return getSessionHostRecoveryLabel(meta3) !== null;
1573
+ }
1574
+ function getSessionHostSurfaceKind(record2) {
1575
+ if (isSessionHostLiveRuntime(record2)) return "live_runtime";
1576
+ if (isSessionHostRecoverySnapshot(record2)) return "recovery_snapshot";
1577
+ return "inactive_record";
1578
+ }
1579
+ function partitionSessionHostRecords(records) {
1580
+ const liveRuntimes = [];
1581
+ const recoverySnapshots = [];
1582
+ const inactiveRecords = [];
1583
+ for (const record2 of records) {
1584
+ const kind = getSessionHostSurfaceKind(record2);
1585
+ if (kind === "live_runtime") {
1586
+ liveRuntimes.push(record2);
1587
+ } else if (kind === "recovery_snapshot") {
1588
+ recoverySnapshots.push(record2);
1589
+ } else {
1590
+ inactiveRecords.push(record2);
1591
+ }
1592
+ }
1593
+ return {
1594
+ liveRuntimes,
1595
+ recoverySnapshots,
1596
+ inactiveRecords
1597
+ };
1598
+ }
1599
+ function partitionSessionHostDiagnosticsSessions(records) {
1600
+ return partitionSessionHostRecords(records || []);
1601
+ }
1602
+ var LIVE_LIFECYCLES;
1603
+ var init_runtime_surface = __esm({
1604
+ "../../oss/packages/daemon-core/src/session-host/runtime-surface.ts"() {
1605
+ "use strict";
1606
+ LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
1607
+ }
1608
+ });
1609
+
1549
1610
  // ../../oss/packages/daemon-core/src/status/chat-tail-hot-sessions.ts
1550
1611
  function parseMessageTimestamp(value) {
1551
1612
  if (typeof value === "number" && Number.isFinite(value)) return value;
@@ -1555,6 +1616,23 @@ function parseMessageTimestamp(value) {
1555
1616
  }
1556
1617
  return 0;
1557
1618
  }
1619
+ function isDefinitelyNonLiveRuntimeSession(session) {
1620
+ const surfaceKind = String(session?.runtimeSurfaceKind || "").trim();
1621
+ if (surfaceKind === "live_runtime") return false;
1622
+ if (surfaceKind === "recovery_snapshot") return true;
1623
+ if (surfaceKind === "inactive_record") return false;
1624
+ const lifecycle = String(session?.runtimeLifecycle || "").trim();
1625
+ if (lifecycle && LIVE_RUNTIME_LIFECYCLES.has(lifecycle)) return false;
1626
+ const inferredSurfaceKind = getSessionHostSurfaceKind({
1627
+ lifecycle: lifecycle || null,
1628
+ meta: {
1629
+ restoredFromStorage: session?.runtimeRestoredFromStorage === true,
1630
+ ...session?.runtimeRecoveryState ? { runtimeRecoveryState: session.runtimeRecoveryState } : {}
1631
+ }
1632
+ });
1633
+ if (inferredSurfaceKind === "recovery_snapshot") return true;
1634
+ return false;
1635
+ }
1558
1636
  function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessionIds, options = {}) {
1559
1637
  const now = options.now ?? Date.now();
1560
1638
  const recentMessageGraceMs = Math.max(
@@ -1563,9 +1641,14 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
1563
1641
  );
1564
1642
  const activeStatuses = options.activeStatuses ?? DEFAULT_ACTIVE_CHAT_POLL_STATUSES;
1565
1643
  const active = /* @__PURE__ */ new Set();
1644
+ const excluded = /* @__PURE__ */ new Set();
1566
1645
  for (const session of sessions) {
1567
1646
  const sessionId = typeof session?.id === "string" ? session.id : "";
1568
1647
  if (!sessionId) continue;
1648
+ if (isDefinitelyNonLiveRuntimeSession(session)) {
1649
+ excluded.add(sessionId);
1650
+ continue;
1651
+ }
1569
1652
  const status = String(session?.status || "").toLowerCase();
1570
1653
  const lastMessageAt = parseMessageTimestamp(session?.lastMessageAt);
1571
1654
  const recentlyUpdated = lastMessageAt > 0 && now - lastMessageAt <= recentMessageGraceMs;
@@ -1574,20 +1657,22 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
1574
1657
  }
1575
1658
  }
1576
1659
  const finalizing = new Set(
1577
- Array.from(previousHotSessionIds).filter((sessionId) => !active.has(sessionId))
1660
+ Array.from(previousHotSessionIds).filter((sessionId) => !active.has(sessionId) && !excluded.has(sessionId))
1578
1661
  );
1579
1662
  return { active, finalizing };
1580
1663
  }
1581
- var DEFAULT_ACTIVE_CHAT_POLL_STATUSES, DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS;
1664
+ var DEFAULT_ACTIVE_CHAT_POLL_STATUSES, DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS, LIVE_RUNTIME_LIFECYCLES;
1582
1665
  var init_chat_tail_hot_sessions = __esm({
1583
1666
  "../../oss/packages/daemon-core/src/status/chat-tail-hot-sessions.ts"() {
1584
1667
  "use strict";
1668
+ init_runtime_surface();
1585
1669
  DEFAULT_ACTIVE_CHAT_POLL_STATUSES = /* @__PURE__ */ new Set([
1586
1670
  "generating",
1587
1671
  "waiting_approval",
1588
1672
  "starting"
1589
1673
  ]);
1590
1674
  DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS = 8e3;
1675
+ LIVE_RUNTIME_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
1591
1676
  }
1592
1677
  });
1593
1678
 
@@ -1807,6 +1892,32 @@ var init_logger = __esm({
1807
1892
  });
1808
1893
 
1809
1894
  // ../../oss/packages/daemon-core/src/cdp/manager.ts
1895
+ function normalizeTitle(value) {
1896
+ return String(value || "").trim().replace(/\s+/g, " ").toLowerCase();
1897
+ }
1898
+ function titlesMatch(lhs, rhs) {
1899
+ const a = normalizeTitle(lhs);
1900
+ const b = normalizeTitle(rhs);
1901
+ if (!a || !b) return false;
1902
+ return a === b || a.includes(b) || b.includes(a);
1903
+ }
1904
+ function resolveCdpPageTarget(params) {
1905
+ const { pages, pinnedTargetId, previousPageTitle } = params;
1906
+ if (pages.length === 0) return { target: null, retargeted: false };
1907
+ if (!pinnedTargetId) {
1908
+ return { target: pages[0] || null, retargeted: false };
1909
+ }
1910
+ const exact = pages.find((page) => page.id === pinnedTargetId);
1911
+ if (exact) return { target: exact, retargeted: false };
1912
+ const titleMatchesList = pages.filter((page) => titlesMatch(page.title, previousPageTitle));
1913
+ if (titleMatchesList.length === 1) {
1914
+ return { target: titleMatchesList[0], retargeted: true };
1915
+ }
1916
+ if (pages.length === 1) {
1917
+ return { target: pages[0], retargeted: true };
1918
+ }
1919
+ return { target: null, retargeted: false };
1920
+ }
1810
1921
  var import_ws, http, DaemonCdpManager;
1811
1922
  var init_manager = __esm({
1812
1923
  "../../oss/packages/daemon-core/src/cdp/manager.ts"() {
@@ -1974,18 +2085,28 @@ var init_manager = __esm({
1974
2085
  resolve17(targets.find((t) => t.webSocketDebuggerUrl) || null);
1975
2086
  return;
1976
2087
  }
1977
- const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
1978
- const list = mainPages.length > 0 ? mainPages : pages;
2088
+ const titleFilteredPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
2089
+ const mainPages = titleFilteredPages.filter((t) => this.isMainPageUrl(t.url));
2090
+ const list = mainPages.length > 0 ? mainPages : titleFilteredPages.length > 0 ? titleFilteredPages : pages;
1979
2091
  this.log(`[CDP] pages(${list.length}): ${list.map((t) => `"${t.title}"`).join(", ")}`);
1980
- if (this._targetId) {
1981
- const specific = list.find((t) => t.id === this._targetId);
1982
- if (specific) {
1983
- this._pageTitle = specific.title || "";
1984
- resolve17(specific);
1985
- } else {
1986
- this.log(`[CDP] Target ${this._targetId} not found in page list`);
1987
- resolve17(null);
2092
+ const previousTargetId = this._targetId;
2093
+ const selected = resolveCdpPageTarget({
2094
+ pages: list,
2095
+ pinnedTargetId: previousTargetId,
2096
+ previousPageTitle: this._pageTitle
2097
+ });
2098
+ if (selected.target) {
2099
+ if (selected.retargeted && previousTargetId && previousTargetId !== selected.target.id) {
2100
+ this.log(`[CDP] Target ${previousTargetId} rekeyed to ${selected.target.id}`);
2101
+ this._targetId = selected.target.id;
1988
2102
  }
2103
+ this._pageTitle = selected.target.title || "";
2104
+ resolve17(selected.target);
2105
+ return;
2106
+ }
2107
+ if (previousTargetId) {
2108
+ this.log(`[CDP] Target ${previousTargetId} not found in page list`);
2109
+ resolve17(null);
1989
2110
  return;
1990
2111
  }
1991
2112
  this._pageTitle = list[0]?.title || "";
@@ -3862,6 +3983,68 @@ function sanitizeHistoryMessage(agentType, message) {
3862
3983
  content
3863
3984
  };
3864
3985
  }
3986
+ function sortSavedHistorySessionSummaries(summaries) {
3987
+ return summaries.slice().sort((a, b) => b.lastMessageAt - a.lastMessageAt);
3988
+ }
3989
+ function buildSavedHistorySessionSummaryMapFromEntries(entries) {
3990
+ const summaries = /* @__PURE__ */ new Map();
3991
+ for (const entry of Array.from(entries.values())) {
3992
+ const fileSummary = entry.summary;
3993
+ if (!fileSummary || fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) continue;
3994
+ const existing = summaries.get(fileSummary.historySessionId);
3995
+ if (!existing) {
3996
+ summaries.set(fileSummary.historySessionId, {
3997
+ historySessionId: fileSummary.historySessionId,
3998
+ sessionTitle: fileSummary.sessionTitle,
3999
+ messageCount: fileSummary.messageCount,
4000
+ firstMessageAt: fileSummary.firstMessageAt,
4001
+ lastMessageAt: fileSummary.lastMessageAt,
4002
+ preview: fileSummary.preview,
4003
+ workspace: fileSummary.workspace
4004
+ });
4005
+ continue;
4006
+ }
4007
+ existing.messageCount += fileSummary.messageCount;
4008
+ if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
4009
+ existing.firstMessageAt = fileSummary.firstMessageAt;
4010
+ }
4011
+ if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
4012
+ existing.lastMessageAt = fileSummary.lastMessageAt;
4013
+ if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
4014
+ if (fileSummary.preview) existing.preview = fileSummary.preview;
4015
+ }
4016
+ if (!existing.workspace && fileSummary.workspace) {
4017
+ existing.workspace = fileSummary.workspace;
4018
+ }
4019
+ }
4020
+ return Object.fromEntries(sortSavedHistorySessionSummaries(Array.from(summaries.values())).map((summary) => [summary.historySessionId, summary]));
4021
+ }
4022
+ function readPersistedSavedHistorySessionSummaries(dir) {
4023
+ try {
4024
+ const filePath = getSavedHistoryIndexFilePath(dir);
4025
+ if (!fs3.existsSync(filePath)) return null;
4026
+ const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
4027
+ if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.sessions || typeof raw.sessions !== "object") {
4028
+ return null;
4029
+ }
4030
+ return sortSavedHistorySessionSummaries(
4031
+ Object.values(raw.sessions).filter((summary) => !!summary && typeof summary.historySessionId === "string" && summary.messageCount > 0 && summary.lastMessageAt > 0).map((summary) => ({
4032
+ historySessionId: summary.historySessionId,
4033
+ sessionTitle: summary.sessionTitle,
4034
+ messageCount: summary.messageCount,
4035
+ firstMessageAt: summary.firstMessageAt,
4036
+ lastMessageAt: summary.lastMessageAt,
4037
+ preview: summary.preview,
4038
+ workspace: summary.workspace
4039
+ }))
4040
+ );
4041
+ } catch {
4042
+ return null;
4043
+ }
4044
+ }
4045
+ function shouldScheduleSavedHistoryRollup(totalBytes) {
4046
+ return Number.isFinite(totalBytes) && totalBytes >= SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES;
4047
+ }
3865
4048
  function sanitizeHistoryFileSegment(value) {
3866
4049
  return String(value || "").replace(/[^a-zA-Z0-9_-]/g, "_");
3867
4050
  }
@@ -3875,71 +4058,386 @@ function listHistoryFiles(dir, historySessionId) {
3875
4058
  return true;
3876
4059
  }).sort().reverse();
3877
4060
  }
3878
- function buildSavedHistoryCacheSignature(dir, files) {
3879
- return files.map((file2) => {
4061
+ function normalizeSavedHistorySessionId(agentType, historySessionId) {
4062
+ const normalizedId = String(historySessionId || "").trim();
4063
+ if (!normalizedId) return "";
4064
+ const strictProviderId = normalizeProviderSessionId(agentType, normalizedId);
4065
+ if (strictProviderId) return strictProviderId;
4066
+ return agentType === "hermes-cli" ? "" : normalizedId;
4067
+ }
4068
+ function extractSavedHistorySessionIdFromFile(agentType, file2) {
4069
+ const match = file2.match(/^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/);
4070
+ return normalizeSavedHistorySessionId(agentType, match?.[1] || "");
4071
+ }
4072
+ function buildSavedHistoryFileSignatureMap(dir, files) {
4073
+ return new Map(files.map((file2) => {
3880
4074
  try {
3881
4075
  const stat4 = fs3.statSync(path7.join(dir, file2));
3882
- return `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
4076
+ return [file2, `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`];
3883
4077
  } catch {
3884
- return `${file2}:missing`;
3885
- }
3886
- }).join("|");
3887
- }
3888
- function computeSavedHistorySessionSummaries(agentType, dir, files) {
3889
- const groupedFiles = /* @__PURE__ */ new Map();
3890
- const filePattern = /^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/;
3891
- for (const file2 of files) {
3892
- const match = file2.match(filePattern);
3893
- if (!match?.[1]) continue;
3894
- const historySessionId = match[1];
3895
- const grouped = groupedFiles.get(historySessionId) || [];
3896
- grouped.push(file2);
3897
- groupedFiles.set(historySessionId, grouped);
3898
- }
3899
- const summaries = [];
3900
- for (const [historySessionId, grouped] of groupedFiles.entries()) {
3901
- let messageCount = 0;
3902
- let firstMessageAt = 0;
3903
- let lastMessageAt = 0;
3904
- let sessionTitle = "";
3905
- let preview = "";
3906
- let workspace = "";
3907
- for (const file2 of grouped.sort()) {
3908
- const filePath = path7.join(dir, file2);
3909
- const content = fs3.readFileSync(filePath, "utf-8");
3910
- const lines = content.split("\n").filter(Boolean);
3911
- for (const line of lines) {
3912
- let parsed = null;
4078
+ return [file2, `${file2}:missing`];
4079
+ }
4080
+ }));
4081
+ }
4082
+ function buildSavedHistoryCacheSignature(files, fileSignatures) {
4083
+ return files.map((file2) => fileSignatures.get(file2) || `${file2}:missing`).join("|");
4084
+ }
4085
+ function getSavedHistoryIndexFilePath(dir) {
4086
+ return path7.join(dir, SAVED_HISTORY_INDEX_FILE);
4087
+ }
4088
+ function getSavedHistoryIndexLockPath(dir) {
4089
+ return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
4090
+ }
4091
+ function sleepBlocking(ms) {
4092
+ if (ms <= 0) return;
4093
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
4094
+ }
4095
+ function loadPersistedSavedHistoryIndexFromFile(dir) {
4096
+ try {
4097
+ const filePath = getSavedHistoryIndexFilePath(dir);
4098
+ if (!fs3.existsSync(filePath)) return /* @__PURE__ */ new Map();
4099
+ const raw = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
4100
+ if (!raw || raw.version !== SAVED_HISTORY_INDEX_VERSION || !raw.files || typeof raw.files !== "object") {
4101
+ return /* @__PURE__ */ new Map();
4102
+ }
4103
+ return new Map(
4104
+ Object.entries(raw.files).filter(([file2, entry]) => !!file2 && !!entry && typeof entry.signature === "string").map(([file2, entry]) => [file2, {
4105
+ signature: entry.signature,
4106
+ summary: entry.summary || null
4107
+ }])
4108
+ );
4109
+ } catch {
4110
+ return /* @__PURE__ */ new Map();
4111
+ }
4112
+ }
4113
+ function writePersistedSavedHistoryIndexFile(dir, entries) {
4114
+ const filePath = getSavedHistoryIndexFilePath(dir);
4115
+ const tempPath = `${filePath}.tmp`;
4116
+ const payload = {
4117
+ version: SAVED_HISTORY_INDEX_VERSION,
4118
+ files: Object.fromEntries(entries.entries()),
4119
+ sessions: buildSavedHistorySessionSummaryMapFromEntries(entries)
4120
+ };
4121
+ fs3.writeFileSync(tempPath, JSON.stringify(payload), "utf-8");
4122
+ fs3.renameSync(tempPath, filePath);
4123
+ }
4124
+ function acquireSavedHistoryIndexLock(dir) {
4125
+ const lockPath = getSavedHistoryIndexLockPath(dir);
4126
+ const deadline = Date.now() + SAVED_HISTORY_INDEX_LOCK_WAIT_MS;
4127
+ while (Date.now() <= deadline) {
4128
+ try {
4129
+ fs3.mkdirSync(lockPath);
4130
+ return () => {
3913
4131
  try {
3914
- parsed = JSON.parse(line);
4132
+ fs3.rmSync(lockPath, { recursive: true, force: true });
3915
4133
  } catch {
3916
- parsed = null;
3917
4134
  }
3918
- if (!parsed || parsed.historySessionId !== historySessionId) continue;
3919
- if (parsed.kind === "session_start") {
3920
- if (!workspace && parsed.workspace) workspace = parsed.workspace;
4135
+ };
4136
+ } catch (error48) {
4137
+ if (error48?.code !== "EEXIST") return null;
4138
+ try {
4139
+ const stat4 = fs3.statSync(lockPath);
4140
+ if (Date.now() - stat4.mtimeMs > SAVED_HISTORY_INDEX_LOCK_STALE_MS) {
4141
+ fs3.rmSync(lockPath, { recursive: true, force: true });
3921
4142
  continue;
3922
4143
  }
3923
- messageCount += 1;
3924
- if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
3925
- if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
3926
- if (parsed.sessionTitle) sessionTitle = parsed.sessionTitle;
3927
- if (parsed.role !== "system" && parsed.content.trim()) preview = parsed.content.trim();
3928
- }
3929
- }
3930
- if (messageCount === 0 || !lastMessageAt) continue;
3931
- summaries.push({
3932
- historySessionId,
3933
- sessionTitle: sessionTitle || void 0,
3934
- messageCount,
3935
- firstMessageAt,
3936
- lastMessageAt,
3937
- preview: preview || void 0,
3938
- workspace: workspace || void 0
3939
- });
4144
+ } catch {
4145
+ continue;
4146
+ }
4147
+ sleepBlocking(SAVED_HISTORY_INDEX_LOCK_POLL_MS);
4148
+ }
4149
+ }
4150
+ return null;
4151
+ }
4152
+ function withLockedPersistedSavedHistoryIndex(dir, callback) {
4153
+ const release2 = acquireSavedHistoryIndexLock(dir);
4154
+ if (!release2) return null;
4155
+ try {
4156
+ const entries = loadPersistedSavedHistoryIndexFromFile(dir);
4157
+ const result = callback(entries);
4158
+ writePersistedSavedHistoryIndexFile(dir, entries);
4159
+ return result;
4160
+ } catch {
4161
+ return null;
4162
+ } finally {
4163
+ release2();
3940
4164
  }
3941
- summaries.sort((a, b) => b.lastMessageAt - a.lastMessageAt);
3942
- return summaries;
4165
+ }
4166
+ function loadPersistedSavedHistoryIndex(dir) {
4167
+ return loadPersistedSavedHistoryIndexFromFile(dir);
4168
+ }
4169
+ function savePersistedSavedHistoryIndex(dir, entries) {
4170
+ withLockedPersistedSavedHistoryIndex(dir, (currentEntries) => {
4171
+ const incomingFiles = new Set(Array.from(entries.keys()));
4172
+ for (const [file2, entry] of Array.from(entries.entries())) {
4173
+ const liveSignature = buildSavedHistoryFileSignature(dir, file2);
4174
+ const existingEntry = currentEntries.get(file2);
4175
+ if (existingEntry && existingEntry.signature !== liveSignature && entry.signature !== liveSignature) {
4176
+ continue;
4177
+ }
4178
+ if (entry.signature !== liveSignature && (!existingEntry || existingEntry.signature !== liveSignature)) {
4179
+ continue;
4180
+ }
4181
+ currentEntries.set(file2, entry.signature === liveSignature ? entry : {
4182
+ signature: liveSignature,
4183
+ summary: existingEntry?.summary || entry.summary
4184
+ });
4185
+ }
4186
+ for (const file2 of Array.from(currentEntries.keys())) {
4187
+ if (incomingFiles.has(file2)) continue;
4188
+ if (!fs3.existsSync(path7.join(dir, file2))) {
4189
+ currentEntries.delete(file2);
4190
+ }
4191
+ }
4192
+ });
4193
+ }
4194
+ function invalidatePersistedSavedHistoryIndex(agentType, dir) {
4195
+ try {
4196
+ fs3.rmSync(getSavedHistoryIndexFilePath(dir), { force: true });
4197
+ } catch {
4198
+ }
4199
+ savedHistorySessionCache.delete(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"));
4200
+ }
4201
+ function buildSavedHistoryIndexFileSignature(dir) {
4202
+ try {
4203
+ const stat4 = fs3.statSync(getSavedHistoryIndexFilePath(dir));
4204
+ return `index:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
4205
+ } catch {
4206
+ return "index:missing";
4207
+ }
4208
+ }
4209
+ function historyDirectoryHasFilesNewerThanIndex(dir) {
4210
+ try {
4211
+ const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
4212
+ const files = listHistoryFiles(dir);
4213
+ for (const file2 of files) {
4214
+ const stat4 = fs3.statSync(path7.join(dir, file2));
4215
+ if (stat4.mtimeMs > indexStat.mtimeMs) return true;
4216
+ }
4217
+ return false;
4218
+ } catch {
4219
+ return true;
4220
+ }
4221
+ }
4222
+ function buildSavedHistoryFileSignature(dir, file2) {
4223
+ try {
4224
+ const stat4 = fs3.statSync(path7.join(dir, file2));
4225
+ return `${file2}:${stat4.size}:${Math.trunc(stat4.mtimeMs)}`;
4226
+ } catch {
4227
+ return `${file2}:missing`;
4228
+ }
4229
+ }
4230
+ function persistSavedHistoryFileSummaryEntry(agentType, dir, file2, updater) {
4231
+ const filePath = path7.join(dir, file2);
4232
+ const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
4233
+ const currentEntry = entries.get(file2) || null;
4234
+ const nextSummary = updater(currentEntry?.summary || null);
4235
+ const nextEntry = {
4236
+ signature: buildSavedHistoryFileSignature(dir, file2),
4237
+ summary: nextSummary
4238
+ };
4239
+ entries.set(file2, nextEntry);
4240
+ savedHistoryFileSummaryCache.set(filePath, nextEntry);
4241
+ return nextEntry;
4242
+ });
4243
+ if (!result) return;
4244
+ if (result.summary?.historySessionId && shouldScheduleSavedHistoryRollupForSignature(result.signature)) {
4245
+ scheduleSavedHistoryRollup(agentType, result.summary.historySessionId);
4246
+ }
4247
+ }
4248
+ function updateSavedHistoryIndexForSessionStart(agentType, dir, file2, historySessionId, workspace) {
4249
+ const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId);
4250
+ const normalizedWorkspace = String(workspace || "").trim();
4251
+ if (!normalizedSessionId || !normalizedWorkspace) return;
4252
+ persistSavedHistoryFileSummaryEntry(agentType, dir, file2, (currentSummary) => ({
4253
+ file: file2,
4254
+ historySessionId: normalizedSessionId,
4255
+ messageCount: currentSummary?.messageCount || 0,
4256
+ firstMessageAt: currentSummary?.firstMessageAt || 0,
4257
+ lastMessageAt: currentSummary?.lastMessageAt || 0,
4258
+ sessionTitle: currentSummary?.sessionTitle,
4259
+ preview: currentSummary?.preview,
4260
+ workspace: normalizedWorkspace
4261
+ }));
4262
+ }
4263
+ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file2, historySessionId, messages) {
4264
+ const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId || "");
4265
+ if (!normalizedSessionId || messages.length === 0) return;
4266
+ persistSavedHistoryFileSummaryEntry(agentType, dir, file2, (currentSummary) => {
4267
+ const nextSummary = {
4268
+ file: file2,
4269
+ historySessionId: normalizedSessionId,
4270
+ messageCount: currentSummary?.messageCount || 0,
4271
+ firstMessageAt: currentSummary?.firstMessageAt || 0,
4272
+ lastMessageAt: currentSummary?.lastMessageAt || 0,
4273
+ sessionTitle: currentSummary?.sessionTitle,
4274
+ preview: currentSummary?.preview,
4275
+ workspace: currentSummary?.workspace
4276
+ };
4277
+ for (const message of messages) {
4278
+ if (!message || message.historySessionId !== historySessionId) continue;
4279
+ if (message.kind === "session_start") {
4280
+ if (message.workspace) nextSummary.workspace = message.workspace;
4281
+ continue;
4282
+ }
4283
+ nextSummary.messageCount += 1;
4284
+ if (!nextSummary.firstMessageAt || message.receivedAt < nextSummary.firstMessageAt) {
4285
+ nextSummary.firstMessageAt = message.receivedAt;
4286
+ }
4287
+ if (!nextSummary.lastMessageAt || message.receivedAt >= nextSummary.lastMessageAt) {
4288
+ nextSummary.lastMessageAt = message.receivedAt;
4289
+ if (message.sessionTitle) nextSummary.sessionTitle = message.sessionTitle;
4290
+ if (message.role !== "system" && message.content.trim()) nextSummary.preview = message.content.trim();
4291
+ } else if (message.sessionTitle) {
4292
+ nextSummary.sessionTitle = message.sessionTitle;
4293
+ }
4294
+ if (!nextSummary.preview && message.role !== "system" && message.content.trim()) {
4295
+ nextSummary.preview = message.content.trim();
4296
+ }
4297
+ }
4298
+ return nextSummary;
4299
+ });
4300
+ }
4301
+ function computeSavedHistoryFileSummary(agentType, dir, file2) {
4302
+ const historySessionId = extractSavedHistorySessionIdFromFile(agentType, file2);
4303
+ if (!historySessionId) return null;
4304
+ const filePath = path7.join(dir, file2);
4305
+ const content = fs3.readFileSync(filePath, "utf-8");
4306
+ const lines = content.split("\n").filter(Boolean);
4307
+ let messageCount = 0;
4308
+ let firstMessageAt = 0;
4309
+ let lastMessageAt = 0;
4310
+ let sessionTitle = "";
4311
+ let preview = "";
4312
+ let workspace = "";
4313
+ for (const line of lines) {
4314
+ let parsed = null;
4315
+ try {
4316
+ parsed = JSON.parse(line);
4317
+ } catch {
4318
+ parsed = null;
4319
+ }
4320
+ if (!parsed || parsed.historySessionId !== historySessionId) continue;
4321
+ if (parsed.kind === "session_start") {
4322
+ if (!workspace && parsed.workspace) workspace = parsed.workspace;
4323
+ continue;
4324
+ }
4325
+ messageCount += 1;
4326
+ if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
4327
+ if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
4328
+ if (parsed.sessionTitle) sessionTitle = parsed.sessionTitle;
4329
+ if (parsed.role !== "system" && parsed.content.trim()) preview = parsed.content.trim();
4330
+ }
4331
+ if (messageCount === 0 || !lastMessageAt) return null;
4332
+ return {
4333
+ file: file2,
4334
+ historySessionId,
4335
+ messageCount,
4336
+ firstMessageAt,
4337
+ lastMessageAt,
4338
+ sessionTitle: sessionTitle || void 0,
4339
+ preview: preview || void 0,
4340
+ workspace: workspace || void 0
4341
+ };
4342
+ }
4343
+ function shouldScheduleSavedHistoryRollupForSignature(signature) {
4344
+ const parts = String(signature || "").split(":");
4345
+ const size = Number(parts[1] || 0);
4346
+ return shouldScheduleSavedHistoryRollup(size);
4347
+ }
4348
+ function scheduleSavedHistoryRollup(agentType, historySessionId) {
4349
+ const key = `${agentType}:${historySessionId}`;
4350
+ if (!historySessionId || savedHistoryRollupInFlight.has(key)) return;
4351
+ savedHistoryRollupInFlight.add(key);
4352
+ setTimeout(() => {
4353
+ try {
4354
+ new ChatHistoryWriter().compactHistorySession(agentType, historySessionId);
4355
+ } finally {
4356
+ savedHistoryRollupInFlight.delete(key);
4357
+ }
4358
+ }, 0);
4359
+ }
4360
+ function scheduleSavedHistoryBackgroundRefresh(agentType, dir) {
4361
+ const key = `${agentType}:${dir}`;
4362
+ if (savedHistoryBackgroundRefresh.has(key)) return;
4363
+ savedHistoryBackgroundRefresh.add(key);
4364
+ setTimeout(() => {
4365
+ try {
4366
+ if (!fs3.existsSync(dir)) return;
4367
+ const files = listHistoryFiles(dir);
4368
+ const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
4369
+ const persistedEntries = loadPersistedSavedHistoryIndex(dir);
4370
+ const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
4371
+ savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
4372
+ const refreshedIndexSignature = buildSavedHistoryIndexFileSignature(dir);
4373
+ savedHistorySessionCache.set(agentType.replace(/[^a-zA-Z0-9_-]/g, "_"), {
4374
+ signature: refreshedIndexSignature,
4375
+ summaries: computed.summaries || []
4376
+ });
4377
+ for (const [file2, entry] of Array.from(computed.persistedEntries.entries())) {
4378
+ if (!entry?.summary || !shouldScheduleSavedHistoryRollupForSignature(entry.signature)) continue;
4379
+ scheduleSavedHistoryRollup(agentType, entry.summary.historySessionId);
4380
+ }
4381
+ } catch {
4382
+ } finally {
4383
+ savedHistoryBackgroundRefresh.delete(key);
4384
+ }
4385
+ }, 0);
4386
+ }
4387
+ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries) {
4388
+ const summaryBySessionId = /* @__PURE__ */ new Map();
4389
+ const nextPersistedEntries = /* @__PURE__ */ new Map();
4390
+ for (const file2 of files.slice().sort()) {
4391
+ const filePath = path7.join(dir, file2);
4392
+ const signature = fileSignatures.get(file2) || `${file2}:missing`;
4393
+ const cached2 = savedHistoryFileSummaryCache.get(filePath);
4394
+ const persisted = persistedEntries.get(file2);
4395
+ const reusableEntry = cached2?.signature === signature ? cached2 : persisted?.signature === signature ? persisted : null;
4396
+ const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(agentType, dir, file2);
4397
+ const nextEntry = reusableEntry || {
4398
+ signature,
4399
+ summary: fileSummary
4400
+ };
4401
+ if (!reusableEntry) {
4402
+ nextEntry.signature = signature;
4403
+ nextEntry.summary = fileSummary;
4404
+ }
4405
+ savedHistoryFileSummaryCache.set(filePath, nextEntry);
4406
+ nextPersistedEntries.set(file2, nextEntry);
4407
+ if (!fileSummary) continue;
4408
+ const existing = summaryBySessionId.get(fileSummary.historySessionId);
4409
+ if (fileSummary.messageCount <= 0 || !fileSummary.lastMessageAt) {
4410
+ continue;
4411
+ }
4412
+ if (!existing) {
4413
+ summaryBySessionId.set(fileSummary.historySessionId, {
4414
+ historySessionId: fileSummary.historySessionId,
4415
+ sessionTitle: fileSummary.sessionTitle,
4416
+ messageCount: fileSummary.messageCount,
4417
+ firstMessageAt: fileSummary.firstMessageAt,
4418
+ lastMessageAt: fileSummary.lastMessageAt,
4419
+ preview: fileSummary.preview,
4420
+ workspace: fileSummary.workspace
4421
+ });
4422
+ continue;
4423
+ }
4424
+ existing.messageCount += fileSummary.messageCount;
4425
+ if (!existing.firstMessageAt || fileSummary.firstMessageAt < existing.firstMessageAt) {
4426
+ existing.firstMessageAt = fileSummary.firstMessageAt;
4427
+ }
4428
+ if (fileSummary.lastMessageAt >= existing.lastMessageAt) {
4429
+ existing.lastMessageAt = fileSummary.lastMessageAt;
4430
+ if (fileSummary.sessionTitle) existing.sessionTitle = fileSummary.sessionTitle;
4431
+ if (fileSummary.preview) existing.preview = fileSummary.preview;
4432
+ }
4433
+ if (!existing.workspace && fileSummary.workspace) {
4434
+ existing.workspace = fileSummary.workspace;
4435
+ }
4436
+ }
4437
+ return {
4438
+ summaries: Array.from(summaryBySessionId.values()).sort((a, b) => b.lastMessageAt - a.lastMessageAt),
4439
+ persistedEntries: nextPersistedEntries
4440
+ };
3943
4441
  }
3944
4442
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0) {
3945
4443
  try {
@@ -3997,18 +4495,51 @@ function listSavedHistorySessions(agentType, options = {}) {
3997
4495
  savedHistorySessionCache.delete(sanitized);
3998
4496
  return { sessions: [], hasMore: false };
3999
4497
  }
4000
- const files = listHistoryFiles(dir);
4001
- const signature = buildSavedHistoryCacheSignature(dir, files);
4002
4498
  const cached2 = savedHistorySessionCache.get(sanitized);
4003
- const summaries = cached2?.signature === signature ? cached2.summaries : computeSavedHistorySessionSummaries(agentType, dir, files);
4004
- if (!cached2 || cached2.signature !== signature) {
4499
+ const offset = Math.max(0, options.offset || 0);
4500
+ const limit = Math.max(1, options.limit || 30);
4501
+ const indexSignature = buildSavedHistoryIndexFileSignature(dir);
4502
+ let cacheWasInvalidated = false;
4503
+ if (cached2) {
4504
+ const cacheLooksPersisted = cached2.signature.startsWith("index:");
4505
+ const cacheStillValid = cacheLooksPersisted ? cached2.signature === indexSignature : (() => {
4506
+ const files2 = listHistoryFiles(dir);
4507
+ const fileSignatures2 = buildSavedHistoryFileSignatureMap(dir, files2);
4508
+ return cached2.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
4509
+ })();
4510
+ if (cacheStillValid) {
4511
+ const sliced2 = cached2.summaries.slice(offset, offset + limit);
4512
+ return {
4513
+ sessions: sliced2,
4514
+ hasMore: cached2.summaries.length > offset + limit
4515
+ };
4516
+ }
4517
+ cacheWasInvalidated = true;
4518
+ }
4519
+ const persistedSessions = readPersistedSavedHistorySessionSummaries(dir);
4520
+ if (!cacheWasInvalidated && persistedSessions?.length && !historyDirectoryHasFilesNewerThanIndex(dir)) {
4005
4521
  savedHistorySessionCache.set(sanitized, {
4006
- signature,
4007
- summaries
4522
+ signature: indexSignature,
4523
+ summaries: persistedSessions
4008
4524
  });
4525
+ scheduleSavedHistoryBackgroundRefresh(agentType, dir);
4526
+ const sliced2 = persistedSessions.slice(offset, offset + limit);
4527
+ return {
4528
+ sessions: sliced2,
4529
+ hasMore: persistedSessions.length > offset + limit
4530
+ };
4009
4531
  }
4010
- const offset = Math.max(0, options.offset || 0);
4011
- const limit = Math.max(1, options.limit || 30);
4532
+ const files = listHistoryFiles(dir);
4533
+ const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
4534
+ const signature = buildSavedHistoryCacheSignature(files, fileSignatures);
4535
+ const persistedEntries = loadPersistedSavedHistoryIndex(dir);
4536
+ const computed = computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatures, persistedEntries);
4537
+ const summaries = computed.summaries || [];
4538
+ savePersistedSavedHistoryIndex(dir, computed.persistedEntries || /* @__PURE__ */ new Map());
4539
+ savedHistorySessionCache.set(sanitized, {
4540
+ signature,
4541
+ summaries
4542
+ });
4012
4543
  const sliced = summaries.slice(offset, offset + limit);
4013
4544
  return {
4014
4545
  sessions: sliced,
@@ -4018,7 +4549,7 @@ function listSavedHistorySessions(agentType, options = {}) {
4018
4549
  return { sessions: [], hasMore: false };
4019
4550
  }
4020
4551
  }
4021
- var fs3, path7, os6, HISTORY_DIR, RETAIN_DAYS, savedHistorySessionCache, CODEX_STARTER_PROMPT_RE, ChatHistoryWriter;
4552
+ var fs3, path7, os6, HISTORY_DIR, RETAIN_DAYS, SAVED_HISTORY_INDEX_VERSION, SAVED_HISTORY_INDEX_FILE, SAVED_HISTORY_INDEX_LOCK_SUFFIX, SAVED_HISTORY_INDEX_LOCK_WAIT_MS, SAVED_HISTORY_INDEX_LOCK_STALE_MS, SAVED_HISTORY_INDEX_LOCK_POLL_MS, SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES, savedHistorySessionCache, savedHistoryFileSummaryCache, savedHistoryBackgroundRefresh, savedHistoryRollupInFlight, CODEX_STARTER_PROMPT_RE, ChatHistoryWriter;
4022
4553
  var init_chat_history = __esm({
4023
4554
  "../../oss/packages/daemon-core/src/config/chat-history.ts"() {
4024
4555
  "use strict";
@@ -4026,9 +4557,20 @@ var init_chat_history = __esm({
4026
4557
  path7 = __toESM(require("path"));
4027
4558
  os6 = __toESM(require("os"));
4028
4559
  init_chat_message_normalization();
4560
+ init_provider_session_id();
4029
4561
  HISTORY_DIR = path7.join(os6.homedir(), ".adhdev", "history");
4030
4562
  RETAIN_DAYS = 30;
4563
+ SAVED_HISTORY_INDEX_VERSION = 1;
4564
+ SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
4565
+ SAVED_HISTORY_INDEX_LOCK_SUFFIX = ".lock";
4566
+ SAVED_HISTORY_INDEX_LOCK_WAIT_MS = 1500;
4567
+ SAVED_HISTORY_INDEX_LOCK_STALE_MS = 15e3;
4568
+ SAVED_HISTORY_INDEX_LOCK_POLL_MS = 25;
4569
+ SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES = 16 * 1024 * 1024;
4031
4570
  savedHistorySessionCache = /* @__PURE__ */ new Map();
4571
+ savedHistoryFileSummaryCache = /* @__PURE__ */ new Map();
4572
+ savedHistoryBackgroundRefresh = /* @__PURE__ */ new Set();
4573
+ savedHistoryRollupInFlight = /* @__PURE__ */ new Set();
4032
4574
  CODEX_STARTER_PROMPT_RE = /^(?:[›❯]\s*)?(?:Find and fix a bug in @filename|Improve documentation in @filename|Write tests for @filename|Explain this codebase|Summarize recent commits|Implement \{feature\}|Use \/skills(?: to list available skills)?|Run \/review on my current changes)$/i;
4033
4575
  ChatHistoryWriter = class {
4034
4576
  /** Last seen message count per agent (deduplication) */
@@ -4103,9 +4645,11 @@ var init_chat_history = __esm({
4103
4645
  fs3.mkdirSync(dir, { recursive: true });
4104
4646
  const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4105
4647
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
4106
- const filePath = path7.join(dir, `${filePrefix}${date5}.jsonl`);
4648
+ const fileName = `${filePrefix}${date5}.jsonl`;
4649
+ const filePath = path7.join(dir, fileName);
4107
4650
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
4108
4651
  fs3.appendFileSync(filePath, lines, "utf-8");
4652
+ updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
4109
4653
  const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
4110
4654
  if (!historySessionId && messages.length < prevCount * 0.5 && prevCount > 3) {
4111
4655
  seenHashes.clear();
@@ -4196,7 +4740,8 @@ var init_chat_history = __esm({
4196
4740
  const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
4197
4741
  fs3.mkdirSync(dir, { recursive: true });
4198
4742
  const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4199
- const filePath = path7.join(dir, `${this.sanitize(id)}_${date5}.jsonl`);
4743
+ const fileName = `${this.sanitize(id)}_${date5}.jsonl`;
4744
+ const filePath = path7.join(dir, fileName);
4200
4745
  const record2 = {
4201
4746
  ts: (/* @__PURE__ */ new Date()).toISOString(),
4202
4747
  receivedAt: Date.now(),
@@ -4209,6 +4754,7 @@ var init_chat_history = __esm({
4209
4754
  workspace: ws
4210
4755
  };
4211
4756
  fs3.appendFileSync(filePath, JSON.stringify(record2) + "\n", "utf-8");
4757
+ updateSavedHistoryIndexForSessionStart(agentType, dir, fileName, id, ws);
4212
4758
  } catch {
4213
4759
  }
4214
4760
  }
@@ -4274,6 +4820,7 @@ var init_chat_history = __esm({
4274
4820
  }
4275
4821
  fs3.unlinkSync(sourcePath);
4276
4822
  }
4823
+ invalidatePersistedSavedHistoryIndex(agentType, dir);
4277
4824
  } catch {
4278
4825
  }
4279
4826
  }
@@ -4323,6 +4870,7 @@ var init_chat_history = __esm({
4323
4870
  fs3.writeFileSync(filePath, `${collapsed.map((entry) => JSON.stringify(entry)).join("\n")}
4324
4871
  `, "utf-8");
4325
4872
  }
4873
+ invalidatePersistedSavedHistoryIndex(agentType, dir);
4326
4874
  } catch {
4327
4875
  }
4328
4876
  }
@@ -4342,13 +4890,18 @@ var init_chat_history = __esm({
4342
4890
  for (const dir of agentDirs) {
4343
4891
  const dirPath = path7.join(HISTORY_DIR, dir.name);
4344
4892
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
4893
+ let removedAny = false;
4345
4894
  for (const file2 of files) {
4346
4895
  const filePath = path7.join(dirPath, file2);
4347
4896
  const stat4 = fs3.statSync(filePath);
4348
4897
  if (stat4.mtimeMs < cutoff) {
4349
4898
  fs3.unlinkSync(filePath);
4899
+ removedAny = true;
4350
4900
  }
4351
4901
  }
4902
+ if (removedAny) {
4903
+ invalidatePersistedSavedHistoryIndex(dir.name, dirPath);
4904
+ }
4352
4905
  }
4353
4906
  } catch {
4354
4907
  }
@@ -6183,7 +6736,7 @@ function shouldIncludeSessionMetadata(profile) {
6183
6736
  return profile !== "live";
6184
6737
  }
6185
6738
  function shouldIncludeRuntimeMetadata(profile) {
6186
- return profile !== "live";
6739
+ return true;
6187
6740
  }
6188
6741
  function findCdpManager(cdpManagers, key) {
6189
6742
  const exact = cdpManagers.get(key);
@@ -6275,6 +6828,21 @@ function buildExtensionAgentSession(parent, ext, options) {
6275
6828
  lastUpdated: ext.lastUpdated
6276
6829
  };
6277
6830
  }
6831
+ function shouldIncludeExtensionSession(ext) {
6832
+ const status = String(ext.status || "").trim().toLowerCase();
6833
+ const hasActiveChat = !!ext.activeChat;
6834
+ const hasMessages = Array.isArray(ext.activeChat?.messages) && ext.activeChat.messages.length > 0;
6835
+ const hasModal = !!ext.activeChat?.activeModal;
6836
+ const hasStreams = Array.isArray(ext.agentStreams) && ext.agentStreams.length > 0;
6837
+ const hasProviderSessionId = typeof ext.providerSessionId === "string" && ext.providerSessionId.trim().length > 0;
6838
+ const hasControlValues = !!(ext.controlValues && Object.keys(ext.controlValues).length > 0);
6839
+ const hasProviderControls = Array.isArray(ext.providerControls) && ext.providerControls.length > 0;
6840
+ const hasOpenPanelCapability = Array.isArray(ext.sessionCapabilities) && ext.sessionCapabilities.includes("open_panel");
6841
+ const hasSummaryMetadata = !!ext.summaryMetadata;
6842
+ const hasError = typeof ext.errorMessage === "string" && ext.errorMessage.trim().length > 0;
6843
+ const hasInterestingStatus = !!status && !["idle", "panel_hidden", "disconnected", "not_monitored"].includes(status);
6844
+ return hasActiveChat || hasMessages || hasModal || hasStreams || hasProviderSessionId || hasControlValues || hasProviderControls || hasOpenPanelCapability || hasSummaryMetadata || hasError || hasInterestingStatus;
6845
+ }
6278
6846
  function buildCliSession(state, options) {
6279
6847
  const profile = options.profile || "full";
6280
6848
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
@@ -6300,8 +6868,12 @@ function buildCliSession(state, options) {
6300
6868
  runtimeKey: state.runtime?.runtimeKey,
6301
6869
  runtimeDisplayName: state.runtime?.displayName,
6302
6870
  runtimeWorkspaceLabel: state.runtime?.workspaceLabel,
6871
+ runtimeLifecycle: state.runtime?.lifecycle ?? null,
6872
+ runtimeSurfaceKind: state.runtime?.surfaceKind,
6303
6873
  runtimeWriteOwner: state.runtime?.writeOwner || null,
6304
- runtimeAttachedClients: state.runtime?.attachedClients || []
6874
+ runtimeAttachedClients: state.runtime?.attachedClients || [],
6875
+ runtimeRestoredFromStorage: state.runtime?.restoredFromStorage === true,
6876
+ runtimeRecoveryState: state.runtime?.recoveryState ?? null
6305
6877
  },
6306
6878
  mode: state.mode,
6307
6879
  resume: state.resume,
@@ -6358,6 +6930,7 @@ function buildSessionEntries(allStates, cdpManagers, options = {}) {
6358
6930
  for (const state of ideStates) {
6359
6931
  sessions.push(buildIdeWorkspaceSession(state, cdpManagers, options));
6360
6932
  for (const ext of state.extensions) {
6933
+ if (!shouldIncludeExtensionSession(ext)) continue;
6361
6934
  sessions.push(buildExtensionAgentSession(state, ext, options));
6362
6935
  }
6363
6936
  }
@@ -8610,7 +9183,9 @@ function applyProviderPatch(h, args, payload) {
8610
9183
  });
8611
9184
  }
8612
9185
  async function executeProviderScript(h, args, scriptName) {
8613
- const resolvedProviderType = h.currentSession?.providerType || h.currentProviderType || args?.agentType || args?.providerType;
9186
+ const explicitTargetSessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
9187
+ const targetSession = explicitTargetSessionId ? h.ctx.sessionRegistry?.get(explicitTargetSessionId) : void 0;
9188
+ const resolvedProviderType = targetSession?.providerType || h.currentSession?.providerType || h.currentProviderType || args?.agentType || args?.providerType;
8614
9189
  if (!resolvedProviderType) return { success: false, error: "targetSessionId or providerType is required" };
8615
9190
  const loader = h.ctx.providerLoader;
8616
9191
  if (!loader) return { success: false, error: "ProviderLoader not initialized" };
@@ -8653,16 +9228,16 @@ async function executeProviderScript(h, args, scriptName) {
8653
9228
  const scriptFn = provider.scripts[actualScriptName];
8654
9229
  const scriptCode = scriptFn(normalizedArgs);
8655
9230
  if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
8656
- const cdpKey = provider.category === "ide" ? h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : h.currentSession?.cdpManagerKey || h.currentManagerKey;
9231
+ const cdpKey = provider.category === "ide" ? targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey || resolvedProviderType : targetSession?.cdpManagerKey || h.currentSession?.cdpManagerKey || h.currentManagerKey;
8657
9232
  LOG.info("Command", `[ExtScript] provider=${provider.type} category=${provider.category} cdpKey=${cdpKey}`);
8658
9233
  const cdp = h.getCdp(cdpKey);
8659
9234
  if (!cdp?.isConnected) return { success: false, error: `No CDP connection for ${cdpKey || "any"}` };
8660
9235
  try {
8661
9236
  let result;
8662
9237
  if (provider.category === "extension") {
8663
- const runtimeSessionId = h.currentSession?.sessionId || args?.targetSessionId;
9238
+ const runtimeSessionId = explicitTargetSessionId || h.currentSession?.sessionId;
8664
9239
  if (!runtimeSessionId) return { success: false, error: `No target session found for ${resolvedProviderType}` };
8665
- const parentSessionId = h.currentSession?.parentSessionId;
9240
+ const parentSessionId = targetSession?.parentSessionId || h.currentSession?.parentSessionId;
8666
9241
  if (parentSessionId) {
8667
9242
  await h.agentStream?.setActiveSession(cdp, parentSessionId, runtimeSessionId);
8668
9243
  await h.agentStream?.syncActiveSession(cdp, parentSessionId);
@@ -10208,11 +10783,11 @@ __export(dist_exports, {
10208
10783
  ensureNodePtySpawnHelperPermissions: () => ensureNodePtySpawnHelperPermissions,
10209
10784
  formatRuntimeOwner: () => formatRuntimeOwner,
10210
10785
  getDefaultSessionHostEndpoint: () => getDefaultSessionHostEndpoint,
10211
- getSessionHostRecoveryLabel: () => getSessionHostRecoveryLabel,
10212
- getSessionHostSurfaceKind: () => getSessionHostSurfaceKind,
10786
+ getSessionHostRecoveryLabel: () => getSessionHostRecoveryLabel2,
10787
+ getSessionHostSurfaceKind: () => getSessionHostSurfaceKind2,
10213
10788
  getWorkspaceLabel: () => getWorkspaceLabel,
10214
- isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
10215
- isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot,
10789
+ isSessionHostLiveRuntime: () => isSessionHostLiveRuntime2,
10790
+ isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot2,
10216
10791
  resolveAttachableRuntimeRecord: () => resolveAttachableRuntimeRecord,
10217
10792
  resolveRuntimeRecord: () => resolveRuntimeRecord,
10218
10793
  sanitizeSpawnEnv: () => sanitizeSpawnEnv,
@@ -10252,14 +10827,14 @@ function buildRuntimeKey(payload, existingKeys) {
10252
10827
  }
10253
10828
  return candidate;
10254
10829
  }
10255
- function isSessionHostLiveRuntime(record2) {
10830
+ function isSessionHostLiveRuntime2(record2) {
10256
10831
  if (!record2) return false;
10257
10832
  if (record2.surfaceKind === "live_runtime") return true;
10258
10833
  if (record2.surfaceKind === "recovery_snapshot" || record2.surfaceKind === "inactive_record") return false;
10259
10834
  const lifecycle = String(record2.lifecycle || "").trim();
10260
- return LIVE_LIFECYCLES.has(lifecycle);
10835
+ return LIVE_LIFECYCLES2.has(lifecycle);
10261
10836
  }
10262
- function getSessionHostRecoveryLabel(meta3) {
10837
+ function getSessionHostRecoveryLabel2(meta3) {
10263
10838
  const recoveryState = typeof meta3?.runtimeRecoveryState === "string" ? String(meta3.runtimeRecoveryState).trim() : "";
10264
10839
  if (!recoveryState) return null;
10265
10840
  if (recoveryState === "auto_resumed") return "restored after restart";
@@ -10268,30 +10843,30 @@ function getSessionHostRecoveryLabel(meta3) {
10268
10843
  if (recoveryState === "orphan_snapshot") return "snapshot recovered";
10269
10844
  return recoveryState.replace(/_/g, " ");
10270
10845
  }
10271
- function isSessionHostRecoverySnapshot(record2) {
10846
+ function isSessionHostRecoverySnapshot2(record2) {
10272
10847
  if (!record2) return false;
10273
10848
  if (record2.surfaceKind === "recovery_snapshot") return true;
10274
10849
  if (record2.surfaceKind === "live_runtime" || record2.surfaceKind === "inactive_record") return false;
10275
- if (isSessionHostLiveRuntime(record2)) return false;
10850
+ if (isSessionHostLiveRuntime2(record2)) return false;
10276
10851
  const lifecycle = String(record2.lifecycle || "").trim();
10277
10852
  if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
10278
10853
  return false;
10279
10854
  }
10280
10855
  const meta3 = record2.meta || void 0;
10281
10856
  if (meta3?.restoredFromStorage === true) return true;
10282
- return getSessionHostRecoveryLabel(meta3) !== null;
10857
+ return getSessionHostRecoveryLabel2(meta3) !== null;
10283
10858
  }
10284
- function getSessionHostSurfaceKind(record2) {
10859
+ function getSessionHostSurfaceKind2(record2) {
10285
10860
  if (record2?.surfaceKind === "live_runtime" || record2?.surfaceKind === "recovery_snapshot" || record2?.surfaceKind === "inactive_record") {
10286
10861
  return record2.surfaceKind;
10287
10862
  }
10288
- if (isSessionHostLiveRuntime(record2)) return "live_runtime";
10289
- if (isSessionHostRecoverySnapshot(record2)) return "recovery_snapshot";
10863
+ if (isSessionHostLiveRuntime2(record2)) return "live_runtime";
10864
+ if (isSessionHostRecoverySnapshot2(record2)) return "recovery_snapshot";
10290
10865
  return "inactive_record";
10291
10866
  }
10292
10867
  function resolveAttachableRuntimeRecord(records, identifier) {
10293
10868
  const record2 = resolveRuntimeRecord(records, identifier);
10294
- const surfaceKind = getSessionHostSurfaceKind(record2);
10869
+ const surfaceKind = getSessionHostSurfaceKind2(record2);
10295
10870
  if (surfaceKind === "live_runtime") {
10296
10871
  return record2;
10297
10872
  }
@@ -10414,7 +10989,7 @@ function ensureNodePtySpawnHelperPermissions(logFn) {
10414
10989
  } catch {
10415
10990
  }
10416
10991
  }
10417
- var import_crypto3, path9, os9, path22, net, import_crypto4, os22, path32, __require, SessionRingBuffer, LIVE_LIFECYCLES, SessionHostRegistry, SessionHostClient;
10992
+ var import_crypto3, path9, os9, path22, net, import_crypto4, os22, path32, __require, SessionRingBuffer, LIVE_LIFECYCLES2, SessionHostRegistry, SessionHostClient;
10418
10993
  var init_dist = __esm({
10419
10994
  "../../oss/packages/session-host-core/dist/index.mjs"() {
10420
10995
  "use strict";
@@ -10492,7 +11067,7 @@ var init_dist = __esm({
10492
11067
  }
10493
11068
  }
10494
11069
  };
10495
- LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
11070
+ LIVE_LIFECYCLES2 = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
10496
11071
  SessionHostRegistry = class {
10497
11072
  sessions = /* @__PURE__ */ new Map();
10498
11073
  createSession(payload) {
@@ -13433,8 +14008,12 @@ var init_cli_provider_instance = __esm({
13433
14008
  runtimeKey: runtime.runtimeKey,
13434
14009
  displayName: runtime.displayName,
13435
14010
  workspaceLabel: runtime.workspaceLabel,
14011
+ lifecycle: runtime.lifecycle ?? null,
14012
+ surfaceKind: runtime.surfaceKind,
13436
14013
  writeOwner: runtime.writeOwner || null,
13437
- attachedClients: runtime.attachedClients || []
14014
+ attachedClients: runtime.attachedClients || [],
14015
+ restoredFromStorage: runtime.restoredFromStorage === true,
14016
+ recoveryState: runtime.recoveryState ?? null
13438
14017
  } : void 0,
13439
14018
  resume: this.provider.resume,
13440
14019
  controlValues: surface.controlValues,
@@ -35845,67 +36424,6 @@ var init_command_log = __esm({
35845
36424
  }
35846
36425
  });
35847
36426
 
35848
- // ../../oss/packages/daemon-core/src/session-host/runtime-surface.ts
35849
- function isSessionHostLiveRuntime2(record2) {
35850
- const lifecycle = String(record2?.lifecycle || "").trim();
35851
- return LIVE_LIFECYCLES2.has(lifecycle);
35852
- }
35853
- function getSessionHostRecoveryLabel2(meta3) {
35854
- const recoveryState = typeof meta3?.runtimeRecoveryState === "string" ? String(meta3.runtimeRecoveryState).trim() : "";
35855
- if (!recoveryState) return null;
35856
- if (recoveryState === "auto_resumed") return "restored after restart";
35857
- if (recoveryState === "resume_failed") return "restore failed";
35858
- if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
35859
- if (recoveryState === "orphan_snapshot") return "snapshot recovered";
35860
- return recoveryState.replace(/_/g, " ");
35861
- }
35862
- function isSessionHostRecoverySnapshot2(record2) {
35863
- if (!record2) return false;
35864
- if (isSessionHostLiveRuntime2(record2)) return false;
35865
- const lifecycle = String(record2.lifecycle || "").trim();
35866
- if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
35867
- return false;
35868
- }
35869
- const meta3 = record2.meta || void 0;
35870
- if (meta3?.restoredFromStorage === true) return true;
35871
- return getSessionHostRecoveryLabel2(meta3) !== null;
35872
- }
35873
- function getSessionHostSurfaceKind2(record2) {
35874
- if (isSessionHostLiveRuntime2(record2)) return "live_runtime";
35875
- if (isSessionHostRecoverySnapshot2(record2)) return "recovery_snapshot";
35876
- return "inactive_record";
35877
- }
35878
- function partitionSessionHostRecords(records) {
35879
- const liveRuntimes = [];
35880
- const recoverySnapshots = [];
35881
- const inactiveRecords = [];
35882
- for (const record2 of records) {
35883
- const kind = getSessionHostSurfaceKind2(record2);
35884
- if (kind === "live_runtime") {
35885
- liveRuntimes.push(record2);
35886
- } else if (kind === "recovery_snapshot") {
35887
- recoverySnapshots.push(record2);
35888
- } else {
35889
- inactiveRecords.push(record2);
35890
- }
35891
- }
35892
- return {
35893
- liveRuntimes,
35894
- recoverySnapshots,
35895
- inactiveRecords
35896
- };
35897
- }
35898
- function partitionSessionHostDiagnosticsSessions(records) {
35899
- return partitionSessionHostRecords(records || []);
35900
- }
35901
- var LIVE_LIFECYCLES2;
35902
- var init_runtime_surface = __esm({
35903
- "../../oss/packages/daemon-core/src/session-host/runtime-surface.ts"() {
35904
- "use strict";
35905
- LIVE_LIFECYCLES2 = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
35906
- }
35907
- });
35908
-
35909
36427
  // ../../oss/packages/daemon-core/src/status/snapshot.ts
35910
36428
  function buildRecentReadDebugSignature(snapshot) {
35911
36429
  return [
@@ -36441,7 +36959,7 @@ function summarizeSessionHostRecord(result) {
36441
36959
  return {
36442
36960
  runtimeKey: typeof record2.runtimeKey === "string" ? record2.runtimeKey : void 0,
36443
36961
  lifecycle: typeof record2.lifecycle === "string" ? record2.lifecycle : void 0,
36444
- surfaceKind: getSessionHostSurfaceKind2(record2),
36962
+ surfaceKind: getSessionHostSurfaceKind(record2),
36445
36963
  attachedClientCount: Array.isArray(record2.attachedClients) ? record2.attachedClients.length : void 0,
36446
36964
  hasWriteOwner: !!record2.writeOwner,
36447
36965
  writeOwnerClientId: typeof record2.writeOwner?.clientId === "string" ? record2.writeOwner.clientId : void 0
@@ -37523,6 +38041,28 @@ var init_subscription_updates = __esm({
37523
38041
  }
37524
38042
  });
37525
38043
 
38044
+ // ../../oss/packages/daemon-core/src/chat/async-batch.ts
38045
+ async function runAsyncBatch(items, worker, options = {}) {
38046
+ const list = Array.from(items);
38047
+ if (list.length === 0) return;
38048
+ const concurrency = Math.max(1, Math.min(list.length, Math.floor(options.concurrency || 1)));
38049
+ let nextIndex = 0;
38050
+ const runners = Array.from({ length: concurrency }, async () => {
38051
+ while (true) {
38052
+ const currentIndex = nextIndex;
38053
+ nextIndex += 1;
38054
+ if (currentIndex >= list.length) return;
38055
+ await worker(list[currentIndex], currentIndex);
38056
+ }
38057
+ });
38058
+ await Promise.all(runners);
38059
+ }
38060
+ var init_async_batch = __esm({
38061
+ "../../oss/packages/daemon-core/src/chat/async-batch.ts"() {
38062
+ "use strict";
38063
+ }
38064
+ });
38065
+
37526
38066
  // ../../oss/packages/daemon-core/src/agent-stream/provider-adapter.ts
37527
38067
  var ProviderStreamAdapter;
37528
38068
  var init_provider_adapter = __esm({
@@ -38004,10 +38544,12 @@ var init_manager2 = __esm({
38004
38544
  }
38005
38545
  }
38006
38546
  /** Collect active extension session state */
38007
- async collectActiveSession(cdp, parentSessionId) {
38547
+ async collectActiveSession(cdp, parentSessionId, attemptedSessionIds = /* @__PURE__ */ new Set(), originSessionId) {
38008
38548
  if (!this.enabled) return null;
38009
38549
  const activeSessionId = this.getActiveSessionId(parentSessionId);
38010
38550
  if (!activeSessionId) return null;
38551
+ const resolvedOriginSessionId = originSessionId || activeSessionId;
38552
+ attemptedSessionIds.add(activeSessionId);
38011
38553
  let agent = this.managedBySessionId.get(activeSessionId);
38012
38554
  if (!agent) {
38013
38555
  agent = await this.connectManagedSession(cdp, parentSessionId, activeSessionId) || void 0;
@@ -38020,18 +38562,44 @@ var init_manager2 = __esm({
38020
38562
  try {
38021
38563
  const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
38022
38564
  const state = await agent.adapter.readChat(evaluate);
38023
- const stateError = this.getStateError(state);
38024
- const selectedModelValue = typeof state.controlValues?.model === "string" ? state.controlValues.model : "";
38025
- LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${selectedModelValue}${state.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
38026
- if (state.status === "error" && this.isRecoverableSessionError(stateError)) {
38565
+ 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;
38566
+ const normalizedState = {
38567
+ ...state,
38568
+ sessionId: agent.runtimeSessionId,
38569
+ ...resolvedProviderSessionId ? { providerSessionId: resolvedProviderSessionId } : {}
38570
+ };
38571
+ const stateError = this.getStateError(normalizedState);
38572
+ const selectedModelValue = typeof normalizedState.controlValues?.model === "string" ? normalizedState.controlValues.model : "";
38573
+ LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${normalizedState.status} msgs=${normalizedState.messages?.length || 0} model=${selectedModelValue}${normalizedState.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
38574
+ if (normalizedState.status === "error" && this.isRecoverableSessionError(stateError)) {
38027
38575
  throw new Error(stateError);
38028
38576
  }
38029
- agent.lastState = state;
38577
+ agent.lastState = normalizedState;
38030
38578
  agent.lastError = null;
38031
- if (state.status === "panel_hidden") {
38579
+ if (normalizedState.status === "panel_hidden") {
38580
+ const discovered = await cdp.discoverAgentWebviews().catch(() => []);
38581
+ const fallbackTarget = discovered.find((entry) => {
38582
+ if (entry.agentType === type) return false;
38583
+ const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, entry.agentType);
38584
+ return !!fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId);
38585
+ });
38586
+ if (fallbackTarget) {
38587
+ const fallbackSessionId = this.resolveSessionIdForTarget(parentSessionId, fallbackTarget.agentType);
38588
+ if (fallbackSessionId && fallbackSessionId !== activeSessionId && !attemptedSessionIds.has(fallbackSessionId)) {
38589
+ this.logFn(`[AgentStream] Active session ${type} is hidden; switching to visible agent ${fallbackTarget.agentType} (${parentSessionId})`);
38590
+ await this.setActiveSession(cdp, parentSessionId, fallbackSessionId);
38591
+ await this.syncActiveSession(cdp, parentSessionId);
38592
+ const fallbackState = await this.collectActiveSession(cdp, parentSessionId, attemptedSessionIds, resolvedOriginSessionId);
38593
+ if (fallbackState?.status === "panel_hidden" && resolvedOriginSessionId !== fallbackSessionId) {
38594
+ await this.setActiveSession(cdp, parentSessionId, resolvedOriginSessionId);
38595
+ await this.syncActiveSession(cdp, parentSessionId);
38596
+ }
38597
+ return fallbackState;
38598
+ }
38599
+ }
38032
38600
  agent.lastHiddenCheckTime = Date.now();
38033
38601
  }
38034
- return state;
38602
+ return normalizedState;
38035
38603
  } catch (e) {
38036
38604
  const errorMsg = e?.message || String(e);
38037
38605
  this.logFn(`[AgentStream] readChat(${type}) error: ${errorMsg.slice(0, 200)}`);
@@ -38343,6 +38911,7 @@ var init_poller = __esm({
38343
38911
  try {
38344
38912
  await agentStreamManager.syncActiveSession(cdp, parentSessionId);
38345
38913
  let stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
38914
+ resolvedActiveSessionId = stream?.sessionId || agentStreamManager.getActiveSessionId(parentSessionId) || resolvedActiveSessionId;
38346
38915
  if (stream?.status === "waiting_approval") {
38347
38916
  const autoApprove = providerLoader.getSettings(stream.agentType).autoApprove !== false;
38348
38917
  if (autoApprove && resolvedActiveSessionId) {
@@ -44385,6 +44954,8 @@ var init_session_host_transport = __esm({
44385
44954
  runtimeKey: record2.runtimeKey,
44386
44955
  displayName: record2.displayName,
44387
44956
  workspaceLabel: record2.workspaceLabel,
44957
+ lifecycle: typeof record2.lifecycle === "string" ? record2.lifecycle : null,
44958
+ surfaceKind: record2.surfaceKind,
44388
44959
  writeOwner: record2.writeOwner ? {
44389
44960
  clientId: record2.writeOwner.clientId,
44390
44961
  ownerType: record2.writeOwner.ownerType
@@ -45112,8 +45683,8 @@ __export(src_exports, {
45112
45683
  getRecentDebugTrace: () => getRecentDebugTrace,
45113
45684
  getRecentLogs: () => getRecentLogs,
45114
45685
  getSavedProviderSessions: () => getSavedProviderSessions,
45115
- getSessionHostRecoveryLabel: () => getSessionHostRecoveryLabel2,
45116
- getSessionHostSurfaceKind: () => getSessionHostSurfaceKind2,
45686
+ getSessionHostRecoveryLabel: () => getSessionHostRecoveryLabel,
45687
+ getSessionHostSurfaceKind: () => getSessionHostSurfaceKind,
45117
45688
  getWorkspaceState: () => getWorkspaceState,
45118
45689
  hasCdpManager: () => hasCdpManager,
45119
45690
  hashSignatureParts: () => hashSignatureParts,
@@ -45126,8 +45697,8 @@ __export(src_exports, {
45126
45697
  isIdeRunning: () => isIdeRunning,
45127
45698
  isManagedStatusWaiting: () => isManagedStatusWaiting,
45128
45699
  isManagedStatusWorking: () => isManagedStatusWorking,
45129
- isSessionHostLiveRuntime: () => isSessionHostLiveRuntime2,
45130
- isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot2,
45700
+ isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
45701
+ isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot,
45131
45702
  isSetupComplete: () => isSetupComplete,
45132
45703
  killIdeProcess: () => killIdeProcess,
45133
45704
  launchIDE: () => launchIDE,
@@ -45162,6 +45733,7 @@ __export(src_exports, {
45162
45733
  resolveChatMessageKind: () => resolveChatMessageKind,
45163
45734
  resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
45164
45735
  resolveSessionHostAppName: () => resolveSessionHostAppName,
45736
+ runAsyncBatch: () => runAsyncBatch,
45165
45737
  saveConfig: () => saveConfig,
45166
45738
  saveState: () => saveState,
45167
45739
  setDebugRuntimeConfig: () => setDebugRuntimeConfig,
@@ -45209,6 +45781,7 @@ var init_src = __esm({
45209
45781
  init_chat_history();
45210
45782
  init_chat_signatures();
45211
45783
  init_subscription_updates();
45784
+ init_async_batch();
45212
45785
  init_agent_stream();
45213
45786
  init_agent_stream();
45214
45787
  init_forward();
@@ -77527,6 +78100,7 @@ var init_daemon_p2p = __esm({
77527
78100
  fs20 = __toESM(require("fs"));
77528
78101
  path26 = __toESM(require("path"));
77529
78102
  import_node_module2 = require("module");
78103
+ init_src();
77530
78104
  init_data_channel_router();
77531
78105
  init_screenshot_sender();
77532
78106
  init_peer_connection_manager();
@@ -77776,14 +78350,22 @@ ${e?.stack || ""}`);
77776
78350
  return false;
77777
78351
  }
77778
78352
  async flushChatSubscriptions(builder) {
78353
+ const tasks = [];
77779
78354
  for (const peer of this.peers.values()) {
77780
78355
  if (peer.state !== "connected" || !peer.chatSubscriptions || peer.chatSubscriptions.size === 0) continue;
77781
78356
  for (const subscription of peer.chatSubscriptions.values()) {
78357
+ tasks.push({ peer, subscription });
78358
+ }
78359
+ }
78360
+ await runAsyncBatch(tasks, async ({ peer, subscription }) => {
78361
+ try {
77782
78362
  const update = await builder(subscription);
77783
- if (!update) continue;
78363
+ if (!update) return;
77784
78364
  this.screenshotSender.sendTopicUpdateToPeer(peer, update);
78365
+ } catch (error48) {
78366
+ log(`chat_tail flush skipped: peer=${peer.peerId} session=${subscription.params.targetSessionId} error=${error48?.message || error48}`);
77785
78367
  }
77786
- }
78368
+ }, { concurrency: 4 });
77787
78369
  }
77788
78370
  async flushMachineRuntimeSubscriptions(builder) {
77789
78371
  for (const peer of this.peers.values()) {
@@ -85267,7 +85849,7 @@ var init_adhdev_daemon = __esm({
85267
85849
  init_source();
85268
85850
  init_version();
85269
85851
  init_src();
85270
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.75" });
85852
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.77" });
85271
85853
  AdhdevDaemon = class _AdhdevDaemon {
85272
85854
  localHttpServer = null;
85273
85855
  localWss = null;
@@ -85681,7 +86263,7 @@ ${err?.stack || ""}`);
85681
86263
  }),
85682
86264
  onStatusChange: () => {
85683
86265
  this.statusReporter?.onStatusChange();
85684
- void this.flushP2PChatSubscriptions({ onlyActive: false });
86266
+ void this.flushP2PChatSubscriptions({ onlyActive: true });
85685
86267
  },
85686
86268
  removeAgentTracking: (key) => this.statusReporter?.removeAgentTracking(key),
85687
86269
  hostedRuntimeManagerTag: "adhdev-cloud",
@@ -85710,7 +86292,7 @@ ${err?.stack || ""}`);
85710
86292
  statusVersion: pkgVersion,
85711
86293
  onStatusChange: () => {
85712
86294
  this.statusReporter?.onStatusChange();
85713
- void this.flushP2PChatSubscriptions({ onlyActive: false });
86295
+ void this.flushP2PChatSubscriptions({ onlyActive: true });
85714
86296
  },
85715
86297
  onPostChatCommand: () => {
85716
86298
  setTimeout(() => this.statusReporter?.throttledReport(), 1e3);
@@ -86736,7 +87318,7 @@ async function buildRuntimeTargetResolutionTrace(records, target, options) {
86736
87318
  runtimeKey: record2.runtimeKey,
86737
87319
  displayName: record2.displayName,
86738
87320
  lifecycle: record2.lifecycle,
86739
- surfaceKind: getSessionHostSurfaceKind(record2),
87321
+ surfaceKind: getSessionHostSurfaceKind2(record2),
86740
87322
  attachedClientCount: Array.isArray(record2.attachedClients) ? record2.attachedClients.length : 0,
86741
87323
  writeOwnerClientId: record2.writeOwner?.clientId
86742
87324
  };