adhdev 0.5.5 → 0.5.6

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.
@@ -19873,6 +19873,39 @@ var require_dist = __commonJS({
19873
19873
  const action = args?.action || "approve";
19874
19874
  const button = args?.button || args?.buttonText || (action === "approve" ? "Accept" : action === "reject" ? "Reject" : "Accept");
19875
19875
  LOG5.info("Command", `[resolveAction] action=${action} button="${button}" provider=${provider2?.type}`);
19876
+ if (provider2?.category === "cli") {
19877
+ const adapter = h.getCliAdapter(provider2.type);
19878
+ if (!adapter) return { success: false, error: "CLI adapter not running" };
19879
+ const status = adapter.getStatus?.();
19880
+ if (status?.status !== "waiting_approval") {
19881
+ return { success: false, error: "Not in approval state" };
19882
+ }
19883
+ const buttons = status.activeModal?.buttons || ["Allow once", "Always allow", "Deny"];
19884
+ let buttonIndex = typeof args?.buttonIndex === "number" ? args.buttonIndex : -1;
19885
+ if (buttonIndex < 0) {
19886
+ const btnLower = button.toLowerCase();
19887
+ buttonIndex = buttons.findIndex((b) => b.toLowerCase().includes(btnLower));
19888
+ }
19889
+ if (buttonIndex < 0) {
19890
+ if (action === "reject" || action === "deny") {
19891
+ buttonIndex = buttons.findIndex((b) => /deny|reject|no/i.test(b));
19892
+ if (buttonIndex < 0) buttonIndex = buttons.length - 1;
19893
+ } else if (action === "always" || /always/i.test(button)) {
19894
+ buttonIndex = buttons.findIndex((b) => /always/i.test(b));
19895
+ if (buttonIndex < 0) buttonIndex = 1;
19896
+ } else {
19897
+ buttonIndex = 0;
19898
+ }
19899
+ }
19900
+ if (typeof adapter.resolveModal === "function") {
19901
+ adapter.resolveModal(buttonIndex);
19902
+ } else {
19903
+ const keys = "\x1B[B".repeat(Math.max(0, buttonIndex)) + "\r";
19904
+ adapter.writeRaw?.(keys);
19905
+ }
19906
+ LOG5.info("Command", `[resolveAction] CLI PTY \u2192 buttonIndex=${buttonIndex} "${buttons[buttonIndex] ?? "?"}"`);
19907
+ return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
19908
+ }
19876
19909
  if (provider2?.category === "extension" && h.agentStream && h.getCdp()) {
19877
19910
  const ok = await h.agentStream.resolveAgentAction(
19878
19911
  h.getCdp(),
@@ -22751,28 +22784,32 @@ var require_dist = __commonJS({
22751
22784
  }
22752
22785
  var FALLBACK_PROMPT = [
22753
22786
  /Type your message/i,
22754
- />\s*$/,
22787
+ /^>\s*$/m,
22788
+ // '>' alone on its own line
22755
22789
  /[›➤]\s*$/,
22756
22790
  /for shortcuts/i,
22757
22791
  /\?\s*for help/i,
22758
- /Press enter/i,
22759
- /^[\s\u2500-\u257f]*>\s*$/m
22792
+ /Press enter/i
22793
+ // NOTE: removed /^[\s\u2500-\u257f]*>\s*$/m — the box-drawing char range is too wide and
22794
+ // can match dialog-clearing ANSI output, causing false prompt detection in approval state.
22760
22795
  ];
22761
22796
  var FALLBACK_GENERATING = [
22762
- /thinking/i,
22763
- /writing/i,
22764
- /Claude is/i,
22765
- /Opus|Sonnet|Haiku/i,
22766
- /[\u2800-\u28ff]/
22767
- // Braille spinner blocks
22797
+ /[\u2800-\u28ff]/,
22798
+ // Braille spinner blocks (universal TUI)
22799
+ /esc to (cancel|interrupt|stop)/i,
22800
+ // Common TUI generation status line
22801
+ /generating\.\.\./i,
22802
+ /Claude is (?:thinking|processing|working)/i
22803
+ // Specific Claude Code status
22768
22804
  ];
22769
22805
  var FALLBACK_APPROVAL = [
22770
- /approve/i,
22771
- /Allow( once)?/i,
22806
+ /Allow\s+once/i,
22807
+ /Always\s+allow/i,
22772
22808
  /\(y\/n\)/i,
22773
22809
  /\[Y\/n\]/i,
22774
- /continue\?/i,
22775
- /Run this command/i
22810
+ /Run\s+this\s+command/i
22811
+ // NOTE: removed /Do you want to (?:run|execute|allow)/i — too broad, matches AI explanation
22812
+ // text like "Do you want to allow this feature?" causing false approval notifications.
22776
22813
  ];
22777
22814
  function defaultCleanOutput(raw, _lastUserInput) {
22778
22815
  return stripAnsi(raw).trim();
@@ -22833,6 +22870,11 @@ var require_dist = __commonJS({
22833
22870
  logBuffer = [];
22834
22871
  // Approval cooldown
22835
22872
  lastApprovalResolvedAt = 0;
22873
+ // Approval state machine
22874
+ approvalTransitionBuffer = "";
22875
+ approvalExitTimeout = null;
22876
+ // Resize redraw suppression
22877
+ resizeSuppressUntil = 0;
22836
22878
  // Resolved timeouts (provider defaults + overrides)
22837
22879
  timeouts;
22838
22880
  // ─── Lifecycle ─────────────────────────────────
@@ -22923,6 +22965,7 @@ var require_dist = __commonJS({
22923
22965
  }
22924
22966
  // ─── Output state machine ────────────────────────────
22925
22967
  handleOutput(rawData) {
22968
+ if (Date.now() < this.resizeSuppressUntil) return;
22926
22969
  const cleanData = stripAnsi(rawData);
22927
22970
  const { patterns } = this.provider;
22928
22971
  if (cleanData.trim()) {
@@ -22955,30 +22998,55 @@ var require_dist = __commonJS({
22955
22998
  const hasApproval = patterns.approval.some((p) => p.test(this.recentOutputBuffer));
22956
22999
  if (hasApproval && this.currentStatus !== "waiting_approval") {
22957
23000
  if (this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown) return;
23001
+ const ctxLines = this.recentOutputBuffer.split("\n").map((l) => l.trim()).filter((l) => l && !/^[─═╭╮╰╯│]+$/.test(l));
22958
23002
  this.isWaitingForResponse = true;
22959
23003
  this.currentStatus = "waiting_approval";
22960
23004
  this.recentOutputBuffer = "";
22961
- const ctxLines = cleanData.split("\n").map((l) => l.trim()).filter((l) => l && !/^[─═╭╮╰╯│]+$/.test(l));
23005
+ this.approvalTransitionBuffer = "";
22962
23006
  this.activeModal = {
22963
23007
  message: ctxLines.slice(-5).join(" ").slice(0, 200) || "Approval required",
22964
23008
  buttons: ["Allow once", "Always allow", "Deny"]
22965
23009
  };
22966
23010
  if (this.idleTimeout) clearTimeout(this.idleTimeout);
23011
+ if (this.approvalExitTimeout) clearTimeout(this.approvalExitTimeout);
23012
+ this.approvalExitTimeout = setTimeout(() => {
23013
+ if (this.currentStatus === "waiting_approval") {
23014
+ LOG5.warn("CLI", `[${this.cliType}] Approval timeout \u2014 auto-exiting waiting_approval`);
23015
+ this.activeModal = null;
23016
+ this.lastApprovalResolvedAt = Date.now();
23017
+ this.recentOutputBuffer = "";
23018
+ this.approvalTransitionBuffer = "";
23019
+ this.approvalExitTimeout = null;
23020
+ this.currentStatus = this.isWaitingForResponse ? "generating" : "idle";
23021
+ this.onStatusChange?.();
23022
+ }
23023
+ }, 6e4);
22967
23024
  this.onStatusChange?.();
22968
23025
  return;
22969
23026
  }
22970
23027
  if (this.currentStatus === "waiting_approval") {
22971
- const genResume = patterns.generating.some((p) => p.test(cleanData));
22972
- const promptResume = patterns.prompt.some((p) => p.test(cleanData));
23028
+ this.approvalTransitionBuffer = (this.approvalTransitionBuffer + cleanData).slice(-500);
23029
+ const genResume = patterns.generating.some((p) => p.test(this.approvalTransitionBuffer));
23030
+ const promptResume = patterns.prompt.some((p) => p.test(this.approvalTransitionBuffer));
22973
23031
  if (genResume) {
23032
+ if (this.approvalExitTimeout) {
23033
+ clearTimeout(this.approvalExitTimeout);
23034
+ this.approvalExitTimeout = null;
23035
+ }
22974
23036
  this.currentStatus = "generating";
22975
23037
  this.activeModal = null;
22976
23038
  this.recentOutputBuffer = "";
23039
+ this.approvalTransitionBuffer = "";
22977
23040
  this.lastApprovalResolvedAt = Date.now();
22978
23041
  this.onStatusChange?.();
22979
23042
  } else if (promptResume) {
23043
+ if (this.approvalExitTimeout) {
23044
+ clearTimeout(this.approvalExitTimeout);
23045
+ this.approvalExitTimeout = null;
23046
+ }
22980
23047
  this.activeModal = null;
22981
23048
  this.recentOutputBuffer = "";
23049
+ this.approvalTransitionBuffer = "";
22982
23050
  this.lastApprovalResolvedAt = Date.now();
22983
23051
  this.finishResponse();
22984
23052
  }
@@ -23004,7 +23072,8 @@ var require_dist = __commonJS({
23004
23072
  this.onStatusChange?.();
23005
23073
  return;
23006
23074
  }
23007
- if (patterns.prompt.some((p) => p.test(this.responseBuffer))) {
23075
+ const trailingLines = cleanData.split("\n").slice(-2).join("\n");
23076
+ if (patterns.prompt.some((p) => p.test(trailingLines))) {
23008
23077
  this.finishResponse();
23009
23078
  } else {
23010
23079
  this.idleTimeout = setTimeout(() => {
@@ -23025,6 +23094,10 @@ var require_dist = __commonJS({
23025
23094
  clearTimeout(this.idleTimeout);
23026
23095
  this.idleTimeout = null;
23027
23096
  }
23097
+ if (this.approvalExitTimeout) {
23098
+ clearTimeout(this.approvalExitTimeout);
23099
+ this.approvalExitTimeout = null;
23100
+ }
23028
23101
  const lastUserText = this.messages.filter((m) => m.role === "user").pop()?.content;
23029
23102
  let response = this.provider.cleanOutput(this.responseBuffer, lastUserText);
23030
23103
  if (lastUserText && response) {
@@ -23074,6 +23147,10 @@ var require_dist = __commonJS({
23074
23147
  this.shutdown();
23075
23148
  }
23076
23149
  shutdown() {
23150
+ if (this.approvalExitTimeout) {
23151
+ clearTimeout(this.approvalExitTimeout);
23152
+ this.approvalExitTimeout = null;
23153
+ }
23077
23154
  if (this.ptyProcess) {
23078
23155
  this.ptyProcess.write("");
23079
23156
  setTimeout(() => {
@@ -23101,10 +23178,22 @@ var require_dist = __commonJS({
23101
23178
  writeRaw(data) {
23102
23179
  this.ptyProcess?.write(data);
23103
23180
  }
23181
+ /**
23182
+ * Resolve an approval modal by navigating to the button at `buttonIndex` and pressing Enter.
23183
+ * Index 0 = first option (already selected by default — just Enter).
23184
+ * Index N = press Arrow Down N times, then Enter.
23185
+ */
23186
+ resolveModal(buttonIndex) {
23187
+ if (!this.ptyProcess || this.currentStatus !== "waiting_approval") return;
23188
+ const DOWN = "\x1B[B";
23189
+ const keys = DOWN.repeat(Math.max(0, buttonIndex)) + "\r";
23190
+ this.ptyProcess.write(keys);
23191
+ }
23104
23192
  resize(cols, rows) {
23105
23193
  if (this.ptyProcess) {
23106
23194
  try {
23107
23195
  this.ptyProcess.resize(cols, rows);
23196
+ this.resizeSuppressUntil = Date.now() + 300;
23108
23197
  } catch {
23109
23198
  }
23110
23199
  }
@@ -23225,20 +23314,24 @@ var require_dist = __commonJS({
23225
23314
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
23226
23315
  const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
23227
23316
  if (newStatus !== this.lastStatus) {
23317
+ LOG5.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
23228
23318
  if (this.lastStatus === "idle" && newStatus === "generating") {
23229
23319
  this.generatingStartedAt = now;
23230
23320
  this.pushEvent({ event: "agent:generating_started", chatTitle, timestamp: now });
23231
23321
  } else if (newStatus === "waiting_approval") {
23232
23322
  if (!this.generatingStartedAt) this.generatingStartedAt = now;
23323
+ const modal = adapterStatus.activeModal;
23324
+ LOG5.info("CLI", `[${this.type}] approval modal: "${modal?.message?.slice(0, 80) ?? "none"}"`);
23233
23325
  this.pushEvent({
23234
23326
  event: "agent:waiting_approval",
23235
23327
  chatTitle,
23236
23328
  timestamp: now,
23237
- modalMessage: adapterStatus.activeModal?.message,
23238
- modalButtons: adapterStatus.activeModal?.buttons
23329
+ modalMessage: modal?.message,
23330
+ modalButtons: modal?.buttons
23239
23331
  });
23240
23332
  } else if (newStatus === "idle" && (this.lastStatus === "generating" || this.lastStatus === "waiting_approval")) {
23241
23333
  const duration3 = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : 0;
23334
+ LOG5.info("CLI", `[${this.type}] completed in ${duration3}s`);
23242
23335
  this.pushEvent({ event: "agent:generating_completed", chatTitle, duration: duration3, timestamp: now });
23243
23336
  this.generatingStartedAt = 0;
23244
23337
  } else if (newStatus === "stopped") {