@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,612 @@
1
+ /**
2
+ * CODEX_HOME-keyed transition state and coordinator transaction ownership.
3
+ *
4
+ * The original JSON read/compare/replace was called a CAS while native and
5
+ * history writers held different locks. It was not one: an old Worker could
6
+ * replace N+1 with stale N. This module owns the SQLite row, the conditional
7
+ * UPDATE, and the opaque one-shot capability backed by an already-open
8
+ * `BEGIN IMMEDIATE` transaction.
9
+ *
10
+ * Design record: devlog/_fin/260804_codex_write_substrate/005_contract.md §1.
11
+ */
12
+ import { randomUUID } from "node:crypto";
13
+ import { chmodSync, lstatSync, realpathSync } from "node:fs";
14
+
15
+ import { Database } from "bun:sqlite";
16
+
17
+ import type {
18
+ BeginCodexTransition,
19
+ CodexCoordinatorTransaction,
20
+ CodexCoordinatorTransactionController,
21
+ CodexHistoryState,
22
+ CodexTransitionState,
23
+ CodexTransitionVersion,
24
+ CommitExpectation,
25
+ ReadCodexTransitionState,
26
+ TransitionStateRead,
27
+ TransitionStateUpdate,
28
+ UpdateCodexHistoryTransition,
29
+ } from "./convergence-types";
30
+ import { resolveCodexHomeDir } from "./home";
31
+ import { readIntegrationRecord } from "./integration-record";
32
+ import { classifyNativeRoutedResidue } from "./native-residue";
33
+ import {
34
+ CodexUserIdentityRefusal,
35
+ resolveCodexCoordinatorDatabasePath,
36
+ resolveEffectiveUserIdentity,
37
+ samePathIdentity,
38
+ } from "./user-identity";
39
+
40
+ export const CODEX_COORDINATOR_SCHEMA_VERSION = 1;
41
+ const DURABLE_HISTORY_STATUSES = new Set(["converged", "pending", "running", "blocked", "unknown"]);
42
+ const DURABLE_HISTORY_REASONS = new Set([
43
+ "db-busy",
44
+ "permission",
45
+ "unreadable",
46
+ "schema",
47
+ "timeout",
48
+ "shutdown-cancelled",
49
+ "worker-died",
50
+ "overtaken",
51
+ "record-write-failed",
52
+ ]);
53
+
54
+ const CREATE_TRANSITION_TABLE = `
55
+ CREATE TABLE IF NOT EXISTS codex_transition_state (
56
+ singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
57
+ native_generation INTEGER NOT NULL CHECK (native_generation >= 0),
58
+ current_tx_id TEXT,
59
+ history_status TEXT NOT NULL,
60
+ history_reason TEXT,
61
+ history_attempts INTEGER NOT NULL CHECK (history_attempts >= 0),
62
+ history_next_retry_at TEXT,
63
+ history_tx_id TEXT,
64
+ history_direction TEXT CHECK (history_direction IN ('apply', 'remove')),
65
+ history_authority_snapshot_id TEXT,
66
+ history_pending_rows INTEGER,
67
+ history_backup_entries INTEGER,
68
+ updated_at TEXT NOT NULL,
69
+ CHECK (history_status IN ('converged', 'pending', 'running', 'blocked', 'unknown')),
70
+ CHECK (history_reason IS NULL OR history_reason IN
71
+ ('db-busy', 'permission', 'unreadable', 'schema', 'timeout',
72
+ 'shutdown-cancelled', 'worker-died', 'overtaken', 'record-write-failed')),
73
+ CHECK (history_pending_rows IS NULL OR history_pending_rows >= 0),
74
+ CHECK (history_backup_entries IS NULL OR history_backup_entries >= 0),
75
+ CHECK ((native_generation = 0 AND current_tx_id IS NULL)
76
+ OR (native_generation > 0 AND length(trim(current_tx_id)) > 0)),
77
+ CHECK ((native_generation = 0
78
+ AND history_tx_id IS NULL
79
+ AND history_direction IS NULL
80
+ AND history_authority_snapshot_id IS NULL)
81
+ OR (native_generation > 0
82
+ AND history_tx_id = current_tx_id
83
+ AND history_direction IS NOT NULL
84
+ AND length(trim(history_authority_snapshot_id)) > 0)),
85
+ CHECK (native_generation > 0 OR
86
+ (history_status = 'unknown'
87
+ AND history_reason IS NULL
88
+ AND history_attempts = 0
89
+ AND history_next_retry_at IS NULL
90
+ AND history_pending_rows IS NULL
91
+ AND history_backup_entries IS NULL))
92
+ )`;
93
+
94
+ const INITIALIZE_TRANSITION_ROW = `
95
+ INSERT OR IGNORE INTO codex_transition_state (
96
+ singleton, native_generation, current_tx_id,
97
+ history_status, history_reason, history_attempts,
98
+ history_next_retry_at, history_tx_id, history_direction,
99
+ history_authority_snapshot_id, history_pending_rows,
100
+ history_backup_entries, updated_at
101
+ ) VALUES (1, 0, NULL, 'unknown', NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, ?)`;
102
+
103
+ const SELECT_TRANSITION_ROW = `
104
+ SELECT native_generation, current_tx_id,
105
+ history_status, history_reason, history_attempts,
106
+ history_next_retry_at, history_tx_id, history_direction,
107
+ history_authority_snapshot_id, history_pending_rows,
108
+ history_backup_entries
109
+ FROM codex_transition_state
110
+ WHERE singleton = 1`;
111
+
112
+ const BEGIN_TRANSITION = `
113
+ UPDATE codex_transition_state
114
+ SET native_generation = ?, current_tx_id = ?,
115
+ history_status = 'pending', history_reason = NULL,
116
+ history_attempts = 0, history_next_retry_at = ?, history_tx_id = ?,
117
+ history_direction = ?, history_authority_snapshot_id = ?,
118
+ history_pending_rows = NULL, history_backup_entries = NULL,
119
+ updated_at = ?
120
+ WHERE singleton = 1
121
+ AND native_generation = ?
122
+ AND current_tx_id IS ?`;
123
+
124
+ const UPDATE_HISTORY = `
125
+ UPDATE codex_transition_state
126
+ SET history_status = ?, history_reason = ?, history_attempts = ?,
127
+ history_next_retry_at = ?, history_tx_id = ?,
128
+ history_pending_rows = ?, history_backup_entries = ?, updated_at = ?
129
+ WHERE singleton = 1
130
+ AND native_generation = ?
131
+ AND current_tx_id IS ?
132
+ AND history_tx_id IS ?
133
+ AND (native_generation = 0 OR history_direction IS NOT NULL)`;
134
+
135
+ interface TransitionRow {
136
+ native_generation: unknown;
137
+ current_tx_id: unknown;
138
+ history_status: unknown;
139
+ history_reason: unknown;
140
+ history_attempts: unknown;
141
+ history_next_retry_at: unknown;
142
+ history_tx_id: unknown;
143
+ history_direction: unknown;
144
+ history_authority_snapshot_id: unknown;
145
+ history_pending_rows: unknown;
146
+ history_backup_entries: unknown;
147
+ }
148
+
149
+ const codexCoordinatorTransactionBrand: unique symbol = Symbol("CodexCoordinatorTransaction");
150
+
151
+ interface BrandedCodexCoordinatorTransaction extends CodexCoordinatorTransaction {
152
+ readonly [codexCoordinatorTransactionBrand]: true;
153
+ }
154
+
155
+ export class CodexCoordinatorTransactionError extends Error {
156
+ constructor(message: string, options?: ErrorOptions) {
157
+ super(message, options);
158
+ this.name = "CodexCoordinatorTransactionError";
159
+ }
160
+ }
161
+
162
+ class CodexCoordinatorLegacyAmbiguousError extends CodexCoordinatorTransactionError {
163
+ constructor(message: string) {
164
+ super(message);
165
+ this.name = "CodexCoordinatorLegacyAmbiguousError";
166
+ }
167
+ }
168
+
169
+ function errorCode(error: unknown): string {
170
+ return error && typeof error === "object" && "code" in error
171
+ ? String((error as { code?: unknown }).code)
172
+ : "";
173
+ }
174
+
175
+ function isBusy(error: unknown): boolean {
176
+ const code = errorCode(error);
177
+ const message = error instanceof Error ? error.message : String(error);
178
+ return code === "SQLITE_BUSY" || code === "SQLITE_LOCKED" || /database (?:is|table is) locked/i.test(message);
179
+ }
180
+
181
+ function isNonNegativeInteger(value: unknown): value is number {
182
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
183
+ }
184
+
185
+ function nullableString(value: unknown): value is string | null {
186
+ return value === null || typeof value === "string";
187
+ }
188
+
189
+ function nullableCount(value: unknown): value is number | null {
190
+ return value === null || isNonNegativeInteger(value);
191
+ }
192
+
193
+ function rowToState(row: TransitionRow | null): CodexTransitionState {
194
+ if (!row) throw new CodexCoordinatorTransactionError("The coordinator transition row is missing.");
195
+ if (!isNonNegativeInteger(row.native_generation)
196
+ || !nullableString(row.current_tx_id)
197
+ || typeof row.history_status !== "string"
198
+ || !DURABLE_HISTORY_STATUSES.has(row.history_status)
199
+ || !nullableString(row.history_reason)
200
+ || (row.history_reason !== null && !DURABLE_HISTORY_REASONS.has(row.history_reason))
201
+ || !isNonNegativeInteger(row.history_attempts)
202
+ || !nullableString(row.history_next_retry_at)
203
+ || !nullableString(row.history_tx_id)
204
+ || !nullableString(row.history_direction)
205
+ || !nullableString(row.history_authority_snapshot_id)
206
+ || !nullableCount(row.history_pending_rows)
207
+ || !nullableCount(row.history_backup_entries)) {
208
+ throw new CodexCoordinatorTransactionError("The coordinator transition row is malformed.");
209
+ }
210
+
211
+ const generation = row.native_generation;
212
+ if (generation === 0) {
213
+ if (row.current_tx_id !== null || row.history_tx_id !== null
214
+ || row.history_direction !== null || row.history_authority_snapshot_id !== null) {
215
+ throw new CodexCoordinatorTransactionError("The initial coordinator row contains transition metadata.");
216
+ }
217
+ } else if (!row.current_tx_id?.trim()
218
+ || row.history_tx_id !== row.current_tx_id
219
+ || (row.history_direction !== "apply" && row.history_direction !== "remove")
220
+ || !row.history_authority_snapshot_id?.trim()) {
221
+ throw new CodexCoordinatorTransactionError("The positive coordinator row lacks its complete history schedule.");
222
+ }
223
+
224
+ const history: CodexHistoryState = {
225
+ status: row.history_status as Exclude<CodexHistoryState["status"], "not-evaluated">,
226
+ attempts: row.history_attempts,
227
+ nextRetryAt: row.history_next_retry_at,
228
+ txId: row.history_tx_id,
229
+ pendingRows: row.history_pending_rows,
230
+ backupEntries: row.history_backup_entries,
231
+ ...(row.history_reason === null ? {} : { reason: row.history_reason as NonNullable<CodexHistoryState["reason"]> }),
232
+ };
233
+ return {
234
+ nativeGeneration: generation,
235
+ currentTxId: row.current_tx_id,
236
+ history,
237
+ historySchedule: generation === 0 ? null : {
238
+ direction: row.history_direction as "apply" | "remove",
239
+ authoritySnapshotId: row.history_authority_snapshot_id as string,
240
+ },
241
+ };
242
+ }
243
+
244
+ export function readCodexCoordinatorState(database: Database): CodexTransitionState {
245
+ const row = database.query<TransitionRow, []>(SELECT_TRANSITION_ROW).get();
246
+ return rowToState(row);
247
+ }
248
+
249
+ function validateHistoryWrite(expected: CodexTransitionVersion, history: CodexHistoryState): void {
250
+ if (history.status === "not-evaluated" || !DURABLE_HISTORY_STATUSES.has(history.status)) {
251
+ throw new CodexCoordinatorTransactionError("Ephemeral history state cannot be persisted.");
252
+ }
253
+ if (!isNonNegativeInteger(history.attempts)
254
+ || !nullableCount(history.pendingRows)
255
+ || !nullableCount(history.backupEntries)
256
+ || (history.reason !== undefined && !DURABLE_HISTORY_REASONS.has(history.reason))) {
257
+ throw new CodexCoordinatorTransactionError("The history update is malformed.");
258
+ }
259
+ if (history.txId !== expected.currentTxId) {
260
+ throw new CodexCoordinatorTransactionError("The history update does not belong to the expected transition.");
261
+ }
262
+ }
263
+
264
+ /**
265
+ * The missing-row incident proved that absence is not authority: installing
266
+ * `{0,null}` over a legacy JSON pair or routed native bytes loses the only
267
+ * evidence that an interrupted transition still needs salvage.
268
+ */
269
+ function assertInitialStateCanBeCreated(): void {
270
+ const integration = readIntegrationRecord();
271
+ if (integration.kind === "invalid") {
272
+ throw new CodexCoordinatorLegacyAmbiguousError(
273
+ "A missing coordinator row cannot be initialized over legacy or invalid Codex integration state.",
274
+ );
275
+ }
276
+ if (classifyNativeRoutedResidue().kind !== "clean") {
277
+ throw new CodexCoordinatorLegacyAmbiguousError(
278
+ "A missing coordinator row cannot be initialized while native Codex routing residue exists.",
279
+ );
280
+ }
281
+ }
282
+
283
+ function initialize(database: Database, databaseWasAbsent: boolean): void {
284
+ const version = database.query<{ user_version: number }, []>("PRAGMA user_version").get()?.user_version;
285
+ if (version !== 0 && version !== CODEX_COORDINATOR_SCHEMA_VERSION) {
286
+ throw new CodexCoordinatorTransactionError("The coordinator database schema version is unsupported.");
287
+ }
288
+ if (!databaseWasAbsent && version === 0) {
289
+ throw new CodexCoordinatorLegacyAmbiguousError(
290
+ "An existing unversioned coordinator database cannot be adopted automatically.",
291
+ );
292
+ }
293
+ database.exec(CREATE_TRANSITION_TABLE);
294
+ const existing = database.query<TransitionRow, []>(SELECT_TRANSITION_ROW).get();
295
+ if (!existing && !databaseWasAbsent) {
296
+ throw new CodexCoordinatorLegacyAmbiguousError(
297
+ "The existing coordinator database has no authoritative transition row.",
298
+ );
299
+ }
300
+ if (!existing) {
301
+ assertInitialStateCanBeCreated();
302
+ database.query(INITIALIZE_TRANSITION_ROW).run(new Date().toISOString());
303
+ }
304
+ if (version === 0) database.exec(`PRAGMA user_version = ${CODEX_COORDINATOR_SCHEMA_VERSION}`);
305
+ readCodexCoordinatorState(database);
306
+ }
307
+
308
+ function createCapability(
309
+ database: Database,
310
+ onResult: (result: TransitionStateUpdate) => void,
311
+ ): BrandedCodexCoordinatorTransaction {
312
+ let consumed = false;
313
+ return {
314
+ [codexCoordinatorTransactionBrand]: true,
315
+ beginTransition(expected, next) {
316
+ if (consumed) {
317
+ throw new CodexCoordinatorTransactionError("The coordinator capability has already been consumed.");
318
+ }
319
+ consumed = true;
320
+ if (!isNonNegativeInteger(expected.nativeGeneration)
321
+ || (expected.currentTxId !== null && !expected.currentTxId.trim())
322
+ || !next.txId.trim()
323
+ || (next.direction !== "apply" && next.direction !== "remove")
324
+ || !next.authoritySnapshotId.trim()) {
325
+ throw new CodexCoordinatorTransactionError("The transition update is malformed.");
326
+ }
327
+
328
+ const result = database.query(BEGIN_TRANSITION).run(
329
+ expected.nativeGeneration + 1,
330
+ next.txId,
331
+ next.nextRetryAt,
332
+ next.txId,
333
+ next.direction,
334
+ next.authoritySnapshotId,
335
+ new Date().toISOString(),
336
+ expected.nativeGeneration,
337
+ expected.currentTxId,
338
+ );
339
+ const state = readCodexCoordinatorState(database);
340
+ const update: TransitionStateUpdate = result.changes === 1
341
+ ? { kind: "updated", state }
342
+ : { kind: "conflict", current: state };
343
+ onResult(update);
344
+ return update;
345
+ },
346
+ };
347
+ }
348
+
349
+ export function openCodexCoordinatorTransaction(finalDatabasePath: string): CodexCoordinatorTransactionController {
350
+ let database: Database | undefined;
351
+ let transactionOpen = false;
352
+ let closed = false;
353
+ let lastResult: TransitionStateUpdate | undefined;
354
+ let initialIdentity: string | undefined;
355
+ let databaseWasAbsent = false;
356
+ let databaseWasEmpty = false;
357
+
358
+ try {
359
+ try {
360
+ const before = lstatSync(finalDatabasePath);
361
+ if (before.isSymbolicLink() || !before.isFile()) {
362
+ throw new CodexUserIdentityRefusal("The coordinator database path is not a real file.");
363
+ }
364
+ // sqlite3_open_v2(..., SQLITE_OPEN_CREATE) makes the pathname visible
365
+ // before the first schema write. A racing process can therefore observe a
366
+ // real but zero-byte file that carries no coordinator authority yet. Treat
367
+ // that exact state like ENOENT; any non-empty unversioned database remains
368
+ // legacy-ambiguous below.
369
+ databaseWasEmpty = before.size === 0;
370
+ if (process.platform !== "win32") {
371
+ const uid = process.getuid?.();
372
+ // Ownership is decided here; MODE is not.
373
+ //
374
+ // Two processes reaching first use together both observe ENOENT, and the
375
+ // loser can lstat the winner's file in the window between its creation
376
+ // and its chmod. Refusing on mode here read as a permission problem when
377
+ // it was a schedule — a real 1-in-12 flake on a 16-core box. Our own file
378
+ // is ours to narrow, so the mode decision moves below the open, where it
379
+ // can tighten once and then judge the settled state. A file owned by
380
+ // somebody else is still refused immediately: that is not a race, and no
381
+ // amount of waiting makes it ours.
382
+ if (uid === undefined || before.uid !== uid) {
383
+ throw new CodexUserIdentityRefusal(
384
+ "The coordinator database has unsafe ownership or permissions.",
385
+ );
386
+ }
387
+ }
388
+ } catch (cause) {
389
+ if (errorCode(cause) !== "ENOENT") throw cause;
390
+ databaseWasAbsent = true;
391
+ }
392
+ database = new Database(finalDatabasePath, { create: true });
393
+ if (databaseWasAbsent) {
394
+ try { chmodSync(finalDatabasePath, 0o600); } catch { /* Windows applies ACLs in WP11. */ }
395
+ }
396
+ // Re-check ownership and mode AFTER the open, not only before it.
397
+ //
398
+ // Two processes reaching first use together both see ENOENT, and the loser
399
+ // opens the winner's file in the window before the winner's chmod lands. Its
400
+ // pre-open check had already passed (the file did not exist), so without this
401
+ // the loser refused with `unsafe-path` — a real flake, reproduced 1-in-12 on
402
+ // a 16-core box, that read as a permission problem when it was a schedule.
403
+ //
404
+ // Narrowing our own descriptor's mode is safe and idempotent; a file that is
405
+ // still wrong afterwards is genuinely wrong, not merely early.
406
+ if (process.platform !== "win32") {
407
+ const uid = process.getuid?.();
408
+ let current = lstatSync(finalDatabasePath);
409
+ if ((current.mode & 0o777) !== 0o600) {
410
+ try { chmodSync(finalDatabasePath, 0o600); } catch { /* refused below */ }
411
+ current = lstatSync(finalDatabasePath);
412
+ }
413
+ if (uid === undefined || current.uid !== uid || (current.mode & 0o777) !== 0o600) {
414
+ throw new CodexUserIdentityRefusal(
415
+ "The coordinator database has unsafe ownership or permissions.",
416
+ );
417
+ }
418
+ }
419
+ const opened = lstatSync(finalDatabasePath);
420
+ if (opened.isSymbolicLink() || !opened.isFile()) {
421
+ throw new CodexUserIdentityRefusal("The coordinator database path changed during open.");
422
+ }
423
+ initialIdentity = `${opened.dev}:${opened.ino}`;
424
+ database.exec("PRAGMA busy_timeout = 0; PRAGMA locking_mode = NORMAL; BEGIN IMMEDIATE");
425
+ transactionOpen = true;
426
+ initialize(database, databaseWasAbsent || databaseWasEmpty);
427
+ } catch (cause) {
428
+ if (transactionOpen) {
429
+ try { database?.exec("ROLLBACK"); } catch { /* close releases the transaction */ }
430
+ }
431
+ try { database?.close(); } catch { /* acquisition already failed */ }
432
+ throw cause;
433
+ }
434
+
435
+ const db = database;
436
+ const requireOpen = (): void => {
437
+ if (closed || !transactionOpen) throw new CodexCoordinatorTransactionError("The coordinator transaction is closed.");
438
+ };
439
+ const assertStablePath = (): void => {
440
+ requireOpen();
441
+ const entry = lstatSync(finalDatabasePath);
442
+ if (entry.isSymbolicLink() || !entry.isFile()
443
+ || `${entry.dev}:${entry.ino}` !== initialIdentity
444
+ || !samePathIdentity(realpathSync.native(finalDatabasePath), finalDatabasePath)) {
445
+ throw new CodexUserIdentityRefusal("The coordinator database path was substituted.");
446
+ }
447
+ };
448
+
449
+ const capability = createCapability(db, result => { lastResult = result; });
450
+ return {
451
+ capability,
452
+ expectation() {
453
+ requireOpen();
454
+ const state = readCodexCoordinatorState(db);
455
+ return {
456
+ nativeBefore: state.nativeGeneration,
457
+ nativeAfter: state.nativeGeneration + 1,
458
+ txId: randomUUID(),
459
+ };
460
+ },
461
+ version() {
462
+ requireOpen();
463
+ const state = readCodexCoordinatorState(db);
464
+ return { nativeGeneration: state.nativeGeneration, currentTxId: state.currentTxId };
465
+ },
466
+ assertPublished(expectation) {
467
+ requireOpen();
468
+ if (lastResult?.kind !== "updated") {
469
+ throw new CodexCoordinatorTransactionError("The coordinator transition was not published.");
470
+ }
471
+ const state = readCodexCoordinatorState(db);
472
+ if (state.nativeGeneration !== expectation.nativeAfter || state.currentTxId !== expectation.txId) {
473
+ throw new CodexCoordinatorTransactionError("The coordinator published a different transition.");
474
+ }
475
+ },
476
+ assertStablePath,
477
+ commit() {
478
+ requireOpen();
479
+ assertStablePath();
480
+ db.exec("COMMIT");
481
+ transactionOpen = false;
482
+ },
483
+ rollback() {
484
+ if (!closed && transactionOpen) {
485
+ try { db.exec("ROLLBACK"); } finally { transactionOpen = false; }
486
+ }
487
+ },
488
+ close() {
489
+ if (closed) return;
490
+ if (transactionOpen) {
491
+ try { db.exec("ROLLBACK"); } catch { /* close still releases the lock */ }
492
+ transactionOpen = false;
493
+ }
494
+ db.close();
495
+ closed = true;
496
+ },
497
+ };
498
+ }
499
+
500
+ function currentCoordinatorDatabasePath(): string {
501
+ const canonicalCodexHome = realpathSync.native(resolveCodexHomeDir());
502
+ return resolveCodexCoordinatorDatabasePath(resolveEffectiveUserIdentity(), canonicalCodexHome);
503
+ }
504
+
505
+ function mapUnavailable(
506
+ error: unknown,
507
+ ): Extract<TransitionStateRead, { kind: "unavailable" }> {
508
+ if (error instanceof CodexUserIdentityRefusal) return { kind: "unavailable", reason: "unsafe-path" };
509
+ return { kind: "unavailable", reason: isBusy(error) ? "busy" : "database" };
510
+ }
511
+
512
+ function mapReadError(error: unknown): TransitionStateRead {
513
+ if (error instanceof CodexCoordinatorLegacyAmbiguousError) {
514
+ return { kind: "legacy-ambiguous", message: error.message };
515
+ }
516
+ return mapUnavailable(error);
517
+ }
518
+
519
+ export const readCodexTransitionState: ReadCodexTransitionState = () => {
520
+ let transaction: CodexCoordinatorTransactionController | undefined;
521
+ try {
522
+ transaction = openCodexCoordinatorTransaction(currentCoordinatorDatabasePath());
523
+ // Initialization and validation happen while N is held. Commit that setup
524
+ // before reopening read-only; the controller never leaks its Database.
525
+ transaction.commit();
526
+ transaction.close();
527
+ transaction = undefined;
528
+ return readCommittedState();
529
+ } catch (error) {
530
+ transaction?.rollback();
531
+ return mapReadError(error);
532
+ } finally {
533
+ transaction?.close();
534
+ }
535
+ };
536
+
537
+ function readCommittedState(): TransitionStateRead {
538
+ const path = currentCoordinatorDatabasePath();
539
+ let database: Database | undefined;
540
+ try {
541
+ database = new Database(path, { readonly: true });
542
+ database.exec("PRAGMA busy_timeout = 0");
543
+ return { kind: "ready", state: readCodexCoordinatorState(database) };
544
+ } catch (error) {
545
+ return mapUnavailable(error);
546
+ } finally {
547
+ try { database?.close(); } catch { /* read already completed */ }
548
+ }
549
+ }
550
+
551
+ export const beginCodexTransition: BeginCodexTransition = (expected, next) => {
552
+ let transaction: CodexCoordinatorTransactionController | undefined;
553
+ try {
554
+ transaction = openCodexCoordinatorTransaction(currentCoordinatorDatabasePath());
555
+ const result = transaction.capability.beginTransition(expected, next);
556
+ transaction.commit();
557
+ return result;
558
+ } catch (error) {
559
+ transaction?.rollback();
560
+ const unavailable = mapUnavailable(error);
561
+ return { kind: "unavailable", reason: unavailable.reason };
562
+ } finally {
563
+ transaction?.close();
564
+ }
565
+ };
566
+
567
+ export const updateCodexHistoryTransition: UpdateCodexHistoryTransition = (expected, history) => {
568
+ let database: Database | undefined;
569
+ let transactionOpen = false;
570
+ try {
571
+ validateHistoryWrite(expected, history);
572
+ // `{ create: false }` ALONE is SQLITE_MISUSE on Bun 1.3.14: the flags must
573
+ // name a read mode. Without `readwrite` every history update failed before
574
+ // reaching its conditional UPDATE and returned `unavailable/database`, so no
575
+ // terminal history state could ever be recorded — and the four tests here
576
+ // still passed, because none of them called this function.
577
+ database = new Database(currentCoordinatorDatabasePath(), { readwrite: true, create: false });
578
+ database.exec("PRAGMA busy_timeout = 0; BEGIN IMMEDIATE");
579
+ transactionOpen = true;
580
+ const current = readCodexCoordinatorState(database);
581
+ if (current.nativeGeneration > 0 && current.historySchedule === null) {
582
+ throw new CodexCoordinatorTransactionError("A positive transition cannot lose its direction.");
583
+ }
584
+ const result = database.query(UPDATE_HISTORY).run(
585
+ history.status,
586
+ history.reason ?? null,
587
+ history.attempts,
588
+ history.nextRetryAt,
589
+ history.txId,
590
+ history.pendingRows,
591
+ history.backupEntries,
592
+ new Date().toISOString(),
593
+ expected.nativeGeneration,
594
+ expected.currentTxId,
595
+ expected.currentTxId,
596
+ );
597
+ const state = readCodexCoordinatorState(database);
598
+ database.exec("COMMIT");
599
+ transactionOpen = false;
600
+ return result.changes === 1
601
+ ? { kind: "updated", state }
602
+ : { kind: "conflict", current: state };
603
+ } catch (error) {
604
+ if (transactionOpen) {
605
+ try { database?.exec("ROLLBACK"); } catch { /* close releases N */ }
606
+ }
607
+ const unavailable = mapUnavailable(error);
608
+ return { kind: "unavailable", reason: unavailable.reason };
609
+ } finally {
610
+ try { database?.close(); } catch { /* operation already completed */ }
611
+ }
612
+ };