@adhdev/daemon-core 0.9.33 → 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.
@@ -27,5 +27,6 @@ export declare function buildPinnedGlobalInstallCommand(options: {
27
27
  currentCliPath?: string;
28
28
  nodeExecutable?: string;
29
29
  }): PinnedGlobalInstallCommand;
30
+ export declare function stopSessionHostProcesses(appName: string): void;
30
31
  export declare function spawnDetachedDaemonUpgradeHelper(payload: DaemonUpgradeHelperPayload): void;
31
32
  export declare function maybeRunDaemonUpgradeHelperFromEnv(): Promise<boolean>;
package/dist/index.js CHANGED
@@ -1690,13 +1690,14 @@ function sliceFromOffset(text, start) {
1690
1690
  function hydrateCliParsedMessages(parsedMessages, options) {
1691
1691
  const { committedMessages, scope, lastOutputAt } = options;
1692
1692
  const referenceMessages = [...committedMessages];
1693
+ const referenceComparables = referenceMessages.map((message) => normalizeComparableMessageContent(message?.content || ""));
1693
1694
  const usedReferenceIndexes = /* @__PURE__ */ new Set();
1694
1695
  const now = options.now ?? Date.now();
1695
1696
  const findReferenceTimestamp = (role, content, parsedIndex) => {
1696
1697
  const normalizedContent = normalizeComparableMessageContent(content);
1697
1698
  if (!normalizedContent) return void 0;
1698
1699
  const sameIndex = referenceMessages[parsedIndex];
1699
- if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && normalizeComparableMessageContent(sameIndex.content) === normalizedContent && typeof sameIndex.timestamp === "number" && Number.isFinite(sameIndex.timestamp)) {
1700
+ if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && referenceComparables[parsedIndex] === normalizedContent && typeof sameIndex.timestamp === "number" && Number.isFinite(sameIndex.timestamp)) {
1700
1701
  usedReferenceIndexes.add(parsedIndex);
1701
1702
  return sameIndex.timestamp;
1702
1703
  }
@@ -1704,7 +1705,7 @@ function hydrateCliParsedMessages(parsedMessages, options) {
1704
1705
  if (usedReferenceIndexes.has(i)) continue;
1705
1706
  const candidate = referenceMessages[i];
1706
1707
  if (!candidate || candidate.role !== role) continue;
1707
- const candidateContent = normalizeComparableMessageContent(candidate.content);
1708
+ const candidateContent = referenceComparables[i];
1708
1709
  if (!candidateContent) continue;
1709
1710
  const exactMatch = candidateContent === normalizedContent;
1710
1711
  const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
@@ -2796,7 +2797,7 @@ var init_provider_cli_adapter = __esm({
2796
2797
  return;
2797
2798
  }
2798
2799
  if (this.currentTurnScope && !lastParsedAssistant) {
2799
- LOG.info(
2800
+ LOG.debug(
2800
2801
  "CLI",
2801
2802
  `[${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 || "-"}`
2802
2803
  );
@@ -3612,9 +3613,43 @@ var init_provider_cli_adapter = __esm({
3612
3613
  }
3613
3614
  armResponseTimeout() {
3614
3615
  if (this.responseTimeout) clearTimeout(this.responseTimeout);
3616
+ const timeoutMs = this.timeouts.maxResponse;
3617
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
3618
+ this.responseTimeout = null;
3619
+ return;
3620
+ }
3615
3621
  this.responseTimeout = setTimeout(() => {
3616
- if (this.isWaitingForResponse) this.finishResponse();
3617
- }, this.timeouts.maxResponse);
3622
+ this.responseTimeout = null;
3623
+ if (!this.isWaitingForResponse) return;
3624
+ const detectedStatusBeforeEval = this.runDetectStatus(this.recentOutputBuffer);
3625
+ this.recordTrace("response_timeout_check", {
3626
+ timeoutMs,
3627
+ detectedStatus: detectedStatusBeforeEval,
3628
+ currentStatus: this.currentStatus,
3629
+ isWaitingForResponse: this.isWaitingForResponse,
3630
+ hasActionableApproval: this.hasActionableApproval(),
3631
+ ...buildCliTraceParseSnapshot({
3632
+ accumulatedBuffer: this.accumulatedBuffer,
3633
+ accumulatedRawBuffer: this.accumulatedRawBuffer,
3634
+ responseBuffer: this.responseBuffer,
3635
+ partialResponse: this.responseBuffer,
3636
+ scope: this.currentTurnScope
3637
+ })
3638
+ });
3639
+ this.settledBuffer = this.recentOutputBuffer;
3640
+ this.evaluateSettled();
3641
+ if (this.isWaitingForResponse && !this.hasActionableApproval()) {
3642
+ const detectedStatusAfterEval = this.runDetectStatus(this.recentOutputBuffer);
3643
+ this.recordTrace("response_timeout_kept_open", {
3644
+ timeoutMs,
3645
+ detectedStatusBeforeEval,
3646
+ detectedStatusAfterEval,
3647
+ currentStatus: this.currentStatus,
3648
+ isWaitingForResponse: this.isWaitingForResponse
3649
+ });
3650
+ this.armResponseTimeout();
3651
+ }
3652
+ }, timeoutMs);
3618
3653
  }
3619
3654
  writeSubmitKeyForRetry(mode) {
3620
3655
  void this.writeToPty(this.sendKey).catch((error) => {
@@ -13403,6 +13438,20 @@ var CliProviderInstance = class {
13403
13438
  getPresentationMode() {
13404
13439
  return this.presentationMode;
13405
13440
  }
13441
+ getHotChatSessionState() {
13442
+ const adapterStatus = this.adapter.getStatus();
13443
+ const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
13444
+ const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
13445
+ const runtime = this.adapter.getRuntimeMetadata();
13446
+ return {
13447
+ id: this.instanceId,
13448
+ status: visibleStatus,
13449
+ runtimeLifecycle: runtime?.lifecycle ?? null,
13450
+ runtimeSurfaceKind: runtime?.surfaceKind,
13451
+ runtimeRestoredFromStorage: runtime?.restoredFromStorage === true,
13452
+ runtimeRecoveryState: runtime?.recoveryState ?? null
13453
+ };
13454
+ }
13406
13455
  updateSettings(newSettings) {
13407
13456
  this.settings = { ...newSettings };
13408
13457
  this.adapter.updateRuntimeSettings?.(this.settings);
@@ -13558,6 +13607,15 @@ var CliProviderInstance = class {
13558
13607
  this.completedDebouncePending = { chatTitle, duration, timestamp: now };
13559
13608
  this.completedDebounceTimer = setTimeout(() => {
13560
13609
  if (this.completedDebouncePending) {
13610
+ const latestStatus = this.adapter.getStatus();
13611
+ const latestAutoApproveActive = latestStatus.status === "waiting_approval" && this.shouldAutoApprove();
13612
+ const latestVisibleStatus = latestAutoApproveActive ? "generating" : latestStatus.status;
13613
+ if (latestVisibleStatus !== "idle") {
13614
+ LOG.info("CLI", `[${this.type}] cancelled pending completed (resumed ${latestVisibleStatus})`);
13615
+ this.completedDebouncePending = null;
13616
+ this.completedDebounceTimer = null;
13617
+ return;
13618
+ }
13561
13619
  LOG.info("CLI", `[${this.type}] completed in ${this.completedDebouncePending.duration}s`);
13562
13620
  this.pushEvent({ event: "agent:generating_completed", ...this.completedDebouncePending });
13563
13621
  this.completedDebouncePending = null;
@@ -18564,6 +18622,51 @@ function killPid(pid) {
18564
18622
  return false;
18565
18623
  }
18566
18624
  }
18625
+ function getWindowsProcessCommandLine(pid) {
18626
+ const pidFilter = `ProcessId=${pid}`;
18627
+ try {
18628
+ const psOut = (0, import_child_process8.execFileSync)("powershell.exe", [
18629
+ "-NoProfile",
18630
+ "-NonInteractive",
18631
+ "-ExecutionPolicy",
18632
+ "Bypass",
18633
+ "-Command",
18634
+ `(Get-CimInstance Win32_Process -Filter "${pidFilter}").CommandLine`
18635
+ ], { encoding: "utf8", timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }).trim();
18636
+ if (psOut) return psOut;
18637
+ } catch {
18638
+ }
18639
+ try {
18640
+ const wmicOut = (0, import_child_process8.execFileSync)("wmic", [
18641
+ "process",
18642
+ "where",
18643
+ pidFilter,
18644
+ "get",
18645
+ "CommandLine"
18646
+ ], { encoding: "utf8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }).trim();
18647
+ if (wmicOut) return wmicOut;
18648
+ } catch {
18649
+ }
18650
+ return null;
18651
+ }
18652
+ function getProcessCommandLine(pid) {
18653
+ if (!Number.isFinite(pid) || pid <= 0) return null;
18654
+ if (process.platform === "win32") return getWindowsProcessCommandLine(pid);
18655
+ try {
18656
+ const text = (0, import_child_process8.execFileSync)("ps", ["-o", "command=", "-p", String(pid)], {
18657
+ encoding: "utf8",
18658
+ timeout: 3e3,
18659
+ stdio: ["ignore", "pipe", "ignore"]
18660
+ }).trim();
18661
+ return text || null;
18662
+ } catch {
18663
+ return null;
18664
+ }
18665
+ }
18666
+ function isManagedSessionHostPid(pid) {
18667
+ const commandLine = getProcessCommandLine(pid);
18668
+ return !!commandLine && /session-host-daemon/i.test(commandLine);
18669
+ }
18567
18670
  async function waitForPidExit(pid, timeoutMs) {
18568
18671
  const start = Date.now();
18569
18672
  while (Date.now() - start < timeoutMs) {
@@ -18580,7 +18683,7 @@ function stopSessionHostProcesses(appName) {
18580
18683
  try {
18581
18684
  if (fs8.existsSync(pidFile)) {
18582
18685
  const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
18583
- if (Number.isFinite(pid)) {
18686
+ if (Number.isFinite(pid) && pid !== process.pid && isManagedSessionHostPid(pid)) {
18584
18687
  killPid(pid);
18585
18688
  }
18586
18689
  }
@@ -18591,18 +18694,6 @@ function stopSessionHostProcesses(appName) {
18591
18694
  } catch {
18592
18695
  }
18593
18696
  }
18594
- if (process.platform !== "win32") {
18595
- try {
18596
- const raw = (0, import_child_process8.execFileSync)("pgrep", ["-f", "session-host-daemon"], { encoding: "utf8" }).trim();
18597
- for (const line of raw.split("\n")) {
18598
- const pid = Number.parseInt(line.trim(), 10);
18599
- if (Number.isFinite(pid)) {
18600
- killPid(pid);
18601
- }
18602
- }
18603
- } catch {
18604
- }
18605
- }
18606
18697
  }
18607
18698
  function removeDaemonPidFile() {
18608
18699
  const pidFile = path16.join(os17.homedir(), ".adhdev", "daemon.pid");
@@ -20837,6 +20928,20 @@ function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
20837
20928
 
20838
20929
  // src/providers/provider-instance-manager.ts
20839
20930
  init_logger();
20931
+ function projectHotChatSessionStatesFromProviderState(state) {
20932
+ const project = (item) => ({
20933
+ id: item.instanceId,
20934
+ status: item.activeChat?.status || item.status,
20935
+ runtimeLifecycle: item.runtime?.lifecycle ?? null,
20936
+ runtimeSurfaceKind: item.runtime?.surfaceKind,
20937
+ runtimeRestoredFromStorage: item.runtime?.restoredFromStorage === true,
20938
+ runtimeRecoveryState: item.runtime?.recoveryState ?? null
20939
+ });
20940
+ if (state.category === "ide") {
20941
+ return [project(state), ...state.extensions.map(project)];
20942
+ }
20943
+ return [project(state)];
20944
+ }
20840
20945
  var ProviderInstanceManager = class {
20841
20946
  instances = /* @__PURE__ */ new Map();
20842
20947
  tickTimer = null;
@@ -20932,6 +21037,27 @@ var ProviderInstanceManager = class {
20932
21037
  }
20933
21038
  return states;
20934
21039
  }
21040
+ collectHotChatSessionStates() {
21041
+ const sessions = [];
21042
+ for (const [id, instance] of this.instances) {
21043
+ try {
21044
+ const projected = instance.getHotChatSessionState?.();
21045
+ if (Array.isArray(projected)) {
21046
+ sessions.push(...projected.filter((session) => !!session?.id));
21047
+ continue;
21048
+ }
21049
+ if (projected?.id) {
21050
+ sessions.push(projected);
21051
+ continue;
21052
+ }
21053
+ const state = instance.getState();
21054
+ sessions.push(...projectHotChatSessionStatesFromProviderState(state));
21055
+ } catch (e) {
21056
+ LOG.warn("InstanceMgr", `[InstanceManager] Failed to collect hot chat metadata from ${id}: ${e.message}`);
21057
+ }
21058
+ }
21059
+ return sessions;
21060
+ }
20935
21061
  /**
20936
21062
  * Per-category status collect
20937
21063
  */