aicodeman 1.48.0 → 1.49.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.
- package/README.md +12 -3
- package/dist/config/cli-registry/schema.d.ts +1 -0
- package/dist/config/cli-registry/schema.d.ts.map +1 -1
- package/dist/config/cli-registry/schema.js +5 -1
- package/dist/config/cli-registry/schema.js.map +1 -1
- package/dist/config/cli-registry/stock.d.ts.map +1 -1
- package/dist/config/cli-registry/stock.js +71 -5
- package/dist/config/cli-registry/stock.js.map +1 -1
- package/dist/config/cli-registry/types.d.ts +4 -4
- package/dist/config/cli-registry/types.d.ts.map +1 -1
- package/dist/config/foreign-tmux.d.ts +48 -0
- package/dist/config/foreign-tmux.d.ts.map +1 -0
- package/dist/config/foreign-tmux.js +48 -0
- package/dist/config/foreign-tmux.js.map +1 -0
- package/dist/custom-model-injection-apply.d.ts +4 -2
- package/dist/custom-model-injection-apply.d.ts.map +1 -1
- package/dist/custom-model-injection-apply.js +35 -21
- package/dist/custom-model-injection-apply.js.map +1 -1
- package/dist/docker-hosts.d.ts +8 -1
- package/dist/docker-hosts.d.ts.map +1 -1
- package/dist/docker-hosts.js +5 -5
- package/dist/docker-hosts.js.map +1 -1
- package/dist/foreign-tmux-discovery.d.ts +140 -0
- package/dist/foreign-tmux-discovery.d.ts.map +1 -0
- package/dist/foreign-tmux-discovery.js +366 -0
- package/dist/foreign-tmux-discovery.js.map +1 -0
- package/dist/foreign-tmux.d.ts +381 -0
- package/dist/foreign-tmux.d.ts.map +1 -0
- package/dist/foreign-tmux.js +775 -0
- package/dist/foreign-tmux.js.map +1 -0
- package/dist/git-fetch-scheduler.d.ts +2 -0
- package/dist/git-fetch-scheduler.d.ts.map +1 -1
- package/dist/git-fetch-scheduler.js +1 -1
- package/dist/git-fetch-scheduler.js.map +1 -1
- package/dist/git-fetch.d.ts +1 -1
- package/dist/git-fetch.d.ts.map +1 -1
- package/dist/git-workspace-status.d.ts +2 -2
- package/dist/git-workspace-status.d.ts.map +1 -1
- package/dist/hooks-config.d.ts +2 -1
- package/dist/hooks-config.d.ts.map +1 -1
- package/dist/hooks-config.js +2 -1
- package/dist/hooks-config.js.map +1 -1
- package/dist/live-worktree.d.ts +53 -0
- package/dist/live-worktree.d.ts.map +1 -0
- package/dist/live-worktree.js +97 -0
- package/dist/live-worktree.js.map +1 -0
- package/dist/mux-interface.d.ts +12 -1
- package/dist/mux-interface.d.ts.map +1 -1
- package/dist/reboot-restore.d.ts +1 -1
- package/dist/reboot-restore.d.ts.map +1 -1
- package/dist/reboot-restore.js +9 -0
- package/dist/reboot-restore.js.map +1 -1
- package/dist/remote-files.d.ts +150 -5
- package/dist/remote-files.d.ts.map +1 -1
- package/dist/remote-files.js +505 -7
- package/dist/remote-files.js.map +1 -1
- package/dist/remote-hosts.d.ts +15 -9
- package/dist/remote-hosts.d.ts.map +1 -1
- package/dist/remote-hosts.js +42 -20
- package/dist/remote-hosts.js.map +1 -1
- package/dist/session-cli-registry-bridge.d.ts.map +1 -1
- package/dist/session-cli-registry-bridge.js +19 -8
- package/dist/session-cli-registry-bridge.js.map +1 -1
- package/dist/session-env-clamp.d.ts +1 -1
- package/dist/session-env-clamp.d.ts.map +1 -1
- package/dist/session-env-clamp.js +4 -3
- package/dist/session-env-clamp.js.map +1 -1
- package/dist/session.d.ts +91 -21
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +190 -33
- package/dist/session.js.map +1 -1
- package/dist/tmux-manager.d.ts +74 -12
- package/dist/tmux-manager.d.ts.map +1 -1
- package/dist/tmux-manager.js +256 -41
- package/dist/tmux-manager.js.map +1 -1
- package/dist/types/foreign-tmux.d.ts +101 -0
- package/dist/types/foreign-tmux.d.ts.map +1 -0
- package/dist/types/foreign-tmux.js +27 -0
- package/dist/types/foreign-tmux.js.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/session.d.ts +106 -2
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js.map +1 -1
- package/dist/types/update.d.ts +4 -1
- package/dist/types/update.d.ts.map +1 -1
- package/dist/web/edit-history-sync.d.ts +27 -7
- package/dist/web/edit-history-sync.d.ts.map +1 -1
- package/dist/web/edit-history-sync.js +35 -19
- package/dist/web/edit-history-sync.js.map +1 -1
- package/dist/web/launch-defaults.d.ts +1 -1
- package/dist/web/launch-defaults.js +2 -2
- package/dist/web/launch-defaults.js.map +1 -1
- package/dist/web/linked-cases-writer.d.ts +43 -0
- package/dist/web/linked-cases-writer.d.ts.map +1 -0
- package/dist/web/linked-cases-writer.js +107 -0
- package/dist/web/linked-cases-writer.js.map +1 -0
- package/dist/web/paste-image-gc.d.ts +4 -1
- package/dist/web/paste-image-gc.d.ts.map +1 -1
- package/dist/web/paste-image-gc.js +4 -2
- package/dist/web/paste-image-gc.js.map +1 -1
- package/dist/web/public/admin-ui.js.gz +0 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/{app.963b5ba8.js → app.9ea37070.js} +6 -6
- package/dist/web/public/app.9ea37070.js.br +0 -0
- package/dist/web/public/app.9ea37070.js.gz +0 -0
- package/dist/web/public/approvals-ui.js.gz +0 -0
- package/dist/web/public/constants.782170e1.js.gz +0 -0
- package/dist/web/public/cron-ui.js.gz +0 -0
- package/dist/web/public/edit-history-ui.js +27 -14
- package/dist/web/public/edit-history-ui.js.br +0 -0
- package/dist/web/public/edit-history-ui.js.gz +0 -0
- package/dist/web/public/entrance-animations.js.gz +0 -0
- package/dist/web/public/foreign-sessions.js +476 -0
- package/dist/web/public/foreign-sessions.js.br +0 -0
- package/dist/web/public/foreign-sessions.js.gz +0 -0
- package/dist/web/public/git-status-ui.js +5 -3
- package/dist/web/public/git-status-ui.js.br +0 -0
- package/dist/web/public/git-status-ui.js.gz +0 -0
- package/dist/web/public/header-divider.eb2d2463.js.gz +0 -0
- package/dist/web/public/home-sessions.js.gz +0 -0
- package/dist/web/public/host-wake-ui.js.gz +0 -0
- package/dist/web/public/i18n.a5e82c95.js +2 -0
- package/dist/web/public/i18n.a5e82c95.js.br +0 -0
- package/dist/web/public/i18n.a5e82c95.js.gz +0 -0
- package/dist/web/public/image-input.a5d0f8f3.js.gz +0 -0
- package/dist/web/public/index.html +36 -17
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
- package/dist/web/public/{keyboard-accessory.d4ec5957.js → keyboard-accessory.b941676c.js} +3 -1
- package/dist/web/public/keyboard-accessory.b941676c.js.br +0 -0
- package/dist/web/public/{keyboard-accessory.d4ec5957.js.gz → keyboard-accessory.b941676c.js.gz} +0 -0
- package/dist/web/public/mobile-handlers.f7c3f692.js.gz +0 -0
- package/dist/web/public/mobile-ime-preview.2dbaf262.js.gz +0 -0
- package/dist/web/public/mobile-overview.js +10 -0
- package/dist/web/public/mobile-overview.js.br +0 -0
- package/dist/web/public/mobile-overview.js.gz +0 -0
- package/dist/web/public/{mobile.5ef2ce85.css → mobile.67c8eb5b.css} +1 -1
- package/dist/web/public/mobile.67c8eb5b.css.br +0 -0
- package/dist/web/public/{mobile.5ef2ce85.css.gz → mobile.67c8eb5b.css.gz} +0 -0
- package/dist/web/public/notification-manager.feb82c04.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/{panels-ui.b100727d.js → panels-ui.8bcd4473.js} +4 -4
- package/dist/web/public/panels-ui.8bcd4473.js.br +0 -0
- package/dist/web/public/panels-ui.8bcd4473.js.gz +0 -0
- package/dist/web/public/ralph-panel.b350e2ef.js.gz +0 -0
- package/dist/web/public/ralph-wizard.b6c0dd19.js.gz +0 -0
- package/dist/web/public/readmymind-ui.js.gz +0 -0
- package/dist/web/public/reboot-restore-ui.js.gz +0 -0
- package/dist/web/public/respawn-ui.304ba0d4.js.gz +0 -0
- package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
- package/dist/web/public/session-lineage.js.gz +0 -0
- package/dist/web/public/{session-ui.5ac82f2c.js → session-ui.a7c8c095.js} +11 -11
- package/dist/web/public/session-ui.a7c8c095.js.br +0 -0
- package/dist/web/public/session-ui.a7c8c095.js.gz +0 -0
- package/dist/web/public/{settings-ui.d1d4fb99.js → settings-ui.18f92052.js} +3 -3
- package/dist/web/public/settings-ui.18f92052.js.br +0 -0
- package/dist/web/public/settings-ui.18f92052.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview-worker.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview.75c751de.js.gz +0 -0
- package/dist/web/public/spreadsheet-xlsx-core.js.gz +0 -0
- package/dist/web/public/{styles.77dc538f.css → styles.6a718331.css} +1 -1
- package/dist/web/public/styles.6a718331.css.br +0 -0
- package/dist/web/public/{styles.77dc538f.css.gz → styles.6a718331.css.gz} +0 -0
- package/dist/web/public/subagent-windows.07277a58.js.gz +0 -0
- package/dist/web/public/sw.js +2 -2
- package/dist/web/public/sw.js.br +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/tab-layout-browser.2d6189f7.js.gz +0 -0
- package/dist/web/public/tab-rail-resize.b5cdceaf.js.gz +0 -0
- package/dist/web/public/terminal-keycode229-recovery.98843069.js.gz +0 -0
- package/dist/web/public/terminal-split.js.gz +0 -0
- package/dist/web/public/terminal-tile.js +2 -2
- package/dist/web/public/terminal-tile.js.br +0 -0
- package/dist/web/public/terminal-tile.js.gz +0 -0
- package/dist/web/public/{terminal-ui.d7c75ce8.js → terminal-ui.a7883640.js} +2 -2
- package/dist/web/public/terminal-ui.a7883640.js.br +0 -0
- package/dist/web/public/terminal-ui.a7883640.js.gz +0 -0
- package/dist/web/public/tile-grid.js.gz +0 -0
- package/dist/web/public/ultracode-panel.js.gz +0 -0
- package/dist/web/public/ultracode-windows.js.gz +0 -0
- package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
- package/dist/web/public/vendor/exceljs.min.js.gz +0 -0
- package/dist/web/public/vendor/fflate.min.js.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.276b11d9.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.1be42307.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/voice-input.2342c37b.js.gz +0 -0
- package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
- package/dist/web/public/webview-tabs.js.gz +0 -0
- package/dist/web/public/whats-new.json +9 -9
- package/dist/web/routes/case-routes.d.ts.map +1 -1
- package/dist/web/routes/case-routes.js +72 -53
- package/dist/web/routes/case-routes.js.map +1 -1
- package/dist/web/routes/discord-routes.js +1 -1
- package/dist/web/routes/discord-routes.js.map +1 -1
- package/dist/web/routes/edit-history-routes.d.ts +2 -2
- package/dist/web/routes/edit-history-routes.d.ts.map +1 -1
- package/dist/web/routes/edit-history-routes.js +4 -3
- package/dist/web/routes/edit-history-routes.js.map +1 -1
- package/dist/web/routes/file-routes.d.ts.map +1 -1
- package/dist/web/routes/file-routes.js +213 -102
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/routes/git-status-routes.d.ts.map +1 -1
- package/dist/web/routes/git-status-routes.js +7 -2
- package/dist/web/routes/git-status-routes.js.map +1 -1
- package/dist/web/routes/mux-routes.d.ts +10 -3
- package/dist/web/routes/mux-routes.d.ts.map +1 -1
- package/dist/web/routes/mux-routes.js +59 -1
- package/dist/web/routes/mux-routes.js.map +1 -1
- package/dist/web/routes/ralph-routes.d.ts.map +1 -1
- package/dist/web/routes/ralph-routes.js +22 -0
- package/dist/web/routes/ralph-routes.js.map +1 -1
- package/dist/web/routes/readmymind-routes.d.ts.map +1 -1
- package/dist/web/routes/readmymind-routes.js +3 -2
- package/dist/web/routes/readmymind-routes.js.map +1 -1
- package/dist/web/routes/respawn-routes.d.ts.map +1 -1
- package/dist/web/routes/respawn-routes.js +24 -0
- package/dist/web/routes/respawn-routes.js.map +1 -1
- package/dist/web/routes/session-routes.d.ts +11 -8
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +262 -29
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/routes/system-routes.d.ts.map +1 -1
- package/dist/web/routes/system-routes.js +3 -2
- package/dist/web/routes/system-routes.js.map +1 -1
- package/dist/web/schemas.d.ts +24 -1
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +34 -9
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/self-update.d.ts +9 -0
- package/dist/web/self-update.d.ts.map +1 -1
- package/dist/web/self-update.js +19 -3
- package/dist/web/self-update.js.map +1 -1
- package/dist/web/server.d.ts +16 -3
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +84 -24
- package/dist/web/server.js.map +1 -1
- package/dist/web/session-wait-registry.d.ts +13 -0
- package/dist/web/session-wait-registry.d.ts.map +1 -1
- package/dist/web/session-wait-registry.js +16 -8
- package/dist/web/session-wait-registry.js.map +1 -1
- package/package.json +2 -2
- package/skills/codeman/SKILL.md +20 -4
- package/dist/web/public/app.963b5ba8.js.br +0 -0
- package/dist/web/public/app.963b5ba8.js.gz +0 -0
- package/dist/web/public/i18n.33f930d7.js +0 -2
- package/dist/web/public/i18n.33f930d7.js.br +0 -0
- package/dist/web/public/i18n.33f930d7.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.d4ec5957.js.br +0 -0
- package/dist/web/public/mobile.5ef2ce85.css.br +0 -0
- package/dist/web/public/panels-ui.b100727d.js.br +0 -0
- package/dist/web/public/panels-ui.b100727d.js.gz +0 -0
- package/dist/web/public/session-ui.5ac82f2c.js.br +0 -0
- package/dist/web/public/session-ui.5ac82f2c.js.gz +0 -0
- package/dist/web/public/settings-ui.d1d4fb99.js.br +0 -0
- package/dist/web/public/settings-ui.d1d4fb99.js.gz +0 -0
- package/dist/web/public/styles.77dc538f.css.br +0 -0
- package/dist/web/public/terminal-ui.d7c75ce8.js.br +0 -0
- package/dist/web/public/terminal-ui.d7c75ce8.js.gz +0 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure core for FOREIGN tmux sessions, the ones a human started
|
|
3
|
+
* by hand, which Codeman neither created nor owns.
|
|
4
|
+
*
|
|
5
|
+
* Everything here is a string in / structure out, so all three locations (local,
|
|
6
|
+
* inside a container, across ssh) go through ONE probe script, ONE parser and ONE
|
|
7
|
+
* classifier. Writing a second copy per location is exactly how the two would
|
|
8
|
+
* drift into disagreeing about what a session is.
|
|
9
|
+
*
|
|
10
|
+
* ## Why the probe script is dumb
|
|
11
|
+
*
|
|
12
|
+
* It runs two commands and prints them: `tmux list-panes` per socket, and one
|
|
13
|
+
* `ps` snapshot. No filtering, no logic. All judgement happens in Node, where it
|
|
14
|
+
* is pure and unit-testable, instead of in a shell string that is embedded three
|
|
15
|
+
* different ways and can only be debugged against a real host.
|
|
16
|
+
*
|
|
17
|
+
* The one thing the script does decide is whether a server is safe to ask, because
|
|
18
|
+
* only the script can. A tmux server that stopped answering holds its client
|
|
19
|
+
* forever, and from outside a container or across ssh no signal reaches that
|
|
20
|
+
* client: a timeout kills `docker exec` or `ssh`, never what they started. So each
|
|
21
|
+
* server gets a bounded ping first, and one that misses it costs its own rows and
|
|
22
|
+
* a `CMFH` line, not the whole scan.
|
|
23
|
+
*
|
|
24
|
+
* ⚠️ The ping exists because a watchdog around `list-panes` cannot work. A tmux
|
|
25
|
+
* client hands dups of its stdout to the server, so a stopped server keeps our
|
|
26
|
+
* stdout pipe open after the client is dead (measured: SIGTERM ended the client at
|
|
27
|
+
* once and no EOF came in the 2.5 s that were watched, while the server stayed
|
|
28
|
+
* stopped). Nothing reading that pipe can finish, and the same hold would keep
|
|
29
|
+
* `docker exec` and `ssh` waiting on it. The ping's stdout is /dev/null, so only a
|
|
30
|
+
* server that just answered ever gets the real one.
|
|
31
|
+
*
|
|
32
|
+
* ⚠️ The script MUST NOT contain a single quote. It is wrapped in single quotes
|
|
33
|
+
* to cross `ssh <host> '<script>'` and `docker exec <c> sh -lc '<script>'`. That
|
|
34
|
+
* is the single-quote dual of the "no double quotes in the docker launch chain"
|
|
35
|
+
* rule in `tmux-manager.ts`: same class of bug, opposite quote.
|
|
36
|
+
*
|
|
37
|
+
* ## Why the mode comes from the process tree
|
|
38
|
+
*
|
|
39
|
+
* `#{pane_current_command}` is `node` for BOTH claude and codex, so it cannot
|
|
40
|
+
* distinguish them. The classifier walks the pane's descendants over the `ps`
|
|
41
|
+
* snapshot with `collectDescendants` (bounded: one snapshot, no per-node spawn,
|
|
42
|
+
* see proc-tree.ts for the incident that rule exists for) and matches argv. What
|
|
43
|
+
* it cannot identify is `shell`, which is also the honest answer for the case
|
|
44
|
+
* this feature was built for: a hand-opened shell.
|
|
45
|
+
*
|
|
46
|
+
* ## Why attaching means creating a grouped session
|
|
47
|
+
*
|
|
48
|
+
* A grouped session (`new-session -t <target>`) shares the target's WINDOWS but
|
|
49
|
+
* is its own session, so our `status off` and our current-window selection land
|
|
50
|
+
* on us alone. A bare `attach` would have to set those on the owner's session,
|
|
51
|
+
* i.e. mutate something we do not own. `destroy-unattached on` then makes our
|
|
52
|
+
* view evaporate when the wrapper pane dies (measured: it does).
|
|
53
|
+
*
|
|
54
|
+
* ⚠️ The group session must be created ATTACHED (no `-d`). tmux's
|
|
55
|
+
* `server_check_unattached()` runs every server loop, so a detached session with
|
|
56
|
+
* `destroy-unattached on` is torn down almost immediately: the option has to
|
|
57
|
+
* land on a session that already has our client on it.
|
|
58
|
+
*
|
|
59
|
+
* ⚠️ **Grouping does NOT give us an independent window SIZE, and believing it did
|
|
60
|
+
* was wrong.** Measured on tmux 3.3a against a target held open by a 200x49
|
|
61
|
+
* client, with our client at 80x24:
|
|
62
|
+
*
|
|
63
|
+
* bare attach -> target becomes 80x23
|
|
64
|
+
* grouped session -> target becomes 80x23 (same!)
|
|
65
|
+
* grouped + `window-size largest` -> target stays 200x49
|
|
66
|
+
*
|
|
67
|
+
* A window is one object with one size; a group shares the object. So attaching
|
|
68
|
+
* from Codeman resizes a session someone else is actively viewing, exactly like
|
|
69
|
+
* any second tmux client does: that is tmux's normal behavior, and it reverses
|
|
70
|
+
* when we detach.
|
|
71
|
+
*
|
|
72
|
+
* `window-size largest` is deliberately NOT set here. It is a WINDOW option on a
|
|
73
|
+
* SHARED window, so it survives our detach (measured: still `largest` after our
|
|
74
|
+
* view is gone): it would permanently rewrite the owner's configuration to buy
|
|
75
|
+
* a cropped view for us. Restoring it would need the previous value captured with
|
|
76
|
+
* `$(...)`, and this string carries no command substitution. It reaches `bash -c`
|
|
77
|
+
* verbatim now (`bashCArg()`), but it crossed `bash -c "..."` for a long time, where
|
|
78
|
+
* the OUTER shell expanded it first. That is the same rule the docker launch chain
|
|
79
|
+
* states as "no command substitution", and the same trap that silently emptied
|
|
80
|
+
* `$TMUX_TMPDIR` while this probe was developed.
|
|
81
|
+
* A user who wants the crop instead of the resize can set `window-size largest`
|
|
82
|
+
* on their own session, which is theirs to set.
|
|
83
|
+
*
|
|
84
|
+
* @module foreign-tmux
|
|
85
|
+
*/
|
|
86
|
+
import type { ForeignPaneProbe, ForeignTmuxLocationKind } from './types/foreign-tmux.js';
|
|
87
|
+
import type { SessionAdopt, SessionMode } from './types/session.js';
|
|
88
|
+
/**
|
|
89
|
+
* The probe, as POSIX sh. NO SINGLE QUOTES (see @fileoverview).
|
|
90
|
+
*
|
|
91
|
+
* Emits, in order:
|
|
92
|
+
* CMFS<sep><socket path> (one per readable socket)
|
|
93
|
+
* CMFP<sep><socket><sep>...<sep>name<sep>path (one per pane on that socket)
|
|
94
|
+
* CMFH<sep><socket path> (a server that did not answer)
|
|
95
|
+
* CMFQ (marker; ps rows follow)
|
|
96
|
+
* <pid> <ppid> <argv...>
|
|
97
|
+
*
|
|
98
|
+
* The two free-form fields (session name, pane path) are LAST so a separator
|
|
99
|
+
* inside one of them can be re-joined by position instead of corrupting the row.
|
|
100
|
+
*/
|
|
101
|
+
export declare function buildForeignProbeScript(): string;
|
|
102
|
+
export interface ForeignProbeOutput {
|
|
103
|
+
panes: ForeignPaneProbe[];
|
|
104
|
+
/** parent pid to child pids, from the ONE `ps` snapshot (proc-tree input). */
|
|
105
|
+
byParent: Map<number, number[]>;
|
|
106
|
+
/** pid to full argv line. */
|
|
107
|
+
argvByPid: Map<number, string>;
|
|
108
|
+
/** Sockets seen, in scan order (may exceed the pane list when a socket is empty). */
|
|
109
|
+
sockets: string[];
|
|
110
|
+
/** Sockets whose server missed the per-socket bound, so their rows are absent. */
|
|
111
|
+
hungSockets: string[];
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Parse one probe's stdout. Never throws: a malformed row is skipped, not fatal.
|
|
115
|
+
*
|
|
116
|
+
* ⚠️ Runs synchronously on the server's event loop over text a process in a pane, a
|
|
117
|
+
* container or an ssh host wrote, so nothing here may cost more than linear time in it:
|
|
118
|
+
* the row caps do not help when one row is the whole 2 MiB.
|
|
119
|
+
*/
|
|
120
|
+
export declare function parseForeignProbeOutput(stdout: string): ForeignProbeOutput;
|
|
121
|
+
/**
|
|
122
|
+
* argv signatures, derived from the registry rather than written here.
|
|
123
|
+
*
|
|
124
|
+
* Matched against the WHOLE argv of a pane descendant, so `node .../bin/claude`
|
|
125
|
+
* hits the claude rule via the path. The binary names come from each entry's
|
|
126
|
+
* `discovery.binaries`, the one place that already knows a mode name is NOT
|
|
127
|
+
* always a binary name (`antigravity` runs `agy`). The hand-written table this
|
|
128
|
+
* replaces keyed on CLI ids, which CLAUDE.md forbids outside `stock.ts`, and it
|
|
129
|
+
* had already fallen behind: `omp` was missing, so a hand-started omp pane read
|
|
130
|
+
* as a plain shell.
|
|
131
|
+
*
|
|
132
|
+
* Resolved at CALL time, never into a module-level const: a CLI enabled (or a
|
|
133
|
+
* custom entry added) at runtime must be recognised without a restart.
|
|
134
|
+
*
|
|
135
|
+
* ⚠️ Longest name first. `pi` is two characters and its "command itself" form
|
|
136
|
+
* would otherwise be tried before `opencode`'s; length order is what keeps a
|
|
137
|
+
* short generic name from claiming a pane that belongs to a longer one.
|
|
138
|
+
*
|
|
139
|
+
* ⚠️ Names are regex-ESCAPED. They reach here from `~/.codeman/clis.json`, and
|
|
140
|
+
* while the schema's SHELL_TOKEN already refuses the dangerous shapes, building
|
|
141
|
+
* a pattern out of an unescaped foreign string is how a config value turns into
|
|
142
|
+
* a regex. Escaping means the worst a bad name can do is match nothing.
|
|
143
|
+
*
|
|
144
|
+
* ⚠️ Keep these free of unbounded tails, since each one runs over someone else's argv on
|
|
145
|
+
* the event loop. The node launcher shape needs one, so it lives in `launcherPrefixes()`
|
|
146
|
+
* and `launcherDir` only has to name the directory.
|
|
147
|
+
*/
|
|
148
|
+
export declare function foreignCliSignatures(): ReadonlyArray<{
|
|
149
|
+
mode: SessionMode;
|
|
150
|
+
test: RegExp;
|
|
151
|
+
launcherDir: RegExp;
|
|
152
|
+
}>;
|
|
153
|
+
export interface ClassifiedPane {
|
|
154
|
+
mode: SessionMode;
|
|
155
|
+
/** The argv line the decision came from, truncated for display. */
|
|
156
|
+
command: string;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Decide what a pane is running.
|
|
160
|
+
*
|
|
161
|
+
* Order matters: the pane's own command is checked against the CLI signatures
|
|
162
|
+
* first (a pane running `claude` directly is unambiguous and needs no walk), then
|
|
163
|
+
* the bounded descendant walk, and only then the shell fallback. The walk is what
|
|
164
|
+
* separates claude from codex, since tmux reports `node` for both.
|
|
165
|
+
*/
|
|
166
|
+
export declare function classifyForeignPaneMode(pane: Pick<ForeignPaneProbe, 'panePid' | 'paneCurrentCommand'>, probe: Pick<ForeignProbeOutput, 'byParent' | 'argvByPid'>, match?: ForeignSignatureMatcher): ClassifiedPane;
|
|
167
|
+
export type ForeignSignatureMatcher = (argv: string) => SessionMode | null;
|
|
168
|
+
/**
|
|
169
|
+
* One scan's answer to "which CLI is this argv?".
|
|
170
|
+
*
|
|
171
|
+
* ⚠️ Scoped to a scan, because this is the cost no row cap bounds. A pane's walk reads up
|
|
172
|
+
* to PROC_WALK_MAX_NODES rows and every pane of a hostile host can claim the same tree, so
|
|
173
|
+
* the walks repeat one set of rows FOREIGN_MAX_PANES times. Building the regexes once and
|
|
174
|
+
* asking about each distinct argv once ties the work to the bytes the probe really carried.
|
|
175
|
+
*/
|
|
176
|
+
export declare function createForeignSignatureMatcher(): ForeignSignatureMatcher;
|
|
177
|
+
/**
|
|
178
|
+
* Is this pane one of Codeman's own, at any location?
|
|
179
|
+
*
|
|
180
|
+
* Excluding them is not cosmetic. Locally it stops Codeman from adopting its own
|
|
181
|
+
* sessions (which would attach a second PTY to a live pane). On a remote host or
|
|
182
|
+
* inside a container it stops the SAME session from being reachable through two
|
|
183
|
+
* different code paths: `remote-hosts.listRemoteCodemanSessions` already owns
|
|
184
|
+
* the `tmux -L codeman` case there, and two paths to one session is how the two
|
|
185
|
+
* end up disagreeing about ownership.
|
|
186
|
+
*
|
|
187
|
+
* @param ownSocket this instance's own socket name (`resolveTmuxSocketName()`),
|
|
188
|
+
* which is instance-scoped and therefore not a constant.
|
|
189
|
+
*/
|
|
190
|
+
export declare function isCodemanOwnedPane(pane: Pick<ForeignPaneProbe, 'socketPath' | 'sessionName'>, ownSocket: string): boolean;
|
|
191
|
+
/** Same rule, plus the path separator and no `..` climbing. */
|
|
192
|
+
export declare function isAdoptableSocketPath(socketPath: string): boolean;
|
|
193
|
+
/** True when this session name can cross the launch chain safely. */
|
|
194
|
+
export declare function isAdoptableSessionName(sessionName: string): boolean;
|
|
195
|
+
/**
|
|
196
|
+
* Stable, opaque id for a candidate. The browser sends this back to adopt, so it
|
|
197
|
+
* must survive a re-scan (same session gets the same id) without the browser ever
|
|
198
|
+
* handing us a socket path or session name to interpolate into a command.
|
|
199
|
+
*/
|
|
200
|
+
export declare function foreignSessionId(location: ForeignTmuxLocationKind, hostKey: string, socketPath: string, sessionName: string): string;
|
|
201
|
+
/**
|
|
202
|
+
* What names one foreign tmux session across every location Codeman can reach.
|
|
203
|
+
* A socket path and a session name are not enough on their own: a socket path is
|
|
204
|
+
* only meaningful INSIDE its location. Containers commonly run tmux as root
|
|
205
|
+
* (`/tmp/tmux-0/default`) with default names `0`, `1`, so session `0` in two
|
|
206
|
+
* containers is the same pair, and so is the same name on this machine and on an
|
|
207
|
+
* ssh host with the same uid.
|
|
208
|
+
*
|
|
209
|
+
* A `ForeignTmuxSession` candidate is one of these as it stands. A wrapper's
|
|
210
|
+
* `SessionAdopt` is turned into one by `adoptTargetIdentity()`.
|
|
211
|
+
*/
|
|
212
|
+
export interface ForeignTargetIdentity {
|
|
213
|
+
location: ForeignTmuxLocationKind;
|
|
214
|
+
/** Registry id of the docker or remote host. Absent for local. */
|
|
215
|
+
hostId?: string;
|
|
216
|
+
/** The container (`location === 'docker'`), which is only unique per engine, hence beside `hostId`. */
|
|
217
|
+
containerName?: string;
|
|
218
|
+
socketPath: string;
|
|
219
|
+
sessionName: string;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* The ONE key that decides "is this foreign session already wrapped?". The adopt
|
|
223
|
+
* route's one-wrapper-per-target check and the listing's `adoptedBy` both read it;
|
|
224
|
+
* two keys are how a row ends up offering a tab that belongs to another location.
|
|
225
|
+
*
|
|
226
|
+
* Unlike `foreignSessionId` this is not opaque, and it stays on the server: the
|
|
227
|
+
* opaque id encodes a discovery detail a restored wrapper does not carry, while
|
|
228
|
+
* everything here is on `SessionAdopt` too.
|
|
229
|
+
*/
|
|
230
|
+
export declare function foreignTargetKey(target: ForeignTargetIdentity): string;
|
|
231
|
+
/** A wrapper's adoption record, as the identity of the foreign session it wraps. */
|
|
232
|
+
export declare function adoptTargetIdentity(adopt: SessionAdopt): ForeignTargetIdentity;
|
|
233
|
+
/**
|
|
234
|
+
* Our grouped view session's name on the FOREIGN server. Deliberately prefixed
|
|
235
|
+
* `codeman-view-` so a human looking at their own `tmux ls` can see what joined
|
|
236
|
+
* them, and so a second Codeman's discovery excludes it (the `codeman-` prefix
|
|
237
|
+
* rule above).
|
|
238
|
+
*/
|
|
239
|
+
export declare function foreignViewSessionName(sessionId: string): string;
|
|
240
|
+
/** Single-quote for POSIX sh. Local copy so this module stays dependency-free. */
|
|
241
|
+
export declare function fshq(str: string): string;
|
|
242
|
+
export interface ForeignAttachTarget {
|
|
243
|
+
socketPath: string;
|
|
244
|
+
targetSession: string;
|
|
245
|
+
viewSession: string;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* The tmux invocation that joins a foreign session, as ONE line of POSIX sh.
|
|
249
|
+
*
|
|
250
|
+
* Shape and why:
|
|
251
|
+
* command -v tmux || { echo no tmux; exit 127; } ;
|
|
252
|
+
* tmux -S <sock> has-session -t '=<target>' || { echo gone; exit 1; } ;
|
|
253
|
+
* tmux -S <sock> kill-session -t '=<view>' 2>/dev/null ;
|
|
254
|
+
* exec tmux -u -S <sock> new-session -t <target> -s <view> ; set destroy-unattached on ; set status off
|
|
255
|
+
*
|
|
256
|
+
* - ⚠️ `command -v` first because the guard below fires on ANY failure, and "tmux is
|
|
257
|
+
* not on this PATH" (exit 127, hidden by the `2>/dev/null`) must not be told to the
|
|
258
|
+
* user as "your session is gone" while it is running.
|
|
259
|
+
* - `-u` on the client: in a POSIX locale it otherwise writes the tab as if the
|
|
260
|
+
* terminal were ASCII (measured: `_ hello qqq ____` for `❯ hello ─── 你好`). Only
|
|
261
|
+
* the join needs it, since the guard prints nothing and tmux compares a target
|
|
262
|
+
* name as bytes in any locale.
|
|
263
|
+
* - ⚠️ The `has-session` guard comes FIRST because `new-session -t` does not fail
|
|
264
|
+
* on a missing target, it invents one. Measured on tmux 3.4: with `work` gone it
|
|
265
|
+
* joined `work-prod`, with nothing matching it created a fresh shell, and on a
|
|
266
|
+
* socket with no server it STARTED one. This line re-runs every time the wrapper
|
|
267
|
+
* pane is respawned, and boot recovery does that for every dead pane, so once the
|
|
268
|
+
* owner exits their session the next Codeman restart would leave a new shell on
|
|
269
|
+
* their machine, in their container or on their ssh host. `=` is what makes the
|
|
270
|
+
* check exact (no prefix match), and `2>/dev/null` keeps tmux's own "no server"
|
|
271
|
+
* noise out of the pane: the message we print says it better. The check only holds
|
|
272
|
+
* for a name `new-session -t` also reads as a name, which is what
|
|
273
|
+
* `isAdoptableSessionName` keeps true (see `TMUX_TARGET_SYNTAX`).
|
|
274
|
+
* - ⚠️ The `=` prefix cannot stand in for that check on `new-session -t`: with the
|
|
275
|
+
* target gone tmux takes it as part of the name and creates a group literally
|
|
276
|
+
* called `=work`. It has to be a separate `has-session`.
|
|
277
|
+
* - `new-session -t` creates a session in the target's GROUP: same windows, our
|
|
278
|
+
* own session options and current window (NOT our own size, see @fileoverview
|
|
279
|
+
* for the measurement that disproved that).
|
|
280
|
+
* - `status off` is why grouping earns its keep: it lands on OUR session, so the
|
|
281
|
+
* owner's status bar is untouched.
|
|
282
|
+
* - No `-d`: the session must be attached before `destroy-unattached` lands on it.
|
|
283
|
+
* - The escaped semicolons reach tmux as plain command separators after one shell
|
|
284
|
+
* parse, the same convention the docker launch chain uses.
|
|
285
|
+
* - ⚠️ There is NO degraded fallback, on purpose. A read-only `attach-session -r`
|
|
286
|
+
* used to hang off `||` "for a tmux too old to group", but `||` fires on ANY
|
|
287
|
+
* `new-session` failure. The one that actually happens is a leftover view with
|
|
288
|
+
* the same name (the in-container leak described above): measured, `new-session`
|
|
289
|
+
* answers `duplicate session: codeman-view-…` and the fallback then handed the
|
|
290
|
+
* user a read-only client showing the owner's status bar, where everything typed
|
|
291
|
+
* is dropped while the API reports success. That is the worst shape a failure can
|
|
292
|
+
* take here. So: clear OUR OWN stale view first, then either group successfully
|
|
293
|
+
* or exit with a message.
|
|
294
|
+
* - The `kill-session` is safe by construction and cannot touch the human's work:
|
|
295
|
+
* the name is `codeman-view-<our own session id>`, `=` makes the match exact, and
|
|
296
|
+
* killing a session in a group removes only that session (measured: the owner's
|
|
297
|
+
* `work` survived its grouped view being killed). `2>/dev/null` because "no such
|
|
298
|
+
* session" is the normal case, not an error.
|
|
299
|
+
* - ⚠️ Nothing here touches the prefix table, unlike the nested servers Codeman runs
|
|
300
|
+
* itself (`nestedPrefixTableResetCommands`). Our own socket already has its table
|
|
301
|
+
* reduced by `createSession`, but key tables are SERVER-WIDE, so reducing the foreign
|
|
302
|
+
* one would rewrite the owner's keys for every session on their server, and it would
|
|
303
|
+
* outlive our detach. Same reason `window-size` is left alone above. The owner's
|
|
304
|
+
* bindings stay reachable from a tab, behind our own `send-prefix`, as theirs to use.
|
|
305
|
+
* - ⚠️ While the view exists the window has two sessions holding it, so an owner's
|
|
306
|
+
* `kill-session` on their own session leaves the window alive under the view
|
|
307
|
+
* (measured on tmux 3.4: `tmux ls` then shows only `codeman-view-…`, the shell keeps
|
|
308
|
+
* running) until the tab closes and `destroy-unattached` lets go of it. Exiting the
|
|
309
|
+
* shell inside the pane ends it at once, view and all. Nothing here can tell the two
|
|
310
|
+
* apart without a hook on the owner's server, which is not ours to install.
|
|
311
|
+
* - Single line: nothing here needs a second one. A real newline would survive
|
|
312
|
+
* `bash -c` now (`bashCArg()`), though not the JSON escaping this line crossed before.
|
|
313
|
+
*/
|
|
314
|
+
export declare function buildForeignTmuxInvocation(target: ForeignAttachTarget): string;
|
|
315
|
+
/** Local adoption: run the invocation directly in the wrapper pane. */
|
|
316
|
+
export declare function buildForeignAttachCommand(target: ForeignAttachTarget): string;
|
|
317
|
+
export interface ForeignDockerAttachOptions extends ForeignAttachTarget {
|
|
318
|
+
/** `buildDockerBaseArgs(...)` joined, e.g. `docker` or `docker --context foo`. */
|
|
319
|
+
dockerBase: string;
|
|
320
|
+
containerName: string;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Docker adoption: `docker exec -it` into the container and attach there.
|
|
324
|
+
*
|
|
325
|
+
* Mirrors the ADOPTED-container branch of `buildDockerLaunchCommand`: look, then
|
|
326
|
+
* exec. Never `create`, never `start`: the container belongs to the user, and a
|
|
327
|
+
* missing or stopped one fails closed with a message instead of being mutated.
|
|
328
|
+
*/
|
|
329
|
+
export declare function buildForeignDockerAttachCommand(opts: ForeignDockerAttachOptions): string;
|
|
330
|
+
/**
|
|
331
|
+
* Tear down OUR grouped view session inside a container.
|
|
332
|
+
*
|
|
333
|
+
* ⚠️ Needed for docker and NOT for the other two, which is a docker fact rather
|
|
334
|
+
* than a design choice. Killing the wrapper pane kills a LOCAL tmux client
|
|
335
|
+
* directly, and over ssh it sends SIGHUP to the remote client (the same
|
|
336
|
+
* propagation the non-owned remote attach has relied on since COD-105), either
|
|
337
|
+
* way the client detaches and `destroy-unattached on` collects the view.
|
|
338
|
+
* A `docker exec` process does NOT die when its client goes away: measured, the
|
|
339
|
+
* in-container tmux client stayed attached after the wrapper was killed, so the
|
|
340
|
+
* view session survived forever and every adoption leaked one of them plus its
|
|
341
|
+
* exec process.
|
|
342
|
+
*
|
|
343
|
+
* Killing a session by name affects ONLY that session, never the group's other
|
|
344
|
+
* members, so this can only ever remove the view Codeman created, never the
|
|
345
|
+
* human's session it is grouped with. Sibling of `buildDockerKillCommand`, and
|
|
346
|
+
* fired best-effort on the same path.
|
|
347
|
+
*/
|
|
348
|
+
export declare function buildForeignDockerViewKillCommand(opts: {
|
|
349
|
+
dockerBase: string;
|
|
350
|
+
containerName: string;
|
|
351
|
+
socketPath: string;
|
|
352
|
+
viewSession: string;
|
|
353
|
+
}): string;
|
|
354
|
+
/**
|
|
355
|
+
* A POSIX script as the command line of an ssh connection.
|
|
356
|
+
*
|
|
357
|
+
* ssh hands its command to the remote user's LOGIN shell, which may be fish: the
|
|
358
|
+
* guard chain's `{ ...; }` and the probe's `${VAR:-x}` are POSIX, so they run in an
|
|
359
|
+
* explicit `sh`. The PATH line stays outside it because it is the part written for
|
|
360
|
+
* whatever that shell is (`withRemoteTmuxPath`), and sshd's non-interactive PATH can
|
|
361
|
+
* miss a Homebrew or per-user tmux, the same reason every other remote tmux call has
|
|
362
|
+
* it. Single-quote-free input stays single-quote-free here, and `exec` keeps the
|
|
363
|
+
* process tree one level shorter.
|
|
364
|
+
*/
|
|
365
|
+
export declare function foreignRemoteShellCommand(script: string): string;
|
|
366
|
+
export interface ForeignRemoteAttachOptions extends ForeignAttachTarget {
|
|
367
|
+
/** `buildSshConnectionArgs(host)`: `['ssh', '-o BatchMode=yes', ...]`. */
|
|
368
|
+
sshArgs: string[];
|
|
369
|
+
/** `remoteSshTarget(host)`: `user@host`. */
|
|
370
|
+
sshTarget: string;
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Remote adoption: ssh in and attach there.
|
|
374
|
+
*
|
|
375
|
+
* `-t` goes right after `ssh -o BatchMode=yes`, exactly where
|
|
376
|
+
* `buildRemoteAttachCommand` puts it: interactive tmux needs a PTY. Connection
|
|
377
|
+
* options come from the shared `buildSshConnectionArgs`, never hand-built here,
|
|
378
|
+
* so adoption reaches a proxied/custom-port host on the same terms discovery did.
|
|
379
|
+
*/
|
|
380
|
+
export declare function buildForeignRemoteAttachCommand(opts: ForeignRemoteAttachOptions): string;
|
|
381
|
+
//# sourceMappingURL=foreign-tmux.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foreign-tmux.d.ts","sourceRoot":"","sources":["../src/foreign-tmux.ts"],"names":[],"mappings":"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"}
|