botmux 3.14.0 → 3.16.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 +2 -2
- package/README.md +2 -2
- package/dist/.runtime-build-id +1 -1
- package/dist/adapters/backend/destroy-result.d.ts +159 -0
- package/dist/adapters/backend/destroy-result.d.ts.map +1 -0
- package/dist/adapters/backend/destroy-result.js +223 -0
- package/dist/adapters/backend/destroy-result.js.map +1 -0
- package/dist/adapters/backend/herdr-backend.d.ts +4 -0
- package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
- package/dist/adapters/backend/herdr-backend.js +23 -1
- package/dist/adapters/backend/herdr-backend.js.map +1 -1
- package/dist/adapters/backend/mojo-backend.d.ts +577 -0
- package/dist/adapters/backend/mojo-backend.d.ts.map +1 -0
- package/dist/adapters/backend/mojo-backend.js +2471 -0
- package/dist/adapters/backend/mojo-backend.js.map +1 -0
- package/dist/adapters/backend/mojo-budgets.d.ts +21 -0
- package/dist/adapters/backend/mojo-budgets.d.ts.map +1 -0
- package/dist/adapters/backend/mojo-budgets.js +22 -0
- package/dist/adapters/backend/mojo-budgets.js.map +1 -0
- package/dist/adapters/backend/mojo-isolated-workspace.d.ts +69 -0
- package/dist/adapters/backend/mojo-isolated-workspace.d.ts.map +1 -0
- package/dist/adapters/backend/mojo-isolated-workspace.js +213 -0
- package/dist/adapters/backend/mojo-isolated-workspace.js.map +1 -0
- package/dist/adapters/backend/mojo-process-tree.d.ts +292 -0
- package/dist/adapters/backend/mojo-process-tree.d.ts.map +1 -0
- package/dist/adapters/backend/mojo-process-tree.js +486 -0
- package/dist/adapters/backend/mojo-process-tree.js.map +1 -0
- package/dist/adapters/backend/mojo-types.d.ts +542 -0
- package/dist/adapters/backend/mojo-types.d.ts.map +1 -0
- package/dist/adapters/backend/mojo-types.js +682 -0
- package/dist/adapters/backend/mojo-types.js.map +1 -0
- package/dist/adapters/backend/reproduce-command.js +3 -3
- package/dist/adapters/backend/reproduce-command.js.map +1 -1
- package/dist/adapters/backend/riff-backend.js +1 -1
- package/dist/adapters/backend/riff-backend.js.map +1 -1
- package/dist/adapters/backend/sandbox.d.ts +44 -7
- package/dist/adapters/backend/sandbox.d.ts.map +1 -1
- package/dist/adapters/backend/sandbox.js +30 -7
- package/dist/adapters/backend/sandbox.js.map +1 -1
- package/dist/adapters/backend/session-backend-selector.d.ts +14 -1
- package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -1
- package/dist/adapters/backend/session-backend-selector.js +82 -10
- package/dist/adapters/backend/session-backend-selector.js.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.d.ts +30 -0
- package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.js +60 -0
- package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
- package/dist/adapters/backend/types.d.ts +108 -6
- package/dist/adapters/backend/types.d.ts.map +1 -1
- package/dist/adapters/backend/types.js.map +1 -1
- package/dist/adapters/backend/zmx-backend.d.ts +11 -0
- package/dist/adapters/backend/zmx-backend.d.ts.map +1 -1
- package/dist/adapters/backend/zmx-backend.js +16 -1
- package/dist/adapters/backend/zmx-backend.js.map +1 -1
- package/dist/adapters/cli/codex-app.d.ts.map +1 -1
- package/dist/adapters/cli/codex-app.js +2 -2
- package/dist/adapters/cli/codex-app.js.map +1 -1
- package/dist/adapters/cli/codex.d.ts.map +1 -1
- package/dist/adapters/cli/codex.js +7 -0
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/copilot.d.ts +3 -1
- package/dist/adapters/cli/copilot.d.ts.map +1 -1
- package/dist/adapters/cli/copilot.js +23 -5
- package/dist/adapters/cli/copilot.js.map +1 -1
- package/dist/adapters/cli/cursor.d.ts.map +1 -1
- package/dist/adapters/cli/cursor.js +26 -4
- package/dist/adapters/cli/cursor.js.map +1 -1
- package/dist/adapters/cli/dsh.d.ts.map +1 -1
- package/dist/adapters/cli/dsh.js +5 -1
- package/dist/adapters/cli/dsh.js.map +1 -1
- package/dist/adapters/cli/grok.d.ts.map +1 -1
- package/dist/adapters/cli/grok.js +24 -5
- package/dist/adapters/cli/grok.js.map +1 -1
- package/dist/adapters/cli/kimi.d.ts.map +1 -1
- package/dist/adapters/cli/kimi.js +19 -1
- package/dist/adapters/cli/kimi.js.map +1 -1
- package/dist/adapters/cli/mojo.d.ts +28 -0
- package/dist/adapters/cli/mojo.d.ts.map +1 -0
- package/dist/adapters/cli/mojo.js +58 -0
- package/dist/adapters/cli/mojo.js.map +1 -0
- package/dist/adapters/cli/pi.d.ts +20 -5
- package/dist/adapters/cli/pi.d.ts.map +1 -1
- package/dist/adapters/cli/pi.js +27 -5
- package/dist/adapters/cli/pi.js.map +1 -1
- package/dist/adapters/cli/read-isolation.d.ts +251 -1
- package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
- package/dist/adapters/cli/read-isolation.js +254 -1
- package/dist/adapters/cli/read-isolation.js.map +1 -1
- package/dist/adapters/cli/registry.d.ts +13 -1
- package/dist/adapters/cli/registry.d.ts.map +1 -1
- package/dist/adapters/cli/registry.js +19 -1
- package/dist/adapters/cli/registry.js.map +1 -1
- package/dist/adapters/cli/runner-input.d.ts +3 -3
- package/dist/adapters/cli/runner-input.d.ts.map +1 -1
- package/dist/adapters/cli/runner-input.js +4 -3
- package/dist/adapters/cli/runner-input.js.map +1 -1
- package/dist/adapters/cli/shared-hints.d.ts +3 -1
- package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
- package/dist/adapters/cli/shared-hints.js +51 -30
- package/dist/adapters/cli/shared-hints.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +33 -4
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/bot-registry.d.ts +42 -0
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +54 -4
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/arg-utils.d.ts +5 -0
- package/dist/cli/arg-utils.d.ts.map +1 -1
- package/dist/cli/arg-utils.js +7 -0
- package/dist/cli/arg-utils.js.map +1 -1
- package/dist/cli/bots-list-output.d.ts +130 -2
- package/dist/cli/bots-list-output.d.ts.map +1 -1
- package/dist/cli/bots-list-output.js +173 -27
- package/dist/cli/bots-list-output.js.map +1 -1
- package/dist/cli/daemon-lifecycle-env.d.ts +10 -3
- package/dist/cli/daemon-lifecycle-env.d.ts.map +1 -1
- package/dist/cli/daemon-lifecycle-env.js +38 -11
- package/dist/cli/daemon-lifecycle-env.js.map +1 -1
- package/dist/cli/dashboard-command.d.ts +15 -0
- package/dist/cli/dashboard-command.d.ts.map +1 -1
- package/dist/cli/dashboard-command.js +22 -0
- package/dist/cli/dashboard-command.js.map +1 -1
- package/dist/cli/log-tail.d.ts +54 -0
- package/dist/cli/log-tail.d.ts.map +1 -0
- package/dist/cli/log-tail.js +167 -0
- package/dist/cli/log-tail.js.map +1 -0
- package/dist/cli/pm2-env.d.ts +16 -0
- package/dist/cli/pm2-env.d.ts.map +1 -0
- package/dist/cli/pm2-env.js +63 -0
- package/dist/cli/pm2-env.js.map +1 -0
- package/dist/cli/pm2-fleet-lock.d.ts +26 -0
- package/dist/cli/pm2-fleet-lock.d.ts.map +1 -0
- package/dist/cli/pm2-fleet-lock.js +50 -0
- package/dist/cli/pm2-fleet-lock.js.map +1 -0
- package/dist/cli/pm2-god-retirement.d.ts +59 -0
- package/dist/cli/pm2-god-retirement.d.ts.map +1 -0
- package/dist/cli/pm2-god-retirement.js +95 -0
- package/dist/cli/pm2-god-retirement.js.map +1 -0
- package/dist/cli/session-list-wake.d.ts +41 -0
- package/dist/cli/session-list-wake.d.ts.map +1 -0
- package/dist/cli/session-list-wake.js +102 -0
- package/dist/cli/session-list-wake.js.map +1 -0
- package/dist/cli/workflow.d.ts.map +1 -1
- package/dist/cli/workflow.js +26 -0
- package/dist/cli/workflow.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +941 -118
- package/dist/cli.js.map +1 -1
- package/dist/codex-app-runner.js +261 -49
- package/dist/codex-app-runner.js.map +1 -1
- package/dist/core/cli-runtime-update.d.ts +8 -0
- package/dist/core/cli-runtime-update.d.ts.map +1 -1
- package/dist/core/cli-runtime-update.js +127 -8
- package/dist/core/cli-runtime-update.js.map +1 -1
- package/dist/core/close-residual.d.ts +64 -0
- package/dist/core/close-residual.d.ts.map +1 -0
- package/dist/core/close-residual.js +93 -0
- package/dist/core/close-residual.js.map +1 -0
- package/dist/core/closed-session-card.d.ts.map +1 -1
- package/dist/core/closed-session-card.js +11 -3
- package/dist/core/closed-session-card.js.map +1 -1
- package/dist/core/command-discovery.d.ts.map +1 -1
- package/dist/core/command-discovery.js +4 -1
- package/dist/core/command-discovery.js.map +1 -1
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +129 -27
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/cost-calculator.d.ts +3 -1
- package/dist/core/cost-calculator.d.ts.map +1 -1
- package/dist/core/cost-calculator.js +230 -1
- package/dist/core/cost-calculator.js.map +1 -1
- package/dist/core/daemon-background-close.d.ts +19 -0
- package/dist/core/daemon-background-close.d.ts.map +1 -0
- package/dist/core/daemon-background-close.js +39 -0
- package/dist/core/daemon-background-close.js.map +1 -0
- package/dist/core/dashboard-command/overview.d.ts +4 -0
- package/dist/core/dashboard-command/overview.d.ts.map +1 -1
- package/dist/core/dashboard-command/overview.js +8 -1
- package/dist/core/dashboard-command/overview.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +415 -42
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dashboard-rows.d.ts +4 -0
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +3 -0
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/core/dashboard-url.d.ts +37 -0
- package/dist/core/dashboard-url.d.ts.map +1 -1
- package/dist/core/dashboard-url.js +71 -0
- package/dist/core/dashboard-url.js.map +1 -1
- package/dist/core/deferred-schedule-settlement.d.ts +15 -1
- package/dist/core/deferred-schedule-settlement.d.ts.map +1 -1
- package/dist/core/deferred-schedule-settlement.js +4 -1
- package/dist/core/deferred-schedule-settlement.js.map +1 -1
- package/dist/core/device-isolation-daemon.d.ts +91 -1
- package/dist/core/device-isolation-daemon.d.ts.map +1 -1
- package/dist/core/device-isolation-daemon.js +346 -2
- package/dist/core/device-isolation-daemon.js.map +1 -1
- package/dist/core/local-terminal-opener.d.ts.map +1 -1
- package/dist/core/local-terminal-opener.js +5 -1
- package/dist/core/local-terminal-opener.js.map +1 -1
- package/dist/core/loopback-target.d.ts +14 -0
- package/dist/core/loopback-target.d.ts.map +1 -0
- package/dist/core/loopback-target.js +20 -0
- package/dist/core/loopback-target.js.map +1 -0
- package/dist/core/maintenance.d.ts.map +1 -1
- package/dist/core/maintenance.js +16 -2
- package/dist/core/maintenance.js.map +1 -1
- package/dist/core/mojo-containment-command.d.ts +20 -0
- package/dist/core/mojo-containment-command.d.ts.map +1 -0
- package/dist/core/mojo-containment-command.js +266 -0
- package/dist/core/mojo-containment-command.js.map +1 -0
- package/dist/core/mojo-containment.d.ts +575 -0
- package/dist/core/mojo-containment.d.ts.map +1 -0
- package/dist/core/mojo-containment.js +1158 -0
- package/dist/core/mojo-containment.js.map +1 -0
- package/dist/core/mojo-launcher-env-quarantine.d.ts +30 -0
- package/dist/core/mojo-launcher-env-quarantine.d.ts.map +1 -0
- package/dist/core/mojo-launcher-env-quarantine.js +175 -0
- package/dist/core/mojo-launcher-env-quarantine.js.map +1 -0
- package/dist/core/mojo-session-identity.d.ts +3 -0
- package/dist/core/mojo-session-identity.d.ts.map +1 -0
- package/dist/core/mojo-session-identity.js +126 -0
- package/dist/core/mojo-session-identity.js.map +1 -0
- package/dist/core/persistent-backend.d.ts +32 -8
- package/dist/core/persistent-backend.d.ts.map +1 -1
- package/dist/core/persistent-backend.js +55 -17
- package/dist/core/persistent-backend.js.map +1 -1
- package/dist/core/plugins/mcp/gateway.d.ts +14 -1
- package/dist/core/plugins/mcp/gateway.d.ts.map +1 -1
- package/dist/core/plugins/mcp/gateway.js +70 -3
- package/dist/core/plugins/mcp/gateway.js.map +1 -1
- package/dist/core/plugins/mcp/host.d.ts +2 -0
- package/dist/core/plugins/mcp/host.d.ts.map +1 -1
- package/dist/core/plugins/mcp/host.js +2 -0
- package/dist/core/plugins/mcp/host.js.map +1 -1
- package/dist/core/plugins/pm2.d.ts.map +1 -1
- package/dist/core/plugins/pm2.js +16 -3
- package/dist/core/plugins/pm2.js.map +1 -1
- package/dist/core/plugins/service-manager.d.ts +9 -0
- package/dist/core/plugins/service-manager.d.ts.map +1 -1
- package/dist/core/plugins/service-manager.js +33 -16
- package/dist/core/plugins/service-manager.js.map +1 -1
- package/dist/core/preview-port-owner.d.ts +109 -0
- package/dist/core/preview-port-owner.d.ts.map +1 -0
- package/dist/core/preview-port-owner.js +320 -0
- package/dist/core/preview-port-owner.js.map +1 -0
- package/dist/core/remote-cli-ids.d.ts +5 -0
- package/dist/core/remote-cli-ids.d.ts.map +1 -0
- package/dist/core/remote-cli-ids.js +24 -0
- package/dist/core/remote-cli-ids.js.map +1 -0
- package/dist/core/{riff-shutdown-detach.d.ts → remote-shutdown-detach.d.ts} +40 -39
- package/dist/core/remote-shutdown-detach.d.ts.map +1 -0
- package/dist/core/{riff-shutdown-detach.js → remote-shutdown-detach.js} +85 -83
- package/dist/core/remote-shutdown-detach.js.map +1 -0
- package/dist/core/{riff-worker-shutdown-readiness.d.ts → remote-worker-shutdown-readiness.d.ts} +5 -4
- package/dist/core/remote-worker-shutdown-readiness.d.ts.map +1 -0
- package/dist/core/{riff-worker-shutdown-readiness.js → remote-worker-shutdown-readiness.js} +4 -3
- package/dist/core/remote-worker-shutdown-readiness.js.map +1 -0
- package/dist/core/reply-target.d.ts +16 -1
- package/dist/core/reply-target.d.ts.map +1 -1
- package/dist/core/reply-target.js +61 -0
- package/dist/core/reply-target.js.map +1 -1
- package/dist/core/session-group-birth.d.ts +26 -0
- package/dist/core/session-group-birth.d.ts.map +1 -1
- package/dist/core/session-group-birth.js +81 -4
- package/dist/core/session-group-birth.js.map +1 -1
- package/dist/core/session-manager.d.ts +15 -2
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +259 -5
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-model.d.ts +46 -0
- package/dist/core/session-model.d.ts.map +1 -0
- package/dist/core/session-model.js +42 -0
- package/dist/core/session-model.js.map +1 -0
- package/dist/core/session-owner-reminder.d.ts +63 -0
- package/dist/core/session-owner-reminder.d.ts.map +1 -0
- package/dist/core/session-owner-reminder.js +196 -0
- package/dist/core/session-owner-reminder.js.map +1 -0
- package/dist/core/session-preview-registry.d.ts +53 -0
- package/dist/core/session-preview-registry.d.ts.map +1 -0
- package/dist/core/session-preview-registry.js +82 -0
- package/dist/core/session-preview-registry.js.map +1 -0
- package/dist/core/session-preview.d.ts +114 -0
- package/dist/core/session-preview.d.ts.map +1 -0
- package/dist/core/session-preview.js +184 -0
- package/dist/core/session-preview.js.map +1 -0
- package/dist/core/session-rename.d.ts.map +1 -1
- package/dist/core/session-rename.js +5 -3
- package/dist/core/session-rename.js.map +1 -1
- package/dist/core/session-wake-deadline.d.ts +5 -0
- package/dist/core/session-wake-deadline.d.ts.map +1 -0
- package/dist/core/session-wake-deadline.js +13 -0
- package/dist/core/session-wake-deadline.js.map +1 -0
- package/dist/core/shutdown-budgets.d.ts +7 -6
- package/dist/core/shutdown-budgets.d.ts.map +1 -1
- package/dist/core/shutdown-budgets.js +11 -10
- package/dist/core/shutdown-budgets.js.map +1 -1
- package/dist/core/skills/frontmatter.d.ts.map +1 -1
- package/dist/core/skills/frontmatter.js +6 -1
- package/dist/core/skills/frontmatter.js.map +1 -1
- package/dist/core/terminal-control-grant.d.ts +74 -0
- package/dist/core/terminal-control-grant.d.ts.map +1 -0
- package/dist/core/terminal-control-grant.js +183 -0
- package/dist/core/terminal-control-grant.js.map +1 -0
- package/dist/core/terminal-proxy.d.ts.map +1 -1
- package/dist/core/terminal-proxy.js +4 -5
- package/dist/core/terminal-proxy.js.map +1 -1
- package/dist/core/terminal-write-auth.d.ts +4 -11
- package/dist/core/terminal-write-auth.d.ts.map +1 -1
- package/dist/core/terminal-write-auth.js +19 -16
- 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 +36 -29
- package/dist/core/trigger-session.js.map +1 -1
- package/dist/core/types.d.ts +88 -10
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +9 -7
- package/dist/core/types.js.map +1 -1
- package/dist/core/workbench-link.d.ts +81 -0
- package/dist/core/workbench-link.d.ts.map +1 -0
- package/dist/core/workbench-link.js +109 -0
- package/dist/core/workbench-link.js.map +1 -0
- package/dist/core/worker-pool.d.ts +312 -11
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +2515 -217
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts +6 -0
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +447 -116
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/aggregator.d.ts +33 -3
- package/dist/dashboard/aggregator.d.ts.map +1 -1
- package/dist/dashboard/aggregator.js +93 -17
- package/dist/dashboard/aggregator.js.map +1 -1
- package/dist/dashboard/auth-session-connections.d.ts +59 -0
- package/dist/dashboard/auth-session-connections.d.ts.map +1 -0
- package/dist/dashboard/auth-session-connections.js +109 -0
- package/dist/dashboard/auth-session-connections.js.map +1 -0
- package/dist/dashboard/auth.d.ts +99 -1
- package/dist/dashboard/auth.d.ts.map +1 -1
- package/dist/dashboard/auth.js +176 -64
- package/dist/dashboard/auth.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 +4 -0
- package/dist/dashboard/bot-payload.js.map +1 -1
- package/dist/dashboard/control-audit.d.ts +112 -0
- package/dist/dashboard/control-audit.d.ts.map +1 -0
- package/dist/dashboard/control-audit.js +195 -0
- package/dist/dashboard/control-audit.js.map +1 -0
- package/dist/dashboard/control-csrf.d.ts +123 -0
- package/dist/dashboard/control-csrf.d.ts.map +1 -0
- package/dist/dashboard/control-csrf.js +392 -0
- package/dist/dashboard/control-csrf.js.map +1 -0
- package/dist/dashboard/daemon-reconcile.d.ts +26 -0
- package/dist/dashboard/daemon-reconcile.d.ts.map +1 -0
- package/dist/dashboard/daemon-reconcile.js +46 -0
- package/dist/dashboard/daemon-reconcile.js.map +1 -0
- package/dist/dashboard/debug-terminal.d.ts.map +1 -1
- package/dist/dashboard/debug-terminal.js +18 -4
- package/dist/dashboard/debug-terminal.js.map +1 -1
- package/dist/dashboard/events-sse.d.ts +60 -0
- package/dist/dashboard/events-sse.d.ts.map +1 -0
- package/dist/dashboard/events-sse.js +63 -0
- package/dist/dashboard/events-sse.js.map +1 -0
- package/dist/dashboard/h5-auth.d.ts +256 -0
- package/dist/dashboard/h5-auth.d.ts.map +1 -0
- package/dist/dashboard/h5-auth.js +825 -0
- package/dist/dashboard/h5-auth.js.map +1 -0
- package/dist/dashboard/managed-spawn.d.ts +36 -0
- package/dist/dashboard/managed-spawn.d.ts.map +1 -0
- package/dist/dashboard/managed-spawn.js +169 -0
- package/dist/dashboard/managed-spawn.js.map +1 -0
- package/dist/dashboard/preview-content-capability.d.ts +41 -0
- package/dist/dashboard/preview-content-capability.d.ts.map +1 -0
- package/dist/dashboard/preview-content-capability.js +127 -0
- package/dist/dashboard/preview-content-capability.js.map +1 -0
- package/dist/dashboard/preview-contract.d.ts +85 -0
- package/dist/dashboard/preview-contract.d.ts.map +1 -0
- package/dist/dashboard/preview-contract.js +198 -0
- package/dist/dashboard/preview-contract.js.map +1 -0
- package/dist/dashboard/preview-guard-page.d.ts +52 -0
- package/dist/dashboard/preview-guard-page.d.ts.map +1 -0
- package/dist/dashboard/preview-guard-page.js +162 -0
- package/dist/dashboard/preview-guard-page.js.map +1 -0
- package/dist/dashboard/preview-interaction.d.ts +57 -0
- package/dist/dashboard/preview-interaction.d.ts.map +1 -0
- package/dist/dashboard/preview-interaction.js +198 -0
- package/dist/dashboard/preview-interaction.js.map +1 -0
- package/dist/dashboard/preview-proxy.d.ts +113 -0
- package/dist/dashboard/preview-proxy.d.ts.map +1 -0
- package/dist/dashboard/preview-proxy.js +543 -0
- package/dist/dashboard/preview-proxy.js.map +1 -0
- package/dist/dashboard/public-redact.d.ts +23 -0
- package/dist/dashboard/public-redact.d.ts.map +1 -1
- package/dist/dashboard/public-redact.js +90 -21
- package/dist/dashboard/public-redact.js.map +1 -1
- package/dist/dashboard/request-identity.d.ts +77 -0
- package/dist/dashboard/request-identity.d.ts.map +1 -0
- package/dist/dashboard/request-identity.js +72 -0
- package/dist/dashboard/request-identity.js.map +1 -0
- package/dist/dashboard/session-cleanup.d.ts +5 -0
- package/dist/dashboard/session-cleanup.d.ts.map +1 -1
- package/dist/dashboard/session-cleanup.js +4 -0
- package/dist/dashboard/session-cleanup.js.map +1 -1
- package/dist/dashboard/settings-write-applier.d.ts +5 -1
- package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
- package/dist/dashboard/settings-write-applier.js +14 -0
- package/dist/dashboard/settings-write-applier.js.map +1 -1
- package/dist/dashboard/standing-link.d.ts +76 -0
- package/dist/dashboard/standing-link.d.ts.map +1 -0
- package/dist/dashboard/standing-link.js +111 -0
- package/dist/dashboard/standing-link.js.map +1 -0
- package/dist/dashboard/terminal-control.d.ts +105 -0
- package/dist/dashboard/terminal-control.d.ts.map +1 -0
- package/dist/dashboard/terminal-control.js +296 -0
- package/dist/dashboard/terminal-control.js.map +1 -0
- package/dist/dashboard/terminal-front-proxy.d.ts +55 -0
- package/dist/dashboard/terminal-front-proxy.d.ts.map +1 -0
- package/dist/dashboard/terminal-front-proxy.js +397 -0
- package/dist/dashboard/terminal-front-proxy.js.map +1 -0
- package/dist/dashboard/terminal-view-capability.d.ts +97 -0
- package/dist/dashboard/terminal-view-capability.d.ts.map +1 -0
- package/dist/dashboard/terminal-view-capability.js +145 -0
- package/dist/dashboard/terminal-view-capability.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-api.d.ts +59 -0
- package/dist/dashboard/web/agent-workbench-api.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-api.js +227 -0
- package/dist/dashboard/web/agent-workbench-api.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-appearance-menu.d.ts +59 -0
- package/dist/dashboard/web/agent-workbench-appearance-menu.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-appearance-menu.js +195 -0
- package/dist/dashboard/web/agent-workbench-appearance-menu.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-appearance.d.ts +222 -0
- package/dist/dashboard/web/agent-workbench-appearance.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-appearance.js +499 -0
- package/dist/dashboard/web/agent-workbench-appearance.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-capabilities.d.ts +13 -0
- package/dist/dashboard/web/agent-workbench-capabilities.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-capabilities.js +24 -0
- package/dist/dashboard/web/agent-workbench-capabilities.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-chat.d.ts +90 -0
- package/dist/dashboard/web/agent-workbench-chat.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-chat.js +168 -0
- package/dist/dashboard/web/agent-workbench-chat.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-dock-page.d.ts +3 -0
- package/dist/dashboard/web/agent-workbench-dock-page.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-dock-page.js +23 -0
- package/dist/dashboard/web/agent-workbench-dock-page.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-dock-view.d.ts +22 -0
- package/dist/dashboard/web/agent-workbench-dock-view.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-dock-view.js +76 -0
- package/dist/dashboard/web/agent-workbench-dock-view.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-model.d.ts +196 -0
- package/dist/dashboard/web/agent-workbench-model.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-model.js +529 -0
- package/dist/dashboard/web/agent-workbench-model.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-page.d.ts +3 -0
- package/dist/dashboard/web/agent-workbench-page.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-page.js +27 -0
- package/dist/dashboard/web/agent-workbench-page.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-panes.d.ts +49 -0
- package/dist/dashboard/web/agent-workbench-panes.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-panes.js +468 -0
- package/dist/dashboard/web/agent-workbench-panes.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-session-list.d.ts +42 -0
- package/dist/dashboard/web/agent-workbench-session-list.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-session-list.js +353 -0
- package/dist/dashboard/web/agent-workbench-session-list.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-storage.d.ts +49 -0
- package/dist/dashboard/web/agent-workbench-storage.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-storage.js +197 -0
- package/dist/dashboard/web/agent-workbench-storage.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-touch.d.ts +46 -0
- package/dist/dashboard/web/agent-workbench-touch.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-touch.js +96 -0
- package/dist/dashboard/web/agent-workbench-touch.js.map +1 -0
- package/dist/dashboard/web/agent-workbench-view.d.ts +34 -0
- package/dist/dashboard/web/agent-workbench-view.d.ts.map +1 -0
- package/dist/dashboard/web/agent-workbench-view.js +439 -0
- package/dist/dashboard/web/agent-workbench-view.js.map +1 -0
- package/dist/dashboard/web/app.d.ts.map +1 -1
- package/dist/dashboard/web/app.js +63 -2
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts +18 -0
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.js +362 -36
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts +8 -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/control-csrf.d.ts +4 -0
- package/dist/dashboard/web/control-csrf.d.ts.map +1 -0
- package/dist/dashboard/web/control-csrf.js +26 -0
- package/dist/dashboard/web/control-csrf.js.map +1 -0
- package/dist/dashboard/web/dashboard-routes.d.ts.map +1 -1
- package/dist/dashboard/web/dashboard-routes.js +2 -0
- package/dist/dashboard/web/dashboard-routes.js.map +1 -1
- package/dist/dashboard/web/groups-page.d.ts.map +1 -1
- package/dist/dashboard/web/groups-page.js +11 -2
- package/dist/dashboard/web/groups-page.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +140 -6
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/overview-page.d.ts.map +1 -1
- package/dist/dashboard/web/overview-page.js +3 -2
- package/dist/dashboard/web/overview-page.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-page.js +41 -1
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +5 -1
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/settings-page.d.ts +3 -0
- package/dist/dashboard/web/settings-page.d.ts.map +1 -1
- package/dist/dashboard/web/settings-page.js +56 -10
- package/dist/dashboard/web/settings-page.js.map +1 -1
- package/dist/dashboard/web/skills-page.d.ts.map +1 -1
- package/dist/dashboard/web/skills-page.js +4 -2
- package/dist/dashboard/web/skills-page.js.map +1 -1
- package/dist/dashboard/web/store.d.ts +27 -2
- package/dist/dashboard/web/store.d.ts.map +1 -1
- package/dist/dashboard/web/store.js +43 -4
- package/dist/dashboard/web/store.js.map +1 -1
- package/dist/dashboard/web/ui.d.ts +3 -0
- package/dist/dashboard/web/ui.d.ts.map +1 -1
- package/dist/dashboard/web/ui.js +11 -0
- package/dist/dashboard/web/ui.js.map +1 -1
- package/dist/dashboard/web/update-action.d.ts +12 -0
- package/dist/dashboard/web/update-action.d.ts.map +1 -1
- package/dist/dashboard/web/update-action.js +11 -0
- package/dist/dashboard/web/update-action.js.map +1 -1
- package/dist/dashboard/workbench-doctor.d.ts +114 -0
- package/dist/dashboard/workbench-doctor.d.ts.map +1 -0
- package/dist/dashboard/workbench-doctor.js +620 -0
- package/dist/dashboard/workbench-doctor.js.map +1 -0
- package/dist/dashboard/workbench-ticket.d.ts +165 -0
- package/dist/dashboard/workbench-ticket.d.ts.map +1 -0
- package/dist/dashboard/workbench-ticket.js +495 -0
- package/dist/dashboard/workbench-ticket.js.map +1 -0
- package/dist/dashboard-web/app.js +1 -1
- package/dist/dashboard-web/chunks/agent-workbench-dock-page-IKAC5CFL.js +1 -0
- package/dist/dashboard-web/chunks/agent-workbench-page-M53UN5EB.js +1 -0
- package/dist/dashboard-web/chunks/bot-defaults-page-YKE5SDZF.js +10 -0
- package/dist/dashboard-web/chunks/chunk-22WIADUT.js +2 -0
- package/dist/dashboard-web/chunks/chunk-24ONYQMR.js +1 -0
- package/dist/dashboard-web/chunks/{chunk-6O7KXFD2.js → chunk-2W6SCN3M.js} +1 -1
- package/dist/dashboard-web/chunks/chunk-4XNJX6B3.js +1 -0
- package/dist/dashboard-web/chunks/{chunk-Q2MT4VWH.js → chunk-F6KNPF4R.js} +11 -9
- package/dist/dashboard-web/chunks/chunk-FXW3V4JR.js +1 -0
- package/dist/dashboard-web/chunks/chunk-G5ZS2YUS.js +1 -0
- package/dist/dashboard-web/chunks/chunk-KTQ7B6ZR.js +1 -0
- package/dist/dashboard-web/chunks/{chunk-U3ZFSO7E.js → chunk-NACP7BMR.js} +1 -1
- package/dist/dashboard-web/chunks/{connectors-page-2KZO5KSJ.js → connectors-page-VOISXXII.js} +1 -1
- package/dist/dashboard-web/chunks/{feedback-page-CLVTOLLO.js → feedback-page-RN6HRZMS.js} +1 -1
- package/dist/dashboard-web/chunks/groups-page-UQT6DCB7.js +8 -0
- package/dist/dashboard-web/chunks/{insights-page-4RPU2CRU.js → insights-page-HJFDYR5N.js} +3 -3
- package/dist/dashboard-web/chunks/{monitor-room-OTKQ2CXK.js → monitor-room-V7PCP47V.js} +1 -1
- package/dist/dashboard-web/chunks/{monitoring-page-IJPUB6JT.js → monitoring-page-NKEKVQAP.js} +1 -1
- package/dist/dashboard-web/chunks/{office-page-QSR3J44Y.js → office-page-GVJF73XW.js} +1 -1
- package/dist/dashboard-web/chunks/overview-page-KHLV6VTI.js +1 -0
- package/dist/dashboard-web/chunks/{plugin-page-VEGTCEAS.js → plugin-page-J3OF5IY4.js} +1 -1
- package/dist/dashboard-web/chunks/{roles-page-6NWJMOB5.js → roles-page-WQIRSOLZ.js} +1 -1
- package/dist/dashboard-web/chunks/{schedules-page-6I3LNXD4.js → schedules-page-J2DEY2X6.js} +1 -1
- package/dist/dashboard-web/chunks/sessions-page-7BQFEA5P.js +8 -0
- package/dist/dashboard-web/chunks/settings-page-BJEIOFJH.js +2 -0
- package/dist/dashboard-web/chunks/{skills-page-M2Q6L5CB.js → skills-page-HGIFR3IU.js} +2 -2
- package/dist/dashboard-web/chunks/{team-federation-page-7I7FDE3B.js → team-federation-page-MR5ZPL4B.js} +1 -1
- package/dist/dashboard-web/chunks/{v3-page-HQXRL65L.js → v3-page-GBR5JWPE.js} +2 -2
- package/dist/dashboard-web/chunks/{whiteboards-page-LQKC4TAZ.js → whiteboards-page-QAZM4BN3.js} +1 -1
- package/dist/dashboard-web/index.html +8 -1
- package/dist/dashboard-web/style.css +2006 -10
- package/dist/dashboard.js +1017 -264
- package/dist/dashboard.js.map +1 -1
- package/dist/dsh-runner.js +8 -1
- package/dist/dsh-runner.js.map +1 -1
- package/dist/global-config.d.ts +30 -0
- package/dist/global-config.d.ts.map +1 -1
- package/dist/global-config.js +33 -0
- package/dist/global-config.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +46 -27
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +43 -27
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts +1 -1
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +22 -6
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +118 -24
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +15 -0
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +30 -0
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +48 -0
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +138 -41
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/identity-cache.d.ts +14 -6
- package/dist/im/lark/identity-cache.d.ts.map +1 -1
- package/dist/im/lark/identity-cache.js +69 -26
- package/dist/im/lark/identity-cache.js.map +1 -1
- package/dist/im/lark/lark-hosts.d.ts +13 -0
- package/dist/im/lark/lark-hosts.d.ts.map +1 -1
- package/dist/im/lark/lark-hosts.js +16 -0
- package/dist/im/lark/lark-hosts.js.map +1 -1
- package/dist/im/lark/overview-card.d.ts +22 -0
- package/dist/im/lark/overview-card.d.ts.map +1 -1
- package/dist/im/lark/overview-card.js +53 -3
- package/dist/im/lark/overview-card.js.map +1 -1
- package/dist/im/lark/sessions-card.d.ts.map +1 -1
- package/dist/im/lark/sessions-card.js +26 -3
- package/dist/im/lark/sessions-card.js.map +1 -1
- package/dist/im/lark/workflow-slash-command.d.ts +6 -0
- package/dist/im/lark/workflow-slash-command.d.ts.map +1 -1
- package/dist/im/lark/workflow-slash-command.js +7 -0
- package/dist/im/lark/workflow-slash-command.js.map +1 -1
- package/dist/index-daemon.js +27 -4
- package/dist/index-daemon.js.map +1 -1
- package/dist/index-dashboard.d.ts +3 -0
- package/dist/index-dashboard.d.ts.map +1 -0
- package/dist/index-dashboard.js +94 -0
- package/dist/index-dashboard.js.map +1 -0
- package/dist/platform/team-agents-client.d.ts +199 -0
- package/dist/platform/team-agents-client.d.ts.map +1 -0
- package/dist/platform/team-agents-client.js +263 -0
- package/dist/platform/team-agents-client.js.map +1 -0
- package/dist/platform/tunnel-client.d.ts +6 -0
- package/dist/platform/tunnel-client.d.ts.map +1 -1
- package/dist/platform/tunnel-client.js.map +1 -1
- package/dist/services/async-trigger-state.d.ts +7 -3
- package/dist/services/async-trigger-state.d.ts.map +1 -1
- package/dist/services/async-trigger-state.js +28 -0
- package/dist/services/async-trigger-state.js.map +1 -1
- package/dist/services/async-trigger-store.d.ts +13 -4
- package/dist/services/async-trigger-store.d.ts.map +1 -1
- package/dist/services/async-trigger-store.js +55 -8
- package/dist/services/async-trigger-store.js.map +1 -1
- package/dist/services/bot-config-store.d.ts +1 -11
- package/dist/services/bot-config-store.d.ts.map +1 -1
- package/dist/services/bot-config-store.js +27 -3
- package/dist/services/bot-config-store.js.map +1 -1
- package/dist/services/bot-profile-store.d.ts +17 -2
- package/dist/services/bot-profile-store.d.ts.map +1 -1
- package/dist/services/bot-profile-store.js +93 -12
- package/dist/services/bot-profile-store.js.map +1 -1
- package/dist/services/bridge-fallback-gate.d.ts +15 -7
- package/dist/services/bridge-fallback-gate.d.ts.map +1 -1
- package/dist/services/bridge-fallback-gate.js +43 -16
- package/dist/services/bridge-fallback-gate.js.map +1 -1
- package/dist/services/bridge-turn-queue.d.ts +10 -1
- package/dist/services/bridge-turn-queue.d.ts.map +1 -1
- package/dist/services/bridge-turn-queue.js +29 -9
- package/dist/services/bridge-turn-queue.js.map +1 -1
- package/dist/services/claude-transcript.d.ts +19 -0
- package/dist/services/claude-transcript.d.ts.map +1 -1
- package/dist/services/claude-transcript.js +57 -5
- package/dist/services/claude-transcript.js.map +1 -1
- package/dist/services/codex-app-threads.d.ts +2 -0
- package/dist/services/codex-app-threads.d.ts.map +1 -1
- package/dist/services/codex-app-threads.js +1 -1
- package/dist/services/codex-app-threads.js.map +1 -1
- package/dist/services/codex-reasoning-effort.d.ts +8 -0
- package/dist/services/codex-reasoning-effort.d.ts.map +1 -1
- package/dist/services/codex-reasoning-effort.js +24 -0
- package/dist/services/codex-reasoning-effort.js.map +1 -1
- package/dist/services/cursor-resume-policy.d.ts.map +1 -1
- package/dist/services/cursor-resume-policy.js +15 -3
- package/dist/services/cursor-resume-policy.js.map +1 -1
- package/dist/services/open-platform-rename.d.ts.map +1 -1
- package/dist/services/open-platform-rename.js +3 -2
- package/dist/services/open-platform-rename.js.map +1 -1
- package/dist/services/ordinary-turn-recovery.d.ts +76 -0
- package/dist/services/ordinary-turn-recovery.d.ts.map +1 -0
- package/dist/services/ordinary-turn-recovery.js +349 -0
- package/dist/services/ordinary-turn-recovery.js.map +1 -0
- package/dist/services/peer-cross-ref-store.d.ts +8 -0
- package/dist/services/peer-cross-ref-store.d.ts.map +1 -0
- package/dist/services/peer-cross-ref-store.js +95 -0
- package/dist/services/peer-cross-ref-store.js.map +1 -0
- package/dist/services/pi-transcript.d.ts.map +1 -1
- package/dist/services/pi-transcript.js +10 -6
- package/dist/services/pi-transcript.js.map +1 -1
- package/dist/services/resume-fresh-policy.d.ts +17 -0
- package/dist/services/resume-fresh-policy.d.ts.map +1 -0
- package/dist/services/resume-fresh-policy.js +24 -0
- package/dist/services/resume-fresh-policy.js.map +1 -0
- package/dist/services/session-group-title.d.ts +1 -0
- package/dist/services/session-group-title.d.ts.map +1 -1
- package/dist/services/session-group-title.js +16 -1
- package/dist/services/session-group-title.js.map +1 -1
- package/dist/services/session-groups-store.d.ts +30 -0
- package/dist/services/session-groups-store.d.ts.map +1 -1
- package/dist/services/session-groups-store.js +26 -4
- package/dist/services/session-groups-store.js.map +1 -1
- package/dist/services/session-owner-notification.d.ts +9 -0
- package/dist/services/session-owner-notification.d.ts.map +1 -0
- package/dist/services/session-owner-notification.js +10 -0
- package/dist/services/session-owner-notification.js.map +1 -0
- package/dist/services/session-owner-reminder-config-store.d.ts +9 -0
- package/dist/services/session-owner-reminder-config-store.d.ts.map +1 -0
- package/dist/services/session-owner-reminder-config-store.js +24 -0
- package/dist/services/session-owner-reminder-config-store.js.map +1 -0
- package/dist/services/session-owner-reminder-store.d.ts +5 -0
- package/dist/services/session-owner-reminder-store.d.ts.map +1 -0
- package/dist/services/session-owner-reminder-store.js +54 -0
- package/dist/services/session-owner-reminder-store.js.map +1 -0
- package/dist/services/session-store.d.ts +98 -21
- package/dist/services/session-store.d.ts.map +1 -1
- package/dist/services/session-store.js +406 -48
- package/dist/services/session-store.js.map +1 -1
- package/dist/services/structured-bridge-clis.d.ts +15 -2
- package/dist/services/structured-bridge-clis.d.ts.map +1 -1
- package/dist/services/structured-bridge-clis.js +16 -1
- package/dist/services/structured-bridge-clis.js.map +1 -1
- package/dist/services/transcript-resolver.d.ts +1 -1
- package/dist/services/transcript-resolver.d.ts.map +1 -1
- package/dist/services/transcript-resolver.js +6 -1
- package/dist/services/transcript-resolver.js.map +1 -1
- package/dist/setup/bot-config-editor.d.ts.map +1 -1
- package/dist/setup/bot-config-editor.js +7 -2
- package/dist/setup/bot-config-editor.js.map +1 -1
- package/dist/setup/ensure-herdr-integrations.d.ts +13 -0
- package/dist/setup/ensure-herdr-integrations.d.ts.map +1 -1
- package/dist/setup/ensure-herdr-integrations.js +21 -3
- package/dist/setup/ensure-herdr-integrations.js.map +1 -1
- package/dist/setup/open-platform-automation.d.ts +1 -0
- package/dist/setup/open-platform-automation.d.ts.map +1 -1
- package/dist/setup/open-platform-automation.js +107 -7
- package/dist/setup/open-platform-automation.js.map +1 -1
- package/dist/skills/definitions.d.ts +17 -0
- package/dist/skills/definitions.d.ts.map +1 -1
- package/dist/skills/definitions.js +78 -8
- package/dist/skills/definitions.js.map +1 -1
- package/dist/skills/injection-mode.d.ts +24 -3
- package/dist/skills/injection-mode.d.ts.map +1 -1
- package/dist/skills/injection-mode.js +64 -15
- package/dist/skills/injection-mode.js.map +1 -1
- package/dist/skills/installer.d.ts +18 -0
- package/dist/skills/installer.d.ts.map +1 -1
- package/dist/skills/installer.js +45 -1
- package/dist/skills/installer.js.map +1 -1
- package/dist/types.d.ts +222 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/bot-routing.d.ts +1 -1
- package/dist/utils/bot-routing.d.ts.map +1 -1
- package/dist/utils/bot-routing.js.map +1 -1
- package/dist/utils/child-env.d.ts +92 -2
- package/dist/utils/child-env.d.ts.map +1 -1
- package/dist/utils/child-env.js +195 -1
- package/dist/utils/child-env.js.map +1 -1
- package/dist/utils/cli-usage-limit.d.ts +25 -14
- package/dist/utils/cli-usage-limit.d.ts.map +1 -1
- package/dist/utils/cli-usage-limit.js +25 -15
- package/dist/utils/cli-usage-limit.js.map +1 -1
- package/dist/utils/daemon-rejection-guard.d.ts +35 -0
- package/dist/utils/daemon-rejection-guard.d.ts.map +1 -0
- package/dist/utils/daemon-rejection-guard.js +101 -0
- package/dist/utils/daemon-rejection-guard.js.map +1 -0
- package/dist/utils/dashboard-env.d.ts +53 -0
- package/dist/utils/dashboard-env.d.ts.map +1 -0
- package/dist/utils/dashboard-env.js +116 -0
- package/dist/utils/dashboard-env.js.map +1 -0
- package/dist/utils/global-install.d.ts.map +1 -1
- package/dist/utils/global-install.js +61 -5
- package/dist/utils/global-install.js.map +1 -1
- package/dist/utils/install-diagnostics.d.ts +14 -7
- package/dist/utils/install-diagnostics.d.ts.map +1 -1
- package/dist/utils/install-diagnostics.js +20 -11
- package/dist/utils/install-diagnostics.js.map +1 -1
- package/dist/utils/local-dev-update.d.ts +132 -0
- package/dist/utils/local-dev-update.d.ts.map +1 -0
- package/dist/utils/local-dev-update.js +176 -0
- package/dist/utils/local-dev-update.js.map +1 -0
- package/dist/utils/pending-input-queue.d.ts +12 -1
- package/dist/utils/pending-input-queue.d.ts.map +1 -1
- package/dist/utils/pending-input-queue.js.map +1 -1
- package/dist/worker.js +1517 -236
- package/dist/worker.js.map +1 -1
- package/dist/workflows/definition.d.ts +68 -68
- package/dist/workflows/events/payloads.d.ts +14 -14
- package/dist/workflows/events/schema.d.ts +312 -312
- package/dist/workflows/migration/v2-run-archive-schema.d.ts +40 -40
- package/dist/workflows/v3/cli-run.d.ts.map +1 -1
- package/dist/workflows/v3/cli-run.js +7 -0
- package/dist/workflows/v3/cli-run.js.map +1 -1
- package/dist/workflows/v3/goal-cli.d.ts +3 -0
- package/dist/workflows/v3/goal-cli.d.ts.map +1 -1
- package/dist/workflows/v3/goal-cli.js +11 -0
- package/dist/workflows/v3/goal-cli.js.map +1 -1
- package/dist/workflows/v3/run-envelope.d.ts +144 -144
- package/package.json +7 -2
- package/dist/cli/pm2-god-admission.d.ts +0 -8
- package/dist/cli/pm2-god-admission.d.ts.map +0 -1
- package/dist/cli/pm2-god-admission.js +0 -25
- package/dist/cli/pm2-god-admission.js.map +0 -1
- package/dist/core/riff-shutdown-detach.d.ts.map +0 -1
- package/dist/core/riff-shutdown-detach.js.map +0 -1
- package/dist/core/riff-worker-shutdown-readiness.d.ts.map +0 -1
- package/dist/core/riff-worker-shutdown-readiness.js.map +0 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-4RENHE7J.js +0 -10
- package/dist/dashboard-web/chunks/chunk-2WQDS65D.js +0 -1
- package/dist/dashboard-web/chunks/chunk-G5XGBCM6.js +0 -1
- package/dist/dashboard-web/chunks/chunk-WLIVBPJC.js +0 -1
- package/dist/dashboard-web/chunks/groups-page-HLASRTSY.js +0 -8
- package/dist/dashboard-web/chunks/overview-page-6OK63V4V.js +0 -1
- package/dist/dashboard-web/chunks/sessions-page-B2TXGJDO.js +0 -8
- package/dist/dashboard-web/chunks/settings-page-6KJADSC6.js +0 -2
package/dist/daemon.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
2
|
import { createHash, randomUUID } from 'node:crypto';
|
|
3
3
|
import { readFileSync, existsSync, mkdirSync, unlinkSync } from 'node:fs';
|
|
4
|
+
import { installDaemonRejectionGuard } from './utils/daemon-rejection-guard.js';
|
|
4
5
|
import { atomicWriteFileSync } from './utils/atomic-write.js';
|
|
6
|
+
import { readPeerCrossRef } from './services/peer-cross-ref-store.js';
|
|
5
7
|
import { readAllowedUsersResolveCache, writeAllowedUsersResolveCache } from './utils/allowed-users-cache.js';
|
|
6
8
|
import { join, dirname } from 'node:path';
|
|
7
9
|
import { homedir, loadavg, cpus, totalmem, freemem } from 'node:os';
|
|
@@ -9,7 +11,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
9
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
12
|
const __dirname = dirname(__filename);
|
|
11
13
|
import { config, getDashboardExternalHost, isVcMeetingAgentGloballyEnabled, vcMeetingAgentGlobalListenerBotAppId, } from './config.js';
|
|
12
|
-
import { readGlobalConfig, repoPickerScanOptions } from './global-config.js';
|
|
14
|
+
import { readGlobalConfig, repoPickerScanOptions, isWorkflowFeatureEnabled } from './global-config.js';
|
|
13
15
|
import { buildDashboardUrls } from './core/dashboard-url.js';
|
|
14
16
|
import { resolveBotmuxDataDir } from './core/data-dir.js';
|
|
15
17
|
import { reloadExactDaemonBotConfig } from './core/daemon-config-fence.js';
|
|
@@ -63,6 +65,15 @@ import { scrubTmuxServerGlobalEnv } from './setup/ensure-tmux.js';
|
|
|
63
65
|
import { entryNeedsContactResolve } from './setup/bot-config-editor.js';
|
|
64
66
|
import { invalidWorkingDirs } from './utils/working-dir.js';
|
|
65
67
|
import { validateWorkingDir } from './core/working-dir.js';
|
|
68
|
+
function trustedCallerForTurn(larkAppId, senderOpenId, senderUnionId) {
|
|
69
|
+
if (!senderOpenId && !senderUnionId)
|
|
70
|
+
return undefined;
|
|
71
|
+
return {
|
|
72
|
+
...(senderOpenId ? { requestUserOpenId: senderOpenId } : {}),
|
|
73
|
+
...(senderUnionId ? { requestUserUnionId: senderUnionId } : {}),
|
|
74
|
+
requestLarkAppId: larkAppId,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
66
77
|
import { activeSessionKey, sessionKey, sessionAnchorId, storedSessionAnchorId, larkTransportEnabled, } from './core/types.js';
|
|
67
78
|
import { stagePendingRepoSetup, persistPendingRepoCardMessageId } from './core/pending-repo-journal.js';
|
|
68
79
|
import { setTerminalProxyPort, setTerminalExternalPort } from './core/terminal-url.js';
|
|
@@ -77,10 +88,11 @@ import { isLocalCliOpenReady } from './services/local-cli-opener.js';
|
|
|
77
88
|
import { RECEIVED_REACTION_EMOJI_TYPE, SUBSTITUTE_RECEIVED_REACTION_EMOJI_TYPE } from './core/pending-response.js';
|
|
78
89
|
import { t as tr, localeForBot } from './i18n/index.js';
|
|
79
90
|
import { createCliAdapterSync } from './adapters/cli/registry.js';
|
|
80
|
-
import { initWorkerPool, setActiveSessionsRegistry, forkWorker, forkAdoptWorker, sendWorkerInput, promoteQueuedActivationTail, admitQueuedActivationTail, reserveQueuedActivationTailAdmission, codexAppCleanInputAcceptedForSession, hasQueuedActivationAdmissionGate, sendWorkerSessionInput, killWorker, reapOrphanWorkers, scheduleCardPatch, setCurrentCliVersion, getCurrentCliVersion, CARD_POSTING_SENTINEL, parkStreamCard, closeSession as closeSessionHelper, setActiveSessionIfActive, rollbackRejectedSessionAndGetWinner, ensureCliEnv, sweepGlobalBotmuxSkills, writableTerminalLinkFor, workerHasInitialized, sessionSupportsWebTerminal, readableTerminalUrlFor, findActiveBySessionId, withActiveSessionKeyLock, getDaemonBootId, getDaemonStreamingCardUsageSnapshot, postTurnStartingCard, isSessionTransferring, snapshotCodexAppFinalSettlements, codexAppFinalSettlementCount, } from './core/worker-pool.js';
|
|
91
|
+
import { initWorkerPool, setActiveSessionsRegistry, forkWorker, forkAdoptWorker, sendWorkerInput, promoteQueuedActivationTail, admitQueuedActivationTail, reserveQueuedActivationTailAdmission, codexAppCleanInputAcceptedForSession, hasQueuedActivationAdmissionGate, sendWorkerSessionInput, killWorker, retireWorkerProcessOnly, retiringWorkersForSession, reapOrphanWorkers, scheduleCardPatch, setCurrentCliVersion, getCurrentCliVersion, CARD_POSTING_SENTINEL, parkStreamCard, closeSession as closeSessionHelper, closeSessionForBackgroundCleanup, setActiveSessionIfActive, rollbackRejectedSessionAndGetWinner, ensureCliEnv, sweepGlobalBotmuxSkills, writableTerminalLinkFor, workerHasInitialized, sessionSupportsWebTerminal, readableTerminalUrlFor, findActiveBySessionId, withActiveSessionKeyLock, getDaemonBootId, getDaemonStreamingCardUsageSnapshot, postTurnStartingCard, isSessionTransferring, snapshotCodexAppFinalSettlements, codexAppFinalSettlementCount, migrateMojoSessionIdentities, mojoLivePatchForSession, } from './core/worker-pool.js';
|
|
81
92
|
import { waitAllWithin, trackProducerQuiet, trackProcessExited } from './core/producer-quiescence.js';
|
|
82
93
|
import { AbortDeadlineError, hasExactSafeJsonKeys, ipcRoute, isTrustedHostIpcRequest, JsonBodyTooLargeError, jsonRes, readJsonBody, runWithAbortDeadline, setBotName, setLarkAppId, startIpcServer, setBotRenamer, setBotAvatarChanger, armCoreOnlyReadinessGate, setCoreOnlyReady, setSupervisorShutdownHandler } from './core/dashboard-ipc-server.js';
|
|
83
94
|
import { setDeviceIsolationDaemonIdentity } from './core/device-isolation-daemon.js';
|
|
95
|
+
import { reconcileContainmentHandlesOnBoot } from './core/mojo-containment.js';
|
|
84
96
|
import { cancelSessionReadyAck, waitForSessionReadyAck, } from './core/session-ready-handshake.js';
|
|
85
97
|
import { loadOrCreateDashboardSecret, loadPersistedToken } from './dashboard/auth.js';
|
|
86
98
|
import { daemonIpcAuthHeaders, fetchDaemonIpc, loadDaemonIpcSecret } from './core/daemon-ipc-auth.js';
|
|
@@ -98,6 +110,7 @@ import { consumeQuota, removeChatGrant, removeGlobalGrant } from './services/gra
|
|
|
98
110
|
import { abortCharge, commitCharge, beginCharge } from './services/quota-dedup.js';
|
|
99
111
|
import { getSessionWorkingDir, getProjectScanDirs, getProjectScanDirsForBot, expandHome, downloadResources, formatAttachmentsHint, buildNewTopicCliInput, buildFollowUpCliInput, buildBridgeInputContent, buildReforkCliInput, getAvailableBots, restoreActiveSessions, executeScheduledTask, persistStreamCardState, rememberLastCliInput, ensureTerminalWorkerPort, ensureSessionWhiteboard, resumeSession, closeCliMismatchedSessionsForBot, } from './core/session-manager.js';
|
|
100
112
|
import { triggerSessionTurn, reconcileIdempotencyLeasesOnBoot, convergeIdempotentAsyncTurnOnWorkerExit, externalEventOpensOwnTopic } from './core/trigger-session.js';
|
|
113
|
+
import { runIdempotencyFailClose, runWithdrawAutoClose, } from './core/daemon-background-close.js';
|
|
101
114
|
import { runDetachedBotTurnMutation, tryWithBotTurnMutation, withBotTurnAdmission, withBotTurnMutation, } from './core/bot-turn-mutation-gate.js';
|
|
102
115
|
import { claimInitialUserTurn, isInitialUserTurnPending, releaseInitialUserTurn } from './core/initial-user-turn.js';
|
|
103
116
|
import { applyQueuedCodexAppLegacyFallback, mergeQueuedCodexAppTurn } from './core/session-create.js';
|
|
@@ -113,11 +126,14 @@ import { HerdrBackend } from './adapters/backend/herdr-backend.js';
|
|
|
113
126
|
import { ZellijBackend } from './adapters/backend/zellij-backend.js';
|
|
114
127
|
import { ZmxBackend } from './adapters/backend/zmx-backend.js';
|
|
115
128
|
import { sweepIdleWorkersAfterTurnDrain, DEFAULT_MAX_LIVE_WORKERS } from './core/idle-worker-sweeper.js';
|
|
116
|
-
import {
|
|
129
|
+
import { DEFAULT_SESSION_OWNER_REMINDER, SessionOwnerReminderController, } from './core/session-owner-reminder.js';
|
|
130
|
+
import { loadSessionOwnerReminderRecords, saveSessionOwnerReminderRecords, } from './services/session-owner-reminder-store.js';
|
|
131
|
+
import { sendSessionOwnerThreadNotification } from './services/session-owner-notification.js';
|
|
132
|
+
import { getSessionPersistentBackendType, isRemoteBackendSession, killPersistentBackendTarget, killPersistentSession, probePersistentBackendTarget, probePersistentSession, resolvePersistentBackendTarget, resolvePairedSpawnBackendType, } from './core/persistent-backend.js';
|
|
117
133
|
import { handleCardAction, runAutoWorktreeCommit } from './im/lark/card-handler.js';
|
|
118
134
|
import { setIssueActivate } from './im/lark/issue-command-deps.js';
|
|
119
135
|
import { startIssueOutboxPump } from './services/issue-outbox-pump.js';
|
|
120
|
-
import { parseWorkflowGrillTrigger, buildWorkflowGrillPrompt, isLegacyTemplateCommand, LEGACY_TEMPLATE_RETIRED_MESSAGE, WORKFLOW_USAGE, } from './im/lark/workflow-slash-command.js';
|
|
136
|
+
import { parseWorkflowGrillTrigger, buildWorkflowGrillPrompt, isLegacyTemplateCommand, LEGACY_TEMPLATE_RETIRED_MESSAGE, WORKFLOW_USAGE, WORKFLOW_DISABLED_MESSAGE, } from './im/lark/workflow-slash-command.js';
|
|
121
137
|
import { parseV3SavedWorkflowCommand, v3SavedWorkflowUsage, } from './im/lark/v3-saved-workflow-command.js';
|
|
122
138
|
import { authorizeV3SavedWorkflowInvocation, defaultV3SavedWorkflowExecutionServices, deliverV3SavedWorkflowNotification, executeV3SavedWorkflowCommand, resolveV3SavedWorkflowMessageTargets, } from './im/lark/v3-saved-workflow-handler.js';
|
|
123
139
|
import { createV3GateRunner, preflightV3RunStart, readV3RunChatBinding, requestV3RunCancel, requestV3Retry, requestV3LoopGrant, } from './workflows/v3/daemon-run.js';
|
|
@@ -172,7 +188,7 @@ function republishResolvedAllowedUsers(larkAppId, resolved) {
|
|
|
172
188
|
catch { /* best effort */ }
|
|
173
189
|
}
|
|
174
190
|
let vcMeetingTerminalReconciler;
|
|
175
|
-
import { isBotMentioned, probeBotOpenId, startLarkEventDispatcher, markForwardFollowupsSessionsReady, writeBotInfoFile, canOperate, canRunDaemonCommand, evaluateTalk, evaluateBotTalk, evaluateAskAnswerTalk, grantCommandRestriction, isKnownPeerBot, checkRequiredScopes } from './im/lark/event-dispatcher.js';
|
|
191
|
+
import { isBotMentioned, probeBotOpenId, startLarkEventDispatcher, markForwardFollowupsSessionsReady, writeBotInfoFile, canOperate, canRunDaemonCommand, evaluateTalk, evaluateBotTalk, evaluateAskAnswerTalk, askCustomReplyCandidate, grantCommandRestriction, isKnownPeerBot, checkRequiredScopes } from './im/lark/event-dispatcher.js';
|
|
176
192
|
import { getDocSubscription, listAllDocSubscriptions, putDocSubscription, removeDocSubscription, setDocCommentPollCursor } from './services/doc-subs-store.js';
|
|
177
193
|
import { BOT_REPLY_SENTINEL, subscribeDocFile, unsubscribeDocFile, addCommentReaction, removeCommentReaction, hasBotSentinel, isBotAuthoredReply, listDocComments } from './im/lark/doc-comment.js';
|
|
178
194
|
import { learnFromMentions, resolveSender, flushIdentityCacheSync } from './im/lark/identity-cache.js';
|
|
@@ -181,7 +197,7 @@ import { buildDocCommentTurnInput, buildDocWatchWarmupTurnInput } from './core/d
|
|
|
181
197
|
import { advanceDocCommentCursor, docCommentRepliesAfterCursor, latestDocCommentPollCursor } from './core/doc-comment-poller.js';
|
|
182
198
|
import { renderBufferedSenderBlock } from './core/session-manager.js';
|
|
183
199
|
import { shutdownBackendDisposition } from './core/persistent-backend.js';
|
|
184
|
-
import {
|
|
200
|
+
import { abortRemoteShutdownFleet, canAbortVerifiedExitedRemotePreparation, collectUniqueDaemonShutdownSessions, commitPreparedRemoteShutdown, isPreparedRemoteSessionCurrent, persistPreparedRemoteShutdownFleet, prepareRemoteFleetForShutdown, } from './core/remote-shutdown-detach.js';
|
|
185
201
|
import { BOT_TURN_MUTATION_SHUTDOWN_ACQUIRE_TIMEOUT_MS, DAEMON_SHUTDOWN_MAX_MS, DAEMON_WORKER_EXIT_GRACE_MS, } from './core/shutdown-budgets.js';
|
|
186
202
|
import { evaluateVcMeetingConsumerIsolation } from './services/vc-meeting-consumer-isolation.js';
|
|
187
203
|
import { markSessionActivity, announcePendingRepoSession, publishAttentionPatch, publishLastInputFromBotPatch, publishSessionMessagePreviewPatch, publishClosedSessionPatch, clearAgentAttention, } from './core/session-activity.js';
|
|
@@ -201,7 +217,7 @@ import { connectRealtimeVoiceTransport, createProtoRealtimeVoiceProtocol, fetchR
|
|
|
201
217
|
import { createGroupWithBots } from './services/group-creator.js';
|
|
202
218
|
import { addBotToChat, isInChat } from './services/groups-store.js';
|
|
203
219
|
import { initSessionGroups, isSessionGroup, getSessionGroup, touchSessionGroup } from './services/session-groups-store.js';
|
|
204
|
-
import { maybeBirthSessionGroup } from './core/session-group-birth.js';
|
|
220
|
+
import { maybeBirthSessionGroup, declinesSessionGroupBirthAsSlashCommand } from './core/session-group-birth.js';
|
|
205
221
|
import { scheduleSessionGroupTitle } from './services/session-group-title.js';
|
|
206
222
|
import { setChatReplyMode } from './services/chat-reply-mode-store.js';
|
|
207
223
|
import { hasVcMeetingEndedTombstone, listVcMeetingRuntimeSessionsByListenerAndAgent, listVcMeetingRuntimeSessions, pruneExpiredVcMeetingRuntimeSessions, recordVcMeetingEndedTombstone, recordVcMeetingRuntimeSession, removeVcMeetingRuntimeSession, } from './services/vc-meeting-runtime-store.js';
|
|
@@ -230,6 +246,9 @@ const activeSessions = new Map();
|
|
|
230
246
|
* (codex P1-2). While false, /api/asks returns a retryable 503 for unknown
|
|
231
247
|
* sessions instead, so the reconnecting hook keeps waiting through the restore. */
|
|
232
248
|
let sessionsRestored = false;
|
|
249
|
+
/** Once-per-daemon guard for the mojo containment boot reconciliation. The store
|
|
250
|
+
* is bot-agnostic, so it must run once regardless of how many bots start. */
|
|
251
|
+
let mojoContainmentReconciledThisBoot = false;
|
|
233
252
|
const VC_MEETING_DELIVERY_LEASE_MS = 15 * 60_000;
|
|
234
253
|
const VC_MEETING_DELIVERY_LEASE_SCAN_MS = 60_000;
|
|
235
254
|
const VC_MEETING_RUNTIME_EXPIRY_ACK_TIMEOUT_MS = 3_000;
|
|
@@ -366,15 +385,37 @@ function vcMeetingPersistentBackendAvailable(backendType) {
|
|
|
366
385
|
return ZellijBackend.isAvailable();
|
|
367
386
|
return ZmxBackend.isAvailable();
|
|
368
387
|
}
|
|
388
|
+
/**
|
|
389
|
+
* VC receiver teardown: this fence's job is to guarantee the local PRODUCER
|
|
390
|
+
* process is dead before hub replay is admitted. killWorker refuses an
|
|
391
|
+
* unprepared live remote worker (P0-2) — the fail-safe direction for lineage,
|
|
392
|
+
* but for THIS caller a silent refusal is fail-OPEN: the pane probes then read
|
|
393
|
+
* `missing` (mojo has no persistent pane) and the fence cleared while the
|
|
394
|
+
* producer kept running. Remote-frozen receivers are therefore retired
|
|
395
|
+
* process-only — no close IPC, no remote cancel, lineage and containment
|
|
396
|
+
* handles intact — with retireWorkerProcessOnly's SIGTERM→SIGKILL backstop
|
|
397
|
+
* guaranteeing death; local receivers keep killWorker so their backing
|
|
398
|
+
* session is torn down as before.
|
|
399
|
+
*/
|
|
400
|
+
function teardownVcReceiverWorker(ds) {
|
|
401
|
+
if (isRemoteBackendSession(ds))
|
|
402
|
+
retireWorkerProcessOnly(ds, 'vc_runtime_lease');
|
|
403
|
+
else
|
|
404
|
+
killWorker(ds);
|
|
405
|
+
}
|
|
369
406
|
let testOnlyVcMeetingBootBackingMissing;
|
|
370
407
|
function vcMeetingBootBackingMissing(sessionId, destroy) {
|
|
371
408
|
if (testOnlyVcMeetingBootBackingMissing) {
|
|
372
409
|
return testOnlyVcMeetingBootBackingMissing(sessionId, destroy);
|
|
373
410
|
}
|
|
374
411
|
const ds = findActiveBySessionId(sessionId);
|
|
412
|
+
// Captured BEFORE teardown: retirement nulls ds.worker while the process
|
|
413
|
+
// dies asynchronously, and the producer-liveness check below needs the real
|
|
414
|
+
// ChildProcess to prove the exit.
|
|
415
|
+
const workerBefore = ds?.worker && !ds.worker.killed ? ds.worker : null;
|
|
375
416
|
if (destroy && ds) {
|
|
376
417
|
try {
|
|
377
|
-
|
|
418
|
+
teardownVcReceiverWorker(ds);
|
|
378
419
|
}
|
|
379
420
|
catch (err) {
|
|
380
421
|
logger.warn(`[vc-delivery] boot recovery worker teardown failed session=${sessionId}: ${err}`);
|
|
@@ -415,6 +456,16 @@ function vcMeetingBootBackingMissing(sessionId, destroy) {
|
|
|
415
456
|
+ `backend=${backendType} session=${sessionId}`);
|
|
416
457
|
}
|
|
417
458
|
}
|
|
459
|
+
// The worker PROCESS is itself the producer this recovery gates on; pane
|
|
460
|
+
// probes say nothing about it (mojo has no pane at all, so they always read
|
|
461
|
+
// `missing`). Clear only once the previously-live worker has actually
|
|
462
|
+
// exited — the retirement's SIGTERM→SIGKILL backstop makes a later reprobe
|
|
463
|
+
// see it gone.
|
|
464
|
+
if (workerBefore && workerBefore.exitCode === null && workerBefore.signalCode === null) {
|
|
465
|
+
allMissing = false;
|
|
466
|
+
logger.error(`[vc-delivery] boot recovery worker process still live; receiver remains gated `
|
|
467
|
+
+ `session=${sessionId}`);
|
|
468
|
+
}
|
|
418
469
|
return allMissing;
|
|
419
470
|
}
|
|
420
471
|
function scheduleVcMeetingBootRecoveryProbe(key, sessionId, delayMs) {
|
|
@@ -448,9 +499,11 @@ function escalateVcMeetingBootRecovery(key, sessionId) {
|
|
|
448
499
|
vcMeetingReceiverRecoveryEscalating.add(key);
|
|
449
500
|
const ds = findActiveBySessionId(sessionId);
|
|
450
501
|
if (ds)
|
|
451
|
-
|
|
452
|
-
// Wait past
|
|
453
|
-
//
|
|
502
|
+
teardownVcReceiverWorker(ds);
|
|
503
|
+
// Wait past the retirement's SIGTERM→SIGKILL backstop window (killWorker for
|
|
504
|
+
// local receivers, retireWorkerProcessOnly for remote-frozen ones — a plain
|
|
505
|
+
// killWorker would REFUSE a live remote worker and arm nothing), then
|
|
506
|
+
// direct-kill and probe. exists/unknown stays scoped-gated and reprobes.
|
|
454
507
|
scheduleVcMeetingBootRecoveryProbe(key, sessionId, VC_MEETING_RUNTIME_EXPIRY_TEARDOWN_MS);
|
|
455
508
|
}
|
|
456
509
|
function acknowledgeVcMeetingReceiverRecovery(key) {
|
|
@@ -579,6 +632,34 @@ function createVcMeetingRuntimeLeaseRecovery(deps) {
|
|
|
579
632
|
scheduleReprobe(fence, 'identity conflict');
|
|
580
633
|
return false;
|
|
581
634
|
}
|
|
635
|
+
// Captured BEFORE teardown: retirement nulls ds.worker while the process
|
|
636
|
+
// dies asynchronously; the producer-liveness gate below needs the real
|
|
637
|
+
// ChildProcess to prove the exit. Falls back to the process observed at
|
|
638
|
+
// arm time when the registry no longer resolves the ds — a deleted
|
|
639
|
+
// registry entry is not proof the producer died (fourth-round review).
|
|
640
|
+
const armedAlive = fence.armedWorker
|
|
641
|
+
&& !fence.armedWorker.killed
|
|
642
|
+
&& fence.armedWorker.exitCode === null
|
|
643
|
+
&& fence.armedWorker.signalCode === null
|
|
644
|
+
? fence.armedWorker : null;
|
|
645
|
+
// Third source, for a fence armed AFTER the registry delete (the other
|
|
646
|
+
// half of the collision-loser timing): a process-only retirement is still
|
|
647
|
+
// dying for this session id, and neither ds nor arm-time capture ever saw
|
|
648
|
+
// it. Pin it onto the fence so later reprobes keep tracking the same
|
|
649
|
+
// process.
|
|
650
|
+
let retiringAlive = null;
|
|
651
|
+
if (!armedAlive && !(ds?.worker && !ds.worker.killed)) {
|
|
652
|
+
for (const w of deps.resolveRetiringWorkers?.(fence.receiverSessionId) ?? []) {
|
|
653
|
+
if (w && !w.killed && w.exitCode === null && w.signalCode === null) {
|
|
654
|
+
retiringAlive = w;
|
|
655
|
+
fence.armedWorker = w;
|
|
656
|
+
break;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
const workerBefore = (ds?.worker && !ds.worker.killed ? ds.worker : null)
|
|
661
|
+
?? armedAlive
|
|
662
|
+
?? retiringAlive;
|
|
582
663
|
if (ds) {
|
|
583
664
|
try {
|
|
584
665
|
deps.killWorker(ds);
|
|
@@ -625,6 +706,17 @@ function createVcMeetingRuntimeLeaseRecovery(deps) {
|
|
|
625
706
|
+ `attempt=${fence.dispatchAttempt}`);
|
|
626
707
|
}
|
|
627
708
|
}
|
|
709
|
+
// The worker PROCESS is itself the producer this fence gates on; pane
|
|
710
|
+
// probes say nothing about it — mojo owns no pane, so they always read
|
|
711
|
+
// `missing`, which is exactly how a refused/incomplete teardown became
|
|
712
|
+
// fail-OPEN (third-round review, gate 3). Clear only once the previously
|
|
713
|
+
// live worker has actually EXITED; the retirement's SIGTERM→SIGKILL
|
|
714
|
+
// backstop guarantees a later reprobe sees it gone.
|
|
715
|
+
if (workerBefore && workerBefore.exitCode === null && workerBefore.signalCode === null) {
|
|
716
|
+
allMissing = false;
|
|
717
|
+
deps.error(`[vc-delivery] runtime lease worker process still live; delivery remains gated `
|
|
718
|
+
+ `session=${fence.receiverSessionId} attempt=${fence.dispatchAttempt}`);
|
|
719
|
+
}
|
|
628
720
|
// PTY has no surviving backing process once its worker has crossed the
|
|
629
721
|
// SIGKILL backstop. Persistent backends unlock only after every applicable
|
|
630
722
|
// deterministic name probes authoritatively missing. The backing proof is
|
|
@@ -679,8 +771,11 @@ function createVcMeetingRuntimeLeaseRecovery(deps) {
|
|
|
679
771
|
deps.error(`[vc-delivery] runtime lease escalation failed to kill worker `
|
|
680
772
|
+ `session=${fence.receiverSessionId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
681
773
|
}
|
|
682
|
-
//
|
|
683
|
-
//
|
|
774
|
+
// The teardown above arms a SIGTERM→SIGKILL backstop (killWorker's close
|
|
775
|
+
// path for local receivers; retireWorkerProcessOnly for remote-frozen
|
|
776
|
+
// ones — a plain killWorker would REFUSE a live remote worker and arm
|
|
777
|
+
// nothing, which is why the fence used to fail open for mojo). Only after
|
|
778
|
+
// that window do we directly kill + probe the deterministic owned pane.
|
|
684
779
|
fence.timer = setTimeout(() => {
|
|
685
780
|
if (!isCurrent(fence) || fence.phase !== 'escalating')
|
|
686
781
|
return;
|
|
@@ -717,6 +812,10 @@ function createVcMeetingRuntimeLeaseRecovery(deps) {
|
|
|
717
812
|
teardownAndProbe(fence, !ds ? 'missing-session teardown' : 'workerless teardown');
|
|
718
813
|
return;
|
|
719
814
|
}
|
|
815
|
+
// Remember the live producer process itself: registry state can stop
|
|
816
|
+
// resolving this ds before the process has died, and the liveness gate in
|
|
817
|
+
// teardownAndProbe must keep seeing it.
|
|
818
|
+
fence.armedWorker = ds.worker;
|
|
720
819
|
if ((ds.workerGeneration ?? 0) !== ref.workerGeneration) {
|
|
721
820
|
deps.error(`[vc-delivery] runtime lease worker generation mismatch; escalating `
|
|
722
821
|
+ `session=${ref.receiverSessionId} receipt=${ref.workerGeneration} `
|
|
@@ -765,6 +864,12 @@ function createVcMeetingRuntimeLeaseRecovery(deps) {
|
|
|
765
864
|
return false;
|
|
766
865
|
}
|
|
767
866
|
if (context.disposition === 'queued_removed') {
|
|
867
|
+
// No producer-exit proof required here, deliberately: `queued_removed`
|
|
868
|
+
// is an ACK from the EXACT expected worker generation saying it removed
|
|
869
|
+
// the queued delivery itself. The producer is alive, current and
|
|
870
|
+
// cooperating — the double-delivery risk this fence gates on is gone
|
|
871
|
+
// without anyone dying. Exit proof is demanded only on the teardown
|
|
872
|
+
// paths, where the producer's state is unknown or adversarial.
|
|
768
873
|
clearFence(fence);
|
|
769
874
|
return true;
|
|
770
875
|
}
|
|
@@ -836,7 +941,8 @@ const vcMeetingRuntimeLeaseRecovery = createVcMeetingRuntimeLeaseRecovery({
|
|
|
836
941
|
throw new Error('receiver worker is not live');
|
|
837
942
|
ds.worker.send(message);
|
|
838
943
|
},
|
|
839
|
-
killWorker,
|
|
944
|
+
killWorker: teardownVcReceiverWorker,
|
|
945
|
+
resolveRetiringWorkers: retiringWorkersForSession,
|
|
840
946
|
resolvePersistentScope(ds) {
|
|
841
947
|
const backendType = getSessionPersistentBackendType(ds);
|
|
842
948
|
if (backendType)
|
|
@@ -1942,19 +2048,34 @@ function scheduleDeferredScheduleSettlement(ds, context) {
|
|
|
1942
2048
|
// Exact transcript terminal needs only a short filesystem visibility grace.
|
|
1943
2049
|
// Screen-only adapters use a longer confirmation and re-check that the same
|
|
1944
2050
|
// turn is still idle before reclaiming the hidden session.
|
|
2051
|
+
// Remote backends (riff / mojo) report their turn boundary over the network,
|
|
2052
|
+
// so allow the same longer grace as the screen-only path instead of the 300ms
|
|
2053
|
+
// local-filesystem one.
|
|
2054
|
+
const remoteTerminal = ds.session.backendType === 'riff'
|
|
2055
|
+
|| ds.session.backendType === 'mojo';
|
|
1945
2056
|
const delayMs = context.source === 'terminal'
|
|
1946
|
-
? (
|
|
2057
|
+
? (remoteTerminal ? 1_500 : 300)
|
|
1947
2058
|
: 1_500;
|
|
1948
2059
|
const timer = setTimeout(() => {
|
|
1949
2060
|
deferredScheduleSettleTimers.delete(sessionId);
|
|
1950
2061
|
void settleDeferredScheduleRun(ds, context, {
|
|
1951
2062
|
reconcile: reconcileDeferredTopicBinding,
|
|
1952
|
-
|
|
2063
|
+
// Background path: no user surface, so a residual/refusal must at least be
|
|
2064
|
+
// logged with its remote id instead of being discarded.
|
|
2065
|
+
closeSession: (id) => closeSessionForBackgroundCleanup(id, 'deferred-schedule settlement'),
|
|
1953
2066
|
}).then((result) => {
|
|
1954
2067
|
if (result.action === 'materialized') {
|
|
1955
2068
|
logger.info(`[scheduler] Deferred topic materialized session=${sessionId.slice(0, 8)} root=${result.rootMessageId.slice(0, 12)}`);
|
|
1956
2069
|
return;
|
|
1957
2070
|
}
|
|
2071
|
+
if (result.action === 'close_refused') {
|
|
2072
|
+
// Must NOT print "Auto-closed": the row is still active and its remote
|
|
2073
|
+
// session may still be running. Two contradictory log lines about the same
|
|
2074
|
+
// session is exactly how a false success hides.
|
|
2075
|
+
logger.error(`[scheduler] Deferred run close REFUSED (${result.error ?? 'unknown'}); session stays `
|
|
2076
|
+
+ `ACTIVE session=${sessionId.slice(0, 8)} turn=${context.turnId.slice(0, 12)} source=${context.source}`);
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
1958
2079
|
if (result.action === 'closed') {
|
|
1959
2080
|
logger.info(`[scheduler] Auto-closed silent deferred run with no botmux send `
|
|
1960
2081
|
+ `session=${sessionId.slice(0, 8)} turn=${context.turnId.slice(0, 12)} source=${context.source}`);
|
|
@@ -2374,8 +2495,11 @@ async function maybeSeedCardlessForceTopicTurn(args) {
|
|
|
2374
2495
|
}
|
|
2375
2496
|
}
|
|
2376
2497
|
async function revokeQuotaGrant(larkAppId, chatId, senderOpenId, ev) {
|
|
2498
|
+
// 会话群里的 chatGrant 是**继承**来的:授权记录挂在出生前那个私聊上(ev.grantChatId),
|
|
2499
|
+
// 不在会话群自己身上。撤销必须落到来源 chat,否则删了个不存在的记录,硬上限失效。
|
|
2500
|
+
const grantChatId = ev.grantChatId ?? chatId;
|
|
2377
2501
|
const result = ev.reason === 'chatGrant'
|
|
2378
|
-
? await removeChatGrant(larkAppId,
|
|
2502
|
+
? await removeChatGrant(larkAppId, grantChatId, senderOpenId)
|
|
2379
2503
|
: ev.reason === 'globalGrant'
|
|
2380
2504
|
? await removeGlobalGrant(larkAppId, senderOpenId)
|
|
2381
2505
|
: { ok: true, removed: false };
|
|
@@ -2396,6 +2520,20 @@ async function notifyQuotaExhausted(larkAppId, anchor, senderOpenId, limit) {
|
|
|
2396
2520
|
export async function enforceMessageQuotaForCliInput(larkAppId, chatId, senderOpenId, messageId, anchor, senderUnionId, memberUnionId, chatType, botSender, opts) {
|
|
2397
2521
|
if (opts?.listenerAuthorized)
|
|
2398
2522
|
return true;
|
|
2523
|
+
// 会话群出生轮:**同一条消息**的授权判定与扣费,刚刚由本函数在原 DM 上下文里
|
|
2524
|
+
// 一起做完(handleNewTopicAdmitted 的建群前扣费点:扣费被拒必须零外部副作用,
|
|
2525
|
+
// 所以它必须排在 createGroupWithBots 之前)。这一轮绝不能再复查一次:
|
|
2526
|
+
// • 新群是 bot 刚为这个发送者建的,chat 维度的 talk 来源(chatGrant /
|
|
2527
|
+
// allowedChatGroup / oncall / p2p 专属的 p2pOpen)按定义不可能已经落在它
|
|
2528
|
+
// 上面,复查只会产出假阴性;
|
|
2529
|
+
// • 而这条消息**已经扣过一次费**——被假阴性丢掉就成了「扣了费还把任务丢了」:
|
|
2530
|
+
// 用户额度少一格,任务无声消失,连一句拒绝提示都没有(丢弃分支只打 debug 日志)。
|
|
2531
|
+
// 「扣了费就不能丢任务,丢任务就不能扣费」是这道闸的硬不变量,两侧只能同进同退。
|
|
2532
|
+
// 授权本身并没有被放宽:真正的判定就是 DM 那次(真实 chatId + chatType='p2p'),
|
|
2533
|
+
// 这里只是不拿一个必然更严的新上下文去推翻它。跨 chat 的授权继承缺口是另一件事
|
|
2534
|
+
//(新群里的**后续**消息仍按新 chat 判定),不由这条已扣费的出生轮来承担。
|
|
2535
|
+
if (opts?.alreadyAuthorizedAndCharged)
|
|
2536
|
+
return true;
|
|
2399
2537
|
// senderUnionId(bot-locked)让 evaluateTalk 认出跨部署团队 peer bot(teamBot 腿);
|
|
2400
2538
|
// memberUnionId(可为真人 union)走 teamMember 腿——否则外部闸门/群闸门放进来的
|
|
2401
2539
|
// 团队 bot 或团队成员消息会在这里复查处被静默丢弃(#332 端到端断点,人腿同理)。
|
|
@@ -2993,6 +3131,13 @@ async function handleV3SavedWorkflowCommandIfAny(invocation) {
|
|
|
2993
3131
|
await notify('❌ Saved Workflow 需要可验证的飞书用户身份。', 'authorization');
|
|
2994
3132
|
return true;
|
|
2995
3133
|
}
|
|
3134
|
+
// Machine-wide workflow kill-switch: refuse starting/authoring a workflow when
|
|
3135
|
+
// the feature is off. `cancel` (and other decrease-only management) stays
|
|
3136
|
+
// available so an in-flight run started before the flip can be wound down.
|
|
3137
|
+
if ((command.kind === 'save' || command.kind === 'run') && !isWorkflowFeatureEnabled()) {
|
|
3138
|
+
await notify(WORKFLOW_DISABLED_MESSAGE, 'validation');
|
|
3139
|
+
return true;
|
|
3140
|
+
}
|
|
2996
3141
|
if (
|
|
2997
3142
|
// Cancellation is decrease-only and is still protected below by the
|
|
2998
3143
|
// immutable owner/chat/app binding (or explicit canOperate). Keep it
|
|
@@ -3128,6 +3273,7 @@ function beginNewTurn(ds, title, turnId) {
|
|
|
3128
3273
|
ds.parkedStreamCardNonce = ds.streamCardNonce;
|
|
3129
3274
|
ds.frozenCards.set(ds.streamCardNonce, {
|
|
3130
3275
|
messageId: ds.streamCardId,
|
|
3276
|
+
replyTargetKey: ds.streamCardReplyTargetKey,
|
|
3131
3277
|
content: ds.lastScreenContent ?? '',
|
|
3132
3278
|
title: prevTitle,
|
|
3133
3279
|
displayMode: prevMode,
|
|
@@ -3685,10 +3831,16 @@ async function adoptCodexNotifierEvent(larkAppId, event, cardMessageId, ownerOpe
|
|
|
3685
3831
|
}
|
|
3686
3832
|
// 接管原生 Codex App 线程时固定为纯 codex-app 启动,不能继承通知 Bot 的
|
|
3687
3833
|
// wrapper/model;这些配置针对普通 CLI,会错误包装 app-server runner。
|
|
3834
|
+
// model 由 resolveSessionLaunchModel 在每次 spawn 时解析:这里把 cliId 钉成
|
|
3835
|
+
// codex-app 后,若通知 Bot 自己不是 codex-app,session 与 bot 的 cliId 不匹配
|
|
3836
|
+
// → 不会拿 bot 那个面向别的 CLI 的 model;清掉历史记录值让兜底也为空。
|
|
3837
|
+
// spawnModelOverride(trigger 的一次性 model)优先级最高且无条件,必须一并清掉,
|
|
3838
|
+
// 否则它会泄漏进接管后的 codex-app 启动。
|
|
3688
3839
|
ds.session.cliId = 'codex-app';
|
|
3689
3840
|
ds.session.cliPathOverride = botCfg.cliPathOverride;
|
|
3690
3841
|
delete ds.session.wrapperCli;
|
|
3691
3842
|
delete ds.session.model;
|
|
3843
|
+
ds.spawnModelOverride = undefined;
|
|
3692
3844
|
ds.session.agentFrozen = true;
|
|
3693
3845
|
sessionStore.updateSession(ds.session);
|
|
3694
3846
|
// 默认 flat DM(p2pMode=chat)下这条按钮回调复用同一私聊的现有会话。若该会话
|
|
@@ -3906,6 +4058,14 @@ workflowDaemonMutationRoute('start', async (reply, params, _body, identity) => {
|
|
|
3906
4058
|
const runId = params.runId;
|
|
3907
4059
|
if (!isValidV3RunId(runId))
|
|
3908
4060
|
return reply(400, { ok: false, error: 'bad_run_id' });
|
|
4061
|
+
// Machine-wide workflow kill-switch: refuse launching a NEW daemon-driven run
|
|
4062
|
+
// when the feature is off. This is the common sink for both `botmux workflow
|
|
4063
|
+
// start` and the grill `approve-dag` kick, so gating here closes the edge where
|
|
4064
|
+
// a run was grilled+approved before the flip. Restart recovery of an
|
|
4065
|
+
// already-started run (coldAttach / reconcileV3PendingGates) is a separate path
|
|
4066
|
+
// and is intentionally NOT gated, and `retry`/`grant`/`cancel` stay available.
|
|
4067
|
+
if (!isWorkflowFeatureEnabled())
|
|
4068
|
+
return reply(409, { ok: false, error: 'workflow_disabled' });
|
|
3909
4069
|
const runDir = join(v3DefaultBaseDir(), runId);
|
|
3910
4070
|
const preflight = preflightV3RunStart(runDir);
|
|
3911
4071
|
if (!preflight.ok) {
|
|
@@ -13696,12 +13856,14 @@ export const __testOnly_onQueuedActivationSubmitted = onQueuedActivationSubmitte
|
|
|
13696
13856
|
* deliberately no await between the final buffered-input snapshot, fork, and
|
|
13697
13857
|
* release: a later handler either buffers before this block or observes the
|
|
13698
13858
|
* live worker after it. */
|
|
13699
|
-
function forkReservedInitialSession(ds, availableBots) {
|
|
13859
|
+
function forkReservedInitialSession(ds, availableBots, trustedCaller) {
|
|
13700
13860
|
const userPrompt = ds.pendingPrompt ?? '';
|
|
13701
13861
|
const input = buildReservedInitialInput(ds, availableBots);
|
|
13862
|
+
if (trustedCaller)
|
|
13863
|
+
input.trustedCaller = trustedCaller;
|
|
13702
13864
|
rememberLastCliInput(ds, userPrompt, input);
|
|
13703
13865
|
const turnId = ds.pendingTurnId ?? ds.session.pendingRepoSetup?.turnId;
|
|
13704
|
-
forkWorker(ds, input, turnId ? { turnId } : false);
|
|
13866
|
+
forkWorker(ds, input, turnId ? { turnId, trustedCaller } : false);
|
|
13705
13867
|
ds.pendingTurnId = undefined;
|
|
13706
13868
|
// A no-project pendingRepo fallback enters forkWorker with `session.queued`
|
|
13707
13869
|
// still set. forkWorker materializes the exact opening as a tokened
|
|
@@ -13804,15 +13966,15 @@ function isInitialSessionPassthrough(larkAppId, cmd) {
|
|
|
13804
13966
|
/** `/fast` is a passthrough keystroke to Codex's native tier toggle — it only
|
|
13805
13967
|
* reaches the executor on a real paste TUI. In RPC input mode the pane is a
|
|
13806
13968
|
* pure viewer (turns go over JSON-RPC, keystrokes never reach the app-server),
|
|
13807
|
-
* and
|
|
13808
|
-
* those backends the toggle is a silent no-op (or worse), so fail closed:
|
|
13969
|
+
* and a remote backend (riff / mojo) turns the text+Enter into two independent
|
|
13970
|
+
* remote turns. On those backends the toggle is a silent no-op (or worse), so fail closed:
|
|
13809
13971
|
* reject with a clear message instead of pretending it worked. The read-only
|
|
13810
13972
|
* card badge is unaffected — it reflects whatever tier Codex actually runs. */
|
|
13811
13973
|
function fastToggleUnsupportedBackend(ds) {
|
|
13812
13974
|
if (!ds)
|
|
13813
13975
|
return false;
|
|
13814
13976
|
const backendType = ds.initConfig?.backendType ?? ds.session.backendType;
|
|
13815
|
-
if (backendType === 'riff')
|
|
13977
|
+
if (backendType === 'riff' || backendType === 'mojo')
|
|
13816
13978
|
return true;
|
|
13817
13979
|
return ds.initConfig?.codexRpcInput === true;
|
|
13818
13980
|
}
|
|
@@ -13887,6 +14049,9 @@ function deliverPassthroughToExistingSession(ds, cmd, commandContent, anchor, la
|
|
|
13887
14049
|
sendWorkerSessionInput(ds, {
|
|
13888
14050
|
type: 'raw_input',
|
|
13889
14051
|
content: commandContent,
|
|
14052
|
+
// Same reason as the worker-pool raw_input send: a passthrough is a real
|
|
14053
|
+
// mojo turn, so it needs the live credential snapshot too.
|
|
14054
|
+
...(mojoLivePatchForSession(ds) ?? {}),
|
|
13890
14055
|
turnId: turn.messageId,
|
|
13891
14056
|
});
|
|
13892
14057
|
turn.onDelivered?.();
|
|
@@ -14151,6 +14316,7 @@ async function handleNewTopicAdmitted(data, ctx) {
|
|
|
14151
14316
|
// routing into thread-scope so the bot's first reply seeds a Lark thread.
|
|
14152
14317
|
let scope = ctx.scope;
|
|
14153
14318
|
let anchor = ctx.anchor;
|
|
14319
|
+
let quotaConsumedBeforeSessionGroupBirth = false;
|
|
14154
14320
|
// ─── p2pMode='group':会话群出生 ────────────────────────────────────────
|
|
14155
14321
|
// group 模式下,顶层 DM 消息在任何会话机制启动前先改道:建一个专属会话群
|
|
14156
14322
|
//(bot 保留群主),把本轮 context 重写到新群(chat-scope)后递归。返回 null
|
|
@@ -14166,10 +14332,32 @@ async function handleNewTopicAdmitted(data, ctx) {
|
|
|
14166
14332
|
&& !substituteTrigger
|
|
14167
14333
|
&& scope === 'thread'
|
|
14168
14334
|
&& anchor === messageId
|
|
14169
|
-
|
|
14335
|
+
// 「话题内发送 + 同时发送到会话」的消息 root_id 为空但带 thread_id——
|
|
14336
|
+
// 语境属于既有话题,绝不当全新会话建群(回退 thread 旧行为)。
|
|
14337
|
+
&& !data?.message?.thread_id
|
|
14338
|
+
// 斜杠命令判定必须**早于扣费**:/help、/login、/close 本来就不进 CLI,既不该
|
|
14339
|
+
// 被预扣一次额度,也不该在额度耗尽时被这道闸静默丢掉(下面的 return 会让命令
|
|
14340
|
+
// 根本执行不到)。maybeBirthSessionGroup 对同一条消息本就返回 null(命令不建
|
|
14341
|
+
// 群),所以这里只是把它的结论提前一步,建群行为一字未改;命令随后照常走
|
|
14342
|
+
// parseSlashCommandInvocation 分支,真正会注入 CLI 的消息(含未注册的 /foo,
|
|
14343
|
+
// 它落不进命令分支)仍由下面 pre-worker 那道闸按原样扣一次费——净扣费不变。
|
|
14344
|
+
// 谓词刻意复用 birth 内部的同一个:两侧同源才能保证「跳过扣费」与「不建群」
|
|
14345
|
+
// 是同一个判断——窄于它会退回本 bug,宽于它则会让本该建群的消息不再建群。
|
|
14346
|
+
&& !declinesSessionGroupBirthAsSlashCommand(data)) {
|
|
14347
|
+
// A quota denial must have zero external side effects. Charge the original
|
|
14348
|
+
// DM before creating the real Feishu chat, then mark the rewritten turn so
|
|
14349
|
+
// the ordinary pre-worker gate below does not charge it a second time.
|
|
14350
|
+
const quotaSenderOpenId = data.sender?.sender_id?.open_id;
|
|
14351
|
+
const quotaSenderUnionId = data.sender?.sender_id?.union_id;
|
|
14352
|
+
const quotaTeamTrustUnionId = (data.sender?.sender_type === 'app' || data.sender?.sender_type === 'bot')
|
|
14353
|
+
? quotaSenderUnionId
|
|
14354
|
+
: undefined;
|
|
14355
|
+
if (!await enforceMessageQuotaForCliInput(larkAppId, chatId, quotaSenderOpenId, messageId, anchor, quotaTeamTrustUnionId, quotaSenderUnionId, chatType))
|
|
14356
|
+
return;
|
|
14357
|
+
quotaConsumedBeforeSessionGroupBirth = true;
|
|
14170
14358
|
const reborn = await maybeBirthSessionGroup(data, ctx);
|
|
14171
14359
|
if (reborn)
|
|
14172
|
-
return handleNewTopic(data, reborn);
|
|
14360
|
+
return handleNewTopic(data, { ...reborn, sessionGroupQuotaConsumed: true });
|
|
14173
14361
|
}
|
|
14174
14362
|
// ─── 会话群同群续聊 ─────────────────────────────────────────────────────
|
|
14175
14363
|
// 会话群里的新消息发现登记的会话已关闭时,自动 resume 原会话(与话题内续聊
|
|
@@ -14251,6 +14439,7 @@ async function handleNewTopicAdmitted(data, ctx) {
|
|
|
14251
14439
|
}
|
|
14252
14440
|
// senderOpenId 已在上方(force-topic grant 限制前)声明;这里只补 master 新增的 senderUnionId。
|
|
14253
14441
|
const senderUnionId = data.sender?.sender_id?.union_id;
|
|
14442
|
+
const trustedCaller = trustedCallerForTurn(larkAppId, senderOpenId, senderUnionId);
|
|
14254
14443
|
// union_id 信任腿(canOperate/evaluateTalk 的 teamBot)只对**飞书盖章的 bot 发送方**
|
|
14255
14444
|
// 生效:平台 roster 是成员机器自报的,若不锁 sender_type,恶意成员把某个真人的
|
|
14256
14445
|
// union_id 报成"自家 bot",那个真人就会在全团队机器上被当队友 bot 放行(talk +
|
|
@@ -14327,6 +14516,10 @@ async function handleNewTopicAdmitted(data, ctx) {
|
|
|
14327
14516
|
let workflowGrillPrompt;
|
|
14328
14517
|
const newTopicGrill = parseWorkflowGrillTrigger(cmdContent);
|
|
14329
14518
|
if (newTopicGrill) {
|
|
14519
|
+
if (!isWorkflowFeatureEnabled()) {
|
|
14520
|
+
await sessionReply(anchor, WORKFLOW_DISABLED_MESSAGE, 'text', larkAppId);
|
|
14521
|
+
return;
|
|
14522
|
+
}
|
|
14330
14523
|
if (await replyGrantRestrictionIfNeeded(larkAppId, chatId, senderOpenId, anchor, '/workflow')) {
|
|
14331
14524
|
return;
|
|
14332
14525
|
}
|
|
@@ -14550,9 +14743,20 @@ async function handleNewTopicAdmitted(data, ctx) {
|
|
|
14550
14743
|
&& buildQuoteHint(parsed, scope, anchor, localeForBot(larkAppId)) === ''
|
|
14551
14744
|
&& !ctx.forwardSeedData
|
|
14552
14745
|
&& !messageListener;
|
|
14746
|
+
// Session-group birth charges the ORIGINAL DM before creating the Feishu chat
|
|
14747
|
+
// (a quota denial must have zero external side effects), so by the time the
|
|
14748
|
+
// rewritten group turn gets here THIS message is already authorized AND
|
|
14749
|
+
// already paid for — see `alreadyAuthorizedAndCharged` in
|
|
14750
|
+
// enforceMessageQuotaForCliInput for why re-deciding it here can only lose
|
|
14751
|
+
// the unit we just took. `skipCharge` stays set as well so that even if that
|
|
14752
|
+
// short-circuit is ever removed, the worst case is a redundant recheck, never
|
|
14753
|
+
// a double charge.
|
|
14754
|
+
const sessionGroupAlreadyCharged = !!ctx.sessionGroupQuotaConsumed
|
|
14755
|
+
|| quotaConsumedBeforeSessionGroupBirth;
|
|
14553
14756
|
if (!await enforceMessageQuotaForCliInput(larkAppId, chatId, senderOpenId, messageId, anchor, teamTrustUnionId, senderUnionId, chatType, isBotSenderType, {
|
|
14554
14757
|
listenerAuthorized: !!messageListener,
|
|
14555
|
-
skipCharge: isBareForceTopic,
|
|
14758
|
+
skipCharge: isBareForceTopic || sessionGroupAlreadyCharged,
|
|
14759
|
+
alreadyAuthorizedAndCharged: sessionGroupAlreadyCharged,
|
|
14556
14760
|
})) {
|
|
14557
14761
|
return;
|
|
14558
14762
|
}
|
|
@@ -14834,7 +15038,7 @@ async function handleNewTopicAdmitted(data, ctx) {
|
|
|
14834
15038
|
// Ack reaction targets the ORIGINAL inbound message (2nd arg); the turn id
|
|
14835
15039
|
// (5th arg) is the reply anchor so provenance holds on session-group births.
|
|
14836
15040
|
await noteTurnReceived(ds, messageId, content, newTopicSender, replyAnchorId, substituteTrigger ? SUBSTITUTE_RECEIVED_REACTION_EMOJI_TYPE : undefined);
|
|
14837
|
-
forkReservedInitialSession(ds, availableBots);
|
|
15041
|
+
forkReservedInitialSession(ds, availableBots, trustedCaller);
|
|
14838
15042
|
// fork 成功即开场已交给 CLI;fork 抛错则开场只存在于内存,保持重发提示。
|
|
14839
15043
|
markIngressAdmitted(ctx);
|
|
14840
15044
|
const reason = oncallEntry
|
|
@@ -14886,7 +15090,7 @@ async function handleNewTopicAdmitted(data, ctx) {
|
|
|
14886
15090
|
// Ack reaction targets the ORIGINAL inbound message (2nd arg); the turn id
|
|
14887
15091
|
// (5th arg) is the reply anchor so provenance holds on session-group births.
|
|
14888
15092
|
await noteTurnReceived(ds, messageId, content, newTopicSender, replyAnchorId, substituteTrigger ? SUBSTITUTE_RECEIVED_REACTION_EMOJI_TYPE : undefined);
|
|
14889
|
-
forkReservedInitialSession(ds, availableBots);
|
|
15093
|
+
forkReservedInitialSession(ds, availableBots, trustedCaller);
|
|
14890
15094
|
logger.info(`Session ${session.sessionId} ready (no projects to select), total active: ${getActiveCount()}`);
|
|
14891
15095
|
}
|
|
14892
15096
|
}
|
|
@@ -15092,6 +15296,15 @@ async function handleBotAdded(chatId, operatorOpenId, larkAppId, opts) {
|
|
|
15092
15296
|
anchor = chatId;
|
|
15093
15297
|
scope = 'chat';
|
|
15094
15298
|
}
|
|
15299
|
+
// bot.added 是成员变更事件,没有用户 message_id 可作首轮 turn 身份。非 shared
|
|
15300
|
+
// 路径没有 shared reply seed 兜底,若以 pendingTurnId=undefined 直接 fork,
|
|
15301
|
+
// worker 发布的 managed_turn_origin 不含 turnId,CLI 首轮 `botmux send` 的
|
|
15302
|
+
// managed-origin attestation 会被 daemon 以 origin_unproven 拒绝——首轮回复
|
|
15303
|
+
// 发不回飞书。这里自行铸造首轮 turn 身份:
|
|
15304
|
+
// - thread scope:seed 消息本身就是可见锚点且是真实 om_ id,直接复用;
|
|
15305
|
+
// - chat scope:没有任何消息存在,铸造 daemon-owned 合成 turn id(同 trigger
|
|
15306
|
+
// 会话的 trg_ 约定),仅作身份标识,不冒充用户消息 id。
|
|
15307
|
+
const joinTurnId = scope === 'thread' ? anchor : `join_${randomUUID()}`;
|
|
15095
15308
|
const dsKey = sessionKey(anchor, larkAppId);
|
|
15096
15309
|
if (activeSessions.has(dsKey)) {
|
|
15097
15310
|
logger.info(`[auto-start:入群] ${chatId.substring(0, 12)} 锚点已有会话,跳过`);
|
|
@@ -15134,7 +15347,9 @@ async function handleBotAdded(chatId, operatorOpenId, larkAppId, opts) {
|
|
|
15134
15347
|
ownerOpenId: operatorOpenId,
|
|
15135
15348
|
currentTurnTitle: title,
|
|
15136
15349
|
workingDir: pinnedWorkingDir,
|
|
15137
|
-
|
|
15350
|
+
// 非 shared 路径的首轮 turn 身份(joinTurnId);shared 路径由
|
|
15351
|
+
// armSharedReplyTarget 用 shared seed id 覆盖。
|
|
15352
|
+
pendingTurnId: needsSharedReply ? undefined : joinTurnId,
|
|
15138
15353
|
};
|
|
15139
15354
|
const registration = await claimNewDaemonSession(activeSessions, ds);
|
|
15140
15355
|
if (!registration.accepted) {
|
|
@@ -15147,7 +15362,9 @@ async function handleBotAdded(chatId, operatorOpenId, larkAppId, opts) {
|
|
|
15147
15362
|
stageClaimedPendingRepoSetup(activeSessions, ds, {
|
|
15148
15363
|
mode: autoWt ? 'auto_worktree' : 'picker',
|
|
15149
15364
|
...(autoWt && pinnedWorkingDir ? { baseDir: pinnedWorkingDir } : {}),
|
|
15150
|
-
|
|
15365
|
+
// 非 shared 路径复用首轮 turn 身份;shared 路径保留 anchor(随后被
|
|
15366
|
+
// armSharedReplyTarget 的 shared seed id 覆盖,此处仅作未 arm 时的兜底)。
|
|
15367
|
+
turnId: needsSharedReply ? anchor : joinTurnId,
|
|
15151
15368
|
});
|
|
15152
15369
|
}
|
|
15153
15370
|
const joinBootstrapExternallyTakenOver = () => (activeSessions.get(dsKey) !== ds
|
|
@@ -15194,6 +15411,11 @@ async function handleBotAdded(chatId, operatorOpenId, larkAppId, opts) {
|
|
|
15194
15411
|
const closing = closeSessionHelper(session.sessionId);
|
|
15195
15412
|
if (activeSessions.get(dsKey) === ds)
|
|
15196
15413
|
activeSessions.delete(dsKey);
|
|
15414
|
+
// 入群去重锚点同样只清自己登记的那条:shared 路径在登记锚点之前就可能
|
|
15415
|
+
// 回滚(此时 get 为 undefined,no-op);非 shared 路径在锚点登记之后
|
|
15416
|
+
// 回滚,不清掉会让后续 bot.added 带着 stale 锚点走进来。
|
|
15417
|
+
if (groupJoinAnchorByChat.get(chatLiveKey) === dsKey)
|
|
15418
|
+
groupJoinAnchorByChat.delete(chatLiveKey);
|
|
15197
15419
|
await closing;
|
|
15198
15420
|
};
|
|
15199
15421
|
// Shared-mode seed/reply authority is externally visible. Publish it only
|
|
@@ -15244,6 +15466,28 @@ async function handleBotAdded(chatId, operatorOpenId, larkAppId, opts) {
|
|
|
15244
15466
|
// Register the anchor so a later duplicate bot.added for this chat is deduped
|
|
15245
15467
|
// even in 话题群 (where dsKey is the seed id, not chatId).
|
|
15246
15468
|
groupJoinAnchorByChat.set(chatLiveKey, dsKey);
|
|
15469
|
+
// 持久化非 shared 首轮的 turn provenance(shared 路径已由 armSharedReplyTarget
|
|
15470
|
+
// 写入)。thread scope 以 seed 为 reply root;chat scope 无根,落 plain chat
|
|
15471
|
+
// 目标且不写 sender——首轮无真人发送者,--mention 回指天然走 incomplete →
|
|
15472
|
+
// 显式指定的安全方向。没有这条记录,worker 虽带 turnId fork,daemon 侧的
|
|
15473
|
+
// 首轮回复目标/参与者窗口仍无据可查。
|
|
15474
|
+
if (!needsSharedReply) {
|
|
15475
|
+
try {
|
|
15476
|
+
beginReplyTargetTurn(ds, scope === 'thread' ? anchor : undefined, joinTurnId, new Date(now).toISOString());
|
|
15477
|
+
sessionStore.updateSession(ds.session);
|
|
15478
|
+
}
|
|
15479
|
+
catch (err) {
|
|
15480
|
+
// 持久化失败(文件系统/数据库瞬态错误)时必须回滚已发布的会话:此时
|
|
15481
|
+
// 会话已进 activeSessions 且 groupJoinAnchorByChat 已登记,finally 只
|
|
15482
|
+
// settle barrier 和释放 in-flight 锁——留下 active 但 worker-null 的会话
|
|
15483
|
+
// 会让后续 bot.added 被无限去重,自动开工无法重试。同
|
|
15484
|
+
// stageClaimedPendingRepoSetup 的 unpublish/close 回滚。
|
|
15485
|
+
logger.warn(`[auto-start:入群] ${chatId.substring(0, 12)} 首轮 turn provenance 持久化失败,回滚会话注册:`
|
|
15486
|
+
+ `${err instanceof Error ? err.message : String(err)}`);
|
|
15487
|
+
await rollbackRegisteredJoinSession();
|
|
15488
|
+
return;
|
|
15489
|
+
}
|
|
15490
|
+
}
|
|
15247
15491
|
// Auto-worktree: register PENDING, build worktree off-path, commit+fork later.
|
|
15248
15492
|
if (pinnedWorkingDir && autoWt) {
|
|
15249
15493
|
if (await replyInvalidWorkingDirs(anchor, larkAppId, ds) || joinBootstrapWasTakenOver()) {
|
|
@@ -15347,17 +15591,10 @@ export const __testOnly_handleBotAdded = handleBotAdded;
|
|
|
15347
15591
|
* than blocking the message.
|
|
15348
15592
|
*/
|
|
15349
15593
|
function lookupForeignBotName(senderOpenId, larkAppId) {
|
|
15350
|
-
|
|
15351
|
-
|
|
15352
|
-
|
|
15353
|
-
const data = JSON.parse(readFileSync(fp, 'utf-8'));
|
|
15354
|
-
for (const [name, openId] of Object.entries(data)) {
|
|
15355
|
-
if (openId === senderOpenId)
|
|
15356
|
-
return name;
|
|
15357
|
-
}
|
|
15358
|
-
}
|
|
15594
|
+
for (const [name, openId] of Object.entries(readPeerCrossRef(config.session.dataDir, larkAppId))) {
|
|
15595
|
+
if (openId === senderOpenId)
|
|
15596
|
+
return name;
|
|
15359
15597
|
}
|
|
15360
|
-
catch { /* fall through */ }
|
|
15361
15598
|
try {
|
|
15362
15599
|
const infoPath = join(config.session.dataDir, 'bots-info.json');
|
|
15363
15600
|
if (existsSync(infoPath)) {
|
|
@@ -15488,6 +15725,7 @@ async function handleThreadReplyAdmitted(data, ctx, prepared) {
|
|
|
15488
15725
|
// 类型的话,把真人 union_id 报成 bot 就能让真人在全团队被当队友 bot 放行
|
|
15489
15726
|
//(talk + operate)。与旧联邦 team-bots「学习入口限 bot sender」同一不变量。
|
|
15490
15727
|
const threadTeamTrustUnionId = (isBotSenderType || isForeignBot) ? threadSenderUnionId : undefined;
|
|
15728
|
+
const threadTrustedCaller = trustedCallerForTurn(larkAppId, threadSenderOpenId, threadSenderUnionId);
|
|
15491
15729
|
const threadChatId = ctxChatId ?? data?.message?.chat_id;
|
|
15492
15730
|
const clearAgentAttentionForHumanInbound = () => {
|
|
15493
15731
|
if (isForeignBot || isBotSenderType)
|
|
@@ -15546,6 +15784,10 @@ async function handleThreadReplyAdmitted(data, ctx, prepared) {
|
|
|
15546
15784
|
// `/template` 只保留退役提示。
|
|
15547
15785
|
const threadGrill = parseWorkflowGrillTrigger(cmdContent);
|
|
15548
15786
|
if (threadGrill) {
|
|
15787
|
+
if (!isWorkflowFeatureEnabled()) {
|
|
15788
|
+
await sessionReply(anchor, WORKFLOW_DISABLED_MESSAGE, 'text', larkAppId);
|
|
15789
|
+
return;
|
|
15790
|
+
}
|
|
15549
15791
|
if (await replyGrantRestrictionIfNeeded(larkAppId, threadChatId, threadSenderOpenId, anchor, '/workflow')) {
|
|
15550
15792
|
return;
|
|
15551
15793
|
}
|
|
@@ -15785,35 +16027,38 @@ async function handleThreadReplyAdmitted(data, ctx, prepared) {
|
|
|
15785
16027
|
// 回调 URL 已在上方 return,可用来中止)。答复权限 = canTalk,由
|
|
15786
16028
|
// broker 在 submitCustomReply 内按注入的 canTalkChecker 判定:非授权人返回
|
|
15787
16029
|
// 'unauthorized',这里 fall through 到正常路由。卡片由 broker.onSettle 自动 PATCH。
|
|
15788
|
-
//
|
|
15789
|
-
//
|
|
15790
|
-
|
|
15791
|
-
|
|
15792
|
-
|
|
15793
|
-
|
|
15794
|
-
|
|
15795
|
-
|
|
15796
|
-
|
|
15797
|
-
|
|
15798
|
-
|
|
15799
|
-
|
|
15800
|
-
|
|
15801
|
-
|
|
15802
|
-
|
|
15803
|
-
|
|
15804
|
-
|
|
15805
|
-
|
|
15806
|
-
|
|
15807
|
-
|
|
15808
|
-
|
|
15809
|
-
|
|
15810
|
-
|
|
15811
|
-
|
|
15812
|
-
|
|
15813
|
-
|
|
15814
|
-
|
|
15815
|
-
|
|
16030
|
+
// 「哪些消息算纯文字答复」收口在 askCustomReplyCandidate(含带资源消息与 grill
|
|
16031
|
+
// 触发的排除理由),拦截器这里只负责拿着结果去 settle。
|
|
16032
|
+
const askCandidate = askCustomReplyCandidate({
|
|
16033
|
+
senderOpenId: threadSenderOpenId,
|
|
16034
|
+
chatId: threadChatId,
|
|
16035
|
+
cmdContent,
|
|
16036
|
+
resourceCount: resources.length,
|
|
16037
|
+
isWorkflowGrillTrigger: !!threadGrill,
|
|
16038
|
+
});
|
|
16039
|
+
if (askCandidate) {
|
|
16040
|
+
const pendingAsk = findPendingAskByAnchor({ larkAppId, chatId: askCandidate.chatId, anchor });
|
|
16041
|
+
if (pendingAsk) {
|
|
16042
|
+
const outcome = submitCustomReply({
|
|
16043
|
+
askId: pendingAsk.askId,
|
|
16044
|
+
by: askCandidate.senderOpenId,
|
|
16045
|
+
text: askCandidate.text,
|
|
16046
|
+
// Actor context so the broker's talk check uses the same predicate as
|
|
16047
|
+
// the dispatcher gate / quota recheck: a bot text-reply → evaluateBotTalk
|
|
16048
|
+
// (covers team-拉群 with no union_id), a platform teamMember human →
|
|
16049
|
+
// evaluateTalk's teamMember union leg. Omitting it (card clicks) degrades
|
|
16050
|
+
// to the plain evaluateTalk(openId, chatType).
|
|
16051
|
+
actor: {
|
|
16052
|
+
botSender: isBotSenderType || isForeignBot,
|
|
16053
|
+
senderUnionId: threadTeamTrustUnionId,
|
|
16054
|
+
memberUnionId: threadSenderUnionId,
|
|
16055
|
+
},
|
|
16056
|
+
});
|
|
16057
|
+
if (outcome === 'accepted') {
|
|
16058
|
+
logger.info(`[${anchor.substring(0, 12)}] ask custom reply accepted from ${askCandidate.senderOpenId.substring(0, 12)}`);
|
|
16059
|
+
return;
|
|
15816
16060
|
}
|
|
16061
|
+
logger.info(`[${anchor.substring(0, 12)}] ask custom reply not accepted (${outcome}); falling through to normal routing`);
|
|
15817
16062
|
}
|
|
15818
16063
|
}
|
|
15819
16064
|
logger.info(`Reply in ${scope}-scope session ${anchor.substring(0, 12)}: ${content.substring(0, 100)} (resources: ${resources.length})`);
|
|
@@ -16402,7 +16647,7 @@ async function handleThreadReplyAdmitted(data, ctx, prepared) {
|
|
|
16402
16647
|
ensureSessionWhiteboard(newDs);
|
|
16403
16648
|
const availableBots = await getAvailableBots(larkAppId, autoCreateChatId);
|
|
16404
16649
|
await noteTurnReceived(newDs, parsed.messageId, parsed.content, autoCreateSender, parsed.messageId, substituteTrigger ? SUBSTITUTE_RECEIVED_REACTION_EMOJI_TYPE : undefined);
|
|
16405
|
-
forkReservedInitialSession(newDs, availableBots);
|
|
16650
|
+
forkReservedInitialSession(newDs, availableBots, threadTrustedCaller);
|
|
16406
16651
|
// fork 成功即开场已交给 CLI;fork 抛错则开场只存在于内存,保持重发提示。
|
|
16407
16652
|
markIngressAdmitted(ctx);
|
|
16408
16653
|
const reason = oncallEntry
|
|
@@ -16442,7 +16687,7 @@ async function handleThreadReplyAdmitted(data, ctx, prepared) {
|
|
|
16442
16687
|
ensureSessionWhiteboard(newDs);
|
|
16443
16688
|
const availableBots = await getAvailableBots(larkAppId, autoCreateChatId);
|
|
16444
16689
|
await noteTurnReceived(newDs, parsed.messageId, parsed.content, autoCreateSender, parsed.messageId, substituteTrigger ? SUBSTITUTE_RECEIVED_REACTION_EMOJI_TYPE : undefined);
|
|
16445
|
-
forkReservedInitialSession(newDs, availableBots);
|
|
16690
|
+
forkReservedInitialSession(newDs, availableBots, threadTrustedCaller);
|
|
16446
16691
|
}
|
|
16447
16692
|
return;
|
|
16448
16693
|
}
|
|
@@ -16520,7 +16765,10 @@ async function handleThreadReplyAdmitted(data, ctx, prepared) {
|
|
|
16520
16765
|
// above (R4-B1); reuse the same frozen value here for the live-worker path.
|
|
16521
16766
|
let accepted = false;
|
|
16522
16767
|
try {
|
|
16523
|
-
accepted = sendWorkerInput(ds, cliInput, parsed.messageId,
|
|
16768
|
+
accepted = sendWorkerInput(ds, cliInput, parsed.messageId, {
|
|
16769
|
+
...(codexAppSteerable ? { codexAppSteerable: true } : {}),
|
|
16770
|
+
...(threadTrustedCaller ? { trustedCaller: threadTrustedCaller } : {}),
|
|
16771
|
+
});
|
|
16524
16772
|
// Record the input as the session's last real CLI turn ONLY after the
|
|
16525
16773
|
// worker accepted it. Recording before delivery (the old order) persisted
|
|
16526
16774
|
// lastCliInput / lastUserPrompt / Codex-App sidecar for a turn that never
|
|
@@ -16616,6 +16864,8 @@ async function handleThreadReplyAdmitted(data, ctx, prepared) {
|
|
|
16616
16864
|
// here, never re-inferred). System/recovery openings keep it absent.
|
|
16617
16865
|
if (codexAppSteerable)
|
|
16618
16866
|
currentFollowUp.codexAppSteerable = true;
|
|
16867
|
+
if (threadTrustedCaller)
|
|
16868
|
+
currentFollowUp.trustedCaller = threadTrustedCaller;
|
|
16619
16869
|
admitQueuedActivationTail(ds, {
|
|
16620
16870
|
userPrompt: promptContent,
|
|
16621
16871
|
cliInput: currentFollowUp,
|
|
@@ -16642,6 +16892,9 @@ async function handleThreadReplyAdmitted(data, ctx, prepared) {
|
|
|
16642
16892
|
resume: ds.session.queuedActivationResume ?? ds.hasHistory,
|
|
16643
16893
|
turnId: ds.session.queuedActivationTurnId,
|
|
16644
16894
|
dispatchAttempt: ds.session.queuedActivationDispatchAttempt,
|
|
16895
|
+
...(ds.session.queuedActivationInput?.trustedCaller
|
|
16896
|
+
? { trustedCaller: ds.session.queuedActivationInput.trustedCaller }
|
|
16897
|
+
: {}),
|
|
16645
16898
|
});
|
|
16646
16899
|
if (ownsInitialStartClaim())
|
|
16647
16900
|
retainInitialStartClaim = true;
|
|
@@ -16667,6 +16920,7 @@ async function handleThreadReplyAdmitted(data, ctx, prepared) {
|
|
|
16667
16920
|
resume: ds.hasHistory,
|
|
16668
16921
|
turnId: ds.session.queuedActivationTurnId,
|
|
16669
16922
|
dispatchAttempt: ds.session.queuedActivationDispatchAttempt,
|
|
16923
|
+
...(retainedQueuedActivation.trustedCaller ? { trustedCaller: retainedQueuedActivation.trustedCaller } : {}),
|
|
16670
16924
|
});
|
|
16671
16925
|
if (ownsInitialStartClaim())
|
|
16672
16926
|
retainInitialStartClaim = true;
|
|
@@ -16789,6 +17043,9 @@ async function handleThreadReplyAdmitted(data, ctx, prepared) {
|
|
|
16789
17043
|
if (codexAppSteerable && !queuedDashboardTurn && !queuedHasDurableTail) {
|
|
16790
17044
|
wrappedInput.codexAppSteerable = true;
|
|
16791
17045
|
}
|
|
17046
|
+
if (threadTrustedCaller && !queuedHasDurableTail) {
|
|
17047
|
+
wrappedInput.trustedCaller = threadTrustedCaller;
|
|
17048
|
+
}
|
|
16792
17049
|
reforkAccepted = forkWorker(ds, wrappedInput, {
|
|
16793
17050
|
// See `hadPriorCliInput` above — an opening on a CLI that never took any
|
|
16794
17051
|
// input cold-spawns rather than `--resume`-ing an empty session.
|
|
@@ -16796,6 +17053,7 @@ async function handleThreadReplyAdmitted(data, ctx, prepared) {
|
|
|
16796
17053
|
turnId: queuedHasDurableTail
|
|
16797
17054
|
? (ds.session.queuedActivationTurnId ?? `queued-opening:${ds.session.sessionId}`)
|
|
16798
17055
|
: parsed.messageId,
|
|
17056
|
+
...(wrappedInput.trustedCaller ? { trustedCaller: wrappedInput.trustedCaller } : {}),
|
|
16799
17057
|
});
|
|
16800
17058
|
}
|
|
16801
17059
|
}
|
|
@@ -17476,6 +17734,18 @@ async function waitForManagedActivationCommit(index, appId) {
|
|
|
17476
17734
|
}
|
|
17477
17735
|
}
|
|
17478
17736
|
export async function startDaemon(botIndex) {
|
|
17737
|
+
// Survive a fire-and-forget rejection instead of dying from it. Installed here
|
|
17738
|
+
// rather than in index-daemon.ts on purpose: startDaemon has TWO entry points
|
|
17739
|
+
// (index-daemon.ts and index-core-only.ts), so guarding the entry file would
|
|
17740
|
+
// leave the other one unprotected. Idempotent, so an entry point may also call
|
|
17741
|
+
// it earlier without harm.
|
|
17742
|
+
//
|
|
17743
|
+
// Node's default is to terminate the process, which is right for a worker (it
|
|
17744
|
+
// owns one session) and wrong for the daemon (it owns every session): one
|
|
17745
|
+
// missed `.catch` on one session's teardown would otherwise end every other
|
|
17746
|
+
// live Lark session too. The rejection is logged loudly at error level — this
|
|
17747
|
+
// is a backstop for the next missed `.catch`, not permission to omit them.
|
|
17748
|
+
installDaemonRejectionGuard(logger);
|
|
17479
17749
|
// Repair a shared tmux server polluted by an older botmux immediately on
|
|
17480
17750
|
// daemon startup. This must not depend on restoring/spawning a bmx-* session:
|
|
17481
17751
|
// a user-held tmux server can outlive every botmux pane and still leak stale
|
|
@@ -17892,8 +18162,7 @@ export async function startDaemon(botIndex) {
|
|
|
17892
18162
|
// status becomes `closed` → trigger-result resolves `failed` (soft terminal),
|
|
17893
18163
|
// and resolveIdempotencyHit sees a not-live session on retry. This is the
|
|
17894
18164
|
// observable fail-closed path the round-8 finding requires.
|
|
17895
|
-
void
|
|
17896
|
-
logger.error(`[idempotency] fail-closed session ${ds.session.sessionId.slice(0, 8)} after exit-convergence write failure`);
|
|
18165
|
+
void runIdempotencyFailClose(ds.session.sessionId, closeSessionForBackgroundCleanup, logger);
|
|
17897
18166
|
}
|
|
17898
18167
|
};
|
|
17899
18168
|
// Initialise worker pool with daemon callbacks
|
|
@@ -17914,9 +18183,7 @@ export async function startDaemon(botIndex) {
|
|
|
17914
18183
|
logger.info(`[${sessionId.substring(0, 8)}] Withdraw auto-close deferred: Codex App FIFO became unsettled`);
|
|
17915
18184
|
return false;
|
|
17916
18185
|
}
|
|
17917
|
-
|
|
17918
|
-
logger.info(`[${sessionId.substring(0, 8)}] Session auto-closed (message withdrawn)`);
|
|
17919
|
-
return true;
|
|
18186
|
+
return runWithdrawAutoClose(sessionId, closeSessionForBackgroundCleanup, logger);
|
|
17920
18187
|
}).catch((err) => {
|
|
17921
18188
|
logger.warn(`[${sessionId.substring(0, 8)}] Withdraw auto-close mutation failed; session retained: `
|
|
17922
18189
|
+ `${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -18039,6 +18306,20 @@ export async function startDaemon(botIndex) {
|
|
|
18039
18306
|
logger.error(`[idempotency] boot reconcile failed to converge — aborting bot startup (fail-closed): ${err instanceof Error ? err.message : err}`);
|
|
18040
18307
|
throw err instanceof Error ? err : new Error(String(err));
|
|
18041
18308
|
}
|
|
18309
|
+
// Release durable mojo containment handles a REBOOT provably killed, BEFORE the
|
|
18310
|
+
// device-isolation activation inventory ever synthesises a blocker from them —
|
|
18311
|
+
// otherwise a post-reboot handle keeps blocking activation forever (round-11
|
|
18312
|
+
// P1-1). Daemon-global and idempotent: guarded so it runs once no matter how
|
|
18313
|
+
// many bots start; any store/proc read failure fails closed inside the helper.
|
|
18314
|
+
if (!mojoContainmentReconciledThisBoot) {
|
|
18315
|
+
mojoContainmentReconciledThisBoot = true;
|
|
18316
|
+
try {
|
|
18317
|
+
reconcileContainmentHandlesOnBoot();
|
|
18318
|
+
}
|
|
18319
|
+
catch (err) {
|
|
18320
|
+
logger.warn(`[mojo] containment boot reconciliation threw (blockers retained): ${err instanceof Error ? err.message : String(err)}`);
|
|
18321
|
+
}
|
|
18322
|
+
}
|
|
18042
18323
|
// Seed dashboard IPC botName with the custom displayName (falling back to the
|
|
18043
18324
|
// bot's config id); the friendly name from /bot/v3/info is wired into the
|
|
18044
18325
|
// registry descriptor (below) but the IPC server also needs its own copy for
|
|
@@ -18401,6 +18682,12 @@ export async function startDaemon(botIndex) {
|
|
|
18401
18682
|
// Restore complete → /api/asks may now safely 403 unknown sessions again; a
|
|
18402
18683
|
// reconnecting ask hook that raced the restore got retryable 503s until here.
|
|
18403
18684
|
sessionsRestored = true;
|
|
18685
|
+
// Freeze the control plane of restored mojo sessions NOW, not at their next
|
|
18686
|
+
// worker fork. Restore completes before the dispatcher can deliver a message,
|
|
18687
|
+
// so this closes the window where an operator edits the bot's endpoint/workspace
|
|
18688
|
+
// between the restart and a session's next wake — which would otherwise let that
|
|
18689
|
+
// session adopt the NEW control plane as its original identity.
|
|
18690
|
+
migrateMojoSessionIdentities(activeSessions);
|
|
18404
18691
|
// Now that activeSessions is populated, release the forward-followup flush
|
|
18405
18692
|
// barrier. Persisted seeds were loaded into the buffer at dispatcher startup
|
|
18406
18693
|
// (so root-linked clarifications can pair with them), but their flushes wait
|
|
@@ -18529,6 +18816,45 @@ export async function startDaemon(botIndex) {
|
|
|
18529
18816
|
enforceLiveSessionCap('periodic');
|
|
18530
18817
|
}, 60_000);
|
|
18531
18818
|
idleWorkerSweepTimer.unref?.();
|
|
18819
|
+
const sessionOwnerReminder = new SessionOwnerReminderController({
|
|
18820
|
+
load: () => loadSessionOwnerReminderRecords(config.session.dataDir, cfg.larkAppId),
|
|
18821
|
+
save: records => saveSessionOwnerReminderRecords(config.session.dataDir, cfg.larkAppId, records),
|
|
18822
|
+
canSend: ds => larkTransportEnabled({
|
|
18823
|
+
chatId: ds.chatId,
|
|
18824
|
+
apiOnly: getBot(ds.larkAppId).config.apiOnly,
|
|
18825
|
+
}),
|
|
18826
|
+
send: async (ds, text, uuid) => {
|
|
18827
|
+
await sendSessionOwnerThreadNotification({
|
|
18828
|
+
larkAppId: ds.larkAppId,
|
|
18829
|
+
rootMessageId: ds.session.rootMessageId,
|
|
18830
|
+
ownerOpenId: ds.session.ownerOpenId,
|
|
18831
|
+
}, text, uuid);
|
|
18832
|
+
},
|
|
18833
|
+
onError: (ds, error) => logger.warn(`[session-owner-reminder] send failed session=${ds.session.sessionId}: `
|
|
18834
|
+
+ `${error instanceof Error ? error.message : String(error)}`),
|
|
18835
|
+
});
|
|
18836
|
+
let sessionOwnerReminderScanInFlight = false;
|
|
18837
|
+
const scanSessionOwnerReminders = async () => {
|
|
18838
|
+
if (sessionOwnerReminderScanInFlight)
|
|
18839
|
+
return;
|
|
18840
|
+
sessionOwnerReminderScanInFlight = true;
|
|
18841
|
+
try {
|
|
18842
|
+
const currentConfig = getBot(cfg.larkAppId).config.sessionOwnerReminder
|
|
18843
|
+
?? DEFAULT_SESSION_OWNER_REMINDER;
|
|
18844
|
+
await sessionOwnerReminder.scan(activeSessions.values(), currentConfig);
|
|
18845
|
+
}
|
|
18846
|
+
catch (error) {
|
|
18847
|
+
logger.warn(`[session-owner-reminder] scan failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
18848
|
+
}
|
|
18849
|
+
finally {
|
|
18850
|
+
sessionOwnerReminderScanInFlight = false;
|
|
18851
|
+
}
|
|
18852
|
+
};
|
|
18853
|
+
const sessionOwnerReminderTimer = setInterval(() => {
|
|
18854
|
+
void scanSessionOwnerReminders();
|
|
18855
|
+
}, 60_000);
|
|
18856
|
+
sessionOwnerReminderTimer.unref?.();
|
|
18857
|
+
void scanSessionOwnerReminders();
|
|
18532
18858
|
// Periodic sandbox reconciler: the daemon's SIGKILL straggler-reaper (and any
|
|
18533
18859
|
// worker SIGKILL) bypasses worker-side killCli(), so the pre-created deny-mask
|
|
18534
18860
|
// mountpoints + per-session tree of a killed-but-still-active sandboxed session
|
|
@@ -18707,8 +19033,8 @@ export async function startDaemon(botIndex) {
|
|
|
18707
19033
|
}, 30_000);
|
|
18708
19034
|
overloadTimer.unref?.();
|
|
18709
19035
|
}
|
|
18710
|
-
// Graceful shutdown.
|
|
18711
|
-
// that durably ACKs every exact final
|
|
19036
|
+
// Graceful shutdown. Remote owners first run a three-phase non-cancelling
|
|
19037
|
+
// drain that durably ACKs every exact final lineage as one fleet transaction.
|
|
18712
19038
|
// No worker exits until every participant is prepared and fresh-verified.
|
|
18713
19039
|
// Ordinary workers then receive SIGTERM / close IPC and the daemon waits up
|
|
18714
19040
|
// to DAEMON_WORKER_EXIT_GRACE_MS for them to exit
|
|
@@ -18735,23 +19061,23 @@ export async function startDaemon(botIndex) {
|
|
|
18735
19061
|
logger.error(`Daemon remains online: ${initialShutdownFleet.error}`);
|
|
18736
19062
|
return;
|
|
18737
19063
|
}
|
|
18738
|
-
// Preflight
|
|
19064
|
+
// Preflight all remote backends before stopping services/removing descriptors. A failed
|
|
18739
19065
|
// drain or persistence write aborts every successfully prepared peer, so a
|
|
18740
19066
|
// refused shutdown returns to a live fleet instead of leaving an early
|
|
18741
19067
|
// participant workerless.
|
|
18742
|
-
const
|
|
18743
|
-
.filter(ds => shutdownBackendDisposition(ds) === '
|
|
18744
|
-
const
|
|
19068
|
+
const remoteCandidates = initialShutdownFleet.sessions
|
|
19069
|
+
.filter(ds => shutdownBackendDisposition(ds) === 'remote-drain-detach');
|
|
19070
|
+
const remotePrepareResults = await prepareRemoteFleetForShutdown(remoteCandidates, {
|
|
18745
19071
|
deadlineMs: shutdownDeadlineMs,
|
|
18746
19072
|
});
|
|
18747
|
-
const
|
|
18748
|
-
const
|
|
18749
|
-
const
|
|
19073
|
+
const remotePrepared = remotePrepareResults.filter((entry) => entry.result.ok);
|
|
19074
|
+
const remoteFenced = remotePrepareResults.filter((entry) => entry.result.fence !== 'none');
|
|
19075
|
+
const abortRemoteFleet = async (reason, retainFenced = new Set()) => {
|
|
18750
19076
|
for (const ds of retainFenced) {
|
|
18751
|
-
logger.error(`[${ds.session.sessionId.slice(0, 8)}]
|
|
19077
|
+
logger.error(`[${ds.session.sessionId.slice(0, 8)}] Remote shutdown participant remains fenced: `
|
|
18752
19078
|
+ 'durable/runtime ownership could not be reconciled safely');
|
|
18753
19079
|
}
|
|
18754
|
-
const aborts = await
|
|
19080
|
+
const aborts = await abortRemoteShutdownFleet(remoteFenced
|
|
18755
19081
|
.filter(({ ds }) => !retainFenced.has(ds))
|
|
18756
19082
|
.map(({ ds, result }) => ({ ds, result })), {
|
|
18757
19083
|
deadlineMs: shutdownDeadlineMs,
|
|
@@ -18759,34 +19085,34 @@ export async function startDaemon(botIndex) {
|
|
|
18759
19085
|
for (const { ds, result } of aborts) {
|
|
18760
19086
|
if (result.ok)
|
|
18761
19087
|
continue;
|
|
18762
|
-
logger.error(`[${ds.session.sessionId.slice(0, 8)}]
|
|
19088
|
+
logger.error(`[${ds.session.sessionId.slice(0, 8)}] Remote shutdown rollback was not ACKed: `
|
|
18763
19089
|
+ `${result.error ?? 'unknown'}; admission remains fail-closed`);
|
|
18764
19090
|
}
|
|
18765
19091
|
setSessionLifecycleShutdown(false);
|
|
18766
19092
|
shuttingDown = false;
|
|
18767
19093
|
logger.error(`Daemon remains online: ${reason}`);
|
|
18768
19094
|
};
|
|
18769
|
-
const
|
|
18770
|
-
if (
|
|
18771
|
-
for (const { ds, result } of
|
|
19095
|
+
const remotePrepareFailures = remotePrepareResults.filter(entry => !entry.result.ok);
|
|
19096
|
+
if (remotePrepareFailures.length > 0) {
|
|
19097
|
+
for (const { ds, result } of remotePrepareFailures) {
|
|
18772
19098
|
if (result.ok)
|
|
18773
19099
|
continue;
|
|
18774
19100
|
logger.error(`[${ds.session.sessionId.slice(0, 8)}] Daemon shutdown prepare refused: `
|
|
18775
19101
|
+ `${result.error}${result.taskId ? ` (task ${result.taskId})` : ''}`);
|
|
18776
19102
|
}
|
|
18777
|
-
await
|
|
19103
|
+
await abortRemoteFleet(`${remotePrepareFailures.length} remote owner(s) could not be safely drained`);
|
|
18778
19104
|
return;
|
|
18779
19105
|
}
|
|
18780
|
-
const
|
|
19106
|
+
const remotePersistence = persistPreparedRemoteShutdownFleet(remotePrepared, {
|
|
18781
19107
|
deadlineMs: shutdownDeadlineMs,
|
|
18782
19108
|
});
|
|
18783
|
-
if (!
|
|
18784
|
-
const retainIds = new Set(
|
|
18785
|
-
const retainFenced = new Set(
|
|
19109
|
+
if (!remotePersistence.ok) {
|
|
19110
|
+
const retainIds = new Set(remotePersistence.retainFencedSessionIds);
|
|
19111
|
+
const retainFenced = new Set(remotePrepared
|
|
18786
19112
|
.filter(({ ds }) => retainIds.has(ds.session.sessionId))
|
|
18787
19113
|
.map(({ ds }) => ds));
|
|
18788
|
-
logger.error(`Daemon shutdown lineage verification refused: ${
|
|
18789
|
-
await
|
|
19114
|
+
logger.error(`Daemon shutdown lineage verification refused: ${remotePersistence.error}`);
|
|
19115
|
+
await abortRemoteFleet(`${remotePersistence.sessionIds.length} remote lineage row(s) could not be fresh-verified`, retainFenced);
|
|
18790
19116
|
return;
|
|
18791
19117
|
}
|
|
18792
19118
|
// Recheck generation ownership while every participant is still fenced and
|
|
@@ -18794,33 +19120,33 @@ export async function startDaemon(botIndex) {
|
|
|
18794
19120
|
const currentShutdownFleet = collectUniqueDaemonShutdownSessions(activeSessions.values());
|
|
18795
19121
|
if (!currentShutdownFleet.ok) {
|
|
18796
19122
|
const ambiguousSessionId = currentShutdownFleet.sessionId;
|
|
18797
|
-
await
|
|
19123
|
+
await abortRemoteFleet(`Remote ownership became ambiguous after shutdown preflight: ${currentShutdownFleet.error}`, new Set(remotePrepared
|
|
18798
19124
|
.filter(({ ds }) => ds.session.sessionId === ambiguousSessionId)
|
|
18799
19125
|
.map(({ ds }) => ds)));
|
|
18800
19126
|
return;
|
|
18801
19127
|
}
|
|
18802
|
-
const
|
|
18803
|
-
.filter(ds => shutdownBackendDisposition(ds) === '
|
|
18804
|
-
const
|
|
18805
|
-
const
|
|
18806
|
-
||
|
|
18807
|
-
if (
|
|
18808
|
-
const retainFenced = new Set(
|
|
18809
|
-
.filter(({ ds, result }) => (!
|
|
18810
|
-
&& !
|
|
19128
|
+
const currentRemoteOwners = currentShutdownFleet.sessions
|
|
19129
|
+
.filter(ds => shutdownBackendDisposition(ds) === 'remote-drain-detach');
|
|
19130
|
+
const remotePreparedOwners = new Set(remotePrepared.map(entry => entry.ds));
|
|
19131
|
+
const remoteGenerationMismatch = currentRemoteOwners.some(ds => !remotePreparedOwners.has(ds))
|
|
19132
|
+
|| remotePrepared.some(({ ds, result }) => !currentRemoteOwners.includes(ds) || !isPreparedRemoteSessionCurrent(ds, result));
|
|
19133
|
+
if (remoteGenerationMismatch) {
|
|
19134
|
+
const retainFenced = new Set(remotePrepared
|
|
19135
|
+
.filter(({ ds, result }) => (!currentRemoteOwners.includes(ds) || !isPreparedRemoteSessionCurrent(ds, result))
|
|
19136
|
+
&& !canAbortVerifiedExitedRemotePreparation(ds, result))
|
|
18811
19137
|
.map(({ ds }) => ds));
|
|
18812
|
-
await
|
|
19138
|
+
await abortRemoteFleet('Remote ownership changed after shutdown preflight', retainFenced);
|
|
18813
19139
|
return;
|
|
18814
19140
|
}
|
|
18815
19141
|
// Validate-all above, then commit-all synchronously with no await or
|
|
18816
19142
|
// callback boundary between peers.
|
|
18817
|
-
const
|
|
18818
|
-
for (const { ds, result } of
|
|
18819
|
-
if (!
|
|
18820
|
-
throw new Error(`
|
|
19143
|
+
const remoteRetiredWorkers = [];
|
|
19144
|
+
for (const { ds, result } of remotePrepared) {
|
|
19145
|
+
if (!commitPreparedRemoteShutdown(ds, result)) {
|
|
19146
|
+
throw new Error(`Remote shutdown commit invariant lost for ${ds.session.sessionId}`);
|
|
18821
19147
|
}
|
|
18822
19148
|
if (result.worker)
|
|
18823
|
-
|
|
19149
|
+
remoteRetiredWorkers.push(result.worker);
|
|
18824
19150
|
}
|
|
18825
19151
|
scheduler.stopScheduler();
|
|
18826
19152
|
// NOTE: turn-terminal queue drain + webhook dispatcher stop are deliberately
|
|
@@ -18860,6 +19186,7 @@ export async function startDaemon(botIndex) {
|
|
|
18860
19186
|
deleteVcMeetingPendingInvite(key);
|
|
18861
19187
|
clearInterval(descriptorHeartbeat);
|
|
18862
19188
|
clearInterval(idleWorkerSweepTimer);
|
|
19189
|
+
clearInterval(sessionOwnerReminderTimer);
|
|
18863
19190
|
if (memoryDiagnostics)
|
|
18864
19191
|
clearInterval(memoryDiagnostics);
|
|
18865
19192
|
removeDaemonDescriptor(cfg.larkAppId);
|
|
@@ -18905,7 +19232,10 @@ export async function startDaemon(botIndex) {
|
|
|
18905
19232
|
}
|
|
18906
19233
|
}
|
|
18907
19234
|
};
|
|
18908
|
-
|
|
19235
|
+
// Union of two renames: this branch generalised the collection
|
|
19236
|
+
// riffRetiredWorkers -> remoteRetiredWorkers (it now carries mojo too), while
|
|
19237
|
+
// master renamed the local helper trackWorkerExit -> trackWorker.
|
|
19238
|
+
for (const worker of remoteRetiredWorkers)
|
|
18909
19239
|
trackWorker(worker);
|
|
18910
19240
|
for (const ds of currentShutdownFleet.sessions) {
|
|
18911
19241
|
const w = ds.worker;
|
|
@@ -18922,8 +19252,8 @@ export async function startDaemon(botIndex) {
|
|
|
18922
19252
|
if (!w.killed) {
|
|
18923
19253
|
logger.info(`Shutting down worker for session ${ds.session.sessionId}`);
|
|
18924
19254
|
const disposition = shutdownBackendDisposition(ds);
|
|
18925
|
-
if (disposition === '
|
|
18926
|
-
throw new Error(`undrained
|
|
19255
|
+
if (disposition === 'remote-drain-detach') {
|
|
19256
|
+
throw new Error(`undrained remote generation after atomic commit: ${ds.session.sessionId}`);
|
|
18927
19257
|
}
|
|
18928
19258
|
// Branch by the session's FROZEN backend (stamped on Session.backendType
|
|
18929
19259
|
// at spawn), NOT the bot's live config — a dashboard backendType edit must
|
|
@@ -19072,6 +19402,7 @@ export async function startDaemon(botIndex) {
|
|
|
19072
19402
|
setSupervisorShutdownHandler(null);
|
|
19073
19403
|
clearInterval(descriptorHeartbeat);
|
|
19074
19404
|
clearInterval(idleWorkerSweepTimer);
|
|
19405
|
+
clearInterval(sessionOwnerReminderTimer);
|
|
19075
19406
|
clearInterval(docCommentPollTimer);
|
|
19076
19407
|
if (memoryDiagnostics)
|
|
19077
19408
|
clearInterval(memoryDiagnostics);
|