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/dashboard.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/dashboard.ts
|
|
2
2
|
import { createServer, get as httpGet, request as httpRequest } from 'node:http';
|
|
3
3
|
import { createServer as createTcpServer, connect as netConnect } from 'node:net';
|
|
4
|
-
import { readFileSync, existsSync, mkdirSync, readdirSync, statSync, createReadStream, } from 'node:fs';
|
|
4
|
+
import { readFileSync, existsSync, mkdirSync, readdirSync, statSync, createReadStream, realpathSync, } from 'node:fs';
|
|
5
5
|
import { atomicWriteFileSync } from './utils/atomic-write.js';
|
|
6
6
|
import { join, dirname, extname, resolve, relative, isAbsolute } from 'node:path';
|
|
7
7
|
import { homedir } from 'node:os';
|
|
@@ -11,8 +11,9 @@ import { logger } from './utils/logger.js';
|
|
|
11
11
|
import { config } from './config.js';
|
|
12
12
|
import { listenWithProbe } from './utils/listen-with-probe.js';
|
|
13
13
|
import { generateToken, parseCookie, buildSetCookie, verifyHmac, cliAuthBind, decideDashboardAuth, loadPersistedToken, persistToken, loadDashboardSecret, loadOrCreateDashboardSecret, } from './dashboard/auth.js';
|
|
14
|
-
import { DaemonRegistry } from './dashboard/registry.js';
|
|
14
|
+
import { DaemonRegistry, botsRosterSignature } from './dashboard/registry.js';
|
|
15
15
|
import { Aggregator, subscribeDaemon } from './dashboard/aggregator.js';
|
|
16
|
+
import { createDebugTerminalManager } from './dashboard/debug-terminal.js';
|
|
16
17
|
import { pickCreatorForGroup } from './dashboard/operator-selector.js';
|
|
17
18
|
import { buildTeamGroupCreatePayload, planGroupCreator } from './dashboard/team-group.js';
|
|
18
19
|
import { jsonRes } from './dashboard/http.js';
|
|
@@ -21,7 +22,7 @@ import { defaultRunsDir as v3RunsDir } from './workflows/v3/ops-projection.js';
|
|
|
21
22
|
import { verifyWorkflowDaemonIpcResponse, workflowDaemonIpcHeaders, WORKFLOW_DAEMON_IPC_ROUTE_PREFIX, } from './workflows/v3/daemon-ipc-auth.js';
|
|
22
23
|
import { handleDashboardTriggerApi } from './dashboard/trigger-api.js';
|
|
23
24
|
import { handleConnectorApi } from './dashboard/connector-api.js';
|
|
24
|
-
import { redactGroupsForPublic, redactSchedulesForPublic } from './dashboard/public-redact.js';
|
|
25
|
+
import { redactGroupsForPublic, redactSchedulesForPublic, redactSettingsForPublic, } from './dashboard/public-redact.js';
|
|
25
26
|
import { handleWebhookRoute } from './dashboard/webhook-routes.js';
|
|
26
27
|
import { handleFederationApi } from './dashboard/federation-api.js';
|
|
27
28
|
import { handleFederationSpokeApi, syncAllMemberships, autoBindOwnerIfUnambiguous } from './dashboard/federation-spoke-api.js';
|
|
@@ -46,7 +47,7 @@ import { listCliRuntimeUpdateEntries } from './core/cli-runtime-update.js';
|
|
|
46
47
|
import { claimRestartLease, clearRestartIntent, clearRestartLease, hasActiveRestartLease, writeManualIntentIfAbsent, writeRestartIntent, } from './services/restart-intent-store.js';
|
|
47
48
|
import { withFileLock } from './utils/file-lock.js';
|
|
48
49
|
import { spawn } from 'node:child_process';
|
|
49
|
-
import { applySettingsWrite, defaultSettingsWriteApplierDeps, } from './dashboard/settings-write-applier.js';
|
|
50
|
+
import { applySettingsWrite, defaultSettingsWriteApplierDeps, hasResolvedCodexNotifierRecipient, resolveCodexNotifierRecipientView, } from './dashboard/settings-write-applier.js';
|
|
50
51
|
import { addBotsToGroup, bindOncall, disbandGroup, leaveGroup, unbindOncall, } from './dashboard/groups-action-helpers.js';
|
|
51
52
|
import { createDaemonInternalApi } from './dashboard/daemon-internal-api.js';
|
|
52
53
|
import { listTeamReports, readTeamBoard, setTeamBoardEntry } from './services/team-board-store.js';
|
|
@@ -56,6 +57,7 @@ import { buildSkillInstallAuditSummary, installLocalSkillLinks, readSkillRegistr
|
|
|
56
57
|
import { redactGitUrlCredentials } from './core/skills/sources.js';
|
|
57
58
|
import { effectiveDefaultWorkingDir, getBot, loadBotConfigs, parseBotConfigsFromText } from './bot-registry.js';
|
|
58
59
|
import { findEntryIndex, readRawConfig, requireConfigPath, writeRawConfigAtomic } from './services/config-store.js';
|
|
60
|
+
import { emitCodexNotifierOutboxItem, installCodexNotifierHook, isCodexNotifierWorkerStateFresh, isCodexNotifierHookInstalled, listCodexNotifierOutbox, readCodexNotifierWorkerState, resolveCodexNotifierConfig, runCodexSideConversationMonitor, runCodexNotifierWorkerSupervisor, } from './features/codex-notifier/index.js';
|
|
59
61
|
import { discoverNativeCliSkillGroups } from './core/skills/discovery.js';
|
|
60
62
|
import { analyzeSkillReferences } from './core/skills/references.js';
|
|
61
63
|
import { discoverDashboardSkills, installDashboardSkill, parseDashboardSkillInstallRequest, parseInstallLocalLinksSources, MAX_LOCAL_LINK_SOURCES } from './dashboard/skill-install-request.js';
|
|
@@ -189,6 +191,20 @@ function verifyDashboardBinding(port) {
|
|
|
189
191
|
mkdirSync(REGISTRY_DIR, { recursive: true });
|
|
190
192
|
const registry = new DaemonRegistry(REGISTRY_DIR);
|
|
191
193
|
const aggregator = new Aggregator();
|
|
194
|
+
// 调试终端(owner-only 裸 bash)。默认工作目录取当前所有 session 的工作目录去重,
|
|
195
|
+
// 让 owner 从熟悉的目录起终端复现问题;都没有时模块内退回 homedir。
|
|
196
|
+
const debugTerminalManager = createDebugTerminalManager({
|
|
197
|
+
getActiveToken: () => activeToken,
|
|
198
|
+
defaultWorkingDirs: () => {
|
|
199
|
+
const dirs = new Set();
|
|
200
|
+
for (const s of aggregator.getSessions()) {
|
|
201
|
+
const wd = s.workingDir;
|
|
202
|
+
if (typeof wd === 'string' && wd.trim())
|
|
203
|
+
dirs.add(wd.trim());
|
|
204
|
+
}
|
|
205
|
+
return [...dirs];
|
|
206
|
+
},
|
|
207
|
+
});
|
|
192
208
|
/**
|
|
193
209
|
* Resolve which daemon owns a schedule row. For rows with an explicit
|
|
194
210
|
* `larkAppId`, returns that. For legacy rows (no owner stamp), falls back to
|
|
@@ -196,6 +212,64 @@ const aggregator = new Aggregator();
|
|
|
196
212
|
* tasks (see scheduler.belongsToOwner). Returns undefined when the row is
|
|
197
213
|
* genuinely unknown or no daemon is online.
|
|
198
214
|
*/
|
|
215
|
+
/**
|
|
216
|
+
* Read-only directory listing for the dashboard sandbox-paths tree picker.
|
|
217
|
+
* Served locally by the dashboard process (same host as the daemons). Returns
|
|
218
|
+
* immediate CHILD DIRECTORIES only — never file contents. Trust model matches
|
|
219
|
+
* validateWorkingDir: the caller is an authed admin and the daemon already runs
|
|
220
|
+
* prompts with full FS access, so this is a convenience browser, not a security
|
|
221
|
+
* boundary. Symlinks are realpath-resolved; a raw path is never echoed into an
|
|
222
|
+
* error the browser renders verbatim.
|
|
223
|
+
*/
|
|
224
|
+
function listDirLocally(rawPath) {
|
|
225
|
+
// Canonicalize $HOME so the root entry + the `~` the frontend expands both use
|
|
226
|
+
// the SAME canonical form the child listings (realpathSync below) and the
|
|
227
|
+
// worker's sandbox binds use. On a symlinked-$HOME host (/home/u →
|
|
228
|
+
// /data00/home/u) the lexical homedir() would make `~/.claude` expand to
|
|
229
|
+
// /home/u/.claude while the tree's child nodes come back as /data00/... — the
|
|
230
|
+
// picker would then never match its own recommendation entries.
|
|
231
|
+
let home = homedir();
|
|
232
|
+
try {
|
|
233
|
+
home = realpathSync(home);
|
|
234
|
+
}
|
|
235
|
+
catch { /* lexical fallback if unresolvable */ }
|
|
236
|
+
if (!rawPath) {
|
|
237
|
+
// Root view: HOME first (the common case), then filesystem root. `home` is
|
|
238
|
+
// also returned explicitly so the frontend doesn't guess from entries[0].
|
|
239
|
+
const roots = [...new Set([home, '/'])];
|
|
240
|
+
return {
|
|
241
|
+
ok: true, path: null, parent: null, home,
|
|
242
|
+
entries: roots.map(p => ({ name: p, path: p, kind: 'dir' })),
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
const expanded = rawPath.startsWith('~') ? join(home, rawPath.slice(1)) : rawPath;
|
|
246
|
+
let resolved;
|
|
247
|
+
try {
|
|
248
|
+
resolved = realpathSync(expanded);
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
return { ok: false, path: null, parent: null, entries: [], error: 'path_not_found' };
|
|
252
|
+
}
|
|
253
|
+
let entries;
|
|
254
|
+
try {
|
|
255
|
+
entries = readdirSync(resolved, { withFileTypes: true })
|
|
256
|
+
.filter(d => {
|
|
257
|
+
try {
|
|
258
|
+
return d.isDirectory() || (d.isSymbolicLink() && statSync(join(resolved, d.name)).isDirectory());
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
})
|
|
264
|
+
.map(d => ({ name: d.name, path: join(resolved, d.name), kind: 'dir' }))
|
|
265
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
266
|
+
}
|
|
267
|
+
catch (e) {
|
|
268
|
+
return { ok: false, path: resolved, parent: null, entries: [], error: e?.code === 'EACCES' ? 'permission_denied' : 'cannot_read_dir' };
|
|
269
|
+
}
|
|
270
|
+
const parent = resolved === '/' ? null : dirname(resolved);
|
|
271
|
+
return { ok: true, path: resolved, parent, entries };
|
|
272
|
+
}
|
|
199
273
|
function resolveScheduleOwner(id) {
|
|
200
274
|
const explicit = aggregator.scheduleOwnerOf(id);
|
|
201
275
|
if (explicit)
|
|
@@ -269,8 +343,58 @@ function spawnStartBotLive(appId) {
|
|
|
269
343
|
}
|
|
270
344
|
});
|
|
271
345
|
}
|
|
346
|
+
function spawnStopBotLive(appId) {
|
|
347
|
+
return new Promise((resolve) => {
|
|
348
|
+
let out = '';
|
|
349
|
+
let err = '';
|
|
350
|
+
let settled = false;
|
|
351
|
+
const done = (r) => { if (!settled) {
|
|
352
|
+
settled = true;
|
|
353
|
+
resolve(r);
|
|
354
|
+
} };
|
|
355
|
+
try {
|
|
356
|
+
const child = spawn(process.execPath, [botmuxCliEntry(), 'stop-bot', appId, '--json'], {
|
|
357
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
358
|
+
env: process.env,
|
|
359
|
+
cwd: globalInstallUpdateCwd(),
|
|
360
|
+
});
|
|
361
|
+
const timer = setTimeout(() => {
|
|
362
|
+
try {
|
|
363
|
+
child.kill('SIGKILL');
|
|
364
|
+
}
|
|
365
|
+
catch { /* already gone */ }
|
|
366
|
+
done({ ok: false, message: 'stop-bot 超时(30s)' });
|
|
367
|
+
}, 30_000);
|
|
368
|
+
timer.unref?.();
|
|
369
|
+
child.stdout?.on('data', (d) => { out += String(d); });
|
|
370
|
+
child.stderr?.on('data', (d) => { err += String(d); });
|
|
371
|
+
child.on('error', (e) => {
|
|
372
|
+
clearTimeout(timer);
|
|
373
|
+
done({ ok: false, message: e instanceof Error ? e.message : String(e) });
|
|
374
|
+
});
|
|
375
|
+
child.on('exit', (code) => {
|
|
376
|
+
clearTimeout(timer);
|
|
377
|
+
let parsed;
|
|
378
|
+
try {
|
|
379
|
+
parsed = JSON.parse(out.trim());
|
|
380
|
+
}
|
|
381
|
+
catch { /* non-JSON */ }
|
|
382
|
+
if (code === 0) {
|
|
383
|
+
done({ ok: true, message: parsed?.processName ? `${parsed.processName} 已停止` : undefined });
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
done({ ok: false, message: parsed?.message || err.trim() || `stop-bot 退出码 ${code}` });
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
catch (e) {
|
|
391
|
+
done({ ok: false, message: e instanceof Error ? e.message : String(e) });
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
}
|
|
272
395
|
const botOnboarding = new BotOnboardingManager({
|
|
273
396
|
botsJsonPath: BOTS_JSON_PATH,
|
|
397
|
+
stopBotLive: spawnStopBotLive,
|
|
274
398
|
startBotLive: spawnStartBotLive,
|
|
275
399
|
});
|
|
276
400
|
// 飞书 Web 登录态刷新(机器人改名缺登录态时的 dashboard 扫码入口)。机器级单例,
|
|
@@ -306,6 +430,51 @@ async function validateVcMeetingListenerBotAppId(appId) {
|
|
|
306
430
|
return { ok: false, error: 'vcMeetingAgent_listenerBot_unknown' };
|
|
307
431
|
return { ok: true };
|
|
308
432
|
}
|
|
433
|
+
async function validateCodexNotifierTargetBotAppId(appId, options = {}) {
|
|
434
|
+
try {
|
|
435
|
+
const bot = loadBotConfigs().find(candidate => candidate.larkAppId === appId);
|
|
436
|
+
if (!bot)
|
|
437
|
+
return { ok: false, error: 'codexNotifier_target_unknown' };
|
|
438
|
+
if (bot.cliId !== 'codex' && bot.cliId !== 'codex-app') {
|
|
439
|
+
return { ok: false, error: 'codexNotifier_target_cli_unsupported' };
|
|
440
|
+
}
|
|
441
|
+
if (!(bot.allowedUsers ?? []).some(user => typeof user === 'string' && user.trim())) {
|
|
442
|
+
return { ok: false, error: 'codexNotifier_target_owner_missing' };
|
|
443
|
+
}
|
|
444
|
+
if (options.requireReady !== true)
|
|
445
|
+
return { ok: true };
|
|
446
|
+
const daemon = registry.list().find(candidate => candidate.larkAppId === appId);
|
|
447
|
+
if (!daemon)
|
|
448
|
+
return { ok: false, error: 'codexNotifier_target_daemon_offline' };
|
|
449
|
+
const resolvedOwners = daemon.resolvedAllowedUsers ?? [];
|
|
450
|
+
if (!hasResolvedCodexNotifierRecipient(resolvedOwners)) {
|
|
451
|
+
return { ok: false, error: 'codexNotifier_target_owner_unverified' };
|
|
452
|
+
}
|
|
453
|
+
return { ok: true };
|
|
454
|
+
}
|
|
455
|
+
catch {
|
|
456
|
+
return { ok: false, error: 'codexNotifier_target_unknown' };
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
function codexNotifierBotOptions() {
|
|
460
|
+
try {
|
|
461
|
+
const onlineByAppId = new Map(registry.list().map(bot => [bot.larkAppId, bot]));
|
|
462
|
+
return loadBotConfigs()
|
|
463
|
+
.filter(bot => bot.cliId === 'codex' || bot.cliId === 'codex-app')
|
|
464
|
+
.map(bot => {
|
|
465
|
+
const resolvedOwners = onlineByAppId.get(bot.larkAppId)?.resolvedAllowedUsers ?? [];
|
|
466
|
+
return {
|
|
467
|
+
larkAppId: bot.larkAppId,
|
|
468
|
+
botName: bot.displayName ?? onlineByAppId.get(bot.larkAppId)?.botName ?? bot.name ?? null,
|
|
469
|
+
cliId: onlineByAppId.get(bot.larkAppId)?.cliId ?? bot.cliId,
|
|
470
|
+
...resolveCodexNotifierRecipientView(bot.allowedUsers, resolvedOwners),
|
|
471
|
+
};
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
catch {
|
|
475
|
+
return [];
|
|
476
|
+
}
|
|
477
|
+
}
|
|
309
478
|
function normalizeVcMeetingAgentRecord(raw) {
|
|
310
479
|
return raw && typeof raw === 'object' && !Array.isArray(raw)
|
|
311
480
|
? { ...raw }
|
|
@@ -664,6 +833,9 @@ async function syncVcMeetingListenerBotConfig(listenerBotAppId, previousListener
|
|
|
664
833
|
function resolveDashboardSettings() {
|
|
665
834
|
const global = readGlobalConfig();
|
|
666
835
|
const dashboard = global.dashboard ?? {};
|
|
836
|
+
const codexNotifier = resolveCodexNotifierConfig();
|
|
837
|
+
const codexNotifierBots = codexNotifierBotOptions();
|
|
838
|
+
const codexNotifierState = readCodexNotifierWorkerState(config.session.dataDir);
|
|
667
839
|
const larkCli = checkLarkCliVersion();
|
|
668
840
|
return {
|
|
669
841
|
publicReadOnly: dashboard.publicReadOnly ?? config.dashboard.publicReadOnly,
|
|
@@ -679,6 +851,19 @@ function resolveDashboardSettings() {
|
|
|
679
851
|
recommendedRef: TRAEX_RECOMMENDED_REF,
|
|
680
852
|
},
|
|
681
853
|
codexRpcInput: dashboard.codexRpcInput === true, // default OFF until live-verified
|
|
854
|
+
codexNotifier: {
|
|
855
|
+
enabled: codexNotifier.enabled,
|
|
856
|
+
targetBotAppId: codexNotifier.targetBotAppId ?? null,
|
|
857
|
+
notifyWhen: codexNotifier.notifyWhen,
|
|
858
|
+
platformSupported: process.platform === 'darwin',
|
|
859
|
+
hookInstalled: isCodexNotifierHookInstalled(),
|
|
860
|
+
botOptions: codexNotifierBots,
|
|
861
|
+
targetDaemonOnline: !!codexNotifier.targetBotAppId
|
|
862
|
+
&& registry.list().some(bot => bot.larkAppId === codexNotifier.targetBotAppId),
|
|
863
|
+
pendingCount: listCodexNotifierOutbox(config.session.dataDir).length,
|
|
864
|
+
workerOnline: isCodexNotifierWorkerStateFresh(codexNotifierState),
|
|
865
|
+
lastError: codexNotifierState?.lastError ?? null,
|
|
866
|
+
},
|
|
682
867
|
vcMeetingAgent: {
|
|
683
868
|
enabled: global.vcMeetingAgent?.enabled !== false,
|
|
684
869
|
listenerBotAppId: global.vcMeetingAgent?.listenerBotAppId ?? null,
|
|
@@ -707,6 +892,7 @@ async function reloadLocaleOnAllDaemons() {
|
|
|
707
892
|
const settingsWriteApplierDeps = defaultSettingsWriteApplierDeps(resolveDashboardSettings, reloadLocaleOnAllDaemons);
|
|
708
893
|
settingsWriteApplierDeps.syncVcMeetingListenerBotConfig = syncVcMeetingListenerBotConfig;
|
|
709
894
|
settingsWriteApplierDeps.validateVcMeetingListenerBotAppId = validateVcMeetingListenerBotAppId;
|
|
895
|
+
settingsWriteApplierDeps.validateCodexNotifierTargetBotAppId = validateCodexNotifierTargetBotAppId;
|
|
710
896
|
/** Helper to render a {status, body} HandlerResult through `res`. */
|
|
711
897
|
function writeHandlerResult(res, result) {
|
|
712
898
|
const headers = { 'content-type': 'application/json', ...(result.headers ?? {}) };
|
|
@@ -940,6 +1126,29 @@ registry.on(syncSubscriptions);
|
|
|
940
1126
|
// Initial attach for every daemon already known. Run in parallel so a slow
|
|
941
1127
|
// daemon doesn't block the others.
|
|
942
1128
|
await Promise.all(registry.list().map(attachDaemon));
|
|
1129
|
+
const codexNotifierAbort = new AbortController();
|
|
1130
|
+
if (resolveCodexNotifierConfig().enabled) {
|
|
1131
|
+
try {
|
|
1132
|
+
installCodexNotifierHook();
|
|
1133
|
+
}
|
|
1134
|
+
catch (error) {
|
|
1135
|
+
logger.warn(`[codex-notifier] Hook reconcile failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
void runCodexNotifierWorkerSupervisor({
|
|
1139
|
+
dataDir: config.session.dataDir,
|
|
1140
|
+
signal: codexNotifierAbort.signal,
|
|
1141
|
+
emit: item => emitCodexNotifierOutboxItem(item, { signal: codexNotifierAbort.signal }),
|
|
1142
|
+
runProducer: signal => runCodexSideConversationMonitor({
|
|
1143
|
+
dataDir: config.session.dataDir,
|
|
1144
|
+
signal,
|
|
1145
|
+
logger,
|
|
1146
|
+
}),
|
|
1147
|
+
logger,
|
|
1148
|
+
onLeaseUnavailable: path => {
|
|
1149
|
+
logger.warn(`[codex-notifier] outbox worker 已由另一 Dashboard 持有,等待接管:${path}`);
|
|
1150
|
+
},
|
|
1151
|
+
});
|
|
943
1152
|
const resourceMonitor = createResourceMonitorService({
|
|
944
1153
|
intervalMs: 10_000,
|
|
945
1154
|
topSessionLimit: 30,
|
|
@@ -2104,14 +2313,15 @@ const server = createServer(async (req, res) => {
|
|
|
2104
2313
|
return jsonRes(res, 200, { ok: true });
|
|
2105
2314
|
}
|
|
2106
2315
|
const presentedToken = authedToken(req, url);
|
|
2107
|
-
const
|
|
2316
|
+
const globalDashboardConfig = readGlobalConfig().dashboard;
|
|
2108
2317
|
const decision = decideDashboardAuth({
|
|
2109
2318
|
method: req.method ?? 'GET',
|
|
2110
2319
|
pathname: url.pathname,
|
|
2111
2320
|
hasTokenParam: url.searchParams.has('t'),
|
|
2112
2321
|
presentedToken,
|
|
2113
2322
|
activeToken: activeToken ?? '',
|
|
2114
|
-
publicReadOnly:
|
|
2323
|
+
publicReadOnly: globalDashboardConfig?.publicReadOnly
|
|
2324
|
+
?? config.dashboard.publicReadOnly,
|
|
2115
2325
|
});
|
|
2116
2326
|
// `authed` is consumed by route handlers that distinguish the public-read
|
|
2117
2327
|
// carve-out from a valid management cookie (notably v3 run details).
|
|
@@ -2160,6 +2370,16 @@ const server = createServer(async (req, res) => {
|
|
|
2160
2370
|
&& await handlePluginManagementApi(req, res, url)) {
|
|
2161
2371
|
return;
|
|
2162
2372
|
}
|
|
2373
|
+
// 调试终端(owner-only):HTTP 路由挂在 auth gate 之后 → 已确保是管理 token。
|
|
2374
|
+
// /api/debug-terminal(创建/关闭)+ /debug-terminal/<id>(xterm 页面)。
|
|
2375
|
+
// WS 升级 /debug-terminal/<id>/ws 在下方 server.on('upgrade') 里由本 manager
|
|
2376
|
+
// 自行校验 cookie(upgrade 不经这段 gate)。
|
|
2377
|
+
if (url.pathname === '/api/debug-terminal'
|
|
2378
|
+
|| url.pathname.startsWith('/api/debug-terminal/')
|
|
2379
|
+
|| url.pathname.startsWith('/debug-terminal/')) {
|
|
2380
|
+
if (debugTerminalManager.handleHttp(req, res, url))
|
|
2381
|
+
return;
|
|
2382
|
+
}
|
|
2163
2383
|
if (req.method === 'GET' && url.pathname === '/api/plugins/dashboard') {
|
|
2164
2384
|
return jsonRes(res, 200, { plugins: listDashboardPluginEntries() });
|
|
2165
2385
|
}
|
|
@@ -2326,6 +2546,7 @@ const server = createServer(async (req, res) => {
|
|
|
2326
2546
|
return jsonRes(res, 200, { schedules, timezone: scheduleTimeZone() });
|
|
2327
2547
|
}
|
|
2328
2548
|
if (req.method === 'GET' && url.pathname === '/api/settings') {
|
|
2549
|
+
const dashboardSettings = resolveDashboardSettings();
|
|
2329
2550
|
// `authed` lets the Settings page disable toggles for read-only
|
|
2330
2551
|
// visitors up front, instead of letting them flip a switch that
|
|
2331
2552
|
// 401s + rolls back on save.
|
|
@@ -2335,7 +2556,7 @@ const server = createServer(async (req, res) => {
|
|
|
2335
2556
|
// `bound` reflects central-platform binding; the Settings UI only shows the
|
|
2336
2557
|
// 远程访问 toggle when bound (the central URLs are meaningless otherwise).
|
|
2337
2558
|
return jsonRes(res, 200, {
|
|
2338
|
-
settings: dashboardSettings,
|
|
2559
|
+
settings: authed ? dashboardSettings : redactSettingsForPublic(dashboardSettings),
|
|
2339
2560
|
lang: readGlobalConfig().lang ?? null,
|
|
2340
2561
|
authed,
|
|
2341
2562
|
bound: readPlatformBinding() !== null,
|
|
@@ -3053,6 +3274,14 @@ const server = createServer(async (req, res) => {
|
|
|
3053
3274
|
return jsonRes(res, 400, { ok: false, error: 'missing_expected_identity', message: '免扫码添加前必须确认当前账号与企业' });
|
|
3054
3275
|
}
|
|
3055
3276
|
const sessionMode = sessionModeRaw === 'reuse' ? 'reuse' : 'qr';
|
|
3277
|
+
if (parsed.requireCriticalScopesBeforeActivation !== undefined
|
|
3278
|
+
&& typeof parsed.requireCriticalScopesBeforeActivation !== 'boolean') {
|
|
3279
|
+
return jsonRes(res, 400, {
|
|
3280
|
+
ok: false,
|
|
3281
|
+
error: 'invalid_critical_scope_activation_gate',
|
|
3282
|
+
message: 'requireCriticalScopesBeforeActivation 必须是 boolean',
|
|
3283
|
+
});
|
|
3284
|
+
}
|
|
3056
3285
|
const job = botOnboarding.start({
|
|
3057
3286
|
appName,
|
|
3058
3287
|
registrationMode,
|
|
@@ -3062,9 +3291,93 @@ const server = createServer(async (req, res) => {
|
|
|
3062
3291
|
workingDir,
|
|
3063
3292
|
dirMode,
|
|
3064
3293
|
model,
|
|
3294
|
+
...(parsed.requireCriticalScopesBeforeActivation === true
|
|
3295
|
+
? { requireCriticalScopesBeforeActivation: true }
|
|
3296
|
+
: {}),
|
|
3065
3297
|
});
|
|
3066
3298
|
return jsonRes(res, 202, { job: botOnboarding.get(job.id) });
|
|
3067
3299
|
}
|
|
3300
|
+
if (req.method === 'POST' && url.pathname === '/api/bot-onboarding/recover-permissions') {
|
|
3301
|
+
let parsed;
|
|
3302
|
+
try {
|
|
3303
|
+
const chunks = [];
|
|
3304
|
+
for await (const c of req)
|
|
3305
|
+
chunks.push(c);
|
|
3306
|
+
const raw = Buffer.concat(chunks).toString('utf8');
|
|
3307
|
+
parsed = raw ? JSON.parse(raw) : {};
|
|
3308
|
+
}
|
|
3309
|
+
catch {
|
|
3310
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
3311
|
+
}
|
|
3312
|
+
const workingDir = typeof parsed.workingDir === 'string' ? parsed.workingDir.trim() : '';
|
|
3313
|
+
const predecessorJobId = typeof parsed.predecessorJobId === 'string' ? parsed.predecessorJobId.trim() : '';
|
|
3314
|
+
const expectedAppId = typeof parsed.expectedAppId === 'string' ? parsed.expectedAppId.trim() : '';
|
|
3315
|
+
const priorRecoveryJobId = typeof parsed.priorRecoveryJobId === 'string' ? parsed.priorRecoveryJobId.trim() : undefined;
|
|
3316
|
+
if (parsed.requireCriticalScopesBeforeActivation !== undefined
|
|
3317
|
+
&& typeof parsed.requireCriticalScopesBeforeActivation !== 'boolean') {
|
|
3318
|
+
return jsonRes(res, 400, {
|
|
3319
|
+
ok: false,
|
|
3320
|
+
error: 'invalid_critical_scope_activation_gate',
|
|
3321
|
+
message: 'requireCriticalScopesBeforeActivation 必须是 boolean',
|
|
3322
|
+
});
|
|
3323
|
+
}
|
|
3324
|
+
if (!workingDir || !predecessorJobId || !expectedAppId || invalidWorkingDirs({ workingDir }).length > 0) {
|
|
3325
|
+
return jsonRes(res, 400, { ok: false, error: 'permission_recovery_target_invalid' });
|
|
3326
|
+
}
|
|
3327
|
+
const recovered = botOnboarding.startPermissionRecovery({
|
|
3328
|
+
workingDir,
|
|
3329
|
+
predecessorJobId,
|
|
3330
|
+
expectedAppId,
|
|
3331
|
+
priorRecoveryJobId,
|
|
3332
|
+
...(parsed.requireCriticalScopesBeforeActivation === true
|
|
3333
|
+
? { requireCriticalScopesBeforeActivation: true }
|
|
3334
|
+
: {}),
|
|
3335
|
+
});
|
|
3336
|
+
if (!recovered.ok) {
|
|
3337
|
+
const status = recovered.error === 'permission_recovery_target_missing' ? 404
|
|
3338
|
+
: recovered.error === 'permission_recovery_target_ambiguous' ? 409
|
|
3339
|
+
: recovered.error === 'permission_recovery_state_unavailable' ? 503
|
|
3340
|
+
: 400;
|
|
3341
|
+
return jsonRes(res, status, recovered);
|
|
3342
|
+
}
|
|
3343
|
+
return jsonRes(res, 202, { job: botOnboarding.get(recovered.job.id) });
|
|
3344
|
+
}
|
|
3345
|
+
let mScopePropagation;
|
|
3346
|
+
if (req.method === 'POST'
|
|
3347
|
+
&& (mScopePropagation = url.pathname.match(/^\/api\/bot-onboarding\/([^/]+)\/complete-scope-propagation$/))) {
|
|
3348
|
+
const onboardingId = decodeURIComponent(mScopePropagation[1]);
|
|
3349
|
+
let parsed;
|
|
3350
|
+
try {
|
|
3351
|
+
const chunks = [];
|
|
3352
|
+
for await (const c of req)
|
|
3353
|
+
chunks.push(c);
|
|
3354
|
+
const raw = Buffer.concat(chunks).toString('utf8');
|
|
3355
|
+
parsed = raw ? JSON.parse(raw) : {};
|
|
3356
|
+
}
|
|
3357
|
+
catch {
|
|
3358
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
3359
|
+
}
|
|
3360
|
+
const workingDir = typeof parsed.workingDir === 'string' ? parsed.workingDir.trim() : '';
|
|
3361
|
+
const expectedAppId = typeof parsed.expectedAppId === 'string' ? parsed.expectedAppId.trim() : '';
|
|
3362
|
+
if (!workingDir || !expectedAppId || invalidWorkingDirs({ workingDir }).length > 0) {
|
|
3363
|
+
return jsonRes(res, 400, { ok: false, error: 'permission_recovery_target_invalid' });
|
|
3364
|
+
}
|
|
3365
|
+
const completed = await botOnboarding.completeScopePropagation({
|
|
3366
|
+
jobId: onboardingId,
|
|
3367
|
+
workingDir,
|
|
3368
|
+
expectedAppId,
|
|
3369
|
+
});
|
|
3370
|
+
if (!completed.ok) {
|
|
3371
|
+
const status = completed.error === 'permission_recovery_target_missing' ? 404
|
|
3372
|
+
: completed.error === 'permission_recovery_target_ambiguous' ? 409
|
|
3373
|
+
: completed.error === 'permission_recovery_scopes_pending' ? 425
|
|
3374
|
+
: (completed.error === 'permission_recovery_state_unavailable'
|
|
3375
|
+
|| completed.error === 'permission_recovery_activation_failed') ? 503
|
|
3376
|
+
: 400;
|
|
3377
|
+
return jsonRes(res, status, completed);
|
|
3378
|
+
}
|
|
3379
|
+
return jsonRes(res, 200, { job: botOnboarding.get(onboardingId) });
|
|
3380
|
+
}
|
|
3068
3381
|
let mOwner;
|
|
3069
3382
|
if (req.method === 'POST' && (mOwner = url.pathname.match(/^\/api\/bot-onboarding\/([^/]+)\/owner$/))) {
|
|
3070
3383
|
// needs_owner 状态下用户手动提交 owner:扫码人身份验证不了时的兜底入口。
|
|
@@ -3219,6 +3532,18 @@ const server = createServer(async (req, res) => {
|
|
|
3219
3532
|
res.end(await upstream.text());
|
|
3220
3533
|
return;
|
|
3221
3534
|
}
|
|
3535
|
+
// Dashboard「复现命令」:透传到 owning daemon 取该 session 的真实 CLI 调用。
|
|
3536
|
+
// 与 write-link 同样只在管理 cookie(写权限)下可达:命令含 token/凭证。
|
|
3537
|
+
if (req.method === 'GET' && (m = url.pathname.match(/^\/api\/sessions\/([^/]+)\/spawn-command$/))) {
|
|
3538
|
+
const sid = decodeURIComponent(m[1]);
|
|
3539
|
+
const owner = aggregator.ownerOf(sid);
|
|
3540
|
+
if (!owner)
|
|
3541
|
+
return jsonRes(res, 404, { ok: false, error: 'unknown_session' });
|
|
3542
|
+
const upstream = await proxyToDaemon(owner, `/api/sessions/${sid}/spawn-command`, { method: 'GET' });
|
|
3543
|
+
res.writeHead(upstream.status, { 'content-type': 'application/json' });
|
|
3544
|
+
res.end(await upstream.text());
|
|
3545
|
+
return;
|
|
3546
|
+
}
|
|
3222
3547
|
// Sandbox landing: review the clone's diff (GET) then apply/discard (POST).
|
|
3223
3548
|
if (req.method === 'GET' && (m = url.pathname.match(/^\/api\/sessions\/([^/]+)\/sandbox-diff$/))) {
|
|
3224
3549
|
const sid = decodeURIComponent(m[1]);
|
|
@@ -3805,6 +4130,33 @@ const server = createServer(async (req, res) => {
|
|
|
3805
4130
|
res.end(await upstream.text());
|
|
3806
4131
|
return;
|
|
3807
4132
|
}
|
|
4133
|
+
// PUT /api/bots/:appId/sandbox-paths — proxy to that bot's daemon.
|
|
4134
|
+
// Body `{ readWrite?: string[]; readOnly?: string[]; deny?: string[] }`.
|
|
4135
|
+
let mBotSandboxPaths;
|
|
4136
|
+
if (req.method === 'PUT' && (mBotSandboxPaths = url.pathname.match(/^\/api\/bots\/([^/]+)\/sandbox-paths$/))) {
|
|
4137
|
+
const appId = decodeURIComponent(mBotSandboxPaths[1]);
|
|
4138
|
+
const chunks = [];
|
|
4139
|
+
for await (const c of req)
|
|
4140
|
+
chunks.push(c);
|
|
4141
|
+
const raw = Buffer.concat(chunks).toString('utf8') || '{}';
|
|
4142
|
+
const upstream = await proxyToDaemon(appId, `/api/bot-sandbox-paths`, {
|
|
4143
|
+
method: 'PUT',
|
|
4144
|
+
headers: { 'content-type': 'application/json' },
|
|
4145
|
+
body: raw,
|
|
4146
|
+
});
|
|
4147
|
+
res.writeHead(upstream.status, { 'content-type': 'application/json' });
|
|
4148
|
+
res.end(await upstream.text());
|
|
4149
|
+
return;
|
|
4150
|
+
}
|
|
4151
|
+
// GET /api/fs/list?path=… — read-only directory listing for the sandbox-paths
|
|
4152
|
+
// tree picker. Not bot-specific (the filesystem is shared with this host's
|
|
4153
|
+
// daemons — the dashboard process runs on the SAME machine), so serve it
|
|
4154
|
+
// locally instead of proxying. Returns immediate child directories only.
|
|
4155
|
+
if (req.method === 'GET' && url.pathname === '/api/fs/list') {
|
|
4156
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
4157
|
+
res.end(JSON.stringify(listDirLocally(url.searchParams.get('path') ?? '')));
|
|
4158
|
+
return;
|
|
4159
|
+
}
|
|
3808
4160
|
// PUT /api/bots/:appId/sandbox — proxy to that bot's daemon. Body `{ enabled: boolean }`.
|
|
3809
4161
|
let mBotSandbox;
|
|
3810
4162
|
if (req.method === 'PUT' && (mBotSandbox = url.pathname.match(/^\/api\/bots\/([^/]+)\/sandbox$/))) {
|
|
@@ -4325,7 +4677,20 @@ const server = createServer(async (req, res) => {
|
|
|
4325
4677
|
const hb = setInterval(() => {
|
|
4326
4678
|
res.write(`event: heartbeat\ndata: ${JSON.stringify({ ts: Date.now() })}\n\n`);
|
|
4327
4679
|
}, 15_000);
|
|
4328
|
-
|
|
4680
|
+
// Push a bots.changed frame whenever the online bot roster actually
|
|
4681
|
+
// changes (bot added / removed / renamed / re-indexed) so the Bot 配置
|
|
4682
|
+
// page can auto-refresh without a manual reload. registry.on fires on
|
|
4683
|
+
// every 15s poll and 30s heartbeat rewrite, so gate on a roster signature
|
|
4684
|
+
// that ignores lastHeartbeat — otherwise we'd spam a frame every poll.
|
|
4685
|
+
let lastRoster = botsRosterSignature(registry.list());
|
|
4686
|
+
const offRoster = registry.on(online => {
|
|
4687
|
+
const sig = botsRosterSignature(online);
|
|
4688
|
+
if (sig === lastRoster)
|
|
4689
|
+
return;
|
|
4690
|
+
lastRoster = sig;
|
|
4691
|
+
res.write(`event: bots.changed\ndata: ${JSON.stringify({ body: { signature: sig } })}\n\n`);
|
|
4692
|
+
});
|
|
4693
|
+
res.on('close', () => { off(); offRoster(); clearInterval(hb); });
|
|
4329
4694
|
return;
|
|
4330
4695
|
}
|
|
4331
4696
|
// Public API + static frontend land in Task 17 / 18. For now: 404.
|
|
@@ -4346,6 +4711,11 @@ const server = createServer(async (req, res) => {
|
|
|
4346
4711
|
server.on('upgrade', (req, clientSocket, head) => {
|
|
4347
4712
|
try {
|
|
4348
4713
|
const rawUrl = req.url ?? '/';
|
|
4714
|
+
// 调试终端 WS(owner-only):manager 内部自校验管理 cookie。命中即接管。
|
|
4715
|
+
if (rawUrl.startsWith('/debug-terminal/')) {
|
|
4716
|
+
if (debugTerminalManager.handleUpgrade(req, clientSocket, head))
|
|
4717
|
+
return;
|
|
4718
|
+
}
|
|
4349
4719
|
if (!(rawUrl === '/s' || rawUrl.startsWith('/s/') || rawUrl.startsWith('/s?'))) {
|
|
4350
4720
|
return clientSocket.destroy();
|
|
4351
4721
|
}
|
|
@@ -4671,12 +5041,14 @@ async function maybeAnnounceHallPresence() {
|
|
|
4671
5041
|
}
|
|
4672
5042
|
// Graceful shutdown
|
|
4673
5043
|
function shutdown() {
|
|
5044
|
+
codexNotifierAbort.abort();
|
|
4674
5045
|
for (const off of subs.values())
|
|
4675
5046
|
off();
|
|
4676
5047
|
subs.clear();
|
|
4677
5048
|
registry.stop();
|
|
4678
5049
|
resourceMonitor.stop();
|
|
4679
5050
|
platformTunnel?.stop();
|
|
5051
|
+
debugTerminalManager.shutdown();
|
|
4680
5052
|
server.close(() => process.exit(0));
|
|
4681
5053
|
// Hard-exit fallback after 5s
|
|
4682
5054
|
setTimeout(() => process.exit(0), 5_000).unref();
|