@openrig/cli 0.6.2 → 0.6.4-rc.1
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/daemon/assets/onboarding/01-world-and-purpose.md +15 -5
- package/daemon/assets/onboarding/02-self-and-competent-action.md +9 -13
- package/daemon/assets/plugins/openrig-core/skills/claude-compaction-restore/scripts/precompact-hook.mjs +2 -1
- package/daemon/assets/plugins/openrig-core/skills/delegating-work/SKILL.md +6 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-skills/SKILL.md +2 -1
- package/daemon/context-packs/help/help.md +1 -0
- package/daemon/context-packs/help/manifest.yaml +1 -1
- package/daemon/context-packs/onboarding-width/manifest.yaml +1 -1
- package/daemon/context-packs/reference/manifest.yaml +1 -1
- package/daemon/context-packs/skills/agent-operated-software/manifest.yaml +1 -1
- package/daemon/context-packs/skills/agent-operated-workflows/manifest.yaml +1 -1
- package/daemon/context-packs/skills/applying-a-permission-policy/manifest.yaml +1 -1
- package/daemon/context-packs/skills/claude-compaction-restore/manifest.yaml +1 -1
- package/daemon/context-packs/skills/claude-compaction-restore/scripts/precompact-hook.mjs +2 -1
- package/daemon/context-packs/skills/core/agent-starters/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/agent-startup-and-context-ingestion/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/cross-host-rig-commands/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/human-in-the-loop/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/messaging-the-human/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-architect/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-cmux/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-herdr/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-skills/SKILL.md +2 -1
- package/daemon/context-packs/skills/core/openrig-skills/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-software-factory/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-upgrade/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/rig-bundles-and-shareable-artifacts/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/rig-lifecycle/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/session-source-fork/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/specification-system/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/topology-mutation-and-seat-management/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/watchdog/manifest.yaml +1 -1
- package/daemon/context-packs/skills/delegating-work/SKILL.md +6 -0
- package/daemon/context-packs/skills/delegating-work/manifest.yaml +1 -1
- package/daemon/context-packs/skills/forming-an-openrig-mental-model/manifest.yaml +1 -1
- package/daemon/context-packs/skills/loading-addressable-markdown/manifest.yaml +1 -1
- package/daemon/context-packs/skills/mission-slice-sop/manifest.yaml +1 -1
- package/daemon/context-packs/skills/openrig-operating-model/manifest.yaml +1 -1
- package/daemon/context-packs/skills/openrig-user/manifest.yaml +1 -1
- package/daemon/context-packs/skills/orienting-to-an-inherited-seat/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/backlog-capture/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/context-builder/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/exec-summary/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/office-hours/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/plan-review/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/requirements-writer/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/ui-mockup/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pods/development-team/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pods/orchestration-team/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pods/oversight-team/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pods/review-team/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/agent-browser/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/context-engineering/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/dogfood/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/frontend-design/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/systematic-debugging/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/test-driven-development/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/verification-before-completion/manifest.yaml +1 -1
- package/daemon/context-packs/skills/queue-handoff/manifest.yaml +1 -1
- package/daemon/context-packs/skills/refocusing/manifest.yaml +1 -1
- package/daemon/context-packs/skills/retiring-and-inheriting-a-seat/manifest.yaml +1 -1
- package/daemon/context-packs/skills/seat-continuity-and-handover/manifest.yaml +1 -1
- package/daemon/context-packs/skills/session-compaction-and-restore/manifest.yaml +1 -1
- package/daemon/context-packs/skills/software-for-agents/manifest.yaml +1 -1
- package/daemon/context-packs/world-example/manifest.yaml +1 -1
- package/daemon/context-packs/world-public/manifest.yaml +1 -1
- package/daemon/dist/adapters/claude-code-adapter.d.ts +5 -0
- package/daemon/dist/adapters/claude-code-adapter.d.ts.map +1 -1
- package/daemon/dist/adapters/claude-code-adapter.js +65 -19
- package/daemon/dist/adapters/claude-code-adapter.js.map +1 -1
- package/daemon/dist/adapters/claude-resume.d.ts.map +1 -1
- package/daemon/dist/adapters/claude-resume.js +15 -5
- package/daemon/dist/adapters/claude-resume.js.map +1 -1
- package/daemon/dist/adapters/codex-runtime-adapter.d.ts.map +1 -1
- package/daemon/dist/adapters/codex-runtime-adapter.js +12 -2
- package/daemon/dist/adapters/codex-runtime-adapter.js.map +1 -1
- package/daemon/dist/adapters/pi-runtime-adapter.d.ts.map +1 -1
- package/daemon/dist/adapters/pi-runtime-adapter.js +11 -1
- package/daemon/dist/adapters/pi-runtime-adapter.js.map +1 -1
- package/daemon/dist/adapters/stub-runtime-adapter.d.ts.map +1 -1
- package/daemon/dist/adapters/stub-runtime-adapter.js +11 -1
- package/daemon/dist/adapters/stub-runtime-adapter.js.map +1 -1
- package/daemon/dist/adapters/tmux-exec.d.ts +8 -1
- package/daemon/dist/adapters/tmux-exec.d.ts.map +1 -1
- package/daemon/dist/adapters/tmux-exec.js +24 -1
- package/daemon/dist/adapters/tmux-exec.js.map +1 -1
- package/daemon/dist/adapters/tmux.d.ts +26 -2
- package/daemon/dist/adapters/tmux.d.ts.map +1 -1
- package/daemon/dist/adapters/tmux.js +172 -78
- package/daemon/dist/adapters/tmux.js.map +1 -1
- package/daemon/dist/build-info.js +3 -3
- package/daemon/dist/domain/bootstrap-orchestrator.js +1 -1
- package/daemon/dist/domain/bootstrap-orchestrator.js.map +1 -1
- package/daemon/dist/domain/builtin-startup-files.d.ts +35 -0
- package/daemon/dist/domain/builtin-startup-files.d.ts.map +1 -0
- package/daemon/dist/domain/builtin-startup-files.js +117 -0
- package/daemon/dist/domain/builtin-startup-files.js.map +1 -0
- package/daemon/dist/domain/bundle-skills-router.d.ts +2 -2
- package/daemon/dist/domain/bundle-skills-router.d.ts.map +1 -1
- package/daemon/dist/domain/bundle-skills-router.js +1 -2
- package/daemon/dist/domain/bundle-skills-router.js.map +1 -1
- package/daemon/dist/domain/bundle-workflow-specs-router.d.ts +2 -2
- package/daemon/dist/domain/bundle-workflow-specs-router.d.ts.map +1 -1
- package/daemon/dist/domain/bundle-workflow-specs-router.js +1 -2
- package/daemon/dist/domain/bundle-workflow-specs-router.js.map +1 -1
- package/daemon/dist/domain/claude-managed-launch.d.ts +1 -0
- package/daemon/dist/domain/claude-managed-launch.d.ts.map +1 -1
- package/daemon/dist/domain/claude-managed-launch.js +9 -5
- package/daemon/dist/domain/claude-managed-launch.js.map +1 -1
- package/daemon/dist/domain/discovery-repository.d.ts.map +1 -1
- package/daemon/dist/domain/discovery-repository.js +2 -1
- package/daemon/dist/domain/discovery-repository.js.map +1 -1
- package/daemon/dist/domain/files/file-write-service.d.ts.map +1 -1
- package/daemon/dist/domain/files/file-write-service.js +2 -0
- package/daemon/dist/domain/files/file-write-service.js.map +1 -1
- package/daemon/dist/domain/gateway/slack/inbound.js +1 -1
- package/daemon/dist/domain/gateway/slack/inbound.js.map +1 -1
- package/daemon/dist/domain/gateway/slack/socket-inbound.d.ts.map +1 -1
- package/daemon/dist/domain/gateway/slack/socket-inbound.js +7 -2
- package/daemon/dist/domain/gateway/slack/socket-inbound.js.map +1 -1
- package/daemon/dist/domain/kernel-boot.d.ts +25 -0
- package/daemon/dist/domain/kernel-boot.d.ts.map +1 -1
- package/daemon/dist/domain/kernel-boot.js +54 -2
- package/daemon/dist/domain/kernel-boot.js.map +1 -1
- package/daemon/dist/domain/markdown-address.d.ts.map +1 -1
- package/daemon/dist/domain/markdown-address.js +2 -1
- package/daemon/dist/domain/markdown-address.js.map +1 -1
- package/daemon/dist/domain/native-process-lineage.d.ts +17 -3
- package/daemon/dist/domain/native-process-lineage.d.ts.map +1 -1
- package/daemon/dist/domain/native-process-lineage.js +155 -17
- package/daemon/dist/domain/native-process-lineage.js.map +1 -1
- package/daemon/dist/domain/native-resume-probe.d.ts +2 -0
- package/daemon/dist/domain/native-resume-probe.d.ts.map +1 -1
- package/daemon/dist/domain/native-resume-probe.js +6 -0
- package/daemon/dist/domain/native-resume-probe.js.map +1 -1
- package/daemon/dist/domain/occupant-invalidator.d.ts +4 -2
- package/daemon/dist/domain/occupant-invalidator.d.ts.map +1 -1
- package/daemon/dist/domain/occupant-invalidator.js +4 -2
- package/daemon/dist/domain/occupant-invalidator.js.map +1 -1
- package/daemon/dist/domain/pod-bundle-assembler.d.ts +3 -1
- package/daemon/dist/domain/pod-bundle-assembler.d.ts.map +1 -1
- package/daemon/dist/domain/pod-bundle-assembler.js +2 -2
- package/daemon/dist/domain/pod-bundle-assembler.js.map +1 -1
- package/daemon/dist/domain/queue-pickup.d.ts +2 -2
- package/daemon/dist/domain/queue-pickup.d.ts.map +1 -1
- package/daemon/dist/domain/queue-pickup.js +12 -1
- package/daemon/dist/domain/queue-pickup.js.map +1 -1
- package/daemon/dist/domain/queue-repository.d.ts +6 -2
- package/daemon/dist/domain/queue-repository.d.ts.map +1 -1
- package/daemon/dist/domain/queue-repository.js +13 -1
- package/daemon/dist/domain/queue-repository.js.map +1 -1
- package/daemon/dist/domain/queue-wake-repository.d.ts +4 -0
- package/daemon/dist/domain/queue-wake-repository.d.ts.map +1 -1
- package/daemon/dist/domain/queue-wake-repository.js +17 -0
- package/daemon/dist/domain/queue-wake-repository.js.map +1 -1
- package/daemon/dist/domain/restore-check-service.d.ts +2 -0
- package/daemon/dist/domain/restore-check-service.d.ts.map +1 -1
- package/daemon/dist/domain/restore-check-service.js +12 -1
- package/daemon/dist/domain/restore-check-service.js.map +1 -1
- package/daemon/dist/domain/restore-orchestrator.d.ts.map +1 -1
- package/daemon/dist/domain/restore-orchestrator.js +9 -4
- package/daemon/dist/domain/restore-orchestrator.js.map +1 -1
- package/daemon/dist/domain/resume-metadata-refresher.d.ts.map +1 -1
- package/daemon/dist/domain/resume-metadata-refresher.js +2 -1
- package/daemon/dist/domain/resume-metadata-refresher.js.map +1 -1
- package/daemon/dist/domain/rig-lifecycle-service.d.ts +2 -0
- package/daemon/dist/domain/rig-lifecycle-service.d.ts.map +1 -1
- package/daemon/dist/domain/rig-lifecycle-service.js +21 -4
- package/daemon/dist/domain/rig-lifecycle-service.js.map +1 -1
- package/daemon/dist/domain/rig-repository.d.ts +2 -0
- package/daemon/dist/domain/rig-repository.d.ts.map +1 -1
- package/daemon/dist/domain/rig-repository.js +8 -0
- package/daemon/dist/domain/rig-repository.js.map +1 -1
- package/daemon/dist/domain/rigspec-instantiator.d.ts +1 -4
- package/daemon/dist/domain/rigspec-instantiator.d.ts.map +1 -1
- package/daemon/dist/domain/rigspec-instantiator.js +90 -2
- package/daemon/dist/domain/rigspec-instantiator.js.map +1 -1
- package/daemon/dist/domain/running-name-guard.d.ts +20 -0
- package/daemon/dist/domain/running-name-guard.d.ts.map +1 -1
- package/daemon/dist/domain/running-name-guard.js +40 -0
- package/daemon/dist/domain/running-name-guard.js.map +1 -1
- package/daemon/dist/domain/seat-delivery-guard.d.ts +4 -1
- package/daemon/dist/domain/seat-delivery-guard.d.ts.map +1 -1
- package/daemon/dist/domain/seat-delivery-guard.js +12 -3
- package/daemon/dist/domain/seat-delivery-guard.js.map +1 -1
- package/daemon/dist/domain/seat-handover-service.d.ts.map +1 -1
- package/daemon/dist/domain/seat-handover-service.js +7 -20
- package/daemon/dist/domain/seat-handover-service.js.map +1 -1
- package/daemon/dist/domain/seat-lifecycle-service.d.ts.map +1 -1
- package/daemon/dist/domain/seat-lifecycle-service.js +13 -5
- package/daemon/dist/domain/seat-lifecycle-service.js.map +1 -1
- package/daemon/dist/domain/seat-status-service.js +1 -1
- package/daemon/dist/domain/seat-status-service.js.map +1 -1
- package/daemon/dist/domain/session-owner.d.ts +20 -0
- package/daemon/dist/domain/session-owner.d.ts.map +1 -0
- package/daemon/dist/domain/session-owner.js +33 -0
- package/daemon/dist/domain/session-owner.js.map +1 -0
- package/daemon/dist/domain/session-transport.d.ts +4 -2
- package/daemon/dist/domain/session-transport.d.ts.map +1 -1
- package/daemon/dist/domain/session-transport.js +74 -14
- package/daemon/dist/domain/session-transport.js.map +1 -1
- package/daemon/dist/domain/terminal/herdr-transport.d.ts.map +1 -1
- package/daemon/dist/domain/terminal/herdr-transport.js +2 -1
- package/daemon/dist/domain/terminal/herdr-transport.js.map +1 -1
- package/daemon/dist/domain/transcript-store.d.ts.map +1 -1
- package/daemon/dist/domain/transcript-store.js +14 -6
- package/daemon/dist/domain/transcript-store.js.map +1 -1
- package/daemon/dist/domain/types.d.ts +6 -0
- package/daemon/dist/domain/types.d.ts.map +1 -1
- package/daemon/dist/domain/user-settings/settings-store.d.ts +1 -1
- package/daemon/dist/domain/user-settings/settings-store.d.ts.map +1 -1
- package/daemon/dist/domain/user-settings/settings-store.js +5 -0
- package/daemon/dist/domain/user-settings/settings-store.js.map +1 -1
- package/daemon/dist/domain/watchdog-jobs-repository.d.ts +3 -2
- package/daemon/dist/domain/watchdog-jobs-repository.d.ts.map +1 -1
- package/daemon/dist/domain/watchdog-jobs-repository.js +6 -4
- package/daemon/dist/domain/watchdog-jobs-repository.js.map +1 -1
- package/daemon/dist/domain/workflow/starter-spec-loader.d.ts.map +1 -1
- package/daemon/dist/domain/workflow/starter-spec-loader.js +2 -1
- package/daemon/dist/domain/workflow/starter-spec-loader.js.map +1 -1
- package/daemon/dist/index.d.ts.map +1 -1
- package/daemon/dist/index.js +5 -1
- package/daemon/dist/index.js.map +1 -1
- package/daemon/dist/middleware/browser-boundary.d.ts +85 -0
- package/daemon/dist/middleware/browser-boundary.d.ts.map +1 -0
- package/daemon/dist/middleware/browser-boundary.js +278 -0
- package/daemon/dist/middleware/browser-boundary.js.map +1 -0
- package/daemon/dist/routes/bundles.js +4 -4
- package/daemon/dist/routes/bundles.js.map +1 -1
- package/daemon/dist/routes/chat.d.ts.map +1 -1
- package/daemon/dist/routes/chat.js +18 -17
- package/daemon/dist/routes/chat.js.map +1 -1
- package/daemon/dist/routes/events.js +4 -3
- package/daemon/dist/routes/events.js.map +1 -1
- package/daemon/dist/routes/files.js +1 -1
- package/daemon/dist/routes/files.js.map +1 -1
- package/daemon/dist/routes/restore-check.d.ts.map +1 -1
- package/daemon/dist/routes/restore-check.js +2 -0
- package/daemon/dist/routes/restore-check.js.map +1 -1
- package/daemon/dist/routes/rigs.js +1 -1
- package/daemon/dist/routes/rigs.js.map +1 -1
- package/daemon/dist/routes/rigspec.js +4 -2
- package/daemon/dist/routes/rigspec.js.map +1 -1
- package/daemon/dist/routes/slices.js +1 -1
- package/daemon/dist/routes/slices.js.map +1 -1
- package/daemon/dist/routes/stream.d.ts.map +1 -1
- package/daemon/dist/routes/stream.js +15 -14
- package/daemon/dist/routes/stream.js.map +1 -1
- package/daemon/dist/routes/terminal-ws.d.ts +16 -0
- package/daemon/dist/routes/terminal-ws.d.ts.map +1 -1
- package/daemon/dist/routes/terminal-ws.js +14 -19
- package/daemon/dist/routes/terminal-ws.js.map +1 -1
- package/daemon/dist/routes/up.js +3 -2
- package/daemon/dist/routes/up.js.map +1 -1
- package/daemon/dist/server.d.ts +9 -0
- package/daemon/dist/server.d.ts.map +1 -1
- package/daemon/dist/server.js +22 -2
- package/daemon/dist/server.js.map +1 -1
- package/daemon/dist/startup.d.ts +5 -1
- package/daemon/dist/startup.d.ts.map +1 -1
- package/daemon/dist/startup.js +16 -4
- package/daemon/dist/startup.js.map +1 -1
- package/daemon/docs/reference/browser-access.md +45 -0
- package/daemon/docs/reference/help.md +1 -0
- package/daemon/specs/agents/shared/skills/core/openrig-skills/SKILL.md +2 -1
- package/daemon/specs/rigs/launch/kernel/agents/advisor/lead/agent.yaml +1 -1
- package/daemon/specs/rigs/launch/kernel/agents/operator/agent/agent.yaml +1 -1
- package/daemon/specs/rigs/launch/kernel/agents/queue/worker/agent.yaml +1 -1
- package/dist/build-info.js +3 -3
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +43 -10
- package/dist/client.js.map +1 -1
- package/dist/commands/attach.js +1 -1
- package/dist/commands/attach.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +1 -0
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/daemon.d.ts +4 -0
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +12 -8
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +5 -0
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/proof.d.ts +8 -0
- package/dist/commands/proof.d.ts.map +1 -1
- package/dist/commands/proof.js +95 -4
- package/dist/commands/proof.js.map +1 -1
- package/dist/commands/ps.d.ts.map +1 -1
- package/dist/commands/ps.js +6 -0
- package/dist/commands/ps.js.map +1 -1
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +3 -0
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/seat.d.ts.map +1 -1
- package/dist/commands/seat.js +37 -4
- package/dist/commands/seat.js.map +1 -1
- package/dist/commands/setup.d.ts +17 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +65 -12
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/shrink.d.ts.map +1 -1
- package/dist/commands/shrink.js +6 -1
- package/dist/commands/shrink.js.map +1 -1
- package/dist/commands/ui.d.ts +8 -0
- package/dist/commands/ui.d.ts.map +1 -1
- package/dist/commands/ui.js +14 -0
- package/dist/commands/ui.js.map +1 -1
- package/dist/commands/up.d.ts.map +1 -1
- package/dist/commands/up.js +7 -2
- package/dist/commands/up.js.map +1 -1
- package/dist/config-store.d.ts +3 -1
- package/dist/config-store.d.ts.map +1 -1
- package/dist/config-store.js +5 -0
- package/dist/config-store.js.map +1 -1
- package/dist/cross-host-executor.d.ts.map +1 -1
- package/dist/cross-host-executor.js +7 -2
- package/dist/cross-host-executor.js.map +1 -1
- package/dist/fetch-with-timeout.d.ts +2 -0
- package/dist/fetch-with-timeout.d.ts.map +1 -1
- package/dist/fetch-with-timeout.js +3 -1
- package/dist/fetch-with-timeout.js.map +1 -1
- package/dist/lib/file-transfer.d.ts.map +1 -1
- package/dist/lib/file-transfer.js +11 -3
- package/dist/lib/file-transfer.js.map +1 -1
- package/package.json +1 -1
- package/tui/dist/config/config-model.d.ts.map +1 -1
- package/tui/dist/config/config-model.js +1 -0
- package/tui/dist/config/config-model.js.map +1 -1
- package/tui/dist/daemon-client.d.ts.map +1 -1
- package/tui/dist/daemon-client.js +5 -2
- package/tui/dist/daemon-client.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tmux.d.ts","sourceRoot":"","sources":["../../src/adapters/tmux.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAM9F,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEtD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,+EAA+E;IAC/E,OAAO,IAAI,MAAM,CAAC;IAClB,uFAAuF;IACvF,UAAU,IAAI,MAAM,CAAC;CACtB;AAWD,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GACpB;IAAE,KAAK,EAAE,SAAS,CAAA;CAAE,GACpB;IAAE,KAAK,EAAE,QAAQ,CAAA;CAAE,GACnB;IAAE,KAAK,EAAE,uBAAuB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"tmux.d.ts","sourceRoot":"","sources":["../../src/adapters/tmux.ts"],"names":[],"mappings":"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"}
|
|
@@ -24,9 +24,10 @@ const WINDOW_FORMAT = [
|
|
|
24
24
|
"#{window_panes}",
|
|
25
25
|
"#{window_active}",
|
|
26
26
|
].join(TMUX_FIELD_SEPARATOR);
|
|
27
|
-
// tmux 3.6 sanitizes literal control characters in -F output to underscores,
|
|
28
|
-
// so tab-delimited
|
|
29
|
-
//
|
|
27
|
+
// tmux 3.6 sanitizes literal control characters in -F output to underscores, and
|
|
28
|
+
// tmux 3.3a replaces tabs with underscores, so tab-delimited rows become
|
|
29
|
+
// unparseable on those versions. EVERY adapter-owned format uses the printable
|
|
30
|
+
// delimiter instead.
|
|
30
31
|
const PANE_FORMAT = [
|
|
31
32
|
"#{pane_id}",
|
|
32
33
|
"#{pane_index}",
|
|
@@ -35,7 +36,16 @@ const PANE_FORMAT = [
|
|
|
35
36
|
"#{pane_height}",
|
|
36
37
|
"#{pane_active}",
|
|
37
38
|
].join(TMUX_FIELD_SEPARATOR);
|
|
38
|
-
const CLIENT_FORMAT =
|
|
39
|
+
const CLIENT_FORMAT = [
|
|
40
|
+
"#{client_name}",
|
|
41
|
+
"#{client_session}",
|
|
42
|
+
].join(TMUX_FIELD_SEPARATOR);
|
|
43
|
+
const CURSOR_FORMAT = [
|
|
44
|
+
"#{cursor_x}",
|
|
45
|
+
"#{cursor_y}",
|
|
46
|
+
"#{pane_width}",
|
|
47
|
+
"#{pane_height}",
|
|
48
|
+
].join(TMUX_FIELD_SEPARATOR);
|
|
39
49
|
function isNoServerError(err) {
|
|
40
50
|
return err instanceof Error && err.message.includes("no server running");
|
|
41
51
|
}
|
|
@@ -99,6 +109,16 @@ function shellQuote(s) {
|
|
|
99
109
|
// Replace each ' with '"'"' (end quote, double-quote the apostrophe, resume quote)
|
|
100
110
|
return "'" + s.replace(/'/g, "'\"'\"'") + "'";
|
|
101
111
|
}
|
|
112
|
+
/** Elements safe to leave bare in a POSIX shell word list. */
|
|
113
|
+
const SHELL_SAFE = /^[A-Za-z0-9_@%+=:,./-]+$/;
|
|
114
|
+
/** Join argv for a POSIX shell — the legacy string form. Only used when
|
|
115
|
+
* no ArgvExecFn is wired. Flags and safe words stay bare (matching the
|
|
116
|
+
* historical template strings); anything else is single-quoted. The argv
|
|
117
|
+
* arrays stay the single source of truth for what is EXECUTED on either
|
|
118
|
+
* path — this join only renders them for a shell. */
|
|
119
|
+
function posixJoinArgv(argv) {
|
|
120
|
+
return argv.map((a) => (SHELL_SAFE.test(a) ? a : shellQuote(a))).join(" ");
|
|
121
|
+
}
|
|
102
122
|
function parseSessionLine(line) {
|
|
103
123
|
const parts = line.split(TMUX_FIELD_SEPARATOR);
|
|
104
124
|
if (parts.length < 4)
|
|
@@ -114,15 +134,16 @@ function parseSessionLine(line) {
|
|
|
114
134
|
};
|
|
115
135
|
}
|
|
116
136
|
function parseClientLine(line) {
|
|
117
|
-
|
|
118
|
-
|
|
137
|
+
// First-separator split keeps any separator inside the session name intact.
|
|
138
|
+
const separator = line.indexOf(TMUX_FIELD_SEPARATOR);
|
|
139
|
+
if (separator <= 0)
|
|
119
140
|
return null;
|
|
120
|
-
const
|
|
121
|
-
if (
|
|
141
|
+
const session = line.slice(separator + 1);
|
|
142
|
+
if (session === "")
|
|
122
143
|
return null;
|
|
123
144
|
return {
|
|
124
|
-
name,
|
|
125
|
-
session
|
|
145
|
+
name: line.slice(0, separator),
|
|
146
|
+
session,
|
|
126
147
|
};
|
|
127
148
|
}
|
|
128
149
|
function parseWindowLine(line) {
|
|
@@ -170,6 +191,7 @@ function parseLines(output, parser) {
|
|
|
170
191
|
export class TmuxAdapter {
|
|
171
192
|
exec;
|
|
172
193
|
fileOps;
|
|
194
|
+
argvExec;
|
|
173
195
|
deliveryGuard;
|
|
174
196
|
freshProbes = new Map();
|
|
175
197
|
freshManaged = new Map();
|
|
@@ -178,19 +200,58 @@ export class TmuxAdapter {
|
|
|
178
200
|
async createProbeSession(name, cwd) {
|
|
179
201
|
if (this.deliveryGuard?.maybeTarget(name))
|
|
180
202
|
return { ok: false, code: "guard_target_managed", message: "A probe cannot reuse a managed seat." };
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
203
|
+
// #188: the create itself reports the new session's id and creation time, the only identity a rollback
|
|
204
|
+
// uses. An id alone is unique only for one server's lifetime.
|
|
205
|
+
let created;
|
|
206
|
+
try {
|
|
207
|
+
const out = await this.exec(`tmux new-session -d -P -F ${shellQuote("#{session_id} #{session_created}")} -s ${shellQuote(name)}${cwd != null ? ` -c ${shellQuote(cwd)}` : ""}`);
|
|
208
|
+
const match = /^(\$\d+) (\d+)$/.exec(out.trim());
|
|
209
|
+
created = match ? { id: match[1], at: match[2] } : null;
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
return classifyWriteError(err);
|
|
213
|
+
}
|
|
214
|
+
let message = "New probe pane could not be established; no input written.";
|
|
215
|
+
let pane = null;
|
|
184
216
|
try {
|
|
185
217
|
const panes = await this.listPanes(name);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
218
|
+
pane = panes.length === 1 ? panes[0].id : null;
|
|
219
|
+
// #188: a fresh tmux server reuses pane ids, so a stale seat binding can name the new pane. That
|
|
220
|
+
// probe could not be cleaned up safely later, so it is not used.
|
|
221
|
+
if (pane && this.deliveryGuard?.maybeTarget(pane))
|
|
222
|
+
message = "New probe pane is named by a managed record; no input written.";
|
|
223
|
+
else if (pane) {
|
|
224
|
+
this.freshProbes.set(name, pane);
|
|
225
|
+
this.freshProbes.set(pane, pane);
|
|
226
|
+
return { ok: true };
|
|
190
227
|
}
|
|
191
228
|
}
|
|
192
229
|
catch { /* no target proof, no input */ }
|
|
193
|
-
|
|
230
|
+
// #188: remove the unusable helper by the id its own create returned, unless a managed record has
|
|
231
|
+
// since claimed its name (a binding naming only the reused pane id, under another session name, is
|
|
232
|
+
// stale: that pane belongs to this session). A name reused by another session has a different id.
|
|
233
|
+
const byPane = pane ? this.deliveryGuard?.maybeTarget(pane) : null;
|
|
234
|
+
if (!created || this.deliveryGuard?.maybeTarget(name) || byPane?.session === name) {
|
|
235
|
+
return { ok: false, code: "guard_target_unknown", message: `${message} The helper session was left in place: its ownership could not be proven.` };
|
|
236
|
+
}
|
|
237
|
+
const removed = await this.removeCreatedSession(name, created);
|
|
238
|
+
if (!removed.ok && removed.code !== "session_not_found")
|
|
239
|
+
message += ` The helper session was not removed: ${removed.message}`;
|
|
240
|
+
return { ok: false, code: "guard_target_unknown", message };
|
|
241
|
+
}
|
|
242
|
+
/** #188: kill the session this adapter created only while its id still names that session. tmux checks
|
|
243
|
+
* the name and creation time and kills in one command, so a later server that reuses the id is safe. */
|
|
244
|
+
async removeCreatedSession(name, created) {
|
|
245
|
+
const same = `#{&&:#{==:#{session_name},${name}},#{==:#{session_created},${created.at}}}`;
|
|
246
|
+
try {
|
|
247
|
+
const out = await this.exec(`tmux if-shell -F -t ${shellQuote(created.id)} ${shellQuote(same)} ${shellQuote(`kill-session -t '${created.id}'`)} ${shellQuote("display-message -p kept")}`);
|
|
248
|
+
if (out.includes("kept"))
|
|
249
|
+
return { ok: false, code: "guard_target_changed", message: `its id ${created.id} no longer names it (it may already be gone); nothing was killed.` };
|
|
250
|
+
return { ok: true };
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
return classifyWriteError(err);
|
|
254
|
+
}
|
|
194
255
|
}
|
|
195
256
|
async guardedInput(target, write, allowAbsent = false) {
|
|
196
257
|
const guard = this.deliveryGuard;
|
|
@@ -202,7 +263,8 @@ export class TmuxAdapter {
|
|
|
202
263
|
const panes = await this.listPanes(target);
|
|
203
264
|
if (panes.length !== 1 || panes[0].id !== probePane)
|
|
204
265
|
throw new Error("Private probe target changed; no input written.");
|
|
205
|
-
|
|
266
|
+
// Awaited so a refusal inside the write (#188: the probe kill) returns as a result, not a throw.
|
|
267
|
+
return await write(probePane, () => { });
|
|
206
268
|
}
|
|
207
269
|
const created = this.freshManaged.get(target);
|
|
208
270
|
const identity = created?.nodeId ?? target;
|
|
@@ -242,9 +304,24 @@ export class TmuxAdapter {
|
|
|
242
304
|
operation(target, fn) {
|
|
243
305
|
return this.deliveryGuard ? this.deliveryGuard.operation(target, fn) : fn();
|
|
244
306
|
}
|
|
245
|
-
constructor(exec, fileOps = defaultTmuxFileOps()) {
|
|
307
|
+
constructor(exec, fileOps = defaultTmuxFileOps(), argvExec) {
|
|
246
308
|
this.exec = exec;
|
|
247
309
|
this.fileOps = fileOps;
|
|
310
|
+
this.argvExec = argvExec;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Run a multiplexer command. `argv` is what is EXECUTED on both paths:
|
|
314
|
+
* elements are verbatim (no quoting layer) when argvExec is wired;
|
|
315
|
+
* otherwise they are POSIX-joined — byte-identical to the legacy
|
|
316
|
+
* template strings for all current call sites (the suite pins them).
|
|
317
|
+
* `legacy` overrides the joined form only where history quoted
|
|
318
|
+
* differently (the `-F "..."` double-quoted formats); pass it ONLY to
|
|
319
|
+
* preserve an exact legacy string, never to smuggle new semantics.
|
|
320
|
+
*/
|
|
321
|
+
async run(argv, legacy) {
|
|
322
|
+
if (this.argvExec)
|
|
323
|
+
return this.argvExec(argv);
|
|
324
|
+
return this.exec(legacy ?? posixJoinArgv(argv));
|
|
248
325
|
}
|
|
249
326
|
/** Start an empty native terminal server, without inventing a seat/session. */
|
|
250
327
|
async startServer() {
|
|
@@ -252,7 +329,10 @@ export class TmuxAdapter {
|
|
|
252
329
|
try {
|
|
253
330
|
if ((await this.probeSession(probeName)).state !== "transport_unavailable")
|
|
254
331
|
return { ok: true };
|
|
255
|
-
// tmux -D keeps an empty server alive.
|
|
332
|
+
// tmux -D keeps an empty server alive. Stays on the shell-string path
|
|
333
|
+
// deliberately: detach + stdio redirection have no argv equivalent,
|
|
334
|
+
// and server bootstrap is POSIX-specific (psmux auto-starts its own).
|
|
335
|
+
// Native socket ownership arbitrates
|
|
256
336
|
// concurrent starts; the readback below, not shell exit, proves availability.
|
|
257
337
|
await this.exec("tmux -D </dev/null >/dev/null 2>&1 &");
|
|
258
338
|
for (let attempt = 0; attempt < 20; attempt++) {
|
|
@@ -268,7 +348,7 @@ export class TmuxAdapter {
|
|
|
268
348
|
}
|
|
269
349
|
async listSessions() {
|
|
270
350
|
try {
|
|
271
|
-
const output = await this.
|
|
351
|
+
const output = await this.run(["tmux", "list-sessions", "-F", SESSION_FORMAT], `tmux list-sessions -F "${SESSION_FORMAT}"`);
|
|
272
352
|
return parseLines(output, parseSessionLine);
|
|
273
353
|
}
|
|
274
354
|
catch (err) {
|
|
@@ -279,7 +359,7 @@ export class TmuxAdapter {
|
|
|
279
359
|
}
|
|
280
360
|
async listWindows(sessionName) {
|
|
281
361
|
try {
|
|
282
|
-
const output = await this.
|
|
362
|
+
const output = await this.run(["tmux", "list-windows", "-t", sessionName, "-F", WINDOW_FORMAT], `tmux list-windows -t ${shellQuote(sessionName)} -F "${WINDOW_FORMAT}"`);
|
|
283
363
|
return parseLines(output, parseWindowLine);
|
|
284
364
|
}
|
|
285
365
|
catch (err) {
|
|
@@ -290,7 +370,7 @@ export class TmuxAdapter {
|
|
|
290
370
|
}
|
|
291
371
|
async listPanes(target) {
|
|
292
372
|
try {
|
|
293
|
-
const output = await this.
|
|
373
|
+
const output = await this.run(["tmux", "list-panes", "-t", target, "-F", PANE_FORMAT], `tmux list-panes -t ${shellQuote(target)} -F "${PANE_FORMAT}"`);
|
|
294
374
|
return parseLines(output, parsePaneLine);
|
|
295
375
|
}
|
|
296
376
|
catch (err) {
|
|
@@ -314,7 +394,7 @@ export class TmuxAdapter {
|
|
|
314
394
|
// Use `tmux has-session` directly for reliable existence check — avoids
|
|
315
395
|
// parsing format-string output from `list-sessions` which can fail when
|
|
316
396
|
// tab delimiters are malformed across tmux versions.
|
|
317
|
-
await this.
|
|
397
|
+
await this.run(["tmux", "has-session", "-t", name], `tmux has-session -t ${shellQuote(name)}`);
|
|
318
398
|
return { state: "present" }; // exit 0 = session exists
|
|
319
399
|
}
|
|
320
400
|
catch (err) {
|
|
@@ -355,13 +435,20 @@ export class TmuxAdapter {
|
|
|
355
435
|
/** The committed binding now owns identity; this is not filesystem cleanup. */
|
|
356
436
|
finishLaunchBinding(session) { this.freshManaged.delete(session); }
|
|
357
437
|
async createSessionUnchecked(name, cwd, env) {
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
438
|
+
const argv = ["tmux", "new-session", "-d", "-s", name];
|
|
439
|
+
if (cwd != null)
|
|
440
|
+
argv.push("-c", cwd);
|
|
441
|
+
if (env)
|
|
442
|
+
for (const [k, v] of Object.entries(env))
|
|
443
|
+
argv.push("-e", `${k}=${v}`);
|
|
444
|
+
const legacyParts = ["tmux", "new-session", "-d", "-s", shellQuote(name)];
|
|
445
|
+
if (cwd != null)
|
|
446
|
+
legacyParts.push("-c", shellQuote(cwd));
|
|
447
|
+
if (env)
|
|
448
|
+
for (const [k, v] of Object.entries(env))
|
|
449
|
+
legacyParts.push("-e", shellQuote(`${k}=${v}`));
|
|
450
|
+
try {
|
|
451
|
+
await this.run(argv, legacyParts.join(" "));
|
|
365
452
|
return { ok: true };
|
|
366
453
|
}
|
|
367
454
|
catch (err) {
|
|
@@ -392,10 +479,10 @@ export class TmuxAdapter {
|
|
|
392
479
|
let bufferLoaded = false;
|
|
393
480
|
try {
|
|
394
481
|
await this.fileOps.writeFile(path, text);
|
|
395
|
-
await this.
|
|
482
|
+
await this.run(["tmux", "load-buffer", "-b", buffer, path], `tmux load-buffer -b ${shellQuote(buffer)} ${shellQuote(path)}`);
|
|
396
483
|
bufferLoaded = true;
|
|
397
484
|
beforeWrite();
|
|
398
|
-
await this.
|
|
485
|
+
await this.run(["tmux", "paste-buffer", "-t", target, "-b", buffer, "-d", "-r", "-p"], `tmux paste-buffer -t ${shellQuote(target)} -b ${shellQuote(buffer)} -d -r -p`);
|
|
399
486
|
return { ok: true };
|
|
400
487
|
}
|
|
401
488
|
catch (err) {
|
|
@@ -403,7 +490,7 @@ export class TmuxAdapter {
|
|
|
403
490
|
// paste failed after load - `-d` never ran, so the buffer is still
|
|
404
491
|
// resident. Best-effort delete to avoid leaking it.
|
|
405
492
|
try {
|
|
406
|
-
await this.
|
|
493
|
+
await this.run(["tmux", "delete-buffer", "-b", buffer], `tmux delete-buffer -b ${shellQuote(buffer)}`);
|
|
407
494
|
}
|
|
408
495
|
catch { /* best-effort cleanup */ }
|
|
409
496
|
}
|
|
@@ -471,9 +558,8 @@ export class TmuxAdapter {
|
|
|
471
558
|
return this.guardedInput(target, pane => this.sendKeysUnchecked(pane, keys));
|
|
472
559
|
}
|
|
473
560
|
async sendKeysUnchecked(target, keys) {
|
|
474
|
-
const cmd = `tmux send-keys -t ${shellQuote(target)} ${keys.map(shellQuote).join(" ")}`;
|
|
475
561
|
try {
|
|
476
|
-
await this.
|
|
562
|
+
await this.run(["tmux", "send-keys", "-t", target, ...keys], `tmux send-keys -t ${shellQuote(target)} ${keys.map(shellQuote).join(" ")}`);
|
|
477
563
|
return { ok: true };
|
|
478
564
|
}
|
|
479
565
|
catch (err) {
|
|
@@ -481,9 +567,8 @@ export class TmuxAdapter {
|
|
|
481
567
|
}
|
|
482
568
|
}
|
|
483
569
|
async setWindowOption(target, option, value) {
|
|
484
|
-
const cmd = `tmux set-option -w -t ${shellQuote(target)} ${shellQuote(option)} ${shellQuote(value)}`;
|
|
485
570
|
try {
|
|
486
|
-
await this.
|
|
571
|
+
await this.run(["tmux", "set-option", "-w", "-t", target, option, value], `tmux set-option -w -t ${shellQuote(target)} ${shellQuote(option)} ${shellQuote(value)}`);
|
|
487
572
|
return { ok: true };
|
|
488
573
|
}
|
|
489
574
|
catch (err) {
|
|
@@ -497,9 +582,8 @@ export class TmuxAdapter {
|
|
|
497
582
|
if (!Number.isFinite(rows) || !Number.isInteger(rows) || rows < 1) {
|
|
498
583
|
return { ok: false, code: "validation_error", message: `resizeWindow: rows must be a positive integer, got ${rows}` };
|
|
499
584
|
}
|
|
500
|
-
const cmd = `tmux resize-window -t ${shellQuote(target)} -x ${cols} -y ${rows}`;
|
|
501
585
|
try {
|
|
502
|
-
await this.
|
|
586
|
+
await this.run(["tmux", "resize-window", "-t", target, "-x", String(cols), "-y", String(rows)]);
|
|
503
587
|
return { ok: true };
|
|
504
588
|
}
|
|
505
589
|
catch (err) {
|
|
@@ -509,7 +593,7 @@ export class TmuxAdapter {
|
|
|
509
593
|
async killSession(name) {
|
|
510
594
|
if (this.deliveryGuard) {
|
|
511
595
|
return this.guardedInput(name, async (pane) => {
|
|
512
|
-
const stdout = await this.
|
|
596
|
+
const stdout = await this.run(["tmux", "display-message", "-p", "-t", pane, "#{session_id}"], `tmux display-message -p -t ${shellQuote(pane)} '#{session_id}'`);
|
|
513
597
|
const sessionId = stdout.trim();
|
|
514
598
|
if (!/^\$\d+$/.test(sessionId))
|
|
515
599
|
return { ok: false, code: "guard_target_unknown", message: "Cannot establish immutable session identity; no session killed." };
|
|
@@ -530,9 +614,8 @@ export class TmuxAdapter {
|
|
|
530
614
|
return this.killSessionUnchecked(name);
|
|
531
615
|
}
|
|
532
616
|
async killSessionUnchecked(name) {
|
|
533
|
-
const cmd = `tmux kill-session -t ${shellQuote(name)}`;
|
|
534
617
|
try {
|
|
535
|
-
await this.
|
|
618
|
+
await this.run(["tmux", "kill-session", "-t", name], `tmux kill-session -t ${shellQuote(name)}`);
|
|
536
619
|
const pane = this.freshProbes.get(name);
|
|
537
620
|
this.freshProbes.delete(name);
|
|
538
621
|
if (pane)
|
|
@@ -565,14 +648,25 @@ export class TmuxAdapter {
|
|
|
565
648
|
return this.guardedInput(paneTarget, pane => this.respawnPaneUnchecked(pane, command, opts));
|
|
566
649
|
}
|
|
567
650
|
async respawnPaneUnchecked(paneTarget, command, opts) {
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
651
|
+
const argv = ["tmux", "respawn-pane", "-t", paneTarget];
|
|
652
|
+
if (opts?.cwd != null)
|
|
653
|
+
argv.push("-c", opts.cwd);
|
|
654
|
+
if (opts?.env)
|
|
655
|
+
for (const [k, v] of Object.entries(opts.env))
|
|
656
|
+
argv.push("-e", `${k}=${v}`);
|
|
657
|
+
// The respawn command is ONE argv unit: tmux runs it via the shell.
|
|
658
|
+
if (command != null && command.length > 0)
|
|
659
|
+
argv.push(command);
|
|
660
|
+
const legacyRespawn = ["tmux", "respawn-pane", "-t", shellQuote(paneTarget)];
|
|
661
|
+
if (opts?.cwd != null)
|
|
662
|
+
legacyRespawn.push("-c", shellQuote(opts.cwd));
|
|
663
|
+
if (opts?.env)
|
|
664
|
+
for (const [k, v] of Object.entries(opts.env))
|
|
665
|
+
legacyRespawn.push("-e", shellQuote(`${k}=${v}`));
|
|
666
|
+
if (command != null && command.length > 0)
|
|
667
|
+
legacyRespawn.push(shellQuote(command));
|
|
668
|
+
try {
|
|
669
|
+
await this.run(argv, legacyRespawn.join(" "));
|
|
576
670
|
return { ok: true };
|
|
577
671
|
}
|
|
578
672
|
catch (err) {
|
|
@@ -584,9 +678,8 @@ export class TmuxAdapter {
|
|
|
584
678
|
* Set to `on` BEFORE the retiree is signalled to exit (else the pane is destroyed on exit and there
|
|
585
679
|
* is nothing to respawn into). */
|
|
586
680
|
async setRemainOnExit(paneTarget, on) {
|
|
587
|
-
const cmd = `tmux set-option -p -t ${shellQuote(paneTarget)} remain-on-exit ${on ? "on" : "off"}`;
|
|
588
681
|
try {
|
|
589
|
-
await this.
|
|
682
|
+
await this.run(["tmux", "set-option", "-p", "-t", paneTarget, "remain-on-exit", on ? "on" : "off"], `tmux set-option -p -t ${shellQuote(paneTarget)} remain-on-exit ${on ? "on" : "off"}`);
|
|
590
683
|
return { ok: true };
|
|
591
684
|
}
|
|
592
685
|
catch (err) {
|
|
@@ -597,7 +690,7 @@ export class TmuxAdapter {
|
|
|
597
690
|
* remain-on-exit)? A known-missing pane also proves physical cutover; unknown probe errors stay false. */
|
|
598
691
|
async isPaneDead(paneId) {
|
|
599
692
|
try {
|
|
600
|
-
const output = await this.
|
|
693
|
+
const output = await this.run(["tmux", "display-message", "-p", "-t", paneId, "#{pane_dead}"], `tmux display-message -p -t ${shellQuote(paneId)} "#{pane_dead}"`);
|
|
601
694
|
return output.trim() === "1";
|
|
602
695
|
}
|
|
603
696
|
catch (error) {
|
|
@@ -606,7 +699,9 @@ export class TmuxAdapter {
|
|
|
606
699
|
}
|
|
607
700
|
/** Seat-handover cutover: signal the pane's foreground process (the retiree) — `TERM` for the graceful
|
|
608
701
|
* exit-in-place, `KILL` for the bounded-timeout force fallback. Resolves the pane pid then `kill`s it;
|
|
609
|
-
* an unresolvable pid is a structured, non-throwing failure.
|
|
702
|
+
* an unresolvable pid is a structured, non-throwing failure.
|
|
703
|
+
* Stays on the shell-string path deliberately: this is a Unix `kill`,
|
|
704
|
+
* not a multiplexer command (Windows needs taskkill — named follow-up). */
|
|
610
705
|
async signalPaneProcess(paneId, signal) {
|
|
611
706
|
return this.guardedInput(paneId, (pane, beforeWrite) => this.signalPaneProcessUnchecked(pane, signal, beforeWrite));
|
|
612
707
|
}
|
|
@@ -627,7 +722,7 @@ export class TmuxAdapter {
|
|
|
627
722
|
/** Get the PID of the foreground process in a pane. Returns null if unavailable. */
|
|
628
723
|
async getPanePid(paneId) {
|
|
629
724
|
try {
|
|
630
|
-
const output = await this.
|
|
725
|
+
const output = await this.run(["tmux", "display-message", "-p", "-t", paneId, "#{pane_pid}"], `tmux display-message -p -t ${shellQuote(paneId)} "#{pane_pid}"`);
|
|
631
726
|
const trimmed = output.trim();
|
|
632
727
|
const parsed = parseInt(trimmed, 10);
|
|
633
728
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
@@ -641,7 +736,7 @@ export class TmuxAdapter {
|
|
|
641
736
|
* command the pane was created with. Returns null if unavailable (caller falls back). */
|
|
642
737
|
async getDefaultShell() {
|
|
643
738
|
try {
|
|
644
|
-
const output = await this.
|
|
739
|
+
const output = await this.run(["tmux", "show-options", "-gv", "default-shell"]);
|
|
645
740
|
const trimmed = output.trim();
|
|
646
741
|
return trimmed || null;
|
|
647
742
|
}
|
|
@@ -652,7 +747,7 @@ export class TmuxAdapter {
|
|
|
652
747
|
/** Get the current foreground command in a pane. Returns null if unavailable. */
|
|
653
748
|
async getPaneCommand(paneId) {
|
|
654
749
|
try {
|
|
655
|
-
const output = await this.
|
|
750
|
+
const output = await this.run(["tmux", "display-message", "-p", "-t", paneId, "#{pane_current_command}"], `tmux display-message -p -t ${shellQuote(paneId)} "#{pane_current_command}"`);
|
|
656
751
|
const trimmed = output.trim();
|
|
657
752
|
return trimmed || null;
|
|
658
753
|
}
|
|
@@ -667,7 +762,7 @@ export class TmuxAdapter {
|
|
|
667
762
|
* nonzero lookup exit. */
|
|
668
763
|
async hasSessionEnv(sessionName, varName) {
|
|
669
764
|
try {
|
|
670
|
-
const output = await this.
|
|
765
|
+
const output = await this.run(["tmux", "show-environment", "-t", sessionName], `tmux show-environment -t ${shellQuote(sessionName)}`);
|
|
671
766
|
const prefix = `${varName}=`;
|
|
672
767
|
return output.split(/\r?\n/).some((line) => line.startsWith(prefix) && line.slice(prefix.length).trim().length > 0);
|
|
673
768
|
}
|
|
@@ -680,9 +775,12 @@ export class TmuxAdapter {
|
|
|
680
775
|
// Shell-quote the path for safe injection into the pipe-pane command.
|
|
681
776
|
// The entire pipe command is passed as a single argument to tmux,
|
|
682
777
|
// which executes it via sh -c. We use shellQuote on the path.
|
|
683
|
-
|
|
778
|
+
// The sink travels as ONE argv unit: the multiplexer runs it via a
|
|
779
|
+
// shell, so its inner quoting stays POSIX here (psmux documents the same
|
|
780
|
+
// `cat >` server-side form for its own path).
|
|
781
|
+
const sink = "cat >> " + shellQuote(outputPath);
|
|
684
782
|
try {
|
|
685
|
-
await this.
|
|
783
|
+
await this.run(["tmux", "pipe-pane", "-t", sessionName, sink], `tmux pipe-pane -t ${shellQuote(sessionName)} ${shellQuote(sink)}`);
|
|
686
784
|
return { ok: true };
|
|
687
785
|
}
|
|
688
786
|
catch (err) {
|
|
@@ -691,9 +789,8 @@ export class TmuxAdapter {
|
|
|
691
789
|
}
|
|
692
790
|
/** Stop pipe-pane on a session. */
|
|
693
791
|
async stopPipePane(sessionName) {
|
|
694
|
-
const cmd = `tmux pipe-pane -t ${shellQuote(sessionName)}`;
|
|
695
792
|
try {
|
|
696
|
-
await this.
|
|
793
|
+
await this.run(["tmux", "pipe-pane", "-t", sessionName], `tmux pipe-pane -t ${shellQuote(sessionName)}`);
|
|
697
794
|
return { ok: true };
|
|
698
795
|
}
|
|
699
796
|
catch (err) {
|
|
@@ -703,7 +800,7 @@ export class TmuxAdapter {
|
|
|
703
800
|
/** Capture pane content (last N lines). Returns null if unavailable. */
|
|
704
801
|
async capturePaneContent(paneId, lines = 20) {
|
|
705
802
|
try {
|
|
706
|
-
const output = await this.
|
|
803
|
+
const output = await this.run(["tmux", "capture-pane", "-p", "-t", paneId, "-S", `-${lines}`], `tmux capture-pane -p -t ${shellQuote(paneId)} -S -${lines}`);
|
|
707
804
|
return output || null;
|
|
708
805
|
}
|
|
709
806
|
catch {
|
|
@@ -718,7 +815,7 @@ export class TmuxAdapter {
|
|
|
718
815
|
*/
|
|
719
816
|
async capturePaneScreen(paneId) {
|
|
720
817
|
try {
|
|
721
|
-
const output = await this.
|
|
818
|
+
const output = await this.run(["tmux", "capture-pane", "-p", "-t", paneId], `tmux capture-pane -p -t ${shellQuote(paneId)}`);
|
|
722
819
|
return output || null;
|
|
723
820
|
}
|
|
724
821
|
catch {
|
|
@@ -733,8 +830,8 @@ export class TmuxAdapter {
|
|
|
733
830
|
*/
|
|
734
831
|
async getPaneCursorPosition(paneId) {
|
|
735
832
|
try {
|
|
736
|
-
const output = await this.
|
|
737
|
-
const [xRaw, yRaw, widthRaw, heightRaw] = output.trim().split(
|
|
833
|
+
const output = await this.run(["tmux", "display-message", "-p", "-t", paneId, CURSOR_FORMAT], `tmux display-message -p -t ${shellQuote(paneId)} "${CURSOR_FORMAT}"`);
|
|
834
|
+
const [xRaw, yRaw, widthRaw, heightRaw] = output.trim().split(TMUX_FIELD_SEPARATOR);
|
|
738
835
|
const x = Number.parseInt(xRaw ?? "", 10);
|
|
739
836
|
const y = Number.parseInt(yRaw ?? "", 10);
|
|
740
837
|
const width = Number.parseInt(widthRaw ?? "", 10);
|
|
@@ -758,9 +855,8 @@ export class TmuxAdapter {
|
|
|
758
855
|
* scopes are never crossed (guard b2).
|
|
759
856
|
*/
|
|
760
857
|
async setSessionOption(sessionName, key, value) {
|
|
761
|
-
const cmd = `tmux set-option -t ${shellQuote(sessionName)} ${shellQuote(key)} ${shellQuote(value)}`;
|
|
762
858
|
try {
|
|
763
|
-
await this.
|
|
859
|
+
await this.run(["tmux", "set-option", "-t", sessionName, key, value], `tmux set-option -t ${shellQuote(sessionName)} ${shellQuote(key)} ${shellQuote(value)}`);
|
|
764
860
|
return { ok: true };
|
|
765
861
|
}
|
|
766
862
|
catch (err) {
|
|
@@ -775,9 +871,8 @@ export class TmuxAdapter {
|
|
|
775
871
|
* Used for `set-clipboard` / `copy-command`.
|
|
776
872
|
*/
|
|
777
873
|
async setServerOption(option, value) {
|
|
778
|
-
const cmd = `tmux set-option -s ${shellQuote(option)} ${shellQuote(value)}`;
|
|
779
874
|
try {
|
|
780
|
-
await this.
|
|
875
|
+
await this.run(["tmux", "set-option", "-s", option, value], `tmux set-option -s ${shellQuote(option)} ${shellQuote(value)}`);
|
|
781
876
|
return { ok: true };
|
|
782
877
|
}
|
|
783
878
|
catch (err) {
|
|
@@ -791,7 +886,7 @@ export class TmuxAdapter {
|
|
|
791
886
|
*/
|
|
792
887
|
async showServerOption(option) {
|
|
793
888
|
try {
|
|
794
|
-
const output = await this.
|
|
889
|
+
const output = await this.run(["tmux", "show-options", "-sv", option], `tmux show-options -sv ${shellQuote(option)}`);
|
|
795
890
|
const v = output.trim();
|
|
796
891
|
return v.length > 0 ? v : null;
|
|
797
892
|
}
|
|
@@ -802,7 +897,7 @@ export class TmuxAdapter {
|
|
|
802
897
|
/** Get a session-scoped user option value. Returns null if not set or error. */
|
|
803
898
|
async getSessionOption(sessionName, key) {
|
|
804
899
|
try {
|
|
805
|
-
const output = await this.
|
|
900
|
+
const output = await this.run(["tmux", "show-option", "-v", "-t", sessionName, key], `tmux show-option -v -t ${shellQuote(sessionName)} ${shellQuote(key)}`);
|
|
806
901
|
return output.trim() || null;
|
|
807
902
|
}
|
|
808
903
|
catch {
|
|
@@ -832,7 +927,7 @@ export class TmuxAdapter {
|
|
|
832
927
|
*/
|
|
833
928
|
async readPaneLastActivity(paneId) {
|
|
834
929
|
try {
|
|
835
|
-
const output = await this.
|
|
930
|
+
const output = await this.run(["tmux", "display-message", "-p", "-t", paneId, "#{window_activity}"], `tmux display-message -p -t ${shellQuote(paneId)} '#{window_activity}'`);
|
|
836
931
|
const trimmed = output.trim();
|
|
837
932
|
if (!/^\d+$/.test(trimmed))
|
|
838
933
|
return null;
|
|
@@ -855,7 +950,7 @@ export class TmuxAdapter {
|
|
|
855
950
|
*/
|
|
856
951
|
async listClients() {
|
|
857
952
|
try {
|
|
858
|
-
const output = await this.
|
|
953
|
+
const output = await this.run(["tmux", "list-clients", "-F", CLIENT_FORMAT], `tmux list-clients -F "${CLIENT_FORMAT}"`);
|
|
859
954
|
return parseLines(output, parseClientLine);
|
|
860
955
|
}
|
|
861
956
|
catch (err) {
|
|
@@ -871,9 +966,8 @@ export class TmuxAdapter {
|
|
|
871
966
|
* kills, or rebinds a session and never touches OpenRig routing/identity.
|
|
872
967
|
*/
|
|
873
968
|
async switchClient(client, target) {
|
|
874
|
-
const cmd = `tmux switch-client -c ${shellQuote(client)} -t ${shellQuote(target)}`;
|
|
875
969
|
try {
|
|
876
|
-
await this.
|
|
970
|
+
await this.run(["tmux", "switch-client", "-c", client, "-t", target], `tmux switch-client -c ${shellQuote(client)} -t ${shellQuote(target)}`);
|
|
877
971
|
return { ok: true };
|
|
878
972
|
}
|
|
879
973
|
catch (err) {
|