botmux 2.25.0 → 2.26.0

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 (32) hide show
  1. package/dist/adapters/backend/session-backend-selector.d.ts +11 -0
  2. package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -0
  3. package/dist/adapters/backend/session-backend-selector.js +26 -0
  4. package/dist/adapters/backend/session-backend-selector.js.map +1 -0
  5. package/dist/adapters/backend/tmux-pipe-backend.d.ts +55 -15
  6. package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
  7. package/dist/adapters/backend/tmux-pipe-backend.js +163 -21
  8. package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
  9. package/dist/adapters/cli/claude-code.d.ts.map +1 -1
  10. package/dist/adapters/cli/claude-code.js +90 -14
  11. package/dist/adapters/cli/claude-code.js.map +1 -1
  12. package/dist/cli.js +4 -4
  13. package/dist/cli.js.map +1 -1
  14. package/dist/im/lark/client.d.ts +7 -7
  15. package/dist/im/lark/client.d.ts.map +1 -1
  16. package/dist/im/lark/client.js +7 -11
  17. package/dist/im/lark/client.js.map +1 -1
  18. package/dist/skills/definitions.js +3 -3
  19. package/dist/utils/screenshot-renderer.d.ts.map +1 -1
  20. package/dist/utils/screenshot-renderer.js +63 -26
  21. package/dist/utils/screenshot-renderer.js.map +1 -1
  22. package/dist/utils/terminal-renderer.d.ts +16 -0
  23. package/dist/utils/terminal-renderer.d.ts.map +1 -1
  24. package/dist/utils/terminal-renderer.js +35 -21
  25. package/dist/utils/terminal-renderer.js.map +1 -1
  26. package/dist/utils/transient-snapshot.d.ts +28 -0
  27. package/dist/utils/transient-snapshot.d.ts.map +1 -0
  28. package/dist/utils/transient-snapshot.js +96 -0
  29. package/dist/utils/transient-snapshot.js.map +1 -0
  30. package/dist/worker.js +94 -31
  31. package/dist/worker.js.map +1 -1
  32. package/package.json +1 -1
@@ -0,0 +1,11 @@
1
+ import type { SessionBackend } from './types.js';
2
+ export interface SelectedSessionBackend {
3
+ backend: SessionBackend;
4
+ isTmuxMode: boolean;
5
+ isPipeMode: boolean;
6
+ }
7
+ export declare function selectSessionBackend(opts: {
8
+ sessionId: string;
9
+ useTmux: boolean;
10
+ }): SelectedSessionBackend;
11
+ //# sourceMappingURL=session-backend-selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-backend-selector.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/session-backend-selector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,sBAAsB,CAuB1G"}
@@ -0,0 +1,26 @@
1
+ import { PtyBackend } from './pty-backend.js';
2
+ import { TmuxBackend } from './tmux-backend.js';
3
+ import { TmuxPipeBackend } from './tmux-pipe-backend.js';
4
+ export function selectSessionBackend(opts) {
5
+ if (!opts.useTmux) {
6
+ return {
7
+ backend: new PtyBackend(),
8
+ isTmuxMode: false,
9
+ isPipeMode: false,
10
+ };
11
+ }
12
+ const sessionName = TmuxBackend.sessionName(opts.sessionId);
13
+ if (TmuxBackend.hasSession(sessionName)) {
14
+ return {
15
+ backend: new TmuxPipeBackend(sessionName, { ownsSession: true, isReattach: true }),
16
+ isTmuxMode: true,
17
+ isPipeMode: true,
18
+ };
19
+ }
20
+ return {
21
+ backend: new TmuxPipeBackend(sessionName, { createSession: true, ownsSession: true }),
22
+ isTmuxMode: true,
23
+ isPipeMode: true,
24
+ };
25
+ }
26
+ //# sourceMappingURL=session-backend-selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-backend-selector.js","sourceRoot":"","sources":["../../../src/adapters/backend/session-backend-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AASzD,MAAM,UAAU,oBAAoB,CAAC,IAA6C;IAChF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO;YACL,OAAO,EAAE,IAAI,UAAU,EAAE;YACzB,UAAU,EAAE,KAAK;YACjB,UAAU,EAAE,KAAK;SAClB,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5D,IAAI,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACxC,OAAO;YACL,OAAO,EAAE,IAAI,eAAe,CAAC,WAAW,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;YAClF,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,IAAI;SACjB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI,eAAe,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QACrF,UAAU,EAAE,IAAI;QAChB,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC"}
@@ -4,22 +4,42 @@ import type { SessionBackend, SpawnOpts } from './types.js';
4
4
  * to xterm.js (which treats bare LF as "down one row, keep column"). */
5
5
  export declare function normaliseCaptureLineEndings(s: string): string;
6
6
  export declare class TmuxPipeBackend implements SessionBackend {
7
- /** Real tmux pane address (e.g. "0:2.0"). */
7
+ /** Real tmux pane address (e.g. "0:2.0") or botmux session name (bmx-*). */
8
8
  private readonly paneTarget;
9
9
  private readonly fifoPath;
10
10
  private readStream;
11
11
  private readonly dataCbs;
12
12
  private readonly exitCbs;
13
+ private lifecycleTimer;
13
14
  private cols;
14
15
  private rows;
15
16
  private exited;
16
17
  /** Set after pipe-pane subscription is active so kill() knows to cancel it. */
17
18
  private pipeAttached;
18
- constructor(paneTarget: string);
19
- /** spawn() in this backend doesn't actually spawn a process; it sets up
20
- * the pipe-pane subscription + fifo reader. The bin/args params are
21
- * ignored (the CLI is already running in the user's pane). */
22
- spawn(_bin: string, _args: string[], opts: SpawnOpts): void;
19
+ private readonly createSession;
20
+ private readonly ownsSession;
21
+ private readonly _isReattach;
22
+ /** Claude Code session JSONL path set by worker for claude-code sessions so
23
+ * the claude-code adapter can verify paste+Enter submissions via file growth. */
24
+ claudeJsonlPath?: string;
25
+ /** PID of the spawned Claude Code child — used by the claude-code adapter to
26
+ * follow Claude's authoritative session id via ~/.claude/sessions/<pid>.json. */
27
+ cliPid?: number;
28
+ /** Working directory the CLI was spawned in — cross-checked against the pid
29
+ * file's cwd field so a recycled PID can't mislead the resolver. */
30
+ cliCwd?: string;
31
+ /** Whether this backend re-attached to an existing bmx-* tmux session
32
+ * (rather than creating a new detached one). Mirrors TmuxBackend.isReattach
33
+ * so the worker can branch on reattach behaviour without a private-cast. */
34
+ get isReattach(): boolean;
35
+ constructor(paneTarget: string, opts?: {
36
+ createSession?: boolean;
37
+ ownsSession?: boolean;
38
+ isReattach?: boolean;
39
+ });
40
+ /** spawn() sets up the pipe-pane subscription + fifo reader. In managed
41
+ * mode it first creates a detached bmx-* tmux session that runs the CLI. */
42
+ spawn(bin: string, args: string[], opts: SpawnOpts): void;
23
43
  write(data: string): void;
24
44
  sendText(text: string): void;
25
45
  sendSpecialKeys(...keys: string[]): void;
@@ -34,20 +54,40 @@ export declare class TmuxPipeBackend implements SessionBackend {
34
54
  destroySession(): void;
35
55
  getChildPid(): number | null;
36
56
  getAttachInfo(): null;
37
- /** Snapshot the current screen of the adopted pane WITH ANSI escapes,
38
- * including history (-S - = start of scrollback). New web-terminal
39
- * connections receive this string so xterm.js renders the existing
40
- * session state instead of a blank screen.
57
+ private startLifecycleWatcher;
58
+ private stopLifecycleWatcher;
59
+ private handlePaneExit;
60
+ private createDetachedSession;
61
+ private applySessionOptions;
62
+ /** Snapshot the full pane history WITH ANSI escapes (`-S - -E -`).
63
+ *
64
+ * Used by web reattach so a brand-new web client sees the whole prior
65
+ * conversation. For the screenshot / screen_update fast path use
66
+ * `captureViewport()` instead — that one only returns the visible pane
67
+ * and is safe to seed a transient xterm-headless with.
41
68
  *
42
69
  * IMPORTANT: tmux capture-pane separates rows with bare `\n`, no `\r`.
43
70
  * xterm.js (and any VT100-compliant emulator) treats a bare LF as
44
71
  * "move down one row, keep column" — every captured line lands further
45
- * to the right than the previous one, producing the staircase artefact
46
- * observed in early pipe-mode dogfooding. Normalising every `\n` to
47
- * `\r\n` makes the snapshot render correctly. The live pipe-pane stream
48
- * itself doesn't need this fix — applications write proper `\r\n` (and
49
- * Claude Code uses cursor-positioning instead of bare LF anyway). */
72
+ * to the right than the previous one. Normalising every `\n` to `\r\n`
73
+ * makes the snapshot render correctly. The live pipe-pane stream itself
74
+ * doesn't need this fix applications write proper `\r\n`. */
50
75
  captureCurrentScreen(): string;
76
+ /** Snapshot ONLY the currently visible pane (no scrollback). Equivalent to
77
+ * `tmux capture-pane` with no `-S`/`-E` flags, which defaults to the
78
+ * viewport. This is the right input for a transient xterm-headless seed:
79
+ * the snapshot row count matches the transient terminal's row count, so
80
+ * no normal-buffer scroll happens and the rendered screenshot lines up
81
+ * with what the user is seeing in the web terminal right now. */
82
+ captureViewport(): string;
83
+ private captureWithBounds;
84
+ /** Current real tmux pane dimensions. Drives transient-renderer sizing so
85
+ * the screenshot canvas matches whatever the web client resized the pane
86
+ * to. Returns null if tmux can't be queried (pane gone, server gone). */
87
+ getPaneSize(): {
88
+ cols: number;
89
+ rows: number;
90
+ } | null;
51
91
  /** Cheap probe: is the adopted pane currently in the alternate screen
52
92
  * buffer? Used by captureCurrentScreen to decide whether the snapshot
53
93
  * needs an alt-buffer-enter prefix for correct rendering. */
@@ -1 +1 @@
1
- {"version":3,"file":"tmux-pipe-backend.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/tmux-pipe-backend.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAQ5D;;yEAEyE;AACzE,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,qBAAa,eAAgB,YAAW,cAAc;IACpD,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,UAAU,CAA8B;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkC;IAC1D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmE;IAC3F,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,MAAM,CAAS;IACvB,+EAA+E;IAC/E,OAAO,CAAC,YAAY,CAAS;gBAEjB,UAAU,EAAE,MAAM;IAQ9B;;mEAE+D;IAC/D,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAoD3D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAU5B,eAAe,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAUxC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAgB7B,OAAO,CAAC,oBAAoB;IAuB5B,aAAa,IAAI,IAAI;IASrB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAS3C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAQxC,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIxC,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI;IAItE,IAAI,IAAI,IAAI;IAmBZ,cAAc,IAAI,IAAI;IAKtB,WAAW,IAAI,MAAM,GAAG,IAAI;IAkB5B,aAAa;IAMb;;;;;;;;;;;;0EAYsE;IACtE,oBAAoB,IAAI,MAAM;IAyB9B;;kEAE8D;IAC9D,OAAO,CAAC,iBAAiB;IAazB;iFAC6E;IAC7E,WAAW,IAAI,OAAO;IActB,OAAO,CAAC,QAAQ;CAKjB"}
1
+ {"version":3,"file":"tmux-pipe-backend.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/tmux-pipe-backend.ts"],"names":[],"mappings":"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"}
@@ -29,6 +29,7 @@ import { tmpdir } from 'node:os';
29
29
  import { join } from 'node:path';
30
30
  import { randomBytes } from 'node:crypto';
31
31
  import { tmuxEnv } from '../../setup/ensure-tmux.js';
32
+ import { buildBotmuxEnvAssignments, resolveUserShell, SHELL_WRAPPER_SCRIPT, TmuxBackend } from './tmux-backend.js';
32
33
  function shellescape(s) {
33
34
  // Single-quote-escape, replacing internal ' with '\''
34
35
  return `'${s.replace(/'/g, "'\\''")}'`;
@@ -40,29 +41,59 @@ export function normaliseCaptureLineEndings(s) {
40
41
  return s.replace(/\r?\n/g, '\r\n');
41
42
  }
42
43
  export class TmuxPipeBackend {
43
- /** Real tmux pane address (e.g. "0:2.0"). */
44
+ /** Real tmux pane address (e.g. "0:2.0") or botmux session name (bmx-*). */
44
45
  paneTarget;
45
46
  fifoPath;
46
47
  readStream = null;
47
48
  dataCbs = [];
48
49
  exitCbs = [];
50
+ lifecycleTimer = null;
49
51
  cols = 200;
50
52
  rows = 50;
51
53
  exited = false;
52
54
  /** Set after pipe-pane subscription is active so kill() knows to cancel it. */
53
55
  pipeAttached = false;
54
- constructor(paneTarget) {
56
+ createSession;
57
+ ownsSession;
58
+ _isReattach;
59
+ /** Claude Code session JSONL path — set by worker for claude-code sessions so
60
+ * the claude-code adapter can verify paste+Enter submissions via file growth. */
61
+ claudeJsonlPath;
62
+ /** PID of the spawned Claude Code child — used by the claude-code adapter to
63
+ * follow Claude's authoritative session id via ~/.claude/sessions/<pid>.json. */
64
+ cliPid;
65
+ /** Working directory the CLI was spawned in — cross-checked against the pid
66
+ * file's cwd field so a recycled PID can't mislead the resolver. */
67
+ cliCwd;
68
+ /** Whether this backend re-attached to an existing bmx-* tmux session
69
+ * (rather than creating a new detached one). Mirrors TmuxBackend.isReattach
70
+ * so the worker can branch on reattach behaviour without a private-cast. */
71
+ get isReattach() {
72
+ return this._isReattach;
73
+ }
74
+ constructor(paneTarget, opts) {
55
75
  this.paneTarget = paneTarget;
76
+ this.createSession = opts?.createSession ?? false;
77
+ this.ownsSession = opts?.ownsSession ?? false;
78
+ this._isReattach = opts?.isReattach ?? false;
56
79
  // Per-instance fifo so concurrent adopt sessions don't collide.
57
80
  this.fifoPath = join(tmpdir(), `botmux-pipe-${randomBytes(8).toString('hex')}.fifo`);
58
81
  }
59
82
  // ─── SessionBackend implementation ────────────────────────────────────────
60
- /** spawn() in this backend doesn't actually spawn a process; it sets up
61
- * the pipe-pane subscription + fifo reader. The bin/args params are
62
- * ignored (the CLI is already running in the user's pane). */
63
- spawn(_bin, _args, opts) {
83
+ /** spawn() sets up the pipe-pane subscription + fifo reader. In managed
84
+ * mode it first creates a detached bmx-* tmux session that runs the CLI. */
85
+ spawn(bin, args, opts) {
64
86
  this.cols = opts.cols;
65
87
  this.rows = opts.rows;
88
+ if (this.createSession) {
89
+ this.createDetachedSession(bin, args, opts);
90
+ }
91
+ else if (this.ownsSession && this._isReattach) {
92
+ // Backfill tmux options on an existing bmx-* session — daemon may have
93
+ // been upgraded since the session was originally created, and options
94
+ // like set-clipboard / window-size largest are idempotent to re-apply.
95
+ this.applySessionOptions();
96
+ }
66
97
  // Step 1: create the fifo. mkfifo is POSIX; linux/darwin both have it.
67
98
  spawnSync('mkfifo', [this.fifoPath], { stdio: 'ignore' });
68
99
  // Step 2: open the read end with O_RDWR (no O_NONBLOCK).
@@ -102,6 +133,7 @@ export class TmuxPipeBackend {
102
133
  try {
103
134
  execSync(`tmux pipe-pane -O -t ${shellescape(this.paneTarget)} 'cat > ${shellescape(this.fifoPath)}'`, { stdio: 'ignore', timeout: 5000, env: tmuxEnv() });
104
135
  this.pipeAttached = true;
136
+ this.startLifecycleWatcher();
105
137
  }
106
138
  catch (err) {
107
139
  this.fireExit(1, null);
@@ -189,11 +221,15 @@ export class TmuxPipeBackend {
189
221
  });
190
222
  }
191
223
  resize(cols, rows) {
192
- // Don't resize the user's tmux pane on every web client resize — that
193
- // would visibly snap the user's own client around. We just remember the
194
- // requested size for getAttachInfo / capture sizing.
195
224
  this.cols = cols;
196
225
  this.rows = rows;
226
+ if (this.ownsSession) {
227
+ execFileSync('tmux', ['resize-window', '-t', this.paneTarget, '-x', String(cols), '-y', String(rows)], {
228
+ stdio: 'ignore',
229
+ timeout: 5000,
230
+ env: tmuxEnv(),
231
+ });
232
+ }
197
233
  }
198
234
  onData(cb) {
199
235
  this.dataCbs.push(cb);
@@ -205,6 +241,7 @@ export class TmuxPipeBackend {
205
241
  if (this.exited)
206
242
  return;
207
243
  this.exited = true;
244
+ this.stopLifecycleWatcher();
208
245
  // Cancel tmux's pipe subscription. Calling pipe-pane without a command
209
246
  // turns it off for the target pane.
210
247
  if (this.pipeAttached) {
@@ -225,11 +262,12 @@ export class TmuxPipeBackend {
225
262
  fs.unlinkSync(this.fifoPath);
226
263
  }
227
264
  catch { /* already gone */ }
228
- this.fireExit(0, null);
229
265
  }
230
266
  destroySession() {
231
- // Adopt mode never owns the source session — kill() is enough.
232
267
  this.kill();
268
+ if (this.ownsSession) {
269
+ TmuxBackend.killSession(this.paneTarget);
270
+ }
233
271
  }
234
272
  getChildPid() {
235
273
  try {
@@ -251,25 +289,111 @@ export class TmuxPipeBackend {
251
289
  return null;
252
290
  }
253
291
  // ─── Pipe-specific helpers ────────────────────────────────────────────────
254
- /** Snapshot the current screen of the adopted pane WITH ANSI escapes,
255
- * including history (-S - = start of scrollback). New web-terminal
256
- * connections receive this string so xterm.js renders the existing
257
- * session state instead of a blank screen.
292
+ startLifecycleWatcher() {
293
+ this.stopLifecycleWatcher();
294
+ this.lifecycleTimer = setInterval(() => {
295
+ if (this.exited)
296
+ return;
297
+ try {
298
+ const paneId = execSync(`tmux display-message -p -t ${shellescape(this.paneTarget)} '#{pane_id}'`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 2000, env: tmuxEnv() }).trim();
299
+ if (!paneId)
300
+ this.handlePaneExit();
301
+ }
302
+ catch {
303
+ this.handlePaneExit();
304
+ }
305
+ }, 1000);
306
+ }
307
+ stopLifecycleWatcher() {
308
+ if (this.lifecycleTimer) {
309
+ clearInterval(this.lifecycleTimer);
310
+ this.lifecycleTimer = null;
311
+ }
312
+ }
313
+ handlePaneExit() {
314
+ if (this.exited)
315
+ return;
316
+ this.exited = true;
317
+ this.stopLifecycleWatcher();
318
+ if (this.readStream) {
319
+ try {
320
+ this.readStream.destroy();
321
+ }
322
+ catch { /* already closed */ }
323
+ this.readStream = null;
324
+ }
325
+ try {
326
+ fs.unlinkSync(this.fifoPath);
327
+ }
328
+ catch { /* already gone */ }
329
+ this.fireExit(1, null);
330
+ }
331
+ createDetachedSession(bin, args, opts) {
332
+ const shellSpec = resolveUserShell();
333
+ const envAssignments = buildBotmuxEnvAssignments(opts.env);
334
+ execFileSync('tmux', [
335
+ 'new-session',
336
+ '-d',
337
+ '-s', this.paneTarget,
338
+ '-x', String(opts.cols),
339
+ '-y', String(opts.rows),
340
+ '--',
341
+ shellSpec.shell, ...shellSpec.flags, '-c', SHELL_WRAPPER_SCRIPT, '_',
342
+ opts.cwd,
343
+ ...envAssignments,
344
+ bin, ...args,
345
+ ], {
346
+ cwd: opts.cwd,
347
+ stdio: 'ignore',
348
+ timeout: 5000,
349
+ env: tmuxEnv(opts.env),
350
+ });
351
+ this.applySessionOptions();
352
+ }
353
+ applySessionOptions() {
354
+ const t = shellescape(this.paneTarget);
355
+ const env = tmuxEnv();
356
+ try {
357
+ execSync(`tmux set-option -t ${t} status off`, { stdio: 'ignore', env });
358
+ execSync(`tmux set-option -t ${t} mouse on`, { stdio: 'ignore', env });
359
+ execSync(`tmux set-option -s set-clipboard on`, { stdio: 'ignore', env });
360
+ execSync(`tmux set-option -t ${t} history-limit 50000`, { stdio: 'ignore', env });
361
+ execSync(`tmux set-option -t ${t} window-size largest`, { stdio: 'ignore', env });
362
+ }
363
+ catch { /* session may not be ready yet — benign */ }
364
+ }
365
+ /** Snapshot the full pane history WITH ANSI escapes (`-S - -E -`).
366
+ *
367
+ * Used by web reattach so a brand-new web client sees the whole prior
368
+ * conversation. For the screenshot / screen_update fast path use
369
+ * `captureViewport()` instead — that one only returns the visible pane
370
+ * and is safe to seed a transient xterm-headless with.
258
371
  *
259
372
  * IMPORTANT: tmux capture-pane separates rows with bare `\n`, no `\r`.
260
373
  * xterm.js (and any VT100-compliant emulator) treats a bare LF as
261
374
  * "move down one row, keep column" — every captured line lands further
262
- * to the right than the previous one, producing the staircase artefact
263
- * observed in early pipe-mode dogfooding. Normalising every `\n` to
264
- * `\r\n` makes the snapshot render correctly. The live pipe-pane stream
265
- * itself doesn't need this fix — applications write proper `\r\n` (and
266
- * Claude Code uses cursor-positioning instead of bare LF anyway). */
375
+ * to the right than the previous one. Normalising every `\n` to `\r\n`
376
+ * makes the snapshot render correctly. The live pipe-pane stream itself
377
+ * doesn't need this fix applications write proper `\r\n`. */
267
378
  captureCurrentScreen() {
379
+ return this.captureWithBounds('-S - -E -');
380
+ }
381
+ /** Snapshot ONLY the currently visible pane (no scrollback). Equivalent to
382
+ * `tmux capture-pane` with no `-S`/`-E` flags, which defaults to the
383
+ * viewport. This is the right input for a transient xterm-headless seed:
384
+ * the snapshot row count matches the transient terminal's row count, so
385
+ * no normal-buffer scroll happens and the rendered screenshot lines up
386
+ * with what the user is seeing in the web terminal right now. */
387
+ captureViewport() {
388
+ // No `-S`/`-E` flags = tmux default = current viewport only.
389
+ return this.captureWithBounds('');
390
+ }
391
+ captureWithBounds(bounds) {
268
392
  if (this.exited)
269
393
  return '';
270
394
  try {
271
395
  const altOn = this.isPaneInAltBuffer();
272
- const raw = execSync(`tmux capture-pane -e -p -t ${shellescape(this.paneTarget)} -S -`,
396
+ const raw = execSync(`tmux capture-pane -e -p -t ${shellescape(this.paneTarget)}${bounds ? ' ' + bounds : ''}`,
273
397
  // Explicit stdio — see getChildPid for why default leaks tmux stderr.
274
398
  { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 5000, maxBuffer: 16 * 1024 * 1024, env: tmuxEnv() });
275
399
  const normalised = normaliseCaptureLineEndings(raw);
@@ -288,6 +412,24 @@ export class TmuxPipeBackend {
288
412
  return '';
289
413
  }
290
414
  }
415
+ /** Current real tmux pane dimensions. Drives transient-renderer sizing so
416
+ * the screenshot canvas matches whatever the web client resized the pane
417
+ * to. Returns null if tmux can't be queried (pane gone, server gone). */
418
+ getPaneSize() {
419
+ if (this.exited)
420
+ return null;
421
+ try {
422
+ const out = execSync(`tmux display-message -p -t ${shellescape(this.paneTarget)} '#{pane_width} #{pane_height}'`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 2000, env: tmuxEnv() }).trim();
423
+ const [cols, rows] = out.split(/\s+/).map(s => parseInt(s, 10));
424
+ if (Number.isFinite(cols) && Number.isFinite(rows) && cols > 0 && rows > 0) {
425
+ return { cols, rows };
426
+ }
427
+ return null;
428
+ }
429
+ catch {
430
+ return null;
431
+ }
432
+ }
291
433
  /** Cheap probe: is the adopted pane currently in the alternate screen
292
434
  * buffer? Used by captureCurrentScreen to decide whether the snapshot
293
435
  * needs an alt-buffer-enter prefix for correct rendering. */
@@ -1 +1 @@
1
- {"version":3,"file":"tmux-pipe-backend.js","sourceRoot":"","sources":["../../../src/adapters/backend/tmux-pipe-backend.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tmux-pipe-backend.js","sourceRoot":"","sources":["../../../src/adapters/backend/tmux-pipe-backend.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../../src/adapters/cli/claude-code.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,YAAY,CAAC;AAiBxD;;;gEAGgE;AAChE,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGhF;AAoDD;;;;;;;;;wEASwE;AACxE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAoBD;;;;;0CAK0C;AAC1C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAyBnH;AAED;;;;;;;;;;;;;;oDAcoD;AACpD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA+B9D;AAID,wBAAgB,uBAAuB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CA+RzE;AAED,eAAO,MAAM,MAAM,gCAA0B,CAAC"}
1
+ {"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../../src/adapters/cli/claude-code.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,YAAY,CAAC;AAiBxD;;;gEAGgE;AAChE,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGhF;AAoDD;;;;;;;;;wEASwE;AACxE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtD;AAoBD;;;;;0CAK0C;AAC1C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAoCnH;AAED;;;;;;;;;;;;;;oDAcoD;AACpD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA+B9D;AA0CD,wBAAgB,uBAAuB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CAqTzE;AAED,eAAO,MAAM,MAAM,gCAA0B,CAAC"}
@@ -142,19 +142,31 @@ export function resolveJsonlFromPid(pid, expectedCwd) {
142
142
  return null;
143
143
  if (typeof parsed.sessionId !== 'string' || !SESSION_UUID_RE.test(parsed.sessionId))
144
144
  return null;
145
- // Compare on realpath: Claude's pid file always records the canonical cwd
146
- // (Node's process.cwd() returns getcwd(3)), but `expectedCwd` may still be
147
- // the symlink we spawned under. A raw equality check would reject a
148
- // legitimate match when workingDir is e.g. /home/x → /data00/home/x.
149
- if (typeof parsed.cwd !== 'string' || realpathCwd(parsed.cwd) !== realpathCwd(expectedCwd))
145
+ if (typeof parsed.cwd !== 'string')
150
146
  return null;
147
+ // Identity check: procStart matching against /proc/<pid>/stat field 22 is
148
+ // the strong signal that this pid file belongs to the live process (rules
149
+ // out pid reuse). When that holds, Claude's recorded cwd is authoritative
150
+ // even if it disagrees with `expectedCwd` — the worker's cliCwd can drift
151
+ // (e.g. a schedule resumes a session with a different workingDir than the
152
+ // original spawn, but Claude itself loads the session with its own cwd).
153
+ // When procStart is unavailable/unverifiable, fall back to cwd equality as
154
+ // the only remaining sanity check. Realpath both sides so a symlinked
155
+ // workingDir (/home/x → /data00/home/x) still matches Claude's canonical
156
+ // cwd from getcwd(3).
157
+ let procStartVerified = false;
151
158
  if (typeof parsed.procStart === 'string') {
152
159
  const live = readProcStarttime(pid);
153
160
  if (live === null && process.platform === 'linux')
154
161
  return null;
155
- if (live !== null && live !== parsed.procStart)
156
- return null;
162
+ if (live !== null) {
163
+ if (live !== parsed.procStart)
164
+ return null;
165
+ procStartVerified = true;
166
+ }
157
167
  }
168
+ if (!procStartVerified && realpathCwd(parsed.cwd) !== realpathCwd(expectedCwd))
169
+ return null;
158
170
  return {
159
171
  path: claudeJsonlPathForSession(parsed.sessionId, parsed.cwd),
160
172
  cliSessionId: parsed.sessionId,
@@ -213,6 +225,48 @@ export function findOpenClaudeSessionIds(pid) {
213
225
  }
214
226
  return [...out];
215
227
  }
228
+ /** Fingerprint search that fans out from the pinned project dir to every
229
+ * sibling under `~/.claude/projects/`. Used as the writeInput fallback
230
+ * when the pinned `claudeJsonlPath` doesn't contain the submit marker —
231
+ * Claude may have written to a different project hash than the worker
232
+ * expected (e.g. a schedule resumed the session with a workingDir that
233
+ * differs from Claude's internal cwd, so the worker computes the wrong
234
+ * -project-hash- but Claude appends to the original session's hash dir).
235
+ * Tries the primary dir first (fast path, unchanged behavior); only fans
236
+ * out when no match is found there. Per-dir, `findJsonlContainingFingerprint`
237
+ * still applies its newest-first ordering and the minMtimeMs guard, so a
238
+ * stale historical match in some unrelated project can't false-positive. */
239
+ function findJsonlAcrossProjectsRoot(searchPath, fingerprint, options) {
240
+ const primaryDir = dirname(searchPath);
241
+ const primary = findJsonlContainingFingerprint(primaryDir, fingerprint, {
242
+ excludePath: searchPath,
243
+ ...options,
244
+ });
245
+ if (primary)
246
+ return primary;
247
+ const projectsRoot = dirname(primaryDir);
248
+ if (!existsSync(projectsRoot))
249
+ return null;
250
+ let siblings;
251
+ try {
252
+ siblings = readdirSync(projectsRoot);
253
+ }
254
+ catch {
255
+ return null;
256
+ }
257
+ for (const name of siblings) {
258
+ const sib = join(projectsRoot, name);
259
+ if (sib === primaryDir)
260
+ continue;
261
+ const matched = findJsonlContainingFingerprint(sib, fingerprint, {
262
+ excludePath: searchPath,
263
+ ...options,
264
+ });
265
+ if (matched)
266
+ return matched;
267
+ }
268
+ return null;
269
+ }
216
270
  const COMPLETION_RE = /\u2733\s*(?:Worked|Crunched|Cogitated|Cooked|Churned|Saut[eé]ed|Baked|Brewed) for \d+[smh]/;
217
271
  export function createClaudeCodeAdapter(pathOverride) {
218
272
  const bin = resolveCommand(pathOverride ?? 'claude');
@@ -414,9 +468,12 @@ export function createClaudeCodeAdapter(pathOverride) {
414
468
  }
415
469
  }
416
470
  // Final fallback when the pid file is unavailable / fails validation:
417
- // scan the project dir for a recently-written jsonl whose tail
418
- // contains our content fingerprint. Stricter than mtime-based
471
+ // scan the pinned project dir for a recently-written jsonl whose
472
+ // tail contains our content fingerprint. Stricter than mtime-based
419
473
  // detection so a sibling pane in the same dir can't hijack us.
474
+ // Per-attempt scope is intentionally narrow (dirname only) — the
475
+ // cross-project fan-out only runs once at end-of-writeInput and in
476
+ // the recheck closure, not per retry, to keep the worst case bounded.
420
477
  if (submitFingerprint) {
421
478
  const searchPath = pty.claudeJsonlPath ?? startPath;
422
479
  const matched = findJsonlContainingFingerprint(dirname(searchPath), submitFingerprint, {
@@ -452,6 +509,24 @@ export function createClaudeCodeAdapter(pathOverride) {
452
509
  if (await confirmSubmit(800)) {
453
510
  return observedCliSessionId ? buildResult(true) : undefined;
454
511
  }
512
+ // Last-resort cross-project fan-out, run ONCE before declaring failure:
513
+ // catches the case where workingDir/cwd drift made every per-attempt
514
+ // scan look in the wrong project dir AND the pid resolver also failed
515
+ // (e.g. pid file missing, /proc unavailable). minMtimeMs filtering and
516
+ // newest-first ordering keep the cost bounded — only jsonls touched in
517
+ // the last 60s are actually read, which is typically a handful even
518
+ // across all sibling project dirs. Per-attempt scans stay narrow
519
+ // (dirname only) so this work doesn't repeat 4×.
520
+ if (submitFingerprint && pty.claudeJsonlPath) {
521
+ const matched = findJsonlAcrossProjectsRoot(pty.claudeJsonlPath, submitFingerprint, {
522
+ minMtimeMs: submitSearchMinMtime,
523
+ includeQueueOperations: true,
524
+ });
525
+ if (matched) {
526
+ pty.claudeJsonlPath = matched;
527
+ return observedCliSessionId ? buildResult(true) : undefined;
528
+ }
529
+ }
455
530
  // All retries exhausted and still no submit marker in JSONL. Signal failure
456
531
  // so the worker can notify the user in Lark instead of silently dropping.
457
532
  // We still surface observedCliSessionId so the worker can persist Claude's
@@ -475,14 +550,15 @@ export function createClaudeCodeAdapter(pathOverride) {
475
550
  if (currentPath && jsonlContainsFingerprint(currentPath, submitFingerprint, { includeQueueOperations: true })) {
476
551
  return true;
477
552
  }
478
- // Fan out to sibling jsonls in the project dir (excluding the pinned
479
- // path which we already checked). Same minMtime guard as the in-band
480
- // fingerprint fallback so a stale historical match can't suppress.
553
+ // Fan out to sibling jsonls in the project dir, then across every
554
+ // sibling project dir under `~/.claude/projects/` (catches workingDir
555
+ // drift like worker thinking `-foo-bar/` while Claude actually appends
556
+ // to `-foo-bar-baz/`). Same minMtime guard as the in-band fingerprint
557
+ // fallback so a stale historical match can't suppress the warning.
481
558
  const searchPath = currentPath ?? pty.claudeJsonlPath;
482
559
  if (!searchPath)
483
560
  return false;
484
- const matched = findJsonlContainingFingerprint(dirname(searchPath), submitFingerprint, {
485
- excludePath: searchPath,
561
+ const matched = findJsonlAcrossProjectsRoot(searchPath, submitFingerprint, {
486
562
  minMtimeMs: submitSearchMinMtime,
487
563
  includeQueueOperations: true,
488
564
  });