oh-my-codex 0.14.4 → 0.15.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/.agents/plugins/marketplace.json +20 -0
- package/Cargo.lock +6 -6
- package/Cargo.toml +2 -1
- package/README.md +40 -7
- package/crates/omx-explore/Cargo.toml +1 -0
- package/crates/omx-explore/src/main.rs +246 -24
- package/crates/omx-mux/Cargo.toml +1 -0
- package/crates/omx-runtime/Cargo.toml +1 -0
- package/crates/omx-runtime-core/Cargo.toml +1 -0
- package/crates/omx-runtime-core/src/dispatch.rs +2 -1
- package/crates/omx-runtime-core/src/engine.rs +2 -2
- package/crates/omx-runtime-core/src/mailbox.rs +2 -1
- package/crates/omx-sparkshell/Cargo.toml +1 -0
- package/crates/omx-sparkshell/src/codex_bridge.rs +1 -0
- package/crates/omx-sparkshell/src/prompt.rs +1 -0
- package/crates/omx-sparkshell/src/threshold.rs +1 -0
- package/dist/agents/__tests__/native-config.test.js +98 -4
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/agents/native-config.d.ts +4 -0
- package/dist/agents/native-config.d.ts.map +1 -1
- package/dist/agents/native-config.js +19 -3
- package/dist/agents/native-config.js.map +1 -1
- package/dist/agents/policy.d.ts +10 -0
- package/dist/agents/policy.d.ts.map +1 -0
- package/dist/agents/policy.js +61 -0
- package/dist/agents/policy.js.map +1 -0
- package/dist/catalog/__tests__/generator.test.js +2 -0
- package/dist/catalog/__tests__/generator.test.js.map +1 -1
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.d.ts +2 -0
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.d.ts.map +1 -0
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +72 -0
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -0
- package/dist/catalog/installable.d.ts +5 -0
- package/dist/catalog/installable.d.ts.map +1 -0
- package/dist/catalog/installable.js +13 -0
- package/dist/catalog/installable.js.map +1 -0
- package/dist/catalog/skill-mirror.d.ts +20 -0
- package/dist/catalog/skill-mirror.d.ts.map +1 -0
- package/dist/catalog/skill-mirror.js +104 -0
- package/dist/catalog/skill-mirror.js.map +1 -0
- package/dist/cli/__tests__/ask.test.js +4 -1
- package/dist/cli/__tests__/ask.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.d.ts +2 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.d.ts.map +1 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.js +210 -0
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-team.test.js +46 -1
- package/dist/cli/__tests__/doctor-team.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +225 -111
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/exec.test.js +96 -1
- package/dist/cli/__tests__/exec.test.js.map +1 -1
- package/dist/cli/__tests__/explore.test.js +26 -9
- package/dist/cli/__tests__/explore.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +301 -7
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +358 -4
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/list.test.d.ts +2 -0
- package/dist/cli/__tests__/list.test.d.ts.map +1 -0
- package/dist/cli/__tests__/list.test.js +38 -0
- package/dist/cli/__tests__/list.test.js.map +1 -0
- package/dist/cli/__tests__/mcp-parity.test.js +86 -0
- package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
- package/dist/cli/__tests__/mcp-serve.test.d.ts +2 -0
- package/dist/cli/__tests__/mcp-serve.test.d.ts.map +1 -0
- package/dist/cli/__tests__/mcp-serve.test.js +38 -0
- package/dist/cli/__tests__/mcp-serve.test.js.map +1 -0
- package/dist/cli/__tests__/nested-help-routing.test.js +1 -0
- package/dist/cli/__tests__/nested-help-routing.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +58 -3
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/question.test.js +209 -5
- package/dist/cli/__tests__/question.test.js.map +1 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js +146 -3
- package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.d.ts +2 -0
- package/dist/cli/__tests__/setup-install-mode.test.d.ts.map +1 -0
- package/dist/cli/__tests__/setup-install-mode.test.js +873 -0
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -0
- package/dist/cli/__tests__/setup-prompts-overwrite.test.js +83 -22
- package/dist/cli/__tests__/setup-prompts-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +120 -2
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js +32 -13
- package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/sidecar.test.d.ts +2 -0
- package/dist/cli/__tests__/sidecar.test.d.ts.map +1 -0
- package/dist/cli/__tests__/sidecar.test.js +24 -0
- package/dist/cli/__tests__/sidecar.test.js.map +1 -0
- package/dist/cli/__tests__/team.test.js +90 -42
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/version-sync-contract.test.js +11 -0
- package/dist/cli/__tests__/version-sync-contract.test.js.map +1 -1
- package/dist/cli/codex-home.d.ts +4 -5
- package/dist/cli/codex-home.d.ts.map +1 -1
- package/dist/cli/codex-home.js +9 -37
- package/dist/cli/codex-home.js.map +1 -1
- package/dist/cli/doctor.d.ts +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +509 -278
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +13 -5
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +351 -60
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/list.d.ts +2 -0
- package/dist/cli/list.d.ts.map +1 -0
- package/dist/cli/list.js +40 -0
- package/dist/cli/list.js.map +1 -0
- package/dist/cli/mcp-serve.d.ts +12 -0
- package/dist/cli/mcp-serve.d.ts.map +1 -0
- package/dist/cli/mcp-serve.js +63 -0
- package/dist/cli/mcp-serve.js.map +1 -0
- package/dist/cli/plugin-marketplace.d.ts +13 -0
- package/dist/cli/plugin-marketplace.d.ts.map +1 -0
- package/dist/cli/plugin-marketplace.js +77 -0
- package/dist/cli/plugin-marketplace.js.map +1 -0
- package/dist/cli/question.d.ts.map +1 -1
- package/dist/cli/question.js +27 -2
- package/dist/cli/question.js.map +1 -1
- package/dist/cli/setup-preferences.d.ts +20 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -0
- package/dist/cli/setup-preferences.js +71 -0
- package/dist/cli/setup-preferences.js.map +1 -0
- package/dist/cli/setup.d.ts +12 -3
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +1080 -254
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/team.d.ts +1 -0
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +22 -3
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +2 -8
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +100 -3
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +6 -5
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/__tests__/generator-status-line-presets.test.d.ts +2 -0
- package/dist/config/__tests__/generator-status-line-presets.test.d.ts.map +1 -0
- package/dist/config/__tests__/generator-status-line-presets.test.js +203 -0
- package/dist/config/__tests__/generator-status-line-presets.test.js.map +1 -0
- package/dist/config/__tests__/models.test.js +35 -2
- package/dist/config/__tests__/models.test.js.map +1 -1
- package/dist/config/codex-hooks.d.ts.map +1 -1
- package/dist/config/codex-hooks.js +2 -7
- package/dist/config/codex-hooks.js.map +1 -1
- package/dist/config/generator.d.ts +10 -0
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +259 -76
- package/dist/config/generator.js.map +1 -1
- package/dist/config/models.d.ts +13 -3
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +25 -5
- package/dist/config/models.js.map +1 -1
- package/dist/config/omx-first-party-mcp.d.ts +18 -0
- package/dist/config/omx-first-party-mcp.d.ts.map +1 -0
- package/dist/config/omx-first-party-mcp.js +76 -0
- package/dist/config/omx-first-party-mcp.js.map +1 -0
- package/dist/document-refresh/__tests__/enforcer.test.d.ts +2 -0
- package/dist/document-refresh/__tests__/enforcer.test.d.ts.map +1 -0
- package/dist/document-refresh/__tests__/enforcer.test.js +128 -0
- package/dist/document-refresh/__tests__/enforcer.test.js.map +1 -0
- package/dist/document-refresh/config.d.ts +9 -0
- package/dist/document-refresh/config.d.ts.map +1 -0
- package/dist/document-refresh/config.js +70 -0
- package/dist/document-refresh/config.js.map +1 -0
- package/dist/document-refresh/enforcer.d.ts +43 -0
- package/dist/document-refresh/enforcer.d.ts.map +1 -0
- package/dist/document-refresh/enforcer.js +329 -0
- package/dist/document-refresh/enforcer.js.map +1 -0
- package/dist/exec/followup.d.ts +44 -0
- package/dist/exec/followup.d.ts.map +1 -0
- package/dist/exec/followup.js +349 -0
- package/dist/exec/followup.js.map +1 -0
- package/dist/hooks/__tests__/codebase-map.test.js +63 -1
- package/dist/hooks/__tests__/codebase-map.test.js.map +1 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.js +10 -7
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +89 -0
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +84 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +23 -2
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +43 -0
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +17 -0
- package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +53 -0
- package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js +4 -4
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +103 -0
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +27 -13
- package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js +35 -0
- package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +70 -3
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js +5 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js +3 -2
- package/dist/hooks/__tests__/prompt-guidance-fragments.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/prompt-refactor-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/prompt-refactor-contract.test.js +22 -0
- package/dist/hooks/__tests__/prompt-refactor-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js +28 -0
- package/dist/hooks/__tests__/team-runtime-gating-docs-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/triage-heuristic.test.js +59 -4
- package/dist/hooks/__tests__/triage-heuristic.test.js.map +1 -1
- package/dist/hooks/__tests__/visual-ralph-skill.test.d.ts +2 -0
- package/dist/hooks/__tests__/visual-ralph-skill.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/visual-ralph-skill.test.js +44 -0
- package/dist/hooks/__tests__/visual-ralph-skill.test.js.map +1 -0
- package/dist/hooks/codebase-map.d.ts.map +1 -1
- package/dist/hooks/codebase-map.js +83 -6
- package/dist/hooks/codebase-map.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +19 -14
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/prompt-guidance-contract.d.ts +6 -0
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
- package/dist/hooks/prompt-guidance-contract.js +89 -0
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/session.d.ts +2 -0
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js +6 -0
- package/dist/hooks/session.js.map +1 -1
- package/dist/hooks/triage-heuristic.d.ts +2 -2
- package/dist/hooks/triage-heuristic.d.ts.map +1 -1
- package/dist/hooks/triage-heuristic.js +97 -20
- package/dist/hooks/triage-heuristic.js.map +1 -1
- package/dist/hooks/triage-state.d.ts +1 -1
- package/dist/hooks/triage-state.d.ts.map +1 -1
- package/dist/hooks/triage-state.js +2 -1
- package/dist/hooks/triage-state.js.map +1 -1
- package/dist/hud/__tests__/index.test.js +4 -4
- package/dist/hud/__tests__/index.test.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +4 -0
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/__tests__/types.test.js +27 -0
- package/dist/hud/__tests__/types.test.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +8 -0
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/types.d.ts +9 -0
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.js +3 -0
- package/dist/hud/types.js.map +1 -1
- package/dist/mcp/__tests__/bootstrap.test.js +45 -5
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
- package/dist/mcp/__tests__/server-lifecycle.test.js +50 -7
- package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +67 -9
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/bootstrap.d.ts +12 -1
- package/dist/mcp/bootstrap.d.ts.map +1 -1
- package/dist/mcp/bootstrap.js +87 -29
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/state-server.d.ts +5 -11
- package/dist/mcp/state-server.d.ts.map +1 -1
- package/dist/mcp/state-server.js +16 -432
- package/dist/mcp/state-server.js.map +1 -1
- package/dist/planning/__tests__/artifacts.test.js +152 -1
- package/dist/planning/__tests__/artifacts.test.js.map +1 -1
- package/dist/planning/artifacts.d.ts +9 -0
- package/dist/planning/artifacts.d.ts.map +1 -1
- package/dist/planning/artifacts.js +60 -1
- package/dist/planning/artifacts.js.map +1 -1
- package/dist/question/__tests__/deep-interview.test.js +1 -1
- package/dist/question/__tests__/deep-interview.test.js.map +1 -1
- package/dist/question/__tests__/renderer.test.js +70 -0
- package/dist/question/__tests__/renderer.test.js.map +1 -1
- package/dist/question/__tests__/ui.test.js +49 -0
- package/dist/question/__tests__/ui.test.js.map +1 -1
- package/dist/question/renderer.d.ts +14 -1
- package/dist/question/renderer.d.ts.map +1 -1
- package/dist/question/renderer.js +109 -10
- package/dist/question/renderer.js.map +1 -1
- package/dist/question/state.d.ts +2 -0
- package/dist/question/state.d.ts.map +1 -1
- package/dist/question/state.js +4 -0
- package/dist/question/state.js.map +1 -1
- package/dist/question/types.d.ts +2 -1
- package/dist/question/types.d.ts.map +1 -1
- package/dist/question/types.js.map +1 -1
- package/dist/question/ui.d.ts.map +1 -1
- package/dist/question/ui.js +28 -8
- package/dist/question/ui.js.map +1 -1
- package/dist/runtime/__tests__/bridge.test.js +143 -1
- package/dist/runtime/__tests__/bridge.test.js.map +1 -1
- package/dist/runtime/bridge.d.ts +21 -0
- package/dist/runtime/bridge.d.ts.map +1 -1
- package/dist/runtime/bridge.js +54 -4
- package/dist/runtime/bridge.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +1904 -230
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/generate-release-body.test.js +90 -1
- package/dist/scripts/__tests__/generate-release-body.test.js.map +1 -1
- package/dist/scripts/__tests__/hook-derived-watcher.test.js +110 -2
- package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -1
- package/dist/scripts/__tests__/postinstall.test.js +7 -93
- package/dist/scripts/__tests__/postinstall.test.js.map +1 -1
- package/dist/scripts/__tests__/prompt-inventory.test.d.ts +2 -0
- package/dist/scripts/__tests__/prompt-inventory.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/prompt-inventory.test.js +56 -0
- package/dist/scripts/__tests__/prompt-inventory.test.js.map +1 -0
- package/dist/scripts/__tests__/run-test-files.test.d.ts +2 -0
- package/dist/scripts/__tests__/run-test-files.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/run-test-files.test.js +62 -0
- package/dist/scripts/__tests__/run-test-files.test.js.map +1 -0
- package/dist/scripts/__tests__/smoke-packed-install.test.js +13 -1
- package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
- package/dist/scripts/__tests__/verify-native-agents.test.d.ts +2 -0
- package/dist/scripts/__tests__/verify-native-agents.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/verify-native-agents.test.js +166 -0
- package/dist/scripts/__tests__/verify-native-agents.test.js.map +1 -0
- package/dist/scripts/codex-execution-surface.d.ts +16 -0
- package/dist/scripts/codex-execution-surface.d.ts.map +1 -0
- package/dist/scripts/codex-execution-surface.js +42 -0
- package/dist/scripts/codex-execution-surface.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +418 -76
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/codex-native-pre-post.d.ts +8 -0
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
- package/dist/scripts/codex-native-pre-post.js +133 -19
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/generate-release-body.d.ts +1 -0
- package/dist/scripts/generate-release-body.d.ts.map +1 -1
- package/dist/scripts/generate-release-body.js +32 -3
- package/dist/scripts/generate-release-body.js.map +1 -1
- package/dist/scripts/hook-derived-watcher.js +46 -7
- package/dist/scripts/hook-derived-watcher.js.map +1 -1
- package/dist/scripts/notify-fallback-watcher.js +59 -9
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts +2 -0
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.d.ts.map +1 -0
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js +153 -0
- package/dist/scripts/notify-hook/__tests__/team-worker-posttooluse.test.js.map +1 -0
- package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.js +18 -1
- package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
- package/dist/scripts/notify-hook/process-runner.d.ts.map +1 -1
- package/dist/scripts/notify-hook/process-runner.js +7 -3
- 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 +96 -11
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js +3 -3
- package/dist/scripts/notify-hook/team-worker-posttooluse.d.ts +34 -0
- package/dist/scripts/notify-hook/team-worker-posttooluse.d.ts.map +1 -0
- package/dist/scripts/notify-hook/team-worker-posttooluse.js +434 -0
- package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -0
- package/dist/scripts/notify-hook/team-worker.d.ts +1 -1
- package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-worker.js +3 -43
- package/dist/scripts/notify-hook/team-worker.js.map +1 -1
- package/dist/scripts/notify-hook.js +36 -5
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/postinstall.d.ts +1 -5
- package/dist/scripts/postinstall.d.ts.map +1 -1
- package/dist/scripts/postinstall.js +3 -42
- package/dist/scripts/postinstall.js.map +1 -1
- package/dist/scripts/prompt-inventory.d.ts +29 -0
- package/dist/scripts/prompt-inventory.d.ts.map +1 -0
- package/dist/scripts/prompt-inventory.js +178 -0
- package/dist/scripts/prompt-inventory.js.map +1 -0
- package/dist/scripts/run-test-files.js +32 -2
- 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 +9 -1
- package/dist/scripts/smoke-packed-install.js.map +1 -1
- package/dist/scripts/sync-plugin-mirror.d.ts +13 -0
- package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -0
- package/dist/scripts/sync-plugin-mirror.js +242 -0
- package/dist/scripts/sync-plugin-mirror.js.map +1 -0
- package/dist/scripts/verify-native-agents.d.ts +16 -0
- package/dist/scripts/verify-native-agents.d.ts.map +1 -0
- package/dist/scripts/verify-native-agents.js +188 -0
- package/dist/scripts/verify-native-agents.js.map +1 -0
- package/dist/session-history/search.d.ts.map +1 -1
- package/dist/session-history/search.js +7 -2
- package/dist/session-history/search.js.map +1 -1
- package/dist/sidecar/__tests__/boundary.test.d.ts +2 -0
- package/dist/sidecar/__tests__/boundary.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/boundary.test.js +48 -0
- package/dist/sidecar/__tests__/boundary.test.js.map +1 -0
- package/dist/sidecar/__tests__/collector.test.d.ts +2 -0
- package/dist/sidecar/__tests__/collector.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/collector.test.js +162 -0
- package/dist/sidecar/__tests__/collector.test.js.map +1 -0
- package/dist/sidecar/__tests__/render.test.d.ts +2 -0
- package/dist/sidecar/__tests__/render.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/render.test.js +67 -0
- package/dist/sidecar/__tests__/render.test.js.map +1 -0
- package/dist/sidecar/__tests__/tmux.test.d.ts +2 -0
- package/dist/sidecar/__tests__/tmux.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/tmux.test.js +30 -0
- package/dist/sidecar/__tests__/tmux.test.js.map +1 -0
- package/dist/sidecar/__tests__/watch.test.d.ts +2 -0
- package/dist/sidecar/__tests__/watch.test.d.ts.map +1 -0
- package/dist/sidecar/__tests__/watch.test.js +42 -0
- package/dist/sidecar/__tests__/watch.test.js.map +1 -0
- package/dist/sidecar/collector.d.ts +4 -0
- package/dist/sidecar/collector.d.ts.map +1 -0
- package/dist/sidecar/collector.js +377 -0
- package/dist/sidecar/collector.js.map +1 -0
- package/dist/sidecar/index.d.ts +25 -0
- package/dist/sidecar/index.d.ts.map +1 -0
- package/dist/sidecar/index.js +165 -0
- package/dist/sidecar/index.js.map +1 -0
- package/dist/sidecar/render.d.ts +3 -0
- package/dist/sidecar/render.d.ts.map +1 -0
- package/dist/sidecar/render.js +72 -0
- package/dist/sidecar/render.js.map +1 -0
- package/dist/sidecar/tmux.d.ts +13 -0
- package/dist/sidecar/tmux.d.ts.map +1 -0
- package/dist/sidecar/tmux.js +44 -0
- package/dist/sidecar/tmux.js.map +1 -0
- package/dist/sidecar/types.d.ts +125 -0
- package/dist/sidecar/types.d.ts.map +1 -0
- package/dist/sidecar/types.js +2 -0
- package/dist/sidecar/types.js.map +1 -0
- package/dist/state/__tests__/operations.test.js +50 -22
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/operations.d.ts +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +19 -7
- package/dist/state/operations.js.map +1 -1
- package/dist/team/__tests__/commit-hygiene.test.d.ts +2 -0
- package/dist/team/__tests__/commit-hygiene.test.d.ts.map +1 -0
- package/dist/team/__tests__/commit-hygiene.test.js +93 -0
- package/dist/team/__tests__/commit-hygiene.test.js.map +1 -0
- package/dist/team/__tests__/delegation-policy.test.d.ts +2 -0
- package/dist/team/__tests__/delegation-policy.test.d.ts.map +1 -0
- package/dist/team/__tests__/delegation-policy.test.js +69 -0
- package/dist/team/__tests__/delegation-policy.test.js.map +1 -0
- package/dist/team/__tests__/events.test.js +54 -4
- package/dist/team/__tests__/events.test.js.map +1 -1
- package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts +2 -0
- package/dist/team/__tests__/hook-primary-e2e-contract.test.d.ts.map +1 -0
- package/dist/team/__tests__/hook-primary-e2e-contract.test.js +78 -0
- package/dist/team/__tests__/hook-primary-e2e-contract.test.js.map +1 -0
- package/dist/team/__tests__/model-contract.test.js +18 -2
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/repo-aware-decomposition.test.d.ts +2 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.d.ts.map +1 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.js +95 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.js.map +1 -0
- package/dist/team/__tests__/runtime.test.js +677 -17
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.js +177 -1
- package/dist/team/__tests__/state-root.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +110 -0
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +301 -2
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +94 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/commit-hygiene.d.ts +22 -3
- package/dist/team/commit-hygiene.d.ts.map +1 -1
- package/dist/team/commit-hygiene.js +134 -2
- package/dist/team/commit-hygiene.js.map +1 -1
- package/dist/team/contracts.d.ts +1 -1
- package/dist/team/contracts.d.ts.map +1 -1
- package/dist/team/contracts.js +2 -0
- package/dist/team/contracts.js.map +1 -1
- package/dist/team/dag-schema.d.ts +38 -0
- package/dist/team/dag-schema.d.ts.map +1 -0
- package/dist/team/dag-schema.js +221 -0
- package/dist/team/dag-schema.js.map +1 -0
- package/dist/team/delegation-policy.d.ts +3 -0
- package/dist/team/delegation-policy.d.ts.map +1 -0
- package/dist/team/delegation-policy.js +82 -0
- package/dist/team/delegation-policy.js.map +1 -0
- package/dist/team/model-contract.d.ts +3 -1
- package/dist/team/model-contract.d.ts.map +1 -1
- package/dist/team/model-contract.js +44 -5
- package/dist/team/model-contract.js.map +1 -1
- package/dist/team/repo-aware-decomposition.d.ts +60 -0
- package/dist/team/repo-aware-decomposition.d.ts.map +1 -0
- package/dist/team/repo-aware-decomposition.js +229 -0
- package/dist/team/repo-aware-decomposition.js.map +1 -0
- package/dist/team/runtime.d.ts +34 -0
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +191 -50
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/state/tasks.d.ts.map +1 -1
- package/dist/team/state/tasks.js +33 -0
- package/dist/team/state/tasks.js.map +1 -1
- package/dist/team/state/types.d.ts +23 -1
- package/dist/team/state/types.d.ts.map +1 -1
- package/dist/team/state/types.js.map +1 -1
- package/dist/team/state-root.d.ts +35 -0
- package/dist/team/state-root.d.ts.map +1 -1
- package/dist/team/state-root.js +281 -1
- package/dist/team/state-root.js.map +1 -1
- package/dist/team/state.d.ts +27 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +6 -0
- package/dist/team/state.js.map +1 -1
- package/dist/team/tmux-session.d.ts +1 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +83 -6
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +3 -0
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +77 -4
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/utils/__tests__/agents-model-table.test.js +8 -0
- package/dist/utils/__tests__/agents-model-table.test.js.map +1 -1
- package/dist/utils/__tests__/paths.test.js +42 -9
- package/dist/utils/__tests__/paths.test.js.map +1 -1
- package/dist/utils/agents-md.d.ts +3 -0
- package/dist/utils/agents-md.d.ts.map +1 -1
- package/dist/utils/agents-md.js +25 -0
- package/dist/utils/agents-md.js.map +1 -1
- package/dist/utils/agents-model-table.d.ts.map +1 -1
- package/dist/utils/agents-model-table.js +2 -3
- package/dist/utils/agents-model-table.js.map +1 -1
- package/package.json +14 -7
- package/plugins/oh-my-codex/.app.json +3 -0
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +30 -0
- package/plugins/oh-my-codex/.mcp.json +44 -0
- package/plugins/oh-my-codex/skills/ai-slop-cleaner/SKILL.md +114 -0
- package/plugins/oh-my-codex/skills/analyze/SKILL.md +148 -0
- package/plugins/oh-my-codex/skills/ask-claude/SKILL.md +61 -0
- package/plugins/oh-my-codex/skills/ask-gemini/SKILL.md +61 -0
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +231 -0
- package/plugins/oh-my-codex/skills/autoresearch/SKILL.md +68 -0
- package/plugins/oh-my-codex/skills/cancel/SKILL.md +399 -0
- package/plugins/oh-my-codex/skills/code-review/SKILL.md +290 -0
- package/plugins/oh-my-codex/skills/configure-notifications/SKILL.md +287 -0
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +464 -0
- package/plugins/oh-my-codex/skills/doctor/SKILL.md +239 -0
- package/plugins/oh-my-codex/skills/help/SKILL.md +202 -0
- package/plugins/oh-my-codex/skills/hud/SKILL.md +98 -0
- package/plugins/oh-my-codex/skills/note/SKILL.md +62 -0
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +135 -0
- package/plugins/oh-my-codex/skills/pipeline/SKILL.md +86 -0
- package/plugins/oh-my-codex/skills/plan/SKILL.md +276 -0
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +269 -0
- package/plugins/oh-my-codex/skills/ralplan/SKILL.md +162 -0
- package/plugins/oh-my-codex/skills/security-review/SKILL.md +300 -0
- package/plugins/oh-my-codex/skills/skill/SKILL.md +835 -0
- package/plugins/oh-my-codex/skills/team/SKILL.md +510 -0
- package/plugins/oh-my-codex/skills/trace/SKILL.md +33 -0
- package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +143 -0
- package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +175 -0
- package/plugins/oh-my-codex/skills/visual-ralph/SKILL.md +153 -0
- package/plugins/oh-my-codex/skills/visual-verdict/SKILL.md +76 -0
- package/plugins/oh-my-codex/skills/wiki/SKILL.md +57 -0
- package/plugins/oh-my-codex/skills/worker/SKILL.md +106 -0
- package/prompts/critic.md +35 -83
- package/prompts/executor.md +32 -109
- package/prompts/explore-harness.md +1 -1
- package/prompts/explore.md +37 -90
- package/prompts/planner.md +28 -58
- package/prompts/researcher.md +46 -78
- package/prompts/verifier.md +23 -31
- package/skills/autopilot/SKILL.md +1 -4
- package/skills/deep-interview/SKILL.md +8 -5
- package/skills/doctor/SKILL.md +45 -17
- package/skills/help/SKILL.md +2 -2
- package/skills/omx-setup/SKILL.md +52 -9
- package/skills/plan/SKILL.md +1 -4
- package/skills/ralph/SKILL.md +3 -5
- package/skills/ralplan/SKILL.md +2 -6
- package/skills/team/SKILL.md +2 -5
- package/skills/ultraqa/SKILL.md +1 -4
- package/skills/ultrawork/SKILL.md +2 -3
- package/skills/visual-ralph/SKILL.md +153 -0
- package/skills/web-clone/SKILL.md +12 -354
- package/src/scripts/__tests__/codex-native-hook.test.ts +2306 -224
- package/src/scripts/__tests__/generate-release-body.test.ts +109 -0
- package/src/scripts/__tests__/hook-derived-watcher.test.ts +132 -2
- package/src/scripts/__tests__/postinstall.test.ts +7 -104
- package/src/scripts/__tests__/prompt-inventory.test.ts +64 -0
- package/src/scripts/__tests__/run-test-files.test.ts +72 -0
- package/src/scripts/__tests__/smoke-packed-install.test.ts +15 -0
- package/src/scripts/__tests__/verify-native-agents.test.ts +204 -0
- package/src/scripts/codex-execution-surface.ts +73 -0
- package/src/scripts/codex-native-hook.ts +579 -82
- package/src/scripts/codex-native-pre-post.ts +157 -19
- package/src/scripts/generate-release-body.ts +34 -2
- package/src/scripts/hook-derived-watcher.ts +51 -8
- package/src/scripts/notify-fallback-watcher.ts +65 -9
- package/src/scripts/notify-hook/__tests__/team-worker-posttooluse.test.ts +180 -0
- package/src/scripts/notify-hook/managed-tmux.ts +22 -4
- package/src/scripts/notify-hook/process-runner.ts +7 -3
- package/src/scripts/notify-hook/team-dispatch.ts +103 -11
- package/src/scripts/notify-hook/team-tmux-guard.ts +3 -3
- package/src/scripts/notify-hook/team-worker-posttooluse.ts +536 -0
- package/src/scripts/notify-hook/team-worker.ts +4 -48
- package/src/scripts/notify-hook.ts +36 -5
- package/src/scripts/postinstall.ts +4 -58
- package/src/scripts/prompt-inventory.ts +218 -0
- package/src/scripts/run-test-files.ts +41 -2
- package/src/scripts/smoke-packed-install.ts +10 -1
- package/src/scripts/sync-plugin-mirror.ts +360 -0
- package/src/scripts/verify-native-agents.ts +245 -0
- package/templates/AGENTS.md +26 -91
- package/templates/catalog-manifest.json +16 -1
package/dist/cli/setup.js
CHANGED
|
@@ -2,35 +2,49 @@
|
|
|
2
2
|
* omx setup - Automated installation of oh-my-codex
|
|
3
3
|
* Installs skills, prompts, MCP servers config, and AGENTS.md
|
|
4
4
|
*/
|
|
5
|
-
import { mkdir, copyFile, readdir, readFile, rename, writeFile, stat, rm, } from "fs/promises";
|
|
5
|
+
import { mkdir, cp, copyFile, readdir, readFile, rename, writeFile, stat, rm, } from "fs/promises";
|
|
6
6
|
import { join, dirname, relative, basename } from "path";
|
|
7
7
|
import { existsSync } from "fs";
|
|
8
8
|
import { spawnSync } from "child_process";
|
|
9
9
|
import { createInterface } from "readline/promises";
|
|
10
10
|
import { homedir } from "os";
|
|
11
11
|
import { codexHome, codexConfigPath, codexPromptsDir, codexAgentsDir, userSkillsDir, omxStateDir, detectLegacySkillRootOverlap, omxPlansDir, omxLogsDir, } from "../utils/paths.js";
|
|
12
|
-
import { buildMergedConfig, getRootModelName, hasLegacyOmxTeamRunTable, } from "../config/generator.js";
|
|
12
|
+
import { buildMergedConfig, getRootModelName, hasLegacyOmxTeamRunTable, stripExistingOmxBlocks, stripExistingSharedMcpRegistryBlock, stripOmxEnvSettings, stripOmxFeatureFlags, stripOmxSeededBehavioralDefaults, upsertCodexHooksFeatureFlag, OMX_DEVELOPER_INSTRUCTIONS, } from "../config/generator.js";
|
|
13
13
|
import { mergeManagedCodexHooksConfig } from "../config/codex-hooks.js";
|
|
14
14
|
import { getLegacyUnifiedMcpRegistryCandidate, getUnifiedMcpRegistryCandidates, loadUnifiedMcpRegistry, planClaudeCodeMcpSettingsSync, } from "../config/mcp-registry.js";
|
|
15
15
|
import { generateAgentToml } from "../agents/native-config.js";
|
|
16
16
|
import { AGENT_DEFINITIONS } from "../agents/definitions.js";
|
|
17
|
+
import { getCatalogAgentStatusByName, getInstallableNativeAgentNames, isNativeAgentInstallableStatus, isSetupPromptAssetName, } from "../agents/policy.js";
|
|
17
18
|
import { getPackageRoot } from "../utils/package.js";
|
|
18
19
|
import { readSessionState, isSessionStale } from "../hooks/session.js";
|
|
19
20
|
import { getCatalogHeadlineCounts } from "./catalog-contract.js";
|
|
20
21
|
import { tryReadCatalogManifest } from "../catalog/reader.js";
|
|
21
22
|
import { DEFAULT_FRONTIER_MODEL } from "../config/models.js";
|
|
22
|
-
import { addGeneratedAgentsMarker, hasOmxManagedAgentsSections, isOmxGeneratedAgentsMd, } from "../utils/agents-md.js";
|
|
23
|
+
import { addGeneratedAgentsMarker, hasOmxManagedAgentsSections, isOmxGeneratedAgentsMd, upsertManagedAgentsBlock, } from "../utils/agents-md.js";
|
|
24
|
+
import { DEFAULT_HUD_CONFIG } from "../hud/types.js";
|
|
25
|
+
import { SETUP_INSTALL_MODES, SETUP_SCOPES, getSetupScopeFilePath, readPersistedSetupPreferences, } from "./setup-preferences.js";
|
|
26
|
+
import { OMX_LOCAL_MARKETPLACE_NAME, resolvePackagedOmxMarketplace, upsertLocalOmxMarketplaceRegistration, } from "./plugin-marketplace.js";
|
|
27
|
+
async function resolveStatusLinePresetForSetup(projectRoot, options) {
|
|
28
|
+
if (options.force) {
|
|
29
|
+
return DEFAULT_HUD_CONFIG.statusLine.preset;
|
|
30
|
+
}
|
|
31
|
+
const path = join(projectRoot, ".omx", "hud-config.json");
|
|
32
|
+
if (!existsSync(path))
|
|
33
|
+
return undefined;
|
|
34
|
+
try {
|
|
35
|
+
const raw = JSON.parse(await readFile(path, "utf-8"));
|
|
36
|
+
const preset = raw?.statusLine?.preset;
|
|
37
|
+
if (preset === "minimal" || preset === "focused" || preset === "full") {
|
|
38
|
+
return preset;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Malformed hud-config.json — fall through to default.
|
|
43
|
+
}
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
23
46
|
import { resolveAgentsModelTableContext, upsertAgentsModelTable, } from "../utils/agents-model-table.js";
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Legacy scope values that may appear in persisted setup-scope.json files.
|
|
27
|
-
* Both 'project-local' (renamed) and old 'project' (minimal, removed) are
|
|
28
|
-
* migrated to the current 'project' scope on read.
|
|
29
|
-
*/
|
|
30
|
-
const LEGACY_SCOPE_MIGRATION = {
|
|
31
|
-
"project-local": "project",
|
|
32
|
-
};
|
|
33
|
-
export const SETUP_SCOPES = ["user", "project"];
|
|
47
|
+
export { SETUP_INSTALL_MODES, SETUP_SCOPES };
|
|
34
48
|
const PROJECT_GITIGNORE_ENTRIES = [
|
|
35
49
|
".omx/",
|
|
36
50
|
".codex/*",
|
|
@@ -44,6 +58,19 @@ const PROJECT_GITIGNORE_ENTRIES = [
|
|
|
44
58
|
];
|
|
45
59
|
const LEGACY_PROJECT_GITIGNORE_ENTRIES = [".codex/"];
|
|
46
60
|
const SETUP_ONLY_INSTALLABLE_SKILLS = new Set(["wiki"]);
|
|
61
|
+
const HARD_DEPRECATED_SKILL_NAMES = new Set(["web-clone"]);
|
|
62
|
+
function isCatalogInstallableStatus(status) {
|
|
63
|
+
return status === "active" || status === "internal";
|
|
64
|
+
}
|
|
65
|
+
function getSetupInstallableSkillNames(manifest = tryReadCatalogManifest()) {
|
|
66
|
+
return new Set([
|
|
67
|
+
...(manifest?.skills ?? [])
|
|
68
|
+
.filter((skill) => typeof skill.name === "string" &&
|
|
69
|
+
isCatalogInstallableStatus(skill.status))
|
|
70
|
+
.map((skill) => skill.name),
|
|
71
|
+
...SETUP_ONLY_INSTALLABLE_SKILLS,
|
|
72
|
+
]);
|
|
73
|
+
}
|
|
47
74
|
function applyScopePathRewritesToAgentsTemplate(content, scope) {
|
|
48
75
|
if (scope !== "project")
|
|
49
76
|
return content;
|
|
@@ -55,10 +82,10 @@ const REQUIRED_TEAM_CLI_API_MARKERS = [
|
|
|
55
82
|
"TEAM_API_OPERATIONS",
|
|
56
83
|
];
|
|
57
84
|
const DEFAULT_SETUP_SCOPE = "user";
|
|
85
|
+
const DEFAULT_SETUP_INSTALL_MODE = "legacy";
|
|
58
86
|
const LEGACY_SETUP_MODEL = "gpt-5.3-codex";
|
|
59
87
|
const DEFAULT_SETUP_MODEL = DEFAULT_FRONTIER_MODEL;
|
|
60
88
|
const OBSOLETE_NATIVE_AGENT_FIELD = ["skill", "ref"].join("_");
|
|
61
|
-
const TUI_OWNED_BY_CODEX_VERSION = [0, 107, 0];
|
|
62
89
|
function createEmptyCategorySummary() {
|
|
63
90
|
return {
|
|
64
91
|
updated: 0,
|
|
@@ -234,16 +261,6 @@ async function buildLegacySkillOverlapNotice(scope) {
|
|
|
234
261
|
message: `Detected ${overlap.overlappingSkillNames.length} overlapping skill names between canonical ${overlap.canonicalDir} and legacy ${overlap.legacyDir}.${mismatchSuffix} Remove or archive ~/.agents/skills after confirming ${overlap.canonicalDir} is the version you want Codex to load.`,
|
|
235
262
|
};
|
|
236
263
|
}
|
|
237
|
-
function logCategorySummary(name, summary) {
|
|
238
|
-
console.log(` ${name}: updated=${summary.updated}, unchanged=${summary.unchanged}, ` +
|
|
239
|
-
`backed_up=${summary.backedUp}, skipped=${summary.skipped}, removed=${summary.removed}`);
|
|
240
|
-
}
|
|
241
|
-
function isSetupScope(value) {
|
|
242
|
-
return SETUP_SCOPES.includes(value);
|
|
243
|
-
}
|
|
244
|
-
function getScopeFilePath(projectRoot) {
|
|
245
|
-
return join(projectRoot, ".omx", "setup-scope.json");
|
|
246
|
-
}
|
|
247
264
|
export function resolveScopeDirectories(scope, projectRoot) {
|
|
248
265
|
if (scope === "project") {
|
|
249
266
|
const codexHomeDir = join(projectRoot, ".codex");
|
|
@@ -265,33 +282,9 @@ export function resolveScopeDirectories(scope, projectRoot) {
|
|
|
265
282
|
skillsDir: userSkillsDir(),
|
|
266
283
|
};
|
|
267
284
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
return undefined;
|
|
272
|
-
try {
|
|
273
|
-
const raw = await readFile(scopePath, "utf-8");
|
|
274
|
-
const parsed = JSON.parse(raw);
|
|
275
|
-
const persisted = {};
|
|
276
|
-
if (parsed && typeof parsed.scope === "string") {
|
|
277
|
-
// Direct match to current scopes
|
|
278
|
-
if (isSetupScope(parsed.scope)) {
|
|
279
|
-
persisted.scope = parsed.scope;
|
|
280
|
-
}
|
|
281
|
-
// Migrate legacy scope values (project-local → project)
|
|
282
|
-
const migrated = LEGACY_SCOPE_MIGRATION[parsed.scope];
|
|
283
|
-
if (migrated) {
|
|
284
|
-
console.warn(`[omx] Migrating persisted setup scope "${parsed.scope}" → "${migrated}" ` +
|
|
285
|
-
`(see issue #243: simplified to user/project).`);
|
|
286
|
-
persisted.scope = migrated;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
return Object.keys(persisted).length > 0 ? persisted : undefined;
|
|
290
|
-
}
|
|
291
|
-
catch {
|
|
292
|
-
// ignore invalid persisted scope and fall back to prompt/default
|
|
293
|
-
}
|
|
294
|
-
return undefined;
|
|
285
|
+
function logCategorySummary(name, summary) {
|
|
286
|
+
console.log(` ${name}: updated=${summary.updated}, unchanged=${summary.unchanged}, ` +
|
|
287
|
+
`backed_up=${summary.backedUp}, skipped=${summary.skipped}, removed=${summary.removed}`);
|
|
295
288
|
}
|
|
296
289
|
async function promptForSetupScope(defaultScope) {
|
|
297
290
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
@@ -302,20 +295,89 @@ async function promptForSetupScope(defaultScope) {
|
|
|
302
295
|
output: process.stdout,
|
|
303
296
|
});
|
|
304
297
|
try {
|
|
298
|
+
const userDefaultMarker = defaultScope === "user" ? " (default)" : "";
|
|
299
|
+
const projectDefaultMarker = defaultScope === "project" ? " (default)" : "";
|
|
300
|
+
const defaultChoice = defaultScope === "project" ? "2" : "1";
|
|
305
301
|
console.log("Select setup scope:");
|
|
306
|
-
console.log(` 1) user
|
|
307
|
-
console.log(
|
|
308
|
-
const answer = (await rl.question(
|
|
302
|
+
console.log(` 1) user${userDefaultMarker} — installs to ${codexHome()} (skills default to ${userSkillsDir()})`);
|
|
303
|
+
console.log(` 2) project${projectDefaultMarker} — installs to ./.codex (local to project)`);
|
|
304
|
+
const answer = (await rl.question(`Scope [1-2] (default: ${defaultChoice}): `))
|
|
309
305
|
.trim()
|
|
310
306
|
.toLowerCase();
|
|
311
307
|
if (answer === "2" || answer === "project")
|
|
312
308
|
return "project";
|
|
309
|
+
if (answer === "1" || answer === "user")
|
|
310
|
+
return "user";
|
|
313
311
|
return defaultScope;
|
|
314
312
|
}
|
|
315
313
|
finally {
|
|
316
314
|
rl.close();
|
|
317
315
|
}
|
|
318
316
|
}
|
|
317
|
+
async function promptForSetupInstallMode(defaultMode) {
|
|
318
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
319
|
+
return defaultMode;
|
|
320
|
+
}
|
|
321
|
+
const rl = createInterface({
|
|
322
|
+
input: process.stdin,
|
|
323
|
+
output: process.stdout,
|
|
324
|
+
});
|
|
325
|
+
try {
|
|
326
|
+
console.log("Select user-scope skill delivery mode:");
|
|
327
|
+
console.log(` 1) legacy${defaultMode === "legacy" ? " (default)" : ""} — install/update OMX skills in the resolved user skill root`);
|
|
328
|
+
console.log(` 2) plugin${defaultMode === "plugin" ? " (default)" : ""} — rely on Codex plugin discovery and clean up matching legacy OMX-managed setup artifacts`);
|
|
329
|
+
const defaultChoice = defaultMode === "plugin" ? "2" : "1";
|
|
330
|
+
const answer = (await rl.question(`Install mode [1-2] (default: ${defaultChoice}): `))
|
|
331
|
+
.trim()
|
|
332
|
+
.toLowerCase();
|
|
333
|
+
if (answer === "2" || answer === "plugin")
|
|
334
|
+
return "plugin";
|
|
335
|
+
if (answer === "1" || answer === "legacy")
|
|
336
|
+
return "legacy";
|
|
337
|
+
return defaultMode;
|
|
338
|
+
}
|
|
339
|
+
finally {
|
|
340
|
+
rl.close();
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
function hasPersistedSetupPreferences(preferences) {
|
|
344
|
+
return Boolean(preferences?.scope || preferences?.installMode);
|
|
345
|
+
}
|
|
346
|
+
function formatPersistedSetupPreferenceSummary(preferences) {
|
|
347
|
+
return [
|
|
348
|
+
`scope=${preferences.scope ?? "not recorded"}`,
|
|
349
|
+
`installMode=${preferences.installMode ?? "not recorded"}`,
|
|
350
|
+
].join(", ");
|
|
351
|
+
}
|
|
352
|
+
async function promptForPersistedSetupReview(preferences) {
|
|
353
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
354
|
+
return "keep";
|
|
355
|
+
}
|
|
356
|
+
const rl = createInterface({
|
|
357
|
+
input: process.stdin,
|
|
358
|
+
output: process.stdout,
|
|
359
|
+
});
|
|
360
|
+
try {
|
|
361
|
+
console.log("Existing OMX setup preferences detected:");
|
|
362
|
+
console.log(` ${formatPersistedSetupPreferenceSummary(preferences)}`);
|
|
363
|
+
console.log(" 1) keep — reuse these choices for this setup run");
|
|
364
|
+
console.log(" 2) review — review/change choices, using these values as defaults");
|
|
365
|
+
console.log(" 3) reset — ignore saved choices and run setup as if fresh");
|
|
366
|
+
const answer = (await rl.question("Setup preferences [1-3] (default: 1 keep): "))
|
|
367
|
+
.trim()
|
|
368
|
+
.toLowerCase();
|
|
369
|
+
if (answer === "2" || answer === "review" || answer === "change") {
|
|
370
|
+
return "review";
|
|
371
|
+
}
|
|
372
|
+
if (answer === "3" || answer === "reset" || answer === "fresh") {
|
|
373
|
+
return "reset";
|
|
374
|
+
}
|
|
375
|
+
return "keep";
|
|
376
|
+
}
|
|
377
|
+
finally {
|
|
378
|
+
rl.close();
|
|
379
|
+
}
|
|
380
|
+
}
|
|
319
381
|
async function promptForModelUpgrade(currentModel, targetModel) {
|
|
320
382
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
321
383
|
return false;
|
|
@@ -334,38 +396,43 @@ async function promptForModelUpgrade(currentModel, targetModel) {
|
|
|
334
396
|
rl.close();
|
|
335
397
|
}
|
|
336
398
|
}
|
|
337
|
-
function
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
if (version[0] !== minimum[0])
|
|
345
|
-
return version[0] > minimum[0];
|
|
346
|
-
if (version[1] !== minimum[1])
|
|
347
|
-
return version[1] > minimum[1];
|
|
348
|
-
return version[2] >= minimum[2];
|
|
349
|
-
}
|
|
350
|
-
function probeInstalledCodexVersion() {
|
|
351
|
-
const { result } = spawnPlatformCommandSync("codex", ["--version"], {
|
|
352
|
-
encoding: "utf-8",
|
|
353
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
399
|
+
async function promptForAgentsOverwrite(destinationPath) {
|
|
400
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
401
|
+
return false;
|
|
402
|
+
}
|
|
403
|
+
const rl = createInterface({
|
|
404
|
+
input: process.stdin,
|
|
405
|
+
output: process.stdout,
|
|
354
406
|
});
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
407
|
+
try {
|
|
408
|
+
const answer = (await rl.question(`Overwrite existing AGENTS.md at "${destinationPath}"? [y/N]: `))
|
|
409
|
+
.trim()
|
|
410
|
+
.toLowerCase();
|
|
411
|
+
return answer === "y" || answer === "yes";
|
|
412
|
+
}
|
|
413
|
+
finally {
|
|
414
|
+
rl.close();
|
|
415
|
+
}
|
|
359
416
|
}
|
|
360
|
-
function
|
|
361
|
-
if (!
|
|
362
|
-
return
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
417
|
+
async function promptForPluginAgentsMdDefault(destinationPath) {
|
|
418
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
const rl = createInterface({
|
|
422
|
+
input: process.stdin,
|
|
423
|
+
output: process.stdout,
|
|
424
|
+
});
|
|
425
|
+
try {
|
|
426
|
+
const answer = (await rl.question(`Plugin mode: install OMX AGENTS.md defaults at "${destinationPath}"? [y/N]: `))
|
|
427
|
+
.trim()
|
|
428
|
+
.toLowerCase();
|
|
429
|
+
return answer === "y" || answer === "yes";
|
|
430
|
+
}
|
|
431
|
+
finally {
|
|
432
|
+
rl.close();
|
|
433
|
+
}
|
|
367
434
|
}
|
|
368
|
-
async function
|
|
435
|
+
async function promptForPluginDeveloperInstructionsDefault(configPath) {
|
|
369
436
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
370
437
|
return false;
|
|
371
438
|
}
|
|
@@ -374,7 +441,25 @@ async function promptForAgentsOverwrite(destinationPath) {
|
|
|
374
441
|
output: process.stdout,
|
|
375
442
|
});
|
|
376
443
|
try {
|
|
377
|
-
const answer = (await rl.question(`
|
|
444
|
+
const answer = (await rl.question(`Plugin mode: add OMX developer_instructions defaults to "${configPath}"? [y/N]: `))
|
|
445
|
+
.trim()
|
|
446
|
+
.toLowerCase();
|
|
447
|
+
return answer === "y" || answer === "yes";
|
|
448
|
+
}
|
|
449
|
+
finally {
|
|
450
|
+
rl.close();
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
async function promptForPluginDeveloperInstructionsOverwrite(configPath) {
|
|
454
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
const rl = createInterface({
|
|
458
|
+
input: process.stdin,
|
|
459
|
+
output: process.stdout,
|
|
460
|
+
});
|
|
461
|
+
try {
|
|
462
|
+
const answer = (await rl.question(`Plugin mode: overwrite existing developer_instructions in "${configPath}" with OMX defaults? [y/N]: `))
|
|
378
463
|
.trim()
|
|
379
464
|
.toLowerCase();
|
|
380
465
|
return answer === "y" || answer === "yes";
|
|
@@ -383,26 +468,132 @@ async function promptForAgentsOverwrite(destinationPath) {
|
|
|
383
468
|
rl.close();
|
|
384
469
|
}
|
|
385
470
|
}
|
|
386
|
-
async function resolveSetupScope(projectRoot, requestedScope) {
|
|
471
|
+
async function resolveSetupScope(projectRoot, requestedScope, persistedReviewDecision = "keep", persistedPreferences, setupScopePrompt) {
|
|
387
472
|
if (requestedScope) {
|
|
388
473
|
return { scope: requestedScope, source: "cli" };
|
|
389
474
|
}
|
|
390
|
-
const persisted = await readPersistedSetupPreferences(projectRoot);
|
|
391
|
-
if (persisted?.scope) {
|
|
475
|
+
const persisted = persistedPreferences ?? (await readPersistedSetupPreferences(projectRoot));
|
|
476
|
+
if (persisted?.scope && persistedReviewDecision === "keep") {
|
|
392
477
|
return { scope: persisted.scope, source: "persisted" };
|
|
393
478
|
}
|
|
394
|
-
if (
|
|
395
|
-
|
|
479
|
+
if (typeof setupScopePrompt === "function" ||
|
|
480
|
+
(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
481
|
+
const defaultScope = persistedReviewDecision === "review" && persisted?.scope
|
|
482
|
+
? persisted.scope
|
|
483
|
+
: DEFAULT_SETUP_SCOPE;
|
|
484
|
+
const scope = setupScopePrompt
|
|
485
|
+
? await setupScopePrompt(defaultScope)
|
|
486
|
+
: await promptForSetupScope(defaultScope);
|
|
396
487
|
return { scope, source: "prompt" };
|
|
397
488
|
}
|
|
398
489
|
return { scope: DEFAULT_SETUP_SCOPE, source: "default" };
|
|
399
490
|
}
|
|
491
|
+
async function readPluginManifestName(manifestPath) {
|
|
492
|
+
try {
|
|
493
|
+
const parsed = JSON.parse(await readFile(manifestPath, "utf-8"));
|
|
494
|
+
return typeof parsed === "object" &&
|
|
495
|
+
parsed !== null &&
|
|
496
|
+
"name" in parsed &&
|
|
497
|
+
typeof parsed.name === "string"
|
|
498
|
+
? parsed.name
|
|
499
|
+
: null;
|
|
500
|
+
}
|
|
501
|
+
catch {
|
|
502
|
+
return null;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
async function discoverOmxPluginCacheDir(cacheRoot = join(codexHome(), "plugins", "cache")) {
|
|
506
|
+
if (!existsSync(cacheRoot))
|
|
507
|
+
return null;
|
|
508
|
+
const queue = [
|
|
509
|
+
{ path: cacheRoot, depth: 0 },
|
|
510
|
+
];
|
|
511
|
+
const maxDepth = 5;
|
|
512
|
+
while (queue.length > 0) {
|
|
513
|
+
const current = queue.shift();
|
|
514
|
+
if (!current)
|
|
515
|
+
break;
|
|
516
|
+
const manifestPath = join(current.path, ".codex-plugin", "plugin.json");
|
|
517
|
+
if (existsSync(manifestPath)) {
|
|
518
|
+
const name = await readPluginManifestName(manifestPath);
|
|
519
|
+
if (name === "oh-my-codex") {
|
|
520
|
+
return current.path;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (current.depth >= maxDepth)
|
|
524
|
+
continue;
|
|
525
|
+
let entries;
|
|
526
|
+
try {
|
|
527
|
+
entries = await readdir(current.path, { withFileTypes: true });
|
|
528
|
+
}
|
|
529
|
+
catch {
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
532
|
+
for (const entry of entries) {
|
|
533
|
+
if (!entry.isDirectory())
|
|
534
|
+
continue;
|
|
535
|
+
if (entry.name === ".git" || entry.name === "node_modules")
|
|
536
|
+
continue;
|
|
537
|
+
queue.push({
|
|
538
|
+
path: join(current.path, entry.name),
|
|
539
|
+
depth: current.depth + 1,
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return null;
|
|
544
|
+
}
|
|
545
|
+
async function resolveSetupInstallMode(projectRoot, scope, requestedInstallMode, installModePrompt, persistedReviewDecision = "keep", persistedPreferences) {
|
|
546
|
+
if (requestedInstallMode) {
|
|
547
|
+
return { installMode: requestedInstallMode, source: "cli" };
|
|
548
|
+
}
|
|
549
|
+
const persisted = persistedPreferences ?? (await readPersistedSetupPreferences(projectRoot));
|
|
550
|
+
if (persisted?.installMode &&
|
|
551
|
+
persistedReviewDecision === "keep" &&
|
|
552
|
+
persisted.scope === scope) {
|
|
553
|
+
return { installMode: persisted.installMode, source: "persisted" };
|
|
554
|
+
}
|
|
555
|
+
if (scope !== "user")
|
|
556
|
+
return null;
|
|
557
|
+
const discoveredPluginCacheDir = await discoverOmxPluginCacheDir();
|
|
558
|
+
const defaultMode = persistedReviewDecision === "review" && persisted?.installMode
|
|
559
|
+
? persisted.installMode
|
|
560
|
+
: discoveredPluginCacheDir
|
|
561
|
+
? "plugin"
|
|
562
|
+
: DEFAULT_SETUP_INSTALL_MODE;
|
|
563
|
+
if (typeof installModePrompt === "function" ||
|
|
564
|
+
(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
565
|
+
if (discoveredPluginCacheDir) {
|
|
566
|
+
console.log(`Detected installed oh-my-codex Codex plugin cache at ${discoveredPluginCacheDir}.`);
|
|
567
|
+
}
|
|
568
|
+
const installMode = installModePrompt
|
|
569
|
+
? await installModePrompt(defaultMode)
|
|
570
|
+
: await promptForSetupInstallMode(defaultMode);
|
|
571
|
+
return { installMode, source: "prompt" };
|
|
572
|
+
}
|
|
573
|
+
return { installMode: defaultMode, source: "default" };
|
|
574
|
+
}
|
|
400
575
|
function hasGitignoreEntry(content, entry) {
|
|
401
576
|
return content
|
|
402
577
|
.split(/\r?\n/)
|
|
403
578
|
.map((line) => line.trim())
|
|
404
579
|
.some((line) => line === entry);
|
|
405
580
|
}
|
|
581
|
+
function isProjectPathIgnoredByGit(projectRoot, path) {
|
|
582
|
+
const result = spawnSync("git", ["check-ignore", "--no-index", "-q", path], {
|
|
583
|
+
cwd: projectRoot,
|
|
584
|
+
stdio: "ignore",
|
|
585
|
+
windowsHide: true,
|
|
586
|
+
});
|
|
587
|
+
return result.status === 0;
|
|
588
|
+
}
|
|
589
|
+
function shouldAddProjectGitignoreEntry(projectRoot, content, entry) {
|
|
590
|
+
if (hasGitignoreEntry(content, entry))
|
|
591
|
+
return false;
|
|
592
|
+
if (entry === ".omx/" && isProjectPathIgnoredByGit(projectRoot, entry)) {
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
return true;
|
|
596
|
+
}
|
|
406
597
|
function stripLegacyGitignoreEntries(content, legacyEntries) {
|
|
407
598
|
const legacyEntrySet = new Set(legacyEntries);
|
|
408
599
|
const lines = content.split(/\r?\n/);
|
|
@@ -420,13 +611,13 @@ async function ensureProjectGitignore(projectRoot, backupContext, options) {
|
|
|
420
611
|
? await readFile(gitignorePath, "utf-8")
|
|
421
612
|
: "";
|
|
422
613
|
const normalized = stripLegacyGitignoreEntries(existing, LEGACY_PROJECT_GITIGNORE_ENTRIES);
|
|
423
|
-
const missingEntries = PROJECT_GITIGNORE_ENTRIES.filter((entry) =>
|
|
614
|
+
const missingEntries = PROJECT_GITIGNORE_ENTRIES.filter((entry) => shouldAddProjectGitignoreEntry(projectRoot, normalized.content, entry));
|
|
424
615
|
if (missingEntries.length === 0 && !normalized.removed) {
|
|
425
616
|
return "unchanged";
|
|
426
617
|
}
|
|
427
618
|
const nextContent = destinationExists
|
|
428
619
|
? `${normalized.content}${normalized.content.endsWith("\n") || normalized.content.length === 0 ? "" : "\n"}${missingEntries.join("\n")}${missingEntries.length > 0 ? "\n" : ""}`
|
|
429
|
-
: `${
|
|
620
|
+
: `${missingEntries.join("\n")}\n`;
|
|
430
621
|
if (await ensureBackup(gitignorePath, destinationExists, backupContext, options)) {
|
|
431
622
|
// backup created when refreshing a pre-existing .gitignore
|
|
432
623
|
}
|
|
@@ -444,41 +635,379 @@ async function ensureProjectGitignore(projectRoot, backupContext, options) {
|
|
|
444
635
|
}
|
|
445
636
|
return destinationExists ? "updated" : "created";
|
|
446
637
|
}
|
|
447
|
-
async function
|
|
448
|
-
const scopePath =
|
|
638
|
+
async function persistSetupPreferences(projectRoot, preferences, options) {
|
|
639
|
+
const scopePath = getSetupScopeFilePath(projectRoot);
|
|
449
640
|
if (options.dryRun) {
|
|
450
641
|
if (options.verbose)
|
|
451
642
|
console.log(` dry-run: skip persisting ${scopePath}`);
|
|
452
643
|
return;
|
|
453
644
|
}
|
|
454
645
|
await mkdir(dirname(scopePath), { recursive: true });
|
|
455
|
-
|
|
456
|
-
await writeFile(scopePath, JSON.stringify(payload, null, 2) + "\n");
|
|
646
|
+
await writeFile(scopePath, JSON.stringify(preferences, null, 2) + "\n");
|
|
457
647
|
if (options.verbose)
|
|
458
648
|
console.log(` Wrote ${scopePath}`);
|
|
459
649
|
}
|
|
650
|
+
async function removeEmptyDirectoryIfPresent(dirPath, options) {
|
|
651
|
+
if (options.dryRun || !existsSync(dirPath))
|
|
652
|
+
return;
|
|
653
|
+
try {
|
|
654
|
+
const remaining = await readdir(dirPath);
|
|
655
|
+
if (remaining.length === 0) {
|
|
656
|
+
await rm(dirPath, { recursive: true, force: true });
|
|
657
|
+
if (options.verbose)
|
|
658
|
+
console.log(` removed empty directory ${dirPath}`);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
catch {
|
|
662
|
+
// Best-effort cleanup only.
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
async function cleanupPluginModeLegacyPrompts(srcDir, dstDir, backupContext, options) {
|
|
666
|
+
const summary = createEmptyCategorySummary();
|
|
667
|
+
if (!existsSync(srcDir) || !existsSync(dstDir))
|
|
668
|
+
return summary;
|
|
669
|
+
const manifest = tryReadCatalogManifest();
|
|
670
|
+
for (const file of await readdir(srcDir)) {
|
|
671
|
+
if (!file.endsWith(".md"))
|
|
672
|
+
continue;
|
|
673
|
+
const promptName = file.slice(0, -3);
|
|
674
|
+
if (manifest && !isSetupPromptAssetName(promptName, manifest))
|
|
675
|
+
continue;
|
|
676
|
+
const dst = join(dstDir, file);
|
|
677
|
+
if (!existsSync(dst))
|
|
678
|
+
continue;
|
|
679
|
+
if (await ensureBackup(dst, true, backupContext, options)) {
|
|
680
|
+
summary.backedUp += 1;
|
|
681
|
+
}
|
|
682
|
+
if (!options.dryRun) {
|
|
683
|
+
await rm(dst, { force: true });
|
|
684
|
+
}
|
|
685
|
+
summary.removed += 1;
|
|
686
|
+
if (options.verbose) {
|
|
687
|
+
console.log(` ${options.dryRun ? "would archive and remove" : "archived and removed"} legacy prompt ${file}`);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
await removeEmptyDirectoryIfPresent(dstDir, options);
|
|
691
|
+
return summary;
|
|
692
|
+
}
|
|
693
|
+
async function cleanupPluginModeLegacyNativeAgents(pkgRoot, agentsDir, backupContext, options) {
|
|
694
|
+
const summary = createEmptyCategorySummary();
|
|
695
|
+
if (!existsSync(agentsDir))
|
|
696
|
+
return summary;
|
|
697
|
+
const manifest = tryReadCatalogManifest();
|
|
698
|
+
const agentStatusByName = manifest
|
|
699
|
+
? getCatalogAgentStatusByName(manifest)
|
|
700
|
+
: null;
|
|
701
|
+
for (const [name, agent] of Object.entries(AGENT_DEFINITIONS)) {
|
|
702
|
+
const status = agentStatusByName?.get(name);
|
|
703
|
+
if (agentStatusByName && !isNativeAgentInstallableStatus(status))
|
|
704
|
+
continue;
|
|
705
|
+
const dst = join(agentsDir, `${name}.toml`);
|
|
706
|
+
const promptPath = join(pkgRoot, "prompts", `${name}.md`);
|
|
707
|
+
if (!existsSync(dst) || !existsSync(promptPath))
|
|
708
|
+
continue;
|
|
709
|
+
const promptContent = await readFile(promptPath, "utf-8");
|
|
710
|
+
const expectedToml = generateAgentToml(agent, promptContent, {
|
|
711
|
+
codexHomeOverride: join(agentsDir, ".."),
|
|
712
|
+
});
|
|
713
|
+
const installedToml = await readFile(dst, "utf-8");
|
|
714
|
+
if (installedToml !== expectedToml &&
|
|
715
|
+
!isGeneratedOmxNativeAgentToml(installedToml, name)) {
|
|
716
|
+
summary.skipped += 1;
|
|
717
|
+
if (options.verbose) {
|
|
718
|
+
console.log(` skipped legacy native agent cleanup for ${name}.toml: installed content is not an OMX-generated native agent`);
|
|
719
|
+
}
|
|
720
|
+
continue;
|
|
721
|
+
}
|
|
722
|
+
if (await ensureBackup(dst, true, backupContext, options)) {
|
|
723
|
+
summary.backedUp += 1;
|
|
724
|
+
}
|
|
725
|
+
if (!options.dryRun) {
|
|
726
|
+
await rm(dst, { force: true });
|
|
727
|
+
}
|
|
728
|
+
summary.removed += 1;
|
|
729
|
+
if (options.verbose) {
|
|
730
|
+
console.log(` ${options.dryRun ? "would archive and remove" : "archived and removed"} legacy native agent ${name}.toml`);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
if (manifest) {
|
|
734
|
+
const generatedCleanup = await cleanupGeneratedNonInstallableNativeAgents(agentsDir, manifest, backupContext, options);
|
|
735
|
+
summary.backedUp += generatedCleanup.backedUp;
|
|
736
|
+
summary.removed += generatedCleanup.removed;
|
|
737
|
+
}
|
|
738
|
+
await removeEmptyDirectoryIfPresent(agentsDir, options);
|
|
739
|
+
return summary;
|
|
740
|
+
}
|
|
741
|
+
function stripPluginModeLegacyRootDefaults(config) {
|
|
742
|
+
const lines = config.split(/\r?\n/);
|
|
743
|
+
const firstTableIndex = lines.findIndex((line) => /^\s*\[/.test(line));
|
|
744
|
+
const boundary = firstTableIndex >= 0 ? firstTableIndex : lines.length;
|
|
745
|
+
const result = [];
|
|
746
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
747
|
+
const line = lines[index];
|
|
748
|
+
if (index < boundary &&
|
|
749
|
+
line.trim() ===
|
|
750
|
+
"# oh-my-codex top-level settings (must be before any [table])") {
|
|
751
|
+
continue;
|
|
752
|
+
}
|
|
753
|
+
if (index < boundary &&
|
|
754
|
+
/^\s*notify\s*=\s*\["node",\s*".*notify-hook\.js"\]\s*$/.test(line)) {
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
if (index < boundary &&
|
|
758
|
+
/^\s*model_reasoning_effort\s*=\s*"medium"\s*$/.test(line)) {
|
|
759
|
+
continue;
|
|
760
|
+
}
|
|
761
|
+
if (index < boundary &&
|
|
762
|
+
/^\s*developer_instructions\s*=/.test(line) &&
|
|
763
|
+
line.includes("You have oh-my-codex installed.")) {
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
result.push(line);
|
|
767
|
+
}
|
|
768
|
+
return result.join("\n").replace(/\n{3,}/g, "\n\n");
|
|
769
|
+
}
|
|
770
|
+
function rootHasTomlKey(config, key) {
|
|
771
|
+
const lines = config.split(/\r?\n/);
|
|
772
|
+
const firstTableIndex = lines.findIndex((line) => /^\s*\[/.test(line));
|
|
773
|
+
const boundary = firstTableIndex >= 0 ? firstTableIndex : lines.length;
|
|
774
|
+
const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
775
|
+
const pattern = new RegExp(`^\\s*${escapedKey}\\s*=`);
|
|
776
|
+
return lines.slice(0, boundary).some((line) => pattern.test(line));
|
|
777
|
+
}
|
|
778
|
+
function replaceRootTomlKey(config, key, line) {
|
|
779
|
+
const lines = config.trimEnd().split(/\r?\n/);
|
|
780
|
+
const firstTableIndex = lines.findIndex((entry) => /^\s*\[/.test(entry));
|
|
781
|
+
const boundary = firstTableIndex < 0 ? lines.length : firstTableIndex;
|
|
782
|
+
const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
783
|
+
const pattern = new RegExp(`^\\s*${escapedKey}\\s*=`);
|
|
784
|
+
for (let i = 0; i < boundary; i++) {
|
|
785
|
+
if (pattern.test(lines[i])) {
|
|
786
|
+
lines[i] = line;
|
|
787
|
+
return lines.join("\n") + "\n";
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return insertRootTomlKey(config, line);
|
|
791
|
+
}
|
|
792
|
+
function insertRootTomlKey(config, line) {
|
|
793
|
+
const lines = config.trimEnd().split(/\r?\n/);
|
|
794
|
+
if (lines.length === 1 && lines[0] === "")
|
|
795
|
+
return `${line}\n`;
|
|
796
|
+
const firstTableIndex = lines.findIndex((entry) => /^\s*\[/.test(entry));
|
|
797
|
+
if (firstTableIndex < 0)
|
|
798
|
+
return `${lines.join("\n")}\n${line}\n`;
|
|
799
|
+
const before = lines
|
|
800
|
+
.slice(0, firstTableIndex)
|
|
801
|
+
.filter((entry) => entry.trim() !== "");
|
|
802
|
+
const after = lines.slice(firstTableIndex);
|
|
803
|
+
return [...before, line, "", ...after].join("\n") + "\n";
|
|
804
|
+
}
|
|
805
|
+
async function ensurePluginMarketplaceRegistration(configPath, pkgRoot, backupContext, summary, options) {
|
|
806
|
+
const packagedMarketplace = await resolvePackagedOmxMarketplace(pkgRoot);
|
|
807
|
+
if (!packagedMarketplace) {
|
|
808
|
+
summary.skipped += 1;
|
|
809
|
+
return "unavailable";
|
|
810
|
+
}
|
|
811
|
+
const existingConfig = existsSync(configPath)
|
|
812
|
+
? await readFile(configPath, "utf-8")
|
|
813
|
+
: "";
|
|
814
|
+
const nextConfig = upsertLocalOmxMarketplaceRegistration(existingConfig, pkgRoot);
|
|
815
|
+
const destinationExists = existsSync(configPath);
|
|
816
|
+
if (nextConfig === existingConfig) {
|
|
817
|
+
summary.unchanged += 1;
|
|
818
|
+
return "unchanged";
|
|
819
|
+
}
|
|
820
|
+
if (await ensureBackup(configPath, destinationExists, backupContext, options)) {
|
|
821
|
+
summary.backedUp += 1;
|
|
822
|
+
}
|
|
823
|
+
if (!options.dryRun) {
|
|
824
|
+
await mkdir(dirname(configPath), { recursive: true });
|
|
825
|
+
await writeFile(configPath, nextConfig);
|
|
826
|
+
}
|
|
827
|
+
summary.updated += 1;
|
|
828
|
+
if (options.verbose) {
|
|
829
|
+
console.log(` ${options.dryRun ? "would register" : "registered"} local Codex plugin marketplace ${OMX_LOCAL_MARKETPLACE_NAME} from ${pkgRoot}`);
|
|
830
|
+
}
|
|
831
|
+
return "updated";
|
|
832
|
+
}
|
|
833
|
+
async function applyPluginModeHooksConfig(configPath, hooksPath, pkgRoot, backupContext, summary, options) {
|
|
834
|
+
const existingConfig = existsSync(configPath)
|
|
835
|
+
? await readFile(configPath, "utf-8")
|
|
836
|
+
: "";
|
|
837
|
+
const nextConfig = upsertCodexHooksFeatureFlag(existingConfig).trimEnd() + "\n";
|
|
838
|
+
if (nextConfig !== existingConfig) {
|
|
839
|
+
if (await ensureBackup(configPath, existsSync(configPath), backupContext, options)) {
|
|
840
|
+
summary.backedUp += 1;
|
|
841
|
+
}
|
|
842
|
+
if (!options.dryRun) {
|
|
843
|
+
await mkdir(dirname(configPath), { recursive: true });
|
|
844
|
+
await writeFile(configPath, nextConfig);
|
|
845
|
+
}
|
|
846
|
+
summary.updated += 1;
|
|
847
|
+
}
|
|
848
|
+
else {
|
|
849
|
+
summary.unchanged += 1;
|
|
850
|
+
}
|
|
851
|
+
const existingHooksContent = existsSync(hooksPath)
|
|
852
|
+
? await readFile(hooksPath, "utf-8")
|
|
853
|
+
: null;
|
|
854
|
+
const hooksConfig = mergeManagedCodexHooksConfig(existingHooksContent, pkgRoot);
|
|
855
|
+
await syncManagedContent(hooksConfig, hooksPath, summary, backupContext, options, `native hooks ${hooksPath}`);
|
|
856
|
+
if (options.verbose) {
|
|
857
|
+
console.log(` ${options.dryRun ? "would configure" : "configured"} plugin-mode native hooks at ${hooksPath}`);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
async function applyPluginDeveloperInstructionsDefault(configPath, backupContext, summary, options) {
|
|
861
|
+
const existing = existsSync(configPath)
|
|
862
|
+
? await readFile(configPath, "utf-8")
|
|
863
|
+
: "";
|
|
864
|
+
const line = `developer_instructions = ${JSON.stringify(OMX_DEVELOPER_INSTRUCTIONS)}`;
|
|
865
|
+
const hasExistingDeveloperInstructions = rootHasTomlKey(existing, "developer_instructions");
|
|
866
|
+
if (hasExistingDeveloperInstructions) {
|
|
867
|
+
const overwrite = options.pluginDeveloperInstructionsOverwritePrompt
|
|
868
|
+
? await options.pluginDeveloperInstructionsOverwritePrompt(configPath)
|
|
869
|
+
: await promptForPluginDeveloperInstructionsOverwrite(configPath);
|
|
870
|
+
if (!overwrite) {
|
|
871
|
+
summary.skipped += 1;
|
|
872
|
+
if (options.verbose) {
|
|
873
|
+
console.log(" skipped plugin developer_instructions default: root developer_instructions already exists");
|
|
874
|
+
}
|
|
875
|
+
return "exists";
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
const nextConfig = hasExistingDeveloperInstructions
|
|
879
|
+
? replaceRootTomlKey(existing, "developer_instructions", line)
|
|
880
|
+
: insertRootTomlKey(existing, line);
|
|
881
|
+
const destinationExists = existsSync(configPath);
|
|
882
|
+
if (await ensureBackup(configPath, destinationExists, backupContext, options)) {
|
|
883
|
+
summary.backedUp += 1;
|
|
884
|
+
}
|
|
885
|
+
if (!options.dryRun) {
|
|
886
|
+
await mkdir(dirname(configPath), { recursive: true });
|
|
887
|
+
await writeFile(configPath, nextConfig);
|
|
888
|
+
}
|
|
889
|
+
summary.updated += 1;
|
|
890
|
+
if (options.verbose) {
|
|
891
|
+
console.log(` ${options.dryRun ? "would add" : "added"} plugin developer_instructions default to ${configPath}`);
|
|
892
|
+
}
|
|
893
|
+
return "updated";
|
|
894
|
+
}
|
|
895
|
+
async function cleanupPluginModeLegacyConfig(configPath, backupContext, options) {
|
|
896
|
+
if (!existsSync(configPath))
|
|
897
|
+
return false;
|
|
898
|
+
const original = await readFile(configPath, "utf-8");
|
|
899
|
+
let config = original;
|
|
900
|
+
config = stripExistingOmxBlocks(config).cleaned;
|
|
901
|
+
config = stripExistingSharedMcpRegistryBlock(config).cleaned;
|
|
902
|
+
config = stripPluginModeLegacyRootDefaults(config);
|
|
903
|
+
config = stripOmxSeededBehavioralDefaults(config);
|
|
904
|
+
config = stripOmxFeatureFlags(config);
|
|
905
|
+
config = stripOmxEnvSettings(config);
|
|
906
|
+
config = config.trim();
|
|
907
|
+
const nextConfig = config.length > 0 ? `${config}\n` : "";
|
|
908
|
+
if (nextConfig === original)
|
|
909
|
+
return false;
|
|
910
|
+
if (await ensureBackup(configPath, true, backupContext, options)) {
|
|
911
|
+
// backup created for pre-existing config
|
|
912
|
+
}
|
|
913
|
+
if (!options.dryRun) {
|
|
914
|
+
if (nextConfig.length === 0) {
|
|
915
|
+
await rm(configPath, { force: true });
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
918
|
+
await writeFile(configPath, nextConfig);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
if (options.verbose) {
|
|
922
|
+
console.log(` ${options.dryRun ? "would clean" : nextConfig.length === 0 ? "removed" : "cleaned"} legacy OMX config ${basename(configPath)}`);
|
|
923
|
+
}
|
|
924
|
+
return true;
|
|
925
|
+
}
|
|
926
|
+
async function cleanupPluginModeLegacyAgentsMd(agentsMdPath, backupContext, options) {
|
|
927
|
+
if (!existsSync(agentsMdPath))
|
|
928
|
+
return false;
|
|
929
|
+
const content = await readFile(agentsMdPath, "utf-8");
|
|
930
|
+
if (!isOmxGeneratedAgentsMd(content))
|
|
931
|
+
return false;
|
|
932
|
+
if (await ensureBackup(agentsMdPath, true, backupContext, options)) {
|
|
933
|
+
// backup created for pre-existing AGENTS.md
|
|
934
|
+
}
|
|
935
|
+
if (!options.dryRun) {
|
|
936
|
+
await rm(agentsMdPath, { force: true });
|
|
937
|
+
}
|
|
938
|
+
if (options.verbose) {
|
|
939
|
+
console.log(` ${options.dryRun ? "would remove" : "removed"} legacy OMX-generated AGENTS.md`);
|
|
940
|
+
}
|
|
941
|
+
return true;
|
|
942
|
+
}
|
|
460
943
|
export async function setup(options = {}) {
|
|
461
|
-
const { force = false, dryRun = false, scope: requestedScope, verbose = false, modelUpgradePrompt, } = options;
|
|
944
|
+
const { force = false, dryRun = false, installMode: requestedInstallMode, scope: requestedScope, verbose = false, setupScopePrompt, persistedSetupReviewPrompt, installModePrompt, modelUpgradePrompt, pluginAgentsMdPrompt, pluginDeveloperInstructionsPrompt, pluginDeveloperInstructionsOverwritePrompt, } = options;
|
|
462
945
|
const pkgRoot = getPackageRoot();
|
|
463
946
|
const projectRoot = process.cwd();
|
|
464
|
-
const
|
|
947
|
+
const persistedPreferences = await readPersistedSetupPreferences(projectRoot, { warnOnLegacyScope: true });
|
|
948
|
+
let persistedReviewDecision = "keep";
|
|
949
|
+
const effectiveScopeForInstallMode = requestedScope ?? persistedPreferences?.scope ?? DEFAULT_SETUP_SCOPE;
|
|
950
|
+
const wouldUsePersistedScope = !requestedScope && Boolean(persistedPreferences?.scope);
|
|
951
|
+
const wouldUsePersistedInstallMode = !requestedInstallMode &&
|
|
952
|
+
Boolean(persistedPreferences?.installMode) &&
|
|
953
|
+
(!persistedPreferences?.scope ||
|
|
954
|
+
persistedPreferences.scope === effectiveScopeForInstallMode);
|
|
955
|
+
const shouldReviewPersistedSetup = hasPersistedSetupPreferences(persistedPreferences) &&
|
|
956
|
+
(wouldUsePersistedScope || wouldUsePersistedInstallMode) &&
|
|
957
|
+
(typeof persistedSetupReviewPrompt === "function" ||
|
|
958
|
+
(process.stdin.isTTY && process.stdout.isTTY));
|
|
959
|
+
if (shouldReviewPersistedSetup) {
|
|
960
|
+
persistedReviewDecision = persistedSetupReviewPrompt
|
|
961
|
+
? await persistedSetupReviewPrompt(persistedPreferences)
|
|
962
|
+
: await promptForPersistedSetupReview(persistedPreferences);
|
|
963
|
+
console.log(`Setup preference review: ${persistedReviewDecision} (${formatPersistedSetupPreferenceSummary(persistedPreferences)})\n`);
|
|
964
|
+
}
|
|
965
|
+
const resolvedScope = await resolveSetupScope(projectRoot, requestedScope, persistedReviewDecision, persistedPreferences, setupScopePrompt);
|
|
966
|
+
const resolvedInstallMode = await resolveSetupInstallMode(projectRoot, resolvedScope.scope, requestedInstallMode, installModePrompt, persistedReviewDecision, persistedPreferences);
|
|
465
967
|
const scopeDirs = resolveScopeDirectories(resolvedScope.scope, projectRoot);
|
|
466
968
|
const scopeSourceMessage = resolvedScope.source === "persisted" ? " (from .omx/setup-scope.json)" : "";
|
|
467
969
|
const backupContext = getBackupContext(resolvedScope.scope, projectRoot);
|
|
970
|
+
const isPluginInstallMode = resolvedInstallMode?.installMode === "plugin";
|
|
971
|
+
const pluginAgentsMdDst = resolvedScope.scope === "project"
|
|
972
|
+
? join(projectRoot, "AGENTS.md")
|
|
973
|
+
: join(scopeDirs.codexHomeDir, "AGENTS.md");
|
|
974
|
+
const usePluginDeveloperInstructionsDefault = isPluginInstallMode
|
|
975
|
+
? pluginDeveloperInstructionsPrompt
|
|
976
|
+
? await pluginDeveloperInstructionsPrompt(scopeDirs.codexConfigFile)
|
|
977
|
+
: await promptForPluginDeveloperInstructionsDefault(scopeDirs.codexConfigFile)
|
|
978
|
+
: false;
|
|
979
|
+
const usePluginAgentsMdDefault = isPluginInstallMode
|
|
980
|
+
? pluginAgentsMdPrompt
|
|
981
|
+
? await pluginAgentsMdPrompt(pluginAgentsMdDst)
|
|
982
|
+
: await promptForPluginAgentsMdDefault(pluginAgentsMdDst)
|
|
983
|
+
: false;
|
|
468
984
|
console.log("oh-my-codex setup");
|
|
469
985
|
console.log("=================\n");
|
|
470
986
|
console.log(`Using setup scope: ${resolvedScope.scope}${scopeSourceMessage}\n`);
|
|
987
|
+
if (resolvedInstallMode) {
|
|
988
|
+
const installModeSourceMessage = resolvedInstallMode.source === "persisted"
|
|
989
|
+
? " (from .omx/setup-scope.json)"
|
|
990
|
+
: "";
|
|
991
|
+
console.log(`Using setup install mode: ${resolvedInstallMode.installMode}${installModeSourceMessage}\n`);
|
|
992
|
+
}
|
|
471
993
|
// Step 1: Ensure directories exist
|
|
472
994
|
console.log("[1/8] Creating directories...");
|
|
473
|
-
const dirs =
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
995
|
+
const dirs = isPluginInstallMode
|
|
996
|
+
? [
|
|
997
|
+
scopeDirs.codexHomeDir,
|
|
998
|
+
omxStateDir(projectRoot),
|
|
999
|
+
omxPlansDir(projectRoot),
|
|
1000
|
+
omxLogsDir(projectRoot),
|
|
1001
|
+
]
|
|
1002
|
+
: [
|
|
1003
|
+
scopeDirs.codexHomeDir,
|
|
1004
|
+
scopeDirs.promptsDir,
|
|
1005
|
+
scopeDirs.skillsDir,
|
|
1006
|
+
scopeDirs.nativeAgentsDir,
|
|
1007
|
+
omxStateDir(projectRoot),
|
|
1008
|
+
omxPlansDir(projectRoot),
|
|
1009
|
+
omxLogsDir(projectRoot),
|
|
1010
|
+
];
|
|
482
1011
|
for (const dir of dirs) {
|
|
483
1012
|
if (!dryRun) {
|
|
484
1013
|
await mkdir(dir, { recursive: true });
|
|
@@ -486,7 +1015,17 @@ export async function setup(options = {}) {
|
|
|
486
1015
|
if (verbose)
|
|
487
1016
|
console.log(` mkdir ${dir}`);
|
|
488
1017
|
}
|
|
489
|
-
|
|
1018
|
+
const setupPreferencesToPersist = resolvedInstallMode &&
|
|
1019
|
+
(resolvedScope.scope === "user" ||
|
|
1020
|
+
resolvedInstallMode.installMode === "plugin")
|
|
1021
|
+
? {
|
|
1022
|
+
scope: resolvedScope.scope,
|
|
1023
|
+
installMode: resolvedInstallMode.installMode,
|
|
1024
|
+
}
|
|
1025
|
+
: {
|
|
1026
|
+
scope: resolvedScope.scope,
|
|
1027
|
+
};
|
|
1028
|
+
await persistSetupPreferences(projectRoot, setupPreferencesToPersist, {
|
|
490
1029
|
dryRun,
|
|
491
1030
|
verbose,
|
|
492
1031
|
});
|
|
@@ -507,37 +1046,63 @@ export async function setup(options = {}) {
|
|
|
507
1046
|
{
|
|
508
1047
|
const promptsSrc = join(pkgRoot, "prompts");
|
|
509
1048
|
const promptsDst = scopeDirs.promptsDir;
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
1049
|
+
if (isPluginInstallMode) {
|
|
1050
|
+
summary.prompts = await cleanupPluginModeLegacyPrompts(promptsSrc, promptsDst, backupContext, { dryRun, verbose });
|
|
1051
|
+
console.log(summary.prompts.removed > 0
|
|
1052
|
+
? ` ${dryRun ? "Would archive and remove" : "Archived and removed"} ${summary.prompts.removed} legacy OMX-managed prompt file(s).\n`
|
|
1053
|
+
: " Prompt refresh skipped; no legacy OMX-managed prompt files found.\n");
|
|
1054
|
+
}
|
|
1055
|
+
else {
|
|
1056
|
+
summary.prompts = await installPrompts(promptsSrc, promptsDst, backupContext, { force, dryRun, verbose });
|
|
1057
|
+
const cleanedLegacyPromptShims = await cleanupLegacySkillPromptShims(promptsSrc, promptsDst, {
|
|
1058
|
+
dryRun,
|
|
1059
|
+
verbose,
|
|
1060
|
+
});
|
|
1061
|
+
summary.prompts.removed += cleanedLegacyPromptShims;
|
|
1062
|
+
if (cleanedLegacyPromptShims > 0) {
|
|
1063
|
+
if (dryRun) {
|
|
1064
|
+
console.log(` Would remove ${cleanedLegacyPromptShims} legacy skill prompt shim file(s).`);
|
|
1065
|
+
}
|
|
1066
|
+
else {
|
|
1067
|
+
console.log(` Removed ${cleanedLegacyPromptShims} legacy skill prompt shim file(s).`);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
if (catalogCounts) {
|
|
1071
|
+
console.log(` Prompt refresh complete (catalog baseline: ${catalogCounts.prompts}).\n`);
|
|
519
1072
|
}
|
|
520
1073
|
else {
|
|
521
|
-
console.log(
|
|
1074
|
+
console.log(" Prompt refresh complete.\n");
|
|
522
1075
|
}
|
|
523
1076
|
}
|
|
524
|
-
if (catalogCounts) {
|
|
525
|
-
console.log(` Prompt refresh complete (catalog baseline: ${catalogCounts.prompts}).\n`);
|
|
526
|
-
}
|
|
527
|
-
else {
|
|
528
|
-
console.log(" Prompt refresh complete.\n");
|
|
529
|
-
}
|
|
530
1077
|
}
|
|
531
1078
|
// Step 3: Install skills
|
|
532
1079
|
console.log("[3/8] Installing skills...");
|
|
533
1080
|
{
|
|
534
1081
|
const skillsSrc = join(pkgRoot, "skills");
|
|
535
1082
|
const skillsDst = scopeDirs.skillsDir;
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
dryRun,
|
|
539
|
-
|
|
540
|
-
|
|
1083
|
+
if (isPluginInstallMode) {
|
|
1084
|
+
summary.skills = createEmptyCategorySummary();
|
|
1085
|
+
const cleanup = await cleanupLegacyManagedSkills(skillsSrc, skillsDst, backupContext, { dryRun, verbose });
|
|
1086
|
+
summary.skills.backedUp += cleanup.backedUp;
|
|
1087
|
+
summary.skills.removed += cleanup.removedSkillNames.length;
|
|
1088
|
+
summary.skills.skipped += cleanup.skippedSkillNames.length;
|
|
1089
|
+
for (const warning of cleanup.warnings) {
|
|
1090
|
+
console.log(` warning: ${warning}`);
|
|
1091
|
+
}
|
|
1092
|
+
if (cleanup.removedSkillNames.length > 0) {
|
|
1093
|
+
console.log(` ${dryRun ? "Would remove" : "Removed"} ${cleanup.removedSkillNames.length} legacy OMX-managed skill director${cleanup.removedSkillNames.length === 1 ? "y" : "ies"}.`);
|
|
1094
|
+
}
|
|
1095
|
+
else {
|
|
1096
|
+
console.log(" Skill refresh skipped; no removable legacy OMX-managed skill directories found.");
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
else {
|
|
1100
|
+
summary.skills = await installSkills(skillsSrc, skillsDst, backupContext, {
|
|
1101
|
+
force,
|
|
1102
|
+
dryRun,
|
|
1103
|
+
verbose,
|
|
1104
|
+
});
|
|
1105
|
+
}
|
|
541
1106
|
if (catalogCounts) {
|
|
542
1107
|
console.log(` Skill refresh complete (catalog baseline: ${catalogCounts.skills}).\n`);
|
|
543
1108
|
}
|
|
@@ -547,7 +1112,13 @@ export async function setup(options = {}) {
|
|
|
547
1112
|
}
|
|
548
1113
|
// Step 4: Install native agent configs
|
|
549
1114
|
console.log("[4/8] Installing native agent configs...");
|
|
550
|
-
{
|
|
1115
|
+
if (isPluginInstallMode) {
|
|
1116
|
+
summary.nativeAgents = await cleanupPluginModeLegacyNativeAgents(pkgRoot, scopeDirs.nativeAgentsDir, backupContext, { dryRun, verbose });
|
|
1117
|
+
console.log(summary.nativeAgents.removed > 0
|
|
1118
|
+
? ` ${dryRun ? "Would archive and remove" : "Archived and removed"} ${summary.nativeAgents.removed} legacy OMX-managed native agent config(s).\n`
|
|
1119
|
+
: " Native agent refresh skipped; no legacy OMX-managed native agent configs found.\n");
|
|
1120
|
+
}
|
|
1121
|
+
else {
|
|
551
1122
|
summary.nativeAgents = await refreshNativeAgentConfigs(pkgRoot, scopeDirs.nativeAgentsDir, backupContext, {
|
|
552
1123
|
force,
|
|
553
1124
|
dryRun,
|
|
@@ -557,39 +1128,93 @@ export async function setup(options = {}) {
|
|
|
557
1128
|
}
|
|
558
1129
|
// Step 5: Update config.toml
|
|
559
1130
|
console.log("[5/8] Updating config.toml...");
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
1131
|
+
let resolvedConfig = "";
|
|
1132
|
+
let omxManagesTui = false;
|
|
1133
|
+
if (isPluginInstallMode) {
|
|
1134
|
+
const configCleaned = await cleanupPluginModeLegacyConfig(scopeDirs.codexConfigFile, backupContext, { dryRun, verbose });
|
|
1135
|
+
if (configCleaned)
|
|
1136
|
+
summary.config.removed += 1;
|
|
1137
|
+
console.log(configCleaned
|
|
1138
|
+
? ` ${dryRun ? "Would clean" : "Cleaned"} legacy OMX config entries for plugin mode.\n`
|
|
1139
|
+
: " Config refresh skipped; no legacy OMX config entries found.\n");
|
|
1140
|
+
await applyPluginModeHooksConfig(scopeDirs.codexConfigFile, scopeDirs.codexHooksFile, pkgRoot, backupContext, summary.config, { dryRun, verbose });
|
|
1141
|
+
const pluginMarketplaceResult = await ensurePluginMarketplaceRegistration(scopeDirs.codexConfigFile, pkgRoot, backupContext, summary.config, { dryRun, verbose });
|
|
1142
|
+
if (pluginMarketplaceResult === "unavailable") {
|
|
1143
|
+
console.log(` warning: packaged ${OMX_LOCAL_MARKETPLACE_NAME} Codex plugin marketplace metadata not found; /skills plugin discovery was not registered.`);
|
|
1144
|
+
}
|
|
1145
|
+
else if (pluginMarketplaceResult === "updated") {
|
|
1146
|
+
console.log(` ${dryRun ? "Would register" : "Registered"} local Codex plugin marketplace ${OMX_LOCAL_MARKETPLACE_NAME} (${pkgRoot}).`);
|
|
1147
|
+
}
|
|
1148
|
+
else {
|
|
1149
|
+
console.log(` Local Codex plugin marketplace ${OMX_LOCAL_MARKETPLACE_NAME} already registered (${pkgRoot}).`);
|
|
1150
|
+
}
|
|
1151
|
+
resolvedConfig = existsSync(scopeDirs.codexConfigFile)
|
|
1152
|
+
? await readFile(scopeDirs.codexConfigFile, "utf-8")
|
|
1153
|
+
: "";
|
|
1154
|
+
console.log(` Native Codex hooks refresh complete (${scopeDirs.codexHooksFile}).\n`);
|
|
1155
|
+
if (usePluginDeveloperInstructionsDefault) {
|
|
1156
|
+
const developerInstructionsResult = await applyPluginDeveloperInstructionsDefault(scopeDirs.codexConfigFile, backupContext, summary.config, {
|
|
1157
|
+
dryRun,
|
|
1158
|
+
verbose,
|
|
1159
|
+
pluginDeveloperInstructionsOverwritePrompt,
|
|
1160
|
+
});
|
|
1161
|
+
if (developerInstructionsResult === "updated") {
|
|
1162
|
+
resolvedConfig = existsSync(scopeDirs.codexConfigFile)
|
|
1163
|
+
? await readFile(scopeDirs.codexConfigFile, "utf-8")
|
|
1164
|
+
: "";
|
|
1165
|
+
console.log(` ${dryRun ? "Would add" : "Added"} plugin-mode developer_instructions default (${scopeDirs.codexConfigFile}).\n`);
|
|
1166
|
+
}
|
|
1167
|
+
else {
|
|
1168
|
+
console.log(` Preserved existing developer_instructions in ${scopeDirs.codexConfigFile}.\n`);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
else {
|
|
1172
|
+
console.log(" Plugin-mode developer_instructions default not selected.\n");
|
|
1173
|
+
}
|
|
582
1174
|
}
|
|
583
|
-
|
|
584
|
-
|
|
1175
|
+
else {
|
|
1176
|
+
const registryCandidates = getUnifiedMcpRegistryCandidates();
|
|
1177
|
+
const defaultRegistryCandidates = registryCandidates.slice(0, 1);
|
|
1178
|
+
const legacyRegistryCandidate = getLegacyUnifiedMcpRegistryCandidate();
|
|
1179
|
+
const sharedMcpRegistry = await loadUnifiedMcpRegistry({
|
|
1180
|
+
candidates: options.mcpRegistryCandidates ?? defaultRegistryCandidates,
|
|
1181
|
+
});
|
|
1182
|
+
if (!options.mcpRegistryCandidates &&
|
|
1183
|
+
!sharedMcpRegistry.sourcePath &&
|
|
1184
|
+
existsSync(legacyRegistryCandidate) &&
|
|
1185
|
+
!existsSync(defaultRegistryCandidates[0])) {
|
|
1186
|
+
console.log(` warning: legacy shared MCP registry detected at ${legacyRegistryCandidate} but ignored by default; move it to ${defaultRegistryCandidates[0]} if you still want setup to sync those servers`);
|
|
1187
|
+
}
|
|
1188
|
+
if (verbose && sharedMcpRegistry.sourcePath) {
|
|
1189
|
+
console.log(` shared MCP registry: ${sharedMcpRegistry.sourcePath} (${sharedMcpRegistry.servers.length} servers)`);
|
|
1190
|
+
}
|
|
1191
|
+
for (const warning of sharedMcpRegistry.warnings) {
|
|
1192
|
+
console.log(` warning: ${warning}`);
|
|
1193
|
+
}
|
|
1194
|
+
const statusLinePreset = await resolveStatusLinePresetForSetup(projectRoot, { force });
|
|
1195
|
+
const managedConfig = await updateManagedConfig(scopeDirs.codexConfigFile, pkgRoot, sharedMcpRegistry, summary.config, backupContext, {
|
|
1196
|
+
dryRun,
|
|
1197
|
+
modelUpgradePrompt,
|
|
1198
|
+
verbose,
|
|
1199
|
+
statusLinePreset,
|
|
1200
|
+
forceStatusLinePreset: force,
|
|
1201
|
+
});
|
|
1202
|
+
resolvedConfig = managedConfig.finalConfig;
|
|
1203
|
+
omxManagesTui = managedConfig.omxManagesTui;
|
|
1204
|
+
if (managedConfig.repairedLegacyTeamRunTable) {
|
|
1205
|
+
console.log(" Removed retired [mcp_servers.omx_team_run] config during refresh.");
|
|
1206
|
+
}
|
|
1207
|
+
if (resolvedScope.scope === "user") {
|
|
1208
|
+
await syncClaudeCodeMcpSettings(sharedMcpRegistry, summary.config, backupContext, { dryRun, verbose });
|
|
1209
|
+
}
|
|
1210
|
+
console.log(` Config refresh complete (${scopeDirs.codexConfigFile}).\n`);
|
|
1211
|
+
const existingHooksContent = existsSync(scopeDirs.codexHooksFile)
|
|
1212
|
+
? await readFile(scopeDirs.codexHooksFile, "utf-8")
|
|
1213
|
+
: null;
|
|
1214
|
+
const hooksConfig = mergeManagedCodexHooksConfig(existingHooksContent, pkgRoot);
|
|
1215
|
+
await syncManagedContent(hooksConfig, scopeDirs.codexHooksFile, summary.config, backupContext, { dryRun, verbose }, `native hooks ${scopeDirs.codexHooksFile}`);
|
|
1216
|
+
console.log(` Native Codex hooks refresh complete (${scopeDirs.codexHooksFile}).\n`);
|
|
585
1217
|
}
|
|
586
|
-
console.log(` Config refresh complete (${scopeDirs.codexConfigFile}).\n`);
|
|
587
|
-
const existingHooksContent = existsSync(scopeDirs.codexHooksFile)
|
|
588
|
-
? await readFile(scopeDirs.codexHooksFile, "utf-8")
|
|
589
|
-
: null;
|
|
590
|
-
const hooksConfig = mergeManagedCodexHooksConfig(existingHooksContent, pkgRoot);
|
|
591
|
-
await syncManagedContent(hooksConfig, scopeDirs.codexHooksFile, summary.config, backupContext, { dryRun, verbose }, `native hooks ${scopeDirs.codexHooksFile}`);
|
|
592
|
-
console.log(` Native Codex hooks refresh complete (${scopeDirs.codexHooksFile}).\n`);
|
|
593
1218
|
// Step 5.5: Verify team CLI interop surface is available.
|
|
594
1219
|
console.log("[5.5/8] Verifying Team CLI API interop...");
|
|
595
1220
|
const teamToolsCheck = await verifyTeamCliApiInterop(pkgRoot);
|
|
@@ -603,84 +1228,159 @@ export async function setup(options = {}) {
|
|
|
603
1228
|
console.log();
|
|
604
1229
|
// Step 6: Generate AGENTS.md
|
|
605
1230
|
console.log("[6/8] Generating AGENTS.md...");
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
1231
|
+
if (isPluginInstallMode) {
|
|
1232
|
+
const agentsMdRemoved = await cleanupPluginModeLegacyAgentsMd(pluginAgentsMdDst, backupContext, { dryRun, verbose });
|
|
1233
|
+
if (agentsMdRemoved) {
|
|
1234
|
+
summary.agentsMd.removed += 1;
|
|
1235
|
+
console.log(` ${dryRun ? "Would remove" : "Removed"} legacy OMX-generated AGENTS.md for plugin mode.\n`);
|
|
1236
|
+
}
|
|
1237
|
+
if (usePluginAgentsMdDefault) {
|
|
1238
|
+
const agentsMdSrc = join(pkgRoot, "templates", "AGENTS.md");
|
|
1239
|
+
if (existsSync(agentsMdSrc)) {
|
|
1240
|
+
const content = await readFile(agentsMdSrc, "utf-8");
|
|
1241
|
+
const modelTableContext = resolveAgentsModelTableContext(resolvedConfig, {
|
|
1242
|
+
codexHomeOverride: scopeDirs.codexHomeDir,
|
|
1243
|
+
});
|
|
1244
|
+
const rewritten = upsertAgentsModelTable(addGeneratedAgentsMarker(applyScopePathRewritesToAgentsTemplate(content, resolvedScope.scope)), modelTableContext);
|
|
1245
|
+
const result = await syncManagedAgentsContent(rewritten, pluginAgentsMdDst, summary.agentsMd, backupContext, {
|
|
1246
|
+
agentsOverwritePrompt: options.agentsOverwritePrompt,
|
|
1247
|
+
dryRun,
|
|
1248
|
+
force,
|
|
1249
|
+
verbose,
|
|
1250
|
+
});
|
|
1251
|
+
if (result === "updated") {
|
|
1252
|
+
console.log(resolvedScope.scope === "project"
|
|
1253
|
+
? " Generated plugin-mode AGENTS.md defaults in project root."
|
|
1254
|
+
: ` Generated plugin-mode AGENTS.md defaults in ${scopeDirs.codexHomeDir}.`);
|
|
1255
|
+
}
|
|
1256
|
+
else if (result === "unchanged") {
|
|
1257
|
+
console.log(resolvedScope.scope === "project"
|
|
1258
|
+
? " Plugin-mode AGENTS.md defaults already up to date in project root."
|
|
1259
|
+
: ` Plugin-mode AGENTS.md defaults already up to date in ${scopeDirs.codexHomeDir}.`);
|
|
1260
|
+
}
|
|
1261
|
+
else {
|
|
1262
|
+
console.log(` Skipped plugin-mode AGENTS.md defaults for ${pluginAgentsMdDst}.`);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
else {
|
|
1266
|
+
summary.agentsMd.skipped += 1;
|
|
1267
|
+
console.log(" AGENTS.md template not found, skipping.");
|
|
631
1268
|
}
|
|
632
1269
|
}
|
|
633
|
-
|
|
634
|
-
sessionIsActive &&
|
|
635
|
-
agentsMdExists &&
|
|
636
|
-
changed) {
|
|
1270
|
+
else {
|
|
637
1271
|
summary.agentsMd.skipped += 1;
|
|
638
|
-
console.log(
|
|
639
|
-
|
|
640
|
-
"
|
|
641
|
-
console.log(" Skipping AGENTS.md overwrite to avoid corrupting runtime overlay.");
|
|
642
|
-
console.log(" Stop the active session first, then re-run setup.");
|
|
643
|
-
}
|
|
644
|
-
else if (canApplyManagedModelRefresh) {
|
|
645
|
-
await syncManagedContent(managedRefreshContent, agentsMdDst, summary.agentsMd, backupContext, { dryRun, verbose }, `AGENTS model table ${agentsMdDst}`);
|
|
646
|
-
console.log(resolvedScope.scope === "project"
|
|
647
|
-
? " Refreshed AGENTS.md model capability table in project root."
|
|
648
|
-
: ` Refreshed AGENTS.md model capability table in ${scopeDirs.codexHomeDir}.`);
|
|
1272
|
+
console.log(agentsMdRemoved
|
|
1273
|
+
? " Plugin-mode AGENTS.md defaults not selected.\n"
|
|
1274
|
+
: " AGENTS.md generation skipped; no legacy OMX-generated AGENTS.md found and defaults not selected.\n");
|
|
649
1275
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
1276
|
+
}
|
|
1277
|
+
else {
|
|
1278
|
+
const agentsMdSrc = join(pkgRoot, "templates", "AGENTS.md");
|
|
1279
|
+
const agentsMdDst = resolvedScope.scope === "project"
|
|
1280
|
+
? join(projectRoot, "AGENTS.md")
|
|
1281
|
+
: join(scopeDirs.codexHomeDir, "AGENTS.md");
|
|
1282
|
+
const agentsMdExists = existsSync(agentsMdDst);
|
|
1283
|
+
// Guard: refuse to overwrite project-root AGENTS.md during active session
|
|
1284
|
+
const activeSession = resolvedScope.scope === "project"
|
|
1285
|
+
? await readSessionState(projectRoot)
|
|
1286
|
+
: null;
|
|
1287
|
+
const sessionIsActive = activeSession && !isSessionStale(activeSession);
|
|
1288
|
+
if (existsSync(agentsMdSrc)) {
|
|
1289
|
+
const content = await readFile(agentsMdSrc, "utf-8");
|
|
1290
|
+
const modelTableContext = resolveAgentsModelTableContext(resolvedConfig, {
|
|
1291
|
+
codexHomeOverride: scopeDirs.codexHomeDir,
|
|
656
1292
|
});
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
1293
|
+
const rewritten = upsertAgentsModelTable(addGeneratedAgentsMarker(applyScopePathRewritesToAgentsTemplate(content, resolvedScope.scope)), modelTableContext);
|
|
1294
|
+
let changed = true;
|
|
1295
|
+
let canApplyManagedModelRefresh = false;
|
|
1296
|
+
let managedRefreshContent = "";
|
|
1297
|
+
let canApplyManagedAgentsMerge = false;
|
|
1298
|
+
let mergedAgentsContent = "";
|
|
1299
|
+
if (agentsMdExists) {
|
|
1300
|
+
const existing = await readFile(agentsMdDst, "utf-8");
|
|
1301
|
+
changed = existing !== rewritten;
|
|
1302
|
+
if (options.mergeAgents) {
|
|
1303
|
+
mergedAgentsContent = upsertManagedAgentsBlock(existing, rewritten);
|
|
1304
|
+
canApplyManagedAgentsMerge = mergedAgentsContent !== existing;
|
|
1305
|
+
}
|
|
1306
|
+
else {
|
|
1307
|
+
if (hasOmxManagedAgentsSections(existing)) {
|
|
1308
|
+
managedRefreshContent = upsertAgentsModelTable(existing, modelTableContext);
|
|
1309
|
+
canApplyManagedModelRefresh = managedRefreshContent !== existing;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
if (resolvedScope.scope === "project" &&
|
|
1314
|
+
sessionIsActive &&
|
|
1315
|
+
agentsMdExists &&
|
|
1316
|
+
(changed || canApplyManagedAgentsMerge || canApplyManagedModelRefresh)) {
|
|
1317
|
+
summary.agentsMd.skipped += 1;
|
|
1318
|
+
console.log(" WARNING: Active omx session detected (pid " +
|
|
1319
|
+
activeSession?.pid +
|
|
1320
|
+
").");
|
|
1321
|
+
console.log(" Skipping AGENTS.md overwrite to avoid corrupting runtime overlay.");
|
|
1322
|
+
console.log(" Stop the active session first, then re-run setup.");
|
|
661
1323
|
}
|
|
662
|
-
else if (
|
|
1324
|
+
else if (options.mergeAgents &&
|
|
1325
|
+
agentsMdExists &&
|
|
1326
|
+
!canApplyManagedAgentsMerge) {
|
|
1327
|
+
summary.agentsMd.unchanged += 1;
|
|
663
1328
|
console.log(resolvedScope.scope === "project"
|
|
664
1329
|
? " AGENTS.md already up to date in project root."
|
|
665
1330
|
: ` AGENTS.md already up to date in ${scopeDirs.codexHomeDir}.`);
|
|
666
1331
|
}
|
|
667
|
-
else if (
|
|
668
|
-
|
|
1332
|
+
else if (canApplyManagedAgentsMerge) {
|
|
1333
|
+
await syncManagedContent(mergedAgentsContent, agentsMdDst, summary.agentsMd, backupContext, { dryRun, verbose }, `merged AGENTS ${agentsMdDst}`);
|
|
1334
|
+
console.log(resolvedScope.scope === "project"
|
|
1335
|
+
? " Merged OMX-managed AGENTS.md sections into project root."
|
|
1336
|
+
: ` Merged OMX-managed AGENTS.md sections into ${scopeDirs.codexHomeDir}.`);
|
|
1337
|
+
}
|
|
1338
|
+
else if (canApplyManagedModelRefresh) {
|
|
1339
|
+
await syncManagedContent(managedRefreshContent, agentsMdDst, summary.agentsMd, backupContext, { dryRun, verbose }, `AGENTS model table ${agentsMdDst}`);
|
|
1340
|
+
console.log(resolvedScope.scope === "project"
|
|
1341
|
+
? " Refreshed AGENTS.md model capability table in project root."
|
|
1342
|
+
: ` Refreshed AGENTS.md model capability table in ${scopeDirs.codexHomeDir}.`);
|
|
1343
|
+
}
|
|
1344
|
+
else {
|
|
1345
|
+
const result = await syncManagedAgentsContent(rewritten, agentsMdDst, summary.agentsMd, backupContext, {
|
|
1346
|
+
agentsOverwritePrompt: options.agentsOverwritePrompt,
|
|
1347
|
+
dryRun,
|
|
1348
|
+
force,
|
|
1349
|
+
verbose,
|
|
1350
|
+
});
|
|
1351
|
+
if (result === "updated") {
|
|
1352
|
+
console.log(resolvedScope.scope === "project"
|
|
1353
|
+
? " Generated AGENTS.md in project root."
|
|
1354
|
+
: ` Generated AGENTS.md in ${scopeDirs.codexHomeDir}.`);
|
|
1355
|
+
}
|
|
1356
|
+
else if (result === "unchanged") {
|
|
1357
|
+
console.log(resolvedScope.scope === "project"
|
|
1358
|
+
? " AGENTS.md already up to date in project root."
|
|
1359
|
+
: ` AGENTS.md already up to date in ${scopeDirs.codexHomeDir}.`);
|
|
1360
|
+
}
|
|
1361
|
+
else if (agentsMdExists) {
|
|
1362
|
+
console.log(` Skipped AGENTS.md overwrite for ${agentsMdDst}. Re-run interactively to confirm or use --force.`);
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
if (resolvedScope.scope === "user") {
|
|
1366
|
+
console.log(" User scope leaves project AGENTS.md unchanged.");
|
|
669
1367
|
}
|
|
670
1368
|
}
|
|
671
|
-
|
|
672
|
-
|
|
1369
|
+
else {
|
|
1370
|
+
summary.agentsMd.skipped += 1;
|
|
1371
|
+
console.log(" AGENTS.md template not found, skipping.");
|
|
673
1372
|
}
|
|
1373
|
+
console.log();
|
|
674
1374
|
}
|
|
675
|
-
else {
|
|
676
|
-
summary.agentsMd.skipped += 1;
|
|
677
|
-
console.log(" AGENTS.md template not found, skipping.");
|
|
678
|
-
}
|
|
679
|
-
console.log();
|
|
680
1375
|
// Step 7: Set up notify hook
|
|
681
1376
|
console.log("[7/8] Configuring notification hook...");
|
|
682
|
-
|
|
683
|
-
|
|
1377
|
+
if (isPluginInstallMode) {
|
|
1378
|
+
console.log(" Skipped for plugin skill delivery mode.\n");
|
|
1379
|
+
}
|
|
1380
|
+
else {
|
|
1381
|
+
await setupNotifyHook(pkgRoot, { dryRun, verbose });
|
|
1382
|
+
console.log(" Done.\n");
|
|
1383
|
+
}
|
|
684
1384
|
// Step 8: Configure HUD
|
|
685
1385
|
console.log("[8/8] Configuring HUD...");
|
|
686
1386
|
const hudConfigPath = join(projectRoot, ".omx", "hud-config.json");
|
|
@@ -696,12 +1396,9 @@ export async function setup(options = {}) {
|
|
|
696
1396
|
else {
|
|
697
1397
|
console.log(" HUD config already exists (use --force to overwrite).");
|
|
698
1398
|
}
|
|
699
|
-
if (
|
|
1399
|
+
if (omxManagesTui) {
|
|
700
1400
|
console.log(" StatusLine configured in config.toml via [tui] section.");
|
|
701
1401
|
}
|
|
702
|
-
else {
|
|
703
|
-
console.log(" Codex CLI >= 0.107.0 manages [tui]; OMX left that section untouched.");
|
|
704
|
-
}
|
|
705
1402
|
console.log();
|
|
706
1403
|
console.log("Setup refresh summary:");
|
|
707
1404
|
logCategorySummary("prompts", summary.prompts);
|
|
@@ -722,10 +1419,18 @@ export async function setup(options = {}) {
|
|
|
722
1419
|
console.log('Setup complete! Run "omx doctor" to verify installation.');
|
|
723
1420
|
console.log("\nNext steps:");
|
|
724
1421
|
console.log(" 1. Start Codex CLI in your project directory");
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
1422
|
+
if (isPluginInstallMode) {
|
|
1423
|
+
console.log(` 2. Registered Codex marketplace ${OMX_LOCAL_MARKETPLACE_NAME} supplies OMX skills and workflow surfaces`);
|
|
1424
|
+
console.log(" 3. Browse plugin-provided skills with /skills");
|
|
1425
|
+
console.log(" 4. Optional AGENTS.md and developer_instructions defaults are only installed when selected during plugin-mode setup");
|
|
1426
|
+
console.log(" 5. Legacy native-agent TOML defaults remain uninstalled in plugin mode");
|
|
1427
|
+
}
|
|
1428
|
+
else {
|
|
1429
|
+
console.log(" 2. Use role/workflow keywords like $architect, $executor, and $plan in Codex");
|
|
1430
|
+
console.log(" 3. Browse skills with /skills; AGENTS keyword routing can also activate them implicitly");
|
|
1431
|
+
console.log(" 4. The AGENTS.md orchestration brain is loaded automatically");
|
|
1432
|
+
console.log(" 5. Native agent defaults configured in config.toml [agents] and TOML files written to .codex/agents/");
|
|
1433
|
+
}
|
|
729
1434
|
console.log(' 6. "omx explore" and "omx sparkshell" can hydrate native release binaries on first use; source installs still allow repo-local fallbacks and OMX_EXPLORE_BIN / OMX_SPARKSHELL_BIN overrides');
|
|
730
1435
|
if (isGitHubCliConfigured()) {
|
|
731
1436
|
console.log("\nSupport the project: gh repo star Yeachan-Heo/oh-my-codex");
|
|
@@ -766,7 +1471,8 @@ async function cleanupLegacySkillPromptShims(promptsSrcDir, promptsDstDir, optio
|
|
|
766
1471
|
return removed;
|
|
767
1472
|
}
|
|
768
1473
|
function isGitHubCliConfigured() {
|
|
769
|
-
const result = spawnSync("gh", ["auth", "status"], {
|
|
1474
|
+
const result = spawnSync("gh", ["auth", "status"], {
|
|
1475
|
+
stdio: "ignore",
|
|
770
1476
|
windowsHide: true,
|
|
771
1477
|
});
|
|
772
1478
|
return result.status === 0;
|
|
@@ -872,21 +1578,18 @@ async function installPrompts(srcDir, dstDir, backupContext, options) {
|
|
|
872
1578
|
return summary;
|
|
873
1579
|
const manifest = tryReadCatalogManifest();
|
|
874
1580
|
const agentStatusByName = manifest
|
|
875
|
-
?
|
|
1581
|
+
? getCatalogAgentStatusByName(manifest)
|
|
876
1582
|
: null;
|
|
877
|
-
const isInstallableStatus = (status) => status === "active" || status === "internal";
|
|
878
1583
|
const files = await readdir(srcDir);
|
|
879
|
-
const staleCandidatePromptNames = new Set(manifest?.agents.map((agent) => agent.name) ?? []);
|
|
880
1584
|
for (const file of files) {
|
|
881
1585
|
if (!file.endsWith(".md"))
|
|
882
1586
|
continue;
|
|
883
1587
|
const promptName = file.slice(0, -3);
|
|
884
|
-
staleCandidatePromptNames.add(promptName);
|
|
885
1588
|
const status = agentStatusByName?.get(promptName);
|
|
886
|
-
if (
|
|
1589
|
+
if (manifest && !isSetupPromptAssetName(promptName, manifest)) {
|
|
887
1590
|
summary.skipped += 1;
|
|
888
1591
|
if (options.verbose) {
|
|
889
|
-
const label = status ?? "
|
|
1592
|
+
const label = status ?? "unclassified";
|
|
890
1593
|
console.log(` skipped ${file} (status: ${label})`);
|
|
891
1594
|
}
|
|
892
1595
|
continue;
|
|
@@ -905,13 +1608,14 @@ async function installPrompts(srcDir, dstDir, backupContext, options) {
|
|
|
905
1608
|
continue;
|
|
906
1609
|
const promptName = file.slice(0, -3);
|
|
907
1610
|
const status = agentStatusByName?.get(promptName);
|
|
908
|
-
if (
|
|
909
|
-
continue;
|
|
910
|
-
if (!staleCandidatePromptNames.has(promptName) && status === undefined)
|
|
1611
|
+
if (isSetupPromptAssetName(promptName, manifest))
|
|
911
1612
|
continue;
|
|
912
1613
|
const stalePromptPath = join(dstDir, file);
|
|
913
1614
|
if (!existsSync(stalePromptPath))
|
|
914
1615
|
continue;
|
|
1616
|
+
if (await ensureBackup(stalePromptPath, true, backupContext, options)) {
|
|
1617
|
+
summary.backedUp += 1;
|
|
1618
|
+
}
|
|
915
1619
|
if (!options.dryRun) {
|
|
916
1620
|
await rm(stalePromptPath, { force: true });
|
|
917
1621
|
}
|
|
@@ -927,6 +1631,55 @@ async function installPrompts(srcDir, dstDir, backupContext, options) {
|
|
|
927
1631
|
}
|
|
928
1632
|
return summary;
|
|
929
1633
|
}
|
|
1634
|
+
function isGeneratedOmxNativeAgentToml(content, agentName) {
|
|
1635
|
+
const firstLine = content.split(/\r?\n/, 1)[0]?.trim();
|
|
1636
|
+
return firstLine === `# oh-my-codex agent: ${agentName}`;
|
|
1637
|
+
}
|
|
1638
|
+
async function cleanupGeneratedNonInstallableNativeAgents(agentsDir, manifest, backupContext, options) {
|
|
1639
|
+
const summary = createEmptyCategorySummary();
|
|
1640
|
+
if (!existsSync(agentsDir))
|
|
1641
|
+
return summary;
|
|
1642
|
+
const agentStatusByName = getCatalogAgentStatusByName(manifest);
|
|
1643
|
+
const installedFiles = await readdir(agentsDir);
|
|
1644
|
+
for (const file of installedFiles) {
|
|
1645
|
+
if (!file.endsWith(".toml"))
|
|
1646
|
+
continue;
|
|
1647
|
+
const agentName = file.slice(0, -5);
|
|
1648
|
+
const agentStatus = agentStatusByName.get(agentName);
|
|
1649
|
+
if (agentStatus === undefined ||
|
|
1650
|
+
isNativeAgentInstallableStatus(agentStatus)) {
|
|
1651
|
+
continue;
|
|
1652
|
+
}
|
|
1653
|
+
const staleAgentPath = join(agentsDir, file);
|
|
1654
|
+
let content = "";
|
|
1655
|
+
try {
|
|
1656
|
+
content = await readFile(staleAgentPath, "utf-8");
|
|
1657
|
+
}
|
|
1658
|
+
catch {
|
|
1659
|
+
continue;
|
|
1660
|
+
}
|
|
1661
|
+
if (!isGeneratedOmxNativeAgentToml(content, agentName)) {
|
|
1662
|
+
if (options.verbose) {
|
|
1663
|
+
console.log(` skipped stale native agent ${file}: not an OMX-generated native agent`);
|
|
1664
|
+
}
|
|
1665
|
+
continue;
|
|
1666
|
+
}
|
|
1667
|
+
if (await ensureBackup(staleAgentPath, true, backupContext, options)) {
|
|
1668
|
+
summary.backedUp += 1;
|
|
1669
|
+
}
|
|
1670
|
+
if (!options.dryRun) {
|
|
1671
|
+
await rm(staleAgentPath, { force: true });
|
|
1672
|
+
}
|
|
1673
|
+
summary.removed += 1;
|
|
1674
|
+
if (options.verbose) {
|
|
1675
|
+
const prefix = options.dryRun
|
|
1676
|
+
? "would remove stale generated native agent"
|
|
1677
|
+
: "removed stale generated native agent";
|
|
1678
|
+
console.log(` ${prefix} ${file} (status: ${agentStatus})`);
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
return summary;
|
|
1682
|
+
}
|
|
930
1683
|
async function refreshNativeAgentConfigs(pkgRoot, agentsDir, backupContext, options) {
|
|
931
1684
|
const summary = createEmptyCategorySummary();
|
|
932
1685
|
if (!options.dryRun) {
|
|
@@ -934,17 +1687,18 @@ async function refreshNativeAgentConfigs(pkgRoot, agentsDir, backupContext, opti
|
|
|
934
1687
|
}
|
|
935
1688
|
const manifest = tryReadCatalogManifest();
|
|
936
1689
|
const agentStatusByName = manifest
|
|
937
|
-
?
|
|
1690
|
+
? getCatalogAgentStatusByName(manifest)
|
|
938
1691
|
: null;
|
|
939
|
-
const isInstallableStatus = (status) => status === "active" || status === "internal";
|
|
940
1692
|
const staleCandidateNativeAgentNames = new Set(manifest?.agents.map((agent) => agent.name) ?? []);
|
|
941
|
-
|
|
1693
|
+
const nativeAgentNames = manifest
|
|
1694
|
+
? [...getInstallableNativeAgentNames(manifest)].sort()
|
|
1695
|
+
: Object.keys(AGENT_DEFINITIONS).sort();
|
|
1696
|
+
for (const name of nativeAgentNames) {
|
|
942
1697
|
staleCandidateNativeAgentNames.add(name);
|
|
943
|
-
const
|
|
944
|
-
if (
|
|
1698
|
+
const agent = AGENT_DEFINITIONS[name];
|
|
1699
|
+
if (!agent) {
|
|
945
1700
|
if (options.verbose) {
|
|
946
|
-
|
|
947
|
-
console.log(` skipped native agent ${name}.toml (status: ${label})`);
|
|
1701
|
+
console.log(` skipped native agent ${name}.toml (missing definition)`);
|
|
948
1702
|
}
|
|
949
1703
|
summary.skipped += 1;
|
|
950
1704
|
continue;
|
|
@@ -961,6 +1715,11 @@ async function refreshNativeAgentConfigs(pkgRoot, agentsDir, backupContext, opti
|
|
|
961
1715
|
await syncManagedContent(toml, dst, summary, backupContext, options, `native agent ${name}.toml`);
|
|
962
1716
|
}
|
|
963
1717
|
summary.removed += await cleanupObsoleteNativeAgents(agentsDir, backupContext, options);
|
|
1718
|
+
if (manifest) {
|
|
1719
|
+
const generatedCleanup = await cleanupGeneratedNonInstallableNativeAgents(agentsDir, manifest, backupContext, options);
|
|
1720
|
+
summary.backedUp += generatedCleanup.backedUp;
|
|
1721
|
+
summary.removed += generatedCleanup.removed;
|
|
1722
|
+
}
|
|
964
1723
|
if (options.force && manifest && existsSync(agentsDir)) {
|
|
965
1724
|
const installedFiles = await readdir(agentsDir);
|
|
966
1725
|
for (const file of installedFiles) {
|
|
@@ -968,7 +1727,7 @@ async function refreshNativeAgentConfigs(pkgRoot, agentsDir, backupContext, opti
|
|
|
968
1727
|
continue;
|
|
969
1728
|
const agentName = file.slice(0, -5);
|
|
970
1729
|
const agentStatus = agentStatusByName?.get(agentName);
|
|
971
|
-
if (
|
|
1730
|
+
if (isNativeAgentInstallableStatus(agentStatus))
|
|
972
1731
|
continue;
|
|
973
1732
|
if (!staleCandidateNativeAgentNames.has(agentName) &&
|
|
974
1733
|
agentStatus === undefined)
|
|
@@ -976,6 +1735,9 @@ async function refreshNativeAgentConfigs(pkgRoot, agentsDir, backupContext, opti
|
|
|
976
1735
|
const staleAgentPath = join(agentsDir, file);
|
|
977
1736
|
if (!existsSync(staleAgentPath))
|
|
978
1737
|
continue;
|
|
1738
|
+
if (await ensureBackup(staleAgentPath, true, backupContext, options)) {
|
|
1739
|
+
summary.backedUp += 1;
|
|
1740
|
+
}
|
|
979
1741
|
if (!options.dryRun) {
|
|
980
1742
|
await rm(staleAgentPath, { force: true });
|
|
981
1743
|
}
|
|
@@ -1029,13 +1791,13 @@ export async function installSkills(srcDir, dstDir, backupContext, options) {
|
|
|
1029
1791
|
const summary = createEmptyCategorySummary();
|
|
1030
1792
|
if (!existsSync(srcDir))
|
|
1031
1793
|
return summary;
|
|
1794
|
+
const installableSkillNames = getSetupInstallableSkillNames();
|
|
1032
1795
|
const installableSkills = [];
|
|
1033
1796
|
const manifest = tryReadCatalogManifest();
|
|
1034
1797
|
const skillStatusByName = manifest
|
|
1035
1798
|
? new Map(manifest.skills.map((skill) => [skill.name, skill.status]))
|
|
1036
1799
|
: null;
|
|
1037
|
-
const
|
|
1038
|
-
const isSetupInstallableSkill = (skillName, status) => isInstallableStatus(status) || SETUP_ONLY_INSTALLABLE_SKILLS.has(skillName);
|
|
1800
|
+
const isSetupInstallableSkill = (skillName, status) => isCatalogInstallableStatus(status) || installableSkillNames.has(skillName);
|
|
1039
1801
|
const entries = await readdir(srcDir, { withFileTypes: true });
|
|
1040
1802
|
const staleCandidateSkillNames = new Set(manifest?.skills.map((skill) => skill.name) ?? []);
|
|
1041
1803
|
for (const entry of entries) {
|
|
@@ -1086,11 +1848,14 @@ export async function installSkills(srcDir, dstDir, backupContext, options) {
|
|
|
1086
1848
|
await syncManagedFileFromDisk(sfPath, dstPath, summary, backupContext, options, `skill ${skillName}/${sf}`);
|
|
1087
1849
|
}
|
|
1088
1850
|
}
|
|
1089
|
-
if (
|
|
1851
|
+
if (manifest && existsSync(dstDir)) {
|
|
1090
1852
|
for (const staleSkill of staleCandidateSkillNames) {
|
|
1091
1853
|
const status = skillStatusByName?.get(staleSkill);
|
|
1092
1854
|
if (isSetupInstallableSkill(staleSkill, status))
|
|
1093
1855
|
continue;
|
|
1856
|
+
const hardDeprecated = HARD_DEPRECATED_SKILL_NAMES.has(staleSkill);
|
|
1857
|
+
if (!options.force && !hardDeprecated)
|
|
1858
|
+
continue;
|
|
1094
1859
|
const staleSkillDir = join(dstDir, staleSkill);
|
|
1095
1860
|
if (!existsSync(staleSkillDir))
|
|
1096
1861
|
continue;
|
|
@@ -1103,12 +1868,72 @@ export async function installSkills(srcDir, dstDir, backupContext, options) {
|
|
|
1103
1868
|
? "would remove stale skill"
|
|
1104
1869
|
: "removed stale skill";
|
|
1105
1870
|
const label = status ?? "unlisted";
|
|
1106
|
-
|
|
1871
|
+
const reason = hardDeprecated ? ", hard-deprecated" : "";
|
|
1872
|
+
console.log(` ${prefix} ${staleSkill}/ (status: ${label}${reason})`);
|
|
1107
1873
|
}
|
|
1108
1874
|
}
|
|
1109
1875
|
}
|
|
1110
1876
|
return summary;
|
|
1111
1877
|
}
|
|
1878
|
+
async function removeDirectoryCopyAware(sourceDir, backupContext, options) {
|
|
1879
|
+
const destinationExists = existsSync(sourceDir);
|
|
1880
|
+
if (!destinationExists)
|
|
1881
|
+
return false;
|
|
1882
|
+
const relativePath = relative(backupContext.baseRoot, sourceDir);
|
|
1883
|
+
const safeRelativePath = relativePath.startsWith("..") || relativePath === ""
|
|
1884
|
+
? sourceDir.replace(/^[/]+/, "")
|
|
1885
|
+
: relativePath;
|
|
1886
|
+
const backupPath = join(backupContext.backupRoot, safeRelativePath);
|
|
1887
|
+
if (!options.dryRun) {
|
|
1888
|
+
await mkdir(dirname(backupPath), { recursive: true });
|
|
1889
|
+
await cp(sourceDir, backupPath, { recursive: true });
|
|
1890
|
+
}
|
|
1891
|
+
if (options.verbose) {
|
|
1892
|
+
console.log(` backup ${sourceDir} -> ${backupPath}`);
|
|
1893
|
+
}
|
|
1894
|
+
if (!options.dryRun) {
|
|
1895
|
+
await rm(sourceDir, { recursive: true, force: true });
|
|
1896
|
+
}
|
|
1897
|
+
return true;
|
|
1898
|
+
}
|
|
1899
|
+
async function cleanupLegacyManagedSkills(srcDir, dstDir, backupContext, options) {
|
|
1900
|
+
const result = {
|
|
1901
|
+
backedUp: 0,
|
|
1902
|
+
removedSkillNames: [],
|
|
1903
|
+
skippedSkillNames: [],
|
|
1904
|
+
warnings: [],
|
|
1905
|
+
};
|
|
1906
|
+
if (!existsSync(dstDir) || !existsSync(srcDir)) {
|
|
1907
|
+
return result;
|
|
1908
|
+
}
|
|
1909
|
+
const manifest = tryReadCatalogManifest();
|
|
1910
|
+
const installableSkillNames = getSetupInstallableSkillNames(manifest);
|
|
1911
|
+
for (const skillName of installableSkillNames) {
|
|
1912
|
+
const shippedSkillDir = join(srcDir, skillName);
|
|
1913
|
+
const installedSkillDir = join(dstDir, skillName);
|
|
1914
|
+
const shippedSkillMd = join(shippedSkillDir, "SKILL.md");
|
|
1915
|
+
const installedSkillMd = join(installedSkillDir, "SKILL.md");
|
|
1916
|
+
if (!existsSync(shippedSkillMd) || !existsSync(installedSkillMd))
|
|
1917
|
+
continue;
|
|
1918
|
+
const [shippedSkillContent, installedSkillContent] = await Promise.all([
|
|
1919
|
+
readFile(shippedSkillMd, "utf-8"),
|
|
1920
|
+
readFile(installedSkillMd, "utf-8"),
|
|
1921
|
+
]);
|
|
1922
|
+
const expectedInstalledContent = rewriteInstalledSkillDescriptionBadge(shippedSkillContent, shippedSkillMd);
|
|
1923
|
+
if (installedSkillContent !== expectedInstalledContent) {
|
|
1924
|
+
const warning = `Skipping legacy skill cleanup for ${skillName}: installed SKILL.md differs from OMX-managed content.`;
|
|
1925
|
+
result.skippedSkillNames.push(skillName);
|
|
1926
|
+
result.warnings.push(warning);
|
|
1927
|
+
continue;
|
|
1928
|
+
}
|
|
1929
|
+
const removed = await removeDirectoryCopyAware(installedSkillDir, backupContext, options);
|
|
1930
|
+
if (removed) {
|
|
1931
|
+
result.backedUp += 1;
|
|
1932
|
+
result.removedSkillNames.push(skillName);
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
return result;
|
|
1936
|
+
}
|
|
1112
1937
|
async function updateManagedConfig(configPath, pkgRoot, sharedMcpRegistry, summary, backupContext, options) {
|
|
1113
1938
|
const existing = existsSync(configPath)
|
|
1114
1939
|
? await readFile(configPath, "utf-8")
|
|
@@ -1116,8 +1941,7 @@ async function updateManagedConfig(configPath, pkgRoot, sharedMcpRegistry, summa
|
|
|
1116
1941
|
const hadLegacyTeamRunTable = hasLegacyOmxTeamRunTable(existing);
|
|
1117
1942
|
const currentModel = getRootModelName(existing);
|
|
1118
1943
|
let modelOverride;
|
|
1119
|
-
const
|
|
1120
|
-
const omxManagesTui = shouldOmxManageTuiFromCodexVersion(codexVersion);
|
|
1944
|
+
const omxManagesTui = true;
|
|
1121
1945
|
if (currentModel === LEGACY_SETUP_MODEL) {
|
|
1122
1946
|
const shouldPrompt = typeof options.modelUpgradePrompt === "function" ||
|
|
1123
1947
|
(process.stdin.isTTY && process.stdout.isTTY);
|
|
@@ -1136,6 +1960,8 @@ async function updateManagedConfig(configPath, pkgRoot, sharedMcpRegistry, summa
|
|
|
1136
1960
|
sharedMcpServers: sharedMcpRegistry.servers,
|
|
1137
1961
|
sharedMcpRegistrySource: sharedMcpRegistry.sourcePath,
|
|
1138
1962
|
verbose: options.verbose,
|
|
1963
|
+
statusLinePreset: options.statusLinePreset,
|
|
1964
|
+
forceStatusLinePreset: options.forceStatusLinePreset,
|
|
1139
1965
|
});
|
|
1140
1966
|
const changed = existing !== finalConfig;
|
|
1141
1967
|
if (!changed) {
|