lazycodex-ai 5.1.61 → 5.1.63

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 (300) hide show
  1. package/dist/cli/index.js +1722 -281
  2. package/dist/cli/service-auth/closed-device-login.fixture.d.ts +1 -0
  3. package/dist/cli/service-auth/credential-lock.d.ts +8 -2
  4. package/dist/cli/service-auth/index.d.ts +2 -1
  5. package/dist/cli/service-auth/keychain-helper/access.d.ts +27 -0
  6. package/dist/cli/service-auth/keychain-helper/approval-cache.d.ts +51 -0
  7. package/dist/cli/service-auth/keychain-helper/client.d.ts +68 -0
  8. package/dist/cli/service-auth/keychain-helper/creator-handoff.d.ts +31 -0
  9. package/dist/cli/service-auth/keychain-helper/darwin-backend.d.ts +75 -0
  10. package/dist/cli/service-auth/keychain-helper/darwin-read.d.ts +46 -0
  11. package/dist/cli/service-auth/keychain-helper/darwin-store.d.ts +28 -0
  12. package/dist/cli/service-auth/keychain-helper/fake-keychain.test-support.d.ts +85 -0
  13. package/dist/cli/service-auth/keychain-helper/location.d.ts +28 -0
  14. package/dist/cli/service-auth/keychain-helper/migration.d.ts +20 -0
  15. package/dist/cli/service-auth/keychain-helper/owner-marker.d.ts +7 -0
  16. package/dist/cli/service-auth/keychain-helper/pin.d.ts +20 -0
  17. package/dist/cli/service-auth/keychain-helper/process-copy.test-support.d.ts +3 -0
  18. package/dist/cli/service-auth/keychain-helper/process-state.d.ts +19 -0
  19. package/dist/cli/service-auth/keychain-helper/prompt-lock.d.ts +14 -0
  20. package/dist/cli/service-auth/keychain-helper/recovery.d.ts +34 -0
  21. package/dist/cli/service-auth/keychain-helper/runtime-capabilities.d.ts +13 -0
  22. package/dist/cli/service-auth/keychain-helper/secrets-gate.d.ts +4 -0
  23. package/dist/cli/service-auth/keychain-helper/signature.d.ts +17 -0
  24. package/dist/cli/service-auth/keychain-helper/store-binding.d.ts +46 -0
  25. package/dist/cli/service-auth/keystore.d.ts +18 -3
  26. package/dist/cli/service-auth/session.d.ts +29 -2
  27. package/dist/cli/service-auth/sync-pin-retire.d.ts +7 -0
  28. package/dist/cli-node/index.js +1722 -281
  29. package/package.json +1 -1
  30. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  31. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  32. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  33. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  34. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  35. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  36. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  37. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  38. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  39. package/packages/omo-codex/plugin/components/lcx/skills/lcx-doctor/SKILL.md +1 -1
  40. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  41. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  42. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  43. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  44. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  45. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  46. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  47. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  48. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  49. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +2 -0
  50. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  51. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  52. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +1 -1
  53. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +2 -2
  54. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
  55. package/packages/omo-codex/plugin/components/ulw-execute-continuation/directive.md +1 -1
  56. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  57. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  58. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +2 -0
  59. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  60. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  61. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +1 -1
  62. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +1 -1
  63. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +10 -10
  64. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  65. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  66. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  67. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  68. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  69. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  70. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  71. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  72. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  73. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  74. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  75. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  76. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  77. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  78. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  79. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  80. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  81. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  82. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  83. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  84. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  85. package/packages/omo-codex/plugin/package-lock.json +12 -12
  86. package/packages/omo-codex/plugin/package.json +1 -1
  87. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +6 -3
  88. package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +2 -2
  89. package/packages/omo-codex/plugin/skills/ast-grep/README.md +4 -4
  90. package/packages/omo-codex/plugin/skills/ast-grep/SKILL.md +10 -8
  91. package/packages/omo-codex/plugin/skills/ast-grep/references/cli.md +4 -3
  92. package/packages/omo-codex/plugin/skills/ast-grep/references/patterns.md +5 -5
  93. package/packages/omo-codex/plugin/skills/ast-grep/references/pitfalls.md +3 -3
  94. package/packages/omo-codex/plugin/skills/ast-grep/references/recipes.md +6 -4
  95. package/packages/omo-codex/plugin/skills/ast-grep/references/yaml-rules.md +3 -3
  96. package/packages/omo-codex/plugin/skills/ast-grep/scripts/ast_grep_helper.py +3 -3
  97. package/packages/omo-codex/plugin/skills/browser/SKILL.md +2 -3
  98. package/packages/omo-codex/plugin/skills/browser/references/owned-engine/README.md +1 -1
  99. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
  100. package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +1 -1
  101. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +2 -1
  102. package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +8 -6
  103. package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +9 -5
  104. package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +3 -3
  105. package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +19 -4
  106. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +5 -5
  107. package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +2 -2
  108. package/packages/omo-codex/plugin/skills/debugging/references/methodology/06-fix.md +2 -0
  109. package/packages/omo-codex/plugin/skills/debugging/references/methodology/09-cleanup.md +2 -2
  110. package/packages/omo-codex/plugin/skills/debugging/references/methodology/partial-runtime-evidence.md +1 -1
  111. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/bundled-js-binary.md +1 -1
  112. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +1 -1
  113. package/packages/omo-codex/plugin/skills/debugging/references/tools/browser-qa.md +1 -2
  114. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +4 -4
  115. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +2 -2
  116. package/packages/omo-codex/plugin/skills/frontend/references/design/component-catalogs.md +1 -1
  117. package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +2 -2
  118. package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +1 -1
  119. package/packages/omo-codex/plugin/skills/frontend/references/design/react-dev-tooling-skill.md +1 -1
  120. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +5 -5
  121. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +2 -2
  122. package/packages/omo-codex/plugin/skills/frontend/references/perfection/README.md +1 -2
  123. package/packages/omo-codex/plugin/skills/frontend/references/perfection/react-perf-tooling.md +27 -8
  124. package/packages/omo-codex/plugin/skills/frontend/scripts/perfection/lighthouse-audit.py +0 -1
  125. package/packages/omo-codex/plugin/skills/git-master/SKILL.md +12 -2
  126. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +1 -1
  127. package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +1 -1
  128. package/packages/omo-codex/plugin/skills/lsp-setup/SKILL.md +24 -15
  129. package/packages/omo-codex/plugin/skills/lsp-setup/references/bash/README.md +3 -3
  130. package/packages/omo-codex/plugin/skills/lsp-setup/references/c-cpp/README.md +2 -2
  131. package/packages/omo-codex/plugin/skills/lsp-setup/references/csharp/README.md +2 -2
  132. package/packages/omo-codex/plugin/skills/lsp-setup/references/dart/README.md +2 -2
  133. package/packages/omo-codex/plugin/skills/lsp-setup/references/elixir/README.md +2 -2
  134. package/packages/omo-codex/plugin/skills/lsp-setup/references/go/README.md +2 -2
  135. package/packages/omo-codex/plugin/skills/lsp-setup/references/haskell/README.md +2 -2
  136. package/packages/omo-codex/plugin/skills/lsp-setup/references/java/README.md +3 -3
  137. package/packages/omo-codex/plugin/skills/lsp-setup/references/julia/README.md +3 -3
  138. package/packages/omo-codex/plugin/skills/lsp-setup/references/kotlin/README.md +4 -4
  139. package/packages/omo-codex/plugin/skills/lsp-setup/references/lua/README.md +2 -2
  140. package/packages/omo-codex/plugin/skills/lsp-setup/references/php/README.md +3 -3
  141. package/packages/omo-codex/plugin/skills/lsp-setup/references/python/README.md +13 -12
  142. package/packages/omo-codex/plugin/skills/lsp-setup/references/ruby/README.md +2 -2
  143. package/packages/omo-codex/plugin/skills/lsp-setup/references/rust/README.md +2 -2
  144. package/packages/omo-codex/plugin/skills/lsp-setup/references/swift/README.md +4 -4
  145. package/packages/omo-codex/plugin/skills/lsp-setup/references/terraform/README.md +2 -2
  146. package/packages/omo-codex/plugin/skills/lsp-setup/references/typescript/README.md +3 -3
  147. package/packages/omo-codex/plugin/skills/lsp-setup/references/yaml/README.md +2 -2
  148. package/packages/omo-codex/plugin/skills/lsp-setup/references/zig/README.md +2 -2
  149. package/packages/omo-codex/plugin/skills/lsp-setup/scripts/detect-lsp.ts +1 -1
  150. package/packages/omo-codex/plugin/skills/lsp-setup/scripts/lsp-server-table.ts +3 -2
  151. package/packages/omo-codex/plugin/skills/programming/SKILL.md +5 -5
  152. package/packages/omo-codex/plugin/skills/programming/references/code-smells.md +2 -2
  153. package/packages/omo-codex/plugin/skills/programming/references/go/README.md +3 -3
  154. package/packages/omo-codex/plugin/skills/programming/references/python/README.md +8 -8
  155. package/packages/omo-codex/plugin/skills/programming/references/python/data-processing.md +9 -9
  156. package/packages/omo-codex/plugin/skills/programming/references/python/libraries.md +3 -3
  157. package/packages/omo-codex/plugin/skills/programming/references/python/one-liners.md +1 -1
  158. package/packages/omo-codex/plugin/skills/programming/references/python/pyproject-strict.md +1 -1
  159. package/packages/omo-codex/plugin/skills/programming/references/rust/libraries.md +2 -2
  160. package/packages/omo-codex/plugin/skills/programming/references/rust-ub/README.md +3 -3
  161. package/packages/omo-codex/plugin/skills/programming/references/typescript/README.md +5 -5
  162. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/new-project.ts +1 -1
  163. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +36 -36
  164. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +6 -6
  165. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +2 -2
  166. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +11 -8
  167. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +4 -4
  168. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/README.md +2 -2
  169. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/career.md +1 -1
  170. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
  171. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/web.md +4 -4
  172. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +2 -1
  173. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +17 -18
  174. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/fallback.md +10 -6
  175. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/jina.md +12 -12
  176. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/naver.md +3 -3
  177. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/playwright.md +1 -1
  178. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/rss.md +1 -1
  179. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/tls-impersonate.md +12 -7
  180. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +2 -0
  181. package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +9 -6
  182. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +1 -1
  183. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +1 -1
  184. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +10 -10
  185. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +1 -1
  186. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +2 -2
  187. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +4 -4
  188. package/packages/omo-codex/plugin/skills/ulw-research/references/deliverable-phase.md +5 -5
  189. package/packages/omo-codex/plugin/skills/ulw-research/references/report-visualization.md +2 -2
  190. package/packages/omo-codex/plugin/skills/ulw-research/references/research-collection.md +2 -2
  191. package/packages/omo-codex/plugin/skills/ulw-research/references/unit-rules.md +2 -2
  192. package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +1 -1
  193. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +5 -5
  194. package/packages/omo-codex/plugin/skills/visual-qa/references/browser-setup.md +4 -2
  195. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +2 -0
  196. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +7 -3
  197. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
  198. package/packages/prompts-core/prompts/ultrawork/codex.md +2 -0
  199. package/packages/shared-skills/skills/ast-grep/AGENTS.md +2 -2
  200. package/packages/shared-skills/skills/ast-grep/README.md +4 -4
  201. package/packages/shared-skills/skills/ast-grep/SKILL.md +10 -8
  202. package/packages/shared-skills/skills/ast-grep/references/cli.md +4 -3
  203. package/packages/shared-skills/skills/ast-grep/references/patterns.md +5 -5
  204. package/packages/shared-skills/skills/ast-grep/references/pitfalls.md +3 -3
  205. package/packages/shared-skills/skills/ast-grep/references/recipes.md +6 -4
  206. package/packages/shared-skills/skills/ast-grep/references/yaml-rules.md +3 -3
  207. package/packages/shared-skills/skills/ast-grep/scripts/ast_grep_helper.py +3 -3
  208. package/packages/shared-skills/skills/browser/SKILL.md +2 -3
  209. package/packages/shared-skills/skills/browser/references/owned-engine/README.md +1 -1
  210. package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
  211. package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +1 -1
  212. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +2 -1
  213. package/packages/shared-skills/skills/data-scientist/SKILL.md +8 -6
  214. package/packages/shared-skills/skills/data-scientist/references/placement.md +9 -5
  215. package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +3 -3
  216. package/packages/shared-skills/skills/data-scientist/references/visualization.md +19 -4
  217. package/packages/shared-skills/skills/debugging/SKILL.md +5 -5
  218. package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +2 -2
  219. package/packages/shared-skills/skills/debugging/references/methodology/06-fix.md +2 -0
  220. package/packages/shared-skills/skills/debugging/references/methodology/09-cleanup.md +2 -2
  221. package/packages/shared-skills/skills/debugging/references/methodology/partial-runtime-evidence.md +1 -1
  222. package/packages/shared-skills/skills/debugging/references/runtimes/bundled-js-binary.md +1 -1
  223. package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +1 -1
  224. package/packages/shared-skills/skills/debugging/references/tools/browser-qa.md +1 -2
  225. package/packages/shared-skills/skills/frontend/SKILL.md +4 -4
  226. package/packages/shared-skills/skills/frontend/references/design/README.md +2 -2
  227. package/packages/shared-skills/skills/frontend/references/design/component-catalogs.md +1 -1
  228. package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +2 -2
  229. package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +1 -1
  230. package/packages/shared-skills/skills/frontend/references/design/react-dev-tooling-skill.md +1 -1
  231. package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +5 -5
  232. package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +2 -2
  233. package/packages/shared-skills/skills/frontend/references/perfection/README.md +1 -2
  234. package/packages/shared-skills/skills/frontend/references/perfection/react-perf-tooling.md +27 -8
  235. package/packages/shared-skills/skills/frontend/scripts/perfection/lighthouse-audit.py +0 -1
  236. package/packages/shared-skills/skills/git-master/SKILL.md +12 -2
  237. package/packages/shared-skills/skills/init-deep/SKILL.md +1 -1
  238. package/packages/shared-skills/skills/lsp-setup/SKILL.md +24 -15
  239. package/packages/shared-skills/skills/lsp-setup/references/bash/README.md +3 -3
  240. package/packages/shared-skills/skills/lsp-setup/references/c-cpp/README.md +2 -2
  241. package/packages/shared-skills/skills/lsp-setup/references/csharp/README.md +2 -2
  242. package/packages/shared-skills/skills/lsp-setup/references/dart/README.md +2 -2
  243. package/packages/shared-skills/skills/lsp-setup/references/elixir/README.md +2 -2
  244. package/packages/shared-skills/skills/lsp-setup/references/go/README.md +2 -2
  245. package/packages/shared-skills/skills/lsp-setup/references/haskell/README.md +2 -2
  246. package/packages/shared-skills/skills/lsp-setup/references/java/README.md +3 -3
  247. package/packages/shared-skills/skills/lsp-setup/references/julia/README.md +3 -3
  248. package/packages/shared-skills/skills/lsp-setup/references/kotlin/README.md +4 -4
  249. package/packages/shared-skills/skills/lsp-setup/references/lua/README.md +2 -2
  250. package/packages/shared-skills/skills/lsp-setup/references/php/README.md +3 -3
  251. package/packages/shared-skills/skills/lsp-setup/references/python/README.md +13 -12
  252. package/packages/shared-skills/skills/lsp-setup/references/ruby/README.md +2 -2
  253. package/packages/shared-skills/skills/lsp-setup/references/rust/README.md +2 -2
  254. package/packages/shared-skills/skills/lsp-setup/references/swift/README.md +4 -4
  255. package/packages/shared-skills/skills/lsp-setup/references/terraform/README.md +2 -2
  256. package/packages/shared-skills/skills/lsp-setup/references/typescript/README.md +3 -3
  257. package/packages/shared-skills/skills/lsp-setup/references/yaml/README.md +2 -2
  258. package/packages/shared-skills/skills/lsp-setup/references/zig/README.md +2 -2
  259. package/packages/shared-skills/skills/lsp-setup/scripts/detect-lsp.ts +1 -1
  260. package/packages/shared-skills/skills/lsp-setup/scripts/lsp-server-table.ts +3 -2
  261. package/packages/shared-skills/skills/programming/SKILL.md +5 -5
  262. package/packages/shared-skills/skills/programming/references/code-smells.md +2 -2
  263. package/packages/shared-skills/skills/programming/references/go/README.md +3 -3
  264. package/packages/shared-skills/skills/programming/references/python/README.md +8 -8
  265. package/packages/shared-skills/skills/programming/references/python/data-processing.md +9 -9
  266. package/packages/shared-skills/skills/programming/references/python/libraries.md +3 -3
  267. package/packages/shared-skills/skills/programming/references/python/one-liners.md +1 -1
  268. package/packages/shared-skills/skills/programming/references/python/pyproject-strict.md +1 -1
  269. package/packages/shared-skills/skills/programming/references/rust/libraries.md +2 -2
  270. package/packages/shared-skills/skills/programming/references/rust-ub/README.md +3 -3
  271. package/packages/shared-skills/skills/programming/references/typescript/README.md +5 -5
  272. package/packages/shared-skills/skills/programming/scripts/typescript/new-project.ts +1 -1
  273. package/packages/shared-skills/skills/refactor/SKILL.md +36 -36
  274. package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +6 -6
  275. package/packages/shared-skills/skills/review-work/SKILL.md +2 -2
  276. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +11 -8
  277. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +4 -4
  278. package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/README.md +2 -2
  279. package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/career.md +1 -1
  280. package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
  281. package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/web.md +4 -4
  282. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +2 -1
  283. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +17 -18
  284. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/fallback.md +10 -6
  285. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/jina.md +12 -12
  286. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/naver.md +3 -3
  287. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/playwright.md +1 -1
  288. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/rss.md +1 -1
  289. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/tls-impersonate.md +12 -7
  290. package/packages/shared-skills/skills/ulw-execute/SKILL.md +9 -6
  291. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +1 -1
  292. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +2 -2
  293. package/packages/shared-skills/skills/ulw-research/SKILL.md +5 -5
  294. package/packages/shared-skills/skills/ulw-research/references/deliverable-phase.md +5 -5
  295. package/packages/shared-skills/skills/ulw-research/references/report-visualization.md +2 -2
  296. package/packages/shared-skills/skills/ulw-research/references/research-collection.md +2 -2
  297. package/packages/shared-skills/skills/ulw-research/references/unit-rules.md +2 -2
  298. package/packages/shared-skills/skills/visual-qa/AGENTS.md +1 -1
  299. package/packages/shared-skills/skills/visual-qa/SKILL.md +5 -5
  300. package/packages/shared-skills/skills/visual-qa/references/browser-setup.md +4 -2
@@ -2133,7 +2133,7 @@ var package_default;
2133
2133
  var init_package = __esm(() => {
2134
2134
  package_default = {
2135
2135
  name: "oh-my-opencode",
2136
- version: "5.1.61",
2136
+ version: "5.1.63",
2137
2137
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
2138
2138
  main: "./dist/index.js",
2139
2139
  types: "dist/index.d.ts",
@@ -2320,7 +2320,7 @@ var init_package = __esm(() => {
2320
2320
  },
2321
2321
  devDependencies: {
2322
2322
  "@clack/prompts": "^1.8.1",
2323
- "@code-yeongyu/senpi": "2026.11.3-3",
2323
+ "@code-yeongyu/senpi": "2026.11.5-1",
2324
2324
  "@modelcontextprotocol/sdk": "^1.30.0",
2325
2325
  "@oh-my-opencode/agents-md-core": "workspace:*",
2326
2326
  "@oh-my-opencode/ast-grep-mcp": "workspace:*",
@@ -2385,18 +2385,18 @@ var init_package = __esm(() => {
2385
2385
  typescript: "^7.0.2"
2386
2386
  },
2387
2387
  optionalDependencies: {
2388
- "oh-my-opencode-darwin-arm64": "5.1.61",
2389
- "oh-my-opencode-darwin-x64": "5.1.61",
2390
- "oh-my-opencode-darwin-x64-baseline": "5.1.61",
2391
- "oh-my-opencode-linux-arm64": "5.1.61",
2392
- "oh-my-opencode-linux-arm64-musl": "5.1.61",
2393
- "oh-my-opencode-linux-x64": "5.1.61",
2394
- "oh-my-opencode-linux-x64-baseline": "5.1.61",
2395
- "oh-my-opencode-linux-x64-musl": "5.1.61",
2396
- "oh-my-opencode-linux-x64-musl-baseline": "5.1.61",
2397
- "oh-my-opencode-windows-arm64": "5.1.61",
2398
- "oh-my-opencode-windows-x64": "5.1.61",
2399
- "oh-my-opencode-windows-x64-baseline": "5.1.61"
2388
+ "oh-my-opencode-darwin-arm64": "5.1.63",
2389
+ "oh-my-opencode-darwin-x64": "5.1.63",
2390
+ "oh-my-opencode-darwin-x64-baseline": "5.1.63",
2391
+ "oh-my-opencode-linux-arm64": "5.1.63",
2392
+ "oh-my-opencode-linux-arm64-musl": "5.1.63",
2393
+ "oh-my-opencode-linux-x64": "5.1.63",
2394
+ "oh-my-opencode-linux-x64-baseline": "5.1.63",
2395
+ "oh-my-opencode-linux-x64-musl": "5.1.63",
2396
+ "oh-my-opencode-linux-x64-musl-baseline": "5.1.63",
2397
+ "oh-my-opencode-windows-arm64": "5.1.63",
2398
+ "oh-my-opencode-windows-x64": "5.1.63",
2399
+ "oh-my-opencode-windows-x64-baseline": "5.1.63"
2400
2400
  },
2401
2401
  overrides: {
2402
2402
  hono: "^4.13.8",
@@ -7340,7 +7340,34 @@ var init_which = __esm(() => {
7340
7340
  });
7341
7341
 
7342
7342
  // packages/utils/src/runtime/file.ts
7343
- var init_file = () => {};
7343
+ import { access, readFile, unlink, writeFile } from "node:fs/promises";
7344
+ function createNodeFile(path) {
7345
+ return {
7346
+ text() {
7347
+ return readFile(path, "utf8");
7348
+ },
7349
+ async arrayBuffer() {
7350
+ const buffer = await readFile(path);
7351
+ return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
7352
+ },
7353
+ exists() {
7354
+ return access(path).then(() => true, () => false);
7355
+ },
7356
+ delete() {
7357
+ return unlink(path);
7358
+ }
7359
+ };
7360
+ }
7361
+ function bunFile(path) {
7362
+ const bun = runtime3.Bun;
7363
+ if (bun)
7364
+ return bun.file(path);
7365
+ return createNodeFile(path);
7366
+ }
7367
+ var runtime3;
7368
+ var init_file = __esm(() => {
7369
+ runtime3 = globalThis;
7370
+ });
7344
7371
 
7345
7372
  // packages/utils/src/runtime/git-bash.ts
7346
7373
  import { execFileSync } from "node:child_process";
@@ -12284,7 +12311,9 @@ var init_zip_extractor = __esm(() => {
12284
12311
  });
12285
12312
 
12286
12313
  // packages/omo-opencode/src/shared/bun-file-shim.ts
12287
- var init_bun_file_shim = () => {};
12314
+ var init_bun_file_shim = __esm(() => {
12315
+ init_runtime();
12316
+ });
12288
12317
 
12289
12318
  // packages/omo-opencode/src/shared/binary-downloader.ts
12290
12319
  import { chmodSync, existsSync as existsSync9, mkdirSync as mkdirSync4, unlinkSync as unlinkSync3 } from "node:fs";
@@ -92789,7 +92818,7 @@ var package_default2;
92789
92818
  var init_package2 = __esm(() => {
92790
92819
  package_default2 = {
92791
92820
  name: "@oh-my-opencode/omo-codex",
92792
- version: "5.1.61",
92821
+ version: "5.1.63",
92793
92822
  type: "module",
92794
92823
  private: true,
92795
92824
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -93405,7 +93434,7 @@ var init_check_for_update = __esm(() => {
93405
93434
  });
93406
93435
 
93407
93436
  // packages/omo-opencode/src/hooks/auto-update-checker/checker/sync-package-json.ts
93408
- import * as crypto from "node:crypto";
93437
+ import * as crypto2 from "node:crypto";
93409
93438
  import * as fs8 from "node:fs";
93410
93439
  import * as path11 from "node:path";
93411
93440
  function safeUnlink(filePath) {
@@ -93429,7 +93458,7 @@ function getPackageNameFromIntent(pluginInfo) {
93429
93458
  return ACCEPTED_PACKAGE_NAMES2.find((packageName) => pluginInfo.entry === packageName || pluginInfo.entry.startsWith(`${packageName}@`)) ?? PACKAGE_NAME3;
93430
93459
  }
93431
93460
  function writeCachePackageJson(cachePackageJsonPath, pkgJson) {
93432
- const tmpPath = `${cachePackageJsonPath}.${crypto.randomUUID()}`;
93461
+ const tmpPath = `${cachePackageJsonPath}.${crypto2.randomUUID()}`;
93433
93462
  try {
93434
93463
  fs8.mkdirSync(path11.dirname(cachePackageJsonPath), { recursive: true });
93435
93464
  fs8.writeFileSync(tmpPath, JSON.stringify(pkgJson, null, 2));
@@ -94350,7 +94379,7 @@ import { existsSync as existsSync27 } from "node:fs";
94350
94379
  import { homedir as homedir7 } from "node:os";
94351
94380
 
94352
94381
  // packages/omo-codex/src/install/codex-cache-bins.ts
94353
- import { chmod, lstat as lstat4, mkdir, readFile as readFile3, readdir as readdir2, readlink as readlink3, rm as rm3, stat as stat2, symlink, writeFile } from "node:fs/promises";
94382
+ import { chmod, lstat as lstat4, mkdir, readFile as readFile4, readdir as readdir2, readlink as readlink3, rm as rm3, stat as stat2, symlink, writeFile as writeFile2 } from "node:fs/promises";
94354
94383
  import { basename as basename4, isAbsolute as isAbsolute2, join as join26, relative, resolve as resolve6, sep } from "node:path";
94355
94384
 
94356
94385
  // packages/omo-codex/src/install/codex-cache-command-shim.ts
@@ -94394,7 +94423,7 @@ function windowsCommandShim(targetPath) {
94394
94423
  }
94395
94424
 
94396
94425
  // packages/omo-codex/src/install/codex-cache-dangling-bins.ts
94397
- import { lstat as lstat2, readFile, readdir, readlink, rm, stat } from "node:fs/promises";
94426
+ import { lstat as lstat2, readFile as readFile2, readdir, readlink, rm, stat } from "node:fs/promises";
94398
94427
  import { dirname as dirname10, isAbsolute, join as join23, resolve as resolve5 } from "node:path";
94399
94428
 
94400
94429
  // packages/omo-codex/src/install/codex-cache-fs.ts
@@ -94456,7 +94485,7 @@ async function removeDanglingGeneratedCommandShim(linkPath) {
94456
94485
  const linkStat = await lstat2(linkPath);
94457
94486
  if (!linkStat.isFile())
94458
94487
  return;
94459
- const content = await readFile(linkPath, "utf8");
94488
+ const content = await readFile2(linkPath, "utf8");
94460
94489
  if (!content.includes(COMMAND_SHIM_MARKER))
94461
94490
  return;
94462
94491
  const target = extractCommandShimTarget(content);
@@ -94504,7 +94533,7 @@ function hasOmoCodexPluginPrefix(parts, endExclusive) {
94504
94533
  }
94505
94534
 
94506
94535
  // packages/omo-codex/src/install/codex-cache-legacy-bins.ts
94507
- import { lstat as lstat3, readFile as readFile2, readlink as readlink2, rm as rm2 } from "node:fs/promises";
94536
+ import { lstat as lstat3, readFile as readFile3, readlink as readlink2, rm as rm2 } from "node:fs/promises";
94508
94537
  import { join as join24 } from "node:path";
94509
94538
  var LEGACY_CODEX_COMPONENT_BINS = [
94510
94539
  { name: "omo", component: "ulw-loop" },
@@ -94539,7 +94568,7 @@ async function removeLegacyCodexComponentBin(linkPath, component, platform) {
94539
94568
  }
94540
94569
  if (!stat.isFile())
94541
94570
  return;
94542
- const content = await readFile2(linkPath, "utf8");
94571
+ const content = await readFile3(linkPath, "utf8");
94543
94572
  if (content.includes(COMMAND_SHIM_MARKER))
94544
94573
  await rm2(linkPath, { force: true });
94545
94574
  } catch (error) {
@@ -94776,7 +94805,7 @@ async function collectPackageBins(directory, root, links) {
94776
94805
  }
94777
94806
  }
94778
94807
  async function appendPackageBinLinks(packageJsonPath, packageRoot, root, links) {
94779
- const packageJson = JSON.parse(await readFile3(packageJsonPath, "utf8"));
94808
+ const packageJson = JSON.parse(await readFile4(packageJsonPath, "utf8"));
94780
94809
  if (!isPlainRecord4(packageJson))
94781
94810
  return;
94782
94811
  const packageName = packageJson.name;
@@ -94828,13 +94857,13 @@ async function replaceSymlink(linkPath, targetPath) {
94828
94857
  async function replaceCommandShim(linkPath, targetPath) {
94829
94858
  if (await existingNonShim(linkPath))
94830
94859
  throw new Error(`${linkPath} already exists and is not a command shim`);
94831
- await writeFile(linkPath, windowsCommandShim(targetPath));
94860
+ await writeFile2(linkPath, windowsCommandShim(targetPath));
94832
94861
  }
94833
94862
  async function replaceRuntimeWrapper(linkPath, content) {
94834
94863
  if (await existingNonRuntimeWrapper(linkPath))
94835
94864
  throw new Error(`${linkPath} already exists and is not a generated OMO runtime wrapper`);
94836
94865
  await rm3(linkPath, { force: true });
94837
- await writeFile(linkPath, content);
94866
+ await writeFile2(linkPath, content);
94838
94867
  }
94839
94868
  async function removeGeneratedRuntimeWrapper(path) {
94840
94869
  try {
@@ -94852,7 +94881,7 @@ async function removeGeneratedRuntimeWrapper(path) {
94852
94881
  }
94853
94882
  async function readGeneratedWrapperContent(path) {
94854
94883
  try {
94855
- return await readFile3(path, "utf8");
94884
+ return await readFile4(path, "utf8");
94856
94885
  } catch (error) {
94857
94886
  if (isNodeErrorWithCode(error) && (error.code === "ENOENT" || error.code === "EISDIR"))
94858
94887
  return "";
@@ -94866,7 +94895,7 @@ async function existingNonRuntimeWrapper(path) {
94866
94895
  return false;
94867
94896
  if (!stat.isFile())
94868
94897
  return true;
94869
- const content = await readFile3(path, "utf8");
94898
+ const content = await readFile4(path, "utf8");
94870
94899
  return !content.includes(RUNTIME_WRAPPER_MARKER);
94871
94900
  } catch (error) {
94872
94901
  if (isNodeErrorWithCode(error) && error.code === "ENOENT")
@@ -94879,7 +94908,7 @@ async function existingNonShim(path) {
94879
94908
  const stat = await lstat4(path);
94880
94909
  if (!stat.isFile())
94881
94910
  return true;
94882
- const content = await readFile3(path, "utf8");
94911
+ const content = await readFile4(path, "utf8");
94883
94912
  if (content.includes(COMMAND_SHIM_MARKER))
94884
94913
  return false;
94885
94914
  throw new Error(`${path} already exists and is not a generated command shim`);
@@ -94903,11 +94932,11 @@ async function existingNonSymlink(path) {
94903
94932
  }
94904
94933
  }
94905
94934
  // packages/omo-codex/src/install/codex-cache-install.ts
94906
- import { cp as cp3, mkdir as mkdir3, readFile as readFile8, readdir as readdir5, rename as rename2, rm as rm5 } from "node:fs/promises";
94935
+ import { cp as cp3, mkdir as mkdir3, readFile as readFile9, readdir as readdir5, rename as rename2, rm as rm5 } from "node:fs/promises";
94907
94936
  import { basename as basename5, dirname as dirname13, join as join33, sep as sep6 } from "node:path";
94908
94937
 
94909
94938
  // packages/omo-codex/src/install/codex-cache-bundled-mcps.ts
94910
- import { cp, mkdir as mkdir2, readFile as readFile4, stat as stat3 } from "node:fs/promises";
94939
+ import { cp, mkdir as mkdir2, readFile as readFile5, stat as stat3 } from "node:fs/promises";
94911
94940
  import { dirname as dirname11, join as join27, resolve as resolve7 } from "node:path";
94912
94941
  var BUNDLED_MCP_RUNTIMES = [
94913
94942
  {
@@ -94949,7 +94978,7 @@ async function copyBundledMcpRuntimeDist(pluginRoot, sourceRoot, runtime) {
94949
94978
  async function readSourceMcpArgs(path) {
94950
94979
  let parsed;
94951
94980
  try {
94952
- parsed = JSON.parse(await readFile4(path, "utf8"));
94981
+ parsed = JSON.parse(await readFile5(path, "utf8"));
94953
94982
  } catch (error) {
94954
94983
  if (error instanceof Error)
94955
94984
  return new Set;
@@ -94980,7 +95009,7 @@ async function isDirectory(path) {
94980
95009
 
94981
95010
  // packages/omo-codex/src/install/codex-cache-local-dependencies.ts
94982
95011
  import { realpathSync as realpathSync7 } from "node:fs";
94983
- import { readFile as readFile5, readdir as readdir3, writeFile as writeFile2 } from "node:fs/promises";
95012
+ import { readFile as readFile6, readdir as readdir3, writeFile as writeFile3 } from "node:fs/promises";
94984
95013
  import { dirname as dirname12, isAbsolute as isAbsolute4, join as join29, relative as relative3, resolve as resolve9, sep as sep2 } from "node:path";
94985
95014
 
94986
95015
  // packages/omo-codex/src/install/codex-cache-paths.ts
@@ -95046,7 +95075,7 @@ async function rewriteCachedPackageLocalFileDependencies(pluginRoot, sourceRoot)
95046
95075
  const packageLock = await readPackageLock(pluginRoot);
95047
95076
  let rewroteAnyPackageJson = false;
95048
95077
  for (const packageJsonPath of packageJsonPaths) {
95049
- const raw = await readFile5(packageJsonPath, "utf8");
95078
+ const raw = await readFile6(packageJsonPath, "utf8");
95050
95079
  const parsed = JSON.parse(raw);
95051
95080
  if (!isPlainRecord4(parsed))
95052
95081
  continue;
@@ -95081,20 +95110,20 @@ async function rewriteCachedPackageLocalFileDependencies(pluginRoot, sourceRoot)
95081
95110
  }
95082
95111
  }
95083
95112
  if (changed) {
95084
- await writeFile2(packageJsonPath, `${JSON.stringify(parsed, null, "\t")}
95113
+ await writeFile3(packageJsonPath, `${JSON.stringify(parsed, null, "\t")}
95085
95114
  `);
95086
95115
  rewroteAnyPackageJson = true;
95087
95116
  }
95088
95117
  }
95089
95118
  if (packageLock.changed)
95090
- await writeFile2(packageLock.path, `${JSON.stringify(packageLock.value, null, "\t")}
95119
+ await writeFile3(packageLock.path, `${JSON.stringify(packageLock.value, null, "\t")}
95091
95120
  `);
95092
95121
  return rewroteAnyPackageJson;
95093
95122
  }
95094
95123
  async function readPackageLock(pluginRoot) {
95095
95124
  const path = join29(pluginRoot, "package-lock.json");
95096
95125
  try {
95097
- const parsed = JSON.parse(await readFile5(path, "utf8"));
95126
+ const parsed = JSON.parse(await readFile6(path, "utf8"));
95098
95127
  return { path, value: isPlainRecord4(parsed) ? parsed : null, changed: false };
95099
95128
  } catch (error) {
95100
95129
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -95168,14 +95197,14 @@ async function collectPackageJsonPaths(directory, root, paths) {
95168
95197
  }
95169
95198
 
95170
95199
  // packages/omo-codex/src/install/codex-cache-mcp-manifest.ts
95171
- import { readFile as readFile6, writeFile as writeFile3 } from "node:fs/promises";
95200
+ import { readFile as readFile7, writeFile as writeFile4 } from "node:fs/promises";
95172
95201
  import { join as join30, sep as sep3 } from "node:path";
95173
95202
  var CONTEXT7_API_KEY_ENV = "CONTEXT7_API_KEY";
95174
95203
  async function rewriteCachedMcpManifest(pluginRoot, sourceRoot = pluginRoot) {
95175
95204
  const manifestPath = join30(pluginRoot, ".mcp.json");
95176
95205
  if (!await fileExistsStrict(manifestPath))
95177
95206
  return;
95178
- const raw = await readFile6(manifestPath, "utf8");
95207
+ const raw = await readFile7(manifestPath, "utf8");
95179
95208
  const parsed = JSON.parse(raw);
95180
95209
  if (!isPlainRecord4(parsed) || !isPlainRecord4(parsed.mcpServers))
95181
95210
  return;
@@ -95209,7 +95238,7 @@ async function rewriteCachedMcpManifest(pluginRoot, sourceRoot = pluginRoot) {
95209
95238
  }
95210
95239
  }
95211
95240
  if (changed)
95212
- await writeFile3(manifestPath, `${JSON.stringify(parsed, null, "\t")}
95241
+ await writeFile4(manifestPath, `${JSON.stringify(parsed, null, "\t")}
95213
95242
  `);
95214
95243
  }
95215
95244
  function sanitizeContext7Auth(server) {
@@ -95268,7 +95297,7 @@ async function rewriteCachedManifestRoot(pluginRoot, fromRoot, toRoot) {
95268
95297
  const manifestPath = join30(pluginRoot, ".mcp.json");
95269
95298
  if (!await fileExistsStrict(manifestPath))
95270
95299
  return;
95271
- const raw = await readFile6(manifestPath, "utf8");
95300
+ const raw = await readFile7(manifestPath, "utf8");
95272
95301
  const parsed = JSON.parse(raw);
95273
95302
  if (!isPlainRecord4(parsed) || !isPlainRecord4(parsed.mcpServers))
95274
95303
  return;
@@ -95295,7 +95324,7 @@ async function rewriteCachedManifestRoot(pluginRoot, fromRoot, toRoot) {
95295
95324
  }
95296
95325
  }
95297
95326
  if (changed)
95298
- await writeFile3(manifestPath, `${JSON.stringify(parsed, null, "\t")}
95327
+ await writeFile4(manifestPath, `${JSON.stringify(parsed, null, "\t")}
95299
95328
  `);
95300
95329
  }
95301
95330
 
@@ -95357,7 +95386,7 @@ async function unsupportedEntries(root, directory) {
95357
95386
  }
95358
95387
 
95359
95388
  // packages/omo-codex/src/install/codex-hook-targets.ts
95360
- import { readFile as readFile7 } from "node:fs/promises";
95389
+ import { readFile as readFile8 } from "node:fs/promises";
95361
95390
  import { join as join32, sep as sep5 } from "node:path";
95362
95391
  var PLUGIN_ROOT_TARGET_PATTERN = /\$\{PLUGIN_ROOT\}[\\/]+([^"']+)/g;
95363
95392
  async function findMissingHookCommandTargets(pluginRoot) {
@@ -95365,7 +95394,7 @@ async function findMissingHookCommandTargets(pluginRoot) {
95365
95394
  for (const manifestPath of await hookManifestPaths(pluginRoot)) {
95366
95395
  if (!await fileExistsStrict(manifestPath))
95367
95396
  continue;
95368
- const parsed = JSON.parse(await readFile7(manifestPath, "utf8"));
95397
+ const parsed = JSON.parse(await readFile8(manifestPath, "utf8"));
95369
95398
  collectCommands(parsed, commands);
95370
95399
  }
95371
95400
  const missing = [];
@@ -95389,7 +95418,7 @@ async function hookManifestPaths(pluginRoot) {
95389
95418
  const pluginManifestPath = join32(pluginRoot, ".codex-plugin", "plugin.json");
95390
95419
  if (!await fileExistsStrict(pluginManifestPath))
95391
95420
  return [join32(pluginRoot, "hooks", "hooks.json")];
95392
- const parsed = JSON.parse(await readFile7(pluginManifestPath, "utf8"));
95421
+ const parsed = JSON.parse(await readFile8(pluginManifestPath, "utf8"));
95393
95422
  if (!isPlainRecord4(parsed))
95394
95423
  return [];
95395
95424
  if (typeof parsed.hooks === "string" && parsed.hooks.trim() !== "") {
@@ -95476,7 +95505,7 @@ async function maybeRunNpmInstall(cwd, runCommand, env, args = ["install"]) {
95476
95505
  async function maybeRunNpmBuild(cwd, runCommand, env) {
95477
95506
  if (!await fileExistsStrict(join33(cwd, "package.json")))
95478
95507
  return;
95479
- const packageJson = JSON.parse(await readFile8(join33(cwd, "package.json"), "utf8"));
95508
+ const packageJson = JSON.parse(await readFile9(join33(cwd, "package.json"), "utf8"));
95480
95509
  if (!isPlainRecord4(packageJson))
95481
95510
  return;
95482
95511
  const scripts = packageJson.scripts;
@@ -95487,7 +95516,7 @@ async function maybeRunNpmBuild(cwd, runCommand, env) {
95487
95516
  async function maybeRunNpmSyncSkills(cwd, runCommand, env) {
95488
95517
  if (!await fileExistsStrict(join33(cwd, "package.json")))
95489
95518
  return;
95490
- const packageJson = JSON.parse(await readFile8(join33(cwd, "package.json"), "utf8"));
95519
+ const packageJson = JSON.parse(await readFile9(join33(cwd, "package.json"), "utf8"));
95491
95520
  if (!isPlainRecord4(packageJson))
95492
95521
  return;
95493
95522
  const scripts = packageJson.scripts;
@@ -95550,7 +95579,7 @@ var removedSparkshellPromptSurfaceFiles = new Set(["directive.md", "plugin.json"
95550
95579
  var removedSparkshellTextFilePattern = /\.(?:json|md|toml|ya?ml)$/i;
95551
95580
  async function assertNoRemovedSparkshellPromptReferences(pluginRoot) {
95552
95581
  for (const filePath of await listRemovedSparkshellPromptSurfaceFiles(pluginRoot, "")) {
95553
- const content = await readFile8(join33(pluginRoot, filePath), "utf8");
95582
+ const content = await readFile9(join33(pluginRoot, filePath), "utf8");
95554
95583
  if (!removedSparkshellReferencePattern.test(content))
95555
95584
  continue;
95556
95585
  throw new Error(`removed sparkshell reference found in Codex plugin prompt surface: ${filePath}`);
@@ -95699,7 +95728,7 @@ async function isBrokenCacheSymlink(path) {
95699
95728
  }
95700
95729
  }
95701
95730
  // packages/omo-codex/src/install/codex-cached-marketplace-manifest.ts
95702
- import { mkdir as mkdir4, rename as rename3, rm as rm7, stat as stat5, writeFile as writeFile4 } from "node:fs/promises";
95731
+ import { mkdir as mkdir4, rename as rename3, rm as rm7, stat as stat5, writeFile as writeFile5 } from "node:fs/promises";
95703
95732
  import { join as join35 } from "node:path";
95704
95733
  async function writeCachedMarketplaceManifest(input) {
95705
95734
  const marketplaceDir = join35(input.marketplaceRoot, ".agents", "plugins");
@@ -95712,7 +95741,7 @@ async function writeCachedMarketplaceManifest(input) {
95712
95741
  const manifestPath = join35(marketplaceDir, "marketplace.json");
95713
95742
  const tempPath = join35(marketplaceDir, `.marketplace.json.tmp-${process.pid}-${Date.now()}`);
95714
95743
  try {
95715
- await writeFile4(tempPath, `${JSON.stringify({
95744
+ await writeFile5(tempPath, `${JSON.stringify({
95716
95745
  name: input.marketplaceName,
95717
95746
  plugins: input.plugins.map((plugin) => ({
95718
95747
  name: plugin.name,
@@ -95738,7 +95767,7 @@ async function isDirectory2(path) {
95738
95767
 
95739
95768
  // packages/omo-codex/src/install/codex-package-layout.ts
95740
95769
  import { existsSync as existsSync24 } from "node:fs";
95741
- import { readFile as readFile9 } from "node:fs/promises";
95770
+ import { readFile as readFile10 } from "node:fs/promises";
95742
95771
  import { join as join36 } from "node:path";
95743
95772
  var PACKAGED_CODEX_INSTALLER_NAMES = new Set([
95744
95773
  "@code-yeongyu/lazycodex",
@@ -95754,14 +95783,14 @@ async function shouldBuildSourcePackages(repoRoot) {
95754
95783
  const packageJsonPath = join36(repoRoot, "package.json");
95755
95784
  if (!existsSync24(packageJsonPath))
95756
95785
  return true;
95757
- const packageJson = JSON.parse(await readFile9(packageJsonPath, "utf8"));
95786
+ const packageJson = JSON.parse(await readFile10(packageJsonPath, "utf8"));
95758
95787
  if (!isPlainRecord4(packageJson) || typeof packageJson.name !== "string")
95759
95788
  return true;
95760
95789
  return !PACKAGED_CODEX_INSTALLER_NAMES.has(packageJson.name);
95761
95790
  }
95762
95791
 
95763
95792
  // packages/omo-codex/src/install/codex-config-toml.ts
95764
- import { mkdir as mkdir5, readFile as readFile11 } from "node:fs/promises";
95793
+ import { mkdir as mkdir5, readFile as readFile12 } from "node:fs/promises";
95765
95794
  import { dirname as dirname16 } from "node:path";
95766
95795
 
95767
95796
  // packages/omo-codex/src/install/toml-section-editor.ts
@@ -96358,18 +96387,18 @@ function tomlKeySegment(value) {
96358
96387
  }
96359
96388
 
96360
96389
  // packages/omo-codex/src/install/codex-config-atomic-write.ts
96361
- import { lstat as lstat7, readlink as readlink4, realpath, rename as rename4, unlink, writeFile as writeFile5 } from "node:fs/promises";
96390
+ import { lstat as lstat7, readlink as readlink4, realpath, rename as rename4, unlink as unlink2, writeFile as writeFile6 } from "node:fs/promises";
96362
96391
  import { basename as basename6, dirname as dirname14, isAbsolute as isAbsolute5, join as join37, resolve as resolve10 } from "node:path";
96363
96392
  var RENAME_RETRY_DELAYS_MS = [10, 25, 50];
96364
96393
  var RETRIABLE_RENAME_CODES = new Set(["EPERM", "EBUSY"]);
96365
96394
  async function writeFileAtomic(targetPath, data) {
96366
96395
  const writeTarget = await resolveSymlinkTarget(targetPath);
96367
96396
  const temporaryPath = join37(dirname14(writeTarget), `.tmp-${basename6(writeTarget)}-${process.pid}-${Date.now()}`);
96368
- await writeFile5(temporaryPath, data);
96397
+ await writeFile6(temporaryPath, data);
96369
96398
  try {
96370
96399
  await renameWithRetry(temporaryPath, writeTarget);
96371
96400
  } catch (error) {
96372
- await unlink(temporaryPath).catch((unlinkError) => {
96401
+ await unlink2(temporaryPath).catch((unlinkError) => {
96373
96402
  if (unlinkError instanceof Error)
96374
96403
  return;
96375
96404
  return;
@@ -96864,7 +96893,7 @@ function isRootSetting(line, key) {
96864
96893
 
96865
96894
  // packages/omo-codex/src/install/codex-model-catalog.ts
96866
96895
  init_latest_models();
96867
- import { readFile as readFile10 } from "node:fs/promises";
96896
+ import { readFile as readFile11 } from "node:fs/promises";
96868
96897
  import { join as join38 } from "node:path";
96869
96898
  var FALLBACK_CODEX_MODEL_CATALOG = {
96870
96899
  current: {
@@ -96898,7 +96927,7 @@ var FALLBACK_CODEX_MODEL_CATALOG = {
96898
96927
  async function readCodexModelCatalog(codexPackageRoot) {
96899
96928
  const catalogPath = join38(codexPackageRoot, "plugin", "model-catalog.json");
96900
96929
  try {
96901
- const parsed = JSON.parse(await readFile10(catalogPath, "utf8"));
96930
+ const parsed = JSON.parse(await readFile11(catalogPath, "utf8"));
96902
96931
  return parseCodexModelCatalog(parsed) ?? FALLBACK_CODEX_MODEL_CATALOG;
96903
96932
  } catch (error) {
96904
96933
  if (error instanceof Error)
@@ -97123,7 +97152,7 @@ async function updateCodexConfig(input) {
97123
97152
  await mkdir5(dirname16(input.configPath), { recursive: true });
97124
97153
  let config;
97125
97154
  try {
97126
- config = await readFile11(input.configPath, "utf8");
97155
+ config = await readFile12(input.configPath, "utf8");
97127
97156
  } catch (error) {
97128
97157
  if (!isMissingFileError(error))
97129
97158
  throw error;
@@ -97171,7 +97200,7 @@ function isMissingFileError(error) {
97171
97200
 
97172
97201
  // packages/omo-codex/src/install/codex-hook-trust.ts
97173
97202
  import { createHash as createHash3 } from "node:crypto";
97174
- import { readFile as readFile12 } from "node:fs/promises";
97203
+ import { readFile as readFile13 } from "node:fs/promises";
97175
97204
  import { join as join40 } from "node:path";
97176
97205
  var EVENT_LABELS = new Map([
97177
97206
  ["PreToolUse", "pre_tool_use"],
@@ -97189,7 +97218,7 @@ async function trustedHookStatesForPlugin(input) {
97189
97218
  const manifestPath = join40(input.pluginRoot, ".codex-plugin", "plugin.json");
97190
97219
  if (!await exists(manifestPath))
97191
97220
  return [];
97192
- const manifest = JSON.parse(await readFile12(manifestPath, "utf8"));
97221
+ const manifest = JSON.parse(await readFile13(manifestPath, "utf8"));
97193
97222
  if (!isPlainRecord4(manifest))
97194
97223
  return [];
97195
97224
  const states = [];
@@ -97197,7 +97226,7 @@ async function trustedHookStatesForPlugin(input) {
97197
97226
  const hooksPath = join40(input.pluginRoot, hookPath);
97198
97227
  if (!await exists(hooksPath))
97199
97228
  continue;
97200
- const parsed = JSON.parse(await readFile12(hooksPath, "utf8"));
97229
+ const parsed = JSON.parse(await readFile13(hooksPath, "utf8"));
97201
97230
  if (!isPlainRecord4(parsed) || !isPlainRecord4(parsed.hooks))
97202
97231
  continue;
97203
97232
  states.push(...trustedHookStatesForHooksFile({
@@ -97280,7 +97309,7 @@ function stripDotSlash2(value) {
97280
97309
  }
97281
97310
  async function exists(path) {
97282
97311
  try {
97283
- await readFile12(path, "utf8");
97312
+ await readFile13(path, "utf8");
97284
97313
  return true;
97285
97314
  } catch (error) {
97286
97315
  if (error instanceof Error)
@@ -97380,7 +97409,7 @@ function recordAt2(value, key) {
97380
97409
  }
97381
97410
 
97382
97411
  // packages/omo-codex/src/install/codex-marketplace-snapshot.ts
97383
- import { cp as cp4, mkdir as mkdir6, rename as rename5, rm as rm8, writeFile as writeFile6 } from "node:fs/promises";
97412
+ import { cp as cp4, mkdir as mkdir6, rename as rename5, rm as rm8, writeFile as writeFile7 } from "node:fs/promises";
97384
97413
  import { join as join41, sep as sep7 } from "node:path";
97385
97414
  var INSTALLED_MARKETPLACES_DIR = ".tmp/marketplaces";
97386
97415
  async function writeInstalledMarketplaceSnapshot(input) {
@@ -97400,7 +97429,7 @@ async function writeMarketplaceManifest(marketplaceRoot, marketplace) {
97400
97429
  const manifestDir = join41(marketplaceRoot, ".agents", "plugins");
97401
97430
  await mkdir6(manifestDir, { recursive: true });
97402
97431
  const tempPath = join41(manifestDir, `.marketplace-${process.pid}-${Date.now()}.json.tmp`);
97403
- await writeFile6(tempPath, `${JSON.stringify(marketplace, null, "\t")}
97432
+ await writeFile7(tempPath, `${JSON.stringify(marketplace, null, "\t")}
97404
97433
  `);
97405
97434
  await rename5(tempPath, join41(manifestDir, "marketplace.json"));
97406
97435
  }
@@ -97429,15 +97458,15 @@ function shouldCopyMarketplaceSourcePath(path, root) {
97429
97458
  }
97430
97459
 
97431
97460
  // packages/omo-codex/src/install/link-cached-plugin-agents.ts
97432
- import { copyFile, lstat as lstat11, mkdir as mkdir7, readdir as readdir8, readFile as readFile17, rm as rm12, writeFile as writeFile9 } from "node:fs/promises";
97461
+ import { copyFile, lstat as lstat11, mkdir as mkdir7, readdir as readdir8, readFile as readFile18, rm as rm12, writeFile as writeFile10 } from "node:fs/promises";
97433
97462
  import { basename as basename7, join as join46 } from "node:path";
97434
97463
 
97435
97464
  // packages/omo-codex/src/install/agent-model-overrides.ts
97436
- import { readFile as readFile14, rm as rm9, writeFile as writeFile8 } from "node:fs/promises";
97465
+ import { readFile as readFile15, rm as rm9, writeFile as writeFile9 } from "node:fs/promises";
97437
97466
  import { join as join43 } from "node:path";
97438
97467
 
97439
97468
  // packages/omo-codex/src/install/preserved-agent-settings.ts
97440
- import { lstat as lstat8, readFile as readFile13, readdir as readdir7, writeFile as writeFile7 } from "node:fs/promises";
97469
+ import { lstat as lstat8, readFile as readFile14, readdir as readdir7, writeFile as writeFile8 } from "node:fs/promises";
97441
97470
  import { join as join42 } from "node:path";
97442
97471
 
97443
97472
  // packages/omo-codex/src/install/managed-agent-reasoning-defaults.ts
@@ -97672,7 +97701,7 @@ async function capturePreservedAgentServiceTier(input) {
97672
97701
  async function restorePreservedReasoning(input) {
97673
97702
  if (input.value === undefined)
97674
97703
  return;
97675
- const content = await readFile13(input.target, "utf8");
97704
+ const content = await readFile14(input.target, "utf8");
97676
97705
  const bundledEffort = extractReasoningEffort(content);
97677
97706
  const effort = resolveManagedAgentReasoning({
97678
97707
  agentName: input.agentName,
@@ -97685,33 +97714,33 @@ async function restorePreservedReasoning(input) {
97685
97714
  const replacement = replaceTopLevelStringSetting(content, "model_reasoning_effort", effort, { insertIfMissing: false });
97686
97715
  if (!replacement.replaced)
97687
97716
  return;
97688
- await writeFile7(input.linkPath, replacement.content);
97717
+ await writeFile8(input.linkPath, replacement.content);
97689
97718
  }
97690
97719
  async function restorePreservedServiceTier(input) {
97691
97720
  if (!input.preserved)
97692
97721
  return;
97693
- const content = await readFile13(input.linkPath, "utf8");
97722
+ const content = await readFile14(input.linkPath, "utf8");
97694
97723
  if (extractServiceTier(content) === input.value)
97695
97724
  return;
97696
97725
  const replacement = replaceTopLevelStringSetting(content, "service_tier", input.value, { insertIfMissing: true });
97697
97726
  if (!replacement.replaced)
97698
97727
  return;
97699
- await writeFile7(input.linkPath, replacement.content);
97728
+ await writeFile8(input.linkPath, replacement.content);
97700
97729
  }
97701
97730
  async function restorePreservedModel(input) {
97702
97731
  if (input.value === null)
97703
97732
  return;
97704
- const content = await readFile13(input.linkPath, "utf8");
97733
+ const content = await readFile14(input.linkPath, "utf8");
97705
97734
  if (extractModel(content) === input.value)
97706
97735
  return;
97707
97736
  const replacement = replaceTopLevelStringSetting(content, "model", input.value, { insertIfMissing: true });
97708
97737
  if (!replacement.replaced)
97709
97738
  return;
97710
- await writeFile7(input.linkPath, replacement.content);
97739
+ await writeFile8(input.linkPath, replacement.content);
97711
97740
  }
97712
97741
  async function readTextIfExists(path) {
97713
97742
  try {
97714
- return await readFile13(path, "utf8");
97743
+ return await readFile14(path, "utf8");
97715
97744
  } catch (error) {
97716
97745
  if (nodeErrorCode(error) === "ENOENT")
97717
97746
  return null;
@@ -97833,13 +97862,13 @@ async function writeAgentModelReceipts(codexHome, receipts) {
97833
97862
  await rm9(path, { force: true });
97834
97863
  return;
97835
97864
  }
97836
- await writeFile8(path, `${JSON.stringify(Object.fromEntries(receipts), null, "\t")}
97865
+ await writeFile9(path, `${JSON.stringify(Object.fromEntries(receipts), null, "\t")}
97837
97866
  `);
97838
97867
  }
97839
97868
  async function applyAgentOverride(input) {
97840
97869
  if (input.override === undefined)
97841
97870
  return;
97842
- let content = await readFile14(input.linkPath, "utf8");
97871
+ let content = await readFile15(input.linkPath, "utf8");
97843
97872
  if (input.override.model !== undefined) {
97844
97873
  content = replaceTopLevelStringSetting(content, "model", input.override.model, { insertIfMissing: true }).content;
97845
97874
  }
@@ -97848,7 +97877,7 @@ async function applyAgentOverride(input) {
97848
97877
  insertIfMissing: true
97849
97878
  }).content;
97850
97879
  }
97851
- await writeFile8(input.linkPath, content);
97880
+ await writeFile9(input.linkPath, content);
97852
97881
  }
97853
97882
  function receiptPath(codexHome) {
97854
97883
  return join43(codexHome, "agents", RECEIPT_FILE);
@@ -97883,7 +97912,7 @@ function handEditedAgentModel(installedModel, receipt) {
97883
97912
  }
97884
97913
 
97885
97914
  // packages/omo-codex/src/install/retired-managed-agent-purge.ts
97886
- import { lstat as lstat9, readFile as readFile15, rm as rm10 } from "node:fs/promises";
97915
+ import { lstat as lstat9, readFile as readFile16, rm as rm10 } from "node:fs/promises";
97887
97916
  import { join as join44 } from "node:path";
97888
97917
  var RETIRED_MANAGED_AGENT_FILES = [
97889
97918
  {
@@ -97917,7 +97946,7 @@ function hasRequiredMarkers(content, markers) {
97917
97946
  }
97918
97947
  async function readTextIfExists2(path) {
97919
97948
  try {
97920
- return await readFile15(path, "utf8");
97949
+ return await readFile16(path, "utf8");
97921
97950
  } catch (error) {
97922
97951
  if (nodeErrorCode2(error) === "ENOENT")
97923
97952
  return null;
@@ -97942,7 +97971,7 @@ function nodeErrorCode2(error) {
97942
97971
 
97943
97972
  // packages/omo-codex/src/install/default-agent-role.ts
97944
97973
  import { createHash as createHash4 } from "node:crypto";
97945
- import { lstat as lstat10, readFile as readFile16, rm as rm11 } from "node:fs/promises";
97974
+ import { lstat as lstat10, readFile as readFile17, rm as rm11 } from "node:fs/promises";
97946
97975
  import { join as join45 } from "node:path";
97947
97976
  var REGISTRATION = { name: "default", configFile: "./agents/default.toml" };
97948
97977
  async function installDefaultAgentRole(input) {
@@ -97979,7 +98008,7 @@ async function installDefaultAgentRole(input) {
97979
98008
  if (foreign || existing !== null && !owned) {
97980
98009
  throw new Error("Preserved user-owned agents.default / agents/default.toml. Move it aside to install the LazyCodex fallback, or set [codex].agents.default.disable = true in omo.jsonc. Explicit LazyCodex roles remain required.");
97981
98010
  }
97982
- const worker = await readFile16(input.worker.path, "utf8");
98011
+ const worker = await readFile17(input.worker.path, "utf8");
97983
98012
  const content = worker.replace(/^name\s*=\s*["']lazycodex-worker-medium["']\s*$/m, 'name = "default"');
97984
98013
  if (content === worker)
97985
98014
  throw new Error("Cannot derive default: medium worker has no matching internal name");
@@ -97989,7 +98018,7 @@ async function installDefaultAgentRole(input) {
97989
98018
  }
97990
98019
  async function readIfPresent(path) {
97991
98020
  try {
97992
- return await readFile16(path, "utf8");
98021
+ return await readFile17(path, "utf8");
97993
98022
  } catch (error) {
97994
98023
  if (error instanceof Error && "code" in error && error.code === "ENOENT")
97995
98024
  return null;
@@ -98050,7 +98079,7 @@ async function syncAgentFile(input) {
98050
98079
  value: input.preservedServiceTier?.get(input.agentName) ?? null
98051
98080
  });
98052
98081
  await applyAgentOverride({ linkPath: input.linkPath, override });
98053
- const model = override?.model ?? extractModel(await readFile17(input.agentPath, "utf8"));
98082
+ const model = override?.model ?? extractModel(await readFile18(input.agentPath, "utf8"));
98054
98083
  return {
98055
98084
  ...model === null ? {} : { model },
98056
98085
  ...override?.reasoningEffort === undefined ? {} : { reasoningEffort: override.reasoningEffort }
@@ -98094,7 +98123,7 @@ async function prepareReplacement(linkPath) {
98094
98123
  async function writeManifest(pluginRoot, agentPaths) {
98095
98124
  const manifestPath = join46(pluginRoot, MANIFEST_FILE);
98096
98125
  const payload = { agents: [...agentPaths].sort() };
98097
- await writeFile9(manifestPath, `${JSON.stringify(payload, null, "\t")}
98126
+ await writeFile10(manifestPath, `${JSON.stringify(payload, null, "\t")}
98098
98127
  `);
98099
98128
  }
98100
98129
  function agentNameFromToml2(fileName) {
@@ -98163,12 +98192,12 @@ function agentNameFromToml3(fileName) {
98163
98192
  }
98164
98193
 
98165
98194
  // packages/omo-codex/src/install/codex-marketplace.ts
98166
- import { readFile as readFile18 } from "node:fs/promises";
98195
+ import { readFile as readFile19 } from "node:fs/promises";
98167
98196
  import { join as join47 } from "node:path";
98168
98197
  var DEFAULT_MARKETPLACE_PATH = "packages/omo-codex/marketplace.json";
98169
98198
  async function readMarketplace(repoRoot, options) {
98170
98199
  const marketplacePath = options?.marketplacePath ?? join47(repoRoot, DEFAULT_MARKETPLACE_PATH);
98171
- const raw = await readFile18(marketplacePath, "utf8");
98200
+ const raw = await readFile19(marketplacePath, "utf8");
98172
98201
  const parsed = JSON.parse(raw);
98173
98202
  if (!isPlainRecord4(parsed))
98174
98203
  throw new Error("marketplace.json must be an object");
@@ -98189,7 +98218,7 @@ function resolvePluginSource(repoRoot, plugin, options) {
98189
98218
  return join47(repoRoot, ...relativePath.split(/[\\/]/));
98190
98219
  }
98191
98220
  async function readPluginManifest(pluginRoot) {
98192
- const raw = await readFile18(join47(pluginRoot, ".codex-plugin", "plugin.json"), "utf8");
98221
+ const raw = await readFile19(join47(pluginRoot, ".codex-plugin", "plugin.json"), "utf8");
98193
98222
  const parsed = JSON.parse(raw);
98194
98223
  if (!isPlainRecord4(parsed))
98195
98224
  throw new Error(`${pluginRoot} plugin.json must be an object`);
@@ -98270,11 +98299,11 @@ function validateLocalSourcePath(path) {
98270
98299
  }
98271
98300
 
98272
98301
  // packages/omo-codex/src/install/lazycodex-version-stamp.ts
98273
- import { readdir as readdir9, readFile as readFile19, writeFile as writeFile10 } from "node:fs/promises";
98302
+ import { readdir as readdir9, readFile as readFile20, writeFile as writeFile11 } from "node:fs/promises";
98274
98303
  import { join as join48 } from "node:path";
98275
98304
  async function readDistributionManifest(repoRoot) {
98276
98305
  try {
98277
- const parsed = JSON.parse(await readFile19(join48(repoRoot, "package.json"), "utf8"));
98306
+ const parsed = JSON.parse(await readFile20(join48(repoRoot, "package.json"), "utf8"));
98278
98307
  if (!isPlainRecord4(parsed) || typeof parsed.version !== "string" || parsed.version.trim().length === 0)
98279
98308
  return;
98280
98309
  return {
@@ -98310,7 +98339,7 @@ async function stampLazyCodexPluginVersion(input) {
98310
98339
  async function writeLazyCodexInstallSnapshot(input) {
98311
98340
  if (input.distributionManifest === undefined)
98312
98341
  return;
98313
- await writeFile10(join48(input.pluginRoot, "lazycodex-install.json"), `${JSON.stringify({
98342
+ await writeFile11(join48(input.pluginRoot, "lazycodex-install.json"), `${JSON.stringify({
98314
98343
  packageName: input.distributionManifest.name,
98315
98344
  version: input.distributionManifest.version
98316
98345
  }, null, "\t")}
@@ -98318,11 +98347,11 @@ async function writeLazyCodexInstallSnapshot(input) {
98318
98347
  }
98319
98348
  async function stampJsonVersion(path, version) {
98320
98349
  try {
98321
- const parsed = JSON.parse(await readFile19(path, "utf8"));
98350
+ const parsed = JSON.parse(await readFile20(path, "utf8"));
98322
98351
  if (!isPlainRecord4(parsed))
98323
98352
  return;
98324
98353
  parsed.version = version;
98325
- await writeFile10(path, `${JSON.stringify(parsed, null, "\t")}
98354
+ await writeFile11(path, `${JSON.stringify(parsed, null, "\t")}
98326
98355
  `);
98327
98356
  } catch (error) {
98328
98357
  if (error instanceof Error)
@@ -98332,7 +98361,7 @@ async function stampJsonVersion(path, version) {
98332
98361
  }
98333
98362
  async function readPluginHookPaths(manifestPath) {
98334
98363
  try {
98335
- const parsed = JSON.parse(await readFile19(manifestPath, "utf8"));
98364
+ const parsed = JSON.parse(await readFile20(manifestPath, "utf8"));
98336
98365
  if (!isPlainRecord4(parsed))
98337
98366
  return [];
98338
98367
  if (typeof parsed.hooks === "string" && parsed.hooks.trim().length > 0)
@@ -98352,11 +98381,11 @@ function stripDotSlash3(path) {
98352
98381
  }
98353
98382
  async function stampHookStatusMessages(path, version) {
98354
98383
  try {
98355
- const parsed = JSON.parse(await readFile19(path, "utf8"));
98384
+ const parsed = JSON.parse(await readFile20(path, "utf8"));
98356
98385
  if (!isPlainRecord4(parsed))
98357
98386
  return;
98358
98387
  stampHookGroups(parsed.hooks, version);
98359
- await writeFile10(path, `${JSON.stringify(parsed, null, "\t")}
98388
+ await writeFile11(path, `${JSON.stringify(parsed, null, "\t")}
98360
98389
  `);
98361
98390
  } catch (error) {
98362
98391
  if (error instanceof Error)
@@ -98433,7 +98462,7 @@ var defaultRunCommand = async (command, args, options) => {
98433
98462
  };
98434
98463
 
98435
98464
  // packages/omo-codex/src/install/codex-project-local-cleanup.ts
98436
- import { copyFile as copyFile2, lstat as lstat12, readFile as readFile20, writeFile as writeFile11 } from "node:fs/promises";
98465
+ import { copyFile as copyFile2, lstat as lstat12, readFile as readFile21, writeFile as writeFile12 } from "node:fs/promises";
98437
98466
  import { dirname as dirname17, join as join49, resolve as resolve11 } from "node:path";
98438
98467
  var LEGACY_AGENT_CONFLICT_KEYS = ["max_threads"];
98439
98468
  var PROJECT_LOCAL_ARTIFACT_PATHS = [
@@ -98453,7 +98482,7 @@ async function repairNearestProjectLocalCodexArtifacts(input) {
98453
98482
  const artifacts = await collectProjectLocalArtifacts(project.artifactRoots);
98454
98483
  const configs = [];
98455
98484
  for (const configPath of project.configPaths) {
98456
- const original = await readFile20(configPath, "utf8");
98485
+ const original = await readFile21(configPath, "utf8");
98457
98486
  const repair = repairProjectLocalCodexConfigText(original);
98458
98487
  if (!repair.changed) {
98459
98488
  configs.push({
@@ -98466,7 +98495,7 @@ async function repairNearestProjectLocalCodexArtifacts(input) {
98466
98495
  }
98467
98496
  const backupPath = `${configPath}.backup-${formatBackupTimestamp(input.now?.() ?? new Date)}`;
98468
98497
  await copyFile2(configPath, backupPath);
98469
- await writeFile11(configPath, `${repair.config.trimEnd()}
98498
+ await writeFile12(configPath, `${repair.config.trimEnd()}
98470
98499
  `);
98471
98500
  configs.push({
98472
98501
  projectRoot: project.projectRoot,
@@ -98663,13 +98692,13 @@ function formatUnknownError(error) {
98663
98692
 
98664
98693
  // packages/omo-codex/src/install/lsp-daemon-reaper.ts
98665
98694
  import { createHash as createHash5 } from "node:crypto";
98666
- import { lstat as lstat13, readFile as readFile22, readdir as readdir11, rm as rm13 } from "node:fs/promises";
98695
+ import { lstat as lstat13, readFile as readFile23, readdir as readdir11, rm as rm13 } from "node:fs/promises";
98667
98696
  import { tmpdir as tmpdir4 } from "node:os";
98668
98697
  import { join as join50, posix as posix6 } from "node:path";
98669
98698
 
98670
98699
  // packages/omo-codex/src/install/lsp-daemon-reaper-attestation.ts
98671
98700
  import { execFile } from "node:child_process";
98672
- import { readFile as readFile21, readdir as readdir10, readlink as readlink5 } from "node:fs/promises";
98701
+ import { readFile as readFile22, readdir as readdir10, readlink as readlink5 } from "node:fs/promises";
98673
98702
  import { connect } from "node:net";
98674
98703
  import { basename as basename8 } from "node:path";
98675
98704
  var PROBE_TIMEOUT_MS = 500;
@@ -98711,7 +98740,7 @@ async function attestLegacyDaemonOwnership(input, deps = {}) {
98711
98740
  return false;
98712
98741
  }
98713
98742
  async function attestLinuxOwnership(input, deps) {
98714
- const readFileImpl = deps.readFile ?? readFile21;
98743
+ const readFileImpl = deps.readFile ?? readFile22;
98715
98744
  const readDirImpl = deps.readDir ?? readdir10;
98716
98745
  const readLinkImpl = deps.readLink ?? readlink5;
98717
98746
  const procNetUnix = await readText(readFileImpl, "/proc/net/unix");
@@ -98936,7 +98965,7 @@ async function readRegularTrimmedFile(path) {
98936
98965
  return null;
98937
98966
  if (!stats.isFile())
98938
98967
  return "non_regular";
98939
- const content = (await readFile22(path, "utf8")).trim();
98968
+ const content = (await readFile23(path, "utf8")).trim();
98940
98969
  return content.length > 0 ? content : null;
98941
98970
  }
98942
98971
  function shortDigest(value) {
@@ -98997,11 +99026,11 @@ function resolveCodexInstallerBinDir(input) {
98997
99026
  }
98998
99027
 
98999
99028
  // packages/omo-codex/src/install/codex-installed-bin-dir.ts
99000
- import { readFile as readFile23, readdir as readdir12, writeFile as writeFile12 } from "node:fs/promises";
99029
+ import { readFile as readFile24, readdir as readdir12, writeFile as writeFile13 } from "node:fs/promises";
99001
99030
  import { join as join52 } from "node:path";
99002
99031
  var INSTALLED_BIN_DIR_MANIFEST = ".installed-bin-dir.json";
99003
99032
  async function writeInstalledCodexBinDir(input) {
99004
- await writeFile12(join52(input.pluginRoot, INSTALLED_BIN_DIR_MANIFEST), `${JSON.stringify({ binDir: input.binDir }, null, 2)}
99033
+ await writeFile13(join52(input.pluginRoot, INSTALLED_BIN_DIR_MANIFEST), `${JSON.stringify({ binDir: input.binDir }, null, 2)}
99005
99034
  `);
99006
99035
  }
99007
99036
  async function readInstalledCodexBinDir(codexHome) {
@@ -99027,7 +99056,7 @@ async function installedBinDirManifestPaths(codexHome) {
99027
99056
  return paths;
99028
99057
  }
99029
99058
  async function readBinDirFromManifest(manifestPath) {
99030
- const raw = await readFile23(manifestPath, "utf8").catch(() => null);
99059
+ const raw = await readFile24(manifestPath, "utf8").catch(() => null);
99031
99060
  if (raw === null)
99032
99061
  return null;
99033
99062
  let parsed;
@@ -99045,7 +99074,7 @@ async function readBinDirFromManifest(manifestPath) {
99045
99074
  }
99046
99075
 
99047
99076
  // packages/omo-codex/src/install/codex-git-bash-hooks.ts
99048
- import { readFile as readFile24, writeFile as writeFile13 } from "node:fs/promises";
99077
+ import { readFile as readFile25, writeFile as writeFile14 } from "node:fs/promises";
99049
99078
  import { join as join53 } from "node:path";
99050
99079
  var WINDOWS_ONLY_GIT_BASH_HOOKS = new Set([
99051
99080
  "./hooks/pre-tool-use-recommending-git-bash-mcp.json",
@@ -99055,13 +99084,13 @@ async function removeGitBashHooksOffWindows(input) {
99055
99084
  if (input.platform === "win32")
99056
99085
  return;
99057
99086
  const manifestPath = join53(input.pluginRoot, ".codex-plugin", "plugin.json");
99058
- const parsed = JSON.parse(await readFile24(manifestPath, "utf8"));
99087
+ const parsed = JSON.parse(await readFile25(manifestPath, "utf8"));
99059
99088
  if (!isPlainRecord4(parsed) || !Array.isArray(parsed.hooks))
99060
99089
  return;
99061
99090
  const hooks = parsed.hooks.filter((hook) => typeof hook !== "string" || !WINDOWS_ONLY_GIT_BASH_HOOKS.has(hook));
99062
99091
  if (hooks.length === parsed.hooks.length)
99063
99092
  return;
99064
- await writeFile13(manifestPath, `${JSON.stringify({ ...parsed, hooks }, null, "\t")}
99093
+ await writeFile14(manifestPath, `${JSON.stringify({ ...parsed, hooks }, null, "\t")}
99065
99094
  `);
99066
99095
  }
99067
99096
 
@@ -99432,12 +99461,12 @@ function defaultRunCommand2(command, args) {
99432
99461
  });
99433
99462
  }
99434
99463
  // packages/omo-codex/src/install/codex-cleanup.ts
99435
- import { lstat as lstat16, readFile as readFile27, readdir as readdir14, rm as rm15, rmdir } from "node:fs/promises";
99464
+ import { lstat as lstat16, readFile as readFile28, readdir as readdir14, rm as rm15, rmdir } from "node:fs/promises";
99436
99465
  import { homedir as homedir9 } from "node:os";
99437
99466
  import { isAbsolute as isAbsolute11, join as join62, relative as relative7, resolve as resolve16 } from "node:path";
99438
99467
 
99439
99468
  // packages/omo-codex/src/install/codex-cleanup-bins.ts
99440
- import { lstat as lstat14, readFile as readFile25, readdir as readdir13, readlink as readlink6, rm as rm14 } from "node:fs/promises";
99469
+ import { lstat as lstat14, readFile as readFile26, readdir as readdir13, readlink as readlink6, rm as rm14 } from "node:fs/promises";
99441
99470
  import { dirname as dirname20, isAbsolute as isAbsolute9, join as join60, resolve as resolve14 } from "node:path";
99442
99471
  var ROOT_RUNTIME_BIN_NAME = "omo";
99443
99472
  var MANAGED_CODEX_BIN_NAMES = new Set([
@@ -99499,12 +99528,12 @@ async function isManagedCodexBin(linkPath, platform, binName) {
99499
99528
  }
99500
99529
  if (!entryStat.isFile())
99501
99530
  return false;
99502
- const content = await readFile25(linkPath, "utf8");
99531
+ const content = await readFile26(linkPath, "utf8");
99503
99532
  return content.includes(RUNTIME_WRAPPER_MARKER) || content.includes(COMMAND_SHIM_MARKER);
99504
99533
  }
99505
99534
 
99506
99535
  // packages/omo-codex/src/install/codex-cleanup-config.ts
99507
- import { lstat as lstat15, mkdir as mkdir8, readFile as readFile26, writeFile as writeFile14 } from "node:fs/promises";
99536
+ import { lstat as lstat15, mkdir as mkdir8, readFile as readFile27, writeFile as writeFile15 } from "node:fs/promises";
99508
99537
  import { dirname as dirname21 } from "node:path";
99509
99538
  var MANAGED_MARKETPLACES = ["sisyphuslabs", "lazycodex", "code-yeongyu-codex-plugins"];
99510
99539
  var LEGACY_MANAGED_CODEX_AGENT_NAMES_TO_PURGE2 = ["codex-ultrawork-reviewer"];
@@ -99537,14 +99566,14 @@ function cleanupCodexLightConfigText(config) {
99537
99566
  async function cleanupCodexConfig(configPath, now) {
99538
99567
  if (!await configExists(configPath))
99539
99568
  return { changed: false };
99540
- const original = await readFile26(configPath, "utf8");
99569
+ const original = await readFile27(configPath, "utf8");
99541
99570
  const next = cleanupCodexLightConfigText(original);
99542
99571
  if (next === original)
99543
99572
  return { changed: false };
99544
99573
  const backupPath = `${configPath}.backup-${formatBackupTimestamp2(now?.() ?? new Date)}`;
99545
99574
  await mkdir8(dirname21(configPath), { recursive: true });
99546
- await writeFile14(backupPath, original);
99547
- await writeFile14(configPath, `${next.trimEnd()}
99575
+ await writeFile15(backupPath, original);
99576
+ await writeFile15(configPath, `${next.trimEnd()}
99548
99577
  `);
99549
99578
  return { changed: true, backupPath };
99550
99579
  }
@@ -99821,13 +99850,13 @@ async function collectInstalledAgentPaths(codexHome, configPath) {
99821
99850
  async function readManagedAgentPathsFromConfig(codexHome, configPath) {
99822
99851
  if (!await exists6(configPath))
99823
99852
  return [];
99824
- const config = await readFile27(configPath, "utf8");
99853
+ const config = await readFile28(configPath, "utf8");
99825
99854
  return MANAGED_CODEX_AGENT_NAMES2.filter((agentName) => config.includes(`config_file = ${JSON.stringify(`./agents/${agentName}.toml`)}`)).map((agentName) => join62(codexHome, "agents", `${agentName}.toml`));
99826
99855
  }
99827
99856
  async function readInstalledAgentManifest(manifestPath) {
99828
99857
  if (!await exists6(manifestPath))
99829
99858
  return [];
99830
- const parsed = JSON.parse(await readFile27(manifestPath, "utf8"));
99859
+ const parsed = JSON.parse(await readFile28(manifestPath, "utf8"));
99831
99860
  if (!isPlainRecord4(parsed) || !Array.isArray(parsed.agents))
99832
99861
  return [];
99833
99862
  return parsed.agents.filter((path) => typeof path === "string");
@@ -100019,7 +100048,7 @@ node "%~dp0omo" %*\r
100019
100048
  // packages/omo-senpi/src/install/plugin-artifacts.ts
100020
100049
  import { createHash as createHash7 } from "node:crypto";
100021
100050
  import { constants as constants9 } from "node:fs";
100022
- import { access as access2, readFile as readFile29, stat as stat6 } from "node:fs/promises";
100051
+ import { access as access3, readFile as readFile30, stat as stat6 } from "node:fs/promises";
100023
100052
  import { dirname as dirname25, join as join66 } from "node:path";
100024
100053
 
100025
100054
  // packages/memory-core/src/personas/manifest.ts
@@ -100038,7 +100067,7 @@ var PERSONA_ASSET_FILES = [
100038
100067
 
100039
100068
  // packages/omo-senpi/src/install/senpi-settings.ts
100040
100069
  import { constants as constants8 } from "node:fs";
100041
- import { access, copyFile as copyFile3, mkdir as mkdir9, readFile as readFile28, rename as rename6, writeFile as writeFile15 } from "node:fs/promises";
100070
+ import { access as access2, copyFile as copyFile3, mkdir as mkdir9, readFile as readFile29, rename as rename6, writeFile as writeFile16 } from "node:fs/promises";
100042
100071
  import { basename as basename10, dirname as dirname24, join as join65, resolve as resolve19 } from "node:path";
100043
100072
  var OMO_SENPI_PACKAGE_NAME = "@code-yeongyu/omo-senpi";
100044
100073
  var GENERATED_PLUGIN_BASENAME = /^omo-senpi-cli-plugin-[A-Za-z0-9]{6}$/;
@@ -100049,7 +100078,7 @@ var LEGACY_BUILTIN_SHADOW_PACKAGES = [
100049
100078
  async function readSettings(settingsPath) {
100050
100079
  let raw;
100051
100080
  try {
100052
- raw = await readFile28(settingsPath, "utf8");
100081
+ raw = await readFile29(settingsPath, "utf8");
100053
100082
  } catch (error) {
100054
100083
  if (isErrno(error, "ENOENT"))
100055
100084
  return {};
@@ -100096,11 +100125,11 @@ async function writeSettingsAtomically(settingsPath, settings) {
100096
100125
  if (await fileExists(settingsPath)) {
100097
100126
  await copyFile3(settingsPath, backupPath);
100098
100127
  } else {
100099
- await writeFile15(backupPath, `{}
100128
+ await writeFile16(backupPath, `{}
100100
100129
  `, "utf8");
100101
100130
  }
100102
100131
  const tempPath = `${settingsPath}.${process.pid}.${Date.now()}.tmp`;
100103
- await writeFile15(tempPath, `${JSON.stringify(settings, null, 2)}
100132
+ await writeFile16(tempPath, `${JSON.stringify(settings, null, 2)}
100104
100133
  `, "utf8");
100105
100134
  await rename6(tempPath, settingsPath);
100106
100135
  return backupPath;
@@ -100123,7 +100152,7 @@ function isRecord15(value) {
100123
100152
  async function readPackageName(packagePath) {
100124
100153
  let raw;
100125
100154
  try {
100126
- raw = await readFile28(join65(packagePath, "package.json"), "utf8");
100155
+ raw = await readFile29(join65(packagePath, "package.json"), "utf8");
100127
100156
  } catch (error) {
100128
100157
  if (isErrno(error, "ENOENT") || isErrno(error, "ENOTDIR"))
100129
100158
  return;
@@ -100141,7 +100170,7 @@ async function readPackageName(packagePath) {
100141
100170
  }
100142
100171
  async function fileExists(path) {
100143
100172
  try {
100144
- await access(path, constants8.F_OK);
100173
+ await access2(path, constants8.F_OK);
100145
100174
  return true;
100146
100175
  } catch (error) {
100147
100176
  if (isErrno(error, "ENOENT"))
@@ -100204,6 +100233,7 @@ var REQUIRED_PLUGIN_ARTIFACTS = [
100204
100233
  join66("skills", "visual-qa", "SKILL.md"),
100205
100234
  join66("skills-conditional", "x-search", "SKILL.md"),
100206
100235
  join66("runtime", "agent-toolkit-sdk", "sdk.js"),
100236
+ join66("runtime", "bunshin-ts", "sdk.js"),
100207
100237
  join66("runtime", "thread-sdk", "sdk.js"),
100208
100238
  join66("runtime", "ast-grep-mcp", "cli.js"),
100209
100239
  join66("runtime", "lsp-daemon", "dist", "cli.js"),
@@ -100246,7 +100276,7 @@ async function verifyAstGrepRuntimeIntegrity(pluginPath, platform) {
100246
100276
  runtimeStat = await stat6(runtimeEntry);
100247
100277
  if (!runtimeStat.isFile())
100248
100278
  throw new Error("runtime is not a file");
100249
- await access2(runtimeEntry, constants9.R_OK | constants9.X_OK);
100279
+ await access3(runtimeEntry, constants9.R_OK | constants9.X_OK);
100250
100280
  } catch (error) {
100251
100281
  throw astGrepIntegrityError(runtimeEntry, `runtime is unreadable or non-executable: ${messageOf(error)}`);
100252
100282
  }
@@ -100255,7 +100285,7 @@ async function verifyAstGrepRuntimeIntegrity(pluginPath, platform) {
100255
100285
  }
100256
100286
  let manifest;
100257
100287
  try {
100258
- manifest = JSON.parse(await readFile29(manifestPath, "utf8"));
100288
+ manifest = JSON.parse(await readFile30(manifestPath, "utf8"));
100259
100289
  } catch (error) {
100260
100290
  throw astGrepIntegrityError(runtimeEntry, `manifest is unreadable or invalid JSON: ${messageOf(error)}`);
100261
100291
  }
@@ -100264,7 +100294,7 @@ async function verifyAstGrepRuntimeIntegrity(pluginPath, platform) {
100264
100294
  }
100265
100295
  let actualSha256;
100266
100296
  try {
100267
- actualSha256 = createHash7("sha256").update(await readFile29(runtimeEntry)).digest("hex");
100297
+ actualSha256 = createHash7("sha256").update(await readFile30(runtimeEntry)).digest("hex");
100268
100298
  } catch (error) {
100269
100299
  throw astGrepIntegrityError(runtimeEntry, `runtime hash could not be computed: ${messageOf(error)}`);
100270
100300
  }
@@ -100289,7 +100319,7 @@ function messageOf(error) {
100289
100319
  }
100290
100320
  async function fileExists2(path) {
100291
100321
  try {
100292
- await access2(path, constants9.F_OK);
100322
+ await access3(path, constants9.F_OK);
100293
100323
  return true;
100294
100324
  } catch (error) {
100295
100325
  if (isErrno2(error, "ENOENT"))
@@ -104452,6 +104482,7 @@ var BuiltinSkillNameSchema = _enum([
104452
104482
  "debugging",
104453
104483
  "security-research",
104454
104484
  "security-review",
104485
+ "hyperplan",
104455
104486
  "visual-qa",
104456
104487
  "team-mode"
104457
104488
  ]);
@@ -107981,7 +108012,7 @@ function getSuggestedInstallTag(currentVersion) {
107981
108012
  // packages/omo-opencode/src/cli/doctor/checks/system.ts
107982
108013
  init_jsonc_parser2();
107983
108014
  init_plugin_identity();
107984
- var runtime4 = globalThis;
108015
+ var runtime5 = globalThis;
107985
108016
  var defaultDeps5 = {
107986
108017
  findOpenCodeBinary,
107987
108018
  getOpenCodeVersion: getOpenCodeVersion3,
@@ -108042,7 +108073,7 @@ async function gatherSystemInfo(deps = defaultDeps5) {
108042
108073
  opencodePath: binaryInfo?.path ?? null,
108043
108074
  pluginVersion,
108044
108075
  loadedVersion: loadedInfo.loadedVersion,
108045
- bunVersion: runtime4.Bun?.version ?? "unavailable",
108076
+ bunVersion: runtime5.Bun?.version ?? "unavailable",
108046
108077
  configPath: pluginInfo.configPath,
108047
108078
  configValid: isConfigValid(pluginInfo.configPath, deps),
108048
108079
  isLocalDev: pluginInfo.isLocalDev
@@ -109521,7 +109552,7 @@ async function pathExists2(dir) {
109521
109552
  // packages/omo-opencode/src/cli/doctor/checks/codex.ts
109522
109553
  init_src();
109523
109554
  import { existsSync as existsSync61 } from "node:fs";
109524
- import { lstat as lstat17, readdir as readdir15, readFile as readFile30 } from "node:fs/promises";
109555
+ import { lstat as lstat17, readdir as readdir15, readFile as readFile31 } from "node:fs/promises";
109525
109556
  import { homedir as homedir26 } from "node:os";
109526
109557
  import { basename as basename13, join as join99, resolve as resolve27 } from "node:path";
109527
109558
  // packages/omo-opencode/package.json
@@ -109550,8 +109581,8 @@ var package_default3 = {
109550
109581
  },
109551
109582
  dependencies: {
109552
109583
  "@clack/prompts": "^1.8.1",
109553
- "@code-yeongyu/senpi": "2026.11.3-3",
109554
- "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.11.3-3",
109584
+ "@code-yeongyu/senpi": "2026.11.5-1",
109585
+ "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.11.5-1",
109555
109586
  "@modelcontextprotocol/sdk": "^1.30.0",
109556
109587
  "@oh-my-opencode/agents-md-core": "workspace:*",
109557
109588
  "@oh-my-opencode/boulder-state": "workspace:*",
@@ -109746,7 +109777,7 @@ async function readCodexConfigSummary(configPath) {
109746
109777
  companionLifecycleHookStateEvents: []
109747
109778
  };
109748
109779
  }
109749
- const content = await readFile30(configPath, "utf8");
109780
+ const content = await readFile31(configPath, "utf8");
109750
109781
  return {
109751
109782
  exists: true,
109752
109783
  marketplaceConfigured: content.includes("[marketplaces.sisyphuslabs]"),
@@ -109774,7 +109805,7 @@ async function readLinkedAgents(codexHome) {
109774
109805
  }
109775
109806
  async function readJson(path) {
109776
109807
  try {
109777
- const parsed = JSON.parse(await readFile30(path, "utf8"));
109808
+ const parsed = JSON.parse(await readFile31(path, "utf8"));
109778
109809
  return isPlainRecord(parsed) ? parsed : null;
109779
109810
  } catch (error) {
109780
109811
  if (error instanceof Error)
@@ -109898,7 +109929,7 @@ function resolveLatestVersion(input) {
109898
109929
 
109899
109930
  // packages/omo-opencode/src/cli/doctor/checks/codex-components.ts
109900
109931
  init_src();
109901
- import { readdir as readdir16, readFile as readFile31, stat as stat7 } from "node:fs/promises";
109932
+ import { readdir as readdir16, readFile as readFile32, stat as stat7 } from "node:fs/promises";
109902
109933
  import { homedir as homedir27 } from "node:os";
109903
109934
  import { dirname as dirname40, isAbsolute as isAbsolute15, join as join100, relative as relative10, resolve as resolve28, sep as sep11 } from "node:path";
109904
109935
  var CODEX_COMPONENTS_CHECK_ID = "codex-components";
@@ -110151,7 +110182,7 @@ function degradedDetailLines(entries) {
110151
110182
  }
110152
110183
  async function readJson2(path) {
110153
110184
  try {
110154
- const parsed = JSON.parse(await readFile31(path, "utf8"));
110185
+ const parsed = JSON.parse(await readFile32(path, "utf8"));
110155
110186
  return isRecord18(parsed) ? parsed : null;
110156
110187
  } catch (error) {
110157
110188
  if (error instanceof Error)
@@ -110179,7 +110210,7 @@ function isRecord18(value) {
110179
110210
 
110180
110211
  // packages/omo-opencode/src/cli/doctor/checks/codex-runtime-wrapper.ts
110181
110212
  import { existsSync as existsSync62 } from "node:fs";
110182
- import { readFile as readFile32 } from "node:fs/promises";
110213
+ import { readFile as readFile33 } from "node:fs/promises";
110183
110214
  import { homedir as homedir28 } from "node:os";
110184
110215
  import { join as join101, resolve as resolve29 } from "node:path";
110185
110216
  var RUNTIME_WRAPPER_MARKER2 = "OMO_GENERATED_RUNTIME_WRAPPER";
@@ -110224,7 +110255,7 @@ async function checkCodexRuntimeWrapper(deps = {}) {
110224
110255
  }
110225
110256
  async function readRuntimeWrapper(path) {
110226
110257
  try {
110227
- return await readFile32(path, "utf8");
110258
+ return await readFile33(path, "utf8");
110228
110259
  } catch (error) {
110229
110260
  if (error instanceof Error)
110230
110261
  return null;
@@ -112148,6 +112179,73 @@ async function loadDeviceKeyring(store) {
112148
112179
  import { execFile as execFile5 } from "node:child_process";
112149
112180
  import { homedir as homedir30 } from "node:os";
112150
112181
  import { join as join105 } from "node:path";
112182
+
112183
+ // packages/omo-opencode/src/shared/bun-ffi-shim.ts
112184
+ async function loadBunFfi() {
112185
+ return import("bun:ffi");
112186
+ }
112187
+
112188
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/process-state.ts
112189
+ var KEY = Symbol.for("omo.keychain-helper.process.v1");
112190
+ function keychainProcessState() {
112191
+ const holder = globalThis;
112192
+ holder[KEY] ??= {
112193
+ secretsQueue: Promise.resolve(),
112194
+ interactionSwitch: undefined,
112195
+ approvalCache: undefined,
112196
+ entryCandidates: [],
112197
+ helperAccess: undefined,
112198
+ heldPromptLocks: new Set,
112199
+ handOff: undefined
112200
+ };
112201
+ return holder[KEY];
112202
+ }
112203
+
112204
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/secrets-gate.ts
112205
+ async function loadInteractionSwitch() {
112206
+ const state = keychainProcessState();
112207
+ if (state.interactionSwitch !== undefined)
112208
+ return state.interactionSwitch;
112209
+ if (process.platform !== "darwin")
112210
+ return state.interactionSwitch = null;
112211
+ try {
112212
+ const { dlopen, FFIType } = await loadBunFfi();
112213
+ const security = dlopen("/System/Library/Frameworks/Security.framework/Security", {
112214
+ SecKeychainSetUserInteractionAllowed: { args: [FFIType.u8], returns: FFIType.i32 }
112215
+ });
112216
+ state.interactionSwitch = (allowed) => {
112217
+ security.symbols.SecKeychainSetUserInteractionAllowed(allowed ? 1 : 0);
112218
+ };
112219
+ } catch {
112220
+ state.interactionSwitch = null;
112221
+ }
112222
+ return state.interactionSwitch;
112223
+ }
112224
+ function gatedSecrets(run) {
112225
+ const state = keychainProcessState();
112226
+ const next = state.secretsQueue.then(run, run);
112227
+ state.secretsQueue = next.then(() => {
112228
+ return;
112229
+ }, () => {
112230
+ return;
112231
+ });
112232
+ return next;
112233
+ }
112234
+ function silentSecrets(run) {
112235
+ return gatedSecrets(async () => {
112236
+ const setInteraction = await loadInteractionSwitch();
112237
+ if (setInteraction === null)
112238
+ throw new Error("Keychain interaction cannot be switched off on this host.");
112239
+ setInteraction(false);
112240
+ try {
112241
+ return await run();
112242
+ } finally {
112243
+ setInteraction(true);
112244
+ }
112245
+ });
112246
+ }
112247
+
112248
+ // packages/omo-opencode/src/cli/account-keys/keystore.ts
112151
112249
  var DEFAULT_SERVICE = "omo-cli";
112152
112250
  function defaultRun(argv, input) {
112153
112251
  const [file, ...args] = argv;
@@ -112171,7 +112269,7 @@ function createOsKeyStore(name, platform = process.platform, run = defaultRun, s
112171
112269
  const resolved = secrets === undefined ? run === defaultRun && typeof Bun !== "undefined" ? Bun.secrets : null : secrets;
112172
112270
  switch (platform) {
112173
112271
  case "darwin":
112174
- return resolved !== null ? createBunSecretsKeyStore(name, resolved) : createMacOsKeychainKeyStore(name, run);
112272
+ return resolved !== null ? createBunSecretsKeyStore(name, gateRealSecrets(resolved)) : createMacOsKeychainKeyStore(name, run);
112175
112273
  case "linux":
112176
112274
  return resolved !== null ? createBunSecretsKeyStore(name, resolved) : createLibsecretKeyStore(name, run);
112177
112275
  case "win32":
@@ -112190,6 +112288,10 @@ async function guarded(run, fail, argv, input) {
112190
112288
  throw fail();
112191
112289
  }
112192
112290
  }
112291
+ var gateRealSecrets = (secrets) => typeof Bun !== "undefined" && secrets === Bun.secrets ? {
112292
+ get: (key) => gatedSecrets(() => secrets.get(key)),
112293
+ set: (entry) => gatedSecrets(() => secrets.set(entry))
112294
+ } : secrets;
112193
112295
  function createBunSecretsKeyStore(name, secrets) {
112194
112296
  const key = { service: DEFAULT_SERVICE, name };
112195
112297
  const unavailable = () => new Error("omo account keys: cannot access the OS credential store. Unlock the login keychain (macOS), the Secret Service keyring (Linux), or DPAPI (Windows), then try again. " + "Private keys are only ever stored through the OS credential facility.");
@@ -112727,64 +112829,705 @@ async function loginDevice(session, options) {
112727
112829
  }
112728
112830
 
112729
112831
  // packages/omo-opencode/src/cli/service-auth/keystore.ts
112730
- import { createHash as createHash12, randomUUID as randomUUID7 } from "node:crypto";
112731
- import { basename as basename15 } from "node:path";
112832
+ import { createHash as createHash12, randomUUID as randomUUID8 } from "node:crypto";
112833
+ import { basename as basename17 } from "node:path";
112732
112834
 
112733
- // packages/omo-opencode/src/cli/service-auth/secret-service-lock.ts
112734
- import { spawn as spawn5 } from "node:child_process";
112735
- var DEFAULT_COLLECTION = "/org/freedesktop/secrets/aliases/default";
112736
- var PROBE_TIMEOUT_MS2 = 1e4;
112737
- var parseLockedReply = (stdout) => {
112738
- const match = /<\s*(true|false)\s*>/.exec(stdout);
112739
- if (match === null)
112740
- return null;
112741
- return match[1] === "true" ? "locked" : "unlocked";
112835
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/darwin-backend.ts
112836
+ import { homedir as homedir31 } from "node:os";
112837
+ import { join as join109 } from "node:path";
112838
+
112839
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/client.ts
112840
+ init_zod();
112841
+ init_bun_spawn_shim();
112842
+ var MUTATING = new Set(["write", "stage", "retire", "promote", "remove"]);
112843
+ var helperReplySchema = object({
112844
+ owned: boolean2(),
112845
+ value: string2(),
112846
+ marker: boolean2(),
112847
+ cdat: number2(),
112848
+ mdat: number2(),
112849
+ partition: _enum(["ours", "other", "none", "unknown"]),
112850
+ present: object({ staging: boolean2(), old: boolean2(), oldSlots: array(number2().int().min(0).max(7)).optional() }).strict(),
112851
+ missing: boolean2(),
112852
+ recover: boolean2(),
112853
+ ok: boolean2(),
112854
+ created: boolean2(),
112855
+ skipped: boolean2(),
112856
+ slot: number2().int().min(0).max(7),
112857
+ error: _enum(["locked", "store", "not-owned", "exists", "missing", "denied", "refused"]),
112858
+ reason: string2(),
112859
+ status: number2()
112860
+ }).partial().strict();
112861
+
112862
+ class HelperProtocolError extends Error {
112863
+ }
112864
+ async function firstLine(stream) {
112865
+ const reader = stream.getReader();
112866
+ const decoder = new TextDecoder;
112867
+ let text = "";
112868
+ for (;; ) {
112869
+ const newline = text.indexOf(`
112870
+ `);
112871
+ if (newline !== -1)
112872
+ return text.slice(0, newline);
112873
+ const chunk = await reader.read();
112874
+ if (chunk.done)
112875
+ return null;
112876
+ text += decoder.decode(chunk.value, { stream: true });
112877
+ }
112878
+ }
112879
+ function isFlushable(stream) {
112880
+ return typeof stream.flush === "function";
112881
+ }
112882
+ var spawnDetachedHelper = (path) => {
112883
+ const child = spawn([path], {
112884
+ stdin: "pipe",
112885
+ stdout: "pipe",
112886
+ stderr: "ignore",
112887
+ detached: true,
112888
+ env: process.env.HOME === undefined ? {} : { HOME: process.env.HOME }
112889
+ });
112890
+ const pid = child.pid;
112891
+ if (pid === undefined)
112892
+ throw new HelperProtocolError("The keychain helper did not start.");
112893
+ const stdin = child.stdin;
112894
+ return {
112895
+ pid,
112896
+ send: (line) => {
112897
+ stdin.write(line);
112898
+ if (isFlushable(stdin))
112899
+ stdin.flush();
112900
+ },
112901
+ reply: firstLine(child.stdout),
112902
+ close: () => {
112903
+ stdin.end();
112904
+ }
112905
+ };
112742
112906
  };
112743
- var probeSecretServiceLock = () => new Promise((resolve) => {
112744
- const child = spawn5("gdbus", [
112745
- "call",
112746
- "--session",
112747
- "--dest",
112748
- "org.freedesktop.secrets",
112749
- "--object-path",
112750
- DEFAULT_COLLECTION,
112751
- "--method",
112752
- "org.freedesktop.DBus.Properties.Get",
112753
- "org.freedesktop.Secret.Collection",
112754
- "Locked"
112755
- ], { stdio: ["ignore", "pipe", "ignore"] });
112756
- let stdout = "";
112757
- const timer = setTimeout(() => {
112758
- child.kill();
112759
- resolve("unknown");
112760
- }, PROBE_TIMEOUT_MS2);
112761
- child.stdout.on("data", (chunk) => {
112762
- stdout += chunk.toString();
112907
+ async function callHelper(path, call, options = {}) {
112908
+ const mutates = MUTATING.has(call.verb);
112909
+ if (mutates && options.lease === undefined)
112910
+ throw new HelperProtocolError(`The ${call.verb} helper call needs the session lock.`);
112911
+ const helper = (options.spawn ?? spawnDetachedHelper)(path);
112912
+ let handedOver = false;
112913
+ try {
112914
+ if (mutates && options.lease !== undefined) {
112915
+ await options.lease.handOver(helper.pid);
112916
+ handedOver = true;
112917
+ }
112918
+ helper.send(`${JSON.stringify({ v: 1, verb: call.verb, account: call.account, ...call.value === undefined ? {} : { value: call.value } })}
112919
+ `);
112920
+ const line = await helper.reply;
112921
+ if (handedOver && options.lease !== undefined) {
112922
+ handedOver = false;
112923
+ await options.lease.restore();
112924
+ }
112925
+ if (line === null)
112926
+ throw new HelperProtocolError(`The keychain helper exited without answering ${call.verb}.`);
112927
+ let json;
112928
+ try {
112929
+ json = JSON.parse(line);
112930
+ } catch {
112931
+ throw new HelperProtocolError(`The keychain helper sent a ${call.verb} reply that is not JSON.`);
112932
+ }
112933
+ const parsed = helperReplySchema.safeParse(json);
112934
+ if (!parsed.success)
112935
+ throw new HelperProtocolError(`The keychain helper sent an unexpected ${call.verb} reply.`);
112936
+ return parsed.data;
112937
+ } catch (error) {
112938
+ if (handedOver && options.lease !== undefined) {
112939
+ try {
112940
+ await options.lease.restore();
112941
+ } catch (restoreError) {
112942
+ throw new AggregateError([error, restoreError], `The ${call.verb} helper call failed and the session lock could not be restored.`);
112943
+ }
112944
+ }
112945
+ throw error;
112946
+ } finally {
112947
+ helper.close();
112948
+ }
112949
+ }
112950
+
112951
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/location.ts
112952
+ import { dirname as dirname42, join as join106, posix as posix13 } from "node:path";
112953
+ import { fileURLToPath as fileURLToPath8 } from "node:url";
112954
+ function bundleCandidates(moduleUrl) {
112955
+ const root = dirname42(dirname42(dirname42(fileURLToPath8(moduleUrl))));
112956
+ return [join106(root, "bin", "darwin", "omo-keychain"), join106(root, "omo-keychain")];
112957
+ }
112958
+ function machineCandidates(home, arch = process.arch) {
112959
+ const runtimeArch = arch === "arm64" ? "arm64" : "x64";
112960
+ return [
112961
+ `/Applications/OmO.app/Contents/Resources/omo-runtime/darwin-${runtimeArch}/omo-keychain`,
112962
+ posix13.join(home, "Applications", "OmO.app", "Contents", "Resources", "omo-runtime", `darwin-${runtimeArch}`, "omo-keychain"),
112963
+ posix13.join(home, ".bun", "install", "global", "node_modules", "omo-ai", "bin", "darwin", "omo-keychain")
112964
+ ];
112965
+ }
112966
+ async function locateHelper(candidates, verify) {
112967
+ const rejected = [];
112968
+ for (const path of candidates) {
112969
+ const verdict = await verify(path);
112970
+ if (verdict === "valid")
112971
+ return { kind: "found", path };
112972
+ if (verdict === "invalid")
112973
+ rejected.push(path);
112974
+ }
112975
+ return rejected.length === 0 ? { kind: "missing" } : { kind: "invalid", rejected };
112976
+ }
112977
+
112978
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/pin.ts
112979
+ import { readdirSync as readdirSync14, rmSync as rmSync9 } from "node:fs";
112980
+ import { chmod as chmod2, copyFile as copyFile4, constants as constants13, mkdtemp as mkdtemp2, rm as rm16, stat as stat8 } from "node:fs/promises";
112981
+ import { tmpdir as tmpdir6 } from "node:os";
112982
+ import { basename as basename15, join as join107 } from "node:path";
112983
+ var DIR_PREFIX = "omo-keychain-";
112984
+ var OWNED_DIR = new RegExp(`^${DIR_PREFIX}(\\d+)-`);
112985
+ var isAlive = (pid) => {
112986
+ try {
112987
+ process.kill(pid, 0);
112988
+ return true;
112989
+ } catch (error) {
112990
+ return !(error instanceof Error && ("code" in error) && error.code === "ESRCH");
112991
+ }
112992
+ };
112993
+ function sweepDeadPinDirs(root = tmpdir6()) {
112994
+ const removed = [];
112995
+ let entries;
112996
+ try {
112997
+ entries = readdirSync14(root);
112998
+ } catch {
112999
+ return removed;
113000
+ }
113001
+ for (const entry of entries) {
113002
+ const owner = OWNED_DIR.exec(entry)?.[1];
113003
+ if (owner === undefined || Number(owner) === process.pid || isAlive(Number(owner)))
113004
+ continue;
113005
+ try {
113006
+ rmSync9(join107(root, entry), { recursive: true, force: true });
113007
+ } catch {
113008
+ continue;
113009
+ }
113010
+ removed.push(entry);
113011
+ }
113012
+ return removed;
113013
+ }
113014
+ var processDir;
113015
+ async function processPinDir() {
113016
+ if (processDir !== undefined)
113017
+ return processDir;
113018
+ sweepDeadPinDirs();
113019
+ const dir = await mkdtemp2(join107(tmpdir6(), `${DIR_PREFIX}${process.pid}-`));
113020
+ process.once("exit", () => rmSync9(dir, { recursive: true, force: true }));
113021
+ processDir = dir;
113022
+ return dir;
113023
+ }
113024
+ var pinned = new Map;
113025
+ async function sourceIdentity(source) {
113026
+ const info = await stat8(source);
113027
+ return `${source}\x00${info.dev}\x00${info.ino}\x00${info.size}\x00${info.mtimeMs}\x00${info.ctimeMs}`;
113028
+ }
113029
+ async function copyAndVerify(source, verify, dir) {
113030
+ const target = join107(dir, `${crypto.randomUUID()}-${basename15(source)}`);
113031
+ try {
113032
+ await copyFile4(source, target, constants13.COPYFILE_EXCL);
113033
+ await chmod2(target, 320);
113034
+ } catch (error) {
113035
+ await rm16(target, { force: true });
113036
+ return { kind: "unavailable", reason: error instanceof Error ? error.message : String(error) };
113037
+ }
113038
+ let verdict;
113039
+ try {
113040
+ verdict = await verify(target);
113041
+ } catch (error) {
113042
+ await rm16(target, { force: true });
113043
+ return { kind: "unavailable", reason: error instanceof Error ? error.message : String(error) };
113044
+ }
113045
+ if (verdict === "valid")
113046
+ return { kind: "pinned", path: target };
113047
+ await rm16(target, { force: true });
113048
+ return { kind: "invalid" };
113049
+ }
113050
+ async function pinVerifiedCopy(source, verify, dir) {
113051
+ let identity;
113052
+ try {
113053
+ identity = `${dir ?? ""}\x00${await sourceIdentity(source)}`;
113054
+ } catch (error) {
113055
+ return { kind: "unavailable", reason: error instanceof Error ? error.message : String(error) };
113056
+ }
113057
+ const known = pinned.get(identity);
113058
+ if (known !== undefined) {
113059
+ const result = await known;
113060
+ if (result.kind !== "pinned")
113061
+ return result;
113062
+ let verdict;
113063
+ try {
113064
+ verdict = await verify(result.path);
113065
+ } catch (error) {
113066
+ pinned.delete(identity);
113067
+ await rm16(result.path, { force: true });
113068
+ return { kind: "unavailable", reason: error instanceof Error ? error.message : String(error) };
113069
+ }
113070
+ if (verdict === "valid")
113071
+ return result;
113072
+ }
113073
+ const created = Promise.resolve(dir ?? processPinDir()).then((target) => copyAndVerify(source, verify, target), (error) => ({ kind: "unavailable", reason: error instanceof Error ? error.message : String(error) }));
113074
+ pinned.set(identity, created);
113075
+ const result = await created;
113076
+ if (result.kind !== "pinned")
113077
+ pinned.delete(identity);
113078
+ return result;
113079
+ }
113080
+
113081
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/signature.ts
113082
+ import { stat as stat9 } from "node:fs/promises";
113083
+ init_bun_spawn_shim();
113084
+ var KEYCHAIN_HELPER_REQUIREMENT = 'identifier "com.mengmota.omo-keychain-helper" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] ' + 'and certificate leaf[field.1.2.840.113635.100.6.1.13] and certificate leaf[subject.OU] = "523JNR86LZ"';
113085
+ var STRICT_ALL_ARCHITECTURES = 1 << 4 | 1 << 0;
113086
+ var UTF8 = 134217984;
113087
+ var security;
113088
+ async function loadSecurity() {
113089
+ if (security !== undefined)
113090
+ return security;
113091
+ try {
113092
+ const { dlopen, FFIType, ptr } = await loadBunFfi();
113093
+ const cf = dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", {
113094
+ CFStringCreateWithCString: { args: [FFIType.u64, FFIType.ptr, FFIType.u32], returns: FFIType.u64 },
113095
+ CFURLCreateFromFileSystemRepresentation: { args: [FFIType.u64, FFIType.ptr, FFIType.i64, FFIType.bool], returns: FFIType.u64 },
113096
+ CFRelease: { args: [FFIType.u64], returns: FFIType.void }
113097
+ });
113098
+ const sec = dlopen("/System/Library/Frameworks/Security.framework/Security", {
113099
+ SecStaticCodeCreateWithPath: { args: [FFIType.u64, FFIType.u32, FFIType.ptr], returns: FFIType.i32 },
113100
+ SecRequirementCreateWithString: { args: [FFIType.u64, FFIType.u32, FFIType.ptr], returns: FFIType.i32 },
113101
+ SecStaticCodeCheckValidityWithErrors: { args: [FFIType.u64, FFIType.u32, FFIType.u64, FFIType.u64], returns: FFIType.i32 }
113102
+ });
113103
+ const cString = (text) => Buffer.from(`${text}\x00`, "utf8");
113104
+ security = {
113105
+ check(path, requirement) {
113106
+ const pathBytes = Buffer.from(path, "utf8");
113107
+ const url = BigInt(cf.symbols.CFURLCreateFromFileSystemRepresentation(0n, ptr(pathBytes), pathBytes.length, false));
113108
+ const text = BigInt(cf.symbols.CFStringCreateWithCString(0n, ptr(cString(requirement)), UTF8));
113109
+ const codeOut = new BigUint64Array(1);
113110
+ const requirementOut = new BigUint64Array(1);
113111
+ try {
113112
+ if (url === 0n || text === 0n)
113113
+ return false;
113114
+ if (sec.symbols.SecStaticCodeCreateWithPath(url, 0, ptr(codeOut)) !== 0)
113115
+ return false;
113116
+ if (sec.symbols.SecRequirementCreateWithString(text, 0, ptr(requirementOut)) !== 0)
113117
+ return false;
113118
+ const code = codeOut[0] ?? 0n;
113119
+ const designated = requirementOut[0] ?? 0n;
113120
+ return sec.symbols.SecStaticCodeCheckValidityWithErrors(code, STRICT_ALL_ARCHITECTURES, designated, 0n) === 0;
113121
+ } finally {
113122
+ for (const ref of [url, text, codeOut[0] ?? 0n, requirementOut[0] ?? 0n])
113123
+ if (ref !== 0n)
113124
+ cf.symbols.CFRelease(ref);
113125
+ }
113126
+ }
113127
+ };
113128
+ } catch {
113129
+ security = null;
113130
+ }
113131
+ return security;
113132
+ }
113133
+ async function verifyWithCodesign(path, requirement) {
113134
+ const child = spawn(["/usr/bin/codesign", "--verify", "--strict", `-R=${requirement}`, path], {
113135
+ stdout: "ignore",
113136
+ stderr: "ignore",
113137
+ env: {}
112763
113138
  });
112764
- child.on("error", () => {
112765
- clearTimeout(timer);
112766
- resolve("unknown");
113139
+ return await child.exited === 0;
113140
+ }
113141
+ var verifyWithSecurityFramework = async (path, requirement) => {
113142
+ const loaded = await loadSecurity();
113143
+ return loaded === null ? verifyWithCodesign(path, requirement) : loaded.check(path, requirement);
113144
+ };
113145
+ async function fileIdentity(path) {
113146
+ try {
113147
+ const info = await stat9(path);
113148
+ if (!info.isFile())
113149
+ return null;
113150
+ return `${path}\x00${info.dev}\x00${info.ino}\x00${info.size}\x00${info.mtimeMs}\x00${info.ctimeMs}`;
113151
+ } catch {
113152
+ return null;
113153
+ }
113154
+ }
113155
+ function createSignatureChecker(check = verifyWithSecurityFramework, requirement = KEYCHAIN_HELPER_REQUIREMENT) {
113156
+ const verdicts = new Map;
113157
+ const checker = async (path) => {
113158
+ const before = await fileIdentity(path);
113159
+ if (before === null)
113160
+ return "missing";
113161
+ const known = verdicts.get(before);
113162
+ if (known !== undefined)
113163
+ return known;
113164
+ const passed = await check(path, requirement);
113165
+ if (await fileIdentity(path) !== before)
113166
+ return "invalid";
113167
+ const verdict = passed ? "valid" : "invalid";
113168
+ verdicts.set(before, verdict);
113169
+ return verdict;
113170
+ };
113171
+ return checker;
113172
+ }
113173
+ var processChecker;
113174
+ var processSignatureChecker = () => processChecker ??= createSignatureChecker();
113175
+
113176
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/access.ts
113177
+ async function resolveHelperAccess(candidates, options = {}) {
113178
+ const verify = options.verify ?? processSignatureChecker();
113179
+ let source;
113180
+ let pin;
113181
+ try {
113182
+ const location = await locateHelper(candidates, verify);
113183
+ if (location.kind !== "found")
113184
+ return location;
113185
+ source = location.path;
113186
+ pin = await (options.pin ?? pinVerifiedCopy)(source, verify);
113187
+ } catch (error) {
113188
+ return { kind: "unavailable", reason: error instanceof Error ? error.message : String(error) };
113189
+ }
113190
+ if (pin.kind === "invalid")
113191
+ return { kind: "invalid", rejected: [source] };
113192
+ if (pin.kind === "unavailable")
113193
+ return { kind: "unavailable", reason: pin.reason };
113194
+ const pinned = pin.path;
113195
+ const spawn = options.spawn ?? spawnDetachedHelper;
113196
+ return {
113197
+ kind: "ready",
113198
+ path: pinned,
113199
+ call: async (call, lease) => {
113200
+ const verdict = await verify(pinned).catch((error) => {
113201
+ throw new HelperProtocolError(`OmO's keychain helper could not be checked before it ran: ${error instanceof Error ? error.message : String(error)}`);
113202
+ });
113203
+ if (verdict !== "valid")
113204
+ throw new HelperProtocolError("OmO's keychain helper changed on disk and failed its signature check; it was not run.");
113205
+ return callHelper(pinned, call, { spawn, ...lease === undefined ? {} : { lease } });
113206
+ }
113207
+ };
113208
+ }
113209
+
113210
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/approval-cache.ts
113211
+ var systemClock = { nowSeconds: () => Date.now() / 1000, sleepMs: (ms) => new Promise((resolve) => setTimeout(resolve, ms)) };
113212
+ function isEntryValid(entry, current, nowSeconds) {
113213
+ if (nowSeconds < entry.readStartedAt)
113214
+ return false;
113215
+ return current.cdat === entry.cdat && current.mdat === entry.mdat && Math.floor(current.mdat) < Math.floor(entry.readStartedAt);
113216
+ }
113217
+ function createApprovalCache(clock = systemClock) {
113218
+ let entry = null;
113219
+ let deniedForBackground = false;
113220
+ let pending = null;
113221
+ return {
113222
+ consume(current) {
113223
+ if (entry === null)
113224
+ return null;
113225
+ if (!isEntryValid(entry, current, clock.nowSeconds())) {
113226
+ entry = null;
113227
+ return null;
113228
+ }
113229
+ return entry.value;
113230
+ },
113231
+ deniedForBackground: () => deniedForBackground,
113232
+ inFlight: () => pending,
113233
+ approve(run) {
113234
+ if (pending !== null)
113235
+ return pending;
113236
+ const readStartedAt = clock.nowSeconds();
113237
+ const started = run().then((answer) => {
113238
+ if (answer.kind === "approved") {
113239
+ entry = { value: answer.value, ...answer.attributes, readStartedAt };
113240
+ deniedForBackground = false;
113241
+ } else if (answer.kind === "denied")
113242
+ deniedForBackground = true;
113243
+ return answer;
113244
+ });
113245
+ const settled = () => {
113246
+ if (pending === started)
113247
+ pending = null;
113248
+ };
113249
+ started.then(settled, settled);
113250
+ pending = started;
113251
+ return started;
113252
+ },
113253
+ async afterOwnWrite(value, readAttributes) {
113254
+ if (entry === null)
113255
+ return;
113256
+ const written = await readAttributes();
113257
+ if (written === null) {
113258
+ entry = null;
113259
+ return;
113260
+ }
113261
+ while (Math.floor(clock.nowSeconds()) <= Math.floor(written.mdat)) {
113262
+ await clock.sleepMs(Math.max(1, Math.ceil((Math.floor(written.mdat) + 1 - clock.nowSeconds()) * 1000)));
113263
+ }
113264
+ const readStartedAt = clock.nowSeconds();
113265
+ const fresh = await readAttributes();
113266
+ entry = fresh === null ? null : { value, ...fresh, readStartedAt };
113267
+ },
113268
+ drop() {
113269
+ entry = null;
113270
+ }
113271
+ };
113272
+ }
113273
+ var processApprovalCache = () => {
113274
+ const state = keychainProcessState();
113275
+ state.approvalCache ??= createApprovalCache();
113276
+ return state.approvalCache;
113277
+ };
113278
+
113279
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/darwin-read.ts
113280
+ var ROW_8B_DEFAULT = "re-login";
113281
+
113282
+ class HelperReadError extends Error {
113283
+ failure;
113284
+ constructor(failure, message) {
113285
+ super(message);
113286
+ this.failure = failure;
113287
+ }
113288
+ }
113289
+ function failure2(reply) {
113290
+ if (reply.error === "locked")
113291
+ return new HelperReadError("locked", "The keychain is locked.");
113292
+ return new HelperReadError("store", `The keychain helper answered ${reply.error ?? "unexpectedly"}.`);
113293
+ }
113294
+ async function approveOnce(deps) {
113295
+ const running = deps.cache.inFlight();
113296
+ if (running !== null)
113297
+ return running;
113298
+ const release = await deps.takePromptLock();
113299
+ if (release === null)
113300
+ throw new HelperReadError("pending", "Another omo process is waiting for your keychain approval.");
113301
+ try {
113302
+ return await deps.cache.approve(async () => {
113303
+ const reply = await deps.access.call({ verb: "approve", account: deps.account });
113304
+ if (reply.missing === true)
113305
+ return { kind: "missing" };
113306
+ if (reply.error === "denied")
113307
+ return { kind: "denied" };
113308
+ if (reply.error !== undefined || reply.value === undefined || reply.cdat === undefined || reply.mdat === undefined)
113309
+ throw failure2(reply);
113310
+ return { kind: "approved", value: reply.value, attributes: { cdat: reply.cdat, mdat: reply.mdat } };
113311
+ });
113312
+ } finally {
113313
+ await release();
113314
+ }
113315
+ }
113316
+ async function readThroughHelper(deps, allowPrompt) {
113317
+ const reply = await deps.access.call({ verb: "read", account: deps.account });
113318
+ if (reply.error !== undefined)
113319
+ throw failure2(reply);
113320
+ if (reply.missing === true)
113321
+ return { kind: "missing", reply };
113322
+ if (reply.owned === true && reply.value !== undefined)
113323
+ return { kind: "value", value: reply.value, source: reply.marker === true || reply.recover === true ? "owned" : "owned-unmarked", reply };
113324
+ const own = await deps.ownSilentGet().catch(() => {
113325
+ return;
112767
113326
  });
112768
- child.on("close", (code) => {
112769
- clearTimeout(timer);
112770
- resolve(code === 0 ? parseLockedReply(stdout) ?? "absent" : "absent");
113327
+ if (typeof own === "string")
113328
+ return { kind: "value", value: own, source: "own-identity", reply };
113329
+ if (reply.cdat === undefined || reply.mdat === undefined)
113330
+ throw failure2(reply);
113331
+ const cached = deps.cache.consume({ cdat: reply.cdat, mdat: reply.mdat });
113332
+ if (cached !== null)
113333
+ return { kind: "value", value: cached, source: "approved", reply };
113334
+ const reloginInstead = reply.partition !== "ours" && reply.partition !== "none" && (deps.row8b ?? ROW_8B_DEFAULT) === "re-login";
113335
+ if (!allowPrompt) {
113336
+ if (reloginInstead)
113337
+ return { kind: "missing", reply };
113338
+ throw new HelperReadError("pending", "The keychain needs your approval; run an omo command in a terminal.");
113339
+ }
113340
+ if (deps.background && deps.cache.deniedForBackground())
113341
+ throw new HelperReadError("pending", "Keychain access was denied; run an omo command in a terminal to approve it.");
113342
+ if (reloginInstead)
113343
+ return { kind: "missing", reply };
113344
+ if (deps.noDialog === true)
113345
+ throw new HelperReadError("pending", "The keychain hand-off cannot show a dialog.");
113346
+ if (deps.handOff !== undefined && await deps.handOff()) {
113347
+ const after = await deps.access.call({ verb: "read", account: deps.account });
113348
+ if (after.owned === true && after.value !== undefined)
113349
+ return { kind: "value", value: after.value, source: "owned", reply: after };
113350
+ }
113351
+ const answer = await approveOnce(deps);
113352
+ if (answer.kind === "approved")
113353
+ return { kind: "value", value: answer.value, source: "approved", reply };
113354
+ if (answer.kind === "missing")
113355
+ return { kind: "missing", reply };
113356
+ throw new HelperReadError("denied", "Keychain access was denied.");
113357
+ }
113358
+
113359
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/recovery.ts
113360
+ var OLD_SLOT_COUNT = 8;
113361
+ var oldSlotName = (account, slot) => slot === 0 ? `${account}.old` : `${account}.old.${slot}`;
113362
+ function recoveryPlan(names) {
113363
+ if (!names.original && names.staging)
113364
+ return names.old ? ["promote", "delete-old"] : ["promote"];
113365
+ if (!names.original && names.old)
113366
+ return ["delete-old"];
113367
+ if (names.original && names.staging)
113368
+ return names.old ? ["remove-staging", "delete-old"] : ["remove-staging"];
113369
+ if (names.original && names.old)
113370
+ return ["delete-old"];
113371
+ return [];
113372
+ }
113373
+ function oldSlotsOf(reply) {
113374
+ return reply.present?.oldSlots ?? (reply.present?.old === true ? [0] : []);
113375
+ }
113376
+ function namesFromRead(reply) {
113377
+ const original = reply.owned === false || reply.owned === true && reply.recover !== true;
113378
+ return { original, staging: reply.present?.staging === true, old: reply.present?.old === true, oldSlots: oldSlotsOf(reply) };
113379
+ }
113380
+ async function deleteOld(name, helper, deleteOwn) {
113381
+ const removed = await helper({ verb: "remove", account: name }).catch(() => null);
113382
+ if (removed?.ok === true)
113383
+ return true;
113384
+ return deleteOwn(name).catch(() => false);
113385
+ }
113386
+ async function deleteOldSlots(account, slots, helper, deleteOwn) {
113387
+ let cleared = true;
113388
+ for (const slot of slots)
113389
+ if (!await deleteOld(oldSlotName(account, slot), helper, deleteOwn))
113390
+ cleared = false;
113391
+ return cleared;
113392
+ }
113393
+ async function runRecovery(account, names, helper, deleteOwnOld) {
113394
+ const applied = [];
113395
+ for (const step of recoveryPlan(names)) {
113396
+ const ok = step === "promote" ? (await helper({ verb: "promote", account })).ok === true : step === "remove-staging" ? (await helper({ verb: "remove", account: `${account}.staging` })).ok === true : await deleteOldSlots(account, names.oldSlots, helper, deleteOwnOld);
113397
+ if (!ok && step !== "delete-old")
113398
+ return { applied, failed: step };
113399
+ if (ok)
113400
+ applied.push(step);
113401
+ }
113402
+ return { applied, failed: null };
113403
+ }
113404
+
113405
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/migration.ts
113406
+ var MIGRATABLE = new Set(["own-identity", "owned-unmarked", "approved"]);
113407
+ async function migrate(account, value, source, helper, deleteOwnOld) {
113408
+ if (!MIGRATABLE.has(source))
113409
+ return { kind: "skipped", reason: "not-migratable" };
113410
+ if ((await helper({ verb: "stage", account, value })).ok !== true)
113411
+ return { kind: "failed", step: "stage" };
113412
+ const retired = await helper({ verb: "retire", account });
113413
+ if (retired.error === "exists" && retired.reason === "old-slots-full" || retired.ok === true && retired.skipped === true) {
113414
+ await helper({ verb: "remove", account: `${account}.staging` });
113415
+ return { kind: "skipped", reason: "old-slots-full" };
113416
+ }
113417
+ if (retired.ok !== true)
113418
+ return { kind: "failed", step: "retire" };
113419
+ const slot = retired.slot ?? 0;
113420
+ if ((await helper({ verb: "promote", account })).ok !== true)
113421
+ return { kind: "failed", step: "promote" };
113422
+ return { kind: "migrated", oldDeleted: await deleteOld(oldSlotName(account, slot), helper, deleteOwnOld) };
113423
+ }
113424
+
113425
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/darwin-store.ts
113426
+ class HelperOldSlotsFull extends Error {
113427
+ }
113428
+ var ALL_OLD_SLOTS = Array.from({ length: OLD_SLOT_COUNT }, (_, slot) => slot);
113429
+ var OLD_SLOTS_FULL_MESSAGE = 'The macOS keychain holds 8 earlier OmO sign-ins that cannot be removed automatically. Open Keychain Access, delete the items whose account name ends in ".old" or ".old.1" to ".old.7" for OmO, then sign in again.';
113430
+ var failed = (reply, verb) => new HelperReadError(reply.error === "locked" ? "locked" : "store", `The keychain helper could not ${verb} the sign-in (${reply.error ?? "no answer"}).`);
113431
+ function lockedDarwinStore(deps, lease) {
113432
+ const helper = (call) => deps.access.call(call, lease);
113433
+ const deleteOwnOld = (name) => deps.ownDelete(name);
113434
+ let lastRead = null;
113435
+ const read = async () => {
113436
+ const result = await readThroughHelper(deps, false);
113437
+ lastRead = result.kind === "value" ? result : null;
113438
+ return result.kind === "value" ? result.value : null;
113439
+ };
113440
+ return {
113441
+ async recover() {
113442
+ const reply = await deps.access.call({ verb: "read", account: deps.account });
113443
+ if (reply.error === undefined)
113444
+ await runRecovery(deps.account, namesFromRead(reply), helper, deleteOwnOld);
113445
+ },
113446
+ read,
113447
+ async settle() {
113448
+ if (lastRead === null)
113449
+ return;
113450
+ const outcome = await migrate(deps.account, lastRead.value, lastRead.source, helper, deleteOwnOld);
113451
+ if (outcome.kind === "skipped" && outcome.reason === "old-slots-full")
113452
+ deps.notice(`omo: ${OLD_SLOTS_FULL_MESSAGE}`);
113453
+ if (outcome.kind === "failed")
113454
+ deps.notice(`omo: the macOS keychain item could not be moved to OmO's keychain helper (${outcome.step}); it keeps working as before.`);
113455
+ },
113456
+ async write(value, intent, beforeRetire) {
113457
+ const state = await deps.access.call({ verb: "read", account: deps.account });
113458
+ if (state.error !== undefined)
113459
+ throw failed(state, "check");
113460
+ if (state.owned === false) {
113461
+ const approved = state.cdat !== undefined && state.mdat !== undefined && deps.cache.consume({ cdat: state.cdat, mdat: state.mdat }) !== null;
113462
+ const readable = lastRead !== null || approved || await deps.ownSilentGet().catch(() => {
113463
+ return;
113464
+ }) !== undefined;
113465
+ if (readable || intent !== "fresh-sign-in") {
113466
+ await deps.ownOverwrite(value);
113467
+ if (lastRead?.source === "approved")
113468
+ await deps.cache.afterOwnWrite(value, async () => {
113469
+ const after = await deps.access.call({ verb: "read", account: deps.account });
113470
+ return after.cdat === undefined || after.mdat === undefined ? null : { cdat: after.cdat, mdat: after.mdat };
113471
+ });
113472
+ return;
113473
+ }
113474
+ await beforeRetire?.();
113475
+ const retired = await helper({ verb: "retire", account: deps.account });
113476
+ if (retired.reason === "old-slots-full" || retired.ok === true && retired.skipped === true)
113477
+ throw new HelperOldSlotsFull(OLD_SLOTS_FULL_MESSAGE);
113478
+ if (retired.ok !== true)
113479
+ throw failed(retired, "replace");
113480
+ }
113481
+ const written = await helper({ verb: "write", account: deps.account, value });
113482
+ if (written.ok !== true)
113483
+ throw failed(written, "save");
113484
+ lastRead = { kind: "value", value, source: "owned", reply: written };
113485
+ },
113486
+ async clear() {
113487
+ const removed = await helper({ verb: "remove", account: deps.account });
113488
+ if (removed.error === "not-owned")
113489
+ await deps.ownDelete(deps.account);
113490
+ else if (removed.ok !== true)
113491
+ throw failed(removed, "remove");
113492
+ await helper({ verb: "remove", account: `${deps.account}.staging` });
113493
+ const present = await helper({ verb: "read", account: deps.account });
113494
+ const slots = present.error === undefined ? oldSlotsOf(present) : ALL_OLD_SLOTS;
113495
+ await deleteOldSlots(deps.account, slots, helper, deleteOwnOld);
113496
+ lastRead = null;
113497
+ }
113498
+ };
113499
+ }
113500
+
113501
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/owner-marker.ts
113502
+ init_bun_spawn_shim();
113503
+ var MARKER_LINE = /^\s*"gena"<blob>="omo-owner\/1"\s*$/m;
113504
+ var ITEM_NOT_FOUND = 44;
113505
+ var probeOwnerMarker = async (service, account, keychain) => {
113506
+ const args = ["find-generic-password", "-s", service, "-a", account, ...keychain === undefined ? [] : [keychain]];
113507
+ const child = spawn(["/usr/bin/security", ...args], {
113508
+ stdout: "pipe",
113509
+ stderr: "ignore",
113510
+ env: process.env.HOME === undefined ? {} : { HOME: process.env.HOME }
112771
113511
  });
112772
- });
113512
+ const [stdout, code] = await Promise.all([new Response(child.stdout).text(), child.exited]);
113513
+ if (code === ITEM_NOT_FOUND)
113514
+ return "absent";
113515
+ if (code !== 0)
113516
+ return "unknown";
113517
+ return MARKER_LINE.test(stdout) ? "helper-owned" : "other";
113518
+ };
112773
113519
 
112774
- // packages/omo-opencode/src/cli/service-auth/credential-lock.ts
112775
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
112776
- import { createHash as createHash11 } from "node:crypto";
113520
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/prompt-lock.ts
112777
113521
  import { mkdir as mkdir11 } from "node:fs/promises";
112778
- import { homedir as homedir31 } from "node:os";
112779
- import { join as join106 } from "node:path";
113522
+ import { dirname as dirname45 } from "node:path";
112780
113523
 
112781
113524
  // packages/team-core/src/team-state-store/lock-publish.ts
112782
- import { access as access4, open as open3, unlink as unlink3 } from "node:fs/promises";
112783
- import { dirname as dirname42 } from "node:path";
113525
+ import { access as access5, open as open3, unlink as unlink4 } from "node:fs/promises";
113526
+ import { dirname as dirname43 } from "node:path";
112784
113527
 
112785
113528
  // packages/team-core/src/team-state-store/lock-record.ts
112786
113529
  import { randomUUID as randomUUID6 } from "node:crypto";
112787
- import { readFile as readFile34, stat as stat9 } from "node:fs/promises";
113530
+ import { readFile as readFile35, stat as stat11 } from "node:fs/promises";
112788
113531
 
112789
113532
  // packages/memory-core/src/locks/process-identity.ts
112790
113533
  import { execFile as execFile7 } from "node:child_process";
@@ -112823,6 +113566,24 @@ function retryOnEintrSync(operation) {
112823
113566
 
112824
113567
  // packages/memory-core/src/fs/rename-contention.ts
112825
113568
  var CONTENTION_CODES = new Set(["EPERM", "EBUSY", "EACCES"]);
113569
+ var CONTENTION_DELAYS_MS = [10, 25, 50, 100, 200, 400];
113570
+ var sleepFor = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
113571
+ async function renameWithContentionRetry(from, to, deps) {
113572
+ const delays = deps.platform === "win32" ? deps.delaysMs ?? CONTENTION_DELAYS_MS : [];
113573
+ const sleep = deps.sleep ?? sleepFor;
113574
+ for (let attempt = 0;; attempt += 1) {
113575
+ try {
113576
+ await retryOnEintr(() => deps.admit === undefined ? deps.rename(from, to) : deps.admit(() => deps.rename(from, to)));
113577
+ return;
113578
+ } catch (error) {
113579
+ const delay = delays[attempt];
113580
+ const code = fsErrorCode(error);
113581
+ if (delay === undefined || code === undefined || !CONTENTION_CODES.has(code))
113582
+ throw error;
113583
+ await sleep(delay);
113584
+ }
113585
+ }
113586
+ }
112826
113587
 
112827
113588
  // packages/memory-core/src/fs/resilient.ts
112828
113589
  function isFunction2(value) {
@@ -112855,25 +113616,32 @@ function resilientNamespace(namespace, kind) {
112855
113616
  }
112856
113617
  var IDEMPOTENT_HANDLE_METHODS = new Set(["stat", "sync", "datasync", "chmod", "chown", "utimes", "truncate"]);
112857
113618
  var promises = resilientNamespace(fsp, "async");
113619
+ function rename8(from, to, admit) {
113620
+ return renameWithContentionRetry(from, to, {
113621
+ rename: (source, target) => fsp.rename(source, target),
113622
+ platform: process.platform,
113623
+ ...admit === undefined ? {} : { admit }
113624
+ });
113625
+ }
112858
113626
  var sync = resilientNamespace(fsSync, "sync");
112859
113627
  var {
112860
- access: access3,
112861
- chmod: chmod2,
112862
- copyFile: copyFile4,
113628
+ access: access4,
113629
+ chmod: chmod3,
113630
+ copyFile: copyFile5,
112863
113631
  cp: cp5,
112864
113632
  link,
112865
113633
  lstat: lstat18,
112866
113634
  mkdir: mkdir10,
112867
- mkdtemp: mkdtemp2,
112868
- readFile: readFile33,
113635
+ mkdtemp: mkdtemp3,
113636
+ readFile: readFile34,
112869
113637
  readdir: readdir17,
112870
113638
  readlink: readlink7,
112871
113639
  realpath: realpath2,
112872
- rm: rm16,
113640
+ rm: rm17,
112873
113641
  rmdir: rmdir2,
112874
- stat: stat8,
113642
+ stat: stat10,
112875
113643
  statfs,
112876
- unlink: unlink2
113644
+ unlink: unlink3
112877
113645
  } = promises;
112878
113646
  var {
112879
113647
  accessSync: accessSync5,
@@ -112883,7 +113651,7 @@ var {
112883
113651
  lstatSync: lstatSync5,
112884
113652
  mkdirSync: mkdirSync19,
112885
113653
  readFileSync: readFileSync44,
112886
- readdirSync: readdirSync14,
113654
+ readdirSync: readdirSync15,
112887
113655
  realpathSync: realpathSync13,
112888
113656
  statSync: statSync8,
112889
113657
  unlinkSync: unlinkSync10,
@@ -112996,7 +113764,7 @@ async function execFileText(command, args) {
112996
113764
  }
112997
113765
  async function readLinuxStartIdentity(pid) {
112998
113766
  try {
112999
- const stat = await readFile33(`/proc/${pid}/stat`, "utf8");
113767
+ const stat = await readFile34(`/proc/${pid}/stat`, "utf8");
113000
113768
  const commandEnd = stat.lastIndexOf(")");
113001
113769
  if (commandEnd < 0)
113002
113770
  return null;
@@ -113235,14 +114003,17 @@ async function isWorkerLockReleased(incarnation, record) {
113235
114003
  // packages/team-core/src/team-state-store/lock-record.ts
113236
114004
  async function buildLockRecord(ownerTag) {
113237
114005
  await registerLockWorker();
113238
- const processStart = await getProcessStartIdentity(process.pid);
114006
+ const processStart = await lockProcessStartLine(process.pid);
113239
114007
  return `${ownerTag} ${randomUUID6()}
113240
114008
  ${process.pid}
113241
114009
  ${Date.now()}
113242
114010
  ${lockOwnerInstanceId}
113243
- ${processStart ?? "unavailable"}
114011
+ ${processStart}
113244
114012
  `;
113245
114013
  }
114014
+ async function lockProcessStartLine(pid) {
114015
+ return await getProcessStartIdentity(pid) ?? "unavailable";
114016
+ }
113246
114017
  function errorCode2(error) {
113247
114018
  if (!(error instanceof Error) || !("code" in error))
113248
114019
  return null;
@@ -113271,8 +114042,8 @@ function parseLockOwner(content) {
113271
114042
  }
113272
114043
  async function readLockRecord(lockPath) {
113273
114044
  try {
113274
- const content = await readFile34(lockPath, "utf8");
113275
- const { mtimeMs } = await stat9(lockPath);
114045
+ const content = await readFile35(lockPath, "utf8");
114046
+ const { mtimeMs } = await stat11(lockPath);
113276
114047
  return { content, modifiedAtEpochMs: mtimeMs };
113277
114048
  } catch (error) {
113278
114049
  if (!(error instanceof Error))
@@ -113303,7 +114074,7 @@ async function isLockRecordStale(record, staleAfterMs) {
113303
114074
 
113304
114075
  // packages/team-core/src/team-state-store/lock-publish.ts
113305
114076
  async function pathMayExist(path, deps = {}) {
113306
- const accessPath = deps.access ?? access4;
114077
+ const accessPath = deps.access ?? access5;
113307
114078
  try {
113308
114079
  await accessPath(path);
113309
114080
  return true;
@@ -113320,7 +114091,7 @@ async function assertRetryableLockOpenError(lockPath, error, deps) {
113320
114091
  if (code === "EPERM") {
113321
114092
  if (await pathMayExist(lockPath, deps))
113322
114093
  return;
113323
- if ((deps?.platform ?? process.platform) === "win32" && await pathMayExist(dirname42(lockPath), deps))
114094
+ if ((deps?.platform ?? process.platform) === "win32" && await pathMayExist(dirname43(lockPath), deps))
113324
114095
  return;
113325
114096
  }
113326
114097
  throw error;
@@ -113340,7 +114111,7 @@ async function publishLockRecord(lockPath, record) {
113340
114111
  } catch (error) {
113341
114112
  markLockRecordReleased(record);
113342
114113
  await fileHandle.close();
113343
- await unlink3(lockPath).catch(() => {
114114
+ await unlink4(lockPath).catch(() => {
113344
114115
  return;
113345
114116
  });
113346
114117
  throw error;
@@ -113349,9 +114120,14 @@ async function publishLockRecord(lockPath, record) {
113349
114120
  return true;
113350
114121
  }
113351
114122
 
114123
+ // packages/team-core/src/team-state-store/lock-lease.ts
114124
+ import { randomUUID as randomUUID7 } from "node:crypto";
114125
+ import { open as open4, readdir as readdir18, readFile as readFile36, rename as rename9, rm as rm18 } from "node:fs/promises";
114126
+ import { basename as basename16, dirname as dirname44, join as join108 } from "node:path";
114127
+
113352
114128
  // packages/team-core/src/team-state-store/lock-reclaim.ts
113353
114129
  import { createHash as createHash10 } from "node:crypto";
113354
- import { unlink as unlink4 } from "node:fs/promises";
114130
+ import { unlink as unlink5 } from "node:fs/promises";
113355
114131
  var RECLAIM_UNLINK_ATTEMPTS = 3;
113356
114132
  var RECLAIM_UNLINK_RETRY_MS = 25;
113357
114133
  function delay2(ms) {
@@ -113364,7 +114140,7 @@ function reclaimGuardPath(lockPath, record) {
113364
114140
  }
113365
114141
  async function unlinkWithRetry(path, deps) {
113366
114142
  const wait = deps.delay ?? delay2;
113367
- const unlinkFile = deps.unlink ?? unlink4;
114143
+ const unlinkFile = deps.unlink ?? unlink5;
113368
114144
  for (let attempt = 1;; attempt += 1) {
113369
114145
  try {
113370
114146
  await unlinkFile(path);
@@ -113382,6 +114158,19 @@ async function unlinkWithRetry(path, deps) {
113382
114158
  }
113383
114159
  }
113384
114160
  async function removeLockRecordIfUnchanged(lockPath, expectedRecord, staleAfterMs, deps = {}) {
114161
+ return withRecordGuard(lockPath, expectedRecord, staleAfterMs, deps, async () => {
114162
+ const current = await readLockRecord(lockPath);
114163
+ if (current === null)
114164
+ return "absent";
114165
+ if (current.content !== expectedRecord || !await isLockRecordStale(current, staleAfterMs))
114166
+ return "changed";
114167
+ const unlinked = await unlinkWithRetry(lockPath, deps);
114168
+ if (unlinked !== "stuck")
114169
+ forgetLockRecord(expectedRecord);
114170
+ return unlinked === "absent" ? "absent" : unlinked;
114171
+ });
114172
+ }
114173
+ async function withRecordGuard(lockPath, expectedRecord, staleAfterMs, deps, act) {
113385
114174
  const guardPath = reclaimGuardPath(lockPath, expectedRecord);
113386
114175
  const guardRecord = await buildLockRecord("lock-reclaim");
113387
114176
  if (!await publishLockRecord(guardPath, guardRecord)) {
@@ -113392,15 +114181,7 @@ async function removeLockRecordIfUnchanged(lockPath, expectedRecord, staleAfterM
113392
114181
  return "busy";
113393
114182
  }
113394
114183
  try {
113395
- const current = await readLockRecord(lockPath);
113396
- if (current === null)
113397
- return "absent";
113398
- if (current.content !== expectedRecord || !await isLockRecordStale(current, staleAfterMs))
113399
- return "changed";
113400
- const unlinked = await unlinkWithRetry(lockPath, deps);
113401
- if (unlinked !== "stuck")
113402
- forgetLockRecord(expectedRecord);
113403
- return unlinked === "absent" ? "absent" : unlinked;
114184
+ return await act();
113404
114185
  } finally {
113405
114186
  markLockRecordReleased(guardRecord);
113406
114187
  if (await unlinkWithRetry(guardPath, deps) !== "stuck")
@@ -113408,6 +114189,97 @@ async function removeLockRecordIfUnchanged(lockPath, expectedRecord, staleAfterM
113408
114189
  }
113409
114190
  }
113410
114191
 
114192
+ // packages/team-core/src/team-state-store/lock-lease.ts
114193
+ class LockLeaseLostError extends Error {
114194
+ constructor(lockPath) {
114195
+ super(`The lock at ${lockPath} changed while it was handed over; the critical section was aborted.`);
114196
+ this.name = "LockLeaseLostError";
114197
+ }
114198
+ }
114199
+ var leaseTempPrefix = (lockPath) => `.${basename16(lockPath)}.`;
114200
+ var LEASE_TEMP_SUFFIX = ".lease";
114201
+ var UUID2 = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
114202
+ var escapeRegExp2 = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
114203
+ var leaseTempPattern = (lockPath) => new RegExp(`^\\.${escapeRegExp2(basename16(lockPath))}\\.${UUID2}\\.lease$`);
114204
+ async function replaceRecord(lockPath, content) {
114205
+ const temporary = join108(dirname44(lockPath), `${leaseTempPrefix(lockPath)}${randomUUID7()}${LEASE_TEMP_SUFFIX}`);
114206
+ try {
114207
+ const handle = await open4(temporary, "wx", 384);
114208
+ try {
114209
+ await handle.writeFile(content);
114210
+ } finally {
114211
+ await handle.close();
114212
+ }
114213
+ await rename9(temporary, lockPath);
114214
+ } catch (error) {
114215
+ await rm18(temporary, { force: true });
114216
+ throw error;
114217
+ }
114218
+ }
114219
+ async function removeLeftoverTemps(lockPath) {
114220
+ const pattern = leaseTempPattern(lockPath);
114221
+ let entries;
114222
+ try {
114223
+ entries = await readdir18(dirname44(lockPath));
114224
+ } catch (error) {
114225
+ if (error instanceof Error && "code" in error && error.code === "ENOENT")
114226
+ return;
114227
+ throw error;
114228
+ }
114229
+ for (const entry of entries) {
114230
+ if (pattern.test(entry))
114231
+ await rm18(join108(dirname44(lockPath), entry), { force: true });
114232
+ }
114233
+ }
114234
+ async function currentRecord(lockPath) {
114235
+ try {
114236
+ return await readFile36(lockPath, "utf8");
114237
+ } catch (error) {
114238
+ if (error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR"))
114239
+ return null;
114240
+ throw error;
114241
+ }
114242
+ }
114243
+ function createLockLease(lockPath, ownerRecord, ownerTag, options = {}) {
114244
+ const staleAfterMs = options.staleAfterMs ?? Number.POSITIVE_INFINITY;
114245
+ let handedTo = null;
114246
+ return {
114247
+ async handOver(pid) {
114248
+ if (handedTo !== null)
114249
+ throw new Error("The lock is already handed over; restore it first.");
114250
+ if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid)
114251
+ throw new Error(`Cannot hand the lock to pid ${pid}.`);
114252
+ if (await currentRecord(lockPath) !== ownerRecord)
114253
+ throw new LockLeaseLostError(lockPath);
114254
+ await removeLeftoverTemps(lockPath);
114255
+ const processStart = await lockProcessStartLine(pid);
114256
+ const record = `${ownerTag} ${randomUUID7()}
114257
+ ${pid}
114258
+ ${Date.now()}
114259
+ ${randomUUID7()}
114260
+ ${processStart}
114261
+ `;
114262
+ await replaceRecord(lockPath, record);
114263
+ handedTo = record;
114264
+ },
114265
+ async restore() {
114266
+ if (handedTo === null)
114267
+ throw new Error("The lock is not handed over.");
114268
+ const expected = handedTo;
114269
+ handedTo = null;
114270
+ const outcome = await withRecordGuard(lockPath, expected, staleAfterMs, {}, async () => {
114271
+ if (await currentRecord(lockPath) !== expected)
114272
+ return "lost";
114273
+ await options.beforeRestoreRename?.();
114274
+ await replaceRecord(lockPath, ownerRecord);
114275
+ return "restored";
114276
+ });
114277
+ if (outcome !== "restored")
114278
+ throw new LockLeaseLostError(lockPath);
114279
+ }
114280
+ };
114281
+ }
114282
+
113411
114283
  // packages/team-core/src/team-state-store/locks.ts
113412
114284
  var LOCK_RETRY_MS = 50;
113413
114285
  var LOCK_WAIT_TIMEOUT_MS = 15000;
@@ -113437,7 +114309,7 @@ async function withLock(lockPath, fn, opts) {
113437
114309
  const ownerTag = opts?.ownerTag ?? "owner";
113438
114310
  const record = await acquireLock(lockPath, ownerTag, staleAfterMs);
113439
114311
  try {
113440
- return await fn();
114312
+ return await fn(createLockLease(lockPath, record, ownerTag, { staleAfterMs }));
113441
114313
  } finally {
113442
114314
  markLockRecordReleased(record);
113443
114315
  const outcome = await removeLockRecordIfUnchanged(lockPath, record, staleAfterMs);
@@ -113454,20 +114326,382 @@ async function reapStaleLock(lockPath, staleAfterMs = DEFAULT_STALE_AFTER_MS, de
113454
114326
  return await removeLockRecordIfUnchanged(lockPath, observed.content, staleAfterMs, deps);
113455
114327
  }
113456
114328
 
114329
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/prompt-lock.ts
114330
+ function promptLockAt(path, hooks = {}) {
114331
+ return async () => {
114332
+ const held = keychainProcessState().heldPromptLocks;
114333
+ if (held.has(path))
114334
+ return null;
114335
+ held.add(path);
114336
+ let granted = false;
114337
+ try {
114338
+ await mkdir11(dirname45(path), { recursive: true, mode: 448 });
114339
+ await hooks.beforePublish?.();
114340
+ for (let attempt = 0;attempt < 2; attempt++) {
114341
+ const record = await buildLockRecord("keychain-prompt");
114342
+ if (await publishLockRecord(path, record)) {
114343
+ granted = true;
114344
+ return async () => {
114345
+ markLockRecordReleased(record);
114346
+ try {
114347
+ await (hooks.removeRecord ?? ((target, owned) => removeLockRecordIfUnchanged(target, owned, Number.POSITIVE_INFINITY)))(path, record);
114348
+ } finally {
114349
+ held.delete(path);
114350
+ }
114351
+ };
114352
+ }
114353
+ if (await reapStaleLock(path, Number.POSITIVE_INFINITY) !== "removed")
114354
+ return null;
114355
+ }
114356
+ return null;
114357
+ } finally {
114358
+ if (!granted)
114359
+ held.delete(path);
114360
+ }
114361
+ };
114362
+ }
114363
+
114364
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/darwin-backend.ts
114365
+ var ROW_9B_DEFAULT = "reinstall-notice";
114366
+ var helperAccess = () => sharedHelperAccess(() => {
114367
+ const { entryCandidates } = keychainProcessState();
114368
+ return resolveHelperAccess([...entryCandidates, ...bundleCandidates(import.meta.url), ...machineCandidates(homedir31())]);
114369
+ });
114370
+ function sharedHelperAccess(resolve) {
114371
+ const state = keychainProcessState();
114372
+ if (state.helperAccess !== undefined)
114373
+ return state.helperAccess;
114374
+ const started = resolve();
114375
+ state.helperAccess = started;
114376
+ started.then((access) => {
114377
+ if (access.kind === "unavailable" && state.helperAccess === started)
114378
+ state.helperAccess = undefined;
114379
+ }, () => {
114380
+ if (state.helperAccess === started)
114381
+ state.helperAccess = undefined;
114382
+ });
114383
+ return started;
114384
+ }
114385
+
114386
+ class HelperMissingForOwnedItem extends Error {
114387
+ }
114388
+ function asKeystoreError(error, pending) {
114389
+ if (!(error instanceof HelperReadError))
114390
+ return error;
114391
+ if (error.failure === "pending")
114392
+ return pending(error.message);
114393
+ if (error.failure === "locked")
114394
+ return Object.assign(new Error(error.message), { code: "-25308" });
114395
+ return error;
114396
+ }
114397
+ function createDarwinBackend(options) {
114398
+ const silently = options.silently ?? silentSecrets;
114399
+ const key = { service: options.service, name: options.account };
114400
+ const deps = {
114401
+ account: options.account,
114402
+ access: options.access,
114403
+ cache: options.cache ?? processApprovalCache(),
114404
+ background: options.background,
114405
+ takePromptLock: promptLockAt(join109(options.home ?? homedir31(), ".omo", "session-locks", `${options.account}.keychain-prompt`)),
114406
+ ownSilentGet: () => silently(() => options.secrets.get(key)),
114407
+ ownOverwrite: (value) => silently(() => options.secrets.set({ ...key, value })),
114408
+ ownDelete: (name) => name === options.account ? gatedSecrets(() => options.secrets.delete({ ...key, name })) : silently(() => options.secrets.delete({ ...key, name })),
114409
+ notice: options.notice,
114410
+ ...options.row8b === undefined ? {} : { row8b: options.row8b },
114411
+ ...options.handOff === undefined ? {} : { handOff: options.handOff },
114412
+ noDialog: options.noDialog === true
114413
+ };
114414
+ let unowned = false;
114415
+ return {
114416
+ read: async () => {
114417
+ const result = await readThroughHelper(deps, true);
114418
+ unowned = result.kind === "value" && result.source !== "owned";
114419
+ return result.kind === "value" ? result.value : null;
114420
+ },
114421
+ underLock: (lease) => lockedDarwinStore(deps, lease),
114422
+ migrationPending: () => unowned
114423
+ };
114424
+ }
114425
+ async function guardHelperlessRead(service, account, choice = ROW_9B_DEFAULT, probe = probeOwnerMarker) {
114426
+ if (choice === "dialog")
114427
+ return;
114428
+ if (await probe(service, account) === "helper-owned")
114429
+ throw new HelperMissingForOwnedItem("OmO's keychain helper is missing or damaged on this Mac. Reinstall omo, then try again.");
114430
+ }
114431
+
114432
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/store-binding.ts
114433
+ import { homedir as homedir32 } from "node:os";
114434
+
114435
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/creator-handoff.ts
114436
+ init_bun_file_shim();
114437
+ init_bun_spawn_shim();
114438
+ import { dirname as dirname47, posix as posix14 } from "node:path";
114439
+
114440
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/runtime-capabilities.ts
114441
+ init_zod();
114442
+ import { readFile as readFile37 } from "node:fs/promises";
114443
+ import { dirname as dirname46, join as join110 } from "node:path";
114444
+ var RUNTIME_CAPABILITIES_FILE = "omo-runtime-capabilities.json";
114445
+ var RUNTIME_CAPABILITIES = { keychainHandoff: 1 };
114446
+ var capabilitiesSchema = object({ keychainHandoff: number2().int() }).passthrough();
114447
+ async function runtimeDeclaresKeychainHandoff(runtime) {
114448
+ const text = await readFile37(join110(dirname46(runtime), RUNTIME_CAPABILITIES_FILE), "utf8").catch(() => null);
114449
+ if (text === null)
114450
+ return false;
114451
+ try {
114452
+ const parsed = capabilitiesSchema.safeParse(JSON.parse(text));
114453
+ return parsed.success && parsed.data.keychainHandoff >= RUNTIME_CAPABILITIES.keychainHandoff;
114454
+ } catch {
114455
+ return false;
114456
+ }
114457
+ }
114458
+
114459
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/creator-handoff.ts
114460
+ var DEVELOPER_ID_TEAM = 'anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] and certificate leaf[field.1.2.840.113635.100.6.1.13] and certificate leaf[subject.OU] = "523JNR86LZ"';
114461
+ var DESKTOP_RUNTIME_REQUIREMENT = `identifier "com.mengmota.omo-desktop-runtime" and ${DEVELOPER_ID_TEAM}`;
114462
+ var DESKTOP_APP_REQUIREMENT = DEVELOPER_ID_TEAM;
114463
+ var HANDOFF_ENV = "OMO_KEYCHAIN_HANDOFF";
114464
+ var HANDOFF_DEADLINE_MS = 45000;
114465
+ function desktopRuntimeCandidates(home, arch = process.arch) {
114466
+ const runtimeArch = arch === "arm64" ? "arm64" : "x64";
114467
+ return ["/Applications/OmO.app", posix14.join(home, "Applications", "OmO.app")].map((app) => ({
114468
+ app,
114469
+ runtime: posix14.join(app, "Contents", "Resources", "omo-runtime", `darwin-${runtimeArch}`, "omo")
114470
+ }));
114471
+ }
114472
+ var verifyBundle = async (app, requirement) => {
114473
+ const child = spawn(["/usr/bin/codesign", "--verify", "--deep", "--strict", `-R=${requirement}`, app], {
114474
+ stdin: "ignore",
114475
+ stdout: "ignore",
114476
+ stderr: "ignore"
114477
+ });
114478
+ return await child.exited === 0;
114479
+ };
114480
+ var runBounded = async (path, args, env, deadlineMs) => {
114481
+ const child = spawn([path, ...args], { cwd: dirname47(path), stdin: "ignore", stdout: "ignore", stderr: "ignore", env });
114482
+ let killed = false;
114483
+ const timer = setTimeout(() => {
114484
+ killed = true;
114485
+ child.kill("SIGKILL");
114486
+ }, deadlineMs);
114487
+ try {
114488
+ const code = await child.exited;
114489
+ return killed ? null : code;
114490
+ } finally {
114491
+ clearTimeout(timer);
114492
+ }
114493
+ };
114494
+ function createCreatorHandOff(options) {
114495
+ return async () => {
114496
+ const env = options.env ?? process.env;
114497
+ if (env[HANDOFF_ENV] === "1")
114498
+ return false;
114499
+ const checkRuntime = options.checkRuntime ?? verifyWithSecurityFramework;
114500
+ const checkBundle = options.checkBundle ?? verifyBundle;
114501
+ const declaresHandOff = options.declaresHandOff ?? runtimeDeclaresKeychainHandoff;
114502
+ const self = options.selfPath ?? process.execPath;
114503
+ for (const { app, runtime } of options.candidates) {
114504
+ if (runtime === self || !await bunFile(runtime).exists())
114505
+ continue;
114506
+ const verified = await Promise.resolve().then(async () => await checkBundle(app, DESKTOP_APP_REQUIREMENT) && await checkRuntime(runtime, DESKTOP_RUNTIME_REQUIREMENT) && await declaresHandOff(runtime)).catch(() => false);
114507
+ if (!verified)
114508
+ continue;
114509
+ const childEnv = { [HANDOFF_ENV]: "1" };
114510
+ if (env.HOME !== undefined)
114511
+ childEnv.HOME = env.HOME;
114512
+ const origin = options.origin ?? env.OMO_SERVICE_API_URL;
114513
+ if (origin !== undefined)
114514
+ childEnv.OMO_SERVICE_API_URL = origin;
114515
+ try {
114516
+ return await (options.run ?? runBounded)(runtime, ["account", "token"], childEnv, HANDOFF_DEADLINE_MS) === 0;
114517
+ } catch {
114518
+ return false;
114519
+ }
114520
+ }
114521
+ return false;
114522
+ };
114523
+ }
114524
+
114525
+ // packages/omo-opencode/src/cli/service-auth/keychain-helper/store-binding.ts
114526
+ var readers = new Map;
114527
+ var INJECTED_SECRETS = Symbol.for("omo.test.injectedSecrets");
114528
+ var isInjectedSecrets = (api) => api[INJECTED_SECRETS] === true;
114529
+ var backends = new Map;
114530
+ function processHandOff(origin) {
114531
+ return () => {
114532
+ const state = keychainProcessState();
114533
+ state.handOff ??= createCreatorHandOff({ candidates: desktopRuntimeCandidates(homedir32()), origin })();
114534
+ return state.handOff;
114535
+ };
114536
+ }
114537
+ function bindKeychainHelper(input) {
114538
+ const { secrets: real, key, options } = input;
114539
+ const eligible = input.platform === "darwin" && input.namespace === "omo-cli" && (options !== undefined || typeof Bun !== "undefined" && real === Bun.secrets && !isInjectedSecrets(real));
114540
+ const secrets = !eligible ? real : {
114541
+ get: (entry) => gatedSecrets(() => real.get(entry)),
114542
+ set: (entry) => gatedSecrets(() => real.set(entry)),
114543
+ delete: (entry) => gatedSecrets(() => real.delete(entry))
114544
+ };
114545
+ const cacheKey = `${key.service}
114546
+ ${key.name}
114547
+ ${input.background ? "bounded" : "interactive"}`;
114548
+ let own;
114549
+ const backend = () => {
114550
+ if (!eligible)
114551
+ return Promise.resolve(null);
114552
+ const known = options === undefined ? backends.get(cacheKey) : own;
114553
+ if (known !== undefined)
114554
+ return known;
114555
+ const created = (options?.access ?? helperAccess)().then((access) => access.kind !== "ready" ? null : createDarwinBackend({
114556
+ access,
114557
+ secrets: real,
114558
+ service: key.service,
114559
+ account: key.name,
114560
+ background: input.background,
114561
+ noDialog: options?.noDialog ?? process.env[HANDOFF_ENV] === "1",
114562
+ notice: input.notice,
114563
+ ...options?.home === undefined ? {} : { home: options.home },
114564
+ ...options?.row8b === undefined ? {} : { row8b: options.row8b },
114565
+ ...options?.silently === undefined ? {} : { silently: options.silently },
114566
+ ...options?.cache === undefined ? {} : { cache: options.cache },
114567
+ handOff: options === undefined ? processHandOff(input.origin) : options.handOff ?? (async () => false)
114568
+ }));
114569
+ if (options === undefined) {
114570
+ backends.set(cacheKey, created);
114571
+ created.then((found) => {
114572
+ if (found === null && backends.get(cacheKey) === created)
114573
+ backends.delete(cacheKey);
114574
+ });
114575
+ } else
114576
+ own = created;
114577
+ return created;
114578
+ };
114579
+ const reader = (helper) => {
114580
+ const known = readers.get(helper);
114581
+ if (known !== undefined)
114582
+ return known;
114583
+ const refuse = async () => {
114584
+ throw new Error("OmO's keychain helper changes the sign-in only under the session lock.");
114585
+ };
114586
+ const created = {
114587
+ get: async () => {
114588
+ try {
114589
+ return await helper.read();
114590
+ } catch (error) {
114591
+ throw asKeystoreError(error, (message) => input.pending(`${message} Credentials are never saved to a file.`));
114592
+ }
114593
+ },
114594
+ set: refuse,
114595
+ delete: refuse
114596
+ };
114597
+ readers.set(helper, created);
114598
+ return created;
114599
+ };
114600
+ return {
114601
+ secrets,
114602
+ eligible,
114603
+ backend,
114604
+ reader,
114605
+ isHelperReader: (api) => [...readers.values()].includes(api),
114606
+ guardHelperless: async () => {
114607
+ if (!eligible)
114608
+ return;
114609
+ if ((options?.noDialog ?? process.env[HANDOFF_ENV] === "1") === true)
114610
+ throw input.pending("The keychain hand-off cannot show a dialog.");
114611
+ await guardHelperlessRead(key.service, key.name, options?.row9b, options?.ownerMarker);
114612
+ }
114613
+ };
114614
+ }
114615
+ function lockedStoreView(helper, lease, codec, mapError, done) {
114616
+ const locked = helper.underLock(lease);
114617
+ const run = async (step) => {
114618
+ try {
114619
+ return await step();
114620
+ } catch (error) {
114621
+ throw mapError(error);
114622
+ } finally {
114623
+ done();
114624
+ }
114625
+ };
114626
+ return {
114627
+ read: () => run(async () => {
114628
+ const text = await locked.read();
114629
+ return text === null ? null : codec.parse(text);
114630
+ }),
114631
+ write: (value, intent = "update", beforeRetire) => run(async () => {
114632
+ const next = codec.amend === undefined ? value : codec.amend(await locked.read(), value);
114633
+ await locked.write(codec.serialize(next), intent, beforeRetire);
114634
+ }),
114635
+ clear: () => run(() => locked.clear()),
114636
+ recover: () => run(() => locked.recover()),
114637
+ settle: () => run(() => locked.settle())
114638
+ };
114639
+ }
114640
+
114641
+ // packages/omo-opencode/src/cli/service-auth/secret-service-lock.ts
114642
+ import { spawn as spawn5 } from "node:child_process";
114643
+ var DEFAULT_COLLECTION = "/org/freedesktop/secrets/aliases/default";
114644
+ var PROBE_TIMEOUT_MS2 = 1e4;
114645
+ var parseLockedReply = (stdout) => {
114646
+ const match = /<\s*(true|false)\s*>/.exec(stdout);
114647
+ if (match === null)
114648
+ return null;
114649
+ return match[1] === "true" ? "locked" : "unlocked";
114650
+ };
114651
+ var probeSecretServiceLock = () => new Promise((resolve) => {
114652
+ const child = spawn5("gdbus", [
114653
+ "call",
114654
+ "--session",
114655
+ "--dest",
114656
+ "org.freedesktop.secrets",
114657
+ "--object-path",
114658
+ DEFAULT_COLLECTION,
114659
+ "--method",
114660
+ "org.freedesktop.DBus.Properties.Get",
114661
+ "org.freedesktop.Secret.Collection",
114662
+ "Locked"
114663
+ ], { stdio: ["ignore", "pipe", "ignore"] });
114664
+ let stdout = "";
114665
+ const timer = setTimeout(() => {
114666
+ child.kill();
114667
+ resolve("unknown");
114668
+ }, PROBE_TIMEOUT_MS2);
114669
+ child.stdout.on("data", (chunk) => {
114670
+ stdout += chunk.toString();
114671
+ });
114672
+ child.on("error", () => {
114673
+ clearTimeout(timer);
114674
+ resolve("unknown");
114675
+ });
114676
+ child.on("close", (code) => {
114677
+ clearTimeout(timer);
114678
+ resolve(code === 0 ? parseLockedReply(stdout) ?? "absent" : "absent");
114679
+ });
114680
+ });
114681
+
113457
114682
  // packages/omo-opencode/src/cli/service-auth/credential-lock.ts
114683
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
114684
+ import { createHash as createHash11 } from "node:crypto";
114685
+ import { mkdir as mkdir12 } from "node:fs/promises";
114686
+ import { homedir as homedir33 } from "node:os";
114687
+ import { join as join112 } from "node:path";
113458
114688
  var held = new AsyncLocalStorage3;
113459
- function credentialLockPaths(api, home = homedir31()) {
114689
+ function credentialLockPaths(api, home = homedir33()) {
113460
114690
  const id = createHash11("sha256").update(serviceOrigin(api)).digest("hex");
113461
- const directory = join106(home, ".omo", "session-locks");
113462
- return { directory, lock: join106(directory, `${id}.lock`), desktopRecord: join106(directory, `${id}.desktop-generation.json`) };
114691
+ const directory = join112(home, ".omo", "session-locks");
114692
+ return { directory, lock: join112(directory, `${id}.lock`), desktopRecord: join112(directory, `${id}.desktop-generation.json`) };
113463
114693
  }
113464
- async function withCredentialLock(api, action, home = homedir31(), ownerTag = "cli-session") {
114694
+ function heldCredentialLease(api, home = homedir33()) {
114695
+ return held.getStore()?.get(credentialLockPaths(api, home).lock);
114696
+ }
114697
+ async function withCredentialLock(api, action, home = homedir33(), ownerTag = "cli-session") {
113465
114698
  const { directory, lock } = credentialLockPaths(api, home);
113466
114699
  const owned = held.getStore();
113467
- if (owned?.has(lock))
113468
- return action();
113469
- await mkdir11(directory, { recursive: true, mode: 448 });
113470
- return withLock(lock, () => held.run(new Set([...owned ?? [], lock]), action), {
114700
+ const outer = owned?.get(lock);
114701
+ if (outer !== undefined)
114702
+ return action(outer);
114703
+ await mkdir12(directory, { recursive: true, mode: 448 });
114704
+ return withLock(lock, (lease) => held.run(new Map([...owned ?? [], [lock, lease]]), () => action(lease)), {
113471
114705
  ownerTag,
113472
114706
  staleAfterMs: Number.POSITIVE_INFINITY
113473
114707
  });
@@ -113519,17 +114753,51 @@ function createCredentialStore(api, options = {}) {
113519
114753
  return {
113520
114754
  ...value,
113521
114755
  ...accountId === undefined ? {} : { accountId },
113522
- credentialGeneration: sameIdentity ? current?.credentialGeneration ?? randomUUID7() : randomUUID7()
114756
+ credentialGeneration: sameIdentity ? current?.credentialGeneration ?? randomUUID8() : randomUUID8()
113523
114757
  };
113524
- });
114758
+ }, options.keychainHelper);
114759
+ const sections = new WeakMap;
114760
+ const underLock = (lease) => {
114761
+ const known = sections.get(lease);
114762
+ if (known !== undefined)
114763
+ return known;
114764
+ const view = (async () => {
114765
+ const opened = await store.underLock?.(lease) ?? null;
114766
+ await opened?.recover();
114767
+ return opened;
114768
+ })();
114769
+ sections.set(lease, view);
114770
+ return view;
114771
+ };
114772
+ const held = async () => {
114773
+ const lease = heldCredentialLease(api, options.home);
114774
+ return lease === undefined ? null : underLock(lease);
114775
+ };
114776
+ const locked = async (helper, plain) => {
114777
+ if (heldCredentialLease(api, options.home) === undefined)
114778
+ await store.prepare?.();
114779
+ await withCredentialLock(api, async (lease) => {
114780
+ const view = await underLock(lease);
114781
+ await (view === null ? plain() : helper(view));
114782
+ }, options.home);
114783
+ };
113525
114784
  return {
113526
- read: store.read,
113527
- readAuthoritative: store.readAuthoritative,
113528
- write: (value) => withCredentialLock(api, () => store.write(value), options.home),
113529
- clear: () => withCredentialLock(api, store.clear, options.home)
114785
+ read: async () => {
114786
+ const view = await held();
114787
+ return view === null ? store.read() : view.read();
114788
+ },
114789
+ readAuthoritative: async () => {
114790
+ const view = await held();
114791
+ return view === null ? store.readAuthoritative() : view.read();
114792
+ },
114793
+ write: (value, intent, beforeRetire) => locked((view) => view.write(value, intent, beforeRetire), () => store.write(value)),
114794
+ clear: () => locked((view) => view.clear(), store.clear),
114795
+ ...store.prepare === undefined ? {} : { prepare: store.prepare },
114796
+ underLock,
114797
+ ...store.migrationPending === undefined ? {} : { migrationPending: store.migrationPending }
113530
114798
  };
113531
114799
  }
113532
- function createSealedStore(api, namespace, schema, secrets = typeof Bun === "undefined" ? null : Bun.secrets, platform = process.platform, lockProbe = probeSecretServiceLock, notice = stderrNoticeOncePerProcess, wait = SESSION_READ_WAIT, amendWrite) {
114800
+ function createSealedStore(api, namespace, schema, secrets = typeof Bun === "undefined" ? null : Bun.secrets, platform = process.platform, lockProbe = probeSecretServiceLock, notice = stderrNoticeOncePerProcess, wait = SESSION_READ_WAIT, amendWrite, keychainHelper) {
113533
114801
  if (!secrets)
113534
114802
  throw new SignInError("OmO sign-in needs Bun 1.4 or newer with OS credential storage. No file fallback is available.");
113535
114803
  const platformName = platform === "darwin" ? "macOS Keychain" : platform === "linux" ? "Linux Secret Service (libsecret and an unlocked keyring)" : platform === "win32" ? "Windows Credential Manager" : null;
@@ -113538,6 +114806,18 @@ function createSealedStore(api, namespace, schema, secrets = typeof Bun === "und
113538
114806
  const key = { service: namespace, name: credentialId(api) };
113539
114807
  const slot = `${key.service}
113540
114808
  ${key.name}`;
114809
+ const helper = bindKeychainHelper({
114810
+ platform,
114811
+ namespace,
114812
+ secrets,
114813
+ key,
114814
+ background: wait.kind === "bounded",
114815
+ origin: api,
114816
+ notice,
114817
+ pending: (message) => new KeychainApprovalPendingError(message),
114818
+ ...keychainHelper === undefined ? {} : { options: keychainHelper }
114819
+ });
114820
+ secrets = helper.secrets;
113541
114821
  const readsOf = (api) => {
113542
114822
  const known = processReads.get(api);
113543
114823
  if (known !== undefined)
@@ -113563,17 +114843,19 @@ ${key.name}`;
113563
114843
  reads.set(slot, read);
113564
114844
  return read;
113565
114845
  };
113566
- const waiting = platform === "darwin" ? `macOS Keychain is waiting for your approval: answer the "${basename15(process.execPath)} wants to access key ${namespace}" dialog ("Always Allow" stops it asking again)` : `${platformName} has not answered; it may be waiting for your approval or an unlock in a system dialog`;
114846
+ const waiting = platform === "darwin" ? `macOS Keychain is waiting for your approval: answer the "${basename17(process.execPath)} wants to access key ${namespace}" dialog ("Always Allow" stops it asking again)` : `${platformName} has not answered; it may be waiting for your approval or an unlock in a system dialog`;
114847
+ const helperWaiting = `macOS Keychain is waiting for your approval: answer the "OmO's keychain helper wants to access key ${namespace}" dialog`;
113567
114848
  const answered = async (api, fresh = false) => {
114849
+ const waitingFor = helper.isHelperReader(api) ? helperWaiting : waiting;
113568
114850
  const read = fresh ? Promise.resolve().then(() => api.get(key)) : sharedRead(api);
113569
114851
  let timer;
113570
114852
  try {
113571
114853
  if (wait.kind === "interactive") {
113572
- timer = setTimeout(() => wait.notice(`omo: ${waiting}.`), wait.noticeAfterMs);
114854
+ timer = setTimeout(() => wait.notice(`omo: ${waitingFor}.`), wait.noticeAfterMs);
113573
114855
  return await read;
113574
114856
  }
113575
114857
  const expired = new Promise((_, reject) => {
113576
- timer = setTimeout(() => reject(new KeychainApprovalPendingError(`${waiting}, then try again. Credentials are never saved to a file.`)), wait.deadlineMs);
114858
+ timer = setTimeout(() => reject(new KeychainApprovalPendingError(`${waitingFor}, then try again. Credentials are never saved to a file.`)), wait.deadlineMs);
113577
114859
  });
113578
114860
  return await Promise.race([read, expired]);
113579
114861
  } finally {
@@ -113598,41 +114880,76 @@ ${key.name}`;
113598
114880
  notice("omo: could not check whether the keyring is locked (gdbus or the Secret Service did not answer); using libsecret directly.");
113599
114881
  }
113600
114882
  };
113601
- const parsedRead = async (fresh) => {
114883
+ const parseStored = (value) => {
114884
+ try {
114885
+ return schema.parse(JSON.parse(value));
114886
+ } catch {
114887
+ throw new InvalidCredentialState(signInRoute() === "cli" ? "Stored sign-in data is invalid. Run omo account forget, then omo login." : "The OmO sign-in saved on this computer can't be read. Run omo account forget to remove it, then sign in again in the desktop app.");
114888
+ }
114889
+ };
114890
+ const previousOf = (raw) => {
114891
+ if (raw === null)
114892
+ return null;
114893
+ try {
114894
+ return schema.parse(JSON.parse(raw));
114895
+ } catch {
114896
+ return null;
114897
+ }
114898
+ };
114899
+ const rawRead = async (fresh) => {
113602
114900
  await assertUsable();
113603
- let value;
114901
+ const backend = await helper.backend();
113604
114902
  try {
113605
- value = await answered(secrets, fresh);
114903
+ if (backend === null)
114904
+ await helper.guardHelperless();
114905
+ return await answered(backend === null ? secrets : helper.reader(backend), fresh);
113606
114906
  } catch (error) {
113607
114907
  if (error instanceof KeychainApprovalPendingError)
113608
114908
  throw error;
114909
+ if (error instanceof HelperMissingForOwnedItem)
114910
+ throw new CredentialStoreError(error.message);
113609
114911
  throw unavailable(error);
113610
114912
  }
113611
- if (value === null)
113612
- return null;
113613
- try {
113614
- return schema.parse(JSON.parse(value));
113615
- } catch {
113616
- throw new InvalidCredentialState(signInRoute() === "cli" ? "Stored sign-in data is invalid. Run omo account forget, then omo login." : "The OmO sign-in saved on this computer can't be read. Run omo account forget to remove it, then sign in again in the desktop app.");
113617
- }
114913
+ };
114914
+ const parsedRead = async (fresh) => {
114915
+ const value = await rawRead(fresh);
114916
+ return value === null ? null : parseStored(value);
114917
+ };
114918
+ const lockedFailure = (error) => {
114919
+ const mapped = asKeystoreError(error, (message) => new KeychainApprovalPendingError(message));
114920
+ if (error instanceof HelperOldSlotsFull)
114921
+ return new CredentialStoreError(error.message);
114922
+ if (mapped instanceof KeychainApprovalPendingError || mapped instanceof SignInError)
114923
+ return mapped;
114924
+ if (mapped instanceof Error && mapped.name === "LockLeaseLostError")
114925
+ return mapped;
114926
+ return unavailable(mapped);
113618
114927
  };
113619
114928
  return {
113620
114929
  read: () => parsedRead(false),
113621
114930
  readAuthoritative: () => parsedRead(true),
114931
+ async prepare() {
114932
+ if (await helper.backend() !== null)
114933
+ await rawRead(false);
114934
+ },
114935
+ async underLock(lease) {
114936
+ const backend = await helper.backend();
114937
+ if (backend === null)
114938
+ return null;
114939
+ const codec = {
114940
+ parse: parseStored,
114941
+ serialize: (value) => JSON.stringify(schema.parse(value)),
114942
+ ...amendWrite === undefined ? {} : { amend: (raw, next) => amendWrite(previousOf(raw), next) }
114943
+ };
114944
+ return lockedStoreView(backend, lease, codec, lockedFailure, () => forget(helper.reader(backend)));
114945
+ },
114946
+ migrationPending: async () => (await helper.backend())?.migrationPending() ?? false,
113622
114947
  async write(value) {
113623
114948
  await assertUsable();
114949
+ if (await helper.backend() !== null)
114950
+ throw new Error("OmO's keychain helper writes only under the session lock.");
113624
114951
  try {
113625
- let next = value;
113626
- if (amendWrite !== undefined) {
113627
- const raw = await answered(secrets, true);
113628
- let previous = null;
113629
- if (raw !== null) {
113630
- try {
113631
- previous = schema.parse(JSON.parse(raw));
113632
- } catch {}
113633
- }
113634
- next = amendWrite(previous, value);
113635
- }
114952
+ const next = amendWrite === undefined ? value : amendWrite(previousOf(await answered(secrets, true)), value);
113636
114953
  await secrets.set({ ...key, value: JSON.stringify(schema.parse(next)) });
113637
114954
  } catch (error) {
113638
114955
  throw unavailable(error);
@@ -113641,6 +114958,8 @@ ${key.name}`;
113641
114958
  },
113642
114959
  async clear() {
113643
114960
  await assertUsable();
114961
+ if (await helper.backend() !== null)
114962
+ throw new Error("OmO's keychain helper deletes only under the session lock.");
113644
114963
  try {
113645
114964
  await secrets.delete(key);
113646
114965
  } catch (error) {
@@ -113750,17 +115069,62 @@ async function loginLoopback(session, options) {
113750
115069
  }
113751
115070
  }
113752
115071
 
115072
+ // packages/memory-core/src/sync/device-retire.ts
115073
+ import { createHash as createHash14, randomBytes as randomBytes6 } from "node:crypto";
115074
+ import { join as join115 } from "node:path";
115075
+
115076
+ // packages/memory-core/src/identity/layout.ts
115077
+ import { homedir as homedir34 } from "node:os";
115078
+ import { join as join113, resolve as resolve31 } from "node:path";
115079
+ var MEMORY_ROOT_ENV_VAR = "OMO_MEMORY_HOME";
115080
+ function defaultMemoryRoot() {
115081
+ return join113(homedir34(), ".omo", "memory");
115082
+ }
115083
+ function resolveMemoryRoot(env, cwd) {
115084
+ const override = env[MEMORY_ROOT_ENV_VAR];
115085
+ if (override === undefined || override.trim() === "") {
115086
+ return defaultMemoryRoot();
115087
+ }
115088
+ return resolve31(cwd, override);
115089
+ }
115090
+ // packages/memory-core/src/sync/pin-dir.ts
115091
+ import { join as join114 } from "node:path";
115092
+ var syncPinDir = (memoryRoot) => join114(memoryRoot, "sync-device");
115093
+
115094
+ // packages/memory-core/src/sync/device-retire.ts
115095
+ var trustAnchorRoot = (pinDir) => join115(pinDir, "trust-anchor");
115096
+ var trustAnchorKey = (account) => createHash14("sha256").update(account, "utf8").digest("base64url");
115097
+ var trustAnchorDir = (pinDir, account) => join115(trustAnchorRoot(pinDir), trustAnchorKey(account));
115098
+ var hasLiveTrustAnchor = async (pinDir) => {
115099
+ try {
115100
+ return (await readdir17(trustAnchorRoot(pinDir))).some((name) => !name.includes(".retired-"));
115101
+ } catch (error) {
115102
+ if (error instanceof Error && "code" in error && error.code === "ENOENT")
115103
+ return false;
115104
+ throw error;
115105
+ }
115106
+ };
115107
+ var retireSyncDevice = async (input) => {
115108
+ const dir = trustAnchorDir(input.pinDir, input.account);
115109
+ try {
115110
+ await rename8(dir, `${dir}.retired-${Date.now()}-${randomBytes6(4).toString("hex")}`);
115111
+ } catch (error) {
115112
+ if (!(error instanceof Error && ("code" in error) && error.code === "ENOENT"))
115113
+ throw error;
115114
+ }
115115
+ };
115116
+
113753
115117
  // packages/omo-opencode/src/cli/service-auth/session.ts
113754
- import { homedir as homedir32 } from "node:os";
115118
+ import { homedir as homedir35 } from "node:os";
113755
115119
 
113756
115120
  // packages/omo-opencode/src/cli/service-auth/signed-out-marker.ts
113757
115121
  init_zod();
113758
- import { mkdir as mkdir12, readFile as readFile35, rename as rename8, rm as rm17, writeFile as writeFile17 } from "node:fs/promises";
113759
- import { dirname as dirname43, join as join107 } from "node:path";
115122
+ import { mkdir as mkdir13, readFile as readFile38, rename as rename10, rm as rm19, writeFile as writeFile18 } from "node:fs/promises";
115123
+ import { dirname as dirname48, join as join116 } from "node:path";
113760
115124
  var markerSchema = object({ device: string2().nullable(), at: string2() });
113761
- var signedOutMarkerPath = (home, credential) => join107(home, ".omo", "account-state", `${credential}.signed-out.json`);
115125
+ var signedOutMarkerPath = (home, credential) => join116(home, ".omo", "account-state", `${credential}.signed-out.json`);
113762
115126
  async function readSignedOutMarker(path) {
113763
- const text = await readFile35(path, "utf8").catch(() => null);
115127
+ const text = await readFile38(path, "utf8").catch(() => null);
113764
115128
  if (text === null)
113765
115129
  return null;
113766
115130
  let value;
@@ -113773,12 +115137,12 @@ async function readSignedOutMarker(path) {
113773
115137
  return parsed.success ? parsed.data : null;
113774
115138
  }
113775
115139
  async function writeSignedOutMarker(path, device) {
113776
- await mkdir12(dirname43(path), { recursive: true, mode: 448 });
115140
+ await mkdir13(dirname48(path), { recursive: true, mode: 448 });
113777
115141
  const staging = `${path}.${process.pid}.tmp`;
113778
- await writeFile17(staging, JSON.stringify({ device, at: new Date().toISOString() }), { mode: 384 });
113779
- await rename8(staging, path);
115142
+ await writeFile18(staging, JSON.stringify({ device, at: new Date().toISOString() }), { mode: 384 });
115143
+ await rename10(staging, path);
113780
115144
  }
113781
- var clearSignedOutMarker = (path) => rm17(path, { force: true });
115145
+ var clearSignedOutMarker = (path) => rm19(path, { force: true });
113782
115146
 
113783
115147
  // packages/omo-opencode/src/cli/service-auth/session.ts
113784
115148
  class SessionEnded extends SignInError {
@@ -113791,19 +115155,33 @@ class SessionEnded extends SignInError {
113791
115155
  }
113792
115156
  }
113793
115157
  var DEVICE_REVOKING_REFUSALS = new Set(["account_deleted", "reauth_required", "device_revoked"]);
115158
+ var discardedOf = (credentials, cause) => ({
115159
+ kind: "credential",
115160
+ deviceId: credentials.device.id,
115161
+ accountId: credentials.accountId,
115162
+ owner: credentials.owner,
115163
+ cause
115164
+ });
113794
115165
  function createSession(options) {
113795
115166
  const api = serviceOrigin(options.api);
113796
115167
  const now = options.now ?? Date.now;
113797
- const { store, signal } = options;
113798
- const markerPath = signedOutMarkerPath(options.home ?? homedir32(), credentialId(api));
115168
+ const { store, signal, beforeKeysDiscarded } = options;
115169
+ const markerPath = signedOutMarkerPath(options.home ?? homedir35(), credentialId(api));
113799
115170
  async function locked(action) {
113800
115171
  signal?.throwIfAborted();
113801
- return withCredentialLock(api, async () => {
115172
+ if (heldCredentialLease(api, options.home) === undefined)
115173
+ await store.prepare?.();
115174
+ return withCredentialLock(api, async (lease) => {
113802
115175
  signal?.throwIfAborted();
113803
- return action();
115176
+ return action(await store.underLock?.(lease) ?? null);
113804
115177
  }, options.home);
113805
115178
  }
113806
115179
  const request = (path, init) => requestApi(api, path, init, signal);
115180
+ const accountOf = async (access) => {
115181
+ const body = await request("/v1/me", { headers: { authorization: `Bearer ${access}` } }).catch(() => null);
115182
+ const id = typeof body === "object" && body !== null && "account" in body && typeof body.account === "object" && body.account !== null && "id" in body.account ? body.account.id : undefined;
115183
+ return typeof id === "string" && id !== "" ? id : undefined;
115184
+ };
113807
115185
  async function refreshed(current) {
113808
115186
  if (current.refreshState === "uncertain" || current.refreshAttempt !== undefined) {
113809
115187
  throw new SessionEnded(`Refresh recovery can no longer be proved safe. ${signInHint("again")}`, false, "refresh_recovery_expired");
@@ -113820,6 +115198,7 @@ function createSession(options) {
113820
115198
  if (error instanceof CredentialStoreError)
113821
115199
  throw error;
113822
115200
  if (error instanceof ApiRefusal && error.status < 500 && ["unauthorized", "account_deleted", "reauth_required", "invalid_grant", "device_revoked"].includes(error.code)) {
115201
+ await beforeKeysDiscarded(discardedOf(current, "refused"));
113823
115202
  await store.clear();
113824
115203
  throw new SessionEnded(error.code === "reauth_required" ? `This session was ended because its refresh token was reused. ${signInHint("again")}` : refusalMessage(refusalGuidance(error.code, error.status)), DEVICE_REVOKING_REFUSALS.has(error.code), error.code);
113825
115204
  }
@@ -113831,9 +115210,12 @@ function createSession(options) {
113831
115210
  }
113832
115211
  }
113833
115212
  async function snapshot() {
113834
- return locked(async () => {
115213
+ return locked(async (view) => {
113835
115214
  const current = await store.read();
113836
- return current === null ? null : refreshed(current);
115215
+ if (current === null)
115216
+ return null;
115217
+ await view?.settle();
115218
+ return refreshed(current);
113837
115219
  });
113838
115220
  }
113839
115221
  return {
@@ -113845,7 +115227,18 @@ function createSession(options) {
113845
115227
  },
113846
115228
  async save(value) {
113847
115229
  await locked(async () => {
113848
- await store.write(value);
115230
+ let stored;
115231
+ try {
115232
+ stored = await store.readAuthoritative();
115233
+ } catch (error) {
115234
+ if (!(error instanceof InvalidCredentialState))
115235
+ throw error;
115236
+ await beforeKeysDiscarded({ kind: "unreadable" });
115237
+ stored = null;
115238
+ }
115239
+ if (stored !== null && stored.device.id !== value.device.id)
115240
+ await beforeKeysDiscarded(discardedOf(stored, "replaced"));
115241
+ await store.write(value, "fresh-sign-in", () => beforeKeysDiscarded({ kind: "unreadable" }));
113849
115242
  await clearSignedOutMarker(markerPath);
113850
115243
  });
113851
115244
  },
@@ -113871,12 +115264,16 @@ function createSession(options) {
113871
115264
  async logout() {
113872
115265
  return locked(async () => {
113873
115266
  let current = null;
115267
+ let account;
113874
115268
  try {
113875
115269
  current = await store.readAuthoritative();
113876
115270
  if (current !== null) {
113877
115271
  if (current.refreshState === "uncertain")
113878
115272
  return false;
113879
115273
  const access = Date.parse(current.accessTokenExpiresAt) <= now() ? (await refreshed(current)).accessToken : current.accessToken;
115274
+ if (current.accountId === undefined && current.owner === undefined && await beforeKeysDiscarded.wantsAccount?.() === true) {
115275
+ account = await accountOf(access);
115276
+ }
113880
115277
  await request(`/v1/devices/${encodeURIComponent(current.device.id)}`, {
113881
115278
  method: "DELETE",
113882
115279
  headers: { authorization: `Bearer ${access}` }
@@ -113891,6 +115288,9 @@ function createSession(options) {
113891
115288
  throw error;
113892
115289
  } finally {
113893
115290
  await writeSignedOutMarker(markerPath, current?.device.id ?? null);
115291
+ const stored = current === null ? null : await store.read().catch(() => current);
115292
+ if (stored !== null)
115293
+ await beforeKeysDiscarded(discardedOf(stored.accountId === undefined && account !== undefined ? { ...stored, accountId: account } : stored, "logout"));
113894
115294
  await store.clear();
113895
115295
  }
113896
115296
  });
@@ -113899,14 +115299,15 @@ function createSession(options) {
113899
115299
  signal?.throwIfAborted();
113900
115300
  const snapshot = await store.read();
113901
115301
  signal?.throwIfAborted();
113902
- if (snapshot !== null && snapshot.refreshState !== "uncertain" && snapshot.refreshAttempt === undefined && Date.parse(snapshot.accessTokenExpiresAt) > now() + 30000 && (expect === undefined || expect(snapshot)))
115302
+ if (snapshot !== null && snapshot.refreshState !== "uncertain" && snapshot.refreshAttempt === undefined && Date.parse(snapshot.accessTokenExpiresAt) > now() + 30000 && (expect === undefined || expect(snapshot)) && !await store.migrationPending?.())
113903
115303
  return snapshot.accessToken;
113904
- return locked(async () => {
115304
+ return locked(async (view) => {
113905
115305
  const current = await store.readAuthoritative();
113906
115306
  if (current === null)
113907
115307
  throw new SignInError(`Not signed in. ${signInHint("first")}`);
113908
115308
  if (expect !== undefined && !expect(current))
113909
115309
  throw new CredentialIdentityChanged;
115310
+ await view?.settle();
113910
115311
  return (await refreshed(current)).accessToken;
113911
115312
  });
113912
115313
  },
@@ -113927,6 +115328,26 @@ function createSession(options) {
113927
115328
  };
113928
115329
  }
113929
115330
 
115331
+ // packages/omo-opencode/src/cli/service-auth/sync-pin-retire.ts
115332
+ var reason = (error) => error instanceof Error && ("code" in error) && typeof error.code === "string" ? error.code : "unknown";
115333
+ function retireSyncPinOnDiscard(options) {
115334
+ const hook = async (discarded) => {
115335
+ if (discarded.kind === "unreadable") {
115336
+ options.log("memory sync: a stored sign-in could not be read while it was replaced; its sync pin was left in place");
115337
+ return;
115338
+ }
115339
+ const account = discarded.owner?.accountId ?? discarded.accountId;
115340
+ if (account === undefined)
115341
+ return;
115342
+ try {
115343
+ await retireSyncDevice({ pinDir: options.pinDir(), account });
115344
+ } catch (error) {
115345
+ options.log(`memory sync: the sync pin could not be retired (${reason(error)}); it was left in place`);
115346
+ }
115347
+ };
115348
+ return Object.assign(hook, { wantsAccount: () => hasLiveTrustAnchor(options.pinDir()).catch(() => false) });
115349
+ }
115350
+
113930
115351
  // packages/omo-opencode/src/cli/service-auth/commands.ts
113931
115352
  async function ensureServiceAvailable(session, api) {
113932
115353
  try {
@@ -113969,7 +115390,12 @@ async function run2(action, options) {
113969
115390
  try {
113970
115391
  const api = serviceOrigin(options.api ?? process.env.OMO_SERVICE_API_URL ?? "https://api.omo.dev");
113971
115392
  const store = createCredentialStore(api, { wait: INTERACTIVE_READ_WAIT });
113972
- const session = createSession({ api, store, signal: controller.signal });
115393
+ const session = createSession({
115394
+ api,
115395
+ store,
115396
+ signal: controller.signal,
115397
+ beforeKeysDiscarded: retireSyncPinOnDiscard({ pinDir: () => syncPinDir(resolveMemoryRoot(process.env, process.cwd())), log: (line) => console.error(line) })
115398
+ });
113973
115399
  if (action === "logout") {
113974
115400
  const revoked = await session.logout();
113975
115401
  console.log("Signed out of OmO. Stored credentials and device keys were removed.");
@@ -114029,6 +115455,10 @@ function refuseClosedServiceAuth() {
114029
115455
  }
114030
115456
  function configureClosedServiceAuthCommands(program) {
114031
115457
  for (const name of SERVICE_AUTH_COMMANDS) {
115458
+ if (name === "login") {
115459
+ configureClosedDeviceLogin(program);
115460
+ continue;
115461
+ }
114032
115462
  const command = program.command(name, { hidden: true }).helpOption(false).allowUnknownOption().allowExcessArguments().action(() => {
114033
115463
  console.error(SERVICE_ACCOUNTS_CLOSED_MESSAGE);
114034
115464
  process.exitCode = 1;
@@ -114036,6 +115466,17 @@ function configureClosedServiceAuthCommands(program) {
114036
115466
  command.help = refuseClosedServiceAuth;
114037
115467
  }
114038
115468
  }
115469
+ function configureClosedDeviceLogin(program) {
115470
+ const command = program.command("login", { hidden: true }).helpOption(false).allowUnknownOption().allowExcessArguments().option("--device").option("--no-browser").option("--api <url>").action((options) => {
115471
+ if (options.device !== true && options.browser !== false || command.args.length > 0) {
115472
+ console.error(SERVICE_ACCOUNTS_CLOSED_MESSAGE);
115473
+ process.exitCode = 1;
115474
+ return;
115475
+ }
115476
+ return run2("login", { ...options, device: true });
115477
+ });
115478
+ command.help = refuseClosedServiceAuth;
115479
+ }
114039
115480
  function configureServiceAuthCommands(program, open = serviceAccountsOpen()) {
114040
115481
  if (!open) {
114041
115482
  configureClosedServiceAuthCommands(program);
@@ -114237,11 +115678,11 @@ async function boulder(options) {
114237
115678
  // packages/omo-opencode/src/cli/codex-ulw-loop.ts
114238
115679
  import { spawn as spawn6 } from "node:child_process";
114239
115680
  import { existsSync as existsSync67, readFileSync as readFileSync45, realpathSync as realpathSync14 } from "node:fs";
114240
- import { homedir as homedir33 } from "node:os";
115681
+ import { homedir as homedir36 } from "node:os";
114241
115682
  var ULW_LOOP_DELEGATION_SENTINEL = "OMO_ULW_LOOP_DELEGATED";
114242
115683
  function resolveCodexUlwLoopCommand(input = {}) {
114243
115684
  const env = input.env ?? process.env;
114244
- const homeDir = input.homeDir ?? homedir33();
115685
+ const homeDir = input.homeDir ?? homedir36();
114245
115686
  const localComponentBin = resolveLocalUlwLoopBin(env, homeDir);
114246
115687
  if (localComponentBin !== null)
114247
115688
  return { executable: localComponentBin, argsPrefix: [] };
@@ -114484,7 +115925,7 @@ function linkedWorktrees(records) {
114484
115925
  }
114485
115926
  // packages/omo-opencode/src/cli/worktree-sweep/sweep.ts
114486
115927
  import { existsSync as existsSync68 } from "node:fs";
114487
- import { stat as stat10 } from "node:fs/promises";
115928
+ import { stat as stat12 } from "node:fs/promises";
114488
115929
  import os7 from "node:os";
114489
115930
  import { normalize as normalize2 } from "node:path";
114490
115931
 
@@ -114567,7 +116008,7 @@ async function isOlderThan(worktreePath, days, now) {
114567
116008
  if (days <= 0)
114568
116009
  return false;
114569
116010
  try {
114570
- const stats = await stat10(worktreePath);
116011
+ const stats = await stat12(worktreePath);
114571
116012
  return now - stats.mtimeMs > days * DAY_MS;
114572
116013
  } catch {
114573
116014
  return false;
@@ -114732,7 +116173,7 @@ prunes.
114732
116173
 
114733
116174
  // packages/omo-opencode/src/cli/config-migrate.ts
114734
116175
  init_startup_migration();
114735
- import { posix as posix13 } from "node:path";
116176
+ import { posix as posix15 } from "node:path";
114736
116177
  function reports(result) {
114737
116178
  return result.results.map((entry) => ({
114738
116179
  diagnostics: entry.diagnostics,
@@ -114766,7 +116207,7 @@ function runConfigMigrate(options = {}) {
114766
116207
  dryRun: options.dryRun ?? false,
114767
116208
  environment,
114768
116209
  ...homeDir === undefined ? {} : { env: { HOME: homeDir }, homeDir },
114769
- pathOperations: posix13
116210
+ pathOperations: posix15
114770
116211
  });
114771
116212
  const report = reports(result);
114772
116213
  const response = {