botmux 2.106.1-canary.0 → 2.107.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +10 -10
- package/README.md +10 -10
- package/dist/adapters/backend/sandbox.d.ts +6 -20
- package/dist/adapters/backend/sandbox.d.ts.map +1 -1
- package/dist/adapters/backend/sandbox.js +26 -150
- package/dist/adapters/backend/sandbox.js.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.d.ts +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.js +1 -1
- package/dist/adapters/backend/zellij-observe-backend.d.ts +1 -1
- package/dist/adapters/backend/zellij-observe-backend.js +1 -1
- package/dist/adapters/cli/read-isolation.d.ts +2 -1
- package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
- package/dist/adapters/cli/read-isolation.js +51 -4
- package/dist/adapters/cli/read-isolation.js.map +1 -1
- package/dist/bot-registry.d.ts +90 -1
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +151 -0
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/vc-agent.d.ts +2 -0
- package/dist/cli/vc-agent.d.ts.map +1 -0
- package/dist/cli/vc-agent.js +331 -0
- package/dist/cli/vc-agent.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +30 -4
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -1
- package/dist/config.js.map +1 -1
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +7 -1
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +74 -3
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dashboard-rows.d.ts +6 -0
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +25 -0
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/core/idle-worker-sweeper.d.ts +1 -1
- package/dist/core/idle-worker-sweeper.js +1 -1
- package/dist/core/passthrough-commands.d.ts.map +1 -1
- package/dist/core/passthrough-commands.js +2 -1
- package/dist/core/passthrough-commands.js.map +1 -1
- package/dist/core/pending-response.d.ts +1 -0
- package/dist/core/pending-response.d.ts.map +1 -1
- package/dist/core/pending-response.js +1 -0
- package/dist/core/pending-response.js.map +1 -1
- package/dist/core/resource-monitor/attribution.d.ts +70 -0
- package/dist/core/resource-monitor/attribution.d.ts.map +1 -0
- package/dist/core/resource-monitor/attribution.js +222 -0
- package/dist/core/resource-monitor/attribution.js.map +1 -0
- package/dist/core/resource-monitor/procfs.d.ts +22 -0
- package/dist/core/resource-monitor/procfs.d.ts.map +1 -0
- package/dist/core/resource-monitor/procfs.js +134 -0
- package/dist/core/resource-monitor/procfs.js.map +1 -0
- package/dist/core/resource-monitor/ring-buffer.d.ts +15 -0
- package/dist/core/resource-monitor/ring-buffer.d.ts.map +1 -0
- package/dist/core/resource-monitor/ring-buffer.js +61 -0
- package/dist/core/resource-monitor/ring-buffer.js.map +1 -0
- package/dist/core/resource-monitor/runtime.d.ts +31 -0
- package/dist/core/resource-monitor/runtime.d.ts.map +1 -0
- package/dist/core/resource-monitor/runtime.js +92 -0
- package/dist/core/resource-monitor/runtime.js.map +1 -0
- package/dist/core/resource-monitor/top-selector.d.ts +18 -0
- package/dist/core/resource-monitor/top-selector.d.ts.map +1 -0
- package/dist/core/resource-monitor/top-selector.js +57 -0
- package/dist/core/resource-monitor/top-selector.js.map +1 -0
- package/dist/core/resource-monitor/types.d.ts +181 -0
- package/dist/core/resource-monitor/types.d.ts.map +1 -0
- package/dist/core/resource-monitor/types.js +2 -0
- package/dist/core/resource-monitor/types.js.map +1 -0
- package/dist/core/session-manager.d.ts +4 -2
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +82 -7
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/trigger-session.d.ts.map +1 -1
- package/dist/core/trigger-session.js +7 -2
- package/dist/core/trigger-session.js.map +1 -1
- package/dist/core/types.d.ts +4 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts +4 -0
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +27 -9
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/core/zellij-adopt-discovery.js +1 -1
- package/dist/core/zellij-adopt-discovery.js.map +1 -1
- package/dist/daemon.d.ts +145 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +3441 -98
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/bot-payload.d.ts +1 -0
- package/dist/dashboard/bot-payload.d.ts.map +1 -1
- package/dist/dashboard/bot-payload.js +1 -0
- package/dist/dashboard/bot-payload.js.map +1 -1
- package/dist/dashboard/federated-group-core.js +1 -1
- package/dist/dashboard/federated-group-core.js.map +1 -1
- package/dist/dashboard/federation-api.js +1 -1
- package/dist/dashboard/resource-monitor-service.d.ts +56 -0
- package/dist/dashboard/resource-monitor-service.d.ts.map +1 -0
- package/dist/dashboard/resource-monitor-service.js +446 -0
- package/dist/dashboard/resource-monitor-service.js.map +1 -0
- package/dist/dashboard/settings-write-applier.d.ts +31 -1
- package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
- package/dist/dashboard/settings-write-applier.js +47 -0
- package/dist/dashboard/settings-write-applier.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js +160 -1
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/dashboard-routes.d.ts.map +1 -1
- package/dist/dashboard/web/dashboard-routes.js +18 -0
- package/dist/dashboard/web/dashboard-routes.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +296 -2
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/insights.js +19 -19
- package/dist/dashboard/web/insights.js.map +1 -1
- package/dist/dashboard/web/monitor-room-store.d.ts +20 -0
- package/dist/dashboard/web/monitor-room-store.d.ts.map +1 -0
- package/dist/dashboard/web/monitor-room-store.js +80 -0
- package/dist/dashboard/web/monitor-room-store.js.map +1 -0
- package/dist/dashboard/web/monitor-room.d.ts +31 -0
- package/dist/dashboard/web/monitor-room.d.ts.map +1 -0
- package/dist/dashboard/web/monitor-room.js +393 -0
- package/dist/dashboard/web/monitor-room.js.map +1 -0
- package/dist/dashboard/web/monitoring-page.d.ts +155 -0
- package/dist/dashboard/web/monitoring-page.d.ts.map +1 -0
- package/dist/dashboard/web/monitoring-page.js +189 -0
- package/dist/dashboard/web/monitoring-page.js.map +1 -0
- package/dist/dashboard/web/overview-page.d.ts.map +1 -1
- package/dist/dashboard/web/overview-page.js +108 -1
- package/dist/dashboard/web/overview-page.js.map +1 -1
- package/dist/dashboard/web/preferences.d.ts +3 -0
- package/dist/dashboard/web/preferences.d.ts.map +1 -1
- package/dist/dashboard/web/preferences.js +18 -0
- package/dist/dashboard/web/preferences.js.map +1 -1
- package/dist/dashboard/web/session-terminal.d.ts +7 -0
- package/dist/dashboard/web/session-terminal.d.ts.map +1 -0
- package/dist/dashboard/web/session-terminal.js +17 -0
- package/dist/dashboard/web/session-terminal.js.map +1 -0
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-page.js +2 -1
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts +4 -0
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +100 -19
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/settings-page.d.ts.map +1 -1
- package/dist/dashboard/web/settings-page.js +101 -46
- package/dist/dashboard/web/settings-page.js.map +1 -1
- package/dist/dashboard/web/skills-page.js +1 -1
- package/dist/dashboard/web/skills-page.js.map +1 -1
- package/dist/dashboard/web/substitute-targets.d.ts +30 -0
- package/dist/dashboard/web/substitute-targets.d.ts.map +1 -0
- package/dist/dashboard/web/substitute-targets.js +99 -0
- package/dist/dashboard/web/substitute-targets.js.map +1 -0
- package/dist/dashboard/web/ui.d.ts +1 -1
- package/dist/dashboard/web/ui.d.ts.map +1 -1
- package/dist/dashboard/web/ui.js +4 -1
- package/dist/dashboard/web/ui.js.map +1 -1
- package/dist/dashboard-web/app.js +3 -3
- package/dist/dashboard-web/chunks/bot-defaults-page-OCIHPGEU.js +438 -0
- package/dist/dashboard-web/chunks/chunk-3N2PPQVD.js +1 -0
- package/dist/dashboard-web/chunks/chunk-3UJYRR2Q.js +37 -0
- package/dist/dashboard-web/chunks/{chunk-RRBSPQVK.js → chunk-PE6W3C2C.js} +1 -1
- package/dist/dashboard-web/chunks/chunk-QW54DWU3.js +325 -0
- package/dist/dashboard-web/chunks/{connectors-WZR7MAXE.js → connectors-IGETYWCP.js} +1 -1
- package/dist/dashboard-web/chunks/{groups-page-NK6U5JIU.js → groups-page-MYBS4ZYJ.js} +1 -1
- package/dist/dashboard-web/chunks/{insights-page-2TN3ZR33.js → insights-page-UPA32V2S.js} +1 -1
- package/dist/dashboard-web/chunks/monitor-room-RFX4HPS5.js +51 -0
- package/dist/dashboard-web/chunks/monitoring-page-7T3BESZ2.js +1 -0
- package/dist/dashboard-web/chunks/overview-page-LJSBCQW4.js +1 -0
- package/dist/dashboard-web/chunks/{roles-page-J6CRSIJ6.js → roles-page-ESURTVQH.js} +1 -1
- package/dist/dashboard-web/chunks/{schedules-6RONVOOV.js → schedules-LML2ISOT.js} +1 -1
- package/dist/dashboard-web/chunks/sessions-YB73XOTU.js +1 -0
- package/dist/dashboard-web/chunks/sessions-page-MCO5QR7Z.js +1 -0
- package/dist/dashboard-web/chunks/settings-page-OSDKNVS3.js +2 -0
- package/dist/dashboard-web/chunks/skills-page-PXBZJ6P6.js +2 -0
- package/dist/dashboard-web/chunks/{team-federation-page-QYAP7XJF.js → team-federation-page-TTPVHFPX.js} +1 -1
- package/dist/dashboard-web/chunks/{workflows-2L4DKNCK.js → workflows-FCPM4S4D.js} +1 -1
- package/dist/dashboard-web/index.html +2 -1
- package/dist/dashboard-web/style.css +940 -24
- package/dist/dashboard.js +404 -3
- package/dist/dashboard.js.map +1 -1
- package/dist/global-config.d.ts +23 -0
- package/dist/global-config.d.ts.map +1 -1
- package/dist/global-config.js +58 -1
- package/dist/global-config.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +17 -6
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +17 -6
- package/dist/i18n/zh.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 +19 -1
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts +3 -0
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +20 -2
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +13 -0
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +141 -5
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/grant-command.d.ts +1 -1
- package/dist/im/lark/grant-command.js +1 -1
- package/dist/im/lark/message-parser.d.ts +41 -0
- package/dist/im/lark/message-parser.d.ts.map +1 -1
- package/dist/im/lark/message-parser.js +70 -0
- package/dist/im/lark/message-parser.js.map +1 -1
- package/dist/im/lark/substitute-command.d.ts +2 -0
- package/dist/im/lark/substitute-command.d.ts.map +1 -0
- package/dist/im/lark/substitute-command.js +51 -0
- package/dist/im/lark/substitute-command.js.map +1 -0
- package/dist/mir-prompt.d.ts +16 -0
- package/dist/mir-prompt.d.ts.map +1 -0
- package/dist/mir-prompt.js +170 -0
- package/dist/mir-prompt.js.map +1 -0
- package/dist/mir-runner.js +1 -149
- package/dist/mir-runner.js.map +1 -1
- package/dist/services/deployment-identity.d.ts +1 -1
- package/dist/services/deployment-identity.d.ts.map +1 -1
- package/dist/services/deployment-identity.js +1 -1
- package/dist/services/deployment-identity.js.map +1 -1
- package/dist/services/doc-subs-store.js +1 -1
- package/dist/services/substitute-chat-toggle-store.d.ts +3 -0
- package/dist/services/substitute-chat-toggle-store.d.ts.map +1 -0
- package/dist/services/substitute-chat-toggle-store.js +58 -0
- package/dist/services/substitute-chat-toggle-store.js.map +1 -0
- package/dist/services/substitute-mode-normalize.d.ts +22 -0
- package/dist/services/substitute-mode-normalize.d.ts.map +1 -0
- package/dist/services/substitute-mode-normalize.js +56 -0
- package/dist/services/substitute-mode-normalize.js.map +1 -0
- package/dist/services/substitute-mode-store.d.ts +50 -0
- package/dist/services/substitute-mode-store.d.ts.map +1 -0
- package/dist/services/substitute-mode-store.js +115 -0
- package/dist/services/substitute-mode-store.js.map +1 -0
- package/dist/services/team-board-store.js +1 -1
- package/dist/services/team-board-store.js.map +1 -1
- package/dist/services/trigger-types.d.ts +1 -1
- package/dist/services/trigger-types.d.ts.map +1 -1
- package/dist/services/vc-meeting-runtime-store.d.ts +59 -0
- package/dist/services/vc-meeting-runtime-store.d.ts.map +1 -0
- package/dist/services/vc-meeting-runtime-store.js +339 -0
- package/dist/services/vc-meeting-runtime-store.js.map +1 -0
- package/dist/services/voice/index.d.ts +6 -1
- package/dist/services/voice/index.d.ts.map +1 -1
- package/dist/services/voice/index.js +12 -5
- package/dist/services/voice/index.js.map +1 -1
- package/dist/setup/lark-scopes.json +5 -0
- package/dist/setup/open-platform-automation.d.ts +20 -0
- package/dist/setup/open-platform-automation.d.ts.map +1 -1
- package/dist/setup/open-platform-automation.js +78 -1
- package/dist/setup/open-platform-automation.js.map +1 -1
- package/dist/setup/verify-permissions.d.ts +6 -0
- package/dist/setup/verify-permissions.d.ts.map +1 -1
- package/dist/setup/verify-permissions.js +17 -0
- package/dist/setup/verify-permissions.js.map +1 -1
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/daemon-discovery.d.ts +2 -0
- package/dist/utils/daemon-discovery.d.ts.map +1 -1
- package/dist/utils/daemon-discovery.js +2 -0
- package/dist/utils/daemon-discovery.js.map +1 -1
- package/dist/vc-agent/cards.d.ts +49 -0
- package/dist/vc-agent/cards.d.ts.map +1 -0
- package/dist/vc-agent/cards.js +505 -0
- package/dist/vc-agent/cards.js.map +1 -0
- package/dist/vc-agent/meeting-state.d.ts +39 -0
- package/dist/vc-agent/meeting-state.d.ts.map +1 -0
- package/dist/vc-agent/meeting-state.js +186 -0
- package/dist/vc-agent/meeting-state.js.map +1 -0
- package/dist/vc-agent/normalizer.d.ts +13 -0
- package/dist/vc-agent/normalizer.d.ts.map +1 -0
- package/dist/vc-agent/normalizer.js +470 -0
- package/dist/vc-agent/normalizer.js.map +1 -0
- package/dist/vc-agent/polling-source.d.ts +64 -0
- package/dist/vc-agent/polling-source.d.ts.map +1 -0
- package/dist/vc-agent/polling-source.js +181 -0
- package/dist/vc-agent/polling-source.js.map +1 -0
- package/dist/vc-agent/push-source.d.ts +13 -0
- package/dist/vc-agent/push-source.d.ts.map +1 -0
- package/dist/vc-agent/push-source.js +109 -0
- package/dist/vc-agent/push-source.js.map +1 -0
- package/dist/vc-agent/realtime/audio-source.d.ts +6 -0
- package/dist/vc-agent/realtime/audio-source.d.ts.map +1 -0
- package/dist/vc-agent/realtime/audio-source.js +17 -0
- package/dist/vc-agent/realtime/audio-source.js.map +1 -0
- package/dist/vc-agent/realtime/endpoint.d.ts +6 -0
- package/dist/vc-agent/realtime/endpoint.d.ts.map +1 -0
- package/dist/vc-agent/realtime/endpoint.js +25 -0
- package/dist/vc-agent/realtime/endpoint.js.map +1 -0
- package/dist/vc-agent/realtime/errors.d.ts +9 -0
- package/dist/vc-agent/realtime/errors.d.ts.map +1 -0
- package/dist/vc-agent/realtime/errors.js +17 -0
- package/dist/vc-agent/realtime/errors.js.map +1 -0
- package/dist/vc-agent/realtime/events.d.ts +24 -0
- package/dist/vc-agent/realtime/events.d.ts.map +1 -0
- package/dist/vc-agent/realtime/events.js +190 -0
- package/dist/vc-agent/realtime/events.js.map +1 -0
- package/dist/vc-agent/realtime/frontier.d.ts +34 -0
- package/dist/vc-agent/realtime/frontier.d.ts.map +1 -0
- package/dist/vc-agent/realtime/frontier.js +40 -0
- package/dist/vc-agent/realtime/frontier.js.map +1 -0
- package/dist/vc-agent/realtime/index.d.ts +11 -0
- package/dist/vc-agent/realtime/index.d.ts.map +1 -0
- package/dist/vc-agent/realtime/index.js +11 -0
- package/dist/vc-agent/realtime/index.js.map +1 -0
- package/dist/vc-agent/realtime/pacer.d.ts +21 -0
- package/dist/vc-agent/realtime/pacer.d.ts.map +1 -0
- package/dist/vc-agent/realtime/pacer.js +80 -0
- package/dist/vc-agent/realtime/pacer.js.map +1 -0
- package/dist/vc-agent/realtime/protobuf.d.ts +33 -0
- package/dist/vc-agent/realtime/protobuf.d.ts.map +1 -0
- package/dist/vc-agent/realtime/protobuf.js +159 -0
- package/dist/vc-agent/realtime/protobuf.js.map +1 -0
- package/dist/vc-agent/realtime/protocol.d.ts +4 -0
- package/dist/vc-agent/realtime/protocol.d.ts.map +1 -0
- package/dist/vc-agent/realtime/protocol.js +59 -0
- package/dist/vc-agent/realtime/protocol.js.map +1 -0
- package/dist/vc-agent/realtime/session.d.ts +39 -0
- package/dist/vc-agent/realtime/session.d.ts.map +1 -0
- package/dist/vc-agent/realtime/session.js +221 -0
- package/dist/vc-agent/realtime/session.js.map +1 -0
- package/dist/vc-agent/realtime/transport.d.ts +23 -0
- package/dist/vc-agent/realtime/transport.d.ts.map +1 -0
- package/dist/vc-agent/realtime/transport.js +112 -0
- package/dist/vc-agent/realtime/transport.js.map +1 -0
- package/dist/vc-agent/realtime/types.d.ts +84 -0
- package/dist/vc-agent/realtime/types.d.ts.map +1 -0
- package/dist/vc-agent/realtime/types.js +5 -0
- package/dist/vc-agent/realtime/types.js.map +1 -0
- package/dist/vc-agent/types.d.ts +143 -0
- package/dist/vc-agent/types.d.ts.map +1 -0
- package/dist/vc-agent/types.js +2 -0
- package/dist/vc-agent/types.js.map +1 -0
- package/dist/worker.js +71 -12
- package/dist/worker.js.map +1 -1
- package/dist/workflows/definition.d.ts +14 -14
- package/dist/workflows/events/payloads.d.ts +8 -8
- package/dist/workflows/events/schema.d.ts +452 -452
- package/dist/workflows/v3/contract.d.ts +3 -3
- package/dist/workflows/v3/contract.js +3 -3
- package/dist/workflows/v3/runtime.js +1 -1
- package/dist/workflows/v3/runtime.js.map +1 -1
- package/package.json +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-4IF5NB4O.js +0 -409
- package/dist/dashboard-web/chunks/chunk-2KX53XHS.js +0 -317
- package/dist/dashboard-web/chunks/chunk-NHI3SY2K.js +0 -31
- package/dist/dashboard-web/chunks/overview-page-TADULZBE.js +0 -1
- package/dist/dashboard-web/chunks/sessions-I4EZWL5Q.js +0 -1
- package/dist/dashboard-web/chunks/sessions-page-YTQC2EM6.js +0 -1
- package/dist/dashboard-web/chunks/settings-page-TRYWNJ5Y.js +0 -2
- package/dist/dashboard-web/chunks/skills-page-ZZLGLEEL.js +0 -2
package/README.en.md
CHANGED
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
<a href="#design-philosophy">Design</a> ·
|
|
16
16
|
<a href="#key-advantages">Advantages</a> ·
|
|
17
17
|
<a href="#5-minute-setup">Quick Start</a> ·
|
|
18
|
-
<a href="https://
|
|
18
|
+
<a href="https://github.com/deepcoldy/botmux/tree/master/docs-site/docs/en"><b>📖 Docs</b></a>
|
|
19
19
|
</p>
|
|
20
20
|
|
|
21
21
|
[中文](README.md) | English
|
|
22
22
|
|
|
23
23
|
**Plug any AI coding CLI into Feishu/Lark — every DM, group or topic gets its own CLI session, with live-streaming cards, a web terminal, and zero glue code.**
|
|
24
24
|
|
|
25
|
-
> 📖 **Full docs** (commands / config / best practices / troubleshooting): **<https://
|
|
25
|
+
> 📖 **Full docs** (commands / config / best practices / troubleshooting): **<https://github.com/deepcoldy/botmux/tree/master/docs-site/docs/en>** — this README only covers why and how to get started fast.
|
|
26
26
|
|
|
27
27
|
| Lark Streaming Cards | Web Terminal | tmux Session Management | Multi-Bot Collaboration |
|
|
28
28
|
|:-:|:-:|:-:|:-:|
|
|
@@ -223,7 +223,7 @@ On mobile/tablet, a floating shortcut toolbar provides Esc, Ctrl+C, Tab, arrow k
|
|
|
223
223
|
|
|
224
224
|
### Multi-Bot Collaboration
|
|
225
225
|
|
|
226
|
-
Run multiple Lark bots on a single machine, each mapped to a different CLI. In the same group chat, messages are routed via @mention — each bot gets its own isolated CLI process. With a single bot in the group, it responds automatically without @. In a regular (non-topic) group, `@<bot1> @<bot2> /t xxx` spawns one independent thread per mentioned bot anchored at the same message. Send `@<bot1> @<bot2> /introduce` once so they register each other's open_id; afterwards each bot can explicitly @-mention the others from within its own session (commands: [📖 Docs · Slash Commands](https://
|
|
226
|
+
Run multiple Lark bots on a single machine, each mapped to a different CLI. In the same group chat, messages are routed via @mention — each bot gets its own isolated CLI process. With a single bot in the group, it responds automatically without @. In a regular (non-topic) group, `@<bot1> @<bot2> /t xxx` spawns one independent thread per mentioned bot anchored at the same message. Send `@<bot1> @<bot2> /introduce` once so they register each other's open_id; afterwards each bot can explicitly @-mention the others from within its own session (commands: [📖 Docs · Slash Commands](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/en/slash-commands.md)).
|
|
227
227
|
|
|
228
228
|
### Multi-Topic Collaboration
|
|
229
229
|
|
|
@@ -387,16 +387,16 @@ Notes:
|
|
|
387
387
|
|
|
388
388
|
The full reference — commands, config, best practices, troubleshooting — lives in the docs site; not duplicated here —
|
|
389
389
|
|
|
390
|
-
### 👉 https://
|
|
390
|
+
### 👉 https://github.com/deepcoldy/botmux/tree/master/docs-site/docs/en
|
|
391
391
|
|
|
392
392
|
| Topic | Docs |
|
|
393
393
|
|-------|------|
|
|
394
|
-
| Slash commands / CLI commands / agent-facing subcommands | [Commands](https://
|
|
395
|
-
| `bots.json` fields / env vars / file locations | [Configuration](https://
|
|
396
|
-
| Multi-CLI adapters (incl. wrapper / gateway integration) | [Adapters](https://
|
|
397
|
-
| Scenario-based best practices (Oncall / alerting-ops / solo dev / team) | [Best Practices](https://
|
|
398
|
-
| Common pitfalls / FAQ | [Pitfalls](https://
|
|
399
|
-
| Features: scheduled tasks / Oncall / Dashboard / multi-bot / session relay | [Schedule](https://
|
|
394
|
+
| Slash commands / CLI commands / agent-facing subcommands | [Commands](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/en/slash-commands.md) |
|
|
395
|
+
| `bots.json` fields / env vars / file locations | [Configuration](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/en/bots-json.md) |
|
|
396
|
+
| Multi-CLI adapters (incl. wrapper / gateway integration) | [Adapters](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/en/adapters.md) |
|
|
397
|
+
| Scenario-based best practices (Oncall / alerting-ops / solo dev / team) | [Best Practices](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/en/best-practices.md) |
|
|
398
|
+
| Common pitfalls / FAQ | [Pitfalls](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/en/pitfalls.md) · [FAQ](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/en/faq.md) |
|
|
399
|
+
| Features: scheduled tasks / Oncall / Dashboard / multi-bot / session relay | [Schedule](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/en/schedule.md) · [Oncall](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/en/oncall.md) · [Dashboard](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/en/dashboard.md) · [Multi-bot](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/en/multi-bot.mdx) · [Relay](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/en/relay.md) |
|
|
400
400
|
|
|
401
401
|
## Contributing
|
|
402
402
|
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
14
|
<p align="center">
|
|
15
|
-
<a href="#设计理念">设计理念</a> · <a href="#核心优势">核心优势</a> · <a href="#5-分钟快速接入">快速接入</a> · <a href="https://
|
|
15
|
+
<a href="#设计理念">设计理念</a> · <a href="#核心优势">核心优势</a> · <a href="#5-分钟快速接入">快速接入</a> · <a href="https://github.com/deepcoldy/botmux/tree/master/docs-site/docs/zh"><b>📖 文档</b></a>
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
18
|
<p align="center">
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
**飞书 + AI 编程 CLI——私聊 / 群聊 / 话题,每个会话一个独立 CLI 进程,实时流式回传。** Daemon 监听飞书消息,为每个新会话自动启动独立 CLI 进程(Claude Code / Codex / Cursor / Gemini / OpenCode / Antigravity / GitHub Copilot / Kimi Code),提供实时流式卡片和可交互 Web 终端。
|
|
25
25
|
|
|
26
|
-
> 📖 **完整文档**(命令 / 配置 / 最佳实践 / 排错):**<https://
|
|
26
|
+
> 📖 **完整文档**(命令 / 配置 / 最佳实践 / 排错):**<https://github.com/deepcoldy/botmux/tree/master/docs-site/docs/zh>** ——本 README 只讲为什么用它和怎么快速上手。
|
|
27
27
|
|
|
28
28
|
## 演示
|
|
29
29
|
|
|
@@ -92,7 +92,7 @@ botmux 可以管理 CLI 无关的自定义 Skill Registry,并按 bot 配置在
|
|
|
92
92
|
|
|
93
93
|
### 多机器人协作
|
|
94
94
|
|
|
95
|
-
同一台机器上可运行多个飞书机器人,每个机器人可对应不同的 CLI。同一群聊中通过 @mention 路由消息,仅有一个机器人时无需 @ 自动响应;多机器人时 `@<bot1> @<bot2> /t xxx` 可让每个被 @ 的机器人在同一条消息上各自独立开新话题。先发一次 `@<bot1> @<bot2> /introduce` 让它们互相登记 open_id,之后各 bot 就能在自己的会话里显式 @mention 对方协作(命令详见 [📖 文档 · 斜杠命令](https://
|
|
95
|
+
同一台机器上可运行多个飞书机器人,每个机器人可对应不同的 CLI。同一群聊中通过 @mention 路由消息,仅有一个机器人时无需 @ 自动响应;多机器人时 `@<bot1> @<bot2> /t xxx` 可让每个被 @ 的机器人在同一条消息上各自独立开新话题。先发一次 `@<bot1> @<bot2> /introduce` 让它们互相登记 open_id,之后各 bot 就能在自己的会话里显式 @mention 对方协作(命令详见 [📖 文档 · 斜杠命令](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/zh/slash-commands.md))。
|
|
96
96
|
|
|
97
97
|
### 多话题协作模式
|
|
98
98
|
|
|
@@ -384,16 +384,16 @@ PersonalAgent 默认配好事件订阅 + bot 能力,正常情况下不用动
|
|
|
384
384
|
|
|
385
385
|
命令、配置、最佳实践、排错的完整内容都在文档站,这里不再重复 ——
|
|
386
386
|
|
|
387
|
-
### 👉 https://
|
|
387
|
+
### 👉 https://github.com/deepcoldy/botmux/tree/master/docs-site/docs/zh
|
|
388
388
|
|
|
389
389
|
| 主题 | 文档 |
|
|
390
390
|
|------|------|
|
|
391
|
-
| 斜杠命令 / CLI 命令 / 会话内子命令 | [命令参考](https://
|
|
392
|
-
| `bots.json` 字段 / 环境变量 / 文件位置 | [配置参考](https://
|
|
393
|
-
| 多 CLI 适配器(含 wrapper / 网关接入) | [适配器](https://
|
|
394
|
-
| 按场景的最佳实践(Oncall / 报警运维 / 个人研发 / 多人协作) | [最佳实践](https://
|
|
395
|
-
| 常见踩坑 / FAQ 排错 | [踩坑](https://
|
|
396
|
-
| 功能详解:定时任务 / Oncall / Dashboard / 多机器人协作 / 会话接力 | [定时](https://
|
|
391
|
+
| 斜杠命令 / CLI 命令 / 会话内子命令 | [命令参考](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/zh/slash-commands.md) |
|
|
392
|
+
| `bots.json` 字段 / 环境变量 / 文件位置 | [配置参考](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/zh/bots-json.md) |
|
|
393
|
+
| 多 CLI 适配器(含 wrapper / 网关接入) | [适配器](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/zh/adapters.md) |
|
|
394
|
+
| 按场景的最佳实践(Oncall / 报警运维 / 个人研发 / 多人协作) | [最佳实践](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/zh/best-practices.md) |
|
|
395
|
+
| 常见踩坑 / FAQ 排错 | [踩坑](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/zh/pitfalls.md) · [FAQ](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/zh/faq.md) |
|
|
396
|
+
| 功能详解:定时任务 / Oncall / Dashboard / 多机器人协作 / 会话接力 | [定时](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/zh/schedule.md) · [Oncall](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/zh/oncall.md) · [Dashboard](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/zh/dashboard.md) · [多 bot](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/zh/multi-bot.mdx) · [接力](https://github.com/deepcoldy/botmux/blob/master/docs-site/docs/zh/relay.md) |
|
|
397
397
|
|
|
398
398
|
## 贡献
|
|
399
399
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export declare function sandboxVartmpRoot(): string;
|
|
2
1
|
/**
|
|
3
2
|
* Mount an overlayfs: reads fall through to `lower` (real, zero copy); writes
|
|
4
3
|
* copy-up into `upper` (the landable changeset). `work` is overlayfs scratch on
|
|
@@ -124,7 +123,7 @@ export interface SandboxSpawn {
|
|
|
124
123
|
outbox: string;
|
|
125
124
|
/** Project overlay UPPER dir — THE LANDABLE CHANGESET (used by sandbox-land). */
|
|
126
125
|
workDir: string;
|
|
127
|
-
/** HOME overlay UPPER dir (/var/tmp/botmux-sbx
|
|
126
|
+
/** HOME overlay UPPER dir (/var/tmp/botmux-sbx/<sid>/home-upper). The sandboxed
|
|
128
127
|
* CLI's $HOME writes — INCLUDING its session jsonl under CLAUDE_CONFIG_DIR —
|
|
129
128
|
* land here (invisible at the real path). The worker redirects its bridge/idle
|
|
130
129
|
* watch into this via sandboxedClaudeDataDir() so it sees the CLI's turns. */
|
|
@@ -150,12 +149,10 @@ export declare function sandboxedClaudeDataDir(sessionId: string, realDataDir: s
|
|
|
150
149
|
* is off / unsupported / a required overlay mount fails (fail-safe = the worker
|
|
151
150
|
* treats null as a hard error and does NOT silently run unsandboxed).
|
|
152
151
|
*
|
|
153
|
-
* Layout under <dataDir>/sandboxes/<sessionId>/: shimbin, proj-upper
|
|
154
|
-
* landable changeset), proj-work, proj-merged, home-merged. The HOME
|
|
155
|
-
* upper/work
|
|
156
|
-
*
|
|
157
|
-
* the lower (= the real home), and keeping the outbox outside HOME avoids a
|
|
158
|
-
* nested bind under the HOME overlay on bwrap hosts that hang on that pattern.
|
|
152
|
+
* Layout under <dataDir>/sandboxes/<sessionId>/: outbox, shimbin, proj-upper
|
|
153
|
+
* (the landable changeset), proj-work, proj-merged, home-merged. The HOME
|
|
154
|
+
* overlay's upper/work live under /var/tmp/botmux-sbx/<sessionId>/ because
|
|
155
|
+
* overlayfs forbids upper/work inside the lower (= the real home).
|
|
159
156
|
*/
|
|
160
157
|
export declare function prepareSandbox(opts: {
|
|
161
158
|
/** Whether the sandbox is on for THIS session (per-bot BotConfig.sandbox OR
|
|
@@ -197,10 +194,7 @@ export declare function prepareSandbox(opts: {
|
|
|
197
194
|
* path back so the watcher can keep servicing the live CLI's `botmux send`, plus
|
|
198
195
|
* the workDir (upper changeset for landing) and a cleanup that tears the residue
|
|
199
196
|
* down at close/exit. Returns null if the session has no sandbox tree on disk
|
|
200
|
-
* (never sandboxed). Linux-only, mirrors prepareSandbox's layout.
|
|
201
|
-
* keep outbox under /var/tmp/botmux-sbx-<uid>/<sid>/outbox; fall back to legacy
|
|
202
|
-
* /var/tmp/botmux-sbx/<sid>/outbox or <dataDir>/sandboxes/<sid>/outbox for
|
|
203
|
-
* sessions that were already running before the layout changed.
|
|
197
|
+
* (never sandboxed). Linux-only, mirrors prepareSandbox's layout.
|
|
204
198
|
*/
|
|
205
199
|
export declare function attachSandboxOutbox(opts: {
|
|
206
200
|
sessionId: string;
|
|
@@ -275,14 +269,6 @@ export declare function validateRelayRequest(req: RelayRequest): {
|
|
|
275
269
|
* be swapped under us. Returns false (reject) on symlink / non-regular / any error.
|
|
276
270
|
*/
|
|
277
271
|
export declare function materializeOutboxFile(outbox: string, name: string, dest: string): boolean;
|
|
278
|
-
/**
|
|
279
|
-
* TOCTOU-safe read of the `.req.json` trigger file itself. The request file is
|
|
280
|
-
* also sandbox-controlled input, so it needs the same hardening as content and
|
|
281
|
-
* attachments: no symlinks, no FIFO/device files, no blocking opens, and a small
|
|
282
|
-
* size cap before JSON.parse. Returns null on any unsafe/non-regular/oversized
|
|
283
|
-
* input so the watcher can reject and keep its event loop moving.
|
|
284
|
-
*/
|
|
285
|
-
export declare function readRelayRequestFile(reqPath: string): string | null;
|
|
286
272
|
/**
|
|
287
273
|
* Daemon/worker-side outbox watcher. The sandboxed `botmux send` (relay mode)
|
|
288
274
|
* drops `<id>.req.json`; we validate (validateRelayRequest) and then MATERIALIZE
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/sandbox.ts"],"names":[],"mappings":"AAkCA
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/sandbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,61 +20,14 @@
|
|
|
20
20
|
* sandbox-exec approach and is handled elsewhere.
|
|
21
21
|
*/
|
|
22
22
|
import { homedir } from 'node:os';
|
|
23
|
-
import { mkdirSync, existsSync, writeFileSync, chmodSync, readdirSync, readFileSync, rmSync, statSync,
|
|
23
|
+
import { mkdirSync, existsSync, writeFileSync, chmodSync, readdirSync, readFileSync, rmSync, statSync, realpathSync, openSync, fstatSync, readSync, writeSync, closeSync, constants as fsConstants } from 'node:fs';
|
|
24
24
|
import { atomicWriteFileSync } from '../../utils/atomic-write.js';
|
|
25
25
|
import { join, dirname, relative, resolve } from 'node:path';
|
|
26
26
|
import { fileURLToPath } from 'node:url';
|
|
27
27
|
import { spawn, spawnSync } from 'node:child_process';
|
|
28
28
|
/** Host root for the HOME overlay's upper/work — MUST be OUTSIDE the home lower
|
|
29
|
-
* (overlayfs forbids upper/work inside lower).
|
|
30
|
-
|
|
31
|
-
* that starts sandbox block every other Unix user on the same machine. */
|
|
32
|
-
const LEGACY_VARTMP_ROOT = '/var/tmp/botmux-sbx';
|
|
33
|
-
export function sandboxVartmpRoot() {
|
|
34
|
-
const uid = process.getuid?.() ?? 0;
|
|
35
|
-
return `/var/tmp/botmux-sbx-${uid}`;
|
|
36
|
-
}
|
|
37
|
-
function legacySandboxVartmpDir(sessionId) {
|
|
38
|
-
return join(LEGACY_VARTMP_ROOT, sessionId);
|
|
39
|
-
}
|
|
40
|
-
function sandboxVartmpDir(sessionId) {
|
|
41
|
-
return join(sandboxVartmpRoot(), sessionId);
|
|
42
|
-
}
|
|
43
|
-
function sandboxHomeUpperDir(sessionId) {
|
|
44
|
-
const next = join(sandboxVartmpDir(sessionId), 'home-upper');
|
|
45
|
-
const legacy = join(legacySandboxVartmpDir(sessionId), 'home-upper');
|
|
46
|
-
// Published versions stored HOME upper under the global /var/tmp/botmux-sbx.
|
|
47
|
-
// A daemon upgrade may reattach a still-running tmux sandbox whose bwrap
|
|
48
|
-
// namespace continues writing that old overlay upper. If the new per-uid upper
|
|
49
|
-
// does not exist, keep the bridge pointed at the legacy path.
|
|
50
|
-
if (existsSync(legacy) && !existsSync(next))
|
|
51
|
-
return legacy;
|
|
52
|
-
return next;
|
|
53
|
-
}
|
|
54
|
-
/** Create a daemon-private directory and repair legacy/default mkdir modes.
|
|
55
|
-
* Anything under /var/tmp is on a shared multi-user surface, while the outbox
|
|
56
|
-
* carries in-flight Lark message bodies/attachments. Refuse to proceed unless
|
|
57
|
-
* the path is a real directory owned by this daemon user, and group/other bits
|
|
58
|
-
* are gone after chmod. */
|
|
59
|
-
function ensurePrivateDir(dir) {
|
|
60
|
-
try {
|
|
61
|
-
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
62
|
-
const lst = lstatSync(dir);
|
|
63
|
-
if (lst.isSymbolicLink() || !lst.isDirectory())
|
|
64
|
-
return false;
|
|
65
|
-
const stBefore = statSync(dir);
|
|
66
|
-
const uid = process.getuid?.();
|
|
67
|
-
if (typeof uid === 'number' && stBefore.uid !== uid)
|
|
68
|
-
return false;
|
|
69
|
-
chmodSync(dir, 0o700); // repair dirs created before this hardening or under a loose umask
|
|
70
|
-
const st = statSync(dir);
|
|
71
|
-
return st.isDirectory() && (typeof uid !== 'number' || st.uid === uid) && (st.mode & 0o077) === 0;
|
|
72
|
-
}
|
|
73
|
-
catch (err) {
|
|
74
|
-
console.error(`[sandbox] failed to prepare private dir ${dir}: ${err instanceof Error ? err.message : String(err)}`);
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
29
|
+
* (overlayfs forbids upper/work inside lower). */
|
|
30
|
+
const VARTMP_ROOT = '/var/tmp/botmux-sbx';
|
|
78
31
|
// ───────────────────────────── overlay primitives ────────────────────────────
|
|
79
32
|
/**
|
|
80
33
|
* Mount an overlayfs: reads fall through to `lower` (real, zero copy); writes
|
|
@@ -349,7 +302,7 @@ export function sandboxEnabled() {
|
|
|
349
302
|
export function sandboxedClaudeDataDir(sessionId, realDataDir) {
|
|
350
303
|
const raw = relative(homedir(), realDataDir);
|
|
351
304
|
const rel = raw.startsWith('..') ? relative(resolveSandboxMountPath(homedir()), realDataDir) : raw;
|
|
352
|
-
return join(
|
|
305
|
+
return join(VARTMP_ROOT, sessionId, 'home-upper', rel);
|
|
353
306
|
}
|
|
354
307
|
/** Proxy env vars forwarded into the sandbox so the CLI reaches the API even on
|
|
355
308
|
* the tmux backend (which otherwise only forwards a fixed whitelist). */
|
|
@@ -359,12 +312,10 @@ const PROXY_ENV_KEYS = ['http_proxy', 'https_proxy', 'HTTP_PROXY', 'HTTPS_PROXY'
|
|
|
359
312
|
* is off / unsupported / a required overlay mount fails (fail-safe = the worker
|
|
360
313
|
* treats null as a hard error and does NOT silently run unsandboxed).
|
|
361
314
|
*
|
|
362
|
-
* Layout under <dataDir>/sandboxes/<sessionId>/: shimbin, proj-upper
|
|
363
|
-
* landable changeset), proj-work, proj-merged, home-merged. The HOME
|
|
364
|
-
* upper/work
|
|
365
|
-
*
|
|
366
|
-
* the lower (= the real home), and keeping the outbox outside HOME avoids a
|
|
367
|
-
* nested bind under the HOME overlay on bwrap hosts that hang on that pattern.
|
|
315
|
+
* Layout under <dataDir>/sandboxes/<sessionId>/: outbox, shimbin, proj-upper
|
|
316
|
+
* (the landable changeset), proj-work, proj-merged, home-merged. The HOME
|
|
317
|
+
* overlay's upper/work live under /var/tmp/botmux-sbx/<sessionId>/ because
|
|
318
|
+
* overlayfs forbids upper/work inside the lower (= the real home).
|
|
368
319
|
*/
|
|
369
320
|
export function prepareSandbox(opts) {
|
|
370
321
|
if (!opts.enabled)
|
|
@@ -378,6 +329,7 @@ export function prepareSandbox(opts) {
|
|
|
378
329
|
return null;
|
|
379
330
|
const dataDir = resolveSandboxMountPath(opts.dataDir);
|
|
380
331
|
const sessionRoot = join(dataDir, 'sandboxes', opts.sessionId);
|
|
332
|
+
const outbox = join(sessionRoot, 'outbox');
|
|
381
333
|
const shimBin = join(sessionRoot, 'shimbin');
|
|
382
334
|
const empties = join(sessionRoot, 'empties');
|
|
383
335
|
const projUpper = join(sessionRoot, 'proj-upper'); // THE LANDABLE CHANGESET
|
|
@@ -385,12 +337,9 @@ export function prepareSandbox(opts) {
|
|
|
385
337
|
const projMerged = join(sessionRoot, 'proj-merged');
|
|
386
338
|
const homeMerged = join(sessionRoot, 'home-merged'); // merged may live under sessionRoot
|
|
387
339
|
// HOME overlay upper/work MUST be OUTSIDE the home lower (overlayfs constraint).
|
|
388
|
-
const vartmp =
|
|
389
|
-
const outbox = join(vartmp, 'outbox');
|
|
340
|
+
const vartmp = join(VARTMP_ROOT, opts.sessionId);
|
|
390
341
|
const homeUpper = join(vartmp, 'home-upper');
|
|
391
342
|
const homeWork = join(vartmp, 'home-work');
|
|
392
|
-
if (!ensurePrivateDir(sandboxVartmpRoot()) || !ensurePrivateDir(vartmp) || !ensurePrivateDir(outbox))
|
|
393
|
-
return null;
|
|
394
343
|
for (const d of [outbox, shimBin, empties])
|
|
395
344
|
mkdirSync(d, { recursive: true });
|
|
396
345
|
const home = resolveSandboxMountPath(homedir());
|
|
@@ -526,10 +475,6 @@ export function prepareSandbox(opts) {
|
|
|
526
475
|
rmSync(vartmp, { recursive: true, force: true });
|
|
527
476
|
}
|
|
528
477
|
catch { /* */ }
|
|
529
|
-
try {
|
|
530
|
-
rmSync(legacySandboxVartmpDir(opts.sessionId), { recursive: true, force: true });
|
|
531
|
-
}
|
|
532
|
-
catch { /* */ }
|
|
533
478
|
},
|
|
534
479
|
};
|
|
535
480
|
}
|
|
@@ -542,37 +487,25 @@ export function prepareSandbox(opts) {
|
|
|
542
487
|
* path back so the watcher can keep servicing the live CLI's `botmux send`, plus
|
|
543
488
|
* the workDir (upper changeset for landing) and a cleanup that tears the residue
|
|
544
489
|
* down at close/exit. Returns null if the session has no sandbox tree on disk
|
|
545
|
-
* (never sandboxed). Linux-only, mirrors prepareSandbox's layout.
|
|
546
|
-
* keep outbox under /var/tmp/botmux-sbx-<uid>/<sid>/outbox; fall back to legacy
|
|
547
|
-
* /var/tmp/botmux-sbx/<sid>/outbox or <dataDir>/sandboxes/<sid>/outbox for
|
|
548
|
-
* sessions that were already running before the layout changed.
|
|
490
|
+
* (never sandboxed). Linux-only, mirrors prepareSandbox's layout.
|
|
549
491
|
*/
|
|
550
492
|
export function attachSandboxOutbox(opts) {
|
|
551
493
|
if (process.platform !== 'linux')
|
|
552
494
|
return null;
|
|
553
495
|
const dataDir = resolveSandboxMountPath(opts.dataDir);
|
|
554
496
|
const sessionRoot = join(dataDir, 'sandboxes', opts.sessionId);
|
|
555
|
-
const
|
|
556
|
-
const newOutbox = join(vartmp, 'outbox');
|
|
557
|
-
const legacyVartmpOutbox = join(legacySandboxVartmpDir(opts.sessionId), 'outbox');
|
|
558
|
-
const legacyOutbox = join(sessionRoot, 'outbox');
|
|
497
|
+
const outbox = join(sessionRoot, 'outbox');
|
|
559
498
|
const projUpper = join(sessionRoot, 'proj-upper');
|
|
560
|
-
if (!existsSync(
|
|
499
|
+
if (!existsSync(outbox) && !existsSync(projUpper))
|
|
561
500
|
return null; // never sandboxed
|
|
562
|
-
const outbox = existsSync(newOutbox) ? newOutbox : (existsSync(legacyVartmpOutbox) ? legacyVartmpOutbox : (existsSync(legacyOutbox) ? legacyOutbox : newOutbox));
|
|
563
501
|
// Ensure the outbox exists (the watcher reads it); never (re)mount here.
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
return null;
|
|
567
|
-
}
|
|
568
|
-
else if (outbox === legacyVartmpOutbox) {
|
|
569
|
-
if (!ensurePrivateDir(legacySandboxVartmpDir(opts.sessionId)) || !ensurePrivateDir(outbox))
|
|
570
|
-
return null;
|
|
502
|
+
try {
|
|
503
|
+
mkdirSync(outbox, { recursive: true });
|
|
571
504
|
}
|
|
572
|
-
|
|
573
|
-
return null;
|
|
505
|
+
catch { /* */ }
|
|
574
506
|
const projMerged = join(sessionRoot, 'proj-merged');
|
|
575
507
|
const homeMerged = join(sessionRoot, 'home-merged');
|
|
508
|
+
const vartmp = join(VARTMP_ROOT, opts.sessionId);
|
|
576
509
|
return {
|
|
577
510
|
outbox,
|
|
578
511
|
workDir: projUpper,
|
|
@@ -587,10 +520,6 @@ export function attachSandboxOutbox(opts) {
|
|
|
587
520
|
rmSync(vartmp, { recursive: true, force: true });
|
|
588
521
|
}
|
|
589
522
|
catch { /* */ }
|
|
590
|
-
try {
|
|
591
|
-
rmSync(legacySandboxVartmpDir(opts.sessionId), { recursive: true, force: true });
|
|
592
|
-
}
|
|
593
|
-
catch { /* */ }
|
|
594
523
|
},
|
|
595
524
|
};
|
|
596
525
|
}
|
|
@@ -605,17 +534,13 @@ function reclaimSandbox(dataDir, sid) {
|
|
|
605
534
|
}
|
|
606
535
|
catch { /* */ }
|
|
607
536
|
try {
|
|
608
|
-
rmSync(join(
|
|
609
|
-
}
|
|
610
|
-
catch { /* */ }
|
|
611
|
-
try {
|
|
612
|
-
rmSync(legacySandboxVartmpDir(sid), { recursive: true, force: true });
|
|
537
|
+
rmSync(join(VARTMP_ROOT, sid), { recursive: true, force: true });
|
|
613
538
|
}
|
|
614
539
|
catch { /* */ }
|
|
615
540
|
}
|
|
616
541
|
/** Scan the process table for sandbox session-ids referenced by any running
|
|
617
542
|
* process's argv. A live bwrap's bind/overlay paths contain `sandboxes/<sid>`
|
|
618
|
-
* and `botmux-sbx
|
|
543
|
+
* and `botmux-sbx/<sid>`, so this physically detects which sandbox dirs are
|
|
619
544
|
* still in use — by overlay sessions AND old clone-model sessions alike. Used as
|
|
620
545
|
* a hard guard so the sweep never deletes a dir out from under a live CLI. */
|
|
621
546
|
function liveSandboxSids() {
|
|
@@ -627,7 +552,7 @@ function liveSandboxSids() {
|
|
|
627
552
|
catch {
|
|
628
553
|
return live;
|
|
629
554
|
}
|
|
630
|
-
const re = /(?:sandboxes|botmux-sbx
|
|
555
|
+
const re = /(?:sandboxes|botmux-sbx)\/([^/\0]+)/g;
|
|
631
556
|
for (const pid of pids) {
|
|
632
557
|
if (!/^\d+$/.test(pid))
|
|
633
558
|
continue;
|
|
@@ -677,9 +602,9 @@ export function sweepOrphanSandboxes(dataDir, activeSessionIds) {
|
|
|
677
602
|
return;
|
|
678
603
|
} // no sandboxes dir yet
|
|
679
604
|
// Grace before reclaiming an ACTIVE-but-unmounted sandbox: a worker that just
|
|
680
|
-
// (re)spawned creates the
|
|
681
|
-
// overlay. Without this, a sweep firing in that tiny window would nuke an
|
|
682
|
-
// in-progress session's
|
|
605
|
+
// (re)spawned creates the outbox/shimbin dirs a few syscalls BEFORE it mounts
|
|
606
|
+
// the overlay. Without this, a sweep firing in that tiny window would nuke an
|
|
607
|
+
// in-progress session's outbox. Non-active orphans are reclaimed immediately
|
|
683
608
|
// (no live worker can be mid-spawn for a session that isn't active).
|
|
684
609
|
const ACTIVE_DEAD_GRACE_MS = 60_000;
|
|
685
610
|
const now = Date.now();
|
|
@@ -824,49 +749,6 @@ export function materializeOutboxFile(outbox, name, dest) {
|
|
|
824
749
|
closeSync(outFd);
|
|
825
750
|
}
|
|
826
751
|
}
|
|
827
|
-
const RELAY_REQUEST_MAX_BYTES = 64 * 1024;
|
|
828
|
-
/**
|
|
829
|
-
* TOCTOU-safe read of the `.req.json` trigger file itself. The request file is
|
|
830
|
-
* also sandbox-controlled input, so it needs the same hardening as content and
|
|
831
|
-
* attachments: no symlinks, no FIFO/device files, no blocking opens, and a small
|
|
832
|
-
* size cap before JSON.parse. Returns null on any unsafe/non-regular/oversized
|
|
833
|
-
* input so the watcher can reject and keep its event loop moving.
|
|
834
|
-
*/
|
|
835
|
-
export function readRelayRequestFile(reqPath) {
|
|
836
|
-
let fd;
|
|
837
|
-
try {
|
|
838
|
-
fd = openSync(reqPath, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW | fsConstants.O_NONBLOCK);
|
|
839
|
-
}
|
|
840
|
-
catch {
|
|
841
|
-
return null;
|
|
842
|
-
}
|
|
843
|
-
try {
|
|
844
|
-
const st = fstatSync(fd);
|
|
845
|
-
if (!st.isFile())
|
|
846
|
-
return null;
|
|
847
|
-
if (st.size > RELAY_REQUEST_MAX_BYTES)
|
|
848
|
-
return null;
|
|
849
|
-
const chunks = [];
|
|
850
|
-
let total = 0;
|
|
851
|
-
const buf = Buffer.alloc(Math.min(8192, RELAY_REQUEST_MAX_BYTES));
|
|
852
|
-
for (;;) {
|
|
853
|
-
const n = readSync(fd, buf, 0, buf.length, null);
|
|
854
|
-
if (n <= 0)
|
|
855
|
-
break;
|
|
856
|
-
total += n;
|
|
857
|
-
if (total > RELAY_REQUEST_MAX_BYTES)
|
|
858
|
-
return null;
|
|
859
|
-
chunks.push(Buffer.from(buf.subarray(0, n)));
|
|
860
|
-
}
|
|
861
|
-
return Buffer.concat(chunks, total).toString('utf8');
|
|
862
|
-
}
|
|
863
|
-
catch {
|
|
864
|
-
return null;
|
|
865
|
-
}
|
|
866
|
-
finally {
|
|
867
|
-
closeSync(fd);
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
752
|
/**
|
|
871
753
|
* Daemon/worker-side outbox watcher. The sandboxed `botmux send` (relay mode)
|
|
872
754
|
* drops `<id>.req.json`; we validate (validateRelayRequest) and then MATERIALIZE
|
|
@@ -886,7 +768,7 @@ export function startOutboxWatcher(outbox, baseEnv, sessionId) {
|
|
|
886
768
|
const finish = (id, reqPath, name, staged, code, stdout, stderr) => {
|
|
887
769
|
// 原子写:沙盒侧 CLI 在 existsSync 轮询这个 res.json,rename 保证它读到完整 JSON。
|
|
888
770
|
try {
|
|
889
|
-
atomicWriteFileSync(join(outbox, `${id}.res.json`), JSON.stringify({ code, stdout, stderr })
|
|
771
|
+
atomicWriteFileSync(join(outbox, `${id}.res.json`), JSON.stringify({ code, stdout, stderr }));
|
|
890
772
|
}
|
|
891
773
|
catch { /* */ }
|
|
892
774
|
try {
|
|
@@ -917,13 +799,8 @@ export function startOutboxWatcher(outbox, baseEnv, sessionId) {
|
|
|
917
799
|
const id = name.slice(0, -'.req.json'.length);
|
|
918
800
|
const staged = [];
|
|
919
801
|
let req;
|
|
920
|
-
const reqText = readRelayRequestFile(reqPath);
|
|
921
|
-
if (reqText === null) {
|
|
922
|
-
finish(id, reqPath, name, staged, 1, '', 'relay rejected: request not a regular file or too large');
|
|
923
|
-
continue;
|
|
924
|
-
}
|
|
925
802
|
try {
|
|
926
|
-
req = JSON.parse(
|
|
803
|
+
req = JSON.parse(readFileSync(reqPath, 'utf8'));
|
|
927
804
|
}
|
|
928
805
|
catch {
|
|
929
806
|
finish(id, reqPath, name, staged, 1, '', 'relay: bad json');
|
|
@@ -935,8 +812,7 @@ export function startOutboxWatcher(outbox, baseEnv, sessionId) {
|
|
|
935
812
|
continue;
|
|
936
813
|
}
|
|
937
814
|
try {
|
|
938
|
-
mkdirSync(staging, { recursive: true
|
|
939
|
-
chmodSync(staging, 0o700);
|
|
815
|
+
mkdirSync(staging, { recursive: true });
|
|
940
816
|
}
|
|
941
817
|
catch { /* */ }
|
|
942
818
|
// Materialize content (TOCTOU-safe) into the private staging dir.
|