botmux 1.0.0 → 1.2.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 (96) hide show
  1. package/.env.example +3 -4
  2. package/README.en.md +44 -5
  3. package/README.md +44 -5
  4. package/dist/adapters/backend/tmux-backend.d.ts +33 -7
  5. package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
  6. package/dist/adapters/backend/tmux-backend.js +123 -13
  7. package/dist/adapters/backend/tmux-backend.js.map +1 -1
  8. package/dist/adapters/backend/types.d.ts +3 -0
  9. package/dist/adapters/backend/types.d.ts.map +1 -1
  10. package/dist/adapters/cli/aiden.d.ts.map +1 -1
  11. package/dist/adapters/cli/aiden.js +4 -0
  12. package/dist/adapters/cli/aiden.js.map +1 -1
  13. package/dist/adapters/cli/claude-code.d.ts.map +1 -1
  14. package/dist/adapters/cli/claude-code.js +5 -0
  15. package/dist/adapters/cli/claude-code.js.map +1 -1
  16. package/dist/adapters/cli/coco.d.ts.map +1 -1
  17. package/dist/adapters/cli/coco.js +5 -0
  18. package/dist/adapters/cli/coco.js.map +1 -1
  19. package/dist/adapters/cli/codex.d.ts.map +1 -1
  20. package/dist/adapters/cli/codex.js +3 -0
  21. package/dist/adapters/cli/codex.js.map +1 -1
  22. package/dist/adapters/cli/types.d.ts +3 -0
  23. package/dist/adapters/cli/types.d.ts.map +1 -1
  24. package/dist/cli.js +1 -4
  25. package/dist/cli.js.map +1 -1
  26. package/dist/config.d.ts +1 -0
  27. package/dist/config.d.ts.map +1 -1
  28. package/dist/config.js +13 -2
  29. package/dist/config.js.map +1 -1
  30. package/dist/core/command-handler.d.ts.map +1 -1
  31. package/dist/core/command-handler.js +8 -7
  32. package/dist/core/command-handler.js.map +1 -1
  33. package/dist/core/session-manager.d.ts +2 -0
  34. package/dist/core/session-manager.d.ts.map +1 -1
  35. package/dist/core/session-manager.js +37 -5
  36. package/dist/core/session-manager.js.map +1 -1
  37. package/dist/core/worker-pool.d.ts.map +1 -1
  38. package/dist/core/worker-pool.js +41 -0
  39. package/dist/core/worker-pool.js.map +1 -1
  40. package/dist/daemon.d.ts.map +1 -1
  41. package/dist/daemon.js +28 -11
  42. package/dist/daemon.js.map +1 -1
  43. package/dist/im/lark/client.d.ts +2 -3
  44. package/dist/im/lark/client.d.ts.map +1 -1
  45. package/dist/im/lark/client.js +5 -16
  46. package/dist/im/lark/client.js.map +1 -1
  47. package/dist/services/project-scanner.d.ts +4 -0
  48. package/dist/services/project-scanner.d.ts.map +1 -1
  49. package/dist/services/project-scanner.js +22 -0
  50. package/dist/services/project-scanner.js.map +1 -1
  51. package/dist/types.d.ts +2 -0
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/types.js.map +1 -1
  54. package/dist/utils/logger.d.ts.map +1 -1
  55. package/dist/utils/logger.js +13 -6
  56. package/dist/utils/logger.js.map +1 -1
  57. package/dist/worker.js +30 -5
  58. package/dist/worker.js.map +1 -1
  59. package/ecosystem.config.cjs +2 -2
  60. package/package.json +1 -1
  61. package/dist/scheduler.d.ts +0 -38
  62. package/dist/scheduler.d.ts.map +0 -1
  63. package/dist/scheduler.js +0 -221
  64. package/dist/scheduler.js.map +0 -1
  65. package/dist/services/lark-client.d.ts +0 -22
  66. package/dist/services/lark-client.d.ts.map +0 -1
  67. package/dist/services/lark-client.js +0 -238
  68. package/dist/services/lark-client.js.map +0 -1
  69. package/dist/services/lark-ws.d.ts +0 -5
  70. package/dist/services/lark-ws.d.ts.map +0 -1
  71. package/dist/services/lark-ws.js +0 -79
  72. package/dist/services/lark-ws.js.map +0 -1
  73. package/dist/services/message-router.d.ts +0 -8
  74. package/dist/services/message-router.d.ts.map +0 -1
  75. package/dist/services/message-router.js +0 -73
  76. package/dist/services/message-router.js.map +0 -1
  77. package/dist/tools/close-session.d.ts +0 -22
  78. package/dist/tools/close-session.d.ts.map +0 -1
  79. package/dist/tools/close-session.js +0 -38
  80. package/dist/tools/close-session.js.map +0 -1
  81. package/dist/tools/create-session.d.ts +0 -28
  82. package/dist/tools/create-session.d.ts.map +0 -1
  83. package/dist/tools/create-session.js +0 -40
  84. package/dist/tools/create-session.js.map +0 -1
  85. package/dist/tools/wait-for-reply.d.ts +0 -17
  86. package/dist/tools/wait-for-reply.d.ts.map +0 -1
  87. package/dist/tools/wait-for-reply.js +0 -65
  88. package/dist/tools/wait-for-reply.js.map +0 -1
  89. package/dist/utils/card-builder.d.ts +0 -16
  90. package/dist/utils/card-builder.d.ts.map +0 -1
  91. package/dist/utils/card-builder.js +0 -183
  92. package/dist/utils/card-builder.js.map +0 -1
  93. package/dist/utils/message-parser.d.ts +0 -45
  94. package/dist/utils/message-parser.d.ts.map +0 -1
  95. package/dist/utils/message-parser.js +0 -132
  96. package/dist/utils/message-parser.js.map +0 -1
package/.env.example CHANGED
@@ -7,11 +7,10 @@ LARK_APP_SECRET=
7
7
 
8
8
  # Daemon settings
9
9
  # CLI_ID=claude-code # CLI adapter: claude-code, aiden, coco, codex
10
- # WORKING_DIR=~ # Default working directory
10
+ # WORKING_DIR=~ # Default working directory (comma-separated for multiple dirs, e.g. ~/projects,~/work)
11
11
 
12
- # Access control (comma-separated email prefixes or Lark open_ids, empty = allow all)
13
- # ALLOWED_USERS=alice,bob
14
- # LARK_EMAIL_DOMAIN=example.com # Default email domain for ALLOWED_USERS prefixes
12
+ # Access control (comma-separated emails or Lark open_ids, empty = allow all)
13
+ # ALLOWED_USERS=alice@example.com,ou_xxxx
15
14
 
16
15
  # Project scanning directory for /repo command (default: parent of WORKING_DIR)
17
16
  # PROJECT_SCAN_DIR=
package/README.en.md CHANGED
@@ -4,13 +4,17 @@
4
4
 
5
5
  Bridge between Lark (Feishu) topic groups and AI coding CLIs. The daemon listens for Lark messages and automatically spawns an independent CLI process (supporting Claude Code, Aiden, CoCo, Codex) for each new topic thread, with live streaming cards and a web-based terminal.
6
6
 
7
+ ## Demo
8
+
9
+ <video src="https://github.com/user-attachments/assets/840d3bb6-3b98-465a-8662-b4beadeb48ce" width="100%" controls></video>
10
+
7
11
  ## Features
8
12
 
9
13
  - **One topic = one AI coding session** — each Lark thread gets its own isolated CLI process
10
14
  - **Multi-CLI support** — adapter architecture supports Claude Code, Aiden, CoCo, Codex, and is extensible
11
15
  - **Live streaming cards** — real-time terminal output rendered in Feishu cards with markdown support, per-turn card lifecycle
12
16
  - **Web terminal (xterm.js)** — full PTY output in the browser with optional write access via on-demand DM link
13
- - **Session persistence** — sessions survive daemon restarts and resume automatically
17
+ - **Session persistence** — sessions survive daemon restarts; with tmux backend, CLI processes persist across restarts with zero interruption
14
18
  - **Scheduled tasks** — cron-based recurring prompts with natural language scheduling (Chinese supported)
15
19
  - **Project management** — interactive repo selector, per-session working directory
16
20
  - **MCP integration** — CLI can reply to Lark threads, read message history, and add reactions via MCP tools
@@ -31,7 +35,7 @@ Daemon (daemon.ts → core/ modules)
31
35
  |
32
36
  Worker (worker.ts) -- forked child process per session
33
37
  |-- adapters/cli/*: CLI adapters (Claude Code / Aiden / CoCo / Codex)
34
- |-- adapters/backend/pty-backend: pseudo-terminal management (node-pty)
38
+ |-- adapters/backend: PtyBackend (node-pty) or TmuxBackend (tmux + node-pty)
35
39
  |-- utils/idle-detector: idle detection (quiescence + spinner + completion marker)
36
40
  |-- HTTP + WebSocket server: serves xterm.js web terminal
37
41
  |-- Headless xterm: captures screen for streaming cards
@@ -49,6 +53,7 @@ Lark API
49
53
  - **Node.js** >= 20
50
54
  - **AI coding CLI** installed and authenticated (`claude`, `aiden`, `coco`, or `codex` in PATH)
51
55
  - **Lark app** with Bot and Message permissions (WebSocket event subscription)
56
+ - **tmux** >= 3.x (optional — auto-enabled when installed for persistent CLI sessions)
52
57
 
53
58
  ## Installation
54
59
 
@@ -100,8 +105,8 @@ Configuration is stored at `~/.botmux/.env`. Run `botmux setup` to create it int
100
105
  |----------|---------|-------------|
101
106
  | `CLI_ID` | `claude-code` | CLI adapter (`claude-code`, `aiden`, `coco`, `codex`) |
102
107
  | `CLI_PATH` | _(auto-detect by CLI_ID)_ | CLI binary path override |
103
- | `BACKEND_TYPE` | `pty` | Session backend (`pty`, `tmux`) |
104
- | `WORKING_DIR` | `~` | Default working directory |
108
+ | `BACKEND_TYPE` | _(auto-detect)_ | Session backend: `tmux` if available, otherwise `pty` |
109
+ | `WORKING_DIR` | `~` | Default working directory; supports comma-separated multiple dirs (e.g. `~/a,~/b`), `/repo` scans all |
105
110
  | `ALLOWED_USERS` | _(empty = allow all)_ | Comma-separated email prefixes or Lark open_ids |
106
111
  | `PROJECT_SCAN_DIR` | _(parent of CWD)_ | Directory to scan for git repos |
107
112
  | `WEB_HOST` | `0.0.0.0` | HTTP server bind address |
@@ -183,6 +188,40 @@ Each session exposes a web terminal at `http://<WEB_EXTERNAL_HOST>:<port>`.
183
188
 
184
189
  Features: xterm.js with fit/unicode11/web-links addons, TokyoNight theme, scrollback buffer, mobile-friendly viewport.
185
190
 
191
+ ### Tmux Persistent Sessions
192
+
193
+ When tmux is installed, botmux automatically uses the tmux backend (pty-under-tmux architecture). CLI processes run inside tmux sessions while the daemon attaches via node-pty to capture output — streaming cards, idle detection, and web terminal all work unchanged.
194
+
195
+ **Key benefit: daemon restarts don't interrupt the CLI.** During `botmux restart`, the worker process exits but the tmux session (and the CLI inside it) keeps running. The next incoming message triggers a re-attach — no `--resume` context reload needed.
196
+
197
+ ```bash
198
+ # List active botmux tmux sessions
199
+ tmux list-sessions | grep bmx-
200
+
201
+ # Manually attach for debugging (observe CLI in real time)
202
+ tmux attach -t bmx-<first-8-chars-of-session-id>
203
+ # Ctrl+B, D to detach — CLI keeps running
204
+
205
+ # Force pure pty mode (disable tmux)
206
+ BACKEND_TYPE=pty botmux start
207
+ ```
208
+
209
+ **Session naming:** `bmx-<first 8 chars of session UUID>`, deterministically derived.
210
+
211
+ **Lifecycle:**
212
+
213
+ | Event | tmux session | CLI process |
214
+ |-------|-------------|-------------|
215
+ | `botmux restart` | Survives | Survives (re-attaches on next message) |
216
+ | `/close` or close button | Destroyed | Terminated (SIGHUP) |
217
+ | CLI exits / crashes | Closes with it | Already exited (auto-restart creates new session) |
218
+ | `CLI_ID` changed + restart | All destroyed | All terminated (prevents pattern mismatch) |
219
+
220
+ **Notes:**
221
+ - Switching `CLI_ID` (e.g. `claude-code` → `coco`) and restarting the daemon will kill all existing tmux sessions, since the old CLI's idle detection patterns are incompatible with the new adapter
222
+ - Orphaned tmux sessions (not in the active session list) are cleaned up automatically on daemon startup
223
+ - Set `BACKEND_TYPE=pty` to opt out of tmux persistence
224
+
186
225
  ## MCP Tools
187
226
 
188
227
  Claude Code has access to three MCP tools for interacting with Lark:
@@ -230,7 +269,7 @@ src/
230
269
  backend/
231
270
  types.ts # SessionBackend interface
232
271
  pty-backend.ts # node-pty backend
233
- tmux-backend.ts # tmux backend (stub)
272
+ tmux-backend.ts # tmux backend (pty-under-tmux, persistent sessions)
234
273
  core/
235
274
  types.ts # DaemonSession core type
236
275
  worker-pool.ts # Worker process pool management
package/README.md CHANGED
@@ -4,13 +4,17 @@
4
4
 
5
5
  飞书话题群与 AI 编程 CLI 的桥接工具。Daemon 监听飞书消息,为每个新话题自动启动一个独立的 CLI 进程(支持 Claude Code、Aiden、CoCo、Codex),提供实时流式卡片和 Web 终端。
6
6
 
7
+ ## 演示
8
+
9
+ <video src="https://github.com/user-attachments/assets/840d3bb6-3b98-465a-8662-b4beadeb48ce" width="100%" controls></video>
10
+
7
11
  ## 功能特性
8
12
 
9
13
  - **一个话题 = 一个 AI 编程会话** — 每个飞书话题线程对应一个独立的 CLI 进程
10
14
  - **多 CLI 支持** — 通过适配器架构支持 Claude Code、Aiden、CoCo、Codex,可扩展
11
15
  - **实时流式卡片** — 终端输出实时渲染到飞书卡片中,支持 Markdown 格式,每轮对话独立卡片
12
16
  - **Web 终端 (xterm.js)** — 浏览器查看完整 PTY 输出,按需获取可操作链接
13
- - **会话持久化** — 会话在 Daemon 重启后自动恢复
17
+ - **会话持久化** — 会话在 Daemon 重启后自动恢复;tmux 后端下 CLI 进程常驻,重启零中断
14
18
  - **定时任务** — 基于 Cron 的周期性任务,支持中文自然语言配置
15
19
  - **项目管理** — 交互式仓库选择器,每个会话独立工作目录
16
20
  - **MCP 集成** — CLI 可通过 MCP 工具回复飞书话题、读取消息历史、添加表情回应
@@ -31,7 +35,7 @@ Daemon (daemon.ts → core/ 模块)
31
35
  |
32
36
  Worker (worker.ts) -- 每个会话 fork 一个子进程
33
37
  |-- adapters/cli/*: CLI 适配器 (Claude Code / Aiden / CoCo / Codex)
34
- |-- adapters/backend/pty-backend: 伪终端管理 (node-pty)
38
+ |-- adapters/backend: PtyBackend (node-pty) 或 TmuxBackend (tmux + node-pty)
35
39
  |-- utils/idle-detector: 空闲检测(静默 + Spinner + 完成标记)
36
40
  |-- HTTP + WebSocket: 提供 xterm.js Web 终端
37
41
  |-- Headless xterm: 捕获屏幕内容用于流式卡片
@@ -49,6 +53,7 @@ AI 编程 CLI (交互式 TTY 模式)
49
53
  - **Node.js** >= 20
50
54
  - **AI 编程 CLI** 已安装并完成认证(`claude`、`aiden`、`coco` 或 `codex` 在 PATH 中)
51
55
  - **飞书应用** 具备机器人和消息权限(WebSocket 事件订阅)
56
+ - **tmux** >= 3.x(可选,安装后自动启用会话常驻)
52
57
 
53
58
  ## 安装
54
59
 
@@ -100,8 +105,8 @@ botmux start
100
105
  |------|--------|------|
101
106
  | `CLI_ID` | `claude-code` | CLI 适配器(`claude-code`、`aiden`、`coco`、`codex`) |
102
107
  | `CLI_PATH` | _(按 CLI_ID 自动检测)_ | CLI 可执行文件路径覆盖 |
103
- | `BACKEND_TYPE` | `pty` | 会话后端(`pty`、`tmux`) |
104
- | `WORKING_DIR` | `~` | 默认工作目录 |
108
+ | `BACKEND_TYPE` | _(自动检测)_ | 会话后端:有 tmux 则用 `tmux`,否则 `pty` |
109
+ | `WORKING_DIR` | `~` | 默认工作目录,支持逗号分隔多个目录(如 `~/a,~/b`),`/repo` 会扫描所有目录 |
105
110
  | `ALLOWED_USERS` | _(空 = 不限制)_ | 允许的用户,邮箱前缀或 open_id,逗号分隔 |
106
111
  | `PROJECT_SCAN_DIR` | _(工作目录的上级)_ | 扫描 Git 仓库的目录 |
107
112
  | `WEB_HOST` | `0.0.0.0` | HTTP 服务绑定地址 |
@@ -183,6 +188,40 @@ botmux start
183
188
 
184
189
  特性:xterm.js + fit/unicode11/web-links 插件、TokyoNight 主题、滚动缓冲区、移动端适配。
185
190
 
191
+ ### Tmux 会话常驻
192
+
193
+ 安装 tmux 后,botmux 自动使用 tmux 后端(`pty-under-tmux` 架构)。CLI 进程运行在 tmux session 内,daemon 通过 node-pty attach 到 tmux 来捕获输出,现有的流式卡片、空闲检测、Web 终端等功能全部不受影响。
194
+
195
+ **核心收益:Daemon 重启不中断 CLI。** `botmux restart` 时 worker 进程退出,但 tmux session(及其中的 CLI 进程)保持运行。下次收到消息时 worker 自动 re-attach,无需 `--resume` 重载上下文。
196
+
197
+ ```bash
198
+ # 查看活跃的 botmux tmux 会话
199
+ tmux list-sessions | grep bmx-
200
+
201
+ # 手动 attach 调试(实时观察 CLI 终端)
202
+ tmux attach -t bmx-<session-id-前8位>
203
+ # Ctrl+B, D 退出 attach,不影响 CLI 继续运行
204
+
205
+ # 强制降级到纯 pty 模式(不使用 tmux)
206
+ BACKEND_TYPE=pty botmux start
207
+ ```
208
+
209
+ **tmux 会话命名规则:** `bmx-<sessionId 前 8 位>`,由 session UUID 确定性派生。
210
+
211
+ **生命周期:**
212
+
213
+ | 事件 | tmux session | CLI 进程 |
214
+ |------|-------------|---------|
215
+ | `botmux restart` | 存活 | 存活(下次消息 re-attach) |
216
+ | `/close` 或关闭按钮 | 销毁 | 终止(SIGHUP) |
217
+ | CLI 自行退出 / 崩溃 | 随之关闭 | 已退出(自动重启用新 session) |
218
+ | 切换 `CLI_ID` 后重启 | 全部销毁 | 全部终止(防止 pattern 不匹配) |
219
+
220
+ **注意事项:**
221
+ - 切换 `CLI_ID`(如 `claude-code` → `coco`)后重启 daemon,所有旧 tmux session 会被自动清理,因为旧 CLI 的 idle detection pattern 与新适配器不兼容
222
+ - 孤儿 tmux session(不在 active session 列表中的)会在 daemon 启动时自动清理
223
+ - 如果不需要 tmux 常驻特性,设置 `BACKEND_TYPE=pty` 即可降级
224
+
186
225
  ## MCP 工具
187
226
 
188
227
  Claude Code 可使用三个 MCP 工具与飞书交互:
@@ -230,7 +269,7 @@ src/
230
269
  backend/
231
270
  types.ts # SessionBackend 接口
232
271
  pty-backend.ts # node-pty 后端
233
- tmux-backend.ts # tmux 后端(stub)
272
+ tmux-backend.ts # tmux 后端(pty-under-tmux,会话常驻)
234
273
  core/
235
274
  types.ts # DaemonSession 核心类型
236
275
  worker-pool.ts # Worker 进程池管理
@@ -1,17 +1,43 @@
1
1
  import type { SessionBackend, SpawnOpts } from './types.js';
2
2
  /**
3
- * TmuxBackend — experimental session backend using tmux.
4
- * Enables: physical `tmux attach`, web terminal, and IM all on same session.
5
- * TODO: Full implementation.
3
+ * TmuxBackend — session backend using tmux for process persistence.
4
+ *
5
+ * Architecture: pty-under-tmux.
6
+ * - A node-pty process runs `tmux new-session` or `tmux attach-session`
7
+ * - All output flows through the pty (onData/onExit work unchanged)
8
+ * - kill() only detaches (kills the pty viewer), tmux session survives
9
+ * - destroySession() kills the tmux session (for explicit /close)
10
+ *
11
+ * Naming: tmux sessions are named `bmx-<sessionId.slice(0,8)>`.
6
12
  */
7
13
  export declare class TmuxBackend implements SessionBackend {
8
- private sessionName;
14
+ private process;
15
+ private readonly sessionName;
16
+ private reattaching;
17
+ constructor(sessionName: string);
18
+ /** Check if tmux binary is available on PATH. */
19
+ static isAvailable(): boolean;
20
+ /** Derive tmux session name from a session UUID. */
21
+ static sessionName(sessionId: string): string;
22
+ /** Check if a named tmux session exists. */
23
+ static hasSession(name: string): boolean;
24
+ /** Kill a named tmux session (no-op if it doesn't exist). */
25
+ static killSession(name: string): void;
26
+ /** List all botmux tmux sessions (bmx-* prefix). */
27
+ static listBotmuxSessions(): string[];
9
28
  spawn(bin: string, args: string[], opts: SpawnOpts): void;
29
+ /** Whether the last spawn() re-attached to an existing tmux session. */
30
+ get isReattach(): boolean;
10
31
  write(data: string): void;
11
- resize(_cols: number, _rows: number): void;
12
- onData(_cb: (data: string) => void): void;
13
- onExit(_cb: (code: number | null, signal: string | null) => void): void;
32
+ resize(cols: number, rows: number): void;
33
+ /** Must be called AFTER spawn(). Callbacks registered before spawn are silently lost. */
34
+ onData(cb: (data: string) => void): void;
35
+ /** Must be called AFTER spawn(). Callbacks registered before spawn are silently lost. */
36
+ onExit(cb: (code: number | null, signal: string | null) => void): void;
37
+ /** Detach only — kills the pty viewer but leaves tmux session alive. */
14
38
  kill(): void;
39
+ /** Kill the tmux session permanently. Called on explicit /close. */
40
+ destroySession(): void;
15
41
  getAttachInfo(): {
16
42
  type: "tmux";
17
43
  sessionName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"tmux-backend.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/tmux-backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;GAIG;AACH,qBAAa,WAAY,YAAW,cAAc;IAChD,OAAO,CAAC,WAAW,CAAM;IAEzB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAIzD,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIzB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAI1C,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIzC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI;IAIvE,IAAI,IAAI,IAAI;IAIZ,aAAa;;;;CAGd"}
1
+ {"version":3,"file":"tmux-backend.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/tmux-backend.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;;;;;;;GAUG;AACH,qBAAa,WAAY,YAAW,cAAc;IAChD,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,WAAW,CAAS;gBAEhB,WAAW,EAAE,MAAM;IAM/B,iDAAiD;IACjD,MAAM,CAAC,WAAW,IAAI,OAAO;IAS7B,oDAAoD;IACpD,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI7C,4CAA4C;IAC5C,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IASxC,6DAA6D;IAC7D,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMtC,oDAAoD;IACpD,MAAM,CAAC,kBAAkB,IAAI,MAAM,EAAE;IAarC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IA+BzD,wEAAwE;IACxE,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIzB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAIxC,yFAAyF;IACzF,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIxC,yFAAyF;IACzF,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI;IAMtE,wEAAwE;IACxE,IAAI,IAAI,IAAI;IAOZ,oEAAoE;IACpE,cAAc,IAAI,IAAI;IAKtB,aAAa;;;;CAGd"}
@@ -1,30 +1,140 @@
1
+ import * as pty from 'node-pty';
2
+ import { execSync } from 'node:child_process';
1
3
  /**
2
- * TmuxBackend — experimental session backend using tmux.
3
- * Enables: physical `tmux attach`, web terminal, and IM all on same session.
4
- * TODO: Full implementation.
4
+ * TmuxBackend — session backend using tmux for process persistence.
5
+ *
6
+ * Architecture: pty-under-tmux.
7
+ * - A node-pty process runs `tmux new-session` or `tmux attach-session`
8
+ * - All output flows through the pty (onData/onExit work unchanged)
9
+ * - kill() only detaches (kills the pty viewer), tmux session survives
10
+ * - destroySession() kills the tmux session (for explicit /close)
11
+ *
12
+ * Naming: tmux sessions are named `bmx-<sessionId.slice(0,8)>`.
5
13
  */
6
14
  export class TmuxBackend {
7
- sessionName = '';
15
+ process = null;
16
+ sessionName;
17
+ reattaching = false;
18
+ constructor(sessionName) {
19
+ this.sessionName = sessionName;
20
+ }
21
+ // ─── Static helpers ───────────────────────────────────────────────────────
22
+ /** Check if tmux binary is available on PATH. */
23
+ static isAvailable() {
24
+ try {
25
+ execSync('tmux -V', { stdio: 'ignore' });
26
+ return true;
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ }
32
+ /** Derive tmux session name from a session UUID. */
33
+ static sessionName(sessionId) {
34
+ return `bmx-${sessionId.slice(0, 8)}`;
35
+ }
36
+ /** Check if a named tmux session exists. */
37
+ static hasSession(name) {
38
+ try {
39
+ execSync(`tmux has-session -t ${shellescape(name)}`, { stdio: 'ignore' });
40
+ return true;
41
+ }
42
+ catch {
43
+ return false;
44
+ }
45
+ }
46
+ /** Kill a named tmux session (no-op if it doesn't exist). */
47
+ static killSession(name) {
48
+ try {
49
+ execSync(`tmux kill-session -t ${shellescape(name)}`, { stdio: 'ignore' });
50
+ }
51
+ catch { /* session doesn't exist */ }
52
+ }
53
+ /** List all botmux tmux sessions (bmx-* prefix). */
54
+ static listBotmuxSessions() {
55
+ try {
56
+ const out = execSync("tmux list-sessions -F '#{session_name}' 2>/dev/null", {
57
+ encoding: 'utf-8',
58
+ });
59
+ return out.split('\n').filter(s => s.startsWith('bmx-'));
60
+ }
61
+ catch {
62
+ return [];
63
+ }
64
+ }
65
+ // ─── SessionBackend implementation ────────────────────────────────────────
8
66
  spawn(bin, args, opts) {
9
- throw new Error('TmuxBackend is not yet implemented');
67
+ this.reattaching = TmuxBackend.hasSession(this.sessionName);
68
+ if (this.reattaching) {
69
+ // Re-attach to surviving tmux session (CLI is still running)
70
+ this.process = pty.spawn('tmux', ['attach-session', '-t', this.sessionName], {
71
+ name: 'xterm-256color',
72
+ cols: opts.cols,
73
+ rows: opts.rows,
74
+ cwd: opts.cwd,
75
+ env: opts.env,
76
+ });
77
+ }
78
+ else {
79
+ // Create new tmux session running the CLI command
80
+ const tmuxArgs = [
81
+ 'new-session',
82
+ '-s', this.sessionName,
83
+ '-x', String(opts.cols),
84
+ '-y', String(opts.rows),
85
+ '--', bin, ...args,
86
+ ];
87
+ this.process = pty.spawn('tmux', tmuxArgs, {
88
+ name: 'xterm-256color',
89
+ cols: opts.cols,
90
+ rows: opts.rows,
91
+ cwd: opts.cwd,
92
+ env: opts.env,
93
+ });
94
+ }
95
+ }
96
+ /** Whether the last spawn() re-attached to an existing tmux session. */
97
+ get isReattach() {
98
+ return this.reattaching;
10
99
  }
11
100
  write(data) {
12
- throw new Error('TmuxBackend is not yet implemented');
101
+ this.process?.write(data);
13
102
  }
14
- resize(_cols, _rows) {
15
- // tmux resize is handled by the attaching client
103
+ resize(cols, rows) {
104
+ this.process?.resize(cols, rows);
16
105
  }
17
- onData(_cb) {
18
- throw new Error('TmuxBackend is not yet implemented');
106
+ /** Must be called AFTER spawn(). Callbacks registered before spawn are silently lost. */
107
+ onData(cb) {
108
+ this.process?.onData(cb);
19
109
  }
20
- onExit(_cb) {
21
- throw new Error('TmuxBackend is not yet implemented');
110
+ /** Must be called AFTER spawn(). Callbacks registered before spawn are silently lost. */
111
+ onExit(cb) {
112
+ this.process?.onExit(({ exitCode, signal }) => {
113
+ cb(exitCode, signal !== undefined ? String(signal) : null);
114
+ });
22
115
  }
116
+ /** Detach only — kills the pty viewer but leaves tmux session alive. */
23
117
  kill() {
24
- throw new Error('TmuxBackend is not yet implemented');
118
+ if (this.process) {
119
+ try {
120
+ this.process.kill();
121
+ }
122
+ catch { /* already dead */ }
123
+ this.process = null;
124
+ }
125
+ }
126
+ /** Kill the tmux session permanently. Called on explicit /close. */
127
+ destroySession() {
128
+ this.kill();
129
+ TmuxBackend.killSession(this.sessionName);
25
130
  }
26
131
  getAttachInfo() {
27
132
  return { type: 'tmux', sessionName: this.sessionName };
28
133
  }
29
134
  }
135
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
136
+ /** Minimal shell-escape for tmux session names (alphanumeric + dash). */
137
+ function shellescape(s) {
138
+ return `'${s.replace(/'/g, "'\\''")}'`;
139
+ }
30
140
  //# sourceMappingURL=tmux-backend.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tmux-backend.js","sourceRoot":"","sources":["../../../src/adapters/backend/tmux-backend.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,OAAO,WAAW;IACd,WAAW,GAAG,EAAE,CAAC;IAEzB,KAAK,CAAC,GAAW,EAAE,IAAc,EAAE,IAAe;QAChD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,IAAY;QAChB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,CAAC,KAAa,EAAE,KAAa;QACjC,iDAAiD;IACnD,CAAC;IAED,MAAM,CAAC,GAA2B;QAChC,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,CAAC,GAAyD;QAC9D,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,IAAI;QACF,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,aAAa;QACX,OAAO,EAAE,IAAI,EAAE,MAAe,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;IAClE,CAAC;CACF"}
1
+ {"version":3,"file":"tmux-backend.js","sourceRoot":"","sources":["../../../src/adapters/backend/tmux-backend.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,9 @@ export interface SessionBackend {
11
11
  onData(cb: (data: string) => void): void;
12
12
  onExit(cb: (code: number | null, signal: string | null) => void): void;
13
13
  kill(): void;
14
+ /** Permanently destroy the backing session (e.g. kill tmux session).
15
+ * Called only on explicit /close. Default: same as kill(). */
16
+ destroySession?(): void;
14
17
  getAttachInfo?(): {
15
18
  type: 'tmux';
16
19
  sessionName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;IACvE,IAAI,IAAI,IAAI,CAAC;IACb,aAAa,CAAC,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAChE"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;IACvE,IAAI,IAAI,IAAI,CAAC;IACb;mEAC+D;IAC/D,cAAc,CAAC,IAAI,IAAI,CAAC;IACxB,aAAa,CAAC,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAChE"}
@@ -1 +1 @@
1
- {"version":3,"file":"aiden.d.ts","sourceRoot":"","sources":["../../../src/adapters/cli/aiden.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAA6B,MAAM,YAAY,CAAC;AAMxE,wBAAgB,kBAAkB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CAmDpE;AAED,eAAO,MAAM,MAAM,2BAAqB,CAAC"}
1
+ {"version":3,"file":"aiden.d.ts","sourceRoot":"","sources":["../../../src/adapters/cli/aiden.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAA6B,MAAM,YAAY,CAAC;AAMxE,wBAAgB,kBAAkB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CAuDpE;AAED,eAAO,MAAM,MAAM,2BAAqB,CAAC"}
@@ -56,6 +56,10 @@ export function createAidenAdapter(pathOverride) {
56
56
  }
57
57
  },
58
58
  completionPattern: undefined, // quiescence only
59
+ systemHints: [
60
+ '消息可能包含 attachments,每个有 path 字段,用 Read 工具查看',
61
+ '不要使用 EnterPlanMode / ExitPlanMode 工具',
62
+ ],
59
63
  altScreen: false,
60
64
  };
61
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"aiden.js","sourceRoot":"","sources":["../../../src/adapters/cli/aiden.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"aiden.js","sourceRoot":"","sources":["../../../src/adapters/cli/aiden.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,EAA6B,MAAM,YAAY,CAAC;AAIxE,wBAAgB,uBAAuB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CAgDzE;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,EAA6B,MAAM,YAAY,CAAC;AAIxE,wBAAgB,uBAAuB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CAqDzE;AAED,eAAO,MAAM,MAAM,gCAA0B,CAAC"}
@@ -17,6 +17,7 @@ export function createClaudeCodeAdapter(pathOverride) {
17
17
  args.push('--session-id', sessionId);
18
18
  }
19
19
  args.push('--dangerously-skip-permissions');
20
+ args.push('--disallowed-tools', 'EnterPlanMode,ExitPlanMode');
20
21
  return args;
21
22
  },
22
23
  async writeInput(pty, content) {
@@ -52,6 +53,10 @@ export function createClaudeCodeAdapter(pathOverride) {
52
53
  },
53
54
  completionPattern: COMPLETION_RE,
54
55
  readyPattern: /❯/,
56
+ systemHints: [
57
+ '消息可能包含 attachments,每个有 path 字段,用 Read 工具查看',
58
+ '不要使用 EnterPlanMode / ExitPlanMode 工具',
59
+ ],
55
60
  altScreen: false,
56
61
  };
57
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../src/adapters/cli/claude-code.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../src/adapters/cli/claude-code.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"coco.d.ts","sourceRoot":"","sources":["../../../src/adapters/cli/coco.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAA6B,MAAM,YAAY,CAAC;AAExE,wBAAgB,iBAAiB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CA2CnE;AAED,eAAO,MAAM,MAAM,0BAAoB,CAAC"}
1
+ {"version":3,"file":"coco.d.ts","sourceRoot":"","sources":["../../../src/adapters/cli/coco.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAA6B,MAAM,YAAY,CAAC;AAExE,wBAAgB,iBAAiB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CAgDnE;AAED,eAAO,MAAM,MAAM,0BAAoB,CAAC"}
@@ -14,6 +14,7 @@ export function createCocoAdapter(pathOverride) {
14
14
  args.push('--session-id', sessionId);
15
15
  }
16
16
  args.push('--yolo');
17
+ args.push('--disallowed-tool', 'EnterPlanMode', '--disallowed-tool', 'ExitPlanMode');
17
18
  return args;
18
19
  },
19
20
  async writeInput(pty, content) {
@@ -39,6 +40,10 @@ export function createCocoAdapter(pathOverride) {
39
40
  },
40
41
  completionPattern: undefined,
41
42
  readyPattern: /⏵⏵/, // status bar indicator — present when CoCo's TUI is rendered
43
+ systemHints: [
44
+ '消息可能包含 attachments,每个有 path 字段,用 Read 工具查看',
45
+ '不要使用 EnterPlanMode / ExitPlanMode 工具',
46
+ ],
42
47
  altScreen: false,
43
48
  };
44
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"coco.js","sourceRoot":"","sources":["../../../src/adapters/cli/coco.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,MAAM,UAAU,iBAAiB,CAAC,YAAqB;IACrD,MAAM,GAAG,GAAG,cAAc,CAAC,YAAY,IAAI,MAAM,CAAC,CAAC;IACnD,OAAO;QACL,EAAE,EAAE,MAAM;QACV,WAAW,EAAE,GAAG;QAEhB,SAAS,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE;YAC7B,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;YACvC,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACpB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,GAAc,EAAE,OAAe;YAC9C,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;QAC5B,CAAC;QAED,eAAe,CAAC,KAAqB;YACnC,2EAA2E;YAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;gBAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,GAAG,EAAE,KAAK,CAAC,GAAG;aACf,CAAC,CAAC;YACH,IAAI,CAAC;gBACH,QAAQ,CAAC,GAAG,GAAG,iBAAiB,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE;oBACpE,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,MAAM;oBACf,KAAK,EAAE,QAAQ;iBAChB,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC,oCAAoC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAED,iBAAiB,EAAE,SAAS;QAC5B,YAAY,EAAE,IAAI,EAAI,6DAA6D;QACnF,SAAS,EAAE,KAAK;KACjB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,iBAAiB,CAAC"}
1
+ {"version":3,"file":"coco.js","sourceRoot":"","sources":["../../../src/adapters/cli/coco.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,MAAM,UAAU,iBAAiB,CAAC,YAAqB;IACrD,MAAM,GAAG,GAAG,cAAc,CAAC,YAAY,IAAI,MAAM,CAAC,CAAC;IACnD,OAAO;QACL,EAAE,EAAE,MAAM;QACV,WAAW,EAAE,GAAG;QAEhB,SAAS,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE;YAC7B,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;YACvC,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,eAAe,EAAE,mBAAmB,EAAE,cAAc,CAAC,CAAC;YACrF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,GAAc,EAAE,OAAe;YAC9C,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;QAC5B,CAAC;QAED,eAAe,CAAC,KAAqB;YACnC,2EAA2E;YAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;gBAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,GAAG,EAAE,KAAK,CAAC,GAAG;aACf,CAAC,CAAC;YACH,IAAI,CAAC;gBACH,QAAQ,CAAC,GAAG,GAAG,iBAAiB,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE;oBACpE,QAAQ,EAAE,OAAO;oBACjB,OAAO,EAAE,MAAM;oBACf,KAAK,EAAE,QAAQ;iBAChB,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC,oCAAoC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QAED,iBAAiB,EAAE,SAAS;QAC5B,YAAY,EAAE,IAAI,EAAI,6DAA6D;QACnF,WAAW,EAAE;YACX,4CAA4C;YAC5C,sCAAsC;SACvC;QACD,SAAS,EAAE,KAAK;KACjB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,iBAAiB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../../src/adapters/cli/codex.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAA6B,MAAM,YAAY,CAAC;AAMxE,wBAAgB,kBAAkB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CA0CpE;AAED,eAAO,MAAM,MAAM,2BAAqB,CAAC"}
1
+ {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../../src/adapters/cli/codex.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAA6B,MAAM,YAAY,CAAC;AAMxE,wBAAgB,kBAAkB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CA6CpE;AAED,eAAO,MAAM,MAAM,2BAAqB,CAAC"}
@@ -40,6 +40,9 @@ export function createCodexAdapter(pathOverride) {
40
40
  },
41
41
  completionPattern: undefined,
42
42
  readyPattern: /›/, // prompt indicator — present when Codex's input box is rendered
43
+ systemHints: [
44
+ '消息可能包含 attachments,每个有 path 字段,用 file_read 工具查看',
45
+ ],
43
46
  altScreen: false, // --no-alt-screen disables alternate screen
44
47
  };
45
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../src/adapters/cli/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,YAAqB;IACtD,MAAM,GAAG,GAAG,cAAc,CAAC,YAAY,IAAI,OAAO,CAAC,CAAC;IACpD,OAAO;QACL,EAAE,EAAE,OAAO;QACX,WAAW,EAAE,GAAG;QAEhB,SAAS;YACP,sEAAsE;YACtE,uEAAuE;YACvE,OAAO;gBACL,4CAA4C;gBAC5C,iBAAiB;aAClB,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,GAAc,EAAE,OAAe;YAC9C,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACnB,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YACjB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;QAED,eAAe,CAAC,KAAqB;YACnC,mFAAmF;YACnF,IAAI,CAAC;gBACH,QAAQ,CAAC,GAAG,GAAG,eAAe,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACvG,CAAC;YAAC,MAAM,CAAC,CAAC,+BAA+B,CAAC,CAAC;YAE3C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;iBACtC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;iBAClC,IAAI,CAAC,GAAG,CAAC,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,IAAI,IAAI,OAAO,OAAO,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAClG,IAAI,CAAC;gBACH,QAAQ,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACzE,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC,qCAAqC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;QAED,iBAAiB,EAAE,SAAS;QAC5B,YAAY,EAAE,GAAG,EAAG,gEAAgE;QACpF,SAAS,EAAE,KAAK,EAAI,4CAA4C;KACjE,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,kBAAkB,CAAC"}
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../src/adapters/cli/codex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,YAAqB;IACtD,MAAM,GAAG,GAAG,cAAc,CAAC,YAAY,IAAI,OAAO,CAAC,CAAC;IACpD,OAAO;QACL,EAAE,EAAE,OAAO;QACX,WAAW,EAAE,GAAG;QAEhB,SAAS;YACP,sEAAsE;YACtE,uEAAuE;YACvE,OAAO;gBACL,4CAA4C;gBAC5C,iBAAiB;aAClB,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,GAAc,EAAE,OAAe;YAC9C,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACnB,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YACjB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;QAED,eAAe,CAAC,KAAqB;YACnC,mFAAmF;YACnF,IAAI,CAAC;gBACH,QAAQ,CAAC,GAAG,GAAG,eAAe,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACvG,CAAC;YAAC,MAAM,CAAC,CAAC,+BAA+B,CAAC,CAAC;YAE3C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;iBACtC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;iBAClC,IAAI,CAAC,GAAG,CAAC,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,IAAI,IAAI,OAAO,OAAO,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAClG,IAAI,CAAC;gBACH,QAAQ,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACzE,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC,qCAAqC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;QAED,iBAAiB,EAAE,SAAS;QAC5B,YAAY,EAAE,GAAG,EAAG,gEAAgE;QACpF,WAAW,EAAE;YACX,iDAAiD;SAClD;QACD,SAAS,EAAE,KAAK,EAAI,4CAA4C;KACjE,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,kBAAkB,CAAC"}
@@ -32,6 +32,9 @@ export interface CliAdapter {
32
32
  *
33
33
  * Examples: CoCo `⏵⏵` status bar, Codex `›` prompt indicator. */
34
34
  readonly readyPattern?: RegExp;
35
+ /** CLI-specific system hints injected into the initial prompt.
36
+ * e.g. "use Read tool for attachments", "don't use PlanMode" */
37
+ readonly systemHints: string[];
35
38
  /** Whether CLI uses alternate screen buffer */
36
39
  readonly altScreen: boolean;
37
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/adapters/cli/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,+CAA+C;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;uFACmF;IACnF,SAAS,CAAC,IAAI,EAAE;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC;KACjB,GAAG,MAAM,EAAE,CAAC;IAEb;iDAC6C;IAC7C,UAAU,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3D,mEAAmE;IACnE,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAE7C,wFAAwF;IACxF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAEpC;;;;;sEAKkE;IAClE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B,+CAA+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,KAAK,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/adapters/cli/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,+CAA+C;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;uFACmF;IACnF,SAAS,CAAC,IAAI,EAAE;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC;KACjB,GAAG,MAAM,EAAE,CAAC;IAEb;iDAC6C;IAC7C,UAAU,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3D,mEAAmE;IACnE,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAE7C,wFAAwF;IACxF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAEpC;;;;;sEAKkE;IAClE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B;qEACiE;IACjE,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAE/B,+CAA+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,KAAK,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC"}
package/dist/cli.js CHANGED
@@ -112,8 +112,7 @@ async function cmdSetup() {
112
112
  const cliIdMap = { '1': 'claude-code', '2': 'aiden', '3': 'coco', '4': 'codex' };
113
113
  const cliId = cliIdMap[cliChoice] ?? (cliChoice || 'claude-code');
114
114
  const workingDir = await ask(rl, '默认工作目录 [~]: ');
115
- const allowedUsers = await ask(rl, '允许的用户 (邮箱前缀或 open_id,逗号分隔,留空=不限制): ');
116
- const externalHost = await ask(rl, '外部 IP/域名 (终端链接用,留空=自动检测): ');
115
+ const allowedUsers = await ask(rl, '允许的用户 (邮箱或 open_id,逗号分隔,留空=不限制): ');
117
116
  rl.close();
118
117
  const lines = [
119
118
  '# Lark (Feishu) App Credentials',
@@ -129,8 +128,6 @@ async function cmdSetup() {
129
128
  ];
130
129
  if (allowedUsers)
131
130
  lines.push(`ALLOWED_USERS=${allowedUsers}`);
132
- if (externalHost)
133
- lines.push(`WEB_EXTERNAL_HOST=${externalHost}`);
134
131
  writeFileSync(ENV_FILE, lines.join('\n') + '\n');
135
132
  console.log(`\n✅ 配置已写入: ${ENV_FILE}`);
136
133
  console.log(`\n下一步: botmux start`);