oh-my-opencode 4.11.1 → 4.12.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 (149) hide show
  1. package/.agents/skills/codex-qa/scripts/lib/app-server-client.mjs +132 -82
  2. package/.agents/skills/codex-qa/scripts/lib/app-server-client.test.js +48 -0
  3. package/.agents/skills/opencode-qa/scripts/serve-wake-split-probe.sh +361 -84
  4. package/.agents/skills/work-with-pr/SKILL.md +19 -5
  5. package/.opencode/skills/work-with-pr/SKILL.md +19 -5
  6. package/dist/agents/types.d.ts +7 -6
  7. package/dist/cli/index.js +438 -306
  8. package/dist/cli-node/index.js +438 -306
  9. package/dist/features/background-agent/parent-wake-flush-runner.d.ts +1 -0
  10. package/dist/features/background-agent/parent-wake-history-state.d.ts +1 -0
  11. package/dist/features/background-agent/parent-wake-session-history.d.ts +1 -47
  12. package/dist/features/background-agent/parent-wake-session-message.d.ts +47 -0
  13. package/dist/index.js +245 -69
  14. package/dist/plugin/tool-execute-before.d.ts +2 -0
  15. package/dist/plugin-handlers/plugin-components-loader.d.ts +1 -0
  16. package/dist/skills/ulw-plan/SKILL.md +2 -1
  17. package/dist/skills/ulw-plan/references/full-workflow.md +1 -1
  18. package/dist/skills/ulw-plan/references/intent-clear.md +2 -2
  19. package/dist/tools/delegate-task/sync-session-poller.d.ts +1 -2
  20. package/dist/tools/delegate-task/sync-session-turns.d.ts +3 -0
  21. package/dist/tui.js +16 -7
  22. package/package.json +13 -13
  23. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +22 -2
  24. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +25 -9
  25. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  26. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  27. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +10 -3
  28. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +9 -2
  29. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  30. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +7 -2
  31. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +2 -1
  32. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +9 -9
  33. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +94 -0
  34. package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +33 -0
  35. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  36. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  37. package/packages/omo-codex/plugin/components/comment-checker/test/package-smoke.test.ts +2 -71
  38. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  39. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  40. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  41. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  42. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  43. package/packages/omo-codex/plugin/components/lsp/package.json +2 -2
  44. package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +26 -104
  45. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  46. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  47. package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +12 -92
  48. package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +157 -234
  49. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  50. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -2
  51. package/packages/omo-codex/plugin/components/start-work-continuation/src/boulder-reader.ts +227 -15
  52. package/packages/omo-codex/plugin/components/start-work-continuation/test/boulder-reader.test.ts +62 -2
  53. package/packages/omo-codex/plugin/components/start-work-continuation/test/cli.test.ts +34 -3
  54. package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +139 -0
  55. package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-guide.mjs +111 -0
  56. package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-state.mjs +250 -0
  57. package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team.mjs +220 -0
  58. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  59. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  60. package/packages/omo-codex/plugin/components/test-support/package-smoke-fixture.ts +158 -0
  61. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  62. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  63. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +2 -1
  64. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/agents/openai.yaml +1 -1
  65. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +1 -1
  66. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -2
  67. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +76 -49
  68. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
  69. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  70. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/agents/openai.yaml +1 -1
  71. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +1 -1
  72. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +17 -0
  73. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +17 -0
  74. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +17 -0
  75. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +17 -0
  76. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +17 -0
  77. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +17 -0
  78. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +17 -0
  79. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +17 -0
  80. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +17 -0
  81. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +17 -0
  82. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +16 -0
  83. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +16 -0
  84. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +16 -0
  85. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +16 -0
  86. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +16 -0
  87. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +17 -0
  88. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +16 -0
  89. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +16 -0
  90. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +16 -0
  91. package/packages/omo-codex/plugin/package-lock.json +12 -22
  92. package/packages/omo-codex/plugin/package.json +1 -1
  93. package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +14 -11
  94. package/packages/omo-codex/plugin/scripts/sync-hook-status-messages.mjs +15 -4
  95. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +37 -0
  96. package/packages/omo-codex/plugin/skills/ast-grep/agents/openai.yaml +2 -0
  97. package/packages/omo-codex/plugin/skills/comment-checker/agents/openai.yaml +2 -0
  98. package/packages/omo-codex/plugin/skills/debugging/agents/openai.yaml +2 -0
  99. package/packages/omo-codex/plugin/skills/frontend/agents/openai.yaml +2 -0
  100. package/packages/omo-codex/plugin/skills/git-master/agents/openai.yaml +1 -1
  101. package/packages/omo-codex/plugin/skills/init-deep/agents/openai.yaml +2 -0
  102. package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/agents/openai.yaml +1 -1
  103. package/packages/omo-codex/plugin/skills/lcx-doctor/agents/openai.yaml +1 -1
  104. package/packages/omo-codex/plugin/skills/lcx-report-bug/agents/openai.yaml +1 -1
  105. package/packages/omo-codex/plugin/skills/lsp/agents/openai.yaml +2 -0
  106. package/packages/omo-codex/plugin/skills/lsp-setup/agents/openai.yaml +2 -0
  107. package/packages/omo-codex/plugin/skills/programming/agents/openai.yaml +2 -0
  108. package/packages/omo-codex/plugin/skills/refactor/agents/openai.yaml +2 -0
  109. package/packages/omo-codex/plugin/skills/remove-ai-slops/agents/openai.yaml +2 -0
  110. package/packages/omo-codex/plugin/skills/review-work/agents/openai.yaml +2 -0
  111. package/packages/omo-codex/plugin/skills/rules/agents/openai.yaml +2 -0
  112. package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +2 -0
  113. package/packages/omo-codex/plugin/skills/teammode/SKILL.md +139 -0
  114. package/packages/omo-codex/plugin/skills/teammode/agents/openai.yaml +2 -0
  115. package/packages/omo-codex/plugin/skills/teammode/scripts/team-guide.mjs +111 -0
  116. package/packages/omo-codex/plugin/skills/teammode/scripts/team-state.mjs +250 -0
  117. package/packages/omo-codex/plugin/skills/teammode/scripts/team.mjs +220 -0
  118. package/packages/omo-codex/plugin/skills/ultraresearch/agents/openai.yaml +2 -0
  119. package/packages/omo-codex/plugin/skills/ulw-loop/agents/openai.yaml +1 -1
  120. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +2 -1
  121. package/packages/omo-codex/plugin/skills/ulw-plan/agents/openai.yaml +1 -1
  122. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +1 -1
  123. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -2
  124. package/packages/omo-codex/plugin/skills/visual-qa/agents/openai.yaml +2 -0
  125. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +34 -33
  126. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +5 -2
  127. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +13 -0
  128. package/packages/omo-codex/plugin/test/bootstrap-binlinks.test.mjs +1 -1
  129. package/packages/omo-codex/plugin/test/bootstrap-hooks.test.mjs +14 -6
  130. package/packages/omo-codex/plugin/test/bootstrap-ps-guard.test.mjs +7 -3
  131. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +3 -3
  132. package/packages/omo-codex/plugin/test/display-metadata.test.mjs +83 -0
  133. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +30 -19
  134. package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +3 -3
  135. package/packages/omo-codex/plugin/test/sync-hook-status-messages.test.mjs +6 -6
  136. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +2 -0
  137. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +9 -4
  138. package/packages/omo-codex/plugin/test/teammode-safety-fixture.mjs +88 -0
  139. package/packages/omo-codex/plugin/test/teammode-safety.test.mjs +240 -0
  140. package/packages/omo-codex/scripts/install-dist/install-local.mjs +385 -206
  141. package/packages/omo-codex/scripts/install-hook-targets.test.mjs +93 -0
  142. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +2 -2
  143. package/packages/omo-codex/scripts/install-local-bun-global-update.test.mjs +63 -0
  144. package/packages/omo-codex/scripts/install-local-entrypoint.test.mjs +109 -1
  145. package/packages/omo-codex/scripts/install-local.mjs +1 -0
  146. package/packages/shared-skills/skills/ulw-plan/SKILL.md +2 -1
  147. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +1 -1
  148. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -2
  149. package/packages/omo-codex/plugin/hooks/hooks.json +0 -214
@@ -96,20 +96,20 @@ var init_atomic_write = __esm(() => {
96
96
 
97
97
  // packages/telemetry-core/src/activity-state.ts
98
98
  import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync } from "node:fs";
99
- import { basename as basename5, join as join26 } from "node:path";
99
+ import { basename as basename5, join as join27 } from "node:path";
100
100
  function resolveTelemetryStateDir(product, options = {}) {
101
101
  const dataDir = resolveXdgDataDir(product.cacheDirName, {
102
102
  env: options.env,
103
103
  osProvider: options.osProvider
104
104
  });
105
- const xdgStateDir = options.env?.XDG_DATA_HOME === undefined ? undefined : join26(options.env.XDG_DATA_HOME, product.cacheDirName);
105
+ const xdgStateDir = options.env?.XDG_DATA_HOME === undefined ? undefined : join27(options.env.XDG_DATA_HOME, product.cacheDirName);
106
106
  if (dataDir === xdgStateDir || xdgStateDir === undefined && basename5(dataDir) === product.cacheDirName) {
107
107
  return dataDir;
108
108
  }
109
- return join26(dataDir, product.cacheDirName);
109
+ return join27(dataDir, product.cacheDirName);
110
110
  }
111
111
  function getTelemetryActivityStateFilePath(stateDir) {
112
- return join26(stateDir, POSTHOG_ACTIVITY_STATE_FILE);
112
+ return join27(stateDir, POSTHOG_ACTIVITY_STATE_FILE);
113
113
  }
114
114
  function getDailyActiveCaptureState(input) {
115
115
  const state = readPostHogActivityState(input.stateDir, input.diagnostics);
@@ -180,9 +180,9 @@ var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com", DEFAULT_POSTHOG_API_KEY =
180
180
 
181
181
  // packages/telemetry-core/src/diagnostics.ts
182
182
  import { appendFileSync, existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync2 } from "node:fs";
183
- import { join as join27 } from "node:path";
183
+ import { join as join28 } from "node:path";
184
184
  function getTelemetryDiagnosticsFilePath(diagnosticsDir) {
185
- return join27(diagnosticsDir, DIAGNOSTICS_FILE_NAME);
185
+ return join28(diagnosticsDir, DIAGNOSTICS_FILE_NAME);
186
186
  }
187
187
  function writeTelemetryDiagnostic(input, options) {
188
188
  const now = options.now ?? new Date;
@@ -348,7 +348,7 @@ function getTelemetryDistinctId(machineIdPrefix, osProvider = getDefaultTelemetr
348
348
  var init_machine_id = () => {};
349
349
 
350
350
  // node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
351
- import { dirname as dirname7, posix, sep as sep6 } from "node:path";
351
+ import { dirname as dirname7, posix, sep as sep7 } from "node:path";
352
352
  function createModulerModifier() {
353
353
  const getModuleFromFileName = createGetModuleFromFilename();
354
354
  return async (frames) => {
@@ -357,7 +357,7 @@ function createModulerModifier() {
357
357
  return frames;
358
358
  };
359
359
  }
360
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname7(process.argv[1]) : process.cwd(), isWindows = sep6 === "\\") {
360
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname7(process.argv[1]) : process.cwd(), isWindows = sep7 === "\\") {
361
361
  const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
362
362
  return (filename) => {
363
363
  if (!filename)
@@ -3378,9 +3378,9 @@ var init_context_lines_node = __esm(() => {
3378
3378
  });
3379
3379
 
3380
3380
  // node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/relative-path.node.mjs
3381
- import { isAbsolute as isAbsolute5, relative as relative4, sep as sep7 } from "node:path";
3381
+ import { isAbsolute as isAbsolute5, relative as relative4, sep as sep8 } from "node:path";
3382
3382
  function createRelativePathModifier(basePath = process.cwd()) {
3383
- const isWindows = sep7 === "\\";
3383
+ const isWindows = sep8 === "\\";
3384
3384
  const toUnix = (p) => isWindows ? p.replace(/\\/g, "/") : p;
3385
3385
  const normalizedBase = toUnix(basePath);
3386
3386
  return async (frames) => {
@@ -5907,7 +5907,7 @@ var package_default;
5907
5907
  var init_package = __esm(() => {
5908
5908
  package_default = {
5909
5909
  name: "@oh-my-opencode/omo-codex",
5910
- version: "4.11.1",
5910
+ version: "4.12.0",
5911
5911
  type: "module",
5912
5912
  private: true,
5913
5913
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -6127,7 +6127,7 @@ var init_telemetry = __esm(() => {
6127
6127
 
6128
6128
  // packages/omo-codex/src/install/install-local-cli.ts
6129
6129
  import { readFile as readFile19 } from "node:fs/promises";
6130
- import { dirname as dirname9, join as join32, resolve as resolve11 } from "node:path";
6130
+ import { dirname as dirname9, join as join33, resolve as resolve11 } from "node:path";
6131
6131
  import { fileURLToPath as fileURLToPath2 } from "node:url";
6132
6132
 
6133
6133
  // packages/utils/src/runtime/spawn.ts
@@ -6395,7 +6395,7 @@ var defaultRunCommand = async (command, args, options) => {
6395
6395
  };
6396
6396
 
6397
6397
  // packages/omo-codex/src/install/install-codex.ts
6398
- import { join as join28, resolve as resolve10 } from "node:path";
6398
+ import { join as join29, resolve as resolve10 } from "node:path";
6399
6399
  import { existsSync as existsSync6 } from "node:fs";
6400
6400
  import { homedir as homedir2 } from "node:os";
6401
6401
 
@@ -6759,8 +6759,8 @@ async function existingNonSymlink(path) {
6759
6759
  }
6760
6760
  }
6761
6761
  // packages/omo-codex/src/install/codex-cache-install.ts
6762
- import { cp as cp2, mkdir as mkdir3, readFile as readFile6, rename, rm as rm3 } from "node:fs/promises";
6763
- import { basename as basename2, dirname as dirname3, join as join8, sep as sep4 } from "node:path";
6762
+ import { cp as cp2, mkdir as mkdir3, readFile as readFile7, rename, rm as rm3 } from "node:fs/promises";
6763
+ import { basename as basename2, dirname as dirname3, join as join9, sep as sep5 } from "node:path";
6764
6764
 
6765
6765
  // packages/omo-codex/src/install/codex-cache-bundled-mcps.ts
6766
6766
  import { cp, mkdir as mkdir2, readFile as readFile3, stat as stat2 } from "node:fs/promises";
@@ -7055,13 +7055,83 @@ async function rewriteCachedManifestRoot(pluginRoot, fromRoot, toRoot) {
7055
7055
  `);
7056
7056
  }
7057
7057
 
7058
+ // packages/omo-codex/src/install/codex-hook-targets.ts
7059
+ import { readFile as readFile6 } from "node:fs/promises";
7060
+ import { join as join8, sep as sep4 } from "node:path";
7061
+ var PLUGIN_ROOT_TARGET_PATTERN = /\$\{PLUGIN_ROOT\}[\\/]+([^"']+)/g;
7062
+ async function findMissingHookCommandTargets(pluginRoot) {
7063
+ const commands = [];
7064
+ for (const manifestPath of await hookManifestPaths(pluginRoot)) {
7065
+ if (!await fileExistsStrict(manifestPath))
7066
+ continue;
7067
+ const parsed = JSON.parse(await readFile6(manifestPath, "utf8"));
7068
+ collectCommands(parsed, commands);
7069
+ }
7070
+ const missing = [];
7071
+ const seen = new Set;
7072
+ for (const command of commands) {
7073
+ for (const match of command.matchAll(PLUGIN_ROOT_TARGET_PATTERN)) {
7074
+ const targetSuffix = match[1];
7075
+ if (targetSuffix === undefined)
7076
+ continue;
7077
+ const target = join8(pluginRoot, ...targetSuffix.split(/[\\/]+/));
7078
+ if (seen.has(target))
7079
+ continue;
7080
+ seen.add(target);
7081
+ if (!await fileExistsStrict(target))
7082
+ missing.push(target);
7083
+ }
7084
+ }
7085
+ return missing;
7086
+ }
7087
+ async function hookManifestPaths(pluginRoot) {
7088
+ const pluginManifestPath = join8(pluginRoot, ".codex-plugin", "plugin.json");
7089
+ if (!await fileExistsStrict(pluginManifestPath))
7090
+ return [join8(pluginRoot, "hooks", "hooks.json")];
7091
+ const parsed = JSON.parse(await readFile6(pluginManifestPath, "utf8"));
7092
+ if (!isPlainRecord(parsed))
7093
+ return [];
7094
+ if (typeof parsed.hooks === "string" && parsed.hooks.trim() !== "") {
7095
+ return [join8(pluginRoot, stripDotSlash(parsed.hooks))];
7096
+ }
7097
+ if (Array.isArray(parsed.hooks)) {
7098
+ return parsed.hooks.filter((hookPath) => typeof hookPath === "string" && hookPath.trim() !== "").map((hookPath) => join8(pluginRoot, stripDotSlash(hookPath)));
7099
+ }
7100
+ return [];
7101
+ }
7102
+ function stripDotSlash(path) {
7103
+ return path.startsWith("./") ? path.slice(2) : path;
7104
+ }
7105
+ async function assertHookCommandTargets(pluginRoot) {
7106
+ const missing = await findMissingHookCommandTargets(pluginRoot);
7107
+ if (missing.length === 0)
7108
+ return;
7109
+ const relativeMissing = missing.map((path) => path.split(`${pluginRoot}${sep4}`).join("").split(sep4).join("/"));
7110
+ throw new Error(`Plugin payload is missing ${missing.length} hook command target(s) referenced by hooks.json: ${relativeMissing.join(", ")}. ` + "The previous plugin cache was left untouched; this payload was not activated.");
7111
+ }
7112
+ function collectCommands(value, commands) {
7113
+ if (Array.isArray(value)) {
7114
+ for (const entry of value)
7115
+ collectCommands(entry, commands);
7116
+ return;
7117
+ }
7118
+ if (!isPlainRecord(value))
7119
+ return;
7120
+ if (value["type"] === "command" && typeof value["command"] === "string")
7121
+ commands.push(value["command"]);
7122
+ if (value["type"] === "command" && typeof value["commandWindows"] === "string")
7123
+ commands.push(value["commandWindows"]);
7124
+ for (const entry of Object.values(value))
7125
+ collectCommands(entry, commands);
7126
+ }
7127
+
7058
7128
  // packages/omo-codex/src/install/codex-cache-install.ts
7059
7129
  async function installCachedPlugin(input) {
7060
7130
  if (input.buildSource !== false) {
7061
7131
  await maybeRunNpmInstall(input.sourcePath, input.runCommand);
7062
7132
  await maybeRunNpmBuild(input.sourcePath, input.runCommand);
7063
7133
  }
7064
- const targetPath = join8(input.codexHome, "plugins", "cache", input.marketplaceName, input.name, input.version);
7134
+ const targetPath = join9(input.codexHome, "plugins", "cache", input.marketplaceName, input.name, input.version);
7065
7135
  const tempPath = createTempSiblingPath(targetPath);
7066
7136
  await rm3(tempPath, { recursive: true, force: true });
7067
7137
  try {
@@ -7071,6 +7141,7 @@ async function installCachedPlugin(input) {
7071
7141
  await maybeRunNpmInstall(tempPath, input.runCommand, ["ci", "--omit=dev"]);
7072
7142
  await rewriteCachedMcpManifest(tempPath, input.sourcePath);
7073
7143
  await rewriteCachedManifestRoot(tempPath, tempPath, targetPath);
7144
+ await assertHookCommandTargets(tempPath);
7074
7145
  await promoteDirectory(tempPath, targetPath, input.renameDirectory ?? rename);
7075
7146
  } catch (error) {
7076
7147
  await rm3(tempPath, { recursive: true, force: true });
@@ -7079,14 +7150,14 @@ async function installCachedPlugin(input) {
7079
7150
  return { name: input.name, version: input.version, path: targetPath };
7080
7151
  }
7081
7152
  async function maybeRunNpmInstall(cwd, runCommand, args = ["install"]) {
7082
- if (!await fileExistsStrict(join8(cwd, "package.json")))
7153
+ if (!await fileExistsStrict(join9(cwd, "package.json")))
7083
7154
  return;
7084
7155
  await runCommand("npm", args, { cwd });
7085
7156
  }
7086
7157
  async function maybeRunNpmBuild(cwd, runCommand) {
7087
- if (!await fileExistsStrict(join8(cwd, "package.json")))
7158
+ if (!await fileExistsStrict(join9(cwd, "package.json")))
7088
7159
  return;
7089
- const packageJson = JSON.parse(await readFile6(join8(cwd, "package.json"), "utf8"));
7160
+ const packageJson = JSON.parse(await readFile7(join9(cwd, "package.json"), "utf8"));
7090
7161
  if (!isPlainRecord(packageJson))
7091
7162
  return;
7092
7163
  const scripts = packageJson.scripts;
@@ -7095,10 +7166,10 @@ async function maybeRunNpmBuild(cwd, runCommand) {
7095
7166
  await runCommand("npm", ["run", "build"], { cwd });
7096
7167
  }
7097
7168
  function createTempSiblingPath(targetPath) {
7098
- return join8(dirname3(targetPath), `.tmp-${basename2(targetPath)}-${process.pid}-${Date.now()}`);
7169
+ return join9(dirname3(targetPath), `.tmp-${basename2(targetPath)}-${process.pid}-${Date.now()}`);
7099
7170
  }
7100
7171
  function createBackupSiblingPath(targetPath) {
7101
- return join8(dirname3(targetPath), `.backup-${basename2(targetPath)}-${process.pid}-${Date.now()}`);
7172
+ return join9(dirname3(targetPath), `.backup-${basename2(targetPath)}-${process.pid}-${Date.now()}`);
7102
7173
  }
7103
7174
  async function copyDirectory(sourcePath, targetPath) {
7104
7175
  await mkdir3(dirname3(targetPath), { recursive: true });
@@ -7129,17 +7200,17 @@ async function restoreBackupDirectory(backupPath, targetPath, renameDirectory) {
7129
7200
  await renameDirectory(backupPath, targetPath);
7130
7201
  }
7131
7202
  function shouldCopyPluginPath(path, root) {
7132
- const relative4 = path === root ? "" : path.slice(root.length + sep4.length);
7203
+ const relative4 = path === root ? "" : path.slice(root.length + sep5.length);
7133
7204
  if (relative4 === "")
7134
7205
  return true;
7135
- const parts = relative4.split(sep4);
7206
+ const parts = relative4.split(sep5);
7136
7207
  return !parts.some((part) => part === ".git" || part === "node_modules");
7137
7208
  }
7138
7209
  // packages/omo-codex/src/install/codex-cache-prune.ts
7139
7210
  import { lstat as lstat4, readdir as readdir3, rm as rm4, stat as stat3 } from "node:fs/promises";
7140
- import { join as join9 } from "node:path";
7211
+ import { join as join10 } from "node:path";
7141
7212
  async function pruneMarketplaceCache(input) {
7142
- const cacheRoot = join9(input.codexHome, "plugins", "cache", input.marketplaceName);
7213
+ const cacheRoot = join10(input.codexHome, "plugins", "cache", input.marketplaceName);
7143
7214
  if (!await fileExistsStrict(cacheRoot))
7144
7215
  return;
7145
7216
  const keep = new Set(input.keepPluginNames);
@@ -7147,15 +7218,15 @@ async function pruneMarketplaceCache(input) {
7147
7218
  for (const entry of entries) {
7148
7219
  if (!entry.isDirectory() || keep.has(entry.name))
7149
7220
  continue;
7150
- await rm4(join9(cacheRoot, entry.name), { recursive: true, force: true });
7221
+ await rm4(join10(cacheRoot, entry.name), { recursive: true, force: true });
7151
7222
  }
7152
7223
  }
7153
7224
  async function pruneMarketplacePluginCaches(input) {
7154
- const cacheRoot = join9(input.codexHome, "plugins", "cache", input.marketplaceName);
7225
+ const cacheRoot = join10(input.codexHome, "plugins", "cache", input.marketplaceName);
7155
7226
  if (!await fileExistsStrict(cacheRoot))
7156
7227
  return;
7157
7228
  for (const pluginName of input.pluginNames) {
7158
- await rm4(join9(cacheRoot, pluginName), { recursive: true, force: true });
7229
+ await rm4(join10(cacheRoot, pluginName), { recursive: true, force: true });
7159
7230
  }
7160
7231
  const remainingEntries = await readCacheEntryNames(cacheRoot);
7161
7232
  if (remainingEntries.length === 0) {
@@ -7202,11 +7273,11 @@ async function isBrokenCacheSymlink(path) {
7202
7273
  }
7203
7274
  // packages/omo-codex/src/install/codex-cached-marketplace-manifest.ts
7204
7275
  import { mkdir as mkdir4, writeFile as writeFile4 } from "node:fs/promises";
7205
- import { join as join10 } from "node:path";
7276
+ import { join as join11 } from "node:path";
7206
7277
  async function writeCachedMarketplaceManifest(input) {
7207
- const marketplaceDir = join10(input.marketplaceRoot, ".agents", "plugins");
7278
+ const marketplaceDir = join11(input.marketplaceRoot, ".agents", "plugins");
7208
7279
  await mkdir4(marketplaceDir, { recursive: true });
7209
- await writeFile4(join10(marketplaceDir, "marketplace.json"), `${JSON.stringify({
7280
+ await writeFile4(join11(marketplaceDir, "marketplace.json"), `${JSON.stringify({
7210
7281
  name: input.marketplaceName,
7211
7282
  plugins: input.plugins.map((plugin) => ({
7212
7283
  name: plugin.name,
@@ -7218,8 +7289,8 @@ async function writeCachedMarketplaceManifest(input) {
7218
7289
 
7219
7290
  // packages/omo-codex/src/install/codex-package-layout.ts
7220
7291
  import { existsSync as existsSync2 } from "node:fs";
7221
- import { readFile as readFile7 } from "node:fs/promises";
7222
- import { join as join11 } from "node:path";
7292
+ import { readFile as readFile8 } from "node:fs/promises";
7293
+ import { join as join12 } from "node:path";
7223
7294
  var PACKAGED_CODEX_INSTALLER_NAMES = new Set([
7224
7295
  "@code-yeongyu/lazycodex",
7225
7296
  "@code-yeongyu/lazycodex-ai",
@@ -7229,19 +7300,19 @@ var PACKAGED_CODEX_INSTALLER_NAMES = new Set([
7229
7300
  "oh-my-openagent"
7230
7301
  ]);
7231
7302
  async function shouldBuildSourcePackages(repoRoot) {
7232
- if (existsSync2(join11(repoRoot, "packages", "omo-opencode", "src", "index.ts")))
7303
+ if (existsSync2(join12(repoRoot, "packages", "omo-opencode", "src", "index.ts")))
7233
7304
  return true;
7234
- const packageJsonPath = join11(repoRoot, "package.json");
7305
+ const packageJsonPath = join12(repoRoot, "package.json");
7235
7306
  if (!existsSync2(packageJsonPath))
7236
7307
  return true;
7237
- const packageJson = JSON.parse(await readFile7(packageJsonPath, "utf8"));
7308
+ const packageJson = JSON.parse(await readFile8(packageJsonPath, "utf8"));
7238
7309
  if (!isPlainRecord(packageJson) || typeof packageJson.name !== "string")
7239
7310
  return true;
7240
7311
  return !PACKAGED_CODEX_INSTALLER_NAMES.has(packageJson.name);
7241
7312
  }
7242
7313
 
7243
7314
  // packages/omo-codex/src/install/codex-config-toml.ts
7244
- import { mkdir as mkdir5, readFile as readFile9 } from "node:fs/promises";
7315
+ import { mkdir as mkdir5, readFile as readFile10 } from "node:fs/promises";
7245
7316
  import { dirname as dirname5 } from "node:path";
7246
7317
 
7247
7318
  // packages/omo-codex/src/install/toml-section-editor.ts
@@ -7429,12 +7500,12 @@ function tomlKeySegment(value) {
7429
7500
 
7430
7501
  // packages/omo-codex/src/install/codex-config-atomic-write.ts
7431
7502
  import { lstat as lstat5, readlink as readlink3, realpath, rename as rename2, unlink, writeFile as writeFile5 } from "node:fs/promises";
7432
- import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute4, join as join12, resolve as resolve5 } from "node:path";
7503
+ import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute4, join as join13, resolve as resolve5 } from "node:path";
7433
7504
  var RENAME_RETRY_DELAYS_MS = [10, 25, 50];
7434
7505
  var RETRIABLE_RENAME_CODES = new Set(["EPERM", "EBUSY"]);
7435
7506
  async function writeFileAtomic(targetPath, data) {
7436
7507
  const writeTarget = await resolveSymlinkTarget(targetPath);
7437
- const temporaryPath = join12(dirname4(writeTarget), `.tmp-${basename3(writeTarget)}-${process.pid}-${Date.now()}`);
7508
+ const temporaryPath = join13(dirname4(writeTarget), `.tmp-${basename3(writeTarget)}-${process.pid}-${Date.now()}`);
7438
7509
  await writeFile5(temporaryPath, data);
7439
7510
  try {
7440
7511
  await renameWithRetry(temporaryPath, writeTarget);
@@ -7704,8 +7775,8 @@ function isRootSetting(line, key) {
7704
7775
  }
7705
7776
 
7706
7777
  // packages/omo-codex/src/install/codex-model-catalog.ts
7707
- import { readFile as readFile8 } from "node:fs/promises";
7708
- import { join as join13 } from "node:path";
7778
+ import { readFile as readFile9 } from "node:fs/promises";
7779
+ import { join as join14 } from "node:path";
7709
7780
  var FALLBACK_CODEX_MODEL_CATALOG = {
7710
7781
  current: {
7711
7782
  model: "gpt-5.5",
@@ -7724,9 +7795,9 @@ var FALLBACK_CODEX_MODEL_CATALOG = {
7724
7795
  ]
7725
7796
  };
7726
7797
  async function readCodexModelCatalog(codexPackageRoot) {
7727
- const catalogPath = join13(codexPackageRoot, "plugin", "model-catalog.json");
7798
+ const catalogPath = join14(codexPackageRoot, "plugin", "model-catalog.json");
7728
7799
  try {
7729
- const parsed = JSON.parse(await readFile8(catalogPath, "utf8"));
7800
+ const parsed = JSON.parse(await readFile9(catalogPath, "utf8"));
7730
7801
  return parseCodexModelCatalog(parsed) ?? FALLBACK_CODEX_MODEL_CATALOG;
7731
7802
  } catch (error) {
7732
7803
  if (error instanceof Error)
@@ -7807,7 +7878,7 @@ async function updateCodexConfig(input) {
7807
7878
  await mkdir5(dirname5(input.configPath), { recursive: true });
7808
7879
  let config = "";
7809
7880
  if (await exists(input.configPath))
7810
- config = await readFile9(input.configPath, "utf8");
7881
+ config = await readFile10(input.configPath, "utf8");
7811
7882
  const pluginSet = new Set(input.pluginNames);
7812
7883
  for (const legacyMarketplaceName of legacyMarketplaceNames(input.marketplaceName)) {
7813
7884
  config = removeMarketplaceBlock(config, legacyMarketplaceName);
@@ -7843,7 +7914,7 @@ async function updateCodexConfig(input) {
7843
7914
  }
7844
7915
  async function exists(path) {
7845
7916
  try {
7846
- await readFile9(path, "utf8");
7917
+ await readFile10(path, "utf8");
7847
7918
  return true;
7848
7919
  } catch (error) {
7849
7920
  if (error instanceof Error)
@@ -7854,8 +7925,8 @@ async function exists(path) {
7854
7925
 
7855
7926
  // packages/omo-codex/src/install/codex-hook-trust.ts
7856
7927
  import { createHash } from "node:crypto";
7857
- import { readFile as readFile10 } from "node:fs/promises";
7858
- import { join as join14 } from "node:path";
7928
+ import { readFile as readFile11 } from "node:fs/promises";
7929
+ import { join as join15 } from "node:path";
7859
7930
  var EVENT_LABELS = new Map([
7860
7931
  ["PreToolUse", "pre_tool_use"],
7861
7932
  ["PermissionRequest", "permission_request"],
@@ -7869,21 +7940,37 @@ var EVENT_LABELS = new Map([
7869
7940
  ["Stop", "stop"]
7870
7941
  ]);
7871
7942
  async function trustedHookStatesForPlugin(input) {
7872
- const manifestPath = join14(input.pluginRoot, ".codex-plugin", "plugin.json");
7943
+ const manifestPath = join15(input.pluginRoot, ".codex-plugin", "plugin.json");
7873
7944
  if (!await exists2(manifestPath))
7874
7945
  return [];
7875
- const manifest = JSON.parse(await readFile10(manifestPath, "utf8"));
7876
- if (!isPlainRecord(manifest) || typeof manifest.hooks !== "string")
7946
+ const manifest = JSON.parse(await readFile11(manifestPath, "utf8"));
7947
+ if (!isPlainRecord(manifest))
7877
7948
  return [];
7878
- const hooksPath = join14(input.pluginRoot, manifest.hooks);
7879
- if (!await exists2(hooksPath))
7880
- return [];
7881
- const parsed = JSON.parse(await readFile10(hooksPath, "utf8"));
7882
- if (!isPlainRecord(parsed) || !isPlainRecord(parsed.hooks))
7949
+ const states = [];
7950
+ for (const hookPath of hookManifestPaths2(manifest.hooks)) {
7951
+ const hooksPath = join15(input.pluginRoot, hookPath);
7952
+ if (!await exists2(hooksPath))
7953
+ continue;
7954
+ const parsed = JSON.parse(await readFile11(hooksPath, "utf8"));
7955
+ if (!isPlainRecord(parsed) || !isPlainRecord(parsed.hooks))
7956
+ continue;
7957
+ states.push(...trustedHookStatesForHooksFile({
7958
+ keySource: `${input.pluginName}@${input.marketplaceName}:${hookPath}`,
7959
+ hooks: parsed.hooks
7960
+ }));
7961
+ }
7962
+ return states;
7963
+ }
7964
+ function hookManifestPaths2(value) {
7965
+ if (typeof value === "string" && value.trim() !== "")
7966
+ return [stripDotSlash2(value)];
7967
+ if (!Array.isArray(value))
7883
7968
  return [];
7884
- const keySource = `${input.pluginName}@${input.marketplaceName}:${stripDotSlash(manifest.hooks)}`;
7969
+ return value.filter((item) => typeof item === "string" && item.trim() !== "").map(stripDotSlash2);
7970
+ }
7971
+ function trustedHookStatesForHooksFile(input) {
7885
7972
  const states = [];
7886
- for (const [eventName, groups] of Object.entries(parsed.hooks)) {
7973
+ for (const [eventName, groups] of Object.entries(input.hooks)) {
7887
7974
  if (!Array.isArray(groups))
7888
7975
  continue;
7889
7976
  const eventLabel = EVENT_LABELS.get(eventName);
@@ -7899,7 +7986,7 @@ async function trustedHookStatesForPlugin(input) {
7899
7986
  continue;
7900
7987
  if (typeof handler.command !== "string" || handler.command.trim() === "")
7901
7988
  continue;
7902
- const key = `${keySource}:${eventLabel}:${groupIndex}:${handlerIndex}`;
7989
+ const key = `${input.keySource}:${eventLabel}:${groupIndex}:${handlerIndex}`;
7903
7990
  states.push({ key, trustedHash: commandHookHash(eventLabel, group.matcher, handler) });
7904
7991
  }
7905
7992
  }
@@ -7933,12 +8020,12 @@ function canonicalJson(value) {
7933
8020
  }
7934
8021
  return result;
7935
8022
  }
7936
- function stripDotSlash(value) {
8023
+ function stripDotSlash2(value) {
7937
8024
  return value.startsWith("./") ? value.slice(2) : value;
7938
8025
  }
7939
8026
  async function exists2(path) {
7940
8027
  try {
7941
- await readFile10(path, "utf8");
8028
+ await readFile11(path, "utf8");
7942
8029
  return true;
7943
8030
  } catch (error) {
7944
8031
  if (error instanceof Error)
@@ -7989,12 +8076,12 @@ function toCodexResolution(resolution) {
7989
8076
  }
7990
8077
 
7991
8078
  // packages/omo-codex/src/install/link-cached-plugin-agents.ts
7992
- import { copyFile, lstat as lstat7, mkdir as mkdir6, readFile as readFile12, readdir as readdir4, rm as rm6, writeFile as writeFile6 } from "node:fs/promises";
7993
- import { basename as basename4, join as join16 } from "node:path";
8079
+ import { copyFile, lstat as lstat7, mkdir as mkdir6, readFile as readFile13, readdir as readdir4, rm as rm6, writeFile as writeFile6 } from "node:fs/promises";
8080
+ import { basename as basename4, join as join17 } from "node:path";
7994
8081
 
7995
8082
  // packages/omo-codex/src/install/retired-managed-agent-purge.ts
7996
- import { lstat as lstat6, readFile as readFile11, rm as rm5 } from "node:fs/promises";
7997
- import { join as join15 } from "node:path";
8083
+ import { lstat as lstat6, readFile as readFile12, rm as rm5 } from "node:fs/promises";
8084
+ import { join as join16 } from "node:path";
7998
8085
  var RETIRED_MANAGED_AGENT_FILES = [
7999
8086
  {
8000
8087
  fileName: "codex-ultrawork-reviewer.toml",
@@ -8006,11 +8093,11 @@ var RETIRED_MANAGED_AGENT_FILES = [
8006
8093
  }
8007
8094
  ];
8008
8095
  async function purgeRetiredManagedAgentFiles(input) {
8009
- const agentsDir = join15(input.codexHome, "agents");
8096
+ const agentsDir = join16(input.codexHome, "agents");
8010
8097
  if (!await exists3(agentsDir))
8011
8098
  return;
8012
8099
  for (const retiredAgent of RETIRED_MANAGED_AGENT_FILES) {
8013
- const agentPath = join15(agentsDir, retiredAgent.fileName);
8100
+ const agentPath = join16(agentsDir, retiredAgent.fileName);
8014
8101
  if (!await exists3(agentPath))
8015
8102
  continue;
8016
8103
  const agentStat = await lstat6(agentPath);
@@ -8027,7 +8114,7 @@ function hasRequiredMarkers(content, markers) {
8027
8114
  }
8028
8115
  async function readTextIfExists(path) {
8029
8116
  try {
8030
- return await readFile11(path, "utf8");
8117
+ return await readFile12(path, "utf8");
8031
8118
  } catch (error) {
8032
8119
  if (nodeErrorCode(error) === "ENOENT")
8033
8120
  return null;
@@ -8053,7 +8140,7 @@ function nodeErrorCode(error) {
8053
8140
  // packages/omo-codex/src/install/link-cached-plugin-agents.ts
8054
8141
  var MANIFEST_FILE = ".installed-agents.json";
8055
8142
  async function capturePreservedAgentReasoning(input) {
8056
- const agentsDir = join16(input.codexHome, "agents");
8143
+ const agentsDir = join17(input.codexHome, "agents");
8057
8144
  if (!await exists4(agentsDir))
8058
8145
  return new Map;
8059
8146
  const preserved = new Map;
@@ -8061,7 +8148,7 @@ async function capturePreservedAgentReasoning(input) {
8061
8148
  for (const entry of agentEntries) {
8062
8149
  if (!entry.name.endsWith(".toml"))
8063
8150
  continue;
8064
- const content = await readTextIfExists2(join16(agentsDir, entry.name));
8151
+ const content = await readTextIfExists2(join17(agentsDir, entry.name));
8065
8152
  if (content === null)
8066
8153
  continue;
8067
8154
  const effort = extractReasoningEffort(content);
@@ -8071,7 +8158,7 @@ async function capturePreservedAgentReasoning(input) {
8071
8158
  return preserved;
8072
8159
  }
8073
8160
  async function capturePreservedAgentServiceTier(input) {
8074
- const agentsDir = join16(input.codexHome, "agents");
8161
+ const agentsDir = join17(input.codexHome, "agents");
8075
8162
  if (!await exists4(agentsDir))
8076
8163
  return new Map;
8077
8164
  const preserved = new Map;
@@ -8079,7 +8166,7 @@ async function capturePreservedAgentServiceTier(input) {
8079
8166
  for (const entry of agentEntries) {
8080
8167
  if (!entry.name.endsWith(".toml"))
8081
8168
  continue;
8082
- const content = await readTextIfExists2(join16(agentsDir, entry.name));
8169
+ const content = await readTextIfExists2(join17(agentsDir, entry.name));
8083
8170
  if (content === null)
8084
8171
  continue;
8085
8172
  preserved.set(agentNameFromToml(entry.name), extractServiceTier(content));
@@ -8093,13 +8180,13 @@ async function linkCachedPluginAgents(input) {
8093
8180
  await writeManifest(input.pluginRoot, []);
8094
8181
  return [];
8095
8182
  }
8096
- const agentsDir = join16(input.codexHome, "agents");
8183
+ const agentsDir = join17(input.codexHome, "agents");
8097
8184
  await mkdir6(agentsDir, { recursive: true });
8098
8185
  const linked = [];
8099
8186
  for (const agentPath of bundledAgents) {
8100
8187
  const agentFileName = basename4(agentPath);
8101
8188
  const agentName = agentNameFromToml(agentFileName);
8102
- const linkPath = join16(agentsDir, agentFileName);
8189
+ const linkPath = join17(agentsDir, agentFileName);
8103
8190
  await replaceWithCopy(linkPath, agentPath);
8104
8191
  await restorePreservedReasoning({
8105
8192
  agentName,
@@ -8120,7 +8207,7 @@ async function linkCachedPluginAgents(input) {
8120
8207
  async function restorePreservedServiceTier(input) {
8121
8208
  if (!input.preserved)
8122
8209
  return;
8123
- const content = await readFile12(input.linkPath, "utf8");
8210
+ const content = await readFile13(input.linkPath, "utf8");
8124
8211
  if (extractServiceTier(content) === input.value)
8125
8212
  return;
8126
8213
  const replacement = replaceServiceTier(content, input.value);
@@ -8129,7 +8216,7 @@ async function restorePreservedServiceTier(input) {
8129
8216
  await writeFile6(input.linkPath, replacement.content);
8130
8217
  }
8131
8218
  async function discoverBundledAgents(pluginRoot) {
8132
- const componentsRoot = join16(pluginRoot, "components");
8219
+ const componentsRoot = join17(pluginRoot, "components");
8133
8220
  if (!await exists4(componentsRoot))
8134
8221
  return [];
8135
8222
  const componentEntries = await readdir4(componentsRoot, { withFileTypes: true });
@@ -8137,14 +8224,14 @@ async function discoverBundledAgents(pluginRoot) {
8137
8224
  for (const entry of componentEntries) {
8138
8225
  if (!entry.isDirectory())
8139
8226
  continue;
8140
- const agentsRoot = join16(componentsRoot, entry.name, "agents");
8227
+ const agentsRoot = join17(componentsRoot, entry.name, "agents");
8141
8228
  if (!await exists4(agentsRoot))
8142
8229
  continue;
8143
8230
  const agentEntries = await readdir4(agentsRoot, { withFileTypes: true });
8144
8231
  for (const file2 of agentEntries) {
8145
8232
  if (!file2.isFile() || !file2.name.endsWith(".toml"))
8146
8233
  continue;
8147
- agents.push(join16(agentsRoot, file2.name));
8234
+ agents.push(join17(agentsRoot, file2.name));
8148
8235
  }
8149
8236
  }
8150
8237
  agents.sort();
@@ -8164,7 +8251,7 @@ async function prepareReplacement(linkPath) {
8164
8251
  await rm6(linkPath, { force: true });
8165
8252
  }
8166
8253
  async function writeManifest(pluginRoot, agentPaths) {
8167
- const manifestPath = join16(pluginRoot, MANIFEST_FILE);
8254
+ const manifestPath = join17(pluginRoot, MANIFEST_FILE);
8168
8255
  const payload = { agents: [...agentPaths].sort() };
8169
8256
  await writeFile6(manifestPath, `${JSON.stringify(payload, null, "\t")}
8170
8257
  `);
@@ -8172,7 +8259,7 @@ async function writeManifest(pluginRoot, agentPaths) {
8172
8259
  async function restorePreservedReasoning(input) {
8173
8260
  if (input.value === undefined)
8174
8261
  return;
8175
- const content = await readFile12(input.target, "utf8");
8262
+ const content = await readFile13(input.target, "utf8");
8176
8263
  const bundledEffort = extractReasoningEffort(content);
8177
8264
  if (bundledEffort === input.value)
8178
8265
  return;
@@ -8183,7 +8270,7 @@ async function restorePreservedReasoning(input) {
8183
8270
  }
8184
8271
  async function readTextIfExists2(path) {
8185
8272
  try {
8186
- return await readFile12(path, "utf8");
8273
+ return await readFile13(path, "utf8");
8187
8274
  } catch (error) {
8188
8275
  if (nodeErrorCode2(error) === "ENOENT")
8189
8276
  return null;
@@ -8291,12 +8378,12 @@ function nodeErrorCode2(error) {
8291
8378
  }
8292
8379
 
8293
8380
  // packages/omo-codex/src/install/codex-marketplace.ts
8294
- import { readFile as readFile13 } from "node:fs/promises";
8295
- import { join as join17 } from "node:path";
8381
+ import { readFile as readFile14 } from "node:fs/promises";
8382
+ import { join as join18 } from "node:path";
8296
8383
  var DEFAULT_MARKETPLACE_PATH = "packages/omo-codex/marketplace.json";
8297
8384
  async function readMarketplace(repoRoot, options) {
8298
- const marketplacePath = options?.marketplacePath ?? join17(repoRoot, DEFAULT_MARKETPLACE_PATH);
8299
- const raw = await readFile13(marketplacePath, "utf8");
8385
+ const marketplacePath = options?.marketplacePath ?? join18(repoRoot, DEFAULT_MARKETPLACE_PATH);
8386
+ const raw = await readFile14(marketplacePath, "utf8");
8300
8387
  const parsed = JSON.parse(raw);
8301
8388
  if (!isPlainRecord(parsed))
8302
8389
  throw new Error("marketplace.json must be an object");
@@ -8314,10 +8401,10 @@ async function readMarketplace(repoRoot, options) {
8314
8401
  function resolvePluginSource(repoRoot, plugin, options) {
8315
8402
  const sourcePath = localSourcePath(options?.pathOverride ?? plugin.source);
8316
8403
  const relativePath = sourcePath.slice(2);
8317
- return join17(repoRoot, ...relativePath.split(/[\\/]/));
8404
+ return join18(repoRoot, ...relativePath.split(/[\\/]/));
8318
8405
  }
8319
8406
  async function readPluginManifest(pluginRoot) {
8320
- const raw = await readFile13(join17(pluginRoot, ".codex-plugin", "plugin.json"), "utf8");
8407
+ const raw = await readFile14(join18(pluginRoot, ".codex-plugin", "plugin.json"), "utf8");
8321
8408
  const parsed = JSON.parse(raw);
8322
8409
  if (!isPlainRecord(parsed))
8323
8410
  throw new Error(`${pluginRoot} plugin.json must be an object`);
@@ -8327,15 +8414,27 @@ async function readPluginManifest(pluginRoot) {
8327
8414
  if (parsed.version !== undefined && (typeof parsed.version !== "string" || parsed.version.trim() === "")) {
8328
8415
  throw new Error(`${pluginRoot} plugin.json version must be a non-empty string`);
8329
8416
  }
8330
- if (parsed.hooks !== undefined && (typeof parsed.hooks !== "string" || parsed.hooks.trim() === "")) {
8331
- throw new Error(`${pluginRoot} plugin.json hooks must be a non-empty string`);
8417
+ if (parsed.hooks !== undefined && !isPluginHooksManifestValue(parsed.hooks)) {
8418
+ throw new Error(`${pluginRoot} plugin.json hooks must be a non-empty string or string array`);
8332
8419
  }
8333
8420
  return {
8334
8421
  name: parsed.name,
8335
8422
  version: typeof parsed.version === "string" ? parsed.version.trim() : undefined,
8336
- hooks: typeof parsed.hooks === "string" ? parsed.hooks.trim() : undefined
8423
+ hooks: normalizePluginHooksManifestValue(parsed.hooks)
8337
8424
  };
8338
8425
  }
8426
+ function isPluginHooksManifestValue(value) {
8427
+ if (typeof value === "string")
8428
+ return value.trim() !== "";
8429
+ return Array.isArray(value) && value.every((item) => typeof item === "string" && item.trim() !== "");
8430
+ }
8431
+ function normalizePluginHooksManifestValue(value) {
8432
+ if (typeof value === "string")
8433
+ return value.trim();
8434
+ if (Array.isArray(value))
8435
+ return value.map((item) => item.trim());
8436
+ return;
8437
+ }
8339
8438
  function validatePathSegment(value, label) {
8340
8439
  if (!/^[A-Za-z0-9._+-]+$/.test(value)) {
8341
8440
  throw new Error(`${label} contains unsupported characters: ${value}`);
@@ -8387,7 +8486,7 @@ function validateLocalSourcePath(path) {
8387
8486
 
8388
8487
  // packages/omo-codex/src/install/codex-marketplace-snapshot.ts
8389
8488
  import { cp as cp3, mkdir as mkdir7, rename as rename3, rm as rm7, writeFile as writeFile7 } from "node:fs/promises";
8390
- import { join as join18, sep as sep5 } from "node:path";
8489
+ import { join as join19, sep as sep6 } from "node:path";
8391
8490
  var INSTALLED_MARKETPLACES_DIR = ".tmp/marketplaces";
8392
8491
  async function writeInstalledMarketplaceSnapshot(input) {
8393
8492
  const marketplaceRoot = installedMarketplaceRoot(input.codexHome, input.marketplace.name);
@@ -8400,21 +8499,21 @@ async function writeInstalledMarketplaceSnapshot(input) {
8400
8499
  return snapshotPlugins;
8401
8500
  }
8402
8501
  function installedMarketplaceRoot(codexHome, marketplaceName) {
8403
- return join18(codexHome, INSTALLED_MARKETPLACES_DIR, marketplaceName);
8502
+ return join19(codexHome, INSTALLED_MARKETPLACES_DIR, marketplaceName);
8404
8503
  }
8405
8504
  async function writeMarketplaceManifest(marketplaceRoot, marketplace) {
8406
- const manifestDir = join18(marketplaceRoot, ".agents", "plugins");
8505
+ const manifestDir = join19(marketplaceRoot, ".agents", "plugins");
8407
8506
  await mkdir7(manifestDir, { recursive: true });
8408
- const tempPath = join18(manifestDir, `.marketplace-${process.pid}-${Date.now()}.json.tmp`);
8507
+ const tempPath = join19(manifestDir, `.marketplace-${process.pid}-${Date.now()}.json.tmp`);
8409
8508
  await writeFile7(tempPath, `${JSON.stringify(marketplace, null, "\t")}
8410
8509
  `);
8411
- await rename3(tempPath, join18(manifestDir, "marketplace.json"));
8510
+ await rename3(tempPath, join19(manifestDir, "marketplace.json"));
8412
8511
  }
8413
8512
  async function writeSnapshotPlugin(marketplaceRoot, plugin) {
8414
- const pluginsDir = join18(marketplaceRoot, "plugins");
8513
+ const pluginsDir = join19(marketplaceRoot, "plugins");
8415
8514
  await mkdir7(pluginsDir, { recursive: true });
8416
- const targetPath = join18(pluginsDir, plugin.name);
8417
- const tempPath = join18(pluginsDir, `.tmp-${plugin.name}-${process.pid}-${Date.now()}`);
8515
+ const targetPath = join19(pluginsDir, plugin.name);
8516
+ const tempPath = join19(pluginsDir, `.tmp-${plugin.name}-${process.pid}-${Date.now()}`);
8418
8517
  await rm7(tempPath, { recursive: true, force: true });
8419
8518
  await cp3(plugin.sourcePath, tempPath, {
8420
8519
  recursive: true,
@@ -8427,19 +8526,19 @@ async function writeSnapshotPlugin(marketplaceRoot, plugin) {
8427
8526
  return { name: plugin.name, path: targetPath };
8428
8527
  }
8429
8528
  function shouldCopyMarketplaceSourcePath(path, root) {
8430
- const relative4 = path === root ? "" : path.slice(root.length + sep5.length);
8529
+ const relative4 = path === root ? "" : path.slice(root.length + sep6.length);
8431
8530
  if (relative4 === "")
8432
8531
  return true;
8433
- const parts = relative4.split(sep5);
8532
+ const parts = relative4.split(sep6);
8434
8533
  return !parts.some((part) => part === ".git" || part === "node_modules");
8435
8534
  }
8436
8535
 
8437
8536
  // packages/omo-codex/src/install/lazycodex-version-stamp.ts
8438
- import { readdir as readdir5, readFile as readFile14, writeFile as writeFile8 } from "node:fs/promises";
8439
- import { join as join19 } from "node:path";
8537
+ import { readdir as readdir5, readFile as readFile15, writeFile as writeFile8 } from "node:fs/promises";
8538
+ import { join as join20 } from "node:path";
8440
8539
  async function readDistributionManifest(repoRoot) {
8441
8540
  try {
8442
- const parsed = JSON.parse(await readFile14(join19(repoRoot, "package.json"), "utf8"));
8541
+ const parsed = JSON.parse(await readFile15(join20(repoRoot, "package.json"), "utf8"));
8443
8542
  if (!isPlainRecord(parsed) || typeof parsed.version !== "string" || parsed.version.trim().length === 0)
8444
8543
  return;
8445
8544
  return {
@@ -8459,15 +8558,19 @@ function resolveLazyCodexPluginVersion(input) {
8459
8558
  return input.manifestVersion ?? "local";
8460
8559
  }
8461
8560
  async function stampLazyCodexPluginVersion(input) {
8462
- await stampJsonVersion(join19(input.pluginRoot, ".codex-plugin", "plugin.json"), input.version);
8463
- await stampJsonVersion(join19(input.pluginRoot, "package.json"), input.version);
8464
- await stampHookStatusMessages(join19(input.pluginRoot, "hooks", "hooks.json"), input.version);
8561
+ const manifestPath = join20(input.pluginRoot, ".codex-plugin", "plugin.json");
8562
+ const hookPaths = await readPluginHookPaths(manifestPath);
8563
+ await stampJsonVersion(manifestPath, input.version);
8564
+ await stampJsonVersion(join20(input.pluginRoot, "package.json"), input.version);
8565
+ for (const hookPath of hookPaths) {
8566
+ await stampHookStatusMessages(join20(input.pluginRoot, hookPath), input.version);
8567
+ }
8465
8568
  await stampComponentVersions(input);
8466
8569
  }
8467
8570
  async function writeLazyCodexInstallSnapshot(input) {
8468
8571
  if (input.distributionManifest === undefined)
8469
8572
  return;
8470
- await writeFile8(join19(input.pluginRoot, "lazycodex-install.json"), `${JSON.stringify({
8573
+ await writeFile8(join20(input.pluginRoot, "lazycodex-install.json"), `${JSON.stringify({
8471
8574
  packageName: input.distributionManifest.name,
8472
8575
  version: input.distributionManifest.version
8473
8576
  }, null, "\t")}
@@ -8475,7 +8578,7 @@ async function writeLazyCodexInstallSnapshot(input) {
8475
8578
  }
8476
8579
  async function stampJsonVersion(path, version) {
8477
8580
  try {
8478
- const parsed = JSON.parse(await readFile14(path, "utf8"));
8581
+ const parsed = JSON.parse(await readFile15(path, "utf8"));
8479
8582
  if (!isPlainRecord(parsed))
8480
8583
  return;
8481
8584
  parsed.version = version;
@@ -8487,9 +8590,29 @@ async function stampJsonVersion(path, version) {
8487
8590
  throw error;
8488
8591
  }
8489
8592
  }
8593
+ async function readPluginHookPaths(manifestPath) {
8594
+ try {
8595
+ const parsed = JSON.parse(await readFile15(manifestPath, "utf8"));
8596
+ if (!isPlainRecord(parsed))
8597
+ return [];
8598
+ if (typeof parsed.hooks === "string" && parsed.hooks.trim().length > 0)
8599
+ return [stripDotSlash3(parsed.hooks)];
8600
+ if (Array.isArray(parsed.hooks)) {
8601
+ return parsed.hooks.filter((hookPath) => typeof hookPath === "string" && hookPath.trim().length > 0).map(stripDotSlash3);
8602
+ }
8603
+ return [];
8604
+ } catch (error) {
8605
+ if (error instanceof Error)
8606
+ return [];
8607
+ throw error;
8608
+ }
8609
+ }
8610
+ function stripDotSlash3(path) {
8611
+ return path.startsWith("./") ? path.slice(2) : path;
8612
+ }
8490
8613
  async function stampHookStatusMessages(path, version) {
8491
8614
  try {
8492
- const parsed = JSON.parse(await readFile14(path, "utf8"));
8615
+ const parsed = JSON.parse(await readFile15(path, "utf8"));
8493
8616
  if (!isPlainRecord(parsed))
8494
8617
  return;
8495
8618
  stampHookGroups(parsed.hooks, version);
@@ -8504,16 +8627,16 @@ async function stampHookStatusMessages(path, version) {
8504
8627
  async function stampComponentVersions(input) {
8505
8628
  let entries;
8506
8629
  try {
8507
- entries = await readdir5(join19(input.pluginRoot, "components"));
8630
+ entries = await readdir5(join20(input.pluginRoot, "components"));
8508
8631
  } catch (error) {
8509
8632
  if (error instanceof Error)
8510
8633
  return;
8511
8634
  throw error;
8512
8635
  }
8513
8636
  for (const entry of entries) {
8514
- const componentRoot = join19(input.pluginRoot, "components", entry);
8515
- await stampJsonVersion(join19(componentRoot, "package.json"), input.version);
8516
- await stampHookStatusMessages(join19(componentRoot, "hooks", "hooks.json"), input.version);
8637
+ const componentRoot = join20(input.pluginRoot, "components", entry);
8638
+ await stampJsonVersion(join20(componentRoot, "package.json"), input.version);
8639
+ await stampHookStatusMessages(join20(componentRoot, "hooks", "hooks.json"), input.version);
8517
8640
  }
8518
8641
  }
8519
8642
  function stampHookGroups(hooks, version) {
@@ -8534,12 +8657,12 @@ function stampHookGroups(hooks, version) {
8534
8657
  function stampHookStatusMessage(hook, version) {
8535
8658
  if (!isPlainRecord(hook) || typeof hook.statusMessage !== "string")
8536
8659
  return;
8537
- hook.statusMessage = hook.statusMessage.replace(/^LazyCodex\([^)]+\):/, `LazyCodex(${version}):`);
8660
+ hook.statusMessage = hook.statusMessage.replace(/^LazyCodex\([^)]+\):\s*/, "(OmO) ");
8538
8661
  }
8539
8662
 
8540
8663
  // packages/omo-codex/src/install/codex-project-local-cleanup.ts
8541
- import { copyFile as copyFile2, lstat as lstat8, readFile as readFile15, writeFile as writeFile9 } from "node:fs/promises";
8542
- import { dirname as dirname6, join as join20, resolve as resolve6 } from "node:path";
8664
+ import { copyFile as copyFile2, lstat as lstat8, readFile as readFile16, writeFile as writeFile9 } from "node:fs/promises";
8665
+ import { dirname as dirname6, join as join21, resolve as resolve6 } from "node:path";
8543
8666
  var LEGACY_AGENT_CONFLICT_KEYS = ["max_threads"];
8544
8667
  var PROJECT_LOCAL_ARTIFACT_PATHS = [
8545
8668
  ".codex/hooks.json",
@@ -8558,7 +8681,7 @@ async function repairNearestProjectLocalCodexArtifacts(input) {
8558
8681
  const artifacts = await collectProjectLocalArtifacts(project.artifactRoots);
8559
8682
  const configs = [];
8560
8683
  for (const configPath of project.configPaths) {
8561
- const original = await readFile15(configPath, "utf8");
8684
+ const original = await readFile16(configPath, "utf8");
8562
8685
  const repair = repairProjectLocalCodexConfigText(original);
8563
8686
  if (!repair.changed) {
8564
8687
  configs.push({
@@ -8642,17 +8765,17 @@ async function findProjectLocalCodexConfigs(startDirectory, codexHome) {
8642
8765
  if (startDirectoryStat !== null && !startDirectoryStat.isDirectory()) {
8643
8766
  throw new ProjectLocalCleanupStartDirectoryError(startDirectory);
8644
8767
  }
8645
- const codexHomeConfigPath = codexHome === undefined ? null : join20(resolve6(codexHome), "config.toml");
8768
+ const codexHomeConfigPath = codexHome === undefined ? null : join21(resolve6(codexHome), "config.toml");
8646
8769
  let current = resolve6(startDirectory);
8647
8770
  const configPathsFromCwd = [];
8648
8771
  while (true) {
8649
- const configPath = join20(current, ".codex", "config.toml");
8772
+ const configPath = join21(current, ".codex", "config.toml");
8650
8773
  if (await isRegularProjectLocalConfig(current, configPath)) {
8651
8774
  if (codexHomeConfigPath === null || resolve6(configPath) !== codexHomeConfigPath) {
8652
8775
  configPathsFromCwd.push(configPath);
8653
8776
  }
8654
8777
  }
8655
- if (await exists5(join20(current, ".git"))) {
8778
+ if (await exists5(join21(current, ".git"))) {
8656
8779
  return configPathsFromCwd.length === 0 ? null : {
8657
8780
  projectRoot: current,
8658
8781
  configPaths: [...configPathsFromCwd].reverse(),
@@ -8672,7 +8795,7 @@ async function findProjectLocalCodexConfigs(startDirectory, codexHome) {
8672
8795
  }
8673
8796
  }
8674
8797
  async function isRegularProjectLocalConfig(directory, configPath) {
8675
- const codexDirStat = await maybeLstat(join20(directory, ".codex"));
8798
+ const codexDirStat = await maybeLstat(join21(directory, ".codex"));
8676
8799
  if (codexDirStat === null || !codexDirStat.isDirectory() || codexDirStat.isSymbolicLink())
8677
8800
  return false;
8678
8801
  const configStat = await maybeLstat(configPath);
@@ -8692,7 +8815,7 @@ async function collectProjectLocalArtifacts(projectRoots) {
8692
8815
  const seenPaths = new Set;
8693
8816
  for (const projectRoot of projectRoots) {
8694
8817
  for (const relativePath of PROJECT_LOCAL_ARTIFACT_PATHS) {
8695
- const artifactPath = join20(projectRoot, relativePath);
8818
+ const artifactPath = join21(projectRoot, relativePath);
8696
8819
  if (seenPaths.has(artifactPath))
8697
8820
  continue;
8698
8821
  const entryStat = await maybeLstat(artifactPath);
@@ -8767,13 +8890,13 @@ function formatUnknownError(error) {
8767
8890
  }
8768
8891
 
8769
8892
  // packages/omo-codex/src/install/lsp-daemon-reaper.ts
8770
- import { readFile as readFile16, readdir as readdir6, rm as rm8 } from "node:fs/promises";
8893
+ import { readFile as readFile17, readdir as readdir6, rm as rm8 } from "node:fs/promises";
8771
8894
  import { connect } from "node:net";
8772
- import { join as join21 } from "node:path";
8895
+ import { join as join22 } from "node:path";
8773
8896
  async function reapLspDaemons(codexHome, deps = {}) {
8774
8897
  const killProcess = deps.killProcess ?? sendSigterm;
8775
8898
  const isDaemonLive = deps.isDaemonLive ?? probeSocketLive;
8776
- const daemonRoot = join21(codexHome, "codex-lsp", "daemon");
8899
+ const daemonRoot = join22(codexHome, "codex-lsp", "daemon");
8777
8900
  const reaped = [];
8778
8901
  let entries;
8779
8902
  try {
@@ -8782,9 +8905,9 @@ async function reapLspDaemons(codexHome, deps = {}) {
8782
8905
  return reaped;
8783
8906
  }
8784
8907
  for (const entry of entries) {
8785
- const versionDir = join21(daemonRoot, entry);
8786
- const pid = await readPidFile(join21(versionDir, "daemon.pid"));
8787
- const socketPath = await readEndpointFile(join21(versionDir, "daemon.endpoint"));
8908
+ const versionDir = join22(daemonRoot, entry);
8909
+ const pid = await readPidFile(join22(versionDir, "daemon.pid"));
8910
+ const socketPath = await readEndpointFile(join22(versionDir, "daemon.endpoint"));
8788
8911
  if (pid !== null && socketPath !== null && await isDaemonLive(socketPath) && killProcess(pid)) {
8789
8912
  reaped.push(pid);
8790
8913
  }
@@ -8794,7 +8917,7 @@ async function reapLspDaemons(codexHome, deps = {}) {
8794
8917
  }
8795
8918
  async function readEndpointFile(path) {
8796
8919
  try {
8797
- const content = (await readFile16(path, "utf8")).trim();
8920
+ const content = (await readFile17(path, "utf8")).trim();
8798
8921
  return content.length > 0 ? content : null;
8799
8922
  } catch {
8800
8923
  return null;
@@ -8802,7 +8925,7 @@ async function readEndpointFile(path) {
8802
8925
  }
8803
8926
  async function readPidFile(path) {
8804
8927
  try {
8805
- const pid = Number.parseInt((await readFile16(path, "utf8")).trim(), 10);
8928
+ const pid = Number.parseInt((await readFile17(path, "utf8")).trim(), 10);
8806
8929
  return Number.isInteger(pid) && pid > 0 ? pid : null;
8807
8930
  } catch {
8808
8931
  return null;
@@ -8838,7 +8961,7 @@ function sendSigterm(pid) {
8838
8961
 
8839
8962
  // packages/omo-codex/src/install/codex-installer-bin-dir.ts
8840
8963
  import { homedir } from "node:os";
8841
- import { join as join22, resolve as resolve7 } from "node:path";
8964
+ import { join as join23, resolve as resolve7 } from "node:path";
8842
8965
  function resolveCodexInstallerBinDir(input) {
8843
8966
  const explicitBinDir = input.binDir ?? input.env?.CODEX_LOCAL_BIN_DIR;
8844
8967
  if (explicitBinDir !== undefined && explicitBinDir.trim().length > 0)
@@ -8847,15 +8970,15 @@ function resolveCodexInstallerBinDir(input) {
8847
8970
  const defaultCodexHome = resolve7(homeDir, ".codex");
8848
8971
  const resolvedCodexHome = resolve7(input.codexHome);
8849
8972
  if (resolvedCodexHome !== defaultCodexHome)
8850
- return join22(resolvedCodexHome, "bin");
8973
+ return join23(resolvedCodexHome, "bin");
8851
8974
  return resolve7(homeDir, ".local", "bin");
8852
8975
  }
8853
8976
 
8854
8977
  // packages/omo-codex/src/install/omo-sot-migration.ts
8855
- import { join as join23 } from "node:path";
8978
+ import { join as join24 } from "node:path";
8856
8979
  async function seedAndMigrateOmoSot(input) {
8857
8980
  const commandEnv = { ...input.env };
8858
- const scriptPath = join23(input.repoRoot, "packages", "omo-codex", "plugin", "scripts", "migrate-omo-sot.mjs");
8981
+ const scriptPath = join24(input.repoRoot, "packages", "omo-codex", "plugin", "scripts", "migrate-omo-sot.mjs");
8859
8982
  try {
8860
8983
  await input.runCommand(process.execPath, [scriptPath, "--seed"], {
8861
8984
  cwd: input.repoRoot,
@@ -8869,7 +8992,7 @@ async function seedAndMigrateOmoSot(input) {
8869
8992
  }
8870
8993
 
8871
8994
  // packages/omo-codex/src/install/install-ast-grep-sg.ts
8872
- import { join as join25 } from "node:path";
8995
+ import { join as join26 } from "node:path";
8873
8996
 
8874
8997
  // packages/utils/src/deep-merge.ts
8875
8998
  var DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
@@ -11841,11 +11964,11 @@ function runtimeSlug(platform = process.platform, arch = process.arch) {
11841
11964
  // packages/utils/src/ast-grep/install-script.ts
11842
11965
  import { spawn as spawn3 } from "node:child_process";
11843
11966
  import { existsSync as existsSync3 } from "node:fs";
11844
- import { join as join24 } from "node:path";
11967
+ import { join as join25 } from "node:path";
11845
11968
  var AST_GREP_BIN_DIR_ENV_KEY = "OMO_AST_GREP_BIN_DIR";
11846
11969
  var AST_GREP_INSTALL_TIMEOUT_MS = 30000;
11847
11970
  function astGrepRuntimeDir(baseDir, platform = process.platform, arch = process.arch) {
11848
- return join24(baseDir, "runtime", "ast-grep", runtimeSlug(platform, arch));
11971
+ return join25(baseDir, "runtime", "ast-grep", runtimeSlug(platform, arch));
11849
11972
  }
11850
11973
  function isMissingExecutable(error) {
11851
11974
  if (!("code" in error))
@@ -11883,7 +12006,7 @@ function defaultSpawnProcess(command, args, options) {
11883
12006
  };
11884
12007
  }
11885
12008
  function scriptPathForPlatform(skillDir, platform) {
11886
- return join24(skillDir, platform === "win32" ? "install.ps1" : "install.sh");
12009
+ return join25(skillDir, platform === "win32" ? "install.ps1" : "install.sh");
11887
12010
  }
11888
12011
  function invocationsForPlatform(scriptPath, platform) {
11889
12012
  if (platform !== "win32")
@@ -12651,7 +12774,7 @@ async function installAstGrepForCodex(options) {
12651
12774
  return;
12652
12775
  const platform = options.platform ?? process.platform;
12653
12776
  const targetDir = astGrepRuntimeDir(options.codexHome, platform, options.arch ?? process.arch);
12654
- const skillDir = join25(plugin.path, "skills", "ast-grep");
12777
+ const skillDir = join26(plugin.path, "skills", "ast-grep");
12655
12778
  const installer = options.installer ?? runAstGrepSkillInstall;
12656
12779
  try {
12657
12780
  const result = await installer({ platform, skillDir, targetDir });
@@ -12684,7 +12807,7 @@ async function runCodexInstaller(options = {}) {
12684
12807
  const env3 = options.env ?? process.env;
12685
12808
  const platform = options.platform ?? process.platform;
12686
12809
  const repoRoot = resolve10(options.repoRoot ?? findRepoRoot({ importerDir: import.meta.dir, env: env3 }));
12687
- const codexHome = resolve10(options.codexHome ?? env3.CODEX_HOME ?? join28(homedir2(), ".codex"));
12810
+ const codexHome = resolve10(options.codexHome ?? env3.CODEX_HOME ?? join29(homedir2(), ".codex"));
12688
12811
  const projectDirectory = resolve10(options.projectDirectory ?? env3.OMO_CODEX_PROJECT ?? process.cwd());
12689
12812
  const binDir = resolveCodexInstallerBinDir({ binDir: options.binDir, codexHome, env: env3 });
12690
12813
  const runCommand = options.runCommand ?? defaultRunCommand;
@@ -12702,9 +12825,9 @@ async function runCodexInstaller(options = {}) {
12702
12825
  if (!gitBashResolution.found) {
12703
12826
  throw new Error(gitBashResolution.installHint);
12704
12827
  }
12705
- const codexPackageRoot = join28(repoRoot, "packages", "omo-codex");
12828
+ const codexPackageRoot = join29(repoRoot, "packages", "omo-codex");
12706
12829
  const marketplace = await readMarketplace(repoRoot, {
12707
- marketplacePath: join28(codexPackageRoot, "marketplace.json")
12830
+ marketplacePath: join29(codexPackageRoot, "marketplace.json")
12708
12831
  });
12709
12832
  const distributionManifest = await readDistributionManifest(repoRoot);
12710
12833
  const installed = [];
@@ -12746,7 +12869,7 @@ async function runCodexInstaller(options = {}) {
12746
12869
  if (runtimeLink !== null)
12747
12870
  log2(`Linked ${runtimeLink.name} -> ${runtimeLink.target}`);
12748
12871
  else
12749
- log2(`Warning: skipped the omo runtime wrapper because ${join28(repoRoot, "dist", "cli", "index.js")} is missing; omo sparkshell/ulw-loop commands will be unavailable until a package shipping dist/cli is installed`);
12872
+ log2(`Warning: skipped the omo runtime wrapper because ${join29(repoRoot, "dist", "cli", "index.js")} is missing; omo sparkshell/ulw-loop commands will be unavailable until a package shipping dist/cli is installed`);
12750
12873
  }
12751
12874
  pluginSources.push({ name: entry.name, sourcePath });
12752
12875
  installed.push(plugin);
@@ -12799,13 +12922,13 @@ async function runCodexInstaller(options = {}) {
12799
12922
  });
12800
12923
  }
12801
12924
  await reapLspDaemons(codexHome).catch(() => []);
12802
- const marketplaceRoot = join28(codexHome, "plugins", "cache", marketplace.name);
12925
+ const marketplaceRoot = join29(codexHome, "plugins", "cache", marketplace.name);
12803
12926
  await writeCachedMarketplaceManifest({
12804
12927
  marketplaceName: marketplace.name,
12805
12928
  marketplaceRoot,
12806
12929
  plugins: installed
12807
12930
  });
12808
- const configPath = join28(codexHome, "config.toml");
12931
+ const configPath = join29(codexHome, "config.toml");
12809
12932
  await updateCodexConfig({
12810
12933
  configPath,
12811
12934
  repoRoot: codexPackageRoot,
@@ -12864,7 +12987,7 @@ function findRepoRootFromImporter(importerDir) {
12864
12987
  for (let depth = 0;depth <= 7; depth += 1) {
12865
12988
  if (isRepoRootWithCodexPlugin(current))
12866
12989
  return current;
12867
- for (const wrapperPackageRoot of [join28(current, "node_modules", "oh-my-openagent"), join28(current, "oh-my-openagent")]) {
12990
+ for (const wrapperPackageRoot of [join29(current, "node_modules", "oh-my-openagent"), join29(current, "oh-my-openagent")]) {
12868
12991
  if (isRepoRootWithCodexPlugin(wrapperPackageRoot))
12869
12992
  return wrapperPackageRoot;
12870
12993
  }
@@ -12882,7 +13005,7 @@ function findRepoRoot(input) {
12882
13005
  return findRepoRootFromImporter(input.importerDir);
12883
13006
  }
12884
13007
  function isRepoRootWithCodexPlugin(repoRoot) {
12885
- return existsSync6(join28(repoRoot, "packages", "omo-codex", "plugin", ".codex-plugin", "plugin.json"));
13008
+ return existsSync6(join29(repoRoot, "packages", "omo-codex", "plugin", ".codex-plugin", "plugin.json"));
12886
13009
  }
12887
13010
  function codexMarketplaceSource(marketplaceRoot) {
12888
13011
  return { sourceType: "local", source: marketplaceRoot };
@@ -13092,11 +13215,48 @@ function buildDelegatedOmoInvocation(parsed) {
13092
13215
  // packages/omo-codex/src/install/lazycodex-manual-update.ts
13093
13216
  import { spawn as spawn4, spawnSync as spawnSync2 } from "node:child_process";
13094
13217
  import { readFileSync as readFileSync3 } from "node:fs";
13095
- import { dirname as dirname8, join as join29 } from "node:path";
13218
+ import { dirname as dirname8, join as join31 } from "node:path";
13219
+ import { createInterface as createInterface2 } from "node:readline/promises";
13096
13220
  import { fileURLToPath } from "node:url";
13221
+
13222
+ // packages/omo-codex/src/install/lazycodex-bun-global-paths.ts
13223
+ import { join as join30 } from "node:path";
13224
+ function isBunGlobalEntrypointPath(invokedPath, env3) {
13225
+ if (typeof invokedPath !== "string" || invokedPath.trim().length === 0)
13226
+ return false;
13227
+ const normalizedPath = normalizePathForPrefix(invokedPath);
13228
+ return resolveBunGlobalRoots(env3).some((root) => normalizedPath.startsWith(root));
13229
+ }
13230
+ function resolveBunGlobalRoots(env3) {
13231
+ const bunInstallRoot = env3.BUN_INSTALL?.trim();
13232
+ const homeRoot = env3.HOME?.trim();
13233
+ return [
13234
+ ...bunInstallRoot ? [join30(bunInstallRoot, "bin"), join30(bunInstallRoot, "install", "global", "node_modules")] : [],
13235
+ ...homeRoot ? [join30(homeRoot, ".bun", "bin"), join30(homeRoot, ".bun", "install", "global", "node_modules")] : []
13236
+ ].map(normalizePathForPrefix);
13237
+ }
13238
+ function normalizePathForPrefix(path2) {
13239
+ const normalized = path2.replaceAll("\\", "/").replace(/\/+$/, "");
13240
+ return normalized.endsWith("/node_modules") || normalized.endsWith("/bin") ? `${normalized}/` : normalized;
13241
+ }
13242
+
13243
+ // packages/omo-codex/src/install/lazycodex-manual-update.ts
13097
13244
  var DEFAULT_UPDATE_COMMAND = "npx";
13098
13245
  var DEFAULT_UPDATE_ARGS = ["--yes", "lazycodex-ai@latest", "install", "--no-tui", "--codex-autonomous"];
13246
+ var BUN_UPDATE_COMMAND = "bun";
13247
+ var BUN_GLOBAL_UPDATE_ARGS = ["update", "-g", "lazycodex-ai@latest"];
13248
+ var BUN_GLOBAL_UNTRUSTED_ARGS = ["pm", "-g", "untrusted"];
13249
+ var BUN_GLOBAL_TRUST_ARGS = ["pm", "-g", "trust"];
13099
13250
  var INSTALLED_VERSION_FILE = "lazycodex-install.json";
13251
+ var KNOWN_LAZYCODEX_BUN_TRUST_PACKAGES = new Set([
13252
+ "@ast-grep/cli",
13253
+ "@code-yeongyu/comment-checker",
13254
+ "@sisyphuslabs/omo-codex-plugin",
13255
+ "lazycodex-ai",
13256
+ "oh-my-openagent",
13257
+ "oh-my-opencode"
13258
+ ]);
13259
+ var KNOWN_LAZYCODEX_BUN_TRUST_PREFIXES = ["@oh-my-opencode/", "oh-my-openagent-", "oh-my-opencode-"];
13100
13260
  async function runLazyCodexManualUpdate(input = {}) {
13101
13261
  const env3 = input.env ?? process.env;
13102
13262
  const log2 = input.log ?? console.log;
@@ -13107,7 +13267,9 @@ async function runLazyCodexManualUpdate(input = {}) {
13107
13267
  currentVersion,
13108
13268
  latestVersion,
13109
13269
  command: resolveCommand2(env3),
13110
- args: resolveArgs(env3)
13270
+ args: resolveArgs(env3),
13271
+ env: env3,
13272
+ invokedPath: input.invokedPath ?? process.argv[1]
13111
13273
  });
13112
13274
  if (!plan.shouldUpdate) {
13113
13275
  const printableVersion = currentVersion ?? "unknown";
@@ -13116,9 +13278,20 @@ async function runLazyCodexManualUpdate(input = {}) {
13116
13278
  }
13117
13279
  if (input.dryRun) {
13118
13280
  log2(`${plan.command} ${plan.args.join(" ")}`);
13281
+ if (plan.postUpdate === "bun-global-trust")
13282
+ log2(`${DEFAULT_UPDATE_COMMAND} ${DEFAULT_UPDATE_ARGS.join(" ")}`);
13119
13283
  return 0;
13120
13284
  }
13121
13285
  await commandRunner(plan.command, plan.args, { cwd: process.cwd(), env: env3 });
13286
+ if (plan.postUpdate === "bun-global-trust") {
13287
+ await handleBunGlobalTrust({
13288
+ env: env3,
13289
+ log: log2,
13290
+ commandRunner,
13291
+ isInteractive: input.isInteractive ?? (process.stdin.isTTY === true && process.stdout.isTTY === true)
13292
+ });
13293
+ await commandRunner(DEFAULT_UPDATE_COMMAND, DEFAULT_UPDATE_ARGS, { cwd: process.cwd(), env: env3 });
13294
+ }
13122
13295
  return 0;
13123
13296
  }
13124
13297
  function resolveLazyCodexUpdatePlan(input = {}) {
@@ -13130,7 +13303,10 @@ function resolveLazyCodexUpdatePlan(input = {}) {
13130
13303
  return { shouldUpdate: false, reason: "unknown-latest" };
13131
13304
  if (compareVersions(latest, current) <= 0)
13132
13305
  return { shouldUpdate: false, reason: "up-to-date" };
13133
- return { shouldUpdate: true, command: input.command ?? DEFAULT_UPDATE_COMMAND, args: input.args ?? DEFAULT_UPDATE_ARGS };
13306
+ if (isBunGlobalEntrypoint(input.invokedPath, input.env ?? process.env)) {
13307
+ return { shouldUpdate: true, command: BUN_UPDATE_COMMAND, args: BUN_GLOBAL_UPDATE_ARGS, postUpdate: "bun-global-trust" };
13308
+ }
13309
+ return { shouldUpdate: true, command: input.command ?? DEFAULT_UPDATE_COMMAND, args: input.args ?? DEFAULT_UPDATE_ARGS, postUpdate: "none" };
13134
13310
  }
13135
13311
  function resolveCommand2(env3) {
13136
13312
  return env3.LAZYCODEX_AUTO_UPDATE_COMMAND?.trim() || DEFAULT_UPDATE_COMMAND;
@@ -13149,7 +13325,7 @@ function resolveCurrentVersion(env3) {
13149
13325
  if (env3.LAZYCODEX_CURRENT_VERSION?.trim())
13150
13326
  return env3.LAZYCODEX_CURRENT_VERSION.trim();
13151
13327
  const pluginRoot = dirname8(dirname8(fileURLToPath(import.meta.url)));
13152
- return readVersionManifest(resolveInstalledVersionPath(env3, pluginRoot)) ?? readVersionManifest(join29(pluginRoot, "..", "..", "..", "package.json")) ?? readVersionManifest(join29(pluginRoot, ".codex-plugin", "plugin.json"));
13328
+ return readVersionManifest(resolveInstalledVersionPath(env3, pluginRoot)) ?? readVersionManifest(join31(pluginRoot, "..", "..", "..", "package.json")) ?? readVersionManifest(join31(pluginRoot, ".codex-plugin", "plugin.json"));
13153
13329
  }
13154
13330
  function resolveLatestVersion(env3) {
13155
13331
  if (env3.LAZYCODEX_LATEST_VERSION?.trim())
@@ -13163,6 +13339,57 @@ function resolveLatestVersion(env3) {
13163
13339
  const version2 = result.stdout.trim();
13164
13340
  return version2.length > 0 ? version2 : undefined;
13165
13341
  }
13342
+ async function handleBunGlobalTrust(input) {
13343
+ const packageNames = resolveKnownBunGlobalUntrustedPackages(input.env);
13344
+ if (packageNames.length === 0)
13345
+ return;
13346
+ const trustArgs = [...BUN_GLOBAL_TRUST_ARGS, ...packageNames];
13347
+ const trustCommand = [BUN_UPDATE_COMMAND, ...trustArgs].join(" ");
13348
+ if (!input.isInteractive) {
13349
+ input.log(`Bun blocked LazyCodex-related postinstall scripts. Run this command to trust them:
13350
+ ${trustCommand}`);
13351
+ return;
13352
+ }
13353
+ if (await confirmBunGlobalTrust(packageNames)) {
13354
+ await input.commandRunner(BUN_UPDATE_COMMAND, trustArgs, { cwd: process.cwd(), env: input.env });
13355
+ return;
13356
+ }
13357
+ input.log(`Skipped Bun postinstall trust. To run it later:
13358
+ ${trustCommand}`);
13359
+ }
13360
+ function resolveKnownBunGlobalUntrustedPackages(env3) {
13361
+ const result = spawnSync2(BUN_UPDATE_COMMAND, BUN_GLOBAL_UNTRUSTED_ARGS, {
13362
+ encoding: "utf8",
13363
+ env: env3,
13364
+ stdio: ["ignore", "pipe", "ignore"]
13365
+ });
13366
+ if (result.status !== 0)
13367
+ return [];
13368
+ const names = [];
13369
+ for (const match of result.stdout.matchAll(/^\.\/node_modules\/((?:@[^/\s]+\/)?[^\s]+)\s+@/gm)) {
13370
+ const packageName = match[1];
13371
+ if (packageName !== undefined && isKnownLazyCodexBunTrustPackage(packageName) && !names.includes(packageName)) {
13372
+ names.push(packageName);
13373
+ }
13374
+ }
13375
+ return names;
13376
+ }
13377
+ async function confirmBunGlobalTrust(packageNames) {
13378
+ const prompt = `Trust Bun postinstall scripts for ${packageNames.join(", ")}? [y/N] `;
13379
+ const readline = createInterface2({ input: process.stdin, output: process.stdout });
13380
+ try {
13381
+ const answer = (await readline.question(prompt)).trim().toLowerCase();
13382
+ return answer === "y" || answer === "yes";
13383
+ } finally {
13384
+ readline.close();
13385
+ }
13386
+ }
13387
+ function isKnownLazyCodexBunTrustPackage(packageName) {
13388
+ return KNOWN_LAZYCODEX_BUN_TRUST_PACKAGES.has(packageName) || KNOWN_LAZYCODEX_BUN_TRUST_PREFIXES.some((prefix) => packageName.startsWith(prefix));
13389
+ }
13390
+ function isBunGlobalEntrypoint(invokedPath, env3) {
13391
+ return isBunGlobalEntrypointPath(invokedPath, env3);
13392
+ }
13166
13393
  function defaultRunCommandForManualUpdate(command, args, options) {
13167
13394
  return new Promise((resolve11, reject) => {
13168
13395
  const child = spawn4(command, args, {
@@ -13214,7 +13441,7 @@ function compareVersions(left, right) {
13214
13441
  function resolveInstalledVersionPath(env3, pluginRoot) {
13215
13442
  if (env3.LAZYCODEX_INSTALLED_VERSION_FILE?.trim())
13216
13443
  return env3.LAZYCODEX_INSTALLED_VERSION_FILE.trim();
13217
- return join29(pluginRoot, INSTALLED_VERSION_FILE);
13444
+ return join31(pluginRoot, INSTALLED_VERSION_FILE);
13218
13445
  }
13219
13446
  function readVersionManifest(path2) {
13220
13447
  try {
@@ -13230,15 +13457,15 @@ function readVersionManifest(path2) {
13230
13457
  }
13231
13458
  }
13232
13459
  // packages/omo-codex/src/install/codex-git-bash-mcp-env.ts
13233
- import { readFile as readFile17, writeFile as writeFile10 } from "node:fs/promises";
13234
- import { join as join30 } from "node:path";
13460
+ import { readFile as readFile18, writeFile as writeFile10 } from "node:fs/promises";
13461
+ import { join as join32 } from "node:path";
13235
13462
  var GIT_BASH_ENV_KEY2 = "OMO_CODEX_GIT_BASH_PATH";
13236
13463
  var CODEGRAPH_RELATIVE_ARGS2 = new Set(["components/codegraph/dist/serve.js", "./components/codegraph/dist/serve.js"]);
13237
13464
  async function stampGitBashMcpEnv(input) {
13238
- const manifestPath = join30(input.pluginRoot, ".mcp.json");
13465
+ const manifestPath = join32(input.pluginRoot, ".mcp.json");
13239
13466
  if (!await fileExistsStrict(manifestPath))
13240
13467
  return false;
13241
- const parsed = JSON.parse(await readFile17(manifestPath, "utf8"));
13468
+ const parsed = JSON.parse(await readFile18(manifestPath, "utf8"));
13242
13469
  if (!isPlainRecord(parsed) || !isPlainRecord(parsed["mcpServers"]))
13243
13470
  return false;
13244
13471
  let changed = stampCodegraphMcpPath(parsed["mcpServers"], input.pluginRoot);
@@ -13268,57 +13495,9 @@ function stampCodegraphMcpPath(mcpServers, pluginRoot) {
13268
13495
  const entrypoint = args[0];
13269
13496
  if (typeof entrypoint !== "string" || !CODEGRAPH_RELATIVE_ARGS2.has(entrypoint))
13270
13497
  return false;
13271
- codegraphServer["args"] = [join30(pluginRoot, "components", "codegraph", "dist", "serve.js"), ...args.slice(1)];
13498
+ codegraphServer["args"] = [join32(pluginRoot, "components", "codegraph", "dist", "serve.js"), ...args.slice(1)];
13272
13499
  return true;
13273
13500
  }
13274
- // packages/omo-codex/src/install/codex-hook-targets.ts
13275
- import { readFile as readFile18 } from "node:fs/promises";
13276
- import { join as join31, sep as sep8 } from "node:path";
13277
- var PLUGIN_ROOT_TARGET_PATTERN = /\$\{PLUGIN_ROOT\}\/([^"']+)/g;
13278
- async function findMissingHookCommandTargets(pluginRoot) {
13279
- const manifestPath = join31(pluginRoot, "hooks", "hooks.json");
13280
- if (!await fileExistsStrict(manifestPath))
13281
- return [];
13282
- const commands = [];
13283
- const parsed = JSON.parse(await readFile18(manifestPath, "utf8"));
13284
- collectCommands(parsed, commands);
13285
- const missing = [];
13286
- const seen = new Set;
13287
- for (const command of commands) {
13288
- for (const match of command.matchAll(PLUGIN_ROOT_TARGET_PATTERN)) {
13289
- const targetSuffix = match[1];
13290
- if (targetSuffix === undefined)
13291
- continue;
13292
- const target = join31(pluginRoot, ...targetSuffix.split("/"));
13293
- if (seen.has(target))
13294
- continue;
13295
- seen.add(target);
13296
- if (!await fileExistsStrict(target))
13297
- missing.push(target);
13298
- }
13299
- }
13300
- return missing;
13301
- }
13302
- async function assertHookCommandTargets(pluginRoot) {
13303
- const missing = await findMissingHookCommandTargets(pluginRoot);
13304
- if (missing.length === 0)
13305
- return;
13306
- const relativeMissing = missing.map((path2) => path2.split(`${pluginRoot}${sep8}`).join("").split(sep8).join("/"));
13307
- throw new Error(`Plugin payload is missing ${missing.length} hook command target(s) referenced by hooks.json: ${relativeMissing.join(", ")}. ` + "The previous plugin cache was left untouched; this payload was not activated.");
13308
- }
13309
- function collectCommands(value, commands) {
13310
- if (Array.isArray(value)) {
13311
- for (const entry of value)
13312
- collectCommands(entry, commands);
13313
- return;
13314
- }
13315
- if (!isPlainRecord(value))
13316
- return;
13317
- if (value["type"] === "command" && typeof value["command"] === "string")
13318
- commands.push(value["command"]);
13319
- for (const entry of Object.values(value))
13320
- collectCommands(entry, commands);
13321
- }
13322
13501
 
13323
13502
  // packages/omo-codex/src/install/install-local-cli.ts
13324
13503
  async function installMarketplaceLocally(options = {}) {
@@ -13337,7 +13516,7 @@ async function runLazyCodexInstallLocalCli(input) {
13337
13516
  return 0;
13338
13517
  }
13339
13518
  if (parsed.kind === "version") {
13340
- const packageJson = JSON.parse(await readFile19(join32(input.defaultRepoRoot, "package.json"), "utf8"));
13519
+ const packageJson = JSON.parse(await readFile19(join33(input.defaultRepoRoot, "package.json"), "utf8"));
13341
13520
  const version2 = typeof packageJson.version === "string" ? packageJson.version : "unknown";
13342
13521
  input.log(`lazycodex-ai ${version2}`);
13343
13522
  return 0;
@@ -13360,7 +13539,7 @@ async function runLazyCodexInstallLocalCli(input) {
13360
13539
  input.log(`Installed ${result2.installed.length} plugin(s) from ${result2.marketplaceName}.`);
13361
13540
  return 0;
13362
13541
  }
13363
- return runLazyCodexManualUpdate({ env: input.env, dryRun: parsed.dryRun, log: input.log });
13542
+ return runLazyCodexManualUpdate({ env: input.env, dryRun: parsed.dryRun, log: input.log, invokedPath: input.invokedPath });
13364
13543
  }
13365
13544
  const repoRoot = parsed.repoRoot ? resolve11(parsed.repoRoot) : input.defaultRepoRoot;
13366
13545
  const result = await installMarketplaceLocally({