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
package/dist/daemon.js
CHANGED
|
@@ -27,10 +27,10 @@ import { scanMultipleProjects } from './services/project-scanner.js';
|
|
|
27
27
|
import { buildRepoSelectCard, buildStreamingCard, getCliDisplayName } from './im/lark/card-builder.js';
|
|
28
28
|
import { t as tr, botLocale, localeForBot } from './i18n/index.js';
|
|
29
29
|
import { createCliAdapterSync } from './adapters/cli/registry.js';
|
|
30
|
-
import { initWorkerPool, setActiveSessionsRegistry, forkWorker, killWorker, scheduleCardPatch, setCurrentCliVersion, CARD_POSTING_SENTINEL, parkStreamCard, closeSession as closeSessionHelper, } from './core/worker-pool.js';
|
|
31
|
-
import { ipcRoute, jsonRes, readJsonBody, setBotName, setLarkAppId, startIpcServer } from './core/dashboard-ipc-server.js';
|
|
30
|
+
import { initWorkerPool, setActiveSessionsRegistry, forkWorker, killWorker, scheduleCardPatch, setCurrentCliVersion, CARD_POSTING_SENTINEL, parkStreamCard, closeSession as closeSessionHelper, ensureCliEnv, writableTerminalLinkFor, } from './core/worker-pool.js';
|
|
31
|
+
import { ipcRoute, jsonRes, readJsonBody, setBotName, setLarkAppId, startIpcServer, setWorkflowRunner } from './core/dashboard-ipc-server.js';
|
|
32
32
|
import { saveFrozenCards } from './services/frozen-card-store.js';
|
|
33
|
-
import { DAEMON_COMMANDS, PASSTHROUGH_COMMANDS, handleCommand, parseSlashCommandInvocation, parseForceTopicInvocation } from './core/command-handler.js';
|
|
33
|
+
import { DAEMON_COMMANDS, SESSIONLESS_DAEMON_COMMANDS, PASSTHROUGH_COMMANDS, handleCommand, parseSlashCommandInvocation, parseForceTopicInvocation } from './core/command-handler.js';
|
|
34
34
|
import { findInheritablePeer } from './core/inherit-peer.js';
|
|
35
35
|
import { isCallbackUrl, handleCallbackUrl } from './utils/user-token.js';
|
|
36
36
|
import { getSessionWorkingDir, getProjectScanDirs, expandHome, downloadResources, formatAttachmentsHint, buildNewTopicPrompt, buildFollowUpContent, buildBridgeInputContent, buildReforkPrompt, getAvailableBots, restoreActiveSessions, executeScheduledTask, persistStreamCardState, rememberLastCliInput, } from './core/session-manager.js';
|
|
@@ -60,6 +60,9 @@ import { resolveWait } from './workflows/wait.js';
|
|
|
60
60
|
import { replay } from './workflows/events/replay.js';
|
|
61
61
|
import { isValidRunId, readRunSnapshot } from './workflows/ops-projection.js';
|
|
62
62
|
import { AttemptResumeManager } from './workflows/attempt-resume.js';
|
|
63
|
+
import { setCardDispatcher as setAskCardDispatcher, registerAsk as registerAskBroker, } from './core/ask-broker.js';
|
|
64
|
+
import { parseAskBody, resolveAskApprovers } from './core/ask-api.js';
|
|
65
|
+
import { createLarkAskCardDispatcher } from './im/lark/ask-card.js';
|
|
63
66
|
// ─── State ───────────────────────────────────────────────────────────────────
|
|
64
67
|
const activeSessions = new Map();
|
|
65
68
|
const workflowEventWatchers = new Map();
|
|
@@ -724,7 +727,11 @@ async function resolveDashboardWait(runId, resolution, comment) {
|
|
|
724
727
|
resolution,
|
|
725
728
|
by: 'dashboard',
|
|
726
729
|
comment,
|
|
727
|
-
}
|
|
730
|
+
},
|
|
731
|
+
// v0.2: pass def so resolveWait can write activitySucceeded for
|
|
732
|
+
// `decision` node reject instead of activityFailed. entry.ctx.def
|
|
733
|
+
// is the live, in-memory snapshot already loaded for this run.
|
|
734
|
+
{ def: entry.ctx.def });
|
|
728
735
|
const after = replay(await entry.ctx.log.readAll());
|
|
729
736
|
// Fire-and-forget re-drive — same pattern as Lark card path
|
|
730
737
|
// (workflowApprovalResolved hook). Don't await; the dashboard caller
|
|
@@ -929,7 +936,7 @@ function beginNewTurn(ds, title) {
|
|
|
929
936
|
const dsBotCfg = getBot(ds.larkAppId).config;
|
|
930
937
|
const prevTitle = ds.currentTurnTitle || ds.session.title || getCliDisplayName(dsBotCfg.cliId);
|
|
931
938
|
const prevMode = ds.displayMode ?? 'hidden';
|
|
932
|
-
const frozenCard = buildStreamingCard(ds.session.sessionId, sessionAnchorId(ds), readUrl, prevTitle, ds.lastScreenContent ?? '', previousStatus, dsBotCfg.cliId, prevMode, ds.streamCardNonce, ds.currentImageKey, !!ds.adoptedFrom, false, localeForBot(ds.larkAppId), previousUsageLimit);
|
|
939
|
+
const frozenCard = buildStreamingCard(ds.session.sessionId, sessionAnchorId(ds), readUrl, prevTitle, ds.lastScreenContent ?? '', previousStatus, dsBotCfg.cliId, prevMode, ds.streamCardNonce, ds.currentImageKey, !!ds.adoptedFrom, false, localeForBot(ds.larkAppId), previousUsageLimit, writableTerminalLinkFor(ds));
|
|
933
940
|
scheduleCardPatch(ds, frozenCard);
|
|
934
941
|
if (ds.streamCardNonce && ds.streamCardId !== CARD_POSTING_SENTINEL) {
|
|
935
942
|
if (!ds.frozenCards)
|
|
@@ -1074,6 +1081,28 @@ ipcRoute('POST', '/api/workflows/runs/:runId/cancel', async (req, res, params) =
|
|
|
1074
1081
|
}
|
|
1075
1082
|
return jsonRes(res, 200, result);
|
|
1076
1083
|
});
|
|
1084
|
+
/** Heavy deps for triggerWorkflowRun, shared by the catalog `…/run` route and
|
|
1085
|
+
* the `/api/trigger` (kind=workflow) thin layer. */
|
|
1086
|
+
function workflowTriggerDeps() {
|
|
1087
|
+
return {
|
|
1088
|
+
spawnSubagent: workflowSpawnFn(),
|
|
1089
|
+
botResolver: resolveBotSnapshot,
|
|
1090
|
+
makeRuntimeContext: (log, def, spawnSubagent) => ({
|
|
1091
|
+
log,
|
|
1092
|
+
def,
|
|
1093
|
+
spawnSubagent,
|
|
1094
|
+
hostExecutors: createDefaultHostExecutorRegistry(),
|
|
1095
|
+
reconcilers: createDefaultProviderReconcilers(),
|
|
1096
|
+
loadEffectInput: (activityId, attemptId) => loadEffectInputSidecar(log, activityId, attemptId),
|
|
1097
|
+
}),
|
|
1098
|
+
attachRuntime: (runId, ctx) => attachWorkflowEventWatcher(runId, ctx),
|
|
1099
|
+
driveRun: (runId) => {
|
|
1100
|
+
driveWorkflowRun(runId).catch((err) => {
|
|
1101
|
+
logger.warn(`[workflow:${runId}] trigger drive failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1102
|
+
});
|
|
1103
|
+
},
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1077
1106
|
ipcRoute('POST', '/api/workflows/definitions/:id/run', async (req, res, params) => {
|
|
1078
1107
|
const workflowId = params.id;
|
|
1079
1108
|
if (!isValidWorkflowId(workflowId)) {
|
|
@@ -1106,24 +1135,7 @@ ipcRoute('POST', '/api/workflows/definitions/:id/run', async (req, res, params)
|
|
|
1106
1135
|
rawParams,
|
|
1107
1136
|
chatBinding,
|
|
1108
1137
|
initiator: 'dashboard',
|
|
1109
|
-
},
|
|
1110
|
-
spawnSubagent: workflowSpawnFn(),
|
|
1111
|
-
botResolver: resolveBotSnapshot,
|
|
1112
|
-
makeRuntimeContext: (log, def, spawnSubagent) => ({
|
|
1113
|
-
log,
|
|
1114
|
-
def,
|
|
1115
|
-
spawnSubagent,
|
|
1116
|
-
hostExecutors: createDefaultHostExecutorRegistry(),
|
|
1117
|
-
reconcilers: createDefaultProviderReconcilers(),
|
|
1118
|
-
loadEffectInput: (activityId, attemptId) => loadEffectInputSidecar(log, activityId, attemptId),
|
|
1119
|
-
}),
|
|
1120
|
-
attachRuntime: (runId, ctx) => attachWorkflowEventWatcher(runId, ctx),
|
|
1121
|
-
driveRun: (runId) => {
|
|
1122
|
-
driveWorkflowRun(runId).catch((err) => {
|
|
1123
|
-
logger.warn(`[workflow:${runId}] dashboard-trigger drive failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1124
|
-
});
|
|
1125
|
-
},
|
|
1126
|
-
});
|
|
1138
|
+
}, workflowTriggerDeps());
|
|
1127
1139
|
if (!result.ok) {
|
|
1128
1140
|
const status = result.error === 'unknown_workflow' ? 404 :
|
|
1129
1141
|
result.error === 'invalid_params' ? 400 :
|
|
@@ -1132,6 +1144,83 @@ ipcRoute('POST', '/api/workflows/definitions/:id/run', async (req, res, params)
|
|
|
1132
1144
|
}
|
|
1133
1145
|
return jsonRes(res, 200, result);
|
|
1134
1146
|
});
|
|
1147
|
+
// ─── botmux ask v0.1.7 IPC route ─────────────────────────────────────────────
|
|
1148
|
+
//
|
|
1149
|
+
// CLI side: `botmux ask buttons --options "..."` POSTs here and keeps the
|
|
1150
|
+
// connection open until the broker settles the ask. Long keep-alive is OK —
|
|
1151
|
+
// the request's lifetime is bounded by `body.timeoutMs` which the broker
|
|
1152
|
+
// enforces. Default fetch on the CLI side has no read timeout.
|
|
1153
|
+
ipcRoute('POST', '/api/asks', async (req, res) => {
|
|
1154
|
+
let raw;
|
|
1155
|
+
try {
|
|
1156
|
+
raw = await readJsonBody(req);
|
|
1157
|
+
}
|
|
1158
|
+
catch {
|
|
1159
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
1160
|
+
}
|
|
1161
|
+
const parsed = parseAskBody(raw);
|
|
1162
|
+
if ('error' in parsed)
|
|
1163
|
+
return jsonRes(res, 400, { ok: false, error: parsed.error });
|
|
1164
|
+
const approvers = resolveAskApprovers({
|
|
1165
|
+
larkAppId: parsed.larkAppId,
|
|
1166
|
+
sessionId: parsed.sessionId,
|
|
1167
|
+
explicit: parsed.approvers,
|
|
1168
|
+
getBotAllowedUsers: (id) => {
|
|
1169
|
+
try {
|
|
1170
|
+
return getBot(id).resolvedAllowedUsers;
|
|
1171
|
+
}
|
|
1172
|
+
catch {
|
|
1173
|
+
return [];
|
|
1174
|
+
}
|
|
1175
|
+
},
|
|
1176
|
+
getSessionOwner: (sid) => {
|
|
1177
|
+
for (const ds of activeSessions.values()) {
|
|
1178
|
+
if (ds.session.sessionId === sid)
|
|
1179
|
+
return ds.ownerOpenId;
|
|
1180
|
+
}
|
|
1181
|
+
return undefined;
|
|
1182
|
+
},
|
|
1183
|
+
});
|
|
1184
|
+
if (approvers.size === 0) {
|
|
1185
|
+
// Nobody can answer — fail loud rather than registering a
|
|
1186
|
+
// guaranteed-timeout. CLI side maps this to exit 2.
|
|
1187
|
+
return jsonRes(res, 400, { ok: false, error: 'no_approvers' });
|
|
1188
|
+
}
|
|
1189
|
+
const result = await registerAskBroker({
|
|
1190
|
+
larkAppId: parsed.larkAppId,
|
|
1191
|
+
chatId: parsed.chatId,
|
|
1192
|
+
rootMessageId: parsed.rootMessageId,
|
|
1193
|
+
sessionId: parsed.sessionId,
|
|
1194
|
+
approvers,
|
|
1195
|
+
questions: parsed.questions,
|
|
1196
|
+
timeoutMs: parsed.timeoutMs,
|
|
1197
|
+
});
|
|
1198
|
+
return jsonRes(res, 200, result);
|
|
1199
|
+
});
|
|
1200
|
+
// ─── adopt-session 查询端点 ───────────────────────────────────────────────────
|
|
1201
|
+
// CLI side(botmux hook)通过祖先 PID 匹配 adopt 会话,路由 askUserQuestion。
|
|
1202
|
+
// GET /api/adopt-session/:pid — 返回该 pid 对应的 adopt 会话路由信息。
|
|
1203
|
+
// 仅匹配**当前活跃**的 adopt 会话(按 originalCliPid)。残留风险:OS 的 PID 复用——
|
|
1204
|
+
// 若原 adopt 的 Claude 已退出、同号 PID 被别的进程复用,理论上可能误命中;但 hook
|
|
1205
|
+
// 进程是该 Claude 的子孙,只有 Claude 仍在跑时其祖先链里才会出现这个 PID,且 session
|
|
1206
|
+
// 必须仍在 activeSessions 里,复用窗口极小,可接受(不为此引入进程级鉴权)。
|
|
1207
|
+
ipcRoute('GET', '/api/adopt-session/:pid', (_req, res, params) => {
|
|
1208
|
+
const pid = Number(params.pid);
|
|
1209
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
1210
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_pid' });
|
|
1211
|
+
}
|
|
1212
|
+
for (const ds of activeSessions.values()) {
|
|
1213
|
+
if (ds.adoptedFrom?.originalCliPid === pid) {
|
|
1214
|
+
return jsonRes(res, 200, {
|
|
1215
|
+
sessionId: ds.session.sessionId,
|
|
1216
|
+
chatId: ds.chatId,
|
|
1217
|
+
larkAppId: ds.larkAppId,
|
|
1218
|
+
rootMessageId: sessionAnchorId(ds),
|
|
1219
|
+
});
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
return jsonRes(res, 404, { ok: false, error: 'no_adopt_session' });
|
|
1223
|
+
});
|
|
1135
1224
|
function parseTriggerChatBinding(raw) {
|
|
1136
1225
|
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
|
1137
1226
|
return undefined;
|
|
@@ -1222,6 +1311,31 @@ function resolveBotDefaultWorkingDir(larkAppId) {
|
|
|
1222
1311
|
`falling back to repo-select card`);
|
|
1223
1312
|
return undefined;
|
|
1224
1313
|
}
|
|
1314
|
+
/**
|
|
1315
|
+
* Resolve the pinned working dir for a brand-new topic via the layered lookup:
|
|
1316
|
+
* 1) an existing oncall binding (this bot or a sibling)
|
|
1317
|
+
* 2) this bot's defaultOncall — auto-binds a brand-new chat when the flag is on
|
|
1318
|
+
* (this WRITES state, so it must run identically on every spawn path)
|
|
1319
|
+
* 3) a sibling session's workingDir (cross-bot / chat-scope inheritance)
|
|
1320
|
+
* 4) this bot's `defaultWorkingDir` (pure runtime fallback)
|
|
1321
|
+
* Returns the dir plus the oncall / inherited source so callers can log the reason.
|
|
1322
|
+
* Shared by the normal spawn path and the first-message `/repo` command branch so
|
|
1323
|
+
* both honor the defaultOncall auto-bind the same way.
|
|
1324
|
+
*/
|
|
1325
|
+
async function resolvePinnedWorkingDir(ctx) {
|
|
1326
|
+
let oncallEntry = findOncallChatForAnyBot(ctx.chatId);
|
|
1327
|
+
if (!oncallEntry) {
|
|
1328
|
+
oncallEntry = await maybeAutoBindDefaultOncall(ctx.larkAppId, ctx.chatId, ctx.chatType);
|
|
1329
|
+
}
|
|
1330
|
+
const inheritedFrom = !oncallEntry
|
|
1331
|
+
? findInheritablePeer({ scope: ctx.scope, anchor: ctx.anchor, chatId: ctx.chatId, chatType: ctx.chatType, selfAppId: ctx.larkAppId })
|
|
1332
|
+
: null;
|
|
1333
|
+
const botDefaultWorkingDir = (!oncallEntry && !inheritedFrom)
|
|
1334
|
+
? resolveBotDefaultWorkingDir(ctx.larkAppId)
|
|
1335
|
+
: undefined;
|
|
1336
|
+
const pinnedWorkingDir = oncallEntry?.workingDir ?? inheritedFrom?.workingDir ?? botDefaultWorkingDir;
|
|
1337
|
+
return { pinnedWorkingDir, oncallEntry, inheritedFrom };
|
|
1338
|
+
}
|
|
1225
1339
|
async function replyInvalidWorkingDirs(anchor, larkAppId, ds) {
|
|
1226
1340
|
const bot = getBot(larkAppId);
|
|
1227
1341
|
const invalid = invalidWorkingDirs({
|
|
@@ -1279,6 +1393,7 @@ async function handleNewTopic(data, ctx) {
|
|
|
1279
1393
|
logger.info(`[/t] Force-topic invocation: prompt="${forceTopic.prompt.substring(0, 60)}" (scope=${scope}, anchor=${anchor.substring(0, 12)})`);
|
|
1280
1394
|
}
|
|
1281
1395
|
const senderOpenId = data.sender?.sender_id?.open_id;
|
|
1396
|
+
const senderUnionId = data.sender?.sender_id?.union_id;
|
|
1282
1397
|
const botCfg = getBot(larkAppId).config;
|
|
1283
1398
|
logger.info(`New session: "${content.substring(0, 60)}" (scope=${scope}, anchor=${anchor.substring(0, 12)}, resources: ${resources.length}, active: ${getActiveCount()}, messageId: ${messageId}, chatId: ${chatId})`);
|
|
1284
1399
|
if (await handleWorkflowCommandIfAny(cmdContent, anchor, chatId, larkAppId, senderOpenId)) {
|
|
@@ -1302,6 +1417,14 @@ async function handleNewTopic(data, ctx) {
|
|
|
1302
1417
|
await sessionReply(anchor, tr('daemon.cmd_allowed_users_only', { cmd }, localeForBot(larkAppId)), 'text', larkAppId);
|
|
1303
1418
|
return;
|
|
1304
1419
|
}
|
|
1420
|
+
// `/group` (`/g`) doesn't open a conversation — creating a sessionStore
|
|
1421
|
+
// record for it would surface a phantom session in the dashboard. Run it
|
|
1422
|
+
// without a session; pass chatId on the message so the handler can reach
|
|
1423
|
+
// the chat roster (it normally reads it from the active session's ds).
|
|
1424
|
+
if (SESSIONLESS_DAEMON_COMMANDS.has(cmd)) {
|
|
1425
|
+
await handleCommand(cmd, anchor, { ...parsed, content: commandContent, chatId }, commandDeps, larkAppId);
|
|
1426
|
+
return;
|
|
1427
|
+
}
|
|
1305
1428
|
// Same rootMessageId reasoning as below in the main spawn path:
|
|
1306
1429
|
// thread-scope MUST anchor on the thread root or sessionAnchorId() will
|
|
1307
1430
|
// disagree with activeSessions's key and downstream card buttons silently
|
|
@@ -1311,9 +1434,26 @@ async function handleNewTopic(data, ctx) {
|
|
|
1311
1434
|
const now = Date.now();
|
|
1312
1435
|
session.larkAppId = larkAppId;
|
|
1313
1436
|
session.ownerOpenId = senderOpenId;
|
|
1437
|
+
session.ownerUnionId = senderUnionId;
|
|
1314
1438
|
session.lastCallerOpenId = senderOpenId;
|
|
1315
1439
|
session.lastMessageAt = new Date(now).toISOString();
|
|
1316
1440
|
session.scope = scope;
|
|
1441
|
+
// First-message `/repo`: seed the same pending-repo state the card flow
|
|
1442
|
+
// uses, so the `/repo` handler launches the CLI straight away —
|
|
1443
|
+
// `/repo <arg>` in that repo, bare `/repo` in the default workingDir —
|
|
1444
|
+
// instead of taking the mid-session close+recreate path or re-showing the
|
|
1445
|
+
// card. Use the SAME pinned-dir resolver as the normal spawn path (incl.
|
|
1446
|
+
// defaultOncall auto-bind) so a bound/auto-bound chat still launches in the
|
|
1447
|
+
// right place when no arg is given.
|
|
1448
|
+
let cmdPending;
|
|
1449
|
+
if (cmd === '/repo') {
|
|
1450
|
+
const { pinnedWorkingDir } = await resolvePinnedWorkingDir({ scope, anchor, chatId, chatType, larkAppId });
|
|
1451
|
+
if (pinnedWorkingDir)
|
|
1452
|
+
session.workingDir = pinnedWorkingDir;
|
|
1453
|
+
// pendingPrompt is empty (the message *is* the command), so the CLI just
|
|
1454
|
+
// boots and waits for the user's next message; no sender tag needed.
|
|
1455
|
+
cmdPending = { pendingRepo: true, pendingPrompt: '', workingDir: pinnedWorkingDir };
|
|
1456
|
+
}
|
|
1317
1457
|
sessionStore.updateSession(session);
|
|
1318
1458
|
activeSessions.set(sessionKey(anchor, larkAppId), {
|
|
1319
1459
|
session,
|
|
@@ -1329,6 +1469,7 @@ async function handleNewTopic(data, ctx) {
|
|
|
1329
1469
|
lastMessageAt: now,
|
|
1330
1470
|
hasHistory: false,
|
|
1331
1471
|
ownerOpenId: senderOpenId,
|
|
1472
|
+
...cmdPending,
|
|
1332
1473
|
});
|
|
1333
1474
|
// Pass mention-stripped content so /command argument parsing works.
|
|
1334
1475
|
await handleCommand(cmd, anchor, { ...parsed, content: commandContent }, commandDeps, larkAppId);
|
|
@@ -1370,36 +1511,24 @@ async function handleNewTopic(data, ctx) {
|
|
|
1370
1511
|
const now = Date.now();
|
|
1371
1512
|
session.larkAppId = larkAppId;
|
|
1372
1513
|
session.ownerOpenId = senderOpenId;
|
|
1514
|
+
session.ownerUnionId = senderUnionId;
|
|
1515
|
+
session.lastCallerOpenId = senderOpenId;
|
|
1516
|
+
// First turn of a brand-new topic: seed quoteTarget* so the very first
|
|
1517
|
+
// `botmux send` can --mention-back / 引用 the triggering message (chat scope).
|
|
1518
|
+
// Without this the first reply hits hasQuoteTargetSender=false (exit 2) and
|
|
1519
|
+
// chat-scope首条不引用. Use the event's sender open_id (correct app scope).
|
|
1520
|
+
session.quoteTargetId = parsed.messageId;
|
|
1521
|
+
session.quoteTargetSenderOpenId = senderOpenId;
|
|
1522
|
+
session.quoteTargetSenderIsBot = parsed.senderType === 'app' || parsed.senderType === 'bot';
|
|
1373
1523
|
session.lastMessageAt = new Date(now).toISOString();
|
|
1374
1524
|
session.scope = scope;
|
|
1375
1525
|
sessionStore.updateSession(session);
|
|
1376
1526
|
messageQueue.ensureQueue(anchor);
|
|
1377
1527
|
messageQueue.appendMessage(anchor, parsed);
|
|
1378
|
-
//
|
|
1379
|
-
//
|
|
1380
|
-
//
|
|
1381
|
-
|
|
1382
|
-
// 2) this bot's defaultOncall — auto-binds the chat if it's brand new
|
|
1383
|
-
// and the flag is on. Once auto-bound, the chat appears in oncallChats
|
|
1384
|
-
// so the next handleNewTopic sees it via (1).
|
|
1385
|
-
let oncallEntry = findOncallChatForAnyBot(chatId);
|
|
1386
|
-
if (!oncallEntry) {
|
|
1387
|
-
oncallEntry = await maybeAutoBindDefaultOncall(larkAppId, chatId, chatType);
|
|
1388
|
-
}
|
|
1389
|
-
// Cross-bot / chat-scope inheritance: reuse a sibling session's workingDir
|
|
1390
|
-
// and skip the repo card. Same block lives in handleThreadReply's auto-create
|
|
1391
|
-
// branch — both handlers land unowned messages after the 4fec43c routing
|
|
1392
|
-
// change. Helper is shared.
|
|
1393
|
-
const inheritedFrom = !oncallEntry
|
|
1394
|
-
? findInheritablePeer({ scope, anchor, chatId, chatType, selfAppId: larkAppId })
|
|
1395
|
-
: null;
|
|
1396
|
-
// Last-resort fallback: this bot's `defaultWorkingDir`. Pure runtime — no
|
|
1397
|
-
// oncall binding written, no permission-model change. Lets a single-repo
|
|
1398
|
-
// bot skip the repo-select card without committing to oncall semantics.
|
|
1399
|
-
const botDefaultWorkingDir = (!oncallEntry && !inheritedFrom)
|
|
1400
|
-
? resolveBotDefaultWorkingDir(larkAppId)
|
|
1401
|
-
: undefined;
|
|
1402
|
-
const pinnedWorkingDir = oncallEntry?.workingDir ?? inheritedFrom?.workingDir ?? botDefaultWorkingDir;
|
|
1528
|
+
// Pin the working dir via the layered oncall / inherit / default lookup
|
|
1529
|
+
// (auto-binds a defaultOncall chat as a side effect). Shared with the
|
|
1530
|
+
// first-message `/repo` command branch so both paths stay consistent.
|
|
1531
|
+
const { pinnedWorkingDir, oncallEntry, inheritedFrom } = await resolvePinnedWorkingDir({ scope, anchor, chatId, chatType, larkAppId });
|
|
1403
1532
|
const ds = {
|
|
1404
1533
|
session,
|
|
1405
1534
|
worker: null,
|
|
@@ -1611,7 +1740,8 @@ async function handleThreadReply(data, ctx) {
|
|
|
1611
1740
|
return;
|
|
1612
1741
|
}
|
|
1613
1742
|
// Pass mention-stripped content so /command argument parsing works.
|
|
1614
|
-
|
|
1743
|
+
// chatId lets session-less handlers (e.g. /group) reach the chat roster.
|
|
1744
|
+
handleCommand(cmd, anchor, { ...parsed, content: commandContent, chatId: threadChatId }, commandDeps, larkAppId);
|
|
1615
1745
|
return;
|
|
1616
1746
|
}
|
|
1617
1747
|
}
|
|
@@ -1650,10 +1780,16 @@ async function handleThreadReply(data, ctx) {
|
|
|
1650
1780
|
if (ds) {
|
|
1651
1781
|
markSessionActivity(ds);
|
|
1652
1782
|
const callerOpenId = parsed.senderId || data?.sender?.sender_id?.open_id;
|
|
1783
|
+
// quoteTargetId changes every inbound message (always a new message_id), so
|
|
1784
|
+
// — unlike lastCallerOpenId — persist unconditionally. Powers `botmux send`'s
|
|
1785
|
+
// default chat-scope quote chain + --mention-back.
|
|
1786
|
+
ds.session.quoteTargetId = parsed.messageId;
|
|
1787
|
+
ds.session.quoteTargetSenderOpenId = callerOpenId;
|
|
1788
|
+
ds.session.quoteTargetSenderIsBot = isForeignBot;
|
|
1653
1789
|
if (callerOpenId && ds.session.lastCallerOpenId !== callerOpenId) {
|
|
1654
1790
|
ds.session.lastCallerOpenId = callerOpenId;
|
|
1655
|
-
sessionStore.updateSession(ds.session);
|
|
1656
1791
|
}
|
|
1792
|
+
sessionStore.updateSession(ds.session);
|
|
1657
1793
|
}
|
|
1658
1794
|
// If waiting for repo selection, buffer the message and remind user
|
|
1659
1795
|
if (ds?.pendingRepo) {
|
|
@@ -1668,13 +1804,18 @@ async function handleThreadReply(data, ctx) {
|
|
|
1668
1804
|
});
|
|
1669
1805
|
enriched += `\n\n${tr('daemon.enriched_mentions_label', undefined, localeForBot(larkAppId))}\n${mentionLines.join('\n')}`;
|
|
1670
1806
|
}
|
|
1671
|
-
// Stamp
|
|
1672
|
-
//
|
|
1673
|
-
//
|
|
1674
|
-
//
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1807
|
+
// Stamp a buffered follow-up with its own <sender> tag ONLY when it comes
|
|
1808
|
+
// from a different user than the first message (ds.pendingSender) — the
|
|
1809
|
+
// deferred spawn already carries that sender's <sender> block, and the
|
|
1810
|
+
// follow-ups now fold into the same <user_message>, so a same-user tag is
|
|
1811
|
+
// pure duplication. A differing sender still gets attributed so the CLI can
|
|
1812
|
+
// tell multi-user buffered messages apart after repo selection unlocks.
|
|
1813
|
+
const followUpSender = await getThreadSender();
|
|
1814
|
+
if (followUpSender?.openId && followUpSender.openId !== ds.pendingSender?.openId) {
|
|
1815
|
+
const followUpSenderTag = renderSenderTag(followUpSender);
|
|
1816
|
+
if (followUpSenderTag)
|
|
1817
|
+
enriched = `${followUpSenderTag}\n${enriched}`;
|
|
1818
|
+
}
|
|
1678
1819
|
if (!ds.pendingFollowUps)
|
|
1679
1820
|
ds.pendingFollowUps = [];
|
|
1680
1821
|
ds.pendingFollowUps.push(enriched);
|
|
@@ -1699,15 +1840,24 @@ async function handleThreadReply(data, ctx) {
|
|
|
1699
1840
|
logger.info(`No active session for ${scope}-scope ${anchor}, auto-creating new session...`);
|
|
1700
1841
|
refreshCliVersion(botCfg.cliId, botCfg.cliPathOverride);
|
|
1701
1842
|
const senderOId = data.sender?.sender_id?.open_id;
|
|
1843
|
+
const senderUId = data.sender?.sender_id?.union_id;
|
|
1702
1844
|
// For thread-scope: rootMessageId = anchor (real thread root).
|
|
1703
1845
|
// For chat-scope: rootMessageId = the message_id that triggered this auto-create
|
|
1704
1846
|
// (used as audit trail; routing key is chatId).
|
|
1705
1847
|
const rootIdForStore = scope === 'thread' ? anchor : parsed.messageId;
|
|
1706
1848
|
const session = sessionStore.createSession(autoCreateChatId, rootIdForStore, parsed.content.substring(0, 50), autoCreateChatType);
|
|
1707
1849
|
const now = Date.now();
|
|
1850
|
+
// Bot-started handoff sessions have no human owner; keeping the bot as
|
|
1851
|
+
// owner makes daemon-generated footers wake that bot again.
|
|
1852
|
+
const ownerOpenId = isForeignBot ? undefined : senderOId;
|
|
1853
|
+
const ownerUnionId = isForeignBot ? undefined : senderUId;
|
|
1708
1854
|
session.larkAppId = larkAppId;
|
|
1709
|
-
session.ownerOpenId =
|
|
1855
|
+
session.ownerOpenId = ownerOpenId;
|
|
1856
|
+
session.ownerUnionId = ownerUnionId;
|
|
1710
1857
|
session.lastCallerOpenId = senderOId;
|
|
1858
|
+
session.quoteTargetId = parsed.messageId;
|
|
1859
|
+
session.quoteTargetSenderOpenId = senderOId;
|
|
1860
|
+
session.quoteTargetSenderIsBot = isForeignBot;
|
|
1711
1861
|
session.lastMessageAt = new Date(now).toISOString();
|
|
1712
1862
|
session.scope = scope;
|
|
1713
1863
|
sessionStore.updateSession(session);
|
|
@@ -1759,7 +1909,7 @@ async function handleThreadReply(data, ctx) {
|
|
|
1759
1909
|
pendingAttachments: attachments.length > 0 ? attachments : undefined,
|
|
1760
1910
|
pendingMentions: parsed.mentions,
|
|
1761
1911
|
pendingSender: autoCreateSender,
|
|
1762
|
-
ownerOpenId
|
|
1912
|
+
ownerOpenId,
|
|
1763
1913
|
currentTurnTitle: parsed.content.substring(0, 50),
|
|
1764
1914
|
workingDir: pinnedWorkingDir,
|
|
1765
1915
|
};
|
|
@@ -1905,12 +2055,23 @@ export async function startDaemon(botIndex) {
|
|
|
1905
2055
|
}
|
|
1906
2056
|
const cfg = botConfigs[idx];
|
|
1907
2057
|
registerBot(cfg);
|
|
2058
|
+
// 启动即为本 bot 的 CLI 预装环境(skills + askUserQuestion hook + 兜底 skill)。
|
|
2059
|
+
// 关键:adopt 路径会跳过 ensureCliSkills,若重启后第一次就是 adopt 一个外部
|
|
2060
|
+
// claude 会话,必须保证此时全局 ~/.claude/settings.json 已带 hook——否则"全局
|
|
2061
|
+
// hook 适配 adopt"不成立。这里幂等、best-effort,不阻塞启动。
|
|
2062
|
+
try {
|
|
2063
|
+
ensureCliEnv(cfg.cliId, cfg.cliPathOverride);
|
|
2064
|
+
}
|
|
2065
|
+
catch (err) {
|
|
2066
|
+
logger.warn(`[hook] startup ensureCliEnv failed for ${cfg.cliId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
2067
|
+
}
|
|
1908
2068
|
sessionStore.init(cfg.larkAppId);
|
|
1909
2069
|
chatFirstSeenStore.init(cfg.larkAppId);
|
|
1910
2070
|
// Watch schedules.json for external writes (e.g. `botmux schedule add`
|
|
1911
2071
|
// running in a separate node process) so dashboard event bus stays in sync.
|
|
1912
2072
|
scheduleStore.startExternalWriteWatcher();
|
|
1913
2073
|
logger.info(`Bot ${idx}/${botConfigs.length}: ${cfg.larkAppId} (cli: ${cfg.cliId})`);
|
|
2074
|
+
setAskCardDispatcher(createLarkAskCardDispatcher());
|
|
1914
2075
|
writePidFile();
|
|
1915
2076
|
const memoryDiagnostics = startMemoryDiagnostics();
|
|
1916
2077
|
// Publish self-descriptor for the dashboard registry. The dashboard sibling
|
|
@@ -1945,6 +2106,9 @@ export async function startDaemon(botIndex) {
|
|
|
1945
2106
|
// Expose the activeSessions Map (owned by daemon) to worker-pool readers,
|
|
1946
2107
|
// so dashboard IPC and other consumers can list/lookup live sessions.
|
|
1947
2108
|
setActiveSessionsRegistry(activeSessions);
|
|
2109
|
+
// Wire the workflow runner for /api/trigger (kind=workflow): reuse the same
|
|
2110
|
+
// heavy deps as the catalog run route.
|
|
2111
|
+
setWorkflowRunner((input) => triggerWorkflowRun(input, workflowTriggerDeps()));
|
|
1948
2112
|
// Seed dashboard IPC botName with the bot's config id; the friendly name from
|
|
1949
2113
|
// /bot/v3/info is wired into the registry descriptor (below) but the IPC server
|
|
1950
2114
|
// also needs its own copy for SessionRow.botName.
|
|
@@ -2048,7 +2212,7 @@ export async function startDaemon(botIndex) {
|
|
|
2048
2212
|
});
|
|
2049
2213
|
}
|
|
2050
2214
|
// Restore active sessions from previous run
|
|
2051
|
-
restoreActiveSessions(activeSessions);
|
|
2215
|
+
await restoreActiveSessions(activeSessions);
|
|
2052
2216
|
await attachColdWorkflowRuns(cfg.larkAppId);
|
|
2053
2217
|
// Start scheduler in every daemon. Each daemon owns exactly one bot, so
|
|
2054
2218
|
// each filters to only execute tasks whose `larkAppId` matches its bot
|