oh-my-opencode 4.6.0 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/bin/version-mismatch.js +47 -0
  2. package/bin/version-mismatch.test.ts +120 -0
  3. package/dist/cli/codex-ulw-loop.d.ts +12 -0
  4. package/dist/cli/doctor/checks/tui-plugin-config.d.ts +2 -0
  5. package/dist/cli/index.js +577 -304
  6. package/dist/cli/install-codex/codex-config-reasoning.d.ts +2 -1
  7. package/dist/cli/install-codex/codex-model-catalog.d.ts +13 -0
  8. package/dist/features/background-agent/concurrency.d.ts +1 -0
  9. package/dist/features/background-agent/process-cleanup.d.ts +6 -0
  10. package/dist/features/claude-code-session-state/state.d.ts +1 -0
  11. package/dist/features/opencode-skill-loader/index.d.ts +1 -0
  12. package/dist/features/opencode-skill-loader/opencode-config-skills-reader.d.ts +5 -0
  13. package/dist/features/tmux-subagent/attachable-session-status.d.ts +1 -1
  14. package/dist/features/tmux-subagent/session-status-parser.d.ts +1 -0
  15. package/dist/hooks/comment-checker/cli.d.ts +1 -0
  16. package/dist/hooks/tasks-todowrite-disabler/constants.d.ts +1 -1
  17. package/dist/index.js +811 -450
  18. package/dist/shared/command-executor/execute-hook-command.d.ts +2 -0
  19. package/dist/tools/skill/description-formatter.d.ts +5 -1
  20. package/dist/tools/skill/types.d.ts +1 -0
  21. package/package.json +12 -13
  22. package/packages/ast-grep-mcp/dist/cli.js +53 -9
  23. package/packages/lsp-tools-mcp/dist/lsp/process.js +1 -1
  24. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus.md +6 -4
  25. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +0 -2
  26. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +1 -1
  27. package/packages/omo-codex/plugin/components/ultrawork/CHANGELOG.md +1 -1
  28. package/packages/omo-codex/plugin/components/ultrawork/README.md +1 -1
  29. package/packages/omo-codex/plugin/components/ultrawork/agents/codex-ultrawork-reviewer.toml +3 -1
  30. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +7 -7
  31. package/packages/omo-codex/plugin/components/ultrawork/directive.md +1 -1
  32. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +5 -4
  33. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +4 -3
  34. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +12 -1
  35. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint.test.ts +19 -1
  36. package/packages/omo-codex/plugin/hooks/hooks.json +11 -0
  37. package/packages/omo-codex/plugin/model-catalog.json +49 -0
  38. package/packages/omo-codex/plugin/scripts/auto-update.mjs +159 -0
  39. package/packages/omo-codex/plugin/scripts/migrate-codex-config.mjs +269 -0
  40. package/packages/omo-codex/plugin/scripts/sync-hook-status-messages.mjs +3 -1
  41. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +6 -6
  42. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +6 -6
  43. package/packages/omo-codex/plugin/skills/lcx-report-bug/SKILL.md +127 -0
  44. package/packages/omo-codex/plugin/skills/lcx-report-bug/agents/openai.yaml +9 -0
  45. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +6 -6
  46. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +6 -6
  47. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +7 -7
  48. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +6 -6
  49. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +5 -4
  50. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +4 -3
  51. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +17 -17
  52. package/packages/omo-codex/plugin/test/aggregate.test.mjs +172 -19
  53. package/packages/omo-codex/plugin/test/auto-update.test.mjs +129 -0
  54. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +2 -0
  55. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +146 -0
  56. package/packages/omo-codex/plugin/test/sync-hook-status-messages.test.mjs +1 -0
  57. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +22 -0
  58. package/packages/omo-codex/scripts/install/cli-args.mjs +1 -1
  59. package/packages/omo-codex/scripts/install/config.mjs +2 -15
  60. package/packages/omo-codex/scripts/install/delegated-command.mjs +1 -1
  61. package/packages/omo-codex/scripts/install/legacy-bins.mjs +1 -0
  62. package/packages/omo-codex/scripts/install/model-catalog.mjs +66 -0
  63. package/packages/omo-codex/scripts/install/reasoning-config.mjs +65 -7
  64. package/packages/omo-codex/scripts/install-bin-links.test.mjs +23 -0
  65. package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +82 -3
  66. package/packages/omo-codex/scripts/install-config.test.mjs +5 -6
  67. package/packages/omo-codex/scripts/install-local-entrypoint.test.mjs +30 -2
  68. package/packages/omo-codex/scripts/install-local.mjs +1 -1
  69. package/packages/shared-skills/skills/lcx-report-bug/SKILL.md +127 -0
  70. package/packages/shared-skills/skills/lcx-report-bug/agents/openai.yaml +9 -0
  71. package/packages/shared-skills/skills/review-work/SKILL.md +7 -7
  72. package/packages/shared-skills/skills/start-work/SKILL.md +6 -6
  73. package/packages/shared-skills/skills/ulw-plan/SKILL.md +11 -11
  74. package/postinstall.mjs +36 -3
  75. package/dist/cli/install-codex/codex-config-mcp.d.ts +0 -1
package/dist/cli/index.js CHANGED
@@ -6181,8 +6181,8 @@ var init_model_requirements = __esm(() => {
6181
6181
  { providers: ["opencode-go"], model: "qwen3.5-plus" },
6182
6182
  { providers: ["vercel"], model: "minimax-m2.7-highspeed" },
6183
6183
  { providers: ["opencode-go", "vercel"], model: "minimax-m2.7" },
6184
- { providers: ["anthropic", "opencode", "vercel"], model: "claude-haiku-4-5" },
6185
- { providers: ["openai", "opencode", "vercel"], model: "gpt-5.4-nano" }
6184
+ { providers: ["anthropic", "vercel"], model: "claude-haiku-4-5" },
6185
+ { providers: ["openai", "vercel"], model: "gpt-5.4-nano" }
6186
6186
  ]
6187
6187
  },
6188
6188
  explore: {
@@ -6191,8 +6191,8 @@ var init_model_requirements = __esm(() => {
6191
6191
  { providers: ["opencode-go"], model: "qwen3.5-plus" },
6192
6192
  { providers: ["vercel"], model: "minimax-m2.7-highspeed" },
6193
6193
  { providers: ["opencode-go", "vercel"], model: "minimax-m2.7" },
6194
- { providers: ["anthropic", "opencode", "vercel"], model: "claude-haiku-4-5" },
6195
- { providers: ["openai", "opencode", "vercel"], model: "gpt-5.4-nano" }
6194
+ { providers: ["anthropic", "vercel"], model: "claude-haiku-4-5" },
6195
+ { providers: ["openai", "vercel"], model: "gpt-5.4-nano" }
6196
6196
  ]
6197
6197
  },
6198
6198
  "multimodal-looker": {
@@ -6371,7 +6371,7 @@ var init_model_requirements = __esm(() => {
6371
6371
  model: "gpt-5.4-mini"
6372
6372
  },
6373
6373
  {
6374
- providers: ["anthropic", "github-copilot", "opencode", "vercel"],
6374
+ providers: ["anthropic", "github-copilot", "vercel"],
6375
6375
  model: "claude-haiku-4-5"
6376
6376
  },
6377
6377
  {
@@ -6606,7 +6606,7 @@ var init_model_capability_heuristics = __esm(() => {
6606
6606
  },
6607
6607
  {
6608
6608
  family: "kimi",
6609
- includes: ["kimi", "k2"],
6609
+ pattern: /(?:kimi|k2(?![-.]?p\d))/,
6610
6610
  variants: ["low", "medium", "high"],
6611
6611
  supportsThinking: false
6612
6612
  },
@@ -6679,7 +6679,7 @@ function claudeVersionDot(model) {
6679
6679
  function applyGatewayTransforms(model) {
6680
6680
  return claudeVersionDot(model).replace(GEMINI_31_PRO_PREVIEW, "gemini-3.1-pro-preview");
6681
6681
  }
6682
- function transformModelForProviderUsingAnthropicBehavior(provider, model, directAnthropicTransform) {
6682
+ function transformModelForProviderUsingAnthropicBehavior(provider, model) {
6683
6683
  if (provider === "vercel") {
6684
6684
  const slashIndex = model.indexOf("/");
6685
6685
  if (slashIndex !== -1) {
@@ -6700,12 +6700,12 @@ function transformModelForProviderUsingAnthropicBehavior(provider, model, direct
6700
6700
  return model.replace(GEMINI_31_PRO_PREVIEW, "gemini-3.1-pro-preview").replace(GEMINI_3_FLASH_PREVIEW, "gemini-3-flash-preview");
6701
6701
  }
6702
6702
  if (provider === "anthropic") {
6703
- return directAnthropicTransform(model);
6703
+ return model;
6704
6704
  }
6705
6705
  return model;
6706
6706
  }
6707
6707
  function transformModelForProviderDisplay(provider, model) {
6708
- return transformModelForProviderUsingAnthropicBehavior(provider, model, (model2) => model2);
6708
+ return transformModelForProviderUsingAnthropicBehavior(provider, model);
6709
6709
  }
6710
6710
  var CLAUDE_VERSION_DOT, GEMINI_31_PRO_PREVIEW, GEMINI_3_FLASH_PREVIEW;
6711
6711
  var init_provider_model_id_transform = __esm(() => {
@@ -7874,8 +7874,30 @@ function resolveConfigPath(pathValue) {
7874
7874
  return resolvedPath;
7875
7875
  }
7876
7876
  }
7877
+ function isWslEnvironment() {
7878
+ return process.platform === "linux" && (Boolean(process.env.WSL_DISTRO_NAME?.trim()) || Boolean(process.env.WSL_INTEROP?.trim()));
7879
+ }
7880
+ function isWindowsUserConfigRoot(pathValue) {
7881
+ const normalizedPath = pathValue.replaceAll("\\", "/").toLowerCase();
7882
+ return /^[a-z]:\/users\//.test(normalizedPath) || /^\/mnt\/[a-z]\/users\//.test(normalizedPath);
7883
+ }
7884
+ function getWindowsUserFromConfigRoot(pathValue) {
7885
+ const normalizedPath = pathValue.replaceAll("\\", "/");
7886
+ const match = /^(?:[a-z]:|\/mnt\/[a-z])\/Users\/([^/]+)/i.exec(normalizedPath);
7887
+ return match?.[1] ?? null;
7888
+ }
7889
+ function getWslLinuxHomeDir(windowsConfigRoot) {
7890
+ const envHome = process.env.HOME?.trim();
7891
+ if (envHome && envHome.startsWith("/") && !isWindowsUserConfigRoot(envHome)) {
7892
+ return envHome;
7893
+ }
7894
+ const user = process.env.USER?.trim() || process.env.LOGNAME?.trim() || process.env.SUDO_USER?.trim() || (windowsConfigRoot ? getWindowsUserFromConfigRoot(windowsConfigRoot) : undefined);
7895
+ return user ? join5("/home", user) : null;
7896
+ }
7877
7897
  function getCliDefaultConfigDir() {
7878
- const xdgConfig = process.env.XDG_CONFIG_HOME || join5(homedir3(), ".config");
7898
+ const envXdgConfig = process.env.XDG_CONFIG_HOME?.trim();
7899
+ const shouldIgnoreWindowsXdg = envXdgConfig !== undefined && envXdgConfig.length > 0 && isWslEnvironment() && isWindowsUserConfigRoot(envXdgConfig);
7900
+ const xdgConfig = shouldIgnoreWindowsXdg ? join5(getWslLinuxHomeDir(envXdgConfig) ?? "/home", ".config") : envXdgConfig || join5(homedir3(), ".config");
7879
7901
  return resolveConfigPath(join5(xdgConfig, "opencode"));
7880
7902
  }
7881
7903
  function getCliCustomConfigDir() {
@@ -53617,18 +53639,10 @@ function generateModelConfig(config) {
53617
53639
  const categories = {};
53618
53640
  for (const [role, req] of Object.entries(CLI_AGENT_MODEL_REQUIREMENTS)) {
53619
53641
  if (role === "librarian") {
53620
- let agentConfig;
53621
- if (avail.native.openai) {
53622
- agentConfig = { model: "openai/gpt-5.4-mini-fast" };
53623
- } else if (avail.opencodeGo) {
53624
- agentConfig = { model: "opencode-go/qwen3.5-plus" };
53625
- } else if (avail.zai) {
53626
- agentConfig = { model: ZAI_MODEL };
53627
- } else if (avail.vercelAiGateway) {
53628
- agentConfig = { model: "vercel/minimax/minimax-m2.7" };
53629
- }
53630
- if (agentConfig) {
53631
- agents[role] = attachAllFallbackModels(agentConfig, req.fallbackChain, avail);
53642
+ const resolved2 = resolveModelFromChain(req.fallbackChain, avail);
53643
+ if (resolved2) {
53644
+ const agentConfig = resolved2.variant ? { model: resolved2.model, variant: resolved2.variant } : { model: resolved2.model };
53645
+ agents[role] = attachFallbackModels(agentConfig, req.fallbackChain, avail);
53632
53646
  }
53633
53647
  continue;
53634
53648
  }
@@ -53639,7 +53653,7 @@ function generateModelConfig(config) {
53639
53653
  } else if (avail.native.claude) {
53640
53654
  agentConfig = { model: "anthropic/claude-haiku-4-5" };
53641
53655
  } else if (avail.opencodeZen) {
53642
- agentConfig = { model: "opencode/claude-haiku-4-5" };
53656
+ agentConfig = { model: "opencode/gpt-5-nano" };
53643
53657
  } else if (avail.opencodeGo) {
53644
53658
  agentConfig = { model: "opencode-go/qwen3.5-plus" };
53645
53659
  } else if (avail.copilot) {
@@ -53704,7 +53718,7 @@ function generateModelConfig(config) {
53704
53718
  };
53705
53719
  return isOpenAiOnlyAvailability(avail) ? applyOpenAiOnlyModelCatalog(generatedConfig) : generatedConfig;
53706
53720
  }
53707
- var ZAI_MODEL = "zai-coding-plan/glm-4.7", ULTIMATE_FALLBACK = "opencode/gpt-5-nano", SCHEMA_URL = "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json";
53721
+ var ULTIMATE_FALLBACK = "opencode/gpt-5-nano", SCHEMA_URL = "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json";
53708
53722
  var init_model_fallback = __esm(() => {
53709
53723
  init_model_fallback_requirements();
53710
53724
  init_openai_only_model_catalog();
@@ -59711,9 +59725,9 @@ var init_data_path2 = __esm(() => {
59711
59725
 
59712
59726
  // packages/omo-codex/src/telemetry/posthog-activity-state.ts
59713
59727
  import { existsSync as existsSync24, mkdirSync as mkdirSync8, readFileSync as readFileSync13 } from "fs";
59714
- import { join as join29 } from "path";
59728
+ import { join as join30 } from "path";
59715
59729
  function getPostHogActivityStateFilePath() {
59716
- return join29(getActivityStateDir(), POSTHOG_ACTIVITY_STATE_FILE);
59730
+ return join30(getActivityStateDir(), POSTHOG_ACTIVITY_STATE_FILE);
59717
59731
  }
59718
59732
  function getUtcDayString(date) {
59719
59733
  return date.toISOString().slice(0, 10);
@@ -61062,7 +61076,7 @@ var init_update_toasts = __esm(() => {
61062
61076
 
61063
61077
  // src/hooks/auto-update-checker/hook/background-update-check.ts
61064
61078
  import { existsSync as existsSync41 } from "fs";
61065
- import { join as join46 } from "path";
61079
+ import { join as join47 } from "path";
61066
61080
  function getCacheWorkspaceDir(deps) {
61067
61081
  return deps.join(deps.getOpenCodeCacheDir(), "packages");
61068
61082
  }
@@ -61181,7 +61195,7 @@ var init_background_update_check = __esm(() => {
61181
61195
  init_update_toasts();
61182
61196
  defaultDeps3 = {
61183
61197
  existsSync: existsSync41,
61184
- join: join46,
61198
+ join: join47,
61185
61199
  runBunInstallWithDetails,
61186
61200
  log,
61187
61201
  getOpenCodeCacheDir,
@@ -61423,13 +61437,13 @@ v${latestVersion} available. Restart OpenCode to apply.` : "OpenCode is now on S
61423
61437
  }
61424
61438
  };
61425
61439
  }
61426
- var defaultDeps4, isRecord15 = (value) => {
61440
+ var defaultDeps4, isRecord16 = (value) => {
61427
61441
  return typeof value === "object" && value !== null;
61428
61442
  }, getParentID = (properties) => {
61429
- if (!isRecord15(properties))
61443
+ if (!isRecord16(properties))
61430
61444
  return;
61431
61445
  const { info } = properties;
61432
- if (!isRecord15(info))
61446
+ if (!isRecord16(info))
61433
61447
  return;
61434
61448
  const { parentID } = info;
61435
61449
  return typeof parentID === "string" && parentID.length > 0 ? parentID : undefined;
@@ -61493,7 +61507,7 @@ var {
61493
61507
  // package.json
61494
61508
  var package_default = {
61495
61509
  name: "oh-my-opencode",
61496
- version: "4.6.0",
61510
+ version: "4.7.0",
61497
61511
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
61498
61512
  main: "./dist/index.js",
61499
61513
  types: "dist/index.d.ts",
@@ -61599,7 +61613,6 @@ var package_default = {
61599
61613
  commander: "^14.0.3",
61600
61614
  "detect-libc": "^2.1.2",
61601
61615
  diff: "^9.0.0",
61602
- effect: "4.0.0-beta.65",
61603
61616
  "js-yaml": "^4.1.1",
61604
61617
  "jsonc-parser": "^3.3.1",
61605
61618
  picocolors: "^1.1.1",
@@ -61629,17 +61642,17 @@ var package_default = {
61629
61642
  zod: "^4.4.3"
61630
61643
  },
61631
61644
  optionalDependencies: {
61632
- "oh-my-opencode-darwin-arm64": "4.6.0",
61633
- "oh-my-opencode-darwin-x64": "4.6.0",
61634
- "oh-my-opencode-darwin-x64-baseline": "4.6.0",
61635
- "oh-my-opencode-linux-arm64": "4.6.0",
61636
- "oh-my-opencode-linux-arm64-musl": "4.6.0",
61637
- "oh-my-opencode-linux-x64": "4.6.0",
61638
- "oh-my-opencode-linux-x64-baseline": "4.6.0",
61639
- "oh-my-opencode-linux-x64-musl": "4.6.0",
61640
- "oh-my-opencode-linux-x64-musl-baseline": "4.6.0",
61641
- "oh-my-opencode-windows-x64": "4.6.0",
61642
- "oh-my-opencode-windows-x64-baseline": "4.6.0"
61645
+ "oh-my-opencode-darwin-arm64": "4.7.0",
61646
+ "oh-my-opencode-darwin-x64": "4.7.0",
61647
+ "oh-my-opencode-darwin-x64-baseline": "4.7.0",
61648
+ "oh-my-opencode-linux-arm64": "4.7.0",
61649
+ "oh-my-opencode-linux-arm64-musl": "4.7.0",
61650
+ "oh-my-opencode-linux-x64": "4.7.0",
61651
+ "oh-my-opencode-linux-x64-baseline": "4.7.0",
61652
+ "oh-my-opencode-linux-x64-musl": "4.7.0",
61653
+ "oh-my-opencode-linux-x64-musl-baseline": "4.7.0",
61654
+ "oh-my-opencode-windows-x64": "4.7.0",
61655
+ "oh-my-opencode-windows-x64-baseline": "4.7.0"
61643
61656
  },
61644
61657
  overrides: {
61645
61658
  hono: "^4.12.18",
@@ -61700,7 +61713,7 @@ function formatConfigSummary(config) {
61700
61713
  lines.push(formatProvider("Gemini", config.hasGemini));
61701
61714
  lines.push(formatProvider("GitHub Copilot", config.hasCopilot, "fallback"));
61702
61715
  lines.push(formatProvider("OpenCode Zen", config.hasOpencodeZen, "opencode/ models"));
61703
- lines.push(formatProvider("Z.ai Coding Plan", config.hasZaiCodingPlan, "Librarian/Multimodal"));
61716
+ lines.push(formatProvider("Z.ai Coding Plan", config.hasZaiCodingPlan, "GLM fallbacks"));
61704
61717
  lines.push(formatProvider("Kimi For Coding", config.hasKimiForCoding, "Sisyphus/Prometheus fallback"));
61705
61718
  lines.push(formatProvider("Vercel AI Gateway", config.hasVercelAiGateway, "universal proxy"));
61706
61719
  lines.push("");
@@ -61841,7 +61854,7 @@ function argsToConfig(args) {
61841
61854
  hasKimiForCoding: hasOpenCode && args.kimiForCoding === "yes",
61842
61855
  hasOpencodeGo: hasOpenCode && args.opencodeGo === "yes",
61843
61856
  hasVercelAiGateway: hasOpenCode && args.vercelAiGateway === "yes",
61844
- codexAutonomous: hasCodex && args.codexAutonomous === true
61857
+ codexAutonomous: hasCodex && args.codexAutonomous !== false
61845
61858
  };
61846
61859
  }
61847
61860
  function detectedToInitialValues(detected) {
@@ -61918,7 +61931,7 @@ function getUnsupportedOpenCodeVersionMessage(openCodeVersion) {
61918
61931
 
61919
61932
  // src/cli/install-codex/install-codex.ts
61920
61933
  import { homedir as homedir5 } from "os";
61921
- import { join as join30, resolve as resolve9 } from "path";
61934
+ import { join as join31, resolve as resolve9 } from "path";
61922
61935
  import { existsSync as existsSync25 } from "fs";
61923
61936
  import { mkdir as mkdir6, writeFile as writeFile7 } from "fs/promises";
61924
61937
 
@@ -62016,6 +62029,7 @@ import { lstat, readFile as readFile2, readlink, rm } from "fs/promises";
62016
62029
  import { join as join20 } from "path";
62017
62030
  var LEGACY_CODEX_COMPONENT_BINS = [
62018
62031
  { name: "codex-comment-checker", component: "comment-checker" },
62032
+ { name: "codex-lsp", component: "lsp" },
62019
62033
  { name: "codex-rules", component: "rules" },
62020
62034
  { name: "codex-start-work-continuation", component: "start-work-continuation" },
62021
62035
  { name: "codex-telemetry", component: "telemetry" },
@@ -62391,10 +62405,10 @@ function isRecord11(value) {
62391
62405
  }
62392
62406
 
62393
62407
  // src/cli/install-codex/codex-config-toml.ts
62394
- import { mkdir as mkdir3, readFile as readFile6, writeFile as writeFile3 } from "fs/promises";
62408
+ import { mkdir as mkdir3, readFile as readFile7, writeFile as writeFile3 } from "fs/promises";
62395
62409
  import { dirname as dirname12 } from "path";
62396
62410
 
62397
- // src/cli/install-codex/toml-section-editor.ts
62411
+ // packages/omo-codex/scripts/install/toml-editor.mjs
62398
62412
  function findTomlSection(config, header) {
62399
62413
  const headerLine = `[${header}]`;
62400
62414
  const lines = config.match(/[^\n]*\n?|$/g) ?? [];
@@ -62462,23 +62476,33 @@ function escapeRegExp(value) {
62462
62476
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
62463
62477
  }
62464
62478
 
62465
- // src/cli/install-codex/codex-config-mcp.ts
62466
- var CONTEXT7_MCP_SERVER_HEADER = "mcp_servers.context7";
62467
- var CONTEXT7_MCP_SERVER_BLOCK = [
62468
- `[${CONTEXT7_MCP_SERVER_HEADER}]`,
62469
- 'command = "npx"',
62470
- 'args = ["-y", "@upstash/context7-mcp", "--api-key", "YOUR_API_KEY"]',
62471
- "startup_timeout_sec = 20",
62472
- ""
62473
- ].join(`
62474
- `);
62475
- function ensureContext7McpServer(config) {
62476
- if (findTomlSection(config, CONTEXT7_MCP_SERVER_HEADER))
62479
+ // packages/omo-codex/scripts/install/permissions.mjs
62480
+ function ensureAutonomousPermissions(config) {
62481
+ let next = replaceOrInsertRootSetting(config, "approval_policy", JSON.stringify("never"));
62482
+ next = replaceOrInsertRootSetting(next, "sandbox_mode", JSON.stringify("danger-full-access"));
62483
+ next = replaceOrInsertRootSetting(next, "network_access", JSON.stringify("enabled"));
62484
+ next = removeWindowsSandboxSetting(next);
62485
+ next = ensureNoticeEnabled(next, "hide_full_access_warning");
62486
+ return ensureNoticeEnabled(next, "hide_world_writable_warning");
62487
+ }
62488
+ function removeWindowsSandboxSetting(config) {
62489
+ const section = findTomlSection(config, "windows");
62490
+ if (!section)
62477
62491
  return config;
62478
- return appendBlock(config, CONTEXT7_MCP_SERVER_BLOCK);
62492
+ return removeSetting(config, section, "sandbox");
62479
62493
  }
62480
-
62481
- // packages/omo-codex/scripts/install/toml-editor.mjs
62494
+ function ensureNoticeEnabled(config, key) {
62495
+ const section = findTomlSection(config, "notice");
62496
+ if (!section)
62497
+ return appendNoticeBlock(config, key);
62498
+ return replaceOrInsertSetting(config, section, key, "true");
62499
+ }
62500
+ function appendNoticeBlock(config, key) {
62501
+ return appendBlock(config, `[notice]
62502
+ ${key} = true
62503
+ `);
62504
+ }
62505
+ // src/cli/install-codex/toml-section-editor.ts
62482
62506
  function findTomlSection2(config, header) {
62483
62507
  const headerLine = `[${header}]`;
62484
62508
  const lines = config.match(/[^\n]*\n?|$/g) ?? [];
@@ -62546,39 +62570,138 @@ function escapeRegExp2(value) {
62546
62570
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
62547
62571
  }
62548
62572
 
62549
- // packages/omo-codex/scripts/install/permissions.mjs
62550
- function ensureAutonomousPermissions(config) {
62551
- let next = replaceOrInsertRootSetting2(config, "approval_policy", JSON.stringify("never"));
62552
- next = replaceOrInsertRootSetting2(next, "sandbox_mode", JSON.stringify("danger-full-access"));
62553
- next = replaceOrInsertRootSetting2(next, "network_access", JSON.stringify("enabled"));
62554
- next = removeWindowsSandboxSetting(next);
62555
- next = ensureNoticeEnabled(next, "hide_full_access_warning");
62556
- return ensureNoticeEnabled(next, "hide_world_writable_warning");
62557
- }
62558
- function removeWindowsSandboxSetting(config) {
62559
- const section = findTomlSection2(config, "windows");
62560
- if (!section)
62573
+ // src/cli/install-codex/codex-config-reasoning.ts
62574
+ var MANAGED_KEYS = ["model", "model_context_window", "model_reasoning_effort", "plan_mode_reasoning_effort"];
62575
+ function ensureCodexReasoningConfig(config, catalog) {
62576
+ const current = readRootReasoningSettings(config);
62577
+ if (Object.keys(current).length > 0 && !matchesProfile(current, catalog.current) && !catalog.managedProfiles.some((profile) => matchesProfile(current, profile))) {
62561
62578
  return config;
62562
- return removeSetting2(config, section, "sandbox");
62579
+ }
62580
+ let next = replaceOrInsertRootSetting2(config, "model", JSON.stringify(catalog.current.model));
62581
+ next = replaceOrInsertRootSetting2(next, "model_context_window", catalog.current.modelContextWindow.toString());
62582
+ next = replaceOrInsertRootSetting2(next, "model_reasoning_effort", JSON.stringify(catalog.current.modelReasoningEffort));
62583
+ next = replaceOrInsertRootSetting2(next, "plan_mode_reasoning_effort", JSON.stringify(catalog.current.planModeReasoningEffort));
62584
+ return next;
62563
62585
  }
62564
- function ensureNoticeEnabled(config, key) {
62565
- const section = findTomlSection2(config, "notice");
62566
- if (!section)
62567
- return appendNoticeBlock(config, key);
62568
- return replaceOrInsertSetting2(config, section, key, "true");
62586
+ function readRootReasoningSettings(config) {
62587
+ const settings = {};
62588
+ for (const line of config.split(/\n/)) {
62589
+ if (isSectionHeader(line))
62590
+ break;
62591
+ for (const key of MANAGED_KEYS) {
62592
+ if (!isRootSetting(line, key))
62593
+ continue;
62594
+ const value = parseTomlScalar(line.slice(line.indexOf("=") + 1));
62595
+ if (key === "model" && typeof value === "string")
62596
+ settings.model = value;
62597
+ if (key === "model_context_window" && typeof value === "number")
62598
+ settings.modelContextWindow = value;
62599
+ if (key === "model_reasoning_effort" && typeof value === "string")
62600
+ settings.modelReasoningEffort = value;
62601
+ if (key === "plan_mode_reasoning_effort" && typeof value === "string")
62602
+ settings.planModeReasoningEffort = value;
62603
+ }
62604
+ }
62605
+ return settings;
62606
+ }
62607
+ function matchesProfile(current, profile) {
62608
+ for (const [key, value] of Object.entries(profile)) {
62609
+ if (current[key] !== value)
62610
+ return false;
62611
+ }
62612
+ return true;
62569
62613
  }
62570
- function appendNoticeBlock(config, key) {
62571
- return appendBlock2(config, `[notice]
62572
- ${key} = true
62573
- `);
62614
+ function parseTomlScalar(value) {
62615
+ const trimmed = value.trim();
62616
+ if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
62617
+ try {
62618
+ return JSON.parse(trimmed);
62619
+ } catch (error) {
62620
+ if (error instanceof SyntaxError)
62621
+ return;
62622
+ throw error;
62623
+ }
62624
+ }
62625
+ const numeric = Number(trimmed);
62626
+ return Number.isFinite(numeric) ? numeric : undefined;
62574
62627
  }
62575
- // src/cli/install-codex/codex-config-reasoning.ts
62576
- var DEFAULT_MODE_REASONING_EFFORT = "high";
62577
- var PLAN_MODE_REASONING_EFFORT = "xhigh";
62578
- function ensureCodexReasoningConfig(config) {
62579
- let next = replaceOrInsertRootSetting(config, "model_reasoning_effort", JSON.stringify(DEFAULT_MODE_REASONING_EFFORT));
62580
- next = replaceOrInsertRootSetting(next, "plan_mode_reasoning_effort", JSON.stringify(PLAN_MODE_REASONING_EFFORT));
62581
- return next;
62628
+ function isSectionHeader(line) {
62629
+ const trimmed = line.trim();
62630
+ return trimmed.startsWith("[") && trimmed.endsWith("]");
62631
+ }
62632
+ function isRootSetting(line, key) {
62633
+ const trimmed = line.trimStart();
62634
+ if (trimmed.startsWith("#") || trimmed.startsWith("["))
62635
+ return false;
62636
+ const match = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=/);
62637
+ return match?.[1] === key;
62638
+ }
62639
+
62640
+ // src/cli/install-codex/codex-model-catalog.ts
62641
+ import { readFile as readFile6 } from "fs/promises";
62642
+ import { join as join24 } from "path";
62643
+ var FALLBACK_CODEX_MODEL_CATALOG = {
62644
+ current: {
62645
+ model: "gpt-5.5",
62646
+ modelContextWindow: 400000,
62647
+ modelReasoningEffort: "high",
62648
+ planModeReasoningEffort: "xhigh"
62649
+ },
62650
+ managedProfiles: [{ model: "gpt-5.2" }]
62651
+ };
62652
+ async function readCodexModelCatalog(codexPackageRoot) {
62653
+ const catalogPath = join24(codexPackageRoot, "plugin", "model-catalog.json");
62654
+ try {
62655
+ const parsed = JSON.parse(await readFile6(catalogPath, "utf8"));
62656
+ return parseCodexModelCatalog(parsed) ?? FALLBACK_CODEX_MODEL_CATALOG;
62657
+ } catch (error) {
62658
+ if (error instanceof Error)
62659
+ return FALLBACK_CODEX_MODEL_CATALOG;
62660
+ throw error;
62661
+ }
62662
+ }
62663
+ function parseCodexModelCatalog(value) {
62664
+ if (!isRecord12(value))
62665
+ return null;
62666
+ const current = value["current"];
62667
+ const managedProfiles = value["managedProfiles"];
62668
+ if (!isRecord12(current) || !Array.isArray(managedProfiles))
62669
+ return null;
62670
+ const model = current["model"];
62671
+ const modelContextWindow = current["model_context_window"];
62672
+ const modelReasoningEffort = current["model_reasoning_effort"];
62673
+ const planModeReasoningEffort = current["plan_mode_reasoning_effort"];
62674
+ if (typeof model !== "string" || typeof modelContextWindow !== "number" || typeof modelReasoningEffort !== "string" || typeof planModeReasoningEffort !== "string") {
62675
+ return null;
62676
+ }
62677
+ const parsedManagedProfiles = [];
62678
+ for (const profile of managedProfiles) {
62679
+ if (!isRecord12(profile))
62680
+ return null;
62681
+ const match = profile["match"];
62682
+ if (!isRecord12(match))
62683
+ return null;
62684
+ parsedManagedProfiles.push(parseProfileMatch(match));
62685
+ }
62686
+ return {
62687
+ current: { model, modelContextWindow, modelReasoningEffort, planModeReasoningEffort },
62688
+ managedProfiles: parsedManagedProfiles
62689
+ };
62690
+ }
62691
+ function parseProfileMatch(match) {
62692
+ const profile = {};
62693
+ if (typeof match["model"] === "string")
62694
+ profile.model = match["model"];
62695
+ if (typeof match["model_context_window"] === "number")
62696
+ profile.modelContextWindow = match["model_context_window"];
62697
+ if (typeof match["model_reasoning_effort"] === "string")
62698
+ profile.modelReasoningEffort = match["model_reasoning_effort"];
62699
+ if (typeof match["plan_mode_reasoning_effort"] === "string")
62700
+ profile.planModeReasoningEffort = match["plan_mode_reasoning_effort"];
62701
+ return profile;
62702
+ }
62703
+ function isRecord12(value) {
62704
+ return typeof value === "object" && value !== null && !Array.isArray(value);
62582
62705
  }
62583
62706
 
62584
62707
  // src/cli/install-codex/codex-multi-agent-v2-config.ts
@@ -62586,35 +62709,35 @@ var CODEX_MULTI_AGENT_V2_HEADER = "features.multi_agent_v2";
62586
62709
  var CODEX_MULTI_AGENT_V2_MAX_CONCURRENT_THREADS_PER_SESSION = 1e4;
62587
62710
  function ensureCodexMultiAgentV2Config(config) {
62588
62711
  const normalizedConfig = removeLegacyAgentsMaxThreadsSetting(removeFeatureFlagSetting(config, "multi_agent_v2"));
62589
- const section = findTomlSection(normalizedConfig, CODEX_MULTI_AGENT_V2_HEADER);
62712
+ const section = findTomlSection2(normalizedConfig, CODEX_MULTI_AGENT_V2_HEADER);
62590
62713
  const maxThreadsValue = CODEX_MULTI_AGENT_V2_MAX_CONCURRENT_THREADS_PER_SESSION.toString();
62591
62714
  if (!section) {
62592
- return appendBlock(normalizedConfig, `[${CODEX_MULTI_AGENT_V2_HEADER}]
62715
+ return appendBlock2(normalizedConfig, `[${CODEX_MULTI_AGENT_V2_HEADER}]
62593
62716
  enabled = true
62594
62717
  max_concurrent_threads_per_session = ${maxThreadsValue}
62595
62718
  `);
62596
62719
  }
62597
- const enabledConfig = replaceOrInsertSetting(normalizedConfig, section, "enabled", "true");
62598
- const updatedSection = findTomlSection(enabledConfig, CODEX_MULTI_AGENT_V2_HEADER);
62720
+ const enabledConfig = replaceOrInsertSetting2(normalizedConfig, section, "enabled", "true");
62721
+ const updatedSection = findTomlSection2(enabledConfig, CODEX_MULTI_AGENT_V2_HEADER);
62599
62722
  if (!updatedSection) {
62600
- return appendBlock(enabledConfig, `[${CODEX_MULTI_AGENT_V2_HEADER}]
62723
+ return appendBlock2(enabledConfig, `[${CODEX_MULTI_AGENT_V2_HEADER}]
62601
62724
  enabled = true
62602
62725
  max_concurrent_threads_per_session = ${maxThreadsValue}
62603
62726
  `);
62604
62727
  }
62605
- return replaceOrInsertSetting(enabledConfig, updatedSection, "max_concurrent_threads_per_session", maxThreadsValue);
62728
+ return replaceOrInsertSetting2(enabledConfig, updatedSection, "max_concurrent_threads_per_session", maxThreadsValue);
62606
62729
  }
62607
62730
  function removeFeatureFlagSetting(config, featureName) {
62608
- const section = findTomlSection(config, "features");
62731
+ const section = findTomlSection2(config, "features");
62609
62732
  if (!section)
62610
62733
  return config;
62611
- return removeSetting(config, section, featureName);
62734
+ return removeSetting2(config, section, featureName);
62612
62735
  }
62613
62736
  function removeLegacyAgentsMaxThreadsSetting(config) {
62614
- const section = findTomlSection(config, "agents");
62737
+ const section = findTomlSection2(config, "agents");
62615
62738
  if (!section)
62616
62739
  return config;
62617
- return removeSetting(config, section, "max_threads");
62740
+ return removeSetting2(config, section, "max_threads");
62618
62741
  }
62619
62742
 
62620
62743
  // src/cli/install-codex/codex-config-toml.ts
@@ -62631,7 +62754,7 @@ async function updateCodexConfig(input) {
62631
62754
  await mkdir3(dirname12(input.configPath), { recursive: true });
62632
62755
  let config = "";
62633
62756
  if (await exists2(input.configPath))
62634
- config = await readFile6(input.configPath, "utf8");
62757
+ config = await readFile7(input.configPath, "utf8");
62635
62758
  const pluginSet = new Set(input.pluginNames);
62636
62759
  for (const legacyMarketplaceName of legacyMarketplaceNames(input.marketplaceName)) {
62637
62760
  config = removeMarketplaceBlock(config, legacyMarketplaceName);
@@ -62643,9 +62766,8 @@ async function updateCodexConfig(input) {
62643
62766
  config = removeStaleManagedAgentBlocks(config, new Set((input.agentConfigs ?? []).map((agentConfig) => agentConfig.name)));
62644
62767
  config = ensureFeatureEnabled(config, "plugins");
62645
62768
  config = ensureFeatureEnabled(config, "plugin_hooks");
62646
- config = ensureCodexReasoningConfig(config);
62769
+ config = ensureCodexReasoningConfig(config, await readCodexModelCatalog(input.repoRoot));
62647
62770
  config = ensureCodexMultiAgentV2Config(config);
62648
- config = ensureContext7McpServer(config);
62649
62771
  if (input.autonomousPermissions === true)
62650
62772
  config = ensureAutonomousPermissions(config);
62651
62773
  config = ensureMarketplaceBlock(config, input.marketplaceName, input.marketplaceSource);
@@ -62711,12 +62833,12 @@ function removeStaleManagedAgentBlocks(config, keepAgentNames) {
62711
62833
  `);
62712
62834
  }
62713
62835
  function ensureFeatureEnabled(config, featureName) {
62714
- const section = findTomlSection(config, "features");
62836
+ const section = findTomlSection2(config, "features");
62715
62837
  if (!section)
62716
- return appendBlock(config, `[features]
62838
+ return appendBlock2(config, `[features]
62717
62839
  ${featureName} = true
62718
62840
  `);
62719
- return replaceOrInsertSetting(config, section, featureName, "true");
62841
+ return replaceOrInsertSetting2(config, section, featureName, "true");
62720
62842
  }
62721
62843
  function ensureMarketplaceBlock(config, marketplaceName, source) {
62722
62844
  const header = `marketplaces.${marketplaceName}`;
@@ -62732,29 +62854,29 @@ function ensureMarketplaceBlock(config, marketplaceName, source) {
62732
62854
  lines.push("");
62733
62855
  const block = lines.join(`
62734
62856
  `);
62735
- const section = findTomlSection(config, header);
62857
+ const section = findTomlSection2(config, header);
62736
62858
  if (section)
62737
62859
  return config.slice(0, section.start) + block + config.slice(section.end);
62738
- return appendBlock(config, block);
62860
+ return appendBlock2(config, block);
62739
62861
  }
62740
62862
  function ensurePluginEnabled(config, pluginKey) {
62741
62863
  const header = `plugins.${JSON.stringify(pluginKey)}`;
62742
- const section = findTomlSection(config, header);
62864
+ const section = findTomlSection2(config, header);
62743
62865
  if (!section)
62744
- return appendBlock(config, `[${header}]
62866
+ return appendBlock2(config, `[${header}]
62745
62867
  enabled = true
62746
62868
  `);
62747
- return replaceOrInsertSetting(config, section, "enabled", "true");
62869
+ return replaceOrInsertSetting2(config, section, "enabled", "true");
62748
62870
  }
62749
62871
  function ensurePluginMcpEnabled(config, pluginKey, serverName, enabled) {
62750
62872
  const header = `plugins.${JSON.stringify(pluginKey)}.mcp_servers.${serverName}`;
62751
- const section = findTomlSection(config, header);
62873
+ const section = findTomlSection2(config, header);
62752
62874
  const enabledValue = enabled ? "true" : "false";
62753
62875
  if (!section)
62754
- return appendBlock(config, `[${header}]
62876
+ return appendBlock2(config, `[${header}]
62755
62877
  enabled = ${enabledValue}
62756
62878
  `);
62757
- return replaceOrInsertSetting(config, section, "enabled", enabledValue);
62879
+ return replaceOrInsertSetting2(config, section, "enabled", enabledValue);
62758
62880
  }
62759
62881
  function ensureOmoGitBashMcpPolicy(config, input) {
62760
62882
  if (input.marketplaceName !== "sisyphuslabs" || !input.pluginNames.includes("omo"))
@@ -62764,22 +62886,22 @@ function ensureOmoGitBashMcpPolicy(config, input) {
62764
62886
  }
62765
62887
  function ensureHookTrusted(config, key, trustedHash) {
62766
62888
  const header = `hooks.state.${JSON.stringify(key)}`;
62767
- const section = findTomlSection(config, header);
62889
+ const section = findTomlSection2(config, header);
62768
62890
  if (!section)
62769
- return appendBlock(config, `[${header}]
62891
+ return appendBlock2(config, `[${header}]
62770
62892
  trusted_hash = ${JSON.stringify(trustedHash)}
62771
62893
  `);
62772
- return replaceOrInsertSetting(config, section, "trusted_hash", JSON.stringify(trustedHash));
62894
+ return replaceOrInsertSetting2(config, section, "trusted_hash", JSON.stringify(trustedHash));
62773
62895
  }
62774
62896
  function ensureAgentConfig(config, agentConfig) {
62775
62897
  const header = `agents.${tomlKeySegment(agentConfig.name)}`;
62776
- const section = findTomlSection(config, header);
62898
+ const section = findTomlSection2(config, header);
62777
62899
  const configFile = JSON.stringify(agentConfig.configFile);
62778
62900
  if (!section)
62779
- return appendBlock(config, `[${header}]
62901
+ return appendBlock2(config, `[${header}]
62780
62902
  config_file = ${configFile}
62781
62903
  `);
62782
- return replaceOrInsertSetting(config, section, "config_file", configFile);
62904
+ return replaceOrInsertSetting2(config, section, "config_file", configFile);
62783
62905
  }
62784
62906
  function tomlKeySegment(value) {
62785
62907
  return /^[A-Za-z0-9_-]+$/.test(value) ? value : JSON.stringify(value);
@@ -62859,7 +62981,7 @@ function parseJsonString(value) {
62859
62981
  }
62860
62982
  async function exists2(path6) {
62861
62983
  try {
62862
- await readFile6(path6, "utf8");
62984
+ await readFile7(path6, "utf8");
62863
62985
  return true;
62864
62986
  } catch (error) {
62865
62987
  if (error instanceof Error)
@@ -62870,8 +62992,8 @@ async function exists2(path6) {
62870
62992
 
62871
62993
  // src/cli/install-codex/codex-hook-trust.ts
62872
62994
  import { createHash as createHash2 } from "crypto";
62873
- import { readFile as readFile7 } from "fs/promises";
62874
- import { join as join24 } from "path";
62995
+ import { readFile as readFile8 } from "fs/promises";
62996
+ import { join as join25 } from "path";
62875
62997
  var EVENT_LABELS = new Map([
62876
62998
  ["PreToolUse", "pre_tool_use"],
62877
62999
  ["PermissionRequest", "permission_request"],
@@ -62885,17 +63007,17 @@ var EVENT_LABELS = new Map([
62885
63007
  ["Stop", "stop"]
62886
63008
  ]);
62887
63009
  async function trustedHookStatesForPlugin(input) {
62888
- const manifestPath = join24(input.pluginRoot, ".codex-plugin", "plugin.json");
63010
+ const manifestPath = join25(input.pluginRoot, ".codex-plugin", "plugin.json");
62889
63011
  if (!await exists3(manifestPath))
62890
63012
  return [];
62891
- const manifest = JSON.parse(await readFile7(manifestPath, "utf8"));
62892
- if (!isRecord12(manifest) || typeof manifest.hooks !== "string")
63013
+ const manifest = JSON.parse(await readFile8(manifestPath, "utf8"));
63014
+ if (!isRecord13(manifest) || typeof manifest.hooks !== "string")
62893
63015
  return [];
62894
- const hooksPath = join24(input.pluginRoot, manifest.hooks);
63016
+ const hooksPath = join25(input.pluginRoot, manifest.hooks);
62895
63017
  if (!await exists3(hooksPath))
62896
63018
  return [];
62897
- const parsed = JSON.parse(await readFile7(hooksPath, "utf8"));
62898
- if (!isRecord12(parsed) || !isRecord12(parsed.hooks))
63019
+ const parsed = JSON.parse(await readFile8(hooksPath, "utf8"));
63020
+ if (!isRecord13(parsed) || !isRecord13(parsed.hooks))
62899
63021
  return [];
62900
63022
  const keySource = `${input.pluginName}@${input.marketplaceName}:${stripDotSlash(manifest.hooks)}`;
62901
63023
  const states = [];
@@ -62906,10 +63028,10 @@ async function trustedHookStatesForPlugin(input) {
62906
63028
  if (eventLabel === undefined)
62907
63029
  continue;
62908
63030
  for (const [groupIndex, group] of groups.entries()) {
62909
- if (!isRecord12(group) || !Array.isArray(group.hooks))
63031
+ if (!isRecord13(group) || !Array.isArray(group.hooks))
62910
63032
  continue;
62911
63033
  for (const [handlerIndex, handler] of group.hooks.entries()) {
62912
- if (!isRecord12(handler) || handler.type !== "command")
63034
+ if (!isRecord13(handler) || handler.type !== "command")
62913
63035
  continue;
62914
63036
  if (handler.async === true)
62915
63037
  continue;
@@ -62941,7 +63063,7 @@ function commandHookHash(eventName, matcher, handler) {
62941
63063
  function canonicalJson(value) {
62942
63064
  if (Array.isArray(value))
62943
63065
  return value.map(canonicalJson);
62944
- if (!isRecord12(value))
63066
+ if (!isRecord13(value))
62945
63067
  return value;
62946
63068
  const result = {};
62947
63069
  for (const key of Object.keys(value).sort()) {
@@ -62954,13 +63076,13 @@ function stripDotSlash(value) {
62954
63076
  }
62955
63077
  async function exists3(path6) {
62956
63078
  try {
62957
- await readFile7(path6, "utf8");
63079
+ await readFile8(path6, "utf8");
62958
63080
  return true;
62959
63081
  } catch {
62960
63082
  return false;
62961
63083
  }
62962
63084
  }
62963
- function isRecord12(value) {
63085
+ function isRecord13(value) {
62964
63086
  return typeof value === "object" && value !== null && !Array.isArray(value);
62965
63087
  }
62966
63088
 
@@ -63060,7 +63182,7 @@ function whereCommand(command) {
63060
63182
 
63061
63183
  // src/cli/install-codex/link-cached-plugin-agents.ts
63062
63184
  import { copyFile, lstat as lstat3, mkdir as mkdir4, readdir as readdir3, rm as rm3, symlink as symlink2, writeFile as writeFile4 } from "fs/promises";
63063
- import { basename as basename6, join as join25 } from "path";
63185
+ import { basename as basename6, join as join26 } from "path";
63064
63186
  var MANIFEST_FILE = ".installed-agents.json";
63065
63187
  async function linkCachedPluginAgents(input) {
63066
63188
  const platform = input.platform ?? process.platform;
@@ -63069,11 +63191,11 @@ async function linkCachedPluginAgents(input) {
63069
63191
  await writeManifest(input.pluginRoot, []);
63070
63192
  return [];
63071
63193
  }
63072
- const agentsDir = join25(input.codexHome, "agents");
63194
+ const agentsDir = join26(input.codexHome, "agents");
63073
63195
  await mkdir4(agentsDir, { recursive: true });
63074
63196
  const linked = [];
63075
63197
  for (const agentPath of bundledAgents) {
63076
- const linkPath = join25(agentsDir, basename6(agentPath));
63198
+ const linkPath = join26(agentsDir, basename6(agentPath));
63077
63199
  if (platform === "win32") {
63078
63200
  await replaceWithCopy(linkPath, agentPath);
63079
63201
  } else {
@@ -63085,7 +63207,7 @@ async function linkCachedPluginAgents(input) {
63085
63207
  return linked;
63086
63208
  }
63087
63209
  async function discoverBundledAgents(pluginRoot) {
63088
- const componentsRoot = join25(pluginRoot, "components");
63210
+ const componentsRoot = join26(pluginRoot, "components");
63089
63211
  if (!await exists4(componentsRoot))
63090
63212
  return [];
63091
63213
  const componentEntries = await readdir3(componentsRoot, { withFileTypes: true });
@@ -63093,14 +63215,14 @@ async function discoverBundledAgents(pluginRoot) {
63093
63215
  for (const entry of componentEntries) {
63094
63216
  if (!entry.isDirectory())
63095
63217
  continue;
63096
- const agentsRoot = join25(componentsRoot, entry.name, "agents");
63218
+ const agentsRoot = join26(componentsRoot, entry.name, "agents");
63097
63219
  if (!await exists4(agentsRoot))
63098
63220
  continue;
63099
63221
  const agentEntries = await readdir3(agentsRoot, { withFileTypes: true });
63100
63222
  for (const file of agentEntries) {
63101
63223
  if (!file.isFile() || !file.name.endsWith(".toml"))
63102
63224
  continue;
63103
- agents.push(join25(agentsRoot, file.name));
63225
+ agents.push(join26(agentsRoot, file.name));
63104
63226
  }
63105
63227
  }
63106
63228
  agents.sort();
@@ -63124,7 +63246,7 @@ async function prepareReplacement(linkPath) {
63124
63246
  await rm3(linkPath, { force: true });
63125
63247
  }
63126
63248
  async function writeManifest(pluginRoot, agentPaths) {
63127
- const manifestPath = join25(pluginRoot, MANIFEST_FILE);
63249
+ const manifestPath = join26(pluginRoot, MANIFEST_FILE);
63128
63250
  const payload = { agents: [...agentPaths].sort() };
63129
63251
  await writeFile4(manifestPath, `${JSON.stringify(payload, null, "\t")}
63130
63252
  `);
@@ -63139,14 +63261,14 @@ async function exists4(path6) {
63139
63261
  }
63140
63262
 
63141
63263
  // src/cli/install-codex/codex-marketplace.ts
63142
- import { readFile as readFile8 } from "fs/promises";
63143
- import { join as join26 } from "path";
63264
+ import { readFile as readFile9 } from "fs/promises";
63265
+ import { join as join27 } from "path";
63144
63266
  var DEFAULT_MARKETPLACE_PATH = "packages/omo-codex/marketplace.json";
63145
63267
  async function readMarketplace(repoRoot, options) {
63146
- const marketplacePath = options?.marketplacePath ?? join26(repoRoot, DEFAULT_MARKETPLACE_PATH);
63147
- const raw = await readFile8(marketplacePath, "utf8");
63268
+ const marketplacePath = options?.marketplacePath ?? join27(repoRoot, DEFAULT_MARKETPLACE_PATH);
63269
+ const raw = await readFile9(marketplacePath, "utf8");
63148
63270
  const parsed = JSON.parse(raw);
63149
- if (!isRecord13(parsed))
63271
+ if (!isRecord14(parsed))
63150
63272
  throw new Error("marketplace.json must be an object");
63151
63273
  if (typeof parsed.name !== "string" || parsed.name.trim() === "") {
63152
63274
  throw new Error("marketplace.json name must be a non-empty string");
@@ -63162,12 +63284,12 @@ async function readMarketplace(repoRoot, options) {
63162
63284
  function resolvePluginSource(repoRoot, plugin, options) {
63163
63285
  const sourcePath = localSourcePath(options?.pathOverride ?? plugin.source);
63164
63286
  const relativePath = sourcePath.slice(2);
63165
- return join26(repoRoot, ...relativePath.split(/[\\/]/));
63287
+ return join27(repoRoot, ...relativePath.split(/[\\/]/));
63166
63288
  }
63167
63289
  async function readPluginManifest(pluginRoot) {
63168
- const raw = await readFile8(join26(pluginRoot, ".codex-plugin", "plugin.json"), "utf8");
63290
+ const raw = await readFile9(join27(pluginRoot, ".codex-plugin", "plugin.json"), "utf8");
63169
63291
  const parsed = JSON.parse(raw);
63170
- if (!isRecord13(parsed))
63292
+ if (!isRecord14(parsed))
63171
63293
  throw new Error(`${pluginRoot} plugin.json must be an object`);
63172
63294
  if (typeof parsed.name !== "string" || parsed.name.trim() === "") {
63173
63295
  throw new Error(`${pluginRoot} plugin.json name must be a non-empty string`);
@@ -63193,7 +63315,7 @@ function validatePathSegment(value, label) {
63193
63315
  }
63194
63316
  }
63195
63317
  function normalizeMarketplacePlugin(plugin, index) {
63196
- if (!isRecord13(plugin))
63318
+ if (!isRecord14(plugin))
63197
63319
  throw new Error(`marketplace plugin ${index} must be an object`);
63198
63320
  if (typeof plugin.name !== "string" || plugin.name.trim() === "") {
63199
63321
  throw new Error(`marketplace plugin ${index} name must be a non-empty string`);
@@ -63205,7 +63327,7 @@ function normalizeMarketplacePlugin(plugin, index) {
63205
63327
  }
63206
63328
  return { name: plugin.name, source: plugin.source };
63207
63329
  }
63208
- if (isRecord13(plugin.source) && plugin.source.source === "local" && typeof plugin.source.path === "string") {
63330
+ if (isRecord14(plugin.source) && plugin.source.source === "local" && typeof plugin.source.path === "string") {
63209
63331
  validateLocalSourcePath(plugin.source.path);
63210
63332
  const local = { source: "local", path: plugin.source.path };
63211
63333
  return { name: plugin.name, source: local };
@@ -63232,13 +63354,13 @@ function validateLocalSourcePath(path6) {
63232
63354
  }
63233
63355
  return path6;
63234
63356
  }
63235
- function isRecord13(value) {
63357
+ function isRecord14(value) {
63236
63358
  return typeof value === "object" && value !== null && !Array.isArray(value);
63237
63359
  }
63238
63360
 
63239
63361
  // src/cli/install-codex/codex-marketplace-snapshot.ts
63240
63362
  import { cp as cp3, mkdir as mkdir5, rename as rename2, rm as rm4, writeFile as writeFile5 } from "fs/promises";
63241
- import { join as join27, sep as sep2 } from "path";
63363
+ import { join as join28, sep as sep2 } from "path";
63242
63364
  var INSTALLED_MARKETPLACES_DIR = ".tmp/marketplaces";
63243
63365
  async function writeInstalledMarketplaceSnapshot(input) {
63244
63366
  const marketplaceRoot = installedMarketplaceRoot(input.codexHome, input.marketplace.name);
@@ -63251,21 +63373,21 @@ async function writeInstalledMarketplaceSnapshot(input) {
63251
63373
  return snapshotPlugins;
63252
63374
  }
63253
63375
  function installedMarketplaceRoot(codexHome, marketplaceName) {
63254
- return join27(codexHome, INSTALLED_MARKETPLACES_DIR, marketplaceName);
63376
+ return join28(codexHome, INSTALLED_MARKETPLACES_DIR, marketplaceName);
63255
63377
  }
63256
63378
  async function writeMarketplaceManifest(marketplaceRoot, marketplace) {
63257
- const manifestDir = join27(marketplaceRoot, ".agents", "plugins");
63379
+ const manifestDir = join28(marketplaceRoot, ".agents", "plugins");
63258
63380
  await mkdir5(manifestDir, { recursive: true });
63259
- const tempPath = join27(manifestDir, `.marketplace-${process.pid}-${Date.now()}.json.tmp`);
63381
+ const tempPath = join28(manifestDir, `.marketplace-${process.pid}-${Date.now()}.json.tmp`);
63260
63382
  await writeFile5(tempPath, `${JSON.stringify(marketplace, null, "\t")}
63261
63383
  `);
63262
- await rename2(tempPath, join27(manifestDir, "marketplace.json"));
63384
+ await rename2(tempPath, join28(manifestDir, "marketplace.json"));
63263
63385
  }
63264
63386
  async function writeSnapshotPlugin(marketplaceRoot, plugin) {
63265
- const pluginsDir = join27(marketplaceRoot, "plugins");
63387
+ const pluginsDir = join28(marketplaceRoot, "plugins");
63266
63388
  await mkdir5(pluginsDir, { recursive: true });
63267
- const targetPath = join27(pluginsDir, plugin.name);
63268
- const tempPath = join27(pluginsDir, `.tmp-${plugin.name}-${process.pid}-${Date.now()}`);
63389
+ const targetPath = join28(pluginsDir, plugin.name);
63390
+ const tempPath = join28(pluginsDir, `.tmp-${plugin.name}-${process.pid}-${Date.now()}`);
63269
63391
  await rm4(tempPath, { recursive: true, force: true });
63270
63392
  await cp3(plugin.sourcePath, tempPath, {
63271
63393
  recursive: true,
@@ -63304,8 +63426,8 @@ var defaultRunCommand = async (command, args, options) => {
63304
63426
  };
63305
63427
 
63306
63428
  // src/cli/install-codex/codex-project-local-cleanup.ts
63307
- import { copyFile as copyFile2, lstat as lstat4, readFile as readFile9, writeFile as writeFile6 } from "fs/promises";
63308
- import { dirname as dirname13, join as join28, resolve as resolve8 } from "path";
63429
+ import { copyFile as copyFile2, lstat as lstat4, readFile as readFile10, writeFile as writeFile6 } from "fs/promises";
63430
+ import { dirname as dirname13, join as join29, resolve as resolve8 } from "path";
63309
63431
  var LEGACY_AGENT_CONFLICT_KEYS = ["max_threads"];
63310
63432
  var PROJECT_LOCAL_ARTIFACT_PATHS = [
63311
63433
  ".omx",
@@ -63322,7 +63444,7 @@ async function repairNearestProjectLocalCodexArtifacts(input) {
63322
63444
  const artifacts = await collectProjectLocalArtifacts(project.artifactRoots);
63323
63445
  const configs = [];
63324
63446
  for (const configPath of project.configPaths) {
63325
- const original = await readFile9(configPath, "utf8");
63447
+ const original = await readFile10(configPath, "utf8");
63326
63448
  const repair = repairProjectLocalCodexConfigText(original);
63327
63449
  if (!repair.changed) {
63328
63450
  configs.push({
@@ -63387,10 +63509,10 @@ function repairProjectLocalCodexConfigText(config) {
63387
63509
  let nextConfig = config;
63388
63510
  const removedKeys = [];
63389
63511
  for (const key of LEGACY_AGENT_CONFLICT_KEYS) {
63390
- const section = findTomlSection(nextConfig, "agents");
63512
+ const section = findTomlSection2(nextConfig, "agents");
63391
63513
  if (section === null || !hasSetting(section.text, key))
63392
63514
  continue;
63393
- nextConfig = removeSetting(nextConfig, section, key);
63515
+ nextConfig = removeSetting2(nextConfig, section, key);
63394
63516
  removedKeys.push(key);
63395
63517
  }
63396
63518
  return {
@@ -63406,17 +63528,17 @@ async function findProjectLocalCodexConfigs(startDirectory, codexHome) {
63406
63528
  if (startDirectoryStat !== null && !startDirectoryStat.isDirectory()) {
63407
63529
  throw new ProjectLocalCleanupStartDirectoryError(startDirectory);
63408
63530
  }
63409
- const codexHomeConfigPath = codexHome === undefined ? null : join28(resolve8(codexHome), "config.toml");
63531
+ const codexHomeConfigPath = codexHome === undefined ? null : join29(resolve8(codexHome), "config.toml");
63410
63532
  let current = resolve8(startDirectory);
63411
63533
  const configPathsFromCwd = [];
63412
63534
  while (true) {
63413
- const configPath = join28(current, ".codex", "config.toml");
63535
+ const configPath = join29(current, ".codex", "config.toml");
63414
63536
  if (await isRegularProjectLocalConfig(current, configPath)) {
63415
63537
  if (codexHomeConfigPath === null || resolve8(configPath) !== codexHomeConfigPath) {
63416
63538
  configPathsFromCwd.push(configPath);
63417
63539
  }
63418
63540
  }
63419
- if (await exists5(join28(current, ".git"))) {
63541
+ if (await exists5(join29(current, ".git"))) {
63420
63542
  return configPathsFromCwd.length === 0 ? null : {
63421
63543
  projectRoot: current,
63422
63544
  configPaths: [...configPathsFromCwd].reverse(),
@@ -63436,7 +63558,7 @@ async function findProjectLocalCodexConfigs(startDirectory, codexHome) {
63436
63558
  }
63437
63559
  }
63438
63560
  async function isRegularProjectLocalConfig(directory, configPath) {
63439
- const codexDirStat = await maybeLstat(join28(directory, ".codex"));
63561
+ const codexDirStat = await maybeLstat(join29(directory, ".codex"));
63440
63562
  if (codexDirStat === null || !codexDirStat.isDirectory() || codexDirStat.isSymbolicLink())
63441
63563
  return false;
63442
63564
  const configStat = await maybeLstat(configPath);
@@ -63456,7 +63578,7 @@ async function collectProjectLocalArtifacts(projectRoots) {
63456
63578
  const seenPaths = new Set;
63457
63579
  for (const projectRoot of projectRoots) {
63458
63580
  for (const relativePath of PROJECT_LOCAL_ARTIFACT_PATHS) {
63459
- const artifactPath = join28(projectRoot, relativePath);
63581
+ const artifactPath = join29(projectRoot, relativePath);
63460
63582
  if (seenPaths.has(artifactPath))
63461
63583
  continue;
63462
63584
  const entryStat = await maybeLstat(artifactPath);
@@ -63473,17 +63595,17 @@ async function collectProjectLocalArtifacts(projectRoots) {
63473
63595
  return artifacts;
63474
63596
  }
63475
63597
  function isMultiAgentV2Enabled(config) {
63476
- const featuresSection = findTomlSection(config, "features");
63598
+ const featuresSection = findTomlSection2(config, "features");
63477
63599
  if (featuresSection !== null && settingIsBooleanTrue(featuresSection.text, "multi_agent_v2"))
63478
63600
  return true;
63479
- const multiAgentSection = findTomlSection(config, "features.multi_agent_v2");
63601
+ const multiAgentSection = findTomlSection2(config, "features.multi_agent_v2");
63480
63602
  return multiAgentSection !== null && settingIsBooleanTrue(multiAgentSection.text, "enabled");
63481
63603
  }
63482
63604
  function settingIsBooleanTrue(sectionText, key) {
63483
- return new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*true\\s*(?:#.*)?$`, "m").test(sectionText);
63605
+ return new RegExp(`^\\s*${escapeRegExp2(key)}\\s*=\\s*true\\s*(?:#.*)?$`, "m").test(sectionText);
63484
63606
  }
63485
63607
  function hasSetting(sectionText, key) {
63486
- return new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`, "m").test(sectionText);
63608
+ return new RegExp(`^\\s*${escapeRegExp2(key)}\\s*=`, "m").test(sectionText);
63487
63609
  }
63488
63610
  function formatBackupTimestamp(date) {
63489
63611
  return date.toISOString().replace(/[:.]/g, "-");
@@ -63536,7 +63658,7 @@ async function runCodexInstaller(options = {}) {
63536
63658
  const env = options.env ?? process.env;
63537
63659
  const platform = options.platform ?? process.platform;
63538
63660
  const repoRoot = resolve9(options.repoRoot ?? findRepoRoot({ importerDir: import.meta.dir, env }));
63539
- const codexHome = resolve9(options.codexHome ?? env.CODEX_HOME ?? join30(homedir5(), ".codex"));
63661
+ const codexHome = resolve9(options.codexHome ?? env.CODEX_HOME ?? join31(homedir5(), ".codex"));
63540
63662
  const projectDirectory = resolve9(options.projectDirectory ?? env.OMO_CODEX_PROJECT ?? process.cwd());
63541
63663
  const binDir = resolveCodexInstallerBinDir({ binDir: options.binDir, codexHome, env });
63542
63664
  const runCommand = options.runCommand ?? defaultRunCommand;
@@ -63554,9 +63676,9 @@ async function runCodexInstaller(options = {}) {
63554
63676
  if (!gitBashResolution.found) {
63555
63677
  throw new Error(gitBashResolution.installHint);
63556
63678
  }
63557
- const codexPackageRoot = join30(repoRoot, "packages", "omo-codex");
63679
+ const codexPackageRoot = join31(repoRoot, "packages", "omo-codex");
63558
63680
  const marketplace = await readMarketplace(repoRoot, {
63559
- marketplacePath: join30(codexPackageRoot, "marketplace.json")
63681
+ marketplacePath: join31(codexPackageRoot, "marketplace.json")
63560
63682
  });
63561
63683
  const installed = [];
63562
63684
  const pluginSources = [];
@@ -63618,13 +63740,13 @@ async function runCodexInstaller(options = {}) {
63618
63740
  pluginNames: marketplace.plugins.map((plugin) => plugin.name)
63619
63741
  });
63620
63742
  }
63621
- const marketplaceRoot = join30(codexHome, "plugins", "cache", marketplace.name);
63743
+ const marketplaceRoot = join31(codexHome, "plugins", "cache", marketplace.name);
63622
63744
  await writeCachedMarketplaceManifest({
63623
63745
  marketplaceName: marketplace.name,
63624
63746
  marketplaceRoot,
63625
63747
  plugins: installed
63626
63748
  });
63627
- const configPath = join30(codexHome, "config.toml");
63749
+ const configPath = join31(codexHome, "config.toml");
63628
63750
  await updateCodexConfig({
63629
63751
  configPath,
63630
63752
  repoRoot: codexPackageRoot,
@@ -63634,7 +63756,7 @@ async function runCodexInstaller(options = {}) {
63634
63756
  platform,
63635
63757
  trustedHookStates,
63636
63758
  agentConfigs: [...agentConfigs.values()].sort((left, right) => left.name.localeCompare(right.name)),
63637
- autonomousPermissions: options.autonomousPermissions === true
63759
+ autonomousPermissions: options.autonomousPermissions !== false
63638
63760
  });
63639
63761
  const projectCleanup = await repairProjectLocalCodexArtifactsBestEffort({
63640
63762
  startDirectory: projectDirectory,
@@ -63667,7 +63789,7 @@ function resolveCodexInstallerBinDir(input) {
63667
63789
  const defaultCodexHome = resolve9(homeDir, ".codex");
63668
63790
  const resolvedCodexHome = resolve9(input.codexHome);
63669
63791
  if (resolvedCodexHome !== defaultCodexHome)
63670
- return join30(resolvedCodexHome, "bin");
63792
+ return join31(resolvedCodexHome, "bin");
63671
63793
  return resolve9(homeDir, ".local", "bin");
63672
63794
  }
63673
63795
  function agentNameFromToml(fileName) {
@@ -63685,9 +63807,9 @@ async function agentSourceRootsForInstall(input) {
63685
63807
  return new Map(snapshotPlugins.map((plugin) => [plugin.name, plugin.path]));
63686
63808
  }
63687
63809
  async function writeCachedMarketplaceManifest(input) {
63688
- const marketplaceDir = join30(input.marketplaceRoot, ".agents", "plugins");
63810
+ const marketplaceDir = join31(input.marketplaceRoot, ".agents", "plugins");
63689
63811
  await mkdir6(marketplaceDir, { recursive: true });
63690
- await writeFile7(join30(marketplaceDir, "marketplace.json"), `${JSON.stringify({
63812
+ await writeFile7(join31(marketplaceDir, "marketplace.json"), `${JSON.stringify({
63691
63813
  name: input.marketplaceName,
63692
63814
  plugins: input.plugins.map((plugin) => ({
63693
63815
  name: plugin.name,
@@ -63704,7 +63826,7 @@ function findRepoRootFromImporter(importerDir) {
63704
63826
  for (let depth = 0;depth <= 5; depth += 1) {
63705
63827
  if (isRepoRootWithCodexPlugin(current))
63706
63828
  return current;
63707
- for (const wrapperPackageRoot of [join30(current, "node_modules", "oh-my-openagent"), join30(current, "oh-my-openagent")]) {
63829
+ for (const wrapperPackageRoot of [join31(current, "node_modules", "oh-my-openagent"), join31(current, "oh-my-openagent")]) {
63708
63830
  if (isRepoRootWithCodexPlugin(wrapperPackageRoot))
63709
63831
  return wrapperPackageRoot;
63710
63832
  }
@@ -63722,7 +63844,7 @@ function findRepoRoot(input) {
63722
63844
  return findRepoRootFromImporter(input.importerDir);
63723
63845
  }
63724
63846
  function isRepoRootWithCodexPlugin(repoRoot) {
63725
- return existsSync25(join30(repoRoot, "packages", "omo-codex", "plugin", ".codex-plugin", "plugin.json"));
63847
+ return existsSync25(join31(repoRoot, "packages", "omo-codex", "plugin", ".codex-plugin", "plugin.json"));
63726
63848
  }
63727
63849
  function codexMarketplaceSource(marketplaceRoot) {
63728
63850
  return { sourceType: "local", source: marketplaceRoot };
@@ -63743,11 +63865,11 @@ async function trackCodexInstallTelemetry() {
63743
63865
  import { execFile } from "child_process";
63744
63866
  import { existsSync as existsSync26 } from "fs";
63745
63867
  import { homedir as homedir6 } from "os";
63746
- import { join as join32, win32 as win322 } from "path";
63868
+ import { join as join33, win32 as win322 } from "path";
63747
63869
 
63748
63870
  // src/shared/bun-which-shim.ts
63749
63871
  import { accessSync as accessSync3, constants as constants4 } from "fs";
63750
- import { delimiter, join as join31 } from "path";
63872
+ import { delimiter, join as join32 } from "path";
63751
63873
  var runtime3 = globalThis;
63752
63874
  var IS_BUN2 = typeof runtime3.Bun !== "undefined";
63753
63875
  function isUnsafeCommandName(commandName) {
@@ -63795,7 +63917,7 @@ function bunWhich(commandName) {
63795
63917
  const candidateNames = getWindowsCandidates(commandName);
63796
63918
  for (const pathEntry of pathEntries) {
63797
63919
  for (const candidateName of candidateNames) {
63798
- const candidatePath = join31(pathEntry, candidateName);
63920
+ const candidatePath = join32(pathEntry, candidateName);
63799
63921
  if (isExecutable(candidatePath))
63800
63922
  return candidatePath;
63801
63923
  }
@@ -63880,11 +64002,11 @@ async function findWindowsCodexStartApp(runCommand) {
63880
64002
  }
63881
64003
  }
63882
64004
  function macCodexAppPaths(homeDir) {
63883
- return ["/Applications/Codex.app", join32(homeDir, "Applications", "Codex.app")];
64005
+ return ["/Applications/Codex.app", join33(homeDir, "Applications", "Codex.app")];
63884
64006
  }
63885
64007
  function macCodexDmgPaths(homeDir) {
63886
- const downloads = join32(homeDir, "Downloads");
63887
- return [join32(downloads, "codex.dmg"), join32(downloads, "Codex.dmg")];
64008
+ const downloads = join33(homeDir, "Downloads");
64009
+ return [join33(downloads, "codex.dmg"), join33(downloads, "Codex.dmg")];
63888
64010
  }
63889
64011
  function windowsCodexCliPaths(env) {
63890
64012
  const candidates = [];
@@ -63928,12 +64050,12 @@ function defaultRunCommand2(command, args) {
63928
64050
  });
63929
64051
  }
63930
64052
  // src/cli/install-codex/codex-cleanup.ts
63931
- import { lstat as lstat6, readFile as readFile11, readdir as readdir4, rm as rm5 } from "fs/promises";
64053
+ import { lstat as lstat6, readFile as readFile12, readdir as readdir4, rm as rm5 } from "fs/promises";
63932
64054
  import { homedir as homedir7 } from "os";
63933
- import { isAbsolute as isAbsolute6, join as join33, relative as relative5, resolve as resolve10 } from "path";
64055
+ import { isAbsolute as isAbsolute6, join as join34, relative as relative5, resolve as resolve10 } from "path";
63934
64056
 
63935
64057
  // src/cli/install-codex/codex-cleanup-config.ts
63936
- import { lstat as lstat5, mkdir as mkdir7, readFile as readFile10, writeFile as writeFile8 } from "fs/promises";
64058
+ import { lstat as lstat5, mkdir as mkdir7, readFile as readFile11, writeFile as writeFile8 } from "fs/promises";
63937
64059
  import { dirname as dirname15 } from "path";
63938
64060
  var MANAGED_MARKETPLACES = ["sisyphuslabs", "lazycodex", "code-yeongyu-codex-plugins"];
63939
64061
  var MANAGED_CODEX_AGENT_NAMES2 = [
@@ -63959,7 +64081,7 @@ function cleanupCodexLightConfigText(config) {
63959
64081
  async function cleanupCodexConfig(configPath, now) {
63960
64082
  if (!await configExists(configPath))
63961
64083
  return { changed: false };
63962
- const original = await readFile10(configPath, "utf8");
64084
+ const original = await readFile11(configPath, "utf8");
63963
64085
  const next = cleanupCodexLightConfigText(original);
63964
64086
  if (next === original)
63965
64087
  return { changed: false };
@@ -64091,8 +64213,8 @@ function nodeErrorCode2(error) {
64091
64213
  var INSTALLED_AGENTS_MANIFEST = ".installed-agents.json";
64092
64214
  async function cleanupCodexLight(input = {}) {
64093
64215
  const env = input.env ?? process.env;
64094
- const codexHome = resolve10(input.codexHome ?? env.CODEX_HOME ?? join33(homedir7(), ".codex"));
64095
- const configPath = join33(codexHome, "config.toml");
64216
+ const codexHome = resolve10(input.codexHome ?? env.CODEX_HOME ?? join34(homedir7(), ".codex"));
64217
+ const configPath = join34(codexHome, "config.toml");
64096
64218
  const agentPaths = await collectInstalledAgentPaths(codexHome);
64097
64219
  const configCleanup = await cleanupCodexConfig(configPath, input.now);
64098
64220
  const agentCleanup = await removeManifestListedAgentLinks(codexHome, agentPaths);
@@ -64123,20 +64245,20 @@ async function cleanupCodexLight(input = {}) {
64123
64245
  }
64124
64246
  function managedGlobalStatePaths(codexHome) {
64125
64247
  return [
64126
- join33(codexHome, "plugins", "cache", "sisyphuslabs"),
64127
- join33(codexHome, ".tmp", "marketplaces", "sisyphuslabs")
64248
+ join34(codexHome, "plugins", "cache", "sisyphuslabs"),
64249
+ join34(codexHome, ".tmp", "marketplaces", "sisyphuslabs")
64128
64250
  ];
64129
64251
  }
64130
64252
  async function collectInstalledAgentPaths(codexHome) {
64131
64253
  const manifestPaths = [
64132
- join33(codexHome, ".tmp", "marketplaces", "sisyphuslabs", "plugins", "omo", INSTALLED_AGENTS_MANIFEST)
64254
+ join34(codexHome, ".tmp", "marketplaces", "sisyphuslabs", "plugins", "omo", INSTALLED_AGENTS_MANIFEST)
64133
64255
  ];
64134
- const versionRoot = join33(codexHome, "plugins", "cache", "sisyphuslabs", "omo");
64256
+ const versionRoot = join34(codexHome, "plugins", "cache", "sisyphuslabs", "omo");
64135
64257
  if (await exists6(versionRoot)) {
64136
64258
  const entries = await readdir4(versionRoot, { withFileTypes: true });
64137
64259
  for (const entry of entries) {
64138
64260
  if (entry.isDirectory())
64139
- manifestPaths.push(join33(versionRoot, entry.name, INSTALLED_AGENTS_MANIFEST));
64261
+ manifestPaths.push(join34(versionRoot, entry.name, INSTALLED_AGENTS_MANIFEST));
64140
64262
  }
64141
64263
  }
64142
64264
  const paths = new Set;
@@ -64150,13 +64272,13 @@ async function collectInstalledAgentPaths(codexHome) {
64150
64272
  async function readInstalledAgentManifest(manifestPath) {
64151
64273
  if (!await exists6(manifestPath))
64152
64274
  return [];
64153
- const parsed = JSON.parse(await readFile11(manifestPath, "utf8"));
64154
- if (!isRecord14(parsed) || !Array.isArray(parsed.agents))
64275
+ const parsed = JSON.parse(await readFile12(manifestPath, "utf8"));
64276
+ if (!isRecord15(parsed) || !Array.isArray(parsed.agents))
64155
64277
  return [];
64156
64278
  return parsed.agents.filter((path7) => typeof path7 === "string");
64157
64279
  }
64158
64280
  async function removeManifestListedAgentLinks(codexHome, paths) {
64159
- const agentsDir = join33(codexHome, "agents");
64281
+ const agentsDir = join34(codexHome, "agents");
64160
64282
  const removed = [];
64161
64283
  const skipped = [];
64162
64284
  for (const path7 of paths) {
@@ -64210,7 +64332,7 @@ function nodeErrorCode3(error) {
64210
64332
  return null;
64211
64333
  return typeof error.code === "string" ? error.code : null;
64212
64334
  }
64213
- function isRecord14(value) {
64335
+ function isRecord15(value) {
64214
64336
  return typeof value === "object" && value !== null && !Array.isArray(value);
64215
64337
  }
64216
64338
  // src/cli/star-request.ts
@@ -64346,7 +64468,9 @@ async function runCliInstaller(args, version2) {
64346
64468
  printBox(`${import_picocolors3.default.bold("Pro Tip:")} Include ${import_picocolors3.default.cyan("ultrawork")} (or ${import_picocolors3.default.cyan("ulw")}) in your prompt.
64347
64469
  ` + `All features work like magic-parallel agents, background tasks,
64348
64470
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
64349
- await maybePromptForGitHubStars(config.platform);
64471
+ if (args.tui) {
64472
+ await maybePromptForGitHubStars(config.platform);
64473
+ }
64350
64474
  console.log(import_picocolors3.default.dim("oMoMoMoMo... Enjoy!"));
64351
64475
  console.log();
64352
64476
  if (hasOpenCode && (config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
@@ -65856,14 +65980,7 @@ async function resolveCodexAutonomous(hasCodex, override) {
65856
65980
  return false;
65857
65981
  if (override !== undefined)
65858
65982
  return override;
65859
- return selectOrCancel({
65860
- message: "Configure Codex for autonomous full-permissions mode?",
65861
- options: [
65862
- { value: true, label: "Yes", hint: "Recommended: approval never, danger-full-access, network enabled" },
65863
- { value: false, label: "No", hint: "Leave existing Codex permissions unchanged" }
65864
- ],
65865
- initialValue: true
65866
- });
65983
+ return true;
65867
65984
  }
65868
65985
 
65869
65986
  // src/cli/tui-installer.ts
@@ -83662,7 +83779,7 @@ var import_picocolors9 = __toESM(require_picocolors(), 1);
83662
83779
 
83663
83780
  // src/cli/run/opencode-binary-resolver.ts
83664
83781
  init_spawn_with_windows_hide();
83665
- import { delimiter as delimiter2, dirname as dirname17, join as join35 } from "path";
83782
+ import { delimiter as delimiter2, dirname as dirname17, join as join36 } from "path";
83666
83783
  var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
83667
83784
  var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
83668
83785
  function getCommandCandidates(platform) {
@@ -83685,7 +83802,7 @@ function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = proc
83685
83802
  }
83686
83803
  for (const entry of (pathEnv ?? "").split(delimiter2).filter(Boolean)) {
83687
83804
  for (const command of commandCandidates) {
83688
- addCandidate(join35(entry, command));
83805
+ addCandidate(join36(entry, command));
83689
83806
  }
83690
83807
  }
83691
83808
  return candidates;
@@ -83763,6 +83880,7 @@ function isPortRangeExhausted(error51) {
83763
83880
  async function startServer(options, deps) {
83764
83881
  const { signal, port } = options;
83765
83882
  const { client: client3, server: server2 } = await deps.withWorkingOpencodePath(() => deps.createOpencode({ signal, port, hostname: "127.0.0.1" }));
83883
+ deps.injectServerAuthIntoClient(client3);
83766
83884
  console.log(import_picocolors9.default.dim("Server listening at"), import_picocolors9.default.cyan(server2.url));
83767
83885
  return { client: client3, cleanup: () => server2.close() };
83768
83886
  }
@@ -84016,11 +84134,10 @@ var normalizeAgentName = (agent) => {
84016
84134
  return;
84017
84135
  const configKey = getAgentConfigKey(trimmed);
84018
84136
  const displayName = getAgentDisplayName(configKey);
84019
- const runtimeName = getAgentDisplayName(configKey);
84020
84137
  const isKnownAgent = displayName !== configKey;
84021
84138
  return {
84022
84139
  configKey,
84023
- resolvedName: isKnownAgent ? runtimeName : trimmed
84140
+ resolvedName: isKnownAgent ? configKey : trimmed
84024
84141
  };
84025
84142
  };
84026
84143
  var isAgentDisabled = (agentConfigKey, config2) => {
@@ -84044,19 +84161,18 @@ var resolveRunAgent = (options, pluginConfig, env = process.env) => {
84044
84161
  const configAgent = normalizeAgentName(pluginConfig.default_run_agent);
84045
84162
  const resolved = cliAgent ?? envAgent ?? configAgent ?? {
84046
84163
  configKey: DEFAULT_AGENT,
84047
- resolvedName: getAgentDisplayName(DEFAULT_AGENT)
84164
+ resolvedName: DEFAULT_AGENT
84048
84165
  };
84049
84166
  if (isAgentDisabled(resolved.configKey, pluginConfig)) {
84050
84167
  const fallback = pickFallbackAgent(pluginConfig);
84051
84168
  const fallbackDisplayName = getAgentDisplayName(fallback);
84052
- const fallbackRuntimeName = getAgentDisplayName(fallback);
84053
84169
  const fallbackDisabled = isAgentDisabled(fallback, pluginConfig);
84054
84170
  if (fallbackDisabled) {
84055
84171
  console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled and no enabled core agent was found. Proceeding with "${fallbackDisplayName}".`));
84056
- return fallbackRuntimeName;
84172
+ return fallback;
84057
84173
  }
84058
84174
  console.log(import_picocolors11.default.yellow(`Requested agent "${resolved.resolvedName}" is disabled. Falling back to "${fallbackDisplayName}".`));
84059
- return fallbackRuntimeName;
84175
+ return fallback;
84060
84176
  }
84061
84177
  return resolved.resolvedName;
84062
84178
  };
@@ -84151,9 +84267,9 @@ function readCurrentTopLevelTask(planPath) {
84151
84267
  }
84152
84268
  // packages/boulder-state/src/storage/path.ts
84153
84269
  import { existsSync as existsSync29 } from "fs";
84154
- import { isAbsolute as isAbsolute7, join as join36, relative as relative6, resolve as resolve11 } from "path";
84270
+ import { isAbsolute as isAbsolute7, join as join37, relative as relative6, resolve as resolve11 } from "path";
84155
84271
  function getBoulderFilePath(directory) {
84156
- return join36(directory, BOULDER_DIR, BOULDER_FILE);
84272
+ return join37(directory, BOULDER_DIR, BOULDER_FILE);
84157
84273
  }
84158
84274
  function resolveTrackedPath(baseDirectory, trackedPath) {
84159
84275
  return isAbsolute7(trackedPath) ? resolve11(trackedPath) : resolve11(baseDirectory, trackedPath);
@@ -84390,9 +84506,9 @@ function getSessionAgent(sessionID) {
84390
84506
  var CONTINUATION_MARKER_DIR = ".omo/run-continuation";
84391
84507
  // src/features/run-continuation-state/storage.ts
84392
84508
  import { existsSync as existsSync32, mkdirSync as mkdirSync9, readFileSync as readFileSync18, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
84393
- import { join as join37 } from "path";
84509
+ import { join as join38 } from "path";
84394
84510
  function getMarkerPath(directory, sessionID) {
84395
- return join37(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
84511
+ return join38(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
84396
84512
  }
84397
84513
  function readContinuationMarker(directory, sessionID) {
84398
84514
  const markerPath = getMarkerPath(directory, sessionID);
@@ -84462,7 +84578,7 @@ async function isSessionInBoulderLineage(input) {
84462
84578
  init_shared();
84463
84579
  init_compaction_marker();
84464
84580
  import { readFileSync as readFileSync19, readdirSync as readdirSync5 } from "fs";
84465
- import { join as join38 } from "path";
84581
+ import { join as join39 } from "path";
84466
84582
  var defaultSessionLastAgentDeps = {
84467
84583
  getMessageDir,
84468
84584
  isSqliteBackend,
@@ -84516,7 +84632,7 @@ async function getLastAgentFromSession(sessionID, client3, deps = {}) {
84516
84632
  try {
84517
84633
  const messages = readdirSync5(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
84518
84634
  try {
84519
- const content = readFileSync19(join38(messageDir, fileName), "utf-8");
84635
+ const content = readFileSync19(join39(messageDir, fileName), "utf-8");
84520
84636
  const parsed = JSON.parse(content);
84521
84637
  return {
84522
84638
  fileName,
@@ -84553,7 +84669,7 @@ init_agent_display_names();
84553
84669
  // src/hooks/ralph-loop/storage.ts
84554
84670
  init_frontmatter2();
84555
84671
  import { existsSync as existsSync33, readFileSync as readFileSync20, writeFileSync as writeFileSync7, unlinkSync as unlinkSync5, mkdirSync as mkdirSync10 } from "fs";
84556
- import { dirname as dirname18, join as join39 } from "path";
84672
+ import { dirname as dirname18, join as join40 } from "path";
84557
84673
 
84558
84674
  // src/hooks/ralph-loop/constants.ts
84559
84675
  var DEFAULT_STATE_FILE = ".omo/ralph-loop.local.md";
@@ -84562,7 +84678,7 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
84562
84678
 
84563
84679
  // src/hooks/ralph-loop/storage.ts
84564
84680
  function getStateFilePath(directory, customPath) {
84565
- return customPath ? join39(directory, customPath) : join39(directory, DEFAULT_STATE_FILE);
84681
+ return customPath ? join40(directory, customPath) : join40(directory, DEFAULT_STATE_FILE);
84566
84682
  }
84567
84683
  function readState(directory, customPath) {
84568
84684
  const filePath = getStateFilePath(directory, customPath);
@@ -85136,10 +85252,10 @@ init_logger();
85136
85252
  init_plugin_identity();
85137
85253
  init_write_file_atomically();
85138
85254
  import { existsSync as existsSync34, mkdirSync as mkdirSync11, readFileSync as readFileSync21 } from "fs";
85139
- import { join as join40 } from "path";
85255
+ import { join as join41 } from "path";
85140
85256
  var POSTHOG_ACTIVITY_STATE_FILE2 = "posthog-activity.json";
85141
85257
  function getPostHogActivityStateFilePath2() {
85142
- return join40(getDataDir(), CACHE_DIR_NAME, POSTHOG_ACTIVITY_STATE_FILE2);
85258
+ return join41(getDataDir(), CACHE_DIR_NAME, POSTHOG_ACTIVITY_STATE_FILE2);
85143
85259
  }
85144
85260
  function getUtcDayString2(date5) {
85145
85261
  return date5.toISOString().slice(0, 10);
@@ -85170,7 +85286,7 @@ function readPostHogActivityState2() {
85170
85286
  function writePostHogActivityState2(nextState) {
85171
85287
  const stateFilePath = getPostHogActivityStateFilePath2();
85172
85288
  try {
85173
- mkdirSync11(join40(getDataDir(), CACHE_DIR_NAME), { recursive: true });
85289
+ mkdirSync11(join41(getDataDir(), CACHE_DIR_NAME), { recursive: true });
85174
85290
  writeFileAtomically(stateFilePath, `${JSON.stringify(nextState, null, 2)}
85175
85291
  `);
85176
85292
  } catch (error51) {
@@ -85218,8 +85334,11 @@ var NO_OP_POSTHOG2 = {
85218
85334
  function isFalsy(value) {
85219
85335
  return value === "0" || value === "false" || value === "no";
85220
85336
  }
85337
+ function isTruthy(value) {
85338
+ return value === "1" || value === "true" || value === "yes";
85339
+ }
85221
85340
  function shouldDisablePostHog2() {
85222
- if (process.env.OMO_DISABLE_POSTHOG === "true" || process.env.OMO_DISABLE_POSTHOG === "1") {
85341
+ if (isTruthy(process.env.OMO_DISABLE_POSTHOG?.trim().toLowerCase())) {
85223
85342
  return true;
85224
85343
  }
85225
85344
  return isFalsy(process.env.OMO_SEND_ANONYMOUS_TELEMETRY?.trim().toLowerCase());
@@ -85624,7 +85743,7 @@ import { existsSync as existsSync45, readFileSync as readFileSync31 } from "fs";
85624
85743
  init_extract_semver();
85625
85744
  import { existsSync as existsSync42, accessSync as accessSync4, constants as constants7 } from "fs";
85626
85745
  import { homedir as homedir11 } from "os";
85627
- import { join as join47 } from "path";
85746
+ import { join as join48 } from "path";
85628
85747
 
85629
85748
  // src/cli/doctor/spawn-with-timeout.ts
85630
85749
  init_spawn_with_windows_hide();
@@ -85672,17 +85791,17 @@ function getDesktopAppPaths(platform) {
85672
85791
  case "darwin":
85673
85792
  return [
85674
85793
  "/Applications/OpenCode.app/Contents/MacOS/OpenCode",
85675
- join47(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
85794
+ join48(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
85676
85795
  ];
85677
85796
  case "win32": {
85678
85797
  const programFiles = process.env.ProgramFiles;
85679
85798
  const localAppData = process.env.LOCALAPPDATA;
85680
85799
  const paths = [];
85681
85800
  if (programFiles) {
85682
- paths.push(join47(programFiles, "OpenCode", "OpenCode.exe"));
85801
+ paths.push(join48(programFiles, "OpenCode", "OpenCode.exe"));
85683
85802
  }
85684
85803
  if (localAppData) {
85685
- paths.push(join47(localAppData, "OpenCode", "OpenCode.exe"));
85804
+ paths.push(join48(localAppData, "OpenCode", "OpenCode.exe"));
85686
85805
  }
85687
85806
  return paths;
85688
85807
  }
@@ -85690,8 +85809,8 @@ function getDesktopAppPaths(platform) {
85690
85809
  return [
85691
85810
  "/usr/bin/opencode",
85692
85811
  "/usr/lib/opencode/opencode",
85693
- join47(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
85694
- join47(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
85812
+ join48(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
85813
+ join48(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
85695
85814
  ];
85696
85815
  default:
85697
85816
  return [];
@@ -85723,7 +85842,7 @@ async function findOpenCodeBinary(platform = process.platform, checkExists = exi
85723
85842
  const candidates = getCommandCandidates2(platform);
85724
85843
  for (const entry of pathEnv.split(delimiter3).filter(Boolean)) {
85725
85844
  for (const command of candidates) {
85726
- const fullPath = join47(entry, command);
85845
+ const fullPath = join48(entry, command);
85727
85846
  if (checkExists(fullPath) && isExecutable2(fullPath)) {
85728
85847
  return { binary: command, path: fullPath };
85729
85848
  }
@@ -85858,21 +85977,21 @@ init_auto_update_checker();
85858
85977
  import { existsSync as existsSync44, readFileSync as readFileSync30 } from "fs";
85859
85978
  import { createRequire } from "module";
85860
85979
  import { homedir as homedir12 } from "os";
85861
- import { join as join48 } from "path";
85980
+ import { join as join49 } from "path";
85862
85981
  init_shared();
85863
85982
  function getPlatformDefaultCacheDir(platform = process.platform) {
85864
85983
  if (platform === "darwin")
85865
- return join48(homedir12(), "Library", "Caches");
85984
+ return join49(homedir12(), "Library", "Caches");
85866
85985
  if (platform === "win32")
85867
- return process.env.LOCALAPPDATA ?? join48(homedir12(), "AppData", "Local");
85868
- return join48(homedir12(), ".cache");
85986
+ return process.env.LOCALAPPDATA ?? join49(homedir12(), "AppData", "Local");
85987
+ return join49(homedir12(), ".cache");
85869
85988
  }
85870
85989
  function resolveOpenCodeCacheDir() {
85871
85990
  const xdgCacheHome = process.env.XDG_CACHE_HOME;
85872
85991
  if (xdgCacheHome)
85873
- return join48(xdgCacheHome, "opencode");
85992
+ return join49(xdgCacheHome, "opencode");
85874
85993
  const fromShared = getOpenCodeCacheDir();
85875
- const platformDefault = join48(getPlatformDefaultCacheDir(), "opencode");
85994
+ const platformDefault = join49(getPlatformDefaultCacheDir(), "opencode");
85876
85995
  if (existsSync44(fromShared) || !existsSync44(platformDefault))
85877
85996
  return fromShared;
85878
85997
  return platformDefault;
@@ -85901,7 +86020,7 @@ function normalizeVersion(value) {
85901
86020
  function createPackageCandidates(rootDir) {
85902
86021
  return ACCEPTED_PACKAGE_NAMES.map((packageName) => ({
85903
86022
  packageName,
85904
- installedPackagePath: join48(rootDir, "node_modules", packageName, "package.json")
86023
+ installedPackagePath: join49(rootDir, "node_modules", packageName, "package.json")
85905
86024
  }));
85906
86025
  }
85907
86026
  function selectInstalledPackage(candidate) {
@@ -85935,12 +86054,12 @@ function getLoadedPluginVersion() {
85935
86054
  const candidates = [
85936
86055
  {
85937
86056
  cacheDir: configDir,
85938
- cachePackagePath: join48(configDir, "package.json"),
86057
+ cachePackagePath: join49(configDir, "package.json"),
85939
86058
  packageCandidates: createPackageCandidates(configDir)
85940
86059
  },
85941
86060
  {
85942
86061
  cacheDir,
85943
- cachePackagePath: join48(cacheDir, "package.json"),
86062
+ cachePackagePath: join49(cacheDir, "package.json"),
85944
86063
  packageCandidates: createPackageCandidates(cacheDir)
85945
86064
  }
85946
86065
  ];
@@ -86113,7 +86232,7 @@ async function checkSystem(deps = defaultDeps5) {
86113
86232
 
86114
86233
  // src/cli/doctor/checks/config.ts
86115
86234
  import { readFileSync as readFileSync34 } from "fs";
86116
- import { join as join52 } from "path";
86235
+ import { join as join53 } from "path";
86117
86236
  init_shared();
86118
86237
  init_plugin_identity();
86119
86238
 
@@ -86121,18 +86240,18 @@ init_plugin_identity();
86121
86240
  init_shared();
86122
86241
  import { existsSync as existsSync46, readFileSync as readFileSync32 } from "fs";
86123
86242
  import { homedir as homedir13 } from "os";
86124
- import { join as join49 } from "path";
86243
+ import { join as join50 } from "path";
86125
86244
  function getUserConfigDir2() {
86126
86245
  const xdgConfig = process.env.XDG_CONFIG_HOME;
86127
86246
  if (xdgConfig)
86128
- return join49(xdgConfig, "opencode");
86129
- return join49(homedir13(), ".config", "opencode");
86247
+ return join50(xdgConfig, "opencode");
86248
+ return join50(homedir13(), ".config", "opencode");
86130
86249
  }
86131
86250
  function loadCustomProviderNames() {
86132
86251
  const configDir = getUserConfigDir2();
86133
86252
  const candidatePaths = [
86134
- join49(configDir, "opencode.json"),
86135
- join49(configDir, "opencode.jsonc")
86253
+ join50(configDir, "opencode.json"),
86254
+ join50(configDir, "opencode.jsonc")
86136
86255
  ];
86137
86256
  for (const configPath of candidatePaths) {
86138
86257
  if (!existsSync46(configPath))
@@ -86148,7 +86267,7 @@ function loadCustomProviderNames() {
86148
86267
  return [];
86149
86268
  }
86150
86269
  function loadAvailableModelsFromCache() {
86151
- const cacheFile = join49(getOpenCodeCacheDir(), "models.json");
86270
+ const cacheFile = join50(getOpenCodeCacheDir(), "models.json");
86152
86271
  const customProviders = loadCustomProviderNames();
86153
86272
  if (!existsSync46(cacheFile)) {
86154
86273
  if (customProviders.length > 0) {
@@ -86182,8 +86301,8 @@ init_model_capabilities2();
86182
86301
  init_shared();
86183
86302
  init_plugin_identity();
86184
86303
  import { readFileSync as readFileSync33 } from "fs";
86185
- import { join as join50 } from "path";
86186
- var PROJECT_CONFIG_DIR = join50(process.cwd(), ".opencode");
86304
+ import { join as join51 } from "path";
86305
+ var PROJECT_CONFIG_DIR = join51(process.cwd(), ".opencode");
86187
86306
  function loadOmoConfig() {
86188
86307
  const projectDetected = detectPluginConfigFile(PROJECT_CONFIG_DIR, {
86189
86308
  basenames: [CONFIG_BASENAME],
@@ -86215,7 +86334,7 @@ function loadOmoConfig() {
86215
86334
 
86216
86335
  // src/cli/doctor/checks/model-resolution-details.ts
86217
86336
  init_shared();
86218
- import { join as join51 } from "path";
86337
+ import { join as join52 } from "path";
86219
86338
 
86220
86339
  // src/cli/doctor/checks/model-resolution-variant.ts
86221
86340
  function formatModelWithVariant(model, variant) {
@@ -86257,7 +86376,7 @@ function formatCapabilityResolutionLabel(mode) {
86257
86376
  }
86258
86377
  function buildModelResolutionDetails(options) {
86259
86378
  const details = [];
86260
- const cacheFile = join51(getOpenCodeCacheDir(), "models.json");
86379
+ const cacheFile = join52(getOpenCodeCacheDir(), "models.json");
86261
86380
  details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
86262
86381
  details.push("");
86263
86382
  if (options.available.cacheExists) {
@@ -86412,7 +86531,7 @@ async function checkModels() {
86412
86531
  }
86413
86532
 
86414
86533
  // src/cli/doctor/checks/config.ts
86415
- var PROJECT_CONFIG_DIR2 = join52(process.cwd(), ".opencode");
86534
+ var PROJECT_CONFIG_DIR2 = join53(process.cwd(), ".opencode");
86416
86535
  function findConfigPath() {
86417
86536
  const projectConfig = detectPluginConfigFile(PROJECT_CONFIG_DIR2, {
86418
86537
  basenames: [CONFIG_BASENAME],
@@ -86540,25 +86659,25 @@ async function checkConfig() {
86540
86659
  // src/cli/doctor/checks/dependencies.ts
86541
86660
  import { existsSync as existsSync47 } from "fs";
86542
86661
  import { createRequire as createRequire2 } from "module";
86543
- import { dirname as dirname22, join as join54 } from "path";
86662
+ import { dirname as dirname22, join as join55 } from "path";
86544
86663
 
86545
86664
  // src/hooks/comment-checker/downloader.ts
86546
- import { join as join53 } from "path";
86665
+ import { join as join54 } from "path";
86547
86666
  import { homedir as homedir14, tmpdir as tmpdir3 } from "os";
86548
86667
  init_binary_downloader();
86549
86668
  init_logger();
86550
86669
  init_plugin_identity();
86551
86670
  var DEBUG = process.env.COMMENT_CHECKER_DEBUG === "1";
86552
- var DEBUG_FILE = join53(tmpdir3(), "comment-checker-debug.log");
86671
+ var DEBUG_FILE = join54(tmpdir3(), "comment-checker-debug.log");
86553
86672
  function getCacheDir2() {
86554
86673
  if (process.platform === "win32") {
86555
86674
  const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
86556
- const base2 = localAppData || join53(homedir14(), "AppData", "Local");
86557
- return join53(base2, CACHE_DIR_NAME, "bin");
86675
+ const base2 = localAppData || join54(homedir14(), "AppData", "Local");
86676
+ return join54(base2, CACHE_DIR_NAME, "bin");
86558
86677
  }
86559
86678
  const xdgCache = process.env.XDG_CACHE_HOME;
86560
- const base = xdgCache || join53(homedir14(), ".cache");
86561
- return join53(base, CACHE_DIR_NAME, "bin");
86679
+ const base = xdgCache || join54(homedir14(), ".cache");
86680
+ return join54(base, CACHE_DIR_NAME, "bin");
86562
86681
  }
86563
86682
  function getBinaryName() {
86564
86683
  return process.platform === "win32" ? "comment-checker.exe" : "comment-checker";
@@ -86623,11 +86742,11 @@ async function checkAstGrepNapi() {
86623
86742
  };
86624
86743
  } catch {
86625
86744
  const { existsSync: existsSync48 } = await import("fs");
86626
- const { join: join55 } = await import("path");
86745
+ const { join: join56 } = await import("path");
86627
86746
  const { homedir: homedir15 } = await import("os");
86628
86747
  const pathsToCheck = [
86629
- join55(homedir15(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
86630
- join55(process.cwd(), "node_modules", "@ast-grep", "napi")
86748
+ join56(homedir15(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
86749
+ join56(process.cwd(), "node_modules", "@ast-grep", "napi")
86631
86750
  ];
86632
86751
  for (const napiPath of pathsToCheck) {
86633
86752
  if (existsSync48(napiPath)) {
@@ -86655,7 +86774,7 @@ function findCommentCheckerPackageBinary() {
86655
86774
  try {
86656
86775
  const require2 = createRequire2(import.meta.url);
86657
86776
  const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
86658
- const binaryPath = join54(dirname22(pkgPath), "bin", binaryName);
86777
+ const binaryPath = join55(dirname22(pkgPath), "bin", binaryName);
86659
86778
  if (existsSync47(binaryPath))
86660
86779
  return binaryPath;
86661
86780
  } catch {}
@@ -86789,7 +86908,7 @@ async function getGhCliInfo() {
86789
86908
 
86790
86909
  // src/cli/doctor/checks/tools-lsp.ts
86791
86910
  import { readFileSync as readFileSync35 } from "fs";
86792
- import { join as join55 } from "path";
86911
+ import { join as join56 } from "path";
86793
86912
 
86794
86913
  // src/mcp/lsp.ts
86795
86914
  import { existsSync as existsSync48 } from "fs";
@@ -86975,7 +87094,7 @@ function readOmoConfig(configDirectory) {
86975
87094
  }
86976
87095
  function isLspMcpDisabled(options) {
86977
87096
  const userConfigDirectory = options.configDirectory ?? getOpenCodeConfigDir({ binary: "opencode" });
86978
- const projectConfigDirectory = join55(options.cwd ?? process.cwd(), ".opencode");
87097
+ const projectConfigDirectory = join56(options.cwd ?? process.cwd(), ".opencode");
86979
87098
  const userConfig = readOmoConfig(userConfigDirectory);
86980
87099
  const projectConfig = readOmoConfig(projectConfigDirectory);
86981
87100
  const disabledMcps = new Set([
@@ -86996,13 +87115,13 @@ function getInstalledLspServers(options = {}) {
86996
87115
  init_shared();
86997
87116
  import { existsSync as existsSync49, readFileSync as readFileSync36 } from "fs";
86998
87117
  import { homedir as homedir15 } from "os";
86999
- import { join as join56 } from "path";
87118
+ import { join as join57 } from "path";
87000
87119
  var BUILTIN_MCP_SERVERS = ["websearch", "context7", "grep_app", "lsp", "ast_grep"];
87001
87120
  function getMcpConfigPaths() {
87002
87121
  return [
87003
- join56(homedir15(), ".claude", ".mcp.json"),
87004
- join56(process.cwd(), ".mcp.json"),
87005
- join56(process.cwd(), ".claude", ".mcp.json")
87122
+ join57(homedir15(), ".claude", ".mcp.json"),
87123
+ join57(process.cwd(), ".mcp.json"),
87124
+ join57(process.cwd(), ".claude", ".mcp.json")
87006
87125
  ];
87007
87126
  }
87008
87127
  function loadUserMcpConfig() {
@@ -87236,21 +87355,56 @@ async function pathExists(dir) {
87236
87355
  // src/cli/doctor/checks/tui-plugin-config.ts
87237
87356
  init_shared();
87238
87357
  import { existsSync as existsSync50, readFileSync as readFileSync38 } from "fs";
87239
- import { join as join57 } from "path";
87358
+ import { join as join58 } from "path";
87240
87359
  var TUI_SUBPATH = "tui";
87241
- function isOurFilePluginEntry(entry) {
87242
- if (!entry.startsWith("file:"))
87243
- return false;
87360
+ var TUI_EXPORT_SUBPATH = `./${TUI_SUBPATH}`;
87361
+ function fileEntryPackageJsonPath(entry) {
87244
87362
  let path16 = entry.slice("file:".length);
87245
87363
  if (path16.startsWith("//"))
87246
87364
  path16 = path16.slice(2);
87365
+ return join58(path16, "package.json");
87366
+ }
87367
+ function packageJsonExportsTui(pkgJsonPath) {
87368
+ if (!existsSync50(pkgJsonPath))
87369
+ return null;
87247
87370
  try {
87248
- const pkgJsonPath = join57(path16, "package.json");
87371
+ const parsed = JSON.parse(readFileSync38(pkgJsonPath, "utf-8"));
87372
+ if (parsed.exports === undefined)
87373
+ return null;
87374
+ if (typeof parsed.exports === "string")
87375
+ return false;
87376
+ if (parsed.exports == null || typeof parsed.exports !== "object" || Array.isArray(parsed.exports))
87377
+ return null;
87378
+ return Object.hasOwn(parsed.exports, TUI_EXPORT_SUBPATH);
87379
+ } catch (error51) {
87380
+ return null;
87381
+ }
87382
+ }
87383
+ function packageNameFromServerEntry(entry) {
87384
+ if (entry === PLUGIN_NAME || entry.startsWith(`${PLUGIN_NAME}@`))
87385
+ return PLUGIN_NAME;
87386
+ if (entry === LEGACY_PLUGIN_NAME || entry.startsWith(`${LEGACY_PLUGIN_NAME}@`))
87387
+ return LEGACY_PLUGIN_NAME;
87388
+ return null;
87389
+ }
87390
+ function packageExportsTuiForServerEntry(entry) {
87391
+ if (entry.startsWith("file:"))
87392
+ return packageJsonExportsTui(fileEntryPackageJsonPath(entry));
87393
+ const packageName = packageNameFromServerEntry(entry);
87394
+ if (packageName === null)
87395
+ return null;
87396
+ return packageJsonExportsTui(join58(getOpenCodeConfigDir({ binary: "opencode" }), "node_modules", packageName, "package.json"));
87397
+ }
87398
+ function isOurFilePluginEntry(entry) {
87399
+ if (!entry.startsWith("file:"))
87400
+ return false;
87401
+ try {
87402
+ const pkgJsonPath = fileEntryPackageJsonPath(entry);
87249
87403
  if (!existsSync50(pkgJsonPath))
87250
87404
  return false;
87251
87405
  const parsed = JSON.parse(readFileSync38(pkgJsonPath, "utf-8"));
87252
87406
  return typeof parsed.name === "string" && ACCEPTED_PACKAGE_NAMES.includes(parsed.name);
87253
- } catch {
87407
+ } catch (error51) {
87254
87408
  return false;
87255
87409
  }
87256
87410
  }
@@ -87264,41 +87418,56 @@ function isServerPluginEntry(entry) {
87264
87418
  return false;
87265
87419
  }
87266
87420
  function isTuiPluginEntry(entry) {
87421
+ if (isNamedTuiPluginEntry(entry))
87422
+ return true;
87423
+ if (entry.startsWith("file:") && isOurFilePluginEntry(entry))
87424
+ return true;
87425
+ return false;
87426
+ }
87427
+ function isNamedTuiPluginEntry(entry) {
87267
87428
  const canonicalPrefix = `${PLUGIN_NAME}/${TUI_SUBPATH}`;
87268
87429
  const legacyPrefix = `${LEGACY_PLUGIN_NAME}/${TUI_SUBPATH}`;
87269
87430
  if (entry === canonicalPrefix || entry.startsWith(`${canonicalPrefix}@`))
87270
87431
  return true;
87271
87432
  if (entry === legacyPrefix || entry.startsWith(`${legacyPrefix}@`))
87272
87433
  return true;
87273
- if (entry.startsWith("file:") && isOurFilePluginEntry(entry))
87274
- return true;
87275
87434
  return false;
87276
87435
  }
87277
87436
  function detectServerPluginRegistration() {
87278
87437
  const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
87279
87438
  const configPath = existsSync50(paths.configJsonc) ? paths.configJsonc : existsSync50(paths.configJson) ? paths.configJson : null;
87280
87439
  if (!configPath) {
87281
- return { registered: false, configPath: null };
87440
+ return { registered: false, configPath: null, packageExportsTui: null };
87282
87441
  }
87283
87442
  try {
87284
87443
  const parsed = parseJsonc(readFileSync38(configPath, "utf-8"));
87285
87444
  const plugins = parsed.plugin ?? [];
87286
- return { registered: plugins.some(isServerPluginEntry), configPath };
87287
- } catch {
87288
- return { registered: false, configPath };
87445
+ const serverEntry = plugins.find(isServerPluginEntry);
87446
+ return {
87447
+ registered: serverEntry !== undefined,
87448
+ configPath,
87449
+ packageExportsTui: serverEntry === undefined ? null : packageExportsTuiForServerEntry(serverEntry)
87450
+ };
87451
+ } catch (error51) {
87452
+ return { registered: false, configPath, packageExportsTui: null };
87289
87453
  }
87290
87454
  }
87291
87455
  function detectTuiPluginRegistration() {
87292
- const tuiJsonPath = join57(getOpenCodeConfigDir({ binary: "opencode" }), "tui.json");
87456
+ const tuiJsonPath = join58(getOpenCodeConfigDir({ binary: "opencode" }), "tui.json");
87293
87457
  if (!existsSync50(tuiJsonPath)) {
87294
- return { registered: false, configPath: tuiJsonPath, exists: false };
87458
+ return { registered: false, configPath: tuiJsonPath, exists: false, hasNamedTuiEntry: false };
87295
87459
  }
87296
87460
  try {
87297
87461
  const parsed = parseJsonc(readFileSync38(tuiJsonPath, "utf-8"));
87298
87462
  const plugins = parsed.plugin ?? [];
87299
- return { registered: plugins.some(isTuiPluginEntry), configPath: tuiJsonPath, exists: true };
87300
- } catch {
87301
- return { registered: false, configPath: tuiJsonPath, exists: true };
87463
+ return {
87464
+ registered: plugins.some(isTuiPluginEntry),
87465
+ configPath: tuiJsonPath,
87466
+ exists: true,
87467
+ hasNamedTuiEntry: plugins.some(isNamedTuiPluginEntry)
87468
+ };
87469
+ } catch (error51) {
87470
+ return { registered: false, configPath: tuiJsonPath, exists: true, hasNamedTuiEntry: false };
87302
87471
  }
87303
87472
  }
87304
87473
  async function checkTuiPluginConfig() {
@@ -87320,7 +87489,32 @@ async function checkTuiPluginConfig() {
87320
87489
  issues
87321
87490
  };
87322
87491
  }
87492
+ if (server2.registered && server2.packageExportsTui === false && tui.hasNamedTuiEntry) {
87493
+ issues.push({
87494
+ title: "TUI plugin entry in tui.json is unresolvable",
87495
+ description: `The installed ${PLUGIN_NAME} package registered in opencode.json does not export ` + `"${TUI_EXPORT_SUBPATH}", but tui.json contains "${PLUGIN_NAME}/${TUI_SUBPATH}". ` + "OpenCode TUI may try to resolve that package subpath as a GitHub repository and fail.",
87496
+ fix: `Remove "${PLUGIN_NAME}/${TUI_SUBPATH}" or "${LEGACY_PLUGIN_NAME}/${TUI_SUBPATH}" from the "plugin" array in ${tui.configPath}.`,
87497
+ affects: ["TUI startup", "plugin loading"],
87498
+ severity: "warning"
87499
+ });
87500
+ return {
87501
+ name,
87502
+ status: "warn",
87503
+ message: "TUI plugin entry in tui.json is unresolvable",
87504
+ details: details.length > 0 ? details : undefined,
87505
+ issues
87506
+ };
87507
+ }
87323
87508
  if (server2.registered && !tui.registered) {
87509
+ if (server2.packageExportsTui === false) {
87510
+ return {
87511
+ name,
87512
+ status: "pass",
87513
+ message: "Server plugin registered; TUI subpath not shipped by this package version",
87514
+ details: details.length > 0 ? details : undefined,
87515
+ issues
87516
+ };
87517
+ }
87324
87518
  issues.push({
87325
87519
  title: "TUI plugin entry missing from tui.json",
87326
87520
  description: "The server plugin is registered in opencode.json, but the TUI plugin entry " + `("${PLUGIN_NAME}/${TUI_SUBPATH}") is missing from tui.json. The Roles \xB7 ` + "Models sidebar section and TUI-only commands will not appear.",
@@ -87748,10 +87942,10 @@ async function refreshModelCapabilities(options, deps = {}) {
87748
87942
  // src/features/mcp-oauth/storage.ts
87749
87943
  init_shared();
87750
87944
  import { chmodSync as chmodSync2, existsSync as existsSync51, mkdirSync as mkdirSync13, readFileSync as readFileSync39, renameSync as renameSync6, unlinkSync as unlinkSync8, writeFileSync as writeFileSync10 } from "fs";
87751
- import { dirname as dirname24, join as join58 } from "path";
87945
+ import { dirname as dirname24, join as join59 } from "path";
87752
87946
  var STORAGE_FILE_NAME = "mcp-oauth.json";
87753
87947
  function getMcpOauthStoragePath() {
87754
- return join58(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
87948
+ return join59(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
87755
87949
  }
87756
87950
  function normalizeHost2(serverHost) {
87757
87951
  let host = serverHost.trim();
@@ -88008,7 +88202,7 @@ async function getOrRegisterClient(options) {
88008
88202
  }
88009
88203
  }
88010
88204
  function parseRegistrationResponse(data) {
88011
- if (!isRecord16(data))
88205
+ if (!isRecord17(data))
88012
88206
  return null;
88013
88207
  const clientId = data.client_id;
88014
88208
  if (typeof clientId !== "string" || clientId.length === 0)
@@ -88019,7 +88213,7 @@ function parseRegistrationResponse(data) {
88019
88213
  }
88020
88214
  return { clientId };
88021
88215
  }
88022
- function isRecord16(value) {
88216
+ function isRecord17(value) {
88023
88217
  return typeof value === "object" && value !== null;
88024
88218
  }
88025
88219
 
@@ -88575,6 +88769,81 @@ async function boulder(options) {
88575
88769
  `);
88576
88770
  return 0;
88577
88771
  }
88772
+ // src/cli/codex-ulw-loop.ts
88773
+ import { spawn as spawn3 } from "child_process";
88774
+ import { existsSync as existsSync53, readdirSync as readdirSync7, realpathSync as realpathSync7 } from "fs";
88775
+ import { homedir as homedir17 } from "os";
88776
+ import { join as join60 } from "path";
88777
+ function resolveCodexUlwLoopCommand(input = {}) {
88778
+ const env = input.env ?? process.env;
88779
+ const homeDir = input.homeDir ?? homedir17();
88780
+ const localBin = resolveLocalOmoBin(env, homeDir, input.currentExecutablePaths ?? [process.argv[1]].filter((value) => typeof value === "string"));
88781
+ if (localBin !== null)
88782
+ return { executable: localBin, argsPrefix: ["ulw-loop"] };
88783
+ const componentCli = resolveNewestCachedUlwLoopCli(env.CODEX_HOME ?? join60(homeDir, ".codex"));
88784
+ if (componentCli !== null)
88785
+ return { executable: process.execPath, argsPrefix: [componentCli] };
88786
+ return null;
88787
+ }
88788
+ async function codexUlwLoop(args) {
88789
+ const command = resolveCodexUlwLoopCommand();
88790
+ if (command === null) {
88791
+ console.error("Codex ulw-loop is not installed. Run: npx lazycodex-ai@latest install --no-tui");
88792
+ return 1;
88793
+ }
88794
+ return new Promise((resolve13) => {
88795
+ const child = spawn3(command.executable, [...command.argsPrefix, ...args], { stdio: "inherit" });
88796
+ child.on("error", (error51) => {
88797
+ console.error(error51.message);
88798
+ resolve13(1);
88799
+ });
88800
+ child.on("close", (code) => resolve13(code ?? 1));
88801
+ });
88802
+ }
88803
+ function resolveLocalOmoBin(env, homeDir, currentExecutablePaths) {
88804
+ const candidates = [
88805
+ env.CODEX_LOCAL_BIN_DIR ? join60(env.CODEX_LOCAL_BIN_DIR, "omo") : undefined,
88806
+ join60(homeDir, ".local", "bin", "omo"),
88807
+ join60(homeDir, ".codex", "bin", "omo")
88808
+ ].filter((value) => typeof value === "string");
88809
+ return candidates.find((candidate) => existsSync53(candidate) && !isCurrentExecutable(candidate, currentExecutablePaths)) ?? null;
88810
+ }
88811
+ function isCurrentExecutable(candidate, currentExecutablePaths) {
88812
+ const candidateRealPath = realpathOrSelf(candidate);
88813
+ return currentExecutablePaths.some((currentPath) => realpathOrSelf(currentPath) === candidateRealPath);
88814
+ }
88815
+ function realpathOrSelf(path16) {
88816
+ try {
88817
+ return realpathSync7(path16);
88818
+ } catch {
88819
+ return path16;
88820
+ }
88821
+ }
88822
+ function resolveNewestCachedUlwLoopCli(codexHome) {
88823
+ const versionsRoot = join60(codexHome, "plugins", "cache", "sisyphuslabs", "omo");
88824
+ if (!existsSync53(versionsRoot))
88825
+ return null;
88826
+ const versions2 = readdirSync7(versionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareVersionNames).reverse();
88827
+ for (const version3 of versions2) {
88828
+ const candidate = join60(versionsRoot, version3, "components", "ulw-loop", "dist", "cli.js");
88829
+ if (existsSync53(candidate))
88830
+ return candidate;
88831
+ }
88832
+ return null;
88833
+ }
88834
+ function compareVersionNames(left, right) {
88835
+ const leftParts = left.split(".").map((part) => Number.parseInt(part, 10));
88836
+ const rightParts = right.split(".").map((part) => Number.parseInt(part, 10));
88837
+ const length = Math.max(leftParts.length, rightParts.length);
88838
+ for (let index = 0;index < length; index += 1) {
88839
+ const leftValue = Number.isFinite(leftParts[index] ?? Number.NaN) ? leftParts[index] ?? 0 : 0;
88840
+ const rightValue = Number.isFinite(rightParts[index] ?? Number.NaN) ? rightParts[index] ?? 0 : 0;
88841
+ if (leftValue !== rightValue)
88842
+ return leftValue - rightValue;
88843
+ }
88844
+ return left.localeCompare(right);
88845
+ }
88846
+
88578
88847
  // src/cli/cli-program.ts
88579
88848
  var VERSION2 = package_default.version;
88580
88849
  var program2 = new Command;
@@ -88719,6 +88988,10 @@ program2.command("boulder").description("Show boulder progress, elapsed time, an
88719
88988
  });
88720
88989
  process.exit(exitCode);
88721
88990
  });
88991
+ program2.command("ulw-loop [args...]").allowUnknownOption().passThroughOptions().description("Run the Codex LazyCodex ulw-loop CLI").action(async (args = []) => {
88992
+ const exitCode = await codexUlwLoop(args);
88993
+ process.exit(exitCode);
88994
+ });
88722
88995
  program2.addCommand(createMcpOAuthCommand());
88723
88996
  function runCli() {
88724
88997
  program2.parse();