adhdev 0.6.56 → 0.6.57

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.js CHANGED
@@ -16284,6 +16284,38 @@ function shSingleQuote(arg) {
16284
16284
  if (/^[a-zA-Z0-9@%_+=:,./-]+$/.test(arg)) return arg;
16285
16285
  return `'${arg.replace(/'/g, `'\\''`)}'`;
16286
16286
  }
16287
+ function estimatePromptDisplayLines(text, cols = 100) {
16288
+ const normalized = String(text || "").replace(/\r/g, "");
16289
+ if (!normalized) return 1;
16290
+ return normalized.split("\n").reduce((sum, line) => sum + Math.max(1, Math.ceil(Math.max(1, line.length) / cols)), 0);
16291
+ }
16292
+ function extractPromptRetrySnippet(text) {
16293
+ const lines = String(text || "").replace(/\r/g, "").split("\n").map((line) => line.trim()).filter(Boolean);
16294
+ const candidate = lines[lines.length - 1] || lines[0] || "";
16295
+ return candidate.slice(-120);
16296
+ }
16297
+ function normalizePromptText(text) {
16298
+ return String(text || "").replace(/\s+/g, " ").trim();
16299
+ }
16300
+ function compactPromptText(text) {
16301
+ return String(text || "").replace(/\s+/g, "").trim();
16302
+ }
16303
+ function promptLikelyVisible(screenText, promptSnippet) {
16304
+ const snippet = normalizePromptText(promptSnippet);
16305
+ if (!snippet) return false;
16306
+ const normalizedScreen = normalizePromptText(screenText);
16307
+ if (normalizedScreen.includes(snippet)) return true;
16308
+ const compactScreen = compactPromptText(screenText);
16309
+ const compactSnippet = compactPromptText(promptSnippet);
16310
+ if (compactSnippet && compactScreen.includes(compactSnippet)) return true;
16311
+ const tokens = snippet.split(/[^A-Za-z0-9_.:/-]+/).map((token) => token.trim()).filter((token) => token.length >= 4);
16312
+ if (tokens.length === 0) return false;
16313
+ const required2 = Math.min(tokens.length, 3);
16314
+ const matched = tokens.filter(
16315
+ (token) => normalizedScreen.includes(token) || compactScreen.includes(compactPromptText(token))
16316
+ ).length;
16317
+ return matched >= required2;
16318
+ }
16287
16319
  function parsePatternEntry(x) {
16288
16320
  if (x instanceof RegExp) return x;
16289
16321
  if (x && typeof x === "object" && typeof x.source === "string") {
@@ -16403,6 +16435,11 @@ var init_provider_cli_adapter = __esm({
16403
16435
  settleTimer = null;
16404
16436
  settledBuffer = "";
16405
16437
  submitPendingUntil = 0;
16438
+ responseSettleIgnoreUntil = 0;
16439
+ responseEpoch = 0;
16440
+ submitRetryTimer = null;
16441
+ submitRetryUsed = false;
16442
+ submitRetryPromptSnippet = "";
16406
16443
  // Resize redraw suppression
16407
16444
  resizeSuppressUntil = 0;
16408
16445
  // Debug: status transition history
@@ -16526,7 +16563,7 @@ var init_provider_cli_adapter = __esm({
16526
16563
  this.startupParseGate = true;
16527
16564
  this.startupBuffer = "";
16528
16565
  this.terminalScreen.reset(40, 120);
16529
- this.ready = true;
16566
+ this.ready = false;
16530
16567
  this.setStatus("idle", "pty_ready");
16531
16568
  this.onStatusChange?.();
16532
16569
  }
@@ -16571,7 +16608,9 @@ var init_provider_cli_adapter = __esm({
16571
16608
  const isReady = scriptStatus === "idle" || elapsed > 8e3 || bufCap;
16572
16609
  if (isReady) {
16573
16610
  this.startupParseGate = false;
16611
+ this.ready = true;
16574
16612
  LOG.info("CLI", `[${this.cliType}] Startup gate end (${elapsed}ms, scriptStatus=${scriptStatus})`);
16613
+ this.onStatusChange?.();
16575
16614
  } else {
16576
16615
  return;
16577
16616
  }
@@ -16580,19 +16619,45 @@ var init_provider_cli_adapter = __esm({
16580
16619
  }
16581
16620
  scheduleSettle() {
16582
16621
  if (this.settleTimer) clearTimeout(this.settleTimer);
16622
+ const settleEpoch = this.responseEpoch;
16583
16623
  const delay = Math.max(
16584
16624
  this.timeouts.outputSettle,
16585
16625
  this.submitPendingUntil > Date.now() ? this.submitPendingUntil - Date.now() + this.timeouts.outputSettle : 0
16586
16626
  );
16587
16627
  this.settleTimer = setTimeout(() => {
16588
16628
  this.settleTimer = null;
16629
+ if (settleEpoch !== this.responseEpoch) return;
16589
16630
  this.settledBuffer = this.recentOutputBuffer;
16590
16631
  this.evaluateSettled();
16591
16632
  }, delay);
16592
16633
  }
16634
+ armApprovalExitTimeout() {
16635
+ if (this.approvalExitTimeout) clearTimeout(this.approvalExitTimeout);
16636
+ this.approvalExitTimeout = setTimeout(() => {
16637
+ if (this.currentStatus !== "waiting_approval") return;
16638
+ const tail = this.recentOutputBuffer;
16639
+ const modal = this.runParseApproval(tail);
16640
+ const stillWaiting = this.runDetectStatus(tail) === "waiting_approval" || !!modal;
16641
+ if (stillWaiting) {
16642
+ this.activeModal = modal || this.activeModal || { message: "Approval required", buttons: ["Allow", "Deny"] };
16643
+ this.onStatusChange?.();
16644
+ this.armApprovalExitTimeout();
16645
+ return;
16646
+ }
16647
+ LOG.warn("CLI", `[${this.cliType}] Approval timeout \u2014 auto-clearing`);
16648
+ this.activeModal = null;
16649
+ this.lastApprovalResolvedAt = Date.now();
16650
+ this.setStatus("idle", "approval_timeout");
16651
+ this.onStatusChange?.();
16652
+ }, 6e4);
16653
+ }
16593
16654
  evaluateSettled() {
16655
+ if (this.submitPendingUntil > Date.now()) return;
16656
+ if (this.responseSettleIgnoreUntil > Date.now()) return;
16594
16657
  const tail = this.settledBuffer;
16595
- const scriptStatus = this.runDetectStatus(tail);
16658
+ const modal = this.runParseApproval(tail);
16659
+ const rawScriptStatus = this.runDetectStatus(tail);
16660
+ const scriptStatus = rawScriptStatus === "waiting_approval" || modal ? "waiting_approval" : rawScriptStatus;
16596
16661
  if (!scriptStatus) return;
16597
16662
  const prevStatus = this.currentStatus;
16598
16663
  if (scriptStatus === "waiting_approval") {
@@ -16600,19 +16665,9 @@ var init_provider_cli_adapter = __esm({
16600
16665
  if (!inCooldown) {
16601
16666
  this.isWaitingForResponse = true;
16602
16667
  this.setStatus("waiting_approval", "script_detect");
16603
- const modal = this.runParseApproval(tail);
16604
16668
  this.activeModal = modal || { message: "Approval required", buttons: ["Allow", "Deny"] };
16605
16669
  if (this.idleTimeout) clearTimeout(this.idleTimeout);
16606
- if (this.approvalExitTimeout) clearTimeout(this.approvalExitTimeout);
16607
- this.approvalExitTimeout = setTimeout(() => {
16608
- if (this.currentStatus === "waiting_approval") {
16609
- LOG.warn("CLI", `[${this.cliType}] Approval timeout \u2014 auto-clearing`);
16610
- this.activeModal = null;
16611
- this.lastApprovalResolvedAt = Date.now();
16612
- this.setStatus("idle", "approval_timeout");
16613
- this.onStatusChange?.();
16614
- }
16615
- }, 6e4);
16670
+ this.armApprovalExitTimeout();
16616
16671
  this.onStatusChange?.();
16617
16672
  return;
16618
16673
  }
@@ -16648,7 +16703,12 @@ var init_provider_cli_adapter = __esm({
16648
16703
  this.lastApprovalResolvedAt = Date.now();
16649
16704
  }
16650
16705
  if (this.isWaitingForResponse) {
16651
- this.finishResponse();
16706
+ if (this.idleTimeout) clearTimeout(this.idleTimeout);
16707
+ this.idleTimeout = setTimeout(() => {
16708
+ if (this.isWaitingForResponse && this.currentStatus !== "waiting_approval") {
16709
+ this.finishResponse();
16710
+ }
16711
+ }, this.timeouts.idleFinish);
16652
16712
  } else if (prevStatus !== "idle") {
16653
16713
  this.setStatus("idle", "script_detect");
16654
16714
  this.onStatusChange?.();
@@ -16656,6 +16716,8 @@ var init_provider_cli_adapter = __esm({
16656
16716
  }
16657
16717
  }
16658
16718
  finishResponse() {
16719
+ if (this.submitPendingUntil > Date.now()) return;
16720
+ if (this.responseSettleIgnoreUntil > Date.now()) return;
16659
16721
  if (this.responseTimeout) {
16660
16722
  clearTimeout(this.responseTimeout);
16661
16723
  this.responseTimeout = null;
@@ -16668,8 +16730,15 @@ var init_provider_cli_adapter = __esm({
16668
16730
  clearTimeout(this.approvalExitTimeout);
16669
16731
  this.approvalExitTimeout = null;
16670
16732
  }
16733
+ if (this.submitRetryTimer) {
16734
+ clearTimeout(this.submitRetryTimer);
16735
+ this.submitRetryTimer = null;
16736
+ }
16671
16737
  this.responseBuffer = "";
16672
16738
  this.isWaitingForResponse = false;
16739
+ this.responseSettleIgnoreUntil = 0;
16740
+ this.submitRetryUsed = false;
16741
+ this.submitRetryPromptSnippet = "";
16673
16742
  this.activeModal = null;
16674
16743
  this.setStatus("idle", "response_finished");
16675
16744
  this.onStatusChange?.();
@@ -16784,29 +16853,95 @@ ${data.message || ""}`.trim();
16784
16853
  }
16785
16854
  async sendMessage(text) {
16786
16855
  if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
16856
+ if (this.startupParseGate) {
16857
+ const deadline = Date.now() + 1e4;
16858
+ while (this.startupParseGate && Date.now() < deadline) {
16859
+ await new Promise((resolve8) => setTimeout(resolve8, 50));
16860
+ }
16861
+ }
16787
16862
  if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
16788
16863
  if (this.isWaitingForResponse) return;
16789
16864
  this.messages.push({ role: "user", content: text, timestamp: Date.now() });
16790
16865
  this.structuredMessages.push({ role: "user", content: text, timestamp: Date.now() });
16791
16866
  this.isWaitingForResponse = true;
16792
16867
  this.responseBuffer = "";
16868
+ this.submitRetryUsed = false;
16869
+ this.submitRetryPromptSnippet = extractPromptRetrySnippet(text);
16870
+ const normalizedPromptSnippet = normalizePromptText(this.submitRetryPromptSnippet);
16871
+ if (this.submitRetryTimer) {
16872
+ clearTimeout(this.submitRetryTimer);
16873
+ this.submitRetryTimer = null;
16874
+ }
16875
+ const estimatedLines = estimatePromptDisplayLines(text);
16876
+ const submitDelayMs = this.sendDelayMs + Math.min(2e3, Math.max(0, estimatedLines - 1) * 350);
16877
+ const maxEchoWaitMs = submitDelayMs + Math.max(1500, Math.min(5e3, estimatedLines * 500));
16878
+ const retryDelayMs = Math.max(350, Math.min(1500, Math.max(this.sendDelayMs, submitDelayMs)));
16879
+ if (this.settleTimer) {
16880
+ clearTimeout(this.settleTimer);
16881
+ this.settleTimer = null;
16882
+ }
16883
+ this.responseEpoch += 1;
16884
+ this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
16793
16885
  this.setStatus("generating", "sendMessage");
16794
16886
  this.onStatusChange?.();
16887
+ if (submitDelayMs > 0) {
16888
+ this.submitPendingUntil = Date.now() + submitDelayMs;
16889
+ }
16795
16890
  this.ptyProcess.write(text);
16796
16891
  const submit = () => {
16797
16892
  if (!this.ptyProcess) return;
16798
16893
  this.submitPendingUntil = 0;
16799
16894
  this.ptyProcess.write(this.sendKey);
16895
+ const retrySubmitIfStuck = (attempt) => {
16896
+ this.submitRetryTimer = null;
16897
+ if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
16898
+ if (this.currentStatus !== "generating") return;
16899
+ if ((this.responseBuffer || "").trim()) return;
16900
+ const screenText = this.terminalScreen.getText();
16901
+ if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
16902
+ if (/Esc to interrupt|Do you want to proceed|This command requires approval|Allow Codex to|Approve and run now|Always approve this session|Running…|Running\.\.\./i.test(screenText)) return;
16903
+ this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
16904
+ LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
16905
+ this.ptyProcess.write(this.sendKey);
16906
+ if (attempt >= 3) {
16907
+ this.submitRetryUsed = true;
16908
+ return;
16909
+ }
16910
+ this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(attempt + 1), retryDelayMs);
16911
+ };
16912
+ this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(1), retryDelayMs);
16800
16913
  this.responseTimeout = setTimeout(() => {
16801
16914
  if (this.isWaitingForResponse) this.finishResponse();
16802
16915
  }, this.timeouts.maxResponse);
16803
16916
  };
16804
- if (this.sendDelayMs > 0) {
16805
- this.submitPendingUntil = Date.now() + this.sendDelayMs;
16806
- setTimeout(submit, this.sendDelayMs);
16807
- } else {
16808
- submit();
16809
- }
16917
+ const submitStartedAt = Date.now();
16918
+ let lastNormalizedScreen = "";
16919
+ let lastScreenChangeAt = submitStartedAt;
16920
+ const waitForEchoAndSubmit = () => {
16921
+ if (!this.ptyProcess) return;
16922
+ const now = Date.now();
16923
+ const elapsed = now - submitStartedAt;
16924
+ const screenText = this.terminalScreen.getText();
16925
+ const normalizedScreen = normalizePromptText(screenText);
16926
+ if (normalizedScreen !== lastNormalizedScreen) {
16927
+ lastNormalizedScreen = normalizedScreen;
16928
+ lastScreenChangeAt = now;
16929
+ }
16930
+ const echoVisible = !normalizedPromptSnippet || promptLikelyVisible(screenText, normalizedPromptSnippet);
16931
+ if (echoVisible) {
16932
+ const screenSettled = now - lastScreenChangeAt >= 500;
16933
+ if (elapsed >= submitDelayMs && screenSettled) {
16934
+ submit();
16935
+ return;
16936
+ }
16937
+ }
16938
+ if (elapsed >= maxEchoWaitMs) {
16939
+ submit();
16940
+ return;
16941
+ }
16942
+ setTimeout(waitForEchoAndSubmit, 50);
16943
+ };
16944
+ waitForEchoAndSubmit();
16810
16945
  }
16811
16946
  getPartialResponse() {
16812
16947
  if (!this.isWaitingForResponse) return "";
@@ -16824,6 +16959,10 @@ ${data.message || ""}`.trim();
16824
16959
  clearTimeout(this.approvalExitTimeout);
16825
16960
  this.approvalExitTimeout = null;
16826
16961
  }
16962
+ if (this.submitRetryTimer) {
16963
+ clearTimeout(this.submitRetryTimer);
16964
+ this.submitRetryTimer = null;
16965
+ }
16827
16966
  if (this.ptyProcess) {
16828
16967
  this.ptyProcess.write("");
16829
16968
  setTimeout(() => {
@@ -16845,6 +16984,8 @@ ${data.message || ""}`.trim();
16845
16984
  this.structuredMessages = [];
16846
16985
  this.accumulatedBuffer = "";
16847
16986
  this.accumulatedRawBuffer = "";
16987
+ this.submitRetryUsed = false;
16988
+ this.submitRetryPromptSnippet = "";
16848
16989
  this.terminalScreen.reset();
16849
16990
  this.onStatusChange?.();
16850
16991
  }
@@ -16858,7 +16999,16 @@ ${data.message || ""}`.trim();
16858
16999
  this.ptyProcess?.write(data);
16859
17000
  }
16860
17001
  resolveModal(buttonIndex) {
16861
- if (!this.ptyProcess || this.currentStatus !== "waiting_approval") return;
17002
+ if (!this.ptyProcess || this.currentStatus !== "waiting_approval" && !this.activeModal) return;
17003
+ this.activeModal = null;
17004
+ this.lastApprovalResolvedAt = Date.now();
17005
+ this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
17006
+ if (this.approvalExitTimeout) {
17007
+ clearTimeout(this.approvalExitTimeout);
17008
+ this.approvalExitTimeout = null;
17009
+ }
17010
+ this.setStatus("generating", "approval_resolved");
17011
+ this.onStatusChange?.();
16862
17012
  if (buttonIndex in this.approvalKeys) {
16863
17013
  this.ptyProcess.write(this.approvalKeys[buttonIndex]);
16864
17014
  } else {
@@ -16900,6 +17050,10 @@ ${data.message || ""}`.trim();
16900
17050
  isWaitingForResponse: this.isWaitingForResponse,
16901
17051
  activeModal: this.activeModal,
16902
17052
  lastApprovalResolvedAt: this.lastApprovalResolvedAt,
17053
+ sendDelayMs: this.sendDelayMs,
17054
+ sendKey: this.sendKey,
17055
+ submitPendingUntil: this.submitPendingUntil,
17056
+ responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
16903
17057
  resizeSuppressUntil: this.resizeSuppressUntil,
16904
17058
  hasCliScripts: this.hasCliScripts(),
16905
17059
  scriptNames: Object.keys(this.cliScripts).filter((k) => typeof this.cliScripts[k] === "function"),
@@ -40432,7 +40586,7 @@ var init_adhdev_daemon = __esm({
40432
40586
  fs12 = __toESM(require("fs"));
40433
40587
  path14 = __toESM(require("path"));
40434
40588
  import_chalk2 = __toESM(require("chalk"));
40435
- pkgVersion = "0.6.56";
40589
+ pkgVersion = "0.6.57";
40436
40590
  if (pkgVersion === "unknown") {
40437
40591
  try {
40438
40592
  const possiblePaths = [