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