@0xmaxma/claude-gateway 1.8.3 → 1.8.4

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.
Files changed (41) hide show
  1. package/README.md +56 -0
  2. package/dist/cli/commands/debug-bundle.d.ts.map +1 -1
  3. package/dist/cli/commands/debug-bundle.js +9 -52
  4. package/dist/cli/commands/debug-bundle.js.map +1 -1
  5. package/dist/cli/commands/gateway.d.ts +6 -1
  6. package/dist/cli/commands/gateway.d.ts.map +1 -1
  7. package/dist/cli/commands/gateway.js +14 -3
  8. package/dist/cli/commands/gateway.js.map +1 -1
  9. package/dist/cli/commands/logs.d.ts +37 -0
  10. package/dist/cli/commands/logs.d.ts.map +1 -0
  11. package/dist/cli/commands/logs.js +356 -0
  12. package/dist/cli/commands/logs.js.map +1 -0
  13. package/dist/cli/index.d.ts.map +1 -1
  14. package/dist/cli/index.js +16 -5
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/cli/logs-dir.d.ts +69 -0
  17. package/dist/cli/logs-dir.d.ts.map +1 -0
  18. package/dist/cli/logs-dir.js +166 -0
  19. package/dist/cli/logs-dir.js.map +1 -0
  20. package/dist/config/watcher.d.ts.map +1 -1
  21. package/dist/config/watcher.js +5 -0
  22. package/dist/config/watcher.js.map +1 -1
  23. package/dist/index.js +26 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/logger.d.ts +52 -1
  26. package/dist/logger.d.ts.map +1 -1
  27. package/dist/logger.js +264 -2
  28. package/dist/logger.js.map +1 -1
  29. package/dist/shell/bypass-dialog.d.ts +104 -12
  30. package/dist/shell/bypass-dialog.d.ts.map +1 -1
  31. package/dist/shell/bypass-dialog.js +146 -14
  32. package/dist/shell/bypass-dialog.js.map +1 -1
  33. package/dist/shell/claude-pty-shell.js +29 -4
  34. package/dist/shell/claude-pty-shell.js.map +1 -1
  35. package/dist/shell/screen.d.ts +15 -11
  36. package/dist/shell/screen.d.ts.map +1 -1
  37. package/dist/shell/screen.js +42 -33
  38. package/dist/shell/screen.js.map +1 -1
  39. package/dist/types.d.ts +20 -0
  40. package/dist/types.d.ts.map +1 -1
  41. package/package.json +1 -1
package/dist/logger.js CHANGED
@@ -33,16 +33,201 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.LOGS_DEFAULTS = void 0;
37
+ exports.isLogLevel = isLogLevel;
38
+ exports.configureLogging = configureLogging;
39
+ exports.loggingConfig = loggingConfig;
40
+ exports.resetLoggingForTests = resetLoggingForTests;
36
41
  exports.createLogger = createLogger;
42
+ exports.sweepOldLogs = sweepOldLogs;
43
+ exports.startLogRetentionSweep = startLogRetentionSweep;
37
44
  const fs = __importStar(require("fs"));
38
45
  const path = __importStar(require("path"));
46
+ /** Ordering for the level gate. Only the relative order matters. */
47
+ const LEVEL_RANK = { debug: 10, info: 20, warn: 30, error: 40 };
48
+ function isLogLevel(value) {
49
+ return typeof value === 'string' && value in LEVEL_RANK;
50
+ }
51
+ /**
52
+ * Defaults applied when `gateway.logs` is absent or partial.
53
+ *
54
+ * `level: 'info'` is the load-bearing one. Session processes log every stream
55
+ * event at debug (src/session/process.ts), which on a live host measured as
56
+ * 19,995 debug lines to 5 info lines in a single 217 MB file — so `debug`
57
+ * on-by-default was, in practice, the whole log directory. Rotation alone would
58
+ * not have helped: it bounds what is *kept*, not what is *written*.
59
+ */
60
+ exports.LOGS_DEFAULTS = {
61
+ level: 'info',
62
+ maxFileBytes: 16 * 1024 * 1024,
63
+ maxFiles: 3,
64
+ retentionDays: 14,
65
+ };
66
+ let active = { ...exports.LOGS_DEFAULTS };
67
+ /**
68
+ * Install the process-wide logging policy. Called once at boot, before the
69
+ * first logger exists.
70
+ *
71
+ * Policy is module state rather than a per-logger argument because there is one
72
+ * of it per process, and `createLogger()` has 13 call sites — several of which
73
+ * (routers, the session process) have no access to the gateway config. Threading
74
+ * an options bag through all of them would put the same value in 13 places and
75
+ * let them drift.
76
+ */
77
+ function configureLogging(cfg) {
78
+ const level = isLogLevel(cfg?.level) ? cfg.level : exports.LOGS_DEFAULTS.level;
79
+ active = {
80
+ level,
81
+ maxFileBytes: positiveOrDefault(cfg?.maxFileBytes, exports.LOGS_DEFAULTS.maxFileBytes),
82
+ maxFiles: nonNegativeOrDefault(cfg?.maxFiles, exports.LOGS_DEFAULTS.maxFiles),
83
+ retentionDays: nonNegativeOrDefault(cfg?.retentionDays, exports.LOGS_DEFAULTS.retentionDays),
84
+ };
85
+ return { ...active };
86
+ }
87
+ /** The policy currently in force (a copy — callers must not mutate it). */
88
+ function loggingConfig() {
89
+ return { ...active };
90
+ }
91
+ /** Test hook: restore defaults and forget per-file state. */
92
+ function resetLoggingForTests() {
93
+ active = { ...exports.LOGS_DEFAULTS };
94
+ fileSizes.clear();
95
+ writeFailureReported = false;
96
+ }
97
+ /** 0 is meaningful for `maxFiles`/`retentionDays` (= disabled) but not for a
98
+ * size threshold, where it would rotate on every line. */
99
+ function positiveOrDefault(value, fallback) {
100
+ return typeof value === 'number' && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
101
+ }
102
+ function nonNegativeOrDefault(value, fallback) {
103
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? Math.floor(value) : fallback;
104
+ }
105
+ /**
106
+ * Live size per log file, keyed by absolute path.
107
+ *
108
+ * Kept at module scope rather than on the instance because one file can have
109
+ * several loggers writing to it — `createLogger(agentConfig.id, …)` is called
110
+ * from both the boot path and the runner constructor. Per-instance counters
111
+ * would each see only their own share of the file and rotate late. Seeded from
112
+ * `statSync` once per file, then maintained by arithmetic so the common path
113
+ * costs no syscall.
114
+ *
115
+ * One entry per log file, and session logs create a new file each. The
116
+ * retention sweep deletes its entry along with the file, which bounds the map
117
+ * for any configuration that keeps retention on; with `retentionDays: 0` it
118
+ * grows with the session count, at roughly a path string per session. That is
119
+ * small enough not to be worth a second eviction mechanism whose only job would
120
+ * be to duplicate the sweep.
121
+ */
122
+ const fileSizes = new Map();
123
+ /**
124
+ * A failed append is latched and reported once per process.
125
+ *
126
+ * This used to be a bare `catch {}` — a full disk or a permission change
127
+ * silently stopped all file logging, which is precisely the failure that makes
128
+ * the next incident undiagnosable. Reporting every occurrence would be its own
129
+ * denial of service (the failing call is in the logger), so it is reported once
130
+ * and then suppressed.
131
+ */
132
+ let writeFailureReported = false;
133
+ function reportWriteFailure(file, err) {
134
+ if (writeFailureReported)
135
+ return;
136
+ writeFailureReported = true;
137
+ const reason = err?.code ?? err?.message ?? String(err);
138
+ process.stderr.write(`[logger] cannot write to ${file} (${reason}) — file logging is degraded for the rest of this process. ` +
139
+ 'Further write failures will not be reported.\n');
140
+ }
141
+ /**
142
+ * Remove every rotated generation at or above `maxFiles`.
143
+ *
144
+ * Deleting only `<file>.<maxFiles>` would be dead code: `renameSync` clobbers
145
+ * its destination, so the top generation is overwritten by the shift below
146
+ * anyway — but only while `maxFiles` stays where it was. Lower it in the config
147
+ * (5 → 2) and generations 2..5 are orphaned: nothing renames onto them, and the
148
+ * age sweep is the only thing that would ever collect them. A rotation happens
149
+ * once per `maxFileBytes`, so it can afford one readdir to stay bounded.
150
+ */
151
+ function pruneGenerations(file, maxFiles) {
152
+ const dir = path.dirname(file);
153
+ const prefix = `${path.basename(file)}.`;
154
+ let names;
155
+ try {
156
+ names = fs.readdirSync(dir);
157
+ }
158
+ catch {
159
+ return; // best-effort
160
+ }
161
+ for (const name of names) {
162
+ if (!name.startsWith(prefix))
163
+ continue;
164
+ const gen = Number(name.slice(prefix.length));
165
+ if (!Number.isInteger(gen) || gen < maxFiles)
166
+ continue;
167
+ try {
168
+ fs.rmSync(path.join(dir, name), { force: true });
169
+ }
170
+ catch {
171
+ /* best-effort */
172
+ }
173
+ }
174
+ }
175
+ /** `<name>.log` → `<name>.log.1`, dropping generations past `maxFiles`.
176
+ *
177
+ * Synchronous and best-effort by design: it runs inside a logging call, so it
178
+ * must neither block on I/O the caller did not ask for nor throw into code
179
+ * that was only trying to log. A rotation that fails leaves the live file in
180
+ * place and logging simply continues into it. */
181
+ function rotate(file, maxFiles) {
182
+ if (maxFiles <= 0) {
183
+ // No generations kept: the live file is the only file, so start it over.
184
+ try {
185
+ fs.unlinkSync(file);
186
+ }
187
+ catch {
188
+ /* best-effort */
189
+ }
190
+ return;
191
+ }
192
+ pruneGenerations(file, maxFiles);
193
+ for (let gen = maxFiles - 1; gen >= 1; gen--) {
194
+ try {
195
+ fs.renameSync(`${file}.${gen}`, `${file}.${gen + 1}`);
196
+ }
197
+ catch {
198
+ /* a generation that does not exist yet is the normal case */
199
+ }
200
+ }
201
+ try {
202
+ fs.renameSync(file, `${file}.1`);
203
+ }
204
+ catch {
205
+ /* best-effort */
206
+ }
207
+ }
39
208
  class AgentLogger {
40
209
  constructor(agentId, logDir) {
41
210
  this.agentId = agentId;
42
211
  fs.mkdirSync(logDir, { recursive: true });
43
212
  this.logFilePath = path.join(logDir, `${agentId}.log`);
44
213
  }
214
+ currentSize() {
215
+ const known = fileSizes.get(this.logFilePath);
216
+ if (known !== undefined)
217
+ return known;
218
+ let size = 0;
219
+ try {
220
+ size = fs.statSync(this.logFilePath).size;
221
+ }
222
+ catch {
223
+ size = 0; // not created yet
224
+ }
225
+ fileSizes.set(this.logFilePath, size);
226
+ return size;
227
+ }
45
228
  log(level, message, data) {
229
+ if (LEVEL_RANK[level] < LEVEL_RANK[active.level])
230
+ return;
46
231
  const entry = {
47
232
  ts: new Date().toISOString(),
48
233
  agentId: this.agentId,
@@ -55,11 +240,18 @@ class AgentLogger {
55
240
  // Write to stdout (pretty-printed for readability)
56
241
  process.stdout.write(pretty + '\n');
57
242
  // Write to log file (compact, one entry per line)
243
+ const bytes = Buffer.byteLength(line, 'utf-8') + 1;
58
244
  try {
245
+ if (active.maxFileBytes > 0 && this.currentSize() + bytes > active.maxFileBytes) {
246
+ rotate(this.logFilePath, active.maxFiles);
247
+ fileSizes.set(this.logFilePath, 0);
248
+ }
59
249
  fs.appendFileSync(this.logFilePath, line + '\n', 'utf-8');
250
+ fileSizes.set(this.logFilePath, this.currentSize() + bytes);
60
251
  }
61
- catch {
62
- // If we can't write to the log file, just continue
252
+ catch (err) {
253
+ // Logging must never throw into a caller, but it must not vanish either.
254
+ reportWriteFailure(this.logFilePath, err);
63
255
  }
64
256
  }
65
257
  info(message, data) {
@@ -78,4 +270,74 @@ class AgentLogger {
78
270
  function createLogger(agentId, logDir) {
79
271
  return new AgentLogger(agentId, logDir);
80
272
  }
273
+ /**
274
+ * Delete log files (live and rotated generations) last modified more than
275
+ * `retentionDays` ago. Returns the paths removed.
276
+ *
277
+ * Age, not count, is what bounds a directory of *session* logs: each session
278
+ * gets its own `<agent>:session:<uuid>.log` that is never written again once the
279
+ * session ends, so `maxFiles` — which only prunes generations of one stream —
280
+ * never touches them.
281
+ */
282
+ function sweepOldLogs(logDir, retentionDays, now = Date.now()) {
283
+ const removed = [];
284
+ if (!(retentionDays > 0))
285
+ return removed; // 0 = keep forever
286
+ const cutoff = now - retentionDays * 24 * 60 * 60 * 1000;
287
+ let names;
288
+ try {
289
+ names = fs.readdirSync(logDir);
290
+ }
291
+ catch {
292
+ return removed; // no directory yet, or unreadable — nothing to sweep
293
+ }
294
+ for (const name of names) {
295
+ // `.log` and its rotated generations (`.log.1`), and nothing else: the
296
+ // directory is not exclusively ours to delete from.
297
+ if (!/\.log(\.\d+)?$/.test(name))
298
+ continue;
299
+ const full = path.join(logDir, name);
300
+ try {
301
+ if (fs.statSync(full).mtimeMs >= cutoff)
302
+ continue;
303
+ fs.rmSync(full, { force: true });
304
+ fileSizes.delete(full);
305
+ removed.push(full);
306
+ }
307
+ catch {
308
+ /* best-effort — a file that vanished or cannot be read is not fatal */
309
+ }
310
+ }
311
+ return removed;
312
+ }
313
+ /**
314
+ * Sweep now, then once a day. Returns a stop function.
315
+ *
316
+ * Modelled on `AppInstaller.startBackupCleanup()`: the timer is unref'd so it
317
+ * never keeps the process alive, and a failing sweep is swallowed rather than
318
+ * escalated — retention is housekeeping, not a reason to take the gateway down.
319
+ *
320
+ * The timer is created unconditionally, including when retention is currently
321
+ * off. `retentionDays` is read on each run rather than captured, so a policy
322
+ * reloaded from `gateway.logs` takes effect at the next sweep — and a timer
323
+ * that was never started because retention happened to be 0 at boot could not
324
+ * do that. A disabled sweep costs one no-op call a day.
325
+ */
326
+ function startLogRetentionSweep(logDir, onSwept) {
327
+ const run = () => {
328
+ try {
329
+ const removed = sweepOldLogs(logDir, active.retentionDays);
330
+ if (removed.length > 0)
331
+ onSwept?.(removed);
332
+ }
333
+ catch {
334
+ /* best-effort */
335
+ }
336
+ };
337
+ run();
338
+ const timer = setInterval(run, 24 * 60 * 60 * 1000);
339
+ if (typeof timer.unref === 'function')
340
+ timer.unref();
341
+ return () => clearInterval(timer);
342
+ }
81
343
  //# sourceMappingURL=logger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgEA,oCAEC;AAlED,uCAAyB;AACzB,2CAA6B;AAa7B,MAAM,WAAW;IAIf,YAAY,OAAe,EAAE,MAAc;QACzC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,MAAM,CAAC,CAAC;IACzD,CAAC;IAEO,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,IAA8B;QAC1E,MAAM,KAAK,GAAa;YACtB,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK;YACL,OAAO;YACP,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACxC,CAAC;QAEF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAE9C,mDAAmD;QACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QAEpC,kDAAkD;QAClD,IAAI,CAAC;YACH,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;QACrD,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAA8B;QAClD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAA8B;QAClD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAA8B;QACnD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAA8B;QACnD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;CACF;AAED,SAAgB,YAAY,CAAC,OAAe,EAAE,MAAc;IAC1D,OAAO,IAAI,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAC1C,CAAC"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -26,9 +26,10 @@
26
26
  * reordering must not send us to "No, exit"), and anything unparseable or
27
27
  * ambiguous produces no keystroke at all.
28
28
  *
29
- * This module is the pure decision — kept free of node-pty / screen imports so
30
- * it is cheap to unit-test in isolation, same pattern as menu-probe.ts's
31
- * decideProbeAttempt and menu-cancel.ts's decideMenuCancel. See
29
+ * This module is the pure detection + decision — kept free of node-pty / screen
30
+ * imports so it is cheap to unit-test in isolation, same pattern as
31
+ * menu-probe.ts's decideProbeAttempt and menu-cancel.ts's decideMenuCancel.
32
+ * ScreenModel.detectDialog() calls isBypassDialogOnScreen() below; see
32
33
  * Driver.maybeHandleDialog() in claude-pty-shell.ts for where it is wired in.
33
34
  */
34
35
  /**
@@ -40,6 +41,40 @@
40
41
  */
41
42
  export declare const BYPASS_ACCEPT_LABEL = "Yes, I accept";
42
43
  export declare const BYPASS_DECLINE_LABEL = "No, exit";
44
+ /**
45
+ * The dialog's own confirm affordance, rendered a line or two below the option
46
+ * rows ("Enter to confirm · Esc to cancel"). Only the stable prefix is matched.
47
+ *
48
+ * Required by {@link isBypassDialogOnScreen} for the same reason
49
+ * TUI_REQUEST_TOO_LARGE_DISMISS is required by detectRequestTooLarge(): the
50
+ * labels alone appear in ordinary prose (this very dialog's warning text, a
51
+ * chat reply explaining it, re-injected history quoting it), whereas the
52
+ * footer is the affordance the live overlay renders — and it is exactly the
53
+ * affordance the accepting keystroke relies on, so gating on it keeps
54
+ * detection and the action consistent.
55
+ */
56
+ export declare const BYPASS_CONFIRM_FOOTER = "Enter to confirm";
57
+ /**
58
+ * The dialog's heading — the same string screen.ts lists first in
59
+ * TUI_BYPASS_PERMS, repeated here for the dependency-free reason above, with a
60
+ * unit test asserting the two never drift apart.
61
+ *
62
+ * Required by {@link isBypassDialogOnScreen} so that predicate is the COMPLETE
63
+ * rule rather than half of one split across two files. See the note there.
64
+ */
65
+ export declare const BYPASS_HEADING = "Bypass Permissions mode";
66
+ /**
67
+ * How far apart the dialog's own rows may sit before they stop being one block.
68
+ *
69
+ * The real capture has the two options on adjacent rows and the footer two rows
70
+ * below them (one blank row between). These bounds allow a little repaint slack
71
+ * while still requiring the elements to be visually together: without them the
72
+ * "structure" was only an ordering, so an option row, a second option row 15
73
+ * lines further down and any sentence containing "Enter to confirm" below that
74
+ * satisfied it — on a screen of ordinary conversation (review round 2, M3).
75
+ */
76
+ export declare const BYPASS_MAX_ROW_GAP = 2;
77
+ export declare const BYPASS_MAX_FOOTER_GAP = 3;
43
78
  /** Arrow keystrokes used to walk the caret onto the accept row. */
44
79
  export declare const BYPASS_KEY_DOWN = "\u001B[B";
45
80
  export declare const BYPASS_KEY_UP = "\u001B[A";
@@ -73,12 +108,12 @@ export declare const BYPASS_MAX_KEYS = 60;
73
108
  * Consecutive rounds with no dialog on screen before the keystroke ceiling is
74
109
  * considered spent on a dialog that is gone.
75
110
  *
76
- * Not 1: detection needs both TUI_BYPASS_PERMS markers inside the same bottom
77
- * region (screen.ts DIALOG_REGION_ROWS), so a repaint that shifts the box by a
78
- * row drops the header out of that window for a single read. Resetting on one
79
- * miss would zero the counter mid-dialog — precisely the case the ceiling
80
- * exists for. Requiring sustained absence costs the next dialog one extra
81
- * cooldown round at most.
111
+ * Not 1: detection is structural (see isBypassDialogOnScreen), so a mid-repaint
112
+ * frame the option rows drawn but the footer not yet, or the caret momentarily
113
+ * on neither row reads as "no dialog" for a single round while the dialog is
114
+ * still very much up. Resetting on one miss would zero the counter mid-dialog —
115
+ * precisely the case the ceiling exists for. Requiring sustained absence costs
116
+ * the next dialog one extra cooldown round at most.
82
117
  */
83
118
  export declare const BYPASS_RESET_AFTER_MISSES = 2;
84
119
  export type BypassDialogAction =
@@ -117,17 +152,74 @@ export interface BypassDialogState {
117
152
  * Record a round in which no dialog was detected, clearing the keystroke count
118
153
  * once the dialog has been absent for BYPASS_RESET_AFTER_MISSES consecutive
119
154
  * rounds so the next dialog starts with a full allowance. Tolerating a single
120
- * miss keeps a one-round detection flicker (a repaint shifting the header out
121
- * of the detection window) from silently refilling the allowance mid-dialog.
155
+ * miss keeps a one-round detection flicker (a repaint catching the dialog
156
+ * half-drawn) from silently refilling the allowance mid-dialog.
122
157
  */
123
158
  export declare function noteDialogAbsent(state: BypassDialogState): void;
124
159
  /** Record a round in which the dialog *was* detected, restarting the miss run. */
125
160
  export declare function noteDialogPresent(state: BypassDialogState): void;
126
161
  /** Exported only so a unit test can prove the escaping above. */
127
162
  export declare function rowPattern(label: string): RegExp;
163
+ /**
164
+ * Is a live, drivable bypass-permissions dialog on this screen?
165
+ *
166
+ * This replaced a positional test — "both marker substrings inside the bottom
167
+ * 20 rows" — which assumed a modal is always anchored to the bottom. This
168
+ * dialog is not: it renders at boot, before there is any conversation to push
169
+ * it down, so on a clean start it sits at the TOP of the screen with the rest
170
+ * blank. Both markers then fall outside the window, detection returns null,
171
+ * nothing is pressed, and the session dies at the 120 s startup timeout and
172
+ * respawns into the same dialog (issue #436). Whether a given boot emitted
173
+ * enough output to push the dialog into the window is what made the wedge look
174
+ * random.
175
+ *
176
+ * The window was never really about position, though — it was a cheap proxy for
177
+ * "this is the live modal, not text that quotes it". Quoted text is a genuine
178
+ * hazard: an agent explaining this dialog, or re-injected conversation history,
179
+ * puts the same characters on the same screen, and a mis-aimed Enter can land on
180
+ * "No, exit" and kill Claude Code unrecoverably. So the proxy is replaced with
181
+ * the thing it was proxying for — structural properties, all position-
182
+ * independent, all read off a verbatim capture of the real dialog:
183
+ *
184
+ * 1. The dialog's heading is somewhere on screen. Cheap substring reject.
185
+ * 2. Both option labels occupy a WHOLE row (findRow's anchored patterns), so
186
+ * prose that mentions them mid-sentence never qualifies.
187
+ * 3. Exactly ONE of those two rows carries the ❯ caret. Zero means the frame
188
+ * is still rendering (or is not a live select); two is a shape we do not
189
+ * understand.
190
+ * 4. The rows and the footer form one BLOCK — the options within
191
+ * BYPASS_MAX_ROW_GAP rows of each other, the footer within
192
+ * BYPASS_MAX_FOOTER_GAP below them. Without this the three elements only
193
+ * had to appear in order, so an option row, an unrelated option row 15
194
+ * lines later and a sentence containing "Enter to confirm" further down
195
+ * still qualified (review round 2, finding M3).
196
+ * 5. The dialog's own confirm footer renders BELOW the option rows.
197
+ * 6. Nothing but blank rows renders below that footer.
198
+ *
199
+ * (6) is the load-bearing one, and it is what the old bottom-region test was
200
+ * actually encoding: a live modal owns the screen. Quoted text never can — the
201
+ * input box, its border and the status bar always render underneath it — so
202
+ * scrollback, a pasted dialog, and re-injected history all fail (6) no matter
203
+ * where on the screen they land.
204
+ *
205
+ * (6) is deliberately ZERO-tolerance: not even a box border may follow the
206
+ * footer. A future Claude Code that draws this dialog inside a box, or paints a
207
+ * status line beneath it, would therefore stop being detected. That is the
208
+ * intended direction of the trade — a miss is fail-safe (the operator sees the
209
+ * dialog, and maybeHandleDialog() now logs a warning naming this exact case),
210
+ * whereas relaxing (6) to tolerate border rows would admit a quoted dialog
211
+ * sitting above an EMPTY input box, whose rows are themselves nothing but
212
+ * border characters. Given "No, exit" is unrecoverable and a visible dialog is
213
+ * not, a miss beats a false accept (review round 2, finding M2 — accepted as
214
+ * accurate, resolved this way rather than by relaxing the rule).
215
+ *
216
+ * Fail-safe in the same direction as before: anything unrecognised reads as "no
217
+ * dialog", which means no keystroke and an operator who simply sees the dialog.
218
+ */
219
+ export declare function isBypassDialogOnScreen(screenText: string): boolean;
128
220
  /**
129
221
  * Decide the single keystroke to send at a bypass-permissions dialog, given
130
- * the screen region the dialog was detected in.
222
+ * the screen text the dialog was detected on.
131
223
  *
132
224
  * Callers send at most one key per call and re-read the screen before the
133
225
  * next one (the DIALOG_ACTION_COOLDOWN_MS re-entry in maybeHandleDialog()),
@@ -1 +1 @@
1
- {"version":3,"file":"bypass-dialog.d.ts","sourceRoot":"","sources":["../../src/shell/bypass-dialog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAE/C,mEAAmE;AACnE,eAAO,MAAM,eAAe,aAAW,CAAC;AACxC,eAAO,MAAM,aAAa,aAAW,CAAC;AACtC,qFAAqF;AACrF,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,MAAM,MAAM,kBAAkB;AAC5B,kFAAkF;AAChF;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AAChC;;;;GAIG;GACD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AAC/B,oDAAoD;GAClD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AAClC,8DAA8D;GAC5D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC,yEAAyE;AACzE,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAG/D;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAEhE;AAmCD,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhD;AAkBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,iBAAiB,GACvB,kBAAkB,CA+CpB"}
1
+ {"version":3,"file":"bypass-dialog.d.ts","sourceRoot":"","sources":["../../src/shell/bypass-dialog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AAExD;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,4BAA4B,CAAC;AAExD;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,mEAAmE;AACnE,eAAO,MAAM,eAAe,aAAW,CAAC;AACxC,eAAO,MAAM,aAAa,aAAW,CAAC;AACtC,qFAAqF;AACrF,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C,MAAM,MAAM,kBAAkB;AAC5B,kFAAkF;AAChF;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AAChC;;;;GAIG;GACD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AAC/B,oDAAoD;GAClD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AAClC,8DAA8D;GAC5D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC,yEAAyE;AACzE,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAG/D;AAED,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAEhE;AAmCD,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhD;AAkBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAuBlE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,iBAAiB,GACvB,kBAAkB,CA4DpB"}