botmux 3.13.0 → 3.14.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 +1 -1
- package/README.md +25 -1
- package/dist/.runtime-build-id +1 -1
- package/dist/adapters/adopt-route.d.ts +58 -0
- package/dist/adapters/adopt-route.d.ts.map +1 -1
- package/dist/adapters/adopt-route.js +136 -0
- package/dist/adapters/adopt-route.js.map +1 -1
- package/dist/adapters/backend/capabilities.js +1 -1
- package/dist/adapters/backend/capabilities.js.map +1 -1
- package/dist/adapters/backend/herdr-backend.d.ts +1 -1
- package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
- package/dist/adapters/backend/herdr-backend.js +2 -1
- package/dist/adapters/backend/herdr-backend.js.map +1 -1
- package/dist/adapters/backend/riff-backend.d.ts +97 -0
- package/dist/adapters/backend/riff-backend.d.ts.map +1 -1
- package/dist/adapters/backend/riff-backend.js +380 -66
- package/dist/adapters/backend/riff-backend.js.map +1 -1
- package/dist/adapters/backend/sandbox.d.ts +8 -0
- package/dist/adapters/backend/sandbox.d.ts.map +1 -1
- package/dist/adapters/backend/sandbox.js +16 -2
- package/dist/adapters/backend/sandbox.js.map +1 -1
- package/dist/adapters/backend/tmux-backend.d.ts +12 -13
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +113 -53
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.d.ts +4 -3
- package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.js +12 -9
- package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
- package/dist/adapters/backend/zellij-backend.d.ts +2 -3
- package/dist/adapters/backend/zellij-backend.d.ts.map +1 -1
- package/dist/adapters/backend/zellij-backend.js +6 -13
- package/dist/adapters/backend/zellij-backend.js.map +1 -1
- package/dist/adapters/backend/zellij-observe-backend.d.ts +2 -1
- package/dist/adapters/backend/zellij-observe-backend.d.ts.map +1 -1
- package/dist/adapters/backend/zellij-observe-backend.js +6 -3
- package/dist/adapters/backend/zellij-observe-backend.js.map +1 -1
- package/dist/adapters/backend/zmx-backend.d.ts.map +1 -1
- package/dist/adapters/backend/zmx-backend.js +40 -18
- package/dist/adapters/backend/zmx-backend.js.map +1 -1
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +12 -1
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/adapters/cli/codex.d.ts.map +1 -1
- package/dist/adapters/cli/codex.js +3 -2
- package/dist/adapters/cli/codex.js.map +1 -1
- package/dist/adapters/cli/dsh.d.ts +4 -0
- package/dist/adapters/cli/dsh.d.ts.map +1 -0
- package/dist/adapters/cli/dsh.js +96 -0
- package/dist/adapters/cli/dsh.js.map +1 -0
- package/dist/adapters/cli/fs-policy.d.ts.map +1 -1
- package/dist/adapters/cli/fs-policy.js +5 -0
- package/dist/adapters/cli/fs-policy.js.map +1 -1
- package/dist/adapters/cli/opencode.d.ts +52 -1
- package/dist/adapters/cli/opencode.d.ts.map +1 -1
- package/dist/adapters/cli/opencode.js +117 -76
- package/dist/adapters/cli/opencode.js.map +1 -1
- package/dist/adapters/cli/opencode2.d.ts +4 -0
- package/dist/adapters/cli/opencode2.d.ts.map +1 -0
- package/dist/adapters/cli/opencode2.js +137 -0
- package/dist/adapters/cli/opencode2.js.map +1 -0
- package/dist/adapters/cli/read-isolation.d.ts +1 -1
- package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
- package/dist/adapters/cli/read-isolation.js +5 -2
- package/dist/adapters/cli/read-isolation.js.map +1 -1
- package/dist/adapters/cli/registry.d.ts +7 -1
- package/dist/adapters/cli/registry.d.ts.map +1 -1
- package/dist/adapters/cli/registry.js +19 -6
- package/dist/adapters/cli/registry.js.map +1 -1
- package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
- package/dist/adapters/cli/shared-hints.js +13 -0
- package/dist/adapters/cli/shared-hints.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +24 -3
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/adapters/hook-command.d.ts +8 -0
- package/dist/adapters/hook-command.d.ts.map +1 -1
- package/dist/adapters/hook-command.js +11 -0
- package/dist/adapters/hook-command.js.map +1 -1
- package/dist/adapters/hook-installer.d.ts +16 -1
- package/dist/adapters/hook-installer.d.ts.map +1 -1
- package/dist/adapters/hook-installer.js +232 -2
- package/dist/adapters/hook-installer.js.map +1 -1
- package/dist/bot-registry.d.ts +116 -8
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +52 -4
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/pm2-start-transaction.d.ts +14 -0
- package/dist/cli/pm2-start-transaction.d.ts.map +1 -1
- package/dist/cli/pm2-start-transaction.js +25 -9
- package/dist/cli/pm2-start-transaction.js.map +1 -1
- package/dist/cli/restart-failure-notification.d.ts +54 -0
- package/dist/cli/restart-failure-notification.d.ts.map +1 -0
- package/dist/cli/restart-failure-notification.js +142 -0
- package/dist/cli/restart-failure-notification.js.map +1 -0
- package/dist/cli/restart-failure-owner.d.ts +20 -0
- package/dist/cli/restart-failure-owner.d.ts.map +1 -0
- package/dist/cli/restart-failure-owner.js +27 -0
- package/dist/cli/restart-failure-owner.js.map +1 -0
- package/dist/cli/restart-shutdown-preflight.d.ts +24 -0
- package/dist/cli/restart-shutdown-preflight.d.ts.map +1 -0
- package/dist/cli/restart-shutdown-preflight.js +105 -0
- package/dist/cli/restart-shutdown-preflight.js.map +1 -0
- package/dist/cli/send-dispatch.d.ts +26 -0
- package/dist/cli/send-dispatch.d.ts.map +1 -1
- package/dist/cli/send-dispatch.js +30 -0
- package/dist/cli/send-dispatch.js.map +1 -1
- package/dist/cli.d.ts +4 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +665 -399
- package/dist/cli.js.map +1 -1
- package/dist/codex-app-runner.js +38 -15
- package/dist/codex-app-runner.js.map +1 -1
- package/dist/codex-rpc-lifecycle.d.ts +14 -2
- package/dist/codex-rpc-lifecycle.d.ts.map +1 -1
- package/dist/codex-rpc-lifecycle.js +13 -3
- package/dist/codex-rpc-lifecycle.js.map +1 -1
- package/dist/core/ask-broker.d.ts +3 -0
- package/dist/core/ask-broker.d.ts.map +1 -1
- package/dist/core/ask-broker.js +29 -7
- package/dist/core/ask-broker.js.map +1 -1
- package/dist/core/ask-hook/registry.d.ts.map +1 -1
- package/dist/core/ask-hook/registry.js +4 -0
- package/dist/core/ask-hook/registry.js.map +1 -1
- package/dist/core/ask-types.d.ts +5 -1
- package/dist/core/ask-types.d.ts.map +1 -1
- package/dist/core/ask-types.js.map +1 -1
- package/dist/core/browser-restart.d.ts +112 -0
- package/dist/core/browser-restart.d.ts.map +1 -0
- package/dist/core/browser-restart.js +233 -0
- package/dist/core/browser-restart.js.map +1 -0
- package/dist/core/command-handler.d.ts +19 -11
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +237 -43
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/current-turn-provenance.d.ts.map +1 -1
- package/dist/core/current-turn-provenance.js +7 -27
- package/dist/core/current-turn-provenance.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +317 -10
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dispatch-registry.d.ts.map +1 -1
- package/dist/core/dispatch-registry.js +6 -0
- package/dist/core/dispatch-registry.js.map +1 -1
- package/dist/core/dispatch-report-binding.d.ts +31 -0
- package/dist/core/dispatch-report-binding.d.ts.map +1 -0
- package/dist/core/dispatch-report-binding.js +88 -0
- package/dist/core/dispatch-report-binding.js.map +1 -0
- package/dist/core/doc-comment-prompt.d.ts +2 -0
- package/dist/core/doc-comment-prompt.d.ts.map +1 -1
- package/dist/core/doc-comment-prompt.js +6 -0
- package/dist/core/doc-comment-prompt.js.map +1 -1
- package/dist/core/host-overload-alert.d.ts +25 -1
- package/dist/core/host-overload-alert.d.ts.map +1 -1
- package/dist/core/host-overload-alert.js +69 -8
- package/dist/core/host-overload-alert.js.map +1 -1
- package/dist/core/local-terminal-opener.js +1 -1
- package/dist/core/local-terminal-opener.js.map +1 -1
- package/dist/core/managed-origin-capability.d.ts +7 -6
- package/dist/core/managed-origin-capability.d.ts.map +1 -1
- package/dist/core/managed-origin-capability.js +32 -1
- package/dist/core/managed-origin-capability.js.map +1 -1
- package/dist/core/passthrough-commands.d.ts.map +1 -1
- package/dist/core/passthrough-commands.js +3 -2
- package/dist/core/passthrough-commands.js.map +1 -1
- package/dist/core/plugins/materializer.d.ts.map +1 -1
- package/dist/core/plugins/materializer.js +1 -0
- package/dist/core/plugins/materializer.js.map +1 -1
- package/dist/core/producer-quiescence.d.ts +70 -0
- package/dist/core/producer-quiescence.d.ts.map +1 -0
- package/dist/core/producer-quiescence.js +90 -0
- package/dist/core/producer-quiescence.js.map +1 -0
- package/dist/core/raw-command-write-options.d.ts +10 -0
- package/dist/core/raw-command-write-options.d.ts.map +1 -0
- package/dist/core/raw-command-write-options.js +23 -0
- package/dist/core/raw-command-write-options.js.map +1 -0
- package/dist/core/raw-command-writer.d.ts +4 -0
- package/dist/core/raw-command-writer.d.ts.map +1 -1
- package/dist/core/raw-command-writer.js +15 -6
- package/dist/core/raw-command-writer.js.map +1 -1
- package/dist/core/reply-target.d.ts +11 -0
- package/dist/core/reply-target.d.ts.map +1 -1
- package/dist/core/reply-target.js +22 -7
- package/dist/core/reply-target.js.map +1 -1
- package/dist/core/report-session-relay.d.ts +53 -0
- package/dist/core/report-session-relay.d.ts.map +1 -0
- package/dist/core/report-session-relay.js +116 -0
- package/dist/core/report-session-relay.js.map +1 -0
- package/dist/core/session-discovery.d.ts +5 -0
- package/dist/core/session-discovery.d.ts.map +1 -1
- package/dist/core/session-discovery.js +13 -0
- package/dist/core/session-discovery.js.map +1 -1
- package/dist/core/session-group-birth.d.ts +7 -0
- package/dist/core/session-group-birth.d.ts.map +1 -0
- package/dist/core/session-group-birth.js +145 -0
- package/dist/core/session-group-birth.js.map +1 -0
- package/dist/core/session-manager.d.ts +16 -21
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +140 -21
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/trigger-session.d.ts.map +1 -1
- package/dist/core/trigger-session.js +18 -3
- package/dist/core/trigger-session.js.map +1 -1
- package/dist/core/types.d.ts +18 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts +63 -11
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +241 -13
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts +33 -0
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +900 -137
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/auth.d.ts +20 -0
- package/dist/dashboard/auth.d.ts.map +1 -1
- package/dist/dashboard/auth.js +86 -1
- 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 -1
- package/dist/dashboard/bot-payload.js.map +1 -1
- package/dist/dashboard/federation-spoke-api.d.ts.map +1 -1
- package/dist/dashboard/federation-spoke-api.js +27 -3
- package/dist/dashboard/federation-spoke-api.js.map +1 -1
- package/dist/dashboard/feedback-analytics-api.d.ts +6 -0
- package/dist/dashboard/feedback-analytics-api.d.ts.map +1 -0
- package/dist/dashboard/feedback-analytics-api.js +39 -0
- package/dist/dashboard/feedback-analytics-api.js.map +1 -0
- package/dist/dashboard/session-action-timeout.d.ts +3 -0
- package/dist/dashboard/session-action-timeout.d.ts.map +1 -0
- package/dist/dashboard/session-action-timeout.js +12 -0
- package/dist/dashboard/session-action-timeout.js.map +1 -0
- package/dist/dashboard/vc-consumer-profiles-api.d.ts +9 -3
- package/dist/dashboard/vc-consumer-profiles-api.d.ts.map +1 -1
- package/dist/dashboard/vc-consumer-profiles-api.js +2 -1
- package/dist/dashboard/vc-consumer-profiles-api.js.map +1 -1
- package/dist/dashboard/web/app.d.ts.map +1 -1
- package/dist/dashboard/web/app.js +48 -5
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts +4 -0
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.js +273 -36
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts +6 -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/dashboard-routes.d.ts.map +1 -1
- package/dist/dashboard/web/dashboard-routes.js +1 -0
- package/dist/dashboard/web/dashboard-routes.js.map +1 -1
- package/dist/dashboard/web/feedback-page.d.ts +3 -0
- package/dist/dashboard/web/feedback-page.d.ts.map +1 -0
- package/dist/dashboard/web/feedback-page.js +34 -0
- package/dist/dashboard/web/feedback-page.js.map +1 -0
- package/dist/dashboard/web/groups-page.d.ts.map +1 -1
- package/dist/dashboard/web/groups-page.js +7 -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 +114 -22
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/team-federation-page.d.ts.map +1 -1
- package/dist/dashboard/web/team-federation-page.js +26 -2
- package/dist/dashboard/web/team-federation-page.js.map +1 -1
- package/dist/dashboard/web/team-federation.d.ts +19 -0
- package/dist/dashboard/web/team-federation.d.ts.map +1 -1
- package/dist/dashboard/web/team-federation.js +3 -0
- package/dist/dashboard/web/team-federation.js.map +1 -1
- package/dist/dashboard/web/update-action.d.ts +8 -0
- package/dist/dashboard/web/update-action.d.ts.map +1 -1
- package/dist/dashboard/web/update-action.js +10 -0
- package/dist/dashboard/web/update-action.js.map +1 -1
- package/dist/dashboard/web/vc-consumer-profiles-section.d.ts.map +1 -1
- package/dist/dashboard/web/vc-consumer-profiles-section.js +58 -9
- package/dist/dashboard/web/vc-consumer-profiles-section.js.map +1 -1
- package/dist/dashboard-web/app.js +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-4RENHE7J.js +10 -0
- package/dist/dashboard-web/chunks/chunk-2WQDS65D.js +1 -0
- package/dist/dashboard-web/chunks/{chunk-CU4SUKK3.js → chunk-6O7KXFD2.js} +1 -1
- package/dist/dashboard-web/chunks/chunk-G5XGBCM6.js +1 -0
- package/dist/dashboard-web/chunks/{chunk-6JTZJRQJ.js → chunk-Q2MT4VWH.js} +15 -15
- package/dist/dashboard-web/chunks/{chunk-5QJB24I2.js → chunk-U3ZFSO7E.js} +1 -1
- package/dist/dashboard-web/chunks/connectors-page-2KZO5KSJ.js +1 -0
- package/dist/dashboard-web/chunks/feedback-page-CLVTOLLO.js +1 -0
- package/dist/dashboard-web/chunks/groups-page-HLASRTSY.js +8 -0
- package/dist/dashboard-web/chunks/{insights-page-EVGGJI5L.js → insights-page-4RPU2CRU.js} +1 -1
- package/dist/dashboard-web/chunks/{monitor-room-HRGR2ENP.js → monitor-room-OTKQ2CXK.js} +1 -1
- package/dist/dashboard-web/chunks/monitoring-page-IJPUB6JT.js +2 -0
- package/dist/dashboard-web/chunks/office-page-QSR3J44Y.js +1 -0
- package/dist/dashboard-web/chunks/overview-page-6OK63V4V.js +1 -0
- package/dist/dashboard-web/chunks/roles-page-6NWJMOB5.js +1 -0
- package/dist/dashboard-web/chunks/schedules-page-6I3LNXD4.js +1 -0
- package/dist/dashboard-web/chunks/{sessions-page-DXBCDWCS.js → sessions-page-B2TXGJDO.js} +1 -1
- package/dist/dashboard-web/chunks/settings-page-6KJADSC6.js +2 -0
- package/dist/dashboard-web/chunks/{skills-page-2QAVB2SA.js → skills-page-M2Q6L5CB.js} +1 -1
- package/dist/dashboard-web/chunks/team-federation-page-7I7FDE3B.js +1 -0
- package/dist/dashboard-web/chunks/{v3-page-AY35LKCX.js → v3-page-HQXRL65L.js} +1 -1
- package/dist/dashboard-web/chunks/whiteboards-page-LQKC4TAZ.js +1 -0
- package/dist/dashboard-web/style.css +35 -0
- package/dist/dashboard.js +199 -12
- package/dist/dashboard.js.map +1 -1
- package/dist/desktop/shared/shell-path-probes.d.ts +1 -1
- package/dist/desktop/shared/shell-path-probes.js +2 -2
- package/dist/desktop/shared/shell-path-probes.js.map +1 -1
- package/dist/dsh-runner.d.ts +3 -0
- package/dist/dsh-runner.d.ts.map +1 -0
- package/dist/dsh-runner.js +666 -0
- package/dist/dsh-runner.js.map +1 -0
- package/dist/global-config.d.ts +24 -0
- package/dist/global-config.d.ts.map +1 -1
- package/dist/global-config.js +35 -0
- package/dist/global-config.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +25 -6
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +25 -6
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/ask-card.d.ts +3 -1
- package/dist/im/lark/ask-card.d.ts.map +1 -1
- package/dist/im/lark/ask-card.js +61 -5
- package/dist/im/lark/ask-card.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +13 -6
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts +2 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +145 -5
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts +18 -0
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +36 -9
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/md-card.d.ts +18 -0
- package/dist/im/lark/md-card.d.ts.map +1 -1
- package/dist/im/lark/md-card.js +21 -0
- package/dist/im/lark/md-card.js.map +1 -1
- package/dist/im/lark/relay-target-routing.d.ts.map +1 -1
- package/dist/im/lark/relay-target-routing.js +3 -2
- package/dist/im/lark/relay-target-routing.js.map +1 -1
- package/dist/im/lark/reply-mode-command.d.ts.map +1 -1
- package/dist/im/lark/reply-mode-command.js +19 -8
- package/dist/im/lark/reply-mode-command.js.map +1 -1
- package/dist/im/lark/skill-feedback-card.d.ts +15 -0
- package/dist/im/lark/skill-feedback-card.d.ts.map +1 -0
- package/dist/im/lark/skill-feedback-card.js +149 -0
- package/dist/im/lark/skill-feedback-card.js.map +1 -0
- package/dist/services/bot-config-store.d.ts +10 -1
- package/dist/services/bot-config-store.d.ts.map +1 -1
- package/dist/services/bot-config-store.js +103 -3
- package/dist/services/bot-config-store.js.map +1 -1
- package/dist/services/bridge-fallback-gate.d.ts +14 -0
- package/dist/services/bridge-fallback-gate.d.ts.map +1 -1
- package/dist/services/bridge-fallback-gate.js +15 -0
- package/dist/services/bridge-fallback-gate.js.map +1 -1
- package/dist/services/codex-reasoning-effort.d.ts +9 -0
- package/dist/services/codex-reasoning-effort.d.ts.map +1 -0
- package/dist/services/codex-reasoning-effort.js +23 -0
- package/dist/services/codex-reasoning-effort.js.map +1 -0
- package/dist/services/codex-service-tier.d.ts +1 -1
- package/dist/services/codex-service-tier.d.ts.map +1 -1
- package/dist/services/codex-transcript.d.ts +9 -0
- package/dist/services/codex-transcript.d.ts.map +1 -1
- package/dist/services/codex-transcript.js +13 -6
- package/dist/services/codex-transcript.js.map +1 -1
- package/dist/services/feed-group-tagger.d.ts +15 -0
- package/dist/services/feed-group-tagger.d.ts.map +1 -0
- package/dist/services/feed-group-tagger.js +348 -0
- package/dist/services/feed-group-tagger.js.map +1 -0
- package/dist/services/feedback-analytics.d.ts +82 -0
- package/dist/services/feedback-analytics.d.ts.map +1 -0
- package/dist/services/feedback-analytics.js +95 -0
- package/dist/services/feedback-analytics.js.map +1 -0
- package/dist/services/feedback-outbox.d.ts +24 -0
- package/dist/services/feedback-outbox.d.ts.map +1 -0
- package/dist/services/feedback-outbox.js +12 -0
- package/dist/services/feedback-outbox.js.map +1 -0
- package/dist/services/feedback-policy-resolver.d.ts +56 -0
- package/dist/services/feedback-policy-resolver.d.ts.map +1 -0
- package/dist/services/feedback-policy-resolver.js +156 -0
- package/dist/services/feedback-policy-resolver.js.map +1 -0
- package/dist/services/feedback-policy.d.ts +41 -0
- package/dist/services/feedback-policy.d.ts.map +1 -0
- package/dist/services/feedback-policy.js +102 -0
- package/dist/services/feedback-policy.js.map +1 -0
- package/dist/services/feedback-webhook-dispatcher.d.ts +76 -0
- package/dist/services/feedback-webhook-dispatcher.d.ts.map +1 -0
- package/dist/services/feedback-webhook-dispatcher.js +237 -0
- package/dist/services/feedback-webhook-dispatcher.js.map +1 -0
- package/dist/services/grant-prefs-store.d.ts +3 -0
- package/dist/services/grant-prefs-store.d.ts.map +1 -1
- package/dist/services/grant-prefs-store.js +30 -1
- package/dist/services/grant-prefs-store.js.map +1 -1
- package/dist/services/groups-store.d.ts +14 -0
- package/dist/services/groups-store.d.ts.map +1 -1
- package/dist/services/groups-store.js +23 -0
- package/dist/services/groups-store.js.map +1 -1
- package/dist/services/local-cli-opener.d.ts +1 -1
- package/dist/services/local-cli-opener.d.ts.map +1 -1
- package/dist/services/local-cli-opener.js +2 -0
- package/dist/services/local-cli-opener.js.map +1 -1
- package/dist/services/prompt-context-store.d.ts +29 -0
- package/dist/services/prompt-context-store.d.ts.map +1 -0
- package/dist/services/prompt-context-store.js +205 -0
- package/dist/services/prompt-context-store.js.map +1 -0
- package/dist/services/session-group-avatar.d.ts +6 -0
- package/dist/services/session-group-avatar.d.ts.map +1 -0
- package/dist/services/session-group-avatar.js +96 -0
- package/dist/services/session-group-avatar.js.map +1 -0
- package/dist/services/session-group-title.d.ts +47 -0
- package/dist/services/session-group-title.d.ts.map +1 -0
- package/dist/services/session-group-title.js +226 -0
- package/dist/services/session-group-title.js.map +1 -0
- package/dist/services/session-groups-store.d.ts +30 -0
- package/dist/services/session-groups-store.d.ts.map +1 -0
- package/dist/services/session-groups-store.js +132 -0
- package/dist/services/session-groups-store.js.map +1 -0
- package/dist/services/session-store.d.ts +58 -0
- package/dist/services/session-store.d.ts.map +1 -1
- package/dist/services/session-store.js +174 -0
- package/dist/services/session-store.js.map +1 -1
- package/dist/services/skill-feedback-store.d.ts +252 -0
- package/dist/services/skill-feedback-store.d.ts.map +1 -0
- package/dist/services/skill-feedback-store.js +795 -0
- package/dist/services/skill-feedback-store.js.map +1 -0
- package/dist/services/skill-registry-store.d.ts +23 -0
- package/dist/services/skill-registry-store.d.ts.map +1 -1
- package/dist/services/skill-registry-store.js +93 -7
- package/dist/services/skill-registry-store.js.map +1 -1
- package/dist/services/team-store.d.ts +4 -0
- package/dist/services/team-store.d.ts.map +1 -1
- package/dist/services/team-store.js +16 -0
- package/dist/services/team-store.js.map +1 -1
- package/dist/services/traex-transcript.d.ts +32 -4
- package/dist/services/traex-transcript.d.ts.map +1 -1
- package/dist/services/traex-transcript.js +116 -8
- package/dist/services/traex-transcript.js.map +1 -1
- package/dist/services/trigger-types.d.ts +1 -1
- package/dist/services/trigger-types.d.ts.map +1 -1
- package/dist/services/trigger-types.js +2 -2
- package/dist/services/trigger-types.js.map +1 -1
- package/dist/services/turn-completion-events.d.ts +57 -0
- package/dist/services/turn-completion-events.d.ts.map +1 -0
- package/dist/services/turn-completion-events.js +179 -0
- package/dist/services/turn-completion-events.js.map +1 -0
- package/dist/services/vc-meeting-consumer-isolation.d.ts +21 -12
- package/dist/services/vc-meeting-consumer-isolation.d.ts.map +1 -1
- package/dist/services/vc-meeting-consumer-isolation.js +25 -19
- package/dist/services/vc-meeting-consumer-isolation.js.map +1 -1
- package/dist/services/vc-meeting-consumer-profile-bootstrap.d.ts +8 -2
- package/dist/services/vc-meeting-consumer-profile-bootstrap.d.ts.map +1 -1
- package/dist/services/vc-meeting-consumer-profile-bootstrap.js +18 -10
- package/dist/services/vc-meeting-consumer-profile-bootstrap.js.map +1 -1
- package/dist/setup/bot-config-editor.d.ts.map +1 -1
- package/dist/setup/bot-config-editor.js +6 -0
- package/dist/setup/bot-config-editor.js.map +1 -1
- package/dist/setup/cli-availability.d.ts +2 -1
- package/dist/setup/cli-availability.d.ts.map +1 -1
- package/dist/setup/cli-availability.js +2 -1
- package/dist/setup/cli-availability.js.map +1 -1
- package/dist/setup/cli-selection.d.ts +8 -0
- package/dist/setup/cli-selection.d.ts.map +1 -1
- package/dist/setup/cli-selection.js +31 -0
- package/dist/setup/cli-selection.js.map +1 -1
- package/dist/setup/ensure-fonts.d.ts +5 -0
- package/dist/setup/ensure-fonts.d.ts.map +1 -1
- package/dist/setup/ensure-fonts.js +26 -1
- package/dist/setup/ensure-fonts.js.map +1 -1
- package/dist/setup/lark-scopes.json +3 -1
- package/dist/setup/open-platform-automation.d.ts +1 -1
- package/dist/setup/open-platform-automation.d.ts.map +1 -1
- package/dist/setup/open-platform-automation.js +15 -3
- package/dist/setup/open-platform-automation.js.map +1 -1
- package/dist/skills/definitions.d.ts +1 -1
- package/dist/skills/definitions.d.ts.map +1 -1
- package/dist/skills/definitions.js +9 -2
- package/dist/skills/definitions.js.map +1 -1
- package/dist/types.d.ts +10 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/user-token.d.ts +38 -0
- package/dist/utils/user-token.d.ts.map +1 -1
- package/dist/utils/user-token.js +76 -1
- package/dist/utils/user-token.js.map +1 -1
- package/dist/utils/web-terminal-scroll.d.ts +27 -0
- package/dist/utils/web-terminal-scroll.d.ts.map +1 -0
- package/dist/utils/web-terminal-scroll.js +60 -0
- package/dist/utils/web-terminal-scroll.js.map +1 -0
- package/dist/vc-agent/polling-source.d.ts +70 -0
- package/dist/vc-agent/polling-source.d.ts.map +1 -1
- package/dist/vc-agent/polling-source.js +115 -0
- package/dist/vc-agent/polling-source.js.map +1 -1
- package/dist/worker.js +237 -76
- package/dist/worker.js.map +1 -1
- package/dist/workflows/definition.d.ts +22 -22
- package/dist/workflows/events/payloads.d.ts +8 -8
- package/dist/workflows/events/schema.d.ts +20 -20
- package/dist/workflows/migration/v2-run-archive-schema.d.ts +20 -20
- package/package.json +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-NQJFJ45Z.js +0 -10
- package/dist/dashboard-web/chunks/chunk-KEEYQ3WF.js +0 -1
- package/dist/dashboard-web/chunks/connectors-page-HADHZXXZ.js +0 -1
- package/dist/dashboard-web/chunks/groups-page-5TYF46RS.js +0 -8
- package/dist/dashboard-web/chunks/monitoring-page-LBU7TTTW.js +0 -2
- package/dist/dashboard-web/chunks/office-page-DF6RRBMN.js +0 -1
- package/dist/dashboard-web/chunks/overview-page-ZB6QH2EX.js +0 -1
- package/dist/dashboard-web/chunks/roles-page-ZBZGHIIF.js +0 -1
- package/dist/dashboard-web/chunks/schedules-page-NQVQC3QY.js +0 -1
- package/dist/dashboard-web/chunks/settings-page-E7NN4NVQ.js +0 -2
- package/dist/dashboard-web/chunks/team-federation-page-VGWL53AE.js +0 -1
- package/dist/dashboard-web/chunks/whiteboards-page-BNWUU4KG.js +0 -1
package/dist/worker.js
CHANGED
|
@@ -23,18 +23,20 @@ import { evaluateCredentialOnlyIsolationGate, credentialIsolationRequired, devic
|
|
|
23
23
|
import { buildFsPolicy, compileToSeatbelt, migrateLegacySandboxFields, resolveRedirectedAdapterAuthPaths, FsPolicyConfigError } from './adapters/cli/fs-policy.js';
|
|
24
24
|
import { killPersistentBackendTarget, killPersistentSession, probePersistentBackendTarget, probePersistentSession, shouldRejectPersistentPostKillProbe } from './core/persistent-backend.js';
|
|
25
25
|
import { finalizeRawCommandDelivery, writeRawCommandLine } from './core/raw-command-writer.js';
|
|
26
|
+
import { rawCommandWriteOptionsFor } from './core/raw-command-write-options.js';
|
|
26
27
|
import { publishCliSessionIdToDaemon } from './core/cli-session-id-publisher.js';
|
|
27
28
|
import { readProcessStartIdentity } from './core/session-marker.js';
|
|
28
29
|
import { roleLibraryRoot, roleLibrarySubtree } from './core/role-library.js';
|
|
29
30
|
import { drainTranscript, joinAssistantText, trailingAssistantText, findJsonlContainingFingerprint, findJsonlsContainingExactContent, findLatestJsonl, extractLastAssistantTurn, extractTurnStartText, splitTranscriptEventsByCutoff, isTranscriptRateLimitEvent, apiErrorMessageText } from './services/claude-transcript.js';
|
|
30
31
|
import { BridgeTurnQueue, makeFingerprint, normaliseForFingerprint } from './services/bridge-turn-queue.js';
|
|
31
|
-
import { bridgePostText, isBridgeNothingToSendFinal,
|
|
32
|
+
import { bridgePostText, isBridgeNothingToSendFinal, shouldSuppressBridgeEmit, structuredFallbackKind, stripTrailingBridgeSentinelLine } from './services/bridge-fallback-gate.js';
|
|
32
33
|
import { buildSubmitMessagePreview } from './services/submit-notification.js';
|
|
33
34
|
import { decideHardTimeoutAction, decidePostHookPromptEvidence, decideSettleMarkReady, shouldArmPostHookPromptEvidenceFallback, shouldReleaseFirstPromptTimeout, shouldWaitForPostSessionStartPromptEvidence, shouldWriteNow, POST_HOOK_EVIDENCE_FALLBACK_MS, POST_HOOK_EVIDENCE_RETRY_MS, } from './utils/input-gate.js';
|
|
34
35
|
import { decideCodexRunnerFreshness, CodexRunnerFreshnessInputQueue, shouldHoldCodexRunnerInput, } from './services/codex-runner-freshness.js';
|
|
35
36
|
import { canStartInjectionFlush, shouldDeferUserFlush, shouldFlushInjectionsFirst } from './core/inject-queue-policy.js';
|
|
36
37
|
import { decideRestartFollowup, settleDurableTurnForRestart } from './core/restart-followup-policy.js';
|
|
37
38
|
import { stripAnsiForLog, tailChars } from './utils/crash-log.js';
|
|
39
|
+
import { parseReadOnlyRemoteScrollPayload, READ_ONLY_REMOTE_SCROLL_SESSION_BUDGET, READ_ONLY_REMOTE_SCROLL_WINDOW_MS, ReadOnlyRemoteScrollLimiter, } from './utils/web-terminal-scroll.js';
|
|
38
40
|
import { CodexUpdateDialogGuard } from './utils/codex-update-dialog.js';
|
|
39
41
|
import { EffortConfirmDialogGuard } from './utils/effort-confirm-dialog.js';
|
|
40
42
|
import { installStdioEpipeGuard, isIgnorableStreamError } from './utils/stdio-epipe-guard.js';
|
|
@@ -63,7 +65,7 @@ import { CodexBridgeQueue, pruneExpiredPreStartHeadsAndEmit } from './services/c
|
|
|
63
65
|
import { detectCodexComposerState } from './services/codex-composer-state.js';
|
|
64
66
|
import { generateCodexAppThreadTitle, readCodexAppThreadMetadata, setCodexAppThreadName, } from './services/codex-app-threads.js';
|
|
65
67
|
import { buildBotmuxLarkNativeSessionTitle } from './core/session-title.js';
|
|
66
|
-
import { CODEX_AUTH_ERROR_CODE, CODEX_CONNECTION_ERROR_CODE, CODEX_INVALID_REQUEST_ERROR_CODE,
|
|
68
|
+
import { CODEX_AUTH_ERROR_CODE, CODEX_CONNECTION_ERROR_CODE, CODEX_INVALID_REQUEST_ERROR_CODE, drainCodexRollout, findCodexRolloutBySessionId, findCodexRolloutByPid, findCodexRolloutSetByPid, codexHistorySidIsOwned, splitCodexEventsByCutoff, extractLastCodexTurn, codexSessionIdFromRolloutPath, isCodexRateLimitEvent, scanCodexThreadSettings, readLatestCodexRuntime } from './services/codex-transcript.js';
|
|
67
69
|
import { CodexServiceTierTracker, resolveCodexServiceTierSnapshot } from './services/codex-service-tier.js';
|
|
68
70
|
import { WORKER_IPC_HANDLER_READY_EVENT } from './worker-ipc-preload.js';
|
|
69
71
|
import { drainTraexRollout, findTraexRolloutBySessionId, findTraexRolloutByPid, findTraexRolloutSetByPid, readLatestTraexRuntime, traexHistorySidIsOwned } from './services/traex-transcript.js';
|
|
@@ -91,9 +93,9 @@ import { t, setDefaultLocale } from './i18n/index.js';
|
|
|
91
93
|
import { TerminalRenderer } from './utils/terminal-renderer.js';
|
|
92
94
|
import { DEFAULT_RENDER_COLS, DEFAULT_RENDER_ROWS, MAX_RENDER_COLS, MAX_RENDER_ROWS, MIN_RENDER_COLS, MIN_RENDER_ROWS, clamp, resolveRenderDimensions, } from './utils/render-dimensions.js';
|
|
93
95
|
import { createCliAdapterSync, locateOnPath } from './adapters/cli/registry.js';
|
|
94
|
-
import { buildWrappedLaunch, parseWrapperCli, isTtadkWrapper } from './setup/cli-selection.js';
|
|
96
|
+
import { buildWrappedLaunch, parseWrapperCli, isTtadkWrapper, wrapperLaunchEnv } from './setup/cli-selection.js';
|
|
95
97
|
import { cliUnavailableMessage } from './setup/cli-availability.js';
|
|
96
|
-
import { findLaunchedCliPid, scheduleWrapperRealCliPid, readComm, isBareShellComm, bareShellLaunchKind, settleLaunchComm, } from './core/session-discovery.js';
|
|
98
|
+
import { findLaunchedCliPid, scheduleWrapperRealCliPid, readComm, isBareShellComm, bareShellLaunchKind, bareShellLaunchGuidance, settleLaunchComm, } from './core/session-discovery.js';
|
|
97
99
|
import { CODEX_RPC_TERMINAL_HYDRATION_DELAYS_MS, RpcEngagementFence, codexRpcEligible, paneRunsRemoteTui, orchestrateCodexRpcInit, rolloutUserTurnMatches, decideStartupDialogAction, shouldQueueInitialPrompt, shouldPreMarkFirstTurn, killAndVerifyPersistentPane, rpcTranscriptIngestBlockedByAwaitingActivation } from './codex-rpc-lifecycle.js';
|
|
98
100
|
import { delay } from './utils/timing.js';
|
|
99
101
|
import { claudeJsonlPathForSession, resolveJsonlFromPid, findOpenClaudeSessionIds, syncClaudeResumeTargetToCwd, DEFAULT_CLAUDE_DATA_DIR } from './adapters/cli/claude-code.js';
|
|
@@ -143,7 +145,7 @@ import { withCodexAppContext } from './utils/codex-app-context.js';
|
|
|
143
145
|
import { resolveCodexAppFinalTurnIdentity } from './adapters/cli/codex-app-turn.js';
|
|
144
146
|
import { RunnerControlDecoder } from './adapters/cli/runner-control-channel.js';
|
|
145
147
|
import { normalizeCodexAppLifecycleEvent, normalizeFinalUsage, } from './services/codex-app-runner-protocol.js';
|
|
146
|
-
import { hasMatchingManagedOriginCapability, ensureManagedOriginAttestationDirectory, ensureManagedOriginCapabilityLeafSafe, ensureManagedOriginDataRootProbe, ensureManagedOriginIsolationSentinel, ensureManagedOriginRootLocator, managedOriginLegacyIsolationProbeAccess, managedOriginDataRootProbeAccess, managedOriginIsolationSentinelAccess, managedOriginAttestationDirectory, managedOriginCapabilityPath, managedOriginRootLocatorPath, readManagedOriginAuthorityFile, RELAY_ORIGIN_CAPABILITY_BASENAME, replaceManagedOriginCapabilityFile, sweepManagedOriginAttestationProofs, } from './core/managed-origin-capability.js';
|
|
148
|
+
import { hasMatchingManagedOriginCapability, ensureManagedOriginAttestationDirectory, ensureManagedOriginCapabilityLeafSafe, ensureManagedOriginDataRootProbe, ensureManagedOriginIsolationSentinel, ensureManagedOriginRootLocator, managedOriginLegacyIsolationProbeAccess, managedOriginDataRootProbeAccess, managedOriginIsolationSentinelAccess, managedOriginAttestationDirectory, managedOriginCapabilityDirectory, managedOriginCapabilityPath, managedOriginRootLocatorPath, readManagedOriginAuthorityFile, RELAY_ORIGIN_CAPABILITY_BASENAME, replaceManagedOriginCapabilityFile, sweepManagedOriginAttestationProofs, } from './core/managed-origin-capability.js';
|
|
147
149
|
import { CodexRpcEngine, } from './codex-rpc-engine.js';
|
|
148
150
|
import { beginRuntimeWriteCycle, isCliBackendGenerationCurrent, PtyOutputGeneration, projectRuntimeScreenStatus, } from './utils/runtime-screen-status.js';
|
|
149
151
|
import { AsyncSerialQueue } from './utils/async-serial-queue.js';
|
|
@@ -422,14 +424,22 @@ function persistentPaneInfo(backendType, sessionId) {
|
|
|
422
424
|
: HerdrBackend.hasSession(name);
|
|
423
425
|
return { name, live };
|
|
424
426
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
427
|
+
/** Tri-state pane liveness, for callers that must not read "no answer" as an
|
|
428
|
+
* answer. The `hasSession()` helpers collapse an unanswered probe into
|
|
429
|
+
* `false`, which is safe where a wrong guess just means "treat as fresh" but
|
|
430
|
+
* NOT where the boolean is consumed as proof that a kill succeeded. Every
|
|
431
|
+
* backend already classifies this correctly; only the boolean wrapper threw
|
|
432
|
+
* the distinction away. */
|
|
433
|
+
function persistentPaneProbe(backendType, name) {
|
|
434
|
+
const probe = backendType === 'tmux' ? TmuxBackend.probeSession(name)
|
|
435
|
+
: backendType === 'zellij' ? ZellijBackend.probeSession(name)
|
|
436
|
+
: backendType === 'herdr' ? HerdrBackend.probeSession(name)
|
|
437
|
+
: ZmxBackend.probeSession(name);
|
|
438
|
+
if (probe === 'exists')
|
|
439
|
+
return 'live';
|
|
440
|
+
if (probe === 'missing')
|
|
441
|
+
return 'gone';
|
|
442
|
+
return 'unknown';
|
|
433
443
|
}
|
|
434
444
|
function probeOwnedZmxSession(name, sessionId, expectedPid) {
|
|
435
445
|
const managed = ZmxBackend.probeManagedSession(name, sessionId);
|
|
@@ -459,7 +469,7 @@ function probeOwnedZmxSession(name, sessionId, expectedPid) {
|
|
|
459
469
|
async function killPersistentSessionVerified(backendType, name, sessionId) {
|
|
460
470
|
return killAndVerifyPersistentPane(name, {
|
|
461
471
|
kill: (resolvedName) => killPersistentSession(backendType, resolvedName, sessionId),
|
|
462
|
-
|
|
472
|
+
probeLive: (resolvedName) => persistentPaneProbe(backendType, resolvedName),
|
|
463
473
|
wait: delay,
|
|
464
474
|
});
|
|
465
475
|
}
|
|
@@ -1439,6 +1449,10 @@ const authedClients = new WeakSet();
|
|
|
1439
1449
|
const clientPtys = new Map();
|
|
1440
1450
|
/** Managed-Herdr viewers survive an in-worker /restart while backend changes. */
|
|
1441
1451
|
const herdrWebBindings = new Map();
|
|
1452
|
+
const readOnlyRemoteScrollLimiter = new ReadOnlyRemoteScrollLimiter({
|
|
1453
|
+
budget: READ_ONLY_REMOTE_SCROLL_SESSION_BUDGET,
|
|
1454
|
+
windowMs: READ_ONLY_REMOTE_SCROLL_WINDOW_MS,
|
|
1455
|
+
});
|
|
1442
1456
|
// Standalone/test fallback. Production replaces this after init with a stable
|
|
1443
1457
|
// per-session HMAC derived from the host-only dashboard secret, so an
|
|
1444
1458
|
// already-issued 「操作链接」/write link survives a worker restart (a silent
|
|
@@ -1511,7 +1525,7 @@ let closeRequested = false;
|
|
|
1511
1525
|
let capturedSpawnCommand = null;
|
|
1512
1526
|
let deferredTopicOutputTail = '';
|
|
1513
1527
|
const reportedDeferredTopicRoots = new Set();
|
|
1514
|
-
const CLI_DISPLAY_NAMES = { 'claude-code': 'Claude', seed: 'Seed', relay: 'Relay', aiden: 'Aiden', coco: 'CoCo', codex: 'Codex', 'codex-app': 'Codex App', cursor: 'Cursor', gemini: 'Gemini', genius: 'Genius', opencode: 'OpenCode', antigravity: 'Antigravity', mtr: 'MTR', hermes: 'Hermes', mira: 'Mira', mir: 'Mir CLI', traex: 'TRAE', pi: 'Pi', copilot: 'Copilot', 'oh-my-pi': 'Oh My Pi', kimi: 'Kimi', grok: 'Grok Build', 'kiro-cli': 'Kiro', riff: 'Riff', reasonix: 'Reasonix' };
|
|
1528
|
+
const CLI_DISPLAY_NAMES = { 'claude-code': 'Claude', seed: 'Seed', relay: 'Relay', aiden: 'Aiden', coco: 'CoCo', codex: 'Codex', 'codex-app': 'Codex App', cursor: 'Cursor', gemini: 'Gemini', genius: 'Genius', opencode: 'OpenCode', opencode2: 'OpenCode 2', antigravity: 'Antigravity', mtr: 'MTR', hermes: 'Hermes', mira: 'Mira', mir: 'Mir CLI', traex: 'TRAE', pi: 'Pi', copilot: 'Copilot', 'oh-my-pi': 'Oh My Pi', kimi: 'Kimi', grok: 'Grok Build', 'kiro-cli': 'Kiro', riff: 'Riff', reasonix: 'Reasonix', dsh: 'DeepSeek Harness' };
|
|
1515
1529
|
function cliName() {
|
|
1516
1530
|
return (lastInitConfig?.cliRuntime?.source === 'configured'
|
|
1517
1531
|
? (lastInitConfig.cliRuntime.displayName?.trim() || lastInitConfig.cliRuntime.id)
|
|
@@ -1677,17 +1691,14 @@ function releaseReadyGate(reason, opts) {
|
|
|
1677
1691
|
* the next command, capped so a slow/redrawing command can't stall the queue. */
|
|
1678
1692
|
const STARTUP_CMD_QUIET_MS = 500;
|
|
1679
1693
|
const STARTUP_CMD_CAP_MS = 4_000;
|
|
1680
|
-
/** Inter-keystroke spacing when typing a slash command into CoCo char-by-char.
|
|
1681
|
-
* CoCo (Trae CLI, Ink TUI) treats "several bytes delivered in one PTY read" as a
|
|
1682
|
-
* paste, which skips command mode + the slash picker — so each char must land as
|
|
1683
|
-
* its own keystroke. 40ms is comfortably above CoCo's coalescing window (verified
|
|
1684
|
-
* against Trae CLI 0.120.45) while keeping a short command sub-second. */
|
|
1685
|
-
const COCO_SLASH_TYPE_THROTTLE_MS = 40;
|
|
1686
1694
|
/** Type one literal input LINE into the CLI exactly like a passthrough slash
|
|
1687
|
-
* command
|
|
1688
|
-
*
|
|
1689
|
-
*
|
|
1690
|
-
* so
|
|
1695
|
+
* command. Delivery is adapter-derived: adapters that declare a paste-line
|
|
1696
|
+
* input mode (e.g. OpenCode) paste the line up front, then wait out the
|
|
1697
|
+
* adapter's settle window before pressing Enter; generic backends keep the
|
|
1698
|
+
* classic raw text → a 200ms beat (so the TUI's slash-command picker
|
|
1699
|
+
* registers the match before submit) → a separate Enter, or fall back to a
|
|
1700
|
+
* single write + CR. Shared by the `raw_input` IPC handler and
|
|
1701
|
+
* runStartupCommands so both stay in lockstep. */
|
|
1691
1702
|
async function sendRawCommandLine(be, content) {
|
|
1692
1703
|
// PR #597 extracted the CoCo/pty keystroke choreography into the shared
|
|
1693
1704
|
// writeRawCommandLine helper (unit-tested in raw-command-writer.ts). It
|
|
@@ -1695,11 +1706,7 @@ async function sendRawCommandLine(be, content) {
|
|
|
1695
1706
|
// recovery-fence transaction detects a failed submission by a thrown error, so
|
|
1696
1707
|
// bridge the two: turn an explicit `false` into the same throw the inline
|
|
1697
1708
|
// implementation used, letting runAmbiguousSubmissionTransaction cancel the WAL.
|
|
1698
|
-
const accepted = await writeRawCommandLine(be, content,
|
|
1699
|
-
coco: lastInitConfig?.cliId === 'coco',
|
|
1700
|
-
cocoThrottleMs: COCO_SLASH_TYPE_THROTTLE_MS,
|
|
1701
|
-
submitBeatMs: 200,
|
|
1702
|
-
});
|
|
1709
|
+
const accepted = await writeRawCommandLine(be, content, rawCommandWriteOptionsFor(cliAdapter ?? undefined, lastInitConfig?.cliId));
|
|
1703
1710
|
if (accepted === false) {
|
|
1704
1711
|
throw new Error('backend rejected command text or submit key input');
|
|
1705
1712
|
}
|
|
@@ -2090,6 +2097,7 @@ let currentBotmuxDispatchAttempt;
|
|
|
2090
2097
|
let currentVcMeetingImTurnOrigin;
|
|
2091
2098
|
let durableTurnInFlight = false;
|
|
2092
2099
|
function publishSandboxRelayCapability(opts = {}) {
|
|
2100
|
+
const daemonIpcPort = parseDaemonIpcPort(process.env.BOTMUX_DAEMON_IPC_PORT);
|
|
2093
2101
|
const capability = {
|
|
2094
2102
|
token: randomBytes(32).toString('hex'),
|
|
2095
2103
|
...(currentBotmuxTurnId ? { turnId: currentBotmuxTurnId } : {}),
|
|
@@ -2104,6 +2112,21 @@ function publishSandboxRelayCapability(opts = {}) {
|
|
|
2104
2112
|
body: JSON.stringify({ token: capability.token }),
|
|
2105
2113
|
}]
|
|
2106
2114
|
: []),
|
|
2115
|
+
...(readIsolationOriginChannelId
|
|
2116
|
+
? [{
|
|
2117
|
+
path: managedOriginCapabilityPath(process.env.SESSION_DATA_DIR ?? config.session.dataDir, sessionId, readIsolationOriginChannelId),
|
|
2118
|
+
body: JSON.stringify({
|
|
2119
|
+
sessionId,
|
|
2120
|
+
channelId: readIsolationOriginChannelId,
|
|
2121
|
+
capability: capability.token,
|
|
2122
|
+
...(capability.turnId ? { turnId: capability.turnId } : {}),
|
|
2123
|
+
...(capability.dispatchAttempt !== undefined
|
|
2124
|
+
? { dispatchAttempt: capability.dispatchAttempt }
|
|
2125
|
+
: {}),
|
|
2126
|
+
...(daemonIpcPort !== undefined ? { ipcPort: daemonIpcPort } : {}),
|
|
2127
|
+
}),
|
|
2128
|
+
}]
|
|
2129
|
+
: []),
|
|
2107
2130
|
];
|
|
2108
2131
|
let publishError;
|
|
2109
2132
|
for (const file of files) {
|
|
@@ -4800,8 +4823,11 @@ function currentHermesBridgeDbPath() {
|
|
|
4800
4823
|
function structuredBridgeIngestPath(path, offset) {
|
|
4801
4824
|
if (structuredBridgeIsCodex())
|
|
4802
4825
|
return drainCodexRollout(path, offset);
|
|
4803
|
-
|
|
4804
|
-
|
|
4826
|
+
// adoptMode gates the drainer's bare-sentinel synthesis: adopt posts
|
|
4827
|
+
// transcript text verbatim, so a synthesised token would leak into Lark.
|
|
4828
|
+
if (structuredBridgeIsTraex()) {
|
|
4829
|
+
return drainTraexRollout(path, offset, { adoptMode: lastInitConfig?.adoptMode === true });
|
|
4830
|
+
}
|
|
4805
4831
|
if (codexBridgeIsCursor())
|
|
4806
4832
|
return drainCursorTranscript(path, offset);
|
|
4807
4833
|
if (structuredBridgeIsPi())
|
|
@@ -6020,13 +6046,17 @@ function emitReadyCodexTurns() {
|
|
|
6020
6046
|
isLocal: turn.isLocal,
|
|
6021
6047
|
finalText: turn.finalText,
|
|
6022
6048
|
terminalStatus: turn.terminalStatus,
|
|
6049
|
+
terminalErrorCode: turn.terminalErrorCode,
|
|
6023
6050
|
};
|
|
6024
|
-
|
|
6025
|
-
|
|
6051
|
+
// The rate-limit skip is narrowed to CLIs with a dedicated structured
|
|
6052
|
+
// rate-limit chain (Codex): TRAE 429 has no such chain, so skipping the
|
|
6053
|
+
// generic failed fallback would post nothing at all.
|
|
6054
|
+
const fallbackKind = structuredFallbackKind(gateInput, nextBoundaryMs, markers, adoptMode, structuredBridgeIsCodex());
|
|
6055
|
+
const content = fallbackKind === 'failed'
|
|
6026
6056
|
? failedBridgeFallbackContent(turn.terminalErrorCode, turn.terminalErrorSummary, turn.finalText)
|
|
6027
|
-
:
|
|
6028
|
-
? turn.finalText
|
|
6029
|
-
:
|
|
6057
|
+
: fallbackKind === 'final'
|
|
6058
|
+
? turn.finalText ?? ''
|
|
6059
|
+
: fallbackKind === 'empty_completed'
|
|
6030
6060
|
? emptyCompletedBridgeFallbackContent()
|
|
6031
6061
|
: '';
|
|
6032
6062
|
if (!content)
|
|
@@ -6295,6 +6325,10 @@ function restoreHerdrWebBindings() {
|
|
|
6295
6325
|
applyHerdrWebBindingResult(ws, binding.restore());
|
|
6296
6326
|
}
|
|
6297
6327
|
}
|
|
6328
|
+
function canHandleReadOnlyRemoteScroll() {
|
|
6329
|
+
return cliAdapter?.readOnlyRemoteScroll === true
|
|
6330
|
+
&& !(lastInitConfig?.adoptMode && lastInitConfig.adoptZellijPaneId);
|
|
6331
|
+
}
|
|
6298
6332
|
function wireHerdrWebTerminalRelays(be) {
|
|
6299
6333
|
be.onSnapshot(relayHerdrWebSnapshot);
|
|
6300
6334
|
be.onWebTerminalCursor(relayHerdrWebCursor);
|
|
@@ -7548,11 +7582,11 @@ function handleVisibleStartupInteraction(data) {
|
|
|
7548
7582
|
}
|
|
7549
7583
|
return true;
|
|
7550
7584
|
}
|
|
7551
|
-
// Mira/Mir
|
|
7585
|
+
// Mira/Mir/dsh send terminal OSC control messages. Codex App deliberately
|
|
7552
7586
|
// does not (PR #597): its signed Unix-socket channel is independent of the
|
|
7553
7587
|
// terminal/backend rendering (including Herdr and Zellij), so it is no longer
|
|
7554
7588
|
// in the terminal-OSC decode set.
|
|
7555
|
-
const APP_RUNNER_OSC_CLI_IDS = new Set(['mira', 'mir']);
|
|
7589
|
+
const APP_RUNNER_OSC_CLI_IDS = new Set(['mira', 'mir', 'dsh']);
|
|
7556
7590
|
const appRunnerControlDecoder = new RunnerControlDecoder();
|
|
7557
7591
|
let kiroSessionIdCaptureArmed = false;
|
|
7558
7592
|
let kiroSessionIdCaptureBuffer = '';
|
|
@@ -8706,7 +8740,17 @@ function markPromptReady() {
|
|
|
8706
8740
|
// make the CLI busy, so the idle state is transient and shouldn't appear
|
|
8707
8741
|
// in the card. This avoids a false "就绪" flash on daemon restart
|
|
8708
8742
|
// (where the initial prompt is queued before the CLI becomes idle).
|
|
8709
|
-
|
|
8743
|
+
//
|
|
8744
|
+
// ALSO skip when the Grok-class busy arm is pending (spawnArgvInitialPromptBusy):
|
|
8745
|
+
// for these adapters the FIRST ready is a pre-execution SessionStart edge, not a
|
|
8746
|
+
// turn boundary — the argv-baked first prompt is still running. isPromptReady was
|
|
8747
|
+
// just set true above, so this generic snapshot would project 'idle' and reach the
|
|
8748
|
+
// daemon BEFORE the busy arm below re-publishes 'working'. Combined with the
|
|
8749
|
+
// first-turn working already sent by startScreenUpdates, the daemon would then see
|
|
8750
|
+
// working→idle and fire finishTurnReactions() — a premature ✅ DONE mid-turn (and a
|
|
8751
|
+
// 「工作中→等待输入→工作中」 flicker on the open card). The busy arm below owns the
|
|
8752
|
+
// correct 'working' publish for this path, so this idle must not escape first.
|
|
8753
|
+
if (renderer && !spawnArgvInitialPromptBusy && pendingMessages.length === 0 && pendingAdoptMessages.length === 0 && pendingRawInputs.length === 0 && pendingSessionRename === null && !isFlushing) {
|
|
8710
8754
|
const { content } = renderer.snapshot();
|
|
8711
8755
|
send({
|
|
8712
8756
|
type: 'screen_update',
|
|
@@ -9079,7 +9123,10 @@ async function detectBareShellLaunch() {
|
|
|
9079
9123
|
// rcfile may still finish and exec the CLI after this bounded check.
|
|
9080
9124
|
const launchShell = (lastInitConfig?.launchShell || process.env.SHELL || '').trim();
|
|
9081
9125
|
const expectedShell = launchShell ? basename(launchShell) : '';
|
|
9082
|
-
|
|
9126
|
+
if (!comm)
|
|
9127
|
+
return false;
|
|
9128
|
+
const shellComm = comm;
|
|
9129
|
+
const trampolined = bareShellLaunchKind(shellComm, expectedShell) === 'trampoline';
|
|
9083
9130
|
bareShellLaunchBlocked = true;
|
|
9084
9131
|
// Injection-first flushes can enter while isPromptReady is still true. Make
|
|
9085
9132
|
// this a real busy/blocked transition so a later PTY-ready event re-enters
|
|
@@ -9094,17 +9141,18 @@ async function detectBareShellLaunch() {
|
|
|
9094
9141
|
const cli = cliName();
|
|
9095
9142
|
let message;
|
|
9096
9143
|
if (trampolined) {
|
|
9144
|
+
const guidance = bareShellLaunchGuidance(shellComm, expectedShell);
|
|
9097
9145
|
message =
|
|
9098
|
-
`⚠️ 会话没能启动:pane 里现在是裸 \`${
|
|
9099
|
-
`最可能原因:botmux 用 \`${expectedShell}\` 启动 CLI,但 pane 落到了 \`${
|
|
9146
|
+
`⚠️ 会话没能启动:pane 里现在是裸 \`${shellComm}\`,${cli} 没真正跑起来——所以我没把你的消息打进去(否则会被当 shell 命令执行,报 \`parse error\`)。\n\n` +
|
|
9147
|
+
`最可能原因:botmux 用 \`${expectedShell}\` 启动 CLI,但 pane 落到了 \`${shellComm}\`。通常是 rc 文件(如 \`${guidance.rcFileHint}\`)里有 \`exec ${shellComm}\` 这类跳转——\`${expectedShell} -i\` 会 source rc,于是 shell 被顶替,CLI 的启动命令没机会跑。\n\n` +
|
|
9100
9148
|
`两种修法(任选其一,改完重启 daemon 再发一条消息):\n` +
|
|
9101
|
-
`①
|
|
9102
|
-
`② 给这个 bot 配 \`launchShell: ${
|
|
9149
|
+
`① 给那行加守卫,只在手动开终端时切:\`${guidance.manualTerminalGuard}\`(注意 PATH/nvm 等导出放在它之前)\n` +
|
|
9150
|
+
`② 给这个 bot 配 \`launchShell: ${shellComm}\`(dashboard 机器人配置,或 \`/config launchShell ${shellComm}\`),直接用 \`${shellComm}\` 启动绕开 \`${expectedShell}\` 的 rc——但要确保 PATH/nvm 在 \`${shellComm}\` 的 rc 里。`;
|
|
9103
9151
|
}
|
|
9104
9152
|
else {
|
|
9105
9153
|
message =
|
|
9106
|
-
`⚠️ ${cli} 启动时间较长:pane 里暂时仍是 \`${
|
|
9107
|
-
`仅凭进程仍是 \`${
|
|
9154
|
+
`⚠️ ${cli} 启动时间较长:pane 里暂时仍是 \`${shellComm}\`。我没有把消息写进 shell,消息还在队列里;检测到真实输入框后会自动继续投递,无需重发。\n\n` +
|
|
9155
|
+
`仅凭进程仍是 \`${shellComm}\` 无法判断具体原因,可能只是 rc 文件或机器负载让启动变慢。若长时间没有恢复,请打开 Web 终端查看当前提示,处理后等待自动继续,或使用 \`/restart\` 重启会话。`;
|
|
9108
9156
|
}
|
|
9109
9157
|
const pendingTurn = pendingMessages[0];
|
|
9110
9158
|
send({
|
|
@@ -9985,8 +10033,48 @@ function startScreenUpdates() {
|
|
|
9985
10033
|
// watermark — there we must capture every tick (see shouldCaptureScreen).
|
|
9986
10034
|
let lastSnapshotPtyActivity = -1;
|
|
9987
10035
|
screenUpdateTimer = setInterval(() => {
|
|
9988
|
-
if (awaitingFirstPrompt)
|
|
10036
|
+
if (awaitingFirstPrompt) {
|
|
10037
|
+
// First-turn 「工作中」 publisher. The async sampler below is fully gated
|
|
10038
|
+
// until the first turn ends (markPromptReady flips awaitingFirstPrompt) or
|
|
10039
|
+
// the 15s soft timeout, so an argv-baked first prompt (Pi/Grok/…, delivered
|
|
10040
|
+
// via the launch command — it never goes through flushPending) would emit
|
|
10041
|
+
// NO screen_update for the whole turn: the daemon card sits at 'starting'
|
|
10042
|
+
// and jumps straight to 「等待输入」 on the first idle, skipping 「工作中」.
|
|
10043
|
+
//
|
|
10044
|
+
// The status projection already reads 'working' during turn one (isPromptReady
|
|
10045
|
+
// is still false — same rule that makes every post-submit turn working), so we
|
|
10046
|
+
// simply PUBLISH that projection once instead of scraping the screen for a busy
|
|
10047
|
+
// marker. This is the general "sent to the CLI ⇒ working" model: it fires for
|
|
10048
|
+
// every argv-baked first prompt (spawnArgvNeedsWorkingSeed), not just CLIs that
|
|
10049
|
+
// happen to render a detectable busyPattern.
|
|
10050
|
+
//
|
|
10051
|
+
// Gate on spawnArgvNeedsWorkingSeed so it stays a no-op for a NON-argv first
|
|
10052
|
+
// turn (Claude/Codex/type-ahead): there the prompt is still queued and the CLI
|
|
10053
|
+
// is genuinely booting — not working — until flushPending() submits it after
|
|
10054
|
+
// the ready edge. Empty-prompt adopt sessions also don't arm the flag, so an
|
|
10055
|
+
// attach never falsely claims working.
|
|
10056
|
+
//
|
|
10057
|
+
// Pure publisher: it only send()s a status and updates the local lastSentStatus
|
|
10058
|
+
// dedup — it never touches isPromptReady, the idle detector, or the argv seed
|
|
10059
|
+
// flags (spawnArgvInitialPromptBusy / -NeedsWorkingSeed), so the first-prompt
|
|
10060
|
+
// evidence machinery and the end-of-turn seed are unchanged.
|
|
10061
|
+
if (spawnArgvNeedsWorkingSeed && lastSentStatus !== 'working' && renderer) {
|
|
10062
|
+
const projected = projectedRuntimeScreenStatus();
|
|
10063
|
+
if (projected === 'working') {
|
|
10064
|
+
const { content } = renderer.snapshot();
|
|
10065
|
+
lastSentStatus = 'working';
|
|
10066
|
+
send({
|
|
10067
|
+
type: 'screen_update',
|
|
10068
|
+
content,
|
|
10069
|
+
status: 'working',
|
|
10070
|
+
turnId: currentBotmuxTurnId,
|
|
10071
|
+
dispatchAttempt: currentBotmuxDispatchAttempt,
|
|
10072
|
+
});
|
|
10073
|
+
log('Argv-baked first prompt in flight — publishing projected working before first prompt');
|
|
10074
|
+
}
|
|
10075
|
+
}
|
|
9989
10076
|
return;
|
|
10077
|
+
}
|
|
9990
10078
|
void (async () => {
|
|
9991
10079
|
const { snapshot, status } = await snapshotWithLatestRuntimeStatus(async () => {
|
|
9992
10080
|
let content = lastContent;
|
|
@@ -10708,6 +10796,8 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
10708
10796
|
// Feishu. Thread the flag so the reconstructed config keeps the boundary.
|
|
10709
10797
|
if (cfg.apiOnly)
|
|
10710
10798
|
sessionEnv.BOTMUX_API_ONLY = '1';
|
|
10799
|
+
if (cfg.feedback)
|
|
10800
|
+
sessionEnv.BOTMUX_FEEDBACK_POLICY = JSON.stringify(cfg.feedback);
|
|
10711
10801
|
// Session scope for `botmux send` inside the sandbox. Thread sessions
|
|
10712
10802
|
// anchor on a real om_ message (reply_in_thread); chat-scope sessions use
|
|
10713
10803
|
// the chat id as anchor (sessionAnchorId), which is NOT a message id —
|
|
@@ -10744,6 +10834,12 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
10744
10834
|
// Per-bot env (bots.json `env`) takes precedence over session context;
|
|
10745
10835
|
// explicit riff config.env takes precedence over both.
|
|
10746
10836
|
const mergedEnv = { ...sessionEnv, ...sanitizePerBotEnv(cfg.env), ...cfg.backendConfig.env };
|
|
10837
|
+
// The effective policy is a host-resolved snapshot, not a user-overridable
|
|
10838
|
+
// backend env knob. Re-freeze it after config.env/per-bot env merge.
|
|
10839
|
+
if (cfg.feedback)
|
|
10840
|
+
mergedEnv.BOTMUX_FEEDBACK_POLICY = JSON.stringify(cfg.feedback);
|
|
10841
|
+
else
|
|
10842
|
+
delete mergedEnv.BOTMUX_FEEDBACK_POLICY;
|
|
10747
10843
|
// Re-freeze the no-transport capability keys AFTER the merge: a stale or
|
|
10748
10844
|
// attacker-shaped backendConfig.env / per-bot env merges LAST and would
|
|
10749
10845
|
// otherwise override the frozen values, restoring send capability for a
|
|
@@ -10896,6 +10992,19 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
10896
10992
|
resolvedBin: canonicalPolicyPath(cliAdapter.resolvedBin),
|
|
10897
10993
|
})
|
|
10898
10994
|
: undefined;
|
|
10995
|
+
const managedOriginChannelRequired = willReadIsolate
|
|
10996
|
+
|| credentialOnlySeatbelt
|
|
10997
|
+
|| credentialOnlyBwrap;
|
|
10998
|
+
const managedOriginChannelPolicyDigest = (willReadIsolate || willWriteSandbox)
|
|
10999
|
+
? darwinIsolationPolicyDigest
|
|
11000
|
+
: managedOriginChannelRequired
|
|
11001
|
+
? createHash('sha256').update(JSON.stringify({
|
|
11002
|
+
domain: 'botmux.credential-origin-channel.v1',
|
|
11003
|
+
platform: process.platform,
|
|
11004
|
+
configuredBotmuxHome: canonicalPolicyPath(configuredBotmuxHome),
|
|
11005
|
+
defaultBotmuxHome: canonicalPolicyPath(defaultBotmuxHome),
|
|
11006
|
+
})).digest('hex')
|
|
11007
|
+
: undefined;
|
|
10899
11008
|
let mcpRuntimeManifest = readSessionMcpRuntimeManifest(cfg.sessionId, config.session.dataDir);
|
|
10900
11009
|
const hasMcpRuntimeEntries = !!cliAdapter.mcpGateway && !!mcpRuntimeManifest?.entries.length;
|
|
10901
11010
|
const reuseRecordedHerdrTarget = !sandboxRequested && !hasMcpRuntimeEntries;
|
|
@@ -11052,8 +11161,7 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
11052
11161
|
if (paneLive) {
|
|
11053
11162
|
const markerPath = join(isolationRuntimeDataDir, 'read-isolation', `${cfg.sessionId}.boot`);
|
|
11054
11163
|
const marker = readManagedOriginAuthorityFile(markerPath);
|
|
11055
|
-
const
|
|
11056
|
-
&& (willReadIsolate || willWriteSandbox);
|
|
11164
|
+
const originChannelPolicyExpected = !!managedOriginChannelPolicyDigest;
|
|
11057
11165
|
// A stamped pane must match even when the new policy is OFF. Otherwise a
|
|
11058
11166
|
// disable followed by restart could reattach the still-confined process
|
|
11059
11167
|
// without rebuilding its authority/profile. An unsafe planted marker
|
|
@@ -11062,16 +11170,16 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
11062
11170
|
? isolatedPaneReattachSafe(marker, {
|
|
11063
11171
|
requiredCapabilities: appliedIsolationCapabilities,
|
|
11064
11172
|
exactCapabilities: true,
|
|
11065
|
-
...(
|
|
11173
|
+
...(originChannelPolicyExpected ? {
|
|
11066
11174
|
readIsolation: willReadIsolate,
|
|
11067
11175
|
writeSandbox: willWriteSandbox,
|
|
11068
11176
|
requireOriginChannel: true,
|
|
11069
|
-
policyDigest:
|
|
11177
|
+
policyDigest: managedOriginChannelPolicyDigest,
|
|
11070
11178
|
} : {}),
|
|
11071
11179
|
})
|
|
11072
11180
|
: marker === null && !hostEntryExistsNoFollow(markerPath);
|
|
11073
11181
|
if (policyMatches) {
|
|
11074
|
-
if (
|
|
11182
|
+
if (originChannelPolicyExpected) {
|
|
11075
11183
|
persistentPaneOriginChannelId = isolatedPaneOriginChannel(marker);
|
|
11076
11184
|
}
|
|
11077
11185
|
// Pane was spawned under the current isolation policy → still confined
|
|
@@ -11132,7 +11240,7 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
11132
11240
|
}
|
|
11133
11241
|
}
|
|
11134
11242
|
}
|
|
11135
|
-
readIsolationOriginChannelId =
|
|
11243
|
+
readIsolationOriginChannelId = managedOriginChannelRequired
|
|
11136
11244
|
? (persistentPaneOriginChannelId ?? randomBytes(32).toString('hex'))
|
|
11137
11245
|
: null;
|
|
11138
11246
|
if (readIsolationOriginChannelId) {
|
|
@@ -11479,7 +11587,7 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
11479
11587
|
try {
|
|
11480
11588
|
const credPath = sendCredFilePath(process.env.SESSION_DATA_DIR, cfg.larkAppId);
|
|
11481
11589
|
mkdirSync(dirname(credPath), { recursive: true });
|
|
11482
|
-
writeFileSync(credPath, JSON.stringify({ larkAppId: cfg.larkAppId, larkAppSecret: cfg.larkAppSecret, brand: cfg.brand, apiOnly: cfg.apiOnly }), { mode: 0o600 });
|
|
11590
|
+
writeFileSync(credPath, JSON.stringify({ larkAppId: cfg.larkAppId, larkAppSecret: cfg.larkAppSecret, brand: cfg.brand, apiOnly: cfg.apiOnly, feedback: cfg.feedback }), { mode: 0o600 });
|
|
11483
11591
|
}
|
|
11484
11592
|
catch (e) {
|
|
11485
11593
|
log(`[sandbox] WARN could not write send-cred file: ${e.message}`);
|
|
@@ -11772,8 +11880,19 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
11772
11880
|
throw new Error('[read-isolation] origin channel is unavailable');
|
|
11773
11881
|
}
|
|
11774
11882
|
childEnv.BOTMUX_READ_ISOLATED = '1';
|
|
11883
|
+
}
|
|
11884
|
+
if (readIsolationOriginChannelId) {
|
|
11775
11885
|
childEnv.BOTMUX_ORIGIN_CHANNEL_ID = readIsolationOriginChannelId;
|
|
11776
11886
|
}
|
|
11887
|
+
// Credential-only children have no writable relay outbox. Publish the same
|
|
11888
|
+
// rotating managed-origin claim through a host-owned per-channel directory
|
|
11889
|
+
// before the Seatbelt/bwrap wrapper is compiled, then expose only that
|
|
11890
|
+
// directory read-only below.
|
|
11891
|
+
if (readIsolationOriginChannelId && !sandboxRequested) {
|
|
11892
|
+
readIsolationOriginCapabilityFile = managedOriginCapabilityPath(isolationRuntimeDataDir, cfg.sessionId, readIsolationOriginChannelId);
|
|
11893
|
+
ensureManagedOriginCapabilityLeafSafe(readIsolationOriginCapabilityFile);
|
|
11894
|
+
publishSandboxRelayCapability({ failClosed: true });
|
|
11895
|
+
}
|
|
11777
11896
|
// Per-bot env (bots.json `env`): extra vars for THIS bot's CLI only — e.g.
|
|
11778
11897
|
// ANTHROPIC_BASE_URL/ANTHROPIC_AUTH_TOKEN to run a bot on GLM/a 3rd-party
|
|
11779
11898
|
// provider, an HTTPS_PROXY, or a CLI feature flag. Passed as injectEnv (NOT
|
|
@@ -11948,6 +12067,11 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
11948
12067
|
writeFileSync(tsFile, '');
|
|
11949
12068
|
}
|
|
11950
12069
|
catch { /* */ }
|
|
12070
|
+
// UserPromptSubmit sidecar 目录(#794):daemon 逐 turn 写入,沙盒内 hook 只读。
|
|
12071
|
+
try {
|
|
12072
|
+
mkdirSync(join(dataDir, 'prompt-ctx', cfg.sessionId), { recursive: true, mode: 0o700 });
|
|
12073
|
+
}
|
|
12074
|
+
catch { /* */ }
|
|
11951
12075
|
try {
|
|
11952
12076
|
mkdirSync(join(dataDir, 'attachments', cfg.larkAppId), { recursive: true });
|
|
11953
12077
|
}
|
|
@@ -12002,7 +12126,7 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
12002
12126
|
if (readIsolationOriginCapabilityFile) {
|
|
12003
12127
|
ensureManagedOriginCapabilityLeafSafe(readIsolationOriginCapabilityFile);
|
|
12004
12128
|
publishSandboxRelayCapability({ failClosed: true });
|
|
12005
|
-
mandatoryReadOnlyPaths.push(
|
|
12129
|
+
mandatoryReadOnlyPaths.push(managedOriginCapabilityDirectory(dataDir, cfg.sessionId, readIsolationOriginChannelId));
|
|
12006
12130
|
mandatoryReadOnlyPaths.push(managedOriginAttestationDirectory(dataDir, cfg.sessionId, readIsolationOriginChannelId));
|
|
12007
12131
|
mandatoryReadOnlyPaths.push(managedOriginRootLocatorPath(userInfo().homedir, cfg.sessionId));
|
|
12008
12132
|
}
|
|
@@ -12288,12 +12412,12 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
12288
12412
|
try {
|
|
12289
12413
|
const markerDir = join(isolationRuntimeDataDir, 'read-isolation');
|
|
12290
12414
|
mkdirSync(markerDir, { recursive: true });
|
|
12291
|
-
replaceManagedOriginCapabilityFile(join(markerDir, `${cfg.sessionId}.boot`), isolationPaneMarkerContent(cfg.daemonBootId ?? '', appliedIsolationCapabilities,
|
|
12415
|
+
replaceManagedOriginCapabilityFile(join(markerDir, `${cfg.sessionId}.boot`), isolationPaneMarkerContent(cfg.daemonBootId ?? '', appliedIsolationCapabilities, managedOriginChannelPolicyDigest
|
|
12292
12416
|
? {
|
|
12293
12417
|
originChannelId: persistentPaneOriginChannelId,
|
|
12294
12418
|
readIsolation: willReadIsolate,
|
|
12295
12419
|
writeSandbox: willWriteSandbox,
|
|
12296
|
-
policyDigest:
|
|
12420
|
+
policyDigest: managedOriginChannelPolicyDigest,
|
|
12297
12421
|
}
|
|
12298
12422
|
: undefined));
|
|
12299
12423
|
}
|
|
@@ -12337,11 +12461,13 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
12337
12461
|
// the input box). cjadk's own botmux integration (`cjadk feishu`, see its
|
|
12338
12462
|
// botmux-wrapper-writer) sets CJADK_INTERACTIVE=0 to disable all of that.
|
|
12339
12463
|
// We mirror it here so a `cjadk <agent>` wrapperCli is driven the way
|
|
12340
|
-
// cjadk intends — no selector, clean soft-newline input.
|
|
12341
|
-
//
|
|
12342
|
-
|
|
12343
|
-
|
|
12344
|
-
|
|
12464
|
+
// cjadk intends — no selector, clean soft-newline input. The env set
|
|
12465
|
+
// comes from wrapperLaunchEnv — the shared single source of truth also
|
|
12466
|
+
// used by one-shot children (session-group AI titling).
|
|
12467
|
+
const wrapperEnv = wrapperLaunchEnv(cfg.wrapperCli);
|
|
12468
|
+
if (wrapperEnv) {
|
|
12469
|
+
Object.assign(childEnv, wrapperEnv);
|
|
12470
|
+
log(`wrapper launcher env applied: ${Object.keys(wrapperEnv).join(', ')} (mirrors the wrapper's own non-interactive integration)`);
|
|
12345
12471
|
}
|
|
12346
12472
|
}
|
|
12347
12473
|
}
|
|
@@ -12379,8 +12505,9 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
12379
12505
|
});
|
|
12380
12506
|
const profileDir = join(isolationRuntimeDataDir, 'read-isolation');
|
|
12381
12507
|
mkdirSync(profileDir, { recursive: true });
|
|
12508
|
+
const originDirectory = managedOriginCapabilityDirectory(isolationRuntimeDataDir, cfg.sessionId, readIsolationOriginChannelId);
|
|
12382
12509
|
const profilePath = join(profileDir, `${cfg.sessionId}.sb`);
|
|
12383
|
-
replaceManagedOriginCapabilityFile(profilePath, buildSeatbeltProfile(rules.denyPaths.map(canonical), [], [], [], rules.denyRegexes, undefined, {
|
|
12510
|
+
replaceManagedOriginCapabilityFile(profilePath, buildSeatbeltProfile([...rules.denyPaths.map(canonical), canonical(profileDir)], [canonical(originDirectory)], [], [canonical(profileDir)], rules.denyRegexes, undefined, {
|
|
12384
12511
|
denyWritePaths: [...new Set([
|
|
12385
12512
|
...rules.denyWritePaths.map(canonical),
|
|
12386
12513
|
canonical(profileDir),
|
|
@@ -12482,7 +12609,10 @@ async function spawnCli(cfg, opts = {}) {
|
|
|
12482
12609
|
const credentialSandbox = prepareCredentialOnlySandbox({
|
|
12483
12610
|
hideDirectories: [...hideDirectories],
|
|
12484
12611
|
hideFiles: [...hideFiles],
|
|
12485
|
-
|
|
12612
|
+
privateReadonlyDirectories: [{
|
|
12613
|
+
parent: realpathSync(panePolicyDir),
|
|
12614
|
+
directory: realpathSync(managedOriginCapabilityDirectory(isolationRuntimeDataDir, cfg.sessionId, readIsolationOriginChannelId)),
|
|
12615
|
+
}],
|
|
12486
12616
|
workingDir: spawnCwd,
|
|
12487
12617
|
cliBin: credentialCliBin,
|
|
12488
12618
|
cliArgs: spawnArgs,
|
|
@@ -13590,6 +13720,7 @@ function startWebServer(host, preferredPort) {
|
|
|
13590
13720
|
// normal buffer until resize causes a redraw. Preserve that mode so
|
|
13591
13721
|
// scroll gestures continue to target the CLI's own transcript.
|
|
13592
13722
|
const forceRemoteScroll = effectiveBackendType === 'herdr' && cliAdapter?.altScreen === true;
|
|
13723
|
+
const allowReadOnlyRemoteScroll = canHandleReadOnlyRemoteScroll();
|
|
13593
13724
|
// The wheel burst cap throttles backends where a forwarded wheel is
|
|
13594
13725
|
// EXPENSIVE or has no local terminal to drive:
|
|
13595
13726
|
// • Herdr — each forwarded wheel → pane send-text + snapshot re-render.
|
|
@@ -13607,7 +13738,7 @@ function startWebServer(host, preferredPort) {
|
|
|
13607
13738
|
|| effectiveBackendType === 'tmux'
|
|
13608
13739
|
|| effectiveBackendType === 'zellij';
|
|
13609
13740
|
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
13610
|
-
res.end(getTerminalHtml(hasWrite, platformReadonly, loginUrl, forceRemoteScroll, localTerminalBackend));
|
|
13741
|
+
res.end(getTerminalHtml(hasWrite, platformReadonly, loginUrl, forceRemoteScroll, localTerminalBackend, allowReadOnlyRemoteScroll));
|
|
13611
13742
|
});
|
|
13612
13743
|
wss = new WebSocketServer({
|
|
13613
13744
|
server: httpServer,
|
|
@@ -13639,6 +13770,7 @@ function startWebServer(host, preferredPort) {
|
|
|
13639
13770
|
return;
|
|
13640
13771
|
}
|
|
13641
13772
|
const { hasWrite } = resolveTerminalAccessForReq(req, url);
|
|
13773
|
+
const allowReadOnlyRemoteScroll = canHandleReadOnlyRemoteScroll();
|
|
13642
13774
|
if (hasWrite)
|
|
13643
13775
|
authedClients.add(ws);
|
|
13644
13776
|
log(`WS client connected (total: ${wsClients.size}, write: ${hasWrite})`);
|
|
@@ -13890,6 +14022,18 @@ function startWebServer(host, preferredPort) {
|
|
|
13890
14022
|
}
|
|
13891
14023
|
backend?.write(msg.data);
|
|
13892
14024
|
}
|
|
14025
|
+
else if (msg.type === 'scroll' && typeof msg.data === 'string') {
|
|
14026
|
+
if (!allowReadOnlyRemoteScroll || authedClients.has(ws))
|
|
14027
|
+
return;
|
|
14028
|
+
const parsed = parseReadOnlyRemoteScrollPayload(msg.data);
|
|
14029
|
+
if (!parsed)
|
|
14030
|
+
return;
|
|
14031
|
+
if (!readOnlyRemoteScrollLimiter.tryConsume(parsed.eventCount))
|
|
14032
|
+
return;
|
|
14033
|
+
if (usesHerdrSnapshotWebHistory())
|
|
14034
|
+
herdrWebScrollDirection = parsed.direction;
|
|
14035
|
+
backend?.write(msg.data);
|
|
14036
|
+
}
|
|
13893
14037
|
}
|
|
13894
14038
|
catch { /* ignore non-JSON or bad messages */ }
|
|
13895
14039
|
});
|
|
@@ -13912,7 +14056,7 @@ function startWebServer(host, preferredPort) {
|
|
|
13912
14056
|
.then(resolve, reject);
|
|
13913
14057
|
});
|
|
13914
14058
|
}
|
|
13915
|
-
function getTerminalHtml(hasWrite, platformReadonly = false, loginUrl = '', forceRemoteScroll = false, localTerminalBackend = false) {
|
|
14059
|
+
function getTerminalHtml(hasWrite, platformReadonly = false, loginUrl = '', forceRemoteScroll = false, localTerminalBackend = false, allowReadOnlyRemoteScroll = false) {
|
|
13916
14060
|
const label = sessionId.substring(0, 8);
|
|
13917
14061
|
return `<!DOCTYPE html>
|
|
13918
14062
|
<html>
|
|
@@ -14050,6 +14194,7 @@ var hasToken=${hasWrite};
|
|
|
14050
14194
|
var platformReadonly=${platformReadonly};
|
|
14051
14195
|
var remoteScroll=${forceRemoteScroll};
|
|
14052
14196
|
var localTerminalBackend=${localTerminalBackend};
|
|
14197
|
+
var readOnlyRemoteScroll=${allowReadOnlyRemoteScroll};
|
|
14053
14198
|
if(!hasToken){
|
|
14054
14199
|
if(platformReadonly){var _lb=document.getElementById('login-banner');_lb.classList.add('show');}
|
|
14055
14200
|
else{var _rb=document.getElementById('readonly-banner');_rb.classList.add('show');_rb.addEventListener('click',function(){_rb.classList.remove('show')});}
|
|
@@ -14346,8 +14491,9 @@ window.addEventListener('resize',onViewportResize);
|
|
|
14346
14491
|
// Alt-screen + mouse-mode CLIs (e.g. Claude Code) keep NO scrollback in xterm OR
|
|
14347
14492
|
// tmux — their whole transcript is redrawn by the app inside the fixed alt-screen
|
|
14348
14493
|
// grid, so term.scrollLines() reveals nothing. In the alternate buffer we forward
|
|
14349
|
-
// scrolling as SGR mouse-wheel events so the CLI scrolls its own transcript
|
|
14350
|
-
//
|
|
14494
|
+
// scrolling as SGR mouse-wheel events so the CLI scrolls its own transcript.
|
|
14495
|
+
// Read-only viewers get this remote path only for adapters that explicitly opt
|
|
14496
|
+
// in; the server then accepts only validated wheel events, never general input.
|
|
14351
14497
|
// Normal-buffer CLIs keep xterm's native scrollback scroll. Capture-phase +
|
|
14352
14498
|
// stopPropagation pre-empts xterm's own handler. Skipped for pure tmux/zellij
|
|
14353
14499
|
// ATTACH (gate), where the attach client owns scrolling via copy-mode.
|
|
@@ -14407,7 +14553,7 @@ function _cellAt(clientX,clientY){
|
|
|
14407
14553
|
return col+';'+row;
|
|
14408
14554
|
}
|
|
14409
14555
|
function _fwdScroll(px,coord){
|
|
14410
|
-
if(!hasToken||!ws_||ws_.readyState!==1||!px)return;
|
|
14556
|
+
if((!hasToken&&!readOnlyRemoteScroll)||!ws_||ws_.readyState!==1||!px)return;
|
|
14411
14557
|
coord=coord||(((term.cols>>1)+1)+';'+((term.rows>>1)+1)); // never (1,1)
|
|
14412
14558
|
var dir=px<0?-1:1;
|
|
14413
14559
|
if(_scrollBurstDir&&dir!==_scrollBurstDir){_scrollAccum=0;_scrollBurstTicks=0;}
|
|
@@ -14421,7 +14567,7 @@ function _fwdScroll(px,coord){
|
|
|
14421
14567
|
_scrollAccum+=up?_SCROLL_STEP:-_SCROLL_STEP;n++;_scrollBurstTicks++;
|
|
14422
14568
|
}
|
|
14423
14569
|
if(_scrollBurstTicks>=_SCROLL_BURST_MAX)_scrollAccum=0;
|
|
14424
|
-
if(data)ws_.send(JSON.stringify({type:'input',data:data}));
|
|
14570
|
+
if(data)ws_.send(JSON.stringify({type:hasToken?'input':'scroll',data:data}));
|
|
14425
14571
|
}
|
|
14426
14572
|
if(!${isTmuxMode && !isPipeMode}){
|
|
14427
14573
|
document.getElementById('terminal').addEventListener('wheel',function(e){
|
|
@@ -14434,7 +14580,9 @@ if(!${isTmuxMode && !isPipeMode}){
|
|
|
14434
14580
|
return;
|
|
14435
14581
|
}
|
|
14436
14582
|
if(!hasToken){
|
|
14437
|
-
e.preventDefault();e.stopPropagation();
|
|
14583
|
+
e.preventDefault();e.stopPropagation();
|
|
14584
|
+
if(readOnlyRemoteScroll)_fwdScroll(px,_cellAt(e.clientX,e.clientY));
|
|
14585
|
+
else term.scrollLines(e.deltaY>0?3:-3);return;
|
|
14438
14586
|
}
|
|
14439
14587
|
e.preventDefault();e.stopPropagation();
|
|
14440
14588
|
_fwdScroll(px,_cellAt(e.clientX,e.clientY)); // report the cell under the pointer
|
|
@@ -14755,8 +14903,7 @@ if(!${isTmuxMode && !isPipeMode}){
|
|
|
14755
14903
|
if(e.touches.length===1)_tLastY=e.touches[0].clientY;
|
|
14756
14904
|
},{capture:true,passive:true});
|
|
14757
14905
|
_tTerm.addEventListener('touchmove',function(e){
|
|
14758
|
-
|
|
14759
|
-
if(!hasToken||_tLastY===null||e.touches.length!==1)return;
|
|
14906
|
+
if((!hasToken&&!readOnlyRemoteScroll)||_tLastY===null||e.touches.length!==1)return;
|
|
14760
14907
|
e.preventDefault();e.stopPropagation();
|
|
14761
14908
|
var y=e.touches[0].clientY;
|
|
14762
14909
|
var px=_tLastY-y;
|
|
@@ -15934,7 +16081,17 @@ process.on('message', async (raw) => {
|
|
|
15934
16081
|
break;
|
|
15935
16082
|
}
|
|
15936
16083
|
closeRequested = true;
|
|
15937
|
-
|
|
16084
|
+
// This ACK is what resolves the daemon's close fence (worker-pool
|
|
16085
|
+
// resolveCloseFence) so `/close` can return. It MUST be flushed: a plain
|
|
16086
|
+
// send() only queues on process.send's async IPC buffer, and the fully
|
|
16087
|
+
// synchronous teardown + process.exit(0) below never yield the event loop
|
|
16088
|
+
// to drain it. Worse, process.exit(0) can wedge in node-pty's native
|
|
16089
|
+
// reader-thread join whenever a web-terminal client PTY was attached — so
|
|
16090
|
+
// the queued ACK would be lost entirely and the fence would only resolve
|
|
16091
|
+
// on the daemon's 7s SIGKILL backstop (the ~7s dashboard/card close stall).
|
|
16092
|
+
// closeRequested already fences bridge-marker reads, so ACKing before
|
|
16093
|
+
// teardown stays safe; sendAndFlush yields so the ACK truly departs.
|
|
16094
|
+
await sendAndFlush({ type: 'session_close_ready', sessionId });
|
|
15938
16095
|
stopScreenshotLoop();
|
|
15939
16096
|
stopBridgeWatcher();
|
|
15940
16097
|
stopCodexBridge();
|
|
@@ -16115,7 +16272,11 @@ process.on('message', async (raw) => {
|
|
|
16115
16272
|
lastAbortedCloseRequestId = null;
|
|
16116
16273
|
backend?.commitDestroySession?.();
|
|
16117
16274
|
closeRequested = true;
|
|
16118
|
-
|
|
16275
|
+
// Flush the fence-resolving ACK before the synchronous teardown +
|
|
16276
|
+
// process.exit(0); see the local-close case for the node-pty exit-wedge
|
|
16277
|
+
// rationale (a queued send() would be dropped and strand `/close` behind
|
|
16278
|
+
// the daemon's 7s SIGKILL backstop).
|
|
16279
|
+
await sendAndFlush({ type: 'session_close_ready', sessionId });
|
|
16119
16280
|
stopScreenshotLoop();
|
|
16120
16281
|
stopBridgeWatcher();
|
|
16121
16282
|
stopCodexBridge();
|