botmux 3.4.2 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +10 -7
- package/README.md +11 -6
- package/dist/adapters/backend/herdr-backend.d.ts +43 -6
- package/dist/adapters/backend/herdr-backend.d.ts.map +1 -1
- package/dist/adapters/backend/herdr-backend.js +362 -28
- package/dist/adapters/backend/herdr-backend.js.map +1 -1
- package/dist/adapters/backend/reproduce-command.d.ts +39 -0
- package/dist/adapters/backend/reproduce-command.d.ts.map +1 -0
- package/dist/adapters/backend/reproduce-command.js +63 -0
- package/dist/adapters/backend/reproduce-command.js.map +1 -0
- package/dist/adapters/backend/session-backend-selector.d.ts +10 -1
- package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -1
- package/dist/adapters/backend/session-backend-selector.js +73 -4
- package/dist/adapters/backend/session-backend-selector.js.map +1 -1
- package/dist/adapters/backend/types.d.ts +16 -0
- package/dist/adapters/backend/types.d.ts.map +1 -1
- package/dist/adapters/backend/types.js.map +1 -1
- package/dist/adapters/cli/pi-initial-prompt-extension.d.ts +27 -0
- package/dist/adapters/cli/pi-initial-prompt-extension.d.ts.map +1 -0
- package/dist/adapters/cli/pi-initial-prompt-extension.js +38 -0
- package/dist/adapters/cli/pi-initial-prompt-extension.js.map +1 -0
- package/dist/adapters/cli/pi-initial-prompt.d.ts +21 -0
- package/dist/adapters/cli/pi-initial-prompt.d.ts.map +1 -0
- package/dist/adapters/cli/pi-initial-prompt.js +59 -0
- package/dist/adapters/cli/pi-initial-prompt.js.map +1 -0
- package/dist/adapters/cli/pi.d.ts.map +1 -1
- package/dist/adapters/cli/pi.js +15 -4
- package/dist/adapters/cli/pi.js.map +1 -1
- package/dist/adapters/cli/read-isolation.d.ts.map +1 -1
- package/dist/adapters/cli/read-isolation.js +5 -0
- package/dist/adapters/cli/read-isolation.js.map +1 -1
- package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
- package/dist/adapters/cli/shared-hints.js +8 -0
- package/dist/adapters/cli/shared-hints.js.map +1 -1
- package/dist/adapters/cli/traex.d.ts.map +1 -1
- package/dist/adapters/cli/traex.js +5 -0
- package/dist/adapters/cli/traex.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +23 -3
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/adapters/hook-installer.d.ts +7 -0
- package/dist/adapters/hook-installer.d.ts.map +1 -1
- package/dist/adapters/hook-installer.js +56 -0
- package/dist/adapters/hook-installer.js.map +1 -1
- package/dist/bot-registry.d.ts +13 -0
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +118 -2
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/capabilities.d.ts +24 -0
- package/dist/cli/capabilities.d.ts.map +1 -0
- package/dist/cli/capabilities.js +25 -0
- package/dist/cli/capabilities.js.map +1 -0
- package/dist/cli/create-group-resolver.d.ts +24 -0
- package/dist/cli/create-group-resolver.d.ts.map +1 -1
- package/dist/cli/create-group-resolver.js +23 -0
- package/dist/cli/create-group-resolver.js.map +1 -1
- package/dist/cli/daemon-lifecycle-env.d.ts +5 -7
- package/dist/cli/daemon-lifecycle-env.d.ts.map +1 -1
- package/dist/cli/daemon-lifecycle-env.js +13 -7
- package/dist/cli/daemon-lifecycle-env.js.map +1 -1
- package/dist/cli/exact-chat-grant-client.d.ts +48 -0
- package/dist/cli/exact-chat-grant-client.d.ts.map +1 -0
- package/dist/cli/exact-chat-grant-client.js +108 -0
- package/dist/cli/exact-chat-grant-client.js.map +1 -0
- package/dist/cli/exact-chat-grant.d.ts +18 -0
- package/dist/cli/exact-chat-grant.d.ts.map +1 -0
- package/dist/cli/exact-chat-grant.js +97 -0
- package/dist/cli/exact-chat-grant.js.map +1 -0
- package/dist/cli.d.ts +10 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +770 -126
- package/dist/cli.js.map +1 -1
- package/dist/codex-rpc-engine.d.ts +26 -0
- package/dist/codex-rpc-engine.d.ts.map +1 -1
- package/dist/codex-rpc-engine.js +113 -2
- package/dist/codex-rpc-engine.js.map +1 -1
- package/dist/config.d.ts +16 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +16 -0
- package/dist/config.js.map +1 -1
- package/dist/core/bot-live-control.d.ts +41 -0
- package/dist/core/bot-live-control.d.ts.map +1 -0
- package/dist/core/bot-live-control.js +135 -0
- package/dist/core/bot-live-control.js.map +1 -0
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +28 -8
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/daemon-config-fence.d.ts +8 -0
- package/dist/core/daemon-config-fence.d.ts.map +1 -0
- package/dist/core/daemon-config-fence.js +13 -0
- package/dist/core/daemon-config-fence.js.map +1 -0
- package/dist/core/dashboard-events.d.ts +5 -0
- package/dist/core/dashboard-events.d.ts.map +1 -1
- package/dist/core/dashboard-events.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts +21 -2
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +232 -5
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dispatch-registry.d.ts +12 -0
- package/dist/core/dispatch-registry.d.ts.map +1 -0
- package/dist/core/dispatch-registry.js +33 -0
- package/dist/core/dispatch-registry.js.map +1 -0
- package/dist/core/dispatch.d.ts +99 -0
- package/dist/core/dispatch.d.ts.map +1 -1
- package/dist/core/dispatch.js +136 -0
- package/dist/core/dispatch.js.map +1 -1
- package/dist/core/inflight-input-tracker.d.ts +1 -0
- package/dist/core/inflight-input-tracker.d.ts.map +1 -1
- package/dist/core/inflight-input-tracker.js.map +1 -1
- package/dist/core/maintenance.d.ts.map +1 -1
- package/dist/core/maintenance.js +10 -3
- package/dist/core/maintenance.js.map +1 -1
- package/dist/core/persistent-backend.d.ts +16 -2
- package/dist/core/persistent-backend.d.ts.map +1 -1
- package/dist/core/persistent-backend.js +40 -0
- package/dist/core/persistent-backend.js.map +1 -1
- package/dist/core/session-discovery.d.ts +8 -1
- package/dist/core/session-discovery.d.ts.map +1 -1
- package/dist/core/session-discovery.js +140 -8
- package/dist/core/session-discovery.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +12 -8
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-title.d.ts +8 -0
- package/dist/core/session-title.d.ts.map +1 -1
- package/dist/core/session-title.js +54 -0
- package/dist/core/session-title.js.map +1 -1
- package/dist/core/terminal-write-auth.d.ts +15 -0
- package/dist/core/terminal-write-auth.d.ts.map +1 -1
- package/dist/core/terminal-write-auth.js +20 -0
- package/dist/core/terminal-write-auth.js.map +1 -1
- package/dist/core/trigger-session.d.ts.map +1 -1
- package/dist/core/trigger-session.js +3 -2
- package/dist/core/trigger-session.js.map +1 -1
- package/dist/core/types.d.ts +33 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/worker-pool.d.ts +27 -8
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +389 -19
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts +4 -2
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +397 -26
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/bot-onboarding.d.ts +127 -1
- package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
- package/dist/dashboard/bot-onboarding.js +1104 -25
- package/dist/dashboard/bot-onboarding.js.map +1 -1
- package/dist/dashboard/debug-terminal.d.ts +18 -0
- package/dist/dashboard/debug-terminal.d.ts.map +1 -0
- package/dist/dashboard/debug-terminal.js +338 -0
- package/dist/dashboard/debug-terminal.js.map +1 -0
- package/dist/dashboard/public-redact.d.ts +2 -0
- package/dist/dashboard/public-redact.d.ts.map +1 -1
- package/dist/dashboard/public-redact.js +12 -3
- package/dist/dashboard/public-redact.js.map +1 -1
- package/dist/dashboard/registry.d.ts +8 -0
- package/dist/dashboard/registry.d.ts.map +1 -1
- package/dist/dashboard/registry.js +13 -0
- package/dist/dashboard/registry.js.map +1 -1
- package/dist/dashboard/settings-write-applier.d.ts +47 -1
- package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
- package/dist/dashboard/settings-write-applier.js +102 -1
- package/dist/dashboard/settings-write-applier.js.map +1 -1
- package/dist/dashboard/web/app.d.ts.map +1 -1
- package/dist/dashboard/web/app.js +2 -0
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts +1 -0
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.js +24 -5
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts +15 -0
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js +19 -0
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +76 -6
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/icon-tooltip.d.ts +3 -0
- package/dist/dashboard/web/icon-tooltip.d.ts.map +1 -0
- package/dist/dashboard/web/icon-tooltip.js +108 -0
- package/dist/dashboard/web/icon-tooltip.js.map +1 -0
- package/dist/dashboard/web/sessions-kanban.js +2 -2
- package/dist/dashboard/web/sessions-kanban.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-page.js +48 -9
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts +2 -0
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +46 -2
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/settings-page.d.ts +78 -0
- package/dist/dashboard/web/settings-page.d.ts.map +1 -1
- package/dist/dashboard/web/settings-page.js +88 -1
- package/dist/dashboard/web/settings-page.js.map +1 -1
- package/dist/dashboard/web/store.d.ts +2 -0
- package/dist/dashboard/web/store.d.ts.map +1 -1
- package/dist/dashboard/web/store.js +13 -1
- package/dist/dashboard/web/store.js.map +1 -1
- package/dist/dashboard-web/app.js +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-O376WSER.js +5 -0
- package/dist/dashboard-web/chunks/{chunk-JNRSPKLS.js → chunk-EJDYUINZ.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-CUV65BIQ.js → chunk-H7P5UV4W.js} +6 -6
- package/dist/dashboard-web/chunks/{chunk-P6GO5KT4.js → chunk-QCPPKCX3.js} +1 -1
- package/dist/dashboard-web/chunks/{chunk-UBOLHQCK.js → chunk-WXPMNEYV.js} +1 -1
- package/dist/dashboard-web/chunks/{connectors-page-KTC2QWNW.js → connectors-page-IR54AOAI.js} +1 -1
- package/dist/dashboard-web/chunks/{groups-page-B3EKGOLY.js → groups-page-3P4TLUMF.js} +1 -1
- package/dist/dashboard-web/chunks/{insights-page-X6RXNCWX.js → insights-page-TDCZV56A.js} +1 -1
- package/dist/dashboard-web/chunks/{monitor-room-LLRA5LQW.js → monitor-room-QWCWL3SX.js} +1 -1
- package/dist/dashboard-web/chunks/{monitoring-page-7MT5FEOS.js → monitoring-page-IOWFSNVC.js} +1 -1
- package/dist/dashboard-web/chunks/{office-page-KD46D5TD.js → office-page-5AUPEHZP.js} +1 -1
- package/dist/dashboard-web/chunks/{overview-page-JUWNH32O.js → overview-page-QJMI6NLW.js} +1 -1
- package/dist/dashboard-web/chunks/{roles-page-P6F7NLOI.js → roles-page-WJVB52ET.js} +1 -1
- package/dist/dashboard-web/chunks/{schedules-page-XIHWZST4.js → schedules-page-RVRWHP4V.js} +1 -1
- package/dist/dashboard-web/chunks/sessions-page-KWLGBX6G.js +3 -0
- package/dist/dashboard-web/chunks/settings-page-TNZEPC7V.js +2 -0
- package/dist/dashboard-web/chunks/{skills-page-A46KVWBL.js → skills-page-7YT5TIX5.js} +1 -1
- package/dist/dashboard-web/chunks/{team-federation-page-SDUC56DF.js → team-federation-page-NJZKTU7A.js} +1 -1
- package/dist/dashboard-web/chunks/{v3-page-J5JOTUSQ.js → v3-page-NQ73UA2Q.js} +1 -1
- package/dist/dashboard-web/chunks/{whiteboards-page-U7LSOAWI.js → whiteboards-page-DSM3MDMN.js} +1 -1
- package/dist/dashboard-web/style.css +198 -7
- package/dist/dashboard.js +294 -7
- package/dist/dashboard.js.map +1 -1
- package/dist/features/codex-notifier/adoption.d.ts +11 -0
- package/dist/features/codex-notifier/adoption.d.ts.map +1 -0
- package/dist/features/codex-notifier/adoption.js +11 -0
- package/dist/features/codex-notifier/adoption.js.map +1 -0
- package/dist/features/codex-notifier/app-opener.d.ts +21 -0
- package/dist/features/codex-notifier/app-opener.d.ts.map +1 -0
- package/dist/features/codex-notifier/app-opener.js +33 -0
- package/dist/features/codex-notifier/app-opener.js.map +1 -0
- package/dist/features/codex-notifier/card-action.d.ts +27 -0
- package/dist/features/codex-notifier/card-action.d.ts.map +1 -0
- package/dist/features/codex-notifier/card-action.js +84 -0
- package/dist/features/codex-notifier/card-action.js.map +1 -0
- package/dist/features/codex-notifier/card.d.ts +12 -0
- package/dist/features/codex-notifier/card.d.ts.map +1 -0
- package/dist/features/codex-notifier/card.js +150 -0
- package/dist/features/codex-notifier/card.js.map +1 -0
- package/dist/features/codex-notifier/codex-context.d.ts +12 -0
- package/dist/features/codex-notifier/codex-context.d.ts.map +1 -0
- package/dist/features/codex-notifier/codex-context.js +161 -0
- package/dist/features/codex-notifier/codex-context.js.map +1 -0
- package/dist/features/codex-notifier/config.d.ts +9 -0
- package/dist/features/codex-notifier/config.d.ts.map +1 -0
- package/dist/features/codex-notifier/config.js +11 -0
- package/dist/features/codex-notifier/config.js.map +1 -0
- package/dist/features/codex-notifier/confirmed-turn.d.ts +20 -0
- package/dist/features/codex-notifier/confirmed-turn.d.ts.map +1 -0
- package/dist/features/codex-notifier/confirmed-turn.js +130 -0
- package/dist/features/codex-notifier/confirmed-turn.js.map +1 -0
- package/dist/features/codex-notifier/emitter.d.ts +13 -0
- package/dist/features/codex-notifier/emitter.d.ts.map +1 -0
- package/dist/features/codex-notifier/emitter.js +33 -0
- package/dist/features/codex-notifier/emitter.js.map +1 -0
- package/dist/features/codex-notifier/event-store.d.ts +29 -0
- package/dist/features/codex-notifier/event-store.d.ts.map +1 -0
- package/dist/features/codex-notifier/event-store.js +217 -0
- package/dist/features/codex-notifier/event-store.js.map +1 -0
- package/dist/features/codex-notifier/event.d.ts +46 -0
- package/dist/features/codex-notifier/event.d.ts.map +1 -0
- package/dist/features/codex-notifier/event.js +188 -0
- package/dist/features/codex-notifier/event.js.map +1 -0
- package/dist/features/codex-notifier/hook-cli.d.ts +23 -0
- package/dist/features/codex-notifier/hook-cli.d.ts.map +1 -0
- package/dist/features/codex-notifier/hook-cli.js +130 -0
- package/dist/features/codex-notifier/hook-cli.js.map +1 -0
- package/dist/features/codex-notifier/hook-installer.d.ts +19 -0
- package/dist/features/codex-notifier/hook-installer.d.ts.map +1 -0
- package/dist/features/codex-notifier/hook-installer.js +158 -0
- package/dist/features/codex-notifier/hook-installer.js.map +1 -0
- package/dist/features/codex-notifier/index.d.ts +21 -0
- package/dist/features/codex-notifier/index.d.ts.map +1 -0
- package/dist/features/codex-notifier/index.js +19 -0
- package/dist/features/codex-notifier/index.js.map +1 -0
- package/dist/features/codex-notifier/internal-turn.d.ts +5 -0
- package/dist/features/codex-notifier/internal-turn.d.ts.map +1 -0
- package/dist/features/codex-notifier/internal-turn.js +43 -0
- package/dist/features/codex-notifier/internal-turn.js.map +1 -0
- package/dist/features/codex-notifier/outbox-worker.d.ts +71 -0
- package/dist/features/codex-notifier/outbox-worker.d.ts.map +1 -0
- package/dist/features/codex-notifier/outbox-worker.js +290 -0
- package/dist/features/codex-notifier/outbox-worker.js.map +1 -0
- package/dist/features/codex-notifier/outbox.d.ts +25 -0
- package/dist/features/codex-notifier/outbox.d.ts.map +1 -0
- package/dist/features/codex-notifier/outbox.js +225 -0
- package/dist/features/codex-notifier/outbox.js.map +1 -0
- package/dist/features/codex-notifier/paths.d.ts +7 -0
- package/dist/features/codex-notifier/paths.d.ts.map +1 -0
- package/dist/features/codex-notifier/paths.js +20 -0
- package/dist/features/codex-notifier/paths.js.map +1 -0
- package/dist/features/codex-notifier/screen-lock.d.ts +12 -0
- package/dist/features/codex-notifier/screen-lock.d.ts.map +1 -0
- package/dist/features/codex-notifier/screen-lock.js +47 -0
- package/dist/features/codex-notifier/screen-lock.js.map +1 -0
- package/dist/features/codex-notifier/side-conversation-monitor.d.ts +102 -0
- package/dist/features/codex-notifier/side-conversation-monitor.d.ts.map +1 -0
- package/dist/features/codex-notifier/side-conversation-monitor.js +774 -0
- package/dist/features/codex-notifier/side-conversation-monitor.js.map +1 -0
- package/dist/features/codex-notifier/types.d.ts +42 -0
- package/dist/features/codex-notifier/types.d.ts.map +1 -0
- package/dist/features/codex-notifier/types.js +2 -0
- package/dist/features/codex-notifier/types.js.map +1 -0
- package/dist/features/codex-notifier/worker-lock.d.ts +8 -0
- package/dist/features/codex-notifier/worker-lock.d.ts.map +1 -0
- package/dist/features/codex-notifier/worker-lock.js +108 -0
- package/dist/features/codex-notifier/worker-lock.js.map +1 -0
- package/dist/global-config.d.ts +13 -0
- package/dist/global-config.d.ts.map +1 -1
- package/dist/global-config.js +30 -0
- package/dist/global-config.js.map +1 -1
- package/dist/im/lark/card-builder.js +2 -2
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts +2 -0
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +165 -34
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +62 -4
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +237 -29
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +20 -30
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/platform/secure-host-file.d.ts.map +1 -1
- package/dist/platform/secure-host-file.js +173 -54
- package/dist/platform/secure-host-file.js.map +1 -1
- package/dist/services/codex-app-threads.d.ts +47 -0
- package/dist/services/codex-app-threads.d.ts.map +1 -1
- package/dist/services/codex-app-threads.js +502 -10
- package/dist/services/codex-app-threads.js.map +1 -1
- package/dist/services/exact-chat-grant.d.ts +83 -0
- package/dist/services/exact-chat-grant.d.ts.map +1 -0
- package/dist/services/exact-chat-grant.js +249 -0
- package/dist/services/exact-chat-grant.js.map +1 -0
- package/dist/services/group-creator.d.ts +11 -0
- package/dist/services/group-creator.d.ts.map +1 -1
- package/dist/services/group-creator.js +18 -9
- package/dist/services/group-creator.js.map +1 -1
- package/dist/services/local-cli-opener.d.ts.map +1 -1
- package/dist/services/local-cli-opener.js +10 -5
- package/dist/services/local-cli-opener.js.map +1 -1
- package/dist/services/traex-user-input.d.ts +19 -0
- package/dist/services/traex-user-input.d.ts.map +1 -0
- package/dist/services/traex-user-input.js +57 -0
- package/dist/services/traex-user-input.js.map +1 -0
- package/dist/setup/open-platform-automation.d.ts +24 -3
- package/dist/setup/open-platform-automation.d.ts.map +1 -1
- package/dist/setup/open-platform-automation.js +45 -8
- package/dist/setup/open-platform-automation.js.map +1 -1
- package/dist/setup/verify-permissions.d.ts +18 -0
- package/dist/setup/verify-permissions.d.ts.map +1 -1
- package/dist/setup/verify-permissions.js +60 -0
- package/dist/setup/verify-permissions.js.map +1 -1
- package/dist/types.d.ts +70 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/child-env.d.ts +1 -1
- package/dist/utils/child-env.d.ts.map +1 -1
- package/dist/utils/child-env.js +2 -0
- package/dist/utils/child-env.js.map +1 -1
- package/dist/utils/pending-input-queue.d.ts +19 -0
- package/dist/utils/pending-input-queue.d.ts.map +1 -1
- package/dist/utils/pending-input-queue.js +21 -1
- package/dist/utils/pending-input-queue.js.map +1 -1
- package/dist/utils/stuck-detector.d.ts +45 -0
- package/dist/utils/stuck-detector.d.ts.map +1 -0
- package/dist/utils/stuck-detector.js +188 -0
- package/dist/utils/stuck-detector.js.map +1 -0
- package/dist/utils/stuck-key-guard.d.ts +75 -0
- package/dist/utils/stuck-key-guard.d.ts.map +1 -0
- package/dist/utils/stuck-key-guard.js +77 -0
- package/dist/utils/stuck-key-guard.js.map +1 -0
- package/dist/worker.js +807 -117
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-B5AY4B2J.js +0 -5
- package/dist/dashboard-web/chunks/sessions-page-2VECQ27T.js +0 -3
- package/dist/dashboard-web/chunks/settings-page-HMIUE2JA.js +0 -2
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight, AI-free "stuck" detector — fires a callback when a written input
|
|
3
|
+
* has not produced a completed turn within a timeout window.
|
|
4
|
+
*
|
|
5
|
+
* Scope (intentionally narrow): this PR targets the specific Codex PreToolUse
|
|
6
|
+
* hook-review blocking state, where the CLI renders a review screen and waits
|
|
7
|
+
* for t/Enter/Esc (level 1) or t/Esc (level 2). Generic [Y/n]/permission/
|
|
8
|
+
* Press-to-continue prompts are NOT handled here — they require semantic parsing
|
|
9
|
+
* that cannot be safely inferred from a regex, and belong in a follow-up PR.
|
|
10
|
+
*
|
|
11
|
+
* The detector does NOT itself decide the CLI is stuck. It only tracks elapsed
|
|
12
|
+
* time since the last write and asks the owner (worker) to confirm via the
|
|
13
|
+
* `isActuallyStuck` callback — the worker knows whether inflight inputs exist,
|
|
14
|
+
* whether a TUI prompt card is already posted, and whether the PTY has been
|
|
15
|
+
* quiet. This avoids false positives from legitimately long turns.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Codex renders two distinct hook-review screens. We match each independently
|
|
19
|
+
* because their titles and control hints differ, and the safe button set differs
|
|
20
|
+
* (level 1 has Enter to drill in; level 2 has no Enter).
|
|
21
|
+
*
|
|
22
|
+
* Level 1 — hooks browser (the screen that actually blocks on startup):
|
|
23
|
+
* Title: "Hooks"
|
|
24
|
+
* State: "1 hook needs review before it can run."
|
|
25
|
+
* Table: "Event Installed Active Review Description" header + a row
|
|
26
|
+
* whose Review column > 0 (e.g. "PreToolUse 1 0 1 ...")
|
|
27
|
+
* Footer: "Press t to trust all; enter to review hooks; esc to close"
|
|
28
|
+
*
|
|
29
|
+
* Level 2 — per-hook review (after pressing Enter on level 1):
|
|
30
|
+
* Title: "PreToolUse hooks"
|
|
31
|
+
* State: "1 hook needs review before it can run."
|
|
32
|
+
* Body: "[!] Hook 1 · new" + "Trust New hook - review required"
|
|
33
|
+
* Footer: "Press t to trust; esc to go back"
|
|
34
|
+
*
|
|
35
|
+
* Matching rules (addresses retained-history and pasted-text false positives):
|
|
36
|
+
* - Only inspect the bottom VIEWPORT_LINES of the snapshot — the TUI shows the
|
|
37
|
+
* active screen at the bottom; stale overview text scrolled off the top must
|
|
38
|
+
* not count.
|
|
39
|
+
* - The footer (control hint) MUST be present in the viewport and anchors the
|
|
40
|
+
* active region. We scan upward from the footer to find the nearest title.
|
|
41
|
+
* - Level 2 is checked first: if the nearest title above the footer is
|
|
42
|
+
* "PreToolUse hooks" AND the L2 body semantics are present, it is level 2
|
|
43
|
+
* even if a stale "Hooks" overview lingers further up.
|
|
44
|
+
* - Each level requires its semantic content rows, not just title + footer.
|
|
45
|
+
*/
|
|
46
|
+
const VIEWPORT_LINES = 40;
|
|
47
|
+
/** Strip ANSI escape sequences and carriage returns so a line's visible text
|
|
48
|
+
* can be matched against plain-text patterns. */
|
|
49
|
+
function stripAnsi(line) {
|
|
50
|
+
return line.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '').replace(/\r/g, '');
|
|
51
|
+
}
|
|
52
|
+
export function matchHookReviewScreen(snapshot) {
|
|
53
|
+
if (!snapshot)
|
|
54
|
+
return undefined;
|
|
55
|
+
const rawLines = snapshot.split('\n');
|
|
56
|
+
// Strip ANSI/CR from every line — the PTY carries color codes and the
|
|
57
|
+
// renderer can emit \r\n; matching against raw bytes would miss the footer.
|
|
58
|
+
const lines = rawLines.map(stripAnsi);
|
|
59
|
+
// Only inspect the bottom of the screen — the active viewport. Stale overview
|
|
60
|
+
// text that scrolled off the top must not trigger a match.
|
|
61
|
+
const viewport = lines.slice(-VIEWPORT_LINES);
|
|
62
|
+
// Trim trailing blank lines: the footer (control hint) must be the LAST
|
|
63
|
+
// non-empty line of the viewport. If there is content below the footer,
|
|
64
|
+
// the footer belongs to a scrolled-off screen, not the active one.
|
|
65
|
+
let end = viewport.length;
|
|
66
|
+
while (end > 0 && viewport[end - 1].trim() === '')
|
|
67
|
+
end--;
|
|
68
|
+
if (end === 0)
|
|
69
|
+
return undefined;
|
|
70
|
+
const trimmed = viewport.slice(0, end);
|
|
71
|
+
// The footer MUST be the last non-empty line of the viewport, matched as a
|
|
72
|
+
// whole line (^...$) — not a substring. A line like "The old footer said: ..."
|
|
73
|
+
// must NOT match.
|
|
74
|
+
const lastLine = trimmed[trimmed.length - 1].trim();
|
|
75
|
+
let level;
|
|
76
|
+
if (/^Press t to trust all; enter to review hooks; esc to close$/i.test(lastLine)) {
|
|
77
|
+
level = 1;
|
|
78
|
+
}
|
|
79
|
+
else if (/^Press t to trust; esc to go back$/i.test(lastLine)) {
|
|
80
|
+
level = 2;
|
|
81
|
+
}
|
|
82
|
+
if (!level)
|
|
83
|
+
return undefined;
|
|
84
|
+
const footerIdx = trimmed.length - 1;
|
|
85
|
+
// Scan upward from the footer to find the nearest title line. The title must
|
|
86
|
+
// be within the active region (not separated by too many blank lines / other
|
|
87
|
+
// content), otherwise the footer may belong to a different screen.
|
|
88
|
+
let titleIdx = -1;
|
|
89
|
+
for (let i = footerIdx - 1; i >= 0 && footerIdx - i < 30; i--) {
|
|
90
|
+
const line = trimmed[i].trim();
|
|
91
|
+
if (line === 'Hooks' || /^PreToolUse hooks$/i.test(line)) {
|
|
92
|
+
titleIdx = i;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (titleIdx < 0)
|
|
97
|
+
return undefined;
|
|
98
|
+
// Bind footer level to title: a level-1 footer (trust all / review / close)
|
|
99
|
+
// can only belong to the "Hooks" overview; a level-2 footer (trust / back)
|
|
100
|
+
// can only belong to the "PreToolUse hooks" detail. This prevents a stale
|
|
101
|
+
// overview title above a detail footer (or vice versa) from misclassifying.
|
|
102
|
+
const titleLine = trimmed[titleIdx].trim();
|
|
103
|
+
if (level === 1 && titleLine !== 'Hooks')
|
|
104
|
+
return undefined;
|
|
105
|
+
if (level === 2 && !/^PreToolUse hooks$/i.test(titleLine))
|
|
106
|
+
return undefined;
|
|
107
|
+
const region = trimmed.slice(titleIdx, footerIdx + 1).join('\n');
|
|
108
|
+
// Require the pending-review state line in the active region.
|
|
109
|
+
if (!/hook needs review|needs review before it can run/i.test(region))
|
|
110
|
+
return undefined;
|
|
111
|
+
// Level 2 (detail): require the "Trust" action line in the region.
|
|
112
|
+
if (level === 2) {
|
|
113
|
+
if (/Trust\s+New hook/i.test(region))
|
|
114
|
+
return 'hook review level 2';
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
// Level 1 (overview): require the table header + a row with Review > 0 to
|
|
118
|
+
// confirm this is the active hooks browser, not a pasted snippet.
|
|
119
|
+
const hasTableHeader = /Event\s+Installed\s+Active\s+Review/i.test(region);
|
|
120
|
+
const hasReviewRow = /PreToolUse\s+\d+\s+\d+\s+[1-9]/i.test(region);
|
|
121
|
+
if (hasTableHeader && hasReviewRow)
|
|
122
|
+
return 'hook review level 1';
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
export class StuckDetector {
|
|
126
|
+
timeoutMs;
|
|
127
|
+
callbacks;
|
|
128
|
+
timer = null;
|
|
129
|
+
armedAt = 0;
|
|
130
|
+
firedThisWindow = false;
|
|
131
|
+
disposed = false;
|
|
132
|
+
constructor(timeoutMs, callbacks) {
|
|
133
|
+
this.timeoutMs = timeoutMs;
|
|
134
|
+
this.callbacks = callbacks;
|
|
135
|
+
}
|
|
136
|
+
/** Arm the detector — call right after writing input to the PTY. */
|
|
137
|
+
arm() {
|
|
138
|
+
if (this.disposed)
|
|
139
|
+
return;
|
|
140
|
+
this.disarm();
|
|
141
|
+
this.armedAt = Date.now();
|
|
142
|
+
this.firedThisWindow = false;
|
|
143
|
+
this.timer = setTimeout(() => this.tick(), this.timeoutMs);
|
|
144
|
+
}
|
|
145
|
+
/** Disarm — call when the turn completes (prompt ready) or the CLI exits. */
|
|
146
|
+
disarm() {
|
|
147
|
+
if (this.timer) {
|
|
148
|
+
clearTimeout(this.timer);
|
|
149
|
+
this.timer = null;
|
|
150
|
+
}
|
|
151
|
+
this.armedAt = 0;
|
|
152
|
+
this.firedThisWindow = false;
|
|
153
|
+
}
|
|
154
|
+
dispose() {
|
|
155
|
+
this.disposed = true;
|
|
156
|
+
this.disarm();
|
|
157
|
+
}
|
|
158
|
+
tick() {
|
|
159
|
+
this.timer = null;
|
|
160
|
+
if (this.disposed)
|
|
161
|
+
return;
|
|
162
|
+
if (this.firedThisWindow)
|
|
163
|
+
return;
|
|
164
|
+
if (!this.callbacks.isActuallyStuck()) {
|
|
165
|
+
// CLI may have just finished — re-arm for the next window in case it
|
|
166
|
+
// immediately blocks again on a follow-up prompt.
|
|
167
|
+
this.arm();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
// Only fire when the snapshot matches a known hook-review pattern.
|
|
171
|
+
// A 15s PTY silence alone does NOT prove the turn is stuck — long model
|
|
172
|
+
// thinking or tool calls can be quiet. Without a pattern match we silently
|
|
173
|
+
// re-arm and keep waiting, never posting a false "CLI stuck" warning.
|
|
174
|
+
const matched = this.matchSnapshot();
|
|
175
|
+
if (!matched) {
|
|
176
|
+
this.arm();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
this.firedThisWindow = true;
|
|
180
|
+
const elapsed = Date.now() - this.armedAt;
|
|
181
|
+
this.callbacks.onStuck(elapsed, matched);
|
|
182
|
+
}
|
|
183
|
+
matchSnapshot() {
|
|
184
|
+
const snap = this.callbacks.getSnapshot?.();
|
|
185
|
+
return snap ? matchHookReviewScreen(snap) : undefined;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=stuck-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stuck-detector.js","sourceRoot":"","sources":["../../src/utils/stuck-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stuck-warning key-injection guard.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from worker.ts's `tui_keys` message handler so the fail-closed
|
|
5
|
+
* boundary (lifetime pre-check, fresh capture, backend/lifetime re-check,
|
|
6
|
+
* page-type re-match, write success/failure → delivered/expired) can be unit
|
|
7
|
+
* tested in isolation. The production handler delegates to this function.
|
|
8
|
+
*
|
|
9
|
+
* Fail-closed contract:
|
|
10
|
+
* - expected lifetime missing / unequal → no keys written, send expired
|
|
11
|
+
* - fresh capture returns null or throws → no keys written, send expired
|
|
12
|
+
* - backend/lifetime changed after capture, OR page type no longer matches
|
|
13
|
+
* → no keys written, send expired
|
|
14
|
+
* - write success → send delivered; write returns false or throws → send expired
|
|
15
|
+
*
|
|
16
|
+
* backend/lifetime are read via getters (not value snapshots) so the guard can
|
|
17
|
+
* re-check LIVE state after `await capture()` — a backend replacement or CLI
|
|
18
|
+
* restart that happens mid-capture must still be detected.
|
|
19
|
+
*/
|
|
20
|
+
import type { SessionBackend } from '../adapters/backend/types.js';
|
|
21
|
+
export interface StuckKeyGuardMessage {
|
|
22
|
+
stuckNonce: number;
|
|
23
|
+
stuckPageType: string;
|
|
24
|
+
stuckCliLifetime?: number;
|
|
25
|
+
keys: string[];
|
|
26
|
+
isFinal: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface StuckKeyGuardResult {
|
|
29
|
+
/** What was sent back to the daemon, if anything. */
|
|
30
|
+
sent: 'delivered' | 'expired' | 'none';
|
|
31
|
+
/** Whether keys were actually written to the backend. */
|
|
32
|
+
wroteKeys: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Decide whether to re-arm the stuck detector after a tui_keys click.
|
|
36
|
+
*
|
|
37
|
+
* The detector re-arms ONLY when the card-handler explicitly flagged this as a
|
|
38
|
+
* stuck-warning Enter action (advances to the next review layer) AND keys were
|
|
39
|
+
* actually written. An expired click (CLI recovered, page changed — wroteKeys
|
|
40
|
+
* is false) must NOT re-arm: the detector should stay disarmed until the next
|
|
41
|
+
* real stall, otherwise a recovered CLI could immediately re-trigger a warning.
|
|
42
|
+
*/
|
|
43
|
+
export declare function shouldRearmStuckDetector(rearmStuckDetector: boolean, wroteKeys: boolean): boolean;
|
|
44
|
+
export interface StuckKeyGuardDeps {
|
|
45
|
+
/** Live read of the current backend (may change between calls / awaits). */
|
|
46
|
+
getBackend: () => SessionBackend | null;
|
|
47
|
+
/** Live read of the current CLI lifetime nonce (incremented on every backend replacement). */
|
|
48
|
+
getCurrentLifetime: () => number;
|
|
49
|
+
renderCols: number;
|
|
50
|
+
renderRows: number;
|
|
51
|
+
turnId: string | undefined;
|
|
52
|
+
dispatchAttempt: number | undefined;
|
|
53
|
+
/** Fresh PTY capture. Returns null on no-screenshot; may throw. */
|
|
54
|
+
capture: (backend: SessionBackend, cols: number, rows: number, opts: {
|
|
55
|
+
filter: boolean;
|
|
56
|
+
}) => Promise<{
|
|
57
|
+
content: string | null;
|
|
58
|
+
} | null>;
|
|
59
|
+
/** Classifier: returns the page type label or undefined if no match. */
|
|
60
|
+
match: (snap: string) => string | undefined;
|
|
61
|
+
/** Writes keys to the backend. Returns true on success, false on failure. */
|
|
62
|
+
writeKeys: (keys: string[], isFinal: boolean) => Promise<boolean>;
|
|
63
|
+
/** Sends a message back to the daemon. */
|
|
64
|
+
sendExpired: (nonce: number, turnId: string | undefined, dispatchAttempt: number | undefined) => void;
|
|
65
|
+
sendDelivered: (nonce: number, turnId: string | undefined, dispatchAttempt: number | undefined) => void;
|
|
66
|
+
log: (msg: string) => void;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Process a stuck-warning card's tui_keys click with full fail-closed guards.
|
|
70
|
+
*
|
|
71
|
+
* Returns a result describing what happened (for testing); production callers
|
|
72
|
+
* use `result.wroteKeys` to decide whether to re-arm the stuck detector.
|
|
73
|
+
*/
|
|
74
|
+
export declare function processStuckWarningTuiKeys(msg: StuckKeyGuardMessage, deps: StuckKeyGuardDeps): Promise<StuckKeyGuardResult>;
|
|
75
|
+
//# sourceMappingURL=stuck-key-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stuck-key-guard.d.ts","sourceRoot":"","sources":["../../src/utils/stuck-key-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,IAAI,EAAE,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;IACvC,yDAAyD;IACzD,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,kBAAkB,EAAE,OAAO,EAC3B,SAAS,EAAE,OAAO,GACjB,OAAO,CAET;AAED,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,UAAU,EAAE,MAAM,cAAc,GAAG,IAAI,CAAC;IACxC,8FAA8F;IAC9F,kBAAkB,EAAE,MAAM,MAAM,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,mEAAmE;IACnE,OAAO,EAAE,CACP,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,KACtB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAChD,wEAAwE;IACxE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC5C,6EAA6E;IAC7E,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAClE,0CAA0C;IAC1C,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,eAAe,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACtG,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,eAAe,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACxG,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,oBAAoB,EACzB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,mBAAmB,CAAC,CA4D9B"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decide whether to re-arm the stuck detector after a tui_keys click.
|
|
3
|
+
*
|
|
4
|
+
* The detector re-arms ONLY when the card-handler explicitly flagged this as a
|
|
5
|
+
* stuck-warning Enter action (advances to the next review layer) AND keys were
|
|
6
|
+
* actually written. An expired click (CLI recovered, page changed — wroteKeys
|
|
7
|
+
* is false) must NOT re-arm: the detector should stay disarmed until the next
|
|
8
|
+
* real stall, otherwise a recovered CLI could immediately re-trigger a warning.
|
|
9
|
+
*/
|
|
10
|
+
export function shouldRearmStuckDetector(rearmStuckDetector, wroteKeys) {
|
|
11
|
+
return rearmStuckDetector && wroteKeys;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Process a stuck-warning card's tui_keys click with full fail-closed guards.
|
|
15
|
+
*
|
|
16
|
+
* Returns a result describing what happened (for testing); production callers
|
|
17
|
+
* use `result.wroteKeys` to decide whether to re-arm the stuck detector.
|
|
18
|
+
*/
|
|
19
|
+
export async function processStuckWarningTuiKeys(msg, deps) {
|
|
20
|
+
const { stuckNonce, stuckPageType, stuckCliLifetime, keys, isFinal } = msg;
|
|
21
|
+
const { getBackend, getCurrentLifetime, renderCols, renderRows, turnId, dispatchAttempt, capture, match, writeKeys, sendExpired, sendDelivered, log } = deps;
|
|
22
|
+
// P1-2: validate the CLI lifetime the card was issued for BEFORE doing
|
|
23
|
+
// anything else. If the CLI restarted between card post and click,
|
|
24
|
+
// the live lifetime has changed and the card's expected lifetime won't match —
|
|
25
|
+
// fail-closed, do not inject keys into the new CLI. A missing expected
|
|
26
|
+
// lifetime is also rejected (stuck cards must always carry it).
|
|
27
|
+
const currentLifetime = getCurrentLifetime();
|
|
28
|
+
if (stuckCliLifetime === undefined || stuckCliLifetime !== currentLifetime) {
|
|
29
|
+
log(`TUI keys from stale stuck-warning card (nonce=${stuckNonce}, expectedLifetime=${stuckCliLifetime ?? 'none'}, currentLifetime=${currentLifetime}) — CLI replaced since card issued, dropping`);
|
|
30
|
+
sendExpired(stuckNonce, turnId, dispatchAttempt);
|
|
31
|
+
return { sent: 'expired', wroteKeys: false };
|
|
32
|
+
}
|
|
33
|
+
// Freeze the backend identity + CLI lifetime BEFORE capture. If the CLI
|
|
34
|
+
// restarts (new backend object / new cliLifetimeNonce) while we await the
|
|
35
|
+
// capture, the frozen values won't match the live ones and we drop the keys.
|
|
36
|
+
const frozenBackend = getBackend();
|
|
37
|
+
const frozenLifetime = getCurrentLifetime();
|
|
38
|
+
let currentSnap = null;
|
|
39
|
+
if (frozenBackend) {
|
|
40
|
+
try {
|
|
41
|
+
const fresh = await capture(frozenBackend, renderCols, renderRows, { filter: false });
|
|
42
|
+
currentSnap = fresh?.content ?? null;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
currentSnap = null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Fail-closed: no fresh snapshot OR backend/lifetime changed during capture → expired.
|
|
49
|
+
// Re-read LIVE state via getters — the values may have changed while we awaited capture.
|
|
50
|
+
const liveBackend = getBackend();
|
|
51
|
+
const liveLifetime = getCurrentLifetime();
|
|
52
|
+
if (!currentSnap || frozenBackend !== liveBackend || frozenLifetime !== liveLifetime) {
|
|
53
|
+
log(`TUI keys from stale stuck-warning card (nonce=${stuckNonce}, expected=${stuckPageType}) — fresh capture failed or backend replaced, dropping`);
|
|
54
|
+
sendExpired(stuckNonce, turnId, dispatchAttempt);
|
|
55
|
+
return { sent: 'expired', wroteKeys: false };
|
|
56
|
+
}
|
|
57
|
+
const currentMatch = match(currentSnap);
|
|
58
|
+
if (currentMatch !== stuckPageType) {
|
|
59
|
+
log(`TUI keys from stale stuck-warning card (nonce=${stuckNonce}, expected=${stuckPageType}, current=${currentMatch ?? 'none'}) — dropped, notifying daemon`);
|
|
60
|
+
sendExpired(stuckNonce, turnId, dispatchAttempt);
|
|
61
|
+
return { sent: 'expired', wroteKeys: false };
|
|
62
|
+
}
|
|
63
|
+
let writeOk = false;
|
|
64
|
+
try {
|
|
65
|
+
writeOk = await writeKeys(keys, isFinal);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
writeOk = false;
|
|
69
|
+
}
|
|
70
|
+
if (writeOk) {
|
|
71
|
+
sendDelivered(stuckNonce, turnId, dispatchAttempt);
|
|
72
|
+
return { sent: 'delivered', wroteKeys: true };
|
|
73
|
+
}
|
|
74
|
+
sendExpired(stuckNonce, turnId, dispatchAttempt);
|
|
75
|
+
return { sent: 'expired', wroteKeys: false };
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=stuck-key-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stuck-key-guard.js","sourceRoot":"","sources":["../../src/utils/stuck-key-guard.ts"],"names":[],"mappings":"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"}
|