@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,220 @@
1
+ /**
2
+ * Worker-thread entry for the Codex history unit.
3
+ *
4
+ * Everything mutable about history happens here, behind H: the SQLite rows, the
5
+ * backup manifest, and every rollout patch. Those three do not share a
6
+ * transaction — sync writes the manifest before its database transaction, and
7
+ * restore writes rollouts, then the database, then the manifest
8
+ * (`src/codex/history-provider.ts:606-648,656-698`) — so a busy timeout only
9
+ * ever serialized a third of a state transition. Holding H across the whole unit
10
+ * is what stops an opposite-direction process overtaking through the other two.
11
+ *
12
+ * The message is deliberately thin, and it does NOT carry a direction. A caller
13
+ * saying which way history should move is exactly what the durable operation
14
+ * exists to prevent: `syncResumeHistory: false` means leave history alone, apply
15
+ * targets opencodex only in legacy mode, and legacy recovery is a different
16
+ * operation from generic restore. So the Worker is told which JOB to run and
17
+ * reads the operation from the coordinator row itself.
18
+ *
19
+ * Homes are carried explicitly because a Worker is a separate process: it does
20
+ * not inherit the module-load `CODEX_HOME` that `history-provider.ts` resolves
21
+ * at import time, so a request that leaned on those constants would silently
22
+ * address the wrong home.
23
+ *
24
+ * Design record: devlog/_fin/260804_codex_write_substrate/020_history_isolation.md.
25
+ */
26
+ import { withHistoryWriteSerialization } from "./history-lock";
27
+ import { loadConfig } from "../config";
28
+ import { shouldSyncCodexOnStart } from "./desired-state";
29
+ import {
30
+ writeHistoryProviderTransition,
31
+ writeLegacyOpenaiHistoryRecovery,
32
+ type HistoryWriteTarget,
33
+ } from "./internal/history-writer";
34
+ import {
35
+ snapshotCodexHistoryNoop,
36
+ type CodexHistoryFailureReason,
37
+ type CodexHistoryVerifiedNoopProof,
38
+ } from "./history-provider";
39
+
40
+ /**
41
+ * The durable operation, mirrored into the request for diagnostics only.
42
+ *
43
+ * The Worker validates this against what it reads and refuses a mismatch rather
44
+ * than trusting it — a tampered copy must not be able to turn a restore into an
45
+ * apply. Structured-clone safe by construction: a closed set of string literals.
46
+ */
47
+ export type CodexHistoryWorkerOperation =
48
+ | "skip"
49
+ | "apply-opencodex"
50
+ | "migrate-openai"
51
+ | "restore-openai"
52
+ | "recover-legacy-openai";
53
+
54
+ export interface HistoryWorkerRunMessage {
55
+ readonly type: "run";
56
+ readonly requestId: string;
57
+ /** Opaque durable job identity; the Worker refuses work that is not current. */
58
+ readonly jobId: string;
59
+ readonly operation: CodexHistoryWorkerOperation;
60
+ readonly canonicalCodexHome: string;
61
+ readonly canonicalStateDbPath: string;
62
+ readonly canonicalBackupPath: string;
63
+ /** When set, prove this transition's desired direction while H is held. */
64
+ readonly expectedDesiredEnabled?: boolean;
65
+ /** Env snapshot: a Worker may not observe parent mutations on every platform. */
66
+ readonly env?: { readonly CODEX_HOME?: string; readonly OPENCODEX_HOME?: string };
67
+ }
68
+
69
+ export type HistoryWorkerResult =
70
+ | { readonly type: "done"; readonly requestId: string; readonly jobId: string;
71
+ readonly outcome: "converged" | "skipped";
72
+ readonly rows: number; readonly files: number;
73
+ readonly proof?: CodexHistoryVerifiedNoopProof }
74
+ | { readonly type: "blocked"; readonly requestId: string; readonly jobId: string;
75
+ readonly reason: "busy" | "database" | "unsafe-path" | "desired_disabled" | "desired_enabled" }
76
+ | { readonly type: "error"; readonly requestId: string; readonly jobId: string;
77
+ readonly message: string; readonly reason?: CodexHistoryFailureReason };
78
+
79
+ const OPERATIONS: ReadonlySet<string> = new Set<CodexHistoryWorkerOperation>([
80
+ "skip",
81
+ "apply-opencodex",
82
+ "migrate-openai",
83
+ "restore-openai",
84
+ "recover-legacy-openai",
85
+ ]);
86
+
87
+ /**
88
+ * Validate the message before it can reach a writer.
89
+ *
90
+ * A malformed message is dropped rather than coerced. Every field is required
91
+ * and non-empty: an absent path would otherwise fall back to a module-load
92
+ * constant that points at the wrong home in this process.
93
+ */
94
+ export function isHistoryWorkerRunMessage(data: unknown): data is HistoryWorkerRunMessage {
95
+ if (!data || typeof data !== "object" || Array.isArray(data)) return false;
96
+ const message = data as Record<string, unknown>;
97
+ const nonEmpty = (value: unknown): value is string =>
98
+ typeof value === "string" && value.trim().length > 0;
99
+ return message.type === "run"
100
+ && nonEmpty(message.requestId)
101
+ && nonEmpty(message.jobId)
102
+ && typeof message.operation === "string"
103
+ && OPERATIONS.has(message.operation)
104
+ && nonEmpty(message.canonicalCodexHome)
105
+ && nonEmpty(message.canonicalStateDbPath)
106
+ && nonEmpty(message.canonicalBackupPath)
107
+ && (message.expectedDesiredEnabled === undefined || typeof message.expectedDesiredEnabled === "boolean");
108
+ }
109
+
110
+ /**
111
+ * Run one history operation under H.
112
+ *
113
+ * Exported so the unit can be exercised in-process; the Worker entry below is a
114
+ * thin adapter over it. `skip` is a real outcome rather than an absence: opting
115
+ * out of history resume must be recorded, not inferred from nothing happening.
116
+ */
117
+ export function runHistoryUnitUnderLock(
118
+ message: HistoryWorkerRunMessage,
119
+ ): HistoryWorkerResult {
120
+ const { requestId, jobId, operation } = message;
121
+ const target: HistoryWriteTarget = {
122
+ canonicalStateDbPath: message.canonicalStateDbPath,
123
+ canonicalBackupPath: message.canonicalBackupPath,
124
+ };
125
+
126
+ if (operation === "skip") {
127
+ return { type: "done", requestId, jobId, outcome: "skipped", rows: 0, files: 0 };
128
+ }
129
+
130
+ const acquired = withHistoryWriteSerialization(
131
+ message.canonicalCodexHome,
132
+ message.canonicalStateDbPath,
133
+ permit => {
134
+ if (message.expectedDesiredEnabled !== undefined
135
+ && shouldSyncCodexOnStart(loadConfig()) !== message.expectedDesiredEnabled) {
136
+ return { desiredStateChanged: true as const };
137
+ }
138
+ if (operation === "recover-legacy-openai") {
139
+ return writeLegacyOpenaiHistoryRecovery(permit, target);
140
+ }
141
+ if (operation === "migrate-openai") {
142
+ const proof = snapshotCodexHistoryNoop(message.canonicalStateDbPath, message.canonicalBackupPath);
143
+ if (proof.kind === "verified-noop") return { verifiedNoop: proof } as const;
144
+ }
145
+ // apply-opencodex routes history to opencodex; migrate/restore return it to
146
+ // native. The provider is derived from the operation, never from a caller.
147
+ const provider = operation === "apply-opencodex" ? "opencodex" : "openai";
148
+ return writeHistoryProviderTransition(permit, target, provider);
149
+ },
150
+ );
151
+
152
+ if (acquired.kind !== "completed") {
153
+ return { type: "blocked", requestId, jobId, reason: acquired.reason };
154
+ }
155
+ const result = acquired.value;
156
+ if ("desiredStateChanged" in result) {
157
+ return {
158
+ type: "blocked",
159
+ requestId,
160
+ jobId,
161
+ reason: message.expectedDesiredEnabled ? "desired_disabled" : "desired_enabled",
162
+ };
163
+ }
164
+ if ("verifiedNoop" in result) {
165
+ return {
166
+ type: "done",
167
+ requestId,
168
+ jobId,
169
+ outcome: "converged",
170
+ rows: 0,
171
+ files: 0,
172
+ proof: result.verifiedNoop,
173
+ };
174
+ }
175
+ if (result.failed === true) {
176
+ return {
177
+ type: "error",
178
+ requestId,
179
+ jobId,
180
+ message: "history_transition_failed",
181
+ ...(result.failureReason ? { reason: result.failureReason } : {}),
182
+ };
183
+ }
184
+ return {
185
+ type: "done",
186
+ requestId,
187
+ jobId,
188
+ outcome: "converged",
189
+ rows: result.rows,
190
+ files: result.files,
191
+ };
192
+ }
193
+
194
+ declare const self: Worker;
195
+
196
+ // Guarded so the module can be imported directly by tests without a Worker host.
197
+ if (typeof self !== "undefined" && typeof (self as { onmessage?: unknown }) === "object") {
198
+ self.onmessage = (event: MessageEvent<unknown>) => {
199
+ if (!isHistoryWorkerRunMessage(event.data)) return;
200
+ const message = event.data;
201
+ try {
202
+ if (message.env?.CODEX_HOME) process.env.CODEX_HOME = message.env.CODEX_HOME;
203
+ if (message.env?.OPENCODEX_HOME) process.env.OPENCODEX_HOME = message.env.OPENCODEX_HOME;
204
+ self.postMessage(runHistoryUnitUnderLock(message));
205
+ } catch (error) {
206
+ self.postMessage({
207
+ type: "error",
208
+ requestId: message.requestId,
209
+ jobId: message.jobId,
210
+ message: error instanceof Error ? error.message : "history_worker_failed",
211
+ } satisfies HistoryWorkerResult);
212
+ } finally {
213
+ // Close from inside the Worker so the thread begins exiting before the
214
+ // parent's terminate() races isolate realm reclaim on Windows.
215
+ try {
216
+ (self as unknown as { close?: () => void }).close?.();
217
+ } catch { /* already closing */ }
218
+ }
219
+ };
220
+ }
@@ -0,0 +1,290 @@
1
+ /**
2
+ * Coordination helpers for the native Codex write section.
3
+ *
4
+ * Split out of `inject.ts` so the injection function keeps reading as the
5
+ * sequence it is, rather than doubling in length around the lock.
6
+ */
7
+ import { createHash } from "node:crypto";
8
+ import { existsSync, lstatSync, readFileSync } from "node:fs";
9
+
10
+ import { atomicWriteFile } from "../config";
11
+ import type { CodexWriteLockResult } from "./codex-write-lock";
12
+ import { inspectCodexCoordinatorPath } from "./coordinator-doctor";
13
+ import { JOURNAL_PATH } from "./journal";
14
+ import { CODEX_CONFIG_PATH, CODEX_PROFILE_PATH } from "./paths";
15
+ import {
16
+ codexWriteCoordination,
17
+ type CodexWriteCandidate,
18
+ type CodexWriteCoordination,
19
+ type CodexWriteEvidence,
20
+ } from "./write-coordination";
21
+
22
+ /** Bounded so a stuck holder cannot wedge `ocx start` indefinitely. */
23
+ export const DEFAULT_INJECT_LOCK_TIMEOUT_MS = 5_000;
24
+
25
+ /**
26
+ * Can this home be coordinated at all, decided BEFORE any lock attempt?
27
+ *
28
+ * The order matters and is not stylistic. `assertInitialStateCanBeCreated`
29
+ * refuses to create the first coordinator row while native routing residue
30
+ * exists (`transition-state.ts:268-280`) — correctly, because installing
31
+ * `{0,null}` over routed bytes would erase the only evidence that an
32
+ * interrupted transition needs salvage. But "already routed, no coordinator
33
+ * row" is the state of every install predating this substrate, so a "try the
34
+ * lock, fall back on refusal" shape would attempt acquisition on the entire
35
+ * installed base. Deciding first means that refusal path is never entered.
36
+ *
37
+ * `legacy-uncoordinated` is a temporary boundary, not a design: the
38
+ * compatibility-adoption contract (`005_contract.md:709-779`) records an
39
+ * existing routed home into the coordinator, and once that lands this branch
40
+ * narrows to homes not yet adopted.
41
+ */
42
+ export type CodexWriteCoordinationEligibility =
43
+ | { kind: "coordinated" }
44
+ | { kind: "legacy-uncoordinated"; reason: string }
45
+ | { kind: "refused"; reason: string };
46
+
47
+ /**
48
+ * A live SQLite creator exposes a zero-byte pathname before BEGIN IMMEDIATE.
49
+ * Requiring a settled filesystem age makes that scheduling window remain on
50
+ * the coordinated path while old crash remnants can use the legacy boundary.
51
+ */
52
+ export const STABLE_ZERO_BYTE_COORDINATOR_AGE_MS = 1_000;
53
+
54
+ export function codexWriteCoordinationEligibility(deps: {
55
+ coordinatorPath: () => string;
56
+ residue: () => { kind: string };
57
+ integrationRecord: () => { kind: string };
58
+ nowMs?: () => number;
59
+ }): CodexWriteCoordinationEligibility {
60
+ let coordinatorExists: boolean;
61
+ let coordinatorIsStableZeroByte = false;
62
+ try {
63
+ const path = deps.coordinatorPath();
64
+ coordinatorExists = existsSync(path);
65
+ if (coordinatorExists) {
66
+ const entry = lstatSync(path);
67
+ if (entry.isFile() && !entry.isSymbolicLink() && entry.size === 0) {
68
+ const diagnostic = inspectCodexCoordinatorPath(path);
69
+ if (diagnostic.kind === "zero-byte") {
70
+ const lastIdentityChange = Math.max(diagnostic.identity.mtimeMs, diagnostic.identity.ctimeMs);
71
+ coordinatorIsStableZeroByte = (deps.nowMs?.() ?? Date.now()) - lastIdentityChange
72
+ >= STABLE_ZERO_BYTE_COORDINATOR_AGE_MS;
73
+ }
74
+ }
75
+ }
76
+ } catch (error) {
77
+ return { kind: "refused", reason: `the coordinator path could not be resolved: ${String(error)}` };
78
+ }
79
+
80
+ // Every existing coordinator remains authoritative unless it is proven to be
81
+ // an old, immutable SQLite-empty remnant. The age gate is part of that proof:
82
+ // a live creator exposes the same zero-byte pathname briefly before taking N,
83
+ // and sending that fresh file down the legacy path would bypass its lock.
84
+ // Non-empty, fresh, unsafe, changed, unversioned, and rowless files therefore
85
+ // stay coordinated and are validated/refused by the transaction owner.
86
+ //
87
+ // We do NOT initialize or adopt it here. Clean homes still enter the
88
+ // coordinated path, whose SQLite transaction safely initializes it. Routed
89
+ // or indeterminate legacy homes keep the same uncoordinated compatibility
90
+ // boundary they would have had if the remnant pathname were absent.
91
+ if (coordinatorExists && !coordinatorIsStableZeroByte) return { kind: "coordinated" };
92
+
93
+ const record = deps.integrationRecord();
94
+ if (record.kind === "invalid") {
95
+ return { kind: "refused", reason: "the Codex integration record is invalid" };
96
+ }
97
+
98
+ const residue = deps.residue();
99
+ if (residue.kind === "clean") return { kind: "coordinated" };
100
+ /*
101
+ * Everything else keeps the path it has always had.
102
+ *
103
+ * `residue` is a pre-substrate routed home; `indeterminate` means the
104
+ * classifier could not read what is there — a profile it cannot parse, for
105
+ * instance, which is an ordinary re-injection over an older file rather than
106
+ * a hazard.
107
+ *
108
+ * Neither may CREATE a coordinator row: doing that over unclassified or
109
+ * routed bytes would erase the evidence an interrupted transition needs. But
110
+ * refusing the injection outright, which an earlier draft of this function
111
+ * did for `indeterminate`, breaks re-injection on homes that work today —
112
+ * caught by the shipped restore tests rather than by review. Declining to
113
+ * coordinate is the correct scope of the refusal; declining to write is not.
114
+ */
115
+ return {
116
+ kind: "legacy-uncoordinated",
117
+ reason: coordinatorIsStableZeroByte
118
+ ? "the coordinator is a zero-byte non-authoritative remnant and this routed home has not been adopted yet"
119
+ : residue.kind === "residue"
120
+ ? "this home was routed before write coordination existed and has not been adopted yet"
121
+ : "the existing native Codex state could not be classified, so it cannot seed a coordinator row",
122
+ };
123
+ }
124
+
125
+ /** The transition row rejected this publication; a conflict, not an exception. */
126
+ export class CodexWriteConflictError extends Error {
127
+ readonly code = "CODEX_WRITE_CONFLICT";
128
+ constructor(message: string) {
129
+ super(message);
130
+ this.name = "CodexWriteConflictError";
131
+ }
132
+ }
133
+
134
+ /**
135
+ * A write failed AND its compensation failed.
136
+ *
137
+ * Carries which surfaces are unrestored, never their contents — this reaches
138
+ * logs and HTTP responses, and config bytes carry credentials.
139
+ */
140
+ export class CodexPartialWriteError extends Error {
141
+ readonly code = "CODEX_PARTIAL_WRITE";
142
+ constructor(readonly unrestored: readonly string[]) {
143
+ super(`Native Codex files are in a partial state; unrestored: ${unrestored.join(", ")}.`);
144
+ this.name = "CodexPartialWriteError";
145
+ }
146
+ }
147
+
148
+ function contentIdentity(path: string): string {
149
+ try {
150
+ return createHash("sha256").update(readFileSync(path)).digest("hex").slice(0, 32);
151
+ } catch {
152
+ return existsSync(path) ? "unreadable" : "absent";
153
+ }
154
+ }
155
+
156
+ export interface CodexPreImages {
157
+ readonly config: string | null;
158
+ readonly profile: string | null;
159
+ readonly journal: string | null;
160
+ }
161
+
162
+ /** `null` means the file was ABSENT, which restoration must reproduce exactly. */
163
+ function readOrNull(path: string): string | null {
164
+ try {
165
+ return readFileSync(path, "utf-8");
166
+ } catch {
167
+ return null;
168
+ }
169
+ }
170
+
171
+ export function captureCodexPreImages(): CodexPreImages {
172
+ return {
173
+ config: readOrNull(CODEX_CONFIG_PATH),
174
+ profile: readOrNull(CODEX_PROFILE_PATH),
175
+ journal: readOrNull(JOURNAL_PATH),
176
+ };
177
+ }
178
+
179
+ /**
180
+ * Put back exactly what was there, and report honestly when that fails.
181
+ *
182
+ * Every surface is attempted even after one fails: a second failure is worth
183
+ * knowing about, and stopping early would leave more unrestored than necessary.
184
+ */
185
+ export function restoreCodexPreImages(
186
+ pre: CodexPreImages,
187
+ ): { complete: boolean; unrestored: readonly string[] } {
188
+ const unrestored: string[] = [];
189
+ const surfaces: readonly [string, string, string | null][] = [
190
+ ["config", CODEX_CONFIG_PATH, pre.config],
191
+ ["profile", CODEX_PROFILE_PATH, pre.profile],
192
+ ["journal", JOURNAL_PATH, pre.journal],
193
+ ];
194
+ for (const [name, path, bytes] of surfaces) {
195
+ try {
196
+ if (bytes === null) {
197
+ // Absent before, so absent after. A leftover file is not a restoration.
198
+ if (existsSync(path)) require("node:fs").unlinkSync(path);
199
+ } else if (readOrNull(path) !== bytes) {
200
+ atomicWriteFile(path, bytes);
201
+ }
202
+ } catch {
203
+ unrestored.push(name);
204
+ }
205
+ }
206
+ return { complete: unrestored.length === 0, unrestored };
207
+ }
208
+
209
+ export function buildInjectWitness(
210
+ candidate: CodexWriteCandidate,
211
+ nativeInput: string,
212
+ persistedIdentity: string,
213
+ generation: CodexWriteEvidence["generation"],
214
+ observedOwnership: CodexWriteCoordination["observedOwnership"],
215
+ ): CodexWriteCoordination {
216
+ return codexWriteCoordination(
217
+ candidate,
218
+ {
219
+ nativeInputIdentity: createHash("sha256").update(nativeInput).digest("hex"),
220
+ persistedIdentity,
221
+ generation,
222
+ journalIdentity: contentIdentity(JOURNAL_PATH),
223
+ canonicalTargets: {
224
+ config: CODEX_CONFIG_PATH,
225
+ profile: CODEX_PROFILE_PATH,
226
+ journal: JOURNAL_PATH,
227
+ },
228
+ },
229
+ observedOwnership,
230
+ );
231
+ }
232
+
233
+ /**
234
+ * The under-lock re-read.
235
+ *
236
+ * The candidate bytes are fixed — they were computed before acquisition and do
237
+ * not change — so what is re-read is the EVIDENCE: the native input on disk, the
238
+ * journal, the generation from the open transaction. A comparison that copied
239
+ * those forward would match itself and prove nothing.
240
+ */
241
+ export function recomputeInjectWitness(options: {
242
+ candidate: CodexWriteCandidate;
243
+ canonicalTargets: CodexWriteEvidence["canonicalTargets"];
244
+ persistedIdentity: string;
245
+ generation: CodexWriteEvidence["generation"];
246
+ observedOwnership: CodexWriteCoordination["observedOwnership"];
247
+ }): CodexWriteCoordination {
248
+ const nativeInput = readOrNull(options.canonicalTargets.config) ?? "";
249
+ return codexWriteCoordination(
250
+ options.candidate,
251
+ {
252
+ nativeInputIdentity: createHash("sha256").update(nativeInput).digest("hex"),
253
+ persistedIdentity: options.persistedIdentity,
254
+ generation: options.generation,
255
+ journalIdentity: contentIdentity(options.canonicalTargets.journal),
256
+ canonicalTargets: options.canonicalTargets,
257
+ },
258
+ options.observedOwnership,
259
+ );
260
+ }
261
+
262
+ /** Project a non-acquired lock result into the injection result shape. */
263
+ export function codexInjectLockOutcome(
264
+ result: Exclude<CodexWriteLockResult<unknown>, { status: "acquired" }>,
265
+ ): { success: false; message: string; retryable: boolean } | {
266
+ success: true; status: "skipped"; skippedReason: "desired_disabled" | "desired_enabled"; message: string;
267
+ } {
268
+ if (result.status === "skipped") {
269
+ return {
270
+ success: true,
271
+ status: "skipped",
272
+ skippedReason: result.reason,
273
+ message: result.reason === "desired_disabled"
274
+ ? "Codex integration is OFF; no Codex config, catalog, cache, or history was changed."
275
+ : "Codex integration was re-enabled; native restore was skipped.",
276
+ };
277
+ }
278
+ if (result.status === "busy") {
279
+ return {
280
+ success: false,
281
+ retryable: true,
282
+ message: `Another process is writing Codex configuration right now (waited ${result.waitedMs}ms). Retry shortly.`,
283
+ };
284
+ }
285
+ return {
286
+ success: false,
287
+ retryable: false,
288
+ message: `Codex configuration was not written: ${result.message}`,
289
+ };
290
+ }