@adhdev/daemon-core 0.9.30 → 0.9.32

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.
@@ -103,6 +103,7 @@ export declare class ProviderCliAdapter implements CliAdapter {
103
103
  private static readonly STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS;
104
104
  private static readonly SCREEN_SNAPSHOT_MIN_INTERVAL_MS;
105
105
  private static readonly MAX_TRACE_ENTRIES;
106
+ private static readonly PARSE_MESSAGE_TAIL_LIMIT;
106
107
  private readonly providerResolutionMeta;
107
108
  private static readonly FINISH_RETRY_DELAY_MS;
108
109
  private static readonly MAX_FINISH_RETRIES;
@@ -111,6 +112,9 @@ export declare class ProviderCliAdapter implements CliAdapter {
111
112
  private shouldReadTerminalScreenSnapshot;
112
113
  private resetTerminalScreen;
113
114
  private getFreshParsedStatusCache;
115
+ private selectParseBaseMessages;
116
+ private messagesComparable;
117
+ private stitchParsedMessagesWithCommittedBase;
114
118
  private getIdleFinishConfirmMs;
115
119
  private getStatusActivityHoldMs;
116
120
  private setStatus;
package/dist/index.js CHANGED
@@ -350,14 +350,13 @@ function daemonLog(category, msg, level = "info") {
350
350
  const shouldOutput = LEVEL_NUM[level] >= LEVEL_NUM[currentLevel];
351
351
  const label = LEVEL_LABEL[level];
352
352
  const line = `[${ts()}] [${label}] [${category}] ${msg}`;
353
+ if (!shouldOutput) return;
353
354
  writeToFile(line);
354
355
  ringBuffer.push({ ts: Date.now(), level, category, message: msg });
355
356
  if (ringBuffer.length > RING_BUFFER_SIZE) {
356
357
  ringBuffer.splice(0, ringBuffer.length - RING_BUFFER_SIZE);
357
358
  }
358
- if (shouldOutput) {
359
- origConsoleLog(line);
360
- }
359
+ origConsoleLog(line);
361
360
  }
362
361
  function installGlobalInterceptor() {
363
362
  if (interceptorInstalled) return;
@@ -2164,6 +2163,7 @@ var init_provider_cli_adapter = __esm({
2164
2163
  static STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS = 1e3;
2165
2164
  static SCREEN_SNAPSHOT_MIN_INTERVAL_MS = 250;
2166
2165
  static MAX_TRACE_ENTRIES = 250;
2166
+ static PARSE_MESSAGE_TAIL_LIMIT = 100;
2167
2167
  providerResolutionMeta;
2168
2168
  static FINISH_RETRY_DELAY_MS = 300;
2169
2169
  static MAX_FINISH_RETRIES = 2;
@@ -2195,6 +2195,32 @@ var init_provider_cli_adapter = __esm({
2195
2195
  }
2196
2196
  return null;
2197
2197
  }
2198
+ selectParseBaseMessages(baseMessages) {
2199
+ if (baseMessages.length <= _ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
2200
+ return baseMessages.slice(-_ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
2201
+ }
2202
+ messagesComparable(left, right) {
2203
+ if (!left || !right) return false;
2204
+ if ((left.role || "") !== (right.role || "")) return false;
2205
+ const leftText = normalizeComparableTranscriptText(left.content);
2206
+ const rightText = normalizeComparableTranscriptText(right.content);
2207
+ return !!leftText && leftText === rightText;
2208
+ }
2209
+ stitchParsedMessagesWithCommittedBase(parsedMessages, fullBaseMessages, parseBaseMessages) {
2210
+ if (!Array.isArray(parsedMessages) || parsedMessages.length === 0) return parsedMessages;
2211
+ if (fullBaseMessages.length <= parseBaseMessages.length) return parsedMessages;
2212
+ const parsedFirst = parsedMessages[0];
2213
+ const fullFirst = fullBaseMessages[0];
2214
+ if (parsedMessages.length >= fullBaseMessages.length && this.messagesComparable(parsedFirst, fullFirst)) {
2215
+ return parsedMessages;
2216
+ }
2217
+ const tailFirst = parseBaseMessages[0];
2218
+ if (tailFirst && this.messagesComparable(parsedFirst, tailFirst)) {
2219
+ const prefixLength = fullBaseMessages.length - parseBaseMessages.length;
2220
+ return [...fullBaseMessages.slice(0, prefixLength), ...parsedMessages];
2221
+ }
2222
+ return [...fullBaseMessages, ...parsedMessages];
2223
+ }
2198
2224
  getIdleFinishConfirmMs() {
2199
2225
  return this.timeouts.idleFinishConfirm;
2200
2226
  }
@@ -2780,7 +2806,7 @@ var init_provider_cli_adapter = __esm({
2780
2806
  const ctx = { now, modal, status, parsedMessages, lastParsedAssistant, parsedStatus: parsedStatus || null, prevStatus };
2781
2807
  if (!this.applyPendingScriptStatusDebounce(ctx)) return;
2782
2808
  const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
2783
- LOG.info(
2809
+ LOG.debug(
2784
2810
  "CLI",
2785
2811
  `[${this.cliType}] settled diagnostics prompt=${JSON.stringify(this.currentTurnScope?.prompt || "").slice(0, 140)} status=${String(status || "")} parsedStatus=${String(parsedStatus || "")} parsedMsgCount=${parsedMessages.length} lastParsedAssistant=${JSON.stringify(summarizeCliTraceText(lastParsedAssistant?.content || "", 120)).slice(0, 160)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 160)).slice(0, 220)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 160)).slice(0, 220)}`
2786
2812
  );
@@ -3147,18 +3173,26 @@ var init_provider_cli_adapter = __esm({
3147
3173
  try {
3148
3174
  const screenText = this.terminalScreen.getText();
3149
3175
  const tail = this.recentOutputBuffer.slice(-500);
3176
+ const parseBaseMessages = this.selectParseBaseMessages(this.committedMessages);
3150
3177
  const input = buildCliParseInput({
3151
3178
  accumulatedBuffer: this.accumulatedBuffer,
3152
3179
  accumulatedRawBuffer: this.accumulatedRawBuffer,
3153
3180
  recentOutputBuffer: this.recentOutputBuffer,
3154
3181
  terminalScreenText: screenText,
3155
- baseMessages: this.committedMessages,
3182
+ baseMessages: parseBaseMessages,
3156
3183
  partialResponse: this.responseBuffer,
3157
3184
  isWaitingForResponse: this.isWaitingForResponse,
3158
3185
  scope: this.currentTurnScope,
3159
3186
  runtimeSettings: this.runtimeSettings
3160
3187
  });
3161
3188
  const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
3189
+ if (session && typeof session === "object" && Array.isArray(session.messages)) {
3190
+ session.messages = this.stitchParsedMessagesWithCommittedBase(
3191
+ session.messages,
3192
+ this.committedMessages,
3193
+ parseBaseMessages
3194
+ );
3195
+ }
3162
3196
  this.parseErrorMessage = null;
3163
3197
  return session && typeof session === "object" ? session : null;
3164
3198
  } catch (e) {
@@ -3479,12 +3513,13 @@ var init_provider_cli_adapter = __esm({
3479
3513
  }
3480
3514
  try {
3481
3515
  const screenText = typeof screenTextOverride === "string" ? screenTextOverride : this.terminalScreen.getText();
3516
+ const parseBaseMessages = this.selectParseBaseMessages(baseMessages);
3482
3517
  const input = buildCliParseInput({
3483
3518
  accumulatedBuffer: this.accumulatedBuffer,
3484
3519
  accumulatedRawBuffer: this.accumulatedRawBuffer,
3485
3520
  recentOutputBuffer: this.recentOutputBuffer,
3486
3521
  terminalScreenText: screenText,
3487
- baseMessages,
3522
+ baseMessages: parseBaseMessages,
3488
3523
  partialResponse,
3489
3524
  isWaitingForResponse: this.isWaitingForResponse,
3490
3525
  scope,
@@ -3496,6 +3531,11 @@ var init_provider_cli_adapter = __esm({
3496
3531
  }
3497
3532
  const normalizedParsed = this.suppressStaleParsedApproval(parsed, input.recentBuffer, input.screenText);
3498
3533
  if (normalizedParsed && Array.isArray(normalizedParsed.messages)) {
3534
+ normalizedParsed.messages = this.stitchParsedMessagesWithCommittedBase(
3535
+ normalizedParsed.messages,
3536
+ baseMessages,
3537
+ parseBaseMessages
3538
+ );
3499
3539
  this.trimLastAssistantEcho(normalizedParsed.messages, scope?.prompt || getLastUserPromptText(baseMessages));
3500
3540
  }
3501
3541
  this.parseErrorMessage = null;
@@ -5146,6 +5186,7 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
5146
5186
  Number.isFinite(options.recentMessageGraceMs) ? Number(options.recentMessageGraceMs) : DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS
5147
5187
  );
5148
5188
  const activeStatuses = options.activeStatuses ?? DEFAULT_ACTIVE_CHAT_POLL_STATUSES;
5189
+ const activeSessionIds = options.activeSessionIds ?? /* @__PURE__ */ new Set();
5149
5190
  const active = /* @__PURE__ */ new Set();
5150
5191
  const excluded = /* @__PURE__ */ new Set();
5151
5192
  for (const session of sessions) {
@@ -5155,6 +5196,10 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
5155
5196
  excluded.add(sessionId);
5156
5197
  continue;
5157
5198
  }
5199
+ if (activeSessionIds.has(sessionId)) {
5200
+ active.add(sessionId);
5201
+ continue;
5202
+ }
5158
5203
  const status = String(session?.status || "").toLowerCase();
5159
5204
  const unread = session?.unread === true;
5160
5205
  const inboxBucket = String(session?.inboxBucket || "").toLowerCase();
@@ -10700,6 +10745,7 @@ async function handleReadChat(h, args) {
10700
10745
  return { success: false, error: `${transport} adapter not found` };
10701
10746
  }
10702
10747
  if (isExtensionTransport(transport)) {
10748
+ let extensionReadChatError = "";
10703
10749
  try {
10704
10750
  const evalResult = await h.evaluateProviderScript("readChat", void 0, READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS);
10705
10751
  if (evalResult?.result) {
@@ -10707,7 +10753,8 @@ async function handleReadChat(h, args) {
10707
10753
  if (typeof parsed === "string") {
10708
10754
  try {
10709
10755
  parsed = JSON.parse(parsed);
10710
- } catch {
10756
+ } catch (e) {
10757
+ extensionReadChatError = `extension read_chat parse failed: ${e?.message || String(e)}`;
10711
10758
  }
10712
10759
  }
10713
10760
  if (parsed && typeof parsed === "object") {
@@ -10732,8 +10779,14 @@ async function handleReadChat(h, args) {
10732
10779
  );
10733
10780
  return buildReadChatCommandResult(validated, args);
10734
10781
  }
10782
+ if (!extensionReadChatError) {
10783
+ extensionReadChatError = "extension read_chat returned a non-object payload";
10784
+ }
10785
+ } else {
10786
+ extensionReadChatError = "extension read_chat returned no payload";
10735
10787
  }
10736
10788
  } catch (e) {
10789
+ extensionReadChatError = `extension read_chat failed: ${e?.message || String(e)}`;
10737
10790
  _log(`Extension error: ${e.message}`);
10738
10791
  traceProviderEvent(args, "provider", "extension.read_chat.error", {
10739
10792
  h,
@@ -10747,8 +10800,8 @@ async function handleReadChat(h, args) {
10747
10800
  const parentSessionId = h.currentSession?.parentSessionId;
10748
10801
  if (cdp2 && parentSessionId) {
10749
10802
  const stream = await h.agentStream.collectActiveSession(cdp2, parentSessionId);
10750
- if (stream?.agentType !== provider?.type) {
10751
- return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
10803
+ if (stream && stream.agentType !== provider?.type) {
10804
+ return { success: false, error: `extension read_chat stream agent mismatch for ${provider?.type || "unknown_extension"}` };
10752
10805
  }
10753
10806
  if (stream) {
10754
10807
  h.historyWriter.appendNewMessages(
@@ -10766,12 +10819,13 @@ async function handleReadChat(h, args) {
10766
10819
  }
10767
10820
  }
10768
10821
  }
10769
- return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
10822
+ return { success: false, error: extensionReadChatError || "extension read_chat unavailable" };
10770
10823
  }
10771
10824
  const cdp = h.getCdp();
10772
10825
  if (!cdp?.isConnected) return { success: false, error: "CDP not connected" };
10773
10826
  const webviewScript = h.getProviderScript("webviewReadChat") || h.getProviderScript("webview_read_chat");
10774
10827
  if (webviewScript) {
10828
+ let webviewReadChatError = "";
10775
10829
  try {
10776
10830
  const matchText = provider?.webviewMatchText;
10777
10831
  const matchFn = matchText ? (body) => body.includes(matchText) : void 0;
@@ -10781,7 +10835,8 @@ async function handleReadChat(h, args) {
10781
10835
  if (typeof parsed === "string") {
10782
10836
  try {
10783
10837
  parsed = JSON.parse(parsed);
10784
- } catch {
10838
+ } catch (e) {
10839
+ webviewReadChatError = `webview read_chat parse failed: ${e?.message || String(e)}`;
10785
10840
  }
10786
10841
  }
10787
10842
  if (parsed && typeof parsed === "object") {
@@ -10796,14 +10851,21 @@ async function handleReadChat(h, args) {
10796
10851
  );
10797
10852
  return buildReadChatCommandResult(validated, args);
10798
10853
  }
10854
+ if (!webviewReadChatError) {
10855
+ webviewReadChatError = "webview read_chat returned a non-object payload";
10856
+ }
10857
+ } else {
10858
+ webviewReadChatError = "webview read_chat returned no payload";
10799
10859
  }
10800
10860
  } catch (e) {
10861
+ webviewReadChatError = `webview read_chat failed: ${e?.message || String(e)}`;
10801
10862
  _log(`Webview readChat error: ${e.message}`);
10802
10863
  }
10803
- return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
10864
+ return { success: false, error: webviewReadChatError || "webview read_chat unavailable" };
10804
10865
  }
10805
10866
  const script = h.getProviderScript("readChat") || h.getProviderScript("read_chat");
10806
10867
  if (script) {
10868
+ let ideReadChatError = "";
10807
10869
  try {
10808
10870
  const evalResult = await h.evaluateProviderScript("readChat", void 0, READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS);
10809
10871
  if (evalResult?.result) {
@@ -10811,12 +10873,13 @@ async function handleReadChat(h, args) {
10811
10873
  if (typeof parsed === "string") {
10812
10874
  try {
10813
10875
  parsed = JSON.parse(parsed);
10814
- } catch {
10876
+ } catch (e) {
10877
+ ideReadChatError = `ide read_chat parse failed: ${e?.message || String(e)}`;
10815
10878
  }
10816
10879
  }
10817
- if (parsed && typeof parsed === "object" && parsed.messages?.length > 0) {
10880
+ if (parsed && typeof parsed === "object") {
10818
10881
  const validated = validateReadChatResultPayload(parsed, "ide read_chat");
10819
- _log(`OK: ${validated.messages?.length} msgs`);
10882
+ _log(`OK: ${validated.messages?.length || 0} msgs`);
10820
10883
  traceProviderEvent(args, "provider", "ide.read_chat.success", {
10821
10884
  h,
10822
10885
  provider,
@@ -10836,8 +10899,14 @@ async function handleReadChat(h, args) {
10836
10899
  );
10837
10900
  return buildReadChatCommandResult(validated, args);
10838
10901
  }
10902
+ if (!ideReadChatError) {
10903
+ ideReadChatError = "ide read_chat returned a non-object payload";
10904
+ }
10905
+ } else {
10906
+ ideReadChatError = "ide read_chat returned no payload";
10839
10907
  }
10840
10908
  } catch (e) {
10909
+ ideReadChatError = `ide read_chat failed: ${e?.message || String(e)}`;
10841
10910
  LOG.info("Command", `[read_chat] Script error: ${e.message}`);
10842
10911
  traceProviderEvent(args, "provider", "ide.read_chat.error", {
10843
10912
  h,
@@ -10846,8 +10915,9 @@ async function handleReadChat(h, args) {
10846
10915
  payload: { method: "evaluate", error: e.message }
10847
10916
  });
10848
10917
  }
10918
+ return { success: false, error: ideReadChatError || "ide read_chat unavailable" };
10849
10919
  }
10850
- return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
10920
+ return { success: false, error: "read_chat unavailable" };
10851
10921
  }
10852
10922
  async function handleSendChat(h, args) {
10853
10923
  const input = getSendChatInputEnvelope(args);
@@ -16089,6 +16159,9 @@ var ProviderLoader = class _ProviderLoader {
16089
16159
  log(msg) {
16090
16160
  this.logFn(`[ProviderLoader] ${msg}`);
16091
16161
  }
16162
+ debugLog(msg) {
16163
+ LOG.debug("Provider", `[ProviderLoader] ${msg}`);
16164
+ }
16092
16165
  // ─── Public API ────────────────────────────────
16093
16166
  /**
16094
16167
  * User override root (~/.adhdev/providers by default).
@@ -16695,7 +16768,7 @@ var ProviderLoader = class _ProviderLoader {
16695
16768
  const loaded = this.loadScriptsFromDir(type, entry.scriptDir);
16696
16769
  if (loaded) {
16697
16770
  resolved.scripts = loaded;
16698
- this.log(` [compatibility] ${type} v${currentVersion} \u2192 ${entry.scriptDir}`);
16771
+ this.debugLog(` [compatibility] ${type} v${currentVersion} \u2192 ${entry.scriptDir}`);
16699
16772
  resolved._resolvedScriptDir = entry.scriptDir;
16700
16773
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
16701
16774
  if (providerDir) {
@@ -16711,7 +16784,7 @@ var ProviderLoader = class _ProviderLoader {
16711
16784
  const loaded = this.loadScriptsFromDir(type, base.defaultScriptDir);
16712
16785
  if (loaded) {
16713
16786
  resolved.scripts = loaded;
16714
- this.log(` [compatibility] ${type} v${currentVersion} \u2192 default: ${base.defaultScriptDir}`);
16787
+ this.debugLog(` [compatibility] ${type} v${currentVersion} \u2192 default: ${base.defaultScriptDir}`);
16715
16788
  resolved._resolvedScriptDir = base.defaultScriptDir;
16716
16789
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
16717
16790
  if (providerDir) {
@@ -16746,7 +16819,7 @@ var ProviderLoader = class _ProviderLoader {
16746
16819
  const loaded = this.loadScriptsFromDir(type, base.defaultScriptDir);
16747
16820
  if (loaded) {
16748
16821
  resolved.scripts = loaded;
16749
- this.log(` [compatibility] ${type} no version detected \u2192 default: ${base.defaultScriptDir}`);
16822
+ this.debugLog(` [compatibility] ${type} no version detected \u2192 default: ${base.defaultScriptDir}`);
16750
16823
  resolved._resolvedScriptDir = base.defaultScriptDir;
16751
16824
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
16752
16825
  if (providerDir) {