@adhdev/daemon-core 0.9.31 → 0.9.33

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();
@@ -10464,6 +10509,26 @@ function toHistoryPersistedMessages(messages) {
10464
10509
  historyDedupKey: deriveHistoryDedupKey(message)
10465
10510
  }));
10466
10511
  }
10512
+ function findLastMessageIndexBySignature(messages, signature) {
10513
+ if (!signature) return -1;
10514
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
10515
+ if (getChatMessageSignature(messages[index]) === signature) {
10516
+ return index;
10517
+ }
10518
+ }
10519
+ return -1;
10520
+ }
10521
+ function buildBoundedTailSync(messages, cursor) {
10522
+ const totalMessages = messages.length;
10523
+ const tailMessages = cursor.tailLimit > 0 && totalMessages > cursor.tailLimit ? messages.slice(-cursor.tailLimit) : messages;
10524
+ return {
10525
+ syncMode: "full",
10526
+ replaceFrom: 0,
10527
+ messages: tailMessages,
10528
+ totalMessages,
10529
+ lastMessageSignature: getChatMessageSignature(messages[totalMessages - 1])
10530
+ };
10531
+ }
10467
10532
  function computeReadChatSync(messages, cursor) {
10468
10533
  const totalMessages = messages.length;
10469
10534
  const lastMessageSignature = getChatMessageSignature(messages[totalMessages - 1]);
@@ -10495,6 +10560,15 @@ function computeReadChatSync(messages, cursor) {
10495
10560
  lastMessageSignature
10496
10561
  };
10497
10562
  }
10563
+ if (cursor.tailLimit > 0 && knownSignature === lastMessageSignature) {
10564
+ return {
10565
+ syncMode: "noop",
10566
+ replaceFrom: totalMessages,
10567
+ messages: [],
10568
+ totalMessages,
10569
+ lastMessageSignature
10570
+ };
10571
+ }
10498
10572
  if (knownMessageCount < totalMessages) {
10499
10573
  const anchorSignature = getChatMessageSignature(messages[knownMessageCount - 1]);
10500
10574
  if (anchorSignature === knownSignature) {
@@ -10506,6 +10580,19 @@ function computeReadChatSync(messages, cursor) {
10506
10580
  lastMessageSignature
10507
10581
  };
10508
10582
  }
10583
+ if (cursor.tailLimit > 0) {
10584
+ const signatureIndex = findLastMessageIndexBySignature(messages, knownSignature);
10585
+ if (signatureIndex >= 0) {
10586
+ return {
10587
+ syncMode: "append",
10588
+ replaceFrom: knownMessageCount,
10589
+ messages: messages.slice(signatureIndex + 1),
10590
+ totalMessages,
10591
+ lastMessageSignature
10592
+ };
10593
+ }
10594
+ return buildBoundedTailSync(messages, cursor);
10595
+ }
10509
10596
  }
10510
10597
  const replaceFrom = Math.max(0, Math.min(knownMessageCount - 1, totalMessages));
10511
10598
  return {
@@ -16114,6 +16201,9 @@ var ProviderLoader = class _ProviderLoader {
16114
16201
  log(msg) {
16115
16202
  this.logFn(`[ProviderLoader] ${msg}`);
16116
16203
  }
16204
+ debugLog(msg) {
16205
+ LOG.debug("Provider", `[ProviderLoader] ${msg}`);
16206
+ }
16117
16207
  // ─── Public API ────────────────────────────────
16118
16208
  /**
16119
16209
  * User override root (~/.adhdev/providers by default).
@@ -16503,10 +16593,22 @@ var ProviderLoader = class _ProviderLoader {
16503
16593
  setMachineProviderEnabled(type, enabled) {
16504
16594
  return this.setMachineProviderConfig(type, { enabled });
16505
16595
  }
16596
+ getEffectiveProviderAvailability(type) {
16597
+ const providerType = this.resolveAlias(type);
16598
+ const availability = this.providerAvailability.get(providerType);
16599
+ if (availability) return availability;
16600
+ const machineConfig = this.getMachineProviderConfig(providerType);
16601
+ const lastDetection = machineConfig.lastDetection;
16602
+ if (!lastDetection) return void 0;
16603
+ return {
16604
+ installed: lastDetection.ok === true,
16605
+ detectedPath: typeof lastDetection.path === "string" && lastDetection.path.trim() ? lastDetection.path.trim() : null
16606
+ };
16607
+ }
16506
16608
  getMachineProviderStatus(type) {
16507
16609
  const providerType = this.resolveAlias(type);
16508
16610
  if (!this.isMachineProviderEnabled(providerType)) return "disabled";
16509
- const availability = this.providerAvailability.get(providerType);
16611
+ const availability = this.getEffectiveProviderAvailability(providerType);
16510
16612
  if (!availability) return "enabled_unchecked";
16511
16613
  return availability.installed ? "detected" : "not_detected";
16512
16614
  }
@@ -16634,7 +16736,7 @@ var ProviderLoader = class _ProviderLoader {
16634
16736
  }
16635
16737
  getAvailableProviderInfos() {
16636
16738
  return this.getAll().map((provider) => {
16637
- const availability = this.providerAvailability.get(provider.type);
16739
+ const availability = this.getEffectiveProviderAvailability(provider.type);
16638
16740
  const enabled = this.isMachineProviderEnabled(provider.type);
16639
16741
  const machineConfig = this.getMachineProviderConfig(provider.type);
16640
16742
  return {
@@ -16720,7 +16822,7 @@ var ProviderLoader = class _ProviderLoader {
16720
16822
  const loaded = this.loadScriptsFromDir(type, entry.scriptDir);
16721
16823
  if (loaded) {
16722
16824
  resolved.scripts = loaded;
16723
- this.log(` [compatibility] ${type} v${currentVersion} \u2192 ${entry.scriptDir}`);
16825
+ this.debugLog(` [compatibility] ${type} v${currentVersion} \u2192 ${entry.scriptDir}`);
16724
16826
  resolved._resolvedScriptDir = entry.scriptDir;
16725
16827
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
16726
16828
  if (providerDir) {
@@ -16736,7 +16838,7 @@ var ProviderLoader = class _ProviderLoader {
16736
16838
  const loaded = this.loadScriptsFromDir(type, base.defaultScriptDir);
16737
16839
  if (loaded) {
16738
16840
  resolved.scripts = loaded;
16739
- this.log(` [compatibility] ${type} v${currentVersion} \u2192 default: ${base.defaultScriptDir}`);
16841
+ this.debugLog(` [compatibility] ${type} v${currentVersion} \u2192 default: ${base.defaultScriptDir}`);
16740
16842
  resolved._resolvedScriptDir = base.defaultScriptDir;
16741
16843
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
16742
16844
  if (providerDir) {
@@ -16771,7 +16873,7 @@ var ProviderLoader = class _ProviderLoader {
16771
16873
  const loaded = this.loadScriptsFromDir(type, base.defaultScriptDir);
16772
16874
  if (loaded) {
16773
16875
  resolved.scripts = loaded;
16774
- this.log(` [compatibility] ${type} no version detected \u2192 default: ${base.defaultScriptDir}`);
16876
+ this.debugLog(` [compatibility] ${type} no version detected \u2192 default: ${base.defaultScriptDir}`);
16775
16877
  resolved._resolvedScriptDir = base.defaultScriptDir;
16776
16878
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
16777
16879
  if (providerDir) {