@iislee/opencodex 2.11.0 → 2.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (675) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +114 -19
  3. package/bin/ocx.mjs +164 -36
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-BF38heuV.js +104 -0
  6. package/gui/dist/assets/index-DMiI18Kv.css +1 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +19 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +376 -52
  44. package/src/adapters/base.ts +54 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +601 -0
  48. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  49. package/src/adapters/cursor/cursor-errors.ts +129 -6
  50. package/src/adapters/cursor/discovery.ts +61 -4
  51. package/src/adapters/cursor/effort-map.ts +27 -3
  52. package/src/adapters/cursor/framing.ts +39 -0
  53. package/src/adapters/cursor/h2-pool.ts +123 -0
  54. package/src/adapters/cursor/http1-bidi.ts +361 -0
  55. package/src/adapters/cursor/images.ts +704 -0
  56. package/src/adapters/cursor/live-models.ts +174 -58
  57. package/src/adapters/cursor/live-transport.ts +609 -170
  58. package/src/adapters/cursor/native-exec-common.ts +23 -2
  59. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  60. package/src/adapters/cursor/native-exec-network.ts +1 -1
  61. package/src/adapters/cursor/native-exec-shell.ts +0 -1
  62. package/src/adapters/cursor/native-exec.ts +101 -14
  63. package/src/adapters/cursor/protobuf-events.ts +829 -11
  64. package/src/adapters/cursor/protobuf-request.ts +383 -65
  65. package/src/adapters/cursor/request-builder.ts +237 -31
  66. package/src/adapters/cursor/tool-definitions.ts +242 -12
  67. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  68. package/src/adapters/cursor/transport.ts +22 -0
  69. package/src/adapters/cursor/types.ts +28 -1
  70. package/src/adapters/cursor.ts +133 -7
  71. package/src/adapters/google-antigravity-replay.ts +558 -34
  72. package/src/adapters/google-antigravity-wire.ts +43 -10
  73. package/src/adapters/google-http.ts +38 -10
  74. package/src/adapters/google-tool-schema.ts +80 -15
  75. package/src/adapters/google-truncation.ts +11 -0
  76. package/src/adapters/google.ts +618 -74
  77. package/src/adapters/identity.ts +39 -6
  78. package/src/adapters/kiro-errors.ts +11 -0
  79. package/src/adapters/kiro-events.ts +19 -1
  80. package/src/adapters/kiro-thinking.ts +18 -2
  81. package/src/adapters/kiro-tools.ts +10 -1
  82. package/src/adapters/kiro.ts +92 -54
  83. package/src/adapters/mimo-free.ts +17 -0
  84. package/src/adapters/openai-chat-url.ts +11 -0
  85. package/src/adapters/openai-chat.ts +1311 -336
  86. package/src/adapters/openai-responses-url.ts +16 -0
  87. package/src/adapters/openai-responses.ts +830 -56
  88. package/src/adapters/registry.ts +175 -0
  89. package/src/adapters/responses-tool-schema.ts +67 -0
  90. package/src/adapters/tool-call-id.ts +119 -0
  91. package/src/adapters/tool-catalog-nudge.ts +104 -21
  92. package/src/adapters/xai-web-search.ts +185 -0
  93. package/src/bridge.ts +428 -61
  94. package/src/chat/inbound.ts +43 -19
  95. package/src/chat/outbound.ts +82 -26
  96. package/src/claude/agents-inject.ts +32 -9
  97. package/src/claude/context-windows.ts +21 -5
  98. package/src/claude/desktop-3p.ts +243 -9
  99. package/src/claude/gateway-cache.ts +41 -4
  100. package/src/claude/inbound.ts +72 -3
  101. package/src/claude/model-info.ts +38 -15
  102. package/src/claude/outbound.ts +70 -16
  103. package/src/cli/account-api.ts +35 -1
  104. package/src/cli/account-auth.ts +33 -6
  105. package/src/cli/account-catalog-refresh.ts +14 -0
  106. package/src/cli/account-extended.ts +389 -2
  107. package/src/cli/account-main.ts +317 -0
  108. package/src/cli/account.ts +30 -6
  109. package/src/cli/agent.ts +45 -1
  110. package/src/cli/claude-agent-startup-sync.ts +73 -0
  111. package/src/cli/claude-desktop.ts +29 -4
  112. package/src/cli/claude.ts +103 -34
  113. package/src/cli/codex-log-guard-doctor.ts +103 -0
  114. package/src/cli/codex-shim-autorestore.ts +2 -0
  115. package/src/cli/codex-shim-readiness.ts +76 -0
  116. package/src/cli/combo.ts +8 -0
  117. package/src/cli/config-command.ts +74 -10
  118. package/src/cli/dispatch.ts +593 -0
  119. package/src/cli/doctor.ts +315 -43
  120. package/src/cli/ensure-desired-integrations.ts +152 -0
  121. package/src/cli/export-command.ts +46 -20
  122. package/src/cli/help.ts +20 -271
  123. package/src/cli/index.ts +378 -519
  124. package/src/cli/init.ts +4 -17
  125. package/src/cli/integrations.ts +120 -2
  126. package/src/cli/lab.ts +607 -0
  127. package/src/cli/launcher-context.ts +77 -0
  128. package/src/cli/minimax.ts +497 -0
  129. package/src/cli/models-runtime.ts +35 -2
  130. package/src/cli/models.ts +100 -14
  131. package/src/cli/observe.ts +92 -3
  132. package/src/cli/opencode.ts +4 -2
  133. package/src/cli/provider-runtime.ts +18 -1
  134. package/src/cli/provider.ts +24 -3
  135. package/src/cli/ready.ts +301 -0
  136. package/src/cli/registry.ts +437 -0
  137. package/src/cli/root.ts +86 -0
  138. package/src/cli/route-policy.ts +92 -0
  139. package/src/cli/runtime-api.ts +6 -3
  140. package/src/cli/star-prompt.ts +71 -15
  141. package/src/cli/status.ts +10 -3
  142. package/src/cli/system-restart-client.ts +146 -0
  143. package/src/cli/tray-proxy.ts +153 -6
  144. package/src/cli/v2.ts +105 -10
  145. package/src/cli.ts +1 -1
  146. package/src/clients/config-export.ts +1358 -21
  147. package/src/codex/account-label.ts +14 -1
  148. package/src/codex/account-lifecycle.ts +130 -13
  149. package/src/codex/account-namespaces.ts +49 -3
  150. package/src/codex/account-priority.ts +83 -0
  151. package/src/codex/account-store.ts +29 -2
  152. package/src/codex/account-usability.ts +25 -2
  153. package/src/codex/admission.ts +256 -0
  154. package/src/codex/affinity-debug.ts +162 -0
  155. package/src/codex/app-server-processes.ts +493 -106
  156. package/src/codex/app-server-restart-service.ts +232 -0
  157. package/src/codex/auth-api.ts +849 -242
  158. package/src/codex/auth-collision.ts +5 -3
  159. package/src/codex/auth-context.ts +345 -32
  160. package/src/codex/autostart-health.ts +8 -1
  161. package/src/codex/catalog/account-models.ts +67 -0
  162. package/src/codex/catalog/aggregation.ts +68 -10
  163. package/src/codex/catalog/bundled.ts +331 -33
  164. package/src/codex/catalog/effort.ts +121 -30
  165. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  166. package/src/codex/catalog/kinds.ts +2 -0
  167. package/src/codex/catalog/metadata.ts +529 -45
  168. package/src/codex/catalog/native-models.ts +72 -0
  169. package/src/codex/catalog/parsing.ts +224 -30
  170. package/src/codex/catalog/provider-fetch.ts +1460 -134
  171. package/src/codex/catalog/sync.ts +1449 -186
  172. package/src/codex/catalog-admission.ts +199 -0
  173. package/src/codex/catalog-refresh-status.ts +105 -0
  174. package/src/codex/catalog-write-serialization.ts +242 -0
  175. package/src/codex/catalog.ts +6 -3
  176. package/src/codex/codex-write-lock.ts +384 -0
  177. package/src/codex/convergence-types.ts +614 -0
  178. package/src/codex/convergence.ts +651 -0
  179. package/src/codex/coordinator-doctor.ts +332 -0
  180. package/src/codex/custom-model-catalog-migration.ts +176 -0
  181. package/src/codex/desired-state.ts +230 -0
  182. package/src/codex/features.ts +636 -39
  183. package/src/codex/generation.ts +202 -0
  184. package/src/codex/history-job.ts +407 -0
  185. package/src/codex/history-lock.ts +242 -0
  186. package/src/codex/history-migration-guardian.ts +26 -20
  187. package/src/codex/history-provider.ts +231 -28
  188. package/src/codex/history-transition.ts +105 -0
  189. package/src/codex/history-worker.ts +220 -0
  190. package/src/codex/inject-coordination.ts +290 -0
  191. package/src/codex/inject.ts +1073 -152
  192. package/src/codex/injected-marker.ts +37 -3
  193. package/src/codex/integration-record.ts +266 -0
  194. package/src/codex/internal/catalog-writer.ts +203 -0
  195. package/src/codex/internal/history-writer.ts +80 -0
  196. package/src/codex/journal.ts +66 -4
  197. package/src/codex/log-guard/inspect.ts +506 -0
  198. package/src/codex/log-guard/lock.ts +150 -0
  199. package/src/codex/log-guard/maintenance.ts +403 -0
  200. package/src/codex/log-guard/path-safety.ts +88 -0
  201. package/src/codex/log-guard/policy.ts +44 -0
  202. package/src/codex/log-guard/processes.ts +205 -0
  203. package/src/codex/log-guard/protection.ts +489 -0
  204. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  205. package/src/codex/main-account-cache.ts +24 -0
  206. package/src/codex/main-account.ts +29 -1
  207. package/src/codex/management-convergence.ts +167 -0
  208. package/src/codex/model-cache.ts +56 -10
  209. package/src/codex/model-entitlements.ts +353 -0
  210. package/src/codex/native-main-admission.ts +47 -0
  211. package/src/codex/native-main-auth-temp.ts +187 -0
  212. package/src/codex/native-main-claim.ts +178 -0
  213. package/src/codex/native-main-lock-file.ts +162 -0
  214. package/src/codex/native-main-owner.ts +329 -0
  215. package/src/codex/native-profile-api.ts +247 -0
  216. package/src/codex/native-profile-manager.ts +1531 -0
  217. package/src/codex/native-profile-processes.ts +121 -0
  218. package/src/codex/native-profile-recovery.ts +99 -0
  219. package/src/codex/native-profile-stage-store.ts +387 -0
  220. package/src/codex/native-profile-startup.ts +492 -0
  221. package/src/codex/native-profile-store.ts +855 -0
  222. package/src/codex/native-profile-types.ts +120 -0
  223. package/src/codex/native-residue.ts +682 -0
  224. package/src/codex/paths.ts +80 -1
  225. package/src/codex/plan-from-token.ts +140 -0
  226. package/src/codex/plan.ts +40 -0
  227. package/src/codex/plugins-doctor.ts +1 -1
  228. package/src/codex/pool-rotation.ts +74 -4
  229. package/src/codex/project-config-warnings.ts +20 -6
  230. package/src/codex/prompt-journal.ts +352 -0
  231. package/src/codex/prompt-layers.ts +967 -0
  232. package/src/codex/prompt-lock.ts +143 -0
  233. package/src/codex/quota-rejection.ts +298 -0
  234. package/src/codex/quota.ts +175 -13
  235. package/src/codex/refresh.ts +11 -2
  236. package/src/codex/reset-credit-recovery.ts +1044 -0
  237. package/src/codex/routing.ts +505 -94
  238. package/src/codex/runtime.ts +159 -38
  239. package/src/codex/shim.ts +1009 -28
  240. package/src/codex/subagent-model-fallback.ts +350 -35
  241. package/src/codex/sync.ts +191 -2
  242. package/src/codex/transition-state.ts +612 -0
  243. package/src/codex/upstream-host-health.ts +368 -0
  244. package/src/codex/user-identity.ts +557 -0
  245. package/src/codex/warmup.ts +187 -81
  246. package/src/codex/write-coordination.ts +114 -0
  247. package/src/combos/failover.ts +20 -0
  248. package/src/combos/index.ts +4 -0
  249. package/src/combos/request.ts +32 -0
  250. package/src/combos/types.ts +81 -9
  251. package/src/config/provider-name.ts +24 -0
  252. package/src/config.ts +1762 -140
  253. package/src/generated/compatibility-version.json +3164 -0
  254. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  255. package/src/grok/inject.ts +16 -5
  256. package/src/grok/inspect.ts +45 -0
  257. package/src/grok/sync.ts +2 -2
  258. package/src/images/loop.ts +152 -29
  259. package/src/images/plan.ts +23 -13
  260. package/src/integrations/config-io.ts +269 -0
  261. package/src/integrations/journal.ts +315 -0
  262. package/src/integrations/merge.ts +135 -0
  263. package/src/integrations/mutation-flight.ts +71 -0
  264. package/src/integrations/native/ownership-preflight.ts +202 -0
  265. package/src/integrations/omp-yaml-source.ts +358 -0
  266. package/src/integrations/owned-refresh.ts +74 -0
  267. package/src/integrations/ownership.ts +111 -0
  268. package/src/integrations/registry.ts +159 -0
  269. package/src/integrations/serialize.ts +314 -0
  270. package/src/integrations/state.ts +361 -0
  271. package/src/integrations/store.ts +103 -0
  272. package/src/integrations/writer-lock.ts +98 -0
  273. package/src/integrations/writer.ts +691 -0
  274. package/src/lab/artifacts/sanitize.ts +586 -0
  275. package/src/lab/artifacts/secure-fs.ts +475 -0
  276. package/src/lab/artifacts/store.ts +310 -0
  277. package/src/lab/automation/budgets.ts +78 -0
  278. package/src/lab/automation/config-persistence.ts +256 -0
  279. package/src/lab/automation/constants.ts +39 -0
  280. package/src/lab/automation/cooldown.ts +103 -0
  281. package/src/lab/automation/dispatch.ts +211 -0
  282. package/src/lab/automation/index.ts +13 -0
  283. package/src/lab/automation/orchestrator.ts +499 -0
  284. package/src/lab/automation/persistence.ts +512 -0
  285. package/src/lab/automation/planner.ts +371 -0
  286. package/src/lab/automation/policy.ts +136 -0
  287. package/src/lab/automation/queue.ts +191 -0
  288. package/src/lab/automation/recovery.ts +24 -0
  289. package/src/lab/automation/route-context.ts +21 -0
  290. package/src/lab/automation/run-key.ts +44 -0
  291. package/src/lab/automation/runs-query.ts +34 -0
  292. package/src/lab/automation/types.ts +160 -0
  293. package/src/lab/conformance/assertion.ts +325 -0
  294. package/src/lab/conformance/digest.ts +22 -0
  295. package/src/lab/conformance/executor.ts +741 -0
  296. package/src/lab/conformance/fixture-provider.ts +27 -0
  297. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  298. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  299. package/src/lab/conformance/harness-budget.ts +47 -0
  300. package/src/lab/conformance/index.ts +5 -0
  301. package/src/lab/conformance/jcs.ts +64 -0
  302. package/src/lab/conformance/json-pointer.ts +39 -0
  303. package/src/lab/conformance/manifest.ts +180 -0
  304. package/src/lab/conformance/mcp-stub.ts +179 -0
  305. package/src/lab/conformance/negative-controls.ts +164 -0
  306. package/src/lab/conformance/observation.ts +355 -0
  307. package/src/lab/conformance/runner.ts +68 -0
  308. package/src/lab/conformance/sse-normalize.ts +59 -0
  309. package/src/lab/conformance/suite-manifest.ts +78 -0
  310. package/src/lab/conformance/types.ts +214 -0
  311. package/src/lab/constants.ts +126 -0
  312. package/src/lab/digest.ts +64 -0
  313. package/src/lab/events/errors.ts +9 -0
  314. package/src/lab/events/limits.ts +117 -0
  315. package/src/lab/events/types.ts +229 -0
  316. package/src/lab/events/validate.ts +781 -0
  317. package/src/lab/fabric/constants.ts +40 -0
  318. package/src/lab/fabric/executor.ts +492 -0
  319. package/src/lab/fabric/index.ts +80 -0
  320. package/src/lab/fabric/manifest.ts +222 -0
  321. package/src/lab/fabric/observe.ts +489 -0
  322. package/src/lab/fabric/patch.ts +79 -0
  323. package/src/lab/fabric/producer-child.ts +139 -0
  324. package/src/lab/fabric/producer-isolate.ts +276 -0
  325. package/src/lab/fabric/producer-protocol.ts +61 -0
  326. package/src/lab/fabric/scratch.ts +439 -0
  327. package/src/lab/fabric/subject.ts +106 -0
  328. package/src/lab/fabric/types.ts +134 -0
  329. package/src/lab/fabric/verifier.ts +98 -0
  330. package/src/lab/index.ts +54 -0
  331. package/src/lab/ledger/artifact-refs.ts +127 -0
  332. package/src/lab/ledger/invalidation.ts +136 -0
  333. package/src/lab/ledger/purge.ts +310 -0
  334. package/src/lab/ledger/store.ts +532 -0
  335. package/src/lab/live/credential-lease.ts +53 -0
  336. package/src/lab/live/destination.ts +155 -0
  337. package/src/lab/live/executor.ts +336 -0
  338. package/src/lab/live/inert-tools.ts +56 -0
  339. package/src/lab/live/manifest.ts +85 -0
  340. package/src/lab/live/mcp-loopback.ts +57 -0
  341. package/src/lab/live/runner.ts +19 -0
  342. package/src/lab/live/sandbox.ts +61 -0
  343. package/src/lab/live/suite-manifest.ts +41 -0
  344. package/src/lab/live/transport.ts +118 -0
  345. package/src/lab/live/types.ts +197 -0
  346. package/src/lab/observe/from-conformance.ts +301 -0
  347. package/src/lab/observe/from-live.ts +117 -0
  348. package/src/lab/paths.ts +153 -0
  349. package/src/lab/projection/rebuild.ts +495 -0
  350. package/src/lab/projection/schema.ts +135 -0
  351. package/src/lab/projection/verdicts.ts +474 -0
  352. package/src/lab/projection/verification.ts +412 -0
  353. package/src/lab/public/bundle.ts +217 -0
  354. package/src/lab/public/community-authority.ts +175 -0
  355. package/src/lab/public/community-files.ts +29 -0
  356. package/src/lab/public/community.ts +479 -0
  357. package/src/lab/public/file-safety.ts +155 -0
  358. package/src/lab/public/ids.ts +26 -0
  359. package/src/lab/public/index.ts +16 -0
  360. package/src/lab/public/mutation-lock.ts +424 -0
  361. package/src/lab/public/operator.ts +353 -0
  362. package/src/lab/public/origin-purge.ts +79 -0
  363. package/src/lab/public/origin.ts +203 -0
  364. package/src/lab/public/privacy.ts +143 -0
  365. package/src/lab/public/private-file.ts +261 -0
  366. package/src/lab/public/project.ts +124 -0
  367. package/src/lab/public/purge-test-fault.ts +21 -0
  368. package/src/lab/public/purge.ts +223 -0
  369. package/src/lab/public/registry.ts +44 -0
  370. package/src/lab/public/revocation.ts +252 -0
  371. package/src/lab/public/signature.ts +243 -0
  372. package/src/lab/public/storage.ts +105 -0
  373. package/src/lab/public/strict-json.ts +206 -0
  374. package/src/lab/public/time.ts +26 -0
  375. package/src/lab/public/types.ts +172 -0
  376. package/src/lab/public/validate.ts +391 -0
  377. package/src/lab/query/catalog.ts +101 -0
  378. package/src/lab/query/connection.ts +107 -0
  379. package/src/lab/query/constants.ts +4 -0
  380. package/src/lab/query/cursor.ts +132 -0
  381. package/src/lab/query/dto-map.ts +277 -0
  382. package/src/lab/query/errors.ts +22 -0
  383. package/src/lab/query/freshness.ts +53 -0
  384. package/src/lab/query/index.ts +45 -0
  385. package/src/lab/query/latest-observation.ts +59 -0
  386. package/src/lab/query/passive-production.ts +159 -0
  387. package/src/lab/query/queries.ts +444 -0
  388. package/src/lab/query/types.ts +266 -0
  389. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  390. package/src/lab/subject/installation-salt.ts +112 -0
  391. package/src/lab/subject/protocol-subject.ts +80 -0
  392. package/src/lab/subject/route-subject.ts +74 -0
  393. package/src/lib/app-owned-memory-stores.ts +22 -0
  394. package/src/lib/bounded-body.ts +153 -9
  395. package/src/lib/bun-runtime.ts +125 -12
  396. package/src/lib/bun-stream-caps.ts +13 -9
  397. package/src/lib/codex-restart-contract.ts +120 -0
  398. package/src/lib/config-ownership.ts +6 -2
  399. package/src/lib/destination-policy.ts +65 -1
  400. package/src/lib/errors.ts +44 -2
  401. package/src/lib/fabric-task-execution-authority.ts +7 -0
  402. package/src/lib/fabric-task-host.ts +29 -0
  403. package/src/lib/lab-activation.ts +223 -0
  404. package/src/lib/lab-live-execution-authority.ts +13 -0
  405. package/src/lib/lab-live-host.ts +30 -0
  406. package/src/lib/lab-live-pinned-sender.ts +56 -0
  407. package/src/lib/lab-live-route-production.ts +130 -0
  408. package/src/lib/lab-passive-linker-registration.ts +26 -0
  409. package/src/lib/local-management-attestation.ts +51 -0
  410. package/src/lib/local-management-capability.ts +100 -0
  411. package/src/lib/local-provider-reload-contract.ts +100 -0
  412. package/src/lib/optional-shutdown-hooks.ts +57 -0
  413. package/src/lib/pinned-http.ts +145 -26
  414. package/src/lib/process-control.ts +4 -1
  415. package/src/lib/provider-outbound.ts +49 -9
  416. package/src/lib/redact.ts +419 -3
  417. package/src/lib/self-launch-argv.ts +15 -0
  418. package/src/lib/server-resource-ownership.ts +71 -0
  419. package/src/lib/shadow-call.ts +35 -4
  420. package/src/lib/sse-decoder.ts +41 -0
  421. package/src/lib/state-store-registrations.ts +10 -2
  422. package/src/lib/system-restart-contract.ts +73 -0
  423. package/src/lib/token-estimate.ts +19 -2
  424. package/src/lib/tool-argument-integers.ts +202 -0
  425. package/src/lib/translator-budget.ts +44 -0
  426. package/src/lib/upstream-http-version.ts +57 -0
  427. package/src/lib/upstream-reachability.ts +95 -0
  428. package/src/lib/upstream-retry.ts +156 -3
  429. package/src/lib/windows-atomic-replace.ts +155 -0
  430. package/src/lib/windows-elevation.ts +70 -2
  431. package/src/lib/windows-secret-acl.ts +409 -69
  432. package/src/lib/windows-service-wrappers.ts +72 -0
  433. package/src/lib/windows-text.ts +106 -0
  434. package/src/lib/windows-user-principal.ts +341 -0
  435. package/src/lib/winsw.ts +33 -5
  436. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  437. package/src/oauth/account-import/index.ts +15 -0
  438. package/src/oauth/account-import/parser.ts +83 -0
  439. package/src/oauth/account-import/registry.ts +18 -0
  440. package/src/oauth/account-import/service.ts +75 -0
  441. package/src/oauth/account-import/types.ts +91 -0
  442. package/src/oauth/anthropic.ts +12 -1
  443. package/src/oauth/callback-server.ts +8 -2
  444. package/src/oauth/chatgpt.ts +12 -1
  445. package/src/oauth/command-code.ts +239 -0
  446. package/src/oauth/cursor.ts +46 -5
  447. package/src/oauth/google-antigravity.ts +35 -3
  448. package/src/oauth/health.ts +20 -12
  449. package/src/oauth/index.ts +398 -66
  450. package/src/oauth/key-providers.ts +16 -0
  451. package/src/oauth/kimi.ts +16 -2
  452. package/src/oauth/kiro.ts +50 -6
  453. package/src/oauth/local-token-detect.ts +11 -2
  454. package/src/oauth/log.ts +3 -1
  455. package/src/oauth/login-cli.ts +88 -28
  456. package/src/oauth/nous.ts +798 -0
  457. package/src/oauth/store.ts +119 -21
  458. package/src/oauth/token-guardian.ts +9 -3
  459. package/src/pi/models.ts +2 -2
  460. package/src/providers/alibaba-region-migration.ts +1 -1
  461. package/src/providers/antigravity-models.ts +521 -31
  462. package/src/providers/base-url-choices.ts +10 -0
  463. package/src/providers/codex-capacity.ts +292 -0
  464. package/src/providers/command-code-efforts.ts +144 -0
  465. package/src/providers/context-cap.ts +22 -5
  466. package/src/providers/cursor-pool.ts +72 -0
  467. package/src/providers/derive.ts +253 -6
  468. package/src/providers/fastwire.ts +501 -0
  469. package/src/providers/free-directory.ts +10 -7
  470. package/src/providers/google-vertex-location.ts +14 -0
  471. package/src/providers/key-failover.ts +71 -3
  472. package/src/providers/label.ts +1 -1
  473. package/src/providers/model-discovery-limits.ts +16 -0
  474. package/src/providers/model-discovery.ts +115 -22
  475. package/src/providers/model-rename-migration.ts +255 -0
  476. package/src/providers/model-rename-startup.ts +28 -0
  477. package/src/providers/openai-sidecar.ts +72 -4
  478. package/src/providers/openai-tier-startup.ts +31 -2
  479. package/src/providers/openai-tiers.ts +119 -4
  480. package/src/providers/openai-virtual-models.ts +1 -0
  481. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  482. package/src/providers/provider-id-rewrite.ts +29 -0
  483. package/src/providers/quota.ts +1319 -38
  484. package/src/providers/registry.ts +1429 -111
  485. package/src/providers/request-pacing.ts +310 -0
  486. package/src/providers/service-tier.ts +277 -0
  487. package/src/providers/slug-codec.ts +42 -6
  488. package/src/providers/static-model-discovery.ts +86 -0
  489. package/src/providers/xai-responses-opt-in.ts +15 -0
  490. package/src/providers/xai-transport.ts +11 -4
  491. package/src/reasoning-effort.ts +49 -1
  492. package/src/responses/compaction.ts +26 -1
  493. package/src/responses/custom-tool-compat.ts +266 -0
  494. package/src/responses/hosted-tool-policy.ts +9 -0
  495. package/src/responses/namespace-tool-compat.ts +355 -0
  496. package/src/responses/parser.ts +220 -38
  497. package/src/responses/provider-continuation.ts +98 -0
  498. package/src/responses/provider-opaque-metadata.ts +73 -0
  499. package/src/responses/reasoning-envelope.ts +9 -1
  500. package/src/responses/reasoning-replay-cache.ts +426 -0
  501. package/src/responses/schema.ts +7 -1
  502. package/src/responses/spill-store.ts +75 -10
  503. package/src/responses/state.ts +565 -27
  504. package/src/responses/thought-signature-replay.ts +347 -0
  505. package/src/responses/tool-search-compat.ts +301 -0
  506. package/src/responses/truncated-stop-reason.ts +60 -0
  507. package/src/router.ts +366 -30
  508. package/src/routing/analytics.ts +378 -0
  509. package/src/routing/capability.ts +244 -0
  510. package/src/routing/compatibility/assemble.ts +73 -0
  511. package/src/routing/compatibility/behavior.ts +278 -0
  512. package/src/routing/compatibility/catalog.ts +99 -0
  513. package/src/routing/compatibility/endpoint.ts +52 -0
  514. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  515. package/src/routing/compatibility/policy.ts +181 -0
  516. package/src/routing/compatibility/provider-slot.ts +56 -0
  517. package/src/routing/compatibility/reader.ts +110 -0
  518. package/src/routing/compatibility/subject.ts +191 -0
  519. package/src/routing/compatibility/types.ts +64 -0
  520. package/src/routing/compatibility/version.ts +104 -0
  521. package/src/routing/cost.ts +77 -0
  522. package/src/routing/evaluator.ts +495 -0
  523. package/src/routing/health.ts +412 -0
  524. package/src/routing/history/cursor.ts +43 -0
  525. package/src/routing/history/indexer.ts +605 -0
  526. package/src/routing/history/schema.ts +72 -0
  527. package/src/routing/profile-namespace.ts +15 -0
  528. package/src/routing/profile.ts +547 -0
  529. package/src/routing/quota.ts +145 -0
  530. package/src/routing/request-evidence.ts +45 -0
  531. package/src/routing/trace.ts +776 -0
  532. package/src/server/adapter-resolve.ts +2 -29
  533. package/src/server/auth-cors.ts +267 -46
  534. package/src/server/background-lifecycle.ts +182 -0
  535. package/src/server/chat-completions.ts +130 -56
  536. package/src/server/chat-native-sse.ts +331 -0
  537. package/src/server/chat-native.ts +426 -0
  538. package/src/server/claude-messages.ts +159 -43
  539. package/src/server/direct-local-http.ts +347 -0
  540. package/src/server/effort-policy.ts +18 -0
  541. package/src/server/github-copilot-responses-repair.ts +338 -0
  542. package/src/server/gui-static.ts +39 -10
  543. package/src/server/images.ts +94 -12
  544. package/src/server/index.ts +865 -181
  545. package/src/server/lifecycle.ts +284 -13
  546. package/src/server/live.ts +136 -17
  547. package/src/server/local-management-read-client.ts +90 -0
  548. package/src/server/local-provider-reload-client.ts +137 -0
  549. package/src/server/management/agent-settings-routes.ts +398 -103
  550. package/src/server/management/api-key-usage.ts +31 -5
  551. package/src/server/management/body.ts +6 -0
  552. package/src/server/management/combo-routes.ts +62 -24
  553. package/src/server/management/config-routes.ts +464 -51
  554. package/src/server/management/context.ts +80 -2
  555. package/src/server/management/integration-routes.ts +498 -0
  556. package/src/server/management/lab-automation-routes.ts +206 -0
  557. package/src/server/management/lab-routes.ts +563 -0
  558. package/src/server/management/logs-usage-routes.ts +101 -32
  559. package/src/server/management/model-routes.ts +189 -131
  560. package/src/server/management/model-rows.ts +163 -0
  561. package/src/server/management/native-integration-routes.ts +769 -0
  562. package/src/server/management/oauth-account-routes.ts +80 -4
  563. package/src/server/management/provider-capability-config.ts +48 -0
  564. package/src/server/management/provider-routes.ts +764 -157
  565. package/src/server/management/request-history-routes.ts +191 -0
  566. package/src/server/management/routing-analytics-routes.ts +74 -0
  567. package/src/server/management/routing-profile-routes.ts +380 -0
  568. package/src/server/management/shared.ts +27 -11
  569. package/src/server/management/sidebar-routes.ts +47 -31
  570. package/src/server/management/storage-log-guard-routes.ts +186 -0
  571. package/src/server/management/sync-response.ts +69 -0
  572. package/src/server/management/system-restart.ts +288 -32
  573. package/src/server/management/system-routes.ts +77 -0
  574. package/src/server/management/usage-summary-cache.ts +9 -1
  575. package/src/server/management/vision-sidecar-options.ts +167 -0
  576. package/src/server/management/web-search-sidecar-options.ts +120 -0
  577. package/src/server/management-api.ts +115 -14
  578. package/src/server/management-auth.ts +220 -5
  579. package/src/server/passive-route-linker.ts +66 -0
  580. package/src/server/ports.ts +41 -1
  581. package/src/server/proxy-liveness.ts +132 -5
  582. package/src/server/readiness.ts +99 -0
  583. package/src/server/relay-eager.ts +82 -42
  584. package/src/server/relay.ts +236 -76
  585. package/src/server/request-decompress.ts +113 -6
  586. package/src/server/request-log.ts +235 -22
  587. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  588. package/src/server/responses/agent-task-recovery.ts +465 -0
  589. package/src/server/responses/collaboration.ts +204 -35
  590. package/src/server/responses/compact.ts +442 -55
  591. package/src/server/responses/core.ts +2872 -331
  592. package/src/server/responses/empty-completion-guard.ts +276 -0
  593. package/src/server/responses/encrypted-payload.ts +62 -39
  594. package/src/server/responses/fetch-helpers.ts +79 -4
  595. package/src/server/responses/input-admission.ts +185 -0
  596. package/src/server/responses/pacing-overload.ts +13 -0
  597. package/src/server/responses/policy-fallback.ts +178 -0
  598. package/src/server/responses/responses-field-backfill.ts +251 -0
  599. package/src/server/responses/terminal-guard.ts +26 -5
  600. package/src/server/responses/upstream-error.ts +5 -0
  601. package/src/server/responses/ws-upstream.ts +308 -0
  602. package/src/server/responses-custom-tool-repair.ts +282 -0
  603. package/src/server/responses-item-id-repair.ts +54 -6
  604. package/src/server/responses-json-events.ts +90 -0
  605. package/src/server/responses-model-rewrite.ts +29 -0
  606. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  607. package/src/server/responses-snapshot-repair.ts +621 -0
  608. package/src/server/responses-terminal-repair.ts +342 -0
  609. package/src/server/responses-tool-search-repair.ts +267 -0
  610. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  611. package/src/server/responses.ts +18 -2
  612. package/src/server/search.ts +78 -13
  613. package/src/server/sse-frame-buffer.ts +292 -0
  614. package/src/server/sse-payload-rewrite.ts +110 -22
  615. package/src/server/startup-action-control.ts +8 -1
  616. package/src/server/startup-health-cache.ts +19 -1
  617. package/src/server/system-env.ts +80 -9
  618. package/src/server/ws-bridge.ts +39 -38
  619. package/src/service-manager-probe.ts +892 -0
  620. package/src/service.ts +1111 -90
  621. package/src/sidecar/auth.ts +92 -0
  622. package/src/sidecar/candidates.ts +83 -0
  623. package/src/storage/cleanup.ts +2 -2
  624. package/src/storage/scanner.ts +1 -1
  625. package/src/storage/worker-lifecycle.ts +14 -14
  626. package/src/tray/windows-tray.ps1 +83 -9
  627. package/src/tray/windows.ts +43 -16
  628. package/src/types/accounts.ts +37 -0
  629. package/src/types/config.ts +845 -0
  630. package/src/types/provider.ts +545 -0
  631. package/src/types/request.ts +384 -0
  632. package/src/types/tools.ts +131 -0
  633. package/src/types/wire.ts +80 -0
  634. package/src/types.ts +104 -1236
  635. package/src/update/index.ts +32 -19
  636. package/src/update/job.ts +442 -67
  637. package/src/update/notify.ts +12 -6
  638. package/src/update/npm-cache-preflight.d.mts +47 -0
  639. package/src/update/npm-cache-preflight.mjs +201 -0
  640. package/src/update/transactional-install.d.mts +22 -0
  641. package/src/update/transactional-install.mjs +259 -0
  642. package/src/usage/cost.ts +0 -0
  643. package/src/usage/expected-prices.ts +268 -16
  644. package/src/usage/log.ts +606 -41
  645. package/src/usage/summary.ts +177 -9
  646. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  647. package/src/usage/user-cost-overlays.ts +314 -0
  648. package/src/vision/anthropic-describe.ts +10 -6
  649. package/src/vision/backends.ts +97 -0
  650. package/src/vision/describe.ts +9 -3
  651. package/src/vision/eligibility.ts +250 -0
  652. package/src/vision/index.ts +238 -24
  653. package/src/vision/reasoning.ts +55 -0
  654. package/src/vision/routed-describe.ts +175 -0
  655. package/src/vision/timeout-bounds.ts +9 -0
  656. package/src/web-search/anthropic-executor.ts +13 -7
  657. package/src/web-search/backends.ts +108 -0
  658. package/src/web-search/exa-executor.ts +88 -0
  659. package/src/web-search/executor.ts +11 -3
  660. package/src/web-search/gemini-executor.ts +141 -0
  661. package/src/web-search/index.ts +150 -15
  662. package/src/web-search/loop.ts +279 -50
  663. package/src/web-search/parse.ts +125 -30
  664. package/src/web-search/sources.ts +60 -0
  665. package/src/web-search/xai-executor.ts +219 -0
  666. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  667. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  668. package/gui/dist/provider-icons/antigravity.svg +0 -1
  669. package/gui/dist/provider-icons/claude.svg +0 -1
  670. package/gui/dist/provider-icons/copilot.svg +0 -1
  671. package/gui/dist/provider-icons/cursor.svg +0 -2
  672. package/gui/dist/provider-icons/gemini.svg +0 -1
  673. package/gui/dist/provider-icons/grok-color.svg +0 -1
  674. package/gui/dist/provider-icons/kiro.svg +0 -14
  675. package/src/cli/internal-dispatch.ts +0 -20
@@ -0,0 +1,557 @@
1
+ /**
2
+ * Environment-independent identity and namespace resolution for Codex writes.
3
+ *
4
+ * Bun 1.3.14 made the obvious implementation unsafe: both `os.homedir()` and
5
+ * `os.userInfo().homedir` follow HOME. A service and CLI for the same account
6
+ * could therefore coordinate through different databases. The namespace is
7
+ * keyed only by the effective uid/SID and the canonical CODEX_HOME.
8
+ *
9
+ * Design record: devlog/_fin/260804_codex_write_substrate/005_contract.md §7.
10
+ */
11
+ import { createHash } from "node:crypto";
12
+ import {
13
+ lstatSync,
14
+ mkdirSync,
15
+ realpathSync,
16
+ statSync,
17
+ } from "node:fs";
18
+ import { isAbsolute, join, resolve } from "node:path";
19
+
20
+ import { resolveTrustedWindowsPowerShellExe } from "../lib/windows-elevation";
21
+
22
+ import type {
23
+ ResolveCodexCoordinatorDatabasePath,
24
+ ResolveCodexCatalogSerializationDatabasePath,
25
+ ResolveCodexHistorySerializationDatabasePath,
26
+ ResolveEffectiveUserIdentity,
27
+ UserIdentity,
28
+ } from "./convergence-types";
29
+
30
+ const POSIX_PRIVATE_MODE = 0o700;
31
+ const POSIX_TMP_REQUIRED_MODE = 0o1003;
32
+ const POSIX_TMP_PATH = "/tmp";
33
+ const SID_PATTERN = /^S-1-(?:\d+-)+\d+$/i;
34
+
35
+ /**
36
+ * Hard budget for the Windows identity-lookup PowerShell child. These lookups
37
+ * run at startup and on config writes; a hung child must fail the lookup
38
+ * (recoverable — the caller refuses) rather than wedge the proxy indefinitely.
39
+ */
40
+ const WINDOWS_POWERSHELL_LOOKUP_TIMEOUT_MS = 8_000;
41
+
42
+ /**
43
+ * The same budget, widened for a contended CI runner.
44
+ *
45
+ * 8s is a generous ceiling for `powershell.exe -Command` on a real desktop and is not one
46
+ * on a GitHub Windows runner executing a quarter of this suite: the composed-acceptance
47
+ * cases fail there with "Windows effective-account lookup timed out" while the child is
48
+ * still starting. That is runner contention, not a hung lookup, and the budget exists to
49
+ * bound the latter.
50
+ *
51
+ * Gated on `CI` alone. A user's machine keeps the 8s ceiling exactly as before, so the
52
+ * recoverable-refusal contract this budget protects is unchanged where it matters.
53
+ */
54
+ const WINDOWS_POWERSHELL_LOOKUP_TIMEOUT_CI_MS = 30_000;
55
+
56
+ function windowsIdentityLookupTimeoutMs(): number {
57
+ return process.env.CI === "true"
58
+ ? WINDOWS_POWERSHELL_LOOKUP_TIMEOUT_CI_MS
59
+ : WINDOWS_POWERSHELL_LOOKUP_TIMEOUT_MS;
60
+ }
61
+
62
+ /**
63
+ * FOLDERID_LocalAppData, and the flag that makes the lookup ignore the caller's
64
+ * environment.
65
+ *
66
+ * The obvious spelling, .NET's
67
+ * `GetFolderPath(SpecialFolder.LocalApplicationData)`, is unusable here: on
68
+ * Windows it resolves through `USERPROFILE`, and when the profile named there has
69
+ * no local AppData directory on disk it returns an EMPTY STRING rather than an
70
+ * error. Any
71
+ * caller that redirected `USERPROFILE` (the test sandbox does, and so does a
72
+ * service account whose profile has not been materialized) therefore refused every
73
+ * coordinator lookup with "returned an empty value", which is the exact
74
+ * environment dependence this module exists to eliminate.
75
+ *
76
+ * `SHGetKnownFolderPath` with a null token and `KF_FLAG_DEFAULT_PATH` reads the
77
+ * known-folder registration for the effective token instead: it returns the real
78
+ * per-user path whether or not the directory exists, and it is unaffected by
79
+ * `USERPROFILE`, `LOCALAPPDATA`, `HOMEDRIVE`, or `HOMEPATH`. A non-null token argument
80
+ * is NOT equivalent: passing (HANDLE)-1 resolves the DEFAULT USER profile
81
+ * (the built-in "Default" profile), which would key coordination to a namespace
82
+ * no real account writes to.
83
+ */
84
+ const WINDOWS_LOCAL_APPDATA_FOLDER_ID = "F1B32785-6FBA-4FCF-9D55-7B8E7F157091";
85
+ const WINDOWS_KF_FLAG_DEFAULT_PATH = "0x00000400";
86
+
87
+ export class CodexUserIdentityRefusal extends Error {
88
+ readonly code = "CODEX_USER_IDENTITY_REFUSED";
89
+
90
+ constructor(message: string, options?: ErrorOptions) {
91
+ super(message, options);
92
+ this.name = "CodexUserIdentityRefusal";
93
+ }
94
+ }
95
+
96
+ function refuse(message: string, cause?: unknown): never {
97
+ throw new CodexUserIdentityRefusal(message, cause === undefined ? undefined : { cause });
98
+ }
99
+
100
+ function windowsIdentityPowerShellCommand(expression: string): string[] {
101
+ // PowerShell 5.1 can encode redirected native/host output with the active
102
+ // Windows code page. Base64 contains ASCII only, while the payload is
103
+ // explicitly UTF-16LE, so Korean and Western profile paths arrive unchanged.
104
+ const deterministicOutput = [
105
+ "$ErrorActionPreference = 'Stop'",
106
+ `$ocxValue = [string](${expression})`,
107
+ "$ocxBytes = [System.Text.Encoding]::Unicode.GetBytes($ocxValue)",
108
+ "[Console]::Out.Write([Convert]::ToBase64String($ocxBytes))",
109
+ ].join("; ");
110
+ return [
111
+ resolveTrustedWindowsPowerShellExe(),
112
+ "-NoLogo",
113
+ "-NoProfile",
114
+ "-NonInteractive",
115
+ "-Command",
116
+ deterministicOutput,
117
+ ];
118
+ }
119
+
120
+ function windowsIdentityPowerShellSpawnOptions(): {
121
+ stdin: "ignore";
122
+ stdout: "pipe";
123
+ stderr: "pipe";
124
+ timeout: number;
125
+ windowsHide: boolean;
126
+ } {
127
+ return {
128
+ stdin: "ignore",
129
+ stdout: "pipe",
130
+ stderr: "pipe",
131
+ timeout: windowsIdentityLookupTimeoutMs(),
132
+ windowsHide: true,
133
+ };
134
+ }
135
+
136
+ /** Test-only readback of the trusted executable and static arguments (#1278). */
137
+ export function windowsIdentityPowerShellCommandForTests(expression: string): string[] {
138
+ return windowsIdentityPowerShellCommand(expression);
139
+ }
140
+
141
+ /**
142
+ * PowerShell expression yielding the effective account's local AppData path.
143
+ *
144
+ * P/Invoke rather than a .NET convenience wrapper, for the reason recorded on
145
+ * WINDOWS_LOCAL_APPDATA_FOLDER_ID: the wrapper follows `USERPROFILE` and answers
146
+ * an empty string for a profile whose directory is absent, which is precisely
147
+ * the environment dependence this module refuses to inherit. The type is added
148
+ * under a unique name per process because `Add-Type` cannot redefine one.
149
+ *
150
+ * The whole sequence is wrapped in one `$(...)` subexpression because the caller
151
+ * substitutes this text into `[string](<expression>)`; several statements
152
+ * spliced in bare would close that cast's parenthesis early and fail to parse.
153
+ */
154
+ function windowsLocalAppDataExpression(): string {
155
+ const signature =
156
+ '[DllImport("shell32.dll", CharSet = CharSet.Unicode)] public static extern int '
157
+ + 'SHGetKnownFolderPath(ref System.Guid id, uint flags, System.IntPtr token, out System.IntPtr path);';
158
+ const statements = [
159
+ `$ocxShell = Add-Type -MemberDefinition '${signature}'`
160
+ + " -Name OcxKnownFolder -Namespace OcxIdentity -PassThru",
161
+ `$ocxFolderId = [System.Guid]'${WINDOWS_LOCAL_APPDATA_FOLDER_ID}'`,
162
+ "$ocxPathPtr = [System.IntPtr]::Zero",
163
+ "$ocxHr = $ocxShell::SHGetKnownFolderPath([ref]$ocxFolderId, "
164
+ + `${WINDOWS_KF_FLAG_DEFAULT_PATH}, [System.IntPtr]::Zero, [ref]$ocxPathPtr)`,
165
+ "if ($ocxHr -ne 0) { throw 'SHGetKnownFolderPath failed' }",
166
+ "try { [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ocxPathPtr) }"
167
+ + " finally { [System.Runtime.InteropServices.Marshal]::FreeCoTaskMem($ocxPathPtr) }",
168
+ ];
169
+ return `$(${statements.join("; ")})`;
170
+ }
171
+
172
+ /** Test-only readback of the environment-independent known-folder expression. */
173
+ export function windowsLocalAppDataExpressionForTests(): string {
174
+ return windowsLocalAppDataExpression();
175
+ }
176
+
177
+ /** Test-only readback of the spawn options shared by the identity lookups (#1278). */
178
+ export function windowsIdentityPowerShellSpawnOptionsForTests(): ReturnType<
179
+ typeof windowsIdentityPowerShellSpawnOptions
180
+ > {
181
+ return windowsIdentityPowerShellSpawnOptions();
182
+ }
183
+
184
+ function decodeWindowsIdentityPowerShellOutput(output: Uint8Array): string {
185
+ let encoded: string;
186
+ try {
187
+ encoded = new TextDecoder("utf-8", { fatal: true }).decode(output).trim();
188
+ } catch (cause) {
189
+ refuse("Windows effective-account lookup returned a malformed value.", cause);
190
+ }
191
+ if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(encoded)) {
192
+ refuse("Windows effective-account lookup returned a malformed value.");
193
+ }
194
+ const bytes = Buffer.from(encoded, "base64");
195
+ if (bytes.length % 2 !== 0 || bytes.toString("base64") !== encoded) {
196
+ refuse("Windows effective-account lookup returned a malformed value.");
197
+ }
198
+ return bytes.toString("utf16le").trim();
199
+ }
200
+
201
+ /** Test-only decode seam for the deterministic PowerShell output contract. */
202
+ export function decodeWindowsIdentityPowerShellOutputForTests(output: Uint8Array): string {
203
+ return decodeWindowsIdentityPowerShellOutput(output);
204
+ }
205
+
206
+ /**
207
+ * Per-process memo for the Windows lookups.
208
+ *
209
+ * Both values -- the effective token's SID and its known-folder local AppData --
210
+ * are fixed for the lifetime of a process: neither can change without a new logon
211
+ * token, and the lookups deliberately ignore the environment, so nothing a caller
212
+ * does between two calls can alter the answer. Each call otherwise spawns a fresh
213
+ * PowerShell, roughly 150ms for the SID and 310ms for the folder, and the
214
+ * coordinator asks for both on every config write and lock acquisition. That cost
215
+ * pushed real multi-process injection tests past their budget while proving
216
+ * nothing: the second spawn re-derives what the first already established.
217
+ *
218
+ * Only successful lookups are memoized, so a transient failure cannot pin the
219
+ * process into a permanently refusing state.
220
+ */
221
+ const windowsIdentityValueCache = new Map<string, string>();
222
+
223
+ /** Test-only reset so a suite can force a fresh lookup. */
224
+ export function resetWindowsIdentityValueCacheForTests(): void {
225
+ windowsIdentityValueCache.clear();
226
+ }
227
+
228
+ function powershellValue(expression: string): string {
229
+ const memoized = windowsIdentityValueCache.get(expression);
230
+ if (memoized !== undefined) return memoized;
231
+ let command: string[];
232
+ try {
233
+ command = windowsIdentityPowerShellCommand(expression);
234
+ } catch (cause) {
235
+ refuse("Windows effective-account lookup could not start.", cause);
236
+ }
237
+ let result: ReturnType<typeof Bun.spawnSync>;
238
+ try {
239
+ // `windowsHide` is the popup fix (#1278): the desktop proxy parent runs
240
+ // without a console, so a console-subsystem child spawned without
241
+ // CREATE_NO_WINDOW gets a fresh visible console window at startup and on
242
+ // every config write. Do not add PowerShell's `-WindowStyle Hidden` here:
243
+ // Bun 1.3.14 can fail that direct CLI combination before the SID command
244
+ // executes (#1589); the process-level `windowsHide` flag is sufficient.
245
+ result = Bun.spawnSync(command, windowsIdentityPowerShellSpawnOptions());
246
+ } catch (cause) {
247
+ refuse("Windows effective-account lookup could not start.", cause);
248
+ }
249
+ if (result.exitedDueToTimeout) refuse("Windows effective-account lookup timed out.");
250
+ if (result.exitCode !== 0) refuse("Windows effective-account lookup failed.");
251
+ const value = decodeWindowsIdentityPowerShellOutput(result.stdout ?? Buffer.alloc(0));
252
+ if (!value) refuse("Windows effective-account lookup returned an empty value.");
253
+ windowsIdentityValueCache.set(expression, value);
254
+ return value;
255
+ }
256
+
257
+ function resolveWindowsSid(): string {
258
+ const sid = powershellValue(
259
+ "[System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value",
260
+ );
261
+ if (!SID_PATTERN.test(sid)) refuse("Windows effective-account lookup returned an invalid SID.");
262
+ return sid.toUpperCase();
263
+ }
264
+
265
+ export const resolveEffectiveUserIdentity: ResolveEffectiveUserIdentity = () => {
266
+ if (process.platform === "win32") {
267
+ return { platform: "win32", sid: resolveWindowsSid() };
268
+ }
269
+
270
+ const getuid = process.getuid;
271
+ if (typeof getuid !== "function") {
272
+ refuse("The runtime does not expose the effective POSIX uid.");
273
+ }
274
+ let uid: number;
275
+ try {
276
+ uid = getuid.call(process);
277
+ } catch (cause) {
278
+ refuse("The effective POSIX uid lookup failed.", cause);
279
+ }
280
+ if (!Number.isSafeInteger(uid) || uid < 0) {
281
+ refuse("The runtime returned an invalid effective POSIX uid.");
282
+ }
283
+ return { platform: "posix", uid };
284
+ };
285
+
286
+ function assertPrivatePosixDirectory(path: string, uid: number): void {
287
+ let entry;
288
+ try {
289
+ entry = lstatSync(path);
290
+ } catch (cause) {
291
+ refuse("The Codex coordinator namespace cannot be inspected.", cause);
292
+ }
293
+ if (entry.isSymbolicLink() || !entry.isDirectory()) {
294
+ refuse("The Codex coordinator namespace is not a real directory.");
295
+ }
296
+ if (entry.uid !== uid || (entry.mode & 0o777) !== POSIX_PRIVATE_MODE) {
297
+ refuse("The Codex coordinator namespace has unsafe ownership or permissions.");
298
+ }
299
+ }
300
+
301
+ function ensurePrivatePosixDirectory(path: string, uid: number): void {
302
+ try {
303
+ mkdirSync(path, { mode: POSIX_PRIVATE_MODE });
304
+ } catch (cause) {
305
+ const code = cause && typeof cause === "object" && "code" in cause
306
+ ? String((cause as { code?: unknown }).code)
307
+ : "";
308
+ if (code !== "EEXIST") refuse("The Codex coordinator namespace cannot be created.", cause);
309
+ }
310
+ assertPrivatePosixDirectory(path, uid);
311
+ }
312
+
313
+ function resolveTrustedPosixTmp(): string {
314
+ let realTmp: string;
315
+ try {
316
+ realTmp = realpathSync.native(POSIX_TMP_PATH);
317
+ const entry = statSync(realTmp);
318
+ if (!entry.isDirectory() || entry.uid !== 0) {
319
+ refuse("The system temporary directory has unsafe ownership.");
320
+ }
321
+ if ((entry.mode & POSIX_TMP_REQUIRED_MODE) !== POSIX_TMP_REQUIRED_MODE) {
322
+ refuse("The system temporary directory lacks sticky world write/search permissions.");
323
+ }
324
+ } catch (cause) {
325
+ if (cause instanceof CodexUserIdentityRefusal) throw cause;
326
+ refuse("The system temporary directory cannot be trusted.", cause);
327
+ }
328
+ return realTmp;
329
+ }
330
+
331
+ function resolvePosixRuntimeRoot(uid: number): string {
332
+ const realTmp = resolveTrustedPosixTmp();
333
+ const root = join(realTmp, `opencodex-runtime-v1-${uid}`);
334
+ ensurePrivatePosixDirectory(root, uid);
335
+ return root;
336
+ }
337
+
338
+ export type CoordinatorNamespaceProbe =
339
+ | { readonly status: "ok"; readonly root: string }
340
+ | { readonly status: "missing" };
341
+
342
+ /**
343
+ * Read-only namespace probe for diagnostics (`ocx doctor`).
344
+ *
345
+ * Unlike the runtime resolvers, this never creates the root or the lock
346
+ * directories: a doctor run must observe the namespace, not initialize it.
347
+ * A missing namespace is reported as `missing` instead of refused, so a fresh
348
+ * machine does not read as a broken one; an existing but unsafe namespace is
349
+ * refused exactly like the creating path would refuse it.
350
+ */
351
+ export function probeCodexCoordinatorNamespace(identity: UserIdentity): CoordinatorNamespaceProbe {
352
+ if (identity.platform === "posix") {
353
+ const root = join(resolveTrustedPosixTmp(), `opencodex-runtime-v1-${identity.uid}`);
354
+ let entry;
355
+ try {
356
+ entry = lstatSync(root);
357
+ } catch (cause) {
358
+ const code = cause && typeof cause === "object" && "code" in cause
359
+ ? String((cause as { code?: unknown }).code)
360
+ : "";
361
+ if (code === "ENOENT") return { status: "missing" };
362
+ refuse("The Codex coordinator namespace cannot be inspected.", cause);
363
+ }
364
+ if (entry.isSymbolicLink() || !entry.isDirectory()) {
365
+ refuse("The Codex coordinator namespace is not a real directory.");
366
+ }
367
+ if (entry.uid !== identity.uid || (entry.mode & 0o777) !== POSIX_PRIVATE_MODE) {
368
+ refuse("The Codex coordinator namespace has unsafe ownership or permissions.");
369
+ }
370
+ return { status: "ok", root };
371
+ }
372
+
373
+ if (!SID_PATTERN.test(identity.sid)) refuse("The coordinator identity contains an invalid SID.");
374
+ const localAppData = powershellValue(windowsLocalAppDataExpression());
375
+ if (!isAbsolute(localAppData)) refuse("Windows LocalAppData resolution returned a relative path.");
376
+ const root = resolve(localAppData, "OpenCodex", "Runtime", "v1", identity.sid.toUpperCase());
377
+ let entry;
378
+ try {
379
+ entry = lstatSync(root);
380
+ } catch (cause) {
381
+ const code = cause && typeof cause === "object" && "code" in cause
382
+ ? String((cause as { code?: unknown }).code)
383
+ : "";
384
+ if (code === "ENOENT") return { status: "missing" };
385
+ refuse("The Windows coordinator namespace cannot be inspected.", cause);
386
+ }
387
+ if (entry.isSymbolicLink() || !entry.isDirectory()) {
388
+ refuse("The Windows coordinator namespace is not a real directory.");
389
+ }
390
+ try {
391
+ const real = realpathSync.native(root);
392
+ if (!samePathIdentity(real, root, "win32")) {
393
+ refuse("The Windows coordinator namespace is redirected by a junction or reparse point.");
394
+ }
395
+ return { status: "ok", root: real };
396
+ } catch (cause) {
397
+ if (cause instanceof CodexUserIdentityRefusal) throw cause;
398
+ refuse("The Windows coordinator namespace cannot be resolved.", cause);
399
+ }
400
+ }
401
+
402
+ function resolveWindowsRuntimeRoot(identity: Extract<UserIdentity, { platform: "win32" }>): string {
403
+ if (!SID_PATTERN.test(identity.sid)) refuse("The coordinator identity contains an invalid SID.");
404
+ const localAppData = powershellValue(windowsLocalAppDataExpression());
405
+ if (!isAbsolute(localAppData)) refuse("Windows LocalAppData resolution returned a relative path.");
406
+
407
+ // The SID and known-folder values come from the effective token/.NET OS APIs,
408
+ // never USERPROFILE or LOCALAPPDATA. WP11 adds descriptor/reparse/ACL checks at
409
+ // the stable-database open boundary where those checks can cover SQLite too.
410
+ const root = resolve(localAppData, "OpenCodex", "Runtime", "v1", identity.sid.toUpperCase());
411
+ try {
412
+ mkdirSync(root, { recursive: true });
413
+ } catch (cause) {
414
+ refuse("The Windows coordinator namespace cannot be created.", cause);
415
+ }
416
+ // Canonicalize before anything is keyed on the path: a junctioned or
417
+ // differently-cased LocalAppData must land on ONE namespace, or two processes
418
+ // that share the real directory would build different lock paths and never
419
+ // contend. The lock modules also compare this path against realpath, so a
420
+ // non-canonical spelling here would read as "unsafe" on every acquisition.
421
+ //
422
+ // Canonicalizing must only ever fold spelling (case, separators). If the
423
+ // realpath lands somewhere else entirely, a component of the namespace is a
424
+ // junction/reparse redirect; accepting the target would convert the old
425
+ // refusal into silently opening the redirected location, so refuse instead.
426
+ try {
427
+ const real = realpathSync.native(root);
428
+ if (!samePathIdentity(real, root, "win32")) {
429
+ refuse("The Windows coordinator namespace is redirected by a junction or reparse point.");
430
+ }
431
+ return real;
432
+ } catch (cause) {
433
+ if (cause instanceof CodexUserIdentityRefusal) throw cause;
434
+ refuse("The Windows coordinator namespace cannot be resolved.", cause);
435
+ }
436
+ }
437
+
438
+ /**
439
+ * Windows path identity is case-insensitive; everywhere else it is exact.
440
+ *
441
+ * The lock modules compare a requested lock path against its own realpath, and
442
+ * byte equality refuses legitimate Windows spellings (drive-letter case, mixed
443
+ * component casing) as "unsafe". This is the same semantics
444
+ * `history-provider.ts` already applies to manifest paths; the platform
445
+ * argument exists so both branches are testable on any host.
446
+ */
447
+ export function samePathIdentity(
448
+ a: string,
449
+ b: string,
450
+ platform: NodeJS.Platform = process.platform,
451
+ ): boolean {
452
+ const left = resolve(a);
453
+ const right = resolve(b);
454
+ return platform === "win32" ? left.toLowerCase() === right.toLowerCase() : left === right;
455
+ }
456
+
457
+ export const resolveCodexCoordinatorDatabasePath: ResolveCodexCoordinatorDatabasePath = (
458
+ identity,
459
+ canonicalCodexHome,
460
+ ) => {
461
+ if (!isAbsolute(canonicalCodexHome)) {
462
+ refuse("The canonical CODEX_HOME must be an absolute path.");
463
+ }
464
+ const root = identity.platform === "posix"
465
+ ? resolvePosixRuntimeRoot(identity.uid)
466
+ : resolveWindowsRuntimeRoot(identity);
467
+ const locks = join(root, "native-write-locks");
468
+ if (identity.platform === "posix") ensurePrivatePosixDirectory(locks, identity.uid);
469
+ else {
470
+ try {
471
+ mkdirSync(locks, { recursive: true });
472
+ } catch (cause) {
473
+ refuse("The Windows coordinator lock directory cannot be created.", cause);
474
+ }
475
+ }
476
+
477
+ const homeDigest = createHash("sha256").update(canonicalCodexHome).digest("hex");
478
+ return join(locks, `${homeDigest}.sqlite`);
479
+ };
480
+
481
+ /**
482
+ * K's FINAL database path. Never the native coordinator path.
483
+ *
484
+ * Catalog serialization is a different ownership surface from the native
485
+ * coordinator N: `K -> C` is a legal order and `N -> K` nests, so sharing one
486
+ * database would make the required nesting self-contend. The two live in
487
+ * sibling directories under the same per-user runtime root — same identity
488
+ * namespace, same environment-independent parent, distinct exclusion.
489
+ *
490
+ * Consumers use the returned path verbatim and append nothing
491
+ * (`005_contract.md:1256-1330`).
492
+ */
493
+ export const resolveCodexCatalogSerializationDatabasePath:
494
+ ResolveCodexCatalogSerializationDatabasePath = (identity, canonicalCodexHome) => {
495
+ if (!isAbsolute(canonicalCodexHome)) {
496
+ refuse("The canonical CODEX_HOME must be an absolute path.");
497
+ }
498
+ const root = identity.platform === "posix"
499
+ ? resolvePosixRuntimeRoot(identity.uid)
500
+ : resolveWindowsRuntimeRoot(identity);
501
+ const locks = join(root, "catalog-write-locks");
502
+ if (identity.platform === "posix") ensurePrivatePosixDirectory(locks, identity.uid);
503
+ else {
504
+ try {
505
+ mkdirSync(locks, { recursive: true });
506
+ } catch (cause) {
507
+ refuse("The Windows catalog serialization directory cannot be created.", cause);
508
+ }
509
+ }
510
+
511
+ const homeDigest = createHash("sha256").update(canonicalCodexHome).digest("hex");
512
+ return join(locks, `${homeDigest}.sqlite`);
513
+ };
514
+
515
+ /**
516
+ * H's FINAL database path.
517
+ *
518
+ * Keyed by the canonical state DB in addition to the canonical home, unlike N and
519
+ * K. One `CODEX_HOME` can name a different `state_5.sqlite` — `model_catalog_json`
520
+ * has the same shape of indirection for catalogs — and two operations against
521
+ * different history databases are not the same exclusion. Hashing only the home
522
+ * would serialize them together, and hashing the raw request path would let two
523
+ * spellings of one database take different locks.
524
+ */
525
+ export const resolveCodexHistorySerializationDatabasePath:
526
+ ResolveCodexHistorySerializationDatabasePath = (
527
+ identity,
528
+ canonicalCodexHome,
529
+ canonicalStateDbPath,
530
+ ) => {
531
+ if (!isAbsolute(canonicalCodexHome)) {
532
+ refuse("The canonical CODEX_HOME must be an absolute path.");
533
+ }
534
+ if (!isAbsolute(canonicalStateDbPath)) {
535
+ refuse("The canonical Codex state database must be an absolute path.");
536
+ }
537
+ const root = identity.platform === "posix"
538
+ ? resolvePosixRuntimeRoot(identity.uid)
539
+ : resolveWindowsRuntimeRoot(identity);
540
+ const locks = join(root, "history-write-locks");
541
+ if (identity.platform === "posix") ensurePrivatePosixDirectory(locks, identity.uid);
542
+ else {
543
+ try {
544
+ mkdirSync(locks, { recursive: true });
545
+ } catch (cause) {
546
+ refuse("The Windows history serialization directory cannot be created.", cause);
547
+ }
548
+ }
549
+
550
+ // Both components are length-prefixed so no pair of (home, stateDb) values can
551
+ // collide by concatenation.
552
+ const digest = createHash("sha256")
553
+ .update(`${canonicalCodexHome.length}:${canonicalCodexHome}`)
554
+ .update(`${canonicalStateDbPath.length}:${canonicalStateDbPath}`)
555
+ .digest("hex");
556
+ return join(locks, `${digest}.sqlite`);
557
+ };