@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,92 @@
1
+ /**
2
+ * The one place that decides whether a sidecar may treat ChatGPT or Anthropic
3
+ * auth as PRESENT (#2188). Web-search and vision consumed two hand-rolled
4
+ * copies of the Anthropic predicate and no Codex-login predicate at all —
5
+ * provider presence was standing in for "logged in", which let a fresh install
6
+ * with the built-in forward provider but no credential offer Luna as a
7
+ * describer it could never run.
8
+ *
9
+ * Both flags are request-context-free: they read config plus the stored
10
+ * account state, never headers. Per-request usability (exact accounts,
11
+ * generation fences) stays in resolveFirstUsableOpenAiSidecar and the
12
+ * executors; this module only answers "is this side worth offering at all?".
13
+ */
14
+ import type { OcxConfig, OcxProviderConfig } from "../types";
15
+ import { listOpenAiForwardSidecarCandidates } from "../providers/openai-sidecar";
16
+ import { OPENAI_CODEX_PROVIDER_ID } from "../providers/openai-tiers";
17
+ import { isCodexAccountUsable } from "../codex/account-usability";
18
+ import { MAIN_CODEX_ACCOUNT_ID, isSelectableCodexPoolAccount } from "../codex/account-id";
19
+ import { getAccountSet } from "../oauth/store";
20
+
21
+ export interface SidecarAuthState {
22
+ /** ChatGPT login usable: canonical forward provider AND a live stored credential. */
23
+ isCodexAuth: boolean;
24
+ /** Enabled anthropic-adapter OAuth provider whose active account is not marked for reauth. */
25
+ isAnthropicAuth: boolean;
26
+ /** The provider an Anthropic-side executor would dispatch through, when isAnthropicAuth. */
27
+ anthropicProviderName?: string;
28
+ anthropicProvider?: OcxProviderConfig;
29
+ }
30
+
31
+ /**
32
+ * Fixed auth-slot models (#2188): logged-in sides keep these candidates even
33
+ * when the picker hides or disables them. The slot is the LOGIN's entitlement,
34
+ * not the catalog's.
35
+ */
36
+ export const AUTH_SLOT_MODELS = {
37
+ codex: "gpt-5.6-luna",
38
+ anthropic: "claude-haiku-4-5",
39
+ } as const;
40
+
41
+ export interface SidecarAuthSlot {
42
+ provider: string;
43
+ id: string;
44
+ slot: keyof typeof AUTH_SLOT_MODELS;
45
+ }
46
+
47
+ /** Login-shaped, not provider-shaped: a forward provider with no credential is NOT Codex auth. */
48
+ function hasUsableCodexLogin(config: OcxConfig): boolean {
49
+ if (listOpenAiForwardSidecarCandidates(config).length === 0) return false;
50
+ if (isCodexAccountUsable(config, MAIN_CODEX_ACCOUNT_ID)) return true;
51
+ return (config.codexAccounts ?? []).some(account =>
52
+ isSelectableCodexPoolAccount(account) && isCodexAccountUsable(config, account.id));
53
+ }
54
+
55
+ /**
56
+ * The predicate previously duplicated as findAnthropicSidecarProvider
57
+ * (web-search) and findAnthropicVisionProvider (vision): first enabled
58
+ * anthropic-adapter OAuth provider whose ACTIVE stored account holds a usable
59
+ * credential. getAccountSet + needsReauth, not getCredential — a terminally
60
+ * invalid account must not present as auth (audit F1).
61
+ */
62
+ function findAnthropicAuthProvider(
63
+ config: OcxConfig,
64
+ ): { providerName: string; provider: OcxProviderConfig } | undefined {
65
+ for (const [providerName, provider] of Object.entries(config.providers)) {
66
+ if (provider.disabled === true) continue;
67
+ if (provider.adapter !== "anthropic" || provider.authMode !== "oauth") continue;
68
+ const set = getAccountSet(providerName);
69
+ const active = set?.accounts.find(account => account.id === set.activeAccountId);
70
+ if (active && active.needsReauth !== true) return { providerName, provider };
71
+ }
72
+ return undefined;
73
+ }
74
+
75
+ export function resolveSidecarAuth(config: OcxConfig): SidecarAuthState {
76
+ const anthropic = findAnthropicAuthProvider(config);
77
+ return {
78
+ isCodexAuth: hasUsableCodexLogin(config),
79
+ isAnthropicAuth: anthropic !== undefined,
80
+ ...(anthropic ? { anthropicProviderName: anthropic.providerName, anthropicProvider: anthropic.provider } : {}),
81
+ };
82
+ }
83
+
84
+ /** The auth-entitled fixed candidates. Emitted regardless of picker visibility. */
85
+ export function sidecarAuthSlots(auth: SidecarAuthState): SidecarAuthSlot[] {
86
+ const slots: SidecarAuthSlot[] = [];
87
+ if (auth.isCodexAuth) slots.push({ provider: OPENAI_CODEX_PROVIDER_ID, id: AUTH_SLOT_MODELS.codex, slot: "codex" });
88
+ if (auth.isAnthropicAuth && auth.anthropicProviderName) {
89
+ slots.push({ provider: auth.anthropicProviderName, id: AUTH_SLOT_MODELS.anthropic, slot: "anthropic" });
90
+ }
91
+ return slots;
92
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * The unified picker-visibility candidate set both sidecars consume (#2188).
3
+ *
4
+ * Rule 1 (picker): a model may be OFFERED as a sidecar backend only if the
5
+ * management picker would show it — the same `listManagementModelRows` rows
6
+ * the GUI Models tab renders, minus disabled rows. Rule 1's only exception is
7
+ * the auth slots: a logged-in side keeps its fixed slot model (Luna/Haiku)
8
+ * even when the picker hides it, because the slot is the login's entitlement.
9
+ *
10
+ * Vision additionally applies rule 2 (− provably text-only); web-search
11
+ * applies its own rule 2 (∩ probed backend with an executor) in
12
+ * src/web-search/backends.ts. Both start from THIS set so the two sidecars
13
+ * cannot diverge on what "visible" means.
14
+ */
15
+ import type { OcxConfig } from "../types";
16
+ import { listManagementModelRows } from "../server/management/model-rows";
17
+ import { modelAcceptsImageInput, type VisionCandidateModel } from "../vision/eligibility";
18
+ import { sidecarAuthSlots, type SidecarAuthState } from "./auth";
19
+
20
+ export interface SidecarCandidate {
21
+ provider: string;
22
+ id: string;
23
+ native?: boolean;
24
+ inputModalities?: string[];
25
+ /** True when this row is an auth-slot entitlement rather than a picker row. */
26
+ authSlot?: boolean;
27
+ }
28
+
29
+ /**
30
+ * (picker-visible rows) ∪ (auth slots). De-duplicated by provider+id with the
31
+ * auth-slot flag winning, so a slot model that is ALSO picker-visible still
32
+ * reads as slot-backed. A catalog outage degrades to slots only — the settings
33
+ * routes must not 500 and must keep the logged-in floor populated.
34
+ */
35
+ export async function pickerVisibleSidecarCandidates(
36
+ config: OcxConfig,
37
+ auth: SidecarAuthState,
38
+ ): Promise<SidecarCandidate[]> {
39
+ let rows: Awaited<ReturnType<typeof listManagementModelRows>> = [];
40
+ try { rows = await listManagementModelRows(config); } catch { rows = []; }
41
+ const byKey = new Map<string, SidecarCandidate>();
42
+ for (const row of rows) {
43
+ if (row.disabled === true) continue;
44
+ byKey.set(`${row.provider}/${row.id}`, {
45
+ provider: row.provider,
46
+ id: row.id,
47
+ ...(row.inputModalities ? { inputModalities: row.inputModalities } : {}),
48
+ ...(row.native ? { native: true } : {}),
49
+ });
50
+ }
51
+ for (const slot of sidecarAuthSlots(auth)) {
52
+ byKey.set(`${slot.provider}/${slot.id}`, {
53
+ provider: slot.provider,
54
+ id: slot.id,
55
+ // Slot models are known image-capable; their only exclusion path is the
56
+ // provider's explicit consumer list (same stance as baselineCandidate).
57
+ inputModalities: ["text", "image"],
58
+ authSlot: true,
59
+ });
60
+ }
61
+ return [...byKey.values()];
62
+ }
63
+
64
+ /**
65
+ * Rule 2 for vision: drop rows PROVABLY text-only. Unknown stays eligible —
66
+ * the picker filter (rule 1) already bounded the set, so permissive-unknown
67
+ * no longer expands to the whole catalog.
68
+ */
69
+ export function visionSidecarCandidates(
70
+ config: Pick<OcxConfig, "providers">,
71
+ all: readonly SidecarCandidate[],
72
+ ): SidecarCandidate[] {
73
+ return all.filter(candidate => modelAcceptsImageInput(config, toVisionCandidate(candidate)) !== false);
74
+ }
75
+
76
+ function toVisionCandidate(candidate: SidecarCandidate): VisionCandidateModel {
77
+ return {
78
+ provider: candidate.provider,
79
+ id: candidate.id,
80
+ ...(candidate.inputModalities ? { inputModalities: candidate.inputModalities } : {}),
81
+ ...(candidate.native ? { native: true } : {}),
82
+ };
83
+ }
@@ -1091,7 +1091,7 @@ function writeSatelliteBackup(
1091
1091
  throw new Error("test_fail_satellite_backup_replace");
1092
1092
  }
1093
1093
  try {
1094
- renameAtomicFile(tmp, dest);
1094
+ renameAtomicFile(tmp, dest, undefined, "storage-cleanup");
1095
1095
  } catch (error) {
1096
1096
  try { unlinkSync(tmp); } catch { /* */ }
1097
1097
  throw error;
@@ -2435,7 +2435,7 @@ function writeRestorePending(
2435
2435
  throw new Error("test_fail_pending_rename");
2436
2436
  }
2437
2437
  try {
2438
- renameSync(tmp, dest);
2438
+ renameAtomicFile(tmp, dest, undefined, "storage-cleanup");
2439
2439
  } catch (error) {
2440
2440
  try { unlinkSync(tmp); } catch { /* */ }
2441
2441
  throw error;
@@ -16,7 +16,7 @@ const IMMUTABLE_READONLY_FLAGS = constants.SQLITE_OPEN_READONLY | constants.SQLI
16
16
 
17
17
  /**
18
18
  * Read-only CODEX_HOME storage scanner — Phase 1 of the Storage page epic
19
- * (devlog/_plan/500_storage-page-session-cleanup). Pure measurement: sizes via
19
+ * (devlog/_fin/500_storage-page-session-cleanup). Pure measurement: sizes via
20
20
  * fs.stat walks, DB row counts via immutable readonly opens that degrade to
21
21
  * null on lock/corruption. Performs zero writes under CODEX_HOME.
22
22
  */
@@ -11,10 +11,9 @@
11
11
  * time (so we cannot miss `self.close()` / early exit), stays in `liveWorkers`
12
12
  * until that close settles, and `drainStorageWorkers()` joins every in-flight
13
13
  * terminate. Spawns are serialized through `withStorageWorkerSpawnGate` so the
14
- * next Worker cannot be created until prior threads have exited. On Windows and
15
- * macOS, a post-close settle covers the OS join gap Bun does not expose
16
- * (Windows unbalanced join panic; macOS Silicon balanced-count segfault under
17
- * `bun test --isolate`).
14
+ * next Worker cannot be created until prior threads have exited. A post-close
15
+ * settle covers the OS/runtime join gap Bun does not expose on Windows, macOS,
16
+ * and Linux (including Bun 1.3.14 isolate crashes and Linux `epoll_ctl` reuse).
18
17
  */
19
18
 
20
19
  import { createAdmissionGate, type AdmissionMetrics, type AdmissionReservation } from "../lib/admission";
@@ -52,15 +51,15 @@ let spawnCancelEpoch = 0;
52
51
  /**
53
52
  * OS-join gap after the `close` event on platforms where Bun's Worker reclaim
54
53
  * races the isolate/file boundary (not a CI job-timeout bump).
55
- * Windows GHA at 250ms and 750ms still left `workers_spawned(N)
56
- * workers_terminated(N-1)` panics under isolate (seen mid
57
- * `storage-mutation-race` with 11/10). 1500ms covers deferred reclaim under
58
- * stacked policy/restore workers. Darwin uses 250ms.
54
+ * Windows GHA at 250ms and 750ms still left `workers_spawned(N)`
55
+ * `workers_terminated(N-1)` panics under isolate, so Windows keeps 1500ms.
56
+ * Darwin and Linux use a shorter settle for the balanced-count/epoll reclaim
57
+ * window seen on Bun 1.3.14.
59
58
  */
60
- const WORKER_OS_JOIN_MS = process.platform === "win32" ? 1_500 : 250;
61
-
62
- function needsWorkerOsJoinSettle(): boolean {
63
- return process.platform === "win32" || process.platform === "darwin";
59
+ export function storageWorkerOsJoinSettleMs(platform = process.platform): number {
60
+ if (platform === "win32") return 1_500;
61
+ if (platform === "darwin" || platform === "linux") return 250;
62
+ return 0;
64
63
  }
65
64
 
66
65
  /** Invalidate spawn callbacks still waiting on the gate (reset / server drain). */
@@ -181,9 +180,10 @@ export function terminateStorageWorker(worker: Worker, timeoutMs = 5_000): Promi
181
180
  // only forces `closed`, it does not prove the OS thread has exited.
182
181
  // Callers that catch and continue (e.g. drainAndShutdown) still need
183
182
  // that gap before the next isolate reclaim or server.stop.
184
- if (needsWorkerOsJoinSettle()) {
183
+ const settleMs = storageWorkerOsJoinSettleMs();
184
+ if (settleMs > 0) {
185
185
  await Bun.sleep(0);
186
- await Bun.sleep(WORKER_OS_JOIN_MS);
186
+ await Bun.sleep(settleMs);
187
187
  }
188
188
  if (timedOut) {
189
189
  throw new Error(`storage worker did not exit within ${timeoutMs}ms`);
@@ -3,6 +3,9 @@ param(
3
3
  [Parameter(Mandatory = $true)][string]$CliPath,
4
4
  [Parameter(Mandatory = $true)][string]$CodexHome,
5
5
  [Parameter(Mandatory = $true)][string]$OpenCodexHome,
6
+ # Provenance of $BunPath, chosen when the tray entry was built. Optional so an
7
+ # already-installed launcher command from an older version still starts.
8
+ [ValidateSet("", "override", "bundled", "process")][string]$BunRuntimeSource = "",
6
9
  [ValidateSet("Run", "Stop")][string]$Mode = "Run",
7
10
  [int]$HostPid = 0
8
11
  )
@@ -81,7 +84,7 @@ function ConvertTo-NativeArgument([string]$Value) {
81
84
  return '"' + $Value + '"'
82
85
  }
83
86
 
84
- function Start-OcxCommand([string[]]$CommandArgs) {
87
+ function Start-OcxCommand([string[]]$CommandArgs, [switch]$TrackExit) {
85
88
  try {
86
89
  $allArgs = @($CliPath) + $CommandArgs
87
90
  $psi = New-Object System.Diagnostics.ProcessStartInfo
@@ -92,9 +95,17 @@ function Start-OcxCommand([string[]]$CommandArgs) {
92
95
  $psi.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
93
96
  $psi.EnvironmentVariables["CODEX_HOME"] = $CodexHome
94
97
  $psi.EnvironmentVariables["OPENCODEX_HOME"] = $OpenCodexHome
98
+ if ($BunRuntimeSource) {
99
+ $psi.EnvironmentVariables["OCX_BUN_RUNTIME_SOURCE"] = $BunRuntimeSource
100
+ # Paired with the source so a later relaunch can tell the marker still describes
101
+ # this binary rather than one it merely inherited.
102
+ $psi.EnvironmentVariables["OCX_BUN_RUNTIME_PATH"] = $BunPath
103
+ }
95
104
  $process = [System.Diagnostics.Process]::Start($psi)
96
- if ($null -ne $process) { $process.Dispose() }
105
+ if ($null -eq $process) { throw "Process did not start" }
97
106
  Write-ActionLog "dispatched $($CommandArgs -join ' ')"
107
+ if ($TrackExit) { return $process }
108
+ $process.Dispose()
98
109
  return $true
99
110
  } catch {
100
111
  Write-ActionLog "launch failed: $($_.Exception.GetType().Name)"
@@ -163,18 +174,40 @@ $script:pendingAction = $null
163
174
  $script:pendingStarted = 0L
164
175
  $script:pendingDeadline = 0L
165
176
  $script:pendingOldProxyPid = $null
177
+ $script:pendingProcess = $null
166
178
 
167
179
  function Set-PendingAction([string]$Action, [int]$TimeoutSeconds) {
180
+ if ($null -ne $script:pendingAction) {
181
+ Write-ActionLog "$Action ignored because $($script:pendingAction) is still pending"
182
+ return $false
183
+ }
184
+ if ($null -ne $script:pendingProcess) {
185
+ try {
186
+ $script:pendingProcess.Dispose()
187
+ } catch {
188
+ Write-ActionLog "pending process dispose failed: $($_.Exception.GetType().Name)"
189
+ }
190
+ $script:pendingProcess = $null
191
+ }
168
192
  $script:pendingAction = $Action
169
193
  $script:pendingStarted = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
170
194
  $script:pendingDeadline = $script:pendingStarted + ($TimeoutSeconds * 1000)
171
195
  $script:pendingOldProxyPid = $script:proxyPid
196
+ return $true
172
197
  }
173
198
 
174
199
  function Complete-PendingAction([bool]$Success) {
175
200
  if ($null -eq $script:pendingAction) { return }
176
201
  $action = $script:pendingAction
177
202
  $script:pendingAction = $null
203
+ if ($null -ne $script:pendingProcess) {
204
+ try {
205
+ $script:pendingProcess.Dispose()
206
+ } catch {
207
+ Write-ActionLog "pending process dispose failed: $($_.Exception.GetType().Name)"
208
+ }
209
+ $script:pendingProcess = $null
210
+ }
178
211
  if ($Success) {
179
212
  Write-ActionLog "$action completed (port=$($script:port), pid=$($script:proxyPid))"
180
213
  $notify.ShowBalloonTip(2500, "opencodex", "$action completed.", [System.Windows.Forms.ToolTipIcon]::Info)
@@ -217,6 +250,11 @@ function Update-TrayState {
217
250
  $stopItem.Enabled = $false
218
251
  $restartItem.Enabled = $false
219
252
  }
253
+ if ($null -ne $script:pendingAction) {
254
+ $startItem.Enabled = $false
255
+ $stopItem.Enabled = $false
256
+ $restartItem.Enabled = $false
257
+ }
220
258
  $heartbeat = @{ pid = $PID; timestamp = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds() }
221
259
  if ($HostPid -gt 0) { $heartbeat.hostPid = $HostPid }
222
260
  $heartbeatJson = $heartbeat | ConvertTo-Json -Compress
@@ -228,26 +266,59 @@ function Update-TrayState {
228
266
  $reached = ($script:pendingAction -eq "Start Proxy" -and $script:online) -or
229
267
  ($script:pendingAction -eq "Stop Proxy" -and -not $script:online) -or
230
268
  ($script:pendingAction -eq "Restart Proxy" -and $elapsed -gt 3000 -and $script:online -and $script:proxyPid -ne $script:pendingOldProxyPid)
231
- if ($reached) { Complete-PendingAction $true }
269
+ $commandFailed = $false
270
+ if ($null -ne $script:pendingProcess) {
271
+ try {
272
+ $commandFailed = $script:pendingProcess.HasExited -and $script:pendingProcess.ExitCode -ne 0
273
+ } catch {
274
+ Write-ActionLog "pending process result inspection failed: $($_.Exception.GetType().Name)"
275
+ # If we cannot inspect the tracked command, we cannot prove it is still
276
+ # healthy. Fail the pending action instead of silently waiting for a later
277
+ # timeout and presenting an indeterminate process as success-capable.
278
+ $commandFailed = $true
279
+ }
280
+ }
281
+ if ($commandFailed) { Complete-PendingAction $false }
282
+ elseif ($reached) { Complete-PendingAction $true }
232
283
  elseif ($now -gt $script:pendingDeadline) { Complete-PendingAction $false }
233
284
  }
234
285
  }
235
286
 
236
287
  $openItem.add_Click({ Start-OcxCommand @("gui") })
237
288
  $startItem.add_Click({
289
+ if (-not (Set-PendingAction "Start Proxy" 75)) { return }
238
290
  $statusItem.Text = "Proxy: Starting..."
239
- Set-PendingAction "Start Proxy" 15
240
- if (-not (Start-OcxCommand @("__tray-start"))) { $script:pendingAction = $null }
291
+ # service start can spend 20s and the CLI then observes health for another 40s.
292
+ $startProcess = Start-OcxCommand @("__tray-start") -TrackExit
293
+ if ($startProcess -is [System.Diagnostics.Process]) {
294
+ $script:pendingProcess = $startProcess
295
+ } else {
296
+ Complete-PendingAction $false
297
+ }
241
298
  })
242
299
  $stopItem.add_Click({
300
+ if (-not (Set-PendingAction "Stop Proxy" 15)) { return }
243
301
  $statusItem.Text = "Proxy: Stopping..."
244
- Set-PendingAction "Stop Proxy" 15
245
- if (-not (Start-OcxCommand @("stop"))) { $script:pendingAction = $null }
302
+ $stopProcess = Start-OcxCommand @("stop") -TrackExit
303
+ if ($stopProcess -is [System.Diagnostics.Process]) {
304
+ $script:pendingProcess = $stopProcess
305
+ } else {
306
+ Complete-PendingAction $false
307
+ }
246
308
  })
247
309
  $restartItem.add_Click({
310
+ if (-not (Set-PendingAction "Restart Proxy" 160)) { return }
248
311
  $statusItem.Text = "Proxy: Restarting..."
249
- Set-PendingAction "Restart Proxy" 20
250
- if (-not (Start-OcxCommand @("__tray-restart"))) { $script:pendingAction = $null }
312
+ # /api/system/restart may drain active work for 60s and then spend up to 70s
313
+ # handing off to an identity-verified replacement. The tray observes health/PID
314
+ # rather than the detached CLI exit, so keep a watchdog margin around that shared
315
+ # lifecycle budget. The CLI remains the lifecycle owner; the tray never kills.
316
+ $restartProcess = Start-OcxCommand @("__tray-restart") -TrackExit
317
+ if ($restartProcess -is [System.Diagnostics.Process]) {
318
+ $script:pendingProcess = $restartProcess
319
+ } else {
320
+ Complete-PendingAction $false
321
+ }
251
322
  })
252
323
  $logsItem.add_Click({
253
324
  $psi = New-Object System.Diagnostics.ProcessStartInfo
@@ -280,6 +351,9 @@ try {
280
351
  $timer.Stop()
281
352
  $timer.Dispose()
282
353
  $notify.Visible = $false
354
+ if ($null -ne $script:pendingProcess) {
355
+ try { $script:pendingProcess.Dispose() } catch { $null = $_ }
356
+ }
283
357
  $notify.Dispose()
284
358
  foreach ($icon in $script:ownedIcons) { $icon.Dispose() }
285
359
  $menu.Dispose()
@@ -1,12 +1,15 @@
1
1
  import { execFile, execFileSync, spawn } from "node:child_process";
2
2
  import { createHash } from "node:crypto";
3
- import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
3
+ import { chmodSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
4
4
  import { homedir } from "node:os";
5
5
  import { join, resolve } from "node:path";
6
6
  import { expandUserPath, getConfigDir } from "../config";
7
- import { durableBunPath } from "../lib/bun-runtime";
8
- import { forgetHardenedSecretPath, hardenSecretDir, hardenSecretPath } from "../lib/windows-secret-acl";
7
+ import { durableBunRuntime } from "../lib/bun-runtime";
8
+ import type { BunRuntimeSource } from "../lib/bun-runtime";
9
+ import { forgetEphemeralSecretPath, hardenSecretDir, hardenSecretPath } from "../lib/windows-secret-acl";
9
10
  import { recordOwnedConfigPath } from "../lib/config-ownership";
11
+ import { renameAtomicFile } from "../lib/windows-atomic-replace";
12
+ import { decodeWindowsTextBytes } from "../lib/windows-text";
10
13
 
11
14
  const RUN_KEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
12
15
  const RUN_PARENT_KEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion";
@@ -20,6 +23,8 @@ const TRAY_ICON_FILES = [
20
23
 
21
24
  export interface WindowsTrayEntry {
22
25
  bun: string;
26
+ /** Provenance of `bun`, resolved together with it. */
27
+ bunRuntimeSource: BunRuntimeSource;
23
28
  cli: string;
24
29
  script: string;
25
30
  codexHome: string;
@@ -81,8 +86,10 @@ function currentCodexHome(): string {
81
86
  }
82
87
 
83
88
  function currentEntry(): WindowsTrayEntry {
89
+ const runtime = durableBunRuntime();
84
90
  return {
85
- bun: durableBunPath(),
91
+ bun: runtime.path,
92
+ bunRuntimeSource: runtime.source,
86
93
  cli: join(import.meta.dir, "..", "cli", "index.ts"),
87
94
  script: installedTrayScriptPath(),
88
95
  codexHome: currentCodexHome(),
@@ -111,12 +118,31 @@ function registryExe(): string {
111
118
  return existsSync(candidate) ? candidate : "reg.exe";
112
119
  }
113
120
 
121
+ /**
122
+ * Decode `reg.exe` output the way the rest of the product decodes Windows console
123
+ * output.
124
+ *
125
+ * `reg.exe` writes the console ANSI code page when its output is redirected, not
126
+ * UTF-8. Reading it as utf8 corrupts every non-ASCII byte, so a profile path such
127
+ * as `C:\Users\M<o-umlaut>tz` came back with replacement characters, the
128
+ * comparison against the value we wrote could never match, `registrationOwned`
129
+ * went false, and the CLI reported the tray registration as
130
+ * "foreign, stale, or points to missing package files" over an entry that was
131
+ * correct and owned (#1933).
132
+ *
133
+ * `decodeWindowsTextBytes` already solves this for `schtasks` (#1573). The tray
134
+ * reader was the site that class fix missed.
135
+ */
136
+ function decodeRegistryOutput(stdout: Buffer | string): string {
137
+ const bytes = typeof stdout === "string" ? Buffer.from(stdout, "binary") : stdout;
138
+ return decodeWindowsTextBytes(bytes).trim();
139
+ }
140
+
114
141
  function runRegistry(args: string[]): string {
115
- return execFileSync(registryExe(), args, {
116
- encoding: "utf8",
142
+ return decodeRegistryOutput(execFileSync(registryExe(), args, {
117
143
  stdio: ["ignore", "pipe", "pipe"],
118
144
  windowsHide: true,
119
- }).trim();
145
+ }));
120
146
  }
121
147
 
122
148
  function safePath(value: string): string {
@@ -133,9 +159,9 @@ export function windowsTrayProcessArgs(entry: WindowsTrayEntry, mode: "Run" | "S
133
159
  "-NonInteractive",
134
160
  "-STA",
135
161
  "-ExecutionPolicy", "Bypass",
136
- "-WindowStyle", "Hidden",
137
162
  "-File", safePath(entry.script),
138
163
  "-BunPath", safePath(entry.bun),
164
+ "-BunRuntimeSource", entry.bunRuntimeSource,
139
165
  "-CliPath", safePath(entry.cli),
140
166
  "-CodexHome", safePath(entry.codexHome),
141
167
  "-OpenCodexHome", safePath(entry.opencodexHome),
@@ -167,9 +193,9 @@ export function buildWindowsTrayPowerShellCommand(entry: WindowsTrayEntry, power
167
193
  "-NonInteractive",
168
194
  "-STA",
169
195
  "-ExecutionPolicy", "Bypass",
170
- "-WindowStyle", "Hidden",
171
196
  "-File", quoteRunValue(entry.script),
172
197
  "-BunPath", quoteRunValue(entry.bun),
198
+ "-BunRuntimeSource", entry.bunRuntimeSource,
173
199
  "-CliPath", quoteRunValue(entry.cli),
174
200
  "-CodexHome", quoteRunValue(entry.codexHome),
175
201
  "-OpenCodexHome", quoteRunValue(entry.opencodexHome),
@@ -233,10 +259,11 @@ export function replaceWindowsTrayOwnedFile(
233
259
  harden: target => {
234
260
  try { chmodSync(target, 0o600); } catch { /* best-effort */ }
235
261
  if (process.platform !== "win32") return;
236
- const hardened = hardenSecretPath(target, { required: true });
262
+ // Destination-keyed timeout memo: retries share one memo per final path.
263
+ const hardened = hardenSecretPath(target, { required: true, timeoutMemoKey: path });
237
264
  if (!hardened.ok) throw new Error("Windows tray ACL hardening did not complete; refusing to persist executable state.");
238
265
  },
239
- rename: renameSync,
266
+ rename: (source, destination) => renameAtomicFile(source, destination, undefined, "tray"),
240
267
  unlink: unlinkSync,
241
268
  },
242
269
  ): void {
@@ -247,14 +274,14 @@ export function replaceWindowsTrayOwnedFile(
247
274
  io.harden(temporary);
248
275
  io.rename(temporary, path);
249
276
  renamed = true;
250
- forgetHardenedSecretPath(temporary);
277
+ forgetEphemeralSecretPath(temporary);
251
278
  } finally {
252
279
  if (!renamed) {
253
280
  try {
254
281
  io.unlink(temporary);
255
- forgetHardenedSecretPath(temporary);
282
+ forgetEphemeralSecretPath(temporary);
256
283
  } catch (error) {
257
- if ((error as NodeJS.ErrnoException).code === "ENOENT") forgetHardenedSecretPath(temporary);
284
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") forgetEphemeralSecretPath(temporary);
258
285
  }
259
286
  }
260
287
  }
@@ -328,13 +355,13 @@ function readOwnedRunValue(runValue = windowsTrayRunValue(getConfigDir())): stri
328
355
  function runRegistryAsync(args: string[]): Promise<string> {
329
356
  return new Promise((resolvePromise, rejectPromise) => {
330
357
  execFile(registryExe(), args, {
331
- encoding: "utf8",
358
+ encoding: "buffer",
332
359
  timeout: 2_000,
333
360
  windowsHide: true,
334
361
  maxBuffer: 64 * 1024,
335
362
  }, (error, stdout) => {
336
363
  if (error) rejectPromise(error);
337
- else resolvePromise(stdout.trim());
364
+ else resolvePromise(decodeRegistryOutput(stdout));
338
365
  });
339
366
  });
340
367
  }
@@ -0,0 +1,37 @@
1
+ export interface CodexAccount {
2
+ id: string;
3
+ email: string;
4
+ /** User-owned display label; never participates in routing or identity checks. */
5
+ alias?: string;
6
+ plan?: string;
7
+ /**
8
+ * Provenance of `plan`. WHAM (live quota API) is authoritative; the JWT
9
+ * `chatgpt_plan_type` claim is a fallback that may lag a plan change. A JWT write
10
+ * must never overwrite a WHAM-sourced plan observed for the same credential
11
+ * generation — only a newer generation (token refresh after the WHAM read) may.
12
+ */
13
+ planSource?: "jwt" | "wham";
14
+ /** Credential generation at which `plan`/`planSource` was recorded. */
15
+ planCredentialGeneration?: number;
16
+ chatgptAccountId?: string;
17
+ logLabel?: string;
18
+ isMain: boolean;
19
+ }
20
+
21
+ export interface CodexAccountCredentials {
22
+ accessToken: string;
23
+ refreshToken: string;
24
+ expiresAt: number;
25
+ chatgptAccountId: string;
26
+ }
27
+
28
+ export interface CodexAccountCredentialRecord {
29
+ credential?: CodexAccountCredentials;
30
+ generation: number;
31
+ refreshGrantFingerprint?: string;
32
+ deletedAt?: number;
33
+ replacedAt?: number;
34
+ lastCodexValidatedAt?: number;
35
+ lastCodexValidationStatus?: "ok" | "failed";
36
+ lastCodexValidationError?: string;
37
+ }