@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,682 @@
1
+ import { createHash } from "node:crypto";
2
+ import {
3
+ closeSync,
4
+ fstatSync,
5
+ lstatSync,
6
+ openSync,
7
+ readFileSync,
8
+ readdirSync,
9
+ realpathSync,
10
+ readSync,
11
+ statSync,
12
+ } from "node:fs";
13
+ import type { Stats } from "node:fs";
14
+ import { basename, dirname, join, resolve } from "node:path";
15
+
16
+ import { Database } from "bun:sqlite";
17
+
18
+ import { getConfigDir } from "../config";
19
+ import { catalogHasRoutedEntries, parseCatalogJson } from "./catalog/parsing";
20
+ import {
21
+ hasInjectedCodexRouting,
22
+ OCX_SECTION_MARKER,
23
+ providerTableString,
24
+ rootTomlString,
25
+ } from "./injected-marker";
26
+ import {
27
+ CODEX_CONFIG_PATH,
28
+ CODEX_MODELS_CACHE_PATH,
29
+ CODEX_PROFILE_PATH,
30
+ DEFAULT_CATALOG_PATH,
31
+ getCodexHome,
32
+ readRootTomlString,
33
+ resolveCodexStateDbPath,
34
+ } from "./paths";
35
+
36
+ export type NativeResidueSurface =
37
+ | "config"
38
+ | "profile"
39
+ | "catalog"
40
+ | "models-cache"
41
+ | "journal"
42
+ | "partial-write"
43
+ | "history"
44
+ | "history-backup";
45
+
46
+ export type NativeRoutedResidueResult =
47
+ | { kind: "clean" }
48
+ | { kind: "residue"; surface: NativeResidueSurface; path: string }
49
+ | { kind: "indeterminate"; surface: NativeResidueSurface; path: string; reason: string };
50
+
51
+ type ReadResult =
52
+ | { kind: "absent" }
53
+ | { kind: "content"; content: string; path: string }
54
+ | { kind: "indeterminate"; reason: string };
55
+
56
+ type PathResult =
57
+ | { kind: "absent" }
58
+ | { kind: "path"; path: string; stat: Stats }
59
+ | { kind: "indeterminate"; reason: string };
60
+
61
+ type CatalogTarget = {
62
+ path: string;
63
+ configured: boolean;
64
+ };
65
+
66
+ type ConfigObservation = {
67
+ classification: NativeRoutedResidueResult;
68
+ catalogTargets: CatalogTarget[];
69
+ };
70
+
71
+ type RolloutReference = {
72
+ id: string;
73
+ path: string;
74
+ };
75
+
76
+ const CONFIG_FILE_NAME = basename(CODEX_CONFIG_PATH);
77
+ const PROFILE_FILE_NAME = basename(CODEX_PROFILE_PATH);
78
+ const CATALOG_FILE_NAME = basename(DEFAULT_CATALOG_PATH);
79
+ const MODELS_CACHE_FILE_NAME = basename(CODEX_MODELS_CACHE_PATH);
80
+ const JOURNAL_FILE_NAME = "opencodex-journal.json";
81
+ const ROUTED_CATALOG_DESCRIPTION_PREFIX = "Routed via opencodex → ";
82
+ const MAX_ROLLOUT_INSPECTION_BYTES = 64 * 1024 * 1024;
83
+ const ROLLOUT_READ_CHUNK_BYTES = 64 * 1024;
84
+
85
+ function errorCode(error: unknown): string | undefined {
86
+ return (error as NodeJS.ErrnoException | undefined)?.code;
87
+ }
88
+
89
+ function errorReason(error: unknown): string {
90
+ if (error instanceof Error) return `${error.name}: ${error.message}`;
91
+ return String(error);
92
+ }
93
+
94
+ function sameStat(
95
+ left: Stats,
96
+ right: Stats,
97
+ ): boolean {
98
+ return left.dev === right.dev
99
+ && left.ino === right.ino
100
+ && left.size === right.size
101
+ && left.mtimeMs === right.mtimeMs;
102
+ }
103
+
104
+ function resolveRegularFile(path: string): PathResult {
105
+ let entry;
106
+ try {
107
+ entry = lstatSync(path);
108
+ } catch (error) {
109
+ if (errorCode(error) === "ENOENT") return { kind: "absent" };
110
+ return { kind: "indeterminate", reason: errorReason(error) };
111
+ }
112
+
113
+ let target = path;
114
+ if (entry.isSymbolicLink()) {
115
+ try {
116
+ target = realpathSync.native(path);
117
+ } catch (error) {
118
+ return { kind: "indeterminate", reason: `unresolvable symlink: ${errorReason(error)}` };
119
+ }
120
+ }
121
+
122
+ try {
123
+ const before = statSync(target);
124
+ if (!before.isFile()) {
125
+ return { kind: "indeterminate", reason: "surface is not a regular file" };
126
+ }
127
+ return { kind: "path", path: target, stat: before };
128
+ } catch (error) {
129
+ return { kind: "indeterminate", reason: errorReason(error) };
130
+ }
131
+ }
132
+
133
+ function readRegularFile(path: string): ReadResult {
134
+ const resolved = resolveRegularFile(path);
135
+ if (resolved.kind !== "path") return resolved;
136
+ try {
137
+ const content = readFileSync(resolved.path, "utf8");
138
+ const after = statSync(resolved.path);
139
+ if (!sameStat(resolved.stat, after)) {
140
+ return { kind: "indeterminate", reason: "surface changed while it was being observed" };
141
+ }
142
+ return { kind: "content", content, path: resolved.path };
143
+ } catch (error) {
144
+ return { kind: "indeterminate", reason: errorReason(error) };
145
+ }
146
+ }
147
+
148
+ function indeterminate(
149
+ surface: NativeResidueSurface,
150
+ path: string,
151
+ reason: string,
152
+ ): NativeRoutedResidueResult {
153
+ return { kind: "indeterminate", surface, path, reason };
154
+ }
155
+
156
+ function rolloutSessionMetaPayload(
157
+ line: string,
158
+ ): { kind: "payload"; payload: Record<string, unknown> | null } | { kind: "malformed"; reason: string } {
159
+ let parsed: unknown;
160
+ try {
161
+ parsed = JSON.parse(line);
162
+ } catch (error) {
163
+ return { kind: "malformed", reason: `malformed rollout JSONL: ${errorReason(error)}` };
164
+ }
165
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
166
+ return { kind: "malformed", reason: "rollout JSONL record is not an object" };
167
+ }
168
+ const record = parsed as Record<string, unknown>;
169
+ if (record.type !== "session_meta") return { kind: "payload", payload: null };
170
+ if (!record.payload || typeof record.payload !== "object" || Array.isArray(record.payload)) {
171
+ return { kind: "malformed", reason: "session_meta payload has an unknown shape" };
172
+ }
173
+ return { kind: "payload", payload: record.payload as Record<string, unknown> };
174
+ }
175
+
176
+ function consumeRolloutLines(
177
+ surface: "history" | "history-backup",
178
+ path: string,
179
+ partial: string,
180
+ first: Record<string, unknown> | undefined,
181
+ latest: Record<string, unknown> | undefined,
182
+ ): NativeRoutedResidueResult | { kind: "continue"; partial: string; first: Record<string, unknown> | undefined; latest: Record<string, unknown> | undefined } {
183
+ let rest = partial;
184
+ let newline = rest.indexOf("\n");
185
+ while (newline !== -1) {
186
+ const line = rest.slice(0, newline);
187
+ rest = rest.slice(newline + 1);
188
+ if (line.trim()) {
189
+ const payload = rolloutSessionMetaPayload(line);
190
+ if (payload.kind === "malformed") {
191
+ return indeterminate(surface, path, payload.reason);
192
+ }
193
+ if (payload.payload !== null) {
194
+ first ??= payload.payload;
195
+ latest = payload.payload;
196
+ }
197
+ }
198
+ newline = rest.indexOf("\n");
199
+ }
200
+ return { kind: "continue", partial: rest, first, latest };
201
+ }
202
+
203
+ function classifyToml(
204
+ surface: "config" | "profile",
205
+ path: string,
206
+ classify: (content: string) => "clean" | "residue" | "indeterminate",
207
+ ): NativeRoutedResidueResult {
208
+ const read = readRegularFile(path);
209
+ if (read.kind === "absent") return { kind: "clean" };
210
+ if (read.kind === "indeterminate") return indeterminate(surface, path, read.reason);
211
+ try {
212
+ Bun.TOML.parse(read.content);
213
+ } catch (error) {
214
+ return indeterminate(surface, path, `malformed TOML: ${errorReason(error)}`);
215
+ }
216
+ const result = classify(read.content);
217
+ if (result === "residue") return { kind: "residue", surface, path: read.path };
218
+ if (result === "indeterminate") {
219
+ return indeterminate(surface, read.path, "OpenCodex-shaped TOML does not match a complete routed grammar");
220
+ }
221
+ return { kind: "clean" };
222
+ }
223
+
224
+ function catalogPathKey(path: string): string {
225
+ const normalized = resolve(path);
226
+ return process.platform === "win32" ? normalized.toLowerCase() : normalized;
227
+ }
228
+
229
+ function catalogTargets(
230
+ codexHome: string,
231
+ configuredPaths: readonly string[] = [],
232
+ ): CatalogTarget[] {
233
+ const targets = new Map<string, CatalogTarget>();
234
+ const add = (path: string, configured: boolean) => {
235
+ const key = catalogPathKey(path);
236
+ const existing = targets.get(key);
237
+ targets.set(key, { path: resolve(path), configured: configured || existing?.configured === true });
238
+ };
239
+ for (const configuredPath of configuredPaths) {
240
+ add(resolve(codexHome, configuredPath), true);
241
+ }
242
+ add(join(codexHome, CATALOG_FILE_NAME), false);
243
+ return [...targets.values()];
244
+ }
245
+
246
+ function inspectConfig(codexHome: string, path: string): ConfigObservation {
247
+ const read = readRegularFile(path);
248
+ if (read.kind === "absent") {
249
+ return { classification: { kind: "clean" }, catalogTargets: catalogTargets(codexHome) };
250
+ }
251
+ if (read.kind === "indeterminate") {
252
+ return {
253
+ classification: indeterminate("config", path, read.reason),
254
+ catalogTargets: catalogTargets(codexHome),
255
+ };
256
+ }
257
+
258
+ const productionConfiguredPath = readRootTomlString(read.content, "model_catalog_json");
259
+ const productionConfiguredPaths = productionConfiguredPath === null
260
+ ? []
261
+ : [productionConfiguredPath];
262
+ let parsed: unknown;
263
+ try {
264
+ parsed = Bun.TOML.parse(read.content.replace(/^\uFEFF/, ""));
265
+ } catch (error) {
266
+ return {
267
+ classification: indeterminate("config", read.path, `malformed TOML: ${errorReason(error)}`),
268
+ catalogTargets: catalogTargets(codexHome, productionConfiguredPaths),
269
+ };
270
+ }
271
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
272
+ return {
273
+ classification: indeterminate("config", read.path, "TOML root is not a table"),
274
+ catalogTargets: catalogTargets(codexHome, productionConfiguredPaths),
275
+ };
276
+ }
277
+
278
+ const document = parsed as Record<string, unknown>;
279
+ let targets: CatalogTarget[];
280
+ if (!Object.hasOwn(document, "model_catalog_json")) {
281
+ targets = catalogTargets(codexHome, productionConfiguredPaths);
282
+ } else if (typeof document.model_catalog_json !== "string" || !document.model_catalog_json.trim()) {
283
+ return {
284
+ classification: indeterminate("config", read.path, "model_catalog_json must be one non-empty string"),
285
+ catalogTargets: catalogTargets(codexHome, productionConfiguredPaths),
286
+ };
287
+ } else {
288
+ try {
289
+ targets = catalogTargets(codexHome, [
290
+ ...productionConfiguredPaths,
291
+ document.model_catalog_json,
292
+ ]);
293
+ } catch (error) {
294
+ return {
295
+ classification: indeterminate("config", read.path, `model_catalog_json cannot be resolved: ${errorReason(error)}`),
296
+ catalogTargets: catalogTargets(codexHome, productionConfiguredPaths),
297
+ };
298
+ }
299
+ }
300
+
301
+ let classification: NativeRoutedResidueResult = { kind: "clean" };
302
+ if (hasInjectedCodexRouting(read.content)) {
303
+ classification = { kind: "residue", surface: "config", path: read.path };
304
+ } else {
305
+ const hasMarker = read.content.includes(OCX_SECTION_MARKER);
306
+ const provider = rootTomlString(read.content, "model_provider");
307
+ const providerBaseUrl = providerTableString(read.content, "opencodex", "base_url");
308
+ if (hasMarker || provider === "opencodex" || providerBaseUrl !== null) {
309
+ classification = indeterminate(
310
+ "config",
311
+ read.path,
312
+ "OpenCodex-shaped TOML does not match a complete routed grammar",
313
+ );
314
+ }
315
+ }
316
+ return { classification, catalogTargets: targets };
317
+ }
318
+
319
+ function classifyProfile(path: string): NativeRoutedResidueResult {
320
+ return classifyToml("profile", path, content => {
321
+ const generatedFallback = content.startsWith("# OpenCodex proxy fallback config (Design B)")
322
+ && rootTomlString(content, "openai_base_url") !== null;
323
+ const generatedNamedProfile = content.startsWith("# OpenCodex proxy profile — use with:")
324
+ && hasInjectedCodexRouting(content);
325
+ if (generatedFallback || generatedNamedProfile) return "residue";
326
+ return "indeterminate";
327
+ });
328
+ }
329
+
330
+ function isOcxRoutedCatalogEntry(entry: Record<string, unknown>): boolean {
331
+ return typeof entry.description === "string"
332
+ && entry.description.startsWith(ROUTED_CATALOG_DESCRIPTION_PREFIX);
333
+ }
334
+
335
+ function classifyCatalogLike(
336
+ surface: "catalog" | "models-cache",
337
+ path: string,
338
+ configured = false,
339
+ ): NativeRoutedResidueResult {
340
+ const read = readRegularFile(path);
341
+ if (read.kind === "absent") {
342
+ return configured
343
+ ? indeterminate(surface, path, "configured catalog target is absent")
344
+ : { kind: "clean" };
345
+ }
346
+ if (read.kind === "indeterminate") return indeterminate(surface, path, read.reason);
347
+ const catalog = parseCatalogJson(read.content);
348
+ if (!catalog) return indeterminate(surface, path, "malformed catalog JSON");
349
+ if ((catalog.models ?? []).some(isOcxRoutedCatalogEntry)) {
350
+ return { kind: "residue", surface, path: read.path };
351
+ }
352
+ if (catalogHasRoutedEntries(catalog)) {
353
+ return indeterminate(surface, read.path, "routed catalog rows lack the OpenCodex authorship signature");
354
+ }
355
+ return { kind: "clean" };
356
+ }
357
+
358
+ function isJournal(value: unknown): boolean {
359
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
360
+ const journal = value as Record<string, unknown>;
361
+ return journal.version === 1
362
+ && typeof journal.originalConfig === "string"
363
+ && (journal.originalProfile === null || typeof journal.originalProfile === "string")
364
+ && typeof journal.pid === "number"
365
+ && Number.isInteger(journal.pid)
366
+ && typeof journal.timestamp === "string";
367
+ }
368
+
369
+ function classifyJournal(path: string): NativeRoutedResidueResult {
370
+ const read = readRegularFile(path);
371
+ if (read.kind === "absent") return { kind: "clean" };
372
+ if (read.kind === "indeterminate") return indeterminate("journal", path, read.reason);
373
+ let parsed: unknown;
374
+ try {
375
+ parsed = JSON.parse(read.content);
376
+ } catch (error) {
377
+ return indeterminate("journal", read.path, `malformed journal JSON: ${errorReason(error)}`);
378
+ }
379
+ return isJournal(parsed)
380
+ ? { kind: "residue", surface: "journal", path: read.path }
381
+ : indeterminate("journal", read.path, "journal JSON has an unknown or partial shape");
382
+ }
383
+
384
+ function classifyPartialWrites(targetPaths: string[]): NativeRoutedResidueResult {
385
+ const targetsByParent = new Map<string, { path: string; names: Set<string> }>();
386
+ const addTarget = (path: string) => {
387
+ const parent = dirname(path);
388
+ const key = catalogPathKey(parent);
389
+ const observed = targetsByParent.get(key) ?? { path: parent, names: new Set<string>() };
390
+ observed.names.add(basename(path));
391
+ targetsByParent.set(key, observed);
392
+ };
393
+ for (const path of targetPaths) {
394
+ addTarget(path);
395
+ const resolved = resolveRegularFile(path);
396
+ if (resolved.kind === "path") addTarget(resolved.path);
397
+ }
398
+
399
+ for (const target of targetsByParent.values()) {
400
+ let names: string[];
401
+ try {
402
+ names = readdirSync(target.path);
403
+ } catch (error) {
404
+ return indeterminate("partial-write", target.path, errorReason(error));
405
+ }
406
+ for (const name of names) {
407
+ const match = /^(.*)\.ocx\.\d+\.\d+\.tmp$/.exec(name);
408
+ if (match?.[1] && target.names.has(match[1])) {
409
+ return indeterminate("partial-write", join(target.path, name), "OpenCodex atomic-write artifact is still present");
410
+ }
411
+ }
412
+ }
413
+ return { kind: "clean" };
414
+ }
415
+
416
+ function classifyReferencedRollout(
417
+ surface: "history" | "history-backup",
418
+ reference: RolloutReference,
419
+ ): NativeRoutedResidueResult {
420
+ const resolved = resolveRegularFile(reference.path);
421
+ if (resolved.kind === "absent") {
422
+ return indeterminate(surface, reference.path, "referenced rollout is absent");
423
+ }
424
+ if (resolved.kind === "indeterminate") return indeterminate(surface, reference.path, resolved.reason);
425
+
426
+ let handle: number;
427
+ try {
428
+ handle = openSync(resolved.path, "r");
429
+ } catch (error) {
430
+ return indeterminate(surface, resolved.path, `unreadable rollout: ${errorReason(error)}`);
431
+ }
432
+
433
+ let first: Record<string, unknown> | undefined;
434
+ let latest: Record<string, unknown> | undefined;
435
+ let partial = "";
436
+ let totalRead = 0;
437
+ try {
438
+ const opened = fstatSync(handle);
439
+ if (opened.size > MAX_ROLLOUT_INSPECTION_BYTES) {
440
+ return indeterminate(
441
+ surface,
442
+ resolved.path,
443
+ `referenced rollout exceeds the ${MAX_ROLLOUT_INSPECTION_BYTES} byte inspection limit`,
444
+ );
445
+ }
446
+ const decoder = new TextDecoder("utf-8", { ignoreBOM: true });
447
+ const buffer = Buffer.allocUnsafe(ROLLOUT_READ_CHUNK_BYTES);
448
+ while (totalRead < opened.size) {
449
+ const remaining = Math.min(buffer.length, opened.size - totalRead);
450
+ const count = readSync(handle, buffer, 0, remaining, totalRead);
451
+ if (count === 0) {
452
+ return indeterminate(surface, resolved.path, "rollout read ended before the observed size");
453
+ }
454
+ if (count < 0) {
455
+ return indeterminate(surface, resolved.path, "rollout read ended before the observed size");
456
+ }
457
+ totalRead += count;
458
+ partial += decoder.decode(buffer.subarray(0, count), { stream: true });
459
+ const consumed = consumeRolloutLines(surface, resolved.path, partial, first, latest);
460
+ if (consumed.kind !== "continue") return consumed;
461
+ partial = consumed.partial;
462
+ first = consumed.first;
463
+ latest = consumed.latest;
464
+ }
465
+ partial += decoder.decode();
466
+ const consumed = consumeRolloutLines(surface, resolved.path, partial, first, latest);
467
+ if (consumed.kind !== "continue") return consumed;
468
+ partial = consumed.partial;
469
+ first = consumed.first;
470
+ latest = consumed.latest;
471
+ if (partial.trim()) {
472
+ const payload = rolloutSessionMetaPayload(partial);
473
+ if (payload.kind === "malformed") {
474
+ return indeterminate(surface, resolved.path, payload.reason);
475
+ }
476
+ if (payload.payload !== null) {
477
+ first ??= payload.payload;
478
+ latest = payload.payload;
479
+ }
480
+ }
481
+ const after = fstatSync(handle);
482
+ if (!sameStat(resolved.stat, after)) {
483
+ return indeterminate(surface, resolved.path, "rollout changed while it was being observed");
484
+ }
485
+ const pathAfter = statSync(resolved.path);
486
+ if (!sameStat(resolved.stat, pathAfter)) {
487
+ return indeterminate(surface, resolved.path, "rollout pathname was replaced while it was being observed");
488
+ }
489
+ } catch (error) {
490
+ if (errorCode(error) === "ENOENT") {
491
+ return indeterminate(surface, resolved.path, "referenced rollout is absent");
492
+ }
493
+ return indeterminate(surface, resolved.path, `unreadable rollout: ${errorReason(error)}`);
494
+ } finally {
495
+ try {
496
+ closeSync(handle);
497
+ } catch {
498
+ // Closing an already-closed descriptor cannot affect the classification.
499
+ }
500
+ }
501
+
502
+ if (!first || !latest) {
503
+ return indeterminate(surface, resolved.path, "referenced rollout has no session_meta metadata");
504
+ }
505
+ let hasOpenCodexProvider = false;
506
+ for (const [position, payload] of [["first", first], ["latest", latest]] as const) {
507
+ if (payload.id !== reference.id) {
508
+ return indeterminate(surface, resolved.path, `${position} session_meta does not identify the referenced thread`);
509
+ }
510
+ if (typeof payload.model_provider !== "string" || !payload.model_provider) {
511
+ return indeterminate(surface, resolved.path, `${position} session_meta has no provider metadata`);
512
+ }
513
+ hasOpenCodexProvider = hasOpenCodexProvider || payload.model_provider === "opencodex";
514
+ }
515
+ return hasOpenCodexProvider
516
+ ? { kind: "residue", surface, path: resolved.path }
517
+ : { kind: "clean" };
518
+ }
519
+
520
+ function classifyReferencedRollouts(
521
+ surface: "history" | "history-backup",
522
+ references: RolloutReference[],
523
+ ): NativeRoutedResidueResult {
524
+ for (const reference of references) {
525
+ const result = classifyReferencedRollout(surface, reference);
526
+ if (result.kind !== "clean") return result;
527
+ }
528
+ return { kind: "clean" };
529
+ }
530
+
531
+ function classifyHistoryDatabase(path: string): NativeRoutedResidueResult {
532
+ const resolved = resolveRegularFile(path);
533
+ if (resolved.kind === "absent") {
534
+ for (const suffix of ["-wal", "-shm"]) {
535
+ const sidecar = resolveRegularFile(`${path}${suffix}`);
536
+ if (sidecar.kind !== "absent") {
537
+ const reason = sidecar.kind === "indeterminate"
538
+ ? sidecar.reason
539
+ : "SQLite sidecar exists without its history database";
540
+ return indeterminate("history", `${path}${suffix}`, reason);
541
+ }
542
+ }
543
+ return { kind: "clean" };
544
+ }
545
+ if (resolved.kind === "indeterminate") return indeterminate("history", path, resolved.reason);
546
+ let database: Database | undefined;
547
+ try {
548
+ database = new Database(resolved.path, { readonly: true });
549
+ database.exec("PRAGMA busy_timeout = 100");
550
+ const rows = database.query<{ id: string; rollout_path: string; model_provider: string }, []>(`
551
+ SELECT id, rollout_path, model_provider
552
+ FROM threads
553
+ `).all();
554
+ for (const row of rows) {
555
+ if (typeof row.id !== "string" || !row.id || typeof row.rollout_path !== "string" || !row.rollout_path) {
556
+ return indeterminate("history", resolved.path, "history row has an unknown rollout reference");
557
+ }
558
+ if (typeof row.model_provider !== "string" || !row.model_provider) {
559
+ return indeterminate("history", resolved.path, "history row has no provider metadata");
560
+ }
561
+ }
562
+ const rollouts = classifyReferencedRollouts(
563
+ "history",
564
+ rows.map(row => ({ id: row.id, path: row.rollout_path })),
565
+ );
566
+ if (rollouts.kind !== "clean") return rollouts;
567
+ const after = statSync(resolved.path);
568
+ if (!sameStat(resolved.stat, after)) {
569
+ return indeterminate("history", resolved.path, "history database changed while it was being observed");
570
+ }
571
+ return rows.some(row => row.model_provider === "opencodex")
572
+ ? { kind: "residue", surface: "history", path: resolved.path }
573
+ : { kind: "clean" };
574
+ } catch (error) {
575
+ return indeterminate("history", resolved.path, `unreadable history database: ${errorReason(error)}`);
576
+ } finally {
577
+ try { database?.close(); } catch { /* the observation already failed closed */ }
578
+ }
579
+ }
580
+
581
+ function historyBackupPath(stateDatabasePath: string): string {
582
+ const normalized = process.platform === "win32"
583
+ ? resolve(stateDatabasePath).toLowerCase()
584
+ : resolve(stateDatabasePath);
585
+ const id = createHash("sha256").update(normalized).digest("hex").slice(0, 16);
586
+ return join(getConfigDir(), `codex-history-backup-${id}.json`);
587
+ }
588
+
589
+ function classifyHistoryBackup(path: string, stateDatabasePath: string): NativeRoutedResidueResult {
590
+ const read = readRegularFile(path);
591
+ if (read.kind === "absent") return { kind: "clean" };
592
+ if (read.kind === "indeterminate") return indeterminate("history-backup", path, read.reason);
593
+ let parsed: unknown;
594
+ try {
595
+ parsed = JSON.parse(read.content);
596
+ } catch (error) {
597
+ return indeterminate("history-backup", read.path, `malformed history backup JSON: ${errorReason(error)}`);
598
+ }
599
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
600
+ return indeterminate("history-backup", read.path, "history backup has an unknown shape");
601
+ }
602
+ const manifest = parsed as Record<string, unknown>;
603
+ if (manifest.version !== 1 || !manifest.entries || typeof manifest.entries !== "object" || Array.isArray(manifest.entries)) {
604
+ return indeterminate("history-backup", read.path, "history backup has an unknown shape");
605
+ }
606
+ if (typeof manifest.stateDbPath === "string") {
607
+ const expected = process.platform === "win32" ? resolve(stateDatabasePath).toLowerCase() : resolve(stateDatabasePath);
608
+ const actual = process.platform === "win32" ? resolve(manifest.stateDbPath).toLowerCase() : resolve(manifest.stateDbPath);
609
+ if (actual !== expected) {
610
+ return indeterminate("history-backup", read.path, "history backup names a different state database");
611
+ }
612
+ }
613
+ const entries = Object.values(manifest.entries as Record<string, unknown>);
614
+ const references: RolloutReference[] = [];
615
+ for (const entry of entries) {
616
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
617
+ return indeterminate("history-backup", read.path, "history backup entry has an unknown shape");
618
+ }
619
+ const candidate = entry as Record<string, unknown>;
620
+ if (typeof candidate.id !== "string" || !candidate.id
621
+ || typeof candidate.rolloutPath !== "string" || !candidate.rolloutPath) {
622
+ return indeterminate("history-backup", read.path, "history backup entry has an unknown rollout reference");
623
+ }
624
+ references.push({ id: candidate.id, path: candidate.rolloutPath });
625
+ }
626
+ const rollouts = classifyReferencedRollouts("history-backup", references);
627
+ if (rollouts.kind !== "clean") return rollouts;
628
+ return entries.length > 0
629
+ ? { kind: "residue", surface: "history-backup", path: read.path }
630
+ : { kind: "clean" };
631
+ }
632
+
633
+ /** Read-only, fail-closed observation of every OpenCodex-routed Codex surface. */
634
+ export function classifyNativeRoutedResidue(): NativeRoutedResidueResult {
635
+ let codexHome: string;
636
+ try {
637
+ codexHome = getCodexHome();
638
+ } catch (error) {
639
+ const unresolved = process.env.CODEX_HOME?.trim() || "CODEX_HOME";
640
+ return indeterminate("partial-write", unresolved, `CODEX_HOME cannot be resolved: ${errorReason(error)}`);
641
+ }
642
+
643
+ const configPath = join(codexHome, CONFIG_FILE_NAME);
644
+ let stateDatabasePath: string;
645
+ try {
646
+ stateDatabasePath = resolveCodexStateDbPath({ codexHome });
647
+ } catch (error) {
648
+ // Residue classification is a total, read-only safety boundary. An
649
+ // indeterminate SQLite authority must refuse coordination without escaping
650
+ // as an exception or falling through to a different state database.
651
+ return indeterminate(
652
+ "config",
653
+ configPath,
654
+ `SQLite home cannot be resolved: ${errorReason(error)}`,
655
+ );
656
+ }
657
+ const profilePath = join(codexHome, PROFILE_FILE_NAME);
658
+ const modelsCachePath = join(codexHome, MODELS_CACHE_FILE_NAME);
659
+ const journalPath = join(codexHome, JOURNAL_FILE_NAME);
660
+ const config = inspectConfig(codexHome, configPath);
661
+ const atomicWriteTargets = [
662
+ configPath,
663
+ profilePath,
664
+ modelsCachePath,
665
+ journalPath,
666
+ ...config.catalogTargets.map(target => target.path),
667
+ ];
668
+ const classifiers = [
669
+ () => classifyPartialWrites(atomicWriteTargets),
670
+ () => config.classification,
671
+ () => classifyProfile(profilePath),
672
+ ...config.catalogTargets.map(target => () => classifyCatalogLike("catalog", target.path, target.configured)),
673
+ () => classifyCatalogLike("models-cache", modelsCachePath),
674
+ () => classifyJournal(journalPath),
675
+ () => classifyHistoryDatabase(stateDatabasePath),
676
+ () => classifyHistoryBackup(historyBackupPath(stateDatabasePath), stateDatabasePath),
677
+ ];
678
+ const results = classifiers.map(classify => classify());
679
+ return results.find(result => result.kind === "indeterminate")
680
+ ?? results.find(result => result.kind === "residue")
681
+ ?? { kind: "clean" };
682
+ }