botmux 3.4.3 → 3.5.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 -7
- package/README.md +11 -6
- package/dist/adapters/backend/herdr-backend.d.ts +43 -6
- package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
- package/dist/adapters/backend/herdr-backend.js +362 -28
- package/dist/adapters/backend/herdr-backend.js.map +1 -1
- package/dist/adapters/backend/reproduce-command.d.ts +39 -0
- package/dist/adapters/backend/reproduce-command.d.ts.map +1 -0
- package/dist/adapters/backend/reproduce-command.js +63 -0
- package/dist/adapters/backend/reproduce-command.js.map +1 -0
- package/dist/adapters/backend/sandbox.d.ts +99 -279
- package/dist/adapters/backend/sandbox.d.ts.map +1 -1
- package/dist/adapters/backend/sandbox.js +424 -826
- package/dist/adapters/backend/sandbox.js.map +1 -1
- package/dist/adapters/backend/session-backend-selector.d.ts +10 -1
- package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -1
- package/dist/adapters/backend/session-backend-selector.js +73 -4
- package/dist/adapters/backend/session-backend-selector.js.map +1 -1
- package/dist/adapters/backend/types.d.ts +16 -0
- package/dist/adapters/backend/types.d.ts.map +1 -1
- package/dist/adapters/backend/types.js.map +1 -1
- package/dist/adapters/cli/codex.d.ts.map +1 -1
- package/dist/adapters/cli/codex.js +4 -0
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/fs-policy.d.ts +244 -0
- package/dist/adapters/cli/fs-policy.d.ts.map +1 -0
- package/dist/adapters/cli/fs-policy.js +539 -0
- package/dist/adapters/cli/fs-policy.js.map +1 -0
- package/dist/adapters/cli/pi-initial-prompt.d.ts.map +1 -1
- package/dist/adapters/cli/pi-initial-prompt.js +5 -1
- package/dist/adapters/cli/pi-initial-prompt.js.map +1 -1
- package/dist/adapters/cli/read-isolation.d.ts +14 -200
- package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
- package/dist/adapters/cli/read-isolation.js +18 -477
- package/dist/adapters/cli/read-isolation.js.map +1 -1
- package/dist/adapters/cli/traex.d.ts.map +1 -1
- package/dist/adapters/cli/traex.js +5 -0
- package/dist/adapters/cli/traex.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +3 -3
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/adapters/hook-installer.d.ts +7 -0
- package/dist/adapters/hook-installer.d.ts.map +1 -1
- package/dist/adapters/hook-installer.js +56 -0
- package/dist/adapters/hook-installer.js.map +1 -1
- package/dist/bot-registry.d.ts +39 -23
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +134 -2
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/capabilities.d.ts +24 -0
- package/dist/cli/capabilities.d.ts.map +1 -0
- package/dist/cli/capabilities.js +25 -0
- package/dist/cli/capabilities.js.map +1 -0
- package/dist/cli/create-group-resolver.d.ts +24 -0
- package/dist/cli/create-group-resolver.d.ts.map +1 -1
- package/dist/cli/create-group-resolver.js +23 -0
- package/dist/cli/create-group-resolver.js.map +1 -1
- package/dist/cli/daemon-lifecycle-env.d.ts +5 -7
- package/dist/cli/daemon-lifecycle-env.d.ts.map +1 -1
- package/dist/cli/daemon-lifecycle-env.js +13 -7
- package/dist/cli/daemon-lifecycle-env.js.map +1 -1
- package/dist/cli/exact-chat-grant-client.d.ts +48 -0
- package/dist/cli/exact-chat-grant-client.d.ts.map +1 -0
- package/dist/cli/exact-chat-grant-client.js +108 -0
- package/dist/cli/exact-chat-grant-client.js.map +1 -0
- package/dist/cli/exact-chat-grant.d.ts +18 -0
- package/dist/cli/exact-chat-grant.d.ts.map +1 -0
- package/dist/cli/exact-chat-grant.js +97 -0
- package/dist/cli/exact-chat-grant.js.map +1 -0
- package/dist/cli.d.ts +10 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +795 -144
- package/dist/cli.js.map +1 -1
- package/dist/codex-rpc-engine.d.ts +26 -0
- package/dist/codex-rpc-engine.d.ts.map +1 -1
- package/dist/codex-rpc-engine.js +113 -2
- package/dist/codex-rpc-engine.js.map +1 -1
- package/dist/config.d.ts +16 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +16 -0
- package/dist/config.js.map +1 -1
- package/dist/core/bot-live-control.d.ts +41 -0
- package/dist/core/bot-live-control.d.ts.map +1 -0
- package/dist/core/bot-live-control.js +135 -0
- package/dist/core/bot-live-control.js.map +1 -0
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +44 -66
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/daemon-config-fence.d.ts +8 -0
- package/dist/core/daemon-config-fence.d.ts.map +1 -0
- package/dist/core/daemon-config-fence.js +13 -0
- package/dist/core/daemon-config-fence.js.map +1 -0
- package/dist/core/dashboard-events.d.ts +5 -0
- package/dist/core/dashboard-events.d.ts.map +1 -1
- package/dist/core/dashboard-events.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts +21 -2
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +258 -32
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dispatch-registry.d.ts +12 -0
- package/dist/core/dispatch-registry.d.ts.map +1 -0
- package/dist/core/dispatch-registry.js +33 -0
- package/dist/core/dispatch-registry.js.map +1 -0
- package/dist/core/dispatch.d.ts +99 -0
- package/dist/core/dispatch.d.ts.map +1 -1
- package/dist/core/dispatch.js +136 -0
- package/dist/core/dispatch.js.map +1 -1
- package/dist/core/maintenance.d.ts.map +1 -1
- package/dist/core/maintenance.js +10 -3
- package/dist/core/maintenance.js.map +1 -1
- package/dist/core/passthrough-commands.d.ts.map +1 -1
- package/dist/core/passthrough-commands.js +1 -1
- package/dist/core/passthrough-commands.js.map +1 -1
- package/dist/core/persistent-backend.d.ts +16 -2
- package/dist/core/persistent-backend.d.ts.map +1 -1
- package/dist/core/persistent-backend.js +40 -0
- package/dist/core/persistent-backend.js.map +1 -1
- package/dist/core/plugins/mcp/gateway-installer.d.ts.map +1 -1
- package/dist/core/plugins/mcp/gateway-installer.js +14 -2
- package/dist/core/plugins/mcp/gateway-installer.js.map +1 -1
- package/dist/core/session-discovery.d.ts +8 -1
- package/dist/core/session-discovery.d.ts.map +1 -1
- package/dist/core/session-discovery.js +140 -8
- package/dist/core/session-discovery.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +102 -68
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-title.d.ts +8 -0
- package/dist/core/session-title.d.ts.map +1 -1
- package/dist/core/session-title.js +54 -0
- package/dist/core/session-title.js.map +1 -1
- package/dist/core/terminal-write-auth.d.ts +15 -0
- package/dist/core/terminal-write-auth.d.ts.map +1 -1
- package/dist/core/terminal-write-auth.js +20 -0
- package/dist/core/terminal-write-auth.js.map +1 -1
- package/dist/core/trigger-session.d.ts.map +1 -1
- package/dist/core/trigger-session.js +3 -2
- package/dist/core/trigger-session.js.map +1 -1
- package/dist/core/types.d.ts +33 -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 +51 -8
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +439 -25
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts +4 -2
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +403 -26
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/bot-onboarding.d.ts +127 -1
- package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
- package/dist/dashboard/bot-onboarding.js +1104 -25
- package/dist/dashboard/bot-onboarding.js.map +1 -1
- package/dist/dashboard/bot-payload.d.ts +5 -0
- package/dist/dashboard/bot-payload.d.ts.map +1 -1
- package/dist/dashboard/bot-payload.js +7 -0
- package/dist/dashboard/bot-payload.js.map +1 -1
- package/dist/dashboard/debug-terminal.d.ts +18 -0
- package/dist/dashboard/debug-terminal.d.ts.map +1 -0
- package/dist/dashboard/debug-terminal.js +338 -0
- package/dist/dashboard/debug-terminal.js.map +1 -0
- package/dist/dashboard/public-redact.d.ts +2 -0
- package/dist/dashboard/public-redact.d.ts.map +1 -1
- package/dist/dashboard/public-redact.js +12 -3
- package/dist/dashboard/public-redact.js.map +1 -1
- package/dist/dashboard/registry.d.ts +8 -0
- package/dist/dashboard/registry.d.ts.map +1 -1
- package/dist/dashboard/registry.js +13 -0
- package/dist/dashboard/registry.js.map +1 -1
- package/dist/dashboard/settings-write-applier.d.ts +47 -1
- package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
- package/dist/dashboard/settings-write-applier.js +102 -1
- package/dist/dashboard/settings-write-applier.js.map +1 -1
- package/dist/dashboard/web/app.d.ts.map +1 -1
- package/dist/dashboard/web/app.js +2 -0
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts +17 -0
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.js +249 -11
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts +22 -0
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js +19 -0
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +114 -28
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/icon-tooltip.d.ts +3 -0
- package/dist/dashboard/web/icon-tooltip.d.ts.map +1 -0
- package/dist/dashboard/web/icon-tooltip.js +108 -0
- package/dist/dashboard/web/icon-tooltip.js.map +1 -0
- package/dist/dashboard/web/sessions-kanban.js +2 -2
- package/dist/dashboard/web/sessions-kanban.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-page.js +49 -53
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts +2 -0
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +46 -2
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/settings-page.d.ts +78 -0
- package/dist/dashboard/web/settings-page.d.ts.map +1 -1
- package/dist/dashboard/web/settings-page.js +88 -1
- package/dist/dashboard/web/settings-page.js.map +1 -1
- package/dist/dashboard/web/store.d.ts +2 -0
- package/dist/dashboard/web/store.d.ts.map +1 -1
- package/dist/dashboard/web/store.js +13 -1
- package/dist/dashboard/web/store.js.map +1 -1
- package/dist/dashboard-web/app.js +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-AUKV7P4L.js +10 -0
- package/dist/dashboard-web/chunks/{chunk-P6GO5KT4.js → chunk-KPQAUX7V.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-UBOLHQCK.js → chunk-NRL6CVAS.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-JNRSPKLS.js → chunk-R7IAKAYX.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-CUV65BIQ.js → chunk-X2L65IOM.js} +8 -8
- package/dist/dashboard-web/chunks/{connectors-page-KTC2QWNW.js → connectors-page-HDQFEXZI.js} +1 -1
- package/dist/dashboard-web/chunks/{groups-page-B3EKGOLY.js → groups-page-6DKXBYOM.js} +1 -1
- package/dist/dashboard-web/chunks/{insights-page-X6RXNCWX.js → insights-page-NWARTJ6J.js} +1 -1
- package/dist/dashboard-web/chunks/{monitor-room-LLRA5LQW.js → monitor-room-AGX3XRJX.js} +1 -1
- package/dist/dashboard-web/chunks/{monitoring-page-7MT5FEOS.js → monitoring-page-GGGIWN4C.js} +1 -1
- package/dist/dashboard-web/chunks/{office-page-KD46D5TD.js → office-page-6SIVKSK3.js} +1 -1
- package/dist/dashboard-web/chunks/{overview-page-JUWNH32O.js → overview-page-FVR3NKAF.js} +1 -1
- package/dist/dashboard-web/chunks/{roles-page-P6F7NLOI.js → roles-page-WE2YB7KN.js} +1 -1
- package/dist/dashboard-web/chunks/{schedules-page-XIHWZST4.js → schedules-page-TB3I24XN.js} +1 -1
- package/dist/dashboard-web/chunks/sessions-page-KOOOASIL.js +2 -0
- package/dist/dashboard-web/chunks/settings-page-IEBR7TGN.js +2 -0
- package/dist/dashboard-web/chunks/{skills-page-A46KVWBL.js → skills-page-3QAT2IWD.js} +1 -1
- package/dist/dashboard-web/chunks/{team-federation-page-SDUC56DF.js → team-federation-page-K4VVAVAK.js} +1 -1
- package/dist/dashboard-web/chunks/{v3-page-J5JOTUSQ.js → v3-page-V6IOJR2B.js} +1 -1
- package/dist/dashboard-web/chunks/{whiteboards-page-U7LSOAWI.js → whiteboards-page-V6CGKRNX.js} +1 -1
- package/dist/dashboard-web/style.css +218 -10
- package/dist/dashboard.js +380 -8
- package/dist/dashboard.js.map +1 -1
- package/dist/features/codex-notifier/adoption.d.ts +11 -0
- package/dist/features/codex-notifier/adoption.d.ts.map +1 -0
- package/dist/features/codex-notifier/adoption.js +11 -0
- package/dist/features/codex-notifier/adoption.js.map +1 -0
- package/dist/features/codex-notifier/app-opener.d.ts +21 -0
- package/dist/features/codex-notifier/app-opener.d.ts.map +1 -0
- package/dist/features/codex-notifier/app-opener.js +33 -0
- package/dist/features/codex-notifier/app-opener.js.map +1 -0
- package/dist/features/codex-notifier/card-action.d.ts +27 -0
- package/dist/features/codex-notifier/card-action.d.ts.map +1 -0
- package/dist/features/codex-notifier/card-action.js +84 -0
- package/dist/features/codex-notifier/card-action.js.map +1 -0
- package/dist/features/codex-notifier/card.d.ts +12 -0
- package/dist/features/codex-notifier/card.d.ts.map +1 -0
- package/dist/features/codex-notifier/card.js +150 -0
- package/dist/features/codex-notifier/card.js.map +1 -0
- package/dist/features/codex-notifier/codex-context.d.ts +12 -0
- package/dist/features/codex-notifier/codex-context.d.ts.map +1 -0
- package/dist/features/codex-notifier/codex-context.js +161 -0
- package/dist/features/codex-notifier/codex-context.js.map +1 -0
- package/dist/features/codex-notifier/config.d.ts +9 -0
- package/dist/features/codex-notifier/config.d.ts.map +1 -0
- package/dist/features/codex-notifier/config.js +11 -0
- package/dist/features/codex-notifier/config.js.map +1 -0
- package/dist/features/codex-notifier/confirmed-turn.d.ts +20 -0
- package/dist/features/codex-notifier/confirmed-turn.d.ts.map +1 -0
- package/dist/features/codex-notifier/confirmed-turn.js +130 -0
- package/dist/features/codex-notifier/confirmed-turn.js.map +1 -0
- package/dist/features/codex-notifier/emitter.d.ts +13 -0
- package/dist/features/codex-notifier/emitter.d.ts.map +1 -0
- package/dist/features/codex-notifier/emitter.js +33 -0
- package/dist/features/codex-notifier/emitter.js.map +1 -0
- package/dist/features/codex-notifier/event-store.d.ts +29 -0
- package/dist/features/codex-notifier/event-store.d.ts.map +1 -0
- package/dist/features/codex-notifier/event-store.js +217 -0
- package/dist/features/codex-notifier/event-store.js.map +1 -0
- package/dist/features/codex-notifier/event.d.ts +46 -0
- package/dist/features/codex-notifier/event.d.ts.map +1 -0
- package/dist/features/codex-notifier/event.js +188 -0
- package/dist/features/codex-notifier/event.js.map +1 -0
- package/dist/features/codex-notifier/hook-cli.d.ts +23 -0
- package/dist/features/codex-notifier/hook-cli.d.ts.map +1 -0
- package/dist/features/codex-notifier/hook-cli.js +130 -0
- package/dist/features/codex-notifier/hook-cli.js.map +1 -0
- package/dist/features/codex-notifier/hook-installer.d.ts +19 -0
- package/dist/features/codex-notifier/hook-installer.d.ts.map +1 -0
- package/dist/features/codex-notifier/hook-installer.js +158 -0
- package/dist/features/codex-notifier/hook-installer.js.map +1 -0
- package/dist/features/codex-notifier/index.d.ts +21 -0
- package/dist/features/codex-notifier/index.d.ts.map +1 -0
- package/dist/features/codex-notifier/index.js +19 -0
- package/dist/features/codex-notifier/index.js.map +1 -0
- package/dist/features/codex-notifier/internal-turn.d.ts +5 -0
- package/dist/features/codex-notifier/internal-turn.d.ts.map +1 -0
- package/dist/features/codex-notifier/internal-turn.js +43 -0
- package/dist/features/codex-notifier/internal-turn.js.map +1 -0
- package/dist/features/codex-notifier/outbox-worker.d.ts +71 -0
- package/dist/features/codex-notifier/outbox-worker.d.ts.map +1 -0
- package/dist/features/codex-notifier/outbox-worker.js +290 -0
- package/dist/features/codex-notifier/outbox-worker.js.map +1 -0
- package/dist/features/codex-notifier/outbox.d.ts +25 -0
- package/dist/features/codex-notifier/outbox.d.ts.map +1 -0
- package/dist/features/codex-notifier/outbox.js +225 -0
- package/dist/features/codex-notifier/outbox.js.map +1 -0
- package/dist/features/codex-notifier/paths.d.ts +7 -0
- package/dist/features/codex-notifier/paths.d.ts.map +1 -0
- package/dist/features/codex-notifier/paths.js +20 -0
- package/dist/features/codex-notifier/paths.js.map +1 -0
- package/dist/features/codex-notifier/screen-lock.d.ts +12 -0
- package/dist/features/codex-notifier/screen-lock.d.ts.map +1 -0
- package/dist/features/codex-notifier/screen-lock.js +47 -0
- package/dist/features/codex-notifier/screen-lock.js.map +1 -0
- package/dist/features/codex-notifier/side-conversation-monitor.d.ts +102 -0
- package/dist/features/codex-notifier/side-conversation-monitor.d.ts.map +1 -0
- package/dist/features/codex-notifier/side-conversation-monitor.js +774 -0
- package/dist/features/codex-notifier/side-conversation-monitor.js.map +1 -0
- package/dist/features/codex-notifier/types.d.ts +42 -0
- package/dist/features/codex-notifier/types.d.ts.map +1 -0
- package/dist/features/codex-notifier/types.js +2 -0
- package/dist/features/codex-notifier/types.js.map +1 -0
- package/dist/features/codex-notifier/worker-lock.d.ts +8 -0
- package/dist/features/codex-notifier/worker-lock.d.ts.map +1 -0
- package/dist/features/codex-notifier/worker-lock.js +108 -0
- package/dist/features/codex-notifier/worker-lock.js.map +1 -0
- package/dist/global-config.d.ts +13 -0
- package/dist/global-config.d.ts.map +1 -1
- package/dist/global-config.js +34 -1
- package/dist/global-config.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +1 -19
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +1 -19
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts +0 -13
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +2 -36
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts +2 -0
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +166 -64
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +98 -4
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +317 -29
- 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 +48 -33
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/services/codex-app-threads.d.ts +47 -0
- package/dist/services/codex-app-threads.d.ts.map +1 -1
- package/dist/services/codex-app-threads.js +502 -10
- package/dist/services/codex-app-threads.js.map +1 -1
- package/dist/services/exact-chat-grant.d.ts +83 -0
- package/dist/services/exact-chat-grant.d.ts.map +1 -0
- package/dist/services/exact-chat-grant.js +249 -0
- package/dist/services/exact-chat-grant.js.map +1 -0
- package/dist/services/group-creator.d.ts +11 -0
- package/dist/services/group-creator.d.ts.map +1 -1
- package/dist/services/group-creator.js +18 -9
- package/dist/services/group-creator.js.map +1 -1
- package/dist/services/local-cli-opener.d.ts.map +1 -1
- package/dist/services/local-cli-opener.js +10 -5
- package/dist/services/local-cli-opener.js.map +1 -1
- package/dist/services/sandbox-migration.d.ts +14 -0
- package/dist/services/sandbox-migration.d.ts.map +1 -0
- package/dist/services/sandbox-migration.js +85 -0
- package/dist/services/sandbox-migration.js.map +1 -0
- package/dist/services/sandbox-store.d.ts +28 -0
- package/dist/services/sandbox-store.d.ts.map +1 -1
- package/dist/services/sandbox-store.js +82 -0
- package/dist/services/sandbox-store.js.map +1 -1
- package/dist/services/traex-user-input.d.ts +19 -0
- package/dist/services/traex-user-input.d.ts.map +1 -0
- package/dist/services/traex-user-input.js +57 -0
- package/dist/services/traex-user-input.js.map +1 -0
- package/dist/setup/open-platform-automation.d.ts +24 -3
- package/dist/setup/open-platform-automation.d.ts.map +1 -1
- package/dist/setup/open-platform-automation.js +45 -8
- package/dist/setup/open-platform-automation.js.map +1 -1
- package/dist/setup/verify-permissions.d.ts +18 -0
- package/dist/setup/verify-permissions.d.ts.map +1 -1
- package/dist/setup/verify-permissions.js +60 -0
- package/dist/setup/verify-permissions.js.map +1 -1
- package/dist/types.d.ts +83 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/child-env.d.ts +2 -2
- package/dist/utils/child-env.d.ts.map +1 -1
- package/dist/utils/child-env.js +14 -0
- package/dist/utils/child-env.js.map +1 -1
- package/dist/utils/stuck-detector.d.ts +45 -0
- package/dist/utils/stuck-detector.d.ts.map +1 -0
- package/dist/utils/stuck-detector.js +188 -0
- package/dist/utils/stuck-detector.js.map +1 -0
- package/dist/utils/stuck-key-guard.d.ts +75 -0
- package/dist/utils/stuck-key-guard.d.ts.map +1 -0
- package/dist/utils/stuck-key-guard.js +77 -0
- package/dist/utils/stuck-key-guard.js.map +1 -0
- package/dist/worker.js +1119 -588
- package/dist/worker.js.map +1 -1
- package/dist/workflows/events/payloads.d.ts +56 -0
- package/dist/workflows/events/payloads.d.ts.map +1 -1
- package/dist/workflows/events/payloads.js +9 -0
- package/dist/workflows/events/payloads.js.map +1 -1
- package/dist/workflows/events/schema.d.ts +86 -0
- package/dist/workflows/events/schema.d.ts.map +1 -1
- package/dist/workflows/shared/sandbox-policy.d.ts +10 -1
- package/dist/workflows/shared/sandbox-policy.d.ts.map +1 -1
- package/dist/workflows/shared/sandbox-policy.js +12 -0
- package/dist/workflows/shared/sandbox-policy.js.map +1 -1
- package/dist/workflows/v3/bot-resolve.d.ts.map +1 -1
- package/dist/workflows/v3/bot-resolve.js +36 -0
- package/dist/workflows/v3/bot-resolve.js.map +1 -1
- package/dist/workflows/v3/contract.d.ts +8 -0
- package/dist/workflows/v3/contract.d.ts.map +1 -1
- package/dist/workflows/v3/contract.js.map +1 -1
- package/package.json +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-B5AY4B2J.js +0 -5
- package/dist/dashboard-web/chunks/sessions-page-2VECQ27T.js +0 -3
- package/dist/dashboard-web/chunks/settings-page-HMIUE2JA.js +0 -2
- package/dist/services/sandbox-land.d.ts +0 -45
- package/dist/services/sandbox-land.d.ts.map +0 -1
- package/dist/services/sandbox-land.js +0 -394
- package/dist/services/sandbox-land.js.map +0 -1
package/dist/daemon.js
CHANGED
|
@@ -8,20 +8,22 @@ import { fileURLToPath } from 'node:url';
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = dirname(__filename);
|
|
10
10
|
import { config, getDashboardExternalHost, isVcMeetingAgentGloballyEnabled, vcMeetingAgentGlobalListenerBotAppId, } from './config.js';
|
|
11
|
-
import { repoPickerScanOptions } from './global-config.js';
|
|
11
|
+
import { readGlobalConfig, repoPickerScanOptions } from './global-config.js';
|
|
12
12
|
import { buildDashboardUrls } from './core/dashboard-url.js';
|
|
13
13
|
import { resolveBotmuxDataDir } from './core/data-dir.js';
|
|
14
|
+
import { reloadExactDaemonBotConfig } from './core/daemon-config-fence.js';
|
|
14
15
|
import { writeHeartbeat } from './core/daemon-heartbeat.js';
|
|
15
16
|
import { botmuxWrapperFiles } from './core/botmux-wrapper.js';
|
|
16
17
|
import { startMaintenance, stopMaintenance } from './core/maintenance.js';
|
|
17
18
|
import { selectCodexRuntimeUpdateTargets, startCliRuntimeUpdateMonitor, stopCliRuntimeUpdateMonitor, } from './core/cli-runtime-update.js';
|
|
18
19
|
import { sendRestartReportIfPending } from './core/restart-report.js';
|
|
19
20
|
import { statSync } from 'node:fs';
|
|
20
|
-
import { addReaction, getChatMode, getMessageChatId, listChatMemberOpenIds, MessageWithdrawnError, replyMessage, resolveAllowedUsersWithMap, sendMessage, sendUserMessage, updateMessage } from './im/lark/client.js';
|
|
21
|
+
import { addReaction, getChatMode, getChatNameAndMode, getMessageChatId, listChatMemberOpenIds, MessageWithdrawnError, replyMessage, resolveAllowedUsersWithMap, sendMessage, sendUserMessage, updateMessage } from './im/lark/client.js';
|
|
21
22
|
import { resolveGroupJoinPrompt, waitForAllowedUserInChat } from './core/auto-start.js';
|
|
22
|
-
import { loadBotConfigs, registerBot, getBot, getAllBots, getOwnerOpenId, findOncallChat, effectiveDefaultWorkingDir, effectiveBotDisplayName, resolveVcMeetingConsumerProfiles, } from './bot-registry.js';
|
|
23
|
+
import { loadBotConfigAtIndex, loadBotConfigs, isManagedActivationStartingAtIndex, registerBot, getBot, getAllBots, getOwnerOpenId, findOncallChat, effectiveDefaultWorkingDir, effectiveBotDisplayName, resolveVcMeetingConsumerProfiles, } from './bot-registry.js';
|
|
23
24
|
import { setDisplayNameRefresher, findConfigField, applyConfigField } from './services/bot-config-store.js';
|
|
24
25
|
import { renameBotOnOpenPlatform, changeBotAvatarOnOpenPlatform } from './services/open-platform-rename.js';
|
|
26
|
+
import { migrateSandboxConfigAtStartup } from './services/sandbox-migration.js';
|
|
25
27
|
import * as sessionStore from './services/session-store.js';
|
|
26
28
|
import * as chatFirstSeenStore from './services/chat-first-seen-store.js';
|
|
27
29
|
import { ensureDefaultOncallBound } from './services/oncall-store.js';
|
|
@@ -53,7 +55,7 @@ import { RECEIVED_REACTION_EMOJI_TYPE, SUBSTITUTE_RECEIVED_REACTION_EMOJI_TYPE }
|
|
|
53
55
|
import { t as tr, localeForBot } from './i18n/index.js';
|
|
54
56
|
import { createCliAdapterSync } from './adapters/cli/registry.js';
|
|
55
57
|
import { initWorkerPool, setActiveSessionsRegistry, forkWorker, sendWorkerInput, killWorker, reapOrphanWorkers, scheduleCardPatch, setCurrentCliVersion, getCurrentCliVersion, CARD_POSTING_SENTINEL, parkStreamCard, closeSession as closeSessionHelper, ensureCliEnv, sweepGlobalBotmuxSkills, writableTerminalLinkFor, findActiveBySessionId, getDaemonBootId, } from './core/worker-pool.js';
|
|
56
|
-
import { ipcRoute, isTrustedHostIpcRequest, jsonRes, readJsonBody, setBotName, setLarkAppId, startIpcServer, setBotRenamer, setBotAvatarChanger } from './core/dashboard-ipc-server.js';
|
|
58
|
+
import { AbortDeadlineError, hasExactSafeJsonKeys, ipcRoute, isTrustedHostIpcRequest, JsonBodyTooLargeError, jsonRes, readJsonBody, runWithAbortDeadline, setBotName, setLarkAppId, startIpcServer, setBotRenamer, setBotAvatarChanger } from './core/dashboard-ipc-server.js';
|
|
57
59
|
import { setDeviceIsolationDaemonIdentity } from './core/device-isolation-daemon.js';
|
|
58
60
|
import { cancelSessionReadyAck, waitForSessionReadyAck, } from './core/session-ready-handshake.js';
|
|
59
61
|
import { loadOrCreateDashboardSecret } from './dashboard/auth.js';
|
|
@@ -73,13 +75,14 @@ import { applyQueuedCodexAppLegacyFallback, mergeQueuedCodexAppTurn } from './co
|
|
|
73
75
|
import { findOnlineDaemon, listOnlineDaemons } from './utils/daemon-discovery.js';
|
|
74
76
|
import { beginReplyTargetTurn, fallbackTurnId, isSubstituteTurn, resolveSessionReplyTarget, syncReplyTargetState } from './core/reply-target.js';
|
|
75
77
|
import { readDeferredTopicBinding } from './core/deferred-topic-binding.js';
|
|
78
|
+
import { buildBotmuxLarkNativeSessionTitle, extractBotmuxLarkNativeSessionTitlePrompt, } from './core/session-title.js';
|
|
76
79
|
import { settleDeferredScheduleRun } from './core/deferred-schedule-settlement.js';
|
|
77
80
|
import { sweepOrphanSandboxes } from './adapters/backend/sandbox.js';
|
|
78
81
|
import { TmuxBackend } from './adapters/backend/tmux-backend.js';
|
|
79
82
|
import { HerdrBackend } from './adapters/backend/herdr-backend.js';
|
|
80
83
|
import { ZellijBackend } from './adapters/backend/zellij-backend.js';
|
|
81
84
|
import { sweepIdleWorkers, DEFAULT_MAX_LIVE_WORKERS } from './core/idle-worker-sweeper.js';
|
|
82
|
-
import { getSessionPersistentBackendType, killPersistentSession,
|
|
85
|
+
import { getSessionPersistentBackendType, killPersistentBackendTarget, killPersistentSession, probePersistentBackendTarget, probePersistentSession, resolvePersistentBackendTarget, resolvePairedSpawnBackendType, } from './core/persistent-backend.js';
|
|
83
86
|
import { handleCardAction, runAutoWorktreeCommit } from './im/lark/card-handler.js';
|
|
84
87
|
import { parseWorkflowGrillTrigger, buildWorkflowGrillPrompt, isLegacyTemplateCommand, LEGACY_TEMPLATE_RETIRED_MESSAGE, WORKFLOW_USAGE, } from './im/lark/workflow-slash-command.js';
|
|
85
88
|
import { parseV3SavedWorkflowCommand, v3SavedWorkflowUsage, } from './im/lark/v3-saved-workflow-command.js';
|
|
@@ -104,6 +107,8 @@ import { defaultBaseDir as v3DefaultBaseDir } from './workflows/v3/grill-state.j
|
|
|
104
107
|
import { persistV3StartIntent } from './workflows/v3/start-intent.js';
|
|
105
108
|
import { createWorkflowDaemonIpcNonceStore, generateWorkflowDaemonBootInstanceId, loadWorkflowDaemonIpcSecret, signWorkflowDaemonIpcResponse, verifyWorkflowDaemonIpcRequest, WORKFLOW_DAEMON_IPC_ROUTE_PREFIX, } from './workflows/v3/daemon-ipc-auth.js';
|
|
106
109
|
import { parseWorkflowDaemonMutationBody, } from './workflows/v3/daemon-ipc-body.js';
|
|
110
|
+
import { resolveEffectivePluginIds } from './core/plugins/effective.js';
|
|
111
|
+
import { buildCodexCompletionCard, buildCodexNotifierResultCard, CODEX_NOTIFIER_PLUGIN_ID, CodexNotifierEventStore, CodexNotifierEventValidationError, codexNotifierMessageUuid, createCodexNotifierCardActionHandler, materializeCodexNotifierOutboxEvent, openCodexAppThread, parseCodexNotifierEvent, parseCodexNotifierPluginEvent, parseCodexNotifierOutboxItem, startCodexNotifierAdoptionSession, } from './features/codex-notifier/index.js';
|
|
107
112
|
/** This daemon process's bot larkAppId (set in startDaemon). Used to scope v3
|
|
108
113
|
* humanGate cold-attach + start to runs this bot owns (codex blocker #1). */
|
|
109
114
|
let selfV3LarkAppId;
|
|
@@ -248,7 +253,8 @@ function vcMeetingBootBackingMissing(sessionId, destroy) {
|
|
|
248
253
|
}
|
|
249
254
|
}
|
|
250
255
|
const liveBackend = ds ? getSessionPersistentBackendType(ds) : undefined;
|
|
251
|
-
const
|
|
256
|
+
const persistedSession = ds?.session ?? sessionStore.getSession(sessionId);
|
|
257
|
+
const persistedBackend = liveBackend ?? persistedSession?.backendType;
|
|
252
258
|
if (persistedBackend === 'pty')
|
|
253
259
|
return true;
|
|
254
260
|
const backendTypes = persistedBackend === 'tmux' || persistedBackend === 'herdr' || persistedBackend === 'zellij'
|
|
@@ -256,10 +262,11 @@ function vcMeetingBootBackingMissing(sessionId, destroy) {
|
|
|
256
262
|
: VC_MEETING_PERSISTENT_BACKENDS.filter(vcMeetingPersistentBackendAvailable);
|
|
257
263
|
let allMissing = true;
|
|
258
264
|
for (const backendType of backendTypes) {
|
|
259
|
-
const
|
|
265
|
+
const target = resolvePersistentBackendTarget(backendType, sessionId, persistedSession?.persistentBackendTarget);
|
|
266
|
+
const name = target.sessionName;
|
|
260
267
|
if (destroy) {
|
|
261
268
|
try {
|
|
262
|
-
|
|
269
|
+
killPersistentBackendTarget(target);
|
|
263
270
|
}
|
|
264
271
|
catch (err) {
|
|
265
272
|
logger.warn(`[vc-delivery] boot recovery backing kill failed backend=${backendType} `
|
|
@@ -268,7 +275,7 @@ function vcMeetingBootBackingMissing(sessionId, destroy) {
|
|
|
268
275
|
}
|
|
269
276
|
let probe = 'unknown';
|
|
270
277
|
try {
|
|
271
|
-
probe =
|
|
278
|
+
probe = probePersistentBackendTarget(target);
|
|
272
279
|
}
|
|
273
280
|
catch {
|
|
274
281
|
probe = 'unknown';
|
|
@@ -445,10 +452,12 @@ function createVcMeetingRuntimeLeaseRecovery(deps) {
|
|
|
445
452
|
? VC_MEETING_PERSISTENT_BACKENDS.filter(deps.backendAvailable)
|
|
446
453
|
: [persistentScope];
|
|
447
454
|
let allMissing = true;
|
|
455
|
+
const persistedTarget = deps.resolvePersistentTarget?.(fence.receiverSessionId, ds);
|
|
448
456
|
for (const backendType of backendTypes) {
|
|
449
|
-
const
|
|
457
|
+
const target = resolvePersistentBackendTarget(backendType, fence.receiverSessionId, persistedTarget);
|
|
458
|
+
const name = target.sessionName;
|
|
450
459
|
try {
|
|
451
|
-
deps.killPersistent(backendType, name);
|
|
460
|
+
deps.killPersistent(backendType, name, target);
|
|
452
461
|
}
|
|
453
462
|
catch (err) {
|
|
454
463
|
deps.warn(`[vc-delivery] runtime lease backing kill failed backend=${backendType} `
|
|
@@ -456,7 +465,7 @@ function createVcMeetingRuntimeLeaseRecovery(deps) {
|
|
|
456
465
|
}
|
|
457
466
|
let probe = 'unknown';
|
|
458
467
|
try {
|
|
459
|
-
probe = deps.probePersistent(backendType, name);
|
|
468
|
+
probe = deps.probePersistent(backendType, name, target);
|
|
460
469
|
}
|
|
461
470
|
catch {
|
|
462
471
|
probe = 'unknown';
|
|
@@ -619,8 +628,9 @@ function createVcMeetingRuntimeLeaseRecovery(deps) {
|
|
|
619
628
|
return false;
|
|
620
629
|
}
|
|
621
630
|
let probe = 'unknown';
|
|
631
|
+
const target = resolvePersistentBackendTarget(persistentScope, fence.receiverSessionId, ds.session.persistentBackendTarget);
|
|
622
632
|
try {
|
|
623
|
-
probe = deps.probePersistent(persistentScope,
|
|
633
|
+
probe = deps.probePersistent(persistentScope, target.sessionName, target);
|
|
624
634
|
}
|
|
625
635
|
catch {
|
|
626
636
|
probe = 'unknown';
|
|
@@ -684,9 +694,17 @@ const vcMeetingRuntimeLeaseRecovery = createVcMeetingRuntimeLeaseRecovery({
|
|
|
684
694
|
}
|
|
685
695
|
return backendType === 'pty' ? 'none' : 'unknown';
|
|
686
696
|
},
|
|
697
|
+
resolvePersistentTarget(sessionId, ds) {
|
|
698
|
+
return ds?.session.persistentBackendTarget
|
|
699
|
+
?? sessionStore.getSession(sessionId)?.persistentBackendTarget;
|
|
700
|
+
},
|
|
687
701
|
backendAvailable: vcMeetingPersistentBackendAvailable,
|
|
688
|
-
killPersistent:
|
|
689
|
-
|
|
702
|
+
killPersistent: (backendType, sessionName, target) => target
|
|
703
|
+
? killPersistentBackendTarget(target)
|
|
704
|
+
: killPersistentSession(backendType, sessionName),
|
|
705
|
+
probePersistent: (backendType, sessionName, target) => target
|
|
706
|
+
? probePersistentBackendTarget(target)
|
|
707
|
+
: probePersistentSession(backendType, sessionName),
|
|
690
708
|
warn: message => logger.warn(message),
|
|
691
709
|
error: message => logger.error(message),
|
|
692
710
|
});
|
|
@@ -1593,6 +1611,29 @@ function setDirectChatDisplayNameFromSender(session, chatType, sender) {
|
|
|
1593
1611
|
if (name)
|
|
1594
1612
|
session.chatDisplayName = name;
|
|
1595
1613
|
}
|
|
1614
|
+
const NATIVE_TITLE_CHAT_NAME_TIMEOUT_MS = 800;
|
|
1615
|
+
/** 首条只有机器人 mention 时,尽力取群名作为原生会话标题兜底。 */
|
|
1616
|
+
async function resolveGroupChatNameForNativeTitle(larkAppId, chatId, chatType, cliId, rawContent, mentions) {
|
|
1617
|
+
if (chatType !== 'group'
|
|
1618
|
+
|| cliId !== 'codex'
|
|
1619
|
+
|| extractBotmuxLarkNativeSessionTitlePrompt(rawContent, mentions)) {
|
|
1620
|
+
return undefined;
|
|
1621
|
+
}
|
|
1622
|
+
let timer;
|
|
1623
|
+
const timeout = new Promise(resolve => {
|
|
1624
|
+
timer = setTimeout(resolve, NATIVE_TITLE_CHAT_NAME_TIMEOUT_MS);
|
|
1625
|
+
});
|
|
1626
|
+
try {
|
|
1627
|
+
return await Promise.race([
|
|
1628
|
+
getChatNameAndMode(larkAppId, chatId).then(info => info.name ?? undefined),
|
|
1629
|
+
timeout,
|
|
1630
|
+
]);
|
|
1631
|
+
}
|
|
1632
|
+
finally {
|
|
1633
|
+
if (timer)
|
|
1634
|
+
clearTimeout(timer);
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1596
1637
|
// Cache last /repo scan results per chat for /repo <number> fallback.
|
|
1597
1638
|
// Bounded: this is a transient picker cache keyed by chatId (unbounded over a
|
|
1598
1639
|
// long-lived daemon's chat set), so cap it instead of retaining one
|
|
@@ -2699,11 +2740,211 @@ const v3GateRunner = createV3GateRunner({
|
|
|
2699
2740
|
// 每个 bot 的 EventHandlers,授权成功后重放消息时需要。
|
|
2700
2741
|
// key = larkAppId,在 startLarkEventDispatcher 调用时写入。
|
|
2701
2742
|
const botHandlers = new Map();
|
|
2743
|
+
const codexNotifierStores = new Map();
|
|
2744
|
+
const codexNotifierDeliveries = new Map();
|
|
2745
|
+
const CODEX_NOTIFIER_INGRESS_MAX_BYTES = 128 * 1024;
|
|
2746
|
+
const CODEX_NOTIFIER_DELIVERY_TIMEOUT_MS = 10_000;
|
|
2747
|
+
const CODEX_NOTIFIER_ADOPTION_TIMEOUT_MS = 2_200;
|
|
2748
|
+
const CODEX_NOTIFIER_MESSAGE_LOOKUP_TIMEOUT_MS = 1_200;
|
|
2749
|
+
function remainingCodexNotifierDeadline(deadlineAt, capMs) {
|
|
2750
|
+
return Math.max(1, Math.min(capMs, deadlineAt - Date.now()));
|
|
2751
|
+
}
|
|
2752
|
+
function codexNotifierStore(larkAppId) {
|
|
2753
|
+
const existing = codexNotifierStores.get(larkAppId);
|
|
2754
|
+
if (existing)
|
|
2755
|
+
return existing;
|
|
2756
|
+
const suffix = createHash('sha256').update(larkAppId).digest('hex').slice(0, 16);
|
|
2757
|
+
const store = new CodexNotifierEventStore(join(config.session.dataDir, 'plugin-events', `codex-notifier-${suffix}.json`));
|
|
2758
|
+
codexNotifierStores.set(larkAppId, store);
|
|
2759
|
+
return store;
|
|
2760
|
+
}
|
|
2761
|
+
function codexNotifierIngressEnabled(larkAppId, legacyPlugin = false) {
|
|
2762
|
+
const global = readGlobalConfig();
|
|
2763
|
+
if (global.codexNotifier !== undefined || !legacyPlugin) {
|
|
2764
|
+
return global.codexNotifier?.enabled === true;
|
|
2765
|
+
}
|
|
2766
|
+
try {
|
|
2767
|
+
return resolveEffectivePluginIds(getBot(larkAppId).config, global)
|
|
2768
|
+
.includes(CODEX_NOTIFIER_PLUGIN_ID);
|
|
2769
|
+
}
|
|
2770
|
+
catch {
|
|
2771
|
+
return false;
|
|
2772
|
+
}
|
|
2773
|
+
}
|
|
2774
|
+
/** 用 Codex 原生线程名补全通知标题;失败时保留插件事件里的安全兜底信息。 */
|
|
2775
|
+
async function enrichCodexNotifierEvent(larkAppId, event) {
|
|
2776
|
+
if (event.title)
|
|
2777
|
+
return event;
|
|
2778
|
+
try {
|
|
2779
|
+
const { readCodexAppThreadMetadata } = await import('./services/codex-app-threads.js');
|
|
2780
|
+
const metadata = await readCodexAppThreadMetadata({
|
|
2781
|
+
threadId: event.threadId,
|
|
2782
|
+
codexBin: getBot(larkAppId).config.cliPathOverride,
|
|
2783
|
+
cwd: event.cwd,
|
|
2784
|
+
timeoutMs: 3_000,
|
|
2785
|
+
});
|
|
2786
|
+
const title = metadata.name?.trim();
|
|
2787
|
+
return title ? { ...event, title: Array.from(title).slice(0, 300).join('') } : event;
|
|
2788
|
+
}
|
|
2789
|
+
catch (error) {
|
|
2790
|
+
logger.warn(`[codex-notifier] thread title lookup failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2791
|
+
return event;
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
async function deliverCodexNotifierEvent(larkAppId, event) {
|
|
2795
|
+
const store = codexNotifierStore(larkAppId);
|
|
2796
|
+
const enrichedEvent = store.get(event.eventId) ? event : await enrichCodexNotifierEvent(larkAppId, event);
|
|
2797
|
+
const recorded = store.record(enrichedEvent);
|
|
2798
|
+
const deliveryEvent = recorded.record.event;
|
|
2799
|
+
if (!recorded.inserted) {
|
|
2800
|
+
if (deliveryEvent.type !== event.type
|
|
2801
|
+
|| deliveryEvent.source !== event.source
|
|
2802
|
+
|| deliveryEvent.threadId !== event.threadId
|
|
2803
|
+
|| deliveryEvent.nativeTurnId !== event.nativeTurnId
|
|
2804
|
+
|| deliveryEvent.status !== event.status) {
|
|
2805
|
+
throw new Error('codex_notifier_event_id_conflict');
|
|
2806
|
+
}
|
|
2807
|
+
if (recorded.record.delivery.status === 'delivered' && recorded.record.delivery.messageId) {
|
|
2808
|
+
return { status: 'duplicate', messageId: recorded.record.delivery.messageId };
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
const deliveryKey = `${larkAppId}:${event.eventId}`;
|
|
2812
|
+
const current = codexNotifierDeliveries.get(deliveryKey);
|
|
2813
|
+
if (current)
|
|
2814
|
+
return current;
|
|
2815
|
+
const delivery = (async () => {
|
|
2816
|
+
const ownerOpenId = getOwnerOpenId(larkAppId) ?? resolvePrimaryOwnerOpenId(larkAppId);
|
|
2817
|
+
if (!ownerOpenId)
|
|
2818
|
+
throw new Error('codex_notifier_owner_unavailable');
|
|
2819
|
+
store.updateDelivery(event.eventId, { status: 'pending' });
|
|
2820
|
+
try {
|
|
2821
|
+
const messageId = await runWithAbortDeadline('codex_notifier_delivery', CODEX_NOTIFIER_DELIVERY_TIMEOUT_MS, signal => sendUserMessage(larkAppId, ownerOpenId, buildCodexCompletionCard(deliveryEvent), 'interactive', codexNotifierMessageUuid(event.eventId), {
|
|
2822
|
+
timeoutMs: CODEX_NOTIFIER_DELIVERY_TIMEOUT_MS,
|
|
2823
|
+
signal,
|
|
2824
|
+
}));
|
|
2825
|
+
store.updateDelivery(event.eventId, { status: 'delivered', messageId, incrementAttempts: false });
|
|
2826
|
+
return { status: 'accepted', messageId };
|
|
2827
|
+
}
|
|
2828
|
+
catch (error) {
|
|
2829
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
2830
|
+
store.updateDelivery(event.eventId, {
|
|
2831
|
+
status: 'failed',
|
|
2832
|
+
lastError: detail,
|
|
2833
|
+
incrementAttempts: false,
|
|
2834
|
+
});
|
|
2835
|
+
throw error;
|
|
2836
|
+
}
|
|
2837
|
+
})();
|
|
2838
|
+
codexNotifierDeliveries.set(deliveryKey, delivery);
|
|
2839
|
+
try {
|
|
2840
|
+
return await delivery;
|
|
2841
|
+
}
|
|
2842
|
+
finally {
|
|
2843
|
+
codexNotifierDeliveries.delete(deliveryKey);
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
async function adoptCodexNotifierEvent(larkAppId, event, cardMessageId, ownerOpenId, signal, deadlineAt) {
|
|
2847
|
+
signal.throwIfAborted();
|
|
2848
|
+
const chatId = await getMessageChatId(larkAppId, cardMessageId, {
|
|
2849
|
+
timeoutMs: remainingCodexNotifierDeadline(deadlineAt, CODEX_NOTIFIER_MESSAGE_LOOKUP_TIMEOUT_MS),
|
|
2850
|
+
signal,
|
|
2851
|
+
});
|
|
2852
|
+
if (!chatId)
|
|
2853
|
+
throw new Error('无法定位完成通知所在的飞书私聊');
|
|
2854
|
+
signal.throwIfAborted();
|
|
2855
|
+
const botCfg = getBot(larkAppId).config;
|
|
2856
|
+
const scope = botCfg.p2pMode === 'chat' ? 'chat' : 'thread';
|
|
2857
|
+
const anchor = scope === 'chat' ? chatId : cardMessageId;
|
|
2858
|
+
const activeKey = sessionKey(anchor, larkAppId);
|
|
2859
|
+
let ds = activeSessions.get(activeKey);
|
|
2860
|
+
if (!ds) {
|
|
2861
|
+
const fallbackTitle = event.cwd.split(/[\\/]/).filter(Boolean).pop() ?? 'Codex App';
|
|
2862
|
+
const title = (event.title || `Codex App: ${fallbackTitle}`).slice(0, 50);
|
|
2863
|
+
const session = sessionStore.createSession(chatId, cardMessageId, title, 'p2p');
|
|
2864
|
+
const now = Date.now();
|
|
2865
|
+
session.larkAppId = larkAppId;
|
|
2866
|
+
session.scope = scope;
|
|
2867
|
+
session.ownerOpenId = ownerOpenId;
|
|
2868
|
+
session.lastCallerOpenId = ownerOpenId;
|
|
2869
|
+
session.lastMessageAt = new Date(now).toISOString();
|
|
2870
|
+
session.workingDir = event.cwd;
|
|
2871
|
+
session.cliId = 'codex-app';
|
|
2872
|
+
sessionStore.updateSession(session);
|
|
2873
|
+
messageQueue.ensureQueue(anchor);
|
|
2874
|
+
ds = {
|
|
2875
|
+
session,
|
|
2876
|
+
worker: null,
|
|
2877
|
+
workerPort: null,
|
|
2878
|
+
workerToken: null,
|
|
2879
|
+
larkAppId,
|
|
2880
|
+
chatId,
|
|
2881
|
+
chatType: 'p2p',
|
|
2882
|
+
scope,
|
|
2883
|
+
spawnedAt: Date.parse(session.createdAt) || now,
|
|
2884
|
+
cliVersion: getCurrentCliVersion(),
|
|
2885
|
+
lastMessageAt: now,
|
|
2886
|
+
hasHistory: false,
|
|
2887
|
+
workingDir: event.cwd,
|
|
2888
|
+
ownerOpenId,
|
|
2889
|
+
};
|
|
2890
|
+
activeSessions.set(activeKey, ds);
|
|
2891
|
+
}
|
|
2892
|
+
if (ds.session.cliSessionId !== event.threadId || !ds.worker || ds.worker.killed) {
|
|
2893
|
+
// 接管原生 Codex App 线程时固定为纯 codex-app 启动,不能继承通知 Bot 的
|
|
2894
|
+
// wrapper/model;这些配置针对普通 CLI,会错误包装 app-server runner。
|
|
2895
|
+
ds.session.cliId = 'codex-app';
|
|
2896
|
+
ds.session.cliPathOverride = botCfg.cliPathOverride;
|
|
2897
|
+
delete ds.session.wrapperCli;
|
|
2898
|
+
delete ds.session.model;
|
|
2899
|
+
ds.session.agentFrozen = true;
|
|
2900
|
+
sessionStore.updateSession(ds.session);
|
|
2901
|
+
ds.pendingRepo = false;
|
|
2902
|
+
ds.pendingPrompt = undefined;
|
|
2903
|
+
ds.pendingTurnId = undefined;
|
|
2904
|
+
ds.pendingCodexAppText = undefined;
|
|
2905
|
+
ds.pendingCodexAppApplicationContext = undefined;
|
|
2906
|
+
ds.pendingCodexAppMessageContext = undefined;
|
|
2907
|
+
// 完成事件已经携带恢复所需的原生 threadId/cwd。按钮回调不再额外启动一次
|
|
2908
|
+
// app-server 做非必要的元数据刷新,避免子进程把飞书回调拖过截止时间。
|
|
2909
|
+
const target = {
|
|
2910
|
+
threadId: event.threadId,
|
|
2911
|
+
name: event.title,
|
|
2912
|
+
preview: event.finalPreview ?? '',
|
|
2913
|
+
cwd: event.cwd,
|
|
2914
|
+
status: event.status,
|
|
2915
|
+
};
|
|
2916
|
+
const { startCodexAppThreadSession } = await import('./core/command-handler.js');
|
|
2917
|
+
signal.throwIfAborted();
|
|
2918
|
+
await startCodexNotifierAdoptionSession(startCodexAppThreadSession, target, ds, {
|
|
2919
|
+
activeSessions,
|
|
2920
|
+
sessionReply,
|
|
2921
|
+
getActiveCount,
|
|
2922
|
+
lastRepoScan,
|
|
2923
|
+
}, larkAppId, cardMessageId);
|
|
2924
|
+
}
|
|
2925
|
+
return buildCodexNotifierResultCard('已接管 Codex App 任务', scope === 'chat'
|
|
2926
|
+
? '现在可以直接在当前私聊继续发送指令;需要操作终端时,请点击会话卡内的「获取操作链接」。'
|
|
2927
|
+
: '请在本卡片的话题中继续发送指令;需要操作终端时,请点击话题会话卡内的「获取操作链接」。', 'green');
|
|
2928
|
+
}
|
|
2929
|
+
const handleCodexNotifierCardAction = createCodexNotifierCardActionHandler({
|
|
2930
|
+
getExpectedOwnerOpenId: larkAppId => getOwnerOpenId(larkAppId) ?? resolvePrimaryOwnerOpenId(larkAppId),
|
|
2931
|
+
getEventRecord: (larkAppId, eventId) => codexNotifierStore(larkAppId).get(eventId),
|
|
2932
|
+
readConfig: () => readGlobalConfig().codexNotifier,
|
|
2933
|
+
openAppThread: openCodexAppThread,
|
|
2934
|
+
adoptEvent: adoptCodexNotifierEvent,
|
|
2935
|
+
runWithAbortDeadline,
|
|
2936
|
+
isAbortDeadlineError: error => error instanceof AbortDeadlineError,
|
|
2937
|
+
adoptionTimeoutMs: CODEX_NOTIFIER_ADOPTION_TIMEOUT_MS,
|
|
2938
|
+
logInfo: message => logger.info(message),
|
|
2939
|
+
logWarn: message => logger.warn(message),
|
|
2940
|
+
logError: message => logger.error(message),
|
|
2941
|
+
});
|
|
2702
2942
|
const cardDeps = {
|
|
2703
2943
|
activeSessions,
|
|
2704
2944
|
sessionReply,
|
|
2705
2945
|
lastRepoScan,
|
|
2706
2946
|
vcMeetingCardAction: (data, appId) => handleVcMeetingCardAction(data, appId),
|
|
2947
|
+
codexNotifierCardAction: (data, appId) => handleCodexNotifierCardAction(data, appId),
|
|
2707
2948
|
v3GateDeps: {
|
|
2708
2949
|
driveRun: (runId) => v3GateRunner.driveDetached(runId),
|
|
2709
2950
|
// 审批权限:复用 canOperate(话题 owner / allowedUsers / oncall)。无 binding(corrupt /
|
|
@@ -3328,6 +3569,98 @@ ipcRoute('POST', '/api/session-ready', async (req, res) => {
|
|
|
3328
3569
|
}
|
|
3329
3570
|
return jsonRes(res, 200, { ok: true });
|
|
3330
3571
|
});
|
|
3572
|
+
async function respondCodexNotifierIngress(res, larkAppId, rawEvent, pluginId) {
|
|
3573
|
+
if (!codexNotifierIngressEnabled(larkAppId, pluginId === CODEX_NOTIFIER_PLUGIN_ID)) {
|
|
3574
|
+
return jsonRes(res, 403, { ok: false, error: 'codex_notifier_disabled' });
|
|
3575
|
+
}
|
|
3576
|
+
let event;
|
|
3577
|
+
try {
|
|
3578
|
+
event = pluginId === undefined
|
|
3579
|
+
? parseCodexNotifierEvent(rawEvent)
|
|
3580
|
+
: parseCodexNotifierPluginEvent(pluginId, rawEvent);
|
|
3581
|
+
}
|
|
3582
|
+
catch (error) {
|
|
3583
|
+
const code = error instanceof CodexNotifierEventValidationError
|
|
3584
|
+
? error.code
|
|
3585
|
+
: 'invalid_event';
|
|
3586
|
+
return jsonRes(res, 400, { ok: false, error: code });
|
|
3587
|
+
}
|
|
3588
|
+
try {
|
|
3589
|
+
const result = await deliverCodexNotifierEvent(larkAppId, event);
|
|
3590
|
+
return jsonRes(res, 200, { ok: true, status: result.status, messageId: result.messageId });
|
|
3591
|
+
}
|
|
3592
|
+
catch (error) {
|
|
3593
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
3594
|
+
if (detail === 'codex_notifier_event_id_conflict') {
|
|
3595
|
+
return jsonRes(res, 409, { ok: false, error: 'event_id_conflict' });
|
|
3596
|
+
}
|
|
3597
|
+
logger.warn(`[codex-notifier] delivery failed event=${event.eventId.slice(0, 12)}: ${detail}`);
|
|
3598
|
+
return jsonRes(res, 502, { ok: false, error: 'delivery_failed' });
|
|
3599
|
+
}
|
|
3600
|
+
}
|
|
3601
|
+
// ─── 内建 Codex 完成事件入口 ────────────────────────────────────────────────
|
|
3602
|
+
// Dashboard 单例 worker 持有可靠 outbox,通过 host HMAC 投递到入队时选定的 Bot。
|
|
3603
|
+
ipcRoute('POST', '/api/codex-notifier/events', async (req, res) => {
|
|
3604
|
+
if (!isTrustedHostIpcRequest(req)) {
|
|
3605
|
+
return jsonRes(res, 403, { ok: false, error: 'trusted_host_required' });
|
|
3606
|
+
}
|
|
3607
|
+
const larkAppId = selfDaemonLarkAppId;
|
|
3608
|
+
if (!larkAppId) {
|
|
3609
|
+
return jsonRes(res, 503, { ok: false, error: 'daemon_not_ready' });
|
|
3610
|
+
}
|
|
3611
|
+
let raw;
|
|
3612
|
+
try {
|
|
3613
|
+
raw = await readJsonBody(req, CODEX_NOTIFIER_INGRESS_MAX_BYTES);
|
|
3614
|
+
}
|
|
3615
|
+
catch (error) {
|
|
3616
|
+
if (error instanceof JsonBodyTooLargeError) {
|
|
3617
|
+
return jsonRes(res, 413, { ok: false, error: 'payload_too_large' });
|
|
3618
|
+
}
|
|
3619
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
3620
|
+
}
|
|
3621
|
+
let item;
|
|
3622
|
+
try {
|
|
3623
|
+
item = parseCodexNotifierOutboxItem(raw);
|
|
3624
|
+
}
|
|
3625
|
+
catch {
|
|
3626
|
+
return jsonRes(res, 400, { ok: false, error: 'invalid_outbox_item' });
|
|
3627
|
+
}
|
|
3628
|
+
if (item.targetBotAppId !== larkAppId) {
|
|
3629
|
+
return jsonRes(res, 403, { ok: false, error: 'target_bot_mismatch' });
|
|
3630
|
+
}
|
|
3631
|
+
return respondCodexNotifierIngress(res, larkAppId, materializeCodexNotifierOutboxEvent(item));
|
|
3632
|
+
});
|
|
3633
|
+
// 旧独立插件的兼容入口保留一个迁移周期,只负责排空已经落盘的历史 outbox。
|
|
3634
|
+
ipcRoute('POST', '/api/plugin-events', async (req, res) => {
|
|
3635
|
+
if (!isTrustedHostIpcRequest(req)) {
|
|
3636
|
+
return jsonRes(res, 403, { ok: false, error: 'trusted_host_required' });
|
|
3637
|
+
}
|
|
3638
|
+
const larkAppId = selfDaemonLarkAppId;
|
|
3639
|
+
if (!larkAppId) {
|
|
3640
|
+
return jsonRes(res, 503, { ok: false, error: 'daemon_not_ready' });
|
|
3641
|
+
}
|
|
3642
|
+
let raw;
|
|
3643
|
+
try {
|
|
3644
|
+
raw = await readJsonBody(req, CODEX_NOTIFIER_INGRESS_MAX_BYTES);
|
|
3645
|
+
}
|
|
3646
|
+
catch (error) {
|
|
3647
|
+
if (error instanceof JsonBodyTooLargeError) {
|
|
3648
|
+
return jsonRes(res, 413, { ok: false, error: 'payload_too_large' });
|
|
3649
|
+
}
|
|
3650
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
3651
|
+
}
|
|
3652
|
+
if (!hasExactSafeJsonKeys(raw, ['pluginId', 'targetBotAppId', 'event'])) {
|
|
3653
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_body' });
|
|
3654
|
+
}
|
|
3655
|
+
const { pluginId, targetBotAppId, event: rawEvent, } = raw;
|
|
3656
|
+
if (pluginId !== CODEX_NOTIFIER_PLUGIN_ID) {
|
|
3657
|
+
return jsonRes(res, 400, { ok: false, error: 'unsupported_plugin' });
|
|
3658
|
+
}
|
|
3659
|
+
if (targetBotAppId !== larkAppId) {
|
|
3660
|
+
return jsonRes(res, 403, { ok: false, error: 'target_bot_mismatch' });
|
|
3661
|
+
}
|
|
3662
|
+
return respondCodexNotifierIngress(res, larkAppId, rawEvent, pluginId);
|
|
3663
|
+
});
|
|
3331
3664
|
// ─── hooks emit 转发端点 ────────────────────────────────────────────────────
|
|
3332
3665
|
// CLI side(botmux send 等)调用 emitHookEvent 时,把事件转发到 daemon 这条
|
|
3333
3666
|
// 接口;daemon 在自己的长寿命事件循环里负责 spawn hook、跑 timeout、超时杀
|
|
@@ -12288,6 +12621,7 @@ async function handleNewTopic(data, ctx) {
|
|
|
12288
12621
|
// Resolve sender identity for <sender> tag injection. The first call to
|
|
12289
12622
|
// resolveSender for an unseen open_id may await contact.v3.user.get with a
|
|
12290
12623
|
// short budget; subsequent calls hit the cache and are sync-fast.
|
|
12624
|
+
const groupChatNamePromise = resolveGroupChatNameForNativeTitle(larkAppId, chatId, chatType, botCfg.cliId, parsed.content, parsed.mentions);
|
|
12291
12625
|
const newTopicSender = await resolveSender(larkAppId, senderOpenId, parsed.senderType);
|
|
12292
12626
|
refreshCliVersion(botCfg.cliId, botCfg.cliPathOverride);
|
|
12293
12627
|
// Pin the working dir via the layered oncall / inherit / default lookup
|
|
@@ -12310,6 +12644,9 @@ async function handleNewTopic(data, ctx) {
|
|
|
12310
12644
|
const session = sessionStore.createSession(chatId, rootIdForStore, parsed.content.substring(0, 50), chatType);
|
|
12311
12645
|
const now = Date.now();
|
|
12312
12646
|
setDirectChatDisplayNameFromSender(session, chatType, newTopicSender);
|
|
12647
|
+
const groupChatName = await groupChatNamePromise;
|
|
12648
|
+
if (groupChatName)
|
|
12649
|
+
session.chatDisplayName = groupChatName;
|
|
12313
12650
|
session.larkAppId = larkAppId;
|
|
12314
12651
|
session.ownerOpenId = senderOpenId;
|
|
12315
12652
|
session.ownerUnionId = senderUnionId;
|
|
@@ -12323,6 +12660,7 @@ async function handleNewTopic(data, ctx) {
|
|
|
12323
12660
|
session.quoteTargetSenderIsBot = parsed.senderType === 'app' || parsed.senderType === 'bot';
|
|
12324
12661
|
session.lastMessageAt = new Date(now).toISOString();
|
|
12325
12662
|
session.scope = scope;
|
|
12663
|
+
session.nativeSessionTitle = buildBotmuxLarkNativeSessionTitle(parsed.content, parsed.mentions, groupChatName);
|
|
12326
12664
|
sessionStore.updateSession(session);
|
|
12327
12665
|
messageQueue.ensureQueue(anchor);
|
|
12328
12666
|
messageQueue.appendMessage(anchor, parsed);
|
|
@@ -13222,6 +13560,7 @@ async function handleThreadReply(data, ctx) {
|
|
|
13222
13560
|
const autoCreateChatId = ctxChatId ?? data?.message?.chat_id ?? '';
|
|
13223
13561
|
const autoCreateChatType = ctxChatType ?? (data?.message?.chat_type === 'p2p' ? 'p2p' : 'group');
|
|
13224
13562
|
const botCfg = getBot(larkAppId).config;
|
|
13563
|
+
const groupChatNamePromise = resolveGroupChatNameForNativeTitle(larkAppId, autoCreateChatId, autoCreateChatType, botCfg.cliId, parsed.content, parsed.mentions);
|
|
13225
13564
|
logger.info(`No active session for ${scope}-scope ${anchor}, auto-creating new session...`);
|
|
13226
13565
|
refreshCliVersion(botCfg.cliId, botCfg.cliPathOverride);
|
|
13227
13566
|
const senderOId = data.sender?.sender_id?.open_id;
|
|
@@ -13249,6 +13588,10 @@ async function handleThreadReply(data, ctx) {
|
|
|
13249
13588
|
session.quoteTargetSenderIsBot = isForeignBot;
|
|
13250
13589
|
session.lastMessageAt = new Date(now).toISOString();
|
|
13251
13590
|
session.scope = scope;
|
|
13591
|
+
const groupChatName = await groupChatNamePromise;
|
|
13592
|
+
if (groupChatName)
|
|
13593
|
+
session.chatDisplayName = groupChatName;
|
|
13594
|
+
session.nativeSessionTitle = buildBotmuxLarkNativeSessionTitle(parsed.content, parsed.mentions, groupChatName);
|
|
13252
13595
|
sessionStore.updateSession(session);
|
|
13253
13596
|
// chat-scope only — see the handleNewTopic twin above (topic substitute
|
|
13254
13597
|
// sessions keep their streaming card, no control-card compensation).
|
|
@@ -13877,6 +14220,25 @@ function dashboardUrlForReport() {
|
|
|
13877
14220
|
return {};
|
|
13878
14221
|
}
|
|
13879
14222
|
}
|
|
14223
|
+
async function waitForManagedActivationCommit(index, appId) {
|
|
14224
|
+
const activationAppId = process.env.BOTMUX_MANAGED_ACTIVATION_APP_ID;
|
|
14225
|
+
if (activationAppId === undefined)
|
|
14226
|
+
return;
|
|
14227
|
+
if (activationAppId !== appId) {
|
|
14228
|
+
throw new Error(`Managed activation App drifted at BOTMUX_BOT_INDEX=${index}`);
|
|
14229
|
+
}
|
|
14230
|
+
const activationJobId = process.env.BOTMUX_MANAGED_ACTIVATION_JOB_ID;
|
|
14231
|
+
if (!activationJobId) {
|
|
14232
|
+
throw new Error(`Managed activation receipt is missing at BOTMUX_BOT_INDEX=${index}`);
|
|
14233
|
+
}
|
|
14234
|
+
while (isManagedActivationStartingAtIndex(index, appId, activationJobId)) {
|
|
14235
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
14236
|
+
}
|
|
14237
|
+
const committed = loadBotConfigAtIndex(index);
|
|
14238
|
+
if (committed.larkAppId !== appId) {
|
|
14239
|
+
throw new Error(`Managed activation target drifted at BOTMUX_BOT_INDEX=${index}`);
|
|
14240
|
+
}
|
|
14241
|
+
}
|
|
13880
14242
|
export async function startDaemon(botIndex) {
|
|
13881
14243
|
// Repair a shared tmux server polluted by an older botmux immediately on
|
|
13882
14244
|
// daemon startup. This must not depend on restoring/spawning a bmx-* session:
|
|
@@ -13892,27 +14254,36 @@ export async function startDaemon(botIndex) {
|
|
|
13892
14254
|
// 首次启动时后台尝试安装 CJK 字体(Debian/Ubuntu),避免截图中文显示豆腐块。
|
|
13893
14255
|
// 不阻塞:首张截图可能仍是豆腐块,装完重启 daemon 即可正常。
|
|
13894
14256
|
ensureCjkFontsInstalled();
|
|
14257
|
+
// Auto-migrate legacy sandbox fields (readIsolation / sandboxHidePaths /
|
|
14258
|
+
// sandboxReadonlyPaths / readDenyExtraPaths → sandbox + sandboxPaths) BEFORE
|
|
14259
|
+
// loading, so the parsed configs below already carry the new model. Writes
|
|
14260
|
+
// new fields, keeps old ones (downgrade = zero-op), backs up once. Idempotent.
|
|
14261
|
+
await migrateSandboxConfigAtStartup();
|
|
13895
14262
|
// Load the assigned bot (one daemon per bot)
|
|
13896
14263
|
let botConfigs = loadBotConfigs();
|
|
13897
14264
|
const idx = botIndex ?? 0;
|
|
13898
|
-
|
|
13899
|
-
|
|
14265
|
+
let cfg = botIndex === undefined
|
|
14266
|
+
? botConfigs[idx]
|
|
14267
|
+
: loadBotConfigAtIndex(idx);
|
|
14268
|
+
if (!cfg) {
|
|
14269
|
+
throw new Error(`Invalid BOTMUX_BOT_INDEX=${idx}, only ${botConfigs.length} active bot(s) configured`);
|
|
14270
|
+
}
|
|
14271
|
+
if (botIndex !== undefined) {
|
|
14272
|
+
// During managed activation PM2 may report this process online before it
|
|
14273
|
+
// is allowed to register a bot or receive traffic. The dashboard clears
|
|
14274
|
+
// the exact startup marker only after it has re-read the PM2 receipt ACK.
|
|
14275
|
+
await waitForManagedActivationCommit(idx, cfg.larkAppId);
|
|
14276
|
+
botConfigs = loadBotConfigs();
|
|
14277
|
+
cfg = loadBotConfigAtIndex(idx);
|
|
13900
14278
|
}
|
|
13901
|
-
let cfg = botConfigs[idx];
|
|
13902
14279
|
// One-time, lock-protected catalog bootstrap. This runs only after the
|
|
13903
14280
|
// complete bots.json has parsed successfully, and the helper re-reads the
|
|
13904
14281
|
// latest file under its lock before deciding. Explicit [] and legacy agent
|
|
13905
14282
|
// policy are durable opt-outs. Reload the selected config after a write so
|
|
13906
14283
|
// this daemon exposes the seeded selection card immediately on the same boot.
|
|
13907
|
-
const
|
|
14284
|
+
const selectedAppId = cfg.larkAppId;
|
|
14285
|
+
const profileBootstrap = await bootstrapVcMeetingDefaultConsumerProfile(selectedAppId);
|
|
13908
14286
|
if (profileBootstrap.ok) {
|
|
13909
|
-
const selectedAppId = cfg.larkAppId;
|
|
13910
|
-
// Reload even when another concurrent daemon won the one-time write. Both
|
|
13911
|
-
// processes may have loaded the old file before taking the config lock;
|
|
13912
|
-
// the loser still needs the winner's catalog on this boot.
|
|
13913
|
-
botConfigs = loadBotConfigs();
|
|
13914
|
-
cfg = botConfigs.find(candidate => candidate.larkAppId === selectedAppId)
|
|
13915
|
-
?? botConfigs[idx];
|
|
13916
14287
|
if (profileBootstrap.seeded) {
|
|
13917
14288
|
logger.info(`[vc-agent] seeded default meeting minutes profile listener=${selectedAppId} `
|
|
13918
14289
|
+ `agent=${profileBootstrap.agentAppId}`);
|
|
@@ -13922,6 +14293,12 @@ export async function startDaemon(botIndex) {
|
|
|
13922
14293
|
logger.warn(`[vc-agent] default consumer profile bootstrap skipped: ${profileBootstrap.reason}`
|
|
13923
14294
|
+ `${profileBootstrap.error ? ` (${profileBootstrap.error})` : ''}`);
|
|
13924
14295
|
}
|
|
14296
|
+
// A bootstrap failure is not authority to keep an earlier in-memory config.
|
|
14297
|
+
// Every explicit PM2 daemon must prove its same raw slot and App identity
|
|
14298
|
+
// immediately before registerBot, regardless of the bootstrap result.
|
|
14299
|
+
if (botIndex !== undefined) {
|
|
14300
|
+
cfg = reloadExactDaemonBotConfig(idx, selectedAppId, loadBotConfigAtIndex);
|
|
14301
|
+
}
|
|
13925
14302
|
registerBot(cfg);
|
|
13926
14303
|
selfDaemonLarkAppId = cfg.larkAppId;
|
|
13927
14304
|
// Establish the target-scoped daemon control credential before publishing
|