botmux 2.49.0-canary.1 → 2.50.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 +40 -32
- package/README.md +40 -31
- package/dist/adapters/adopt-route.d.ts +63 -0
- package/dist/adapters/adopt-route.d.ts.map +1 -0
- package/dist/adapters/adopt-route.js +195 -0
- package/dist/adapters/adopt-route.js.map +1 -0
- package/dist/adapters/backend/tmux-backend.d.ts +5 -3
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +48 -12
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.d.ts +11 -0
- package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.js +17 -1
- package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
- package/dist/adapters/cli/aiden.js +2 -3
- package/dist/adapters/cli/aiden.js.map +1 -1
- package/dist/adapters/cli/antigravity.js +2 -2
- package/dist/adapters/cli/antigravity.js.map +1 -1
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +40 -15
- 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 +27 -3
- package/dist/adapters/cli/coco.js.map +1 -1
- package/dist/adapters/cli/codex-app.d.ts +4 -0
- package/dist/adapters/cli/codex-app.d.ts.map +1 -0
- package/dist/adapters/cli/codex-app.js +72 -0
- package/dist/adapters/cli/codex-app.js.map +1 -0
- package/dist/adapters/cli/codex.d.ts.map +1 -1
- package/dist/adapters/cli/codex.js +50 -18
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/cursor.d.ts.map +1 -1
- package/dist/adapters/cli/cursor.js +59 -13
- package/dist/adapters/cli/cursor.js.map +1 -1
- package/dist/adapters/cli/gemini.d.ts.map +1 -1
- package/dist/adapters/cli/gemini.js +6 -2
- package/dist/adapters/cli/gemini.js.map +1 -1
- package/dist/adapters/cli/hermes.d.ts +4 -0
- package/dist/adapters/cli/hermes.d.ts.map +1 -0
- package/dist/adapters/cli/hermes.js +40 -0
- package/dist/adapters/cli/hermes.js.map +1 -0
- package/dist/adapters/cli/mira.d.ts +4 -0
- package/dist/adapters/cli/mira.d.ts.map +1 -0
- package/dist/adapters/cli/mira.js +67 -0
- package/dist/adapters/cli/mira.js.map +1 -0
- package/dist/adapters/cli/mtr.d.ts +5 -0
- package/dist/adapters/cli/mtr.d.ts.map +1 -0
- package/dist/adapters/cli/mtr.js +62 -0
- package/dist/adapters/cli/mtr.js.map +1 -0
- package/dist/adapters/cli/opencode.d.ts.map +1 -1
- package/dist/adapters/cli/opencode.js +19 -1
- package/dist/adapters/cli/opencode.js.map +1 -1
- package/dist/adapters/cli/registry.d.ts +5 -1
- package/dist/adapters/cli/registry.d.ts.map +1 -1
- package/dist/adapters/cli/registry.js +22 -2
- package/dist/adapters/cli/registry.js.map +1 -1
- package/dist/adapters/cli/shared-hints.d.ts +1 -1
- package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
- package/dist/adapters/cli/shared-hints.js +2 -1
- package/dist/adapters/cli/shared-hints.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +36 -7
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/adapters/hook-command.d.ts +18 -0
- package/dist/adapters/hook-command.d.ts.map +1 -0
- package/dist/adapters/hook-command.js +38 -0
- package/dist/adapters/hook-command.js.map +1 -0
- package/dist/adapters/hook-installer.d.ts +14 -0
- package/dist/adapters/hook-installer.d.ts.map +1 -0
- package/dist/adapters/hook-installer.js +192 -0
- package/dist/adapters/hook-installer.js.map +1 -0
- package/dist/bot-registry.d.ts +79 -3
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +74 -1
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/bots-list-output.d.ts +8 -0
- package/dist/cli/bots-list-output.d.ts.map +1 -1
- package/dist/cli/bots-list-output.js +9 -0
- package/dist/cli/bots-list-output.js.map +1 -1
- package/dist/cli.d.ts +15 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +686 -116
- package/dist/cli.js.map +1 -1
- package/dist/codex-app-runner.d.ts +3 -0
- package/dist/codex-app-runner.d.ts.map +1 -0
- package/dist/codex-app-runner.js +512 -0
- package/dist/codex-app-runner.js.map +1 -0
- package/dist/config.d.ts +12 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +21 -4
- package/dist/config.js.map +1 -1
- package/dist/core/ask-api.d.ts +47 -0
- package/dist/core/ask-api.d.ts.map +1 -0
- package/dist/core/ask-api.js +139 -0
- package/dist/core/ask-api.js.map +1 -0
- package/dist/core/ask-args.d.ts +53 -0
- package/dist/core/ask-args.d.ts.map +1 -0
- package/dist/core/ask-args.js +122 -0
- package/dist/core/ask-args.js.map +1 -0
- package/dist/core/ask-broker.d.ts +98 -0
- package/dist/core/ask-broker.d.ts.map +1 -0
- package/dist/core/ask-broker.js +329 -0
- package/dist/core/ask-broker.js.map +1 -0
- package/dist/core/ask-hook/claude-code.d.ts +50 -0
- package/dist/core/ask-hook/claude-code.d.ts.map +1 -0
- package/dist/core/ask-hook/claude-code.js +145 -0
- package/dist/core/ask-hook/claude-code.js.map +1 -0
- package/dist/core/ask-hook/codex.d.ts +43 -0
- package/dist/core/ask-hook/codex.d.ts.map +1 -0
- package/dist/core/ask-hook/codex.js +69 -0
- package/dist/core/ask-hook/codex.js.map +1 -0
- package/dist/core/ask-hook/opencode.d.ts +41 -0
- package/dist/core/ask-hook/opencode.d.ts.map +1 -0
- package/dist/core/ask-hook/opencode.js +108 -0
- package/dist/core/ask-hook/opencode.js.map +1 -0
- package/dist/core/ask-hook/registry.d.ts +3 -0
- package/dist/core/ask-hook/registry.d.ts.map +1 -0
- package/dist/core/ask-hook/registry.js +12 -0
- package/dist/core/ask-hook/registry.js.map +1 -0
- package/dist/core/ask-hook/types.d.ts +26 -0
- package/dist/core/ask-hook/types.d.ts.map +1 -0
- package/dist/core/ask-hook/types.js +2 -0
- package/dist/core/ask-hook/types.js.map +1 -0
- package/dist/core/ask-types.d.ts +146 -0
- package/dist/core/ask-types.d.ts.map +1 -0
- package/dist/core/ask-types.js +18 -0
- package/dist/core/ask-types.js.map +1 -0
- package/dist/core/auto-start.d.ts +61 -0
- package/dist/core/auto-start.d.ts.map +1 -0
- package/dist/core/auto-start.js +62 -0
- package/dist/core/auto-start.js.map +1 -0
- package/dist/core/command-handler.d.ts +29 -0
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +789 -313
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts +2 -0
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +232 -3
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dashboard-rows.d.ts +3 -0
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +2 -0
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/core/role-resolver.d.ts +17 -1
- package/dist/core/role-resolver.d.ts.map +1 -1
- package/dist/core/role-resolver.js +64 -10
- package/dist/core/role-resolver.js.map +1 -1
- package/dist/core/session-discovery.d.ts.map +1 -1
- package/dist/core/session-discovery.js +19 -5
- package/dist/core/session-discovery.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -3
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +84 -28
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/terminal-proxy.d.ts +32 -0
- package/dist/core/terminal-proxy.d.ts.map +1 -0
- package/dist/core/terminal-proxy.js +139 -0
- package/dist/core/terminal-proxy.js.map +1 -0
- package/dist/core/terminal-url.d.ts +27 -0
- package/dist/core/terminal-url.d.ts.map +1 -0
- package/dist/core/terminal-url.js +26 -0
- package/dist/core/terminal-url.js.map +1 -0
- package/dist/core/trigger-session.d.ts +9 -0
- package/dist/core/trigger-session.d.ts.map +1 -0
- package/dist/core/trigger-session.js +158 -0
- package/dist/core/trigger-session.js.map +1 -0
- package/dist/core/types.d.ts +5 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts +141 -0
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +550 -30
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +459 -68
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/auth.d.ts +6 -1
- package/dist/dashboard/auth.d.ts.map +1 -1
- package/dist/dashboard/auth.js +9 -1
- package/dist/dashboard/auth.js.map +1 -1
- package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
- package/dist/dashboard/bot-onboarding.js +24 -2
- package/dist/dashboard/bot-onboarding.js.map +1 -1
- package/dist/dashboard/connector-api.d.ts +3 -0
- package/dist/dashboard/connector-api.d.ts.map +1 -0
- package/dist/dashboard/connector-api.js +351 -0
- package/dist/dashboard/connector-api.js.map +1 -0
- package/dist/dashboard/federated-group-core.d.ts +54 -0
- package/dist/dashboard/federated-group-core.d.ts.map +1 -0
- package/dist/dashboard/federated-group-core.js +165 -0
- package/dist/dashboard/federated-group-core.js.map +1 -0
- package/dist/dashboard/federation-api.d.ts +42 -0
- package/dist/dashboard/federation-api.d.ts.map +1 -0
- package/dist/dashboard/federation-api.js +408 -0
- package/dist/dashboard/federation-api.js.map +1 -0
- package/dist/dashboard/federation-spoke-api.d.ts +82 -0
- package/dist/dashboard/federation-spoke-api.d.ts.map +1 -0
- package/dist/dashboard/federation-spoke-api.js +645 -0
- package/dist/dashboard/federation-spoke-api.js.map +1 -0
- package/dist/dashboard/team-group.d.ts +18 -0
- package/dist/dashboard/team-group.d.ts.map +1 -0
- package/dist/dashboard/team-group.js +7 -0
- package/dist/dashboard/team-group.js.map +1 -0
- package/dist/dashboard/trigger-api.d.ts +13 -0
- package/dist/dashboard/trigger-api.d.ts.map +1 -0
- package/dist/dashboard/trigger-api.js +77 -0
- package/dist/dashboard/trigger-api.js.map +1 -0
- package/dist/dashboard/web/app.d.ts +1 -1
- package/dist/dashboard/web/app.d.ts.map +1 -1
- package/dist/dashboard/web/app.js +44 -0
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js +397 -20
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/connectors.d.ts +2 -0
- package/dist/dashboard/web/connectors.d.ts.map +1 -0
- package/dist/dashboard/web/connectors.js +187 -0
- package/dist/dashboard/web/connectors.js.map +1 -0
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +75 -5
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +5 -1
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/team-federation.d.ts +3 -0
- package/dist/dashboard/web/team-federation.d.ts.map +1 -0
- package/dist/dashboard/web/team-federation.js +485 -0
- package/dist/dashboard/web/team-federation.js.map +1 -0
- package/dist/dashboard/web/workflows.js +3 -3
- package/dist/dashboard/web/workflows.js.map +1 -1
- package/dist/dashboard/webhook-routes.d.ts +19 -0
- package/dist/dashboard/webhook-routes.d.ts.map +1 -0
- package/dist/dashboard/webhook-routes.js +321 -0
- package/dist/dashboard/webhook-routes.js.map +1 -0
- package/dist/dashboard/workflow-api.d.ts +8 -1
- package/dist/dashboard/workflow-api.d.ts.map +1 -1
- package/dist/dashboard/workflow-api.js +19 -4
- package/dist/dashboard/workflow-api.js.map +1 -1
- package/dist/dashboard-web/app.js +579 -377
- package/dist/dashboard-web/index.html +3 -1
- package/dist/dashboard-web/style.css +63 -1
- package/dist/dashboard.js +202 -2
- package/dist/dashboard.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +120 -15
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +120 -15
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/ask-card.d.ts +55 -0
- package/dist/im/lark/ask-card.d.ts.map +1 -0
- package/dist/im/lark/ask-card.js +328 -0
- package/dist/im/lark/ask-card.js.map +1 -0
- package/dist/im/lark/card-builder.d.ts +122 -8
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +528 -56
- 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 +337 -36
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +112 -0
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +385 -70
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +9 -2
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +90 -19
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/grant-command.d.ts +8 -1
- package/dist/im/lark/grant-command.d.ts.map +1 -1
- package/dist/im/lark/grant-command.js +53 -24
- package/dist/im/lark/grant-command.js.map +1 -1
- package/dist/im/lark/grant-pending.d.ts +3 -0
- package/dist/im/lark/grant-pending.d.ts.map +1 -1
- package/dist/im/lark/grant-pending.js +8 -1
- package/dist/im/lark/grant-pending.js.map +1 -1
- package/dist/im/lark/identity-cache.d.ts.map +1 -1
- package/dist/im/lark/identity-cache.js +3 -3
- package/dist/im/lark/identity-cache.js.map +1 -1
- package/dist/im/lark/md-card.d.ts +20 -2
- package/dist/im/lark/md-card.d.ts.map +1 -1
- package/dist/im/lark/md-card.js +49 -17
- package/dist/im/lark/md-card.js.map +1 -1
- package/dist/im/lark/message-parser.d.ts.map +1 -1
- package/dist/im/lark/message-parser.js +87 -31
- package/dist/im/lark/message-parser.js.map +1 -1
- package/dist/im/lark/workflow-card-handler.d.ts +2 -2
- package/dist/im/lark/workflow-card-handler.d.ts.map +1 -1
- package/dist/im/lark/workflow-card-handler.js +12 -1
- package/dist/im/lark/workflow-card-handler.js.map +1 -1
- package/dist/im/lark/workflow-progress-card.d.ts.map +1 -1
- package/dist/im/lark/workflow-progress-card.js +53 -0
- package/dist/im/lark/workflow-progress-card.js.map +1 -1
- package/dist/mira-output.d.ts +3 -0
- package/dist/mira-output.d.ts.map +1 -0
- package/dist/mira-output.js +136 -0
- package/dist/mira-output.js.map +1 -0
- package/dist/mira-runner.d.ts +3 -0
- package/dist/mira-runner.d.ts.map +1 -0
- package/dist/mira-runner.js +534 -0
- package/dist/mira-runner.js.map +1 -0
- package/dist/services/bot-owner-store.d.ts +28 -0
- package/dist/services/bot-owner-store.d.ts.map +1 -0
- package/dist/services/bot-owner-store.js +82 -0
- package/dist/services/bot-owner-store.js.map +1 -0
- package/dist/services/bot-profile-store.d.ts +16 -0
- package/dist/services/bot-profile-store.d.ts.map +1 -0
- package/dist/services/bot-profile-store.js +98 -0
- package/dist/services/bot-profile-store.js.map +1 -0
- package/dist/services/brand-store.d.ts +15 -0
- package/dist/services/brand-store.d.ts.map +1 -0
- package/dist/services/brand-store.js +47 -0
- package/dist/services/brand-store.js.map +1 -0
- package/dist/services/card-prefs-store.d.ts +26 -0
- package/dist/services/card-prefs-store.d.ts.map +1 -0
- package/dist/services/card-prefs-store.js +119 -0
- package/dist/services/card-prefs-store.js.map +1 -0
- package/dist/services/codex-bridge-queue.d.ts +1 -0
- package/dist/services/codex-bridge-queue.d.ts.map +1 -1
- package/dist/services/codex-bridge-queue.js +72 -19
- package/dist/services/codex-bridge-queue.js.map +1 -1
- package/dist/services/codex-transcript.d.ts +1 -0
- package/dist/services/codex-transcript.d.ts.map +1 -1
- package/dist/services/codex-transcript.js.map +1 -1
- package/dist/services/connector-store.d.ts +58 -0
- package/dist/services/connector-store.d.ts.map +1 -0
- package/dist/services/connector-store.js +79 -0
- package/dist/services/connector-store.js.map +1 -0
- package/dist/services/deployment-identity.d.ts +22 -0
- package/dist/services/deployment-identity.d.ts.map +1 -0
- package/dist/services/deployment-identity.js +67 -0
- package/dist/services/deployment-identity.js.map +1 -0
- package/dist/services/federation-membership-store.d.ts +23 -0
- package/dist/services/federation-membership-store.d.ts.map +1 -0
- package/dist/services/federation-membership-store.js +66 -0
- package/dist/services/federation-membership-store.js.map +1 -0
- package/dist/services/federation-roster.d.ts +54 -0
- package/dist/services/federation-roster.d.ts.map +1 -0
- package/dist/services/federation-roster.js +51 -0
- package/dist/services/federation-roster.js.map +1 -0
- package/dist/services/federation-store.d.ts +76 -0
- package/dist/services/federation-store.d.ts.map +1 -0
- package/dist/services/federation-store.js +133 -0
- package/dist/services/federation-store.js.map +1 -0
- package/dist/services/grant-store.d.ts +12 -2
- package/dist/services/grant-store.d.ts.map +1 -1
- package/dist/services/grant-store.js +51 -4
- package/dist/services/grant-store.js.map +1 -1
- package/dist/services/group-creator.d.ts +10 -0
- package/dist/services/group-creator.d.ts.map +1 -1
- package/dist/services/group-creator.js +26 -1
- package/dist/services/group-creator.js.map +1 -1
- package/dist/services/groups-store.d.ts +30 -0
- package/dist/services/groups-store.d.ts.map +1 -1
- package/dist/services/groups-store.js +85 -12
- package/dist/services/groups-store.js.map +1 -1
- package/dist/services/hermes-transcript.d.ts +7 -0
- package/dist/services/hermes-transcript.d.ts.map +1 -0
- package/dist/services/hermes-transcript.js +117 -0
- package/dist/services/hermes-transcript.js.map +1 -0
- package/dist/services/invite-store.d.ts +28 -0
- package/dist/services/invite-store.d.ts.map +1 -0
- package/dist/services/invite-store.js +85 -0
- package/dist/services/invite-store.js.map +1 -0
- package/dist/services/mtr-transcript.d.ts +14 -0
- package/dist/services/mtr-transcript.d.ts.map +1 -0
- package/dist/services/mtr-transcript.js +291 -0
- package/dist/services/mtr-transcript.js.map +1 -0
- package/dist/services/pairing-store.d.ts +47 -0
- package/dist/services/pairing-store.d.ts.map +1 -0
- package/dist/services/pairing-store.js +132 -0
- package/dist/services/pairing-store.js.map +1 -0
- package/dist/services/project-scanner.d.ts +10 -0
- package/dist/services/project-scanner.d.ts.map +1 -1
- package/dist/services/project-scanner.js +11 -0
- package/dist/services/project-scanner.js.map +1 -1
- package/dist/services/relay-picker.d.ts +22 -0
- package/dist/services/relay-picker.d.ts.map +1 -0
- package/dist/services/relay-picker.js +82 -0
- package/dist/services/relay-picker.js.map +1 -0
- package/dist/services/send-policy.d.ts +55 -0
- package/dist/services/send-policy.d.ts.map +1 -0
- package/dist/services/send-policy.js +47 -0
- package/dist/services/send-policy.js.map +1 -0
- package/dist/services/session-store.js +1 -1
- package/dist/services/session-store.js.map +1 -1
- package/dist/services/team-roster.d.ts +38 -0
- package/dist/services/team-roster.d.ts.map +1 -0
- package/dist/services/team-roster.js +82 -0
- package/dist/services/team-roster.js.map +1 -0
- package/dist/services/team-store.d.ts +54 -0
- package/dist/services/team-store.d.ts.map +1 -0
- package/dist/services/team-store.js +156 -0
- package/dist/services/team-store.js.map +1 -0
- package/dist/services/trigger-log-store.d.ts +46 -0
- package/dist/services/trigger-log-store.d.ts.map +1 -0
- package/dist/services/trigger-log-store.js +132 -0
- package/dist/services/trigger-log-store.js.map +1 -0
- package/dist/services/trigger-types.d.ts +57 -0
- package/dist/services/trigger-types.d.ts.map +1 -0
- package/dist/services/trigger-types.js +28 -0
- package/dist/services/trigger-types.js.map +1 -0
- package/dist/services/webhook-key.d.ts +16 -0
- package/dist/services/webhook-key.d.ts.map +1 -0
- package/dist/services/webhook-key.js +123 -0
- package/dist/services/webhook-key.js.map +1 -0
- package/dist/services/webhook-lifecycle-extractors.d.ts +15 -0
- package/dist/services/webhook-lifecycle-extractors.d.ts.map +1 -0
- package/dist/services/webhook-lifecycle-extractors.js +59 -0
- package/dist/services/webhook-lifecycle-extractors.js.map +1 -0
- package/dist/services/webhook-lifecycle-store.d.ts +45 -0
- package/dist/services/webhook-lifecycle-store.d.ts.map +1 -0
- package/dist/services/webhook-lifecycle-store.js +159 -0
- package/dist/services/webhook-lifecycle-store.js.map +1 -0
- package/dist/setup/bot-config-editor.d.ts +13 -3
- package/dist/setup/bot-config-editor.d.ts.map +1 -1
- package/dist/setup/bot-config-editor.js +27 -6
- package/dist/setup/bot-config-editor.js.map +1 -1
- package/dist/setup/ensure-tmux.d.ts +0 -22
- package/dist/setup/ensure-tmux.d.ts.map +1 -1
- package/dist/setup/ensure-tmux.js +25 -1
- package/dist/setup/ensure-tmux.js.map +1 -1
- package/dist/setup/open-platform-automation.d.ts +149 -0
- package/dist/setup/open-platform-automation.d.ts.map +1 -0
- package/dist/setup/open-platform-automation.js +845 -0
- package/dist/setup/open-platform-automation.js.map +1 -0
- package/dist/setup/verify-permissions.d.ts.map +1 -1
- package/dist/setup/verify-permissions.js +19 -2
- package/dist/setup/verify-permissions.js.map +1 -1
- package/dist/skills/definitions.d.ts +2 -0
- package/dist/skills/definitions.d.ts.map +1 -1
- package/dist/skills/definitions.js +178 -12
- package/dist/skills/definitions.js.map +1 -1
- package/dist/skills/installer.d.ts +34 -0
- package/dist/skills/installer.d.ts.map +1 -1
- package/dist/skills/installer.js +119 -2
- package/dist/skills/installer.js.map +1 -1
- package/dist/types.d.ts +29 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/bot-routing.d.ts +50 -0
- package/dist/utils/bot-routing.d.ts.map +1 -1
- package/dist/utils/bot-routing.js +83 -0
- package/dist/utils/bot-routing.js.map +1 -1
- package/dist/utils/child-env.d.ts +35 -0
- package/dist/utils/child-env.d.ts.map +1 -0
- package/dist/utils/child-env.js +40 -0
- package/dist/utils/child-env.js.map +1 -0
- package/dist/utils/daemon-discovery.d.ts +11 -0
- package/dist/utils/daemon-discovery.d.ts.map +1 -0
- package/dist/utils/daemon-discovery.js +59 -0
- package/dist/utils/daemon-discovery.js.map +1 -0
- package/dist/utils/user-token.d.ts.map +1 -1
- package/dist/utils/user-token.js +0 -2
- package/dist/utils/user-token.js.map +1 -1
- package/dist/worker.js +365 -77
- package/dist/worker.js.map +1 -1
- package/dist/workflows/attempt-resume.d.ts.map +1 -1
- package/dist/workflows/attempt-resume.js +2 -2
- package/dist/workflows/attempt-resume.js.map +1 -1
- package/dist/workflows/definition.d.ts +420 -17
- package/dist/workflows/definition.d.ts.map +1 -1
- package/dist/workflows/definition.js +238 -3
- package/dist/workflows/definition.js.map +1 -1
- package/dist/workflows/events/payloads.d.ts +122 -19
- package/dist/workflows/events/payloads.d.ts.map +1 -1
- package/dist/workflows/events/payloads.js +46 -0
- package/dist/workflows/events/payloads.js.map +1 -1
- package/dist/workflows/events/replay.d.ts +21 -0
- package/dist/workflows/events/replay.d.ts.map +1 -1
- package/dist/workflows/events/replay.js +103 -0
- package/dist/workflows/events/replay.js.map +1 -1
- package/dist/workflows/events/schema.d.ts +1752 -1057
- package/dist/workflows/events/schema.d.ts.map +1 -1
- package/dist/workflows/events/schema.js +37 -1
- package/dist/workflows/events/schema.js.map +1 -1
- package/dist/workflows/events/types.d.ts +5 -1
- package/dist/workflows/events/types.d.ts.map +1 -1
- package/dist/workflows/loader.d.ts +14 -0
- package/dist/workflows/loader.d.ts.map +1 -1
- package/dist/workflows/loader.js +27 -0
- package/dist/workflows/loader.js.map +1 -1
- package/dist/workflows/loop.js +58 -0
- package/dist/workflows/loop.js.map +1 -1
- package/dist/workflows/ops-projection.d.ts +58 -0
- package/dist/workflows/ops-projection.d.ts.map +1 -1
- package/dist/workflows/ops-projection.js +74 -0
- package/dist/workflows/ops-projection.js.map +1 -1
- package/dist/workflows/orchestrator.d.ts +65 -1
- package/dist/workflows/orchestrator.d.ts.map +1 -1
- package/dist/workflows/orchestrator.js +486 -74
- package/dist/workflows/orchestrator.js.map +1 -1
- package/dist/workflows/output-binding.d.ts +8 -1
- package/dist/workflows/output-binding.d.ts.map +1 -1
- package/dist/workflows/output-binding.js +75 -11
- package/dist/workflows/output-binding.js.map +1 -1
- package/dist/workflows/runtime.d.ts +1 -1
- package/dist/workflows/runtime.d.ts.map +1 -1
- package/dist/workflows/runtime.js +39 -4
- package/dist/workflows/runtime.js.map +1 -1
- package/dist/workflows/trigger-from-envelope.d.ts +13 -0
- package/dist/workflows/trigger-from-envelope.d.ts.map +1 -0
- package/dist/workflows/trigger-from-envelope.js +67 -0
- package/dist/workflows/trigger-from-envelope.js.map +1 -0
- package/dist/workflows/wait.d.ts +23 -2
- package/dist/workflows/wait.d.ts.map +1 -1
- package/dist/workflows/wait.js +39 -17
- package/dist/workflows/wait.js.map +1 -1
- package/package.json +1 -1
- package/dist/services/feishu-task-client.d.ts +0 -28
- package/dist/services/feishu-task-client.d.ts.map +0 -1
- package/dist/services/feishu-task-client.js +0 -123
- package/dist/services/feishu-task-client.js.map +0 -1
- package/dist/services/task-store.d.ts +0 -37
- package/dist/services/task-store.d.ts.map +0 -1
- package/dist/services/task-store.js +0 -115
- package/dist/services/task-store.js.map +0 -1
package/README.en.md
CHANGED
|
@@ -62,7 +62,8 @@ Compared to OpenClaw-style approaches built on Agent SDKs:
|
|
|
62
62
|
## Prerequisites
|
|
63
63
|
|
|
64
64
|
- **Node.js** >= 20
|
|
65
|
-
- **AI coding CLI** installed and authenticated (`claude`, `codex`, `cursor-agent`, `gemini`, `opencode`, or `agy` (Antigravity) in PATH)
|
|
65
|
+
- **AI coding CLI / local agent app** installed and authenticated (`claude`, `codex`, `coco`, `cursor-agent`, `gemini`, `opencode`, `hermes`, or `agy` (Antigravity) in PATH)
|
|
66
|
+
- **CoCo requires `0.120.32+`**: type-ahead (sending a new message while a turn is still running, parked in CoCo's own message queue) relies on 0.120.32+ behavior; earlier versions may drop or serialize input while busy — upgrade before use
|
|
66
67
|
- **tmux** >= 3.x (optional — auto-enabled when installed for persistent CLI sessions)
|
|
67
68
|
- **CJK fonts** (only needed for screenshot rendering of Chinese text / emoji):
|
|
68
69
|
- macOS: ships with PingFang / Hiragino, no action needed
|
|
@@ -71,43 +72,46 @@ Compared to OpenClaw-style approaches built on Agent SDKs:
|
|
|
71
72
|
|
|
72
73
|
## 5-Minute Setup
|
|
73
74
|
|
|
74
|
-
> 💡 **TL;DR**:
|
|
75
|
+
> 💡 **TL;DR**: `npm i -g botmux` → `botmux setup` and **scan two QR codes** to get a working bot → `botmux start`. The 1st scan creates the app and saves the AppID/AppSecret (event subscriptions + bot capability pre-configured); the 2nd scan lets botmux's built-in Feishu Web login **import permissions, configure the redirect URL, and create + submit a publish version automatically**. Steps 4 (permissions) / 5 (redirect) / 6 (publish) below are all done automatically by setup and folded as a manual fallback; pass `--no-open-platform-auto` to skip the second auto-config step.
|
|
75
76
|
|
|
76
|
-
### Step 1:
|
|
77
|
+
### Step 1: Install botmux
|
|
77
78
|
|
|
78
|
-
|
|
79
|
+
```bash
|
|
80
|
+
npm install -g botmux
|
|
81
|
+
```
|
|
79
82
|
|
|
80
|
-
>
|
|
83
|
+
> Requires **Node.js ≥ 20**, with at least one AI coding CLI installed and authenticated (`claude` / `codex` / `cursor-agent` / `gemini` / `opencode` / `coco` / `agy` on your PATH). Installing **tmux** too is recommended (enables session persistence automatically).
|
|
81
84
|
|
|
82
|
-
|
|
85
|
+
### Step 2: Create the App & Configure (`botmux setup`)
|
|
83
86
|
|
|
84
|
-
|
|
87
|
+
Run `botmux setup` and follow the interactive menu:
|
|
85
88
|
|
|
86
|
-
|
|
89
|
+
1. **New config**: type `1` and press Enter (with an existing config, type `2` to add a bot).
|
|
90
|
+
2. **Create the bot**:
|
|
91
|
+
- Type `1` → **Scan-to-create (recommended)**: scan with the Lark mobile app and a PersonalAgent app is created with AppID/AppSecret persisted automatically, **with event subscriptions + bot capability pre-configured** — no manual browser navigation. Uses the official `@larksuiteoapi/node-sdk` device flow.
|
|
92
|
+
- Type `2` → **Manual**: go to the [Lark Open Platform](https://open.larkoffice.com/app), create a "Custom App", copy **App ID / App Secret** from "Credentials & Basic Info", and paste them back.
|
|
93
|
+
3. **Pick the CLI**: choose the CLI to bridge (e.g. type `1` for Claude Code).
|
|
94
|
+
4. **Default working dir**: usually the **parent directory** of your git projects (e.g. `~/projects`); new topics scan **downward** for git repos (up to 3 levels). Avoid `~` (too many folders to traverse).
|
|
87
95
|
|
|
88
|
-
>
|
|
96
|
+
> ⚠️ **Currently only Feishu (feishu.cn) tenants are supported.** If scan detects a Lark international (larksuite.com) tenant, setup aborts — the daemon runtime (Lark Client/WSClient/event-dispatcher) hasn't been wired up for the `larksuite.com` domain yet. A follow-up PR will add full Lark support.
|
|
89
97
|
|
|
90
|
-
|
|
98
|
+
At the end, setup validates credentials with a `tenant_access_token` call (only writing `bots.json` on success), writes the full scope JSON to `~/.botmux/lark-scopes.json`, and prints a one-line clipboard copy command plus deep-links to each remaining step.
|
|
91
99
|
|
|
92
|
-

|
|
93
101
|
|
|
94
|
-
### Step 3:
|
|
102
|
+
### Step 3: Start
|
|
95
103
|
|
|
96
104
|
```bash
|
|
97
|
-
# Install
|
|
98
|
-
npm install -g botmux
|
|
99
|
-
|
|
100
|
-
# Interactive setup — pick "1) Scan-to-create app" or "2) Paste AppID/Secret manually".
|
|
101
|
-
# Credentials are validated with a tenant_access_token call before bots.json is written.
|
|
102
|
-
# At the end of setup the wizard writes the full scope JSON to ~/.botmux/lark-scopes.json
|
|
103
|
-
# and prints a one-line clipboard copy command for your platform.
|
|
104
|
-
botmux setup
|
|
105
|
-
|
|
106
|
-
# Start (if you ever need to verify the event subscription, Lark requires the daemon to be running so it can detect the WebSocket connection)
|
|
107
|
-
# Re-validates credentials before forking workers; missing scopes only WARN, do not block the daemon.
|
|
108
105
|
botmux start
|
|
109
106
|
```
|
|
110
107
|
|
|
108
|
+
> `start` re-validates credentials before forking workers; missing scopes only WARN, they don't block the daemon. If you later need to verify the event subscription, Lark requires the daemon to be running so it can detect the WebSocket connection.
|
|
109
|
+
|
|
110
|
+
<details>
|
|
111
|
+
<summary><b>Manual Open Platform config: permissions / redirect / publish (fallback)</b> —— botmux setup does these automatically (during the 2nd scan); expand only if auto-config failed or you want to verify manually</summary>
|
|
112
|
+
|
|
113
|
+
<br>
|
|
114
|
+
|
|
111
115
|
### Step 4: Add Permissions
|
|
112
116
|
|
|
113
117
|
Run the copy-to-clipboard command setup printed, then go to "Permissions & Scopes" → "Batch Import/Export" and paste. Submit for review — visibility "only me" auto-approves.
|
|
@@ -145,6 +149,8 @@ Go to "Version Management & Release", click "Create Version" and publish. Set av
|
|
|
145
149
|
|
|
146
150
|

|
|
147
151
|
|
|
152
|
+
</details>
|
|
153
|
+
|
|
148
154
|
### Step 7: Create a Group and Start Chatting
|
|
149
155
|
|
|
150
156
|
1. Create a **topic-enabled group** in Lark
|
|
@@ -306,9 +312,9 @@ Send these straight into a topic — the daemon intercepts them (no clash with t
|
|
|
306
312
|
|
|
307
313
|
| Command | Description |
|
|
308
314
|
|---------|-------------|
|
|
309
|
-
| `/repo` |
|
|
315
|
+
| `/repo` | While a repo is pending selection, launch in the default workingDir; mid-session, show the project selector card (interactive dropdown + text list) |
|
|
310
316
|
| `/repo <N>` | Switch to Nth project from last scan |
|
|
311
|
-
| `/
|
|
317
|
+
| `/repo <path\|name>` | Skip the selector card; pass a path (relative/absolute) or a first-level project name under workingDir |
|
|
312
318
|
| `/cd <path>` | Change working directory and restart the CLI process |
|
|
313
319
|
| `/status` | Show session info (uptime, terminal URL, etc.) |
|
|
314
320
|
| `/restart` | Restart CLI process (keeps the session context) |
|
|
@@ -355,8 +361,8 @@ Send these straight into a topic — the daemon intercepts them (no clash with t
|
|
|
355
361
|
|
|
356
362
|
| Command | Description |
|
|
357
363
|
|---------|-------------|
|
|
358
|
-
| `@bot /grant @someone` | Pop an authorization card to add the user to the "this chat" or "global" allowlist; also auto-pops (and @s the owner) when an unauthorized user @-mentions the bot |
|
|
359
|
-
| `@bot /revoke @someone` | Revoke the user's this-chat + global access |
|
|
364
|
+
| `@bot /grant @someone` | Pop an authorization card to add the user to the "this chat" or "global" allowlist; you can @ several people/bots at once (one card lists every target, one scope click applies to all); if a granted target is a bot, it's auto-registered into the roster on success (an implicit `/introduce`) for cross-bot collaboration; also auto-pops (and @s the owner) when an unauthorized user @-mentions the bot |
|
|
365
|
+
| `@bot /revoke @someone` | Revoke the user's this-chat + global access; you can @ several people/bots at once |
|
|
360
366
|
|
|
361
367
|
**🆕 One-shot session group**
|
|
362
368
|
|
|
@@ -369,7 +375,7 @@ Send these straight into a topic — the daemon intercepts them (no clash with t
|
|
|
369
375
|
| Command | Description |
|
|
370
376
|
|---------|-------------|
|
|
371
377
|
| `@botA @botB /t <prompt>` | With multiple bots, each @-mentioned bot opens its own independent topic from the same message |
|
|
372
|
-
| `@botA @botB /introduce` | Bots register each other's open_id so they can later explicitly @-mention one another across sessions (any @ order, extra text allowed) |
|
|
378
|
+
| `@botA @botB /introduce` | Bots register each other's open_id so they can later explicitly @-mention one another across sessions (any @ order, extra text allowed; roster-only, grants no permission — **anyone in the chat can run it, no authorization needed**) |
|
|
373
379
|
|
|
374
380
|
**❓ Help**
|
|
375
381
|
|
|
@@ -414,7 +420,7 @@ Configure bots via `~/.botmux/bots.json`. Run `botmux setup` to create it intera
|
|
|
414
420
|
botmux setup
|
|
415
421
|
```
|
|
416
422
|
|
|
417
|
-
When `~/.botmux/bots.json` already exists, `botmux setup` can add a bot, reconfigure from scratch, edit an existing bot, or delete a bot config. The edit/delete flow accepts the process name shown by `botmux status` (e.g. `botmux-1` or a custom `botmux-claude-main`) or the `larkAppId`; empty input keeps the current value, and `-` clears optional fields such as `name`, `backendType`, `workingDir`, and `allowedUsers`. Changing `larkAppId` asks for confirmation because historical session/chat state under the old app ID is not migrated automatically. Deleting a bot only removes one local `bots.json` entry; it does not delete the Lark app, historical messages, or local session data. Run `botmux restart` for changes to take effect.
|
|
423
|
+
When `~/.botmux/bots.json` already exists, `botmux setup` can add a bot, reconfigure from scratch, edit an existing bot, or delete a bot config. The edit/delete flow accepts the process name shown by `botmux status` (e.g. `botmux-1` or a custom `botmux-claude-main`) or the `larkAppId`; empty input keeps the current value, and `-` clears optional fields such as `name`, `model`, `backendType`, `workingDir`, and `allowedUsers`. Changing `larkAppId` asks for confirmation because historical session/chat state under the old app ID is not migrated automatically. Deleting a bot only removes one local `bots.json` entry; it does not delete the Lark app, historical messages, or local session data. Run `botmux restart` for changes to take effect.
|
|
418
424
|
|
|
419
425
|
**bots.json format:**
|
|
420
426
|
|
|
@@ -425,7 +431,7 @@ When `~/.botmux/bots.json` already exists, `botmux setup` can add a bot, reconfi
|
|
|
425
431
|
"larkAppSecret": "secret_1",
|
|
426
432
|
"name": "claude-main",
|
|
427
433
|
"cliId": "claude-code",
|
|
428
|
-
"
|
|
434
|
+
"model": "sonnet",
|
|
429
435
|
"workingDir": "~/projects",
|
|
430
436
|
"allowedUsers": ["alice@company.com"],
|
|
431
437
|
"allowedChatGroups": ["oc_xxx_team"]
|
|
@@ -434,6 +440,7 @@ When `~/.botmux/bots.json` already exists, `botmux setup` can add a bot, reconfi
|
|
|
434
440
|
"larkAppId": "cli_xxx_bot2",
|
|
435
441
|
"larkAppSecret": "secret_2",
|
|
436
442
|
"cliId": "codex",
|
|
443
|
+
"model": "gpt-5-codex",
|
|
437
444
|
"workingDir": "~/work"
|
|
438
445
|
}
|
|
439
446
|
]
|
|
@@ -444,14 +451,15 @@ When `~/.botmux/bots.json` already exists, `botmux setup` can add a bot, reconfi
|
|
|
444
451
|
| `larkAppId` | Yes | Lark app ID |
|
|
445
452
|
| `larkAppSecret` | Yes | Lark app secret |
|
|
446
453
|
| `name` | No | Process name suffix shown by `botmux status`; e.g. `claude-main` appears as `botmux-claude-main`, defaults to `botmux-<index>` |
|
|
447
|
-
| `cliId` | No | CLI adapter, defaults to `claude-code` (options: `aiden`, `coco`, `codex`, `cursor`, `gemini`, `opencode`, `antigravity`) |
|
|
454
|
+
| `cliId` | No | CLI adapter, defaults to `claude-code` (options: `aiden`, `coco`, `codex`, `codex-app`, `cursor`, `gemini`, `opencode`, `antigravity`, `hermes`) |
|
|
455
|
+
| `model` | No | Model name used when spawning the CLI. Currently honored by: `claude-code`, `codex`, `coco`, `cursor`, `gemini`, `opencode`; other adapters ignore the field. Leave empty to use the CLI default. `botmux setup` proposes per-CLI candidates plus a free-form Other option. |
|
|
448
456
|
| `cliPathOverride` | No | Absolute path to the CLI entry, for wrappers / routers; typical use: `ccr`, `claude-w`, `aiden-x-claude`, etc. |
|
|
449
|
-
| `disableCliBypass` | No | Whether to disable botmux's default CLI bypass / weak-sandbox flag injection. Missing or `false` keeps the legacy behavior: botmux still adds flags such as `--yolo`, `--dangerously-*`, `--force`, or `--permission-mode agentFull`. When `true`, botmux stops adding those flags |
|
|
450
457
|
| `backendType` | No | Session backend: `pty` or `tmux` (auto-detected by default) |
|
|
451
458
|
| `workingDir` | No | Default working directory, supports comma-separated. The new-topic repo-select card scans for git repos **from this directory downward** (recursive, up to 3 levels), no longer climbing to the parent: point it at a repos root (e.g. `~/projects`) to list every repo beneath it, or at a single repo to list just that repo (and its linked worktrees) |
|
|
452
459
|
| `defaultWorkingDir` | No | Single-repo default: new topics with no oncall binding and no peer-session inheritance spawn directly here, skipping the repo-select card. `/cd <path>` still switches mid-session; the next new topic falls back to this default. **Difference from `defaultOncall`:** does NOT write `oncallChats` and does NOT change the `canTalk` / `canOperate` permission model |
|
|
453
460
|
| `allowedUsers` | No | Allowed users (**full emails** like `alice@example.com`, or open_ids `ou_xxx`). Email prefixes can't be resolved and are dropped. Required (at least one entry, as owner) when `allowedChatGroups` is set |
|
|
454
461
|
| `allowedChatGroups` | No | Talk-open chats (`chat_id`, for example `oc_xxx`). Any member talking **inside these chats** can use the bot (decided by the message's chat — new members work immediately, removed members lose access, no restart needed); grants `canTalk` only, sensitive ops still require `allowedUsers`. Equivalent to the owner running `/grant` (no target) in that chat. |
|
|
462
|
+
| `globalGrants` | No | Global talk allowlist (`open_id` list, e.g. `ou_xxx`; humans or bots). Listed entries can talk to the bot in **any** chat; grants `canTalk` only, sensitive ops still require `allowedUsers`. Usually written via the owner's `/grant` card (the "grant talk globally" button); can also be set manually here. |
|
|
455
463
|
| `oncallChats` | No | Oncall bindings (written by `/oncall bind`), e.g. `[{ "chatId": "oc_xxx", "workingDir": "~/projects/foo" }]`; any group member can @ the bot |
|
|
456
464
|
|
|
457
465
|
**Config priority:** `BOTS_CONFIG` env var > `~/.botmux/bots.json`
|
package/README.md
CHANGED
|
@@ -169,7 +169,8 @@ CLI 进入 botmux 会话时自动获得 `~/.botmux/bin` 在 PATH 中,以及一
|
|
|
169
169
|
## 前置要求
|
|
170
170
|
|
|
171
171
|
- **Node.js** >= 20
|
|
172
|
-
- **AI 编程 CLI
|
|
172
|
+
- **AI 编程 CLI / 本地 Agent 应用** 已安装并完成认证(`claude`、`codex`、`coco`、`cursor-agent`、`gemini`、`opencode`、`hermes` 或 `agy`(Antigravity)在 PATH 中)
|
|
173
|
+
- **CoCo 最低版本 `0.120.32`**:type-ahead(会话忙时即可发新消息,由 CoCo 自己的消息队列接住)依赖 0.120.32+ 的行为;更早版本忙时输入可能丢失或串行,请升级后再用
|
|
173
174
|
- **tmux** >= 3.x(可选,安装后自动启用会话常驻)
|
|
174
175
|
- **CJK 字体**(用于截图渲染中文/emoji):
|
|
175
176
|
- macOS 自带 PingFang/Hiragino,无需配置
|
|
@@ -178,42 +179,46 @@ CLI 进入 botmux 会话时自动获得 `~/.botmux/bin` 在 PATH 中,以及一
|
|
|
178
179
|
|
|
179
180
|
## 5 分钟快速接入
|
|
180
181
|
|
|
181
|
-
> 💡 **TL;DR
|
|
182
|
+
> 💡 **TL;DR**:`npm i -g botmux` → `botmux setup`,**扫两次码**就能建好一个可用机器人 → `botmux start`。第 1 次扫码建应用、拿到 AppID/AppSecret(事件订阅 + bot 能力默认已配好);第 2 次扫码让 botmux 内置的飞书 Web 登录**自动导入权限、配置重定向 URL、创建并提交发布版本**。下面的 Step 4 权限 / Step 5 重定向 / Step 6 发版都已由 setup 默认自动完成、折叠为手动备用;加 `--no-open-platform-auto` 可跳过第二次自动配置、改走手动。
|
|
182
183
|
|
|
183
|
-
### Step 1:
|
|
184
|
+
### Step 1: 安装 botmux
|
|
184
185
|
|
|
185
|
-
|
|
186
|
+
```bash
|
|
187
|
+
npm install -g botmux
|
|
188
|
+
```
|
|
186
189
|
|
|
187
|
-
>
|
|
190
|
+
> 要求 **Node.js ≥ 20**,且本地已装好并登录至少一种 AI 编程 CLI(`claude` / `codex` / `cursor-agent` / `gemini` / `opencode` / `coco` / `agy` 等在 PATH 中)。推荐顺手装 **tmux**(装了自动启用会话常驻)。
|
|
188
191
|
|
|
189
|
-
|
|
192
|
+
### Step 2: 创建应用并配置(`botmux setup`)
|
|
190
193
|
|
|
191
|
-
|
|
194
|
+
跑 `botmux setup`,按交互菜单一步步选:
|
|
192
195
|
|
|
193
|
-
|
|
196
|
+
1. **新建配置**:输入 `1` 回车(已有配置时输入 `2` 添加机器人)。
|
|
197
|
+
2. **创建机器人**:
|
|
198
|
+
- 输入 `1` → **扫码创建(推荐)**:飞书扫码完成后自动建出 PersonalAgent 应用并落盘 AppID/AppSecret,**事件订阅 + bot 能力默认已配好**,无需手动浏览器创建。底层走 `@larksuiteoapi/node-sdk` 官方 device flow。
|
|
199
|
+
- 输入 `2` → **手动创建**:去 [飞书开放平台](https://open.larkoffice.com/app) 建「企业自建应用」,在「凭证与基础信息」复制 **App ID / App Secret** 回来粘贴。
|
|
200
|
+
3. **选择 CLI**:选本次要接入的 CLI(如接 Claude Code 就选 `1`)。
|
|
201
|
+
4. **默认工作目录**:通常填 git 项目的**父级目录**(如 `~/projects`),新话题会从该目录**向下**查找 git 仓库(最多 3 层);尽量别填 `~`(要遍历太多文件夹)。
|
|
194
202
|
|
|
195
|
-
>
|
|
203
|
+
> ⚠️ **目前仅支持飞书 (feishu.cn) 租户**。扫码检测到 Lark 国际版 (larksuite.com) 会中止 setup —— daemon runtime (Lark Client/WSClient/event-dispatcher 等) 需要一并接入 lark 域,会在单独 PR 跟进。
|
|
196
204
|
|
|
197
|
-
|
|
205
|
+
setup 末尾会用 `tenant_access_token` 校验凭证(通过才落盘 `bots.json`),并把完整权限 JSON 写到 `~/.botmux/lark-scopes.json` + 打印一键复制命令 + 各步骤深链。
|
|
198
206
|
|
|
199
|
-

|
|
200
208
|
|
|
201
|
-
### Step 3:
|
|
209
|
+
### Step 3: 启动
|
|
202
210
|
|
|
203
211
|
```bash
|
|
204
|
-
# 安装
|
|
205
|
-
npm install -g botmux
|
|
206
|
-
|
|
207
|
-
# 交互式配置 — 选「1) 扫码建应用」或「2) 手动粘 AppID/Secret」
|
|
208
|
-
# 凭证拿到后自动取一次 tenant_access_token 校验,通过才落盘 bots.json
|
|
209
|
-
# setup 末尾会把完整权限 JSON 写到 ~/.botmux/lark-scopes.json 并打印一键复制命令
|
|
210
|
-
botmux setup
|
|
211
|
-
|
|
212
|
-
# 启动(如果之后需要确认事件订阅,飞书后台会要求 daemon 已在跑才能识别长连接)
|
|
213
|
-
# start 前再校验一次凭证;权限未配齐不会阻塞 daemon,只 WARN
|
|
214
212
|
botmux start
|
|
215
213
|
```
|
|
216
214
|
|
|
215
|
+
> start 前再校验一次凭证;权限未配齐不会阻塞 daemon,只 WARN。如果之后需要确认事件订阅,飞书后台会要求 daemon 已在跑才能识别长连接。
|
|
216
|
+
|
|
217
|
+
<details>
|
|
218
|
+
<summary><b>手动配置开放平台:权限 / 重定向 / 发版(备用)</b> —— 这三步 botmux setup 默认已自动完成(扫第二次码时),仅在自动配置失败、或想手动核对时展开</summary>
|
|
219
|
+
|
|
220
|
+
<br>
|
|
221
|
+
|
|
217
222
|
### Step 4: 添加权限
|
|
218
223
|
|
|
219
224
|
setup 完成后,按 terminal 提示的一键复制命令把权限 JSON 复制到剪贴板,进入「权限管理」→「批量导入/导出权限」粘贴 → 提交审批。可用性范围选「仅自己可见」会自动通过:
|
|
@@ -251,6 +256,8 @@ http://127.0.0.1:9768/callback
|
|
|
251
256
|
|
|
252
257
|

|
|
253
258
|
|
|
259
|
+
</details>
|
|
260
|
+
|
|
254
261
|
### Step 7: 建群开聊
|
|
255
262
|
|
|
256
263
|
1. 飞书中创建一个**话题群**
|
|
@@ -300,9 +307,9 @@ botmux autostart enable
|
|
|
300
307
|
|
|
301
308
|
| 命令 | 说明 |
|
|
302
309
|
|------|------|
|
|
303
|
-
| `/repo` |
|
|
310
|
+
| `/repo` | 仓库待选时直接用默认 workingDir 启动会话;会话进行中则弹出项目选择卡片(交互式下拉 + 文本列表) |
|
|
304
311
|
| `/repo <N>` | 切换到上次扫描的第 N 个项目 |
|
|
305
|
-
| `/
|
|
312
|
+
| `/repo <路径\|项目名>` | 跳过选择卡片,直接指定路径(相对/绝对)或 workingDir 下的一级项目名 |
|
|
306
313
|
| `/cd <路径>` | 切换工作目录并重启 CLI 进程 |
|
|
307
314
|
| `/status` | 查看会话信息(运行时间、终端地址等) |
|
|
308
315
|
| `/restart` | 重启 CLI 进程(保留 session 上下文) |
|
|
@@ -349,8 +356,8 @@ botmux autostart enable
|
|
|
349
356
|
|
|
350
357
|
| 命令 | 说明 |
|
|
351
358
|
|------|------|
|
|
352
|
-
| `@机器人 /grant @某人` |
|
|
353
|
-
| `@机器人 /revoke @某人` | 撤销对方的本群 +
|
|
359
|
+
| `@机器人 /grant @某人` | 弹授权卡片,把对方加进「本群使用」或「全局」白名单;可一次 @ 多人/多 bot(一张卡列出全部目标、点一次范围对全部生效);被授权的若是 bot,授权成功后会自动登记进花名册(等于顺带 `/introduce` 一次)便于跨 bot 协作;无权限者 @ 机器人时也会自动弹这张卡并 @owner |
|
|
360
|
+
| `@机器人 /revoke @某人` | 撤销对方的本群 + 全局授权;可一次 @ 多人/多 bot |
|
|
354
361
|
|
|
355
362
|
**🆕 一键新建会话群**
|
|
356
363
|
|
|
@@ -363,7 +370,7 @@ botmux autostart enable
|
|
|
363
370
|
| 命令 | 说明 |
|
|
364
371
|
|------|------|
|
|
365
372
|
| `@botA @botB /t <prompt>` | 多机器人时,让每个被 @ 的机器人在同一条消息上各自独立开新话题 |
|
|
366
|
-
| `@botA @botB /introduce` | 互相登记彼此的 open_id,便于后续跨 bot 显式 @mention 协作(@
|
|
373
|
+
| `@botA @botB /introduce` | 互相登记彼此的 open_id,便于后续跨 bot 显式 @mention 协作(@ 顺序任意,可带额外文本;只记花名册、不授予任何权限,**群内任何人都可用、无需授权**) |
|
|
367
374
|
|
|
368
375
|
**❓ 帮助**
|
|
369
376
|
|
|
@@ -518,7 +525,7 @@ dashboard 走单独 pm2 进程 `botmux-dashboard`,跟着 `pnpm daemon:restart`
|
|
|
518
525
|
botmux setup
|
|
519
526
|
```
|
|
520
527
|
|
|
521
|
-
已有 `~/.botmux/bots.json` 时,`botmux setup` 支持添加新机器人、重新配置、编辑现有机器人,以及删除机器人配置。编辑或删除时用 `botmux status` 里的进程名(如 `botmux-1` 或自定义的 `botmux-claude-main`)或 `larkAppId` 选择目标;字段留空表示保留当前值,`name`、`cliPathOverride`、`backendType`、`workingDir`、`allowedUsers` 等可选字段输入 `-` 表示清空。修改 `larkAppId` 会提示确认,因为旧 appId 下的历史会话和群聊状态数据不会自动迁移。删除机器人只移除本机 `bots.json` 中的一项,不删除飞书开放平台应用、历史消息或本地会话数据;修改完成后运行 `botmux restart` 生效。
|
|
528
|
+
已有 `~/.botmux/bots.json` 时,`botmux setup` 支持添加新机器人、重新配置、编辑现有机器人,以及删除机器人配置。编辑或删除时用 `botmux status` 里的进程名(如 `botmux-1` 或自定义的 `botmux-claude-main`)或 `larkAppId` 选择目标;字段留空表示保留当前值,`name`、`model`、`cliPathOverride`、`backendType`、`workingDir`、`allowedUsers` 等可选字段输入 `-` 表示清空。修改 `larkAppId` 会提示确认,因为旧 appId 下的历史会话和群聊状态数据不会自动迁移。删除机器人只移除本机 `bots.json` 中的一项,不删除飞书开放平台应用、历史消息或本地会话数据;修改完成后运行 `botmux restart` 生效。
|
|
522
529
|
|
|
523
530
|
**bots.json 格式:**
|
|
524
531
|
|
|
@@ -529,7 +536,7 @@ botmux setup
|
|
|
529
536
|
"larkAppSecret": "secret_1",
|
|
530
537
|
"name": "claude-main",
|
|
531
538
|
"cliId": "claude-code",
|
|
532
|
-
"
|
|
539
|
+
"model": "sonnet",
|
|
533
540
|
"workingDir": "~/projects",
|
|
534
541
|
"allowedUsers": ["alice@company.com"],
|
|
535
542
|
"allowedChatGroups": ["oc_xxx_team"]
|
|
@@ -538,6 +545,7 @@ botmux setup
|
|
|
538
545
|
"larkAppId": "cli_xxx_bot2",
|
|
539
546
|
"larkAppSecret": "secret_2",
|
|
540
547
|
"cliId": "codex",
|
|
548
|
+
"model": "gpt-5-codex",
|
|
541
549
|
"workingDir": "~/work"
|
|
542
550
|
}
|
|
543
551
|
]
|
|
@@ -548,14 +556,15 @@ botmux setup
|
|
|
548
556
|
| `larkAppId` | 是 | 飞书应用 App ID |
|
|
549
557
|
| `larkAppSecret` | 是 | 飞书应用 App Secret |
|
|
550
558
|
| `name` | 否 | `botmux status` 中的进程名后缀;例如 `claude-main` 会显示为 `botmux-claude-main`,留空默认 `botmux-<序号>` |
|
|
551
|
-
| `cliId` | 否 | CLI 适配器,默认 `claude-code`(可选:`aiden`、`coco`、`codex`、`cursor`、`gemini`、`opencode`、`antigravity`) |
|
|
559
|
+
| `cliId` | 否 | CLI 适配器,默认 `claude-code`(可选:`aiden`、`coco`、`codex`、`codex-app`、`cursor`、`gemini`、`opencode`、`antigravity`、`hermes`) |
|
|
560
|
+
| `model` | 否 | 启动 CLI 时使用的模型名;留空走 CLI 默认。当前会注入到支持模型参数的适配器:`claude-code` / `codex` / `coco` / `cursor` / `gemini` / `opencode`;其它适配器会忽略该字段 |
|
|
552
561
|
| `cliPathOverride` | 否 | CLI 入口的绝对路径,用于套 wrapper / router;典型场景:ccr、claude-w、aiden-x-claude 等自定义入口 |
|
|
553
|
-
| `disableCliBypass` | 否 | 是否禁用 botmux 默认注入的 CLI bypass / 弱沙箱参数。未配置或 `false` 时保持兼容旧逻辑,botmux 会继续添加 `--yolo`、`--dangerously-*`、`--force`、`--permission-mode agentFull` 等参数;设为 `true` 时不再自动添加这些参数 |
|
|
554
562
|
| `backendType` | 否 | 会话后端:`pty` 或 `tmux`(默认自动检测) |
|
|
555
563
|
| `workingDir` | 否 | 默认工作目录,支持逗号分隔多个目录。新话题的 repo 选择卡片会**从该目录自身向下**递归查找 git 仓库(最多 3 层),不再向上扫父目录:指向仓库集合根目录(如 `~/projects`)即列出其下所有仓库,指向单个仓库则只列该仓库(及其 linked worktrees) |
|
|
556
564
|
| `defaultWorkingDir` | 否 | 单仓库默认目录:新话题在无 oncall 绑定 / 无同群兄弟 session 时直接进入该目录,跳过 repo 选择卡片。`/cd <path>` 仍可临时切换;下一个新话题回到该默认值。**与 `defaultOncall` 的区别**:不写 `oncallChats`、不修改 `canTalk`/`canOperate` 权限模型 |
|
|
557
565
|
| `allowedUsers` | 否 | 允许的用户列表(**完整邮箱**如 `alice@example.com`,或 open_id `ou_xxx`)。邮箱前缀无法解析、会被丢弃。配置了 `allowedChatGroups` 时此项必须至少有一个条目作为 owner |
|
|
558
566
|
| `allowedChatGroups` | 否 | 可对话群列表(飞书 `chat_id`,如 `oc_xxx`)。**在这些群里**任何成员都能与机器人对话(按消息所在群判断,新人进群即生效、退群即失权,无需重启);仅授对话权(`canTalk`),敏感操作仍由 `allowedUsers` 控制。等价于 owner 在该群发 `/grant`(不带 @)。 |
|
|
567
|
+
| `globalGrants` | 否 | 全局可对话名单(`open_id` 列表,如 `ou_xxx`;人或 bot 均可)。名单内的对象可在**任意群**与机器人对话;仅授对话权(`canTalk`),敏感操作仍由 `allowedUsers` 控制。通常由 owner 在授权卡上点「全局授权对话」写入,也可在此手动配置。 |
|
|
559
568
|
| `oncallChats` | 否 | oncall 绑定(`/oncall bind` 写入),形如 `[{ "chatId": "oc_xxx", "workingDir": "~/projects/foo" }]`,群内任何成员可 @ 提问 |
|
|
560
569
|
|
|
561
570
|
**配置优先级:** `BOTS_CONFIG` 环境变量 → `~/.botmux/bots.json`
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adopt-route.ts
|
|
3
|
+
*
|
|
4
|
+
* 为没有 BOTMUX_* 环境变量的"孤立" Claude 进程(即通过 /adopt 接管的外部 CLI)
|
|
5
|
+
* 提供 askUserQuestion hook 的路由解析逻辑。
|
|
6
|
+
*
|
|
7
|
+
* 通过以下步骤确定目标 Lark 会话:
|
|
8
|
+
* 1. 收集 hook 进程的祖先 PID 链
|
|
9
|
+
* 2. 遍历在线 daemon,查询每个 daemon 是否有以某祖先 PID 启动的 adopt 会话
|
|
10
|
+
* 3. 首个命中即返回路由信息
|
|
11
|
+
*/
|
|
12
|
+
/** 从 daemon 取回的 adopt 会话路由信息 */
|
|
13
|
+
export interface AdoptRoute {
|
|
14
|
+
sessionId: string;
|
|
15
|
+
chatId: string;
|
|
16
|
+
larkAppId: string;
|
|
17
|
+
rootMessageId: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 沿进程祖先链向上收集 PID(不含 startPid 自己)。
|
|
21
|
+
*
|
|
22
|
+
* @param startPid 起始进程 PID(自身不包含在结果中)
|
|
23
|
+
* @param readParent 注入式父 PID 读取函数(默认使用 /proc 或 ps)
|
|
24
|
+
* @param maxDepth 最大深度,防止意外无限循环(默认 40)
|
|
25
|
+
* @returns 祖先 PID 数组,从最近父进程到最远祖先
|
|
26
|
+
*/
|
|
27
|
+
export declare function getAncestorPids(startPid: number, readParent?: (pid: number) => number | null, maxDepth?: number): number[];
|
|
28
|
+
/**
|
|
29
|
+
* 查询某个 daemon 是否有以指定 PID 启动的活跃 adopt 会话。
|
|
30
|
+
*
|
|
31
|
+
* GET http://127.0.0.1:<ipcPort>/api/adopt-session/<pid>
|
|
32
|
+
* 200 → 解析 AdoptRoute;其它状态码或异常 → null(不抛)。
|
|
33
|
+
* 超时:2 秒(AbortController)。
|
|
34
|
+
*/
|
|
35
|
+
export declare function queryAdoptSession(ipcPort: number, pid: number): Promise<AdoptRoute | null>;
|
|
36
|
+
/**
|
|
37
|
+
* 通过祖先 PID 匹配在线 adopt 会话。
|
|
38
|
+
*
|
|
39
|
+
* **并发 + 全局 budget 封顶**:候选 = daemon 列表序 × 祖先链序(由近及远)逐个编号;
|
|
40
|
+
* 全部并发查询(每请求各自带 2s 超时),整体不超过 `budgetMs`。命中按候选 index 取
|
|
41
|
+
* 最小,保持确定性。
|
|
42
|
+
*
|
|
43
|
+
* 为何要全局 budget:runHook 在缺 BOTMUX_* 时同步 await 本函数,而全局 hook 会覆盖
|
|
44
|
+
* 非 botmux 的 Claude 会话;若某 daemon still-online 但 IPC 不响应,顺序 await 会
|
|
45
|
+
* `祖先数 × 2s × daemon 数` 线性叠加(可达几十秒),把真·非 botmux 的 ask 卡死。
|
|
46
|
+
* 并发让总耗时收敛到单请求量级,budget 再封顶,保证快速 passthrough。
|
|
47
|
+
*
|
|
48
|
+
* @param deps.startPid hook 进程自身的 PID
|
|
49
|
+
* @param deps.listDaemons 列出在线 daemon(ipcPort)
|
|
50
|
+
* @param deps.queryDaemon 查询某 daemon 是否有该 pid 的活跃 adopt 会话
|
|
51
|
+
* @param deps.getAncestors 取祖先 PID(默认使用 getAncestorPids)
|
|
52
|
+
* @param deps.budgetMs 整体耗时上限(默认 1500ms;可注入便于测试)
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveAdoptRoute(deps: {
|
|
55
|
+
startPid: number;
|
|
56
|
+
listDaemons: () => Array<{
|
|
57
|
+
ipcPort: number;
|
|
58
|
+
}>;
|
|
59
|
+
queryDaemon: (ipcPort: number, pid: number) => Promise<AdoptRoute | null>;
|
|
60
|
+
getAncestors?: (startPid: number) => number[];
|
|
61
|
+
budgetMs?: number;
|
|
62
|
+
}): Promise<AdoptRoute | null>;
|
|
63
|
+
//# sourceMappingURL=adopt-route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopt-route.d.ts","sourceRoot":"","sources":["../../src/adapters/adopt-route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,gCAAgC;AAChC,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AA8CD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,EAC3C,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,EAAE,CAiBV;AAID;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAgC5B;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAC1E,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA+C7B"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adopt-route.ts
|
|
3
|
+
*
|
|
4
|
+
* 为没有 BOTMUX_* 环境变量的"孤立" Claude 进程(即通过 /adopt 接管的外部 CLI)
|
|
5
|
+
* 提供 askUserQuestion hook 的路由解析逻辑。
|
|
6
|
+
*
|
|
7
|
+
* 通过以下步骤确定目标 Lark 会话:
|
|
8
|
+
* 1. 收集 hook 进程的祖先 PID 链
|
|
9
|
+
* 2. 遍历在线 daemon,查询每个 daemon 是否有以某祖先 PID 启动的 adopt 会话
|
|
10
|
+
* 3. 首个命中即返回路由信息
|
|
11
|
+
*/
|
|
12
|
+
import { execFileSync } from 'node:child_process';
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
// ── 祖先 PID 收集 ──────────────────────────────────────────────────────────────
|
|
15
|
+
/**
|
|
16
|
+
* 读取某进程的父 PID。
|
|
17
|
+
*
|
|
18
|
+
* 默认实现:
|
|
19
|
+
* 1. 优先从 /proc/<pid>/stat 读取(Linux),第 4 字段(0-based)是 ppid。
|
|
20
|
+
* 注意 stat 第 2 字段 comm 可以含括号和空格,所以从最后一个 `)` 之后的子串解析。
|
|
21
|
+
* 2. 失败时回退到 `ps -o ppid= -p <pid>`(macOS/Linux 通用)。
|
|
22
|
+
*
|
|
23
|
+
* 失败/进程不存在 → 返回 null。
|
|
24
|
+
*/
|
|
25
|
+
function defaultReadParent(pid) {
|
|
26
|
+
// 先尝试 /proc(Linux 最快)
|
|
27
|
+
try {
|
|
28
|
+
const stat = readFileSync(`/proc/${pid}/stat`, 'utf-8');
|
|
29
|
+
// stat 格式: "<pid> (<comm>) <state> <ppid> ..."
|
|
30
|
+
// comm 字段可能含空格和括号,取最后一个 ')' 之后的部分
|
|
31
|
+
const lastParen = stat.lastIndexOf(')');
|
|
32
|
+
if (lastParen === -1)
|
|
33
|
+
throw new Error('unexpected /proc stat format');
|
|
34
|
+
const tail = stat.slice(lastParen + 1).trim();
|
|
35
|
+
// tail: "<state> <ppid> ..."
|
|
36
|
+
const parts = tail.split(' ');
|
|
37
|
+
// parts[0] = state, parts[1] = ppid
|
|
38
|
+
const ppid = parseInt(parts[1], 10);
|
|
39
|
+
if (Number.isInteger(ppid) && ppid > 0)
|
|
40
|
+
return ppid;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// /proc 不可用或解析失败,回退到 ps
|
|
44
|
+
}
|
|
45
|
+
// 回退到 ps(macOS / 无 /proc 的 Linux)
|
|
46
|
+
try {
|
|
47
|
+
const out = execFileSync('ps', ['-o', 'ppid=', '-p', String(pid)], {
|
|
48
|
+
encoding: 'utf-8',
|
|
49
|
+
});
|
|
50
|
+
const ppid = parseInt(out.trim(), 10);
|
|
51
|
+
if (Number.isInteger(ppid) && ppid > 0)
|
|
52
|
+
return ppid;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// 进程不存在或 ps 调用失败
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 沿进程祖先链向上收集 PID(不含 startPid 自己)。
|
|
61
|
+
*
|
|
62
|
+
* @param startPid 起始进程 PID(自身不包含在结果中)
|
|
63
|
+
* @param readParent 注入式父 PID 读取函数(默认使用 /proc 或 ps)
|
|
64
|
+
* @param maxDepth 最大深度,防止意外无限循环(默认 40)
|
|
65
|
+
* @returns 祖先 PID 数组,从最近父进程到最远祖先
|
|
66
|
+
*/
|
|
67
|
+
export function getAncestorPids(startPid, readParent, maxDepth) {
|
|
68
|
+
const reader = readParent ?? defaultReadParent;
|
|
69
|
+
const depth = maxDepth ?? 40;
|
|
70
|
+
const ancestors = [];
|
|
71
|
+
const visited = new Set([startPid]);
|
|
72
|
+
let current = startPid;
|
|
73
|
+
for (let i = 0; i < depth; i++) {
|
|
74
|
+
const parent = reader(current);
|
|
75
|
+
if (parent === null || parent <= 1)
|
|
76
|
+
break; // 到 init 或读不到,停止
|
|
77
|
+
if (visited.has(parent))
|
|
78
|
+
break; // 防环
|
|
79
|
+
visited.add(parent);
|
|
80
|
+
ancestors.push(parent);
|
|
81
|
+
current = parent;
|
|
82
|
+
}
|
|
83
|
+
return ancestors;
|
|
84
|
+
}
|
|
85
|
+
// ── Daemon 查询辅助 ─────────────────────────────────────────────────────────────
|
|
86
|
+
/**
|
|
87
|
+
* 查询某个 daemon 是否有以指定 PID 启动的活跃 adopt 会话。
|
|
88
|
+
*
|
|
89
|
+
* GET http://127.0.0.1:<ipcPort>/api/adopt-session/<pid>
|
|
90
|
+
* 200 → 解析 AdoptRoute;其它状态码或异常 → null(不抛)。
|
|
91
|
+
* 超时:2 秒(AbortController)。
|
|
92
|
+
*/
|
|
93
|
+
export async function queryAdoptSession(ipcPort, pid) {
|
|
94
|
+
const controller = new AbortController();
|
|
95
|
+
const timer = setTimeout(() => controller.abort(), 2000);
|
|
96
|
+
try {
|
|
97
|
+
const res = await fetch(`http://127.0.0.1:${ipcPort}/api/adopt-session/${pid}`, { signal: controller.signal });
|
|
98
|
+
if (!res.ok)
|
|
99
|
+
return null;
|
|
100
|
+
const body = (await res.json());
|
|
101
|
+
if (!body || typeof body !== 'object')
|
|
102
|
+
return null;
|
|
103
|
+
const b = body;
|
|
104
|
+
if (typeof b.sessionId !== 'string' ||
|
|
105
|
+
typeof b.chatId !== 'string' ||
|
|
106
|
+
typeof b.larkAppId !== 'string' ||
|
|
107
|
+
typeof b.rootMessageId !== 'string') {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
sessionId: b.sessionId,
|
|
112
|
+
chatId: b.chatId,
|
|
113
|
+
larkAppId: b.larkAppId,
|
|
114
|
+
rootMessageId: b.rootMessageId,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// 超时、网络错误、JSON 解析失败等 → null
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
clearTimeout(timer);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// ── 主逻辑 ─────────────────────────────────────────────────────────────────────
|
|
126
|
+
/**
|
|
127
|
+
* 通过祖先 PID 匹配在线 adopt 会话。
|
|
128
|
+
*
|
|
129
|
+
* **并发 + 全局 budget 封顶**:候选 = daemon 列表序 × 祖先链序(由近及远)逐个编号;
|
|
130
|
+
* 全部并发查询(每请求各自带 2s 超时),整体不超过 `budgetMs`。命中按候选 index 取
|
|
131
|
+
* 最小,保持确定性。
|
|
132
|
+
*
|
|
133
|
+
* 为何要全局 budget:runHook 在缺 BOTMUX_* 时同步 await 本函数,而全局 hook 会覆盖
|
|
134
|
+
* 非 botmux 的 Claude 会话;若某 daemon still-online 但 IPC 不响应,顺序 await 会
|
|
135
|
+
* `祖先数 × 2s × daemon 数` 线性叠加(可达几十秒),把真·非 botmux 的 ask 卡死。
|
|
136
|
+
* 并发让总耗时收敛到单请求量级,budget 再封顶,保证快速 passthrough。
|
|
137
|
+
*
|
|
138
|
+
* @param deps.startPid hook 进程自身的 PID
|
|
139
|
+
* @param deps.listDaemons 列出在线 daemon(ipcPort)
|
|
140
|
+
* @param deps.queryDaemon 查询某 daemon 是否有该 pid 的活跃 adopt 会话
|
|
141
|
+
* @param deps.getAncestors 取祖先 PID(默认使用 getAncestorPids)
|
|
142
|
+
* @param deps.budgetMs 整体耗时上限(默认 1500ms;可注入便于测试)
|
|
143
|
+
*/
|
|
144
|
+
export async function resolveAdoptRoute(deps) {
|
|
145
|
+
const { startPid, listDaemons, queryDaemon } = deps;
|
|
146
|
+
const getAncestors = deps.getAncestors ?? ((pid) => getAncestorPids(pid));
|
|
147
|
+
const budgetMs = deps.budgetMs ?? 1500;
|
|
148
|
+
const ancestors = getAncestors(startPid);
|
|
149
|
+
if (ancestors.length === 0)
|
|
150
|
+
return null;
|
|
151
|
+
const daemons = listDaemons();
|
|
152
|
+
if (daemons.length === 0)
|
|
153
|
+
return null;
|
|
154
|
+
// 候选编号:daemon 列表序 × 祖先链序(由近及远),index 决定确定性优先级。
|
|
155
|
+
const candidates = [];
|
|
156
|
+
let idx = 0;
|
|
157
|
+
for (const daemon of daemons) {
|
|
158
|
+
for (const pid of ancestors) {
|
|
159
|
+
candidates.push({ index: idx++, ipcPort: daemon.ipcPort, pid });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// 并发发起全部查询,命中按 index 记入 hits;整体被 budget 封顶。
|
|
163
|
+
const hits = new Map();
|
|
164
|
+
const queries = candidates.map(async (c) => {
|
|
165
|
+
const route = await queryDaemon(c.ipcPort, c.pid);
|
|
166
|
+
if (route)
|
|
167
|
+
hits.set(c.index, route);
|
|
168
|
+
});
|
|
169
|
+
let timer;
|
|
170
|
+
const budget = new Promise((resolve) => {
|
|
171
|
+
timer = setTimeout(resolve, budgetMs);
|
|
172
|
+
timer.unref?.();
|
|
173
|
+
});
|
|
174
|
+
try {
|
|
175
|
+
await Promise.race([Promise.allSettled(queries), budget]);
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
if (timer)
|
|
179
|
+
clearTimeout(timer);
|
|
180
|
+
}
|
|
181
|
+
// 在「budget 内已 settle 的命中」里按候选 index 升序取最早的一个(确定性)。
|
|
182
|
+
let best = null;
|
|
183
|
+
let bestIdx = Infinity;
|
|
184
|
+
for (const [i, route] of hits) {
|
|
185
|
+
if (i < bestIdx) {
|
|
186
|
+
bestIdx = i;
|
|
187
|
+
best = route;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (best && process.env.BOTMUX_HOOK_DEBUG === '1') {
|
|
191
|
+
process.stderr.write(`[adopt-route] matched candidate#${bestIdx} session=${best.sessionId}\n`);
|
|
192
|
+
}
|
|
193
|
+
return best;
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=adopt-route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopt-route.js","sourceRoot":"","sources":["../../src/adapters/adopt-route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAYvC,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,SAAS,iBAAiB,CAAC,GAAW;IACpC,sBAAsB;IACtB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,CAAC,SAAS,GAAG,OAAO,EAAE,OAAO,CAAC,CAAC;QACxD,+CAA+C;QAC/C,kCAAkC;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,SAAS,KAAK,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACtE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,6BAA6B;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,oCAAoC;QACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpC,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,wBAAwB;IAC1B,CAAC;IAED,kCAAkC;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE;YACjE,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACtC,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,UAA2C,EAC3C,QAAiB;IAEjB,MAAM,MAAM,GAAG,UAAU,IAAI,iBAAiB,CAAC;IAC/C,MAAM,KAAK,GAAG,QAAQ,IAAI,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE5C,IAAI,OAAO,GAAG,QAAQ,CAAC;IACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI,CAAC;YAAE,MAAM,CAAE,iBAAiB;QAC7D,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,MAAM,CAAa,KAAK;QACjD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpB,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAe,EACf,GAAW;IAEX,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,oBAAoB,OAAO,sBAAsB,GAAG,EAAE,EACtD,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAC9B,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAY,CAAC;QAC3C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACnD,MAAM,CAAC,GAAG,IAA+B,CAAC;QAC1C,IACE,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ;YAC/B,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;YAC5B,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ;YAC/B,OAAO,CAAC,CAAC,aAAa,KAAK,QAAQ,EACnC,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO;YACL,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,aAAa,EAAE,CAAC,CAAC,aAAa;SAC/B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,4BAA4B;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAMvC;IACC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IACpD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;IACvC,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAExC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,+CAA+C;IAC/C,MAAM,UAAU,GAA2D,EAAE,CAAC;IAC9E,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,UAAU,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,4CAA4C;IAC5C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC3C,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QACzC,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;QAClD,IAAI,KAAK;YAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,IAAI,KAAgD,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAC3C,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACtC,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5D,CAAC;YAAS,CAAC;QACT,IAAI,KAAK;YAAE,YAAY,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,mDAAmD;IACnD,IAAI,IAAI,GAAsB,IAAI,CAAC;IACnC,IAAI,OAAO,GAAG,QAAQ,CAAC;IACvB,KAAK,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,GAAG,OAAO,EAAE,CAAC;YAAC,OAAO,GAAG,CAAC,CAAC;YAAC,IAAI,GAAG,KAAK,CAAC;QAAC,CAAC;IACjD,CAAC;IACD,IAAI,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,GAAG,EAAE,CAAC;QAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,OAAO,YAAY,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC;IACjG,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -115,13 +115,15 @@ export declare function buildBotmuxEnvAssignments(env: NodeJS.ProcessEnv | undef
|
|
|
115
115
|
* $0 = '_' (placeholder), $1 = cwd, $2..N = KEY=VAL... bin args...
|
|
116
116
|
*
|
|
117
117
|
* The `cd` step makes the CLI's cwd survive a wayward `cd` in the user's
|
|
118
|
-
* rcfile. The `
|
|
119
|
-
*
|
|
118
|
+
* rcfile. The `unset` step removes bare creds the pane inherited from the tmux
|
|
119
|
+
* server's global env (REDACTED_ENV_UNSET_CLAUSE). The `exec /usr/bin/env` step
|
|
120
|
+
* injects botmux's per-bot/per-session overrides AFTER rcfile load so they
|
|
121
|
+
* can't be shadowed by leftover exports.
|
|
120
122
|
*
|
|
121
123
|
* POSIX-syntax (works in bash/zsh/sh); fish/csh/nu users get remapped to
|
|
122
124
|
* bash/zsh/sh by resolveUserShell() so they hit the same SCRIPT path.
|
|
123
125
|
*/
|
|
124
|
-
export declare const SHELL_WRAPPER_SCRIPT
|
|
126
|
+
export declare const SHELL_WRAPPER_SCRIPT: string;
|
|
125
127
|
/**
|
|
126
128
|
* Debug variant of the wrapper script — same prelude, but the CLI runs as
|
|
127
129
|
* a *child* (no `exec`) and the wrapper hands off to an interactive shell
|