botmux 2.107.0 → 2.108.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 +17 -14
- package/README.md +19 -14
- package/dist/adapters/backend/sandbox.d.ts +3 -1
- package/dist/adapters/backend/sandbox.d.ts.map +1 -1
- package/dist/adapters/backend/sandbox.js +19 -3
- package/dist/adapters/backend/sandbox.js.map +1 -1
- package/dist/adapters/backend/tmux-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-backend.js +16 -1
- package/dist/adapters/backend/tmux-backend.js.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.d.ts +24 -15
- package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
- package/dist/adapters/backend/tmux-pipe-backend.js +75 -43
- package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
- package/dist/adapters/cli/genius.d.ts.map +1 -1
- package/dist/adapters/cli/genius.js +9 -15
- package/dist/adapters/cli/genius.js.map +1 -1
- package/dist/adapters/cli/grok.d.ts +73 -0
- package/dist/adapters/cli/grok.d.ts.map +1 -0
- package/dist/adapters/cli/grok.js +298 -0
- package/dist/adapters/cli/grok.js.map +1 -0
- package/dist/adapters/cli/oh-my-pi.d.ts.map +1 -1
- package/dist/adapters/cli/oh-my-pi.js +133 -12
- package/dist/adapters/cli/oh-my-pi.js.map +1 -1
- package/dist/adapters/cli/registry.d.ts +2 -1
- package/dist/adapters/cli/registry.d.ts.map +1 -1
- package/dist/adapters/cli/registry.js +3 -1
- package/dist/adapters/cli/registry.js.map +1 -1
- package/dist/adapters/cli/shared-hints.d.ts +8 -4
- package/dist/adapters/cli/shared-hints.d.ts.map +1 -1
- package/dist/adapters/cli/shared-hints.js +8 -4
- package/dist/adapters/cli/shared-hints.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +18 -16
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/adapters/hook-installer.d.ts +5 -4
- package/dist/adapters/hook-installer.d.ts.map +1 -1
- package/dist/adapters/hook-installer.js +42 -0
- package/dist/adapters/hook-installer.js.map +1 -1
- package/dist/cli/send-dispatch.d.ts +21 -0
- package/dist/cli/send-dispatch.d.ts.map +1 -1
- package/dist/cli/send-dispatch.js +159 -0
- package/dist/cli/send-dispatch.js.map +1 -1
- package/dist/cli/session-list-liveness.d.ts +22 -0
- package/dist/cli/session-list-liveness.d.ts.map +1 -0
- package/dist/cli/session-list-liveness.js +22 -0
- package/dist/cli/session-list-liveness.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +182 -33
- package/dist/cli.js.map +1 -1
- package/dist/core/ask-types.d.ts +4 -0
- package/dist/core/ask-types.d.ts.map +1 -1
- package/dist/core/ask-types.js +10 -0
- package/dist/core/ask-types.js.map +1 -1
- package/dist/core/cost-calculator.d.ts.map +1 -1
- package/dist/core/cost-calculator.js +35 -13
- package/dist/core/cost-calculator.js.map +1 -1
- package/dist/core/dashboard-ipc-server.d.ts.map +1 -1
- package/dist/core/dashboard-ipc-server.js +89 -16
- package/dist/core/dashboard-ipc-server.js.map +1 -1
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +6 -2
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/core/dashboard-url.d.ts +6 -5
- package/dist/core/dashboard-url.d.ts.map +1 -1
- package/dist/core/dashboard-url.js +11 -8
- package/dist/core/dashboard-url.js.map +1 -1
- package/dist/core/maintenance.d.ts +11 -8
- package/dist/core/maintenance.d.ts.map +1 -1
- package/dist/core/maintenance.js +45 -20
- package/dist/core/maintenance.js.map +1 -1
- package/dist/core/per-bot-env.d.ts.map +1 -1
- package/dist/core/per-bot-env.js +4 -0
- package/dist/core/per-bot-env.js.map +1 -1
- package/dist/core/session-discovery.d.ts.map +1 -1
- package/dist/core/session-discovery.js +4 -0
- package/dist/core/session-discovery.js.map +1 -1
- package/dist/core/skills/cli-admin-command.d.ts.map +1 -1
- package/dist/core/skills/cli-admin-command.js +8 -2
- package/dist/core/skills/cli-admin-command.js.map +1 -1
- package/dist/core/skills/im-command.d.ts.map +1 -1
- package/dist/core/skills/im-command.js +3 -1
- package/dist/core/skills/im-command.js.map +1 -1
- package/dist/core/skills/sources.d.ts +33 -1
- package/dist/core/skills/sources.d.ts.map +1 -1
- package/dist/core/skills/sources.js +97 -0
- package/dist/core/skills/sources.js.map +1 -1
- package/dist/core/skills/types.d.ts +8 -0
- package/dist/core/skills/types.d.ts.map +1 -1
- package/dist/core/terminal-url.d.ts.map +1 -1
- package/dist/core/terminal-url.js +12 -2
- package/dist/core/terminal-url.js.map +1 -1
- package/dist/core/terminal-write-auth.d.ts +34 -0
- package/dist/core/terminal-write-auth.d.ts.map +1 -0
- package/dist/core/terminal-write-auth.js +76 -0
- package/dist/core/terminal-write-auth.js.map +1 -0
- package/dist/core/tmux-recovery.d.ts +11 -0
- package/dist/core/tmux-recovery.d.ts.map +1 -0
- package/dist/core/tmux-recovery.js +19 -0
- package/dist/core/tmux-recovery.js.map +1 -0
- package/dist/core/types.d.ts +10 -4
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/update-check.d.ts +2 -2
- package/dist/core/update-check.js +2 -2
- package/dist/core/worker-pool.d.ts +3 -0
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +70 -3
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +15 -8
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/auth.d.ts +1 -1
- package/dist/dashboard/auth.d.ts.map +1 -1
- package/dist/dashboard/auth.js +7 -2
- package/dist/dashboard/auth.js.map +1 -1
- package/dist/dashboard/bot-payload.d.ts +3 -0
- package/dist/dashboard/bot-payload.d.ts.map +1 -1
- package/dist/dashboard/bot-payload.js +3 -0
- package/dist/dashboard/bot-payload.js.map +1 -1
- package/dist/dashboard/connector-api.d.ts.map +1 -1
- package/dist/dashboard/connector-api.js +39 -13
- package/dist/dashboard/connector-api.js.map +1 -1
- package/dist/dashboard/history-senders.d.ts +37 -0
- package/dist/dashboard/history-senders.d.ts.map +1 -0
- package/dist/dashboard/history-senders.js +60 -0
- package/dist/dashboard/history-senders.js.map +1 -0
- package/dist/dashboard/roles-batch.d.ts +31 -0
- package/dist/dashboard/roles-batch.d.ts.map +1 -0
- package/dist/dashboard/roles-batch.js +87 -0
- package/dist/dashboard/roles-batch.js.map +1 -0
- package/dist/dashboard/settings-card-model.d.ts +4 -2
- package/dist/dashboard/settings-card-model.d.ts.map +1 -1
- package/dist/dashboard/settings-card-model.js +13 -5
- package/dist/dashboard/settings-card-model.js.map +1 -1
- package/dist/dashboard/settings-write-applier.d.ts +4 -1
- package/dist/dashboard/settings-write-applier.d.ts.map +1 -1
- package/dist/dashboard/settings-write-applier.js +6 -1
- package/dist/dashboard/settings-write-applier.js.map +1 -1
- package/dist/dashboard/skill-install-request.d.ts +4 -0
- package/dist/dashboard/skill-install-request.d.ts.map +1 -1
- package/dist/dashboard/skill-install-request.js +11 -1
- package/dist/dashboard/skill-install-request.js.map +1 -1
- package/dist/dashboard/trigger-api.d.ts +9 -1
- package/dist/dashboard/trigger-api.d.ts.map +1 -1
- package/dist/dashboard/trigger-api.js +48 -10
- package/dist/dashboard/trigger-api.js.map +1 -1
- package/dist/dashboard/web/app.d.ts.map +1 -1
- package/dist/dashboard/web/app.js +286 -271
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts +26 -0
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.js +1408 -12
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
- package/dist/dashboard/web/bot-defaults.d.ts +91 -4
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js +43 -2141
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/bot-onboarding.d.ts +6 -1
- package/dist/dashboard/web/bot-onboarding.d.ts.map +1 -1
- package/dist/dashboard/web/bot-onboarding.js +261 -306
- package/dist/dashboard/web/bot-onboarding.js.map +1 -1
- package/dist/dashboard/web/connectors-page.d.ts +4 -0
- package/dist/dashboard/web/connectors-page.d.ts.map +1 -1
- package/dist/dashboard/web/connectors-page.js +228 -48
- package/dist/dashboard/web/connectors-page.js.map +1 -1
- package/dist/dashboard/web/dashboard-api.d.ts +9 -0
- package/dist/dashboard/web/dashboard-api.d.ts.map +1 -0
- package/dist/dashboard/web/dashboard-api.js +18 -0
- package/dist/dashboard/web/dashboard-api.js.map +1 -0
- package/dist/dashboard/web/dashboard-components.d.ts +92 -0
- package/dist/dashboard/web/dashboard-components.d.ts.map +1 -0
- package/dist/dashboard/web/dashboard-components.js +250 -0
- package/dist/dashboard/web/dashboard-components.js.map +1 -0
- package/dist/dashboard/web/dashboard-routes.d.ts.map +1 -1
- package/dist/dashboard/web/dashboard-routes.js +30 -183
- package/dist/dashboard/web/dashboard-routes.js.map +1 -1
- package/dist/dashboard/web/floating-scrollbars.d.ts +2 -0
- package/dist/dashboard/web/floating-scrollbars.d.ts.map +1 -0
- package/dist/dashboard/web/floating-scrollbars.js +264 -0
- package/dist/dashboard/web/floating-scrollbars.js.map +1 -0
- package/dist/dashboard/web/groups-api.d.ts +36 -0
- package/dist/dashboard/web/groups-api.d.ts.map +1 -0
- package/dist/dashboard/web/groups-api.js +44 -0
- package/dist/dashboard/web/groups-api.js.map +1 -0
- package/dist/dashboard/web/groups-page.d.ts.map +1 -1
- package/dist/dashboard/web/groups-page.js +746 -15
- package/dist/dashboard/web/groups-page.js.map +1 -1
- package/dist/dashboard/web/groups.d.ts +51 -18
- package/dist/dashboard/web/groups.d.ts.map +1 -1
- package/dist/dashboard/web/groups.js +145 -1096
- package/dist/dashboard/web/groups.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +545 -255
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/insights-page.d.ts.map +1 -1
- package/dist/dashboard/web/insights-page.js +1047 -14
- package/dist/dashboard/web/insights-page.js.map +1 -1
- package/dist/dashboard/web/insights.d.ts +177 -7
- package/dist/dashboard/web/insights.d.ts.map +1 -1
- package/dist/dashboard/web/insights.js +187 -1926
- package/dist/dashboard/web/insights.js.map +1 -1
- package/dist/dashboard/web/legacy-workflow-page.d.ts +3 -0
- package/dist/dashboard/web/legacy-workflow-page.d.ts.map +1 -0
- package/dist/dashboard/web/legacy-workflow-page.js +717 -0
- package/dist/dashboard/web/legacy-workflow-page.js.map +1 -0
- package/dist/dashboard/web/monitor-room.d.ts.map +1 -1
- package/dist/dashboard/web/monitor-room.js +10 -8
- package/dist/dashboard/web/monitor-room.js.map +1 -1
- package/dist/dashboard/web/monitoring-page.d.ts.map +1 -1
- package/dist/dashboard/web/monitoring-page.js +188 -14
- package/dist/dashboard/web/monitoring-page.js.map +1 -1
- package/dist/dashboard/web/office-page.d.ts.map +1 -1
- package/dist/dashboard/web/office-page.js +11 -23
- package/dist/dashboard/web/office-page.js.map +1 -1
- package/dist/dashboard/web/overview-page.d.ts.map +1 -1
- package/dist/dashboard/web/overview-page.js +141 -147
- package/dist/dashboard/web/overview-page.js.map +1 -1
- package/dist/dashboard/web/overview.d.ts +0 -1
- package/dist/dashboard/web/overview.d.ts.map +1 -1
- package/dist/dashboard/web/overview.js +3 -275
- package/dist/dashboard/web/overview.js.map +1 -1
- package/dist/dashboard/web/preferences.d.ts +1 -6
- package/dist/dashboard/web/preferences.d.ts.map +1 -1
- package/dist/dashboard/web/preferences.js +0 -21
- package/dist/dashboard/web/preferences.js.map +1 -1
- package/dist/dashboard/web/role-batch.d.ts +9 -0
- package/dist/dashboard/web/role-batch.d.ts.map +1 -0
- package/dist/dashboard/web/role-batch.js +42 -0
- package/dist/dashboard/web/role-batch.js.map +1 -0
- package/dist/dashboard/web/roles-page.d.ts.map +1 -1
- package/dist/dashboard/web/roles-page.js +538 -13
- package/dist/dashboard/web/roles-page.js.map +1 -1
- package/dist/dashboard/web/roles.d.ts +98 -1
- package/dist/dashboard/web/roles.d.ts.map +1 -1
- package/dist/dashboard/web/roles.js +117 -903
- package/dist/dashboard/web/roles.js.map +1 -1
- package/dist/dashboard/web/schedules-page.d.ts.map +1 -1
- package/dist/dashboard/web/schedules-page.js +82 -24
- package/dist/dashboard/web/schedules-page.js.map +1 -1
- package/dist/dashboard/web/sessions-kanban.d.ts +67 -0
- package/dist/dashboard/web/sessions-kanban.d.ts.map +1 -0
- package/dist/dashboard/web/sessions-kanban.js +481 -0
- package/dist/dashboard/web/sessions-kanban.js.map +1 -0
- package/dist/dashboard/web/sessions-page.d.ts +4 -0
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -1
- package/dist/dashboard/web/sessions-page.js +1633 -18
- package/dist/dashboard/web/sessions-page.js.map +1 -1
- package/dist/dashboard/web/sessions.d.ts +45 -4
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +53 -2535
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/settings-page.d.ts +0 -2
- package/dist/dashboard/web/settings-page.d.ts.map +1 -1
- package/dist/dashboard/web/settings-page.js +127 -117
- package/dist/dashboard/web/settings-page.js.map +1 -1
- package/dist/dashboard/web/skills-page.d.ts +10 -1
- package/dist/dashboard/web/skills-page.d.ts.map +1 -1
- package/dist/dashboard/web/skills-page.js +235 -93
- package/dist/dashboard/web/skills-page.js.map +1 -1
- package/dist/dashboard/web/team-federation-page.d.ts.map +1 -1
- package/dist/dashboard/web/team-federation-page.js +446 -28
- package/dist/dashboard/web/team-federation-page.js.map +1 -1
- package/dist/dashboard/web/team-federation.d.ts +91 -2
- package/dist/dashboard/web/team-federation.d.ts.map +1 -1
- package/dist/dashboard/web/team-federation.js +87 -474
- package/dist/dashboard/web/team-federation.js.map +1 -1
- package/dist/dashboard/web/theme-menu.d.ts +1 -0
- package/dist/dashboard/web/theme-menu.d.ts.map +1 -1
- package/dist/dashboard/web/theme-menu.js +79 -20
- package/dist/dashboard/web/theme-menu.js.map +1 -1
- package/dist/dashboard/web/ui.d.ts +1 -2
- package/dist/dashboard/web/ui.d.ts.map +1 -1
- package/dist/dashboard/web/ui.js +8 -20
- package/dist/dashboard/web/ui.js.map +1 -1
- package/dist/dashboard/web/v3-api.d.ts +16 -0
- package/dist/dashboard/web/v3-api.d.ts.map +1 -0
- package/dist/dashboard/web/v3-api.js +21 -0
- package/dist/dashboard/web/v3-api.js.map +1 -0
- package/dist/dashboard/web/v3-components.d.ts +2 -0
- package/dist/dashboard/web/v3-components.d.ts.map +1 -0
- package/dist/dashboard/web/v3-components.js +290 -0
- package/dist/dashboard/web/v3-components.js.map +1 -0
- package/dist/dashboard/web/v3-model.d.ts +80 -0
- package/dist/dashboard/web/v3-model.d.ts.map +1 -0
- package/dist/dashboard/web/v3-model.js +240 -0
- package/dist/dashboard/web/v3-model.js.map +1 -0
- package/dist/dashboard/web/v3-page.d.ts.map +1 -1
- package/dist/dashboard/web/v3-page.js +2 -22
- package/dist/dashboard/web/v3-page.js.map +1 -1
- package/dist/dashboard/web/v3-terminal.d.ts +14 -0
- package/dist/dashboard/web/v3-terminal.d.ts.map +1 -1
- package/dist/dashboard/web/v3-terminal.js +31 -19
- package/dist/dashboard/web/v3-terminal.js.map +1 -1
- package/dist/dashboard/web/webhook-logs-page.d.ts +16 -0
- package/dist/dashboard/web/webhook-logs-page.d.ts.map +1 -0
- package/dist/dashboard/web/webhook-logs-page.js +195 -0
- package/dist/dashboard/web/webhook-logs-page.js.map +1 -0
- package/dist/dashboard/web/whiteboards-page.d.ts.map +1 -1
- package/dist/dashboard/web/whiteboards-page.js +18 -23
- package/dist/dashboard/web/whiteboards-page.js.map +1 -1
- package/dist/dashboard/web/workflow-version-switch.d.ts +8 -0
- package/dist/dashboard/web/workflow-version-switch.d.ts.map +1 -0
- package/dist/dashboard/web/workflow-version-switch.js +9 -0
- package/dist/dashboard/web/workflow-version-switch.js.map +1 -0
- package/dist/dashboard/web/workflows.d.ts +272 -1
- package/dist/dashboard/web/workflows.d.ts.map +1 -1
- package/dist/dashboard/web/workflows.js +211 -1397
- package/dist/dashboard/web/workflows.js.map +1 -1
- package/dist/dashboard/webhook-routes.d.ts.map +1 -1
- package/dist/dashboard/webhook-routes.js +92 -39
- package/dist/dashboard/webhook-routes.js.map +1 -1
- package/dist/dashboard-web/app.js +1 -65
- package/dist/dashboard-web/brand-logo.png +0 -0
- package/dist/dashboard-web/chunks/bot-defaults-page-HSQ6HR3R.js +1 -0
- package/dist/dashboard-web/chunks/chunk-6TPODDDC.js +1 -0
- package/dist/dashboard-web/chunks/chunk-73EJP2MO.js +1 -0
- package/dist/dashboard-web/chunks/chunk-BRTZFELS.js +1 -0
- package/dist/dashboard-web/chunks/chunk-EVK77ASG.js +1 -0
- package/dist/dashboard-web/chunks/chunk-R3FXBFQH.js +1 -0
- package/dist/dashboard-web/chunks/chunk-VRLL7SNU.js +1 -0
- package/dist/dashboard-web/chunks/chunk-XCPSHD3G.js +37 -0
- package/dist/dashboard-web/chunks/chunk-XJ7BGPJH.js +1 -0
- package/dist/dashboard-web/chunks/chunk-YVRWYGXR.js +1 -0
- package/dist/dashboard-web/chunks/chunk-ZJING6FY.js +66 -0
- package/dist/dashboard-web/chunks/connectors-page-ODUA5UCW.js +1 -0
- package/dist/dashboard-web/chunks/groups-page-OYX5M6NK.js +8 -0
- package/dist/dashboard-web/chunks/insights-page-YCQO6OCR.js +22 -0
- package/dist/dashboard-web/chunks/legacy-workflow-page-XJAUNONP.js +2 -0
- package/dist/dashboard-web/chunks/{monitor-room-RFX4HPS5.js → monitor-room-WTZNYAFV.js} +17 -15
- package/dist/dashboard-web/chunks/monitoring-page-R6LJUK7G.js +2 -0
- package/dist/dashboard-web/chunks/office-page-4OXK3GNR.js +1 -0
- package/dist/dashboard-web/chunks/overview-page-4MVEJY6U.js +1 -0
- package/dist/dashboard-web/chunks/roles-page-NQDW27VV.js +1 -0
- package/dist/dashboard-web/chunks/schedules-page-JRNKYHOX.js +1 -0
- package/dist/dashboard-web/chunks/sessions-page-LF7UVI7B.js +3 -0
- package/dist/dashboard-web/chunks/settings-page-WGW7KQQS.js +2 -0
- package/dist/dashboard-web/chunks/skills-page-AMD4XP3T.js +3 -0
- package/dist/dashboard-web/chunks/team-federation-page-SYG3K4GG.js +1 -0
- package/dist/dashboard-web/chunks/v3-page-6NFFWNUK.js +94 -0
- package/dist/dashboard-web/chunks/whiteboards-page-FBRUK2AS.js +1 -0
- package/dist/dashboard-web/favicon.png +0 -0
- package/dist/dashboard-web/index.html +5 -69
- package/dist/dashboard-web/style.css +18835 -7211
- package/dist/dashboard.js +150 -32
- package/dist/dashboard.js.map +1 -1
- package/dist/global-config.d.ts +2 -2
- package/dist/global-config.d.ts.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +3 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +3 -0
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts +7 -5
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +10 -7
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +25 -1
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +84 -0
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/platform/binding.d.ts +9 -0
- package/dist/platform/binding.d.ts.map +1 -1
- package/dist/platform/binding.js +14 -0
- package/dist/platform/binding.js.map +1 -1
- package/dist/platform/tunnel-client.d.ts.map +1 -1
- package/dist/platform/tunnel-client.js +9 -0
- package/dist/platform/tunnel-client.js.map +1 -1
- package/dist/services/bot-config-store.d.ts +1 -1
- package/dist/services/bot-config-store.d.ts.map +1 -1
- package/dist/services/bot-config-store.js +11 -5
- package/dist/services/bot-config-store.js.map +1 -1
- package/dist/services/file-bridge-path.d.ts +8 -0
- package/dist/services/file-bridge-path.d.ts.map +1 -0
- package/dist/services/file-bridge-path.js +75 -0
- package/dist/services/file-bridge-path.js.map +1 -0
- package/dist/services/grok-paths.d.ts +27 -0
- package/dist/services/grok-paths.d.ts.map +1 -0
- package/dist/services/grok-paths.js +106 -0
- package/dist/services/grok-paths.js.map +1 -0
- package/dist/services/grok-transcript.d.ts +67 -0
- package/dist/services/grok-transcript.d.ts.map +1 -0
- package/dist/services/grok-transcript.js +630 -0
- package/dist/services/grok-transcript.js.map +1 -0
- package/dist/services/hermes-session-filter.d.ts +28 -0
- package/dist/services/hermes-session-filter.d.ts.map +1 -0
- package/dist/services/hermes-session-filter.js +53 -0
- package/dist/services/hermes-session-filter.js.map +1 -0
- package/dist/services/hermes-transcript.d.ts +3 -0
- package/dist/services/hermes-transcript.d.ts.map +1 -1
- package/dist/services/hermes-transcript.js +20 -2
- package/dist/services/hermes-transcript.js.map +1 -1
- package/dist/services/resumable-session-discovery.d.ts +3 -0
- package/dist/services/resumable-session-discovery.d.ts.map +1 -1
- package/dist/services/resumable-session-discovery.js +6 -1
- package/dist/services/resumable-session-discovery.js.map +1 -1
- package/dist/services/skill-registry-store.d.ts +9 -0
- package/dist/services/skill-registry-store.d.ts.map +1 -1
- package/dist/services/skill-registry-store.js +304 -1
- package/dist/services/skill-registry-store.js.map +1 -1
- package/dist/services/structured-bridge-clis.d.ts +29 -0
- package/dist/services/structured-bridge-clis.d.ts.map +1 -0
- package/dist/services/structured-bridge-clis.js +76 -0
- package/dist/services/structured-bridge-clis.js.map +1 -0
- package/dist/services/trigger-log-store.d.ts +59 -0
- package/dist/services/trigger-log-store.d.ts.map +1 -1
- package/dist/services/trigger-log-store.js +81 -10
- package/dist/services/trigger-log-store.js.map +1 -1
- package/dist/services/usage-ledger.d.ts +4 -1
- package/dist/services/usage-ledger.d.ts.map +1 -1
- package/dist/services/usage-ledger.js +48 -10
- package/dist/services/usage-ledger.js.map +1 -1
- package/dist/services/webhook-audit.d.ts +10 -0
- package/dist/services/webhook-audit.d.ts.map +1 -0
- package/dist/services/webhook-audit.js +116 -0
- package/dist/services/webhook-audit.js.map +1 -0
- package/dist/setup/bot-config-editor.d.ts.map +1 -1
- package/dist/setup/bot-config-editor.js +2 -0
- package/dist/setup/bot-config-editor.js.map +1 -1
- package/dist/setup/ensure-tmux.d.ts +26 -12
- package/dist/setup/ensure-tmux.d.ts.map +1 -1
- package/dist/setup/ensure-tmux.js +85 -18
- package/dist/setup/ensure-tmux.js.map +1 -1
- package/dist/skills/definitions.d.ts.map +1 -1
- package/dist/skills/definitions.js +14 -1
- package/dist/skills/definitions.js.map +1 -1
- package/dist/skills/injection-mode.d.ts +16 -0
- package/dist/skills/injection-mode.d.ts.map +1 -1
- package/dist/skills/injection-mode.js +25 -0
- package/dist/skills/injection-mode.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/global-install.d.ts +22 -0
- package/dist/utils/global-install.d.ts.map +1 -0
- package/dist/utils/global-install.js +106 -0
- package/dist/utils/global-install.js.map +1 -0
- package/dist/utils/install-diagnostics.d.ts +1 -1
- package/dist/utils/install-diagnostics.d.ts.map +1 -1
- package/dist/utils/install-diagnostics.js +6 -4
- package/dist/utils/install-diagnostics.js.map +1 -1
- package/dist/utils/install-info.d.ts +2 -0
- package/dist/utils/install-info.d.ts.map +1 -1
- package/dist/utils/install-info.js +10 -4
- package/dist/utils/install-info.js.map +1 -1
- package/dist/worker.js +293 -172
- package/dist/worker.js.map +1 -1
- package/dist/workflows/events/payloads.d.ts +10 -10
- package/dist/workflows/events/schema.d.ts +28 -28
- package/package.json +8 -7
- package/dist/dashboard/web/connectors.d.ts +0 -2
- package/dist/dashboard/web/connectors.d.ts.map +0 -1
- package/dist/dashboard/web/connectors.js +0 -2
- package/dist/dashboard/web/connectors.js.map +0 -1
- package/dist/dashboard/web/office.d.ts +0 -2
- package/dist/dashboard/web/office.d.ts.map +0 -1
- package/dist/dashboard/web/office.js +0 -2
- package/dist/dashboard/web/office.js.map +0 -1
- package/dist/dashboard/web/schedules.d.ts +0 -2
- package/dist/dashboard/web/schedules.d.ts.map +0 -1
- package/dist/dashboard/web/schedules.js +0 -2
- package/dist/dashboard/web/schedules.js.map +0 -1
- package/dist/dashboard/web/settings.d.ts +0 -2
- package/dist/dashboard/web/settings.d.ts.map +0 -1
- package/dist/dashboard/web/settings.js +0 -2
- package/dist/dashboard/web/settings.js.map +0 -1
- package/dist/dashboard/web/skills.d.ts +0 -2
- package/dist/dashboard/web/skills.d.ts.map +0 -1
- package/dist/dashboard/web/skills.js +0 -2
- package/dist/dashboard/web/skills.js.map +0 -1
- package/dist/dashboard/web/skin-intro.d.ts +0 -4
- package/dist/dashboard/web/skin-intro.d.ts.map +0 -1
- package/dist/dashboard/web/skin-intro.js +0 -49
- package/dist/dashboard/web/skin-intro.js.map +0 -1
- package/dist/dashboard/web/v3.d.ts +0 -3
- package/dist/dashboard/web/v3.d.ts.map +0 -1
- package/dist/dashboard/web/v3.js +0 -539
- package/dist/dashboard/web/v3.js.map +0 -1
- package/dist/dashboard/web/whiteboards.d.ts +0 -2
- package/dist/dashboard/web/whiteboards.d.ts.map +0 -1
- package/dist/dashboard/web/whiteboards.js +0 -2
- package/dist/dashboard/web/whiteboards.js.map +0 -1
- package/dist/dashboard-web/chunks/bot-defaults-page-OCIHPGEU.js +0 -438
- package/dist/dashboard-web/chunks/chunk-3N2PPQVD.js +0 -1
- package/dist/dashboard-web/chunks/chunk-3UJYRR2Q.js +0 -37
- package/dist/dashboard-web/chunks/chunk-5E3MJJL4.js +0 -1
- package/dist/dashboard-web/chunks/chunk-7SZRL6FY.js +0 -1
- package/dist/dashboard-web/chunks/chunk-JTSE5VP6.js +0 -54
- package/dist/dashboard-web/chunks/chunk-LXIK7OUJ.js +0 -1
- package/dist/dashboard-web/chunks/chunk-PE6W3C2C.js +0 -1
- package/dist/dashboard-web/chunks/chunk-QW54DWU3.js +0 -325
- package/dist/dashboard-web/chunks/connectors-IGETYWCP.js +0 -1
- package/dist/dashboard-web/chunks/groups-page-MYBS4ZYJ.js +0 -207
- package/dist/dashboard-web/chunks/insights-page-UPA32V2S.js +0 -309
- package/dist/dashboard-web/chunks/monitoring-page-7T3BESZ2.js +0 -1
- package/dist/dashboard-web/chunks/office-page-6DXYOG55.js +0 -1
- package/dist/dashboard-web/chunks/overview-page-LJSBCQW4.js +0 -1
- package/dist/dashboard-web/chunks/roles-page-ESURTVQH.js +0 -98
- package/dist/dashboard-web/chunks/schedules-LML2ISOT.js +0 -1
- package/dist/dashboard-web/chunks/sessions-YB73XOTU.js +0 -1
- package/dist/dashboard-web/chunks/sessions-page-MCO5QR7Z.js +0 -1
- package/dist/dashboard-web/chunks/settings-page-OSDKNVS3.js +0 -2
- package/dist/dashboard-web/chunks/skills-page-PXBZJ6P6.js +0 -2
- package/dist/dashboard-web/chunks/team-federation-page-TTPVHFPX.js +0 -10
- package/dist/dashboard-web/chunks/v3-page-FVPUL665.js +0 -149
- package/dist/dashboard-web/chunks/whiteboards-page-HLCTYSSV.js +0 -1
- package/dist/dashboard-web/chunks/workflows-FCPM4S4D.js +0 -184
- package/dist/dashboard-web/skins/bluearchive-hero.webp +0 -0
- package/dist/dashboard-web/skins/dragonball-goku.webp +0 -0
- package/dist/dashboard-web/skins/dragonball-wukong.webp +0 -0
- package/dist/dashboard-web/skins/genshin-breeze.webp +0 -0
- package/dist/dashboard-web/skins/ikun-hero.webp +0 -0
- package/dist/dashboard-web/skins/prts-priestess.webp +0 -0
- package/dist/dashboard-web/skins/zzz-hero.webp +0 -0
- package/dist/dashboard-web/skins/zzz-pattern.svg +0 -25
package/dist/worker.js
CHANGED
|
@@ -30,15 +30,22 @@ import { mergeQueuedCliInput } from './utils/pending-input-queue.js';
|
|
|
30
30
|
import { ReadyGate, shouldArmReadyGate } from './utils/ready-gate.js';
|
|
31
31
|
import { shouldRunStartupCommandsOnSpawn, shouldDeferInitialPromptForStartup } from './core/startup-commands.js';
|
|
32
32
|
import { sanitizePerBotEnv } from './core/per-bot-env.js';
|
|
33
|
+
import { resolveTerminalWriteForRequest } from './core/terminal-write-auth.js';
|
|
34
|
+
import { readPlatformBinding } from './platform/binding.js';
|
|
35
|
+
import { loadPersistedToken } from './dashboard/auth.js';
|
|
33
36
|
import { InflightInputTracker } from './core/inflight-input-tracker.js';
|
|
34
37
|
import { shouldRunQuietRotation, evaluatePidResolverPullback, decideFingerprintSwitch, shouldHealAbsentBaseline, sessionIdFromJsonlPath, SESSION_ID_FILENAME_RE, } from './services/bridge-rotation-policy.js';
|
|
35
38
|
import { CodexBridgeQueue } from './services/codex-bridge-queue.js';
|
|
36
39
|
import { drainCodexRollout, findCodexRolloutBySessionId, findCodexRolloutByPid, splitCodexEventsByCutoff, extractLastCodexTurn } from './services/codex-transcript.js';
|
|
37
40
|
import { findTraexRolloutBySessionId, findTraexRolloutByPid } from './services/traex-transcript.js';
|
|
38
41
|
import { cocoEventsPathForSession, drainCocoEvents, findCocoSessionByPid } from './services/coco-transcript.js';
|
|
39
|
-
import { currentHermesStateOffset, drainHermesStateDb } from './services/hermes-transcript.js';
|
|
42
|
+
import { currentHermesStateOffset, drainHermesStateDb, resolveHermesStateDbPath } from './services/hermes-transcript.js';
|
|
43
|
+
import { filterHermesEventsForBotmuxSession } from './services/hermes-session-filter.js';
|
|
40
44
|
import { currentMtrSessionOffset, drainMtrSession, findLatestMtrSessionByDirectory, findMtrSessionById } from './services/mtr-transcript.js';
|
|
41
|
-
import { drainPiTranscript
|
|
45
|
+
import { drainPiTranscript } from './services/pi-transcript.js';
|
|
46
|
+
import { drainGrokUpdates, grokSessionIdFromPath, } from './services/grok-transcript.js';
|
|
47
|
+
import { resolveFileBridgePath } from './services/file-bridge-path.js';
|
|
48
|
+
import { isStructuredBridgeAdoptIdleCli, isStructuredBridgeAdoptInputCli, isStructuredBridgeFallbackActive, } from './services/structured-bridge-clis.js';
|
|
42
49
|
import { drainCursorTranscript, findCursorChatIdByPid, findCursorTranscriptByChatId, findCursorTranscriptByPid } from './services/cursor-transcript.js';
|
|
43
50
|
import { shouldObserveCursorChatId, shouldPersistObservedCursorChatId } from './services/cursor-resume-policy.js';
|
|
44
51
|
import { baselineJsonlCursor } from './services/jsonl-cursor.js';
|
|
@@ -65,7 +72,8 @@ import { zellijEnv } from './setup/ensure-zellij.js';
|
|
|
65
72
|
import { isObserveBackend } from './adapters/backend/types.js';
|
|
66
73
|
import { selectSessionBackend, decideBackendGate, backendGateUserMessage } from './adapters/backend/session-backend-selector.js';
|
|
67
74
|
import { prepareSandbox, attachSandboxOutbox, startOutboxWatcher, sandboxEnabled, sandboxedClaudeDataDir } from './adapters/backend/sandbox.js';
|
|
68
|
-
import { tmuxEnv,
|
|
75
|
+
import { tmuxEnv, probeTmuxFunctionalWithRetry } from './setup/ensure-tmux.js';
|
|
76
|
+
import { tmuxRestartJitterMs } from './core/tmux-recovery.js';
|
|
69
77
|
import { IdleDetector } from './utils/idle-detector.js';
|
|
70
78
|
import { ScreenAnalyzer } from './utils/screen-analyzer.js';
|
|
71
79
|
import { captureToPng } from './utils/screenshot-renderer.js';
|
|
@@ -98,6 +106,7 @@ let sandboxTeardownDone = false; // guards the exit-time best-effort teardown fr
|
|
|
98
106
|
* (non-forced) config, so healthy restarts (e.g. user `/restart`) are
|
|
99
107
|
* unaffected. */
|
|
100
108
|
let consecutiveInWorkerRestarts = 0;
|
|
109
|
+
let tmuxRestartTimer = null;
|
|
101
110
|
/** Guard: user_notify for "resume → fresh fallback" is sent once per worker
|
|
102
111
|
* lifecycle so a 4× crash loop does not spam the Lark thread with 4 copies
|
|
103
112
|
* of the same warning. */
|
|
@@ -289,23 +298,25 @@ const authedClients = new WeakSet();
|
|
|
289
298
|
/** Per-WS-client tmux/zellij attach PTYs. */
|
|
290
299
|
const clientPtys = new Map();
|
|
291
300
|
const writeToken = randomBytes(16).toString('hex');
|
|
301
|
+
// Active dashboard token, persisted by the dashboard process at this stable
|
|
302
|
+
// path (mirrors dashboard.ts TOKEN_PATH). The platform proxy injects it as the
|
|
303
|
+
// `botmux_dashboard_token` cookie on every request it fronts, so its presence
|
|
304
|
+
// proves a request traversed the platform's authenticated front door.
|
|
305
|
+
const DASHBOARD_TOKEN_PATH = join(homedir(), '.botmux', '.dashboard-token');
|
|
292
306
|
/**
|
|
293
|
-
* Resolve terminal write permission for one request
|
|
294
|
-
* `X-Botmux-Role` header
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
307
|
+
* Resolve terminal write permission for one request. The platform-injected
|
|
308
|
+
* `X-Botmux-Role` header is trusted only when this machine is bound to a central
|
|
309
|
+
* platform AND the request actually came through the platform proxy (proven by a
|
|
310
|
+
* matching `botmux_dashboard_token` cookie — a secret a direct caller lacks).
|
|
311
|
+
* Otherwise write falls back to the `?token=` gate. See
|
|
312
|
+
* ./core/terminal-write-auth for the full rationale.
|
|
313
|
+
*
|
|
314
|
+
* Both the binding and the token are read PER REQUEST, never snapshotted:
|
|
315
|
+
* `botmux bind`/unbind and dashboard token rotation are hot-reloaded without
|
|
316
|
+
* restarting this worker, so a cached value would go stale.
|
|
301
317
|
*/
|
|
302
|
-
function
|
|
303
|
-
|
|
304
|
-
if (typeof role === 'string' && role) {
|
|
305
|
-
const hasWrite = role === 'owner';
|
|
306
|
-
return { hasWrite, platformReadonly: !hasWrite };
|
|
307
|
-
}
|
|
308
|
-
return { hasWrite: tokenMatches, platformReadonly: false };
|
|
318
|
+
function resolveTerminalWriteForReq(req, tokenMatches) {
|
|
319
|
+
return resolveTerminalWriteForRequest(req.headers, tokenMatches, () => readPlatformBinding() !== null, () => loadPersistedToken(DASHBOARD_TOKEN_PATH));
|
|
309
320
|
}
|
|
310
321
|
/** Lazily-written locked-mode zellij config for per-WS web-terminal attach
|
|
311
322
|
* clients: cleared keybinds + locked mode so every keystroke passes straight
|
|
@@ -326,7 +337,7 @@ function ensureZellijAttachConfig() {
|
|
|
326
337
|
}
|
|
327
338
|
let sessionId = '';
|
|
328
339
|
let lastInitConfig = null;
|
|
329
|
-
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' };
|
|
340
|
+
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' };
|
|
330
341
|
function cliName() { return CLI_DISPLAY_NAMES[lastInitConfig?.cliId ?? ''] ?? 'CLI'; }
|
|
331
342
|
let isPromptReady = false;
|
|
332
343
|
/** Mutex for async flushPending — prevents concurrent flush loops. */
|
|
@@ -719,6 +730,8 @@ let codexBridgeWatcher = null;
|
|
|
719
730
|
let codexBridgeTimer = null;
|
|
720
731
|
let hermesBridgeOffset = 0;
|
|
721
732
|
let hermesBridgeBaselineDone = false;
|
|
733
|
+
let hermesBridgeDbPath;
|
|
734
|
+
let hermesBridgeSourceSessionId;
|
|
722
735
|
let mtrBridgeSource;
|
|
723
736
|
let mtrBridgeOffset = 0;
|
|
724
737
|
let mtrBridgeBaselineDone = false;
|
|
@@ -1937,18 +1950,10 @@ function drainPathInto(path, fromOffset) {
|
|
|
1937
1950
|
// marker IO / type-ahead serialisation / one-write-per-idle break) is
|
|
1938
1951
|
// shared with the Claude path.
|
|
1939
1952
|
function codexBridgeFallbackActive() {
|
|
1940
|
-
//
|
|
1941
|
-
//
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
return true;
|
|
1945
|
-
// Cursor only harvests its transcript in adopt mode: a botmux-spawned
|
|
1946
|
-
// cursor session carries the botmux skill and replies via `botmux send`,
|
|
1947
|
-
// and we never resolve a transcript path for it — so leave that flow
|
|
1948
|
-
// (screen capture + botmux send) untouched and scope the bridge to adopt.
|
|
1949
|
-
if (id === 'cursor')
|
|
1950
|
-
return lastInitConfig?.adoptMode === true;
|
|
1951
|
-
return false;
|
|
1953
|
+
// Transcript-backed CLIs whose final output can be harvested when the
|
|
1954
|
+
// model forgets to call `botmux send`. Cursor is adopt-only — see
|
|
1955
|
+
// services/structured-bridge-clis.ts (single source of the allowlist).
|
|
1956
|
+
return isStructuredBridgeFallbackActive(lastInitConfig?.cliId, lastInitConfig?.adoptMode === true);
|
|
1952
1957
|
}
|
|
1953
1958
|
// Both Codex and TRAE share the same rollout JSONL layout (response_item
|
|
1954
1959
|
// messages), so drainCodexRollout works for both.
|
|
@@ -1964,9 +1969,15 @@ function structuredBridgeIsMtr() {
|
|
|
1964
1969
|
function structuredBridgeIsPi() {
|
|
1965
1970
|
return lastInitConfig?.cliId === 'pi';
|
|
1966
1971
|
}
|
|
1972
|
+
function structuredBridgeIsGrok() {
|
|
1973
|
+
return lastInitConfig?.cliId === 'grok';
|
|
1974
|
+
}
|
|
1967
1975
|
function codexBridgeIsCursor() {
|
|
1968
1976
|
return lastInitConfig?.cliId === 'cursor';
|
|
1969
1977
|
}
|
|
1978
|
+
function currentHermesBridgeDbPath() {
|
|
1979
|
+
return hermesBridgeDbPath ?? resolveHermesStateDbPath();
|
|
1980
|
+
}
|
|
1970
1981
|
function structuredBridgeIngestPath(path, offset) {
|
|
1971
1982
|
if (structuredBridgeIsCodex())
|
|
1972
1983
|
return drainCodexRollout(path, offset);
|
|
@@ -1974,8 +1985,10 @@ function structuredBridgeIngestPath(path, offset) {
|
|
|
1974
1985
|
return drainCursorTranscript(path, offset);
|
|
1975
1986
|
if (structuredBridgeIsPi())
|
|
1976
1987
|
return drainPiTranscript(path, offset);
|
|
1988
|
+
if (structuredBridgeIsGrok())
|
|
1989
|
+
return drainGrokUpdates(path, offset);
|
|
1977
1990
|
if (structuredBridgeIsHermes()) {
|
|
1978
|
-
const result = drainHermesStateDb(offset);
|
|
1991
|
+
const result = drainHermesStateDb(offset, currentHermesBridgeDbPath());
|
|
1979
1992
|
return { events: result.events, newOffset: result.newOffset, pendingTail: '' };
|
|
1980
1993
|
}
|
|
1981
1994
|
return drainCocoEvents(path, offset);
|
|
@@ -2050,66 +2063,19 @@ function codexBridgeStartTimer() {
|
|
|
2050
2063
|
return;
|
|
2051
2064
|
}
|
|
2052
2065
|
if (!codexBridgeRolloutPath) {
|
|
2053
|
-
//
|
|
2054
|
-
//
|
|
2055
|
-
//
|
|
2056
|
-
//
|
|
2057
|
-
//
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
const isTraex = lastInitConfig?.cliId === 'traex';
|
|
2064
|
-
const isPi = lastInitConfig?.cliId === 'pi';
|
|
2065
|
-
let path;
|
|
2066
|
-
if (codexBridgePendingSessionId) {
|
|
2067
|
-
if (isCoco) {
|
|
2068
|
-
path = cocoEventsPathForSession(codexBridgePendingSessionId);
|
|
2069
|
-
if (path && !existsSync(path))
|
|
2070
|
-
path = undefined;
|
|
2071
|
-
}
|
|
2072
|
-
else if (isPi) {
|
|
2073
|
-
path = findPiTranscriptBySessionId(codexBridgePendingSessionId, lastInitConfig?.workingDir);
|
|
2074
|
-
}
|
|
2075
|
-
else if (isTraex) {
|
|
2076
|
-
path = findTraexRolloutBySessionId(codexBridgePendingSessionId);
|
|
2077
|
-
}
|
|
2078
|
-
else {
|
|
2079
|
-
path = findCodexRolloutBySessionId(codexBridgePendingSessionId);
|
|
2080
|
-
}
|
|
2081
|
-
}
|
|
2082
|
-
if (!path && codexAdoptPendingPid) {
|
|
2083
|
-
if (isCoco) {
|
|
2084
|
-
const probed = findCocoSessionByPid(codexAdoptPendingPid);
|
|
2085
|
-
if (probed && existsSync(probed.eventsPath))
|
|
2086
|
-
path = probed.eventsPath;
|
|
2087
|
-
}
|
|
2088
|
-
else if (isPi) {
|
|
2089
|
-
const probed = findPiTranscriptByPid(codexAdoptPendingPid);
|
|
2090
|
-
if (probed)
|
|
2091
|
-
path = probed.path;
|
|
2092
|
-
}
|
|
2093
|
-
else if (isTraex) {
|
|
2094
|
-
const probed = findTraexRolloutByPid(codexAdoptPendingPid);
|
|
2095
|
-
if (probed)
|
|
2096
|
-
path = probed.path;
|
|
2097
|
-
}
|
|
2098
|
-
else {
|
|
2099
|
-
const probed = findCodexRolloutByPid(codexAdoptPendingPid);
|
|
2100
|
-
if (probed)
|
|
2101
|
-
path = probed.path;
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2066
|
+
// Late-attach: cliSessionId (writeInput / daemon probe) then adopt
|
|
2067
|
+
// pid. Path lookup is centralized in resolveFileBridgePath so
|
|
2068
|
+
// adding a file-backed CLI does not grow this if-tree.
|
|
2069
|
+
// Adopt → split-live; non-adopt → fresh-empty (queue markTimeMs
|
|
2070
|
+
// lower bound handles history without a split).
|
|
2071
|
+
const path = resolveFileBridgePath(lastInitConfig?.cliId, {
|
|
2072
|
+
sessionId: codexBridgePendingSessionId,
|
|
2073
|
+
cwd: lastInitConfig?.workingDir,
|
|
2074
|
+
pid: codexAdoptPendingPid,
|
|
2075
|
+
});
|
|
2104
2076
|
if (path) {
|
|
2105
2077
|
codexBridgePendingSessionId = undefined;
|
|
2106
2078
|
codexAdoptPendingPid = undefined;
|
|
2107
|
-
// Adopt mode: split-live partitions drained events by
|
|
2108
|
-
// codexAdoptStartMs so anything the user did AFTER adopt but
|
|
2109
|
-
// BEFORE we found the rollout still emits (history is absorbed,
|
|
2110
|
-
// live is ingested). Non-adopt: fresh-empty as before — queue's
|
|
2111
|
-
// markTimeMs - 5s lower bound is enough since there's no
|
|
2112
|
-
// local-turn synthesis on that path.
|
|
2113
2079
|
const mode = lastInitConfig?.adoptMode ? 'split-live' : 'fresh-empty';
|
|
2114
2080
|
codexBridgeAttach(path, mode);
|
|
2115
2081
|
}
|
|
@@ -2124,20 +2090,38 @@ function codexBridgeStartTimer() {
|
|
|
2124
2090
|
}, 1000);
|
|
2125
2091
|
}
|
|
2126
2092
|
function hermesBridgeAttach(mode) {
|
|
2127
|
-
|
|
2093
|
+
const dbPath = currentHermesBridgeDbPath();
|
|
2094
|
+
hermesBridgeOffset = currentHermesStateOffset(dbPath);
|
|
2128
2095
|
hermesBridgeBaselineDone = true;
|
|
2129
|
-
|
|
2096
|
+
hermesBridgeSourceSessionId = undefined;
|
|
2097
|
+
log(`Hermes bridge ${mode}: ${dbPath} offset=${hermesBridgeOffset}`);
|
|
2130
2098
|
codexBridgeStartTimer();
|
|
2131
2099
|
}
|
|
2132
2100
|
function hermesBridgeIngest() {
|
|
2133
2101
|
if (!hermesBridgeBaselineDone)
|
|
2134
2102
|
return;
|
|
2135
|
-
const result = drainHermesStateDb(hermesBridgeOffset);
|
|
2103
|
+
const result = drainHermesStateDb(hermesBridgeOffset, currentHermesBridgeDbPath());
|
|
2136
2104
|
hermesBridgeOffset = result.newOffset;
|
|
2137
|
-
|
|
2105
|
+
const filtered = filterHermesEventsForBotmuxSession(result.events, {
|
|
2106
|
+
botmuxSessionId: sessionId,
|
|
2107
|
+
boundSourceSessionId: hermesBridgeSourceSessionId,
|
|
2108
|
+
});
|
|
2109
|
+
// Announce EVERY source bound this drain, not just the last. A single drain
|
|
2110
|
+
// can bind multiple sources when the worker starts unbound and Hermes
|
|
2111
|
+
// `/clear`-rotates mid-batch; the daemon accumulates them into its authorized
|
|
2112
|
+
// set, so a completed turn from an earlier source is not dropped as foreign.
|
|
2113
|
+
for (const boundSourceSessionId of filtered.newlyBoundSourceSessionIds) {
|
|
2114
|
+
send({ type: 'bridge_source_session', bridge: 'hermes', sourceSessionId: boundSourceSessionId });
|
|
2115
|
+
log(`Hermes bridge bound sourceSessionId=${boundSourceSessionId}`);
|
|
2116
|
+
}
|
|
2117
|
+
hermesBridgeSourceSessionId = filtered.boundSourceSessionId;
|
|
2118
|
+
for (const drop of filtered.drops) {
|
|
2119
|
+
log(`Hermes bridge dropped ${drop.kind} ${drop.uuid} from sourceSessionId=${drop.sourceSessionId ?? '?'} expected=${drop.expectedSourceSessionId ?? hermesBridgeSourceSessionId ?? 'unbound'} reason=${drop.reason}`);
|
|
2120
|
+
}
|
|
2121
|
+
if (filtered.events.length > 0)
|
|
2138
2122
|
lastStructuredBridgeActivityAtMs = Date.now();
|
|
2139
|
-
codexBridgeQueue.ingest(
|
|
2140
|
-
if (
|
|
2123
|
+
codexBridgeQueue.ingest(filtered.events);
|
|
2124
|
+
if (filtered.events.some(e => e.kind === 'assistant_final')) {
|
|
2141
2125
|
idleDetector?.fireIdle();
|
|
2142
2126
|
}
|
|
2143
2127
|
}
|
|
@@ -2302,12 +2286,60 @@ function cursorBridgeAttach(path, mode = 'baseline-existing') {
|
|
|
2302
2286
|
}
|
|
2303
2287
|
codexBridgeAttach(path, mode === 'baseline-existing' ? 'baseline-existing-skip-tail' : mode);
|
|
2304
2288
|
}
|
|
2289
|
+
/** Drop the current file-backed bridge attachment (watcher + path cursor).
|
|
2290
|
+
* Does NOT clear the pending-turn queue — mid-rotation submits still need
|
|
2291
|
+
* fingerprint matching against the next attach. */
|
|
2292
|
+
function codexBridgeDetachFile() {
|
|
2293
|
+
if (codexBridgeWatcher) {
|
|
2294
|
+
try {
|
|
2295
|
+
codexBridgeWatcher.close();
|
|
2296
|
+
}
|
|
2297
|
+
catch { /* ignore */ }
|
|
2298
|
+
codexBridgeWatcher = null;
|
|
2299
|
+
}
|
|
2300
|
+
codexBridgeRolloutPath = undefined;
|
|
2301
|
+
codexBridgeOffset = 0;
|
|
2302
|
+
codexBridgePendingTail = '';
|
|
2303
|
+
codexBridgeBaselineDone = false;
|
|
2304
|
+
}
|
|
2305
2305
|
/** Called from flushPending after writeInput first returns a cliSessionId.
|
|
2306
2306
|
* Tries to locate the rollout file immediately; if it's not on disk yet,
|
|
2307
2307
|
* remembers the sid so the 1s poller can keep retrying. */
|
|
2308
2308
|
function codexBridgeNotifyCliSessionId(cliSessionId) {
|
|
2309
|
-
if (!codexBridgeFallbackActive()
|
|
2309
|
+
if (!codexBridgeFallbackActive())
|
|
2310
2310
|
return;
|
|
2311
|
+
if (codexBridgeRolloutPath) {
|
|
2312
|
+
// Already attached — first-attach-wins for most CLIs. Exception: grok's
|
|
2313
|
+
// `/new` / `/clear` / `/resume` rotate to a NEW session directory at the
|
|
2314
|
+
// SAME pid, and writeInput's prompt_history verify reports the new
|
|
2315
|
+
// session id on the very next submit. Without a re-attach the bridge
|
|
2316
|
+
// stays wedged on the old updates.jsonl and the reply fallback / idle
|
|
2317
|
+
// signal go dark for the rest of the session.
|
|
2318
|
+
if (structuredBridgeIsGrok()) {
|
|
2319
|
+
const currentSid = grokSessionIdFromPath(codexBridgeRolloutPath);
|
|
2320
|
+
if (currentSid && currentSid.toLowerCase() === cliSessionId.toLowerCase())
|
|
2321
|
+
return;
|
|
2322
|
+
const next = resolveFileBridgePath('grok', {
|
|
2323
|
+
sessionId: cliSessionId,
|
|
2324
|
+
cwd: lastInitConfig?.workingDir,
|
|
2325
|
+
});
|
|
2326
|
+
if (next && next !== codexBridgeRolloutPath) {
|
|
2327
|
+
log(`Grok session rotated ${currentSid ?? '?'} → ${cliSessionId}; re-attaching bridge to ${next}`);
|
|
2328
|
+
codexBridgeDetachFile();
|
|
2329
|
+
codexBridgePendingSessionId = undefined;
|
|
2330
|
+
codexBridgeAttach(next, 'fresh-empty');
|
|
2331
|
+
}
|
|
2332
|
+
else if (!next) {
|
|
2333
|
+
// New session id reported but updates.jsonl not on disk yet —
|
|
2334
|
+
// detach the retired session and arm the poller for late-attach.
|
|
2335
|
+
log(`Grok session rotated ${currentSid ?? '?'} → ${cliSessionId}; waiting for updates.jsonl`);
|
|
2336
|
+
codexBridgeDetachFile();
|
|
2337
|
+
codexBridgePendingSessionId = cliSessionId;
|
|
2338
|
+
codexBridgeStartTimer();
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
return;
|
|
2342
|
+
}
|
|
2311
2343
|
if (structuredBridgeIsMtr()) {
|
|
2312
2344
|
const source = findMtrSessionById(cliSessionId);
|
|
2313
2345
|
if (source) {
|
|
@@ -2323,7 +2355,7 @@ function codexBridgeNotifyCliSessionId(cliSessionId) {
|
|
|
2323
2355
|
if (codexBridgeIsCursor()) {
|
|
2324
2356
|
// Cursor's cliSessionId is the chatId — the same UUID naming the
|
|
2325
2357
|
// agent-transcript JSONL, so it resolves the path directly.
|
|
2326
|
-
const cursorPath =
|
|
2358
|
+
const cursorPath = resolveFileBridgePath('cursor', { sessionId: cliSessionId });
|
|
2327
2359
|
if (cursorPath) {
|
|
2328
2360
|
codexBridgePendingSessionId = undefined;
|
|
2329
2361
|
cursorBridgeAttach(cursorPath, cursorLateAttachMode(cursorPath));
|
|
@@ -2334,11 +2366,10 @@ function codexBridgeNotifyCliSessionId(cliSessionId) {
|
|
|
2334
2366
|
}
|
|
2335
2367
|
return;
|
|
2336
2368
|
}
|
|
2337
|
-
const path = lastInitConfig?.cliId
|
|
2338
|
-
|
|
2339
|
-
: lastInitConfig?.
|
|
2340
|
-
|
|
2341
|
-
: findCodexRolloutBySessionId(cliSessionId);
|
|
2369
|
+
const path = resolveFileBridgePath(lastInitConfig?.cliId, {
|
|
2370
|
+
sessionId: cliSessionId,
|
|
2371
|
+
cwd: lastInitConfig?.workingDir,
|
|
2372
|
+
});
|
|
2342
2373
|
if (path) {
|
|
2343
2374
|
codexBridgePendingSessionId = undefined;
|
|
2344
2375
|
codexBridgeAttach(path, 'fresh-empty');
|
|
@@ -2423,6 +2454,7 @@ function emitReadyCodexTurns() {
|
|
|
2423
2454
|
const turn = ready[i];
|
|
2424
2455
|
if (!turn.finalText)
|
|
2425
2456
|
continue;
|
|
2457
|
+
const sourceHermesSessionId = structuredBridgeIsHermes() ? turn.sourceSessionId : undefined;
|
|
2426
2458
|
const nextBoundaryMs = (i + 1 < ready.length ? ready[i + 1].markTimeMs : nextPendingMarkTimeMs);
|
|
2427
2459
|
if (shouldSuppressBridgeEmit({ markTimeMs: turn.markTimeMs, isLocal: turn.isLocal, finalText: turn.finalText }, nextBoundaryMs, markers, adoptMode)) {
|
|
2428
2460
|
log(`Codex bridge fallback suppressed for turn ${turn.turnId.substring(0, 8)} (gate)`);
|
|
@@ -2438,6 +2470,7 @@ function emitReadyCodexTurns() {
|
|
|
2438
2470
|
continue;
|
|
2439
2471
|
send({
|
|
2440
2472
|
type: 'final_output',
|
|
2473
|
+
...(sourceHermesSessionId ? { sourceHermesSessionId } : {}),
|
|
2441
2474
|
content: fields.content,
|
|
2442
2475
|
lastUuid: turn.turnId,
|
|
2443
2476
|
turnId: turn.turnId,
|
|
@@ -2446,7 +2479,13 @@ function emitReadyCodexTurns() {
|
|
|
2446
2479
|
});
|
|
2447
2480
|
continue;
|
|
2448
2481
|
}
|
|
2449
|
-
send({
|
|
2482
|
+
send({
|
|
2483
|
+
type: 'final_output',
|
|
2484
|
+
...(sourceHermesSessionId ? { sourceHermesSessionId } : {}),
|
|
2485
|
+
content: turn.finalText,
|
|
2486
|
+
lastUuid: turn.turnId,
|
|
2487
|
+
turnId: turn.turnId,
|
|
2488
|
+
});
|
|
2450
2489
|
}
|
|
2451
2490
|
}
|
|
2452
2491
|
function stopCodexBridge() {
|
|
@@ -2467,6 +2506,7 @@ function stopCodexBridge() {
|
|
|
2467
2506
|
codexBridgeBaselineDone = false;
|
|
2468
2507
|
hermesBridgeOffset = 0;
|
|
2469
2508
|
hermesBridgeBaselineDone = false;
|
|
2509
|
+
hermesBridgeSourceSessionId = undefined;
|
|
2470
2510
|
mtrBridgeSource = undefined;
|
|
2471
2511
|
mtrBridgeOffset = 0;
|
|
2472
2512
|
mtrBridgeBaselineDone = false;
|
|
@@ -4041,43 +4081,45 @@ function setupAdoptTranscriptBridges(cfg) {
|
|
|
4041
4081
|
codexBridgeStartTimer();
|
|
4042
4082
|
}
|
|
4043
4083
|
}
|
|
4044
|
-
else if (cfg.cliId === 'pi') {
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4084
|
+
else if (cfg.cliId === 'pi' || cfg.cliId === 'grok') {
|
|
4085
|
+
// File-backed bridges share the same adopt attach skeleton (sid → pid →
|
|
4086
|
+
// split-live | pending). Path lookup is resolveFileBridgePath; pi is
|
|
4087
|
+
// intentionally folded here with grok so the two stay in lockstep.
|
|
4088
|
+
setupAdoptFileBridge(cfg);
|
|
4089
|
+
}
|
|
4090
|
+
}
|
|
4091
|
+
/** Adopt attach for file-backed structured bridges (pi/grok today; codex/
|
|
4092
|
+
* traex keep their own branches for rollout-specific probes). */
|
|
4093
|
+
function setupAdoptFileBridge(cfg) {
|
|
4094
|
+
const adoptStartMs = Date.now();
|
|
4095
|
+
codexAdoptStartMs = adoptStartMs;
|
|
4096
|
+
codexBridgeQueue.setLocalTurns(true, adoptStartMs);
|
|
4097
|
+
const path = resolveFileBridgePath(cfg.cliId, {
|
|
4098
|
+
sessionId: cfg.cliSessionId,
|
|
4099
|
+
cwd: cfg.adoptCwd ?? cfg.workingDir,
|
|
4100
|
+
pid: cfg.adoptCliPid,
|
|
4101
|
+
});
|
|
4102
|
+
if (path) {
|
|
4103
|
+
codexBridgeAttach(path, 'split-live');
|
|
4104
|
+
}
|
|
4105
|
+
else {
|
|
4049
4106
|
if (cfg.cliSessionId)
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
if (probed)
|
|
4054
|
-
path = probed.path;
|
|
4055
|
-
}
|
|
4056
|
-
if (path) {
|
|
4057
|
-
codexBridgeAttach(path, 'split-live');
|
|
4058
|
-
}
|
|
4059
|
-
else {
|
|
4060
|
-
if (cfg.cliSessionId)
|
|
4061
|
-
codexBridgePendingSessionId = cfg.cliSessionId;
|
|
4062
|
-
codexAdoptPendingPid = cfg.adoptCliPid;
|
|
4063
|
-
codexBridgeStartTimer();
|
|
4064
|
-
}
|
|
4107
|
+
codexBridgePendingSessionId = cfg.cliSessionId;
|
|
4108
|
+
codexAdoptPendingPid = cfg.adoptCliPid;
|
|
4109
|
+
codexBridgeStartTimer();
|
|
4065
4110
|
}
|
|
4066
4111
|
}
|
|
4067
4112
|
function adoptIdleAdapter(cfg) {
|
|
4068
4113
|
return cfg.bridgeJsonlPath
|
|
4069
4114
|
? createCliAdapterSync('claude-code', undefined)
|
|
4070
|
-
: cfg.cliId
|
|
4115
|
+
: isStructuredBridgeAdoptIdleCli(cfg.cliId)
|
|
4071
4116
|
? createCliAdapterSync(cfg.cliId, undefined)
|
|
4072
4117
|
: { completionPattern: undefined, readyPattern: undefined };
|
|
4073
4118
|
}
|
|
4074
4119
|
function setupAdoptInputAdapter(cfg) {
|
|
4075
|
-
if (cfg.cliId
|
|
4120
|
+
if (isStructuredBridgeAdoptInputCli(cfg.cliId)) {
|
|
4076
4121
|
cliAdapter = createCliAdapterSync(cfg.cliId, cfg.cliPathOverride);
|
|
4077
4122
|
}
|
|
4078
|
-
else if (cfg.cliId === 'mtr') {
|
|
4079
|
-
cliAdapter = createCliAdapterSync('mtr', cfg.cliPathOverride);
|
|
4080
|
-
}
|
|
4081
4123
|
}
|
|
4082
4124
|
function setupAdoptIdleDetection(cfg, label) {
|
|
4083
4125
|
idleDetector = new IdleDetector(adoptIdleAdapter(cfg));
|
|
@@ -4211,8 +4253,16 @@ function spawnCli(cfg) {
|
|
|
4211
4253
|
});
|
|
4212
4254
|
effectiveBackendType = 'herdr';
|
|
4213
4255
|
backend = herdrBe;
|
|
4256
|
+
// Same as tmux/zellij adopt: writeInput (grok preferSessionId via
|
|
4257
|
+
// findGrokSessionByPid, claude pid-state) needs cliPid/cliCwd on the
|
|
4258
|
+
// PtyHandle. spawn() overwrites cliCwd from opts.cwd — use adoptCwd when
|
|
4259
|
+
// present so session discovery stays on the CLI's real working dir.
|
|
4260
|
+
if (cfg.adoptCliPid)
|
|
4261
|
+
herdrBe.cliPid = cfg.adoptCliPid;
|
|
4262
|
+
const herdrAdoptCwd = cfg.adoptCwd ?? cfg.workingDir;
|
|
4263
|
+
herdrBe.cliCwd = herdrAdoptCwd;
|
|
4214
4264
|
herdrBe.spawn('', [], {
|
|
4215
|
-
cwd:
|
|
4265
|
+
cwd: herdrAdoptCwd,
|
|
4216
4266
|
cols,
|
|
4217
4267
|
rows,
|
|
4218
4268
|
env: process.env,
|
|
@@ -4252,6 +4302,12 @@ function spawnCli(cfg) {
|
|
|
4252
4302
|
: new TmuxPipeBackend(cfg.adoptTmuxTarget, { cliPid: cfg.adoptCliPid });
|
|
4253
4303
|
effectiveBackendType = cfg.adoptZellijPaneId ? 'zellij' : 'tmux';
|
|
4254
4304
|
backend = observeBe;
|
|
4305
|
+
// writeInput (grok concurrent prompt_history binding, claude pid-state)
|
|
4306
|
+
// reads these fields off the PtyHandle — constructor only stores
|
|
4307
|
+
// watchCliPid for liveness, so surface them explicitly for adopt.
|
|
4308
|
+
if (cfg.adoptCliPid)
|
|
4309
|
+
observeBe.cliPid = cfg.adoptCliPid;
|
|
4310
|
+
observeBe.cliCwd = cfg.adoptCwd ?? cfg.workingDir;
|
|
4255
4311
|
observeBe.spawn('', [], {
|
|
4256
4312
|
cwd: cfg.workingDir,
|
|
4257
4313
|
cols,
|
|
@@ -4300,7 +4356,7 @@ function spawnCli(cfg) {
|
|
|
4300
4356
|
if (effectiveBackend === 'tmux') {
|
|
4301
4357
|
hasExistingSession = TmuxBackend.hasSession(TmuxBackend.sessionName(cfg.sessionId));
|
|
4302
4358
|
if (!hasExistingSession) {
|
|
4303
|
-
const probe =
|
|
4359
|
+
const probe = probeTmuxFunctionalWithRetry();
|
|
4304
4360
|
available = probe.ok;
|
|
4305
4361
|
if (!probe.ok)
|
|
4306
4362
|
reason = probe.reason;
|
|
@@ -4759,6 +4815,10 @@ function spawnCli(cfg) {
|
|
|
4759
4815
|
const perBotInjectKeys = Object.keys(perBotInjectEnv);
|
|
4760
4816
|
if (perBotInjectKeys.length)
|
|
4761
4817
|
log(`Injecting ${perBotInjectKeys.length} per-bot env var(s): ${perBotInjectKeys.join(', ')}`);
|
|
4818
|
+
const hermesUsesBotmuxSessionProfile = basename(cfg.cliPathOverride ?? '') === 'hermes-botmux-session';
|
|
4819
|
+
hermesBridgeDbPath = cfg.cliId === 'hermes'
|
|
4820
|
+
? resolveHermesStateDbPath({ ...childEnv, ...perBotInjectEnv }, { botmuxSessionProfile: hermesUsesBotmuxSessionProfile })
|
|
4821
|
+
: undefined;
|
|
4762
4822
|
// ── File sandbox (oncall): wrap the CLI in bwrap so it can only touch a
|
|
4763
4823
|
// per-session project copy + de-identified config. The agent's `botmux send`
|
|
4764
4824
|
// routes through a daemon-side outbox watcher (creds never enter the sandbox).
|
|
@@ -5047,15 +5107,15 @@ function spawnCli(cfg) {
|
|
|
5047
5107
|
startWrapperRealPidResolve(cliPid);
|
|
5048
5108
|
if (cliPid)
|
|
5049
5109
|
observeCursorCliSessionId(cliPid);
|
|
5050
|
-
// Wire pid + cwd so
|
|
5051
|
-
// ~/.claude/sessions/<pid>.json
|
|
5052
|
-
//
|
|
5053
|
-
//
|
|
5054
|
-
// '
|
|
5055
|
-
//
|
|
5056
|
-
// initial guess; the resolver corrects
|
|
5057
|
-
// started with `--resume`.
|
|
5058
|
-
if (
|
|
5110
|
+
// Wire pid + cwd so adapters' writeInput can bind submits to this process:
|
|
5111
|
+
// - claude-code: ~/.claude/sessions/<pid>.json
|
|
5112
|
+
// - grok: findGrokSessionByPid → preferSessionId against shared
|
|
5113
|
+
// prompt_history (concurrent same-cwd workers must not cross-claim)
|
|
5114
|
+
// Claude's sessionId is set ONCE at process start (2.1.123); a `--resume`
|
|
5115
|
+
// lookup will surface here, but in-pane `/clear` won't. The pinned
|
|
5116
|
+
// claudeJsonlPath above is still the initial guess; the resolver corrects
|
|
5117
|
+
// it on first write when Claude was started with `--resume`.
|
|
5118
|
+
if (cliPid && (claudeDataDir || cfg.cliId === 'grok')) {
|
|
5059
5119
|
backend.cliPid = cliPid;
|
|
5060
5120
|
backend.cliCwd = cfg.workingDir;
|
|
5061
5121
|
}
|
|
@@ -5085,7 +5145,7 @@ function spawnCli(cfg) {
|
|
|
5085
5145
|
log(`Failed to write CLI PID marker (async): ${err.message}`);
|
|
5086
5146
|
}
|
|
5087
5147
|
}
|
|
5088
|
-
if (claudeDataDir) {
|
|
5148
|
+
if (claudeDataDir || cfg.cliId === 'grok') {
|
|
5089
5149
|
backend.cliPid = pid;
|
|
5090
5150
|
backend.cliCwd = cfg.workingDir;
|
|
5091
5151
|
}
|
|
@@ -5192,17 +5252,21 @@ function spawnCli(cfg) {
|
|
|
5192
5252
|
codexBridgeStartTimer();
|
|
5193
5253
|
}
|
|
5194
5254
|
}
|
|
5195
|
-
else if (cfg.cliId === 'pi') {
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5255
|
+
else if (cfg.cliId === 'pi' || cfg.cliId === 'grok') {
|
|
5256
|
+
// File-backed: pin path when known (pi session id / grok --session-id
|
|
5257
|
+
// UUID), else arm the poller. Grok collision-fallback (dir already
|
|
5258
|
+
// exists → no --session-id → grok mints id) is recovered via writeInput
|
|
5259
|
+
// → codexBridgeNotifyCliSessionId.
|
|
5260
|
+
const sid = effectiveCliSessionId ?? effectiveAdapterSessionId;
|
|
5261
|
+
const path = sid
|
|
5262
|
+
? resolveFileBridgePath(cfg.cliId, { sessionId: sid, cwd: cfg.workingDir })
|
|
5263
|
+
: undefined;
|
|
5264
|
+
if (path) {
|
|
5265
|
+
codexBridgeAttach(path, effectiveResume ? 'baseline-existing' : 'fresh-empty');
|
|
5266
|
+
}
|
|
5267
|
+
else if (sid) {
|
|
5268
|
+
codexBridgePendingSessionId = sid;
|
|
5269
|
+
codexBridgeStartTimer();
|
|
5206
5270
|
}
|
|
5207
5271
|
else {
|
|
5208
5272
|
codexBridgeStartTimer();
|
|
@@ -5411,7 +5475,7 @@ function startWebServer(host, preferredPort) {
|
|
|
5411
5475
|
return;
|
|
5412
5476
|
}
|
|
5413
5477
|
const tokenMatches = url.searchParams.get('token') === writeToken;
|
|
5414
|
-
const { hasWrite, platformReadonly } =
|
|
5478
|
+
const { hasWrite, platformReadonly } = resolveTerminalWriteForReq(req, tokenMatches);
|
|
5415
5479
|
const loginHdr = req.headers['x-botmux-login-url'];
|
|
5416
5480
|
const loginUrl = typeof loginHdr === 'string' && /^https?:\/\/[^"'<>\s]+$/.test(loginHdr) ? loginHdr : '';
|
|
5417
5481
|
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
@@ -5429,7 +5493,7 @@ function startWebServer(host, preferredPort) {
|
|
|
5429
5493
|
return;
|
|
5430
5494
|
}
|
|
5431
5495
|
const tokenMatches = url.searchParams.get('token') === writeToken;
|
|
5432
|
-
const { hasWrite } =
|
|
5496
|
+
const { hasWrite } = resolveTerminalWriteForReq(req, tokenMatches);
|
|
5433
5497
|
if (hasWrite)
|
|
5434
5498
|
authedClients.add(ws);
|
|
5435
5499
|
log(`WS client connected (total: ${wsClients.size}, write: ${hasWrite})`);
|
|
@@ -5787,6 +5851,45 @@ try{
|
|
|
5787
5851
|
try{term.loadAddon(new CanvasAddon.CanvasAddon())}catch(_e2){}
|
|
5788
5852
|
}
|
|
5789
5853
|
fit.fit();
|
|
5854
|
+
// xterm parses writes asynchronously. On a brand-new page the first tmux /
|
|
5855
|
+
// zellij frame (or relay history seed) can therefore finish after the browser
|
|
5856
|
+
// has initialised the viewport scrollbar, leaving that viewport at scrollTop=0
|
|
5857
|
+
// even though the buffer already contains newer rows. Follow only the initial
|
|
5858
|
+
// write burst and explicitly settle at the bottom. Any deliberate user scroll
|
|
5859
|
+
// cancels this so loading a busy session never fights the reader.
|
|
5860
|
+
var _initialFollow=true,_initialFollowT=0;
|
|
5861
|
+
function _cancelInitialFollow(){
|
|
5862
|
+
if(!_initialFollow)return;
|
|
5863
|
+
_initialFollow=false;clearTimeout(_initialFollowT);
|
|
5864
|
+
}
|
|
5865
|
+
function _settleInitialBottom(){
|
|
5866
|
+
if(!_initialFollow)return;
|
|
5867
|
+
try{term.scrollToBottom()}catch(_e){}
|
|
5868
|
+
clearTimeout(_initialFollowT);
|
|
5869
|
+
_initialFollowT=setTimeout(function(){
|
|
5870
|
+
if(!_initialFollow)return;
|
|
5871
|
+
try{term.scrollToBottom()}catch(_e){}
|
|
5872
|
+
_initialFollow=false;
|
|
5873
|
+
},500);
|
|
5874
|
+
}
|
|
5875
|
+
var _initialViewport=term.element&&term.element.querySelector('.xterm-viewport');
|
|
5876
|
+
var _initialTerminalRoot=document.getElementById('terminal');
|
|
5877
|
+
if(_initialTerminalRoot){
|
|
5878
|
+
// Listen above xterm's own root: its wheel handler can stop propagation at
|
|
5879
|
+
// the target, while this ancestor still sees capture-phase user intent.
|
|
5880
|
+
_initialTerminalRoot.addEventListener('wheel',_cancelInitialFollow,{capture:true,passive:true});
|
|
5881
|
+
_initialTerminalRoot.addEventListener('touchstart',_cancelInitialFollow,{capture:true,passive:true});
|
|
5882
|
+
}
|
|
5883
|
+
if(_initialViewport){
|
|
5884
|
+
_initialViewport.addEventListener('pointerdown',function(e){
|
|
5885
|
+
// A pointer press on the native scrollbar targets the viewport itself;
|
|
5886
|
+
// presses on terminal cells target the screen/canvas and keep following.
|
|
5887
|
+
if(e.target===_initialViewport)_cancelInitialFollow();
|
|
5888
|
+
},{capture:true});
|
|
5889
|
+
}
|
|
5890
|
+
window.addEventListener('keydown',function(e){
|
|
5891
|
+
if(e.key==='PageUp'||e.key==='PageDown'||e.key==='Home'||e.key==='End')_cancelInitialFollow();
|
|
5892
|
+
},{capture:true});
|
|
5790
5893
|
// ── OSC 52 clipboard ──
|
|
5791
5894
|
var _clipBuf='';
|
|
5792
5895
|
function _doCopy(text){
|
|
@@ -5872,7 +5975,7 @@ window.addEventListener('resize',onViewportResize);
|
|
|
5872
5975
|
// Intercept OSC 52 clipboard sequence from tmux (set-clipboard on)
|
|
5873
5976
|
var m=data.match(/\\x1b\\]52;[^;]*;([A-Za-z0-9+/=]+)(?:\\x07|\\x1b\\\\)/);
|
|
5874
5977
|
if(m){try{_clipBuf=new TextDecoder().decode(Uint8Array.from(atob(m[1]),function(c){return c.charCodeAt(0)}));_doCopy(_clipBuf);_showCopied()}catch(ex){}}
|
|
5875
|
-
term.write(data);
|
|
5978
|
+
term.write(data,_settleInitialBottom);
|
|
5876
5979
|
};
|
|
5877
5980
|
ws.onclose=function(){ws_=null;el.textContent='disconnected';el.className='err';setTimeout(connect,2000)};
|
|
5878
5981
|
ws.onerror=function(){ws.close()};
|
|
@@ -6165,17 +6268,18 @@ process.on('message', async (raw) => {
|
|
|
6165
6268
|
}
|
|
6166
6269
|
}
|
|
6167
6270
|
// Adopt mode write:
|
|
6168
|
-
// -
|
|
6169
|
-
//
|
|
6170
|
-
//
|
|
6171
|
-
//
|
|
6172
|
-
//
|
|
6271
|
+
// - Structured-bridge adopt-input CLIs (codex/traex/pi/grok/mtr)
|
|
6272
|
+
// route through cliAdapter.writeInput so paste+Enter-retry +
|
|
6273
|
+
// transcript/history verify (and grok's prompt_history →
|
|
6274
|
+
// cliSessionId re-attach after /new) all run. Hardcoding only
|
|
6275
|
+
// codex/traex left grok on raw sendText, so /new rotation never
|
|
6276
|
+
// re-attached the bridge.
|
|
6173
6277
|
// - everything else keeps the simple raw sendText+Enter — the
|
|
6174
6278
|
// claude-code adopt bridge has its own dual-write recovery
|
|
6175
6279
|
// path, and the other CLIs' adopt flows haven't surfaced
|
|
6176
6280
|
// this submit-detection issue.
|
|
6177
6281
|
if (backend) {
|
|
6178
|
-
if ((lastInitConfig?.cliId
|
|
6282
|
+
if (isStructuredBridgeAdoptInputCli(lastInitConfig?.cliId) && cliAdapter) {
|
|
6179
6283
|
// writeInput is async but we're already inside an async
|
|
6180
6284
|
// message handler. Errors are best-effort logged; the bridge
|
|
6181
6285
|
// ingest path is unaffected because mark already happened
|
|
@@ -6187,11 +6291,11 @@ process.on('message', async (raw) => {
|
|
|
6187
6291
|
codexBridgeNotifyCliSessionId(result.cliSessionId);
|
|
6188
6292
|
}
|
|
6189
6293
|
if (result && result.submitted === false) {
|
|
6190
|
-
scheduleSubmitFailureNotify(content, result.recheck, '
|
|
6294
|
+
scheduleSubmitFailureNotify(content, result.recheck, 'submit history', undefined, result.failureReason, turnSeq);
|
|
6191
6295
|
}
|
|
6192
6296
|
}
|
|
6193
6297
|
catch (err) {
|
|
6194
|
-
log(`
|
|
6298
|
+
log(`Adopt writeInput error (${lastInitConfig?.cliId}): ${err.message}`);
|
|
6195
6299
|
}
|
|
6196
6300
|
}
|
|
6197
6301
|
else if ('sendText' in backend && 'sendSpecialKeys' in backend) {
|
|
@@ -6291,16 +6395,29 @@ process.on('message', async (raw) => {
|
|
|
6291
6395
|
// process would never actually restart. destroySession() tears the session
|
|
6292
6396
|
// down so the respawn starts a fresh CLI. (PTY has no destroySession, so
|
|
6293
6397
|
// the ?. no-ops and killCli()'s kill() does the teardown.)
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6398
|
+
const restart = () => {
|
|
6399
|
+
tmuxRestartTimer = null;
|
|
6400
|
+
backend?.destroySession?.();
|
|
6401
|
+
killCli();
|
|
6402
|
+
awaitingFirstPrompt = true;
|
|
6403
|
+
setTimeout(() => {
|
|
6404
|
+
if (lastInitConfig) {
|
|
6405
|
+
startScreenUpdates();
|
|
6406
|
+
startScreenAnalyzer();
|
|
6407
|
+
spawnCli({ ...lastInitConfig, resume: true, prompt: '' });
|
|
6408
|
+
}
|
|
6409
|
+
}, 500);
|
|
6410
|
+
};
|
|
6411
|
+
if (effectiveBackendType === 'tmux') {
|
|
6412
|
+
const delayMs = tmuxRestartJitterMs(lastInitConfig?.sessionId ?? '', consecutiveInWorkerRestarts);
|
|
6413
|
+
log(`Staggering tmux teardown/restart by ${delayMs}ms to avoid shared-server probe storms`);
|
|
6414
|
+
if (tmuxRestartTimer)
|
|
6415
|
+
clearTimeout(tmuxRestartTimer);
|
|
6416
|
+
tmuxRestartTimer = setTimeout(restart, delayMs);
|
|
6417
|
+
}
|
|
6418
|
+
else {
|
|
6419
|
+
restart();
|
|
6420
|
+
}
|
|
6304
6421
|
break;
|
|
6305
6422
|
}
|
|
6306
6423
|
case 'tui_keys': {
|
|
@@ -6425,6 +6542,10 @@ process.on('message', async (raw) => {
|
|
|
6425
6542
|
});
|
|
6426
6543
|
// ─── Cleanup ─────────────────────────────────────────────────────────────────
|
|
6427
6544
|
function cleanup() {
|
|
6545
|
+
if (tmuxRestartTimer) {
|
|
6546
|
+
clearTimeout(tmuxRestartTimer);
|
|
6547
|
+
tmuxRestartTimer = null;
|
|
6548
|
+
}
|
|
6428
6549
|
for (const [, cp] of clientPtys) {
|
|
6429
6550
|
try {
|
|
6430
6551
|
cp.kill();
|