botmux 2.47.0 → 2.47.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +10 -5
- package/README.md +10 -5
- package/dist/adapters/adopt-route.d.ts +63 -0
- package/dist/adapters/adopt-route.d.ts.map +1 -0
- package/dist/adapters/adopt-route.js +195 -0
- package/dist/adapters/adopt-route.js.map +1 -0
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +11 -0
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.d.ts +11 -0
- package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.js +17 -1
- package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +36 -9
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/adapters/cli/coco.d.ts.map +1 -1
- package/dist/adapters/cli/coco.js +26 -1
- package/dist/adapters/cli/coco.js.map +1 -1
- package/dist/adapters/cli/codex-app.d.ts +4 -0
- package/dist/adapters/cli/codex-app.d.ts.map +1 -0
- package/dist/adapters/cli/codex-app.js +72 -0
- package/dist/adapters/cli/codex-app.js.map +1 -0
- package/dist/adapters/cli/codex.d.ts.map +1 -1
- package/dist/adapters/cli/codex.js +34 -17
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/cursor.d.ts.map +1 -1
- package/dist/adapters/cli/cursor.js +58 -12
- package/dist/adapters/cli/cursor.js.map +1 -1
- package/dist/adapters/cli/gemini.d.ts.map +1 -1
- package/dist/adapters/cli/gemini.js +5 -1
- package/dist/adapters/cli/gemini.js.map +1 -1
- package/dist/adapters/cli/hermes.d.ts +4 -0
- package/dist/adapters/cli/hermes.d.ts.map +1 -0
- package/dist/adapters/cli/hermes.js +40 -0
- package/dist/adapters/cli/hermes.js.map +1 -0
- package/dist/adapters/cli/mira.d.ts +4 -0
- package/dist/adapters/cli/mira.d.ts.map +1 -0
- package/dist/adapters/cli/mira.js +67 -0
- package/dist/adapters/cli/mira.js.map +1 -0
- package/dist/adapters/cli/mtr.d.ts +5 -0
- package/dist/adapters/cli/mtr.d.ts.map +1 -0
- package/dist/adapters/cli/mtr.js +62 -0
- package/dist/adapters/cli/mtr.js.map +1 -0
- package/dist/adapters/cli/opencode.d.ts.map +1 -1
- package/dist/adapters/cli/opencode.js +19 -1
- package/dist/adapters/cli/opencode.js.map +1 -1
- package/dist/adapters/cli/registry.d.ts +5 -1
- package/dist/adapters/cli/registry.d.ts.map +1 -1
- package/dist/adapters/cli/registry.js +22 -2
- package/dist/adapters/cli/registry.js.map +1 -1
- package/dist/adapters/cli/shared-hints.d.ts +1 -1
- package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
- package/dist/adapters/cli/shared-hints.js +2 -1
- package/dist/adapters/cli/shared-hints.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +35 -2
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/adapters/hook-command.d.ts +18 -0
- package/dist/adapters/hook-command.d.ts.map +1 -0
- package/dist/adapters/hook-command.js +38 -0
- package/dist/adapters/hook-command.js.map +1 -0
- package/dist/adapters/hook-installer.d.ts +14 -0
- package/dist/adapters/hook-installer.d.ts.map +1 -0
- package/dist/adapters/hook-installer.js +192 -0
- package/dist/adapters/hook-installer.js.map +1 -0
- package/dist/bot-registry.d.ts +59 -0
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +67 -0
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/bots-list-output.d.ts +8 -0
- package/dist/cli/bots-list-output.d.ts.map +1 -1
- package/dist/cli/bots-list-output.js +9 -0
- package/dist/cli/bots-list-output.js.map +1 -1
- package/dist/cli.d.ts +15 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +603 -106
- package/dist/cli.js.map +1 -1
- package/dist/codex-app-runner.d.ts +3 -0
- package/dist/codex-app-runner.d.ts.map +1 -0
- package/dist/codex-app-runner.js +512 -0
- package/dist/codex-app-runner.js.map +1 -0
- package/dist/config.d.ts +11 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -4
- package/dist/config.js.map +1 -1
- package/dist/core/ask-api.d.ts +47 -0
- package/dist/core/ask-api.d.ts.map +1 -0
- package/dist/core/ask-api.js +139 -0
- package/dist/core/ask-api.js.map +1 -0
- package/dist/core/ask-args.d.ts +53 -0
- package/dist/core/ask-args.d.ts.map +1 -0
- package/dist/core/ask-args.js +122 -0
- package/dist/core/ask-args.js.map +1 -0
- package/dist/core/ask-broker.d.ts +98 -0
- package/dist/core/ask-broker.d.ts.map +1 -0
- package/dist/core/ask-broker.js +329 -0
- package/dist/core/ask-broker.js.map +1 -0
- package/dist/core/ask-hook/claude-code.d.ts +50 -0
- package/dist/core/ask-hook/claude-code.d.ts.map +1 -0
- package/dist/core/ask-hook/claude-code.js +145 -0
- package/dist/core/ask-hook/claude-code.js.map +1 -0
- package/dist/core/ask-hook/codex.d.ts +43 -0
- package/dist/core/ask-hook/codex.d.ts.map +1 -0
- package/dist/core/ask-hook/codex.js +69 -0
- package/dist/core/ask-hook/codex.js.map +1 -0
- package/dist/core/ask-hook/opencode.d.ts +41 -0
- package/dist/core/ask-hook/opencode.d.ts.map +1 -0
- package/dist/core/ask-hook/opencode.js +108 -0
- package/dist/core/ask-hook/opencode.js.map +1 -0
- package/dist/core/ask-hook/registry.d.ts +3 -0
- package/dist/core/ask-hook/registry.d.ts.map +1 -0
- package/dist/core/ask-hook/registry.js +12 -0
- package/dist/core/ask-hook/registry.js.map +1 -0
- package/dist/core/ask-hook/types.d.ts +26 -0
- package/dist/core/ask-hook/types.d.ts.map +1 -0
- package/dist/core/ask-hook/types.js +2 -0
- package/dist/core/ask-hook/types.js.map +1 -0
- package/dist/core/ask-types.d.ts +146 -0
- package/dist/core/ask-types.d.ts.map +1 -0
- package/dist/core/ask-types.js +18 -0
- package/dist/core/ask-types.js.map +1 -0
- package/dist/core/command-handler.d.ts +29 -0
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +787 -312
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts +2 -0
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +222 -2
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/role-resolver.d.ts +17 -1
- package/dist/core/role-resolver.d.ts.map +1 -1
- package/dist/core/role-resolver.js +64 -10
- package/dist/core/role-resolver.js.map +1 -1
- package/dist/core/session-discovery.d.ts.map +1 -1
- package/dist/core/session-discovery.js +19 -5
- package/dist/core/session-discovery.js.map +1 -1
- package/dist/core/session-manager.d.ts +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +37 -20
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/trigger-session.d.ts +9 -0
- package/dist/core/trigger-session.d.ts.map +1 -0
- package/dist/core/trigger-session.js +158 -0
- package/dist/core/trigger-session.js.map +1 -0
- package/dist/core/types.d.ts +5 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts +141 -0
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +543 -24
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +224 -60
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/auth.d.ts +6 -1
- package/dist/dashboard/auth.d.ts.map +1 -1
- package/dist/dashboard/auth.js +9 -1
- package/dist/dashboard/auth.js.map +1 -1
- package/dist/dashboard/connector-api.d.ts +3 -0
- package/dist/dashboard/connector-api.d.ts.map +1 -0
- package/dist/dashboard/connector-api.js +351 -0
- package/dist/dashboard/connector-api.js.map +1 -0
- package/dist/dashboard/federated-group-core.d.ts +54 -0
- package/dist/dashboard/federated-group-core.d.ts.map +1 -0
- package/dist/dashboard/federated-group-core.js +165 -0
- package/dist/dashboard/federated-group-core.js.map +1 -0
- package/dist/dashboard/federation-api.d.ts +42 -0
- package/dist/dashboard/federation-api.d.ts.map +1 -0
- package/dist/dashboard/federation-api.js +408 -0
- package/dist/dashboard/federation-api.js.map +1 -0
- package/dist/dashboard/federation-spoke-api.d.ts +76 -0
- package/dist/dashboard/federation-spoke-api.d.ts.map +1 -0
- package/dist/dashboard/federation-spoke-api.js +618 -0
- package/dist/dashboard/federation-spoke-api.js.map +1 -0
- package/dist/dashboard/team-group.d.ts +18 -0
- package/dist/dashboard/team-group.d.ts.map +1 -0
- package/dist/dashboard/team-group.js +7 -0
- package/dist/dashboard/team-group.js.map +1 -0
- package/dist/dashboard/trigger-api.d.ts +13 -0
- package/dist/dashboard/trigger-api.d.ts.map +1 -0
- package/dist/dashboard/trigger-api.js +77 -0
- package/dist/dashboard/trigger-api.js.map +1 -0
- package/dist/dashboard/web/app.js +8 -0
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js +205 -21
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/connectors.d.ts +2 -0
- package/dist/dashboard/web/connectors.d.ts.map +1 -0
- package/dist/dashboard/web/connectors.js +187 -0
- package/dist/dashboard/web/connectors.js.map +1 -0
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +43 -5
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +4 -0
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/team-federation.d.ts +3 -0
- package/dist/dashboard/web/team-federation.d.ts.map +1 -0
- package/dist/dashboard/web/team-federation.js +487 -0
- package/dist/dashboard/web/team-federation.js.map +1 -0
- package/dist/dashboard/web/workflows.js +3 -3
- package/dist/dashboard/web/workflows.js.map +1 -1
- package/dist/dashboard/webhook-routes.d.ts +19 -0
- package/dist/dashboard/webhook-routes.d.ts.map +1 -0
- package/dist/dashboard/webhook-routes.js +321 -0
- package/dist/dashboard/webhook-routes.js.map +1 -0
- package/dist/dashboard/workflow-api.d.ts +8 -1
- package/dist/dashboard/workflow-api.d.ts.map +1 -1
- package/dist/dashboard/workflow-api.js +19 -4
- package/dist/dashboard/workflow-api.js.map +1 -1
- package/dist/dashboard-web/app.js +539 -375
- package/dist/dashboard-web/index.html +3 -1
- package/dist/dashboard-web/style.css +22 -0
- package/dist/dashboard.js +199 -2
- package/dist/dashboard.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +104 -11
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +104 -11
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/ask-card.d.ts +55 -0
- package/dist/im/lark/ask-card.d.ts.map +1 -0
- package/dist/im/lark/ask-card.js +328 -0
- package/dist/im/lark/ask-card.js.map +1 -0
- package/dist/im/lark/card-builder.d.ts +108 -3
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +480 -50
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +241 -18
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +83 -0
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +286 -70
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +29 -4
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/grant-command.d.ts +2 -1
- package/dist/im/lark/grant-command.d.ts.map +1 -1
- package/dist/im/lark/grant-command.js +3 -2
- package/dist/im/lark/grant-command.js.map +1 -1
- package/dist/im/lark/identity-cache.d.ts.map +1 -1
- package/dist/im/lark/identity-cache.js +3 -3
- package/dist/im/lark/identity-cache.js.map +1 -1
- package/dist/im/lark/md-card.d.ts +20 -2
- package/dist/im/lark/md-card.d.ts.map +1 -1
- package/dist/im/lark/md-card.js +49 -17
- package/dist/im/lark/md-card.js.map +1 -1
- package/dist/im/lark/message-parser.d.ts.map +1 -1
- package/dist/im/lark/message-parser.js +87 -31
- package/dist/im/lark/message-parser.js.map +1 -1
- package/dist/im/lark/workflow-card-handler.d.ts +2 -2
- package/dist/im/lark/workflow-card-handler.d.ts.map +1 -1
- package/dist/im/lark/workflow-card-handler.js +12 -1
- package/dist/im/lark/workflow-card-handler.js.map +1 -1
- package/dist/im/lark/workflow-progress-card.d.ts.map +1 -1
- package/dist/im/lark/workflow-progress-card.js +53 -0
- package/dist/im/lark/workflow-progress-card.js.map +1 -1
- package/dist/mira-output.d.ts +3 -0
- package/dist/mira-output.d.ts.map +1 -0
- package/dist/mira-output.js +136 -0
- package/dist/mira-output.js.map +1 -0
- package/dist/mira-runner.d.ts +3 -0
- package/dist/mira-runner.d.ts.map +1 -0
- package/dist/mira-runner.js +534 -0
- package/dist/mira-runner.js.map +1 -0
- package/dist/services/bot-owner-store.d.ts +28 -0
- package/dist/services/bot-owner-store.d.ts.map +1 -0
- package/dist/services/bot-owner-store.js +82 -0
- package/dist/services/bot-owner-store.js.map +1 -0
- package/dist/services/bot-profile-store.d.ts +16 -0
- package/dist/services/bot-profile-store.d.ts.map +1 -0
- package/dist/services/bot-profile-store.js +98 -0
- package/dist/services/bot-profile-store.js.map +1 -0
- package/dist/services/brand-store.d.ts +15 -0
- package/dist/services/brand-store.d.ts.map +1 -0
- package/dist/services/brand-store.js +47 -0
- package/dist/services/brand-store.js.map +1 -0
- package/dist/services/card-prefs-store.d.ts +20 -0
- package/dist/services/card-prefs-store.d.ts.map +1 -0
- package/dist/services/card-prefs-store.js +82 -0
- package/dist/services/card-prefs-store.js.map +1 -0
- package/dist/services/codex-bridge-queue.d.ts +1 -0
- package/dist/services/codex-bridge-queue.d.ts.map +1 -1
- package/dist/services/codex-bridge-queue.js +23 -0
- package/dist/services/codex-bridge-queue.js.map +1 -1
- package/dist/services/codex-transcript.d.ts +1 -0
- package/dist/services/codex-transcript.d.ts.map +1 -1
- package/dist/services/codex-transcript.js.map +1 -1
- package/dist/services/connector-store.d.ts +58 -0
- package/dist/services/connector-store.d.ts.map +1 -0
- package/dist/services/connector-store.js +79 -0
- package/dist/services/connector-store.js.map +1 -0
- package/dist/services/deployment-identity.d.ts +22 -0
- package/dist/services/deployment-identity.d.ts.map +1 -0
- package/dist/services/deployment-identity.js +67 -0
- package/dist/services/deployment-identity.js.map +1 -0
- package/dist/services/federation-membership-store.d.ts +23 -0
- package/dist/services/federation-membership-store.d.ts.map +1 -0
- package/dist/services/federation-membership-store.js +66 -0
- package/dist/services/federation-membership-store.js.map +1 -0
- package/dist/services/federation-roster.d.ts +54 -0
- package/dist/services/federation-roster.d.ts.map +1 -0
- package/dist/services/federation-roster.js +51 -0
- package/dist/services/federation-roster.js.map +1 -0
- package/dist/services/federation-store.d.ts +76 -0
- package/dist/services/federation-store.d.ts.map +1 -0
- package/dist/services/federation-store.js +133 -0
- package/dist/services/federation-store.js.map +1 -0
- package/dist/services/grant-store.d.ts +12 -2
- package/dist/services/grant-store.d.ts.map +1 -1
- package/dist/services/grant-store.js +51 -4
- package/dist/services/grant-store.js.map +1 -1
- package/dist/services/group-creator.d.ts +10 -0
- package/dist/services/group-creator.d.ts.map +1 -1
- package/dist/services/group-creator.js +26 -1
- package/dist/services/group-creator.js.map +1 -1
- package/dist/services/groups-store.d.ts +30 -0
- package/dist/services/groups-store.d.ts.map +1 -1
- package/dist/services/groups-store.js +85 -12
- package/dist/services/groups-store.js.map +1 -1
- package/dist/services/hermes-transcript.d.ts +7 -0
- package/dist/services/hermes-transcript.d.ts.map +1 -0
- package/dist/services/hermes-transcript.js +117 -0
- package/dist/services/hermes-transcript.js.map +1 -0
- package/dist/services/invite-store.d.ts +28 -0
- package/dist/services/invite-store.d.ts.map +1 -0
- package/dist/services/invite-store.js +85 -0
- package/dist/services/invite-store.js.map +1 -0
- package/dist/services/pairing-store.d.ts +47 -0
- package/dist/services/pairing-store.d.ts.map +1 -0
- package/dist/services/pairing-store.js +132 -0
- package/dist/services/pairing-store.js.map +1 -0
- package/dist/services/project-scanner.d.ts +10 -0
- package/dist/services/project-scanner.d.ts.map +1 -1
- package/dist/services/project-scanner.js +11 -0
- package/dist/services/project-scanner.js.map +1 -1
- package/dist/services/relay-picker.d.ts +22 -0
- package/dist/services/relay-picker.d.ts.map +1 -0
- package/dist/services/relay-picker.js +62 -0
- package/dist/services/relay-picker.js.map +1 -0
- package/dist/services/send-policy.d.ts +55 -0
- package/dist/services/send-policy.d.ts.map +1 -0
- package/dist/services/send-policy.js +47 -0
- package/dist/services/send-policy.js.map +1 -0
- package/dist/services/session-store.js +1 -1
- package/dist/services/session-store.js.map +1 -1
- package/dist/services/team-roster.d.ts +38 -0
- package/dist/services/team-roster.d.ts.map +1 -0
- package/dist/services/team-roster.js +82 -0
- package/dist/services/team-roster.js.map +1 -0
- package/dist/services/team-store.d.ts +54 -0
- package/dist/services/team-store.d.ts.map +1 -0
- package/dist/services/team-store.js +156 -0
- package/dist/services/team-store.js.map +1 -0
- package/dist/services/trigger-log-store.d.ts +46 -0
- package/dist/services/trigger-log-store.d.ts.map +1 -0
- package/dist/services/trigger-log-store.js +132 -0
- package/dist/services/trigger-log-store.js.map +1 -0
- package/dist/services/trigger-types.d.ts +57 -0
- package/dist/services/trigger-types.d.ts.map +1 -0
- package/dist/services/trigger-types.js +28 -0
- package/dist/services/trigger-types.js.map +1 -0
- package/dist/services/webhook-key.d.ts +16 -0
- package/dist/services/webhook-key.d.ts.map +1 -0
- package/dist/services/webhook-key.js +123 -0
- package/dist/services/webhook-key.js.map +1 -0
- package/dist/services/webhook-lifecycle-extractors.d.ts +15 -0
- package/dist/services/webhook-lifecycle-extractors.d.ts.map +1 -0
- package/dist/services/webhook-lifecycle-extractors.js +59 -0
- package/dist/services/webhook-lifecycle-extractors.js.map +1 -0
- package/dist/services/webhook-lifecycle-store.d.ts +45 -0
- package/dist/services/webhook-lifecycle-store.d.ts.map +1 -0
- package/dist/services/webhook-lifecycle-store.js +159 -0
- package/dist/services/webhook-lifecycle-store.js.map +1 -0
- package/dist/setup/bot-config-editor.d.ts +8 -1
- package/dist/setup/bot-config-editor.d.ts.map +1 -1
- package/dist/setup/bot-config-editor.js +20 -2
- package/dist/setup/bot-config-editor.js.map +1 -1
- package/dist/setup/ensure-tmux.d.ts +0 -22
- package/dist/setup/ensure-tmux.d.ts.map +1 -1
- package/dist/setup/ensure-tmux.js +25 -1
- package/dist/setup/ensure-tmux.js.map +1 -1
- package/dist/setup/verify-permissions.d.ts.map +1 -1
- package/dist/setup/verify-permissions.js +15 -1
- package/dist/setup/verify-permissions.js.map +1 -1
- package/dist/skills/definitions.d.ts +2 -0
- package/dist/skills/definitions.d.ts.map +1 -1
- package/dist/skills/definitions.js +178 -12
- package/dist/skills/definitions.js.map +1 -1
- package/dist/skills/installer.d.ts +34 -0
- package/dist/skills/installer.d.ts.map +1 -1
- package/dist/skills/installer.js +119 -2
- package/dist/skills/installer.js.map +1 -1
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/bot-routing.d.ts +50 -0
- package/dist/utils/bot-routing.d.ts.map +1 -1
- package/dist/utils/bot-routing.js +83 -0
- package/dist/utils/bot-routing.js.map +1 -1
- package/dist/utils/daemon-discovery.d.ts +11 -0
- package/dist/utils/daemon-discovery.d.ts.map +1 -0
- package/dist/utils/daemon-discovery.js +59 -0
- package/dist/utils/daemon-discovery.js.map +1 -0
- package/dist/utils/user-token.d.ts.map +1 -1
- package/dist/utils/user-token.js +0 -2
- package/dist/utils/user-token.js.map +1 -1
- package/dist/worker.js +233 -51
- package/dist/worker.js.map +1 -1
- package/dist/workflows/attempt-resume.d.ts.map +1 -1
- package/dist/workflows/attempt-resume.js +2 -2
- package/dist/workflows/attempt-resume.js.map +1 -1
- package/dist/workflows/definition.d.ts +412 -9
- package/dist/workflows/definition.d.ts.map +1 -1
- package/dist/workflows/definition.js +238 -3
- package/dist/workflows/definition.js.map +1 -1
- package/dist/workflows/events/payloads.d.ts +114 -11
- package/dist/workflows/events/payloads.d.ts.map +1 -1
- package/dist/workflows/events/payloads.js +46 -0
- package/dist/workflows/events/payloads.js.map +1 -1
- package/dist/workflows/events/replay.d.ts +21 -0
- package/dist/workflows/events/replay.d.ts.map +1 -1
- package/dist/workflows/events/replay.js +103 -0
- package/dist/workflows/events/replay.js.map +1 -1
- package/dist/workflows/events/schema.d.ts +1301 -606
- package/dist/workflows/events/schema.d.ts.map +1 -1
- package/dist/workflows/events/schema.js +37 -1
- package/dist/workflows/events/schema.js.map +1 -1
- package/dist/workflows/events/types.d.ts +5 -1
- package/dist/workflows/events/types.d.ts.map +1 -1
- package/dist/workflows/loader.d.ts +14 -0
- package/dist/workflows/loader.d.ts.map +1 -1
- package/dist/workflows/loader.js +27 -0
- package/dist/workflows/loader.js.map +1 -1
- package/dist/workflows/loop.js +58 -0
- package/dist/workflows/loop.js.map +1 -1
- package/dist/workflows/ops-projection.d.ts +58 -0
- package/dist/workflows/ops-projection.d.ts.map +1 -1
- package/dist/workflows/ops-projection.js +74 -0
- package/dist/workflows/ops-projection.js.map +1 -1
- package/dist/workflows/orchestrator.d.ts +65 -1
- package/dist/workflows/orchestrator.d.ts.map +1 -1
- package/dist/workflows/orchestrator.js +486 -74
- package/dist/workflows/orchestrator.js.map +1 -1
- package/dist/workflows/output-binding.d.ts +8 -1
- package/dist/workflows/output-binding.d.ts.map +1 -1
- package/dist/workflows/output-binding.js +75 -11
- package/dist/workflows/output-binding.js.map +1 -1
- package/dist/workflows/runtime.d.ts +1 -1
- package/dist/workflows/runtime.d.ts.map +1 -1
- package/dist/workflows/runtime.js +39 -4
- package/dist/workflows/runtime.js.map +1 -1
- package/dist/workflows/trigger-from-envelope.d.ts +13 -0
- package/dist/workflows/trigger-from-envelope.d.ts.map +1 -0
- package/dist/workflows/trigger-from-envelope.js +67 -0
- package/dist/workflows/trigger-from-envelope.js.map +1 -0
- package/dist/workflows/wait.d.ts +23 -2
- package/dist/workflows/wait.d.ts.map +1 -1
- package/dist/workflows/wait.js +39 -17
- package/dist/workflows/wait.js.map +1 -1
- package/package.json +1 -1
- package/dist/services/feishu-task-client.d.ts +0 -28
- package/dist/services/feishu-task-client.d.ts.map +0 -1
- package/dist/services/feishu-task-client.js +0 -123
- package/dist/services/feishu-task-client.js.map +0 -1
- package/dist/services/task-store.d.ts +0 -37
- package/dist/services/task-store.d.ts.map +0 -1
- package/dist/services/task-store.js +0 -115
- package/dist/services/task-store.js.map +0 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Federation HUB endpoints. Cross-deployment, so mounted BEFORE the dashboard's
|
|
3
|
+
* `?t=` token gate (like webhook/team routes) — they authenticate by their OWN
|
|
4
|
+
* credentials instead:
|
|
5
|
+
* - POST /api/federation/join → an invite code (single-use admission)
|
|
6
|
+
* - POST /api/federation/sync → a syncToken (per-deployment bearer)
|
|
7
|
+
* - GET /api/federation/roster → a syncToken
|
|
8
|
+
*
|
|
9
|
+
* A spoke deployment registers once with an invite, gets a long-lived syncToken,
|
|
10
|
+
* then pushes bots + pulls the aggregated roster with it. See docs/federation-design.md.
|
|
11
|
+
*/
|
|
12
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
13
|
+
import { type LiveBot } from '../services/team-roster.js';
|
|
14
|
+
import { type Fetcher } from './federated-group-core.js';
|
|
15
|
+
export interface FederationApiDeps {
|
|
16
|
+
dataDir?: string;
|
|
17
|
+
fetcher?: Fetcher;
|
|
18
|
+
/** Live daemon-registry bots (authoritative over bots-info.json) for the
|
|
19
|
+
* delegate-group local-bot guard. */
|
|
20
|
+
liveBots?: () => LiveBot[];
|
|
21
|
+
/** Injected by dashboard.ts — used when a HUB delegates 拉群 to THIS spoke
|
|
22
|
+
* (we create the chat with one of OUR local online bots as creator). */
|
|
23
|
+
createTeamGroup?: (args: {
|
|
24
|
+
name: string;
|
|
25
|
+
larkAppIds: string[];
|
|
26
|
+
ownerUnionIds?: string[];
|
|
27
|
+
}) => Promise<{
|
|
28
|
+
ok: boolean;
|
|
29
|
+
chatId?: string;
|
|
30
|
+
shareLink?: string;
|
|
31
|
+
invalidBotIds?: string[];
|
|
32
|
+
invalidOwnerUnionIds?: string[];
|
|
33
|
+
error?: string;
|
|
34
|
+
}>;
|
|
35
|
+
/** Add owners to an existing chat via one of OUR local bots (defaults to
|
|
36
|
+
* ensure-client + addUsersToChatByUnionId). Test seam. Returns the rejected ids. */
|
|
37
|
+
addOwners?: (viaLarkAppId: string, chatId: string, ownerUnionIds: string[]) => Promise<{
|
|
38
|
+
invalidUserIds: string[];
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
export declare function handleFederationApi(req: IncomingMessage, res: ServerResponse, url: URL, deps?: FederationApiDeps): Promise<boolean>;
|
|
42
|
+
//# sourceMappingURL=federation-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"federation-api.d.ts","sourceRoot":"","sources":["../../src/dashboard/federation-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAWjE,OAAO,EAAmB,KAAK,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAE3E,OAAO,EAA6B,KAAK,OAAO,EAAE,MAAM,2BAA2B,CAAC;AA2FpF,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;0CACsC;IACtC,QAAQ,CAAC,EAAE,MAAM,OAAO,EAAE,CAAC;IAC3B;6EACyE;IACzE,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,OAAO,CAAC;QACpG,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;KAC7H,CAAC,CAAC;IACH;yFACqF;IACrF,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC;QAAE,cAAc,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CACtH;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,GAAG,EACR,IAAI,GAAE,iBAAsB,GAC3B,OAAO,CAAC,OAAO,CAAC,CA4LlB"}
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import { config } from '../config.js';
|
|
2
|
+
import { jsonRes } from './workflow-api.js';
|
|
3
|
+
import { consumeInvite } from '../services/invite-store.js';
|
|
4
|
+
import { getTeam } from '../services/team-store.js';
|
|
5
|
+
import { registerDeployment, syncDeployment, getDeploymentByToken, removeDeploymentByToken, } from '../services/federation-store.js';
|
|
6
|
+
import { buildFederatedRoster } from '../services/federation-roster.js';
|
|
7
|
+
import { findMembershipByDelegationToken } from '../services/federation-membership-store.js';
|
|
8
|
+
import { buildTeamRoster } from '../services/team-roster.js';
|
|
9
|
+
import { getDeploymentIdentity } from '../services/deployment-identity.js';
|
|
10
|
+
import { orchestrateFederatedGroup } from './federated-group-core.js';
|
|
11
|
+
import { addUsersToChatByUnionId } from '../services/groups-store.js';
|
|
12
|
+
import { loadBotConfigs, registerBot, getBot } from '../bot-registry.js';
|
|
13
|
+
/** Ensure a Lark client exists for larkAppId in THIS (dashboard) process, which
|
|
14
|
+
* has no bot registry — register on demand from bots.json (carries the secret).
|
|
15
|
+
* Used by delegate-add-owner so it can add a user via a specific local bot. */
|
|
16
|
+
function ensureLocalClient(larkAppId) {
|
|
17
|
+
try {
|
|
18
|
+
getBot(larkAppId);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch { /* not registered yet */ }
|
|
22
|
+
try {
|
|
23
|
+
const cfg = loadBotConfigs().find(c => c.larkAppId === larkAppId);
|
|
24
|
+
if (!cfg)
|
|
25
|
+
return false;
|
|
26
|
+
registerBot(cfg);
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const MAX_BOTS = 200;
|
|
34
|
+
const MAX_OWNERS = 100;
|
|
35
|
+
/** Short-TTL idempotency cache for delegate-group: a hub may retry the SAME
|
|
36
|
+
* request (timeout/lost response) — replaying must return the first result, not
|
|
37
|
+
* create a duplicate group. Keyed by delegationToken+requestId. In-memory is
|
|
38
|
+
* enough (single dashboard process; the dedup window is seconds–minutes). */
|
|
39
|
+
const DELEGATE_IDEM_TTL_MS = 10 * 60 * 1000;
|
|
40
|
+
const delegateIdem = new Map();
|
|
41
|
+
function idemGet(key) {
|
|
42
|
+
const e = delegateIdem.get(key);
|
|
43
|
+
if (!e)
|
|
44
|
+
return null;
|
|
45
|
+
if (Date.now() > e.expiresAt) {
|
|
46
|
+
delegateIdem.delete(key);
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
return e.result;
|
|
50
|
+
}
|
|
51
|
+
function idemSet(key, result) {
|
|
52
|
+
const now = Date.now();
|
|
53
|
+
for (const [k, v] of delegateIdem)
|
|
54
|
+
if (v.expiresAt <= now)
|
|
55
|
+
delegateIdem.delete(k); // opportunistic prune
|
|
56
|
+
delegateIdem.set(key, { expiresAt: now + DELEGATE_IDEM_TTL_MS, result });
|
|
57
|
+
}
|
|
58
|
+
/** Federation bearer token: prefer the header (keeps the long-lived syncToken out
|
|
59
|
+
* of URLs / access logs); fall back to ?syncToken= for short-term hub compat. */
|
|
60
|
+
function federationToken(req, url) {
|
|
61
|
+
const auth = req.headers['authorization'];
|
|
62
|
+
if (typeof auth === 'string' && auth.startsWith('Bearer '))
|
|
63
|
+
return auth.slice(7).trim();
|
|
64
|
+
const x = req.headers['x-botmux-federation-token'];
|
|
65
|
+
if (typeof x === 'string' && x)
|
|
66
|
+
return x.trim();
|
|
67
|
+
return (url.searchParams.get('syncToken') ?? '').trim();
|
|
68
|
+
}
|
|
69
|
+
/** Header-only bearer for pre-auth WRITE endpoints (group create): the token must
|
|
70
|
+
* never come from URL/body — keep it out of access logs and off replayable surfaces.
|
|
71
|
+
* Unlike federationToken() there is NO ?syncToken= / body fallback here. */
|
|
72
|
+
function bearerOnly(req) {
|
|
73
|
+
const auth = req.headers['authorization'];
|
|
74
|
+
return (typeof auth === 'string' && auth.startsWith('Bearer ')) ? auth.slice(7).trim() : '';
|
|
75
|
+
}
|
|
76
|
+
async function readBody(req, maxBytes = 256 * 1024) {
|
|
77
|
+
const chunks = [];
|
|
78
|
+
let total = 0;
|
|
79
|
+
for await (const c of req) {
|
|
80
|
+
const b = c;
|
|
81
|
+
total += b.length;
|
|
82
|
+
if (total > maxBytes)
|
|
83
|
+
throw new Error('too_large');
|
|
84
|
+
chunks.push(b);
|
|
85
|
+
}
|
|
86
|
+
if (chunks.length === 0)
|
|
87
|
+
return {};
|
|
88
|
+
return JSON.parse(Buffer.concat(chunks).toString('utf-8'));
|
|
89
|
+
}
|
|
90
|
+
/** Defensive: only keep the fields we expect, cap the count, coerce types. */
|
|
91
|
+
function sanitizeBots(input) {
|
|
92
|
+
if (!Array.isArray(input))
|
|
93
|
+
return [];
|
|
94
|
+
const out = [];
|
|
95
|
+
for (const raw of input.slice(0, MAX_BOTS)) {
|
|
96
|
+
if (!raw || typeof raw !== 'object')
|
|
97
|
+
continue;
|
|
98
|
+
const r = raw;
|
|
99
|
+
if (typeof r.larkAppId !== 'string' || !r.larkAppId)
|
|
100
|
+
continue;
|
|
101
|
+
out.push({
|
|
102
|
+
larkAppId: r.larkAppId,
|
|
103
|
+
botName: typeof r.botName === 'string' ? r.botName : r.larkAppId,
|
|
104
|
+
cliId: typeof r.cliId === 'string' ? r.cliId : '',
|
|
105
|
+
botUnionId: typeof r.botUnionId === 'string' ? r.botUnionId : undefined,
|
|
106
|
+
capability: typeof r.capability === 'string' ? r.capability : null,
|
|
107
|
+
hasTeamRole: !!r.hasTeamRole,
|
|
108
|
+
ownerUnionId: typeof r.ownerUnionId === 'string' ? r.ownerUnionId : undefined,
|
|
109
|
+
ownerName: typeof r.ownerName === 'string' ? r.ownerName : undefined,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
export async function handleFederationApi(req, res, url, deps = {}) {
|
|
115
|
+
const path = url.pathname;
|
|
116
|
+
if (!path.startsWith('/api/federation/'))
|
|
117
|
+
return false;
|
|
118
|
+
const dataDir = deps.dataDir ?? config.session.dataDir;
|
|
119
|
+
const method = req.method ?? 'GET';
|
|
120
|
+
// Spoke registers via an invite → issued a syncToken bound to the team.
|
|
121
|
+
if (path === '/api/federation/join' && method === 'POST') {
|
|
122
|
+
let body;
|
|
123
|
+
try {
|
|
124
|
+
body = await readBody(req);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
const inviteCode = String(body?.inviteCode ?? '').trim();
|
|
131
|
+
const dep = body?.deployment;
|
|
132
|
+
if (!inviteCode) {
|
|
133
|
+
jsonRes(res, 400, { ok: false, error: 'code_required' });
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
if (!dep || typeof dep.deploymentId !== 'string' || !dep.deploymentId) {
|
|
137
|
+
jsonRes(res, 400, { ok: false, error: 'deployment_required' });
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
// Self-join is meaningless (a deployment federating with itself) — reject
|
|
141
|
+
// clearly before consuming the invite, so the spoke can surface it.
|
|
142
|
+
if (dep.deploymentId === getDeploymentIdentity(dataDir).deploymentId) {
|
|
143
|
+
jsonRes(res, 400, { ok: false, error: 'cannot_join_self' });
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
const inv = consumeInvite(dataDir, inviteCode);
|
|
147
|
+
if (!inv.ok) {
|
|
148
|
+
jsonRes(res, 403, { ok: false, error: `invite_${inv.reason}` });
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
const team = getTeam(dataDir, inv.teamId);
|
|
152
|
+
if (!team) {
|
|
153
|
+
jsonRes(res, 403, { ok: false, error: 'invite_team_deleted' });
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
const reg = registerDeployment(dataDir, inv.teamId, {
|
|
157
|
+
deploymentId: dep.deploymentId,
|
|
158
|
+
name: typeof dep.name === 'string' && dep.name ? dep.name : dep.deploymentId,
|
|
159
|
+
bots: sanitizeBots(dep.bots),
|
|
160
|
+
ownerUnionId: typeof dep.ownerUnionId === 'string' ? dep.ownerUnionId : undefined,
|
|
161
|
+
ownerName: typeof dep.ownerName === 'string' ? dep.ownerName : undefined,
|
|
162
|
+
callbackUrl: typeof dep.callbackUrl === 'string' && /^https?:\/\//i.test(dep.callbackUrl) ? dep.callbackUrl.replace(/\/+$/, '') : undefined,
|
|
163
|
+
delegationToken: typeof dep.delegationToken === 'string' ? dep.delegationToken : undefined,
|
|
164
|
+
});
|
|
165
|
+
// deploymentId is public (shows in roster) — never hand back an existing
|
|
166
|
+
// deployment's long-lived token. A duplicate must re-bind via an explicit
|
|
167
|
+
// reset proving the old token (future), not by re-joining with an invite.
|
|
168
|
+
if (!reg.created) {
|
|
169
|
+
jsonRes(res, 409, { ok: false, error: 'deployment_already_joined' });
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
jsonRes(res, 200, { ok: true, teamId: inv.teamId, teamName: team.name, syncToken: reg.syncToken });
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
// Spoke-initiated leave/revoke: drop this deployment from its team (authed by
|
|
176
|
+
// its own syncToken). Idempotent — unknown token is treated as already gone.
|
|
177
|
+
if (path === '/api/federation/leave' && method === 'POST') {
|
|
178
|
+
let body;
|
|
179
|
+
try {
|
|
180
|
+
body = await readBody(req);
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
const syncToken = String(body?.syncToken ?? '').trim() || federationToken(req, url);
|
|
187
|
+
if (!syncToken) {
|
|
188
|
+
jsonRes(res, 401, { ok: false, error: 'token_required' });
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
removeDeploymentByToken(dataDir, syncToken);
|
|
192
|
+
jsonRes(res, 200, { ok: true });
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
// Spoke pushes its current bots + heartbeat.
|
|
196
|
+
if (path === '/api/federation/sync' && method === 'POST') {
|
|
197
|
+
let body;
|
|
198
|
+
try {
|
|
199
|
+
body = await readBody(req);
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
const syncToken = String(body?.syncToken ?? '').trim();
|
|
206
|
+
if (!syncToken) {
|
|
207
|
+
jsonRes(res, 401, { ok: false, error: 'token_required' });
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
const ok = syncDeployment(dataDir, syncToken, sanitizeBots(body?.bots), {
|
|
211
|
+
ownerUnionId: typeof body?.ownerUnionId === 'string' ? body.ownerUnionId : undefined,
|
|
212
|
+
ownerName: typeof body?.ownerName === 'string' ? body.ownerName : undefined,
|
|
213
|
+
name: typeof body?.name === 'string' ? body.name : undefined,
|
|
214
|
+
});
|
|
215
|
+
if (!ok) {
|
|
216
|
+
jsonRes(res, 403, { ok: false, error: 'unknown_token' });
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
jsonRes(res, 200, { ok: true });
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
// Spoke pulls the aggregated cross-deployment roster for its team. Hub's own
|
|
223
|
+
// local bots come from the live registry (liveBots) so an empty bots-info.json
|
|
224
|
+
// doesn't hide them from the roster spokes see.
|
|
225
|
+
if (path === '/api/federation/roster' && method === 'GET') {
|
|
226
|
+
const found = getDeploymentByToken(dataDir, federationToken(req, url));
|
|
227
|
+
if (!found) {
|
|
228
|
+
jsonRes(res, 403, { ok: false, error: 'unknown_token' });
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
jsonRes(res, 200, { ok: true, ...buildFederatedRoster(dataDir, found.teamId, undefined, undefined, deps.liveBots?.()) });
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
// Spoke initiates 拉群 on the team it joined; the HUB orchestrates (local
|
|
235
|
+
// creator or delegate). Authed by the spoke's syncToken (team-internal trust).
|
|
236
|
+
// operator = the calling spoke's owner, DERIVED FROM THE TOKEN (never the body).
|
|
237
|
+
if (path === '/api/federation/group' && method === 'POST') {
|
|
238
|
+
if (!deps.createTeamGroup) {
|
|
239
|
+
jsonRes(res, 501, { ok: false, error: 'group_create_unavailable' });
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
let body;
|
|
243
|
+
try {
|
|
244
|
+
body = await readBody(req);
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
const token = bearerOnly(req); // header-only: a write endpoint must not take the token from URL/body
|
|
251
|
+
const found = getDeploymentByToken(dataDir, token);
|
|
252
|
+
if (!found) {
|
|
253
|
+
jsonRes(res, 403, { ok: false, error: 'unknown_token' });
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
const requestId = String(body?.requestId ?? '').trim();
|
|
257
|
+
if (!requestId) {
|
|
258
|
+
jsonRes(res, 400, { ok: false, error: 'request_id_required' });
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
const larkAppIds = Array.isArray(body?.larkAppIds) ? body.larkAppIds.filter((x) => typeof x === 'string') : [];
|
|
262
|
+
const name = String(body?.name ?? '').trim() || '协作群';
|
|
263
|
+
// Idempotency: replay of the same {syncToken, requestId} returns the FIRST
|
|
264
|
+
// terminal result verbatim — including failures (delegation_timeout /
|
|
265
|
+
// group_create_proxy_failed) which may already have side-effected. A genuine
|
|
266
|
+
// retry must use a fresh requestId; replaying must never re-orchestrate.
|
|
267
|
+
const idemKey = `group:${token}:${requestId}`;
|
|
268
|
+
const cached = idemGet(idemKey);
|
|
269
|
+
if (cached) {
|
|
270
|
+
jsonRes(res, cached.status, cached.body);
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
const out = await orchestrateFederatedGroup(dataDir, { name, larkAppIds, operatorUnionId: found.deployment.ownerUnionId, requestId, teamId: found.teamId }, { createTeamGroup: deps.createTeamGroup, fetcher: deps.fetcher ?? fetch, live: deps.liveBots?.() });
|
|
274
|
+
idemSet(idemKey, { status: out.status, body: out.body });
|
|
275
|
+
jsonRes(res, out.status, out.body);
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
// Hub delegates 拉群 to THIS spoke (hub→spoke): the hub had no local online
|
|
279
|
+
// creator, so it asks the deployment that owns a selected bot to create the
|
|
280
|
+
// group with ITS own online bot. Authed by the delegationToken THIS spoke
|
|
281
|
+
// issued to that hub at join (team-internal trust).
|
|
282
|
+
if (path === '/api/federation/delegate-group' && method === 'POST') {
|
|
283
|
+
if (!deps.createTeamGroup) {
|
|
284
|
+
jsonRes(res, 501, { ok: false, error: 'group_create_unavailable' });
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
let body;
|
|
288
|
+
try {
|
|
289
|
+
body = await readBody(req);
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
const token = bearerOnly(req); // header-only: same pre-auth write semantics as /group (never URL/body)
|
|
296
|
+
if (!findMembershipByDelegationToken(dataDir, token)) {
|
|
297
|
+
jsonRes(res, 403, { ok: false, error: 'unknown_token' });
|
|
298
|
+
return true;
|
|
299
|
+
}
|
|
300
|
+
const requestId = String(body?.requestId ?? '').trim();
|
|
301
|
+
if (!requestId) {
|
|
302
|
+
jsonRes(res, 400, { ok: false, error: 'request_id_required' });
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
// Idempotency: replay of {token, requestId} returns the FIRST terminal result
|
|
306
|
+
// verbatim — including failures (createTeamGroup may have side-effected). A
|
|
307
|
+
// genuine retry must use a fresh requestId; replaying never re-creates.
|
|
308
|
+
const idemKey = `delegate:${token}:${requestId}`;
|
|
309
|
+
const cached = idemGet(idemKey);
|
|
310
|
+
if (cached) {
|
|
311
|
+
jsonRes(res, cached.status, cached.body);
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
// Dedup + cap inputs (pre-auth command endpoint — keep blast radius small).
|
|
315
|
+
const larkAppIds = Array.from(new Set((Array.isArray(body?.larkAppIds) ? body.larkAppIds : []).filter((x) => typeof x === 'string')));
|
|
316
|
+
const ownerUnionIds = Array.from(new Set((Array.isArray(body?.ownerUnionIds) ? body.ownerUnionIds : []).filter((x) => typeof x === 'string')));
|
|
317
|
+
const name = (String(body?.name ?? '').trim()) || '协作群';
|
|
318
|
+
if (larkAppIds.length === 0) {
|
|
319
|
+
jsonRes(res, 400, { ok: false, error: 'no_bots_selected' });
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
if (larkAppIds.length > MAX_BOTS || ownerUnionIds.length > MAX_OWNERS) {
|
|
323
|
+
jsonRes(res, 400, { ok: false, error: 'too_many' });
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
// Guardrail: the delegation must involve at least one of OUR local bots
|
|
327
|
+
// (otherwise it's unrelated to this deployment — refuse to act as creator).
|
|
328
|
+
const localIds = new Set(buildTeamRoster(dataDir, undefined, undefined, deps.liveBots?.()).bots.map(b => b.larkAppId));
|
|
329
|
+
if (!larkAppIds.some(id => localIds.has(id))) {
|
|
330
|
+
jsonRes(res, 400, { ok: false, error: 'no_local_bot' });
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
const r = await deps.createTeamGroup({ name, larkAppIds, ownerUnionIds });
|
|
334
|
+
const result = { status: r.ok ? 200 : 502, body: r };
|
|
335
|
+
idemSet(idemKey, result); // cache terminal result (success AND failure)
|
|
336
|
+
jsonRes(res, result.status, result.body);
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
// Hub asks THIS spoke to add ITS OWN owner(s) to an existing chat (hub→spoke):
|
|
340
|
+
// the hub's creator bot can't add users outside its app's visibility scope
|
|
341
|
+
// (Lark code 232024), but THIS deployment's bot has its owner in scope. We add
|
|
342
|
+
// via `viaLarkAppId` — one of our bots that's already a member of the chat.
|
|
343
|
+
// Authed by the delegationToken THIS spoke issued (team-internal trust).
|
|
344
|
+
if (path === '/api/federation/delegate-add-owner' && method === 'POST') {
|
|
345
|
+
let body;
|
|
346
|
+
try {
|
|
347
|
+
body = await readBody(req);
|
|
348
|
+
}
|
|
349
|
+
catch {
|
|
350
|
+
jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
351
|
+
return true;
|
|
352
|
+
}
|
|
353
|
+
const token = bearerOnly(req);
|
|
354
|
+
if (!findMembershipByDelegationToken(dataDir, token)) {
|
|
355
|
+
jsonRes(res, 403, { ok: false, error: 'unknown_token' });
|
|
356
|
+
return true;
|
|
357
|
+
}
|
|
358
|
+
const requestId = String(body?.requestId ?? '').trim();
|
|
359
|
+
if (!requestId) {
|
|
360
|
+
jsonRes(res, 400, { ok: false, error: 'request_id_required' });
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
const idemKey = `add-owner:${token}:${requestId}`;
|
|
364
|
+
const cached = idemGet(idemKey);
|
|
365
|
+
if (cached) {
|
|
366
|
+
jsonRes(res, cached.status, cached.body);
|
|
367
|
+
return true;
|
|
368
|
+
}
|
|
369
|
+
const chatId = String(body?.chatId ?? '').trim();
|
|
370
|
+
const viaLarkAppId = String(body?.viaLarkAppId ?? '').trim();
|
|
371
|
+
const rawOwners = Array.isArray(body?.ownerUnionIds) ? body.ownerUnionIds : [];
|
|
372
|
+
const ownerUnionIds = Array.from(new Set(rawOwners.filter((x) => typeof x === 'string')));
|
|
373
|
+
if (!chatId || ownerUnionIds.length === 0) {
|
|
374
|
+
jsonRes(res, 400, { ok: false, error: 'bad_request' });
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
if (ownerUnionIds.length > MAX_OWNERS) {
|
|
378
|
+
jsonRes(res, 400, { ok: false, error: 'too_many' });
|
|
379
|
+
return true;
|
|
380
|
+
}
|
|
381
|
+
const roster = buildTeamRoster(dataDir, undefined, undefined, deps.liveBots?.());
|
|
382
|
+
// Guardrail: viaLarkAppId must be one of OUR local bots.
|
|
383
|
+
if (!roster.bots.some(b => b.larkAppId === viaLarkAppId)) {
|
|
384
|
+
jsonRes(res, 400, { ok: false, error: 'not_a_local_bot' });
|
|
385
|
+
return true;
|
|
386
|
+
}
|
|
387
|
+
// Capability limit: only add people who are OUR owners (this deployment's owner
|
|
388
|
+
// or a local bot's owner). A delegationToken holder must NOT use our bot to pull
|
|
389
|
+
// arbitrary in-scope users into arbitrary chats. Non-owners → invalid, no Lark call.
|
|
390
|
+
const me = getDeploymentIdentity(dataDir);
|
|
391
|
+
const allowedOwners = new Set([me.ownerUnionId, ...roster.bots.map(b => b.owner?.unionId)].filter((x) => !!x));
|
|
392
|
+
const toAdd = ownerUnionIds.filter(u => allowedOwners.has(u));
|
|
393
|
+
const notOurs = ownerUnionIds.filter(u => !allowedOwners.has(u));
|
|
394
|
+
const addOwners = deps.addOwners ?? (async (via, chat, ids) => {
|
|
395
|
+
if (!ensureLocalClient(via))
|
|
396
|
+
return { invalidUserIds: ids };
|
|
397
|
+
return addUsersToChatByUnionId(via, chat, ids);
|
|
398
|
+
});
|
|
399
|
+
const ar = toAdd.length > 0 ? await addOwners(viaLarkAppId, chatId, toAdd) : { invalidUserIds: [] };
|
|
400
|
+
const result = { status: 200, body: { ok: true, invalidUserIds: [...notOurs, ...ar.invalidUserIds] } };
|
|
401
|
+
idemSet(idemKey, result);
|
|
402
|
+
jsonRes(res, result.status, result.body);
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
jsonRes(res, 404, { ok: false, error: 'not_found' });
|
|
406
|
+
return true;
|
|
407
|
+
}
|
|
408
|
+
//# sourceMappingURL=federation-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"federation-api.js","sourceRoot":"","sources":["../../src/dashboard/federation-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Federation SPOKE endpoints, mounted INSIDE the dashboard's token gate (these
|
|
3
|
+
* are owner actions — the dashboard token already proves the owner). The spoke
|
|
4
|
+
* makes OUTBOUND calls to a hub; it never needs to expose anything inbound.
|
|
5
|
+
* - POST /api/team/join-remote { hubUrl, inviteCode }
|
|
6
|
+
* - GET /api/team/remote-roster
|
|
7
|
+
* - POST /api/team/sync-remote
|
|
8
|
+
* - POST /api/team/leave-remote { hubUrl, teamId }
|
|
9
|
+
*
|
|
10
|
+
* The long-lived syncToken is sent in the `Authorization: Bearer` header (never
|
|
11
|
+
* in a URL, so it stays out of access/proxy logs). All hub calls have a timeout.
|
|
12
|
+
* See docs/federation-design.md.
|
|
13
|
+
*/
|
|
14
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
15
|
+
import { type LiveBot } from '../services/team-roster.js';
|
|
16
|
+
import { type BotConfig } from '../bot-registry.js';
|
|
17
|
+
import { type Fetcher } from './federated-group-core.js';
|
|
18
|
+
export interface OwnerCandidate {
|
|
19
|
+
unionId: string;
|
|
20
|
+
name: string;
|
|
21
|
+
}
|
|
22
|
+
/** Injectable seams for the owner resolver (defaults hit Feishu via the bot's
|
|
23
|
+
* own credentials). Lets the resolver's registry/iteration logic be unit-tested
|
|
24
|
+
* without network. */
|
|
25
|
+
interface OwnerResolveDeps {
|
|
26
|
+
configs?: () => BotConfig[];
|
|
27
|
+
/** Ensure a usable Lark client exists for cfg. The DASHBOARD process has no bot
|
|
28
|
+
* registry (it proxies to daemons), so getBotClient() would throw — register
|
|
29
|
+
* the cfg on demand (it carries the app secret from bots.json). */
|
|
30
|
+
ensureClient?: (cfg: BotConfig) => void;
|
|
31
|
+
resolveAllowed?: (larkAppId: string, allowed: string[]) => Promise<string[]>;
|
|
32
|
+
resolveUnion?: (larkAppId: string, openId: string) => Promise<{
|
|
33
|
+
unionId?: string;
|
|
34
|
+
name?: string;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
/** Resolve this deployment's owner identity from bots.json `allowedUsers` using
|
|
38
|
+
* each bot's OWN app credentials (no /pair, no shared pairings.json — immune to
|
|
39
|
+
* the dataDir-split that broke /pair). Walks bots with allowedUsers in order;
|
|
40
|
+
* returns the first bot's distinct resolved {unionId,name} (skips bots that
|
|
41
|
+
* resolve to nothing, so one mis-config doesn't hide the rest). The UI auto-binds
|
|
42
|
+
* when there's exactly one, else lets the owner pick. */
|
|
43
|
+
export declare function resolveOwnerCandidatesFromAllowedUsers(d?: OwnerResolveDeps): Promise<OwnerCandidate[]>;
|
|
44
|
+
/** Push this deployment's current bots to every joined hub. Best-effort. */
|
|
45
|
+
export declare function syncAllMemberships(dataDir: string, fetcher?: Fetcher, live?: LiveBot[]): Promise<{
|
|
46
|
+
synced: number;
|
|
47
|
+
failed: number;
|
|
48
|
+
}>;
|
|
49
|
+
export interface FederationSpokeDeps {
|
|
50
|
+
dataDir?: string;
|
|
51
|
+
fetcher?: Fetcher;
|
|
52
|
+
/** Live daemon-registry bots (injected by dashboard.ts) — authoritative source
|
|
53
|
+
* for THIS deployment's bots, so an empty/stale bots-info.json never hides
|
|
54
|
+
* running bots from the team roster / federation sync. */
|
|
55
|
+
liveBots?: () => LiveBot[];
|
|
56
|
+
/** Injected by dashboard.ts — picks a local online creator + proxies to its
|
|
57
|
+
* daemon's /api/groups/create (federated bots are added by larkAppId). */
|
|
58
|
+
createTeamGroup?: (args: {
|
|
59
|
+
name: string;
|
|
60
|
+
larkAppIds: string[];
|
|
61
|
+
ownerUnionIds?: string[];
|
|
62
|
+
}) => Promise<{
|
|
63
|
+
ok: boolean;
|
|
64
|
+
chatId?: string;
|
|
65
|
+
shareLink?: string;
|
|
66
|
+
invalidBotIds?: string[];
|
|
67
|
+
invalidOwnerUnionIds?: string[];
|
|
68
|
+
error?: string;
|
|
69
|
+
}>;
|
|
70
|
+
/** Test seam: resolve owner candidates from allowedUsers (defaults to the real
|
|
71
|
+
* Feishu-backed resolver). */
|
|
72
|
+
ownerCandidates?: () => Promise<OwnerCandidate[]>;
|
|
73
|
+
}
|
|
74
|
+
export declare function handleFederationSpokeApi(req: IncomingMessage, res: ServerResponse, url: URL, deps?: FederationSpokeDeps): Promise<boolean>;
|
|
75
|
+
export {};
|
|
76
|
+
//# sourceMappingURL=federation-spoke-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"federation-spoke-api.d.ts","sourceRoot":"","sources":["../../src/dashboard/federation-spoke-api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAMjE,OAAO,EAAmB,KAAK,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAS3E,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAMzF,OAAO,EAAyD,KAAK,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAEhH,MAAM,WAAW,cAAc;IAAG,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAEjE;;uBAEuB;AACvB,UAAU,gBAAgB;IACxB,OAAO,CAAC,EAAE,MAAM,SAAS,EAAE,CAAC;IAC5B;;wEAEoE;IACpE,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpG;AAED;;;;;0DAK0D;AAC1D,wBAAsB,sCAAsC,CAAC,CAAC,GAAE,gBAAqB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAsBhH;AAwDD,4EAA4E;AAC5E,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,OAAe,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAejJ;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;+DAE2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,OAAO,EAAE,CAAC;IAC3B;+EAC2E;IAC3E,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,OAAO,CAAC;QACpG,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;KAC7H,CAAC,CAAC;IACH;mCAC+B;IAC/B,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;CACnD;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,GAAG,EACR,IAAI,GAAE,mBAAwB,GAC7B,OAAO,CAAC,OAAO,CAAC,CAuUlB"}
|