@adhdev/daemon-core 0.9.12 → 0.9.14

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
@@ -3393,6 +3393,29 @@ var init_provider_cli_adapter = __esm({
3393
3393
  }
3394
3394
  await this.sendMessage(promptText);
3395
3395
  }
3396
+ async writeToPty(data) {
3397
+ if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
3398
+ await this.ptyProcess.write(data);
3399
+ }
3400
+ resetPendingSendState(reason) {
3401
+ this.isWaitingForResponse = false;
3402
+ this.responseBuffer = "";
3403
+ this.currentTurnScope = null;
3404
+ this.submitPendingUntil = 0;
3405
+ this.clearIdleFinishCandidate(reason);
3406
+ if (this.responseTimeout) {
3407
+ clearTimeout(this.responseTimeout);
3408
+ this.responseTimeout = null;
3409
+ }
3410
+ if (this.submitRetryTimer) {
3411
+ clearTimeout(this.submitRetryTimer);
3412
+ this.submitRetryTimer = null;
3413
+ }
3414
+ if (this.finishRetryTimer) {
3415
+ clearTimeout(this.finishRetryTimer);
3416
+ this.finishRetryTimer = null;
3417
+ }
3418
+ }
3396
3419
  async sendMessage(text) {
3397
3420
  if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
3398
3421
  const allowInputDuringGeneration = this.provider.allowInputDuringGeneration === true;
@@ -3487,19 +3510,29 @@ var init_provider_cli_adapter = __esm({
3487
3510
  if (this.isWaitingForResponse) this.finishResponse();
3488
3511
  }, this.timeouts.maxResponse);
3489
3512
  };
3490
- await new Promise((resolve12) => {
3513
+ await new Promise((resolve12, reject) => {
3491
3514
  let resolved = false;
3492
3515
  const resolveOnce = () => {
3493
3516
  if (resolved) return;
3494
3517
  resolved = true;
3495
3518
  resolve12();
3496
3519
  };
3520
+ const rejectOnce = (error) => {
3521
+ if (resolved) return;
3522
+ this.resetPendingSendState("send_write_failed");
3523
+ resolved = true;
3524
+ reject(error);
3525
+ };
3526
+ const writeRetryKey = (mode) => {
3527
+ void this.writeToPty(this.sendKey).catch((error) => {
3528
+ LOG.warn("CLI", `[${this.cliType}] ${mode} write failed: ${error?.message || error}`);
3529
+ });
3530
+ };
3497
3531
  const submit = () => {
3498
3532
  if (!this.ptyProcess) {
3499
3533
  resolveOnce();
3500
3534
  return;
3501
3535
  }
3502
- commitUserTurn();
3503
3536
  this.submitPendingUntil = 0;
3504
3537
  const screenText = this.terminalScreen.getText();
3505
3538
  this.recordTrace("submit_write", {
@@ -3507,7 +3540,6 @@ var init_provider_cli_adapter = __esm({
3507
3540
  sendKey: this.sendKey,
3508
3541
  screenText: summarizeCliTraceText(screenText, 500)
3509
3542
  });
3510
- this.ptyProcess.write(this.sendKey);
3511
3543
  const retrySubmitIfStuck = (attempt) => {
3512
3544
  this.submitRetryTimer = null;
3513
3545
  if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
@@ -3527,19 +3559,21 @@ var init_provider_cli_adapter = __esm({
3527
3559
  sendKey: this.sendKey,
3528
3560
  screenText: summarizeCliTraceText(screenText2, 500)
3529
3561
  });
3530
- this.ptyProcess.write(this.sendKey);
3562
+ writeRetryKey("submit_retry");
3531
3563
  if (attempt >= 3) {
3532
3564
  this.submitRetryUsed = true;
3533
3565
  return;
3534
3566
  }
3535
3567
  this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(attempt + 1), retryDelayMs);
3536
3568
  };
3537
- this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(1), retryDelayMs);
3538
- startResponseTimeout();
3539
- resolveOnce();
3569
+ void this.writeToPty(this.sendKey).then(() => {
3570
+ commitUserTurn();
3571
+ this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(1), retryDelayMs);
3572
+ startResponseTimeout();
3573
+ resolveOnce();
3574
+ }, rejectOnce);
3540
3575
  };
3541
3576
  if (this.submitStrategy === "immediate") {
3542
- commitUserTurn();
3543
3577
  this.submitPendingUntil = 0;
3544
3578
  this.recordTrace("submit_write", {
3545
3579
  mode: "immediate",
@@ -3547,37 +3581,38 @@ var init_provider_cli_adapter = __esm({
3547
3581
  sendKey: this.sendKey,
3548
3582
  screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
3549
3583
  });
3550
- this.ptyProcess.write(text + this.sendKey);
3551
- this.submitRetryTimer = setTimeout(() => {
3552
- this.submitRetryTimer = null;
3553
- if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
3554
- if (this.currentStatus === "waiting_approval") return;
3555
- if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
3556
- const screenText = this.terminalScreen.getText();
3557
- if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
3558
- const liveApproval = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
3559
- if (liveApproval) return;
3560
- const liveStatus = this.runDetectStatus(screenText) || this.runDetectStatus(this.recentOutputBuffer);
3561
- if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
3562
- LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
3563
- this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
3564
- this.recordTrace("submit_write", {
3565
- mode: "immediate_retry",
3566
- attempt: 1,
3567
- sendKey: this.sendKey,
3568
- screenText: summarizeCliTraceText(screenText, 500)
3569
- });
3570
- this.ptyProcess.write(this.sendKey);
3571
- this.submitRetryUsed = true;
3572
- }, retryDelayMs);
3573
- startResponseTimeout();
3574
- resolveOnce();
3584
+ void this.writeToPty(text + this.sendKey).then(() => {
3585
+ commitUserTurn();
3586
+ this.submitRetryTimer = setTimeout(() => {
3587
+ this.submitRetryTimer = null;
3588
+ if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
3589
+ if (this.currentStatus === "waiting_approval") return;
3590
+ if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
3591
+ const screenText = this.terminalScreen.getText();
3592
+ if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
3593
+ const liveApproval = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
3594
+ if (liveApproval) return;
3595
+ const liveStatus = this.runDetectStatus(screenText) || this.runDetectStatus(this.recentOutputBuffer);
3596
+ if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
3597
+ LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
3598
+ this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
3599
+ this.recordTrace("submit_write", {
3600
+ mode: "immediate_retry",
3601
+ attempt: 1,
3602
+ sendKey: this.sendKey,
3603
+ screenText: summarizeCliTraceText(screenText, 500)
3604
+ });
3605
+ writeRetryKey("immediate_retry");
3606
+ this.submitRetryUsed = true;
3607
+ }, retryDelayMs);
3608
+ startResponseTimeout();
3609
+ resolveOnce();
3610
+ }, rejectOnce);
3575
3611
  return;
3576
3612
  }
3577
3613
  if (submitDelayMs > 0) {
3578
3614
  this.submitPendingUntil = Date.now() + submitDelayMs;
3579
3615
  }
3580
- this.ptyProcess.write(text);
3581
3616
  this.recordTrace("submit_write", {
3582
3617
  mode: "type_then_submit",
3583
3618
  text: summarizeCliTraceText(text, 500),
@@ -3614,7 +3649,7 @@ var init_provider_cli_adapter = __esm({
3614
3649
  }
3615
3650
  setTimeout(waitForEchoAndSubmit, 50);
3616
3651
  };
3617
- waitForEchoAndSubmit();
3652
+ void this.writeToPty(text).then(() => waitForEchoAndSubmit(), rejectOnce);
3618
3653
  });
3619
3654
  }
3620
3655
  getPartialResponse() {
@@ -3769,12 +3804,12 @@ var init_provider_cli_adapter = __esm({
3769
3804
  isReady() {
3770
3805
  return this.ready;
3771
3806
  }
3772
- writeRaw(data) {
3807
+ async writeRaw(data) {
3773
3808
  this.recordTrace("write_raw", {
3774
3809
  keys: JSON.stringify(data),
3775
3810
  length: data.length
3776
3811
  });
3777
- this.ptyProcess?.write(data);
3812
+ await this.writeToPty(data);
3778
3813
  }
3779
3814
  resolveModal(buttonIndex) {
3780
3815
  let modal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
@@ -11626,14 +11661,14 @@ async function handleOpenPanel(h, args) {
11626
11661
  success: revealState.visible || focusState.focused
11627
11662
  };
11628
11663
  }
11629
- function handlePtyInput(h, args) {
11664
+ async function handlePtyInput(h, args) {
11630
11665
  const { cliType, data, targetSessionId } = args || {};
11631
11666
  if (!data) return { success: false, error: "data required" };
11632
11667
  const adapter = h.getCliAdapter(targetSessionId || cliType);
11633
11668
  if (!adapter || typeof adapter.writeRaw !== "function") {
11634
11669
  return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
11635
11670
  }
11636
- adapter.writeRaw(data);
11671
+ await adapter.writeRaw(data);
11637
11672
  return { success: true };
11638
11673
  }
11639
11674
  function handlePtyResize(_h, args) {
@@ -11810,7 +11845,7 @@ async function executeProviderScript(h, args, scriptName) {
11810
11845
  if (cliCommand?.type === "send_message" && cliCommand.text) {
11811
11846
  await adapter.sendMessage(cliCommand.text);
11812
11847
  } else if (cliCommand?.type === "pty_write" && cliCommand.text && adapter.writeRaw) {
11813
- adapter.writeRaw(cliCommand.text + "\r");
11848
+ await adapter.writeRaw(cliCommand.text + "\r");
11814
11849
  }
11815
11850
  applyProviderPatch(h, args, parsed.payload);
11816
11851
  return {
@@ -12962,7 +12997,7 @@ var CliProviderInstance = class {
12962
12997
  if (cliCommand?.type === "send_message" && cliCommand.text) {
12963
12998
  await this.adapter.sendMessage(cliCommand.text);
12964
12999
  } else if (cliCommand?.type === "pty_write" && cliCommand.text) {
12965
- this.adapter.writeRaw(cliCommand.text + "\r");
13000
+ await this.adapter.writeRaw(cliCommand.text + "\r");
12966
13001
  }
12967
13002
  this.applyProviderResponse(parsed.payload, { phase: "immediate" });
12968
13003
  }
@@ -18607,10 +18642,14 @@ var DaemonCommandRouter = class {
18607
18642
  currentInstalled = parsed?.dependencies?.[pkgName]?.version || null;
18608
18643
  } catch {
18609
18644
  }
18610
- if (currentInstalled === latest) {
18645
+ const runningVersion = typeof this.deps.statusVersion === "string" ? this.deps.statusVersion.trim().replace(/^v/, "") : null;
18646
+ if (currentInstalled === latest && runningVersion === latest) {
18611
18647
  LOG.info("Upgrade", `Already on latest version v${latest}; skipping install`);
18612
18648
  return { success: true, upgraded: false, alreadyLatest: true, version: latest };
18613
18649
  }
18650
+ if (currentInstalled === latest && runningVersion && runningVersion !== latest) {
18651
+ LOG.info("Upgrade", `Installed package is v${latest}, but running daemon is v${runningVersion}; scheduling restart`);
18652
+ }
18614
18653
  spawnDetachedDaemonUpgradeHelper({
18615
18654
  packageName: pkgName,
18616
18655
  targetVersion: latest,
@@ -22716,7 +22755,7 @@ async function handleCliRaw(ctx, req, res) {
22716
22755
  }
22717
22756
  try {
22718
22757
  if (typeof adapter.writeRaw === "function") {
22719
- adapter.writeRaw(keys);
22758
+ await adapter.writeRaw(keys);
22720
22759
  ctx.json(res, 200, { sent: true, type: target.type, instanceId: target.instanceId, keysLength: keys.length });
22721
22760
  } else {
22722
22761
  ctx.json(res, 400, { error: "writeRaw not available on this adapter" });
@@ -25645,7 +25684,7 @@ var SessionHostRuntimeTransport = class {
25645
25684
  this.exitCallbacks.add(callback);
25646
25685
  }
25647
25686
  write(data) {
25648
- this.enqueue(async () => {
25687
+ return this.enqueue(async () => {
25649
25688
  let response = await this.client.request({
25650
25689
  type: "send_input",
25651
25690
  payload: {
@@ -25947,9 +25986,11 @@ var SessionHostRuntimeTransport = class {
25947
25986
  };
25948
25987
  }
25949
25988
  enqueue(action) {
25950
- this.operationChain = this.operationChain.then(() => this.ready).then(action).catch((error) => {
25989
+ const operation = this.operationChain.then(() => this.ready).then(action);
25990
+ this.operationChain = operation.catch((error) => {
25951
25991
  LOG.warn("CLI", `[session-host:${this.options.runtimeId}] ${error?.message || error}`);
25952
25992
  });
25993
+ return operation;
25953
25994
  }
25954
25995
  async closeClient(destroy = false) {
25955
25996
  if (this.closed) return;