botmux 1.5.1 → 1.9.1
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/.env.example +1 -1
- package/README.en.md +17 -125
- package/README.md +15 -124
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +8 -3
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/cli/gemini.d.ts +4 -0
- package/dist/adapters/cli/gemini.d.ts.map +1 -0
- package/dist/adapters/cli/gemini.js +70 -0
- package/dist/adapters/cli/gemini.js.map +1 -0
- package/dist/adapters/cli/opencode.d.ts +4 -0
- package/dist/adapters/cli/opencode.d.ts.map +1 -0
- package/dist/adapters/cli/opencode.js +84 -0
- package/dist/adapters/cli/opencode.js.map +1 -0
- package/dist/adapters/cli/registry.d.ts +6 -2
- package/dist/adapters/cli/registry.d.ts.map +1 -1
- package/dist/adapters/cli/registry.js +25 -9
- package/dist/adapters/cli/registry.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +9 -2
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/cli.js +271 -29
- package/dist/cli.js.map +1 -1
- package/dist/core/types.d.ts +3 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts +6 -0
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +62 -13
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +6 -4
- package/dist/daemon.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts +1 -1
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +4 -2
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +26 -11
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +1 -1
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +5 -2
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/utils/idle-detector.d.ts.map +1 -1
- package/dist/utils/idle-detector.js +4 -2
- package/dist/utils/idle-detector.js.map +1 -1
- package/dist/worker.js +154 -60
- package/dist/worker.js.map +1 -1
- package/package.json +2 -1
package/.env.example
CHANGED
|
@@ -6,7 +6,7 @@ LARK_APP_SECRET=
|
|
|
6
6
|
# SESSION_DATA_DIR=
|
|
7
7
|
|
|
8
8
|
# Daemon settings
|
|
9
|
-
# CLI_ID=claude-code # CLI adapter: claude-code, aiden, coco, codex
|
|
9
|
+
# CLI_ID=claude-code # CLI adapter: claude-code, aiden, coco, codex, gemini, opencode
|
|
10
10
|
# WORKING_DIR=~ # Default working directory (comma-separated for multiple dirs, e.g. ~/projects,~/work)
|
|
11
11
|
|
|
12
12
|
# Access control (comma-separated emails or Lark open_ids, empty = allow all)
|
package/README.en.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[中文](README.md) | English
|
|
4
4
|
|
|
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.
|
|
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, Gemini) for each new topic thread, with live streaming cards and a web-based terminal.
|
|
6
6
|
|
|
7
7
|
## Demo
|
|
8
8
|
|
|
@@ -11,47 +11,19 @@ Bridge between Lark (Feishu) topic groups and AI coding CLIs. The daemon listens
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
13
13
|
- **One topic = one AI coding session** — each Lark thread gets its own isolated CLI process
|
|
14
|
-
- **Multi-CLI support** — adapter architecture supports Claude Code, Aiden, CoCo, Codex, and is extensible
|
|
14
|
+
- **Multi-CLI support** — adapter architecture supports Claude Code, Aiden, CoCo, Codex, Gemini, and is extensible
|
|
15
15
|
- **Live streaming cards** — real-time terminal output rendered in Feishu cards with markdown support, per-turn card lifecycle
|
|
16
|
-
- **Web terminal (xterm.js)** — full PTY output in the browser with
|
|
16
|
+
- **Web terminal (xterm.js)** — full PTY output in the browser with a mobile shortcut toolbar and on-demand write access via DM link
|
|
17
17
|
- **Session persistence** — sessions survive daemon restarts; with tmux backend, CLI processes persist across restarts with zero interruption
|
|
18
18
|
- **Scheduled tasks** — cron-based recurring prompts with natural language scheduling (Chinese supported)
|
|
19
19
|
- **Project management** — interactive repo selector, per-session working directory
|
|
20
20
|
- **MCP integration** — CLI can reply to Lark threads, read message history, and add reactions via MCP tools
|
|
21
21
|
- **Access control** — allowlist for users, token-based write access for terminals, button restrictions on cards
|
|
22
22
|
|
|
23
|
-
## Architecture
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
Lark WebSocket Events
|
|
27
|
-
|
|
|
28
|
-
Daemon (daemon.ts → core/ modules)
|
|
29
|
-
|-- im/lark/event-dispatcher: Lark event routing
|
|
30
|
-
|-- im/lark/card-handler: card interaction handling
|
|
31
|
-
|-- core/worker-pool: worker process pool management
|
|
32
|
-
|-- core/command-handler: slash command processing
|
|
33
|
-
|-- core/session-manager: session lifecycle
|
|
34
|
-
|-- core/scheduler: cron task scheduling
|
|
35
|
-
|
|
|
36
|
-
Worker (worker.ts) -- forked child process per session
|
|
37
|
-
|-- adapters/cli/*: CLI adapters (Claude Code / Aiden / CoCo / Codex)
|
|
38
|
-
|-- adapters/backend: PtyBackend (node-pty) or TmuxBackend (tmux + node-pty)
|
|
39
|
-
|-- utils/idle-detector: idle detection (quiescence + spinner + completion marker)
|
|
40
|
-
|-- HTTP + WebSocket server: serves xterm.js web terminal
|
|
41
|
-
|-- Headless xterm: captures screen for streaming cards
|
|
42
|
-
|-- IPC: communicates with daemon
|
|
43
|
-
|
|
|
44
|
-
AI Coding CLI (interactive TTY mode)
|
|
45
|
-
|-- MCP Server (stdio): send_to_thread, get_thread_messages, react_to_message
|
|
46
|
-
|
|
|
47
|
-
Lark API
|
|
48
|
-
|-- Replies, reactions, card updates, DMs
|
|
49
|
-
```
|
|
50
|
-
|
|
51
23
|
## Prerequisites
|
|
52
24
|
|
|
53
25
|
- **Node.js** >= 20
|
|
54
|
-
- **AI coding CLI** installed and authenticated (`claude`, `aiden`, `coco`, or `
|
|
26
|
+
- **AI coding CLI** installed and authenticated (`claude`, `aiden`, `coco`, `codex`, `gemini`, or `opencode` in PATH)
|
|
55
27
|
- **Lark app** with Bot and Message permissions (WebSocket event subscription)
|
|
56
28
|
- **tmux** >= 3.x (optional — auto-enabled when installed for persistent CLI sessions)
|
|
57
29
|
|
|
@@ -107,7 +79,7 @@ Configuration is stored at `~/.botmux/.env`. Run `botmux setup` to create it int
|
|
|
107
79
|
|
|
108
80
|
| Variable | Default | Description |
|
|
109
81
|
|----------|---------|-------------|
|
|
110
|
-
| `CLI_ID` | `claude-code` | CLI adapter (`claude-code`, `aiden`, `coco`, `codex`) |
|
|
82
|
+
| `CLI_ID` | `claude-code` | CLI adapter (`claude-code`, `aiden`, `coco`, `codex`, `gemini`, `opencode`) |
|
|
111
83
|
| `CLI_PATH` | _(auto-detect by CLI_ID)_ | CLI binary path override |
|
|
112
84
|
| `BACKEND_TYPE` | _(auto-detect)_ | Session backend: `tmux` if available, otherwise `pty` |
|
|
113
85
|
| `WORKING_DIR` | `~` | Default working directory; supports comma-separated multiple dirs (e.g. `~/a,~/b`), `/repo` scans all |
|
|
@@ -168,7 +140,7 @@ botmux setup
|
|
|
168
140
|
| `allowedUsers` | No | Allowed user list |
|
|
169
141
|
| `projectScanDir` | No | Directory to scan for git repos |
|
|
170
142
|
|
|
171
|
-
**Config priority:** `BOTS_CONFIG` env var
|
|
143
|
+
**Config priority:** `BOTS_CONFIG` env var > `~/.botmux/bots.json` > `.env` single-bot mode
|
|
172
144
|
|
|
173
145
|
## File Locations
|
|
174
146
|
|
|
@@ -231,7 +203,7 @@ Manage tasks:
|
|
|
231
203
|
Each conversation turn gets a live-updating Feishu card that shows:
|
|
232
204
|
|
|
233
205
|
- Real-time terminal output (rendered via headless xterm + Feishu Card v2 markdown)
|
|
234
|
-
- Status indicator: 🟡 Starting
|
|
206
|
+
- Status indicator: 🟡 Starting > 🔵 Working > 🟢 Idle
|
|
235
207
|
- Action buttons: Open Terminal, Get Write Link, Restart Claude, Close Session
|
|
236
208
|
|
|
237
209
|
The card content is captured from a headless xterm terminal that filters out TUI chrome (logo, status bar, prompts, box-drawing characters) and shows only Claude's actual work output.
|
|
@@ -243,19 +215,19 @@ Each session exposes a web terminal at `http://<WEB_EXTERNAL_HOST>:<port>`.
|
|
|
243
215
|
- **Read-only link** — shown on the streaming card in the group thread
|
|
244
216
|
- **Write-enabled link** — sent via DM on demand (click "🔑 Get Write Link" on the card)
|
|
245
217
|
|
|
246
|
-
Features: xterm.js with fit/unicode11/web-links addons, TokyoNight theme, scrollback buffer
|
|
218
|
+
Features: xterm.js with fit/unicode11/web-links addons, TokyoNight theme, scrollback buffer. On mobile/tablet, a floating shortcut toolbar provides Esc, Ctrl+C, Tab, arrow keys and other control keys missing from virtual keyboards, with automatic keyboard avoidance.
|
|
247
219
|
|
|
248
220
|
### Tmux Persistent Sessions
|
|
249
221
|
|
|
250
|
-
When tmux is installed, botmux automatically uses the tmux backend
|
|
222
|
+
When tmux is installed, botmux automatically uses the tmux backend. 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.
|
|
251
223
|
|
|
252
224
|
**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.
|
|
253
225
|
|
|
254
226
|
```bash
|
|
255
|
-
#
|
|
256
|
-
|
|
227
|
+
# Recommended: interactive session picker — select and attach to tmux
|
|
228
|
+
npx botmux list
|
|
257
229
|
|
|
258
|
-
#
|
|
230
|
+
# Or manually attach (session name = bmx-<first 8 chars of session ID>)
|
|
259
231
|
tmux attach -t bmx-<first-8-chars-of-session-id>
|
|
260
232
|
# Ctrl+B, D to detach — CLI keeps running
|
|
261
233
|
|
|
@@ -263,7 +235,9 @@ tmux attach -t bmx-<first-8-chars-of-session-id>
|
|
|
263
235
|
BACKEND_TYPE=pty botmux start
|
|
264
236
|
```
|
|
265
237
|
|
|
266
|
-
|
|
238
|
+
`botmux list` provides an interactive TUI showing all active sessions with ID, title, working directory, PID, uptime, and status. Use arrow keys to select and Enter to attach. Use `botmux list --plain` for plain-text table output suitable for scripting.
|
|
239
|
+
|
|
240
|
+
**Session naming:** `bmx-<first 8 chars of session UUID>`
|
|
267
241
|
|
|
268
242
|
**Lifecycle:**
|
|
269
243
|
|
|
@@ -272,92 +246,10 @@ BACKEND_TYPE=pty botmux start
|
|
|
272
246
|
| `botmux restart` | Survives | Survives (re-attaches on next message) |
|
|
273
247
|
| `/close` or close button | Destroyed | Terminated (SIGHUP) |
|
|
274
248
|
| CLI exits / crashes | Closes with it | Already exited (auto-restart creates new session) |
|
|
275
|
-
| `CLI_ID` changed + restart | All destroyed | All terminated (prevents pattern mismatch) |
|
|
276
|
-
|
|
277
|
-
**Notes:**
|
|
278
|
-
- 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
|
|
279
|
-
- Orphaned tmux sessions (not in the active session list) are cleaned up automatically on daemon startup
|
|
280
|
-
- Set `BACKEND_TYPE=pty` to opt out of tmux persistence
|
|
281
|
-
|
|
282
|
-
## MCP Tools
|
|
283
|
-
|
|
284
|
-
Claude Code has access to three MCP tools for interacting with Lark:
|
|
285
|
-
|
|
286
|
-
| Tool | Description |
|
|
287
|
-
|------|-------------|
|
|
288
|
-
| `send_to_thread` | Send a message (text or rich post) to the Lark thread |
|
|
289
|
-
| `get_thread_messages` | Retrieve message history from the thread |
|
|
290
|
-
| `react_to_message` | Add or remove emoji reactions on messages |
|
|
291
|
-
|
|
292
|
-
## Development
|
|
293
249
|
|
|
294
|
-
|
|
295
|
-
git clone <repo-url>
|
|
296
|
-
cd botmux
|
|
297
|
-
pnpm install
|
|
298
|
-
pnpm build
|
|
250
|
+
## Contributing
|
|
299
251
|
|
|
300
|
-
|
|
301
|
-
pnpm daemon
|
|
302
|
-
|
|
303
|
-
# Or with PM2
|
|
304
|
-
pnpm daemon:start
|
|
305
|
-
pnpm daemon:logs
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
## Project Structure
|
|
309
|
-
|
|
310
|
-
```
|
|
311
|
-
src/
|
|
312
|
-
cli.ts # CLI entry point (setup/start/stop/restart/logs/list/delete)
|
|
313
|
-
daemon.ts # Daemon orchestrator (~400 lines, wires modules together)
|
|
314
|
-
worker.ts # Worker process: uses adapters to manage CLI + PTY
|
|
315
|
-
bot-registry.ts # Multi-bot registry (config loading, per-bot state)
|
|
316
|
-
config.ts # Configuration from environment variables
|
|
317
|
-
server.ts # MCP server setup
|
|
318
|
-
types.ts # IPC message types
|
|
319
|
-
adapters/
|
|
320
|
-
cli/
|
|
321
|
-
types.ts # CliAdapter interface, CliId type
|
|
322
|
-
registry.ts # Adapter factory + resolveCommand
|
|
323
|
-
claude-code.ts # Claude Code adapter
|
|
324
|
-
aiden.ts # Aiden adapter
|
|
325
|
-
coco.ts # CoCo adapter
|
|
326
|
-
codex.ts # Codex adapter
|
|
327
|
-
backend/
|
|
328
|
-
types.ts # SessionBackend interface
|
|
329
|
-
pty-backend.ts # node-pty backend
|
|
330
|
-
tmux-backend.ts # tmux backend (pty-under-tmux, persistent sessions)
|
|
331
|
-
core/
|
|
332
|
-
types.ts # DaemonSession core type
|
|
333
|
-
worker-pool.ts # Worker process pool management
|
|
334
|
-
command-handler.ts # Slash command processing
|
|
335
|
-
session-manager.ts # Session lifecycle + path resolution
|
|
336
|
-
cost-calculator.ts # Token usage & cost estimation
|
|
337
|
-
scheduler.ts # Cron scheduling with natural language parsing
|
|
338
|
-
im/
|
|
339
|
-
types.ts # ImAdapter interface definitions (multi-IM abstraction)
|
|
340
|
-
lark/
|
|
341
|
-
client.ts # Lark API wrapper
|
|
342
|
-
event-dispatcher.ts # Lark WebSocket event routing
|
|
343
|
-
card-handler.ts # Lark card interaction handling
|
|
344
|
-
card-builder.ts # Lark interactive card builders
|
|
345
|
-
message-parser.ts # Lark event message parsing
|
|
346
|
-
tools/
|
|
347
|
-
index.ts # MCP tool registry
|
|
348
|
-
send-to-thread.ts # MCP tool: send message
|
|
349
|
-
get-thread-messages.ts # MCP tool: read messages
|
|
350
|
-
react-to-message.ts # MCP tool: emoji reactions
|
|
351
|
-
services/
|
|
352
|
-
session-store.ts # Session persistence (JSON)
|
|
353
|
-
schedule-store.ts # Scheduled task persistence
|
|
354
|
-
message-queue.ts # Per-thread JSONL message queue
|
|
355
|
-
project-scanner.ts # Git repo/worktree discovery
|
|
356
|
-
utils/
|
|
357
|
-
idle-detector.ts # CLI idle detection (quiescence + spinner + completion marker)
|
|
358
|
-
terminal-renderer.ts # Headless xterm renderer for screen capture & TUI filtering
|
|
359
|
-
logger.ts # Logging utility
|
|
360
|
-
```
|
|
252
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
361
253
|
|
|
362
254
|
## License
|
|
363
255
|
|
package/README.md
CHANGED
|
@@ -2,57 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
中文 | [English](README.en.md)
|
|
4
4
|
|
|
5
|
-
飞书话题群与 AI 编程 CLI 的桥接工具。Daemon 监听飞书消息,为每个新话题自动启动一个独立的 CLI 进程(支持 Claude Code、Aiden、CoCo、Codex),提供实时流式卡片和 Web 终端。
|
|
5
|
+
飞书话题群与 AI 编程 CLI 的桥接工具。Daemon 监听飞书消息,为每个新话题自动启动一个独立的 CLI 进程(支持 Claude Code、Aiden、CoCo、Codex、Gemini),提供实时流式卡片和 Web 终端。
|
|
6
6
|
|
|
7
7
|
## 演示
|
|
8
8
|
|
|
9
9
|
[演示视频](https://github.com/user-attachments/assets/3ba4c681-0a7e-4a03-89c8-b8d26b544a65)
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
## 功能特性
|
|
13
12
|
|
|
14
13
|
- **一个话题 = 一个 AI 编程会话** — 每个飞书话题线程对应一个独立的 CLI 进程
|
|
15
|
-
- **多 CLI 支持** — 通过适配器架构支持 Claude Code、Aiden、CoCo、Codex,可扩展
|
|
14
|
+
- **多 CLI 支持** — 通过适配器架构支持 Claude Code、Aiden、CoCo、Codex、Gemini,可扩展
|
|
16
15
|
- **实时流式卡片** — 终端输出实时渲染到飞书卡片中,支持 Markdown 格式,每轮对话独立卡片
|
|
17
|
-
- **Web 终端 (xterm.js)** — 浏览器查看完整 PTY
|
|
16
|
+
- **Web 终端 (xterm.js)** — 浏览器查看完整 PTY 输出,移动端快捷键工具栏,按需获取可操作链接
|
|
18
17
|
- **会话持久化** — 会话在 Daemon 重启后自动恢复;tmux 后端下 CLI 进程常驻,重启零中断
|
|
19
18
|
- **定时任务** — 基于 Cron 的周期性任务,支持中文自然语言配置
|
|
20
19
|
- **项目管理** — 交互式仓库选择器,每个会话独立工作目录
|
|
21
20
|
- **MCP 集成** — CLI 可通过 MCP 工具回复飞书话题、读取消息历史、添加表情回应
|
|
22
21
|
- **权限控制** — 用户白名单、终端 Token 写入权限、卡片按钮操作限制
|
|
23
22
|
|
|
24
|
-
## 架构
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
飞书 WebSocket 事件
|
|
28
|
-
|
|
|
29
|
-
Daemon (daemon.ts → core/ 模块)
|
|
30
|
-
|-- im/lark/event-dispatcher: 飞书事件路由
|
|
31
|
-
|-- im/lark/card-handler: 卡片交互处理
|
|
32
|
-
|-- core/worker-pool: Worker 进程池管理
|
|
33
|
-
|-- core/command-handler: 斜杠命令处理
|
|
34
|
-
|-- core/session-manager: 会话生命周期
|
|
35
|
-
|-- core/scheduler: 定时任务调度
|
|
36
|
-
|
|
|
37
|
-
Worker (worker.ts) -- 每个会话 fork 一个子进程
|
|
38
|
-
|-- adapters/cli/*: CLI 适配器 (Claude Code / Aiden / CoCo / Codex)
|
|
39
|
-
|-- adapters/backend: PtyBackend (node-pty) 或 TmuxBackend (tmux + node-pty)
|
|
40
|
-
|-- utils/idle-detector: 空闲检测(静默 + Spinner + 完成标记)
|
|
41
|
-
|-- HTTP + WebSocket: 提供 xterm.js Web 终端
|
|
42
|
-
|-- Headless xterm: 捕获屏幕内容用于流式卡片
|
|
43
|
-
|-- IPC: 与 Daemon 通信
|
|
44
|
-
|
|
|
45
|
-
AI 编程 CLI (交互式 TTY 模式)
|
|
46
|
-
|-- MCP Server (stdio): send_to_thread, get_thread_messages, react_to_message
|
|
47
|
-
|
|
|
48
|
-
飞书 API
|
|
49
|
-
|-- 回复消息、表情回应、卡片更新、私聊
|
|
50
|
-
```
|
|
51
|
-
|
|
52
23
|
## 前置要求
|
|
53
24
|
|
|
54
25
|
- **Node.js** >= 20
|
|
55
|
-
- **AI 编程 CLI** 已安装并完成认证(`claude`、`aiden`、`coco` 或 `
|
|
26
|
+
- **AI 编程 CLI** 已安装并完成认证(`claude`、`aiden`、`coco`、`codex`、`gemini` 或 `opencode` 在 PATH 中)
|
|
56
27
|
- **飞书应用** 具备机器人和消息权限(WebSocket 事件订阅)
|
|
57
28
|
- **tmux** >= 3.x(可选,安装后自动启用会话常驻)
|
|
58
29
|
|
|
@@ -108,7 +79,7 @@ botmux start
|
|
|
108
79
|
|
|
109
80
|
| 变量 | 默认值 | 说明 |
|
|
110
81
|
|------|--------|------|
|
|
111
|
-
| `CLI_ID` | `claude-code` | CLI 适配器(`claude-code`、`aiden`、`coco`、`codex`) |
|
|
82
|
+
| `CLI_ID` | `claude-code` | CLI 适配器(`claude-code`、`aiden`、`coco`、`codex`、`gemini`、`opencode`) |
|
|
112
83
|
| `CLI_PATH` | _(按 CLI_ID 自动检测)_ | CLI 可执行文件路径覆盖 |
|
|
113
84
|
| `BACKEND_TYPE` | _(自动检测)_ | 会话后端:有 tmux 则用 `tmux`,否则 `pty` |
|
|
114
85
|
| `WORKING_DIR` | `~` | 默认工作目录,支持逗号分隔多个目录(如 `~/a,~/b`),`/repo` 会扫描所有目录 |
|
|
@@ -244,19 +215,19 @@ botmux setup
|
|
|
244
215
|
- **只读链接** — 展示在群话题的流式卡片上
|
|
245
216
|
- **可操作链接** — 按需获取(点击卡片上的「🔑 获取操作链接」通过私聊发送)
|
|
246
217
|
|
|
247
|
-
特性:xterm.js + fit/unicode11/web-links 插件、TokyoNight
|
|
218
|
+
特性:xterm.js + fit/unicode11/web-links 插件、TokyoNight 主题、滚动缓冲区。移动端/平板通过悬浮快捷键工具栏提供 Esc、Ctrl+C、Tab、方向键等虚拟键盘缺失的控制键,工具栏自动避让虚拟键盘。
|
|
248
219
|
|
|
249
220
|
### Tmux 会话常驻
|
|
250
221
|
|
|
251
|
-
安装 tmux 后,botmux 自动使用 tmux
|
|
222
|
+
安装 tmux 后,botmux 自动使用 tmux 后端。CLI 进程运行在 tmux session 内,daemon 通过 node-pty attach 到 tmux 来捕获输出,流式卡片、空闲检测、Web 终端等功能全部不受影响。
|
|
252
223
|
|
|
253
224
|
**核心收益:Daemon 重启不中断 CLI。** `botmux restart` 时 worker 进程退出,但 tmux session(及其中的 CLI 进程)保持运行。下次收到消息时 worker 自动 re-attach,无需 `--resume` 重载上下文。
|
|
254
225
|
|
|
255
226
|
```bash
|
|
256
|
-
#
|
|
257
|
-
|
|
227
|
+
# 推荐:交互式会话列表 — 选择后直接 attach 到 tmux
|
|
228
|
+
npx botmux list
|
|
258
229
|
|
|
259
|
-
#
|
|
230
|
+
# 也可以手动 attach(会话名 = bmx-<sessionId 前 8 位>)
|
|
260
231
|
tmux attach -t bmx-<session-id-前8位>
|
|
261
232
|
# Ctrl+B, D 退出 attach,不影响 CLI 继续运行
|
|
262
233
|
|
|
@@ -264,7 +235,9 @@ tmux attach -t bmx-<session-id-前8位>
|
|
|
264
235
|
BACKEND_TYPE=pty botmux start
|
|
265
236
|
```
|
|
266
237
|
|
|
267
|
-
|
|
238
|
+
`botmux list` 提供交互式 TUI,显示所有活跃会话的 ID、标题、工作目录、PID、运行时长和状态,方向键选择后回车即可 attach。也支持 `botmux list --plain` 输出纯文本表格供脚本使用。
|
|
239
|
+
|
|
240
|
+
**tmux 会话命名规则:** `bmx-<sessionId 前 8 位>`
|
|
268
241
|
|
|
269
242
|
**生命周期:**
|
|
270
243
|
|
|
@@ -273,92 +246,10 @@ BACKEND_TYPE=pty botmux start
|
|
|
273
246
|
| `botmux restart` | 存活 | 存活(下次消息 re-attach) |
|
|
274
247
|
| `/close` 或关闭按钮 | 销毁 | 终止(SIGHUP) |
|
|
275
248
|
| CLI 自行退出 / 崩溃 | 随之关闭 | 已退出(自动重启用新 session) |
|
|
276
|
-
| 切换 `CLI_ID` 后重启 | 全部销毁 | 全部终止(防止 pattern 不匹配) |
|
|
277
|
-
|
|
278
|
-
**注意事项:**
|
|
279
|
-
- 切换 `CLI_ID`(如 `claude-code` → `coco`)后重启 daemon,所有旧 tmux session 会被自动清理,因为旧 CLI 的 idle detection pattern 与新适配器不兼容
|
|
280
|
-
- 孤儿 tmux session(不在 active session 列表中的)会在 daemon 启动时自动清理
|
|
281
|
-
- 如果不需要 tmux 常驻特性,设置 `BACKEND_TYPE=pty` 即可降级
|
|
282
|
-
|
|
283
|
-
## MCP 工具
|
|
284
249
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
| 工具 | 说明 |
|
|
288
|
-
|------|------|
|
|
289
|
-
| `send_to_thread` | 向飞书话题发送消息(纯文本或富文本) |
|
|
290
|
-
| `get_thread_messages` | 获取话题的消息历史 |
|
|
291
|
-
| `react_to_message` | 添加或移除消息的表情回应 |
|
|
250
|
+
## 贡献
|
|
292
251
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
```bash
|
|
296
|
-
git clone <repo-url>
|
|
297
|
-
cd botmux
|
|
298
|
-
pnpm install
|
|
299
|
-
pnpm build
|
|
300
|
-
|
|
301
|
-
# 直接运行(不经 PM2)
|
|
302
|
-
pnpm daemon
|
|
303
|
-
|
|
304
|
-
# 或使用 PM2
|
|
305
|
-
pnpm daemon:start
|
|
306
|
-
pnpm daemon:logs
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
## 项目结构
|
|
310
|
-
|
|
311
|
-
```
|
|
312
|
-
src/
|
|
313
|
-
cli.ts # CLI 入口(setup/start/stop/restart/logs/list/delete)
|
|
314
|
-
daemon.ts # Daemon 编排入口(~400 行,调用各模块)
|
|
315
|
-
worker.ts # Worker 进程:使用适配器管理 CLI + PTY
|
|
316
|
-
bot-registry.ts # 多机器人注册表(配置加载、per-bot 状态管理)
|
|
317
|
-
config.ts # 环境变量配置
|
|
318
|
-
server.ts # MCP Server
|
|
319
|
-
types.ts # IPC 消息类型
|
|
320
|
-
adapters/
|
|
321
|
-
cli/
|
|
322
|
-
types.ts # CliAdapter 接口、CliId 类型
|
|
323
|
-
registry.ts # 适配器工厂 + resolveCommand
|
|
324
|
-
claude-code.ts # Claude Code 适配器
|
|
325
|
-
aiden.ts # Aiden 适配器
|
|
326
|
-
coco.ts # CoCo 适配器
|
|
327
|
-
codex.ts # Codex 适配器
|
|
328
|
-
backend/
|
|
329
|
-
types.ts # SessionBackend 接口
|
|
330
|
-
pty-backend.ts # node-pty 后端
|
|
331
|
-
tmux-backend.ts # tmux 后端(pty-under-tmux,会话常驻)
|
|
332
|
-
core/
|
|
333
|
-
types.ts # DaemonSession 核心类型
|
|
334
|
-
worker-pool.ts # Worker 进程池管理
|
|
335
|
-
command-handler.ts # 斜杠命令处理
|
|
336
|
-
session-manager.ts # 会话生命周期 + 路径解析
|
|
337
|
-
cost-calculator.ts # Token 用量 & 费用估算
|
|
338
|
-
scheduler.ts # 定时任务调度(自然语言解析)
|
|
339
|
-
im/
|
|
340
|
-
types.ts # ImAdapter 接口定义(多 IM 抽象)
|
|
341
|
-
lark/
|
|
342
|
-
client.ts # 飞书 API 封装
|
|
343
|
-
event-dispatcher.ts # 飞书 WebSocket 事件路由
|
|
344
|
-
card-handler.ts # 飞书卡片交互处理
|
|
345
|
-
card-builder.ts # 飞书交互卡片构建
|
|
346
|
-
message-parser.ts # 飞书事件消息解析
|
|
347
|
-
tools/
|
|
348
|
-
index.ts # MCP 工具注册表
|
|
349
|
-
send-to-thread.ts # MCP 工具:发送消息
|
|
350
|
-
get-thread-messages.ts # MCP 工具:读取消息
|
|
351
|
-
react-to-message.ts # MCP 工具:表情回应
|
|
352
|
-
services/
|
|
353
|
-
session-store.ts # 会话持久化 (JSON)
|
|
354
|
-
schedule-store.ts # 定时任务持久化
|
|
355
|
-
message-queue.ts # 话题消息队列 (JSONL)
|
|
356
|
-
project-scanner.ts # Git 仓库/Worktree 扫描
|
|
357
|
-
utils/
|
|
358
|
-
idle-detector.ts # CLI 空闲检测(静默 + Spinner + 完成标记)
|
|
359
|
-
terminal-renderer.ts # Headless xterm 渲染器(屏幕捕获 & TUI 过滤)
|
|
360
|
-
logger.ts # 日志工具
|
|
361
|
-
```
|
|
252
|
+
参见 [CONTRIBUTING.md](CONTRIBUTING.md)。
|
|
362
253
|
|
|
363
254
|
## 许可证
|
|
364
255
|
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;IAwDzD,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"}
|
|
@@ -102,11 +102,16 @@ export class TmuxBackend {
|
|
|
102
102
|
cwd: opts.cwd,
|
|
103
103
|
env: opts.env,
|
|
104
104
|
});
|
|
105
|
-
//
|
|
106
|
-
//
|
|
105
|
+
// Configure tmux session for web terminal use:
|
|
106
|
+
// - status off: avoid cursor-positioning noise in xterm.js
|
|
107
|
+
// - mouse on: let tmux handle scroll wheel → copy mode for scrollback
|
|
108
|
+
// - history-limit: large scrollback buffer (tmux default is 2000)
|
|
107
109
|
setTimeout(() => {
|
|
108
110
|
try {
|
|
109
|
-
|
|
111
|
+
const t = shellescape(this.sessionName);
|
|
112
|
+
execSync(`tmux set-option -t ${t} status off`, { stdio: 'ignore' });
|
|
113
|
+
execSync(`tmux set-option -t ${t} mouse on`, { stdio: 'ignore' });
|
|
114
|
+
execSync(`tmux set-option -t ${t} history-limit 50000`, { stdio: 'ignore' });
|
|
110
115
|
}
|
|
111
116
|
catch { /* session may not be ready yet — benign */ }
|
|
112
117
|
}, 500);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tmux-backend.js","sourceRoot":"","sources":["../../../src/adapters/backend/tmux-backend.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"tmux-backend.js","sourceRoot":"","sources":["../../../src/adapters/backend/tmux-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../../src/adapters/cli/gemini.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAA6B,MAAM,YAAY,CAAC;AAMxE,wBAAgB,mBAAmB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CAiErE;AAED,eAAO,MAAM,MAAM,4BAAsB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { resolveCommand } from './registry.js';
|
|
3
|
+
function delay(ms) {
|
|
4
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
5
|
+
}
|
|
6
|
+
export function createGeminiAdapter(pathOverride) {
|
|
7
|
+
const bin = resolveCommand(pathOverride ?? 'gemini');
|
|
8
|
+
return {
|
|
9
|
+
id: 'gemini',
|
|
10
|
+
resolvedBin: bin,
|
|
11
|
+
buildArgs({ initialPrompt }) {
|
|
12
|
+
// Gemini CLI manages sessions internally (--resume takes "latest" or
|
|
13
|
+
// an index/UUID, not our daemon session IDs). We always start fresh.
|
|
14
|
+
const args = ['--yolo'];
|
|
15
|
+
// Use -i (prompt-interactive) for the initial prompt. Gemini's Ink TUI
|
|
16
|
+
// has a startup phase where the TextInput component isn't mounted yet
|
|
17
|
+
// (auth, model loading, extensions). Writing to stdin during this phase
|
|
18
|
+
// is silently lost. -i injects the prompt inside the session so Gemini
|
|
19
|
+
// processes it once the TUI is fully ready.
|
|
20
|
+
if (initialPrompt) {
|
|
21
|
+
args.push('-i', initialPrompt);
|
|
22
|
+
}
|
|
23
|
+
return args;
|
|
24
|
+
},
|
|
25
|
+
passesInitialPromptViaArgs: true,
|
|
26
|
+
async writeInput(pty, content) {
|
|
27
|
+
// Gemini uses Ink TextInput — multi-line paste needs a delay before Enter
|
|
28
|
+
// to let the TUI process the pasted content.
|
|
29
|
+
pty.write(content);
|
|
30
|
+
await delay(200);
|
|
31
|
+
pty.write('\r');
|
|
32
|
+
},
|
|
33
|
+
ensureMcpConfig(entry) {
|
|
34
|
+
// Clean up stale entries (e.g. old "claude-code-robot" → renamed to "botmux")
|
|
35
|
+
for (const stale of ['claude-code-robot']) {
|
|
36
|
+
if (stale !== entry.name) {
|
|
37
|
+
try {
|
|
38
|
+
execSync(`${bin} mcp remove ${stale}`, { encoding: 'utf-8', timeout: 10_000, stdio: 'ignore' });
|
|
39
|
+
}
|
|
40
|
+
catch { /* not present — fine */ }
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Remove first so re-registration picks up env changes
|
|
44
|
+
try {
|
|
45
|
+
execSync(`${bin} mcp remove ${entry.name}`, { encoding: 'utf-8', timeout: 10_000, stdio: 'ignore' });
|
|
46
|
+
}
|
|
47
|
+
catch { /* not registered yet — fine */ }
|
|
48
|
+
// gemini mcp add <name> <command> [args...] -e K=V --trust --scope user
|
|
49
|
+
const envArgs = Object.entries(entry.env)
|
|
50
|
+
.map(([k, v]) => `-e ${k}=${v}`)
|
|
51
|
+
.join(' ');
|
|
52
|
+
const argsStr = entry.args.join(' ');
|
|
53
|
+
const cmd = `${bin} mcp add ${entry.name} ${entry.command} ${argsStr} ${envArgs} --trust --scope user`;
|
|
54
|
+
try {
|
|
55
|
+
execSync(cmd, { encoding: 'utf-8', timeout: 10_000, stdio: 'ignore' });
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
console.warn(`[gemini] Failed to add MCP config: ${err.message}`);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
completionPattern: undefined, // quiescence only — no explicit completion marker
|
|
62
|
+
readyPattern: undefined, // Ink TUI — '>' is too generic; rely on quiescence + spinner guard
|
|
63
|
+
systemHints: [
|
|
64
|
+
'消息可能包含 attachments,每个有 path 字段,用 Read 工具查看',
|
|
65
|
+
],
|
|
66
|
+
altScreen: true, // Ink renders in alternate screen buffer by default
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export const create = createGeminiAdapter;
|
|
70
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../../src/adapters/cli/gemini.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../../src/adapters/cli/opencode.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAA6B,MAAM,YAAY,CAAC;AAMxE,wBAAgB,qBAAqB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CA6EvE;AAED,eAAO,MAAM,MAAM,8BAAwB,CAAC"}
|