@adhdev/daemon-core 0.9.32 → 0.9.34

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.mjs CHANGED
@@ -1688,13 +1688,14 @@ function sliceFromOffset(text, start) {
1688
1688
  function hydrateCliParsedMessages(parsedMessages, options) {
1689
1689
  const { committedMessages, scope, lastOutputAt } = options;
1690
1690
  const referenceMessages = [...committedMessages];
1691
+ const referenceComparables = referenceMessages.map((message) => normalizeComparableMessageContent(message?.content || ""));
1691
1692
  const usedReferenceIndexes = /* @__PURE__ */ new Set();
1692
1693
  const now = options.now ?? Date.now();
1693
1694
  const findReferenceTimestamp = (role, content, parsedIndex) => {
1694
1695
  const normalizedContent = normalizeComparableMessageContent(content);
1695
1696
  if (!normalizedContent) return void 0;
1696
1697
  const sameIndex = referenceMessages[parsedIndex];
1697
- if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && normalizeComparableMessageContent(sameIndex.content) === normalizedContent && typeof sameIndex.timestamp === "number" && Number.isFinite(sameIndex.timestamp)) {
1698
+ if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && referenceComparables[parsedIndex] === normalizedContent && typeof sameIndex.timestamp === "number" && Number.isFinite(sameIndex.timestamp)) {
1698
1699
  usedReferenceIndexes.add(parsedIndex);
1699
1700
  return sameIndex.timestamp;
1700
1701
  }
@@ -1702,7 +1703,7 @@ function hydrateCliParsedMessages(parsedMessages, options) {
1702
1703
  if (usedReferenceIndexes.has(i)) continue;
1703
1704
  const candidate = referenceMessages[i];
1704
1705
  if (!candidate || candidate.role !== role) continue;
1705
- const candidateContent = normalizeComparableMessageContent(candidate.content);
1706
+ const candidateContent = referenceComparables[i];
1706
1707
  if (!candidateContent) continue;
1707
1708
  const exactMatch = candidateContent === normalizedContent;
1708
1709
  const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
@@ -2793,7 +2794,7 @@ var init_provider_cli_adapter = __esm({
2793
2794
  return;
2794
2795
  }
2795
2796
  if (this.currentTurnScope && !lastParsedAssistant) {
2796
- LOG.info(
2797
+ LOG.debug(
2797
2798
  "CLI",
2798
2799
  `[${this.cliType}] Settled without assistant: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 220)).slice(0, 260)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"}`
2799
2800
  );
@@ -3609,9 +3610,43 @@ var init_provider_cli_adapter = __esm({
3609
3610
  }
3610
3611
  armResponseTimeout() {
3611
3612
  if (this.responseTimeout) clearTimeout(this.responseTimeout);
3613
+ const timeoutMs = this.timeouts.maxResponse;
3614
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
3615
+ this.responseTimeout = null;
3616
+ return;
3617
+ }
3612
3618
  this.responseTimeout = setTimeout(() => {
3613
- if (this.isWaitingForResponse) this.finishResponse();
3614
- }, this.timeouts.maxResponse);
3619
+ this.responseTimeout = null;
3620
+ if (!this.isWaitingForResponse) return;
3621
+ const detectedStatusBeforeEval = this.runDetectStatus(this.recentOutputBuffer);
3622
+ this.recordTrace("response_timeout_check", {
3623
+ timeoutMs,
3624
+ detectedStatus: detectedStatusBeforeEval,
3625
+ currentStatus: this.currentStatus,
3626
+ isWaitingForResponse: this.isWaitingForResponse,
3627
+ hasActionableApproval: this.hasActionableApproval(),
3628
+ ...buildCliTraceParseSnapshot({
3629
+ accumulatedBuffer: this.accumulatedBuffer,
3630
+ accumulatedRawBuffer: this.accumulatedRawBuffer,
3631
+ responseBuffer: this.responseBuffer,
3632
+ partialResponse: this.responseBuffer,
3633
+ scope: this.currentTurnScope
3634
+ })
3635
+ });
3636
+ this.settledBuffer = this.recentOutputBuffer;
3637
+ this.evaluateSettled();
3638
+ if (this.isWaitingForResponse && !this.hasActionableApproval()) {
3639
+ const detectedStatusAfterEval = this.runDetectStatus(this.recentOutputBuffer);
3640
+ this.recordTrace("response_timeout_kept_open", {
3641
+ timeoutMs,
3642
+ detectedStatusBeforeEval,
3643
+ detectedStatusAfterEval,
3644
+ currentStatus: this.currentStatus,
3645
+ isWaitingForResponse: this.isWaitingForResponse
3646
+ });
3647
+ this.armResponseTimeout();
3648
+ }
3649
+ }, timeoutMs);
3615
3650
  }
3616
3651
  writeSubmitKeyForRetry(mode) {
3617
3652
  void this.writeToPty(this.sendKey).catch((error) => {
@@ -10356,6 +10391,26 @@ function toHistoryPersistedMessages(messages) {
10356
10391
  historyDedupKey: deriveHistoryDedupKey(message)
10357
10392
  }));
10358
10393
  }
10394
+ function findLastMessageIndexBySignature(messages, signature) {
10395
+ if (!signature) return -1;
10396
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
10397
+ if (getChatMessageSignature(messages[index]) === signature) {
10398
+ return index;
10399
+ }
10400
+ }
10401
+ return -1;
10402
+ }
10403
+ function buildBoundedTailSync(messages, cursor) {
10404
+ const totalMessages = messages.length;
10405
+ const tailMessages = cursor.tailLimit > 0 && totalMessages > cursor.tailLimit ? messages.slice(-cursor.tailLimit) : messages;
10406
+ return {
10407
+ syncMode: "full",
10408
+ replaceFrom: 0,
10409
+ messages: tailMessages,
10410
+ totalMessages,
10411
+ lastMessageSignature: getChatMessageSignature(messages[totalMessages - 1])
10412
+ };
10413
+ }
10359
10414
  function computeReadChatSync(messages, cursor) {
10360
10415
  const totalMessages = messages.length;
10361
10416
  const lastMessageSignature = getChatMessageSignature(messages[totalMessages - 1]);
@@ -10387,6 +10442,15 @@ function computeReadChatSync(messages, cursor) {
10387
10442
  lastMessageSignature
10388
10443
  };
10389
10444
  }
10445
+ if (cursor.tailLimit > 0 && knownSignature === lastMessageSignature) {
10446
+ return {
10447
+ syncMode: "noop",
10448
+ replaceFrom: totalMessages,
10449
+ messages: [],
10450
+ totalMessages,
10451
+ lastMessageSignature
10452
+ };
10453
+ }
10390
10454
  if (knownMessageCount < totalMessages) {
10391
10455
  const anchorSignature = getChatMessageSignature(messages[knownMessageCount - 1]);
10392
10456
  if (anchorSignature === knownSignature) {
@@ -10398,6 +10462,19 @@ function computeReadChatSync(messages, cursor) {
10398
10462
  lastMessageSignature
10399
10463
  };
10400
10464
  }
10465
+ if (cursor.tailLimit > 0) {
10466
+ const signatureIndex = findLastMessageIndexBySignature(messages, knownSignature);
10467
+ if (signatureIndex >= 0) {
10468
+ return {
10469
+ syncMode: "append",
10470
+ replaceFrom: knownMessageCount,
10471
+ messages: messages.slice(signatureIndex + 1),
10472
+ totalMessages,
10473
+ lastMessageSignature
10474
+ };
10475
+ }
10476
+ return buildBoundedTailSync(messages, cursor);
10477
+ }
10401
10478
  }
10402
10479
  const replaceFrom = Math.max(0, Math.min(knownMessageCount - 1, totalMessages));
10403
10480
  return {
@@ -13208,6 +13285,20 @@ var CliProviderInstance = class {
13208
13285
  getPresentationMode() {
13209
13286
  return this.presentationMode;
13210
13287
  }
13288
+ getHotChatSessionState() {
13289
+ const adapterStatus = this.adapter.getStatus();
13290
+ const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
13291
+ const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
13292
+ const runtime = this.adapter.getRuntimeMetadata();
13293
+ return {
13294
+ id: this.instanceId,
13295
+ status: visibleStatus,
13296
+ runtimeLifecycle: runtime?.lifecycle ?? null,
13297
+ runtimeSurfaceKind: runtime?.surfaceKind,
13298
+ runtimeRestoredFromStorage: runtime?.restoredFromStorage === true,
13299
+ runtimeRecoveryState: runtime?.recoveryState ?? null
13300
+ };
13301
+ }
13211
13302
  updateSettings(newSettings) {
13212
13303
  this.settings = { ...newSettings };
13213
13304
  this.adapter.updateRuntimeSettings?.(this.settings);
@@ -13363,6 +13454,15 @@ var CliProviderInstance = class {
13363
13454
  this.completedDebouncePending = { chatTitle, duration, timestamp: now };
13364
13455
  this.completedDebounceTimer = setTimeout(() => {
13365
13456
  if (this.completedDebouncePending) {
13457
+ const latestStatus = this.adapter.getStatus();
13458
+ const latestAutoApproveActive = latestStatus.status === "waiting_approval" && this.shouldAutoApprove();
13459
+ const latestVisibleStatus = latestAutoApproveActive ? "generating" : latestStatus.status;
13460
+ if (latestVisibleStatus !== "idle") {
13461
+ LOG.info("CLI", `[${this.type}] cancelled pending completed (resumed ${latestVisibleStatus})`);
13462
+ this.completedDebouncePending = null;
13463
+ this.completedDebounceTimer = null;
13464
+ return;
13465
+ }
13366
13466
  LOG.info("CLI", `[${this.type}] completed in ${this.completedDebouncePending.duration}s`);
13367
13467
  this.pushEvent({ event: "agent:generating_completed", ...this.completedDebouncePending });
13368
13468
  this.completedDebouncePending = null;
@@ -16403,10 +16503,22 @@ var ProviderLoader = class _ProviderLoader {
16403
16503
  setMachineProviderEnabled(type, enabled) {
16404
16504
  return this.setMachineProviderConfig(type, { enabled });
16405
16505
  }
16506
+ getEffectiveProviderAvailability(type) {
16507
+ const providerType = this.resolveAlias(type);
16508
+ const availability = this.providerAvailability.get(providerType);
16509
+ if (availability) return availability;
16510
+ const machineConfig = this.getMachineProviderConfig(providerType);
16511
+ const lastDetection = machineConfig.lastDetection;
16512
+ if (!lastDetection) return void 0;
16513
+ return {
16514
+ installed: lastDetection.ok === true,
16515
+ detectedPath: typeof lastDetection.path === "string" && lastDetection.path.trim() ? lastDetection.path.trim() : null
16516
+ };
16517
+ }
16406
16518
  getMachineProviderStatus(type) {
16407
16519
  const providerType = this.resolveAlias(type);
16408
16520
  if (!this.isMachineProviderEnabled(providerType)) return "disabled";
16409
- const availability = this.providerAvailability.get(providerType);
16521
+ const availability = this.getEffectiveProviderAvailability(providerType);
16410
16522
  if (!availability) return "enabled_unchecked";
16411
16523
  return availability.installed ? "detected" : "not_detected";
16412
16524
  }
@@ -16534,7 +16646,7 @@ var ProviderLoader = class _ProviderLoader {
16534
16646
  }
16535
16647
  getAvailableProviderInfos() {
16536
16648
  return this.getAll().map((provider) => {
16537
- const availability = this.providerAvailability.get(provider.type);
16649
+ const availability = this.getEffectiveProviderAvailability(provider.type);
16538
16650
  const enabled = this.isMachineProviderEnabled(provider.type);
16539
16651
  const machineConfig = this.getMachineProviderConfig(provider.type);
16540
16652
  return {
@@ -18362,6 +18474,51 @@ function killPid(pid) {
18362
18474
  return false;
18363
18475
  }
18364
18476
  }
18477
+ function getWindowsProcessCommandLine(pid) {
18478
+ const pidFilter = `ProcessId=${pid}`;
18479
+ try {
18480
+ const psOut = execFileSync2("powershell.exe", [
18481
+ "-NoProfile",
18482
+ "-NonInteractive",
18483
+ "-ExecutionPolicy",
18484
+ "Bypass",
18485
+ "-Command",
18486
+ `(Get-CimInstance Win32_Process -Filter "${pidFilter}").CommandLine`
18487
+ ], { encoding: "utf8", timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).trim();
18488
+ if (psOut) return psOut;
18489
+ } catch {
18490
+ }
18491
+ try {
18492
+ const wmicOut = execFileSync2("wmic", [
18493
+ "process",
18494
+ "where",
18495
+ pidFilter,
18496
+ "get",
18497
+ "CommandLine"
18498
+ ], { encoding: "utf8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }).trim();
18499
+ if (wmicOut) return wmicOut;
18500
+ } catch {
18501
+ }
18502
+ return null;
18503
+ }
18504
+ function getProcessCommandLine(pid) {
18505
+ if (!Number.isFinite(pid) || pid <= 0) return null;
18506
+ if (process.platform === "win32") return getWindowsProcessCommandLine(pid);
18507
+ try {
18508
+ const text = execFileSync2("ps", ["-o", "command=", "-p", String(pid)], {
18509
+ encoding: "utf8",
18510
+ timeout: 3e3,
18511
+ stdio: ["ignore", "pipe", "ignore"]
18512
+ }).trim();
18513
+ return text || null;
18514
+ } catch {
18515
+ return null;
18516
+ }
18517
+ }
18518
+ function isManagedSessionHostPid(pid) {
18519
+ const commandLine = getProcessCommandLine(pid);
18520
+ return !!commandLine && /session-host-daemon/i.test(commandLine);
18521
+ }
18365
18522
  async function waitForPidExit(pid, timeoutMs) {
18366
18523
  const start = Date.now();
18367
18524
  while (Date.now() - start < timeoutMs) {
@@ -18378,7 +18535,7 @@ function stopSessionHostProcesses(appName) {
18378
18535
  try {
18379
18536
  if (fs8.existsSync(pidFile)) {
18380
18537
  const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
18381
- if (Number.isFinite(pid)) {
18538
+ if (Number.isFinite(pid) && pid !== process.pid && isManagedSessionHostPid(pid)) {
18382
18539
  killPid(pid);
18383
18540
  }
18384
18541
  }
@@ -18389,18 +18546,6 @@ function stopSessionHostProcesses(appName) {
18389
18546
  } catch {
18390
18547
  }
18391
18548
  }
18392
- if (process.platform !== "win32") {
18393
- try {
18394
- const raw = execFileSync2("pgrep", ["-f", "session-host-daemon"], { encoding: "utf8" }).trim();
18395
- for (const line of raw.split("\n")) {
18396
- const pid = Number.parseInt(line.trim(), 10);
18397
- if (Number.isFinite(pid)) {
18398
- killPid(pid);
18399
- }
18400
- }
18401
- } catch {
18402
- }
18403
- }
18404
18549
  }
18405
18550
  function removeDaemonPidFile() {
18406
18551
  const pidFile = path16.join(os17.homedir(), ".adhdev", "daemon.pid");
@@ -20635,6 +20780,20 @@ function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
20635
20780
 
20636
20781
  // src/providers/provider-instance-manager.ts
20637
20782
  init_logger();
20783
+ function projectHotChatSessionStatesFromProviderState(state) {
20784
+ const project = (item) => ({
20785
+ id: item.instanceId,
20786
+ status: item.activeChat?.status || item.status,
20787
+ runtimeLifecycle: item.runtime?.lifecycle ?? null,
20788
+ runtimeSurfaceKind: item.runtime?.surfaceKind,
20789
+ runtimeRestoredFromStorage: item.runtime?.restoredFromStorage === true,
20790
+ runtimeRecoveryState: item.runtime?.recoveryState ?? null
20791
+ });
20792
+ if (state.category === "ide") {
20793
+ return [project(state), ...state.extensions.map(project)];
20794
+ }
20795
+ return [project(state)];
20796
+ }
20638
20797
  var ProviderInstanceManager = class {
20639
20798
  instances = /* @__PURE__ */ new Map();
20640
20799
  tickTimer = null;
@@ -20730,6 +20889,27 @@ var ProviderInstanceManager = class {
20730
20889
  }
20731
20890
  return states;
20732
20891
  }
20892
+ collectHotChatSessionStates() {
20893
+ const sessions = [];
20894
+ for (const [id, instance] of this.instances) {
20895
+ try {
20896
+ const projected = instance.getHotChatSessionState?.();
20897
+ if (Array.isArray(projected)) {
20898
+ sessions.push(...projected.filter((session) => !!session?.id));
20899
+ continue;
20900
+ }
20901
+ if (projected?.id) {
20902
+ sessions.push(projected);
20903
+ continue;
20904
+ }
20905
+ const state = instance.getState();
20906
+ sessions.push(...projectHotChatSessionStatesFromProviderState(state));
20907
+ } catch (e) {
20908
+ LOG.warn("InstanceMgr", `[InstanceManager] Failed to collect hot chat metadata from ${id}: ${e.message}`);
20909
+ }
20910
+ }
20911
+ return sessions;
20912
+ }
20733
20913
  /**
20734
20914
  * Per-category status collect
20735
20915
  */