@adhdev/daemon-standalone 0.8.81 → 0.8.83

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/index.js CHANGED
@@ -28806,6 +28806,59 @@ var require_dist2 = __commonJS({
28806
28806
  VALID_ROLES = ["user", "assistant", "system", "human"];
28807
28807
  }
28808
28808
  });
28809
+ function normalizeCategories(categories) {
28810
+ if (!Array.isArray(categories)) return [];
28811
+ return categories.map((category) => String(category || "").trim()).filter(Boolean);
28812
+ }
28813
+ function resolveDebugRuntimeConfig(options = {}) {
28814
+ const dev = options.dev === true;
28815
+ return {
28816
+ logLevel: options.logLevel || (dev ? "debug" : DEFAULT_CONFIG2.logLevel),
28817
+ collectDebugTrace: typeof options.trace === "boolean" ? options.trace : dev,
28818
+ traceContent: options.traceContent === true,
28819
+ traceBufferSize: Number.isFinite(options.traceBufferSize) ? Math.max(10, Math.floor(options.traceBufferSize)) : dev ? DEV_TRACE_BUFFER_SIZE : DEFAULT_CONFIG2.traceBufferSize,
28820
+ traceCategories: normalizeCategories(options.traceCategories)
28821
+ };
28822
+ }
28823
+ function setDebugRuntimeConfig(config2) {
28824
+ currentConfig = {
28825
+ ...config2,
28826
+ traceCategories: normalizeCategories(config2.traceCategories),
28827
+ traceBufferSize: Math.max(10, Math.floor(config2.traceBufferSize || DEFAULT_CONFIG2.traceBufferSize))
28828
+ };
28829
+ }
28830
+ function getDebugRuntimeConfig() {
28831
+ return { ...currentConfig, traceCategories: [...currentConfig.traceCategories] };
28832
+ }
28833
+ function resetDebugRuntimeConfig() {
28834
+ currentConfig = { ...DEFAULT_CONFIG2 };
28835
+ }
28836
+ function shouldCollectTraceCategory(category) {
28837
+ const config2 = currentConfig;
28838
+ if (!config2.collectDebugTrace) return false;
28839
+ if (!category) return true;
28840
+ if (config2.traceCategories.length === 0) return true;
28841
+ return config2.traceCategories.includes(category);
28842
+ }
28843
+ var NORMAL_TRACE_BUFFER_SIZE;
28844
+ var DEV_TRACE_BUFFER_SIZE;
28845
+ var DEFAULT_CONFIG2;
28846
+ var currentConfig;
28847
+ var init_debug_config = __esm2({
28848
+ "src/logging/debug-config.ts"() {
28849
+ "use strict";
28850
+ NORMAL_TRACE_BUFFER_SIZE = 200;
28851
+ DEV_TRACE_BUFFER_SIZE = 1e3;
28852
+ DEFAULT_CONFIG2 = {
28853
+ logLevel: "info",
28854
+ collectDebugTrace: false,
28855
+ traceContent: false,
28856
+ traceBufferSize: NORMAL_TRACE_BUFFER_SIZE,
28857
+ traceCategories: []
28858
+ };
28859
+ currentConfig = { ...DEFAULT_CONFIG2 };
28860
+ }
28861
+ });
28809
28862
  function isModuleNotFoundError(error48, ref) {
28810
28863
  if (!(error48 instanceof Error)) return false;
28811
28864
  const message = error48.message || "";
@@ -29003,10 +29056,12 @@ var require_dist2 = __commonJS({
29003
29056
  if (loggedTerminalBackends.has(key)) return;
29004
29057
  loggedTerminalBackends.add(key);
29005
29058
  if (backendKind === "xterm" && preference !== "xterm" && !ghosttyAvailable) {
29006
- LOG2.warn(
29007
- "Terminal",
29008
- `[terminal-screen] ghostty-vt unavailable; using xterm fallback (preference=${preference})`
29009
- );
29059
+ const message = `[terminal-screen] ghostty-vt unavailable; using xterm fallback (preference=${preference})`;
29060
+ if (preference === "auto") {
29061
+ LOG2.info("Terminal", message);
29062
+ } else {
29063
+ LOG2.warn("Terminal", message);
29064
+ }
29010
29065
  return;
29011
29066
  }
29012
29067
  LOG2.info(
@@ -29654,6 +29709,7 @@ var require_dist2 = __commonJS({
29654
29709
  "use strict";
29655
29710
  os10 = __toESM2(require("os"));
29656
29711
  init_logger();
29712
+ init_debug_config();
29657
29713
  init_terminal_screen();
29658
29714
  init_pty_transport();
29659
29715
  init_provider_cli_shared();
@@ -29687,7 +29743,15 @@ var require_dist2 = __commonJS({
29687
29743
  `[${this.cliType}] Provider resolution: providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"} source=${this.providerResolutionMeta.scriptsSource || "-"} version=${this.providerResolutionMeta.resolvedVersion || "-"}`
29688
29744
  );
29689
29745
  } else {
29690
- LOG2.warn("CLI", `[${this.cliType}] \u26A0 No CLI scripts loaded! Provider needs scripts/{version}/scripts.js`);
29746
+ const resolutionSummary = `providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"} source=${this.providerResolutionMeta.scriptsSource || "-"} version=${this.providerResolutionMeta.resolvedVersion || "-"}`;
29747
+ const hasResolvedProviderScripts = Boolean(
29748
+ this.providerResolutionMeta.providerDir || this.providerResolutionMeta.scriptDir || this.providerResolutionMeta.scriptsPath || this.providerResolutionMeta.scriptsSource || this.providerResolutionMeta.resolvedVersion
29749
+ );
29750
+ if (hasResolvedProviderScripts) {
29751
+ LOG2.warn("CLI", `[${this.cliType}] \u26A0 No CLI scripts loaded! Provider needs scripts/{version}/scripts.js (${resolutionSummary})`);
29752
+ } else {
29753
+ LOG2.info("CLI", `[${this.cliType}] CLI scripts not yet resolved (${resolutionSummary})`);
29754
+ }
29691
29755
  }
29692
29756
  }
29693
29757
  cliType;
@@ -29705,6 +29769,7 @@ var require_dist2 = __commonJS({
29705
29769
  recentOutputBuffer = "";
29706
29770
  isWaitingForResponse = false;
29707
29771
  activeModal = null;
29772
+ parseErrorMessage = null;
29708
29773
  responseTimeout = null;
29709
29774
  idleTimeout = null;
29710
29775
  ready = false;
@@ -29765,7 +29830,8 @@ var require_dist2 = __commonJS({
29765
29830
  currentTurnScope = null;
29766
29831
  traceEntries = [];
29767
29832
  traceSeq = 0;
29768
- traceSessionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
29833
+ traceSessionId = "";
29834
+ parsedStatusCache = null;
29769
29835
  static MAX_TRACE_ENTRIES = 250;
29770
29836
  providerResolutionMeta;
29771
29837
  static FINISH_RETRY_DELAY_MS = 300;
@@ -30006,7 +30072,8 @@ var require_dist2 = __commonJS({
30006
30072
  this.terminalScreen.write(rawData);
30007
30073
  const cleanData = sanitizeTerminalText(rawData);
30008
30074
  const now = Date.now();
30009
- const normalizedScreenSnapshot = normalizeScreenSnapshot(this.terminalScreen.getText());
30075
+ const screenText = this.terminalScreen.getText();
30076
+ const normalizedScreenSnapshot = normalizeScreenSnapshot(screenText);
30010
30077
  this.lastOutputAt = now;
30011
30078
  if (cleanData.trim()) this.lastNonEmptyOutputAt = now;
30012
30079
  if (normalizedScreenSnapshot !== this.lastScreenSnapshot) {
@@ -30019,13 +30086,14 @@ var require_dist2 = __commonJS({
30019
30086
  if (this.idleFinishCandidate && (rawData.length > 0 || cleanData.length > 0)) {
30020
30087
  this.clearIdleFinishCandidate("new_output");
30021
30088
  }
30022
- this.recordTrace("output", {
30023
- rawLength: rawData.length,
30024
- cleanLength: cleanData.length,
30025
- rawPreview: summarizeCliTraceText(rawData, 300),
30026
- cleanPreview: summarizeCliTraceText(cleanData, 300),
30027
- screenText: summarizeCliTraceText(this.terminalScreen.getText(), 1200)
30028
- });
30089
+ if (getDebugRuntimeConfig().collectDebugTrace) {
30090
+ this.recordTrace("output", {
30091
+ rawLength: rawData.length,
30092
+ cleanLength: cleanData.length,
30093
+ rawPreview: summarizeCliTraceText(rawData, 300),
30094
+ cleanPreview: summarizeCliTraceText(cleanData, 300)
30095
+ });
30096
+ }
30029
30097
  if (this.startupParseGate) {
30030
30098
  this.scheduleStartupSettleCheck();
30031
30099
  }
@@ -30699,10 +30767,12 @@ var require_dist2 = __commonJS({
30699
30767
  // ─── Public API (CliAdapter) ───────────────────
30700
30768
  getStatus() {
30701
30769
  return {
30702
- status: this.currentStatus,
30770
+ status: this.parseErrorMessage ? "error" : this.currentStatus,
30703
30771
  messages: [...this.committedMessages],
30704
30772
  workingDir: this.workingDir,
30705
- activeModal: this.activeModal
30773
+ activeModal: this.activeModal,
30774
+ errorMessage: this.parseErrorMessage || void 0,
30775
+ errorReason: this.parseErrorMessage ? "parse_error" : void 0
30706
30776
  };
30707
30777
  }
30708
30778
  seedCommittedMessages(messages) {
@@ -30725,12 +30795,19 @@ var require_dist2 = __commonJS({
30725
30795
  * Called by command handler / dashboard for rich content rendering.
30726
30796
  */
30727
30797
  getScriptParsedStatus() {
30798
+ const screenText = this.terminalScreen.getText();
30799
+ const cached2 = this.parsedStatusCache;
30800
+ if (cached2 && cached2.committedMessagesRef === this.committedMessages && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.accumulatedRawBuffer === this.accumulatedRawBuffer && cached2.screenText === screenText && cached2.currentStatus === this.currentStatus && cached2.activeModal === this.activeModal && cached2.cliName === this.cliName && cached2.lastOutputAt === this.lastOutputAt) {
30801
+ return cached2.result;
30802
+ }
30728
30803
  const parsed = this.parseCurrentTranscript(
30729
30804
  this.committedMessages,
30730
30805
  this.responseBuffer,
30731
- this.currentTurnScope
30806
+ this.currentTurnScope,
30807
+ screenText
30732
30808
  );
30733
30809
  const shouldPreferCommittedMessages = !this.currentTurnScope && this.currentStatus === "idle" && !this.activeModal;
30810
+ let result;
30734
30811
  if (parsed && Array.isArray(parsed.messages)) {
30735
30812
  const hydratedMessages = shouldPreferCommittedMessages ? this.committedMessages.map((message, index) => buildChatMessage({
30736
30813
  ...message,
@@ -30742,7 +30819,7 @@ var require_dist2 = __commonJS({
30742
30819
  scope: this.currentTurnScope,
30743
30820
  lastOutputAt: this.lastOutputAt
30744
30821
  });
30745
- return {
30822
+ result = {
30746
30823
  id: parsed.id || "cli_session",
30747
30824
  status: parsed.status || this.currentStatus,
30748
30825
  title: parsed.title || this.cliName,
@@ -30750,20 +30827,36 @@ var require_dist2 = __commonJS({
30750
30827
  activeModal: parsed.activeModal ?? this.activeModal,
30751
30828
  providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0
30752
30829
  };
30830
+ } else {
30831
+ const messages = [...this.committedMessages];
30832
+ result = {
30833
+ id: "cli_session",
30834
+ status: this.currentStatus,
30835
+ title: this.cliName,
30836
+ messages: messages.map((message, index) => buildChatMessage({
30837
+ ...message,
30838
+ id: message.id || `msg_${index}`,
30839
+ index: typeof message.index === "number" ? message.index : index,
30840
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
30841
+ })),
30842
+ activeModal: this.activeModal
30843
+ };
30753
30844
  }
30754
- const messages = [...this.committedMessages];
30755
- return {
30756
- id: "cli_session",
30757
- status: this.currentStatus,
30758
- title: this.cliName,
30759
- messages: messages.slice(-50).map((message, index) => buildChatMessage({
30760
- ...message,
30761
- id: message.id || `msg_${index}`,
30762
- index: typeof message.index === "number" ? message.index : index,
30763
- receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
30764
- })),
30765
- activeModal: this.activeModal
30845
+ this.parsedStatusCache = {
30846
+ committedMessagesRef: this.committedMessages,
30847
+ responseBuffer: this.responseBuffer,
30848
+ currentTurnScope: this.currentTurnScope,
30849
+ recentOutputBuffer: this.recentOutputBuffer,
30850
+ accumulatedBuffer: this.accumulatedBuffer,
30851
+ accumulatedRawBuffer: this.accumulatedRawBuffer,
30852
+ screenText,
30853
+ currentStatus: this.currentStatus,
30854
+ activeModal: this.activeModal,
30855
+ cliName: this.cliName,
30856
+ lastOutputAt: this.lastOutputAt,
30857
+ result
30766
30858
  };
30859
+ return result;
30767
30860
  }
30768
30861
  async invokeScript(scriptName, args) {
30769
30862
  const fn2 = this.cliScripts?.[scriptName];
@@ -30786,14 +30879,18 @@ var require_dist2 = __commonJS({
30786
30879
  args: args && typeof args === "object" ? { ...args } : {}
30787
30880
  }));
30788
30881
  }
30789
- parseCurrentTranscript(baseMessages, partialResponse, scope) {
30790
- if (!this.cliScripts?.parseOutput) return null;
30882
+ parseCurrentTranscript(baseMessages, partialResponse, scope, screenTextOverride) {
30883
+ if (!this.cliScripts?.parseOutput) {
30884
+ this.parseErrorMessage = null;
30885
+ return null;
30886
+ }
30791
30887
  try {
30888
+ const screenText = typeof screenTextOverride === "string" ? screenTextOverride : this.terminalScreen.getText();
30792
30889
  const input = buildCliParseInput({
30793
30890
  accumulatedBuffer: this.accumulatedBuffer,
30794
30891
  accumulatedRawBuffer: this.accumulatedRawBuffer,
30795
30892
  recentOutputBuffer: this.recentOutputBuffer,
30796
- terminalScreenText: this.terminalScreen.getText(),
30893
+ terminalScreenText: screenText,
30797
30894
  baseMessages,
30798
30895
  partialResponse,
30799
30896
  isWaitingForResponse: this.isWaitingForResponse,
@@ -30815,10 +30912,13 @@ var require_dist2 = __commonJS({
30815
30912
  lastAssistant.content = trimPromptEchoPrefix(lastAssistant.content, promptForTrim);
30816
30913
  }
30817
30914
  }
30915
+ this.parseErrorMessage = null;
30818
30916
  return parsed;
30819
30917
  } catch (e) {
30820
- LOG2.warn("CLI", `[${this.cliType}] parseOutput error: ${e.message}`);
30821
- return null;
30918
+ const message = e?.message || String(e);
30919
+ this.parseErrorMessage = message;
30920
+ LOG2.warn("CLI", `[${this.cliType}] parseOutput error: ${message}`);
30921
+ throw e;
30822
30922
  }
30823
30923
  }
30824
30924
  /** Whether this adapter has CLI scripts loaded */
@@ -31808,6 +31908,96 @@ ${data.message || ""}`.trim();
31808
31908
  const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
31809
31909
  return state.sessionReadMarkers?.[providerKey] || state.sessionReadMarkers?.[sessionId] || "";
31810
31910
  }
31911
+ function getSessionNotificationDismissal(state, sessionId, providerSessionId) {
31912
+ const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
31913
+ return state.sessionNotificationDismissals?.[providerKey] || state.sessionNotificationDismissals?.[sessionId] || "";
31914
+ }
31915
+ function getSessionNotificationUnreadOverride(state, sessionId, providerSessionId) {
31916
+ const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
31917
+ return state.sessionNotificationUnreadOverrides?.[providerKey] || state.sessionNotificationUnreadOverrides?.[sessionId] || "";
31918
+ }
31919
+ function dismissSessionNotification(state, sessionId, notificationId, providerSessionId) {
31920
+ const dismissalId = String(notificationId || "").trim();
31921
+ if (!dismissalId) return state;
31922
+ const dismissalKeys = Array.from(new Set([
31923
+ sessionId,
31924
+ buildSessionReadStateKey(sessionId, providerSessionId)
31925
+ ].filter(Boolean)));
31926
+ const nextSessionNotificationDismissals = { ...state.sessionNotificationDismissals || {} };
31927
+ const nextSessionNotificationUnreadOverrides = { ...state.sessionNotificationUnreadOverrides || {} };
31928
+ for (const key of dismissalKeys) {
31929
+ nextSessionNotificationDismissals[key] = dismissalId;
31930
+ delete nextSessionNotificationUnreadOverrides[key];
31931
+ }
31932
+ return {
31933
+ ...state,
31934
+ sessionNotificationDismissals: nextSessionNotificationDismissals,
31935
+ sessionNotificationUnreadOverrides: nextSessionNotificationUnreadOverrides
31936
+ };
31937
+ }
31938
+ function markSessionNotificationUnread(state, sessionId, notificationId, providerSessionId) {
31939
+ const unreadId = String(notificationId || "").trim();
31940
+ if (!unreadId) return state;
31941
+ const unreadKeys = Array.from(new Set([
31942
+ sessionId,
31943
+ buildSessionReadStateKey(sessionId, providerSessionId)
31944
+ ].filter(Boolean)));
31945
+ const nextSessionNotificationDismissals = { ...state.sessionNotificationDismissals || {} };
31946
+ const nextSessionNotificationUnreadOverrides = { ...state.sessionNotificationUnreadOverrides || {} };
31947
+ for (const key of unreadKeys) {
31948
+ nextSessionNotificationUnreadOverrides[key] = unreadId;
31949
+ delete nextSessionNotificationDismissals[key];
31950
+ }
31951
+ return {
31952
+ ...state,
31953
+ sessionNotificationDismissals: nextSessionNotificationDismissals,
31954
+ sessionNotificationUnreadOverrides: nextSessionNotificationUnreadOverrides
31955
+ };
31956
+ }
31957
+ function getSessionNotificationTargetValue(session) {
31958
+ const providerSessionId = typeof session.providerSessionId === "string" ? session.providerSessionId.trim() : "";
31959
+ return providerSessionId || session.id;
31960
+ }
31961
+ function getSessionCurrentNotificationId(session) {
31962
+ const inboxBucket = session.inboxBucket || "idle";
31963
+ const isNeedsAttention = inboxBucket === "needs_attention" || session.status === "waiting_approval";
31964
+ const isTaskComplete = inboxBucket === "task_complete" && !!session.unread;
31965
+ const type = isNeedsAttention ? "needs_attention" : isTaskComplete ? "task_complete" : "";
31966
+ if (!type) return "";
31967
+ const target = getSessionNotificationTargetValue(session);
31968
+ const lastMessageHash = typeof session.lastMessageHash === "string" ? session.lastMessageHash : "";
31969
+ const timestamp = Number(session.lastMessageAt || session.lastUpdated || 0);
31970
+ return [type, target, lastMessageHash, String(timestamp)].join("|");
31971
+ }
31972
+ function applySessionNotificationOverlay(session, overlay) {
31973
+ const currentNotificationId = getSessionCurrentNotificationId(session);
31974
+ const taskCompleteNotificationId = (() => {
31975
+ const target = getSessionNotificationTargetValue(session);
31976
+ const lastMessageHash = typeof session.lastMessageHash === "string" ? session.lastMessageHash : "";
31977
+ const timestamp = Number(session.lastMessageAt || session.lastUpdated || 0);
31978
+ if (!target || !lastMessageHash || !timestamp) return "";
31979
+ return ["task_complete", target, lastMessageHash, String(timestamp)].join("|");
31980
+ })();
31981
+ const dismissedNotificationId = typeof overlay.dismissedNotificationId === "string" ? overlay.dismissedNotificationId.trim() : "";
31982
+ const unreadNotificationId = typeof overlay.unreadNotificationId === "string" ? overlay.unreadNotificationId.trim() : "";
31983
+ if (unreadNotificationId && (currentNotificationId === unreadNotificationId || taskCompleteNotificationId === unreadNotificationId)) {
31984
+ const forcedInboxBucket = session.inboxBucket === "needs_attention" || session.status === "waiting_approval" ? "needs_attention" : "task_complete";
31985
+ return {
31986
+ unread: true,
31987
+ inboxBucket: forcedInboxBucket
31988
+ };
31989
+ }
31990
+ if (!currentNotificationId || !dismissedNotificationId || currentNotificationId !== dismissedNotificationId) {
31991
+ return {
31992
+ unread: !!session.unread,
31993
+ inboxBucket: session.inboxBucket || "idle"
31994
+ };
31995
+ }
31996
+ return {
31997
+ unread: false,
31998
+ inboxBucket: "idle"
31999
+ };
32000
+ }
31811
32001
  function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker, providerSessionId) {
31812
32002
  const prev = state.sessionReads || {};
31813
32003
  const prevMarkers = state.sessionReadMarkers || {};
@@ -31818,14 +32008,20 @@ ${data.message || ""}`.trim();
31818
32008
  ].filter(Boolean)));
31819
32009
  const nextSessionReads = { ...prev };
31820
32010
  const nextSessionReadMarkers = { ...prevMarkers };
32011
+ const nextSessionNotificationDismissals = { ...state.sessionNotificationDismissals || {} };
32012
+ const nextSessionNotificationUnreadOverrides = { ...state.sessionNotificationUnreadOverrides || {} };
31821
32013
  for (const key of readKeys) {
31822
32014
  nextSessionReads[key] = Math.max(prev[key] || 0, seenAt);
31823
32015
  if (nextMarker) nextSessionReadMarkers[key] = nextMarker;
32016
+ delete nextSessionNotificationDismissals[key];
32017
+ delete nextSessionNotificationUnreadOverrides[key];
31824
32018
  }
31825
32019
  return {
31826
32020
  ...state,
31827
32021
  sessionReads: nextSessionReads,
31828
- sessionReadMarkers: nextMarker ? nextSessionReadMarkers : prevMarkers
32022
+ sessionReadMarkers: nextMarker ? nextSessionReadMarkers : prevMarkers,
32023
+ sessionNotificationDismissals: nextSessionNotificationDismissals,
32024
+ sessionNotificationUnreadOverrides: nextSessionNotificationUnreadOverrides
31829
32025
  };
31830
32026
  }
31831
32027
  var path32 = __toESM2(require("path"));
@@ -31902,7 +32098,9 @@ ${data.message || ""}`.trim();
31902
32098
  recentActivity: [],
31903
32099
  savedProviderSessions: [],
31904
32100
  sessionReads: {},
31905
- sessionReadMarkers: {}
32101
+ sessionReadMarkers: {},
32102
+ sessionNotificationDismissals: {},
32103
+ sessionNotificationUnreadOverrides: {}
31906
32104
  };
31907
32105
  function isPlainObject22(value) {
31908
32106
  return !!value && typeof value === "object" && !Array.isArray(value);
@@ -31934,11 +32132,19 @@ ${data.message || ""}`.trim();
31934
32132
  const sessionReadMarkers = Object.fromEntries(
31935
32133
  Object.entries(isPlainObject22(parsed.sessionReadMarkers) ? parsed.sessionReadMarkers : {}).filter(([key, value]) => !isLegacyVolatileSessionReadKey(key) && typeof value === "string")
31936
32134
  );
32135
+ const sessionNotificationDismissals = Object.fromEntries(
32136
+ Object.entries(isPlainObject22(parsed.sessionNotificationDismissals) ? parsed.sessionNotificationDismissals : {}).filter(([key, value]) => !isLegacyVolatileSessionReadKey(key) && typeof value === "string" && value.length > 0)
32137
+ );
32138
+ const sessionNotificationUnreadOverrides = Object.fromEntries(
32139
+ Object.entries(isPlainObject22(parsed.sessionNotificationUnreadOverrides) ? parsed.sessionNotificationUnreadOverrides : {}).filter(([key, value]) => !isLegacyVolatileSessionReadKey(key) && typeof value === "string" && value.length > 0)
32140
+ );
31937
32141
  return {
31938
32142
  recentActivity,
31939
32143
  savedProviderSessions,
31940
32144
  sessionReads,
31941
- sessionReadMarkers
32145
+ sessionReadMarkers,
32146
+ sessionNotificationDismissals,
32147
+ sessionNotificationUnreadOverrides
31942
32148
  };
31943
32149
  }
31944
32150
  function loadState() {
@@ -32332,9 +32538,15 @@ ${data.message || ""}`.trim();
32332
32538
  continue;
32333
32539
  }
32334
32540
  const status = String(session?.status || "").toLowerCase();
32541
+ const unread = session?.unread === true;
32542
+ const inboxBucket = String(session?.inboxBucket || "").toLowerCase();
32543
+ const runtimeSurfaceKind = String(session?.runtimeSurfaceKind || "").toLowerCase();
32544
+ const runtimeLifecycle = String(session?.runtimeLifecycle || "").toLowerCase();
32545
+ const isLiveRuntime = runtimeSurfaceKind === "live_runtime" || LIVE_RUNTIME_LIFECYCLES.has(runtimeLifecycle);
32335
32546
  const lastMessageAt = parseMessageTimestamp(session?.lastMessageAt);
32336
32547
  const recentlyUpdated = lastMessageAt > 0 && now - lastMessageAt <= recentMessageGraceMs;
32337
- if (activeStatuses.has(status) || recentlyUpdated) {
32548
+ const shouldKeepRecentTailHot = recentlyUpdated && (unread || inboxBucket === "task_complete" || inboxBucket === "needs_attention" || isLiveRuntime || activeStatuses.has(status));
32549
+ if (activeStatuses.has(status) || shouldKeepRecentTailHot) {
32338
32550
  active.add(sessionId);
32339
32551
  }
32340
32552
  }
@@ -35229,7 +35441,6 @@ ${cleanBody}`;
35229
35441
  }
35230
35442
  pushEvent(event) {
35231
35443
  this.events.push(event);
35232
- if (this.events.length > 50) this.events = this.events.slice(-50);
35233
35444
  }
35234
35445
  applyProviderResponse(data, options) {
35235
35446
  if (!data || typeof data !== "object") return;
@@ -35305,7 +35516,6 @@ ${cleanBody}`;
35305
35516
  key: dedupKey,
35306
35517
  message: normalizedMessage
35307
35518
  });
35308
- if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
35309
35519
  if (normalizedContent) {
35310
35520
  this.historyWriter.appendNewMessages(
35311
35521
  this.type,
@@ -35834,7 +36044,6 @@ ${effect.notification.body || ""}`.trim();
35834
36044
  }
35835
36045
  pushEvent(event) {
35836
36046
  this.events.push(event);
35837
- if (this.events.length > 50) this.events = this.events.slice(-50);
35838
36047
  }
35839
36048
  applyProviderResponse(data, options) {
35840
36049
  if (!data || typeof data !== "object") return;
@@ -35924,7 +36133,6 @@ ${effect.notification.body || ""}`.trim();
35924
36133
  key: dedupKey,
35925
36134
  message: normalizedMessage
35926
36135
  });
35927
- if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
35928
36136
  if (normalizedContent) {
35929
36137
  this.historyWriter.appendNewMessages(
35930
36138
  this.type,
@@ -36919,50 +37127,7 @@ ${effect.notification.body || ""}`.trim();
36919
37127
  }
36920
37128
  init_read_chat_contract();
36921
37129
  init_logger();
36922
- var NORMAL_TRACE_BUFFER_SIZE = 200;
36923
- var DEV_TRACE_BUFFER_SIZE = 1e3;
36924
- var DEFAULT_CONFIG2 = {
36925
- logLevel: "info",
36926
- collectDebugTrace: false,
36927
- traceContent: false,
36928
- traceBufferSize: NORMAL_TRACE_BUFFER_SIZE,
36929
- traceCategories: []
36930
- };
36931
- var currentConfig = { ...DEFAULT_CONFIG2 };
36932
- function normalizeCategories(categories) {
36933
- if (!Array.isArray(categories)) return [];
36934
- return categories.map((category) => String(category || "").trim()).filter(Boolean);
36935
- }
36936
- function resolveDebugRuntimeConfig(options = {}) {
36937
- const dev = options.dev === true;
36938
- return {
36939
- logLevel: options.logLevel || (dev ? "debug" : DEFAULT_CONFIG2.logLevel),
36940
- collectDebugTrace: typeof options.trace === "boolean" ? options.trace : dev,
36941
- traceContent: options.traceContent === true,
36942
- traceBufferSize: Number.isFinite(options.traceBufferSize) ? Math.max(10, Math.floor(options.traceBufferSize)) : dev ? DEV_TRACE_BUFFER_SIZE : DEFAULT_CONFIG2.traceBufferSize,
36943
- traceCategories: normalizeCategories(options.traceCategories)
36944
- };
36945
- }
36946
- function setDebugRuntimeConfig(config2) {
36947
- currentConfig = {
36948
- ...config2,
36949
- traceCategories: normalizeCategories(config2.traceCategories),
36950
- traceBufferSize: Math.max(10, Math.floor(config2.traceBufferSize || DEFAULT_CONFIG2.traceBufferSize))
36951
- };
36952
- }
36953
- function getDebugRuntimeConfig() {
36954
- return { ...currentConfig, traceCategories: [...currentConfig.traceCategories] };
36955
- }
36956
- function resetDebugRuntimeConfig() {
36957
- currentConfig = { ...DEFAULT_CONFIG2 };
36958
- }
36959
- function shouldCollectTraceCategory(category) {
36960
- const config2 = currentConfig;
36961
- if (!config2.collectDebugTrace) return false;
36962
- if (!category) return true;
36963
- if (config2.traceCategories.length === 0) return true;
36964
- return config2.traceCategories.includes(category);
36965
- }
37130
+ init_debug_config();
36966
37131
  function summarizeString(value) {
36967
37132
  return `[${value.length} chars]`;
36968
37133
  }
@@ -37458,7 +37623,14 @@ ${effect.notification.body || ""}`.trim();
37458
37623
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
37459
37624
  if (adapter) {
37460
37625
  _log(`${transport} adapter: ${adapter.cliType}`);
37461
- const parsedStatus = typeof adapter.getScriptParsedStatus === "function" ? parseMaybeJson(adapter.getScriptParsedStatus()) : null;
37626
+ let parsedStatus = null;
37627
+ if (typeof adapter.getScriptParsedStatus === "function") {
37628
+ try {
37629
+ parsedStatus = parseMaybeJson(adapter.getScriptParsedStatus());
37630
+ } catch (error48) {
37631
+ return { success: false, error: error48?.message || String(error48) };
37632
+ }
37633
+ }
37462
37634
  const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
37463
37635
  const status = parsedRecord || adapter.getStatus();
37464
37636
  const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
@@ -39774,6 +39946,8 @@ ${effect.notification.body || ""}`.trim();
39774
39946
  runtimeMessages = [];
39775
39947
  instanceId;
39776
39948
  suppressIdleHistoryReplay = false;
39949
+ errorMessage = void 0;
39950
+ errorReason = void 0;
39777
39951
  presentationMode;
39778
39952
  providerSessionId;
39779
39953
  launchMode;
@@ -39840,6 +40014,7 @@ ${effect.notification.body || ""}`.trim();
39840
40014
  }
39841
40015
  async onTick() {
39842
40016
  if (this.providerSessionId) return;
40017
+ if (this.type === "hermes-cli" && this.launchMode === "new") return;
39843
40018
  let probedSessionId = null;
39844
40019
  const probeConfig = this.provider.sessionProbe;
39845
40020
  if (probeConfig) {
@@ -39897,9 +40072,24 @@ ${effect.notification.body || ""}`.trim();
39897
40072
  }
39898
40073
  getState() {
39899
40074
  const adapterStatus = this.adapter.getStatus();
39900
- const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
40075
+ let parsedStatus = null;
40076
+ let parseErrorMessage;
40077
+ if (typeof this.adapter.getScriptParsedStatus === "function") {
40078
+ try {
40079
+ parsedStatus = this.adapter.getScriptParsedStatus() || null;
40080
+ this.errorMessage = void 0;
40081
+ this.errorReason = void 0;
40082
+ } catch (error48) {
40083
+ parseErrorMessage = error48?.message || String(error48);
40084
+ this.errorMessage = parseErrorMessage;
40085
+ this.errorReason = "parse_error";
40086
+ }
40087
+ } else {
40088
+ this.errorMessage = void 0;
40089
+ this.errorReason = void 0;
40090
+ }
39901
40091
  const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
39902
- const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
40092
+ const visibleStatus = parseErrorMessage ? "error" : autoApproveActive ? "generating" : adapterStatus.status;
39903
40093
  const parsedProviderSessionId = normalizeProviderSessionId(
39904
40094
  this.type,
39905
40095
  typeof parsedStatus?.providerSessionId === "string" ? parsedStatus.providerSessionId : ""
@@ -39909,7 +40099,7 @@ ${effect.notification.body || ""}`.trim();
39909
40099
  }
39910
40100
  const runtime = this.adapter.getRuntimeMetadata();
39911
40101
  this.maybeAppendRuntimeRecoveryMessage(runtime);
39912
- let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
40102
+ let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : parseErrorMessage ? normalizeChatMessages(Array.isArray(adapterStatus.messages) ? adapterStatus.messages : []) : [];
39913
40103
  const historyMessageCount = Number.isFinite(parsedStatus?.historyMessageCount) ? Math.max(0, Number(parsedStatus.historyMessageCount)) : null;
39914
40104
  if (historyMessageCount !== null) {
39915
40105
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
@@ -39949,7 +40139,7 @@ ${effect.notification.body || ""}`.trim();
39949
40139
  activeChat: {
39950
40140
  id: `${this.type}_${this.workingDir}`,
39951
40141
  title: parsedStatus?.title || dirName,
39952
- status: autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : parsedStatus?.status || visibleStatus,
40142
+ status: parseErrorMessage ? "error" : autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : parsedStatus?.status || visibleStatus,
39953
40143
  messages: mergedMessages,
39954
40144
  activeModal: autoApproveActive ? null : parsedStatus?.activeModal ?? adapterStatus.activeModal,
39955
40145
  inputContent: ""
@@ -39975,7 +40165,9 @@ ${effect.notification.body || ""}`.trim();
39975
40165
  resume: this.provider.resume,
39976
40166
  controlValues: surface.controlValues,
39977
40167
  providerControls: this.provider.controls,
39978
- summaryMetadata: surface.summaryMetadata
40168
+ summaryMetadata: surface.summaryMetadata,
40169
+ errorMessage: this.errorMessage,
40170
+ errorReason: this.errorReason
39979
40171
  };
39980
40172
  }
39981
40173
  setPresentationMode(mode) {
@@ -40162,7 +40354,6 @@ ${effect.notification.body || ""}`.trim();
40162
40354
  }
40163
40355
  pushEvent(event) {
40164
40356
  this.events.push(event);
40165
- if (this.events.length > 50) this.events = this.events.slice(-50);
40166
40357
  }
40167
40358
  flushEvents() {
40168
40359
  const events = [...this.events];
@@ -40344,9 +40535,6 @@ ${effect.notification.body || ""}`.trim();
40344
40535
  key: dedupKey,
40345
40536
  message: normalizedMessage
40346
40537
  });
40347
- if (this.runtimeMessages.length > 50) {
40348
- this.runtimeMessages = this.runtimeMessages.slice(-50);
40349
- }
40350
40538
  if (normalizedContent) {
40351
40539
  this.historyWriter.appendNewMessages(
40352
40540
  this.type,
@@ -40593,8 +40781,8 @@ ${effect.notification.body || ""}`.trim();
40593
40781
  }
40594
40782
  getState() {
40595
40783
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
40596
- const recentMessages = normalizeChatMessages(this.messages.slice(-50).map((m) => {
40597
- const content = this.truncateContent(m.content);
40784
+ const recentMessages = normalizeChatMessages(this.messages.map((m) => {
40785
+ const content = m.content;
40598
40786
  return buildChatMessage({
40599
40787
  ...m,
40600
40788
  content
@@ -41387,18 +41575,6 @@ ${effect.notification.body || ""}`.trim();
41387
41575
  }
41388
41576
  }
41389
41577
  // ─── Rich Content Helpers ────────────────────────────
41390
- /** Truncate content for transport (text: 2000 chars, images preserved) */
41391
- truncateContent(content) {
41392
- if (typeof content === "string") {
41393
- return content.length > 2e3 ? content.slice(0, 2e3) + "\n... (truncated)" : content;
41394
- }
41395
- return content.map((b2) => {
41396
- if (b2.type === "text" && b2.text.length > 2e3) {
41397
- return { ...b2, text: b2.text.slice(0, 2e3) + "\n... (truncated)" };
41398
- }
41399
- return b2;
41400
- });
41401
- }
41402
41578
  /** Build ContentBlock[] from current partial state */
41403
41579
  buildPartialBlocks() {
41404
41580
  const blocks = [];
@@ -41552,7 +41728,6 @@ ${rawInput}` : rawInput;
41552
41728
  }
41553
41729
  pushEvent(event) {
41554
41730
  this.events.push(event);
41555
- if (this.events.length > 50) this.events = this.events.slice(-50);
41556
41731
  }
41557
41732
  appendSystemMessage(content, timestamp = Date.now()) {
41558
41733
  const normalizedContent = String(content || "").trim();
@@ -44203,7 +44378,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
44203
44378
  "heartbeat",
44204
44379
  "status_report",
44205
44380
  "read_chat",
44206
- "mark_session_seen"
44381
+ "mark_session_seen",
44382
+ "delete_notification",
44383
+ "mark_notification_unread"
44207
44384
  ]);
44208
44385
  function shouldLogCommand(cmd) {
44209
44386
  return !SKIP_COMMANDS.has(cmd);
@@ -44476,9 +44653,24 @@ Run 'adhdev doctor' for detailed diagnostics.`
44476
44653
  completionMarker,
44477
44654
  seenCompletionMarker
44478
44655
  );
44656
+ const { unread: overlayUnread, inboxBucket: overlayInboxBucket } = applySessionNotificationOverlay({
44657
+ id: sourceSession.id,
44658
+ providerSessionId: sourceSession.providerSessionId,
44659
+ status: sourceSession.status,
44660
+ unread,
44661
+ inboxBucket,
44662
+ lastMessageHash: sourceSession.lastMessageHash,
44663
+ lastMessageAt: sourceSession.lastMessageAt,
44664
+ lastUpdated: sourceSession.lastUpdated
44665
+ }, {
44666
+ dismissedNotificationId: getSessionNotificationDismissal(state, sourceSession.id, sourceSession.providerSessionId),
44667
+ unreadNotificationId: getSessionNotificationUnreadOverride(state, sourceSession.id, sourceSession.providerSessionId)
44668
+ });
44479
44669
  session.lastSeenAt = lastSeenAt;
44480
- session.unread = unread;
44481
- session.inboxBucket = inboxBucket;
44670
+ session.unread = overlayUnread;
44671
+ session.inboxBucket = overlayInboxBucket;
44672
+ session.completionMarker = completionMarker;
44673
+ session.seenCompletionMarker = seenCompletionMarker;
44482
44674
  if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
44483
44675
  const recentReadSnapshot = {
44484
44676
  sessionId: session.id,
@@ -45291,6 +45483,62 @@ Run 'adhdev doctor' for detailed diagnostics.`
45291
45483
  completionMarker
45292
45484
  };
45293
45485
  }
45486
+ case "delete_notification": {
45487
+ const sessionId = args?.sessionId;
45488
+ const notificationId = typeof args?.notificationId === "string" ? args.notificationId.trim() : "";
45489
+ if (!sessionId || typeof sessionId !== "string") {
45490
+ return { success: false, error: "sessionId is required" };
45491
+ }
45492
+ if (!notificationId) {
45493
+ return { success: false, error: "notificationId is required" };
45494
+ }
45495
+ const sessionEntries = buildSessionEntries(
45496
+ this.deps.instanceManager.collectAllStates(),
45497
+ this.deps.cdpManagers
45498
+ );
45499
+ const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
45500
+ const next = dismissSessionNotification(
45501
+ loadState(),
45502
+ sessionId,
45503
+ notificationId,
45504
+ targetSession?.providerSessionId
45505
+ );
45506
+ saveState(next);
45507
+ this.deps.onStatusChange?.();
45508
+ return {
45509
+ success: true,
45510
+ sessionId,
45511
+ notificationId
45512
+ };
45513
+ }
45514
+ case "mark_notification_unread": {
45515
+ const sessionId = args?.sessionId;
45516
+ const notificationId = typeof args?.notificationId === "string" ? args.notificationId.trim() : "";
45517
+ if (!sessionId || typeof sessionId !== "string") {
45518
+ return { success: false, error: "sessionId is required" };
45519
+ }
45520
+ if (!notificationId) {
45521
+ return { success: false, error: "notificationId is required" };
45522
+ }
45523
+ const sessionEntries = buildSessionEntries(
45524
+ this.deps.instanceManager.collectAllStates(),
45525
+ this.deps.cdpManagers
45526
+ );
45527
+ const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
45528
+ const next = markSessionNotificationUnread(
45529
+ loadState(),
45530
+ sessionId,
45531
+ notificationId,
45532
+ targetSession?.providerSessionId
45533
+ );
45534
+ saveState(next);
45535
+ this.deps.onStatusChange?.();
45536
+ return {
45537
+ success: true,
45538
+ sessionId,
45539
+ notificationId
45540
+ };
45541
+ }
45294
45542
  // ─── Daemon Self-Upgrade ───
45295
45543
  case "daemon_upgrade": {
45296
45544
  LOG2.info("Upgrade", "Remote upgrade requested from dashboard");
@@ -45665,6 +45913,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
45665
45913
  }
45666
45914
  };
45667
45915
  init_logger();
45916
+ init_debug_config();
45668
45917
  var DEFAULT_DAEMON_PORT = 19222;
45669
45918
  var DAEMON_WS_PATH = "/ipc";
45670
45919
  function normalizeSyncMode(syncMode) {