adhdev 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
@@ -542,6 +542,96 @@ function getSessionSeenMarker(state, sessionId, providerSessionId) {
542
542
  const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
543
543
  return state.sessionReadMarkers?.[providerKey] || state.sessionReadMarkers?.[sessionId] || "";
544
544
  }
545
+ function getSessionNotificationDismissal(state, sessionId, providerSessionId) {
546
+ const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
547
+ return state.sessionNotificationDismissals?.[providerKey] || state.sessionNotificationDismissals?.[sessionId] || "";
548
+ }
549
+ function getSessionNotificationUnreadOverride(state, sessionId, providerSessionId) {
550
+ const providerKey = buildSessionReadStateKey(sessionId, providerSessionId);
551
+ return state.sessionNotificationUnreadOverrides?.[providerKey] || state.sessionNotificationUnreadOverrides?.[sessionId] || "";
552
+ }
553
+ function dismissSessionNotification(state, sessionId, notificationId, providerSessionId) {
554
+ const dismissalId = String(notificationId || "").trim();
555
+ if (!dismissalId) return state;
556
+ const dismissalKeys = Array.from(new Set([
557
+ sessionId,
558
+ buildSessionReadStateKey(sessionId, providerSessionId)
559
+ ].filter(Boolean)));
560
+ const nextSessionNotificationDismissals = { ...state.sessionNotificationDismissals || {} };
561
+ const nextSessionNotificationUnreadOverrides = { ...state.sessionNotificationUnreadOverrides || {} };
562
+ for (const key of dismissalKeys) {
563
+ nextSessionNotificationDismissals[key] = dismissalId;
564
+ delete nextSessionNotificationUnreadOverrides[key];
565
+ }
566
+ return {
567
+ ...state,
568
+ sessionNotificationDismissals: nextSessionNotificationDismissals,
569
+ sessionNotificationUnreadOverrides: nextSessionNotificationUnreadOverrides
570
+ };
571
+ }
572
+ function markSessionNotificationUnread(state, sessionId, notificationId, providerSessionId) {
573
+ const unreadId = String(notificationId || "").trim();
574
+ if (!unreadId) return state;
575
+ const unreadKeys = Array.from(new Set([
576
+ sessionId,
577
+ buildSessionReadStateKey(sessionId, providerSessionId)
578
+ ].filter(Boolean)));
579
+ const nextSessionNotificationDismissals = { ...state.sessionNotificationDismissals || {} };
580
+ const nextSessionNotificationUnreadOverrides = { ...state.sessionNotificationUnreadOverrides || {} };
581
+ for (const key of unreadKeys) {
582
+ nextSessionNotificationUnreadOverrides[key] = unreadId;
583
+ delete nextSessionNotificationDismissals[key];
584
+ }
585
+ return {
586
+ ...state,
587
+ sessionNotificationDismissals: nextSessionNotificationDismissals,
588
+ sessionNotificationUnreadOverrides: nextSessionNotificationUnreadOverrides
589
+ };
590
+ }
591
+ function getSessionNotificationTargetValue(session) {
592
+ const providerSessionId = typeof session.providerSessionId === "string" ? session.providerSessionId.trim() : "";
593
+ return providerSessionId || session.id;
594
+ }
595
+ function getSessionCurrentNotificationId(session) {
596
+ const inboxBucket = session.inboxBucket || "idle";
597
+ const isNeedsAttention = inboxBucket === "needs_attention" || session.status === "waiting_approval";
598
+ const isTaskComplete = inboxBucket === "task_complete" && !!session.unread;
599
+ const type = isNeedsAttention ? "needs_attention" : isTaskComplete ? "task_complete" : "";
600
+ if (!type) return "";
601
+ const target = getSessionNotificationTargetValue(session);
602
+ const lastMessageHash = typeof session.lastMessageHash === "string" ? session.lastMessageHash : "";
603
+ const timestamp = Number(session.lastMessageAt || session.lastUpdated || 0);
604
+ return [type, target, lastMessageHash, String(timestamp)].join("|");
605
+ }
606
+ function applySessionNotificationOverlay(session, overlay) {
607
+ const currentNotificationId = getSessionCurrentNotificationId(session);
608
+ const taskCompleteNotificationId = (() => {
609
+ const target = getSessionNotificationTargetValue(session);
610
+ const lastMessageHash = typeof session.lastMessageHash === "string" ? session.lastMessageHash : "";
611
+ const timestamp = Number(session.lastMessageAt || session.lastUpdated || 0);
612
+ if (!target || !lastMessageHash || !timestamp) return "";
613
+ return ["task_complete", target, lastMessageHash, String(timestamp)].join("|");
614
+ })();
615
+ const dismissedNotificationId = typeof overlay.dismissedNotificationId === "string" ? overlay.dismissedNotificationId.trim() : "";
616
+ const unreadNotificationId = typeof overlay.unreadNotificationId === "string" ? overlay.unreadNotificationId.trim() : "";
617
+ if (unreadNotificationId && (currentNotificationId === unreadNotificationId || taskCompleteNotificationId === unreadNotificationId)) {
618
+ const forcedInboxBucket = session.inboxBucket === "needs_attention" || session.status === "waiting_approval" ? "needs_attention" : "task_complete";
619
+ return {
620
+ unread: true,
621
+ inboxBucket: forcedInboxBucket
622
+ };
623
+ }
624
+ if (!currentNotificationId || !dismissedNotificationId || currentNotificationId !== dismissedNotificationId) {
625
+ return {
626
+ unread: !!session.unread,
627
+ inboxBucket: session.inboxBucket || "idle"
628
+ };
629
+ }
630
+ return {
631
+ unread: false,
632
+ inboxBucket: "idle"
633
+ };
634
+ }
545
635
  function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker, providerSessionId) {
546
636
  const prev = state.sessionReads || {};
547
637
  const prevMarkers = state.sessionReadMarkers || {};
@@ -552,14 +642,20 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
552
642
  ].filter(Boolean)));
553
643
  const nextSessionReads = { ...prev };
554
644
  const nextSessionReadMarkers = { ...prevMarkers };
645
+ const nextSessionNotificationDismissals = { ...state.sessionNotificationDismissals || {} };
646
+ const nextSessionNotificationUnreadOverrides = { ...state.sessionNotificationUnreadOverrides || {} };
555
647
  for (const key of readKeys) {
556
648
  nextSessionReads[key] = Math.max(prev[key] || 0, seenAt);
557
649
  if (nextMarker) nextSessionReadMarkers[key] = nextMarker;
650
+ delete nextSessionNotificationDismissals[key];
651
+ delete nextSessionNotificationUnreadOverrides[key];
558
652
  }
559
653
  return {
560
654
  ...state,
561
655
  sessionReads: nextSessionReads,
562
- sessionReadMarkers: nextMarker ? nextSessionReadMarkers : prevMarkers
656
+ sessionReadMarkers: nextMarker ? nextSessionReadMarkers : prevMarkers,
657
+ sessionNotificationDismissals: nextSessionNotificationDismissals,
658
+ sessionNotificationUnreadOverrides: nextSessionNotificationUnreadOverrides
563
659
  };
564
660
  }
565
661
  var path2, MAX_ACTIVITY;
@@ -689,11 +785,19 @@ function normalizeState(raw) {
689
785
  const sessionReadMarkers = Object.fromEntries(
690
786
  Object.entries(isPlainObject2(parsed.sessionReadMarkers) ? parsed.sessionReadMarkers : {}).filter(([key, value]) => !isLegacyVolatileSessionReadKey(key) && typeof value === "string")
691
787
  );
788
+ const sessionNotificationDismissals = Object.fromEntries(
789
+ Object.entries(isPlainObject2(parsed.sessionNotificationDismissals) ? parsed.sessionNotificationDismissals : {}).filter(([key, value]) => !isLegacyVolatileSessionReadKey(key) && typeof value === "string" && value.length > 0)
790
+ );
791
+ const sessionNotificationUnreadOverrides = Object.fromEntries(
792
+ Object.entries(isPlainObject2(parsed.sessionNotificationUnreadOverrides) ? parsed.sessionNotificationUnreadOverrides : {}).filter(([key, value]) => !isLegacyVolatileSessionReadKey(key) && typeof value === "string" && value.length > 0)
793
+ );
692
794
  return {
693
795
  recentActivity,
694
796
  savedProviderSessions,
695
797
  sessionReads,
696
- sessionReadMarkers
798
+ sessionReadMarkers,
799
+ sessionNotificationDismissals,
800
+ sessionNotificationUnreadOverrides
697
801
  };
698
802
  }
699
803
  function loadState() {
@@ -728,7 +832,9 @@ var init_state_store = __esm({
728
832
  recentActivity: [],
729
833
  savedProviderSessions: [],
730
834
  sessionReads: {},
731
- sessionReadMarkers: {}
835
+ sessionReadMarkers: {},
836
+ sessionNotificationDismissals: {},
837
+ sessionNotificationUnreadOverrides: {}
732
838
  };
733
839
  }
734
840
  });
@@ -1130,9 +1236,15 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
1130
1236
  continue;
1131
1237
  }
1132
1238
  const status = String(session?.status || "").toLowerCase();
1239
+ const unread = session?.unread === true;
1240
+ const inboxBucket = String(session?.inboxBucket || "").toLowerCase();
1241
+ const runtimeSurfaceKind = String(session?.runtimeSurfaceKind || "").toLowerCase();
1242
+ const runtimeLifecycle = String(session?.runtimeLifecycle || "").toLowerCase();
1243
+ const isLiveRuntime = runtimeSurfaceKind === "live_runtime" || LIVE_RUNTIME_LIFECYCLES.has(runtimeLifecycle);
1133
1244
  const lastMessageAt = parseMessageTimestamp(session?.lastMessageAt);
1134
1245
  const recentlyUpdated = lastMessageAt > 0 && now - lastMessageAt <= recentMessageGraceMs;
1135
- if (activeStatuses.has(status) || recentlyUpdated) {
1246
+ const shouldKeepRecentTailHot = recentlyUpdated && (unread || inboxBucket === "task_complete" || inboxBucket === "needs_attention" || isLiveRuntime || activeStatuses.has(status));
1247
+ if (activeStatuses.has(status) || shouldKeepRecentTailHot) {
1136
1248
  active.add(sessionId);
1137
1249
  }
1138
1250
  }
@@ -4697,7 +4809,6 @@ var init_extension_provider_instance = __esm({
4697
4809
  }
4698
4810
  pushEvent(event) {
4699
4811
  this.events.push(event);
4700
- if (this.events.length > 50) this.events = this.events.slice(-50);
4701
4812
  }
4702
4813
  applyProviderResponse(data, options) {
4703
4814
  if (!data || typeof data !== "object") return;
@@ -4773,7 +4884,6 @@ var init_extension_provider_instance = __esm({
4773
4884
  key: dedupKey,
4774
4885
  message: normalizedMessage
4775
4886
  });
4776
- if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
4777
4887
  if (normalizedContent) {
4778
4888
  this.historyWriter.appendNewMessages(
4779
4889
  this.type,
@@ -5450,7 +5560,6 @@ var init_ide_provider_instance = __esm({
5450
5560
  }
5451
5561
  pushEvent(event) {
5452
5562
  this.events.push(event);
5453
- if (this.events.length > 50) this.events = this.events.slice(-50);
5454
5563
  }
5455
5564
  applyProviderResponse(data, options) {
5456
5565
  if (!data || typeof data !== "object") return;
@@ -5540,7 +5649,6 @@ var init_ide_provider_instance = __esm({
5540
5649
  key: dedupKey,
5541
5650
  message: normalizedMessage
5542
5651
  });
5543
- if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
5544
5652
  if (normalizedContent) {
5545
5653
  this.historyWriter.appendNewMessages(
5546
5654
  this.type,
@@ -7167,7 +7275,14 @@ async function handleReadChat(h, args) {
7167
7275
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
7168
7276
  if (adapter) {
7169
7277
  _log(`${transport} adapter: ${adapter.cliType}`);
7170
- const parsedStatus = typeof adapter.getScriptParsedStatus === "function" ? parseMaybeJson(adapter.getScriptParsedStatus()) : null;
7278
+ let parsedStatus = null;
7279
+ if (typeof adapter.getScriptParsedStatus === "function") {
7280
+ try {
7281
+ parsedStatus = parseMaybeJson(adapter.getScriptParsedStatus());
7282
+ } catch (error48) {
7283
+ return { success: false, error: error48?.message || String(error48) };
7284
+ }
7285
+ }
7171
7286
  const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
7172
7287
  const status = parsedRecord || adapter.getStatus();
7173
7288
  const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
@@ -10182,10 +10297,12 @@ function logTerminalBackendSelection(preference, ghosttyAvailable, backendKind)
10182
10297
  if (loggedTerminalBackends.has(key)) return;
10183
10298
  loggedTerminalBackends.add(key);
10184
10299
  if (backendKind === "xterm" && preference !== "xterm" && !ghosttyAvailable) {
10185
- LOG.warn(
10186
- "Terminal",
10187
- `[terminal-screen] ghostty-vt unavailable; using xterm fallback (preference=${preference})`
10188
- );
10300
+ const message = `[terminal-screen] ghostty-vt unavailable; using xterm fallback (preference=${preference})`;
10301
+ if (preference === "auto") {
10302
+ LOG.info("Terminal", message);
10303
+ } else {
10304
+ LOG.warn("Terminal", message);
10305
+ }
10189
10306
  return;
10190
10307
  }
10191
10308
  LOG.info(
@@ -11038,6 +11155,7 @@ var init_provider_cli_adapter = __esm({
11038
11155
  "use strict";
11039
11156
  os12 = __toESM(require("os"));
11040
11157
  init_logger();
11158
+ init_debug_config();
11041
11159
  init_terminal_screen();
11042
11160
  init_pty_transport();
11043
11161
  init_provider_cli_shared();
@@ -11071,7 +11189,15 @@ var init_provider_cli_adapter = __esm({
11071
11189
  `[${this.cliType}] Provider resolution: providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"} source=${this.providerResolutionMeta.scriptsSource || "-"} version=${this.providerResolutionMeta.resolvedVersion || "-"}`
11072
11190
  );
11073
11191
  } else {
11074
- LOG.warn("CLI", `[${this.cliType}] \u26A0 No CLI scripts loaded! Provider needs scripts/{version}/scripts.js`);
11192
+ const resolutionSummary = `providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"} source=${this.providerResolutionMeta.scriptsSource || "-"} version=${this.providerResolutionMeta.resolvedVersion || "-"}`;
11193
+ const hasResolvedProviderScripts = Boolean(
11194
+ this.providerResolutionMeta.providerDir || this.providerResolutionMeta.scriptDir || this.providerResolutionMeta.scriptsPath || this.providerResolutionMeta.scriptsSource || this.providerResolutionMeta.resolvedVersion
11195
+ );
11196
+ if (hasResolvedProviderScripts) {
11197
+ LOG.warn("CLI", `[${this.cliType}] \u26A0 No CLI scripts loaded! Provider needs scripts/{version}/scripts.js (${resolutionSummary})`);
11198
+ } else {
11199
+ LOG.info("CLI", `[${this.cliType}] CLI scripts not yet resolved (${resolutionSummary})`);
11200
+ }
11075
11201
  }
11076
11202
  }
11077
11203
  cliType;
@@ -11089,6 +11215,7 @@ var init_provider_cli_adapter = __esm({
11089
11215
  recentOutputBuffer = "";
11090
11216
  isWaitingForResponse = false;
11091
11217
  activeModal = null;
11218
+ parseErrorMessage = null;
11092
11219
  responseTimeout = null;
11093
11220
  idleTimeout = null;
11094
11221
  ready = false;
@@ -11149,7 +11276,8 @@ var init_provider_cli_adapter = __esm({
11149
11276
  currentTurnScope = null;
11150
11277
  traceEntries = [];
11151
11278
  traceSeq = 0;
11152
- traceSessionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
11279
+ traceSessionId = "";
11280
+ parsedStatusCache = null;
11153
11281
  static MAX_TRACE_ENTRIES = 250;
11154
11282
  providerResolutionMeta;
11155
11283
  static FINISH_RETRY_DELAY_MS = 300;
@@ -11390,7 +11518,8 @@ var init_provider_cli_adapter = __esm({
11390
11518
  this.terminalScreen.write(rawData);
11391
11519
  const cleanData = sanitizeTerminalText(rawData);
11392
11520
  const now = Date.now();
11393
- const normalizedScreenSnapshot = normalizeScreenSnapshot(this.terminalScreen.getText());
11521
+ const screenText = this.terminalScreen.getText();
11522
+ const normalizedScreenSnapshot = normalizeScreenSnapshot(screenText);
11394
11523
  this.lastOutputAt = now;
11395
11524
  if (cleanData.trim()) this.lastNonEmptyOutputAt = now;
11396
11525
  if (normalizedScreenSnapshot !== this.lastScreenSnapshot) {
@@ -11403,13 +11532,14 @@ var init_provider_cli_adapter = __esm({
11403
11532
  if (this.idleFinishCandidate && (rawData.length > 0 || cleanData.length > 0)) {
11404
11533
  this.clearIdleFinishCandidate("new_output");
11405
11534
  }
11406
- this.recordTrace("output", {
11407
- rawLength: rawData.length,
11408
- cleanLength: cleanData.length,
11409
- rawPreview: summarizeCliTraceText(rawData, 300),
11410
- cleanPreview: summarizeCliTraceText(cleanData, 300),
11411
- screenText: summarizeCliTraceText(this.terminalScreen.getText(), 1200)
11412
- });
11535
+ if (getDebugRuntimeConfig().collectDebugTrace) {
11536
+ this.recordTrace("output", {
11537
+ rawLength: rawData.length,
11538
+ cleanLength: cleanData.length,
11539
+ rawPreview: summarizeCliTraceText(rawData, 300),
11540
+ cleanPreview: summarizeCliTraceText(cleanData, 300)
11541
+ });
11542
+ }
11413
11543
  if (this.startupParseGate) {
11414
11544
  this.scheduleStartupSettleCheck();
11415
11545
  }
@@ -12083,10 +12213,12 @@ var init_provider_cli_adapter = __esm({
12083
12213
  // ─── Public API (CliAdapter) ───────────────────
12084
12214
  getStatus() {
12085
12215
  return {
12086
- status: this.currentStatus,
12216
+ status: this.parseErrorMessage ? "error" : this.currentStatus,
12087
12217
  messages: [...this.committedMessages],
12088
12218
  workingDir: this.workingDir,
12089
- activeModal: this.activeModal
12219
+ activeModal: this.activeModal,
12220
+ errorMessage: this.parseErrorMessage || void 0,
12221
+ errorReason: this.parseErrorMessage ? "parse_error" : void 0
12090
12222
  };
12091
12223
  }
12092
12224
  seedCommittedMessages(messages) {
@@ -12109,12 +12241,19 @@ var init_provider_cli_adapter = __esm({
12109
12241
  * Called by command handler / dashboard for rich content rendering.
12110
12242
  */
12111
12243
  getScriptParsedStatus() {
12244
+ const screenText = this.terminalScreen.getText();
12245
+ const cached2 = this.parsedStatusCache;
12246
+ 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) {
12247
+ return cached2.result;
12248
+ }
12112
12249
  const parsed = this.parseCurrentTranscript(
12113
12250
  this.committedMessages,
12114
12251
  this.responseBuffer,
12115
- this.currentTurnScope
12252
+ this.currentTurnScope,
12253
+ screenText
12116
12254
  );
12117
12255
  const shouldPreferCommittedMessages = !this.currentTurnScope && this.currentStatus === "idle" && !this.activeModal;
12256
+ let result;
12118
12257
  if (parsed && Array.isArray(parsed.messages)) {
12119
12258
  const hydratedMessages = shouldPreferCommittedMessages ? this.committedMessages.map((message, index) => buildChatMessage({
12120
12259
  ...message,
@@ -12126,7 +12265,7 @@ var init_provider_cli_adapter = __esm({
12126
12265
  scope: this.currentTurnScope,
12127
12266
  lastOutputAt: this.lastOutputAt
12128
12267
  });
12129
- return {
12268
+ result = {
12130
12269
  id: parsed.id || "cli_session",
12131
12270
  status: parsed.status || this.currentStatus,
12132
12271
  title: parsed.title || this.cliName,
@@ -12134,20 +12273,36 @@ var init_provider_cli_adapter = __esm({
12134
12273
  activeModal: parsed.activeModal ?? this.activeModal,
12135
12274
  providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0
12136
12275
  };
12276
+ } else {
12277
+ const messages = [...this.committedMessages];
12278
+ result = {
12279
+ id: "cli_session",
12280
+ status: this.currentStatus,
12281
+ title: this.cliName,
12282
+ messages: messages.map((message, index) => buildChatMessage({
12283
+ ...message,
12284
+ id: message.id || `msg_${index}`,
12285
+ index: typeof message.index === "number" ? message.index : index,
12286
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
12287
+ })),
12288
+ activeModal: this.activeModal
12289
+ };
12137
12290
  }
12138
- const messages = [...this.committedMessages];
12139
- return {
12140
- id: "cli_session",
12141
- status: this.currentStatus,
12142
- title: this.cliName,
12143
- messages: messages.slice(-50).map((message, index) => buildChatMessage({
12144
- ...message,
12145
- id: message.id || `msg_${index}`,
12146
- index: typeof message.index === "number" ? message.index : index,
12147
- receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
12148
- })),
12149
- activeModal: this.activeModal
12291
+ this.parsedStatusCache = {
12292
+ committedMessagesRef: this.committedMessages,
12293
+ responseBuffer: this.responseBuffer,
12294
+ currentTurnScope: this.currentTurnScope,
12295
+ recentOutputBuffer: this.recentOutputBuffer,
12296
+ accumulatedBuffer: this.accumulatedBuffer,
12297
+ accumulatedRawBuffer: this.accumulatedRawBuffer,
12298
+ screenText,
12299
+ currentStatus: this.currentStatus,
12300
+ activeModal: this.activeModal,
12301
+ cliName: this.cliName,
12302
+ lastOutputAt: this.lastOutputAt,
12303
+ result
12150
12304
  };
12305
+ return result;
12151
12306
  }
12152
12307
  async invokeScript(scriptName, args) {
12153
12308
  const fn = this.cliScripts?.[scriptName];
@@ -12170,14 +12325,18 @@ var init_provider_cli_adapter = __esm({
12170
12325
  args: args && typeof args === "object" ? { ...args } : {}
12171
12326
  }));
12172
12327
  }
12173
- parseCurrentTranscript(baseMessages, partialResponse, scope) {
12174
- if (!this.cliScripts?.parseOutput) return null;
12328
+ parseCurrentTranscript(baseMessages, partialResponse, scope, screenTextOverride) {
12329
+ if (!this.cliScripts?.parseOutput) {
12330
+ this.parseErrorMessage = null;
12331
+ return null;
12332
+ }
12175
12333
  try {
12334
+ const screenText = typeof screenTextOverride === "string" ? screenTextOverride : this.terminalScreen.getText();
12176
12335
  const input = buildCliParseInput({
12177
12336
  accumulatedBuffer: this.accumulatedBuffer,
12178
12337
  accumulatedRawBuffer: this.accumulatedRawBuffer,
12179
12338
  recentOutputBuffer: this.recentOutputBuffer,
12180
- terminalScreenText: this.terminalScreen.getText(),
12339
+ terminalScreenText: screenText,
12181
12340
  baseMessages,
12182
12341
  partialResponse,
12183
12342
  isWaitingForResponse: this.isWaitingForResponse,
@@ -12199,10 +12358,13 @@ var init_provider_cli_adapter = __esm({
12199
12358
  lastAssistant.content = trimPromptEchoPrefix(lastAssistant.content, promptForTrim);
12200
12359
  }
12201
12360
  }
12361
+ this.parseErrorMessage = null;
12202
12362
  return parsed;
12203
12363
  } catch (e) {
12204
- LOG.warn("CLI", `[${this.cliType}] parseOutput error: ${e.message}`);
12205
- return null;
12364
+ const message = e?.message || String(e);
12365
+ this.parseErrorMessage = message;
12366
+ LOG.warn("CLI", `[${this.cliType}] parseOutput error: ${message}`);
12367
+ throw e;
12206
12368
  }
12207
12369
  }
12208
12370
  /** Whether this adapter has CLI scripts loaded */
@@ -12876,6 +13038,8 @@ var init_cli_provider_instance = __esm({
12876
13038
  runtimeMessages = [];
12877
13039
  instanceId;
12878
13040
  suppressIdleHistoryReplay = false;
13041
+ errorMessage = void 0;
13042
+ errorReason = void 0;
12879
13043
  presentationMode;
12880
13044
  providerSessionId;
12881
13045
  launchMode;
@@ -12942,6 +13106,7 @@ var init_cli_provider_instance = __esm({
12942
13106
  }
12943
13107
  async onTick() {
12944
13108
  if (this.providerSessionId) return;
13109
+ if (this.type === "hermes-cli" && this.launchMode === "new") return;
12945
13110
  let probedSessionId = null;
12946
13111
  const probeConfig = this.provider.sessionProbe;
12947
13112
  if (probeConfig) {
@@ -12999,9 +13164,24 @@ var init_cli_provider_instance = __esm({
12999
13164
  }
13000
13165
  getState() {
13001
13166
  const adapterStatus = this.adapter.getStatus();
13002
- const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
13167
+ let parsedStatus = null;
13168
+ let parseErrorMessage;
13169
+ if (typeof this.adapter.getScriptParsedStatus === "function") {
13170
+ try {
13171
+ parsedStatus = this.adapter.getScriptParsedStatus() || null;
13172
+ this.errorMessage = void 0;
13173
+ this.errorReason = void 0;
13174
+ } catch (error48) {
13175
+ parseErrorMessage = error48?.message || String(error48);
13176
+ this.errorMessage = parseErrorMessage;
13177
+ this.errorReason = "parse_error";
13178
+ }
13179
+ } else {
13180
+ this.errorMessage = void 0;
13181
+ this.errorReason = void 0;
13182
+ }
13003
13183
  const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
13004
- const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
13184
+ const visibleStatus = parseErrorMessage ? "error" : autoApproveActive ? "generating" : adapterStatus.status;
13005
13185
  const parsedProviderSessionId = normalizeProviderSessionId(
13006
13186
  this.type,
13007
13187
  typeof parsedStatus?.providerSessionId === "string" ? parsedStatus.providerSessionId : ""
@@ -13011,7 +13191,7 @@ var init_cli_provider_instance = __esm({
13011
13191
  }
13012
13192
  const runtime = this.adapter.getRuntimeMetadata();
13013
13193
  this.maybeAppendRuntimeRecoveryMessage(runtime);
13014
- let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
13194
+ let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : parseErrorMessage ? normalizeChatMessages(Array.isArray(adapterStatus.messages) ? adapterStatus.messages : []) : [];
13015
13195
  const historyMessageCount = Number.isFinite(parsedStatus?.historyMessageCount) ? Math.max(0, Number(parsedStatus.historyMessageCount)) : null;
13016
13196
  if (historyMessageCount !== null) {
13017
13197
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
@@ -13051,7 +13231,7 @@ var init_cli_provider_instance = __esm({
13051
13231
  activeChat: {
13052
13232
  id: `${this.type}_${this.workingDir}`,
13053
13233
  title: parsedStatus?.title || dirName,
13054
- status: autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : parsedStatus?.status || visibleStatus,
13234
+ status: parseErrorMessage ? "error" : autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : parsedStatus?.status || visibleStatus,
13055
13235
  messages: mergedMessages,
13056
13236
  activeModal: autoApproveActive ? null : parsedStatus?.activeModal ?? adapterStatus.activeModal,
13057
13237
  inputContent: ""
@@ -13077,7 +13257,9 @@ var init_cli_provider_instance = __esm({
13077
13257
  resume: this.provider.resume,
13078
13258
  controlValues: surface.controlValues,
13079
13259
  providerControls: this.provider.controls,
13080
- summaryMetadata: surface.summaryMetadata
13260
+ summaryMetadata: surface.summaryMetadata,
13261
+ errorMessage: this.errorMessage,
13262
+ errorReason: this.errorReason
13081
13263
  };
13082
13264
  }
13083
13265
  setPresentationMode(mode) {
@@ -13264,7 +13446,6 @@ var init_cli_provider_instance = __esm({
13264
13446
  }
13265
13447
  pushEvent(event) {
13266
13448
  this.events.push(event);
13267
- if (this.events.length > 50) this.events = this.events.slice(-50);
13268
13449
  }
13269
13450
  flushEvents() {
13270
13451
  const events = [...this.events];
@@ -13446,9 +13627,6 @@ ${effect.notification.body || ""}`.trim();
13446
13627
  key: dedupKey,
13447
13628
  message: normalizedMessage
13448
13629
  });
13449
- if (this.runtimeMessages.length > 50) {
13450
- this.runtimeMessages = this.runtimeMessages.slice(-50);
13451
- }
13452
13630
  if (normalizedContent) {
13453
13631
  this.historyWriter.appendNewMessages(
13454
13632
  this.type,
@@ -30007,8 +30185,8 @@ var init_acp_provider_instance = __esm({
30007
30185
  }
30008
30186
  getState() {
30009
30187
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
30010
- const recentMessages = normalizeChatMessages(this.messages.slice(-50).map((m) => {
30011
- const content = this.truncateContent(m.content);
30188
+ const recentMessages = normalizeChatMessages(this.messages.map((m) => {
30189
+ const content = m.content;
30012
30190
  return buildChatMessage({
30013
30191
  ...m,
30014
30192
  content
@@ -30801,18 +30979,6 @@ var init_acp_provider_instance = __esm({
30801
30979
  }
30802
30980
  }
30803
30981
  // ─── Rich Content Helpers ────────────────────────────
30804
- /** Truncate content for transport (text: 2000 chars, images preserved) */
30805
- truncateContent(content) {
30806
- if (typeof content === "string") {
30807
- return content.length > 2e3 ? content.slice(0, 2e3) + "\n... (truncated)" : content;
30808
- }
30809
- return content.map((b) => {
30810
- if (b.type === "text" && b.text.length > 2e3) {
30811
- return { ...b, text: b.text.slice(0, 2e3) + "\n... (truncated)" };
30812
- }
30813
- return b;
30814
- });
30815
- }
30816
30982
  /** Build ContentBlock[] from current partial state */
30817
30983
  buildPartialBlocks() {
30818
30984
  const blocks = [];
@@ -30966,7 +31132,6 @@ ${rawInput}` : rawInput;
30966
31132
  }
30967
31133
  pushEvent(event) {
30968
31134
  this.events.push(event);
30969
- if (this.events.length > 50) this.events = this.events.slice(-50);
30970
31135
  }
30971
31136
  appendSystemMessage(content, timestamp = Date.now()) {
30972
31137
  const normalizedContent = String(content || "").trim();
@@ -35482,7 +35647,9 @@ var init_command_log = __esm({
35482
35647
  "heartbeat",
35483
35648
  "status_report",
35484
35649
  "read_chat",
35485
- "mark_session_seen"
35650
+ "mark_session_seen",
35651
+ "delete_notification",
35652
+ "mark_notification_unread"
35486
35653
  ]);
35487
35654
  cleanOldFiles();
35488
35655
  }
@@ -35702,9 +35869,24 @@ function buildStatusSnapshot(options) {
35702
35869
  completionMarker,
35703
35870
  seenCompletionMarker
35704
35871
  );
35872
+ const { unread: overlayUnread, inboxBucket: overlayInboxBucket } = applySessionNotificationOverlay({
35873
+ id: sourceSession.id,
35874
+ providerSessionId: sourceSession.providerSessionId,
35875
+ status: sourceSession.status,
35876
+ unread,
35877
+ inboxBucket,
35878
+ lastMessageHash: sourceSession.lastMessageHash,
35879
+ lastMessageAt: sourceSession.lastMessageAt,
35880
+ lastUpdated: sourceSession.lastUpdated
35881
+ }, {
35882
+ dismissedNotificationId: getSessionNotificationDismissal(state, sourceSession.id, sourceSession.providerSessionId),
35883
+ unreadNotificationId: getSessionNotificationUnreadOverride(state, sourceSession.id, sourceSession.providerSessionId)
35884
+ });
35705
35885
  session.lastSeenAt = lastSeenAt;
35706
- session.unread = unread;
35707
- session.inboxBucket = inboxBucket;
35886
+ session.unread = overlayUnread;
35887
+ session.inboxBucket = overlayInboxBucket;
35888
+ session.completionMarker = completionMarker;
35889
+ session.seenCompletionMarker = seenCompletionMarker;
35708
35890
  if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
35709
35891
  const recentReadSnapshot = {
35710
35892
  sessionId: session.id,
@@ -35769,6 +35951,7 @@ var init_snapshot = __esm({
35769
35951
  init_terminal_screen();
35770
35952
  init_logger();
35771
35953
  init_builders();
35954
+ init_recent_activity();
35772
35955
  READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
35773
35956
  recentReadDebugSignatureBySession = /* @__PURE__ */ new Map();
35774
35957
  }
@@ -36568,6 +36751,62 @@ var init_router = __esm({
36568
36751
  completionMarker
36569
36752
  };
36570
36753
  }
36754
+ case "delete_notification": {
36755
+ const sessionId = args?.sessionId;
36756
+ const notificationId = typeof args?.notificationId === "string" ? args.notificationId.trim() : "";
36757
+ if (!sessionId || typeof sessionId !== "string") {
36758
+ return { success: false, error: "sessionId is required" };
36759
+ }
36760
+ if (!notificationId) {
36761
+ return { success: false, error: "notificationId is required" };
36762
+ }
36763
+ const sessionEntries = buildSessionEntries(
36764
+ this.deps.instanceManager.collectAllStates(),
36765
+ this.deps.cdpManagers
36766
+ );
36767
+ const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
36768
+ const next = dismissSessionNotification(
36769
+ loadState(),
36770
+ sessionId,
36771
+ notificationId,
36772
+ targetSession?.providerSessionId
36773
+ );
36774
+ saveState(next);
36775
+ this.deps.onStatusChange?.();
36776
+ return {
36777
+ success: true,
36778
+ sessionId,
36779
+ notificationId
36780
+ };
36781
+ }
36782
+ case "mark_notification_unread": {
36783
+ const sessionId = args?.sessionId;
36784
+ const notificationId = typeof args?.notificationId === "string" ? args.notificationId.trim() : "";
36785
+ if (!sessionId || typeof sessionId !== "string") {
36786
+ return { success: false, error: "sessionId is required" };
36787
+ }
36788
+ if (!notificationId) {
36789
+ return { success: false, error: "notificationId is required" };
36790
+ }
36791
+ const sessionEntries = buildSessionEntries(
36792
+ this.deps.instanceManager.collectAllStates(),
36793
+ this.deps.cdpManagers
36794
+ );
36795
+ const targetSession = sessionEntries.find((entry) => entry.id === sessionId);
36796
+ const next = markSessionNotificationUnread(
36797
+ loadState(),
36798
+ sessionId,
36799
+ notificationId,
36800
+ targetSession?.providerSessionId
36801
+ );
36802
+ saveState(next);
36803
+ this.deps.onStatusChange?.();
36804
+ return {
36805
+ success: true,
36806
+ sessionId,
36807
+ notificationId
36808
+ };
36809
+ }
36571
36810
  // ─── Daemon Self-Upgrade ───
36572
36811
  case "daemon_upgrade": {
36573
36812
  LOG.info("Upgrade", "Remote upgrade requested from dashboard");
@@ -45141,6 +45380,8 @@ var init_server_connection = __esm({
45141
45380
  if (misses >= 3 && this.ws) {
45142
45381
  LOG.warn("Server", `[ServerConn] Pong timeout (${misses}x) \u2014 closing stale WS`);
45143
45382
  this.ws.terminate();
45383
+ } else if (misses === 1) {
45384
+ LOG.info("Server", `[ServerConn] Pong timeout (${misses}x) \u2014 keeping WS open and retrying`);
45144
45385
  } else {
45145
45386
  LOG.warn("Server", `[ServerConn] Pong timeout (${misses}x) \u2014 keeping WS open and retrying`);
45146
45387
  }
@@ -54163,7 +54404,7 @@ var init_adhdev_daemon = __esm({
54163
54404
  init_source2();
54164
54405
  init_version();
54165
54406
  init_src();
54166
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.81" });
54407
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.83" });
54167
54408
  AdhdevDaemon = class _AdhdevDaemon {
54168
54409
  localHttpServer = null;
54169
54410
  localWss = null;