botmux 2.111.0 → 2.112.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 +19 -7
- package/README.md +19 -7
- package/dist/adapters/adopt-route.d.ts.map +1 -1
- package/dist/adapters/adopt-route.js +2 -1
- package/dist/adapters/adopt-route.js.map +1 -1
- package/dist/adapters/backend/herdr-backend.d.ts +29 -0
- package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
- package/dist/adapters/backend/herdr-backend.js +167 -0
- package/dist/adapters/backend/herdr-backend.js.map +1 -1
- package/dist/adapters/backend/riff-backend.js +2 -2
- package/dist/adapters/backend/sandbox.d.ts +61 -6
- package/dist/adapters/backend/sandbox.d.ts.map +1 -1
- package/dist/adapters/backend/sandbox.js +235 -43
- package/dist/adapters/backend/sandbox.js.map +1 -1
- package/dist/adapters/backend/tmux-backend.d.ts +1 -0
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +1 -0
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/cli/claude-code.d.ts +2 -0
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +7 -0
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/adapters/cli/codex-app-turn.d.ts +16 -0
- package/dist/adapters/cli/codex-app-turn.d.ts.map +1 -1
- package/dist/adapters/cli/codex-app-turn.js +26 -0
- package/dist/adapters/cli/codex-app-turn.js.map +1 -1
- package/dist/adapters/cli/codex.d.ts.map +1 -1
- package/dist/adapters/cli/codex.js +1 -0
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/grok.d.ts +8 -6
- package/dist/adapters/cli/grok.d.ts.map +1 -1
- package/dist/adapters/cli/grok.js +14 -6
- package/dist/adapters/cli/grok.js.map +1 -1
- package/dist/adapters/cli/read-isolation.d.ts +40 -14
- package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
- package/dist/adapters/cli/read-isolation.js +116 -19
- package/dist/adapters/cli/read-isolation.js.map +1 -1
- package/dist/adapters/cli/runner-control-channel.d.ts +32 -0
- package/dist/adapters/cli/runner-control-channel.d.ts.map +1 -0
- package/dist/adapters/cli/runner-control-channel.js +104 -0
- package/dist/adapters/cli/runner-control-channel.js.map +1 -0
- 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 +9 -0
- package/dist/adapters/cli/shared-hints.js.map +1 -1
- package/dist/adapters/cli/traex.d.ts.map +1 -1
- package/dist/adapters/cli/traex.js +100 -64
- package/dist/adapters/cli/traex.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +13 -0
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/bot-registry.d.ts +36 -27
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +354 -8
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/saved-workflow.d.ts +25 -0
- package/dist/cli/saved-workflow.d.ts.map +1 -0
- package/dist/cli/saved-workflow.js +338 -0
- package/dist/cli/saved-workflow.js.map +1 -0
- package/dist/cli/send-dispatch.d.ts +18 -3
- package/dist/cli/send-dispatch.d.ts.map +1 -1
- package/dist/cli/send-dispatch.js +22 -3
- package/dist/cli/send-dispatch.js.map +1 -1
- package/dist/cli/v3-run-cancel.d.ts +47 -0
- package/dist/cli/v3-run-cancel.d.ts.map +1 -0
- package/dist/cli/v3-run-cancel.js +96 -0
- package/dist/cli/v3-run-cancel.js.map +1 -0
- package/dist/cli/vc-agent.d.ts.map +1 -1
- package/dist/cli/vc-agent.js +54 -1
- package/dist/cli/vc-agent.js.map +1 -1
- package/dist/cli/workflow-migration.d.ts +39 -0
- package/dist/cli/workflow-migration.d.ts.map +1 -0
- package/dist/cli/workflow-migration.js +302 -0
- package/dist/cli/workflow-migration.js.map +1 -0
- package/dist/cli/workflow-run-archive.d.ts +29 -0
- package/dist/cli/workflow-run-archive.d.ts.map +1 -0
- package/dist/cli/workflow-run-archive.js +183 -0
- package/dist/cli/workflow-run-archive.js.map +1 -0
- package/dist/cli/workflow.d.ts +5 -10
- package/dist/cli/workflow.d.ts.map +1 -1
- package/dist/cli/workflow.js +85 -764
- package/dist/cli/workflow.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1018 -191
- package/dist/cli.js.map +1 -1
- package/dist/codex-app-runner.js +30 -21
- package/dist/codex-app-runner.js.map +1 -1
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +21 -9
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/current-turn-provenance.d.ts +39 -0
- package/dist/core/current-turn-provenance.d.ts.map +1 -0
- package/dist/core/current-turn-provenance.js +122 -0
- package/dist/core/current-turn-provenance.js.map +1 -0
- package/dist/core/daemon-ipc-auth.d.ts +20 -0
- package/dist/core/daemon-ipc-auth.d.ts.map +1 -0
- package/dist/core/daemon-ipc-auth.js +44 -0
- package/dist/core/daemon-ipc-auth.js.map +1 -0
- package/dist/core/daemon-ipc-session-auth.d.ts +37 -0
- package/dist/core/daemon-ipc-session-auth.d.ts.map +1 -0
- package/dist/core/daemon-ipc-session-auth.js +35 -0
- package/dist/core/daemon-ipc-session-auth.js.map +1 -0
- package/dist/core/dashboard-command/index.d.ts +0 -2
- package/dist/core/dashboard-command/index.d.ts.map +1 -1
- package/dist/core/dashboard-command/index.js +2 -2
- package/dist/core/dashboard-command/index.js.map +1 -1
- package/dist/core/dashboard-command/stub.d.ts +1 -1
- package/dist/core/dashboard-command/stub.d.ts.map +1 -1
- package/dist/core/dashboard-command/stub.js +0 -1
- package/dist/core/dashboard-command/stub.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts +11 -2
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +266 -41
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dashboard-secret.d.ts +3 -0
- package/dist/core/dashboard-secret.d.ts.map +1 -0
- package/dist/core/dashboard-secret.js +7 -0
- package/dist/core/dashboard-secret.js.map +1 -0
- package/dist/core/data-dir.d.ts +24 -0
- package/dist/core/data-dir.d.ts.map +1 -0
- package/dist/core/data-dir.js +48 -0
- package/dist/core/data-dir.js.map +1 -0
- package/dist/core/inflight-input-tracker.d.ts +4 -2
- package/dist/core/inflight-input-tracker.d.ts.map +1 -1
- package/dist/core/inflight-input-tracker.js +6 -5
- package/dist/core/inflight-input-tracker.js.map +1 -1
- package/dist/core/inject-queue-policy.d.ts +70 -0
- package/dist/core/inject-queue-policy.d.ts.map +1 -0
- package/dist/core/inject-queue-policy.js +30 -0
- package/dist/core/inject-queue-policy.js.map +1 -0
- package/dist/core/maintenance.d.ts +1 -1
- package/dist/core/maintenance.d.ts.map +1 -1
- package/dist/core/maintenance.js +3 -2
- package/dist/core/maintenance.js.map +1 -1
- package/dist/core/managed-origin-capability.d.ts +30 -0
- package/dist/core/managed-origin-capability.d.ts.map +1 -0
- package/dist/core/managed-origin-capability.js +88 -0
- package/dist/core/managed-origin-capability.js.map +1 -0
- package/dist/core/role-library.d.ts +15 -0
- package/dist/core/role-library.d.ts.map +1 -0
- package/dist/core/role-library.js +75 -0
- package/dist/core/role-library.js.map +1 -0
- package/dist/core/session-cwd.d.ts +14 -0
- package/dist/core/session-cwd.d.ts.map +1 -0
- package/dist/core/session-cwd.js +17 -0
- package/dist/core/session-cwd.js.map +1 -0
- package/dist/core/session-manager.d.ts +4 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +27 -8
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-marker.d.ts +22 -0
- package/dist/core/session-marker.d.ts.map +1 -1
- package/dist/core/session-marker.js +185 -20
- package/dist/core/session-marker.js.map +1 -1
- package/dist/core/slash-inject.d.ts +15 -0
- package/dist/core/slash-inject.d.ts.map +1 -0
- package/dist/core/slash-inject.js +25 -0
- package/dist/core/slash-inject.js.map +1 -0
- package/dist/core/terminal-url.d.ts +1 -0
- package/dist/core/terminal-url.d.ts.map +1 -1
- package/dist/core/terminal-url.js +14 -8
- package/dist/core/terminal-url.js.map +1 -1
- package/dist/core/terminal-write-auth.d.ts +26 -0
- package/dist/core/terminal-write-auth.d.ts.map +1 -1
- package/dist/core/terminal-write-auth.js +48 -3
- package/dist/core/terminal-write-auth.js.map +1 -1
- package/dist/core/trigger-session.d.ts +24 -1
- package/dist/core/trigger-session.d.ts.map +1 -1
- package/dist/core/trigger-session.js +106 -15
- package/dist/core/trigger-session.js.map +1 -1
- package/dist/core/types.d.ts +26 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +10 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts +65 -2
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +459 -39
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts +249 -8
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +7383 -1195
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/aggregator.d.ts +1 -1
- package/dist/dashboard/aggregator.d.ts.map +1 -1
- package/dist/dashboard/aggregator.js +2 -2
- package/dist/dashboard/aggregator.js.map +1 -1
- package/dist/dashboard/auth.d.ts +3 -8
- package/dist/dashboard/auth.d.ts.map +1 -1
- package/dist/dashboard/auth.js +63 -22
- package/dist/dashboard/auth.js.map +1 -1
- package/dist/dashboard/bot-onboarding.d.ts +5 -0
- package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
- package/dist/dashboard/bot-onboarding.js +37 -0
- package/dist/dashboard/bot-onboarding.js.map +1 -1
- package/dist/dashboard/connector-api.d.ts.map +1 -1
- package/dist/dashboard/connector-api.js +42 -2
- package/dist/dashboard/connector-api.js.map +1 -1
- package/dist/dashboard/daemon-internal-api.d.ts +0 -2
- package/dist/dashboard/daemon-internal-api.d.ts.map +1 -1
- package/dist/dashboard/daemon-internal-api.js +26 -93
- package/dist/dashboard/daemon-internal-api.js.map +1 -1
- package/dist/dashboard/daemon-internal-client.d.ts.map +1 -1
- package/dist/dashboard/daemon-internal-client.js +2 -3
- package/dist/dashboard/daemon-internal-client.js.map +1 -1
- package/dist/dashboard/federation-api.js +1 -1
- package/dist/dashboard/federation-api.js.map +1 -1
- package/dist/dashboard/federation-spoke-api.js +1 -1
- package/dist/dashboard/federation-spoke-api.js.map +1 -1
- package/dist/dashboard/history-senders.d.ts +3 -0
- package/dist/dashboard/history-senders.d.ts.map +1 -1
- package/dist/dashboard/history-senders.js.map +1 -1
- package/dist/dashboard/http.d.ts +4 -0
- package/dist/dashboard/http.d.ts.map +1 -0
- package/dist/dashboard/http.js +6 -0
- package/dist/dashboard/http.js.map +1 -0
- package/dist/dashboard/registry.d.ts +4 -0
- package/dist/dashboard/registry.d.ts.map +1 -1
- package/dist/dashboard/registry.js.map +1 -1
- package/dist/dashboard/trigger-api.js +1 -1
- package/dist/dashboard/trigger-api.js.map +1 -1
- package/dist/dashboard/v3-runs-api.d.ts +13 -10
- package/dist/dashboard/v3-runs-api.d.ts.map +1 -1
- package/dist/dashboard/v3-runs-api.js +121 -4
- package/dist/dashboard/v3-runs-api.js.map +1 -1
- package/dist/dashboard/vc-consumer-profiles-api.d.ts +105 -0
- package/dist/dashboard/vc-consumer-profiles-api.d.ts.map +1 -0
- package/dist/dashboard/vc-consumer-profiles-api.js +312 -0
- package/dist/dashboard/vc-consumer-profiles-api.js.map +1 -0
- package/dist/dashboard/web/app.d.ts.map +1 -1
- package/dist/dashboard/web/app.js +7 -6
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.js +9 -14
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
- package/dist/dashboard/web/bot-onboarding.d.ts.map +1 -1
- package/dist/dashboard/web/bot-onboarding.js +7 -3
- package/dist/dashboard/web/bot-onboarding.js.map +1 -1
- package/dist/dashboard/web/connectors-page.d.ts +5 -0
- package/dist/dashboard/web/connectors-page.d.ts.map +1 -1
- package/dist/dashboard/web/connectors-page.js +16 -12
- package/dist/dashboard/web/connectors-page.js.map +1 -1
- package/dist/dashboard/web/create-session-entry.d.ts +4 -0
- package/dist/dashboard/web/create-session-entry.d.ts.map +1 -0
- package/dist/dashboard/web/create-session-entry.js +17 -0
- package/dist/dashboard/web/create-session-entry.js.map +1 -0
- package/dist/dashboard/web/dashboard-components.d.ts +5 -0
- package/dist/dashboard/web/dashboard-components.d.ts.map +1 -1
- package/dist/dashboard/web/dashboard-components.js +29 -4
- package/dist/dashboard/web/dashboard-components.js.map +1 -1
- package/dist/dashboard/web/dashboard-routes.d.ts.map +1 -1
- package/dist/dashboard/web/dashboard-routes.js +0 -1
- 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 +192 -382
- package/dist/dashboard/web/i18n.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/schedules-page.d.ts.map +1 -1
- package/dist/dashboard/web/schedules-page.js +4 -1
- package/dist/dashboard/web/schedules-page.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-page.js +64 -18
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard/web/settings-page.d.ts.map +1 -1
- package/dist/dashboard/web/settings-page.js +2 -1
- package/dist/dashboard/web/settings-page.js.map +1 -1
- package/dist/dashboard/web/v3-api.d.ts +12 -2
- package/dist/dashboard/web/v3-api.d.ts.map +1 -1
- package/dist/dashboard/web/v3-api.js +34 -6
- package/dist/dashboard/web/v3-api.js.map +1 -1
- package/dist/dashboard/web/v3-components.d.ts +6 -0
- package/dist/dashboard/web/v3-components.d.ts.map +1 -1
- package/dist/dashboard/web/v3-components.js +66 -23
- package/dist/dashboard/web/v3-components.js.map +1 -1
- package/dist/dashboard/web/v3-model.js +1 -1
- package/dist/dashboard/web/v3-model.js.map +1 -1
- package/dist/dashboard/web/v3-terminal.js +2 -2
- package/dist/dashboard/web/v3-terminal.js.map +1 -1
- package/dist/dashboard/web/vc-consumer-profiles-section.d.ts +19 -0
- package/dist/dashboard/web/vc-consumer-profiles-section.d.ts.map +1 -0
- package/dist/dashboard/web/vc-consumer-profiles-section.js +382 -0
- package/dist/dashboard/web/vc-consumer-profiles-section.js.map +1 -0
- package/dist/dashboard/webhook-routes.d.ts.map +1 -1
- package/dist/dashboard/webhook-routes.js +29 -6
- package/dist/dashboard/webhook-routes.js.map +1 -1
- package/dist/dashboard-web/app.js +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-RYBL4ZYE.js +4 -0
- package/dist/dashboard-web/chunks/{chunk-OEJIT66L.js → chunk-CMDPZOPK.js} +1 -1
- package/dist/dashboard-web/chunks/chunk-I35DXGM4.js +1 -0
- package/dist/dashboard-web/chunks/chunk-NYZHARIU.js +47 -0
- package/dist/dashboard-web/chunks/chunk-SZOB6VK2.js +1 -0
- package/dist/dashboard-web/chunks/{chunk-YQFXGRSD.js → chunk-YBOHL7T7.js} +1 -1
- package/dist/dashboard-web/chunks/chunk-YWCPDL4S.js +1 -0
- package/dist/dashboard-web/chunks/connectors-page-DAMP7TTV.js +1 -0
- package/dist/dashboard-web/chunks/{groups-page-5AJPPJH2.js → groups-page-BPFA356N.js} +1 -1
- package/dist/dashboard-web/chunks/{insights-page-R3DFECX4.js → insights-page-SHOPHTWY.js} +1 -1
- package/dist/dashboard-web/chunks/{monitor-room-NLMKJLDY.js → monitor-room-PXPJGZCN.js} +1 -1
- package/dist/dashboard-web/chunks/{monitoring-page-EHSOX4GV.js → monitoring-page-4DF54M5Y.js} +1 -1
- package/dist/dashboard-web/chunks/{office-page-OXJKFJ4R.js → office-page-6OHU6KMZ.js} +1 -1
- package/dist/dashboard-web/chunks/{overview-page-GJHIVXJF.js → overview-page-IHIZ6F5M.js} +1 -1
- package/dist/dashboard-web/chunks/{roles-page-6ZODQISW.js → roles-page-JYTBYKEF.js} +1 -1
- package/dist/dashboard-web/chunks/{schedules-page-DAGMHVCH.js → schedules-page-WJ72T7KV.js} +1 -1
- package/dist/dashboard-web/chunks/sessions-page-QC56OIAI.js +3 -0
- package/dist/dashboard-web/chunks/settings-page-TCKWEXTN.js +2 -0
- package/dist/dashboard-web/chunks/{skills-page-J7EVUHXP.js → skills-page-RJJNIECW.js} +1 -1
- package/dist/dashboard-web/chunks/{team-federation-page-YM5JBIII.js → team-federation-page-ZMDX3E7K.js} +1 -1
- package/dist/dashboard-web/chunks/v3-page-VLLAUQ33.js +94 -0
- package/dist/dashboard-web/chunks/{whiteboards-page-75N2U6W4.js → whiteboards-page-NAO53CKM.js} +1 -1
- package/dist/dashboard-web/style.css +363 -274
- package/dist/dashboard.js +194 -78
- package/dist/dashboard.js.map +1 -1
- package/dist/global-config.d.ts +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +12 -87
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +12 -87
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/brand-template.d.ts +15 -0
- package/dist/im/lark/brand-template.d.ts.map +1 -0
- package/dist/im/lark/brand-template.js +114 -0
- package/dist/im/lark/brand-template.js.map +1 -0
- package/dist/im/lark/card-handler.d.ts +6 -3
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +23 -39
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +8 -2
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +33 -31
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/doc-comment.d.ts +18 -0
- package/dist/im/lark/doc-comment.d.ts.map +1 -1
- package/dist/im/lark/doc-comment.js +119 -5
- package/dist/im/lark/doc-comment.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +18 -2
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +41 -19
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/merge-forward.d.ts.map +1 -1
- package/dist/im/lark/merge-forward.js +7 -2
- package/dist/im/lark/merge-forward.js.map +1 -1
- package/dist/im/lark/message-parser.d.ts.map +1 -1
- package/dist/im/lark/message-parser.js +7 -0
- package/dist/im/lark/message-parser.js.map +1 -1
- package/dist/im/lark/overview-card.d.ts +1 -2
- package/dist/im/lark/overview-card.d.ts.map +1 -1
- package/dist/im/lark/overview-card.js +1 -48
- package/dist/im/lark/overview-card.js.map +1 -1
- package/dist/im/lark/v3-blocked-card-handler.d.ts.map +1 -1
- package/dist/im/lark/v3-blocked-card-handler.js +5 -5
- package/dist/im/lark/v3-blocked-card-handler.js.map +1 -1
- package/dist/im/lark/v3-blocked-card.d.ts +1 -0
- package/dist/im/lark/v3-blocked-card.d.ts.map +1 -1
- package/dist/im/lark/v3-blocked-card.js +19 -2
- package/dist/im/lark/v3-blocked-card.js.map +1 -1
- package/dist/im/lark/v3-distillation-card-handler.d.ts +12 -0
- package/dist/im/lark/v3-distillation-card-handler.d.ts.map +1 -0
- package/dist/im/lark/v3-distillation-card-handler.js +107 -0
- package/dist/im/lark/v3-distillation-card-handler.js.map +1 -0
- package/dist/im/lark/v3-distillation-card.d.ts +42 -0
- package/dist/im/lark/v3-distillation-card.d.ts.map +1 -0
- package/dist/im/lark/v3-distillation-card.js +206 -0
- package/dist/im/lark/v3-distillation-card.js.map +1 -0
- package/dist/im/lark/v3-gate-card-handler.d.ts +1 -1
- package/dist/im/lark/v3-gate-card-handler.d.ts.map +1 -1
- package/dist/im/lark/v3-gate-card-handler.js +6 -5
- package/dist/im/lark/v3-gate-card-handler.js.map +1 -1
- package/dist/im/lark/v3-gate-card.d.ts +8 -1
- package/dist/im/lark/v3-gate-card.d.ts.map +1 -1
- package/dist/im/lark/v3-gate-card.js +38 -7
- package/dist/im/lark/v3-gate-card.js.map +1 -1
- package/dist/im/lark/v3-loop-grant-card-handler.d.ts.map +1 -1
- package/dist/im/lark/v3-loop-grant-card-handler.js +3 -4
- package/dist/im/lark/v3-loop-grant-card-handler.js.map +1 -1
- package/dist/im/lark/v3-loop-grant-card.js +1 -1
- package/dist/im/lark/v3-loop-grant-card.js.map +1 -1
- package/dist/im/lark/v3-progress-card-manager.d.ts +79 -0
- package/dist/im/lark/v3-progress-card-manager.d.ts.map +1 -0
- package/dist/im/lark/v3-progress-card-manager.js +444 -0
- package/dist/im/lark/v3-progress-card-manager.js.map +1 -0
- package/dist/im/lark/v3-progress-card.d.ts +26 -0
- package/dist/im/lark/v3-progress-card.d.ts.map +1 -0
- package/dist/im/lark/v3-progress-card.js +211 -0
- package/dist/im/lark/v3-progress-card.js.map +1 -0
- package/dist/im/lark/v3-revisit-grant-card-handler.d.ts.map +1 -1
- package/dist/im/lark/v3-revisit-grant-card-handler.js +3 -4
- package/dist/im/lark/v3-revisit-grant-card-handler.js.map +1 -1
- package/dist/im/lark/v3-revisit-grant-card.js +1 -1
- package/dist/im/lark/v3-revisit-grant-card.js.map +1 -1
- package/dist/im/lark/v3-run-save-card-handler.d.ts +12 -0
- package/dist/im/lark/v3-run-save-card-handler.d.ts.map +1 -0
- package/dist/im/lark/v3-run-save-card-handler.js +160 -0
- package/dist/im/lark/v3-run-save-card-handler.js.map +1 -0
- package/dist/im/lark/v3-run-save-card.d.ts +38 -0
- package/dist/im/lark/v3-run-save-card.d.ts.map +1 -0
- package/dist/im/lark/v3-run-save-card.js +125 -0
- package/dist/im/lark/v3-run-save-card.js.map +1 -0
- package/dist/im/lark/v3-saved-workflow-command.d.ts +36 -0
- package/dist/im/lark/v3-saved-workflow-command.d.ts.map +1 -0
- package/dist/im/lark/v3-saved-workflow-command.js +186 -0
- package/dist/im/lark/v3-saved-workflow-command.js.map +1 -0
- package/dist/im/lark/v3-saved-workflow-handler.d.ts +89 -0
- package/dist/im/lark/v3-saved-workflow-handler.d.ts.map +1 -0
- package/dist/im/lark/v3-saved-workflow-handler.js +212 -0
- package/dist/im/lark/v3-saved-workflow-handler.js.map +1 -0
- package/dist/im/lark/workflow-slash-command.d.ts +7 -110
- package/dist/im/lark/workflow-slash-command.d.ts.map +1 -1
- package/dist/im/lark/workflow-slash-command.js +16 -230
- package/dist/im/lark/workflow-slash-command.js.map +1 -1
- package/dist/index-daemon.js +1 -1
- package/dist/index-daemon.js.map +1 -1
- package/dist/mir-runner.js +11 -15
- package/dist/mir-runner.js.map +1 -1
- package/dist/mira-runner.js +8 -12
- package/dist/mira-runner.js.map +1 -1
- package/dist/services/bridge-turn-queue.d.ts +29 -12
- package/dist/services/bridge-turn-queue.d.ts.map +1 -1
- package/dist/services/bridge-turn-queue.js +59 -23
- package/dist/services/bridge-turn-queue.js.map +1 -1
- package/dist/services/claude-transcript.d.ts +15 -0
- package/dist/services/claude-transcript.d.ts.map +1 -1
- package/dist/services/claude-transcript.js +24 -0
- package/dist/services/claude-transcript.js.map +1 -1
- package/dist/services/codex-bridge-queue.d.ts +13 -2
- package/dist/services/codex-bridge-queue.d.ts.map +1 -1
- package/dist/services/codex-bridge-queue.js +20 -3
- package/dist/services/codex-bridge-queue.js.map +1 -1
- package/dist/services/codex-transcript.d.ts +6 -0
- package/dist/services/codex-transcript.d.ts.map +1 -1
- package/dist/services/codex-transcript.js.map +1 -1
- package/dist/services/grok-transcript.d.ts +3 -2
- package/dist/services/grok-transcript.d.ts.map +1 -1
- package/dist/services/grok-transcript.js +73 -22
- package/dist/services/grok-transcript.js.map +1 -1
- package/dist/services/hook-runner.d.ts.map +1 -1
- package/dist/services/hook-runner.js +26 -3
- package/dist/services/hook-runner.js.map +1 -1
- package/dist/services/schedule-store.d.ts +37 -0
- package/dist/services/schedule-store.d.ts.map +1 -1
- package/dist/services/schedule-store.js +259 -141
- package/dist/services/schedule-store.js.map +1 -1
- package/dist/services/send-policy.d.ts +50 -0
- package/dist/services/send-policy.d.ts.map +1 -1
- package/dist/services/send-policy.js +65 -0
- package/dist/services/send-policy.js.map +1 -1
- package/dist/services/session-lifecycle-hooks.d.ts.map +1 -1
- package/dist/services/session-lifecycle-hooks.js +12 -0
- package/dist/services/session-lifecycle-hooks.js.map +1 -1
- package/dist/services/traex-transcript.d.ts +11 -2
- package/dist/services/traex-transcript.d.ts.map +1 -1
- package/dist/services/traex-transcript.js +142 -8
- package/dist/services/traex-transcript.js.map +1 -1
- package/dist/services/trigger-types.d.ts +6 -1
- package/dist/services/trigger-types.d.ts.map +1 -1
- package/dist/services/trigger-types.js.map +1 -1
- package/dist/services/turn-terminal-deduper.d.ts +14 -0
- package/dist/services/turn-terminal-deduper.d.ts.map +1 -0
- package/dist/services/turn-terminal-deduper.js +34 -0
- package/dist/services/turn-terminal-deduper.js.map +1 -0
- package/dist/services/vc-meeting-action-gate.d.ts +246 -0
- package/dist/services/vc-meeting-action-gate.d.ts.map +1 -0
- package/dist/services/vc-meeting-action-gate.js +756 -0
- package/dist/services/vc-meeting-action-gate.js.map +1 -0
- package/dist/services/vc-meeting-action-store.d.ts +222 -0
- package/dist/services/vc-meeting-action-store.d.ts.map +1 -0
- package/dist/services/vc-meeting-action-store.js +806 -0
- package/dist/services/vc-meeting-action-store.js.map +1 -0
- package/dist/services/vc-meeting-consumer-isolation.d.ts +27 -0
- package/dist/services/vc-meeting-consumer-isolation.d.ts.map +1 -0
- package/dist/services/vc-meeting-consumer-isolation.js +37 -0
- package/dist/services/vc-meeting-consumer-isolation.js.map +1 -0
- package/dist/services/vc-meeting-consumer-profile-bootstrap.d.ts +72 -0
- package/dist/services/vc-meeting-consumer-profile-bootstrap.d.ts.map +1 -0
- package/dist/services/vc-meeting-consumer-profile-bootstrap.js +343 -0
- package/dist/services/vc-meeting-consumer-profile-bootstrap.js.map +1 -0
- package/dist/services/vc-meeting-consumer-profile-store.d.ts +39 -0
- package/dist/services/vc-meeting-consumer-profile-store.d.ts.map +1 -0
- package/dist/services/vc-meeting-consumer-profile-store.js +190 -0
- package/dist/services/vc-meeting-consumer-profile-store.js.map +1 -0
- package/dist/services/vc-meeting-daemon-auth.d.ts +29 -0
- package/dist/services/vc-meeting-daemon-auth.d.ts.map +1 -0
- package/dist/services/vc-meeting-daemon-auth.js +117 -0
- package/dist/services/vc-meeting-daemon-auth.js.map +1 -0
- package/dist/services/vc-meeting-delivery-feed.d.ts +52 -0
- package/dist/services/vc-meeting-delivery-feed.d.ts.map +1 -0
- package/dist/services/vc-meeting-delivery-feed.js +231 -0
- package/dist/services/vc-meeting-delivery-feed.js.map +1 -0
- package/dist/services/vc-meeting-delivery-hub-store.d.ts +213 -0
- package/dist/services/vc-meeting-delivery-hub-store.d.ts.map +1 -0
- package/dist/services/vc-meeting-delivery-hub-store.js +1230 -0
- package/dist/services/vc-meeting-delivery-hub-store.js.map +1 -0
- package/dist/services/vc-meeting-delivery-protocol.d.ts +159 -0
- package/dist/services/vc-meeting-delivery-protocol.d.ts.map +1 -0
- package/dist/services/vc-meeting-delivery-protocol.js +443 -0
- package/dist/services/vc-meeting-delivery-protocol.js.map +1 -0
- package/dist/services/vc-meeting-delivery-receiver.d.ts +80 -0
- package/dist/services/vc-meeting-delivery-receiver.d.ts.map +1 -0
- package/dist/services/vc-meeting-delivery-receiver.js +543 -0
- package/dist/services/vc-meeting-delivery-receiver.js.map +1 -0
- package/dist/services/vc-meeting-delivery-store.d.ts +339 -0
- package/dist/services/vc-meeting-delivery-store.d.ts.map +1 -0
- package/dist/services/vc-meeting-delivery-store.js +1024 -0
- package/dist/services/vc-meeting-delivery-store.js.map +1 -0
- package/dist/services/vc-meeting-feed-metadata-store.d.ts +58 -0
- package/dist/services/vc-meeting-feed-metadata-store.d.ts.map +1 -0
- package/dist/services/vc-meeting-feed-metadata-store.js +356 -0
- package/dist/services/vc-meeting-feed-metadata-store.js.map +1 -0
- package/dist/services/vc-meeting-im-reply.d.ts +55 -0
- package/dist/services/vc-meeting-im-reply.d.ts.map +1 -0
- package/dist/services/vc-meeting-im-reply.js +279 -0
- package/dist/services/vc-meeting-im-reply.js.map +1 -0
- package/dist/services/vc-meeting-im-routing.d.ts +131 -0
- package/dist/services/vc-meeting-im-routing.d.ts.map +1 -0
- package/dist/services/vc-meeting-im-routing.js +449 -0
- package/dist/services/vc-meeting-im-routing.js.map +1 -0
- package/dist/services/vc-meeting-listener-message-store.d.ts +23 -0
- package/dist/services/vc-meeting-listener-message-store.d.ts.map +1 -0
- package/dist/services/vc-meeting-listener-message-store.js +142 -0
- package/dist/services/vc-meeting-listener-message-store.js.map +1 -0
- package/dist/services/vc-meeting-member-policy.d.ts +37 -0
- package/dist/services/vc-meeting-member-policy.d.ts.map +1 -0
- package/dist/services/vc-meeting-member-policy.js +102 -0
- package/dist/services/vc-meeting-member-policy.js.map +1 -0
- package/dist/services/vc-meeting-profile-instructions.d.ts +22 -0
- package/dist/services/vc-meeting-profile-instructions.d.ts.map +1 -0
- package/dist/services/vc-meeting-profile-instructions.js +64 -0
- package/dist/services/vc-meeting-profile-instructions.js.map +1 -0
- package/dist/services/vc-meeting-runtime-store.d.ts +63 -0
- package/dist/services/vc-meeting-runtime-store.d.ts.map +1 -1
- package/dist/services/vc-meeting-runtime-store.js +605 -116
- package/dist/services/vc-meeting-runtime-store.js.map +1 -1
- package/dist/services/vc-meeting-send-policy.d.ts +89 -0
- package/dist/services/vc-meeting-send-policy.d.ts.map +1 -0
- package/dist/services/vc-meeting-send-policy.js +150 -0
- package/dist/services/vc-meeting-send-policy.js.map +1 -0
- package/dist/services/vc-meeting-terminal-reconciler.d.ts +93 -0
- package/dist/services/vc-meeting-terminal-reconciler.d.ts.map +1 -0
- package/dist/services/vc-meeting-terminal-reconciler.js +198 -0
- package/dist/services/vc-meeting-terminal-reconciler.js.map +1 -0
- package/dist/setup/open-platform-automation.d.ts +2 -0
- package/dist/setup/open-platform-automation.d.ts.map +1 -1
- package/dist/setup/open-platform-automation.js +1 -0
- package/dist/setup/open-platform-automation.js.map +1 -1
- package/dist/setup/open-platform-outcome.d.ts +50 -0
- package/dist/setup/open-platform-outcome.d.ts.map +1 -0
- package/dist/setup/open-platform-outcome.js +56 -0
- package/dist/setup/open-platform-outcome.js.map +1 -0
- package/dist/setup/setup-args.d.ts +7 -2
- package/dist/setup/setup-args.d.ts.map +1 -1
- package/dist/setup/setup-args.js +21 -5
- package/dist/setup/setup-args.js.map +1 -1
- package/dist/skills/definitions.d.ts.map +1 -1
- package/dist/skills/definitions.js +66 -54
- package/dist/skills/definitions.js.map +1 -1
- package/dist/skills/injection-mode.d.ts +5 -4
- package/dist/skills/injection-mode.d.ts.map +1 -1
- package/dist/skills/injection-mode.js +19 -10
- package/dist/skills/injection-mode.js.map +1 -1
- package/dist/types.d.ts +187 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/canonical-input-hash.d.ts +5 -0
- package/dist/utils/canonical-input-hash.d.ts.map +1 -0
- package/dist/utils/canonical-input-hash.js +43 -0
- package/dist/utils/canonical-input-hash.js.map +1 -0
- package/dist/utils/canonical-json.d.ts +10 -0
- package/dist/utils/canonical-json.d.ts.map +1 -0
- package/dist/utils/canonical-json.js +23 -0
- package/dist/utils/canonical-json.js.map +1 -0
- package/dist/utils/child-env.d.ts +1 -1
- package/dist/utils/child-env.d.ts.map +1 -1
- package/dist/utils/child-env.js +8 -0
- package/dist/utils/child-env.js.map +1 -1
- package/dist/utils/daemon-discovery.d.ts +4 -0
- package/dist/utils/daemon-discovery.d.ts.map +1 -1
- package/dist/utils/daemon-discovery.js +12 -6
- package/dist/utils/daemon-discovery.js.map +1 -1
- package/dist/utils/file-lock.d.ts.map +1 -1
- package/dist/utils/file-lock.js +696 -102
- package/dist/utils/file-lock.js.map +1 -1
- package/dist/utils/fs-durability.d.ts +20 -0
- package/dist/utils/fs-durability.d.ts.map +1 -0
- package/dist/utils/fs-durability.js +84 -0
- package/dist/utils/fs-durability.js.map +1 -0
- package/dist/utils/global-install.d.ts +5 -2
- package/dist/utils/global-install.d.ts.map +1 -1
- package/dist/utils/global-install.js +22 -4
- package/dist/utils/global-install.js.map +1 -1
- package/dist/utils/herdr-web-history.d.ts +12 -0
- package/dist/utils/herdr-web-history.d.ts.map +1 -0
- package/dist/utils/herdr-web-history.js +74 -0
- package/dist/utils/herdr-web-history.js.map +1 -0
- package/dist/utils/herdr-web-terminal-binding.d.ts +39 -0
- package/dist/utils/herdr-web-terminal-binding.d.ts.map +1 -0
- package/dist/utils/herdr-web-terminal-binding.js +56 -0
- package/dist/utils/herdr-web-terminal-binding.js.map +1 -0
- package/dist/utils/pending-input-queue.d.ts +30 -1
- package/dist/utils/pending-input-queue.d.ts.map +1 -1
- package/dist/utils/pending-input-queue.js +45 -5
- package/dist/utils/pending-input-queue.js.map +1 -1
- package/dist/vc-agent/cards.d.ts +49 -4
- package/dist/vc-agent/cards.d.ts.map +1 -1
- package/dist/vc-agent/cards.js +460 -70
- package/dist/vc-agent/cards.js.map +1 -1
- package/dist/vc-agent/polling-source.d.ts +6 -1
- package/dist/vc-agent/polling-source.d.ts.map +1 -1
- package/dist/vc-agent/polling-source.js +17 -4
- package/dist/vc-agent/polling-source.js.map +1 -1
- package/dist/worker.js +1333 -283
- package/dist/worker.js.map +1 -1
- package/dist/workflows/definition.d.ts +28 -35
- package/dist/workflows/definition.d.ts.map +1 -1
- package/dist/workflows/definition.js +7 -24
- package/dist/workflows/definition.js.map +1 -1
- package/dist/workflows/events/payloads.d.ts +28 -28
- package/dist/workflows/events/replay.d.ts +5 -0
- package/dist/workflows/events/replay.d.ts.map +1 -1
- package/dist/workflows/events/replay.js +6 -1
- package/dist/workflows/events/replay.js.map +1 -1
- package/dist/workflows/events/schema.d.ts +663 -663
- package/dist/workflows/events/schema.d.ts.map +1 -1
- package/dist/workflows/events/schema.js +1 -4
- package/dist/workflows/events/schema.js.map +1 -1
- package/dist/workflows/hostExecutors/botmux-schedule.d.ts +5 -4
- package/dist/workflows/hostExecutors/botmux-schedule.d.ts.map +1 -1
- package/dist/workflows/hostExecutors/botmux-schedule.js +80 -35
- package/dist/workflows/hostExecutors/botmux-schedule.js.map +1 -1
- package/dist/workflows/hostExecutors/feishu-im.d.ts +3 -3
- package/dist/workflows/hostExecutors/feishu-im.d.ts.map +1 -1
- package/dist/workflows/hostExecutors/feishu-im.js +3 -3
- package/dist/workflows/hostExecutors/feishu-im.js.map +1 -1
- package/dist/workflows/hostExecutors/feishu-reply.d.ts +1 -1
- package/dist/workflows/hostExecutors/feishu-reply.d.ts.map +1 -1
- package/dist/workflows/hostExecutors/feishu-reply.js +1 -1
- package/dist/workflows/hostExecutors/feishu-reply.js.map +1 -1
- package/dist/workflows/hostExecutors/feishu-send.d.ts +1 -1
- package/dist/workflows/hostExecutors/feishu-send.d.ts.map +1 -1
- package/dist/workflows/hostExecutors/feishu-send.js +1 -1
- package/dist/workflows/hostExecutors/feishu-send.js.map +1 -1
- package/dist/workflows/hostExecutors/index.d.ts +0 -1
- package/dist/workflows/hostExecutors/index.d.ts.map +1 -1
- package/dist/workflows/hostExecutors/index.js +0 -1
- package/dist/workflows/hostExecutors/index.js.map +1 -1
- package/dist/workflows/hostExecutors/registry.d.ts +1 -1
- package/dist/workflows/hostExecutors/registry.d.ts.map +1 -1
- package/dist/workflows/hostExecutors/types.d.ts +21 -29
- package/dist/workflows/hostExecutors/types.d.ts.map +1 -1
- package/dist/workflows/migration/v2-definition-paths.d.ts +3 -0
- package/dist/workflows/migration/v2-definition-paths.d.ts.map +1 -0
- package/dist/workflows/migration/v2-definition-paths.js +10 -0
- package/dist/workflows/migration/v2-definition-paths.js.map +1 -0
- package/dist/workflows/migration/v2-ledger.d.ts +138 -0
- package/dist/workflows/migration/v2-ledger.d.ts.map +1 -0
- package/dist/workflows/migration/v2-ledger.js +599 -0
- package/dist/workflows/migration/v2-ledger.js.map +1 -0
- package/dist/workflows/migration/v2-migration-service.d.ts +40 -0
- package/dist/workflows/migration/v2-migration-service.d.ts.map +1 -0
- package/dist/workflows/migration/v2-migration-service.js +454 -0
- package/dist/workflows/migration/v2-migration-service.js.map +1 -0
- package/dist/workflows/migration/v2-read-only-ids.d.ts +7 -0
- package/dist/workflows/migration/v2-read-only-ids.d.ts.map +1 -0
- package/dist/workflows/migration/v2-read-only-ids.js +9 -0
- package/dist/workflows/migration/v2-read-only-ids.js.map +1 -0
- package/dist/workflows/migration/v2-run-archive-schema.d.ts +976 -0
- package/dist/workflows/migration/v2-run-archive-schema.d.ts.map +1 -0
- package/dist/workflows/migration/v2-run-archive-schema.js +113 -0
- package/dist/workflows/migration/v2-run-archive-schema.js.map +1 -0
- package/dist/workflows/migration/v2-run-archive.d.ts +92 -0
- package/dist/workflows/migration/v2-run-archive.d.ts.map +1 -0
- package/dist/workflows/migration/v2-run-archive.js +1220 -0
- package/dist/workflows/migration/v2-run-archive.js.map +1 -0
- package/dist/workflows/migration/v2-scanner.d.ts +22 -0
- package/dist/workflows/migration/v2-scanner.d.ts.map +1 -0
- package/dist/workflows/migration/v2-scanner.js +114 -0
- package/dist/workflows/migration/v2-scanner.js.map +1 -0
- package/dist/workflows/migration/v2-to-v3.d.ts +32 -0
- package/dist/workflows/migration/v2-to-v3.d.ts.map +1 -0
- package/dist/workflows/migration/v2-to-v3.js +494 -0
- package/dist/workflows/migration/v2-to-v3.js.map +1 -0
- package/dist/workflows/ops-projection.d.ts.map +1 -1
- package/dist/workflows/ops-projection.js +4 -3
- package/dist/workflows/ops-projection.js.map +1 -1
- package/dist/workflows/shared/idempotency-key.d.ts +19 -0
- package/dist/workflows/shared/idempotency-key.d.ts.map +1 -0
- package/dist/workflows/shared/idempotency-key.js +23 -0
- package/dist/workflows/shared/idempotency-key.js.map +1 -0
- package/dist/workflows/{params.d.ts → shared/params.d.ts} +42 -6
- package/dist/workflows/shared/params.d.ts.map +1 -0
- package/dist/workflows/{params.js → shared/params.js} +91 -4
- package/dist/workflows/shared/params.js.map +1 -0
- package/dist/workflows/shared/provider-reconciler.d.ts +47 -0
- package/dist/workflows/shared/provider-reconciler.d.ts.map +1 -0
- package/dist/workflows/shared/provider-reconciler.js +17 -0
- package/dist/workflows/shared/provider-reconciler.js.map +1 -0
- package/dist/workflows/{spawn-policy.d.ts → shared/sandbox-policy.d.ts} +2 -2
- package/dist/workflows/shared/sandbox-policy.d.ts.map +1 -0
- package/dist/workflows/{spawn-policy.js → shared/sandbox-policy.js} +1 -1
- package/dist/workflows/shared/sandbox-policy.js.map +1 -0
- package/dist/workflows/shared/worker-process.d.ts +29 -0
- package/dist/workflows/shared/worker-process.d.ts.map +1 -0
- package/dist/workflows/shared/worker-process.js +56 -0
- package/dist/workflows/shared/worker-process.js.map +1 -0
- package/dist/workflows/v3/architect.d.ts.map +1 -1
- package/dist/workflows/v3/architect.js +16 -4
- package/dist/workflows/v3/architect.js.map +1 -1
- package/dist/workflows/v3/attempt-ledger.d.ts +23 -0
- package/dist/workflows/v3/attempt-ledger.d.ts.map +1 -0
- package/dist/workflows/v3/attempt-ledger.js +74 -0
- package/dist/workflows/v3/attempt-ledger.js.map +1 -0
- package/dist/workflows/v3/bot-resolve.d.ts +19 -1
- package/dist/workflows/v3/bot-resolve.d.ts.map +1 -1
- package/dist/workflows/v3/bot-resolve.js +129 -3
- package/dist/workflows/v3/bot-resolve.js.map +1 -1
- package/dist/workflows/v3/cli-daemon-command-authority.d.ts +59 -0
- package/dist/workflows/v3/cli-daemon-command-authority.d.ts.map +1 -0
- package/dist/workflows/v3/cli-daemon-command-authority.js +175 -0
- package/dist/workflows/v3/cli-daemon-command-authority.js.map +1 -0
- package/dist/workflows/v3/cli-run.d.ts +27 -0
- package/dist/workflows/v3/cli-run.d.ts.map +1 -1
- package/dist/workflows/v3/cli-run.js +113 -29
- package/dist/workflows/v3/cli-run.js.map +1 -1
- package/dist/workflows/v3/contract.d.ts +16 -16
- package/dist/workflows/v3/contract.d.ts.map +1 -1
- package/dist/workflows/v3/contract.js +15 -11
- package/dist/workflows/v3/contract.js.map +1 -1
- package/dist/workflows/v3/daemon-ipc-auth.d.ts +113 -0
- package/dist/workflows/v3/daemon-ipc-auth.d.ts.map +1 -0
- package/dist/workflows/v3/daemon-ipc-auth.js +294 -0
- package/dist/workflows/v3/daemon-ipc-auth.js.map +1 -0
- package/dist/workflows/v3/daemon-ipc-body.d.ts +30 -0
- package/dist/workflows/v3/daemon-ipc-body.d.ts.map +1 -0
- package/dist/workflows/v3/daemon-ipc-body.js +65 -0
- package/dist/workflows/v3/daemon-ipc-body.js.map +1 -0
- package/dist/workflows/v3/daemon-ipc-client.d.ts +32 -0
- package/dist/workflows/v3/daemon-ipc-client.d.ts.map +1 -0
- package/dist/workflows/v3/daemon-ipc-client.js +74 -0
- package/dist/workflows/v3/daemon-ipc-client.js.map +1 -0
- package/dist/workflows/v3/daemon-run.d.ts +87 -2
- package/dist/workflows/v3/daemon-run.d.ts.map +1 -1
- package/dist/workflows/v3/daemon-run.js +863 -68
- package/dist/workflows/v3/daemon-run.js.map +1 -1
- package/dist/workflows/v3/dag.d.ts +22 -8
- package/dist/workflows/v3/dag.d.ts.map +1 -1
- package/dist/workflows/v3/dag.js +214 -22
- package/dist/workflows/v3/dag.js.map +1 -1
- package/dist/workflows/v3/distillation-compiler.d.ts +36 -0
- package/dist/workflows/v3/distillation-compiler.d.ts.map +1 -0
- package/dist/workflows/v3/distillation-compiler.js +704 -0
- package/dist/workflows/v3/distillation-compiler.js.map +1 -0
- package/dist/workflows/v3/distillation-private-root.d.ts +10 -0
- package/dist/workflows/v3/distillation-private-root.d.ts.map +1 -0
- package/dist/workflows/v3/distillation-private-root.js +34 -0
- package/dist/workflows/v3/distillation-private-root.js.map +1 -0
- package/dist/workflows/v3/distillation-runner.d.ts +64 -0
- package/dist/workflows/v3/distillation-runner.d.ts.map +1 -0
- package/dist/workflows/v3/distillation-runner.js +1028 -0
- package/dist/workflows/v3/distillation-runner.js.map +1 -0
- package/dist/workflows/v3/distillation-schema.d.ts +63 -0
- package/dist/workflows/v3/distillation-schema.d.ts.map +1 -0
- package/dist/workflows/v3/distillation-schema.js +184 -0
- package/dist/workflows/v3/distillation-schema.js.map +1 -0
- package/dist/workflows/v3/distillation-service.d.ts +78 -0
- package/dist/workflows/v3/distillation-service.d.ts.map +1 -0
- package/dist/workflows/v3/distillation-service.js +416 -0
- package/dist/workflows/v3/distillation-service.js.map +1 -0
- package/dist/workflows/v3/distillation-source.d.ts +35 -0
- package/dist/workflows/v3/distillation-source.d.ts.map +1 -0
- package/dist/workflows/v3/distillation-source.js +118 -0
- package/dist/workflows/v3/distillation-source.js.map +1 -0
- package/dist/workflows/v3/distillation-store.d.ts +185 -0
- package/dist/workflows/v3/distillation-store.d.ts.map +1 -0
- package/dist/workflows/v3/distillation-store.js +1127 -0
- package/dist/workflows/v3/distillation-store.js.map +1 -0
- package/dist/workflows/v3/drive-lease.d.ts +7 -0
- package/dist/workflows/v3/drive-lease.d.ts.map +1 -0
- package/dist/workflows/v3/drive-lease.js +10 -0
- package/dist/workflows/v3/drive-lease.js.map +1 -0
- package/dist/workflows/v3/ephemeral-pool.d.ts +1 -1
- package/dist/workflows/v3/ephemeral-pool.d.ts.map +1 -1
- package/dist/workflows/v3/ephemeral-pool.js +222 -37
- package/dist/workflows/v3/ephemeral-pool.js.map +1 -1
- package/dist/workflows/v3/grill-state.d.ts +18 -3
- package/dist/workflows/v3/grill-state.d.ts.map +1 -1
- package/dist/workflows/v3/grill-state.js +22 -5
- package/dist/workflows/v3/grill-state.js.map +1 -1
- package/dist/workflows/v3/host-bindings.d.ts +40 -0
- package/dist/workflows/v3/host-bindings.d.ts.map +1 -0
- package/dist/workflows/v3/host-bindings.js +272 -0
- package/dist/workflows/v3/host-bindings.js.map +1 -0
- package/dist/workflows/v3/host-effect-ledger.d.ts +22 -0
- package/dist/workflows/v3/host-effect-ledger.d.ts.map +1 -0
- package/dist/workflows/v3/host-effect-ledger.js +110 -0
- package/dist/workflows/v3/host-effect-ledger.js.map +1 -0
- package/dist/workflows/v3/host-execution.d.ts +142 -0
- package/dist/workflows/v3/host-execution.d.ts.map +1 -0
- package/dist/workflows/v3/host-execution.js +424 -0
- package/dist/workflows/v3/host-execution.js.map +1 -0
- package/dist/workflows/v3/host.d.ts +46 -10
- package/dist/workflows/v3/host.d.ts.map +1 -1
- package/dist/workflows/v3/host.js +419 -140
- package/dist/workflows/v3/host.js.map +1 -1
- package/dist/workflows/v3/human-gate.d.ts +19 -1
- package/dist/workflows/v3/human-gate.d.ts.map +1 -1
- package/dist/workflows/v3/human-gate.js +145 -19
- package/dist/workflows/v3/human-gate.js.map +1 -1
- package/dist/workflows/v3/journal.d.ts +125 -7
- package/dist/workflows/v3/journal.d.ts.map +1 -1
- package/dist/workflows/v3/journal.js +154 -38
- package/dist/workflows/v3/journal.js.map +1 -1
- package/dist/workflows/v3/library-materialize.d.ts +88 -0
- package/dist/workflows/v3/library-materialize.d.ts.map +1 -0
- package/dist/workflows/v3/library-materialize.js +294 -0
- package/dist/workflows/v3/library-materialize.js.map +1 -0
- package/dist/workflows/v3/library-schema.d.ts +138 -0
- package/dist/workflows/v3/library-schema.d.ts.map +1 -0
- package/dist/workflows/v3/library-schema.js +573 -0
- package/dist/workflows/v3/library-schema.js.map +1 -0
- package/dist/workflows/v3/library-service.d.ts +126 -0
- package/dist/workflows/v3/library-service.d.ts.map +1 -0
- package/dist/workflows/v3/library-service.js +542 -0
- package/dist/workflows/v3/library-service.js.map +1 -0
- package/dist/workflows/v3/library-store.d.ts +124 -0
- package/dist/workflows/v3/library-store.d.ts.map +1 -0
- package/dist/workflows/v3/library-store.js +665 -0
- package/dist/workflows/v3/library-store.js.map +1 -0
- package/dist/workflows/v3/orchestrator.d.ts +9 -1
- package/dist/workflows/v3/orchestrator.d.ts.map +1 -1
- package/dist/workflows/v3/orchestrator.js +2 -1
- package/dist/workflows/v3/orchestrator.js.map +1 -1
- package/dist/workflows/v3/progress-projection.d.ts +99 -0
- package/dist/workflows/v3/progress-projection.d.ts.map +1 -0
- package/dist/workflows/v3/progress-projection.js +197 -0
- package/dist/workflows/v3/progress-projection.js.map +1 -0
- package/dist/workflows/v3/run-envelope.d.ts +1279 -0
- package/dist/workflows/v3/run-envelope.d.ts.map +1 -0
- package/dist/workflows/v3/run-envelope.js +681 -0
- package/dist/workflows/v3/run-envelope.js.map +1 -0
- package/dist/workflows/v3/runtime.d.ts +39 -7
- package/dist/workflows/v3/runtime.d.ts.map +1 -1
- package/dist/workflows/v3/runtime.js +1992 -100
- package/dist/workflows/v3/runtime.js.map +1 -1
- package/dist/workflows/v3/session-relay-client.d.ts +61 -0
- package/dist/workflows/v3/session-relay-client.d.ts.map +1 -0
- package/dist/workflows/v3/session-relay-client.js +92 -0
- package/dist/workflows/v3/session-relay-client.js.map +1 -0
- package/dist/workflows/v3/session-relay.d.ts +66 -0
- package/dist/workflows/v3/session-relay.d.ts.map +1 -0
- package/dist/workflows/v3/session-relay.js +157 -0
- package/dist/workflows/v3/session-relay.js.map +1 -0
- package/dist/workflows/v3/start-intent.d.ts +8 -0
- package/dist/workflows/v3/start-intent.d.ts.map +1 -0
- package/dist/workflows/v3/start-intent.js +34 -0
- package/dist/workflows/v3/start-intent.js.map +1 -0
- package/dist/workflows/v3/state.d.ts +11 -2
- package/dist/workflows/v3/state.d.ts.map +1 -1
- package/dist/workflows/v3/state.js +182 -10
- package/dist/workflows/v3/state.js.map +1 -1
- package/dist/workflows/v3/template-bindings.d.ts +22 -0
- package/dist/workflows/v3/template-bindings.d.ts.map +1 -0
- package/dist/workflows/v3/template-bindings.js +204 -0
- package/dist/workflows/v3/template-bindings.js.map +1 -0
- package/dist/workflows/v3/worker-fence.d.ts +158 -0
- package/dist/workflows/v3/worker-fence.d.ts.map +1 -0
- package/dist/workflows/v3/worker-fence.js +685 -0
- package/dist/workflows/v3/worker-fence.js.map +1 -0
- package/package.json +3 -2
- package/dist/core/dashboard-command/workflows.d.ts +0 -20
- package/dist/core/dashboard-command/workflows.d.ts.map +0 -1
- package/dist/core/dashboard-command/workflows.js +0 -45
- package/dist/core/dashboard-command/workflows.js.map +0 -1
- package/dist/dashboard/web/legacy-workflow-link.d.ts +0 -2
- package/dist/dashboard/web/legacy-workflow-link.d.ts.map +0 -1
- package/dist/dashboard/web/legacy-workflow-link.js +0 -12
- package/dist/dashboard/web/legacy-workflow-link.js.map +0 -1
- package/dist/dashboard/web/legacy-workflow-page.d.ts +0 -3
- package/dist/dashboard/web/legacy-workflow-page.d.ts.map +0 -1
- package/dist/dashboard/web/legacy-workflow-page.js +0 -717
- package/dist/dashboard/web/legacy-workflow-page.js.map +0 -1
- package/dist/dashboard/web/workflow-version-switch.d.ts +0 -8
- package/dist/dashboard/web/workflow-version-switch.d.ts.map +0 -1
- package/dist/dashboard/web/workflow-version-switch.js +0 -9
- package/dist/dashboard/web/workflow-version-switch.js.map +0 -1
- package/dist/dashboard/web/workflows.d.ts +0 -273
- package/dist/dashboard/web/workflows.d.ts.map +0 -1
- package/dist/dashboard/web/workflows.js +0 -436
- package/dist/dashboard/web/workflows.js.map +0 -1
- package/dist/dashboard/workflow-api.d.ts +0 -30
- package/dist/dashboard/workflow-api.d.ts.map +0 -1
- package/dist/dashboard/workflow-api.js +0 -397
- package/dist/dashboard/workflow-api.js.map +0 -1
- package/dist/dashboard/workflow-card-model.d.ts +0 -127
- package/dist/dashboard/workflow-card-model.d.ts.map +0 -1
- package/dist/dashboard/workflow-card-model.js +0 -186
- package/dist/dashboard/workflow-card-model.js.map +0 -1
- package/dist/dashboard/workflows-action-helpers.d.ts +0 -105
- package/dist/dashboard/workflows-action-helpers.d.ts.map +0 -1
- package/dist/dashboard/workflows-action-helpers.js +0 -196
- package/dist/dashboard/workflows-action-helpers.js.map +0 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-7T7DPOV6.js +0 -4
- package/dist/dashboard-web/chunks/chunk-IGXYYRYJ.js +0 -1
- package/dist/dashboard-web/chunks/chunk-ISOD7VDX.js +0 -1
- package/dist/dashboard-web/chunks/chunk-PNK3HQBI.js +0 -37
- package/dist/dashboard-web/chunks/chunk-SRIE4MLQ.js +0 -1
- package/dist/dashboard-web/chunks/connectors-page-UQ4QBE45.js +0 -1
- package/dist/dashboard-web/chunks/legacy-workflow-page-QMC7OZXH.js +0 -2
- package/dist/dashboard-web/chunks/sessions-page-NNZIDHZM.js +0 -3
- package/dist/dashboard-web/chunks/settings-page-LJIXX5LQ.js +0 -2
- package/dist/dashboard-web/chunks/v3-page-YLYVHGKD.js +0 -94
- package/dist/dashboard-web/terminal-replay.html +0 -227
- package/dist/im/lark/workflow-card-handler.d.ts +0 -51
- package/dist/im/lark/workflow-card-handler.d.ts.map +0 -1
- package/dist/im/lark/workflow-card-handler.js +0 -163
- package/dist/im/lark/workflow-card-handler.js.map +0 -1
- package/dist/im/lark/workflow-cards.d.ts +0 -47
- package/dist/im/lark/workflow-cards.d.ts.map +0 -1
- package/dist/im/lark/workflow-cards.js +0 -231
- package/dist/im/lark/workflow-cards.js.map +0 -1
- package/dist/im/lark/workflow-progress-card.d.ts +0 -81
- package/dist/im/lark/workflow-progress-card.d.ts.map +0 -1
- package/dist/im/lark/workflow-progress-card.js +0 -336
- package/dist/im/lark/workflow-progress-card.js.map +0 -1
- package/dist/im/lark/workflows-card.d.ts +0 -102
- package/dist/im/lark/workflows-card.d.ts.map +0 -1
- package/dist/im/lark/workflows-card.js +0 -737
- package/dist/im/lark/workflows-card.js.map +0 -1
- package/dist/workflows/attempt-resume.d.ts +0 -119
- package/dist/workflows/attempt-resume.d.ts.map +0 -1
- package/dist/workflows/attempt-resume.js +0 -392
- package/dist/workflows/attempt-resume.js.map +0 -1
- package/dist/workflows/blob.d.ts +0 -27
- package/dist/workflows/blob.d.ts.map +0 -1
- package/dist/workflows/blob.js +0 -40
- package/dist/workflows/blob.js.map +0 -1
- package/dist/workflows/cancel-run.d.ts +0 -45
- package/dist/workflows/cancel-run.d.ts.map +0 -1
- package/dist/workflows/cancel-run.js +0 -99
- package/dist/workflows/cancel-run.js.map +0 -1
- package/dist/workflows/cancel.d.ts +0 -111
- package/dist/workflows/cancel.d.ts.map +0 -1
- package/dist/workflows/cancel.js +0 -120
- package/dist/workflows/cancel.js.map +0 -1
- package/dist/workflows/catalog.d.ts +0 -60
- package/dist/workflows/catalog.d.ts.map +0 -1
- package/dist/workflows/catalog.js +0 -119
- package/dist/workflows/catalog.js.map +0 -1
- package/dist/workflows/cold-attach.d.ts +0 -30
- package/dist/workflows/cold-attach.d.ts.map +0 -1
- package/dist/workflows/cold-attach.js +0 -40
- package/dist/workflows/cold-attach.js.map +0 -1
- package/dist/workflows/cold-scan.d.ts +0 -21
- package/dist/workflows/cold-scan.d.ts.map +0 -1
- package/dist/workflows/cold-scan.js +0 -70
- package/dist/workflows/cold-scan.js.map +0 -1
- package/dist/workflows/daemon-spawn.d.ts +0 -119
- package/dist/workflows/daemon-spawn.d.ts.map +0 -1
- package/dist/workflows/daemon-spawn.js +0 -564
- package/dist/workflows/daemon-spawn.js.map +0 -1
- package/dist/workflows/effect-input.d.ts +0 -4
- package/dist/workflows/effect-input.d.ts.map +0 -1
- package/dist/workflows/effect-input.js +0 -19
- package/dist/workflows/effect-input.js.map +0 -1
- package/dist/workflows/events/append.d.ts +0 -77
- package/dist/workflows/events/append.d.ts.map +0 -1
- package/dist/workflows/events/append.js +0 -214
- package/dist/workflows/events/append.js.map +0 -1
- package/dist/workflows/events/idempotency.d.ts +0 -77
- package/dist/workflows/events/idempotency.d.ts.map +0 -1
- package/dist/workflows/events/idempotency.js +0 -116
- package/dist/workflows/events/idempotency.js.map +0 -1
- package/dist/workflows/events/index.d.ts +0 -7
- package/dist/workflows/events/index.d.ts.map +0 -1
- package/dist/workflows/events/index.js +0 -7
- package/dist/workflows/events/index.js.map +0 -1
- package/dist/workflows/fanout.d.ts +0 -36
- package/dist/workflows/fanout.d.ts.map +0 -1
- package/dist/workflows/fanout.js +0 -115
- package/dist/workflows/fanout.js.map +0 -1
- package/dist/workflows/hostExecutors/protocol.d.ts +0 -42
- package/dist/workflows/hostExecutors/protocol.d.ts.map +0 -1
- package/dist/workflows/hostExecutors/protocol.js +0 -181
- package/dist/workflows/hostExecutors/protocol.js.map +0 -1
- package/dist/workflows/loader.d.ts +0 -30
- package/dist/workflows/loader.d.ts.map +0 -1
- package/dist/workflows/loader.js +0 -84
- package/dist/workflows/loader.js.map +0 -1
- package/dist/workflows/loop.d.ts +0 -50
- package/dist/workflows/loop.d.ts.map +0 -1
- package/dist/workflows/loop.js +0 -408
- package/dist/workflows/loop.js.map +0 -1
- package/dist/workflows/orchestrator.d.ts +0 -171
- package/dist/workflows/orchestrator.d.ts.map +0 -1
- package/dist/workflows/orchestrator.js +0 -609
- package/dist/workflows/orchestrator.js.map +0 -1
- package/dist/workflows/output-binding.d.ts +0 -77
- package/dist/workflows/output-binding.d.ts.map +0 -1
- package/dist/workflows/output-binding.js +0 -329
- package/dist/workflows/output-binding.js.map +0 -1
- package/dist/workflows/params.d.ts.map +0 -1
- package/dist/workflows/params.js.map +0 -1
- package/dist/workflows/resume.d.ts +0 -263
- package/dist/workflows/resume.d.ts.map +0 -1
- package/dist/workflows/resume.js +0 -808
- package/dist/workflows/resume.js.map +0 -1
- package/dist/workflows/run-id.d.ts +0 -2
- package/dist/workflows/run-id.d.ts.map +0 -1
- package/dist/workflows/run-id.js +0 -7
- package/dist/workflows/run-id.js.map +0 -1
- package/dist/workflows/run-init.d.ts +0 -48
- package/dist/workflows/run-init.d.ts.map +0 -1
- package/dist/workflows/run-init.js +0 -100
- package/dist/workflows/run-init.js.map +0 -1
- package/dist/workflows/runs-dir.d.ts +0 -4
- package/dist/workflows/runs-dir.d.ts.map +0 -1
- package/dist/workflows/runs-dir.js +0 -15
- package/dist/workflows/runs-dir.js.map +0 -1
- package/dist/workflows/runtime.d.ts +0 -215
- package/dist/workflows/runtime.d.ts.map +0 -1
- package/dist/workflows/runtime.js +0 -630
- package/dist/workflows/runtime.js.map +0 -1
- package/dist/workflows/spawn-bot.d.ts +0 -165
- package/dist/workflows/spawn-bot.d.ts.map +0 -1
- package/dist/workflows/spawn-bot.js +0 -215
- package/dist/workflows/spawn-bot.js.map +0 -1
- package/dist/workflows/spawn-policy.d.ts.map +0 -1
- package/dist/workflows/spawn-policy.js.map +0 -1
- package/dist/workflows/system.d.ts +0 -49
- package/dist/workflows/system.d.ts.map +0 -1
- package/dist/workflows/system.js +0 -48
- package/dist/workflows/system.js.map +0 -1
- package/dist/workflows/trigger-from-envelope.d.ts +0 -13
- package/dist/workflows/trigger-from-envelope.d.ts.map +0 -1
- package/dist/workflows/trigger-from-envelope.js +0 -68
- package/dist/workflows/trigger-from-envelope.js.map +0 -1
- package/dist/workflows/trigger-run.d.ts +0 -70
- package/dist/workflows/trigger-run.d.ts.map +0 -1
- package/dist/workflows/trigger-run.js +0 -88
- package/dist/workflows/trigger-run.js.map +0 -1
- package/dist/workflows/wait.d.ts +0 -141
- package/dist/workflows/wait.d.ts.map +0 -1
- package/dist/workflows/wait.js +0 -203
- package/dist/workflows/wait.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
* Usage:
|
|
6
6
|
* botmux setup — interactive first-time configuration
|
|
7
7
|
* botmux setup --no-open-platform-auto — skip Feishu Open Platform automation
|
|
8
|
-
* botmux setup list|add|edit|remove — scripted (non-TUI) bot management, see `botmux setup help`
|
|
8
|
+
* botmux setup list|add|configure|edit|remove — scripted (non-TUI) bot management, see `botmux setup help`
|
|
9
9
|
* botmux start — start daemon and auto plugin services
|
|
10
10
|
* botmux stop [--with-plugin] — stop daemon (optionally stop auto plugin services)
|
|
11
11
|
* botmux restart [--include-pm2] [--with-plugin] — restart daemon, then ensure auto plugin services
|
|
12
12
|
* botmux logs [--lines] — view daemon logs
|
|
13
13
|
* botmux status — show daemon status
|
|
14
|
-
* botmux upgrade
|
|
14
|
+
* botmux upgrade|update — upgrade to latest version
|
|
15
15
|
* botmux list — interactive session picker (TUI), attach to tmux
|
|
16
16
|
* botmux list --plain — plain table output (for piping / scripts)
|
|
17
17
|
* botmux delete <id> — close a session by ID prefix
|
|
@@ -27,9 +27,11 @@ import { homedir } from 'node:os';
|
|
|
27
27
|
import { fileURLToPath } from 'node:url';
|
|
28
28
|
import { createInterface } from 'node:readline';
|
|
29
29
|
import { createRequire } from 'node:module';
|
|
30
|
-
import {
|
|
30
|
+
import { randomBytes } from 'node:crypto';
|
|
31
31
|
import { validateWorkingDir } from './core/working-dir.js';
|
|
32
32
|
import { resolveSessionContext } from './core/session-marker.js';
|
|
33
|
+
import { resolveBotmuxDataDir } from './core/data-dir.js';
|
|
34
|
+
import { dashboardSecretPath } from './core/dashboard-secret.js';
|
|
33
35
|
import { parseDispatchBotSpec, buildDispatchMessages, buildRepoPrimeText, buildReportContent, eligibleAutoMentionAliases, offTopicSubBotTopic, resolveReportTarget, resolveSendTarget } from './core/dispatch.js';
|
|
34
36
|
import { enableAutostart, disableAutostart, autostartStatus, refreshAutostart } from './autostart.js';
|
|
35
37
|
import { tmuxEnv } from './setup/ensure-tmux.js';
|
|
@@ -38,6 +40,7 @@ import { applyBotConfigEdits, assertUniqueBotProcessNames, botProcessName, norma
|
|
|
38
40
|
import { resolveCliSelection, selectionKeyForBot } from './setup/cli-selection.js';
|
|
39
41
|
import { checkCliAvailability, hasAgentLaunchConfigChanged } from './setup/cli-availability.js';
|
|
40
42
|
import { resolveSetupAppName } from './setup/app-name.js';
|
|
43
|
+
import { blocksSetupBotStart, classifySetupOpenPlatformOutcome, scriptedSetupOpenPlatformReuseOnly, setupOpenPlatformOutcomeJson, setupOpenPlatformRetryCommand, } from './setup/open-platform-outcome.js';
|
|
41
44
|
import { buildBotFromAddFlags, editInputFromFlags, isScriptedSetupInvocation, maskAppSecret, parseSetupCommand, SETUP_CLI_USAGE, } from './setup/setup-args.js';
|
|
42
45
|
import { interactiveSelect, pickChoice, pickCliSelection } from './setup/interactive-select.js';
|
|
43
46
|
import { buildPreset, serializePreset, presetFilename } from './setup/agent-preset.js';
|
|
@@ -52,6 +55,10 @@ import { callDashboard } from './cli/dashboard-endpoint.js';
|
|
|
52
55
|
import { installLatestBotmuxSync } from './core/maintenance.js';
|
|
53
56
|
import { formatGlobalInstallCommand, resolveGlobalInstallPlan, UnsupportedGlobalInstallError, } from './utils/global-install.js';
|
|
54
57
|
import { loadDashboardSecret } from './dashboard/auth.js';
|
|
58
|
+
import { postWorkflowDaemonMutation, } from './workflows/v3/daemon-ipc-client.js';
|
|
59
|
+
import { postWorkflowSessionRunMutation, readWorkflowSessionRelayContext, } from './workflows/v3/session-relay-client.js';
|
|
60
|
+
import { fetchDaemonIpc, loadDaemonIpcSecret } from './core/daemon-ipc-auth.js';
|
|
61
|
+
import { readManagedOriginCapability } from './core/managed-origin-capability.js';
|
|
55
62
|
import { rejectLikelyWindowsStdinMojibake, decodeStdinBytes } from './cli/stdin-encoding.js';
|
|
56
63
|
import { formatBotInfoEntriesForCli, formatChatBotsForCli, } from './cli/bots-list-output.js';
|
|
57
64
|
import { buildFooterAddressing, hasKnownBotMention, knownBotOpenIdsFromCrossRef, orderedFooterRecipients, stripCodeSpans, } from './utils/bot-routing.js';
|
|
@@ -62,9 +69,13 @@ import { createWhiteboard, ensureDefaultWhiteboard, getWhiteboard, listWhiteboar
|
|
|
62
69
|
import { buildBridgeSendMarkerContent } from './services/bridge-fallback-gate.js';
|
|
63
70
|
import { writeManualIntentIfAbsentTo } from './services/restart-intent-store.js';
|
|
64
71
|
import { stripLegacyPendingCardFields } from './services/session-store.js';
|
|
72
|
+
import { evaluateVcMeetingManagedSend, isTrustedVcMeetingHostRelayParent, resolveVcMeetingImTurnOrigin, } from './services/vc-meeting-send-policy.js';
|
|
73
|
+
import { finishVcMeetingImReply, prepareVcMeetingDeliveryReply, prepareVcMeetingImReply, } from './services/vc-meeting-im-reply.js';
|
|
74
|
+
import { recordVcMeetingListenerMessage } from './services/vc-meeting-listener-message-store.js';
|
|
65
75
|
import { isValidPluginId, normalizePluginIdList } from './core/plugins/ids.js';
|
|
66
76
|
import { resolveEffectivePluginIds, updateBotPluginOverride } from './core/plugins/effective.js';
|
|
67
77
|
import { assertPluginBindingTransition, describePluginDependencyError, enabledPluginDependents, } from './core/plugins/dependencies.js';
|
|
78
|
+
import { authorizeV3DaemonCommand } from './workflows/v3/cli-daemon-command-authority.js';
|
|
68
79
|
// Resolve the CLI's UI locale once from the global config file, so subsequent
|
|
69
80
|
// CLI output (and any t() callers that don't pass an explicit locale) honour
|
|
70
81
|
// the user's chosen language. Daemon entrypoint sets this separately for the
|
|
@@ -521,19 +532,23 @@ async function finishOpenPlatformSetup(appId, brand, options = {}) {
|
|
|
521
532
|
say('\n已跳过开放平台自动配置 (--no-open-platform-auto)。');
|
|
522
533
|
if (!options.quiet)
|
|
523
534
|
printRemainingSteps(appId, brand);
|
|
524
|
-
return;
|
|
535
|
+
return { status: 'skipped' };
|
|
525
536
|
}
|
|
526
537
|
say('\n── 开放平台自动配置 ──\n');
|
|
527
|
-
say(options.
|
|
528
|
-
? '
|
|
529
|
-
:
|
|
538
|
+
say(options.forceQrLogin
|
|
539
|
+
? '将按 --switch-account 明确重新扫码,自动导入权限、配置 redirect URL 并创建/发布版本。'
|
|
540
|
+
: options.reuseOnly
|
|
541
|
+
? '将复用创建应用时的 Feishu Web session,自动导入权限、配置 redirect URL 并创建/发布版本;本路径不会再显示二维码。'
|
|
542
|
+
: '将获取或复用 Feishu Web session,自动导入权限、配置 redirect URL 并创建/发布版本。');
|
|
530
543
|
say('如失败会自动回退到手动步骤提示,不影响已写入的 botmux 配置。\n');
|
|
531
544
|
const result = await automateOpenPlatformSetup({
|
|
532
545
|
appId,
|
|
533
546
|
brand,
|
|
547
|
+
forceQrLogin: options.forceQrLogin,
|
|
534
548
|
disableQrLogin: options.reuseOnly,
|
|
535
|
-
disableBytedcliFallback: options.reuseOnly,
|
|
549
|
+
disableBytedcliFallback: options.reuseOnly || options.forceQrLogin,
|
|
536
550
|
});
|
|
551
|
+
const outcome = classifySetupOpenPlatformOutcome(result);
|
|
537
552
|
if (result.ok) {
|
|
538
553
|
say('✅ 开放平台自动配置完成');
|
|
539
554
|
say(` Session 来源: ${result.sessionSource}`);
|
|
@@ -552,14 +567,15 @@ async function finishOpenPlatformSetup(appId, brand, options = {}) {
|
|
|
552
567
|
else
|
|
553
568
|
say(' 已创建版本;未从响应中解析到 versionId,请到开放平台确认是否需要手动发布。');
|
|
554
569
|
say('');
|
|
555
|
-
return;
|
|
570
|
+
return outcome;
|
|
556
571
|
}
|
|
557
|
-
say(
|
|
572
|
+
say(`${outcome.status === 'manual' ? 'ℹ️ ' : '⚠️ '} 开放平台自动配置${outcome.status === 'manual' ? '需要手动完成' : '失败'} (${result.reason}): ${result.message}`);
|
|
558
573
|
if (result.sessionFile)
|
|
559
574
|
say(` botmux session 文件: ${result.sessionFile}`);
|
|
560
575
|
say(' 请按下面的手动步骤继续完成开放平台配置。');
|
|
561
576
|
if (!options.quiet)
|
|
562
577
|
printRemainingSteps(appId, brand);
|
|
578
|
+
return outcome;
|
|
563
579
|
}
|
|
564
580
|
/**
|
|
565
581
|
* 「选择已有应用」路径:复用/扫码飞书 Web 登录态 → 拉当前账号可见的自建应用
|
|
@@ -1265,7 +1281,7 @@ function botJsonView(bot, index) {
|
|
|
1265
1281
|
};
|
|
1266
1282
|
}
|
|
1267
1283
|
/**
|
|
1268
|
-
* `botmux setup list|add|edit|remove` — 脚本化(非 TUI)bot 管理。
|
|
1284
|
+
* `botmux setup list|add|configure|edit|remove` — 脚本化(非 TUI)bot 管理。
|
|
1269
1285
|
* 给 coding agent / 脚本一个字段级稳定接口,不依赖交互问答顺序(管道喂数字
|
|
1270
1286
|
* 的老姿势在问题序列变化时会静默错位)。校验口径与 TUI 一致:目录存在性、
|
|
1271
1287
|
* owner 必填、凭证变更时的 tenant_access_token 校验,任一失败不写盘。
|
|
@@ -1299,6 +1315,60 @@ async function cmdSetupScripted(argv) {
|
|
|
1299
1315
|
}
|
|
1300
1316
|
return;
|
|
1301
1317
|
}
|
|
1318
|
+
if (cmd.action === 'configure') {
|
|
1319
|
+
const index = parseBotSelection(cmd.selector, bots);
|
|
1320
|
+
if (index === undefined) {
|
|
1321
|
+
failSetupScripted(cmd.json, `找不到机器人 "${cmd.selector}"(接受进程名 botmux-N 或 AppID,botmux setup list 可查)。`);
|
|
1322
|
+
return;
|
|
1323
|
+
}
|
|
1324
|
+
const bot = bots[index];
|
|
1325
|
+
const processName = botProcessName(bot, index, PM2_NAME);
|
|
1326
|
+
const openPlatform = await finishOpenPlatformSetup(bot.larkAppId, botBrand(bot), {
|
|
1327
|
+
// Machine-readable callers must never be surprised by an interactive QR.
|
|
1328
|
+
reuseOnly: cmd.json && !cmd.switchAccount,
|
|
1329
|
+
forceQrLogin: cmd.switchAccount,
|
|
1330
|
+
quiet: cmd.json,
|
|
1331
|
+
});
|
|
1332
|
+
if (openPlatform.status === 'failed' || openPlatform.status === 'manual') {
|
|
1333
|
+
const continueCommand = setupOpenPlatformRetryCommand(bot.larkAppId, openPlatform);
|
|
1334
|
+
const next = continueCommand ?? 'manual_open_platform_setup';
|
|
1335
|
+
failSetupScripted(cmd.json, openPlatform.status === 'manual'
|
|
1336
|
+
? '该租户不支持自动配置,请按开放平台手动步骤完成。'
|
|
1337
|
+
: `开放平台自动配置未完成;机器人配置保留,未自动上线。请修复后重试 ${continueCommand}。`, {
|
|
1338
|
+
partial: true,
|
|
1339
|
+
action: 'configure',
|
|
1340
|
+
bot: botJsonView(bot, index),
|
|
1341
|
+
appId: bot.larkAppId,
|
|
1342
|
+
openPlatform: setupOpenPlatformOutcomeJson(openPlatform),
|
|
1343
|
+
...(continueCommand ? { continueCommand } : {}),
|
|
1344
|
+
next,
|
|
1345
|
+
});
|
|
1346
|
+
return;
|
|
1347
|
+
}
|
|
1348
|
+
const live = ensureBotDaemonStarted(bot.larkAppId, { quiet: cmd.json });
|
|
1349
|
+
const next = live.ok ? 'live' : (live.reason === 'fleet_down' ? 'botmux start' : 'botmux restart');
|
|
1350
|
+
if (cmd.json) {
|
|
1351
|
+
console.log(JSON.stringify({
|
|
1352
|
+
ok: true,
|
|
1353
|
+
action: 'configure',
|
|
1354
|
+
bot: botJsonView(bot, index),
|
|
1355
|
+
appId: bot.larkAppId,
|
|
1356
|
+
openPlatform: setupOpenPlatformOutcomeJson(openPlatform),
|
|
1357
|
+
live,
|
|
1358
|
+
next,
|
|
1359
|
+
}, null, 2));
|
|
1360
|
+
}
|
|
1361
|
+
else {
|
|
1362
|
+
console.log(`✅ 已完成 ${processName} (${bot.larkAppId}) 的开放平台配置`);
|
|
1363
|
+
if (live.ok)
|
|
1364
|
+
console.log(`✅ 已自动上线(${live.processName})`);
|
|
1365
|
+
else if (live.reason === 'fleet_down')
|
|
1366
|
+
console.log('下一步: botmux start(daemon 尚未运行)');
|
|
1367
|
+
else
|
|
1368
|
+
console.log(`⚠️ 自动上线失败(${live.message})。下一步: botmux restart`);
|
|
1369
|
+
}
|
|
1370
|
+
return;
|
|
1371
|
+
}
|
|
1302
1372
|
if (cmd.action === 'add') {
|
|
1303
1373
|
// 单机器人 .env 老配置:与 TUI「添加新机器人」一致,先迁移进 bots.json 再追加。
|
|
1304
1374
|
let existing = bots;
|
|
@@ -1487,13 +1557,40 @@ async function cmdSetupScripted(argv) {
|
|
|
1487
1557
|
}
|
|
1488
1558
|
}
|
|
1489
1559
|
// 已有凭证模式默认跳过;--create-app 默认开启并复用刚才的 Web session。
|
|
1560
|
+
let openPlatform = { status: 'skipped' };
|
|
1490
1561
|
if (cmd.openPlatformAuto) {
|
|
1491
|
-
await finishOpenPlatformSetup(bot.larkAppId, botBrand(bot), {
|
|
1492
|
-
reuseOnly:
|
|
1562
|
+
openPlatform = await finishOpenPlatformSetup(bot.larkAppId, botBrand(bot), {
|
|
1563
|
+
reuseOnly: scriptedSetupOpenPlatformReuseOnly({
|
|
1564
|
+
json: cmd.json,
|
|
1565
|
+
createApp: cmd.createApp,
|
|
1566
|
+
compatibilityMode: cmd.compatibilityMode,
|
|
1567
|
+
brand: botBrand(bot),
|
|
1568
|
+
}),
|
|
1493
1569
|
quiet: cmd.json,
|
|
1494
1570
|
});
|
|
1495
1571
|
}
|
|
1496
1572
|
const index = existing.length;
|
|
1573
|
+
if (blocksSetupBotStart(openPlatform)) {
|
|
1574
|
+
const continueCommand = setupOpenPlatformRetryCommand(bot.larkAppId, openPlatform);
|
|
1575
|
+
failSetupScripted(cmd.json, `机器人配置已写入,但开放平台自动配置未完成,未自动上线。修复后运行 ${continueCommand};不会重复创建应用。`, {
|
|
1576
|
+
partial: true,
|
|
1577
|
+
action: 'add',
|
|
1578
|
+
bot: botJsonView(bot, index),
|
|
1579
|
+
appId: bot.larkAppId,
|
|
1580
|
+
...(createdAppName ? { appName: createdAppName } : {}),
|
|
1581
|
+
botsFile: BOTS_JSON_FILE,
|
|
1582
|
+
envMigrated: migratedEnv || undefined,
|
|
1583
|
+
openPlatform: setupOpenPlatformOutcomeJson(openPlatform),
|
|
1584
|
+
continueCommand,
|
|
1585
|
+
live: {
|
|
1586
|
+
ok: false,
|
|
1587
|
+
reason: 'open_platform_incomplete',
|
|
1588
|
+
message: '开放平台关键配置未完成,未启动新机器人',
|
|
1589
|
+
},
|
|
1590
|
+
next: continueCommand,
|
|
1591
|
+
});
|
|
1592
|
+
return;
|
|
1593
|
+
}
|
|
1497
1594
|
// daemon 在跑就直接把新 bot 那一个进程拉起来,免整组 botmux restart。
|
|
1498
1595
|
const live = ensureBotDaemonStarted(bot.larkAppId, { quiet: cmd.json });
|
|
1499
1596
|
const next = live.ok ? 'live' : (live.reason === 'fleet_down' ? 'botmux start' : 'botmux restart');
|
|
@@ -1506,7 +1603,7 @@ async function cmdSetupScripted(argv) {
|
|
|
1506
1603
|
...(cmd.createApp && botBrand(bot) === 'feishu' && !cmd.compatibilityMode ? { appName: resolveSetupAppName(cmd.flags.appName, index) } : {}),
|
|
1507
1604
|
botsFile: BOTS_JSON_FILE,
|
|
1508
1605
|
envMigrated: migratedEnv || undefined,
|
|
1509
|
-
openPlatform:
|
|
1606
|
+
openPlatform: setupOpenPlatformOutcomeJson(openPlatform),
|
|
1510
1607
|
live,
|
|
1511
1608
|
next,
|
|
1512
1609
|
}, null, 2));
|
|
@@ -2021,7 +2118,7 @@ async function cmdStart() {
|
|
|
2021
2118
|
* the pm2 zombie-cleanup flow so the dashboard registry stays consistent.
|
|
2022
2119
|
*/
|
|
2023
2120
|
function cleanupStaleDaemonDescriptors() {
|
|
2024
|
-
const regDir = join(
|
|
2121
|
+
const regDir = join(resolveDataDir(), 'dashboard-daemons');
|
|
2025
2122
|
if (!existsSync(regDir))
|
|
2026
2123
|
return;
|
|
2027
2124
|
for (const f of readdirSync(regDir)) {
|
|
@@ -2598,28 +2695,7 @@ async function cmdDashboard() {
|
|
|
2598
2695
|
* Priority: SESSION_DATA_DIR env > daemon breadcrumb (~/.botmux/.data-dir) > default (~/.botmux/data)
|
|
2599
2696
|
*/
|
|
2600
2697
|
function resolveDataDir() {
|
|
2601
|
-
|
|
2602
|
-
return process.env.SESSION_DATA_DIR;
|
|
2603
|
-
// Read breadcrumb written by the daemon at startup
|
|
2604
|
-
const breadcrumb = join(CONFIG_DIR, '.data-dir');
|
|
2605
|
-
if (existsSync(breadcrumb)) {
|
|
2606
|
-
try {
|
|
2607
|
-
const dir = readFileSync(breadcrumb, 'utf-8').trim();
|
|
2608
|
-
if (dir && existsSync(dir)) {
|
|
2609
|
-
// Check for any session file (legacy or per-bot)
|
|
2610
|
-
if (existsSync(join(dir, 'sessions.json')))
|
|
2611
|
-
return dir;
|
|
2612
|
-
try {
|
|
2613
|
-
const files = readdirSync(dir);
|
|
2614
|
-
if (files.some(f => f.startsWith('sessions-') && f.endsWith('.json')))
|
|
2615
|
-
return dir;
|
|
2616
|
-
}
|
|
2617
|
-
catch { /* ignore */ }
|
|
2618
|
-
}
|
|
2619
|
-
}
|
|
2620
|
-
catch { /* ignore */ }
|
|
2621
|
-
}
|
|
2622
|
-
return DATA_DIR;
|
|
2698
|
+
return resolveBotmuxDataDir();
|
|
2623
2699
|
}
|
|
2624
2700
|
/** Load sessions from all session files (legacy + per-bot). */
|
|
2625
2701
|
function loadSessions() {
|
|
@@ -3393,7 +3469,7 @@ async function cmdSuspend() {
|
|
|
3393
3469
|
continue;
|
|
3394
3470
|
}
|
|
3395
3471
|
try {
|
|
3396
|
-
const res = await
|
|
3472
|
+
const res = await fetchDaemonIpc(daemon.ipcPort, `/api/sessions/${encodeURIComponent(s.sessionId)}/suspend`, { method: 'POST' });
|
|
3397
3473
|
const body = await res.json().catch(() => ({}));
|
|
3398
3474
|
if (res.ok && body?.ok) {
|
|
3399
3475
|
if (body.suspended) {
|
|
@@ -3424,6 +3500,120 @@ async function cmdSuspend() {
|
|
|
3424
3500
|
if (failed > 0)
|
|
3425
3501
|
process.exitCode = 1;
|
|
3426
3502
|
}
|
|
3503
|
+
/** 会话级 CLI IPC(slash/cd)的 POST:与 postAsk 同款双路径——能读 host secret
|
|
3504
|
+
* (非隔离进程)走 trusted-host HMAC 签名;读不到(沙箱 BOTMUX_SEND_RELAY /
|
|
3505
|
+
* macOS 读隔离 carve-out)改带本会话当前轮换的 origin capability,由 daemon
|
|
3506
|
+
* handler 与活跃记录比对。两条路都不读 bots.json。 */
|
|
3507
|
+
async function postSessionCliIpc(ipcPort, sessionId, route, payload) {
|
|
3508
|
+
const requestBody = { ...payload };
|
|
3509
|
+
let hostSecret;
|
|
3510
|
+
if (!process.env.BOTMUX_SEND_RELAY) {
|
|
3511
|
+
try {
|
|
3512
|
+
hostSecret = loadDaemonIpcSecret();
|
|
3513
|
+
}
|
|
3514
|
+
catch { /* sandboxed/read-isolated: capability fallback below */ }
|
|
3515
|
+
}
|
|
3516
|
+
if (!hostSecret) {
|
|
3517
|
+
const claim = readManagedOriginCapability(resolveDataDir(), sessionId, process.env.BOTMUX_SEND_RELAY);
|
|
3518
|
+
if (claim) {
|
|
3519
|
+
requestBody.originCapability = claim.capability;
|
|
3520
|
+
if (claim.turnId)
|
|
3521
|
+
requestBody.originTurnId = claim.turnId;
|
|
3522
|
+
if (claim.dispatchAttempt !== undefined)
|
|
3523
|
+
requestBody.originDispatchAttempt = claim.dispatchAttempt;
|
|
3524
|
+
}
|
|
3525
|
+
}
|
|
3526
|
+
const path = `/api/sessions/${encodeURIComponent(sessionId)}/${route}`;
|
|
3527
|
+
const init = {
|
|
3528
|
+
method: 'POST',
|
|
3529
|
+
headers: { 'content-type': 'application/json' },
|
|
3530
|
+
body: JSON.stringify(requestBody),
|
|
3531
|
+
};
|
|
3532
|
+
return hostSecret
|
|
3533
|
+
? fetchDaemonIpc(ipcPort, path, init, hostSecret)
|
|
3534
|
+
: fetch(`http://127.0.0.1:${ipcPort}${path}`, init);
|
|
3535
|
+
}
|
|
3536
|
+
/** botmux slash "<斜杠命令>":请求 daemon 在本会话 idle 后把命令敲入自己的 CLI。
|
|
3537
|
+
* 自识别当前会话(pid marker → BOTMUX_SESSION_ID env),allowlist 由 daemon 侧校验。 */
|
|
3538
|
+
async function cmdSlash() {
|
|
3539
|
+
const argv = process.argv.slice(3);
|
|
3540
|
+
const sIdx = argv.indexOf('--session');
|
|
3541
|
+
const explicitSid = sIdx >= 0 ? argv[sIdx + 1] : undefined;
|
|
3542
|
+
// 所有非 flag 位置参数 join(' '),而不是只取第一个——未加引号的命令若含空格
|
|
3543
|
+
// (如 `botmux slash /model opus`)此前会被截断成 `/model`。
|
|
3544
|
+
const command = argv.filter((a, i) => !a.startsWith('--') && !(sIdx >= 0 && i === sIdx + 1)).join(' ');
|
|
3545
|
+
if (!command) {
|
|
3546
|
+
console.error('用法: botmux slash "/compact" [--session <id>]');
|
|
3547
|
+
process.exit(1);
|
|
3548
|
+
}
|
|
3549
|
+
const ctx = explicitSid ? null : findAncestorSessionContext();
|
|
3550
|
+
const sid = explicitSid ?? ctx?.sessionId;
|
|
3551
|
+
if (!sid) {
|
|
3552
|
+
console.error('❌ 无法定位当前会话(需在 bot 会话内执行,或用 --session 指定)');
|
|
3553
|
+
process.exit(1);
|
|
3554
|
+
}
|
|
3555
|
+
const sessions = loadSessions();
|
|
3556
|
+
const s = [...sessions.values()].find(x => x.sessionId === sid || x.sessionId.startsWith(sid));
|
|
3557
|
+
if (!s) {
|
|
3558
|
+
console.error(`❌ 未找到 session ${sid}`);
|
|
3559
|
+
process.exit(1);
|
|
3560
|
+
}
|
|
3561
|
+
const daemon = findDaemon(s.larkAppId);
|
|
3562
|
+
if (!daemon) {
|
|
3563
|
+
console.error('❌ daemon 不在线');
|
|
3564
|
+
process.exit(1);
|
|
3565
|
+
}
|
|
3566
|
+
const res = await postSessionCliIpc(daemon.ipcPort, s.sessionId, 'slash', { command });
|
|
3567
|
+
const body = await res.json().catch(() => ({}));
|
|
3568
|
+
if (res.ok && body?.ok) {
|
|
3569
|
+
console.log(`✓ 已排队注入: ${body.queued}(会话空闲时执行;CLI 进程若在执行前重启则丢弃)`);
|
|
3570
|
+
return;
|
|
3571
|
+
}
|
|
3572
|
+
console.error(`✗ 被拒绝: ${body?.error ?? `HTTP ${res.status}`}`);
|
|
3573
|
+
process.exit(1);
|
|
3574
|
+
}
|
|
3575
|
+
/** botmux cd <角色目录>:请求 daemon 重钉本话题工作目录(角色切换)。
|
|
3576
|
+
* daemon 侧校验目录必须在 ~/botmux-roles 下;Claude 家族 idle 注入 /cd 不重启,
|
|
3577
|
+
* 其余 CLI 杀进程冷启动。协议要求本命令是该轮最后一个动作。 */
|
|
3578
|
+
async function cmdCd() {
|
|
3579
|
+
const argv = process.argv.slice(3);
|
|
3580
|
+
const sIdx = argv.indexOf('--session');
|
|
3581
|
+
const explicitSid = sIdx >= 0 ? argv[sIdx + 1] : undefined;
|
|
3582
|
+
// 所有非 flag 位置参数 join(' '),而不是只取第一个——路径含空格且未加引号时
|
|
3583
|
+
// (如 `botmux cd ~/botmux-roles/我的 角色`)此前会被截断。
|
|
3584
|
+
const dir = argv.filter((a, i) => !a.startsWith('--') && !(sIdx >= 0 && i === sIdx + 1)).join(' ');
|
|
3585
|
+
if (!dir) {
|
|
3586
|
+
console.error('用法: botmux cd <目标目录(含空格建议加引号)> [--session <id>]');
|
|
3587
|
+
process.exit(1);
|
|
3588
|
+
}
|
|
3589
|
+
const ctx = explicitSid ? null : findAncestorSessionContext();
|
|
3590
|
+
const sid = explicitSid ?? ctx?.sessionId;
|
|
3591
|
+
if (!sid) {
|
|
3592
|
+
console.error('❌ 无法定位当前会话(需在 bot 会话内执行,或用 --session 指定)');
|
|
3593
|
+
process.exit(1);
|
|
3594
|
+
}
|
|
3595
|
+
const sessions = loadSessions();
|
|
3596
|
+
const s = [...sessions.values()].find(x => x.sessionId === sid || x.sessionId.startsWith(sid));
|
|
3597
|
+
if (!s) {
|
|
3598
|
+
console.error(`❌ 未找到 session ${sid}`);
|
|
3599
|
+
process.exit(1);
|
|
3600
|
+
}
|
|
3601
|
+
const daemon = findDaemon(s.larkAppId);
|
|
3602
|
+
if (!daemon) {
|
|
3603
|
+
console.error('❌ daemon 不在线');
|
|
3604
|
+
process.exit(1);
|
|
3605
|
+
}
|
|
3606
|
+
const res = await postSessionCliIpc(daemon.ipcPort, s.sessionId, 'cd', { dir });
|
|
3607
|
+
const body = await res.json().catch(() => ({}));
|
|
3608
|
+
if (res.ok && body?.ok) {
|
|
3609
|
+
console.log(body.mode === 'inject'
|
|
3610
|
+
? `✓ 已切换到 ${body.dir}(会话空闲时生效,进程不重启)`
|
|
3611
|
+
: `✓ 已切换到 ${body.dir}(下条消息在新目录冷启动)`);
|
|
3612
|
+
return;
|
|
3613
|
+
}
|
|
3614
|
+
console.error(`✗ 切换被拒绝: ${body?.error ?? `HTTP ${res.status}`}`);
|
|
3615
|
+
process.exit(1);
|
|
3616
|
+
}
|
|
3427
3617
|
/**
|
|
3428
3618
|
* Discover online daemons. Mirrors the staleness rule used by
|
|
3429
3619
|
* dashboard/registry.ts (90s heartbeat) so we don't try to talk to a daemon
|
|
@@ -3454,7 +3644,17 @@ function listOnlineDaemons() {
|
|
|
3454
3644
|
continue;
|
|
3455
3645
|
if (now - (d.lastHeartbeat ?? 0) > STALE_MS)
|
|
3456
3646
|
continue;
|
|
3457
|
-
all.push({
|
|
3647
|
+
all.push({
|
|
3648
|
+
ipcPort: d.ipcPort,
|
|
3649
|
+
larkAppId: d.larkAppId,
|
|
3650
|
+
...(typeof d.bootInstanceId === 'string' && d.bootInstanceId
|
|
3651
|
+
? { bootInstanceId: d.bootInstanceId }
|
|
3652
|
+
: {}),
|
|
3653
|
+
...(typeof d.workflowIpcProtocol === 'string' && d.workflowIpcProtocol
|
|
3654
|
+
? { workflowIpcProtocol: d.workflowIpcProtocol }
|
|
3655
|
+
: {}),
|
|
3656
|
+
lastHeartbeat: d.lastHeartbeat,
|
|
3657
|
+
});
|
|
3458
3658
|
}
|
|
3459
3659
|
catch { /* skip malformed */ }
|
|
3460
3660
|
}
|
|
@@ -3466,74 +3666,245 @@ function findDaemon(larkAppId) {
|
|
|
3466
3666
|
return all.find(d => d.larkAppId === larkAppId) ?? null;
|
|
3467
3667
|
return all[0] ?? null;
|
|
3468
3668
|
}
|
|
3469
|
-
/**
|
|
3470
|
-
*
|
|
3471
|
-
*
|
|
3472
|
-
*
|
|
3473
|
-
|
|
3669
|
+
/**
|
|
3670
|
+
* Authenticate the human who opened this exact turn against the target run,
|
|
3671
|
+
* then return the only daemon app that may receive the mutation. Inherited
|
|
3672
|
+
* BOTMUX_LARK_APP_ID is deliberately not an authority (long-lived sessions
|
|
3673
|
+
* keep it even when a different human opens a later turn).
|
|
3674
|
+
*/
|
|
3675
|
+
function authorizeWorkflowDaemonCommand(runId, rest) {
|
|
3676
|
+
return authorizeV3DaemonCommand({
|
|
3677
|
+
runId,
|
|
3678
|
+
dataDir: resolveDataDir(),
|
|
3679
|
+
envSessionId: process.env.BOTMUX_SESSION_ID,
|
|
3680
|
+
requestedLarkAppId: argValue(rest, '--bot'),
|
|
3681
|
+
}).larkAppId;
|
|
3682
|
+
}
|
|
3683
|
+
/**
|
|
3684
|
+
* Isolated-session fallback for workflow daemon mutations. Inside a Linux
|
|
3685
|
+
* bwrap sandbox or a macOS read-isolated session every leg of the host path
|
|
3686
|
+
* above is masked by design (process-tree marker, run directory,
|
|
3687
|
+
* `.dashboard-secret`), so the CLI instead presents its per-turn rotating
|
|
3688
|
+
* capability and lets the daemon re-derive the caller/chat/bot tuple from its
|
|
3689
|
+
* own live session record (workflows/v3/session-relay.ts). Detection is
|
|
3690
|
+
* marker-first (a visible live process marker → host path, so a stale
|
|
3691
|
+
* capability file can never hijack a healthy host session), then falls back
|
|
3692
|
+
* to the worker-published capability file that only isolated sessions have.
|
|
3693
|
+
* `--bot` is meaningless here — the run must be bound to this very session's
|
|
3694
|
+
* chat tuple, which pins the daemon.
|
|
3695
|
+
*/
|
|
3696
|
+
async function tryWorkflowSessionRelayMutation(runId, mutation, body) {
|
|
3697
|
+
const context = readWorkflowSessionRelayContext({
|
|
3698
|
+
env: process.env,
|
|
3699
|
+
dataDir: resolveDataDir(),
|
|
3700
|
+
});
|
|
3701
|
+
if (!context)
|
|
3702
|
+
return null;
|
|
3703
|
+
try {
|
|
3704
|
+
return await postWorkflowSessionRunMutation({
|
|
3705
|
+
context,
|
|
3706
|
+
runId,
|
|
3707
|
+
mutation,
|
|
3708
|
+
...(body ? { body } : {}),
|
|
3709
|
+
resolveIpcPort: (larkAppId) => {
|
|
3710
|
+
// Daemon discovery is host state — masked in-sandbox, best-effort under
|
|
3711
|
+
// read isolation. The BOTMUX_DAEMON_IPC_PORT fallback inside the client
|
|
3712
|
+
// covers the masked case.
|
|
3713
|
+
try {
|
|
3714
|
+
return larkAppId ? findDaemon(larkAppId)?.ipcPort : undefined;
|
|
3715
|
+
}
|
|
3716
|
+
catch {
|
|
3717
|
+
return undefined;
|
|
3718
|
+
}
|
|
3719
|
+
},
|
|
3720
|
+
});
|
|
3721
|
+
}
|
|
3722
|
+
catch (err) {
|
|
3723
|
+
console.error(`❌ ${err instanceof Error ? err.message : String(err)}`);
|
|
3724
|
+
process.exit(1);
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
/** `botmux workflow cancel <runId>` — authenticate the exact current caller
|
|
3728
|
+
* against the immutable run binding, then ask the owning daemon to durably
|
|
3729
|
+
* record cancellation before interrupting workers. */
|
|
3730
|
+
async function cmdWorkflowCancelV3(runId, rest) {
|
|
3474
3731
|
if (!runId) {
|
|
3475
|
-
console.error('用法: botmux workflow
|
|
3732
|
+
console.error('用法: botmux workflow cancel <runId> [--reason <text>] [--bot <larkAppId>]');
|
|
3476
3733
|
process.exit(1);
|
|
3477
3734
|
}
|
|
3478
|
-
const
|
|
3479
|
-
const
|
|
3735
|
+
const { formatV3RunCancelCliSuccess, parseV3RunCancelCliOptions, parseV3RunCancelDaemonResponse, } = await import('./cli/v3-run-cancel.js');
|
|
3736
|
+
const parsed = parseV3RunCancelCliOptions(rest);
|
|
3737
|
+
if (!parsed.ok) {
|
|
3738
|
+
console.error(`❌ ${parsed.error}`);
|
|
3739
|
+
console.error('用法: botmux workflow cancel <runId> [--reason <text>] [--bot <larkAppId>]');
|
|
3740
|
+
process.exit(1);
|
|
3741
|
+
}
|
|
3742
|
+
const reason = parsed.reason;
|
|
3743
|
+
// An isolated session can only cancel a daemon-bound chat run (a standalone
|
|
3744
|
+
// manual_cli run lives on masked host disk anyway), so relay short-circuits
|
|
3745
|
+
// ahead of the host authority/standalone branching.
|
|
3746
|
+
const relayed = await tryWorkflowSessionRelayMutation(runId, 'cancel', reason ? { reason } : {});
|
|
3747
|
+
if (relayed) {
|
|
3748
|
+
try {
|
|
3749
|
+
console.log(formatV3RunCancelCliSuccess(parseV3RunCancelDaemonResponse(relayed)));
|
|
3750
|
+
}
|
|
3751
|
+
catch (err) {
|
|
3752
|
+
console.error(`❌ ${err instanceof Error ? err.message : String(err)}`);
|
|
3753
|
+
process.exit(1);
|
|
3754
|
+
}
|
|
3755
|
+
return;
|
|
3756
|
+
}
|
|
3757
|
+
const authority = authorizeV3DaemonCommand({
|
|
3758
|
+
runId,
|
|
3759
|
+
dataDir: resolveDataDir(),
|
|
3760
|
+
envSessionId: process.env.BOTMUX_SESSION_ID,
|
|
3761
|
+
requestedLarkAppId: parsed.larkAppId,
|
|
3762
|
+
allowStandaloneLocal: true,
|
|
3763
|
+
});
|
|
3764
|
+
if (authority.mode === 'standalone') {
|
|
3765
|
+
// A manual_cli run is owned by its foreground/local runtime, not a daemon.
|
|
3766
|
+
// Persisting the shared journal intent is sufficient: runWorkflow polls the
|
|
3767
|
+
// durable cut while a worker is active and aborts it within one tick.
|
|
3768
|
+
const { requestV3RunCancel } = await import('./workflows/v3/daemon-run.js');
|
|
3769
|
+
let outcome;
|
|
3770
|
+
try {
|
|
3771
|
+
outcome = requestV3RunCancel(dirname(authority.runDir), runId, {
|
|
3772
|
+
by: 'standalone-cli',
|
|
3773
|
+
...(reason ? { reason } : {}),
|
|
3774
|
+
});
|
|
3775
|
+
}
|
|
3776
|
+
catch (err) {
|
|
3777
|
+
console.error(`❌ ${err instanceof Error ? err.message : String(err)}`);
|
|
3778
|
+
process.exit(1);
|
|
3779
|
+
}
|
|
3780
|
+
if (outcome.kind === 'stale-run')
|
|
3781
|
+
throw new Error(`找不到 v3 run ${runId}`);
|
|
3782
|
+
if (outcome.kind === 'already-terminal') {
|
|
3783
|
+
console.log(formatV3RunCancelCliSuccess({
|
|
3784
|
+
ok: true, runId, status: outcome.status, alreadyTerminal: true,
|
|
3785
|
+
}));
|
|
3786
|
+
return;
|
|
3787
|
+
}
|
|
3788
|
+
if (outcome.kind === 'already-cancelled') {
|
|
3789
|
+
console.log(formatV3RunCancelCliSuccess({
|
|
3790
|
+
ok: true, runId, status: 'cancelled', alreadyTerminal: true,
|
|
3791
|
+
...(outcome.cancelRequestId ? { cancelRequestId: outcome.cancelRequestId } : {}),
|
|
3792
|
+
}));
|
|
3793
|
+
return;
|
|
3794
|
+
}
|
|
3795
|
+
console.log(formatV3RunCancelCliSuccess({
|
|
3796
|
+
ok: true,
|
|
3797
|
+
runId,
|
|
3798
|
+
status: 'cancelling',
|
|
3799
|
+
cancelRequestId: outcome.cancelRequestId,
|
|
3800
|
+
alreadyRequested: outcome.kind === 'already-requested',
|
|
3801
|
+
}));
|
|
3802
|
+
return;
|
|
3803
|
+
}
|
|
3804
|
+
const daemon = findDaemon(authority.larkAppId);
|
|
3480
3805
|
if (!daemon) {
|
|
3481
|
-
console.error('❌
|
|
3806
|
+
console.error('❌ 没有在线的目标 daemon;v3 run 取消需要由所属 daemon 持久化并中断节点。');
|
|
3482
3807
|
process.exit(1);
|
|
3483
3808
|
}
|
|
3484
|
-
let
|
|
3809
|
+
let secret = null;
|
|
3485
3810
|
try {
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3811
|
+
secret = loadDashboardSecret(dashboardSecretPath());
|
|
3812
|
+
}
|
|
3813
|
+
catch (err) {
|
|
3814
|
+
console.error(`❌ 无法读取 .dashboard-secret:${err instanceof Error ? err.message : String(err)}`);
|
|
3815
|
+
process.exit(1);
|
|
3816
|
+
}
|
|
3817
|
+
if (!secret) {
|
|
3818
|
+
console.error('❌ 缺少 .dashboard-secret,无法认证 v3 cancel daemon 请求;请先重启 botmux 初始化。');
|
|
3819
|
+
process.exit(1);
|
|
3820
|
+
}
|
|
3821
|
+
try {
|
|
3822
|
+
const { postV3RunCancel } = await import('./cli/v3-run-cancel.js');
|
|
3823
|
+
const result = await postV3RunCancel({
|
|
3824
|
+
daemon,
|
|
3825
|
+
runId,
|
|
3826
|
+
secret,
|
|
3827
|
+
...(reason ? { reason } : {}),
|
|
3490
3828
|
});
|
|
3829
|
+
console.log(formatV3RunCancelCliSuccess(result));
|
|
3491
3830
|
}
|
|
3492
3831
|
catch (err) {
|
|
3493
|
-
console.error(`❌
|
|
3832
|
+
console.error(`❌ ${err instanceof Error ? err.message : String(err)}`);
|
|
3494
3833
|
process.exit(1);
|
|
3495
3834
|
}
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3835
|
+
}
|
|
3836
|
+
/** `botmux workflow start <runId>` — POST the daemon's v3 start IPC so the run
|
|
3837
|
+
* is daemon-driven (humanGate → 飞书审批卡). The grill skill calls this after
|
|
3838
|
+
* approve-dag instead of the standalone `botmux v3 run` (which has no card
|
|
3839
|
+
* layer). The daemon is selected from the authenticated run/current-turn
|
|
3840
|
+
* binding, never from the worker's static BOTMUX_LARK_APP_ID env. */
|
|
3841
|
+
async function cmdWorkflowStart(runId, rest) {
|
|
3842
|
+
if (!runId) {
|
|
3843
|
+
console.error('用法: botmux workflow start <runId> [--bot <larkAppId>]');
|
|
3844
|
+
process.exit(1);
|
|
3845
|
+
}
|
|
3846
|
+
let response = await tryWorkflowSessionRelayMutation(runId, 'start');
|
|
3847
|
+
if (!response) {
|
|
3848
|
+
const larkAppId = authorizeWorkflowDaemonCommand(runId, rest);
|
|
3849
|
+
const daemon = findDaemon(larkAppId);
|
|
3850
|
+
if (!daemon) {
|
|
3851
|
+
console.error('❌ 没有在线 daemon;v3 humanGate run 需要 daemon 驱动(审批卡是 daemon 的活)。');
|
|
3852
|
+
process.exit(1);
|
|
3853
|
+
}
|
|
3854
|
+
try {
|
|
3855
|
+
response = await postWorkflowDaemonMutation({
|
|
3856
|
+
daemon,
|
|
3857
|
+
runId,
|
|
3858
|
+
mutation: 'start',
|
|
3859
|
+
});
|
|
3860
|
+
}
|
|
3861
|
+
catch (err) {
|
|
3862
|
+
console.error(`❌ ${err?.message ?? err}`);
|
|
3863
|
+
process.exit(1);
|
|
3864
|
+
}
|
|
3865
|
+
}
|
|
3866
|
+
if (!response.ok) {
|
|
3867
|
+
console.error(`❌ start 失败 (HTTP ${response.status}): ${response.bodyRaw}`);
|
|
3499
3868
|
process.exit(1);
|
|
3500
3869
|
}
|
|
3501
3870
|
console.log(`✅ v3 run "${runId}" 已交 daemon 驱动;humanGate 会在话题里弹审批卡,点了才继续。`);
|
|
3502
3871
|
}
|
|
3503
3872
|
/** `botmux workflow retry <runId> [--node <id>]` — blocked 节点重试入口(CLI 侧)。
|
|
3504
3873
|
* 走 daemon 的 retry IPC(journal 写入留在 daemon 进程内,单写者),daemon append
|
|
3505
|
-
* `nodeRetryRequested` 后以新 attempt
|
|
3874
|
+
* `nodeRetryRequested` 后以新 attempt 重驱动;已退休的 v2 `resume` 不再参与分发。 */
|
|
3506
3875
|
async function cmdWorkflowRetry(runId, rest) {
|
|
3507
3876
|
if (!runId) {
|
|
3508
3877
|
console.error('用法: botmux workflow retry <runId> [--node <nodeId>] [--bot <larkAppId>]');
|
|
3509
3878
|
process.exit(1);
|
|
3510
3879
|
}
|
|
3511
|
-
const larkAppId = argValue(rest, '--bot') ?? process.env.BOTMUX_LARK_APP_ID;
|
|
3512
3880
|
const nodeId = argValue(rest, '--node');
|
|
3513
|
-
|
|
3514
|
-
if (!
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3881
|
+
let response = await tryWorkflowSessionRelayMutation(runId, 'retry', nodeId ? { nodeId } : {});
|
|
3882
|
+
if (!response) {
|
|
3883
|
+
const larkAppId = authorizeWorkflowDaemonCommand(runId, rest);
|
|
3884
|
+
const daemon = findDaemon(larkAppId);
|
|
3885
|
+
if (!daemon) {
|
|
3886
|
+
console.error('❌ 没有在线 daemon;blocked 重试需要 daemon 驱动。');
|
|
3887
|
+
process.exit(1);
|
|
3888
|
+
}
|
|
3889
|
+
try {
|
|
3890
|
+
response = await postWorkflowDaemonMutation({
|
|
3891
|
+
daemon,
|
|
3892
|
+
runId,
|
|
3893
|
+
mutation: 'retry',
|
|
3894
|
+
body: nodeId ? { nodeId } : {},
|
|
3895
|
+
});
|
|
3896
|
+
}
|
|
3897
|
+
catch (err) {
|
|
3898
|
+
console.error(`❌ ${err?.message ?? err}`);
|
|
3899
|
+
process.exit(1);
|
|
3900
|
+
}
|
|
3529
3901
|
}
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
if (txt.includes('loop_node_use_grant')) {
|
|
3902
|
+
if (!response.ok) {
|
|
3903
|
+
if (response.bodyRaw.includes('loop_node_use_grant')) {
|
|
3533
3904
|
console.error(`❌ 该受阻的是一个 loop(轮数耗尽),不是节点 attempt——用 \`botmux workflow grant ${runId}\` 追加一轮。`);
|
|
3534
3905
|
}
|
|
3535
3906
|
else {
|
|
3536
|
-
console.error(`❌ retry 失败 (HTTP ${
|
|
3907
|
+
console.error(`❌ retry 失败 (HTTP ${response.status}): ${response.bodyRaw}`);
|
|
3537
3908
|
}
|
|
3538
3909
|
process.exit(1);
|
|
3539
3910
|
}
|
|
@@ -3547,28 +3918,30 @@ async function cmdWorkflowGrant(runId, rest) {
|
|
|
3547
3918
|
console.error('用法: botmux workflow grant <runId> [--loop <loopId>] [--bot <larkAppId>]');
|
|
3548
3919
|
process.exit(1);
|
|
3549
3920
|
}
|
|
3550
|
-
const larkAppId = argValue(rest, '--bot') ?? process.env.BOTMUX_LARK_APP_ID;
|
|
3551
3921
|
const loopId = argValue(rest, '--loop');
|
|
3552
|
-
|
|
3553
|
-
if (!
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3922
|
+
let response = await tryWorkflowSessionRelayMutation(runId, 'grant', loopId ? { loopId } : {});
|
|
3923
|
+
if (!response) {
|
|
3924
|
+
const larkAppId = authorizeWorkflowDaemonCommand(runId, rest);
|
|
3925
|
+
const daemon = findDaemon(larkAppId);
|
|
3926
|
+
if (!daemon) {
|
|
3927
|
+
console.error('❌ 没有在线 daemon;loop 追加需要 daemon 驱动。');
|
|
3928
|
+
process.exit(1);
|
|
3929
|
+
}
|
|
3930
|
+
try {
|
|
3931
|
+
response = await postWorkflowDaemonMutation({
|
|
3932
|
+
daemon,
|
|
3933
|
+
runId,
|
|
3934
|
+
mutation: 'grant',
|
|
3935
|
+
body: loopId ? { loopId } : {},
|
|
3936
|
+
});
|
|
3937
|
+
}
|
|
3938
|
+
catch (err) {
|
|
3939
|
+
console.error(`❌ ${err?.message ?? err}`);
|
|
3940
|
+
process.exit(1);
|
|
3941
|
+
}
|
|
3568
3942
|
}
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
console.error(`❌ grant 失败 (HTTP ${res.status}): ${txt}`);
|
|
3943
|
+
if (!response.ok) {
|
|
3944
|
+
console.error(`❌ grant 失败 (HTTP ${response.status}): ${response.bodyRaw}`);
|
|
3572
3945
|
process.exit(1);
|
|
3573
3946
|
}
|
|
3574
3947
|
console.log(`➕ v3 run "${runId}" 已追加一轮,loop 将带上一轮反馈重跑。`);
|
|
@@ -3628,7 +4001,7 @@ async function cmdResume() {
|
|
|
3628
4001
|
}
|
|
3629
4002
|
let res;
|
|
3630
4003
|
try {
|
|
3631
|
-
res = await
|
|
4004
|
+
res = await fetchDaemonIpc(daemon.ipcPort, `/api/sessions/${encodeURIComponent(session.sessionId)}/resume`, { method: 'POST' });
|
|
3632
4005
|
}
|
|
3633
4006
|
catch (err) {
|
|
3634
4007
|
console.error(`❌ 无法连接到 daemon (port=${daemon.ipcPort}): ${err?.message ?? err}`);
|
|
@@ -3727,25 +4100,9 @@ async function cmdTermLink(rest) {
|
|
|
3727
4100
|
console.error('❌ 未找到在线 daemon。请确认 daemon 正在运行:botmux status');
|
|
3728
4101
|
process.exit(1);
|
|
3729
4102
|
}
|
|
3730
|
-
const SECRET_PATH = join(CONFIG_DIR, '.dashboard-secret');
|
|
3731
|
-
let secret;
|
|
3732
|
-
try {
|
|
3733
|
-
secret = loadDashboardSecret(SECRET_PATH);
|
|
3734
|
-
}
|
|
3735
|
-
catch (e) {
|
|
3736
|
-
console.error(`❌ 无法读取 .dashboard-secret:${e.message}`);
|
|
3737
|
-
process.exit(1);
|
|
3738
|
-
}
|
|
3739
|
-
if (!secret) {
|
|
3740
|
-
console.error('❌ 缺少或为空 .dashboard-secret(daemon 未初始化)。先 `botmux restart`。');
|
|
3741
|
-
process.exit(1);
|
|
3742
|
-
}
|
|
3743
|
-
const ts = Math.floor(Date.now() / 1000).toString();
|
|
3744
|
-
const nonce = randomBytes(8).toString('hex');
|
|
3745
|
-
const sig = createHmac('sha256', secret).update(`${ts}:${nonce}`).digest('base64url');
|
|
3746
4103
|
let res;
|
|
3747
4104
|
try {
|
|
3748
|
-
res = await
|
|
4105
|
+
res = await fetchDaemonIpc(daemon.ipcPort, `/api/sessions/${encodeURIComponent(session.sessionId)}/write-link-card`, { method: 'POST' });
|
|
3749
4106
|
}
|
|
3750
4107
|
catch (err) {
|
|
3751
4108
|
console.error(`❌ 无法连接到 daemon (port=${daemon.ipcPort}): ${err?.message ?? err}`);
|
|
@@ -3799,7 +4156,7 @@ botmux v${getVersion()} — IM ↔ AI 编程 CLI 桥接
|
|
|
3799
4156
|
restart 重启 daemon(默认不停止插件 service,core 启动后确保 mode=auto 正在运行;--with-plugin 显式先停再启动 auto service;--include-pm2 同时重启 PM2 God)
|
|
3800
4157
|
logs 查看 daemon 日志(--lines N, --bot <0-based-index|pm2-name|appId>)
|
|
3801
4158
|
status 查看 daemon 状态
|
|
3802
|
-
upgrade
|
|
4159
|
+
upgrade 升级到最新版本(别名:update)
|
|
3803
4160
|
dashboard 打印新的 Web Dashboard 一次性登录 URL(旧 token 同时失效)
|
|
3804
4161
|
list 列出活跃会话(交互式选择并连接 tmux)
|
|
3805
4162
|
--plain 纯文本表格输出(管道/脚本场景)
|
|
@@ -3812,6 +4169,9 @@ botmux v${getVersion()} — IM ↔ AI 编程 CLI 桥接
|
|
|
3812
4169
|
--bot <appId> 挂起该 bot 的全部活跃会话
|
|
3813
4170
|
--isolated 挂起所有读隔离 bot(凭证轮换后用;下次冷启动自动同步最新凭证)
|
|
3814
4171
|
--dry-run 只列出目标,不执行
|
|
4172
|
+
slash "<斜杠命令>" 会话空闲后向本会话 CLI 注入一条原生斜杠命令(需 bots.json 配 tuiSlashAllow;/cd 恒被拒)
|
|
4173
|
+
cd <目录> (会话内)切换本话题工作目录到角色库内的目录——角色切换用;
|
|
4174
|
+
目录必须位于 ~/botmux-roles 之下
|
|
3815
4175
|
term-link [id] 获取活跃会话的「可操作终端」(带写 token)。不回显链接,改由
|
|
3816
4176
|
daemon 把可操作卡片私密发给 owner(群内仅你可见,话题/单聊回退 DM)。
|
|
3817
4177
|
单个活跃会话可省略 id
|
|
@@ -3891,9 +4251,23 @@ botmux v${getVersion()} — IM ↔ AI 编程 CLI 桥接
|
|
|
3891
4251
|
skill list 列出本会话可用的技能(用户自定义 + botmux 内置)及其描述
|
|
3892
4252
|
skill show <name> 读取某技能的完整 SKILL.md 说明(prompt 注入模式下按需拉取内置技能全文)
|
|
3893
4253
|
|
|
3894
|
-
编排 / workflow
|
|
3895
|
-
workflow
|
|
3896
|
-
|
|
4254
|
+
编排 / workflow(v3):
|
|
4255
|
+
workflow save [last|runId] [名称]
|
|
4256
|
+
把成功 run 固化为 chat scope Saved Workflow;
|
|
4257
|
+
发布当前 Bot 全局版本 / 确认 unsafe lint 请由用户在飞书显式发送 /workflow save ...
|
|
4258
|
+
workflow run <名称|workflowId> [--param key=value ...]
|
|
4259
|
+
workflow list [--json] | show <名称|workflowId>
|
|
4260
|
+
运行 / 查看 Saved Workflow
|
|
4261
|
+
workflow new|spec-finalize|approve-spec|revise-spec|architect|revise-dag [...]
|
|
4262
|
+
workflow approve-dag|start [...] 创建、修订并运行一次性即兴 Workflow
|
|
4263
|
+
workflow cancel <runId> [--reason <text>] [--bot <larkAppId>]
|
|
4264
|
+
持久化取消 v3 run 并中断活动节点
|
|
4265
|
+
workflow retry|grant [...] 处理受阻节点 / loop
|
|
4266
|
+
template migrate-v3 [id|path ...] [--all] [--commit ...]
|
|
4267
|
+
v2 定义迁移:默认 dry-run,写入需显式 owner/app/scope
|
|
4268
|
+
template archive-runs [--commit|--verify <archive>|--retire <archive> --ack-daemon-stopped]
|
|
4269
|
+
v2 历史 run 私有静态归档;retire 在维护窗双验后原子迁入 quarantine
|
|
4270
|
+
(完整参数见 \`botmux workflow help\` / \`botmux template help\`)
|
|
3897
4271
|
dispatch --bot <name> [...] 多话题编排:开子话题并把 bot 派进去(详见 \`botmux dispatch --help\`)
|
|
3898
4272
|
report [...] v3/编排场景向上汇报进度或结果(详见 \`botmux report --help\`)
|
|
3899
4273
|
|
|
@@ -3930,7 +4304,17 @@ botmux skills 注入方式(仅影响 codex/gemini/opencode 等只支持全局
|
|
|
3930
4304
|
* the env fallback is safe.
|
|
3931
4305
|
*/
|
|
3932
4306
|
function findAncestorSessionContext() {
|
|
3933
|
-
|
|
4307
|
+
const resolved = resolveSessionContext(resolveDataDir(), process.env.BOTMUX_SESSION_ID);
|
|
4308
|
+
if (!resolved)
|
|
4309
|
+
return null;
|
|
4310
|
+
const envAttempt = Number(process.env.BOTMUX_DISPATCH_ATTEMPT);
|
|
4311
|
+
const dispatchAttempt = resolved.dispatchAttempt
|
|
4312
|
+
?? (Number.isSafeInteger(envAttempt) && envAttempt > 0 ? envAttempt : undefined);
|
|
4313
|
+
return {
|
|
4314
|
+
...resolved,
|
|
4315
|
+
turnId: resolved.turnId ?? process.env.BOTMUX_TURN_ID,
|
|
4316
|
+
...(dispatchAttempt !== undefined ? { dispatchAttempt } : {}),
|
|
4317
|
+
};
|
|
3934
4318
|
}
|
|
3935
4319
|
function findAncestorSessionId() {
|
|
3936
4320
|
return findAncestorSessionContext()?.sessionId ?? null;
|
|
@@ -4747,9 +5131,10 @@ function withCustomCardMentionFooter(card, mentionOpenIds, sentToLabel) {
|
|
|
4747
5131
|
// keeps using `buildImageCardElements` from there.
|
|
4748
5132
|
import { buildImageCardElements, brandFooterSegment, prepareCardMarkdown } from './im/lark/md-card.js';
|
|
4749
5133
|
import { applyInlineMentions } from './im/lark/inline-mentions.js';
|
|
5134
|
+
import { renderBrandTemplate } from './im/lark/brand-template.js';
|
|
4750
5135
|
import { resolveBrandLabel } from './bot-registry.js';
|
|
4751
5136
|
import { config } from './config.js';
|
|
4752
|
-
import { resolveQuoteTarget, validateMentionDecision, parseAttentionFlag, attentionUsageError } from './services/send-policy.js';
|
|
5137
|
+
import { resolveQuoteTarget, validateMentionDecision, parseAttentionFlag, attentionUsageError, managedVcQuoteError, managedVcCustomCardError, managedVcSendControlError, managedVcSendPayloadError, containsLarkAtTag, } from './services/send-policy.js';
|
|
4753
5138
|
/**
|
|
4754
5139
|
* Sandbox relay mode for `botmux send`. Inside a file-sandbox the CLI cannot
|
|
4755
5140
|
* read bots.json or reach Lark directly (creds are deliberately absent), so we
|
|
@@ -4803,6 +5188,7 @@ async function relaySend(rest, relayDir) {
|
|
|
4803
5188
|
? prepareCardMarkdown(extractCardText(content), process.cwd(), 'filesystem')
|
|
4804
5189
|
: undefined;
|
|
4805
5190
|
const id = randomBytes(8).toString('hex');
|
|
5191
|
+
const originCapability = readManagedOriginCapability(resolveDataDir(), sid, relayDir)?.capability;
|
|
4806
5192
|
// Structured request: the daemon-side watcher rebuilds the argv from these
|
|
4807
5193
|
// validated fields (it NEVER executes raw argv — see buildRelayHostArgs).
|
|
4808
5194
|
// Content + attachments are written into the shared outbox as plain
|
|
@@ -4873,6 +5259,7 @@ async function relaySend(rest, relayDir) {
|
|
|
4873
5259
|
videos,
|
|
4874
5260
|
videoCovers,
|
|
4875
5261
|
flags,
|
|
5262
|
+
...(originCapability ? { originCapability } : {}),
|
|
4876
5263
|
}));
|
|
4877
5264
|
const resPath = join(relayDir, `${id}.res.json`);
|
|
4878
5265
|
const deadlineMs = Date.now() + 120_000;
|
|
@@ -5017,18 +5404,11 @@ function riffModeSession(opts = {}) {
|
|
|
5017
5404
|
return { session, botConfig };
|
|
5018
5405
|
}
|
|
5019
5406
|
async function cmdSend(rest) {
|
|
5020
|
-
|
|
5021
|
-
//
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
return;
|
|
5026
|
-
}
|
|
5027
|
-
// Safety gate: a CLI agent running inside a workflow subagent (Slice F)
|
|
5028
|
-
// must not chat-post directly — chat-facing side effects are reserved
|
|
5029
|
-
// for `hostExecutor` activities so they can be tracked via
|
|
5030
|
-
// `effectAttempted` + reconciled across retries / resumes. Refuse loud
|
|
5031
|
-
// so the agent (and any human reviewing logs) sees the boundary.
|
|
5407
|
+
const ancestorCtx = findAncestorSessionContext();
|
|
5408
|
+
// Workflow subagents cannot own chat-facing effects: those belong to a
|
|
5409
|
+
// hostExecutor so retries/resumes can reconcile them. Keep this gate ahead
|
|
5410
|
+
// of both the sandbox relay and VC-origin store reads; neither path may turn
|
|
5411
|
+
// a forbidden workflow send into an observable side effect.
|
|
5032
5412
|
if (process.env.BOTMUX_WORKFLOW === '1') {
|
|
5033
5413
|
const runId = process.env.BOTMUX_WORKFLOW_RUN_ID ?? '?';
|
|
5034
5414
|
const nodeId = process.env.BOTMUX_WORKFLOW_NODE_ID ?? '?';
|
|
@@ -5037,11 +5417,106 @@ async function cmdSend(rest) {
|
|
|
5037
5417
|
`chat-facing side effects belong in a hostExecutor activity, not a subagent.`);
|
|
5038
5418
|
process.exit(2);
|
|
5039
5419
|
}
|
|
5420
|
+
// Managed output attribution must come from the live process-tree marker,
|
|
5421
|
+
// whose turn/attempt is refreshed by the worker. BOTMUX_TURN_ID is a
|
|
5422
|
+
// spawn-time fallback and can be stale in a detached child after a later
|
|
5423
|
+
// delivery starts, so it is never authority for receiver policy.
|
|
5424
|
+
const liveMarkerCtx = resolveSessionContext(resolveDataDir(), process.env.BOTMUX_SESSION_ID);
|
|
5425
|
+
const trustedHostRelay = process.env.BOTMUX_HOST_RELAY_AUTHORIZED === '1';
|
|
5426
|
+
const trustedRelayAttemptRaw = Number(process.env.BOTMUX_DISPATCH_ATTEMPT);
|
|
5427
|
+
const trustedRelayCandidate = trustedHostRelay && process.env.BOTMUX_SESSION_ID
|
|
5428
|
+
? {
|
|
5429
|
+
sessionId: process.env.BOTMUX_SESSION_ID,
|
|
5430
|
+
turnId: process.env.BOTMUX_TURN_ID,
|
|
5431
|
+
dispatchAttempt: Number.isSafeInteger(trustedRelayAttemptRaw) && trustedRelayAttemptRaw > 0
|
|
5432
|
+
? trustedRelayAttemptRaw
|
|
5433
|
+
: undefined,
|
|
5434
|
+
}
|
|
5435
|
+
: undefined;
|
|
5436
|
+
const sessionIdArg = argValue(rest, '--session-id');
|
|
5437
|
+
// Inside bwrap the PID namespace makes host marker traversal impossible.
|
|
5438
|
+
// The relay watcher therefore binds a short-lived host-issued capability to
|
|
5439
|
+
// the worker's live turn and performs the authoritative policy check.
|
|
5440
|
+
const relayDir = process.env.BOTMUX_SEND_RELAY;
|
|
5441
|
+
if (relayDir) {
|
|
5442
|
+
await relaySend(rest, relayDir);
|
|
5443
|
+
return;
|
|
5444
|
+
}
|
|
5445
|
+
// Silent is an execution policy, not a prompt suggestion. During a durable
|
|
5446
|
+
// meeting turn, refuse botmux-mediated sends before either the direct-Lark or
|
|
5447
|
+
// sandbox-relay path can run. Explicit human IM turns have no dispatchAttempt
|
|
5448
|
+
// and therefore retain the normal reply path in the same receiver session.
|
|
5449
|
+
const sessionsForOrigin = loadSessions();
|
|
5450
|
+
const trustedRelaySession = trustedRelayCandidate
|
|
5451
|
+
? sessionsForOrigin.get(trustedRelayCandidate.sessionId)
|
|
5452
|
+
: undefined;
|
|
5453
|
+
// The env marker is not authority by itself. A genuine host relay CLI is a
|
|
5454
|
+
// direct child of the session's durably recorded worker pid; sandboxed or
|
|
5455
|
+
// semi-trusted descendants cannot satisfy that parent binding.
|
|
5456
|
+
const trustedRelayCtx = trustedRelayCandidate && isTrustedVcMeetingHostRelayParent(trustedHostRelay, trustedRelaySession?.pid, process.ppid)
|
|
5457
|
+
? trustedRelayCandidate
|
|
5458
|
+
: undefined;
|
|
5459
|
+
const originSessionId = trustedRelayCtx?.sessionId
|
|
5460
|
+
|| liveMarkerCtx?.sessionId
|
|
5461
|
+
|| ancestorCtx?.sessionId
|
|
5462
|
+
|| sessionIdArg;
|
|
5463
|
+
let explicitVcMeetingImOrigin;
|
|
5464
|
+
let vcMeetingListenerOutputOwner;
|
|
5465
|
+
let vcMeetingManagedSendOrigin;
|
|
5466
|
+
let vcMeetingDeliveryReplyOrigin;
|
|
5467
|
+
if (originSessionId) {
|
|
5468
|
+
const originSession = sessionsForOrigin.get(originSessionId);
|
|
5469
|
+
const originTurnId = trustedRelayCtx?.turnId ?? liveMarkerCtx?.turnId;
|
|
5470
|
+
const imOrigin = resolveVcMeetingImTurnOrigin(originSession, originTurnId);
|
|
5471
|
+
const managedOrigin = {
|
|
5472
|
+
receiverSessionId: originSessionId,
|
|
5473
|
+
receiverSession: !!originSession?.vcMeetingReceiver,
|
|
5474
|
+
turnId: originTurnId,
|
|
5475
|
+
dispatchAttempt: trustedRelayCtx?.dispatchAttempt ?? liveMarkerCtx?.dispatchAttempt,
|
|
5476
|
+
currentImTurnOrigin: imOrigin,
|
|
5477
|
+
};
|
|
5478
|
+
const decision = evaluateVcMeetingManagedSend(resolveDataDir(), managedOrigin);
|
|
5479
|
+
if (!decision.ok) {
|
|
5480
|
+
console.error(`botmux send refused by VC managed-output policy (${decision.errorCode}): ${decision.error}`);
|
|
5481
|
+
process.exit(2);
|
|
5482
|
+
}
|
|
5483
|
+
if (decision.kind === 'listener_thread') {
|
|
5484
|
+
vcMeetingListenerOutputOwner = decision.meetingOwner;
|
|
5485
|
+
vcMeetingManagedSendOrigin = managedOrigin;
|
|
5486
|
+
if (managedOrigin.turnId && managedOrigin.dispatchAttempt !== undefined) {
|
|
5487
|
+
vcMeetingDeliveryReplyOrigin = {
|
|
5488
|
+
receiverSessionId: originSessionId,
|
|
5489
|
+
stableTurnId: managedOrigin.turnId,
|
|
5490
|
+
dispatchAttempt: managedOrigin.dispatchAttempt,
|
|
5491
|
+
};
|
|
5492
|
+
}
|
|
5493
|
+
}
|
|
5494
|
+
if (decision.kind === 'listener_thread'
|
|
5495
|
+
&& (trustedRelayCtx?.dispatchAttempt ?? liveMarkerCtx?.dispatchAttempt) === undefined) {
|
|
5496
|
+
explicitVcMeetingImOrigin = imOrigin;
|
|
5497
|
+
}
|
|
5498
|
+
}
|
|
5499
|
+
const revalidateVcMeetingManagedSend = () => {
|
|
5500
|
+
if (!vcMeetingManagedSendOrigin)
|
|
5501
|
+
return;
|
|
5502
|
+
const decision = evaluateVcMeetingManagedSend(resolveDataDir(), vcMeetingManagedSendOrigin);
|
|
5503
|
+
if (!decision.ok) {
|
|
5504
|
+
throw new Error(`VC managed-output authority expired (${decision.errorCode}): ${decision.error}`);
|
|
5505
|
+
}
|
|
5506
|
+
if (decision.kind !== 'listener_thread') {
|
|
5507
|
+
throw new Error('VC managed-output authority no longer targets the listener thread');
|
|
5508
|
+
}
|
|
5509
|
+
vcMeetingListenerOutputOwner = decision.meetingOwner;
|
|
5510
|
+
};
|
|
5511
|
+
const prepareVcMeetingListenerReply = (proposedOutput) => explicitVcMeetingImOrigin
|
|
5512
|
+
? prepareVcMeetingImReply(resolveDataDir(), explicitVcMeetingImOrigin, proposedOutput)
|
|
5513
|
+
: vcMeetingDeliveryReplyOrigin
|
|
5514
|
+
? prepareVcMeetingDeliveryReply(resolveDataDir(), vcMeetingDeliveryReplyOrigin, proposedOutput)
|
|
5515
|
+
: undefined;
|
|
5040
5516
|
process.env.SESSION_DATA_DIR ??= resolveDataDir();
|
|
5041
5517
|
// Read isolation: the sandboxed CLI is denied bots.json → register this bot
|
|
5042
5518
|
// from its own worker-written cred file instead (see registerSelfFromCredFile).
|
|
5043
5519
|
await registerSelfFromCredFile();
|
|
5044
|
-
const sessionIdArg = argValue(rest, '--session-id');
|
|
5045
5520
|
for (const flag of ['--video', '--videos', '--video-cover', '--video-covers']) {
|
|
5046
5521
|
if (flagPresentButValueMissing(rest, flag, true)) {
|
|
5047
5522
|
console.error(`botmux send: ${flag} 需要路径参数`);
|
|
@@ -5059,6 +5534,11 @@ async function cmdSend(rest) {
|
|
|
5059
5534
|
const cardJsonArg = argValue(rest, '--card-json');
|
|
5060
5535
|
const cardFile = argValue(rest, '--card-file');
|
|
5061
5536
|
const customCardRequested = cardJsonArg !== undefined || cardFile !== undefined;
|
|
5537
|
+
const managedCustomCardError = managedVcCustomCardError(!!vcMeetingManagedSendOrigin, customCardRequested);
|
|
5538
|
+
if (managedCustomCardError) {
|
|
5539
|
+
console.error(`botmux send refused for a managed VC turn: ${managedCustomCardError}`);
|
|
5540
|
+
process.exit(2);
|
|
5541
|
+
}
|
|
5062
5542
|
if (cardJsonArg !== undefined && cardFile !== undefined) {
|
|
5063
5543
|
console.error('botmux send: --card-json 与 --card-file 不能同时使用');
|
|
5064
5544
|
process.exit(2);
|
|
@@ -5113,6 +5593,16 @@ async function cmdSend(rest) {
|
|
|
5113
5593
|
// Quote chain (chat scope): --quote <message_id> overrides the auto target,
|
|
5114
5594
|
// --no-quote forces a plain (un-quoted) send.
|
|
5115
5595
|
const explicitQuote = argValue(rest, '--quote');
|
|
5596
|
+
const managedQuoteError = managedVcQuoteError({
|
|
5597
|
+
managed: !!vcMeetingManagedSendOrigin,
|
|
5598
|
+
durableDelivery: !!vcMeetingDeliveryReplyOrigin,
|
|
5599
|
+
explicitImMessageId: explicitVcMeetingImOrigin?.larkMessageId,
|
|
5600
|
+
explicitQuote,
|
|
5601
|
+
});
|
|
5602
|
+
if (managedQuoteError) {
|
|
5603
|
+
console.error(`botmux send refused for a managed VC turn: ${managedQuoteError}`);
|
|
5604
|
+
process.exit(2);
|
|
5605
|
+
}
|
|
5116
5606
|
const noQuote = rest.includes('--no-quote');
|
|
5117
5607
|
// @ hard-gate: every reply must explicitly choose one of these.
|
|
5118
5608
|
const mentionBack = rest.includes('--mention-back');
|
|
@@ -5121,11 +5611,24 @@ async function cmdSend(rest) {
|
|
|
5121
5611
|
// needs-you column for this session. Parsed specially (not argValue) so a bare
|
|
5122
5612
|
// `--attention "我卡住了"` doesn't eat the message as the flag value.
|
|
5123
5613
|
const attention = parseAttentionFlag(rest);
|
|
5614
|
+
const managedControlError = managedVcSendControlError({
|
|
5615
|
+
managed: !!vcMeetingManagedSendOrigin,
|
|
5616
|
+
sendTopLevel,
|
|
5617
|
+
overrideChatId,
|
|
5618
|
+
sendInto,
|
|
5619
|
+
attentionRequested: attention.requested,
|
|
5620
|
+
explicitMentionCount: mentionArgs.length,
|
|
5621
|
+
mentionBack,
|
|
5622
|
+
noMention,
|
|
5623
|
+
});
|
|
5624
|
+
if (managedControlError) {
|
|
5625
|
+
console.error(`botmux send refused for a managed VC turn: ${managedControlError}`);
|
|
5626
|
+
process.exit(2);
|
|
5627
|
+
}
|
|
5124
5628
|
if (customCardRequested && asVoice) {
|
|
5125
5629
|
console.error('botmux send: --card-file/--card-json 不能与 --voice 混用');
|
|
5126
5630
|
process.exit(2);
|
|
5127
5631
|
}
|
|
5128
|
-
const ancestorCtx = findAncestorSessionContext();
|
|
5129
5632
|
const sid = sessionIdArg ?? ancestorCtx?.sessionId ?? process.env.BOTMUX_SESSION_ID ?? null;
|
|
5130
5633
|
if (!sid) {
|
|
5131
5634
|
console.error('无法推断 session-id。请在 Lark 话题内的 CLI 会话中运行,或传 --session-id <id>。');
|
|
@@ -5209,6 +5712,19 @@ async function cmdSend(rest) {
|
|
|
5209
5712
|
}
|
|
5210
5713
|
if (!contentFile && !customCardRequested)
|
|
5211
5714
|
rejectLikelyWindowsStdinMojibake(content);
|
|
5715
|
+
const managedPayloadError = managedVcSendPayloadError({
|
|
5716
|
+
managed: !!vcMeetingManagedSendOrigin,
|
|
5717
|
+
asVoice,
|
|
5718
|
+
hasBodyText: !!content.trim(),
|
|
5719
|
+
imageCount: images.length,
|
|
5720
|
+
fileCount: files.length,
|
|
5721
|
+
videoCount: videoAttachments.length,
|
|
5722
|
+
containsNativeAtTag: containsLarkAtTag(content),
|
|
5723
|
+
});
|
|
5724
|
+
if (managedPayloadError) {
|
|
5725
|
+
console.error(`botmux send refused for a managed VC turn: ${managedPayloadError}`);
|
|
5726
|
+
process.exit(2);
|
|
5727
|
+
}
|
|
5212
5728
|
if (!customCard && !content.trim() && images.length === 0 && files.length === 0 && videoAttachments.length === 0) {
|
|
5213
5729
|
console.error('没有内容可发送。用法:\n echo "消息" | botmux send\n botmux send "消息"\n botmux send --content-file /tmp/msg.md --images /tmp/chart.png\n botmux send --videos /tmp/replay.mp4 --video-covers /tmp/cover.png --no-mention "视频预览"');
|
|
5214
5730
|
process.exit(1);
|
|
@@ -5227,6 +5743,25 @@ async function cmdSend(rest) {
|
|
|
5227
5743
|
console.error(`botmux send: ${attentionErr}`);
|
|
5228
5744
|
process.exit(2);
|
|
5229
5745
|
}
|
|
5746
|
+
const recordVcMeetingPrimaryOutput = (messageId, outputChatId) => {
|
|
5747
|
+
if (!vcMeetingListenerOutputOwner || sendInto)
|
|
5748
|
+
return;
|
|
5749
|
+
try {
|
|
5750
|
+
const recorded = recordVcMeetingListenerMessage(resolveDataDir(), {
|
|
5751
|
+
...vcMeetingListenerOutputOwner,
|
|
5752
|
+
targetChatId: outputChatId,
|
|
5753
|
+
messageId,
|
|
5754
|
+
});
|
|
5755
|
+
if (!recorded.ok) {
|
|
5756
|
+
console.error(`⚠️ VC 监听消息索引拒绝记录 ${messageId}(${recorded.reason})`);
|
|
5757
|
+
}
|
|
5758
|
+
}
|
|
5759
|
+
catch (error) {
|
|
5760
|
+
// The primary message already exists at Lark. Index failure must never
|
|
5761
|
+
// turn a successful send into exit!=0 (which would invite a duplicate).
|
|
5762
|
+
console.error(`⚠️ 消息已发送,但 VC 监听消息索引写入失败:${error instanceof Error ? error.message : String(error)}`);
|
|
5763
|
+
}
|
|
5764
|
+
};
|
|
5230
5765
|
// ── Voice mode ──────────────────────────────────────────────────────────
|
|
5231
5766
|
// Synthesize the (already-condensed, colloquial) content into a Feishu voice
|
|
5232
5767
|
// bubble and return. Deliberately bypasses the text/card path's mentions,
|
|
@@ -5254,17 +5789,53 @@ async function cmdSend(rest) {
|
|
|
5254
5789
|
const { rmSync } = await import('node:fs');
|
|
5255
5790
|
const appId = s.larkAppId;
|
|
5256
5791
|
const targetChatId = overrideChatId ?? s.chatId;
|
|
5257
|
-
const target = resolveSendTarget({ into: sendInto, topLevel: sendTopLevel, chatScope: s.scope === 'chat', chatId: targetChatId, rootMessageId: s.rootMessageId, replyTargetRootId: s.currentReplyTarget?.rootMessageId, replyTargetTurnId: s.currentReplyTarget?.turnId, currentTurnId });
|
|
5258
|
-
const sendAudio = (fileKey) => target.mode === 'plain'
|
|
5259
|
-
? sendMessage(appId, target.chatId, JSON.stringify({ file_key: fileKey }), 'audio')
|
|
5260
|
-
: replyMessage(appId, target.rootMessageId, JSON.stringify({ file_key: fileKey }), 'audio', true);
|
|
5261
5792
|
let dir;
|
|
5262
5793
|
try {
|
|
5263
5794
|
const out = await synthesizeVoiceOpus(appId, content);
|
|
5264
5795
|
dir = out.dir;
|
|
5265
5796
|
const fileKey = await uploadFile(appId, out.path, { duration: out.durationMs });
|
|
5266
5797
|
const sentAtMs = Date.now();
|
|
5267
|
-
const
|
|
5798
|
+
const proposedOutput = {
|
|
5799
|
+
targetChatId,
|
|
5800
|
+
msgType: 'audio',
|
|
5801
|
+
content: JSON.stringify({ file_key: fileKey }),
|
|
5802
|
+
};
|
|
5803
|
+
const prepared = prepareVcMeetingListenerReply(proposedOutput);
|
|
5804
|
+
if (prepared?.kind === 'conflict') {
|
|
5805
|
+
throw new Error(`VC listener assistant reply refused (${prepared.reason}): ${prepared.detail}`);
|
|
5806
|
+
}
|
|
5807
|
+
const canonicalOutput = prepared?.canonicalOutput ?? proposedOutput;
|
|
5808
|
+
if (prepared?.outputMismatch) {
|
|
5809
|
+
console.error(`⚠️ VC listener voice reply output_mismatch action=${prepared.ref.actionId}; `
|
|
5810
|
+
+ 'reusing first canonical output');
|
|
5811
|
+
}
|
|
5812
|
+
let messageId;
|
|
5813
|
+
if (prepared?.kind === 'succeeded' && prepared.messageId) {
|
|
5814
|
+
messageId = prepared.messageId;
|
|
5815
|
+
}
|
|
5816
|
+
else {
|
|
5817
|
+
revalidateVcMeetingManagedSend();
|
|
5818
|
+
const canonicalTarget = resolveSendTarget({
|
|
5819
|
+
into: sendInto,
|
|
5820
|
+
topLevel: sendTopLevel,
|
|
5821
|
+
chatScope: s.scope === 'chat',
|
|
5822
|
+
chatId: canonicalOutput.targetChatId,
|
|
5823
|
+
rootMessageId: s.rootMessageId,
|
|
5824
|
+
replyTargetRootId: s.currentReplyTarget?.rootMessageId,
|
|
5825
|
+
replyTargetTurnId: s.currentReplyTarget?.turnId,
|
|
5826
|
+
currentTurnId,
|
|
5827
|
+
});
|
|
5828
|
+
const managedProviderOptions = prepared
|
|
5829
|
+
? { suppressHook: true }
|
|
5830
|
+
: undefined;
|
|
5831
|
+
messageId = canonicalTarget.mode === 'plain'
|
|
5832
|
+
? await sendMessage(appId, canonicalTarget.chatId, canonicalOutput.content, canonicalOutput.msgType, prepared?.providerKey, undefined, managedProviderOptions)
|
|
5833
|
+
: await replyMessage(appId, canonicalTarget.rootMessageId, canonicalOutput.content, canonicalOutput.msgType, true, prepared?.providerKey, undefined, managedProviderOptions);
|
|
5834
|
+
if (prepared?.kind === 'send' || prepared?.kind === 'succeeded') {
|
|
5835
|
+
finishVcMeetingImReply(resolveDataDir(), prepared.ref, messageId);
|
|
5836
|
+
}
|
|
5837
|
+
}
|
|
5838
|
+
recordVcMeetingPrimaryOutput(messageId, canonicalOutput.targetChatId);
|
|
5268
5839
|
// 语音也是一次回复:写 bridge fallback marker,否则本轮会被判为"没发 botmux send"
|
|
5269
5840
|
// 而触发兜底,多补一张文本卡。与文本/卡片路径同口径:仅同话题回复才记。
|
|
5270
5841
|
if (!sendTopLevel && !overrideChatId && !sendInto) {
|
|
@@ -5383,6 +5954,8 @@ async function cmdSend(rest) {
|
|
|
5383
5954
|
mentions.push({ open_id: m.trim(), name: '' });
|
|
5384
5955
|
}
|
|
5385
5956
|
}
|
|
5957
|
+
const replyTargetSenderOpenId = explicitVcMeetingImOrigin?.replyTargetSenderOpenId
|
|
5958
|
+
?? s.quoteTargetSenderOpenId;
|
|
5386
5959
|
// @ hard-gate (config.send.requireMentionDecision, default on): force the
|
|
5387
5960
|
// model to make an explicit @ decision before sending. --top-level publish
|
|
5388
5961
|
// is exempt. The error text adapts to who is being replied to (人 / bot).
|
|
@@ -5392,7 +5965,7 @@ async function cmdSend(rest) {
|
|
|
5392
5965
|
hasMentionArgs: mentionArgs.length > 0,
|
|
5393
5966
|
mentionBack,
|
|
5394
5967
|
noMention,
|
|
5395
|
-
hasQuoteTargetSender: !!
|
|
5968
|
+
hasQuoteTargetSender: !!replyTargetSenderOpenId,
|
|
5396
5969
|
});
|
|
5397
5970
|
if (!mentionGate.ok) {
|
|
5398
5971
|
console.error(mentionGate.error);
|
|
@@ -5401,9 +5974,9 @@ async function cmdSend(rest) {
|
|
|
5401
5974
|
// --mention-back: @ the sender of the message this turn is replying to
|
|
5402
5975
|
// (open_id from the session — model needn't know it). Bare-name form so it
|
|
5403
5976
|
// renders as a trailing <at>.
|
|
5404
|
-
if (mentionBack &&
|
|
5405
|
-
&& !mentions.some(m => m.open_id ===
|
|
5406
|
-
mentions.push({ open_id:
|
|
5977
|
+
if (mentionBack && replyTargetSenderOpenId
|
|
5978
|
+
&& !mentions.some(m => m.open_id === replyTargetSenderOpenId)) {
|
|
5979
|
+
mentions.push({ open_id: replyTargetSenderOpenId, name: '' });
|
|
5407
5980
|
}
|
|
5408
5981
|
// Validate file paths
|
|
5409
5982
|
for (const p of [...images, ...files, ...videos, ...videoCovers]) {
|
|
@@ -5463,7 +6036,7 @@ async function cmdSend(rest) {
|
|
|
5463
6036
|
// Sub-topic seed if `openId` is a dispatched sub-bot in an active topic that is
|
|
5464
6037
|
// NOT reachable in the current conversation; else null. The bot I'm replying to
|
|
5465
6038
|
// here (quoteTargetSenderOpenId) is reachable, so it's never treated as off-topic.
|
|
5466
|
-
const offTopicSubBotSeed = (openId) => offTopicSubBotTopic({ mentionOpenId: openId, quoteTargetSenderOpenId:
|
|
6039
|
+
const offTopicSubBotSeed = (openId) => offTopicSubBotTopic({ mentionOpenId: openId, quoteTargetSenderOpenId: replyTargetSenderOpenId, chatId: targetChatId, registry: dispatchReg, activeSeeds: dispatchActiveSeeds });
|
|
5467
6040
|
// Explicit --mention / --mention-back of an off-topic sub-bot → block + point to
|
|
5468
6041
|
// the right command (--anyway overrides). Prose @Name injection is filtered
|
|
5469
6042
|
// (dropped, not blocked) at its own site below.
|
|
@@ -5494,9 +6067,14 @@ async function cmdSend(rest) {
|
|
|
5494
6067
|
// Dispatch helper: top-level / chat-scope send vs reply-in-thread, single
|
|
5495
6068
|
// decision point. Used for file attachments (always plain in chat scope).
|
|
5496
6069
|
const sendTarget = resolveSendTarget({ into: sendInto, topLevel: sendTopLevel, chatScope: isChatScope, chatId: targetChatId, rootMessageId: s.rootMessageId, replyTargetRootId: s.currentReplyTarget?.rootMessageId, replyTargetTurnId: s.currentReplyTarget?.turnId, currentTurnId });
|
|
5497
|
-
const dispatch = (content, msgType) =>
|
|
5498
|
-
|
|
5499
|
-
|
|
6070
|
+
const dispatch = (content, msgType, uuid, suppressHook) => {
|
|
6071
|
+
// This closure also carries attachments, so every Lark call re-checks the
|
|
6072
|
+
// exact durable attempt/member instead of inheriting the early cmd gate.
|
|
6073
|
+
revalidateVcMeetingManagedSend();
|
|
6074
|
+
return sendTarget.mode === 'plain'
|
|
6075
|
+
? sendMessage(appId, sendTarget.chatId, content, msgType, uuid, hookContext, suppressHook ? { suppressHook: true } : undefined)
|
|
6076
|
+
: replyMessage(appId, sendTarget.rootMessageId, content, msgType, true, uuid, hookContext, suppressHook ? { suppressHook: true } : undefined);
|
|
6077
|
+
};
|
|
5500
6078
|
const recordBridgeSendMarker = (sentAtMs, messageId, sentContent) => {
|
|
5501
6079
|
try {
|
|
5502
6080
|
const markerDir = join(resolveDataDir(), 'turn-sends');
|
|
@@ -5515,33 +6093,83 @@ async function cmdSend(rest) {
|
|
|
5515
6093
|
// scope and --top-level never quote. Withdrawn target → fall back to plain.
|
|
5516
6094
|
const quoteTargetId = sendInto || sendTarget.mode === 'thread' ? undefined : resolveQuoteTarget({
|
|
5517
6095
|
isChatScope, sendTopLevel, noQuote, explicitQuote,
|
|
5518
|
-
|
|
6096
|
+
// A durable meeting delivery has no Lark-authored trigger message. Never
|
|
6097
|
+
// inherit the receiver session's latest human quote target: that state can
|
|
6098
|
+
// belong to another queued IM turn and is not part of the delivery action.
|
|
6099
|
+
sessionQuoteTargetId: vcMeetingDeliveryReplyOrigin
|
|
6100
|
+
? undefined
|
|
6101
|
+
: explicitVcMeetingImOrigin?.larkMessageId ?? s.quoteTargetId,
|
|
5519
6102
|
});
|
|
5520
6103
|
let primaryQuotedId = null;
|
|
6104
|
+
let vcMeetingListenerReplyReplay = false;
|
|
5521
6105
|
const dispatchPrimary = async (content, msgType) => {
|
|
5522
|
-
|
|
5523
|
-
|
|
6106
|
+
// `dispatchPrimaryMessage` may call replyMessage directly for a quote, so
|
|
6107
|
+
// fence immediately before preparing/performing that primary effect too.
|
|
6108
|
+
revalidateVcMeetingManagedSend();
|
|
6109
|
+
const proposedOutput = {
|
|
5524
6110
|
targetChatId,
|
|
5525
|
-
quoteTargetId,
|
|
5526
|
-
content,
|
|
6111
|
+
...(quoteTargetId ? { quoteTargetId } : {}),
|
|
5527
6112
|
msgType,
|
|
6113
|
+
content,
|
|
6114
|
+
};
|
|
6115
|
+
const prepared = prepareVcMeetingListenerReply(proposedOutput);
|
|
6116
|
+
if (prepared?.kind === 'conflict') {
|
|
6117
|
+
throw new Error(`VC listener assistant reply refused (${prepared.reason}): ${prepared.detail}`);
|
|
6118
|
+
}
|
|
6119
|
+
const canonicalOutput = prepared?.canonicalOutput ?? proposedOutput;
|
|
6120
|
+
if (prepared?.outputMismatch) {
|
|
6121
|
+
console.error(`⚠️ VC listener reply output_mismatch action=${prepared.ref.actionId} `
|
|
6122
|
+
+ `turn=${explicitVcMeetingImOrigin?.larkMessageId ?? vcMeetingDeliveryReplyOrigin?.stableTurnId}; `
|
|
6123
|
+
+ 'reusing first canonical output');
|
|
6124
|
+
}
|
|
6125
|
+
if (prepared?.kind === 'succeeded' && prepared.messageId) {
|
|
6126
|
+
vcMeetingListenerReplyReplay = true;
|
|
6127
|
+
primaryQuotedId = canonicalOutput.quoteTargetId ?? null;
|
|
6128
|
+
recordVcMeetingPrimaryOutput(prepared.messageId, canonicalOutput.targetChatId);
|
|
6129
|
+
return prepared.messageId;
|
|
6130
|
+
}
|
|
6131
|
+
if (prepared?.kind === 'succeeded') {
|
|
6132
|
+
// A legacy/incomplete terminal record without the provider message id is
|
|
6133
|
+
// still safe to reconcile through the same stable UUID.
|
|
6134
|
+
vcMeetingListenerReplyReplay = true;
|
|
6135
|
+
}
|
|
6136
|
+
else if (prepared?.kind === 'send') {
|
|
6137
|
+
vcMeetingListenerReplyReplay = prepared.replay;
|
|
6138
|
+
}
|
|
6139
|
+
const result = await dispatchPrimaryMessage({ sendMessage, replyMessage }, {
|
|
6140
|
+
appId,
|
|
6141
|
+
targetChatId: canonicalOutput.targetChatId,
|
|
6142
|
+
quoteTargetId: canonicalOutput.quoteTargetId,
|
|
6143
|
+
content: canonicalOutput.content,
|
|
6144
|
+
msgType: canonicalOutput.msgType,
|
|
6145
|
+
...(prepared ? { uuid: prepared.providerKey } : {}),
|
|
6146
|
+
// Managed meeting output must never fan out through user-configured
|
|
6147
|
+
// outbound hooks, including its first provider attempt.
|
|
6148
|
+
...(prepared ? { suppressHook: true } : {}),
|
|
5528
6149
|
hookContext,
|
|
5529
6150
|
MessageWithdrawnError,
|
|
5530
|
-
|
|
6151
|
+
// Explicit VC IM --into is rejected above, so an unquoted first send
|
|
6152
|
+
// retains the normal chat-scope dispatch semantics. On a mismatch the
|
|
6153
|
+
// frozen canonical target remains authoritative.
|
|
6154
|
+
dispatch: prepared?.outputMismatch
|
|
6155
|
+
? (body, type, uuid, suppressHook) => {
|
|
6156
|
+
revalidateVcMeetingManagedSend();
|
|
6157
|
+
return sendMessage(appId, canonicalOutput.targetChatId, body, type, uuid, hookContext, suppressHook ? { suppressHook: true } : undefined);
|
|
6158
|
+
}
|
|
6159
|
+
: dispatch,
|
|
6160
|
+
beforeQuoteFallback: revalidateVcMeetingManagedSend,
|
|
5531
6161
|
onQuoteWithdrawn: (id) => {
|
|
5532
6162
|
console.error(`引用目标 ${id} 已撤回,改为普通发送`);
|
|
5533
6163
|
},
|
|
5534
6164
|
});
|
|
5535
6165
|
primaryQuotedId = result.primaryQuotedId;
|
|
6166
|
+
if (prepared?.kind === 'send' || prepared?.kind === 'succeeded') {
|
|
6167
|
+
finishVcMeetingImReply(resolveDataDir(), prepared.ref, result.messageId);
|
|
6168
|
+
}
|
|
6169
|
+
recordVcMeetingPrimaryOutput(result.messageId, canonicalOutput.targetChatId);
|
|
5536
6170
|
return result.messageId;
|
|
5537
6171
|
};
|
|
5538
6172
|
try {
|
|
5539
|
-
// Upload images in parallel
|
|
5540
|
-
const imageKeys = [];
|
|
5541
|
-
if (images.length > 0) {
|
|
5542
|
-
const results = await Promise.all(images.map(p => uploadImage(appId, p)));
|
|
5543
|
-
imageKeys.push(...results);
|
|
5544
|
-
}
|
|
5545
6173
|
// A file-sandbox relay supplies a host-private copy normalized inside the
|
|
5546
6174
|
// sandbox namespace. Voice/doc-comment paths returned above and therefore
|
|
5547
6175
|
// continue using the untouched raw content.
|
|
@@ -5553,6 +6181,31 @@ async function cmdSend(rest) {
|
|
|
5553
6181
|
}
|
|
5554
6182
|
catch { /* fall back safely below */ }
|
|
5555
6183
|
}
|
|
6184
|
+
// `preparedContentFile` is presentation data produced inside an untrusted
|
|
6185
|
+
// sandbox and only TOCTOU-materialized by the host watcher. It is not an
|
|
6186
|
+
// authorization proof. Re-check the exact body/attachment shape that will
|
|
6187
|
+
// reach Lark after JSON extraction and prepared-content substitution, and
|
|
6188
|
+
// do so before even an image upload creates a provider-side effect.
|
|
6189
|
+
const managedRenderedPayloadError = managedVcSendPayloadError({
|
|
6190
|
+
managed: !!vcMeetingManagedSendOrigin,
|
|
6191
|
+
asVoice: false,
|
|
6192
|
+
hasBodyText: !!text.trim(),
|
|
6193
|
+
imageCount: images.length,
|
|
6194
|
+
fileCount: files.length,
|
|
6195
|
+
videoCount: videoAttachments.length,
|
|
6196
|
+
containsNativeAtTag: containsLarkAtTag(text),
|
|
6197
|
+
});
|
|
6198
|
+
if (managedRenderedPayloadError) {
|
|
6199
|
+
console.error(`botmux send refused for a managed VC turn: ${managedRenderedPayloadError}`);
|
|
6200
|
+
process.exit(2);
|
|
6201
|
+
}
|
|
6202
|
+
// Upload images only after the final rendered payload has passed the
|
|
6203
|
+
// managed side-effect gate above.
|
|
6204
|
+
const imageKeys = [];
|
|
6205
|
+
if (images.length > 0) {
|
|
6206
|
+
const results = await Promise.all(images.map(p => uploadImage(appId, p)));
|
|
6207
|
+
imageKeys.push(...results);
|
|
6208
|
+
}
|
|
5556
6209
|
// Auto-detect @BotName in text and inject as mentions, using the sender
|
|
5557
6210
|
// app's cross-ref file for per-app-scoped open_ids. Without this, a plain
|
|
5558
6211
|
// "@Claude" in text only triggers IPC routing but Lark UI shows it as
|
|
@@ -5577,7 +6230,7 @@ async function cmdSend(rest) {
|
|
|
5577
6230
|
// --no-mention 显式不 @ 任何人:跳过正文 @BotName 的自动注入,否则正文里
|
|
5578
6231
|
// 出现的 @名字 仍会被注入成 <at>,破坏 --no-mention 语义、还可能误触发对方
|
|
5579
6232
|
// bot(正是要避免的循环 @)。botEntries/crossRef 仍需加载供 footer 寻址用。
|
|
5580
|
-
if (!noMention) {
|
|
6233
|
+
if (!noMention && !vcMeetingManagedSendOrigin) {
|
|
5581
6234
|
const alreadyMentioned = new Set(mentions.map(m => m.open_id));
|
|
5582
6235
|
// Scan a code-span-stripped copy so a bot name quoted inside backticks or a
|
|
5583
6236
|
// fenced block (e.g. an example `botmux send --mention @Bot …` or an
|
|
@@ -5658,7 +6311,9 @@ async function cmdSend(rest) {
|
|
|
5658
6311
|
// (Codex review P2)。--top-level 同样无特定收件人。
|
|
5659
6312
|
const footerAddressing = (sendTopLevel || noMention)
|
|
5660
6313
|
? { sendTo: undefined, cc: [] }
|
|
5661
|
-
: buildFooterAddressing(
|
|
6314
|
+
: buildFooterAddressing(explicitVcMeetingImOrigin?.replyTargetSenderOpenId
|
|
6315
|
+
? { ...s, lastCallerOpenId: explicitVcMeetingImOrigin.replyTargetSenderOpenId }
|
|
6316
|
+
: s, {
|
|
5662
6317
|
isOncall: !!oncallEntry,
|
|
5663
6318
|
hasExplicitBotMention: explicitKnownBotMention,
|
|
5664
6319
|
knownBotOpenIds,
|
|
@@ -5711,7 +6366,13 @@ async function cmdSend(rest) {
|
|
|
5711
6366
|
// and updates primaryQuotedId). Otherwise a bare `--videos … --no-mention`
|
|
5712
6367
|
// reply in a 普通群 lands as a standalone message that doesn't quote the
|
|
5713
6368
|
// trigger — unlike file-only/image-only sends whose primary card quotes.
|
|
5714
|
-
const videoResult = await sendVideoAttachments({
|
|
6369
|
+
const videoResult = await sendVideoAttachments({
|
|
6370
|
+
uploadFile,
|
|
6371
|
+
uploadImage,
|
|
6372
|
+
dispatch,
|
|
6373
|
+
primaryDispatch: dispatchPrimary,
|
|
6374
|
+
...(vcMeetingManagedSendOrigin ? { maxMessages: 1 } : {}),
|
|
6375
|
+
}, appId, videoAttachments);
|
|
5715
6376
|
failedVideoAttachments = videoResult.failed;
|
|
5716
6377
|
if (videoResult.sent.length === 0) {
|
|
5717
6378
|
const first = failedVideoAttachments[0]?.error ?? 'unknown error';
|
|
@@ -5754,7 +6415,7 @@ async function cmdSend(rest) {
|
|
|
5754
6415
|
// default botmux, '' → suppressed, else custom). Same resolver/rule as
|
|
5755
6416
|
// the daemon's card builders so both send paths render identically.
|
|
5756
6417
|
const footerParts = [];
|
|
5757
|
-
const brandSeg = brandFooterSegment(resolveBrandLabel(appId));
|
|
6418
|
+
const brandSeg = brandFooterSegment(renderBrandTemplate(resolveBrandLabel(appId), s.workingDir));
|
|
5758
6419
|
if (brandSeg)
|
|
5759
6420
|
footerParts.push(brandSeg);
|
|
5760
6421
|
// All real mentions land on one footer line: human addressee first, then
|
|
@@ -5776,7 +6437,9 @@ async function cmdSend(rest) {
|
|
|
5776
6437
|
// v2 cards put buttons inside column_set/column — never the 1.x
|
|
5777
6438
|
// `tag:'action'` container (Feishu rejects it, error 200861).
|
|
5778
6439
|
let voiceOn = false;
|
|
5779
|
-
|
|
6440
|
+
// A managed receiver card has no callback controls: a voice-summary
|
|
6441
|
+
// button would open a second, unledgered model/output action when clicked.
|
|
6442
|
+
if (!sendTopLevel && !vcMeetingManagedSendOrigin) {
|
|
5780
6443
|
try {
|
|
5781
6444
|
const { isVoiceConfigured } = await import('./services/voice/index.js');
|
|
5782
6445
|
voiceOn = isVoiceConfigured(appId);
|
|
@@ -5842,7 +6505,7 @@ async function cmdSend(rest) {
|
|
|
5842
6505
|
// the success JSON. Pure-video sends have no text/card primary, so the media
|
|
5843
6506
|
// message above is the primary and failures before any media is sent still
|
|
5844
6507
|
// surface as command failure.
|
|
5845
|
-
if (!pureVideoSend) {
|
|
6508
|
+
if (!pureVideoSend && !vcMeetingListenerReplyReplay) {
|
|
5846
6509
|
({ failed: failedAttachments } = await sendFileAttachments({ uploadFile, dispatch }, appId, files));
|
|
5847
6510
|
const videoResult = await sendVideoAttachments({ uploadFile, uploadImage, dispatch }, appId, videoAttachments);
|
|
5848
6511
|
failedVideoAttachments = videoResult.failed;
|
|
@@ -5874,11 +6537,29 @@ async function cmdSend(rest) {
|
|
|
5874
6537
|
const daemon = findDaemon(appId);
|
|
5875
6538
|
if (!daemon)
|
|
5876
6539
|
throw new Error(`找不到 daemon (larkAppId=${appId})`);
|
|
5877
|
-
const
|
|
6540
|
+
const originCapability = readManagedOriginCapability(resolveDataDir(), sid, process.env.BOTMUX_SEND_RELAY)?.capability;
|
|
6541
|
+
const request = {
|
|
5878
6542
|
method: 'POST',
|
|
5879
6543
|
headers: { 'content-type': 'application/json' },
|
|
5880
|
-
body: JSON.stringify({
|
|
5881
|
-
|
|
6544
|
+
body: JSON.stringify({
|
|
6545
|
+
sessionId: sid,
|
|
6546
|
+
larkAppId: appId,
|
|
6547
|
+
action: 'raise',
|
|
6548
|
+
kind: attention.kind,
|
|
6549
|
+
reason: text.trim(),
|
|
6550
|
+
originCapability,
|
|
6551
|
+
originTurnId: liveMarkerCtx?.turnId,
|
|
6552
|
+
originDispatchAttempt: liveMarkerCtx?.dispatchAttempt,
|
|
6553
|
+
}),
|
|
6554
|
+
};
|
|
6555
|
+
let secret;
|
|
6556
|
+
try {
|
|
6557
|
+
secret = loadDaemonIpcSecret();
|
|
6558
|
+
}
|
|
6559
|
+
catch { /* Seatbelt/read-isolated CLI */ }
|
|
6560
|
+
const res = secret
|
|
6561
|
+
? await fetchDaemonIpc(daemon.ipcPort, '/api/attention', request, secret)
|
|
6562
|
+
: await fetch(`http://127.0.0.1:${daemon.ipcPort}/api/attention`, request);
|
|
5882
6563
|
if (!res.ok)
|
|
5883
6564
|
throw new Error(`daemon HTTP ${res.status}`);
|
|
5884
6565
|
attentionRaised = true;
|
|
@@ -6443,13 +7124,32 @@ async function postAsk(body) {
|
|
|
6443
7124
|
}
|
|
6444
7125
|
let res;
|
|
6445
7126
|
try {
|
|
6446
|
-
|
|
7127
|
+
const requestBody = { ...body };
|
|
7128
|
+
if (typeof requestBody.originCapability !== 'string') {
|
|
7129
|
+
const sessionId = typeof requestBody.sessionId === 'string'
|
|
7130
|
+
? requestBody.sessionId
|
|
7131
|
+
: undefined;
|
|
7132
|
+
const claim = readManagedOriginCapability(resolveDataDir(), sessionId, process.env.BOTMUX_SEND_RELAY);
|
|
7133
|
+
if (claim)
|
|
7134
|
+
requestBody.originCapability = claim.capability;
|
|
7135
|
+
}
|
|
7136
|
+
const init = {
|
|
6447
7137
|
method: 'POST',
|
|
6448
7138
|
headers: { 'content-type': 'application/json' },
|
|
6449
|
-
body: JSON.stringify(
|
|
7139
|
+
body: JSON.stringify(requestBody),
|
|
6450
7140
|
// No client-side timeout — broker enforces `timeoutMs` and will respond
|
|
6451
7141
|
// with `kind:'timedOut'` so this fetch always settles.
|
|
6452
|
-
}
|
|
7142
|
+
};
|
|
7143
|
+
let hostSecret;
|
|
7144
|
+
if (!process.env.BOTMUX_SEND_RELAY) {
|
|
7145
|
+
try {
|
|
7146
|
+
hostSecret = loadDaemonIpcSecret();
|
|
7147
|
+
}
|
|
7148
|
+
catch { /* read-isolated CLI uses live marker auth */ }
|
|
7149
|
+
}
|
|
7150
|
+
res = hostSecret
|
|
7151
|
+
? await fetchDaemonIpc(daemon.ipcPort, '/api/asks', init, hostSecret)
|
|
7152
|
+
: await fetch(`http://127.0.0.1:${daemon.ipcPort}/api/asks`, init);
|
|
6453
7153
|
}
|
|
6454
7154
|
catch (fetchErr) {
|
|
6455
7155
|
const msg = fetchErr instanceof Error ? fetchErr.message : String(fetchErr);
|
|
@@ -6528,14 +7228,23 @@ async function cmdAsk(sub, rest) {
|
|
|
6528
7228
|
process.exit(2);
|
|
6529
7229
|
}
|
|
6530
7230
|
const larkAppId = process.env.BOTMUX_LARK_APP_ID;
|
|
7231
|
+
const askSessionId = process.env.BOTMUX_SESSION_ID;
|
|
7232
|
+
const liveAskOrigin = resolveSessionContext(resolveDataDir(), askSessionId);
|
|
7233
|
+
const askRelayDir = process.env.BOTMUX_SEND_RELAY;
|
|
7234
|
+
const askOriginCapability = readManagedOriginCapability(resolveDataDir(), askSessionId, askRelayDir)?.capability;
|
|
6531
7235
|
const body = {
|
|
6532
|
-
sessionId:
|
|
7236
|
+
sessionId: askSessionId,
|
|
6533
7237
|
chatId: process.env.BOTMUX_CHAT_ID,
|
|
6534
7238
|
larkAppId,
|
|
6535
7239
|
rootMessageId: process.env.BOTMUX_ROOT_MESSAGE_ID || null,
|
|
6536
7240
|
options,
|
|
6537
7241
|
prompt,
|
|
6538
7242
|
timeoutMs,
|
|
7243
|
+
...(liveAskOrigin?.turnId ? { originTurnId: liveAskOrigin.turnId } : {}),
|
|
7244
|
+
...(liveAskOrigin?.dispatchAttempt !== undefined
|
|
7245
|
+
? { originDispatchAttempt: liveAskOrigin.dispatchAttempt }
|
|
7246
|
+
: {}),
|
|
7247
|
+
...(askOriginCapability ? { originCapability: askOriginCapability } : {}),
|
|
6539
7248
|
};
|
|
6540
7249
|
let result;
|
|
6541
7250
|
try {
|
|
@@ -6758,11 +7467,37 @@ async function cmdSessionReady() {
|
|
|
6758
7467
|
const daemon = findDaemon(larkAppId);
|
|
6759
7468
|
if (daemon) {
|
|
6760
7469
|
try {
|
|
6761
|
-
|
|
7470
|
+
const relayDir = process.env.BOTMUX_SEND_RELAY;
|
|
7471
|
+
const originCapability = readManagedOriginCapability(resolveDataDir(), sessionId, relayDir)?.capability;
|
|
7472
|
+
const liveOrigin = resolveSessionContext(resolveDataDir(), sessionId);
|
|
7473
|
+
const envAttempt = Number(process.env.BOTMUX_DISPATCH_ATTEMPT);
|
|
7474
|
+
const originTurnId = liveOrigin?.turnId ?? process.env.BOTMUX_TURN_ID;
|
|
7475
|
+
const originDispatchAttempt = liveOrigin?.dispatchAttempt
|
|
7476
|
+
?? (Number.isSafeInteger(envAttempt) && envAttempt > 0 ? envAttempt : undefined);
|
|
7477
|
+
const init = {
|
|
6762
7478
|
method: 'POST',
|
|
6763
7479
|
headers: { 'content-type': 'application/json' },
|
|
6764
|
-
body: JSON.stringify({
|
|
6765
|
-
|
|
7480
|
+
body: JSON.stringify({
|
|
7481
|
+
sessionId,
|
|
7482
|
+
source,
|
|
7483
|
+
originCapability,
|
|
7484
|
+
originTurnId,
|
|
7485
|
+
originDispatchAttempt,
|
|
7486
|
+
}),
|
|
7487
|
+
};
|
|
7488
|
+
let hostSecret;
|
|
7489
|
+
if (!relayDir) {
|
|
7490
|
+
try {
|
|
7491
|
+
hostSecret = loadDaemonIpcSecret();
|
|
7492
|
+
}
|
|
7493
|
+
catch { /* Seatbelt/read-isolated CLI */ }
|
|
7494
|
+
}
|
|
7495
|
+
if (!hostSecret) {
|
|
7496
|
+
await fetch(`http://127.0.0.1:${daemon.ipcPort}/api/session-ready`, init);
|
|
7497
|
+
}
|
|
7498
|
+
else {
|
|
7499
|
+
await fetchDaemonIpc(daemon.ipcPort, '/api/session-ready', init, hostSecret);
|
|
7500
|
+
}
|
|
6766
7501
|
}
|
|
6767
7502
|
catch { /* daemon 不可达 → 放弃,worker 走超时兜底 */ }
|
|
6768
7503
|
}
|
|
@@ -6813,7 +7548,7 @@ async function notifyDaemonsReloadLocale() {
|
|
|
6813
7548
|
let failed = 0;
|
|
6814
7549
|
await Promise.all(daemons.map(async (d) => {
|
|
6815
7550
|
try {
|
|
6816
|
-
const r = await
|
|
7551
|
+
const r = await fetchDaemonIpc(d.ipcPort, '/api/locale/reload', { method: 'POST' });
|
|
6817
7552
|
if (r.ok)
|
|
6818
7553
|
notified++;
|
|
6819
7554
|
else
|
|
@@ -7102,13 +7837,44 @@ function getVersion() {
|
|
|
7102
7837
|
}
|
|
7103
7838
|
const command = process.argv[2];
|
|
7104
7839
|
// Workflow safety gate (Slice C0): a CLI invoked inside a workflow
|
|
7105
|
-
// subagent worker (BOTMUX_WORKFLOW=1, set by
|
|
7106
|
-
// trigger chat-facing
|
|
7107
|
-
// in `hostExecutor` activities so they
|
|
7108
|
-
//
|
|
7109
|
-
//
|
|
7840
|
+
// subagent worker (BOTMUX_WORKFLOW=1, set by v3/ephemeral-pool) must not
|
|
7841
|
+
// trigger chat-facing effects, schedule mutations, or recursively authorize /
|
|
7842
|
+
// mutate workflows. Side effects belong in `hostExecutor` activities so they
|
|
7843
|
+
// get `effectAttempted` tracking + reconcile; workflow authorization belongs
|
|
7844
|
+
// to the host/user. Read-only commands stay allowed for introspection.
|
|
7110
7845
|
if (process.env.BOTMUX_WORKFLOW === '1') {
|
|
7111
|
-
|
|
7846
|
+
// Default-deny the root command surface. New botmux commands otherwise
|
|
7847
|
+
// silently become available to a bypass-permission workflow worker until
|
|
7848
|
+
// someone remembers to extend a blacklist. Keep only explicit read-only
|
|
7849
|
+
// introspection plus CLI startup plumbing; mutating subcommands under
|
|
7850
|
+
// schedule/workflow/template/v3 are filtered again below. `mcp serve` is
|
|
7851
|
+
// the stable, botmux-owned Plugin gateway configured for the parent CLI —
|
|
7852
|
+
// it must start inside workflow workers, while every other/future `mcp`
|
|
7853
|
+
// subcommand remains default-denied here.
|
|
7854
|
+
const allowedRoot = new Set([
|
|
7855
|
+
undefined,
|
|
7856
|
+
'--help',
|
|
7857
|
+
'-h',
|
|
7858
|
+
'help',
|
|
7859
|
+
'--version',
|
|
7860
|
+
'-v',
|
|
7861
|
+
'status',
|
|
7862
|
+
'history',
|
|
7863
|
+
'quoted',
|
|
7864
|
+
'bots',
|
|
7865
|
+
'skill',
|
|
7866
|
+
'hook',
|
|
7867
|
+
'session-ready',
|
|
7868
|
+
'mcp',
|
|
7869
|
+
'ask', // dedicated cmdAsk guard emits the humanGate-specific guidance
|
|
7870
|
+
'schedule',
|
|
7871
|
+
'workflow',
|
|
7872
|
+
'template',
|
|
7873
|
+
'v3',
|
|
7874
|
+
]);
|
|
7875
|
+
const rootDenied = !allowedRoot.has(command);
|
|
7876
|
+
const mcpSub = command === 'mcp' ? (process.argv[3] ?? '') : '';
|
|
7877
|
+
const mcpDenied = command === 'mcp' && mcpSub !== 'serve';
|
|
7112
7878
|
const isSchedule = command === 'schedule';
|
|
7113
7879
|
const scheduleSub = isSchedule ? (process.argv[3] ?? '') : '';
|
|
7114
7880
|
const blockedScheduleSub = new Set([
|
|
@@ -7123,12 +7889,56 @@ if (process.env.BOTMUX_WORKFLOW === '1') {
|
|
|
7123
7889
|
'enable',
|
|
7124
7890
|
'run',
|
|
7125
7891
|
]);
|
|
7126
|
-
|
|
7892
|
+
const workflowSub = command === 'workflow' ? (process.argv[3] ?? '') : '';
|
|
7893
|
+
const blockedWorkflowSub = new Set([
|
|
7894
|
+
// v3 grill / authorization state changes.
|
|
7895
|
+
'new',
|
|
7896
|
+
'spec-finalize',
|
|
7897
|
+
'approve-spec',
|
|
7898
|
+
'revise-spec',
|
|
7899
|
+
'architect',
|
|
7900
|
+
'revise-dag',
|
|
7901
|
+
'approve-dag',
|
|
7902
|
+
// Saved Workflow creation / execution and live-run mutations.
|
|
7903
|
+
'save',
|
|
7904
|
+
'run',
|
|
7905
|
+
'start',
|
|
7906
|
+
'retry',
|
|
7907
|
+
'grant',
|
|
7908
|
+
'cancel',
|
|
7909
|
+
]);
|
|
7910
|
+
const templateSub = command === 'template' ? (process.argv[3] ?? '') : '';
|
|
7911
|
+
const blockedTemplateSub = new Set(['migrate-v3', 'archive-runs']);
|
|
7912
|
+
const v3Sub = command === 'v3' ? (process.argv[3] ?? '') : '';
|
|
7913
|
+
const workflowMutation = (command === 'workflow' && blockedWorkflowSub.has(workflowSub)) ||
|
|
7914
|
+
(command === 'template' && blockedTemplateSub.has(templateSub)) ||
|
|
7915
|
+
(command === 'v3' && v3Sub === 'run');
|
|
7916
|
+
if (rootDenied ||
|
|
7917
|
+
mcpDenied ||
|
|
7918
|
+
(isSchedule && blockedScheduleSub.has(scheduleSub)) ||
|
|
7919
|
+
workflowMutation) {
|
|
7127
7920
|
const runId = process.env.BOTMUX_WORKFLOW_RUN_ID ?? '?';
|
|
7128
7921
|
const nodeId = process.env.BOTMUX_WORKFLOW_NODE_ID ?? '?';
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7922
|
+
const sub = isSchedule
|
|
7923
|
+
? scheduleSub
|
|
7924
|
+
: command === 'mcp'
|
|
7925
|
+
? mcpSub
|
|
7926
|
+
: command === 'workflow'
|
|
7927
|
+
? workflowSub
|
|
7928
|
+
: command === 'template'
|
|
7929
|
+
? templateSub
|
|
7930
|
+
: command === 'v3'
|
|
7931
|
+
? v3Sub
|
|
7932
|
+
: '';
|
|
7933
|
+
const guidance = mcpDenied
|
|
7934
|
+
? 'Only the botmux-owned Plugin MCP gateway bootstrap (`mcp serve`) is available inside a workflow subagent.'
|
|
7935
|
+
: workflowMutation
|
|
7936
|
+
? 'Workflow authorization and run mutations must be initiated by the host/user, not a subagent.'
|
|
7937
|
+
: rootDenied
|
|
7938
|
+
? 'This root command is not in the workflow read-only allowlist; chat-facing effects belong in a hostExecutor activity.'
|
|
7939
|
+
: 'Chat-facing or schedule-mutating effects belong in a hostExecutor activity, not a subagent.';
|
|
7940
|
+
console.error(`botmux ${command}${sub ? ` ${sub}` : ''} refused inside workflow ` +
|
|
7941
|
+
`subagent (run=${runId} node=${nodeId}). ${guidance}`);
|
|
7132
7942
|
process.exit(2);
|
|
7133
7943
|
}
|
|
7134
7944
|
}
|
|
@@ -7650,7 +8460,7 @@ switch (command) {
|
|
|
7650
8460
|
console.log(getVersion());
|
|
7651
8461
|
break;
|
|
7652
8462
|
case 'setup': {
|
|
7653
|
-
// 带子命令(list/add/edit/remove/help)走脚本化非 TUI 模式;空参数 / 纯
|
|
8463
|
+
// 带子命令(list/add/configure/edit/remove/help)走脚本化非 TUI 模式;空参数 / 纯
|
|
7654
8464
|
// flag(如 --no-open-platform-auto)保持原交互 TUI,向后兼容。
|
|
7655
8465
|
const setupArgs = process.argv.slice(3);
|
|
7656
8466
|
if (isScriptedSetupInvocation(setupArgs))
|
|
@@ -7678,6 +8488,7 @@ switch (command) {
|
|
|
7678
8488
|
cmdStatus();
|
|
7679
8489
|
break;
|
|
7680
8490
|
case 'upgrade':
|
|
8491
|
+
case 'update':
|
|
7681
8492
|
cmdUpgrade();
|
|
7682
8493
|
break;
|
|
7683
8494
|
case 'dashboard':
|
|
@@ -7704,6 +8515,12 @@ switch (command) {
|
|
|
7704
8515
|
case 'suspend':
|
|
7705
8516
|
await cmdSuspend();
|
|
7706
8517
|
break;
|
|
8518
|
+
case 'slash':
|
|
8519
|
+
await cmdSlash();
|
|
8520
|
+
break;
|
|
8521
|
+
case 'cd':
|
|
8522
|
+
await cmdCd();
|
|
8523
|
+
break;
|
|
7707
8524
|
case 'term-link':
|
|
7708
8525
|
await cmdTermLink(process.argv.slice(3));
|
|
7709
8526
|
break;
|
|
@@ -7763,6 +8580,11 @@ switch (command) {
|
|
|
7763
8580
|
}
|
|
7764
8581
|
case 'workflow': {
|
|
7765
8582
|
const wfSub = process.argv[3] ?? '';
|
|
8583
|
+
if (wfSub === 'cancel') {
|
|
8584
|
+
// Durable v3 run cancellation. The v2 runtime is retired.
|
|
8585
|
+
await cmdWorkflowCancelV3(process.argv[4], process.argv.slice(5));
|
|
8586
|
+
break;
|
|
8587
|
+
}
|
|
7766
8588
|
if (wfSub === 'start') {
|
|
7767
8589
|
// `botmux workflow start <runId>` — kick a daemon-driven v3 run (so
|
|
7768
8590
|
// humanGate posts approval cards). Needs a live daemon; findDaemon is
|
|
@@ -7771,7 +8593,7 @@ switch (command) {
|
|
|
7771
8593
|
break;
|
|
7772
8594
|
}
|
|
7773
8595
|
if (wfSub === 'retry') {
|
|
7774
|
-
// v3 blocked-node retry
|
|
8596
|
+
// v3 blocked-node retry; the former v2 `resume` verb is retired.
|
|
7775
8597
|
await cmdWorkflowRetry(process.argv[4], process.argv.slice(5));
|
|
7776
8598
|
break;
|
|
7777
8599
|
}
|
|
@@ -7784,6 +8606,11 @@ switch (command) {
|
|
|
7784
8606
|
await cmdWorkflow(wfSub, process.argv.slice(4));
|
|
7785
8607
|
break;
|
|
7786
8608
|
}
|
|
8609
|
+
case 'template': {
|
|
8610
|
+
const { cmdTemplate } = await import('./cli/workflow.js');
|
|
8611
|
+
await cmdTemplate(process.argv[3] ?? '', process.argv.slice(4));
|
|
8612
|
+
break;
|
|
8613
|
+
}
|
|
7787
8614
|
case 'v3': {
|
|
7788
8615
|
// `botmux v3 run <dag.json>` — run a hand-written next-gen (v3) DAG on the
|
|
7789
8616
|
// real ephemeral worker pool, daemon-independent (dogfood path).
|