botmux 2.9.1 → 2.9.3
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.en.md +140 -76
- package/README.md +134 -75
- package/dist/adapters/backend/pty-backend.d.ts +6 -0
- package/dist/adapters/backend/pty-backend.d.ts.map +1 -1
- package/dist/adapters/backend/pty-backend.js +10 -0
- package/dist/adapters/backend/pty-backend.js.map +1 -1
- package/dist/adapters/backend/session-backend-selector.d.ts +11 -0
- package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -0
- package/dist/adapters/backend/session-backend-selector.js +26 -0
- package/dist/adapters/backend/session-backend-selector.js.map +1 -0
- package/dist/adapters/backend/tmux-backend.d.ts +80 -3
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +301 -49
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.d.ts +100 -0
- package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -0
- package/dist/adapters/backend/tmux-pipe-backend.js +473 -0
- package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -0
- package/dist/adapters/cli/aiden.d.ts.map +1 -1
- package/dist/adapters/cli/aiden.js +5 -0
- package/dist/adapters/cli/aiden.js.map +1 -1
- package/dist/adapters/cli/claude-code.d.ts +40 -1
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +470 -49
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/adapters/cli/coco.d.ts.map +1 -1
- package/dist/adapters/cli/coco.js +191 -9
- package/dist/adapters/cli/coco.js.map +1 -1
- package/dist/adapters/cli/codex.d.ts.map +1 -1
- package/dist/adapters/cli/codex.js +94 -17
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/shared-hints.d.ts +2 -2
- package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
- package/dist/adapters/cli/shared-hints.js +7 -5
- package/dist/adapters/cli/shared-hints.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +38 -1
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/autostart.d.ts +14 -0
- package/dist/autostart.d.ts.map +1 -0
- package/dist/autostart.js +357 -0
- package/dist/autostart.js.map +1 -0
- package/dist/bot-registry.d.ts +29 -3
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +91 -12
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/arg-utils.d.ts +11 -0
- package/dist/cli/arg-utils.d.ts.map +1 -0
- package/dist/cli/arg-utils.js +25 -0
- package/dist/cli/arg-utils.js.map +1 -0
- package/dist/cli/create-group-resolver.d.ts +32 -0
- package/dist/cli/create-group-resolver.d.ts.map +1 -0
- package/dist/cli/create-group-resolver.js +70 -0
- package/dist/cli/create-group-resolver.js.map +1 -0
- package/dist/cli/quoted-render.d.ts +30 -0
- package/dist/cli/quoted-render.d.ts.map +1 -0
- package/dist/cli/quoted-render.js +29 -0
- package/dist/cli/quoted-render.js.map +1 -0
- package/dist/cli.js +916 -272
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +18 -8
- package/dist/config.js.map +1 -1
- package/dist/core/command-handler.d.ts +43 -0
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +167 -64
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-events.d.ts +57 -0
- package/dist/core/dashboard-events.d.ts.map +1 -0
- package/dist/core/dashboard-events.js +23 -0
- package/dist/core/dashboard-events.js.map +1 -0
- package/dist/core/dashboard-ipc-server.d.ts +43 -0
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -0
- package/dist/core/dashboard-ipc-server.js +481 -0
- package/dist/core/dashboard-ipc-server.js.map +1 -0
- package/dist/core/dashboard-locate.d.ts +20 -0
- package/dist/core/dashboard-locate.d.ts.map +1 -0
- package/dist/core/dashboard-locate.js +26 -0
- package/dist/core/dashboard-locate.js.map +1 -0
- package/dist/core/dashboard-rows.d.ts +31 -0
- package/dist/core/dashboard-rows.d.ts.map +1 -0
- package/dist/core/dashboard-rows.js +65 -0
- package/dist/core/dashboard-rows.js.map +1 -0
- package/dist/core/inherit-peer.d.ts +14 -0
- package/dist/core/inherit-peer.d.ts.map +1 -0
- package/dist/core/inherit-peer.js +32 -0
- package/dist/core/inherit-peer.js.map +1 -0
- package/dist/core/scheduler.d.ts +24 -0
- package/dist/core/scheduler.d.ts.map +1 -1
- package/dist/core/scheduler.js +93 -2
- package/dist/core/scheduler.js.map +1 -1
- package/dist/core/session-activity.d.ts +3 -0
- package/dist/core/session-activity.d.ts.map +1 -0
- package/dist/core/session-activity.js +20 -0
- package/dist/core/session-activity.js.map +1 -0
- package/dist/core/session-discovery.d.ts +39 -0
- package/dist/core/session-discovery.d.ts.map +1 -1
- package/dist/core/session-discovery.js +114 -21
- package/dist/core/session-discovery.js.map +1 -1
- package/dist/core/session-manager.d.ts +72 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +396 -106
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/types.d.ts +27 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +14 -3
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts +72 -3
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +459 -38
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +645 -314
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/aggregator.d.ts +41 -0
- package/dist/dashboard/aggregator.d.ts.map +1 -0
- package/dist/dashboard/aggregator.js +125 -0
- package/dist/dashboard/aggregator.js.map +1 -0
- package/dist/dashboard/auth.d.ts +23 -0
- package/dist/dashboard/auth.d.ts.map +1 -0
- package/dist/dashboard/auth.js +66 -0
- package/dist/dashboard/auth.js.map +1 -0
- package/dist/dashboard/operator-selector.d.ts +20 -0
- package/dist/dashboard/operator-selector.d.ts.map +1 -0
- package/dist/dashboard/operator-selector.js +39 -0
- package/dist/dashboard/operator-selector.js.map +1 -0
- package/dist/dashboard/registry.d.ts +35 -0
- package/dist/dashboard/registry.d.ts.map +1 -0
- package/dist/dashboard/registry.js +74 -0
- package/dist/dashboard/registry.js.map +1 -0
- package/dist/dashboard/web/app.d.ts +2 -0
- package/dist/dashboard/web/app.d.ts.map +1 -0
- package/dist/dashboard/web/app.js +45 -0
- package/dist/dashboard/web/app.js.map +1 -0
- package/dist/dashboard/web/bot-defaults.d.ts +2 -0
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -0
- package/dist/dashboard/web/bot-defaults.js +201 -0
- package/dist/dashboard/web/bot-defaults.js.map +1 -0
- package/dist/dashboard/web/groups.d.ts +16 -0
- package/dist/dashboard/web/groups.d.ts.map +1 -0
- package/dist/dashboard/web/groups.js +584 -0
- package/dist/dashboard/web/groups.js.map +1 -0
- package/dist/dashboard/web/schedules.d.ts +2 -0
- package/dist/dashboard/web/schedules.d.ts.map +1 -0
- package/dist/dashboard/web/schedules.js +105 -0
- package/dist/dashboard/web/schedules.js.map +1 -0
- package/dist/dashboard/web/sessions.d.ts +2 -0
- package/dist/dashboard/web/sessions.d.ts.map +1 -0
- package/dist/dashboard/web/sessions.js +374 -0
- package/dist/dashboard/web/sessions.js.map +1 -0
- package/dist/dashboard/web/store.d.ts +23 -0
- package/dist/dashboard/web/store.d.ts.map +1 -0
- package/dist/dashboard/web/store.js +82 -0
- package/dist/dashboard/web/store.js.map +1 -0
- package/dist/dashboard-web/app.js +263 -0
- package/dist/dashboard-web/index.html +23 -0
- package/dist/dashboard-web/style.css +93 -0
- package/dist/dashboard.d.ts +2 -0
- package/dist/dashboard.d.ts.map +1 -0
- package/dist/dashboard.js +639 -0
- package/dist/dashboard.js.map +1 -0
- package/dist/im/lark/card-builder.d.ts +18 -1
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +70 -9
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +123 -109
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +35 -0
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +114 -11
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +88 -6
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +398 -62
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/forwarded-renderer.d.ts +23 -0
- package/dist/im/lark/forwarded-renderer.d.ts.map +1 -0
- package/dist/im/lark/forwarded-renderer.js +105 -0
- package/dist/im/lark/forwarded-renderer.js.map +1 -0
- package/dist/im/lark/md-card.d.ts +73 -0
- package/dist/im/lark/md-card.d.ts.map +1 -0
- package/dist/im/lark/md-card.js +332 -0
- package/dist/im/lark/md-card.js.map +1 -0
- package/dist/im/lark/merge-forward.d.ts +32 -0
- package/dist/im/lark/merge-forward.d.ts.map +1 -0
- package/dist/im/lark/merge-forward.js +110 -0
- package/dist/im/lark/merge-forward.js.map +1 -0
- package/dist/im/lark/message-parser.d.ts +9 -3
- package/dist/im/lark/message-parser.d.ts.map +1 -1
- package/dist/im/lark/message-parser.js +48 -13
- package/dist/im/lark/message-parser.js.map +1 -1
- package/dist/im/lark/quote-hint.d.ts +18 -0
- package/dist/im/lark/quote-hint.d.ts.map +1 -0
- package/dist/im/lark/quote-hint.js +23 -0
- package/dist/im/lark/quote-hint.js.map +1 -0
- package/dist/services/bridge-fallback-gate.d.ts +42 -0
- package/dist/services/bridge-fallback-gate.d.ts.map +1 -0
- package/dist/services/bridge-fallback-gate.js +12 -0
- package/dist/services/bridge-fallback-gate.js.map +1 -0
- package/dist/services/bridge-rotation-policy.d.ts +139 -0
- package/dist/services/bridge-rotation-policy.d.ts.map +1 -0
- package/dist/services/bridge-rotation-policy.js +125 -0
- package/dist/services/bridge-rotation-policy.js.map +1 -0
- package/dist/services/bridge-turn-queue.d.ts +154 -0
- package/dist/services/bridge-turn-queue.d.ts.map +1 -0
- package/dist/services/bridge-turn-queue.js +316 -0
- package/dist/services/bridge-turn-queue.js.map +1 -0
- package/dist/services/chat-first-seen-store.d.ts +27 -0
- package/dist/services/chat-first-seen-store.d.ts.map +1 -0
- package/dist/services/chat-first-seen-store.js +114 -0
- package/dist/services/chat-first-seen-store.js.map +1 -0
- package/dist/services/claude-transcript.d.ts +268 -0
- package/dist/services/claude-transcript.d.ts.map +1 -0
- package/dist/services/claude-transcript.js +798 -0
- package/dist/services/claude-transcript.js.map +1 -0
- package/dist/services/coco-transcript.d.ts +35 -0
- package/dist/services/coco-transcript.d.ts.map +1 -0
- package/dist/services/coco-transcript.js +192 -0
- package/dist/services/coco-transcript.js.map +1 -0
- package/dist/services/codex-bridge-queue.d.ts +56 -0
- package/dist/services/codex-bridge-queue.d.ts.map +1 -0
- package/dist/services/codex-bridge-queue.js +150 -0
- package/dist/services/codex-bridge-queue.js.map +1 -0
- package/dist/services/codex-transcript.d.ts +84 -0
- package/dist/services/codex-transcript.d.ts.map +1 -0
- package/dist/services/codex-transcript.js +298 -0
- package/dist/services/codex-transcript.js.map +1 -0
- package/dist/services/group-creator.d.ts +23 -0
- package/dist/services/group-creator.d.ts.map +1 -0
- package/dist/services/group-creator.js +75 -0
- package/dist/services/group-creator.js.map +1 -0
- package/dist/services/groups-store.d.ts +98 -0
- package/dist/services/groups-store.d.ts.map +1 -0
- package/dist/services/groups-store.js +213 -0
- package/dist/services/groups-store.js.map +1 -0
- package/dist/services/oncall-store.d.ts +80 -8
- package/dist/services/oncall-store.d.ts.map +1 -1
- package/dist/services/oncall-store.js +265 -55
- package/dist/services/oncall-store.js.map +1 -1
- package/dist/services/project-scanner.d.ts +1 -2
- package/dist/services/project-scanner.d.ts.map +1 -1
- package/dist/services/project-scanner.js +118 -68
- package/dist/services/project-scanner.js.map +1 -1
- package/dist/services/schedule-store.d.ts +5 -0
- package/dist/services/schedule-store.d.ts.map +1 -1
- package/dist/services/schedule-store.js +77 -1
- package/dist/services/schedule-store.js.map +1 -1
- package/dist/services/session-store.d.ts +22 -0
- package/dist/services/session-store.d.ts.map +1 -1
- package/dist/services/session-store.js +62 -4
- package/dist/services/session-store.js.map +1 -1
- package/dist/setup/bots-store.d.ts +3 -0
- package/dist/setup/bots-store.d.ts.map +1 -0
- package/dist/setup/bots-store.js +24 -0
- package/dist/setup/bots-store.js.map +1 -0
- package/dist/setup/detect-platform.d.ts +14 -0
- package/dist/setup/detect-platform.d.ts.map +1 -0
- package/dist/setup/detect-platform.js +139 -0
- package/dist/setup/detect-platform.js.map +1 -0
- package/dist/setup/ensure-fonts.d.ts +13 -0
- package/dist/setup/ensure-fonts.d.ts.map +1 -0
- package/dist/setup/ensure-fonts.js +225 -0
- package/dist/setup/ensure-fonts.js.map +1 -0
- package/dist/setup/ensure-tmux.d.ts +60 -0
- package/dist/setup/ensure-tmux.d.ts.map +1 -0
- package/dist/setup/ensure-tmux.js +236 -0
- package/dist/setup/ensure-tmux.js.map +1 -0
- package/dist/setup/index.d.ts +9 -0
- package/dist/setup/index.d.ts.map +1 -0
- package/dist/setup/index.js +46 -0
- package/dist/setup/index.js.map +1 -0
- package/dist/setup/lark-scopes.json +301 -0
- package/dist/setup/register-app.d.ts +52 -0
- package/dist/setup/register-app.d.ts.map +1 -0
- package/dist/setup/register-app.js +91 -0
- package/dist/setup/register-app.js.map +1 -0
- package/dist/setup/verify-permissions.d.ts +115 -0
- package/dist/setup/verify-permissions.d.ts.map +1 -0
- package/dist/setup/verify-permissions.js +207 -0
- package/dist/setup/verify-permissions.js.map +1 -0
- package/dist/skills/definitions.d.ts +4 -0
- package/dist/skills/definitions.d.ts.map +1 -1
- package/dist/skills/definitions.js +133 -19
- package/dist/skills/definitions.js.map +1 -1
- package/dist/skills/installer.d.ts +3 -1
- package/dist/skills/installer.d.ts.map +1 -1
- package/dist/skills/installer.js +18 -3
- package/dist/skills/installer.js.map +1 -1
- package/dist/types.d.ts +44 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/bot-routing.d.ts +6 -0
- package/dist/utils/bot-routing.d.ts.map +1 -0
- package/dist/utils/bot-routing.js +50 -0
- package/dist/utils/bot-routing.js.map +1 -0
- package/dist/utils/file-lock.d.ts +2 -0
- package/dist/utils/file-lock.d.ts.map +1 -0
- package/dist/utils/file-lock.js +114 -0
- package/dist/utils/file-lock.js.map +1 -0
- package/dist/utils/font-installer.js +1 -1
- package/dist/utils/font-installer.js.map +1 -1
- package/dist/utils/idle-detector.d.ts +6 -0
- package/dist/utils/idle-detector.d.ts.map +1 -1
- package/dist/utils/idle-detector.js +25 -4
- package/dist/utils/idle-detector.js.map +1 -1
- package/dist/utils/logger.d.ts +10 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +60 -8
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/render-dimensions.d.ts +48 -0
- package/dist/utils/render-dimensions.d.ts.map +1 -0
- package/dist/utils/render-dimensions.js +55 -0
- package/dist/utils/render-dimensions.js.map +1 -0
- package/dist/utils/screen-analyzer.d.ts.map +1 -1
- package/dist/utils/screen-analyzer.js +24 -0
- package/dist/utils/screen-analyzer.js.map +1 -1
- package/dist/utils/screenshot-renderer.d.ts.map +1 -1
- package/dist/utils/screenshot-renderer.js +67 -23
- package/dist/utils/screenshot-renderer.js.map +1 -1
- package/dist/utils/terminal-renderer.d.ts +16 -0
- package/dist/utils/terminal-renderer.d.ts.map +1 -1
- package/dist/utils/terminal-renderer.js +40 -23
- package/dist/utils/terminal-renderer.js.map +1 -1
- package/dist/utils/transient-snapshot.d.ts +28 -0
- package/dist/utils/transient-snapshot.d.ts.map +1 -0
- package/dist/utils/transient-snapshot.js +96 -0
- package/dist/utils/transient-snapshot.js.map +1 -0
- package/dist/worker.js +2248 -83
- package/dist/worker.js.map +1 -1
- package/package.json +12 -5
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ botmux 不重新实现 Agent 能力,而是直接桥接已有的 AI 编程 CLI
|
|
|
52
52
|
| 特性 | botmux | OpenClaw 类方案 |
|
|
53
53
|
|------|--------|----------------|
|
|
54
54
|
| 底层架构 | 直接桥接完整 CLI 进程 | 基于 Agent SDK 重新构建 |
|
|
55
|
-
| CLI 能力 | 完整运行时(hooks、memory、plan mode、
|
|
55
|
+
| CLI 能力 | 完整运行时(hooks、memory、plan mode、Skill、`/` 命令) | SDK API 子集,需手动实现缺失功能 |
|
|
56
56
|
| CLI 升级 | 零适配自动受益 | 需要跟进 SDK 版本变更 |
|
|
57
57
|
| 记忆 / 上下文 | 直接复用 CLI 内建的记忆系统,随 CLI 迭代自动增强 | 需自建记忆系统,与 CLI 原生能力重复 |
|
|
58
58
|
| 多 CLI 支持 | 4 种 CLI 一键切换(Claude Code / Codex / Gemini / OpenCode) | 绑定单一 SDK,无法切换 CLI |
|
|
@@ -84,7 +84,7 @@ botmux 不重新实现 Agent 能力,而是直接桥接已有的 AI 编程 CLI
|
|
|
84
84
|
|
|
85
85
|
### 多机器人协作
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
同一台机器上可运行多个飞书机器人,每个机器人可对应不同的 CLI。同一群聊中通过 @mention 路由消息,仅有一个机器人时无需 @ 自动响应;多机器人时 `@<bot1> @<bot2> /t xxx` 可让每个被 @ 的机器人在同一条消息上各自独立开新话题。
|
|
88
88
|
|
|
89
89
|
### Tmux 会话常驻
|
|
90
90
|
|
|
@@ -99,8 +99,8 @@ botmux 不重新实现 Agent 能力,而是直接桥接已有的 AI 编程 CLI
|
|
|
99
99
|
| CLI 自行退出 / 崩溃 | 随之关闭 | 已退出(自动重启用新 session) |
|
|
100
100
|
|
|
101
101
|
```bash
|
|
102
|
-
#
|
|
103
|
-
|
|
102
|
+
# 交互式会话列表 — 选择后直接 attach 到 tmux(见 § CLI 命令)
|
|
103
|
+
botmux list
|
|
104
104
|
|
|
105
105
|
# 也可以手动 attach(会话名 = bmx-<sessionId 前 8 位>)
|
|
106
106
|
tmux attach -t bmx-<session-id-前8位>
|
|
@@ -110,10 +110,6 @@ tmux attach -t bmx-<session-id-前8位>
|
|
|
110
110
|
BACKEND_TYPE=pty botmux start
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
`botmux list` 提供交互式 TUI,显示所有活跃会话的 ID、标题、工作目录、PID、运行时长和状态,方向键选择后回车即可 attach。也支持 `botmux list --plain` 输出纯文本表格供脚本使用。
|
|
114
|
-
|
|
115
|
-
**tmux 会话命名规则:** `bmx-<sessionId 前 8 位>`
|
|
116
|
-
|
|
117
113
|
### 会话接入(Adopt)
|
|
118
114
|
|
|
119
115
|
将已在 tmux 中运行的 CLI 进程无缝接入 Botmux,在手机上通过飞书查看进度和交互。
|
|
@@ -146,11 +142,22 @@ BACKEND_TYPE=pty botmux start
|
|
|
146
142
|
CLI 进入 botmux 会话时自动获得 `~/.botmux/bin` 在 PATH 中,以及一组开箱即用的 Skill:
|
|
147
143
|
|
|
148
144
|
- `botmux send` — 向当前话题发消息(支持文本、图片、文件、@mention)
|
|
149
|
-
- `botmux
|
|
145
|
+
- `botmux history` — 读取当前会话历史消息(话题群拉话题内、普通群拉整群)
|
|
146
|
+
- `botmux quoted <message_id>` — 用户用引用 UI @ 机器人时,按需读取被引用的那条消息
|
|
150
147
|
- `botmux bots list` — 查询当前群聊的机器人及 open_id
|
|
151
148
|
- `botmux schedule` — 增删改查定时任务
|
|
152
149
|
|
|
153
|
-
这些能力通过 `--append-system-prompt` 注入和 Skill 描述自动引导 agent
|
|
150
|
+
这些能力通过 `--append-system-prompt` 注入和 Skill 描述自动引导 agent 使用。Skill + CLI 的组合相比 Anthropic 官方 Telegram channel 那套 MCP 方案:CLI 启动不用做 MCP 握手、不占用工具列表 token,且对 Claude Code / Codex / Gemini / OpenCode 通用 —— 只要 CLI 能读 system prompt 跑 shell 命令就行,不依赖任何 MCP 协议支持。
|
|
151
|
+
|
|
152
|
+
### Dashboard 管控面
|
|
153
|
+
|
|
154
|
+
> 命令行 `botmux dashboard` 出一次性 token URL,浏览器里跨所有 daemon/机器人管控
|
|
155
|
+
|
|
156
|
+
- 一键定位回飞书话题 / 跳 Web 终端 / 多选批量关闭会话
|
|
157
|
+
- 拉新群、自动转让群主、@ 提醒
|
|
158
|
+
- 解散群聊、bot 退群(关联会话自动清理)
|
|
159
|
+
|
|
160
|
+
<img src="docs/dashboard.png" alt="botmux dashboard" width="800" />
|
|
154
161
|
|
|
155
162
|
---
|
|
156
163
|
|
|
@@ -166,78 +173,72 @@ CLI 进入 botmux 会话时自动获得 `~/.botmux/bin` 在 PATH 中,以及一
|
|
|
166
173
|
|
|
167
174
|
## 5 分钟快速接入
|
|
168
175
|
|
|
176
|
+
> 💡 **TL;DR**:跑 `botmux setup` 选「扫码建应用」一步完成 Step 1+2(拿 AppID/AppSecret)。PersonalAgent 应用建出来时事件订阅和 bot 能力都已默认配好,只剩 Step 4 权限申请 + Step 5(按需)重定向 URL + Step 6 发版三步要在浏览器手动点;setup 完成后会自动写 JSON 文件 + 打印一键复制命令 + 各步骤的深链。
|
|
177
|
+
|
|
169
178
|
### Step 1: 创建飞书应用
|
|
170
179
|
|
|
171
|
-
|
|
180
|
+
**推荐路径**:`botmux setup` 选「1) 扫码建应用」,飞书扫码完成后自动落盘 AppID/AppSecret,无需手动浏览器创建。底层走 `@larksuiteoapi/node-sdk` 的官方 device flow。
|
|
181
|
+
|
|
182
|
+
> ⚠️ **目前仅支持飞书 (feishu.cn) 租户**。扫码检测到 Lark 国际版 (larksuite.com) 会中止 setup —— daemon runtime (Lark Client/WSClient/event-dispatcher 等) 需要一并接入 lark 域,会在单独 PR 跟进。
|
|
183
|
+
|
|
184
|
+
**手动路径**:打开 [飞书开放平台](https://open.larkoffice.com/app),点击「创建企业自建应用」。
|
|
172
185
|
|
|
173
186
|

|
|
174
187
|
|
|
175
188
|
### Step 2: 获取凭证
|
|
176
189
|
|
|
190
|
+
> 扫码路径自动完成此步,可直接跳到 Step 3。
|
|
191
|
+
|
|
177
192
|
进入应用详情 →「凭证与基础信息」,复制 **App ID** 和 **App Secret**。
|
|
178
193
|
|
|
179
194
|

|
|
180
195
|
|
|
181
|
-
### Step 3:
|
|
182
|
-
|
|
183
|
-
进入「权限管理」→「批量导入/导出权限」,粘贴以下 JSON 一次性导入所有权限:
|
|
184
|
-
|
|
185
|
-

|
|
186
|
-
|
|
187
|
-
<details>
|
|
188
|
-
<summary>点击展开批量导入 JSON</summary>
|
|
189
|
-
|
|
190
|
-
```json
|
|
191
|
-
{
|
|
192
|
-
"scopes": {
|
|
193
|
-
"tenant": [
|
|
194
|
-
"contact:user.base:readonly",
|
|
195
|
-
"contact:user.id:readonly",
|
|
196
|
-
"im:chat:read",
|
|
197
|
-
"im:chat.members:bot_access",
|
|
198
|
-
"im:chat.members:read",
|
|
199
|
-
"im:message",
|
|
200
|
-
"im:message:readonly",
|
|
201
|
-
"im:message:send_as_bot",
|
|
202
|
-
"im:message:update",
|
|
203
|
-
"im:message.group_at_msg",
|
|
204
|
-
"im:message.group_at_msg:readonly",
|
|
205
|
-
"im:message.group_msg",
|
|
206
|
-
"im:message.p2p_msg:readonly",
|
|
207
|
-
"im:message.reactions:write_only",
|
|
208
|
-
"im:resource"
|
|
209
|
-
]
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
```
|
|
213
|
-
</details>
|
|
214
|
-
|
|
215
|
-
### Step 4: 安装 & 启动 botmux
|
|
196
|
+
### Step 3: 安装 & 启动 botmux
|
|
216
197
|
|
|
217
198
|
```bash
|
|
218
199
|
# 安装
|
|
219
200
|
npm install -g botmux
|
|
220
201
|
|
|
221
|
-
# 交互式配置 —
|
|
202
|
+
# 交互式配置 — 选「1) 扫码建应用」或「2) 手动粘 AppID/Secret」
|
|
203
|
+
# 凭证拿到后自动取一次 tenant_access_token 校验,通过才落盘 bots.json
|
|
204
|
+
# setup 末尾会把完整权限 JSON 写到 ~/.botmux/lark-scopes.json 并打印一键复制命令
|
|
222
205
|
botmux setup
|
|
223
206
|
|
|
224
|
-
#
|
|
207
|
+
# 启动(如果之后需要确认事件订阅,飞书后台会要求 daemon 已在跑才能识别长连接)
|
|
208
|
+
# start 前再校验一次凭证;权限未配齐不会阻塞 daemon,只 WARN
|
|
225
209
|
botmux start
|
|
226
210
|
```
|
|
227
211
|
|
|
228
|
-
### Step
|
|
212
|
+
### Step 4: 添加权限
|
|
229
213
|
|
|
230
|
-
|
|
214
|
+
setup 完成后,按 terminal 提示的一键复制命令把权限 JSON 复制到剪贴板,进入「权限管理」→「批量导入/导出权限」粘贴 → 提交审批。可用性范围选「仅自己可见」会自动通过:
|
|
231
215
|
|
|
232
|
-
|
|
216
|
+

|
|
233
217
|
|
|
234
|
-
|
|
218
|
+
完整 JSON 已经写到 `~/.botmux/lark-scopes.json`,源仓库版本在 [src/setup/lark-scopes.json](src/setup/lark-scopes.json)(与本仓库内部 wiki 文档同步,覆盖 tenant + user 双套域 ≈ 290 项)。
|
|
235
219
|
|
|
236
|
-
|
|
220
|
+
```bash
|
|
221
|
+
# macOS 本地
|
|
222
|
+
cat ~/.botmux/lark-scopes.json | pbcopy
|
|
223
|
+
# Linux 桌面 (本地有 X 服务器)
|
|
224
|
+
cat ~/.botmux/lark-scopes.json | xclip -selection clipboard
|
|
225
|
+
# SSH / 无 DISPLAY:直接 cat, 在本地 terminal 鼠标选中即写本地剪贴板
|
|
226
|
+
cat ~/.botmux/lark-scopes.json
|
|
227
|
+
# SSH 上 OSC 52 直接写本地剪贴板 (iTerm2 / kitty / WezTerm / Alacritty / tmux 1.5+)
|
|
228
|
+
base64 -w0 < ~/.botmux/lark-scopes.json | awk 'BEGIN{printf "\033]52;c;"}{printf "%s",$0}END{printf "\a"}'
|
|
229
|
+
```
|
|
237
230
|
|
|
238
|
-
|
|
231
|
+
> 扫码建出来的 PersonalAgent 应用,botmux 维护者实测默认已订阅 `im.message.receive_v1` + `card.action.trigger` 并开通 bot 能力,所以主线流程不再要求手动配。但飞书没在公开文档里承诺这是稳定行为,**如果配好后机器人完全收不到消息**,参见下方「Step 8: 机器人收不到消息时的自查」。
|
|
239
232
|
|
|
240
|
-
|
|
233
|
+
### Step 5: 添加重定向 URL(按需)
|
|
234
|
+
|
|
235
|
+
如果之后要在飞书里 `/login` 让 botmux 以你的身份调云文档/日历/Wiki 等 API,进入「安全设置」→「重定向 URL」填入:
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
http://127.0.0.1:9768/callback
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
只用 bot 收发消息的话这一步可以跳过。
|
|
241
242
|
|
|
242
243
|
### Step 6: 发版
|
|
243
244
|
|
|
@@ -253,14 +254,33 @@ botmux start
|
|
|
253
254
|
|
|
254
255
|

|
|
255
256
|
|
|
257
|
+
### Step 8: 机器人收不到消息时的自查(fallback)
|
|
258
|
+
|
|
259
|
+
PersonalAgent 默认配好事件订阅 + bot 能力,正常情况下不用动。如果按上面步骤走完 bot **完全收不到任何消息**(连私聊都不回),分别确认这两项:
|
|
260
|
+
|
|
261
|
+
- **事件订阅**:开放平台 → 你的应用 → 事件与回调 → 应当订阅 `im.message.receive_v1` + `card.action.trigger`(默认已订阅,如缺失就手动添加)。订阅方式必须是「使用长连接接收事件」(WebSocket),且 botmux daemon 已经在跑。
|
|
262
|
+
- **机器人能力**:开放平台 → 你的应用 → 应用功能 → 机器人 应当已开通(默认开通),名字/头像可以改。
|
|
263
|
+
|
|
264
|
+
确认后重启 daemon:`botmux restart`。
|
|
265
|
+
|
|
266
|
+
### Step 9: 开机自启(推荐)
|
|
267
|
+
|
|
268
|
+
确认机器人能正常收发消息之后,跑一次:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
botmux autostart enable
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
把 daemon 注册到当前用户的 init 系统(macOS launchd / Linux user systemd),**不需要 sudo**。重启机器自动起来。详见下方 [CLI 命令 § 开机自启](#开机自启)。
|
|
275
|
+
|
|
256
276
|
---
|
|
257
277
|
|
|
258
278
|
## 使用指南
|
|
259
279
|
|
|
260
280
|
### 使用流程
|
|
261
281
|
|
|
262
|
-
1.
|
|
263
|
-
2. 机器人弹出仓库选择卡片 —
|
|
282
|
+
1. 在飞书话题群中发送消息创建新话题;或在普通群中发 `/t <prompt>` 主动开新话题
|
|
283
|
+
2. 机器人弹出仓库选择卡片 — 选择项目或点击「直接开启会话」(`/oncall bind` 过的群会跳过此步)
|
|
264
284
|
3. CLI 在所选目录下启动
|
|
265
285
|
4. 话题中出现实时流式卡片,展示终端输出并支持 Markdown 渲染
|
|
266
286
|
5. 每次回复创建新的流式卡片,上一轮卡片冻结在最后状态
|
|
@@ -277,20 +297,21 @@ botmux start
|
|
|
277
297
|
| `/cd <路径>` | 切换工作目录 |
|
|
278
298
|
| `/status` | 查看会话信息(运行时间、终端地址等) |
|
|
279
299
|
| `/restart` | 重启 CLI 进程 |
|
|
280
|
-
| `/close` |
|
|
300
|
+
| `/close` | 关闭会话并发送可恢复卡片(含 CLI 自身 resume 命令) |
|
|
301
|
+
| `/t <prompt>` / `/topic <prompt>` | 普通群内强制开新话题(弹仓库选择卡片);prompt 留空时也可在选完仓库后再补 |
|
|
302
|
+
| `/oncall bind <path>` | 将当前群绑定到项目目录,跳过仓库选择卡片(群内任何成员可 @ 提问,按钮/命令仍走 `allowedUsers`) |
|
|
303
|
+
| `/oncall unbind` / `/oncall status` | 解绑 / 查看 oncall 绑定 |
|
|
281
304
|
| `/adopt` | 接入已运行的 CLI 会话(tmux) |
|
|
282
305
|
| `/schedule` | 管理定时任务 |
|
|
306
|
+
| `/login` / `/login status` | 飞书用户授权(用于下载第三方卡片图片等)/ 查看授权状态 |
|
|
283
307
|
| `/help` | 显示可用命令 |
|
|
284
308
|
| `/compact` `/model` `/clear` `/plugin` `/usage` | 字面透传给底层 CLI(例如 Claude Code 的内置 slash 命令) |
|
|
285
309
|
|
|
286
310
|
### 定时任务管理
|
|
287
311
|
|
|
288
|
-
|
|
289
|
-
直接说「每天 9:00 帮我生成昨天 PR 汇总」,agent 会用 `botmux-schedule` Skill 处理并跟你确认。
|
|
312
|
+
两种创建方式见上方「[定时任务](#定时任务)」小节,下面只列斜杠命令的语法和管理命令。
|
|
290
313
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
```
|
|
314
|
+
```bash
|
|
294
315
|
# 中文自然语言
|
|
295
316
|
/schedule 每日17:50 帮我看看AI圈有什么新闻
|
|
296
317
|
/schedule 工作日每天9:00 检查服务状态
|
|
@@ -300,22 +321,14 @@ botmux start
|
|
|
300
321
|
/schedule 30分钟后 检查部署状态
|
|
301
322
|
/schedule 明天9:00 发早会提醒
|
|
302
323
|
|
|
303
|
-
#
|
|
324
|
+
# 英文 / cron
|
|
304
325
|
/schedule every 2h 巡检服务
|
|
305
326
|
/schedule 30m 提醒我喝水
|
|
306
|
-
|
|
307
|
-
# 标准 cron
|
|
308
327
|
/schedule 0 9 * * * 早安问候
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
管理任务:
|
|
312
328
|
|
|
313
|
-
|
|
329
|
+
# 管理任务
|
|
314
330
|
/schedule list
|
|
315
|
-
/schedule remove <id>
|
|
316
|
-
/schedule enable <id>
|
|
317
|
-
/schedule disable <id>
|
|
318
|
-
/schedule run <id>
|
|
331
|
+
/schedule remove|enable|disable|run <id>
|
|
319
332
|
```
|
|
320
333
|
|
|
321
334
|
**任务执行行为**:到点会在**创建任务的原话题**内续一条消息并执行,不会另开 thread。工作目录与创建时一致。如果原话题的会话还活着,prompt 直接注入现有会话(不另起 worker)。
|
|
@@ -337,6 +350,22 @@ botmux start
|
|
|
337
350
|
| `botmux delete <id>` | 关闭指定会话,支持 ID 前缀匹配(别名 `del`/`rm`) |
|
|
338
351
|
| `botmux delete all` | 关闭所有活跃会话 |
|
|
339
352
|
| `botmux delete stopped` | 清理所有进程已退出的僵尸会话 |
|
|
353
|
+
| `botmux autostart enable` | 注册开机自启(macOS launchd / Linux user systemd,无需 sudo) |
|
|
354
|
+
| `botmux autostart disable` | 注销开机自启 |
|
|
355
|
+
| `botmux autostart status` | 查看自启状态 |
|
|
356
|
+
| `botmux dashboard` | 输出一次 Web Dashboard URL(每次刷 token,旧链接立即失效) |
|
|
357
|
+
|
|
358
|
+
### 开机自启
|
|
359
|
+
|
|
360
|
+
`botmux autostart enable` 把 daemon 注册到当前用户的 init 系统,重启机器后自动起来:
|
|
361
|
+
|
|
362
|
+
- **macOS**:写 `~/Library/LaunchAgents/com.botmux.daemon.plist`,用 `launchctl bootstrap` 加载,**不需要 sudo**。
|
|
363
|
+
- **Linux**:写 `~/.config/systemd/user/botmux.service`,用 `systemctl --user enable --now` 启用,**不需要 sudo**。
|
|
364
|
+
- 服务器/无桌面环境下,登出会话后 user systemd 默认会停服务。需要跨登出常驻请额外跑 `sudo loginctl enable-linger <你的用户名>`,autostart enable 会在 linger 未启用时提示。
|
|
365
|
+
- 容器或 SSH-only 没有 user DBus 的环境会回退到打印手动指令。
|
|
366
|
+
- 单元文件里的 `node` / `cli.js` 路径来自当前 `process.execPath`,nvm/fnm 切版本后跑一次 `botmux autostart enable` 重写即可。`botmux start`/`restart` 也会自动检测路径变化、原地刷新单元文件,无需手动操作。
|
|
367
|
+
- `enable` / `disable` **只管开机自启钩子,不动正在跑的 daemon**。需要立即启动跑 `botmux start`,需要停跑 `botmux stop`。这样就不会"我只是想关掉自启,结果服务也被一起干掉了"。
|
|
368
|
+
- 想用 systemd 管 daemon 生命周期(`systemctl --user start/stop botmux`)也行——unit 里写了 ExecStop 调用 `botmux stop`,是干净的关停路径。
|
|
340
369
|
|
|
341
370
|
### 会话内子命令(给 CLI agent 用)
|
|
342
371
|
|
|
@@ -346,7 +375,8 @@ botmux start
|
|
|
346
375
|
|------|------|
|
|
347
376
|
| `botmux send [content]` | 向当前话题发消息。支持 stdin / heredoc / `--content-file` 传内容,`--images`/`--files`/`--mention` 附加资源 |
|
|
348
377
|
| `botmux bots list` | 列出当前群聊中的机器人(含 open_id,供 `--mention` 使用) |
|
|
349
|
-
| `botmux
|
|
378
|
+
| `botmux history [--limit N]` | 拉取当前会话的消息历史(JSON);话题群 → 话题内,普通群 → 整群 |
|
|
379
|
+
| `botmux quoted <message_id>` | 拉取被引用的单条消息(JSON),ID 取自 daemon 注入的 `[用户引用了消息 用 botmux quoted om_xxx 查看]` 提示行 |
|
|
350
380
|
| `botmux schedule add <schedule> <prompt>` | 创建定时任务(自动绑定当前话题) |
|
|
351
381
|
| `botmux schedule list/remove/pause/resume/run` | 管理定时任务 |
|
|
352
382
|
|
|
@@ -354,6 +384,34 @@ botmux start
|
|
|
354
384
|
|
|
355
385
|
---
|
|
356
386
|
|
|
387
|
+
## Web Dashboard
|
|
388
|
+
|
|
389
|
+
botmux 启动后会自带一个 Web Dashboard 用来管理所有会话和定时任务。
|
|
390
|
+
|
|
391
|
+
```bash
|
|
392
|
+
botmux dashboard
|
|
393
|
+
# 输出: http://<lan-ip>:7891/?t=<token>
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
每次跑 `botmux dashboard` 都会换一个 token,老 URL 立即失效——这是有意为之,符合一次一密的取链方式。
|
|
397
|
+
|
|
398
|
+
页面功能(v1):
|
|
399
|
+
- **Sessions**:跨所有 bot 列出活跃和已关闭会话,支持按 CLI / 状态 / adopt / 文本搜索过滤。点进 detail drawer 后可以「定位到飞书话题」(机器人在原话题发一条 📍 标记 + 浏览器自动开 chat AppLink,规避飞书没有公开 topic deep-link 的限制)、复制各种 ID、关闭会话。
|
|
400
|
+
- **Schedules**:列出所有定时任务,可以 Run now / Pause / Resume。
|
|
401
|
+
|
|
402
|
+
环境变量(写在 `~/.botmux/.env`):
|
|
403
|
+
|
|
404
|
+
| 变量 | 默认 | 说明 |
|
|
405
|
+
|------|------|------|
|
|
406
|
+
| `BOTMUX_DASHBOARD_HOST` | `0.0.0.0` | dashboard HTTP 绑定地址 |
|
|
407
|
+
| `BOTMUX_DASHBOARD_PORT` | `7891` | dashboard HTTP 端口 |
|
|
408
|
+
| `BOTMUX_DASHBOARD_EXTERNAL_HOST` | `WEB_EXTERNAL_HOST` 或 LAN IP 自动探测 | CLI 输出 URL 用的 host |
|
|
409
|
+
| `BOTMUX_DAEMON_IPC_BASE_PORT` | `7892` | 每个 daemon 的 IPC 端口 = base + botIndex |
|
|
410
|
+
|
|
411
|
+
dashboard 走单独 pm2 进程 `botmux-dashboard`,跟着 `pnpm daemon:restart` 一起起停。每个 daemon 在 127.0.0.1 暴露内部 IPC(仅本机),dashboard 进程做反向代理 + 鉴权。`.dashboard-secret` 在首次启动时生成(`~/.botmux/.dashboard-secret`,mode 0600),仅用于 `botmux dashboard` 命令的 HMAC 鉴权,不下发给浏览器。
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
357
415
|
## 配置
|
|
358
416
|
|
|
359
417
|
通过 `~/.botmux/bots.json` 配置机器人。运行 `botmux setup` 交互式创建,或手动编辑。
|
|
@@ -393,6 +451,7 @@ botmux setup
|
|
|
393
451
|
| `workingDir` | 否 | 默认工作目录,支持逗号分隔多个目录 |
|
|
394
452
|
| `allowedUsers` | 否 | 允许的用户列表(邮箱前缀或 open_id) |
|
|
395
453
|
| `projectScanDir` | 否 | 扫描 Git 仓库的目录 |
|
|
454
|
+
| `oncallChats` | 否 | oncall 绑定(`/oncall bind` 写入),形如 `[{ "chatId": "oc_xxx", "workingDir": "~/projects/foo" }]`,群内任何成员可 @ 提问 |
|
|
396
455
|
|
|
397
456
|
**配置优先级:** `BOTS_CONFIG` 环境变量 → `~/.botmux/bots.json`
|
|
398
457
|
|
|
@@ -4,6 +4,12 @@ export declare class PtyBackend implements SessionBackend {
|
|
|
4
4
|
/** Claude Code session JSONL path — set by worker for claude-code sessions so
|
|
5
5
|
* the claude-code adapter can verify paste+Enter submissions via file growth. */
|
|
6
6
|
claudeJsonlPath?: string;
|
|
7
|
+
/** PID of the spawned Claude Code child — used by the claude-code adapter to
|
|
8
|
+
* follow Claude's authoritative session id via ~/.claude/sessions/<pid>.json. */
|
|
9
|
+
cliPid?: number;
|
|
10
|
+
/** Working directory the CLI was spawned in — cross-checked against the pid
|
|
11
|
+
* file's cwd field so a recycled PID can't mislead the resolver. */
|
|
12
|
+
cliCwd?: string;
|
|
7
13
|
spawn(bin: string, args: string[], opts: SpawnOpts): void;
|
|
8
14
|
write(data: string): void;
|
|
9
15
|
resize(cols: number, rows: number): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pty-backend.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/pty-backend.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"pty-backend.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/pty-backend.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAY5D,qBAAa,UAAW,YAAW,cAAc;IAC/C,OAAO,CAAC,OAAO,CAAyB;IAExC;sFACkF;IAClF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;sFACkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;yEACqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAezD,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,WAAW,IAAI,MAAM,GAAG,IAAI;IAI5B,IAAI,IAAI,IAAI;CAMb"}
|
|
@@ -2,6 +2,7 @@ import * as pty from 'node-pty';
|
|
|
2
2
|
import { chmodSync, statSync } from 'node:fs';
|
|
3
3
|
import { dirname, join } from 'node:path';
|
|
4
4
|
import { createRequire } from 'node:module';
|
|
5
|
+
import { logger } from '../../utils/logger.js';
|
|
5
6
|
// npx may strip execute bits from prebuilt binaries — fix before first spawn.
|
|
6
7
|
try {
|
|
7
8
|
const req = createRequire(import.meta.url);
|
|
@@ -16,7 +17,15 @@ export class PtyBackend {
|
|
|
16
17
|
/** Claude Code session JSONL path — set by worker for claude-code sessions so
|
|
17
18
|
* the claude-code adapter can verify paste+Enter submissions via file growth. */
|
|
18
19
|
claudeJsonlPath;
|
|
20
|
+
/** PID of the spawned Claude Code child — used by the claude-code adapter to
|
|
21
|
+
* follow Claude's authoritative session id via ~/.claude/sessions/<pid>.json. */
|
|
22
|
+
cliPid;
|
|
23
|
+
/** Working directory the CLI was spawned in — cross-checked against the pid
|
|
24
|
+
* file's cwd field so a recycled PID can't mislead the resolver. */
|
|
25
|
+
cliCwd;
|
|
19
26
|
spawn(bin, args, opts) {
|
|
27
|
+
logger.debug(`[pty] spawn bin=${bin} args=${JSON.stringify(args)} ` +
|
|
28
|
+
`cwd=${opts.cwd} ${opts.cols}x${opts.rows}`);
|
|
20
29
|
this.process = pty.spawn(bin, args, {
|
|
21
30
|
name: 'xterm-256color',
|
|
22
31
|
cols: opts.cols,
|
|
@@ -24,6 +33,7 @@ export class PtyBackend {
|
|
|
24
33
|
cwd: opts.cwd,
|
|
25
34
|
env: opts.env,
|
|
26
35
|
});
|
|
36
|
+
logger.debug(`[pty] spawned pid=${this.process.pid}`);
|
|
27
37
|
}
|
|
28
38
|
write(data) {
|
|
29
39
|
this.process?.write(data);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pty-backend.js","sourceRoot":"","sources":["../../../src/adapters/backend/pty-backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"pty-backend.js","sourceRoot":"","sources":["../../../src/adapters/backend/pty-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SessionBackend } from './types.js';
|
|
2
|
+
export interface SelectedSessionBackend {
|
|
3
|
+
backend: SessionBackend;
|
|
4
|
+
isTmuxMode: boolean;
|
|
5
|
+
isPipeMode: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function selectSessionBackend(opts: {
|
|
8
|
+
sessionId: string;
|
|
9
|
+
useTmux: boolean;
|
|
10
|
+
}): SelectedSessionBackend;
|
|
11
|
+
//# sourceMappingURL=session-backend-selector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-backend-selector.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/session-backend-selector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,sBAAsB,CAuB1G"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { PtyBackend } from './pty-backend.js';
|
|
2
|
+
import { TmuxBackend } from './tmux-backend.js';
|
|
3
|
+
import { TmuxPipeBackend } from './tmux-pipe-backend.js';
|
|
4
|
+
export function selectSessionBackend(opts) {
|
|
5
|
+
if (!opts.useTmux) {
|
|
6
|
+
return {
|
|
7
|
+
backend: new PtyBackend(),
|
|
8
|
+
isTmuxMode: false,
|
|
9
|
+
isPipeMode: false,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
const sessionName = TmuxBackend.sessionName(opts.sessionId);
|
|
13
|
+
if (TmuxBackend.hasSession(sessionName)) {
|
|
14
|
+
return {
|
|
15
|
+
backend: new TmuxPipeBackend(sessionName, { ownsSession: true, isReattach: true }),
|
|
16
|
+
isTmuxMode: true,
|
|
17
|
+
isPipeMode: true,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
backend: new TmuxPipeBackend(sessionName, { createSession: true, ownsSession: true }),
|
|
22
|
+
isTmuxMode: true,
|
|
23
|
+
isPipeMode: true,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=session-backend-selector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-backend-selector.js","sourceRoot":"","sources":["../../../src/adapters/backend/session-backend-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AASzD,MAAM,UAAU,oBAAoB,CAAC,IAA6C;IAChF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO;YACL,OAAO,EAAE,IAAI,UAAU,EAAE;YACzB,UAAU,EAAE,KAAK;YACjB,UAAU,EAAE,KAAK;SAClB,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5D,IAAI,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACxC,OAAO;YACL,OAAO,EAAE,IAAI,eAAe,CAAC,WAAW,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;YAClF,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,IAAI;SACjB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI,eAAe,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QACrF,UAAU,EAAE,IAAI;QAChB,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC"}
|
|
@@ -15,10 +15,24 @@ export declare class TmuxBackend implements SessionBackend {
|
|
|
15
15
|
private readonly sessionName;
|
|
16
16
|
private readonly ownsSession;
|
|
17
17
|
private reattaching;
|
|
18
|
+
/** Tmux pane target when in adopt mode (e.g. "0:2.0") — set by attachToExisting.
|
|
19
|
+
* When non-null, ALL pane-scoped tmux commands (send-keys / paste-buffer /
|
|
20
|
+
* copy-mode / list-panes) must address this pane explicitly; using
|
|
21
|
+
* `this.sessionName` would either resolve nothing (the name is synthetic
|
|
22
|
+
* in adopt mode) or fall through to whichever pane tmux happens to have
|
|
23
|
+
* active, which is exactly the bug we're avoiding. */
|
|
24
|
+
private adoptedPaneTarget;
|
|
18
25
|
constructor(sessionName: string, opts?: {
|
|
19
26
|
ownsSession?: boolean;
|
|
20
27
|
});
|
|
21
|
-
/**
|
|
28
|
+
/** Target string to use for pane-scoped tmux commands. In adopt mode this
|
|
29
|
+
* is the real pane address ("0:2.0"); otherwise the bmx-* session name. */
|
|
30
|
+
private get cmdTarget();
|
|
31
|
+
/**
|
|
32
|
+
* Check if tmux is usable — runs a functional probe (start + kill a
|
|
33
|
+
* disposable server), not just `tmux -V`. Same probe as config.ts so
|
|
34
|
+
* backend selection and runtime guard agree.
|
|
35
|
+
*/
|
|
22
36
|
static isAvailable(): boolean;
|
|
23
37
|
/** Derive tmux session name from a session UUID. */
|
|
24
38
|
static sessionName(sessionId: string): string;
|
|
@@ -34,6 +48,12 @@ export declare class TmuxBackend implements SessionBackend {
|
|
|
34
48
|
/** Claude Code session JSONL path — set by worker for claude-code sessions so
|
|
35
49
|
* the claude-code adapter can verify paste+Enter submissions via file growth. */
|
|
36
50
|
claudeJsonlPath?: string;
|
|
51
|
+
/** PID of the spawned Claude Code child — used by the claude-code adapter to
|
|
52
|
+
* follow Claude's authoritative session id via ~/.claude/sessions/<pid>.json. */
|
|
53
|
+
cliPid?: number;
|
|
54
|
+
/** Working directory the CLI was spawned in — cross-checked against the pid
|
|
55
|
+
* file's cwd field so a recycled PID can't mislead the resolver. */
|
|
56
|
+
cliCwd?: string;
|
|
37
57
|
write(data: string): void;
|
|
38
58
|
/**
|
|
39
59
|
* Send text literally to the tmux pane via `tmux send-keys -l`.
|
|
@@ -57,6 +77,7 @@ export declare class TmuxBackend implements SessionBackend {
|
|
|
57
77
|
* Safe for multiline content (unlike sendText where \n becomes Enter).
|
|
58
78
|
*/
|
|
59
79
|
pasteText(text: string): void;
|
|
80
|
+
private exitCopyModeIfNeeded;
|
|
60
81
|
resize(cols: number, rows: number): void;
|
|
61
82
|
/** Must be called AFTER spawn(). Callbacks registered before spawn are silently lost. */
|
|
62
83
|
onData(cb: (data: string) => void): void;
|
|
@@ -75,11 +96,67 @@ export declare class TmuxBackend implements SessionBackend {
|
|
|
75
96
|
* The zoom is undone when the backend is killed (detach/disconnect).
|
|
76
97
|
*/
|
|
77
98
|
attachToExisting(tmuxTarget: string, opts: SpawnOpts): void;
|
|
78
|
-
/** Tmux pane target when in adopt mode (e.g. "0:2.0") — used for zoom cleanup. */
|
|
79
|
-
private adoptedPaneTarget;
|
|
80
99
|
getAttachInfo(): {
|
|
81
100
|
type: "tmux";
|
|
82
101
|
sessionName: string;
|
|
83
102
|
};
|
|
84
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Build the `KEY=VAL` argv slice passed to `/usr/bin/env`. Only forwards the
|
|
106
|
+
* keys in `BOTMUX_INJECTED_ENV_KEYS` and only when the value is defined —
|
|
107
|
+
* `IS_SANDBOX` for instance is only set when the daemon is running as root.
|
|
108
|
+
* Pure function for unit-testing without spawning tmux.
|
|
109
|
+
*/
|
|
110
|
+
export declare function buildBotmuxEnvAssignments(env: NodeJS.ProcessEnv | undefined): string[];
|
|
111
|
+
/**
|
|
112
|
+
* Default wrapper script for `<shell> -c`. Sees argv as:
|
|
113
|
+
* $0 = '_' (placeholder), $1 = cwd, $2..N = KEY=VAL... bin args...
|
|
114
|
+
*
|
|
115
|
+
* The `cd` step makes the CLI's cwd survive a wayward `cd` in the user's
|
|
116
|
+
* rcfile. The `exec /usr/bin/env` step injects botmux's per-bot/per-session
|
|
117
|
+
* overrides AFTER rcfile load so they can't be shadowed by leftover exports.
|
|
118
|
+
*
|
|
119
|
+
* POSIX-syntax (works in bash/zsh/sh); fish/csh/nu users get remapped to
|
|
120
|
+
* bash/zsh/sh by resolveUserShell() so they hit the same SCRIPT path.
|
|
121
|
+
*/
|
|
122
|
+
export declare const SHELL_WRAPPER_SCRIPT = "cd -- \"$1\" && shift && exec /usr/bin/env \"$@\"";
|
|
123
|
+
/**
|
|
124
|
+
* Debug variant of the wrapper script — same prelude, but the CLI runs as
|
|
125
|
+
* a *child* (no `exec`) and the wrapper hands off to an interactive shell
|
|
126
|
+
* once the CLI exits. Useful for diagnosing missing PATH / NVM / pnpm /
|
|
127
|
+
* mise shims in the user's rcfile: hit Ctrl-C in the web terminal, land
|
|
128
|
+
* in `<shell> -i`, run `echo $PATH` / `which node` / etc.
|
|
129
|
+
*
|
|
130
|
+
* Enabled with `BOTMUX_DEBUG_KEEP_SHELL=1` at daemon-start time.
|
|
131
|
+
*
|
|
132
|
+
* `shellPath` is single-quoted into the script with `'` escaped, so it's
|
|
133
|
+
* safe for paths containing spaces or quotes. Caller has already verified
|
|
134
|
+
* it via accessSync().
|
|
135
|
+
*/
|
|
136
|
+
export declare function buildDebugKeepShellScript(shellPath: string): string;
|
|
137
|
+
export type ShellKind = 'bash' | 'zsh' | 'sh';
|
|
138
|
+
export interface ShellSpec {
|
|
139
|
+
/** Absolute path to the shell binary. */
|
|
140
|
+
shell: string;
|
|
141
|
+
/** Rcfile-loading flags (`-i`, `-l -i`, or empty) — caller appends
|
|
142
|
+
* `-c <SCRIPT> _ <cwd> KEY=VAL... bin args...` after these. */
|
|
143
|
+
flags: string[];
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Pick a shell to wrap the CLI launch in, returning the binary path plus the
|
|
147
|
+
* exact argv flags needed for its rcfiles to load. Tries `$SHELL` first, then
|
|
148
|
+
* `/bin/zsh` → `/bin/bash` → `/bin/sh`.
|
|
149
|
+
*
|
|
150
|
+
* If `$SHELL` is fish/nu/csh/etc., emits a warning and falls back to a POSIX
|
|
151
|
+
* shell — our wrapper SCRIPT is POSIX-syntax and would break under fish. The
|
|
152
|
+
* user can still configure their CLI's PATH/etc. inside the fallback shell's
|
|
153
|
+
* rcfile if needed; the alternative (run their fish rcfile under a POSIX
|
|
154
|
+
* harness) does not work.
|
|
155
|
+
*
|
|
156
|
+
* Always returns a usable ShellSpec — the last-resort `/bin/sh` fallback is
|
|
157
|
+
* close enough to universal that surfacing an error here would do more harm
|
|
158
|
+
* than good. If `/bin/sh` is also missing, tmux's own spawn will fail with
|
|
159
|
+
* a clear message.
|
|
160
|
+
*/
|
|
161
|
+
export declare function resolveUserShell(env?: NodeJS.ProcessEnv): ShellSpec;
|
|
85
162
|
//# sourceMappingURL=tmux-backend.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tmux-backend.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/tmux-backend.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tmux-backend.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/tmux-backend.ts"],"names":[],"mappings":"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"}
|