botmux 3.5.2 → 3.6.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 +56 -396
- package/README.md +55 -396
- package/dist/.runtime-build-id +1 -0
- package/dist/adapters/cli/claude-code.d.ts +6 -0
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +197 -11
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/adapters/cli/coco.js +4 -4
- package/dist/adapters/cli/coco.js.map +1 -1
- package/dist/adapters/cli/codex-app.d.ts.map +1 -1
- package/dist/adapters/cli/codex-app.js +9 -6
- package/dist/adapters/cli/codex-app.js.map +1 -1
- package/dist/adapters/cli/codex.js +5 -5
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/fs-policy.d.ts.map +1 -1
- package/dist/adapters/cli/fs-policy.js +5 -7
- package/dist/adapters/cli/fs-policy.js.map +1 -1
- package/dist/adapters/cli/grok.d.ts +2 -1
- package/dist/adapters/cli/grok.d.ts.map +1 -1
- package/dist/adapters/cli/grok.js +2 -1
- package/dist/adapters/cli/grok.js.map +1 -1
- package/dist/adapters/cli/hermes.d.ts.map +1 -1
- package/dist/adapters/cli/hermes.js +8 -4
- package/dist/adapters/cli/hermes.js.map +1 -1
- package/dist/adapters/cli/mtr.d.ts.map +1 -1
- package/dist/adapters/cli/mtr.js +3 -2
- package/dist/adapters/cli/mtr.js.map +1 -1
- package/dist/adapters/cli/opencode.d.ts.map +1 -1
- package/dist/adapters/cli/opencode.js +5 -4
- package/dist/adapters/cli/opencode.js.map +1 -1
- package/dist/adapters/cli/relay.js +2 -2
- package/dist/adapters/cli/relay.js.map +1 -1
- package/dist/adapters/cli/runner-input.d.ts +2 -2
- package/dist/adapters/cli/runner-input.d.ts.map +1 -1
- package/dist/adapters/cli/runner-input.js +9 -6
- package/dist/adapters/cli/runner-input.js.map +1 -1
- package/dist/adapters/cli/seed.d.ts.map +1 -1
- package/dist/adapters/cli/seed.js +2 -1
- package/dist/adapters/cli/seed.js.map +1 -1
- package/dist/adapters/cli/traex.d.ts.map +1 -1
- package/dist/adapters/cli/traex.js +3 -2
- package/dist/adapters/cli/traex.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +25 -18
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/bot-registry.d.ts +28 -0
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +75 -0
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +272 -86
- package/dist/cli.js.map +1 -1
- package/dist/codex-app-runner.js +85 -192
- package/dist/codex-app-runner.js.map +1 -1
- package/dist/config.d.ts +0 -16
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -30
- package/dist/config.js.map +1 -1
- package/dist/core/ask-broker.d.ts +12 -0
- package/dist/core/ask-broker.d.ts.map +1 -1
- package/dist/core/ask-broker.js +41 -0
- package/dist/core/ask-broker.js.map +1 -1
- package/dist/core/bot-turn-mutation-gate.d.ts +24 -0
- package/dist/core/bot-turn-mutation-gate.d.ts.map +1 -0
- package/dist/core/bot-turn-mutation-gate.js +369 -0
- package/dist/core/bot-turn-mutation-gate.js.map +1 -0
- package/dist/core/command-handler.d.ts +5 -0
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +38 -16
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +330 -57
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dashboard-rows.d.ts +8 -0
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/core/host-overload-alert.d.ts +157 -0
- package/dist/core/host-overload-alert.d.ts.map +1 -0
- package/dist/core/host-overload-alert.js +251 -0
- package/dist/core/host-overload-alert.js.map +1 -0
- package/dist/core/passthrough-commands.d.ts +8 -0
- package/dist/core/passthrough-commands.d.ts.map +1 -1
- package/dist/core/passthrough-commands.js +19 -0
- package/dist/core/passthrough-commands.js.map +1 -1
- package/dist/core/restart-coordinator.d.ts +28 -0
- package/dist/core/restart-coordinator.d.ts.map +1 -0
- package/dist/core/restart-coordinator.js +82 -0
- package/dist/core/restart-coordinator.js.map +1 -0
- package/dist/core/restart-followup-policy.d.ts +112 -0
- package/dist/core/restart-followup-policy.d.ts.map +1 -0
- package/dist/core/restart-followup-policy.js +49 -0
- package/dist/core/restart-followup-policy.js.map +1 -0
- package/dist/core/role-library.d.ts +1 -1
- package/dist/core/role-library.js +1 -1
- package/dist/core/session-cwd.d.ts.map +1 -1
- package/dist/core/session-cwd.js +8 -0
- package/dist/core/session-cwd.js.map +1 -1
- package/dist/core/session-discovery.d.ts +14 -0
- package/dist/core/session-discovery.d.ts.map +1 -1
- package/dist/core/session-discovery.js +25 -0
- package/dist/core/session-discovery.js.map +1 -1
- package/dist/core/session-liveness.d.ts +15 -0
- package/dist/core/session-liveness.d.ts.map +1 -0
- package/dist/core/session-liveness.js +76 -0
- package/dist/core/session-liveness.js.map +1 -0
- package/dist/core/session-row-enrichment.d.ts +15 -0
- package/dist/core/session-row-enrichment.d.ts.map +1 -0
- package/dist/core/session-row-enrichment.js +93 -0
- package/dist/core/session-row-enrichment.js.map +1 -0
- package/dist/core/slash-inject.js +1 -1
- package/dist/core/slash-inject.js.map +1 -1
- package/dist/core/trigger-final-suppression.d.ts +24 -0
- package/dist/core/trigger-final-suppression.d.ts.map +1 -0
- package/dist/core/trigger-final-suppression.js +97 -0
- package/dist/core/trigger-final-suppression.js.map +1 -0
- package/dist/core/trigger-session.d.ts.map +1 -1
- package/dist/core/trigger-session.js +64 -4
- package/dist/core/trigger-session.js.map +1 -1
- package/dist/core/types.d.ts +6 -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 +20 -0
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +283 -32
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts +5 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +520 -35
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/aggregator.d.ts +1 -0
- package/dist/dashboard/aggregator.d.ts.map +1 -1
- package/dist/dashboard/aggregator.js +34 -6
- package/dist/dashboard/aggregator.js.map +1 -1
- package/dist/dashboard/bot-payload.d.ts +3 -0
- package/dist/dashboard/bot-payload.d.ts.map +1 -1
- package/dist/dashboard/bot-payload.js +3 -0
- package/dist/dashboard/bot-payload.js.map +1 -1
- package/dist/dashboard/compat.d.ts +102 -2
- package/dist/dashboard/compat.d.ts.map +1 -1
- package/dist/dashboard/compat.js +78 -14
- package/dist/dashboard/compat.js.map +1 -1
- package/dist/dashboard/connector-api.d.ts.map +1 -1
- package/dist/dashboard/connector-api.js +1 -0
- package/dist/dashboard/connector-api.js.map +1 -1
- package/dist/dashboard/desktop-asks.d.ts +21 -0
- package/dist/dashboard/desktop-asks.d.ts.map +1 -0
- package/dist/dashboard/desktop-asks.js +49 -0
- package/dist/dashboard/desktop-asks.js.map +1 -0
- package/dist/dashboard/public-redact.d.ts +7 -0
- package/dist/dashboard/public-redact.d.ts.map +1 -1
- package/dist/dashboard/public-redact.js +35 -3
- package/dist/dashboard/public-redact.js.map +1 -1
- package/dist/dashboard/session-presentation.d.ts +16 -0
- package/dist/dashboard/session-presentation.d.ts.map +1 -0
- package/dist/dashboard/session-presentation.js +62 -0
- package/dist/dashboard/session-presentation.js.map +1 -0
- package/dist/dashboard/settings-write-applier.d.ts +2 -1
- package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
- package/dist/dashboard/settings-write-applier.js +19 -1
- package/dist/dashboard/settings-write-applier.js.map +1 -1
- package/dist/dashboard/trigger-api.d.ts.map +1 -1
- package/dist/dashboard/trigger-api.js +19 -1
- package/dist/dashboard/trigger-api.js.map +1 -1
- package/dist/dashboard/vc-consumer-profiles-api.d.ts +7 -2
- package/dist/dashboard/vc-consumer-profiles-api.d.ts.map +1 -1
- package/dist/dashboard/vc-consumer-profiles-api.js +13 -0
- package/dist/dashboard/vc-consumer-profiles-api.js.map +1 -1
- package/dist/dashboard/web/app.d.ts.map +1 -1
- package/dist/dashboard/web/app.js +18 -5
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.js +97 -35
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts +3 -0
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/client-shell.d.ts +29 -0
- package/dist/dashboard/web/client-shell.d.ts.map +1 -0
- package/dist/dashboard/web/client-shell.js +89 -0
- package/dist/dashboard/web/client-shell.js.map +1 -0
- package/dist/dashboard/web/connectors-page.d.ts.map +1 -1
- package/dist/dashboard/web/connectors-page.js +5 -1
- package/dist/dashboard/web/connectors-page.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +100 -8
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/preferences.d.ts +7 -0
- package/dist/dashboard/web/preferences.d.ts.map +1 -1
- package/dist/dashboard/web/preferences.js +32 -0
- package/dist/dashboard/web/preferences.js.map +1 -1
- package/dist/dashboard/web/sessions-kanban.d.ts +1 -1
- package/dist/dashboard/web/sessions-kanban.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-kanban.js +1 -1
- 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 +77 -23
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts +4 -0
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +14 -1
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/settings-page.d.ts +6 -0
- package/dist/dashboard/web/settings-page.d.ts.map +1 -1
- package/dist/dashboard/web/settings-page.js +55 -30
- package/dist/dashboard/web/settings-page.js.map +1 -1
- package/dist/dashboard/web/store.d.ts +1 -2
- package/dist/dashboard/web/store.d.ts.map +1 -1
- package/dist/dashboard/web/store.js +69 -20
- package/dist/dashboard/web/store.js.map +1 -1
- package/dist/dashboard/web/vc-consumer-profiles-section.d.ts.map +1 -1
- package/dist/dashboard/web/vc-consumer-profiles-section.js +128 -42
- package/dist/dashboard/web/vc-consumer-profiles-section.js.map +1 -1
- package/dist/dashboard/webhook-routes.d.ts.map +1 -1
- package/dist/dashboard/webhook-routes.js +9 -2
- package/dist/dashboard/webhook-routes.js.map +1 -1
- package/dist/dashboard-web/app.js +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-VQMPUJ4Y.js +10 -0
- package/dist/dashboard-web/chunks/chunk-AGCPF6MT.js +1 -0
- package/dist/dashboard-web/chunks/{chunk-KPQAUX7V.js → chunk-JMRGZQDB.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-R7IAKAYX.js → chunk-NP4JUBGS.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-NRL6CVAS.js → chunk-P327LXOT.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-X2L65IOM.js → chunk-SNKATZWK.js} +15 -15
- package/dist/dashboard-web/chunks/connectors-page-DOY4J3ZL.js +1 -0
- package/dist/dashboard-web/chunks/{groups-page-6DKXBYOM.js → groups-page-74TS2DIH.js} +1 -1
- package/dist/dashboard-web/chunks/{insights-page-NWARTJ6J.js → insights-page-AYCO65JC.js} +1 -1
- package/dist/dashboard-web/chunks/{monitor-room-AGX3XRJX.js → monitor-room-YKYLTSAN.js} +1 -1
- package/dist/dashboard-web/chunks/{monitoring-page-GGGIWN4C.js → monitoring-page-QBIUNRBR.js} +1 -1
- package/dist/dashboard-web/chunks/{office-page-6SIVKSK3.js → office-page-4PH2A26P.js} +1 -1
- package/dist/dashboard-web/chunks/overview-page-H73D5UT4.js +1 -0
- package/dist/dashboard-web/chunks/{roles-page-WE2YB7KN.js → roles-page-U4BTOQ7F.js} +1 -1
- package/dist/dashboard-web/chunks/{schedules-page-TB3I24XN.js → schedules-page-RHRHX7R7.js} +1 -1
- package/dist/dashboard-web/chunks/sessions-page-VSC6AM5G.js +2 -0
- package/dist/dashboard-web/chunks/settings-page-LF3RKM5P.js +2 -0
- package/dist/dashboard-web/chunks/{skills-page-3QAT2IWD.js → skills-page-SYOIGGXH.js} +1 -1
- package/dist/dashboard-web/chunks/{team-federation-page-K4VVAVAK.js → team-federation-page-RMBLASTW.js} +1 -1
- package/dist/dashboard-web/chunks/{v3-page-V6IOJR2B.js → v3-page-XJXKKJRN.js} +1 -1
- package/dist/dashboard-web/chunks/{whiteboards-page-V6CGKRNX.js → whiteboards-page-K3YVSTHJ.js} +1 -1
- package/dist/dashboard-web/style.css +551 -0
- package/dist/dashboard.js +153 -9
- package/dist/dashboard.js.map +1 -1
- package/dist/global-config.d.ts +11 -0
- package/dist/global-config.d.ts.map +1 -1
- package/dist/global-config.js +23 -0
- package/dist/global-config.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +5 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +5 -0
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts +1 -1
- package/dist/im/lark/card-builder.js +1 -1
- package/dist/im/lark/card-handler.d.ts +10 -0
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +163 -17
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +11 -0
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +47 -18
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +13 -0
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +20 -0
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/identity-cache.d.ts +25 -1
- package/dist/im/lark/identity-cache.d.ts.map +1 -1
- package/dist/im/lark/identity-cache.js +47 -1
- package/dist/im/lark/identity-cache.js.map +1 -1
- package/dist/im/lark/overload-nonce.d.ts +19 -0
- package/dist/im/lark/overload-nonce.d.ts.map +1 -0
- package/dist/im/lark/overload-nonce.js +72 -0
- package/dist/im/lark/overload-nonce.js.map +1 -0
- package/dist/im/lark/v3-progress-card.d.ts.map +1 -1
- package/dist/im/lark/v3-progress-card.js +5 -0
- package/dist/im/lark/v3-progress-card.js.map +1 -1
- package/dist/services/async-trigger-state.d.ts +82 -0
- package/dist/services/async-trigger-state.d.ts.map +1 -0
- package/dist/services/async-trigger-state.js +95 -0
- package/dist/services/async-trigger-state.js.map +1 -0
- package/dist/services/async-trigger-store.d.ts +28 -0
- package/dist/services/async-trigger-store.d.ts.map +1 -0
- package/dist/services/async-trigger-store.js +120 -0
- package/dist/services/async-trigger-store.js.map +1 -0
- package/dist/services/bot-config-store.d.ts.map +1 -1
- package/dist/services/bot-config-store.js +34 -2
- package/dist/services/bot-config-store.js.map +1 -1
- package/dist/services/bridge-fallback-gate.d.ts +32 -0
- package/dist/services/bridge-fallback-gate.d.ts.map +1 -1
- package/dist/services/bridge-fallback-gate.js +39 -0
- package/dist/services/bridge-fallback-gate.js.map +1 -1
- package/dist/services/bridge-turn-queue.d.ts.map +1 -1
- package/dist/services/bridge-turn-queue.js +15 -1
- package/dist/services/bridge-turn-queue.js.map +1 -1
- package/dist/services/card-prefs-store.d.ts +4 -0
- package/dist/services/card-prefs-store.d.ts.map +1 -1
- package/dist/services/card-prefs-store.js +8 -0
- package/dist/services/card-prefs-store.js.map +1 -1
- package/dist/services/claude-transcript.d.ts +23 -0
- package/dist/services/claude-transcript.d.ts.map +1 -1
- package/dist/services/claude-transcript.js +33 -0
- package/dist/services/claude-transcript.js.map +1 -1
- package/dist/services/codex-app-runner-protocol.d.ts +61 -0
- package/dist/services/codex-app-runner-protocol.d.ts.map +1 -0
- package/dist/services/codex-app-runner-protocol.js +170 -0
- package/dist/services/codex-app-runner-protocol.js.map +1 -0
- package/dist/services/codex-app-turn-controller.d.ts +72 -0
- package/dist/services/codex-app-turn-controller.d.ts.map +1 -0
- package/dist/services/codex-app-turn-controller.js +524 -0
- package/dist/services/codex-app-turn-controller.js.map +1 -0
- package/dist/services/codex-runner-freshness.d.ts +39 -0
- package/dist/services/codex-runner-freshness.d.ts.map +1 -0
- package/dist/services/codex-runner-freshness.js +78 -0
- package/dist/services/codex-runner-freshness.js.map +1 -0
- package/dist/services/connector-store.d.ts +6 -0
- package/dist/services/connector-store.d.ts.map +1 -1
- package/dist/services/connector-store.js.map +1 -1
- package/dist/services/grant-store.d.ts.map +1 -1
- package/dist/services/grant-store.js +16 -0
- package/dist/services/grant-store.js.map +1 -1
- package/dist/services/hermes-transcript.d.ts +1 -0
- package/dist/services/hermes-transcript.d.ts.map +1 -1
- package/dist/services/hermes-transcript.js +49 -0
- package/dist/services/hermes-transcript.js.map +1 -1
- package/dist/services/schedule-split-migration.d.ts +2 -0
- package/dist/services/schedule-split-migration.d.ts.map +1 -0
- package/dist/services/schedule-split-migration.js +159 -0
- package/dist/services/schedule-split-migration.js.map +1 -0
- package/dist/services/schedule-store.d.ts +28 -4
- package/dist/services/schedule-store.d.ts.map +1 -1
- package/dist/services/schedule-store.js +118 -33
- package/dist/services/schedule-store.js.map +1 -1
- package/dist/services/trigger-types.d.ts +18 -1
- package/dist/services/trigger-types.d.ts.map +1 -1
- package/dist/services/trigger-types.js +3 -0
- package/dist/services/trigger-types.js.map +1 -1
- package/dist/services/vc-meeting-consumer-profile-store.d.ts.map +1 -1
- package/dist/services/vc-meeting-consumer-profile-store.js +1 -0
- package/dist/services/vc-meeting-consumer-profile-store.js.map +1 -1
- package/dist/services/vc-meeting-consumer-profile-templates.d.ts +32 -0
- package/dist/services/vc-meeting-consumer-profile-templates.d.ts.map +1 -0
- package/dist/services/vc-meeting-consumer-profile-templates.js +106 -0
- package/dist/services/vc-meeting-consumer-profile-templates.js.map +1 -0
- package/dist/services/vc-meeting-delivery-feed.d.ts +1 -1
- package/dist/services/vc-meeting-delivery-feed.d.ts.map +1 -1
- package/dist/services/vc-meeting-delivery-feed.js +2 -1
- package/dist/services/vc-meeting-delivery-feed.js.map +1 -1
- package/dist/services/vc-meeting-delivery-hub-store.d.ts +3 -1
- package/dist/services/vc-meeting-delivery-hub-store.d.ts.map +1 -1
- package/dist/services/vc-meeting-delivery-hub-store.js +11 -0
- package/dist/services/vc-meeting-delivery-hub-store.js.map +1 -1
- package/dist/services/vc-meeting-delivery-protocol.d.ts +9 -2
- package/dist/services/vc-meeting-delivery-protocol.d.ts.map +1 -1
- package/dist/services/vc-meeting-delivery-protocol.js +10 -1
- package/dist/services/vc-meeting-delivery-protocol.js.map +1 -1
- package/dist/services/vc-meeting-delivery-receiver.d.ts.map +1 -1
- package/dist/services/vc-meeting-delivery-receiver.js +10 -1
- package/dist/services/vc-meeting-delivery-receiver.js.map +1 -1
- package/dist/services/vc-meeting-delivery-store.d.ts +12 -2
- package/dist/services/vc-meeting-delivery-store.d.ts.map +1 -1
- package/dist/services/vc-meeting-delivery-store.js +14 -2
- package/dist/services/vc-meeting-delivery-store.js.map +1 -1
- package/dist/services/vc-meeting-im-reply.d.ts +2 -1
- package/dist/services/vc-meeting-im-reply.d.ts.map +1 -1
- package/dist/services/vc-meeting-im-reply.js +19 -3
- package/dist/services/vc-meeting-im-reply.js.map +1 -1
- package/dist/services/vc-meeting-listener-output-protocol.d.ts +27 -0
- package/dist/services/vc-meeting-listener-output-protocol.d.ts.map +1 -0
- package/dist/services/vc-meeting-listener-output-protocol.js +58 -0
- package/dist/services/vc-meeting-listener-output-protocol.js.map +1 -0
- package/dist/services/vc-meeting-listener-topic-store.d.ts +31 -0
- package/dist/services/vc-meeting-listener-topic-store.d.ts.map +1 -0
- package/dist/services/vc-meeting-listener-topic-store.js +120 -0
- package/dist/services/vc-meeting-listener-topic-store.js.map +1 -0
- package/dist/services/vc-meeting-runtime-store.d.ts +2 -1
- package/dist/services/vc-meeting-runtime-store.d.ts.map +1 -1
- package/dist/services/vc-meeting-runtime-store.js +8 -0
- package/dist/services/vc-meeting-runtime-store.js.map +1 -1
- package/dist/services/vc-meeting-send-policy.d.ts +8 -1
- package/dist/services/vc-meeting-send-policy.d.ts.map +1 -1
- package/dist/services/vc-meeting-send-policy.js +8 -0
- package/dist/services/vc-meeting-send-policy.js.map +1 -1
- package/dist/types.d.ts +40 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/allowed-users-apply.d.ts +76 -0
- package/dist/utils/allowed-users-apply.d.ts.map +1 -0
- package/dist/utils/allowed-users-apply.js +123 -0
- package/dist/utils/allowed-users-apply.js.map +1 -0
- package/dist/utils/allowed-users-cache.d.ts +29 -0
- package/dist/utils/allowed-users-cache.d.ts.map +1 -0
- package/dist/utils/allowed-users-cache.js +82 -0
- package/dist/utils/allowed-users-cache.js.map +1 -0
- package/dist/utils/child-env.d.ts +2 -1
- package/dist/utils/child-env.d.ts.map +1 -1
- package/dist/utils/child-env.js +2 -1
- package/dist/utils/child-env.js.map +1 -1
- package/dist/utils/cli-usage-limit.d.ts +27 -1
- package/dist/utils/cli-usage-limit.d.ts.map +1 -1
- package/dist/utils/cli-usage-limit.js +92 -20
- package/dist/utils/cli-usage-limit.js.map +1 -1
- package/dist/utils/input-gate.d.ts +2 -0
- package/dist/utils/input-gate.d.ts.map +1 -1
- package/dist/utils/input-gate.js +2 -0
- package/dist/utils/input-gate.js.map +1 -1
- package/dist/utils/runtime-build-id.d.ts +21 -0
- package/dist/utils/runtime-build-id.d.ts.map +1 -0
- package/dist/utils/runtime-build-id.js +83 -0
- package/dist/utils/runtime-build-id.js.map +1 -0
- package/dist/utils/terminal-renderer.d.ts +3 -3
- package/dist/utils/terminal-renderer.js +3 -3
- package/dist/vc-agent/cards.d.ts.map +1 -1
- package/dist/vc-agent/cards.js +21 -1
- package/dist/vc-agent/cards.js.map +1 -1
- package/dist/worker.js +601 -179
- package/dist/worker.js.map +1 -1
- package/dist/workflows/hostExecutors/botmux-schedule.d.ts.map +1 -1
- package/dist/workflows/hostExecutors/botmux-schedule.js +13 -1
- package/dist/workflows/hostExecutors/botmux-schedule.js.map +1 -1
- package/dist/workflows/migration/v2-run-archive-schema.d.ts +20 -20
- package/dist/workflows/migration/v2-to-v3.d.ts.map +1 -1
- package/dist/workflows/migration/v2-to-v3.js +5 -1
- package/dist/workflows/migration/v2-to-v3.js.map +1 -1
- package/dist/workflows/v3/architect.d.ts.map +1 -1
- package/dist/workflows/v3/architect.js +1 -0
- package/dist/workflows/v3/architect.js.map +1 -1
- package/dist/workflows/v3/cli-run.d.ts +9 -0
- package/dist/workflows/v3/cli-run.d.ts.map +1 -1
- package/dist/workflows/v3/cli-run.js +17 -2
- package/dist/workflows/v3/cli-run.js.map +1 -1
- package/dist/workflows/v3/goal-cli.d.ts +58 -0
- package/dist/workflows/v3/goal-cli.d.ts.map +1 -0
- package/dist/workflows/v3/goal-cli.js +430 -0
- package/dist/workflows/v3/goal-cli.js.map +1 -0
- package/dist/workflows/v3/library-materialize.d.ts.map +1 -1
- package/dist/workflows/v3/library-materialize.js +5 -1
- package/dist/workflows/v3/library-materialize.js.map +1 -1
- package/dist/workflows/v3/library-schema.d.ts +21 -0
- package/dist/workflows/v3/library-schema.d.ts.map +1 -1
- package/dist/workflows/v3/library-schema.js +95 -1
- package/dist/workflows/v3/library-schema.js.map +1 -1
- package/dist/workflows/v3/progress-projection.d.ts +3 -0
- package/dist/workflows/v3/progress-projection.d.ts.map +1 -1
- package/dist/workflows/v3/progress-projection.js +23 -1
- package/dist/workflows/v3/progress-projection.js.map +1 -1
- package/dist/workflows/v3/run-envelope.d.ts +46 -1
- package/dist/workflows/v3/run-envelope.d.ts.map +1 -1
- package/dist/workflows/v3/run-envelope.js +32 -1
- package/dist/workflows/v3/run-envelope.js.map +1 -1
- package/package.json +2 -2
- package/dist/dashboard-web/chunks/bot-defaults-page-AUKV7P4L.js +0 -10
- package/dist/dashboard-web/chunks/chunk-SZOB6VK2.js +0 -1
- package/dist/dashboard-web/chunks/connectors-page-HDQFEXZI.js +0 -1
- package/dist/dashboard-web/chunks/overview-page-FVR3NKAF.js +0 -1
- package/dist/dashboard-web/chunks/sessions-page-KOOOASIL.js +0 -2
- package/dist/dashboard-web/chunks/settings-page-IEBR7TGN.js +0 -2
- package/dist/utils/screen-analyzer.d.ts +0 -75
- package/dist/utils/screen-analyzer.d.ts.map +0 -1
- package/dist/utils/screen-analyzer.js +0 -333
- package/dist/utils/screen-analyzer.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-ipc-server.d.ts","sourceRoot":"","sources":["../../src/core/dashboard-ipc-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,eAAe,EAAE,KAAK,cAAc,EAAe,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"dashboard-ipc-server.d.ts","sourceRoot":"","sources":["../../src/core/dashboard-ipc-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,8 @@ import { V3_SESSION_RUN_MUTATION_ROUTE_PREFIX } from '../workflows/v3/session-re
|
|
|
9
9
|
import { listenWithProbe } from '../utils/listen-with-probe.js';
|
|
10
10
|
import { dashboardSecretPath } from './dashboard-secret.js';
|
|
11
11
|
import * as sessionStore from '../services/session-store.js';
|
|
12
|
+
import * as asyncTriggerStore from '../services/async-trigger-store.js';
|
|
13
|
+
import { resolveAsyncTriggerState, decideAsyncOwnership } from '../services/async-trigger-state.js';
|
|
12
14
|
import * as scheduleStore from '../services/schedule-store.js';
|
|
13
15
|
import * as groupsStore from '../services/groups-store.js';
|
|
14
16
|
import { createGroupWithBots, transferGroupOwner } from '../services/group-creator.js';
|
|
@@ -68,6 +70,7 @@ import * as chatFirstSeenStore from '../services/chat-first-seen-store.js';
|
|
|
68
70
|
import * as scheduler from './scheduler.js';
|
|
69
71
|
import { listActiveSessions, findActiveBySessionId, closeSession, getActiveSessionsRegistry, transferSession, deliverWriteLinkCardToOwners, forkWorker, suspendWorker, killWorker } from './worker-pool.js';
|
|
70
72
|
import { listOnlineDaemons } from '../utils/daemon-discovery.js';
|
|
73
|
+
import { isSessionStopped } from './session-liveness.js';
|
|
71
74
|
import { getChatMode, replyMessage, sendMessage, resolveUnionIdFromOpenId, listThreadMessages, listChatMessages, listChatBotMembers, getUserProfile, getUserProfileStrict, resolveAllowedUsersWithMap } from '../im/lark/client.js';
|
|
72
75
|
import { parseApiMessage, cardContentHasUpgradeFallback, resolveMergedCardContent } from '../im/lark/message-parser.js';
|
|
73
76
|
import { resumeSession, spawnDashboardSession, activateQueuedSession, closeCliMismatchedSessionsForBot, suspendActiveSessionsForBot } from './session-manager.js';
|
|
@@ -85,6 +88,7 @@ import { validateTriggerRequest } from '../services/trigger-types.js';
|
|
|
85
88
|
import { resolveCliSelection, selectionKeyForBot } from '../setup/cli-selection.js';
|
|
86
89
|
import { checkCliAvailability } from '../setup/cli-availability.js';
|
|
87
90
|
import { enrichHistorySenders } from '../dashboard/history-senders.js';
|
|
91
|
+
import { listPendingAsks, submitAskFromDesktop } from './ask-broker.js';
|
|
88
92
|
let exactChatGrantHandler = applyExactChatGrantRequest;
|
|
89
93
|
/** Test seam: replace the exact-grant service without touching live Feishu/config state. */
|
|
90
94
|
export function setExactChatGrantHandler(handler) {
|
|
@@ -111,6 +115,11 @@ import { sessionAnchorId } from './types.js';
|
|
|
111
115
|
import { attachSkillPolicy, detachSkillPolicy } from './skills/im-command.js';
|
|
112
116
|
import { readSkillRegistry } from '../services/skill-registry-store.js';
|
|
113
117
|
import { commitDeviceIsolationActivation, DEVICE_ISOLATION_COMMIT_PATH, DEVICE_ISOLATION_PREPARE_PATH, DEVICE_ISOLATION_RELEASE_PATH, logDeviceIsolationActivationError, prepareDeviceIsolationActivation, releaseDeviceIsolationActivation, } from './device-isolation-daemon.js';
|
|
118
|
+
// Daemon process start (module load ≈ daemon boot). Used by the SSE snapshot
|
|
119
|
+
// replay to bound the "recently closed" set to sessions that flipped
|
|
120
|
+
// active→closed during THIS run — i.e. restore-time zombies — without replaying
|
|
121
|
+
// the entire closed-session history on every connect.
|
|
122
|
+
const PROCESS_START_MS = Date.now();
|
|
114
123
|
const routes = [];
|
|
115
124
|
/** Requests that crossed the server-wide trusted-host gate. The legacy
|
|
116
125
|
* write-link handlers consult this marker so they do not verify (and consume)
|
|
@@ -326,11 +335,12 @@ function routeHasNarrowUntrustedAuth(method, pathname) {
|
|
|
326
335
|
return true;
|
|
327
336
|
if (method === 'POST' && pathname === '/api/asks')
|
|
328
337
|
return true;
|
|
329
|
-
// botmux slash / botmux
|
|
330
|
-
// 读隔离下读不到 host secret
|
|
338
|
+
// botmux slash / botmux role switch(角色切换)/ botmux delete(关闭自身):合法调用方
|
|
339
|
+
// 是会话内的 CLI 自身,沙箱 / 读隔离下读不到 host secret。handler 内验证
|
|
340
|
+
// 该会话的 rotating per-turn
|
|
331
341
|
// capability 并绑定到 URL 里的 sessionId(同 /api/asks 姿势)——capability 只
|
|
332
342
|
// 证明「我是这个会话当前这一轮的 CLI」,选不了别的会话。
|
|
333
|
-
if (method === 'POST' && /^\/api\/sessions\/[^/]+\/(?:slash|cd)$/.test(pathname))
|
|
343
|
+
if (method === 'POST' && /^\/api\/sessions\/[^/]+\/(?:slash|cd|close)$/.test(pathname))
|
|
334
344
|
return true;
|
|
335
345
|
if (method === 'POST' && pathname === '/api/hooks/emit')
|
|
336
346
|
return true;
|
|
@@ -398,6 +408,47 @@ async function handleDeviceIsolationActivationRoute(req, res, handler) {
|
|
|
398
408
|
ipcRoute('POST', DEVICE_ISOLATION_PREPARE_PATH, (req, res) => handleDeviceIsolationActivationRoute(req, res, prepareDeviceIsolationActivation));
|
|
399
409
|
ipcRoute('POST', DEVICE_ISOLATION_COMMIT_PATH, (req, res) => handleDeviceIsolationActivationRoute(req, res, commitDeviceIsolationActivation));
|
|
400
410
|
ipcRoute('POST', DEVICE_ISOLATION_RELEASE_PATH, (req, res) => handleDeviceIsolationActivationRoute(req, res, releaseDeviceIsolationActivation));
|
|
411
|
+
// ─── Pending asks (trusted Desktop/dashboard operator only) ─────────────────
|
|
412
|
+
ipcRoute('GET', '/api/asks/pending', (req, res) => {
|
|
413
|
+
if (!isTrustedHostIpcRequest(req)) {
|
|
414
|
+
return jsonRes(res, 403, { ok: false, error: 'trusted_host_required' });
|
|
415
|
+
}
|
|
416
|
+
const asks = listPendingAsks().map((ask) => ({
|
|
417
|
+
askId: ask.askId,
|
|
418
|
+
sessionId: ask.sessionId,
|
|
419
|
+
larkAppId: ask.larkAppId,
|
|
420
|
+
chatId: ask.chatId,
|
|
421
|
+
rootMessageId: ask.rootMessageId,
|
|
422
|
+
questions: ask.questions,
|
|
423
|
+
deadlineAt: ask.deadlineAt,
|
|
424
|
+
createdAt: ask.createdAt,
|
|
425
|
+
}));
|
|
426
|
+
return jsonRes(res, 200, { asks });
|
|
427
|
+
});
|
|
428
|
+
ipcRoute('POST', '/api/asks/answer', async (req, res) => {
|
|
429
|
+
if (!isTrustedHostIpcRequest(req)) {
|
|
430
|
+
return jsonRes(res, 403, { ok: false, error: 'trusted_host_required' });
|
|
431
|
+
}
|
|
432
|
+
let body;
|
|
433
|
+
try {
|
|
434
|
+
body = await readJsonBody(req);
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
438
|
+
}
|
|
439
|
+
if (!body.askId || !Array.isArray(body.selections)) {
|
|
440
|
+
return jsonRes(res, 400, { ok: false, error: 'askId_and_selections_required' });
|
|
441
|
+
}
|
|
442
|
+
const outcome = submitAskFromDesktop({
|
|
443
|
+
askId: body.askId,
|
|
444
|
+
selections: body.selections,
|
|
445
|
+
by: typeof body.by === 'string' ? body.by : 'desktop',
|
|
446
|
+
});
|
|
447
|
+
if (outcome !== 'accepted') {
|
|
448
|
+
return jsonRes(res, 409, { ok: false, error: outcome });
|
|
449
|
+
}
|
|
450
|
+
return jsonRes(res, 200, { ok: true, outcome });
|
|
451
|
+
});
|
|
401
452
|
ipcRoute('GET', '/api/sessions', (_req, res) => {
|
|
402
453
|
// Active first (live state), closed appended (historical)
|
|
403
454
|
const active = listActiveSessions().map(composeRowFromActive);
|
|
@@ -416,7 +467,16 @@ ipcRoute('GET', '/api/sessions/:sessionId', (_req, res, params) => {
|
|
|
416
467
|
return jsonRes(res, 200, { session: composeRowFromClosed(closed) });
|
|
417
468
|
jsonRes(res, 404, { error: 'not_found' });
|
|
418
469
|
});
|
|
419
|
-
|
|
470
|
+
/** Canonical daemon-side close used by the dashboard and `botmux delete`.
|
|
471
|
+
* Host callers authenticate with HMAC; a read-isolated CLI may close only its
|
|
472
|
+
* exact live session with the rotating per-turn capability. */
|
|
473
|
+
ipcRoute('POST', '/api/sessions/:sessionId/close', async (req, res, params) => {
|
|
474
|
+
const body = await readJsonBody(req)
|
|
475
|
+
.catch(() => ({}));
|
|
476
|
+
const ds = findActiveBySessionId(params.sessionId);
|
|
477
|
+
const auth = sessionCliIpcAuth(req, ds, params.sessionId, body);
|
|
478
|
+
if (!auth.ok)
|
|
479
|
+
return jsonRes(res, 403, { ok: false, error: auth.error });
|
|
420
480
|
const r = await closeSession(params.sessionId);
|
|
421
481
|
jsonRes(res, 200, r);
|
|
422
482
|
});
|
|
@@ -503,6 +563,92 @@ ipcRoute('POST', '/api/sessions/:sessionId/suspend', (_req, res, params) => {
|
|
|
503
563
|
}
|
|
504
564
|
jsonRes(res, 200, { ok: true, sessionId: params.sessionId, suspended: true });
|
|
505
565
|
});
|
|
566
|
+
/**
|
|
567
|
+
* Count host-overload降压 candidates for THIS daemon's scope, so the alert card
|
|
568
|
+
* can show "僵尸 N / 闲置 M" before the owner clicks. `stopped` counts zombies
|
|
569
|
+
* from the SHARED session store (same answer on every daemon — the card handler
|
|
570
|
+
* only takes it from one), `idle` counts THIS daemon's own idle live workers
|
|
571
|
+
* (owning-daemon-authoritative — the handler sums across daemons). Mirrors the
|
|
572
|
+
* exact classification the sweep uses so the preview matches what a click does.
|
|
573
|
+
*/
|
|
574
|
+
ipcRoute('GET', '/api/host-overload/counts', (_req, res) => {
|
|
575
|
+
const stopped = sessionStore.listSessions().filter(s => s.status === 'active' && isSessionStopped(s)).length;
|
|
576
|
+
let idle = 0;
|
|
577
|
+
for (const ds of listActiveSessions()) {
|
|
578
|
+
if (!ds.worker || ds.worker.killed)
|
|
579
|
+
continue;
|
|
580
|
+
if (ds.adoptedFrom || ds.initConfig?.adoptMode)
|
|
581
|
+
continue;
|
|
582
|
+
if (ds.lastScreenStatus !== 'idle')
|
|
583
|
+
continue;
|
|
584
|
+
idle++;
|
|
585
|
+
}
|
|
586
|
+
jsonRes(res, 200, { ok: true, stopped, idle });
|
|
587
|
+
});
|
|
588
|
+
/**
|
|
589
|
+
* Bulk host-overload降压 sweep, driven by the overload-alert card buttons.
|
|
590
|
+
* `mode`:
|
|
591
|
+
* - `clean_stopped`: close stopped zombie sessions (dead CLI + no tmux) from
|
|
592
|
+
* the SHARED session store — machine-wide, so a single daemon's sweep is
|
|
593
|
+
* enough (the alert-owning daemon calls this once, no fan-out needed).
|
|
594
|
+
* - `suspend_idle`: suspend THIS daemon's own idle (non-busy, suspendable,
|
|
595
|
+
* non-adopt) live workers. Live workers only exist in their owning daemon's
|
|
596
|
+
* process, so the card handler fans this mode out to every online daemon.
|
|
597
|
+
* Returns `{ ok, mode, affected }` — `affected` counts sessions acted on here.
|
|
598
|
+
*/
|
|
599
|
+
ipcRoute('POST', '/api/host-overload/sweep', async (req, res) => {
|
|
600
|
+
let body;
|
|
601
|
+
try {
|
|
602
|
+
body = await readJsonBody(req);
|
|
603
|
+
}
|
|
604
|
+
catch {
|
|
605
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
606
|
+
}
|
|
607
|
+
const mode = body?.mode;
|
|
608
|
+
if (mode === 'clean_stopped') {
|
|
609
|
+
const stopped = sessionStore.listSessions().filter(s => s.status === 'active' && isSessionStopped(s));
|
|
610
|
+
let affected = 0;
|
|
611
|
+
for (const s of stopped) {
|
|
612
|
+
try {
|
|
613
|
+
const r = await closeSession(s.sessionId);
|
|
614
|
+
// Only count sessions this call actually closed. A shared-store session
|
|
615
|
+
// already closed by another daemon's concurrent sweep returns
|
|
616
|
+
// alreadyClosed=true — counting it would inflate `affected` by the
|
|
617
|
+
// number of daemons that raced on the same zombie.
|
|
618
|
+
if (r.ok && !r.alreadyClosed)
|
|
619
|
+
affected++;
|
|
620
|
+
}
|
|
621
|
+
catch (err) {
|
|
622
|
+
logger.warn(`[overload-sweep] close failed for ${s.sessionId.slice(0, 8)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
logger.info(`[overload-sweep] clean_stopped: closed ${affected}/${stopped.length} zombie session(s)`);
|
|
626
|
+
return jsonRes(res, 200, { ok: true, mode, affected });
|
|
627
|
+
}
|
|
628
|
+
if (mode === 'suspend_idle') {
|
|
629
|
+
// This daemon's own idle live workers only. Correctness guards mirror the
|
|
630
|
+
// idle-worker sweeper: never touch adopt sessions or mid-turn (busy) ones.
|
|
631
|
+
let affected = 0;
|
|
632
|
+
for (const ds of listActiveSessions()) {
|
|
633
|
+
if (!ds.worker || ds.worker.killed)
|
|
634
|
+
continue; // no live worker
|
|
635
|
+
if (ds.adoptedFrom || ds.initConfig?.adoptMode)
|
|
636
|
+
continue; // never suspend adopt
|
|
637
|
+
if (ds.lastScreenStatus !== 'idle')
|
|
638
|
+
continue; // never cut an in-flight reply
|
|
639
|
+
try {
|
|
640
|
+
if (suspendWorker(ds, 'host_overload_suspend'))
|
|
641
|
+
affected++;
|
|
642
|
+
}
|
|
643
|
+
catch (err) {
|
|
644
|
+
logger.warn(`[overload-sweep] suspend failed for ${ds.session.sessionId.slice(0, 8)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
logger.info(`[overload-sweep] suspend_idle: suspended ${affected} idle worker(s)`);
|
|
648
|
+
return jsonRes(res, 200, { ok: true, mode, affected });
|
|
649
|
+
}
|
|
650
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_mode' });
|
|
651
|
+
});
|
|
506
652
|
/** 会话级 CLI IPC(slash/cd)的调用方证明:trusted-host(.dashboard-secret HMAC,
|
|
507
653
|
* 外层 gate 已验)直接放行;否则(沙箱/读隔离 CLI 读不到 secret,走
|
|
508
654
|
* routeHasNarrowUntrustedAuth 窄孔进来)必须出示该会话当前轮换的 capability,
|
|
@@ -563,7 +709,18 @@ ipcRoute('POST', '/api/sessions/:sessionId/slash', async (req, res, params) => {
|
|
|
563
709
|
jsonRes(res, 200, { ok: true, sessionId: params.sessionId, queued: v.command });
|
|
564
710
|
});
|
|
565
711
|
/** 会话内切换工作目录(角色切换专用):硬校验角色库根 → 更新记录落盘(唯一事实源)
|
|
566
|
-
* →
|
|
712
|
+
* → 活 worker 走「带 --resume 的进程重启、respawn 在新 cwd」,无活 worker 杀残留
|
|
713
|
+
* pane 让下条消息冷启动。
|
|
714
|
+
*
|
|
715
|
+
* 为什么是 respawn 而不是向活进程注入 /cd(旧实现):CLI 的系统上下文(CLAUDE.md、
|
|
716
|
+
* 记忆路径/索引)是开场按启动 cwd 注入一次的静态快照,/cd 只改 cwd 不重刷——注入
|
|
717
|
+
* 切换后模型仍拿着旧角色的记忆索引读写(读旧索引、写错桶)。respawn 让「开场」在
|
|
718
|
+
* 新 cwd 重新发生:新角色的 CLAUDE.md/记忆索引开场即注入,--resume 回放对话历史
|
|
719
|
+
* 保留上下文(“换角色外壳、留对话内核”)。旧桶 transcript 由 claude-code 适配器的
|
|
720
|
+
* resume 预检 syncClaudeResumeTargetToCwd(worker.ts 每次 resume respawn、probe 之前
|
|
721
|
+
* 把最新 <sid>.jsonl COPY 进新 cwd 的 project 目录,已在 master)接住,不会探空丢
|
|
722
|
+
* 上下文。故本改动可独立部署,不硬依赖任何跨桶迁移专项 PR。
|
|
723
|
+
*
|
|
567
724
|
* 鉴权双路径(见 sessionCliIpcAuth):trusted-host 签名或本会话 rotating
|
|
568
725
|
* capability;目录面由 validateRoleLibraryPath 硬校验承担(realpath 归一 +
|
|
569
726
|
* dev/ino 包含判断,角色库根之外一律拒)。
|
|
@@ -587,21 +744,14 @@ ipcRoute('POST', '/api/sessions/:sessionId/cd', async (req, res, params) => {
|
|
|
587
744
|
return jsonRes(res, v.error === 'outside_role_library' ? 403 : 400, { ok: false, error: v.error });
|
|
588
745
|
}
|
|
589
746
|
repinSessionWorkingDir(ds, v.resolvedPath);
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
}
|
|
595
|
-
catch { /* unknown cli */ }
|
|
596
|
-
if (ds.worker && !ds.worker.killed && canInject) {
|
|
597
|
-
// updateWorkingDir 随 inject_command 带给 worker:会话内 /cd 后 worker 内部的
|
|
598
|
-
// respawn(claude_exit 自动重启 / IM /restart / dashboard restart)必须收敛到
|
|
599
|
-
// 新目录,而不是陈旧的 lastInitConfig.workingDir。daemon 侧的 ds.initConfig 同步
|
|
600
|
-
// 更新,保持与 worker 侧一致(下次 forkWorker 用它重建 init 消息)。
|
|
747
|
+
if (ds.worker && !ds.worker.killed) {
|
|
748
|
+
// updateWorkingDir 随 restart 带给 worker:respawn 必须收敛到新目录,而不是
|
|
749
|
+
// 陈旧的 lastInitConfig.workingDir。daemon 侧的 ds.initConfig 同步更新,保持
|
|
750
|
+
// 与 worker 侧一致(下次 forkWorker 用它重建 init 消息)。
|
|
601
751
|
if (ds.initConfig)
|
|
602
752
|
ds.initConfig.workingDir = v.resolvedPath;
|
|
603
753
|
try {
|
|
604
|
-
ds.worker.send({ type: '
|
|
754
|
+
ds.worker.send({ type: 'restart', updateWorkingDir: v.resolvedPath });
|
|
605
755
|
}
|
|
606
756
|
catch {
|
|
607
757
|
// send() 抛异常:worker 进程实际上已经不可达(管道已断),但 above 的
|
|
@@ -610,7 +760,7 @@ ipcRoute('POST', '/api/sessions/:sessionId/cd', async (req, res, params) => {
|
|
|
610
760
|
killWorker(ds);
|
|
611
761
|
return jsonRes(res, 200, { ok: true, mode: 'cold-restart', dir: v.resolvedPath });
|
|
612
762
|
}
|
|
613
|
-
return jsonRes(res, 200, { ok: true, mode: '
|
|
763
|
+
return jsonRes(res, 200, { ok: true, mode: 'respawn-resume', dir: v.resolvedPath });
|
|
614
764
|
}
|
|
615
765
|
// Unconditional (no `ds.worker` guard), matching the IM `/cd` command handler
|
|
616
766
|
// (src/core/command-handler.ts) — killWorker() already no-ops safely when there
|
|
@@ -628,45 +778,61 @@ ipcRoute('POST', '/api/sessions/:sessionId/cd', async (req, res, params) => {
|
|
|
628
778
|
function findSessionRecord(sessionId) {
|
|
629
779
|
return findActiveBySessionId(sessionId)?.session ?? sessionStore.getSession(sessionId);
|
|
630
780
|
}
|
|
781
|
+
/** Four-state async lookup with durable fallback (design A).
|
|
782
|
+
*
|
|
783
|
+
* In-memory `asyncTriggerResults` lives only on the active DaemonSession and is
|
|
784
|
+
* lost on daemon restart / idle-suspend. To keep a poller from misreading an
|
|
785
|
+
* already-completed turn as `not_found`, this resolves against BOTH the live
|
|
786
|
+
* session and the on-disk stores:
|
|
787
|
+
* - completed (mem or disk) → completed + output.content + finishedAt
|
|
788
|
+
* - pending in mem / session active → running
|
|
789
|
+
* - session record closed, no output → failed (no_output; soft terminal —
|
|
790
|
+
* may be a real failure OR a caller close)
|
|
791
|
+
* - no session record AND no result → not_found (never existed / invalid id)
|
|
792
|
+
*
|
|
793
|
+
* Legacy `action`/`async` fields are still populated so existing webhook
|
|
794
|
+
* consumers keep working; new callers branch on `state`. */
|
|
631
795
|
function buildAsyncTriggerLookupResponse(sessionId, triggerId) {
|
|
632
796
|
const ds = findActiveBySessionId(sessionId);
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
797
|
+
const storedRaw = ds?.session ?? sessionStore.getSession(sessionId);
|
|
798
|
+
const persistedRaw = asyncTriggerStore.lookup(sessionId, triggerId);
|
|
799
|
+
// Cross-bot isolation (fail-closed / positive-proof) — see decideAsyncOwnership.
|
|
800
|
+
// Both sessionStore.getSession() (cross-scans every bot's sessions-*.json) and
|
|
801
|
+
// the async store (machine-wide shared dir) can surface another bot's data for
|
|
802
|
+
// a sessionId routed to THIS daemon; keep only sources positively proven ours.
|
|
803
|
+
const decision = decideAsyncOwnership({
|
|
804
|
+
owner: cachedLarkAppId,
|
|
805
|
+
liveDs: !!ds,
|
|
806
|
+
storedOwner: storedRaw?.larkAppId,
|
|
807
|
+
storedExists: !!storedRaw,
|
|
808
|
+
persistedOwner: persistedRaw?.ownerLarkAppId,
|
|
809
|
+
persistedExists: !!persistedRaw,
|
|
810
|
+
});
|
|
811
|
+
const stored = decision.keepStored ? storedRaw : undefined;
|
|
812
|
+
const persisted = decision.keepPersisted ? persistedRaw : undefined;
|
|
813
|
+
if (decision.foreignLeak) {
|
|
645
814
|
return {
|
|
646
815
|
ok: true,
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
status: 'completed',
|
|
653
|
-
sessionId,
|
|
654
|
-
completedAt: state.completedAt ? new Date(state.completedAt).toISOString() : undefined,
|
|
655
|
-
},
|
|
656
|
-
message: 'async trigger completed',
|
|
816
|
+
state: 'not_found',
|
|
817
|
+
triggerId,
|
|
818
|
+
errorCode: 'session_not_found',
|
|
819
|
+
error: `no session record for: ${sessionId}`,
|
|
820
|
+
message: 'no session found',
|
|
657
821
|
};
|
|
658
822
|
}
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
823
|
+
const memTriggerId = triggerId || ds?.latestAsyncTriggerId;
|
|
824
|
+
const memResult = ds && memTriggerId ? ds.asyncTriggerResults?.get(memTriggerId) : undefined;
|
|
825
|
+
return resolveAsyncTriggerState({
|
|
826
|
+
sessionId,
|
|
827
|
+
liveActive: !!ds,
|
|
828
|
+
chatId: ds?.chatId ?? stored?.chatId,
|
|
829
|
+
memResult: memResult ? { status: memResult.status, content: memResult.content, completedAt: memResult.completedAt } : undefined,
|
|
830
|
+
memTriggerId: memResult ? memTriggerId : undefined,
|
|
831
|
+
persisted,
|
|
832
|
+
storedStatus: stored ? (stored.status === 'closed' ? 'closed' : 'open') : undefined,
|
|
833
|
+
closedAt: stored?.closedAt,
|
|
834
|
+
requestedTriggerId: triggerId,
|
|
835
|
+
});
|
|
670
836
|
}
|
|
671
837
|
// 看板放置:dashboard 看板视图拖拽卡片后持久化列 + 列内排序位置。
|
|
672
838
|
// 改完广播 session.update,所有打开的 dashboard 实时同步。
|
|
@@ -880,12 +1046,10 @@ ipcRoute('GET', '/api/sessions/:sessionId/trigger-result', (req, res, params) =>
|
|
|
880
1046
|
const url = new URL(req.url ?? '/', 'http://localhost');
|
|
881
1047
|
const triggerId = url.searchParams.get('triggerId') ?? undefined;
|
|
882
1048
|
const result = buildAsyncTriggerLookupResponse(params.sessionId, triggerId);
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
: 400;
|
|
888
|
-
jsonRes(res, status, result);
|
|
1049
|
+
// Four-state semantics: the query itself succeeds (HTTP 200) for every
|
|
1050
|
+
// resolved state including not_found — task state lives in `result.state`,
|
|
1051
|
+
// not the HTTP status. Only a malformed lookup (ok:false) maps to non-200.
|
|
1052
|
+
jsonRes(res, result.ok ? 200 : 400, result);
|
|
889
1053
|
});
|
|
890
1054
|
// 会话 insight:只读解析本会话的 transcript,产出动作 span / 失败聚合 / 规则建议
|
|
891
1055
|
// (SafeInsightReport)。底层 services/insight 已做 fail-closed 脱敏投影——raw 命令
|
|
@@ -2182,6 +2346,20 @@ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
|
|
|
2182
2346
|
startupCommands = sc.join('\n');
|
|
2183
2347
|
}
|
|
2184
2348
|
catch { /* none */ }
|
|
2349
|
+
// customPassthroughCommands / canTalkDaemonCommands → space-joined for the
|
|
2350
|
+
// dashboard slash-command editors. Empty string = not configured (回默认).
|
|
2351
|
+
let customPassthroughCommands = '';
|
|
2352
|
+
let canTalkDaemonCommands = '';
|
|
2353
|
+
try {
|
|
2354
|
+
const cfg = getBot(cachedLarkAppId).config;
|
|
2355
|
+
if (Array.isArray(cfg.customPassthroughCommands) && cfg.customPassthroughCommands.length) {
|
|
2356
|
+
customPassthroughCommands = cfg.customPassthroughCommands.join(' ');
|
|
2357
|
+
}
|
|
2358
|
+
if (Array.isArray(cfg.canTalkDaemonCommands) && cfg.canTalkDaemonCommands.length) {
|
|
2359
|
+
canTalkDaemonCommands = cfg.canTalkDaemonCommands.join(' ');
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
catch { /* none */ }
|
|
2185
2363
|
// Per-bot env → pretty JSON for the dashboard textarea. The dashboard is
|
|
2186
2364
|
// owner-authenticated, so showing the real values here is acceptable (same
|
|
2187
2365
|
// as editing bots.json directly); the chat-facing /config get masks them.
|
|
@@ -2240,6 +2418,7 @@ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
|
|
|
2240
2418
|
codexAppCleanInput: cardPrefs.codexAppCleanInput,
|
|
2241
2419
|
writableTerminalLinkInCard: cardPrefs.writableTerminalLinkInCard,
|
|
2242
2420
|
privateCard: cardPrefs.privateCard,
|
|
2421
|
+
overloadAlert: cardPrefs.overloadAlert,
|
|
2243
2422
|
botToBotSameDir: cardPrefs.botToBotSameDir,
|
|
2244
2423
|
autoStartOnGroupJoin: cardPrefs.autoStartOnGroupJoin,
|
|
2245
2424
|
autoStartOnGroupJoinPrompt: cardPrefs.autoStartOnGroupJoinPrompt,
|
|
@@ -2262,6 +2441,8 @@ ipcRoute('GET', '/api/bot-default-oncall', async (_req, res) => {
|
|
|
2262
2441
|
residentSessionCount,
|
|
2263
2442
|
dormantSessionCount,
|
|
2264
2443
|
startupCommands,
|
|
2444
|
+
customPassthroughCommands,
|
|
2445
|
+
canTalkDaemonCommands,
|
|
2265
2446
|
launchShell: getBot(cachedLarkAppId).config.launchShell ?? '',
|
|
2266
2447
|
env,
|
|
2267
2448
|
riff: redactRiffForClient(getBot(cachedLarkAppId).config.riff),
|
|
@@ -2294,6 +2475,8 @@ ipcRoute('PUT', '/api/bot-card-prefs', async (req, res) => {
|
|
|
2294
2475
|
patch.writableTerminalLinkInCard = body.writableTerminalLinkInCard;
|
|
2295
2476
|
if (typeof body.privateCard === 'boolean')
|
|
2296
2477
|
patch.privateCard = body.privateCard;
|
|
2478
|
+
if (typeof body.overloadAlert === 'boolean')
|
|
2479
|
+
patch.overloadAlert = body.overloadAlert;
|
|
2297
2480
|
if (typeof body.autoStartOnGroupJoin === 'boolean')
|
|
2298
2481
|
patch.autoStartOnGroupJoin = body.autoStartOnGroupJoin;
|
|
2299
2482
|
if (typeof body.autoStartOnGroupJoinPrompt === 'string')
|
|
@@ -2742,6 +2925,72 @@ ipcRoute('PUT', '/api/bot-startup-commands', async (req, res) => {
|
|
|
2742
2925
|
return jsonRes(res, 400, { ok: false, error: r.reason });
|
|
2743
2926
|
jsonRes(res, 200, { ok: true, startupCommands: (value ?? []).join('\n') });
|
|
2744
2927
|
});
|
|
2928
|
+
// Per-bot 透传 slash 命令 customPassthroughCommands。Body `{ customPassthroughCommands: string }`
|
|
2929
|
+
// (原始文本,逗号/空格分隔;空白=清除→回仅内置白名单)。走 stringList 的
|
|
2930
|
+
// coerceConfigValue(用字段自带 parseList,与 /botconfig 同口径)+ applyConfigField
|
|
2931
|
+
// (写盘 + 内存热更新),immediate 生效。回包 space-joined 供输入框回填。
|
|
2932
|
+
ipcRoute('PUT', '/api/bot-custom-passthrough', async (req, res) => {
|
|
2933
|
+
if (!cachedLarkAppId)
|
|
2934
|
+
return jsonRes(res, 503, { error: 'larkAppId_not_set' });
|
|
2935
|
+
let body;
|
|
2936
|
+
try {
|
|
2937
|
+
body = await readJsonBody(req);
|
|
2938
|
+
}
|
|
2939
|
+
catch {
|
|
2940
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
2941
|
+
}
|
|
2942
|
+
const spec = findConfigField('customPassthroughCommands');
|
|
2943
|
+
if (!spec)
|
|
2944
|
+
return jsonRes(res, 500, { ok: false, error: 'spec_missing' });
|
|
2945
|
+
const raw = typeof body.customPassthroughCommands === 'string' ? body.customPassthroughCommands : '';
|
|
2946
|
+
let value;
|
|
2947
|
+
if (!raw.trim()) {
|
|
2948
|
+
value = null; // 清除 → 回仅内置白名单
|
|
2949
|
+
}
|
|
2950
|
+
else {
|
|
2951
|
+
const coerced = coerceConfigValue(spec, raw);
|
|
2952
|
+
if (!coerced.ok)
|
|
2953
|
+
return jsonRes(res, 400, { ok: false, error: coerced.reason });
|
|
2954
|
+
value = coerced.value;
|
|
2955
|
+
}
|
|
2956
|
+
const r = await applyConfigField(cachedLarkAppId, spec, value);
|
|
2957
|
+
if (!r.ok)
|
|
2958
|
+
return jsonRes(res, 400, { ok: false, error: r.reason });
|
|
2959
|
+
jsonRes(res, 200, { ok: true, customPassthroughCommands: (value ?? []).join(' ') });
|
|
2960
|
+
});
|
|
2961
|
+
// Per-bot daemon 命令降权名单 canTalkDaemonCommands。Body
|
|
2962
|
+
// `{ canTalkDaemonCommands: string }`(原始文本,逗号/空格分隔;空白=清除→回全部
|
|
2963
|
+
// 仅管理员)。走 stringList 的 coerceConfigValue(字段自带 parseList 只认 daemon
|
|
2964
|
+
// 命令,透传/拼错条目被滤掉)+ applyConfigField(写盘 + 内存热更新),immediate 生效。
|
|
2965
|
+
ipcRoute('PUT', '/api/bot-cantalk-daemon-commands', async (req, res) => {
|
|
2966
|
+
if (!cachedLarkAppId)
|
|
2967
|
+
return jsonRes(res, 503, { error: 'larkAppId_not_set' });
|
|
2968
|
+
let body;
|
|
2969
|
+
try {
|
|
2970
|
+
body = await readJsonBody(req);
|
|
2971
|
+
}
|
|
2972
|
+
catch {
|
|
2973
|
+
return jsonRes(res, 400, { ok: false, error: 'bad_json' });
|
|
2974
|
+
}
|
|
2975
|
+
const spec = findConfigField('canTalkDaemonCommands');
|
|
2976
|
+
if (!spec)
|
|
2977
|
+
return jsonRes(res, 500, { ok: false, error: 'spec_missing' });
|
|
2978
|
+
const raw = typeof body.canTalkDaemonCommands === 'string' ? body.canTalkDaemonCommands : '';
|
|
2979
|
+
let value;
|
|
2980
|
+
if (!raw.trim()) {
|
|
2981
|
+
value = null; // 清除 → 回全部仅管理员
|
|
2982
|
+
}
|
|
2983
|
+
else {
|
|
2984
|
+
const coerced = coerceConfigValue(spec, raw);
|
|
2985
|
+
if (!coerced.ok)
|
|
2986
|
+
return jsonRes(res, 400, { ok: false, error: coerced.reason });
|
|
2987
|
+
value = coerced.value;
|
|
2988
|
+
}
|
|
2989
|
+
const r = await applyConfigField(cachedLarkAppId, spec, value);
|
|
2990
|
+
if (!r.ok)
|
|
2991
|
+
return jsonRes(res, 400, { ok: false, error: r.reason });
|
|
2992
|
+
jsonRes(res, 200, { ok: true, canTalkDaemonCommands: (value ?? []).join(' ') });
|
|
2993
|
+
});
|
|
2745
2994
|
// Per-bot launch-shell override launchShell。Body `{ launchShell: string }`:
|
|
2746
2995
|
// 空字符串=清除(回 $SHELL)。走 applyConfigField(与 /config launchShell 同一写盘
|
|
2747
2996
|
// + 内存热更新路径),next-session 生效(下个会话起用新 shell 启动 CLI)。
|
|
@@ -3351,9 +3600,33 @@ ipcRoute('GET', '/api/events', (_req, res) => {
|
|
|
3351
3600
|
// aggregator and the browser store upsert by sessionId, so any row also
|
|
3352
3601
|
// delivered live just refreshes the same entry.
|
|
3353
3602
|
try {
|
|
3603
|
+
const activeIds = new Set();
|
|
3354
3604
|
for (const ds of listActiveSessions()) {
|
|
3605
|
+
activeIds.add(ds.session.sessionId);
|
|
3355
3606
|
res.write(`event: session.spawned\ndata: ${JSON.stringify({ session: composeRowFromActive(ds) })}\n\n`);
|
|
3356
3607
|
}
|
|
3608
|
+
// Also replay sessions CLOSED during this run as `session.spawned` carrying a
|
|
3609
|
+
// closed row. The active-only replay above can't cover a restore-time zombie:
|
|
3610
|
+
// restoreActiveSessions registers it, announces it, then immediately probes it
|
|
3611
|
+
// 'missing' and closeSession()s it (evicting it from the active Map) — all
|
|
3612
|
+
// before a racing dashboard's SSE subscription exists. By connect time it is
|
|
3613
|
+
// neither in the active Map nor was it a closed row at the dashboard's early
|
|
3614
|
+
// (pre-restore) hydrate, so without this it stays invisible (or, if the
|
|
3615
|
+
// dashboard cached it active from before the restart, lingers as a stale
|
|
3616
|
+
// active row — hydrateSessions only upserts, never deletes absent rows).
|
|
3617
|
+
// Bounded to closedAt >= PROCESS_START_MS so we replay only this run's
|
|
3618
|
+
// closures (the full closed history is already served by GET /api/sessions
|
|
3619
|
+
// on hydrate). `session.spawned` (not session.update) because the row may be
|
|
3620
|
+
// unknown to the client — both consumers upsert by sessionId, and the closed
|
|
3621
|
+
// row's status:'closed' overwrites any stale active entry.
|
|
3622
|
+
for (const s of sessionStore.listSessions()) {
|
|
3623
|
+
if (s.status !== 'closed' || activeIds.has(s.sessionId))
|
|
3624
|
+
continue;
|
|
3625
|
+
const closedMs = s.closedAt ? Date.parse(s.closedAt) : NaN;
|
|
3626
|
+
if (!Number.isFinite(closedMs) || closedMs < PROCESS_START_MS)
|
|
3627
|
+
continue;
|
|
3628
|
+
res.write(`event: session.spawned\ndata: ${JSON.stringify({ session: composeRowFromClosed(s) })}\n\n`);
|
|
3629
|
+
}
|
|
3357
3630
|
}
|
|
3358
3631
|
catch (err) {
|
|
3359
3632
|
logger.warn(`[dashboard-ipc] /api/events snapshot replay failed: ${err}`);
|