oh-my-codex 0.18.0 → 0.18.2
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/Cargo.lock +6 -6
- package/Cargo.toml +1 -1
- package/README.md +45 -19
- package/crates/omx-api/src/lib.rs +66 -9
- package/crates/omx-sparkshell/src/exec.rs +125 -3
- package/crates/omx-sparkshell/src/main.rs +126 -36
- package/crates/omx-sparkshell/tests/execution.rs +225 -1
- package/dist/agents/__tests__/definitions.test.js +14 -0
- package/dist/agents/__tests__/definitions.test.js.map +1 -1
- package/dist/agents/__tests__/native-config.test.js +19 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +30 -0
- package/dist/agents/definitions.js.map +1 -1
- package/dist/agents/native-config.d.ts +1 -0
- package/dist/agents/native-config.d.ts.map +1 -1
- package/dist/agents/native-config.js +4 -0
- package/dist/agents/native-config.js.map +1 -1
- package/dist/catalog/__tests__/generator.test.js +4 -0
- package/dist/catalog/__tests__/generator.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +15 -7
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +137 -8
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +203 -15
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/install-docs-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/install-docs-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/install-docs-contract.test.js +55 -0
- package/dist/cli/__tests__/install-docs-contract.test.js.map +1 -0
- package/dist/cli/__tests__/launch-fallback.test.js +163 -0
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/question.test.js +29 -43
- package/dist/cli/__tests__/question.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +94 -35
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/sparkshell-cli.test.js +20 -1
- package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
- package/dist/cli/__tests__/sparkshell-packaging.test.js +1 -0
- package/dist/cli/__tests__/sparkshell-packaging.test.js.map +1 -1
- package/dist/cli/__tests__/ultragoal.test.js +227 -4
- package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +72 -1
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/codex-feature-probe.d.ts +5 -0
- package/dist/cli/codex-feature-probe.d.ts.map +1 -1
- package/dist/cli/codex-feature-probe.js +13 -7
- package/dist/cli/codex-feature-probe.js.map +1 -1
- package/dist/cli/doctor.d.ts +7 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +297 -17
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +9 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +465 -110
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/plugin-marketplace.d.ts +2 -0
- package/dist/cli/plugin-marketplace.d.ts.map +1 -1
- package/dist/cli/plugin-marketplace.js +15 -1
- package/dist/cli/plugin-marketplace.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +71 -11
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/sparkshell.d.ts +7 -1
- package/dist/cli/sparkshell.d.ts.map +1 -1
- package/dist/cli/sparkshell.js +13 -3
- package/dist/cli/sparkshell.js.map +1 -1
- package/dist/cli/ultragoal.d.ts +1 -1
- package/dist/cli/ultragoal.d.ts.map +1 -1
- package/dist/cli/ultragoal.js +184 -10
- package/dist/cli/ultragoal.js.map +1 -1
- package/dist/cli/update.d.ts +2 -0
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +14 -3
- package/dist/cli/update.js.map +1 -1
- package/dist/compat/__tests__/doctor-contract.test.js +3 -0
- package/dist/compat/__tests__/doctor-contract.test.js.map +1 -1
- package/dist/config/__tests__/codex-feature-flags.test.js +11 -1
- package/dist/config/__tests__/codex-feature-flags.test.js.map +1 -1
- package/dist/config/__tests__/codex-hooks.test.js +22 -11
- package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
- package/dist/config/__tests__/commit-lore-guard.test.d.ts +2 -0
- package/dist/config/__tests__/commit-lore-guard.test.d.ts.map +1 -0
- package/dist/config/__tests__/commit-lore-guard.test.js +20 -0
- package/dist/config/__tests__/commit-lore-guard.test.js.map +1 -0
- package/dist/config/codex-feature-flags.d.ts +4 -0
- package/dist/config/codex-feature-flags.d.ts.map +1 -1
- package/dist/config/codex-feature-flags.js +4 -0
- package/dist/config/codex-feature-flags.js.map +1 -1
- package/dist/config/codex-hooks.d.ts +1 -0
- package/dist/config/codex-hooks.d.ts.map +1 -1
- package/dist/config/codex-hooks.js +8 -10
- package/dist/config/codex-hooks.js.map +1 -1
- package/dist/config/commit-lore-guard.d.ts +1 -0
- package/dist/config/commit-lore-guard.d.ts.map +1 -1
- package/dist/config/commit-lore-guard.js +29 -3
- package/dist/config/commit-lore-guard.js.map +1 -1
- package/dist/config/generator.d.ts +17 -1
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +124 -11
- package/dist/config/generator.js.map +1 -1
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js +21 -0
- package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js.map +1 -1
- package/dist/goal-workflows/codex-goal-snapshot.d.ts +4 -0
- package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -1
- package/dist/goal-workflows/codex-goal-snapshot.js +50 -3
- package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -1
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js +27 -6
- package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/consensus-execution-handoff.test.d.ts +1 -1
- package/dist/hooks/__tests__/consensus-execution-handoff.test.js +13 -11
- package/dist/hooks/__tests__/consensus-execution-handoff.test.js.map +1 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.js +4 -3
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +173 -17
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +33 -0
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
- package/dist/hooks/__tests__/prometheus-strict-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/prometheus-strict-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prometheus-strict-contract.test.js +320 -0
- package/dist/hooks/__tests__/prometheus-strict-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js +12 -0
- package/dist/hooks/__tests__/prompt-guidance-wave-two.test.js.map +1 -1
- package/dist/hooks/__tests__/research-workflow-boundaries.test.d.ts +2 -0
- package/dist/hooks/__tests__/research-workflow-boundaries.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/research-workflow-boundaries.test.js +35 -0
- package/dist/hooks/__tests__/research-workflow-boundaries.test.js.map +1 -0
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js +26 -3
- package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +1 -1
- package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -1
- package/dist/hooks/extensibility/dispatcher.js +29 -14
- package/dist/hooks/extensibility/dispatcher.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +1 -1
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +36 -9
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/keyword-registry.d.ts.map +1 -1
- package/dist/hooks/keyword-registry.js +1 -0
- package/dist/hooks/keyword-registry.js.map +1 -1
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
- package/dist/hooks/prompt-guidance-contract.js +14 -2
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hud/__tests__/hud-tmux-injection.test.js +36 -8
- package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +122 -11
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/__tests__/render.test.js +84 -0
- package/dist/hud/__tests__/render.test.js.map +1 -1
- package/dist/hud/__tests__/resource-leak-watch.test.d.ts +2 -0
- package/dist/hud/__tests__/resource-leak-watch.test.d.ts.map +1 -0
- package/dist/hud/__tests__/resource-leak-watch.test.js +28 -0
- package/dist/hud/__tests__/resource-leak-watch.test.js.map +1 -0
- package/dist/hud/__tests__/state.test.js +51 -1
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/__tests__/tmux.test.js +69 -23
- package/dist/hud/__tests__/tmux.test.js.map +1 -1
- package/dist/hud/index.d.ts +2 -2
- package/dist/hud/index.d.ts.map +1 -1
- package/dist/hud/index.js +17 -6
- package/dist/hud/index.js.map +1 -1
- package/dist/hud/reconcile.d.ts.map +1 -1
- package/dist/hud/reconcile.js +6 -3
- package/dist/hud/reconcile.js.map +1 -1
- package/dist/hud/render.d.ts.map +1 -1
- package/dist/hud/render.js +26 -0
- package/dist/hud/render.js.map +1 -1
- package/dist/hud/state.d.ts +2 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +62 -1
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/tmux.d.ts +10 -3
- package/dist/hud/tmux.d.ts.map +1 -1
- package/dist/hud/tmux.js +60 -11
- package/dist/hud/tmux.js.map +1 -1
- package/dist/hud/types.d.ts +22 -0
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.js.map +1 -1
- package/dist/notifications/__tests__/http-client-resource.test.d.ts +2 -0
- package/dist/notifications/__tests__/http-client-resource.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/http-client-resource.test.js +41 -0
- package/dist/notifications/__tests__/http-client-resource.test.js.map +1 -0
- package/dist/notifications/__tests__/verbosity.test.js +20 -0
- package/dist/notifications/__tests__/verbosity.test.js.map +1 -1
- package/dist/notifications/config.d.ts.map +1 -1
- package/dist/notifications/config.js +6 -3
- package/dist/notifications/config.js.map +1 -1
- package/dist/notifications/http-client.d.ts.map +1 -1
- package/dist/notifications/http-client.js +78 -27
- package/dist/notifications/http-client.js.map +1 -1
- package/dist/notifications/types.d.ts +2 -0
- package/dist/notifications/types.d.ts.map +1 -1
- package/dist/openclaw/__tests__/dispatcher.test.js +49 -1
- package/dist/openclaw/__tests__/dispatcher.test.js.map +1 -1
- package/dist/openclaw/dispatcher.d.ts +7 -4
- package/dist/openclaw/dispatcher.d.ts.map +1 -1
- package/dist/openclaw/dispatcher.js +32 -69
- package/dist/openclaw/dispatcher.js.map +1 -1
- package/dist/pipeline/__tests__/orchestrator.test.js +128 -4
- package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
- package/dist/pipeline/__tests__/stages.test.js +460 -9
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/pipeline/index.d.ts +8 -2
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +5 -2
- package/dist/pipeline/index.js.map +1 -1
- package/dist/pipeline/orchestrator.d.ts +5 -4
- package/dist/pipeline/orchestrator.d.ts.map +1 -1
- package/dist/pipeline/orchestrator.js +85 -17
- package/dist/pipeline/orchestrator.js.map +1 -1
- package/dist/pipeline/stages/code-review.d.ts +2 -2
- package/dist/pipeline/stages/code-review.d.ts.map +1 -1
- package/dist/pipeline/stages/code-review.js +5 -3
- package/dist/pipeline/stages/code-review.js.map +1 -1
- package/dist/pipeline/stages/deep-interview.d.ts +15 -0
- package/dist/pipeline/stages/deep-interview.d.ts.map +1 -0
- package/dist/pipeline/stages/deep-interview.js +32 -0
- package/dist/pipeline/stages/deep-interview.js.map +1 -0
- package/dist/pipeline/stages/ralph-verify.d.ts +5 -5
- package/dist/pipeline/stages/ralph-verify.d.ts.map +1 -1
- package/dist/pipeline/stages/ralph-verify.js +2 -2
- package/dist/pipeline/stages/ralph-verify.js.map +1 -1
- package/dist/pipeline/stages/ralplan.d.ts.map +1 -1
- package/dist/pipeline/stages/ralplan.js +41 -6
- package/dist/pipeline/stages/ralplan.js.map +1 -1
- package/dist/pipeline/stages/ultragoal.d.ts +19 -0
- package/dist/pipeline/stages/ultragoal.d.ts.map +1 -0
- package/dist/pipeline/stages/ultragoal.js +38 -0
- package/dist/pipeline/stages/ultragoal.js.map +1 -0
- package/dist/pipeline/stages/ultraqa.d.ts +30 -0
- package/dist/pipeline/stages/ultraqa.d.ts.map +1 -0
- package/dist/pipeline/stages/ultraqa.js +46 -0
- package/dist/pipeline/stages/ultraqa.js.map +1 -0
- package/dist/pipeline/types.d.ts +8 -6
- package/dist/pipeline/types.d.ts.map +1 -1
- package/dist/pipeline/types.js +2 -2
- package/dist/question/__tests__/ui.test.js +43 -10
- package/dist/question/__tests__/ui.test.js.map +1 -1
- package/dist/question/ui.d.ts +12 -0
- package/dist/question/ui.d.ts.map +1 -1
- package/dist/question/ui.js +83 -46
- package/dist/question/ui.js.map +1 -1
- package/dist/ralplan/__tests__/runtime.test.js +200 -10
- package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
- package/dist/ralplan/consensus-gate.d.ts +23 -0
- package/dist/ralplan/consensus-gate.d.ts.map +1 -0
- package/dist/ralplan/consensus-gate.js +212 -0
- package/dist/ralplan/consensus-gate.js.map +1 -0
- package/dist/ralplan/runtime.d.ts +25 -0
- package/dist/ralplan/runtime.d.ts.map +1 -1
- package/dist/ralplan/runtime.js +144 -8
- package/dist/ralplan/runtime.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +1358 -79
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/docs-site-contract.test.d.ts +2 -0
- package/dist/scripts/__tests__/docs-site-contract.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/docs-site-contract.test.js +42 -0
- package/dist/scripts/__tests__/docs-site-contract.test.js.map +1 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.js +115 -2
- package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -1
- package/dist/scripts/__tests__/run-test-files.test.js +57 -0
- package/dist/scripts/__tests__/run-test-files.test.js.map +1 -1
- package/dist/scripts/__tests__/smoke-packed-install.test.js +23 -1
- package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
- package/dist/scripts/__tests__/verify-native-agents.test.js +18 -3
- package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -1
- package/dist/scripts/cleanup-explore-harness.js +1 -0
- package/dist/scripts/cleanup-explore-harness.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +372 -44
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
- package/dist/scripts/codex-native-pre-post.js +9 -1
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/notify-dispatcher.js +188 -4
- package/dist/scripts/notify-dispatcher.js.map +1 -1
- package/dist/scripts/notify-hook/process-runner.d.ts.map +1 -1
- package/dist/scripts/notify-hook/process-runner.js +39 -17
- package/dist/scripts/notify-hook/process-runner.js.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.js +9 -5
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js +7 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
- package/dist/scripts/run-test-files.js +13 -0
- package/dist/scripts/run-test-files.js.map +1 -1
- package/dist/scripts/smoke-packed-install.d.ts +3 -0
- package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
- package/dist/scripts/smoke-packed-install.js +99 -1
- package/dist/scripts/smoke-packed-install.js.map +1 -1
- package/dist/scripts/sync-plugin-mirror.js +2 -2
- package/dist/scripts/sync-plugin-mirror.js.map +1 -1
- package/dist/scripts/verify-native-agents.js +2 -2
- package/dist/scripts/verify-native-agents.js.map +1 -1
- package/dist/sidecar/__tests__/resource-leak-watch.test.d.ts +2 -0
- package/dist/sidecar/__tests__/resource-leak-watch.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/resource-leak-watch.test.js +38 -0
- package/dist/sidecar/__tests__/resource-leak-watch.test.js.map +1 -0
- package/dist/sidecar/index.d.ts +1 -1
- package/dist/sidecar/index.d.ts.map +1 -1
- package/dist/sidecar/index.js +29 -12
- package/dist/sidecar/index.js.map +1 -1
- package/dist/state/__tests__/operations-ralph-phase.test.js +88 -1
- package/dist/state/__tests__/operations-ralph-phase.test.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +6 -0
- package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +11 -0
- package/dist/state/operations.js.map +1 -1
- package/dist/state/workflow-transition.d.ts +1 -1
- package/dist/state/workflow-transition.d.ts.map +1 -1
- package/dist/state/workflow-transition.js +7 -0
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/subagents/tracker.d.ts.map +1 -1
- package/dist/subagents/tracker.js +4 -3
- package/dist/subagents/tracker.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +36 -44
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +163 -15
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +10 -20
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +51 -21
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/ultragoal/__tests__/artifacts.test.js +764 -10
- package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
- package/dist/ultragoal/__tests__/docs-contract.test.js +57 -1
- package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
- package/dist/ultragoal/__tests__/steering-fixtures.d.ts +68 -0
- package/dist/ultragoal/__tests__/steering-fixtures.d.ts.map +1 -0
- package/dist/ultragoal/__tests__/steering-fixtures.js +259 -0
- package/dist/ultragoal/__tests__/steering-fixtures.js.map +1 -0
- package/dist/ultragoal/__tests__/steering-fixtures.test.d.ts +2 -0
- package/dist/ultragoal/__tests__/steering-fixtures.test.d.ts.map +1 -0
- package/dist/ultragoal/__tests__/steering-fixtures.test.js +65 -0
- package/dist/ultragoal/__tests__/steering-fixtures.test.js.map +1 -0
- package/dist/ultragoal/artifacts.d.ts +97 -2
- package/dist/ultragoal/artifacts.d.ts.map +1 -1
- package/dist/ultragoal/artifacts.js +837 -256
- package/dist/ultragoal/artifacts.js.map +1 -1
- package/dist/utils/__tests__/sleep-resource.test.d.ts +2 -0
- package/dist/utils/__tests__/sleep-resource.test.d.ts.map +1 -0
- package/dist/utils/__tests__/sleep-resource.test.js +39 -0
- package/dist/utils/__tests__/sleep-resource.test.js.map +1 -0
- package/dist/utils/sleep.d.ts.map +1 -1
- package/dist/utils/sleep.js +17 -6
- package/dist/utils/sleep.js.map +1 -1
- package/package.json +2 -1
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +4 -3
- package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +56 -0
- package/plugins/oh-my-codex/hooks/hooks.json +77 -0
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +92 -50
- package/plugins/oh-my-codex/skills/autoresearch/SKILL.md +4 -0
- package/plugins/oh-my-codex/skills/autoresearch-goal/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/best-practice-research/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/cancel/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +8 -8
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/pipeline/SKILL.md +23 -12
- package/plugins/oh-my-codex/skills/plan/SKILL.md +8 -8
- package/plugins/oh-my-codex/skills/prometheus-strict/README.md +35 -0
- package/plugins/oh-my-codex/skills/prometheus-strict/SKILL.md +219 -0
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +7 -0
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +22 -7
- package/plugins/oh-my-codex/skills/team/SKILL.md +1 -1
- package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +38 -4
- package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +1 -1
- package/prompts/planner.md +1 -1
- package/prompts/prometheus-strict-metis.md +274 -0
- package/prompts/prometheus-strict-momus.md +82 -0
- package/prompts/prometheus-strict-oracle.md +107 -0
- package/prompts/researcher.md +22 -3
- package/skills/autopilot/SKILL.md +92 -50
- package/skills/autoresearch/SKILL.md +4 -0
- package/skills/autoresearch-goal/SKILL.md +1 -1
- package/skills/best-practice-research/SKILL.md +1 -1
- package/skills/cancel/SKILL.md +2 -2
- package/skills/deep-interview/SKILL.md +8 -8
- package/skills/omx-setup/SKILL.md +1 -1
- package/skills/pipeline/SKILL.md +23 -12
- package/skills/plan/SKILL.md +8 -8
- package/skills/prometheus-strict/README.md +35 -0
- package/skills/prometheus-strict/SKILL.md +219 -0
- package/skills/ralph/SKILL.md +7 -0
- package/skills/ralplan/SKILL.md +22 -7
- package/skills/team/SKILL.md +1 -1
- package/skills/ultragoal/SKILL.md +38 -4
- package/skills/ultrawork/SKILL.md +1 -1
- package/src/scripts/__tests__/codex-native-hook.test.ts +1757 -210
- package/src/scripts/__tests__/docs-site-contract.test.ts +47 -0
- package/src/scripts/__tests__/notify-dispatcher.test.ts +132 -3
- package/src/scripts/__tests__/run-test-files.test.ts +67 -0
- package/src/scripts/__tests__/smoke-packed-install.test.ts +31 -0
- package/src/scripts/__tests__/verify-native-agents.test.ts +23 -3
- package/src/scripts/cleanup-explore-harness.ts +1 -0
- package/src/scripts/codex-native-hook.ts +393 -40
- package/src/scripts/codex-native-pre-post.ts +16 -1
- package/src/scripts/notify-dispatcher.ts +202 -4
- package/src/scripts/notify-hook/process-runner.ts +40 -16
- package/src/scripts/notify-hook/team-dispatch.ts +9 -5
- package/src/scripts/notify-hook/team-tmux-guard.ts +7 -0
- package/src/scripts/run-test-files.ts +13 -0
- package/src/scripts/smoke-packed-install.ts +105 -0
- package/src/scripts/sync-plugin-mirror.ts +3 -3
- package/src/scripts/verify-native-agents.ts +2 -2
- package/templates/catalog-manifest.json +22 -0
package/dist/cli/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { basename, dirname, join, posix, win32 } from "path";
|
|
|
7
7
|
import { existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "fs";
|
|
8
8
|
import { copyFile, cp, lstat, mkdir, readFile, readdir, rm, symlink, writeFile } from "fs/promises";
|
|
9
9
|
import { constants as osConstants, homedir } from "os";
|
|
10
|
+
import { createHash } from "crypto";
|
|
10
11
|
import { setup, SETUP_MCP_MODES, SETUP_SCOPES, } from "./setup.js";
|
|
11
12
|
import { uninstall } from "./uninstall.js";
|
|
12
13
|
import { version } from "./version.js";
|
|
@@ -48,11 +49,11 @@ import { readSessionState, writeSessionStart, writeSessionEnd, resetSessionMetri
|
|
|
48
49
|
import { buildClientAttachedReconcileHookName, buildReconcileHudResizeArgs, buildRegisterClientAttachedReconcileArgs, buildRegisterResizeHookArgs, buildResizeHookName, buildResizeHookTarget, buildScheduleDelayedHudResizeArgs, buildUnregisterClientAttachedReconcileArgs, buildUnregisterResizeHookArgs, enableMouseScrolling, isMsysOrGitBash, isNativeWindows, isTmuxAvailable, mitigateCopyModeUnderlineArtifacts, } from "../team/tmux-session.js";
|
|
49
50
|
import { getPackageRoot } from "../utils/package.js";
|
|
50
51
|
import { codexConfigPath, omxRoot, rememberOmxLaunchContext, resolveOmxEntryPath } from "../utils/paths.js";
|
|
51
|
-
import { cleanCodexModelAvailabilityNuxIfNeeded, extractSharedMcpRegistryServersFromConfig, repairConfigIfNeeded,
|
|
52
|
+
import { cleanCodexModelAvailabilityNuxIfNeeded, extractSharedMcpRegistryServersFromConfig, repairConfigIfNeeded, syncProjectScopeTrustStateFromRuntime } from "../config/generator.js";
|
|
52
53
|
import { OMX_FIRST_PARTY_MCP_SERVER_NAMES } from "../config/omx-first-party-mcp.js";
|
|
53
54
|
import { HUD_TMUX_HEIGHT_LINES } from "../hud/constants.js";
|
|
54
55
|
import { OMX_TMUX_HUD_OWNER_ENV } from "../hud/reconcile.js";
|
|
55
|
-
import { createHudWatchPane as createSharedHudWatchPane, killTmuxPane as killSharedTmuxPane, listCurrentWindowHudPaneIds, parsePaneIdFromTmuxOutput, registerHudResizeHook, } from "../hud/tmux.js";
|
|
56
|
+
import { createHudWatchPane as createSharedHudWatchPane, killTmuxPane as killSharedTmuxPane, listCurrentWindowHudPaneIds, OMX_TMUX_HUD_LEADER_PANE_ENV, parsePaneIdFromTmuxOutput, registerHudResizeHook, } from "../hud/tmux.js";
|
|
56
57
|
export { parseTmuxPaneSnapshot, isHudWatchPane, findHudWatchPaneIds } from "../hud/tmux.js";
|
|
57
58
|
rememberOmxLaunchContext();
|
|
58
59
|
import { classifySpawnError, resolveTmuxBinaryForPlatform, spawnPlatformCommandSync, } from "../utils/platform-command.js";
|
|
@@ -478,6 +479,32 @@ async function linkOrCopyCodexHomeEntry(source, destination) {
|
|
|
478
479
|
function isCodexSqliteArtifact(entryName) {
|
|
479
480
|
return /^(?:state|logs)_\d+\.sqlite(?:-(?:shm|wal))?$/.test(entryName);
|
|
480
481
|
}
|
|
482
|
+
const PROJECT_LAUNCH_PERSISTED_RUNTIME_ENTRY_NAMES = new Set([
|
|
483
|
+
// Codex CLI writes browser/OTP login state here when CODEX_HOME points at
|
|
484
|
+
// the per-session mirror. Persist only the opaque file itself; never parse or
|
|
485
|
+
// log the contents.
|
|
486
|
+
"auth.json",
|
|
487
|
+
]);
|
|
488
|
+
// Mirroring these files into the runtime CODEX_HOME would cause Codex to load
|
|
489
|
+
// them as user-scope config alongside the canonical project-scope copies under
|
|
490
|
+
// <cwd>/.codex, duplicating every native hook and asking the user to re-trust
|
|
491
|
+
// hooks on every launch. See GH issue #2470.
|
|
492
|
+
const PROJECT_LAUNCH_RUNTIME_SKIPPED_ENTRY_NAMES = new Set(["hooks.json"]);
|
|
493
|
+
function shouldPersistProjectLaunchRuntimeEntry(entryName) {
|
|
494
|
+
return PROJECT_LAUNCH_PERSISTED_RUNTIME_ENTRY_NAMES.has(entryName);
|
|
495
|
+
}
|
|
496
|
+
export async function persistProjectLaunchRuntimeAuthState(runtimeCodexHome, projectCodexHome) {
|
|
497
|
+
if (!runtimeCodexHome || !projectCodexHome)
|
|
498
|
+
return;
|
|
499
|
+
if (!existsSync(runtimeCodexHome))
|
|
500
|
+
return;
|
|
501
|
+
await mkdir(projectCodexHome, { recursive: true });
|
|
502
|
+
for (const entry of await readdir(runtimeCodexHome, { withFileTypes: true })) {
|
|
503
|
+
if (!shouldPersistProjectLaunchRuntimeEntry(entry.name) || !entry.isFile())
|
|
504
|
+
continue;
|
|
505
|
+
await copyFile(join(runtimeCodexHome, entry.name), join(projectCodexHome, entry.name));
|
|
506
|
+
}
|
|
507
|
+
}
|
|
481
508
|
/**
|
|
482
509
|
* Project-scope setup keeps durable Codex config under <repo>/.codex, but the
|
|
483
510
|
* Codex TUI also stores model-availability NUX counters in CODEX_HOME/config.toml.
|
|
@@ -493,22 +520,16 @@ export async function prepareRuntimeCodexHomeForProjectLaunch(cwd, sessionId, pr
|
|
|
493
520
|
for (const entry of await readdir(projectCodexHome, { withFileTypes: true })) {
|
|
494
521
|
if (isCodexSqliteArtifact(entry.name))
|
|
495
522
|
continue;
|
|
523
|
+
if (PROJECT_LAUNCH_RUNTIME_SKIPPED_ENTRY_NAMES.has(entry.name))
|
|
524
|
+
continue;
|
|
496
525
|
const source = join(projectCodexHome, entry.name);
|
|
497
526
|
const destination = join(runtimeCodexHome, entry.name);
|
|
498
|
-
if (entry.name === "config.toml"
|
|
527
|
+
if (entry.name === "config.toml") {
|
|
499
528
|
await copyFile(source, destination);
|
|
500
529
|
continue;
|
|
501
530
|
}
|
|
502
531
|
await linkOrCopyCodexHomeEntry(source, destination);
|
|
503
532
|
}
|
|
504
|
-
const runtimeConfigPath = join(runtimeCodexHome, "config.toml");
|
|
505
|
-
const runtimeHooksPath = join(runtimeCodexHome, "hooks.json");
|
|
506
|
-
if (existsSync(runtimeConfigPath) && existsSync(runtimeHooksPath)) {
|
|
507
|
-
const runtimeConfig = await readFile(runtimeConfigPath, "utf-8");
|
|
508
|
-
if (runtimeConfig.includes("# OMX-owned Codex hook trust state")) {
|
|
509
|
-
await writeFile(runtimeConfigPath, upsertManagedCodexHookTrustState(runtimeConfig, getPackageRoot(), runtimeHooksPath), "utf-8");
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
533
|
return runtimeCodexHome;
|
|
513
534
|
}
|
|
514
535
|
function resolveProjectSqliteHomeForLaunch(projectCodexHome, env) {
|
|
@@ -533,9 +554,29 @@ export async function prepareCodexHomeForLaunch(cwd, sessionId, env = process.en
|
|
|
533
554
|
projectLocalCodexHomeForCleanup,
|
|
534
555
|
};
|
|
535
556
|
}
|
|
536
|
-
async function
|
|
557
|
+
export async function persistProjectLaunchRuntimeProjectTrustState(runtimeCodexHome, projectCodexHome) {
|
|
558
|
+
if (!runtimeCodexHome || !projectCodexHome)
|
|
559
|
+
return;
|
|
560
|
+
const runtimeConfigPath = join(runtimeCodexHome, "config.toml");
|
|
561
|
+
if (!existsSync(runtimeConfigPath))
|
|
562
|
+
return;
|
|
563
|
+
const projectConfigPath = join(projectCodexHome, "config.toml");
|
|
564
|
+
const runtimeConfig = await readFile(runtimeConfigPath, "utf-8");
|
|
565
|
+
const projectConfig = existsSync(projectConfigPath)
|
|
566
|
+
? await readFile(projectConfigPath, "utf-8")
|
|
567
|
+
: "";
|
|
568
|
+
const projectHooksPath = join(projectCodexHome, "hooks.json");
|
|
569
|
+
const nextProjectConfig = syncProjectScopeTrustStateFromRuntime(projectConfig, runtimeConfig, projectHooksPath);
|
|
570
|
+
if (nextProjectConfig !== projectConfig) {
|
|
571
|
+
await mkdir(projectCodexHome, { recursive: true });
|
|
572
|
+
await writeFile(projectConfigPath, nextProjectConfig, "utf-8");
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
async function cleanupRuntimeCodexHome(runtimeCodexHomeForCleanup, projectCodexHomeForPersistence) {
|
|
537
576
|
if (!runtimeCodexHomeForCleanup)
|
|
538
577
|
return;
|
|
578
|
+
await persistProjectLaunchRuntimeAuthState(runtimeCodexHomeForCleanup, projectCodexHomeForPersistence);
|
|
579
|
+
await persistProjectLaunchRuntimeProjectTrustState(runtimeCodexHomeForCleanup, projectCodexHomeForPersistence);
|
|
539
580
|
await rm(runtimeCodexHomeForCleanup, { recursive: true, force: true });
|
|
540
581
|
}
|
|
541
582
|
function execTmuxFileSync(args, options) {
|
|
@@ -800,22 +841,262 @@ export function shouldAutoIsolateMadmaxLaunch(command, launchArgs, env = process
|
|
|
800
841
|
function sanitizeRunIdSegment(value) {
|
|
801
842
|
return value.replace(/[^a-zA-Z0-9._-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
802
843
|
}
|
|
844
|
+
const MADMAX_DETACHED_ACTIVE_DIR = "active-detached";
|
|
845
|
+
const MADMAX_DETACHED_LOCK_STALE_MS = 30_000;
|
|
846
|
+
const MADMAX_DETACHED_LOCK_RETRY_MS = 50;
|
|
847
|
+
const MADMAX_DETACHED_LOCK_MAX_ATTEMPTS = 100;
|
|
848
|
+
const OMX_MADMAX_DETACHED_CONTEXT_ENV = "OMX_MADMAX_DETACHED_CONTEXT";
|
|
849
|
+
function resolveMadmaxRunsRoot(env = process.env) {
|
|
850
|
+
return env.OMX_RUNS_DIR || join(homedir(), ".omx-runs");
|
|
851
|
+
}
|
|
852
|
+
function canonicalizeLaunchCwd(cwd) {
|
|
853
|
+
try {
|
|
854
|
+
return execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
855
|
+
cwd,
|
|
856
|
+
encoding: "utf-8",
|
|
857
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
858
|
+
}).trim() || cwd;
|
|
859
|
+
}
|
|
860
|
+
catch {
|
|
861
|
+
return cwd;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
function normalizeMadmaxDetachedLaunchArgv(argv) {
|
|
865
|
+
const passthrough = [];
|
|
866
|
+
const semanticFlags = new Set();
|
|
867
|
+
let reasoningFlag = null;
|
|
868
|
+
let afterEndOfOptions = false;
|
|
869
|
+
for (const arg of argv) {
|
|
870
|
+
if (afterEndOfOptions) {
|
|
871
|
+
passthrough.push(arg);
|
|
872
|
+
continue;
|
|
873
|
+
}
|
|
874
|
+
if (arg === "--") {
|
|
875
|
+
afterEndOfOptions = true;
|
|
876
|
+
passthrough.push(arg);
|
|
877
|
+
continue;
|
|
878
|
+
}
|
|
879
|
+
if (arg === "--tmux" || arg === "--direct") {
|
|
880
|
+
continue;
|
|
881
|
+
}
|
|
882
|
+
if (arg === MADMAX_FLAG ||
|
|
883
|
+
arg === MADMAX_SPARK_FLAG) {
|
|
884
|
+
semanticFlags.add(arg);
|
|
885
|
+
continue;
|
|
886
|
+
}
|
|
887
|
+
if (arg === HIGH_REASONING_FLAG || arg === XHIGH_REASONING_FLAG) {
|
|
888
|
+
reasoningFlag = arg;
|
|
889
|
+
continue;
|
|
890
|
+
}
|
|
891
|
+
passthrough.push(arg);
|
|
892
|
+
}
|
|
893
|
+
return [
|
|
894
|
+
...Array.from(semanticFlags).sort(),
|
|
895
|
+
...(reasoningFlag ? [reasoningFlag] : []),
|
|
896
|
+
...passthrough,
|
|
897
|
+
];
|
|
898
|
+
}
|
|
899
|
+
export function buildMadmaxDetachedLaunchContextKey(sourceCwd, argv, runIdentity = "") {
|
|
900
|
+
// The boxed run root is part of the lock identity for auto-isolated madmax
|
|
901
|
+
// launches. That lets independent `omx --madmax --high` sessions share the
|
|
902
|
+
// same source cwd/argv without contending on one active-detached lock, while
|
|
903
|
+
// callers that intentionally reuse the same boxed context keep one key.
|
|
904
|
+
const payload = JSON.stringify({
|
|
905
|
+
source_cwd: canonicalizeLaunchCwd(sourceCwd),
|
|
906
|
+
argv: normalizeMadmaxDetachedLaunchArgv(argv),
|
|
907
|
+
run_identity: runIdentity,
|
|
908
|
+
});
|
|
909
|
+
return createHash("sha256").update(payload).digest("hex").slice(0, 32);
|
|
910
|
+
}
|
|
911
|
+
function madmaxDetachedActiveRecordPath(runsRoot, contextKey) {
|
|
912
|
+
return join(runsRoot, MADMAX_DETACHED_ACTIVE_DIR, `${contextKey}.json`);
|
|
913
|
+
}
|
|
914
|
+
function readMadmaxDetachedActiveRecord(recordPath) {
|
|
915
|
+
if (!existsSync(recordPath))
|
|
916
|
+
return null;
|
|
917
|
+
try {
|
|
918
|
+
const parsed = JSON.parse(readFileSync(recordPath, "utf-8"));
|
|
919
|
+
if (parsed.version !== 1 ||
|
|
920
|
+
typeof parsed.context_key !== "string" ||
|
|
921
|
+
typeof parsed.source_cwd !== "string" ||
|
|
922
|
+
typeof parsed.run_dir !== "string" ||
|
|
923
|
+
typeof parsed.tmux_session_name !== "string" ||
|
|
924
|
+
!Array.isArray(parsed.argv) ||
|
|
925
|
+
!parsed.argv.every((arg) => typeof arg === "string")) {
|
|
926
|
+
return null;
|
|
927
|
+
}
|
|
928
|
+
return {
|
|
929
|
+
version: 1,
|
|
930
|
+
context_key: parsed.context_key,
|
|
931
|
+
created_at: typeof parsed.created_at === "string" ? parsed.created_at : "",
|
|
932
|
+
source_cwd: parsed.source_cwd,
|
|
933
|
+
argv: [...parsed.argv],
|
|
934
|
+
run_dir: parsed.run_dir,
|
|
935
|
+
tmux_session_name: parsed.tmux_session_name,
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
catch {
|
|
939
|
+
return null;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
function detachedTmuxSessionExists(sessionName) {
|
|
943
|
+
try {
|
|
944
|
+
execTmuxFileSync(["has-session", "-t", sessionName], { stdio: "ignore" });
|
|
945
|
+
return true;
|
|
946
|
+
}
|
|
947
|
+
catch {
|
|
948
|
+
return false;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
function readMadmaxDetachedLockOwner(lockPath) {
|
|
952
|
+
try {
|
|
953
|
+
const parsed = JSON.parse(readFileSync(join(lockPath, "owner.json"), "utf-8"));
|
|
954
|
+
if (parsed.version !== 1 ||
|
|
955
|
+
typeof parsed.pid !== "number" ||
|
|
956
|
+
!Number.isSafeInteger(parsed.pid) ||
|
|
957
|
+
parsed.pid <= 0 ||
|
|
958
|
+
typeof parsed.context_key !== "string" ||
|
|
959
|
+
typeof parsed.acquired_at !== "string") {
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
return {
|
|
963
|
+
version: 1,
|
|
964
|
+
pid: parsed.pid,
|
|
965
|
+
context_key: parsed.context_key,
|
|
966
|
+
acquired_at: parsed.acquired_at,
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
catch {
|
|
970
|
+
return null;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
function readMadmaxDetachedLockPid(lockPath) {
|
|
974
|
+
const owner = readMadmaxDetachedLockOwner(lockPath);
|
|
975
|
+
if (owner)
|
|
976
|
+
return owner.pid;
|
|
977
|
+
try {
|
|
978
|
+
const holderPid = Number.parseInt(readFileSync(join(lockPath, "pid"), "utf-8").trim(), 10);
|
|
979
|
+
return Number.isSafeInteger(holderPid) && holderPid > 0 ? holderPid : null;
|
|
980
|
+
}
|
|
981
|
+
catch {
|
|
982
|
+
return null;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
function inspectMadmaxDetachedContextLock(lockPath) {
|
|
986
|
+
const lockStat = statSync(lockPath, { throwIfNoEntry: false });
|
|
987
|
+
if (!lockStat) {
|
|
988
|
+
return { stale: false, diagnostic: "lock disappeared while waiting" };
|
|
989
|
+
}
|
|
990
|
+
const ageMs = Math.max(0, Date.now() - lockStat.mtimeMs);
|
|
991
|
+
const owner = readMadmaxDetachedLockOwner(lockPath);
|
|
992
|
+
const holderPid = owner?.pid ?? readMadmaxDetachedLockPid(lockPath);
|
|
993
|
+
if (holderPid) {
|
|
994
|
+
if (!isProcessAlive(holderPid)) {
|
|
995
|
+
return {
|
|
996
|
+
stale: true,
|
|
997
|
+
diagnostic: `stale holder pid ${holderPid} is not running; lock age ${Math.round(ageMs)}ms`,
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
const ownerContext = owner ? `, owner context ${owner.context_key}` : ", legacy pid-only lock";
|
|
1001
|
+
const sameDirectoryGuidance = "Another madmax detached launch is active for this directory; close the existing madmax session or use --worktree for concurrent work. Multiple madmax sessions in one directory are unsafe";
|
|
1002
|
+
return {
|
|
1003
|
+
stale: false,
|
|
1004
|
+
diagnostic: `holder pid ${holderPid} is still running${ownerContext}; lock age ${Math.round(ageMs)}ms. ${sameDirectoryGuidance}`,
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
if (ageMs > MADMAX_DETACHED_LOCK_STALE_MS) {
|
|
1008
|
+
return {
|
|
1009
|
+
stale: true,
|
|
1010
|
+
diagnostic: `legacy lock has no readable owner pid and is older than ${MADMAX_DETACHED_LOCK_STALE_MS}ms; lock age ${Math.round(ageMs)}ms`,
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
return {
|
|
1014
|
+
stale: false,
|
|
1015
|
+
diagnostic: `lock has no readable owner pid yet; lock age ${Math.round(ageMs)}ms`,
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
export function withMadmaxDetachedContextLock(runsRoot, contextKey, run, options = {}) {
|
|
1019
|
+
const lockPath = join(runsRoot, MADMAX_DETACHED_ACTIVE_DIR, `${contextKey}.lock`);
|
|
1020
|
+
const maxAttempts = options.maxAttempts ?? MADMAX_DETACHED_LOCK_MAX_ATTEMPTS;
|
|
1021
|
+
const retryMs = options.retryMs ?? MADMAX_DETACHED_LOCK_RETRY_MS;
|
|
1022
|
+
let lastDiagnostic = "lock was busy";
|
|
1023
|
+
mkdirSync(dirname(lockPath), { recursive: true });
|
|
1024
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
1025
|
+
try {
|
|
1026
|
+
mkdirSync(lockPath);
|
|
1027
|
+
try {
|
|
1028
|
+
const owner = {
|
|
1029
|
+
version: 1,
|
|
1030
|
+
pid: process.pid,
|
|
1031
|
+
context_key: contextKey,
|
|
1032
|
+
acquired_at: new Date().toISOString(),
|
|
1033
|
+
};
|
|
1034
|
+
writeFileSync(join(lockPath, "owner.json"), `${JSON.stringify(owner, null, 2)}\n`, { mode: 0o600 });
|
|
1035
|
+
writeFileSync(join(lockPath, "pid"), String(process.pid));
|
|
1036
|
+
return run();
|
|
1037
|
+
}
|
|
1038
|
+
finally {
|
|
1039
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
catch (err) {
|
|
1043
|
+
const code = err && typeof err === "object" && "code" in err
|
|
1044
|
+
? String(err.code)
|
|
1045
|
+
: "";
|
|
1046
|
+
if (code !== "EEXIST")
|
|
1047
|
+
throw err;
|
|
1048
|
+
const inspection = inspectMadmaxDetachedContextLock(lockPath);
|
|
1049
|
+
lastDiagnostic = inspection.diagnostic;
|
|
1050
|
+
if (inspection.stale) {
|
|
1051
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
1052
|
+
continue;
|
|
1053
|
+
}
|
|
1054
|
+
blockMs(retryMs);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
throw new MadmaxDetachedGuardError(`timed out waiting for madmax detached launch context lock: ${lockPath} (${lastDiagnostic})`);
|
|
1058
|
+
}
|
|
1059
|
+
function isMadmaxDetachedGuardEnabled(env) {
|
|
1060
|
+
return env.OMXBOX_ACTIVE === "1" && typeof env[OMX_MADMAX_DETACHED_CONTEXT_ENV] === "string";
|
|
1061
|
+
}
|
|
1062
|
+
function cleanupCurrentMadmaxReuseRunRoot(env, runsRoot) {
|
|
1063
|
+
const runRoot = env.OMX_ROOT;
|
|
1064
|
+
if (!runRoot || !env.OMXBOX_ACTIVE)
|
|
1065
|
+
return;
|
|
1066
|
+
const normalizedRunsRoot = runsRoot.endsWith("/") ? runsRoot : `${runsRoot}/`;
|
|
1067
|
+
if (runRoot !== runsRoot && !runRoot.startsWith(normalizedRunsRoot))
|
|
1068
|
+
return;
|
|
1069
|
+
rmSync(runRoot, { recursive: true, force: true });
|
|
1070
|
+
}
|
|
1071
|
+
function writeMadmaxDetachedActiveRecord(recordPath, record) {
|
|
1072
|
+
mkdirSync(dirname(recordPath), { recursive: true });
|
|
1073
|
+
writeFileSync(recordPath, `${JSON.stringify(record, null, 2)}\n`, { mode: 0o600 });
|
|
1074
|
+
}
|
|
1075
|
+
class MadmaxDetachedReuseError extends Error {
|
|
1076
|
+
failClosed = true;
|
|
1077
|
+
}
|
|
1078
|
+
class MadmaxDetachedGuardError extends Error {
|
|
1079
|
+
failClosed = true;
|
|
1080
|
+
}
|
|
803
1081
|
export function createMadmaxIsolatedRoot(sourceCwd, argv, env = process.env) {
|
|
804
|
-
const runsRoot = env
|
|
1082
|
+
const runsRoot = resolveMadmaxRunsRoot(env);
|
|
805
1083
|
mkdirSync(runsRoot, { recursive: true });
|
|
806
1084
|
const stamp = new Date().toISOString().replace(/[-:TZ.]/g, "").slice(0, 14);
|
|
807
1085
|
const suffix = Math.random().toString(16).slice(2, 6);
|
|
808
1086
|
const runDir = join(runsRoot, sanitizeRunIdSegment(`run-${stamp}-${suffix}`));
|
|
809
1087
|
mkdirSync(runDir, { recursive: false });
|
|
1088
|
+
const detachedLaunchContext = buildMadmaxDetachedLaunchContextKey(sourceCwd, argv, runDir);
|
|
810
1089
|
const metadata = {
|
|
811
1090
|
launcher: "omx --madmax",
|
|
812
1091
|
created_at: new Date().toISOString(),
|
|
813
1092
|
cwd: runDir,
|
|
814
1093
|
source_cwd: sourceCwd,
|
|
815
1094
|
argv,
|
|
1095
|
+
detached_launch_context: detachedLaunchContext,
|
|
816
1096
|
};
|
|
817
1097
|
writeFileSync(join(runDir, ".omxbox-run.json"), `${JSON.stringify(metadata, null, 2)}\n`);
|
|
818
1098
|
writeFileSync(join(runsRoot, "registry.jsonl"), `${JSON.stringify(metadata)}\n`, { flag: "a" });
|
|
1099
|
+
env[OMX_MADMAX_DETACHED_CONTEXT_ENV] = detachedLaunchContext;
|
|
819
1100
|
return runDir;
|
|
820
1101
|
}
|
|
821
1102
|
function activateMadmaxIsolationIfNeeded(command, launchArgs, cwd, env = process.env) {
|
|
@@ -1028,6 +1309,11 @@ export async function main(args) {
|
|
|
1028
1309
|
case "reasoning":
|
|
1029
1310
|
await reasoningCommand(args.slice(1));
|
|
1030
1311
|
break;
|
|
1312
|
+
case "codex-native-hook": {
|
|
1313
|
+
const { runCodexNativeHookCli } = await import("../scripts/codex-native-hook.js");
|
|
1314
|
+
await runCodexNativeHookCli();
|
|
1315
|
+
break;
|
|
1316
|
+
}
|
|
1031
1317
|
case "help":
|
|
1032
1318
|
case "--help":
|
|
1033
1319
|
case "-h":
|
|
@@ -1227,7 +1513,7 @@ export async function launchWithHud(args) {
|
|
|
1227
1513
|
// ── Phase 3: postLaunch ─────────────────────────────────────────────
|
|
1228
1514
|
if (!postLaunchHandledExternally) {
|
|
1229
1515
|
await postLaunch(cwd, sessionId, codexHomeOverride, enableNotifyFallbackAuthority, projectLocalCodexHomeForCleanup);
|
|
1230
|
-
await cleanupRuntimeCodexHome(preparedCodexHome.runtimeCodexHomeForCleanup).catch(logCliOperationFailure);
|
|
1516
|
+
await cleanupRuntimeCodexHome(preparedCodexHome.runtimeCodexHomeForCleanup, projectLocalCodexHomeForCleanup).catch(logCliOperationFailure);
|
|
1231
1517
|
}
|
|
1232
1518
|
}
|
|
1233
1519
|
}
|
|
@@ -1319,7 +1605,7 @@ export async function execWithOverlay(args) {
|
|
|
1319
1605
|
}
|
|
1320
1606
|
finally {
|
|
1321
1607
|
await postLaunch(cwd, sessionId, codexHomeOverride, true, projectLocalCodexHomeForCleanup);
|
|
1322
|
-
await cleanupRuntimeCodexHome(preparedCodexHome.runtimeCodexHomeForCleanup).catch(logCliOperationFailure);
|
|
1608
|
+
await cleanupRuntimeCodexHome(preparedCodexHome.runtimeCodexHomeForCleanup, projectLocalCodexHomeForCleanup).catch(logCliOperationFailure);
|
|
1323
1609
|
}
|
|
1324
1610
|
}
|
|
1325
1611
|
export function normalizeCodexLaunchArgs(args) {
|
|
@@ -2649,12 +2935,19 @@ function runCodex(cwd, args, sessionId, workerDefaultModel, codexHomeOverride, s
|
|
|
2649
2935
|
if (!omxBin) {
|
|
2650
2936
|
throw new Error("Unable to resolve OMX launcher path for tmux HUD bootstrap");
|
|
2651
2937
|
}
|
|
2938
|
+
const omxRootOverride = resolveOmxRootForLaunch(cwd, process.env);
|
|
2939
|
+
const currentPaneId = process.env.TMUX_PANE;
|
|
2940
|
+
const hudEnvArgs = [
|
|
2941
|
+
`OMX_SESSION_ID=${sessionId}`,
|
|
2942
|
+
`${OMX_TMUX_HUD_OWNER_ENV}=1`,
|
|
2943
|
+
...(currentPaneId ? [`${OMX_TMUX_HUD_LEADER_PANE_ENV}=${currentPaneId}`] : []),
|
|
2944
|
+
...(omxRootOverride ? [`OMX_ROOT=${omxRootOverride}`] : []),
|
|
2945
|
+
];
|
|
2652
2946
|
const hudCmd = nativeWindows
|
|
2653
2947
|
? buildWindowsPromptCommand("node", [omxBin, "hud", "--watch"])
|
|
2654
|
-
: buildTmuxPaneCommand("env", [
|
|
2948
|
+
: buildTmuxPaneCommand("env", [...hudEnvArgs, "node", omxBin, "hud", "--watch"]);
|
|
2655
2949
|
const inheritLeaderFlags = process.env[TEAM_INHERIT_LEADER_FLAGS_ENV] !== "0";
|
|
2656
2950
|
const workerLaunchArgs = resolveTeamWorkerLaunchArgsEnv(process.env[TEAM_WORKER_LAUNCH_ARGS_ENV], launchArgs, inheritLeaderFlags, workerDefaultModel);
|
|
2657
|
-
const omxRootOverride = resolveOmxRootForLaunch(cwd, process.env);
|
|
2658
2951
|
const codexBaseEnv = {
|
|
2659
2952
|
...process.env,
|
|
2660
2953
|
...(codexHomeOverride ? { CODEX_HOME: codexHomeOverride } : {}),
|
|
@@ -2679,14 +2972,16 @@ function runCodex(cwd, args, sessionId, workerDefaultModel, codexHomeOverride, s
|
|
|
2679
2972
|
}
|
|
2680
2973
|
if (launchPolicy === "inside-tmux") {
|
|
2681
2974
|
// Already in tmux: launch codex in current pane, HUD in bottom split
|
|
2682
|
-
const
|
|
2683
|
-
const staleHudPaneIds = listHudWatchPaneIdsInCurrentWindow(currentPaneId);
|
|
2975
|
+
const staleHudPaneIds = listHudWatchPaneIdsInCurrentWindow(currentPaneId, { sessionId, leaderPaneId: currentPaneId });
|
|
2684
2976
|
for (const paneId of staleHudPaneIds) {
|
|
2685
2977
|
killTmuxPane(paneId);
|
|
2686
2978
|
}
|
|
2687
2979
|
let hudPaneId = null;
|
|
2688
2980
|
try {
|
|
2689
|
-
hudPaneId = createHudWatchPane(cwd, hudCmd
|
|
2981
|
+
hudPaneId = createHudWatchPane(cwd, hudCmd, {
|
|
2982
|
+
heightLines: HUD_TMUX_HEIGHT_LINES,
|
|
2983
|
+
targetPaneId: currentPaneId,
|
|
2984
|
+
});
|
|
2690
2985
|
if (hudPaneId && currentPaneId) {
|
|
2691
2986
|
registerHudResizeHook(hudPaneId, currentPaneId, HUD_TMUX_HEIGHT_LINES);
|
|
2692
2987
|
}
|
|
@@ -2750,126 +3045,186 @@ function runCodex(cwd, args, sessionId, workerDefaultModel, codexHomeOverride, s
|
|
|
2750
3045
|
? buildWindowsPromptCommand("codex", launchArgs)
|
|
2751
3046
|
: null;
|
|
2752
3047
|
const sessionName = buildDetachedTmuxSessionName(cwd, sessionId);
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
3048
|
+
const launchDetachedSession = () => {
|
|
3049
|
+
const contextKey = process.env[OMX_MADMAX_DETACHED_CONTEXT_ENV]?.trim();
|
|
3050
|
+
const runsRoot = resolveMadmaxRunsRoot(process.env);
|
|
3051
|
+
const activeRecordPath = contextKey
|
|
3052
|
+
? madmaxDetachedActiveRecordPath(runsRoot, contextKey)
|
|
3053
|
+
: null;
|
|
3054
|
+
const activeRecord = activeRecordPath
|
|
3055
|
+
? readMadmaxDetachedActiveRecord(activeRecordPath)
|
|
3056
|
+
: null;
|
|
3057
|
+
if (activeRecord &&
|
|
3058
|
+
activeRecord.context_key === contextKey &&
|
|
3059
|
+
detachedTmuxSessionExists(activeRecord.tmux_session_name)) {
|
|
3060
|
+
cleanupCurrentMadmaxReuseRunRoot(process.env, runsRoot);
|
|
3061
|
+
process.stderr.write(`[omx] madmax detached launch already active for this context; attaching ${activeRecord.tmux_session_name} instead of starting a duplicate.\n`);
|
|
3062
|
+
try {
|
|
3063
|
+
execTmuxFileSync(["attach-session", "-t", activeRecord.tmux_session_name], {
|
|
3064
|
+
stdio: "inherit",
|
|
3065
|
+
});
|
|
3066
|
+
}
|
|
3067
|
+
catch (err) {
|
|
3068
|
+
logCliOperationFailure(err);
|
|
3069
|
+
throw new MadmaxDetachedReuseError(`refusing duplicate madmax detached launch: existing session ${activeRecord.tmux_session_name} is active but attach failed`);
|
|
3070
|
+
}
|
|
3071
|
+
return { postLaunchHandledExternally: true };
|
|
2771
3072
|
}
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
3073
|
+
if (activeRecordPath && activeRecord) {
|
|
3074
|
+
rmSync(activeRecordPath, { force: true });
|
|
3075
|
+
}
|
|
3076
|
+
void writeSessionStart(cwd, sessionId, { tmuxSessionName: sessionName }).catch((err) => {
|
|
3077
|
+
logCliOperationFailure(err);
|
|
3078
|
+
// Non-fatal: managed tmux recovery can still use compatibility fallback.
|
|
3079
|
+
});
|
|
3080
|
+
let createdDetachedSession = false;
|
|
3081
|
+
let registeredHookTarget = null;
|
|
3082
|
+
let registeredHookName = null;
|
|
3083
|
+
let registeredClientAttachedHookName = null;
|
|
3084
|
+
let detachedParentEnvFilePath;
|
|
3085
|
+
try {
|
|
3086
|
+
// This path is the user-shell interactive launch: OMX creates a tmux
|
|
3087
|
+
// session and immediately attaches the user's terminal to it. If a tmux
|
|
3088
|
+
// server already exists, `new-session -e` only forwards explicit values,
|
|
3089
|
+
// so provider-specific parent-shell keys would disappear. Source a
|
|
3090
|
+
// private env file inside the leader shell instead of putting every
|
|
3091
|
+
// parent env value on the tmux command line or in logs.
|
|
3092
|
+
if (!nativeWindows) {
|
|
3093
|
+
detachedParentEnvFilePath = writeDetachedSessionParentEnvFile(cwd, sessionId, codexEnvWithNotify);
|
|
2781
3094
|
}
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
const
|
|
2785
|
-
|
|
2786
|
-
:
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
3095
|
+
const bootstrapSteps = buildDetachedSessionBootstrapSteps(sessionName, cwd, codexCmd, hudCmd, workerLaunchArgs, codexHomeOverride, notifyTempContractRaw, nativeWindows, sessionId, projectLocalCodexHomeForCleanup, runtimeCodexHomeForCleanup, omxRootOverride, process.env, sqliteHomeOverride, detachedParentEnvFilePath);
|
|
3096
|
+
for (const step of bootstrapSteps) {
|
|
3097
|
+
const output = execTmuxFileSync(step.args, {
|
|
3098
|
+
stdio: "pipe",
|
|
3099
|
+
encoding: "utf-8",
|
|
3100
|
+
});
|
|
3101
|
+
if (step.name === "new-session") {
|
|
3102
|
+
createdDetachedSession = true;
|
|
3103
|
+
if (activeRecordPath && contextKey) {
|
|
3104
|
+
writeMadmaxDetachedActiveRecord(activeRecordPath, {
|
|
3105
|
+
version: 1,
|
|
3106
|
+
context_key: contextKey,
|
|
3107
|
+
created_at: new Date().toISOString(),
|
|
3108
|
+
source_cwd: process.env.OMX_SOURCE_CWD || cwd,
|
|
3109
|
+
argv: args,
|
|
3110
|
+
run_dir: process.env.OMX_ROOT || cwd,
|
|
3111
|
+
tmux_session_name: sessionName,
|
|
3112
|
+
});
|
|
3113
|
+
}
|
|
3114
|
+
parsePaneIdFromTmuxOutput(output || "");
|
|
2799
3115
|
}
|
|
2800
|
-
|
|
2801
|
-
|
|
3116
|
+
if (step.name === "split-and-capture-hud-pane") {
|
|
3117
|
+
const hudPaneId = parsePaneIdFromTmuxOutput(output || "");
|
|
3118
|
+
const hookWindowIndex = hudPaneId
|
|
3119
|
+
? detectDetachedSessionWindowIndex(sessionName)
|
|
3120
|
+
: null;
|
|
3121
|
+
const hookTarget = hudPaneId && hookWindowIndex
|
|
3122
|
+
? buildResizeHookTarget(sessionName, hookWindowIndex)
|
|
3123
|
+
: null;
|
|
3124
|
+
const hookName = hudPaneId && hookWindowIndex
|
|
3125
|
+
? buildResizeHookName("launch", sessionName, hookWindowIndex, hudPaneId)
|
|
3126
|
+
: null;
|
|
3127
|
+
const clientAttachedHookName = hudPaneId && hookWindowIndex
|
|
3128
|
+
? buildClientAttachedReconcileHookName("launch", sessionName, hookWindowIndex, hudPaneId)
|
|
3129
|
+
: null;
|
|
3130
|
+
const finalizeSteps = buildDetachedSessionFinalizeSteps(sessionName, hudPaneId, hookWindowIndex, process.env.OMX_MOUSE !== "0", nativeWindows);
|
|
3131
|
+
if (nativeWindows && detachedWindowsCodexCmd) {
|
|
3132
|
+
scheduleDetachedWindowsCodexLaunch(sessionName, detachedWindowsCodexCmd);
|
|
3133
|
+
}
|
|
3134
|
+
for (const finalizeStep of finalizeSteps) {
|
|
3135
|
+
if (finalizeStep.name === "sanitize-copy-mode-style") {
|
|
3136
|
+
try {
|
|
3137
|
+
mitigateCopyModeUnderlineArtifacts(sessionName);
|
|
3138
|
+
}
|
|
3139
|
+
catch (err) {
|
|
3140
|
+
logCliOperationFailure(err);
|
|
3141
|
+
}
|
|
3142
|
+
continue;
|
|
3143
|
+
}
|
|
3144
|
+
const stdio = finalizeStep.name === "attach-session" ? "inherit" : "ignore";
|
|
2802
3145
|
try {
|
|
2803
|
-
|
|
3146
|
+
const startedAtMs = Date.now();
|
|
3147
|
+
execTmuxFileSync(finalizeStep.args, { stdio });
|
|
3148
|
+
if (finalizeStep.name === "attach-session") {
|
|
3149
|
+
assertDetachedAttachDidNotNoop(sessionName, Date.now() - startedAtMs, process.env);
|
|
3150
|
+
}
|
|
2804
3151
|
}
|
|
2805
3152
|
catch (err) {
|
|
2806
3153
|
logCliOperationFailure(err);
|
|
3154
|
+
if (finalizeStep.name === "attach-session")
|
|
3155
|
+
throw new Error("failed to attach detached tmux session");
|
|
3156
|
+
continue;
|
|
2807
3157
|
}
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
if (finalizeStep.name === "
|
|
2815
|
-
|
|
3158
|
+
if (finalizeStep.name === "register-resize-hook" &&
|
|
3159
|
+
hookTarget &&
|
|
3160
|
+
hookName) {
|
|
3161
|
+
registeredHookTarget = hookTarget;
|
|
3162
|
+
registeredHookName = hookName;
|
|
3163
|
+
}
|
|
3164
|
+
if (finalizeStep.name === "register-client-attached-reconcile" &&
|
|
3165
|
+
clientAttachedHookName) {
|
|
3166
|
+
registeredClientAttachedHookName = clientAttachedHookName;
|
|
2816
3167
|
}
|
|
2817
3168
|
}
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
return { postLaunchHandledExternally: !nativeWindows };
|
|
3172
|
+
}
|
|
3173
|
+
catch (err) {
|
|
3174
|
+
if (detachedParentEnvFilePath) {
|
|
3175
|
+
rmSync(detachedParentEnvFilePath, { force: true });
|
|
3176
|
+
}
|
|
3177
|
+
if (activeRecordPath) {
|
|
3178
|
+
rmSync(activeRecordPath, { force: true });
|
|
3179
|
+
}
|
|
3180
|
+
if (createdDetachedSession) {
|
|
3181
|
+
const rollbackSteps = buildDetachedSessionRollbackSteps(sessionName, registeredHookTarget, registeredHookName, registeredClientAttachedHookName);
|
|
3182
|
+
for (const rollbackStep of rollbackSteps) {
|
|
3183
|
+
try {
|
|
3184
|
+
execTmuxFileSync(rollbackStep.args, { stdio: "ignore" });
|
|
2829
3185
|
}
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
3186
|
+
catch (rollbackErr) {
|
|
3187
|
+
logCliOperationFailure(rollbackErr);
|
|
3188
|
+
// best-effort rollback only
|
|
2833
3189
|
}
|
|
2834
3190
|
}
|
|
2835
3191
|
}
|
|
3192
|
+
throw err;
|
|
3193
|
+
}
|
|
3194
|
+
};
|
|
3195
|
+
const contextKey = process.env[OMX_MADMAX_DETACHED_CONTEXT_ENV]?.trim();
|
|
3196
|
+
const runsRoot = resolveMadmaxRunsRoot(process.env);
|
|
3197
|
+
try {
|
|
3198
|
+
if (isMadmaxDetachedGuardEnabled(process.env) && contextKey) {
|
|
3199
|
+
return withMadmaxDetachedContextLock(runsRoot, contextKey, launchDetachedSession);
|
|
2836
3200
|
}
|
|
2837
|
-
return
|
|
3201
|
+
return launchDetachedSession();
|
|
2838
3202
|
}
|
|
2839
3203
|
catch (err) {
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
rmSync(detachedParentEnvFilePath, { force: true });
|
|
2843
|
-
}
|
|
2844
|
-
if (createdDetachedSession) {
|
|
2845
|
-
const rollbackSteps = buildDetachedSessionRollbackSteps(sessionName, registeredHookTarget, registeredHookName, registeredClientAttachedHookName);
|
|
2846
|
-
for (const rollbackStep of rollbackSteps) {
|
|
2847
|
-
try {
|
|
2848
|
-
execTmuxFileSync(rollbackStep.args, { stdio: "ignore" });
|
|
2849
|
-
}
|
|
2850
|
-
catch (err) {
|
|
2851
|
-
logCliOperationFailure(err);
|
|
2852
|
-
// best-effort rollback only
|
|
2853
|
-
}
|
|
2854
|
-
}
|
|
3204
|
+
if (err instanceof MadmaxDetachedReuseError || err instanceof MadmaxDetachedGuardError) {
|
|
3205
|
+
throw err;
|
|
2855
3206
|
}
|
|
3207
|
+
logCliOperationFailure(err);
|
|
2856
3208
|
// tmux not available or failed, just run codex directly
|
|
2857
3209
|
runCodexBlocking(cwd, launchArgs, codexEnvWithNotify);
|
|
2858
3210
|
return { postLaunchHandledExternally: false };
|
|
2859
3211
|
}
|
|
2860
3212
|
}
|
|
2861
3213
|
}
|
|
2862
|
-
function listHudWatchPaneIdsInCurrentWindow(currentPaneId) {
|
|
3214
|
+
function listHudWatchPaneIdsInCurrentWindow(currentPaneId, owner = {}) {
|
|
2863
3215
|
try {
|
|
2864
|
-
return listCurrentWindowHudPaneIds(currentPaneId);
|
|
3216
|
+
return listCurrentWindowHudPaneIds(currentPaneId, undefined, owner);
|
|
2865
3217
|
}
|
|
2866
3218
|
catch (err) {
|
|
2867
3219
|
logCliOperationFailure(err);
|
|
2868
3220
|
return [];
|
|
2869
3221
|
}
|
|
2870
3222
|
}
|
|
2871
|
-
function createHudWatchPane(cwd, hudCmd) {
|
|
2872
|
-
return createSharedHudWatchPane(cwd, hudCmd, {
|
|
3223
|
+
function createHudWatchPane(cwd, hudCmd, options = {}) {
|
|
3224
|
+
return createSharedHudWatchPane(cwd, hudCmd, {
|
|
3225
|
+
heightLines: options.heightLines ?? HUD_TMUX_HEIGHT_LINES,
|
|
3226
|
+
targetPaneId: options.targetPaneId,
|
|
3227
|
+
});
|
|
2873
3228
|
}
|
|
2874
3229
|
function killTmuxPane(paneId) {
|
|
2875
3230
|
if (!paneId.startsWith("%"))
|
|
@@ -3109,7 +3464,7 @@ async function postLaunch(cwd, sessionId, codexHomeOverride, enableNotifyFallbac
|
|
|
3109
3464
|
}
|
|
3110
3465
|
export async function runDetachedSessionPostLaunch(cwd, sessionId, codexHomeOverride, projectLocalCodexHomeForCleanup, runtimeCodexHomeForCleanup) {
|
|
3111
3466
|
await postLaunch(cwd, sessionId, codexHomeOverride, false, projectLocalCodexHomeForCleanup);
|
|
3112
|
-
await cleanupRuntimeCodexHome(runtimeCodexHomeForCleanup).catch(logCliOperationFailure);
|
|
3467
|
+
await cleanupRuntimeCodexHome(runtimeCodexHomeForCleanup, projectLocalCodexHomeForCleanup).catch(logCliOperationFailure);
|
|
3113
3468
|
}
|
|
3114
3469
|
async function emitNativeHookEvent(cwd, event, opts = {}) {
|
|
3115
3470
|
const payload = buildHookEvent(event, {
|