@iislee/opencodex 2.11.0 → 2.35.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 (733) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +117 -22
  3. package/bin/ocx.mjs +245 -88
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-Be1sDpWw.css +1 -0
  6. package/gui/dist/assets/index-D4OKgUV4.js +114 -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 +21 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +475 -62
  44. package/src/adapters/base.ts +82 -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 +637 -0
  48. package/src/adapters/cursor/call-id.ts +44 -0
  49. package/src/adapters/cursor/catalog.ts +541 -0
  50. package/src/adapters/cursor/checkpoint-store.ts +308 -0
  51. package/src/adapters/cursor/cursor-errors.ts +144 -6
  52. package/src/adapters/cursor/discovery.ts +122 -14
  53. package/src/adapters/cursor/effort-map.ts +106 -4
  54. package/src/adapters/cursor/envelope-echo.ts +290 -0
  55. package/src/adapters/cursor/framing.ts +39 -0
  56. package/src/adapters/cursor/h2-pool.ts +123 -0
  57. package/src/adapters/cursor/http1-bidi.ts +361 -0
  58. package/src/adapters/cursor/images.ts +704 -0
  59. package/src/adapters/cursor/live-models.ts +180 -59
  60. package/src/adapters/cursor/live-transport.ts +623 -170
  61. package/src/adapters/cursor/message-mapper.ts +4 -1
  62. package/src/adapters/cursor/native-exec-common.ts +23 -2
  63. package/src/adapters/cursor/native-exec-desktop.ts +23 -0
  64. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  65. package/src/adapters/cursor/native-exec-network.ts +1 -1
  66. package/src/adapters/cursor/native-exec-shell.ts +5 -3
  67. package/src/adapters/cursor/native-exec.ts +121 -14
  68. package/src/adapters/cursor/protobuf-events.ts +829 -11
  69. package/src/adapters/cursor/protobuf-request.ts +447 -75
  70. package/src/adapters/cursor/request-builder.ts +271 -35
  71. package/src/adapters/cursor/tool-definitions.ts +252 -12
  72. package/src/adapters/cursor/tool-result-normalize.ts +115 -0
  73. package/src/adapters/cursor/transport.ts +22 -0
  74. package/src/adapters/cursor/types.ts +48 -1
  75. package/src/adapters/cursor.ts +336 -39
  76. package/src/adapters/exec-tool-result-normalize.ts +99 -0
  77. package/src/adapters/google-antigravity-replay.ts +713 -41
  78. package/src/adapters/google-antigravity-wire.ts +48 -10
  79. package/src/adapters/google-errors.ts +44 -12
  80. package/src/adapters/google-http.ts +38 -10
  81. package/src/adapters/google-tool-schema.ts +80 -15
  82. package/src/adapters/google-truncation.ts +11 -0
  83. package/src/adapters/google.ts +742 -86
  84. package/src/adapters/identity.ts +39 -6
  85. package/src/adapters/image.ts +1 -1
  86. package/src/adapters/kiro-constants.ts +27 -0
  87. package/src/adapters/kiro-errors.ts +11 -0
  88. package/src/adapters/kiro-events.ts +19 -1
  89. package/src/adapters/kiro-thinking.ts +18 -2
  90. package/src/adapters/kiro-tools.ts +65 -17
  91. package/src/adapters/kiro.ts +270 -73
  92. package/src/adapters/mimo-free.ts +17 -0
  93. package/src/adapters/openai-chat-url.ts +11 -0
  94. package/src/adapters/openai-chat.ts +1377 -344
  95. package/src/adapters/openai-responses-url.ts +16 -0
  96. package/src/adapters/openai-responses.ts +1164 -64
  97. package/src/adapters/registry.ts +175 -0
  98. package/src/adapters/responses-tool-schema.ts +67 -0
  99. package/src/adapters/run-turn-queue.ts +36 -1
  100. package/src/adapters/tool-call-id.ts +119 -0
  101. package/src/adapters/tool-catalog-nudge.ts +105 -21
  102. package/src/adapters/xai-tool-schema.ts +436 -0
  103. package/src/adapters/xai-web-search.ts +186 -0
  104. package/src/bridge.ts +512 -92
  105. package/src/chat/inbound.ts +57 -20
  106. package/src/chat/outbound.ts +97 -33
  107. package/src/claude/agents-inject.ts +40 -10
  108. package/src/claude/context-windows.ts +37 -14
  109. package/src/claude/desktop-3p.ts +243 -9
  110. package/src/claude/gateway-cache.ts +41 -4
  111. package/src/claude/inbound.ts +72 -3
  112. package/src/claude/model-info.ts +38 -15
  113. package/src/claude/outbound.ts +88 -21
  114. package/src/cli/access.ts +46 -3
  115. package/src/cli/account-api.ts +150 -19
  116. package/src/cli/account-auth.ts +33 -6
  117. package/src/cli/account-catalog-refresh.ts +14 -0
  118. package/src/cli/account-extended.ts +648 -28
  119. package/src/cli/account-main.ts +317 -0
  120. package/src/cli/account.ts +97 -19
  121. package/src/cli/agent.ts +53 -2
  122. package/src/cli/alias.ts +66 -0
  123. package/src/cli/capabilities-command.ts +94 -0
  124. package/src/cli/capabilities.ts +496 -0
  125. package/src/cli/claude-agent-startup-sync.ts +73 -0
  126. package/src/cli/claude-desktop.ts +60 -15
  127. package/src/cli/claude.ts +129 -35
  128. package/src/cli/codex-log-guard-doctor.ts +103 -0
  129. package/src/cli/codex-shim-autorestore.ts +2 -0
  130. package/src/cli/codex-shim-readiness.ts +76 -0
  131. package/src/cli/combo.ts +8 -0
  132. package/src/cli/config-command.ts +74 -10
  133. package/src/cli/dispatch.ts +821 -0
  134. package/src/cli/doctor.ts +440 -56
  135. package/src/cli/ensure-desired-integrations.ts +152 -0
  136. package/src/cli/export-command.ts +46 -20
  137. package/src/cli/help.ts +34 -274
  138. package/src/cli/index.ts +417 -528
  139. package/src/cli/init.ts +5 -17
  140. package/src/cli/inspect.ts +230 -0
  141. package/src/cli/integrations.ts +120 -2
  142. package/src/cli/lab.ts +607 -0
  143. package/src/cli/launcher-context.ts +77 -0
  144. package/src/cli/minimax.ts +497 -0
  145. package/src/cli/models-runtime.ts +130 -2
  146. package/src/cli/models.ts +118 -16
  147. package/src/cli/observe.ts +123 -11
  148. package/src/cli/opencode.ts +4 -2
  149. package/src/cli/provider-runtime.ts +34 -3
  150. package/src/cli/provider.ts +25 -3
  151. package/src/cli/ready.ts +301 -0
  152. package/src/cli/registry.ts +476 -0
  153. package/src/cli/root.ts +86 -0
  154. package/src/cli/route-policy.ts +92 -0
  155. package/src/cli/runtime-api.ts +57 -10
  156. package/src/cli/star-prompt.ts +71 -15
  157. package/src/cli/status.ts +51 -4
  158. package/src/cli/storage.ts +234 -0
  159. package/src/cli/system-command.ts +16 -0
  160. package/src/cli/system-restart-client.ts +146 -0
  161. package/src/cli/tray-proxy.ts +153 -6
  162. package/src/cli/usage-report.ts +184 -0
  163. package/src/cli/v2.ts +137 -18
  164. package/src/cli/version-skew.ts +46 -0
  165. package/src/cli.ts +1 -1
  166. package/src/clients/config-export.ts +1442 -23
  167. package/src/clients/effective-status.ts +30 -2
  168. package/src/clients/probes/cline.ts +81 -0
  169. package/src/codex/account-label.ts +35 -1
  170. package/src/codex/account-lifecycle.ts +130 -13
  171. package/src/codex/account-namespaces.ts +49 -3
  172. package/src/codex/account-pause.ts +2 -1
  173. package/src/codex/account-priority.ts +84 -0
  174. package/src/codex/account-store.ts +29 -2
  175. package/src/codex/account-usability.ts +25 -2
  176. package/src/codex/admission.ts +256 -0
  177. package/src/codex/affinity-debug.ts +162 -0
  178. package/src/codex/app-server-processes.ts +570 -107
  179. package/src/codex/app-server-restart-service.ts +232 -0
  180. package/src/codex/auth-api.ts +893 -246
  181. package/src/codex/auth-collision.ts +5 -3
  182. package/src/codex/auth-context.ts +348 -32
  183. package/src/codex/autostart-health.ts +24 -1
  184. package/src/codex/catalog/account-models.ts +67 -0
  185. package/src/codex/catalog/aggregation.ts +86 -10
  186. package/src/codex/catalog/bundled.ts +331 -33
  187. package/src/codex/catalog/effort.ts +138 -32
  188. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  189. package/src/codex/catalog/kinds.ts +2 -0
  190. package/src/codex/catalog/metadata.ts +555 -45
  191. package/src/codex/catalog/native-models.ts +75 -0
  192. package/src/codex/catalog/parsing.ts +269 -30
  193. package/src/codex/catalog/provider-fetch.ts +1626 -144
  194. package/src/codex/catalog/sync.ts +1576 -187
  195. package/src/codex/catalog-admission.ts +199 -0
  196. package/src/codex/catalog-refresh-status.ts +105 -0
  197. package/src/codex/catalog-write-serialization.ts +242 -0
  198. package/src/codex/catalog.ts +6 -3
  199. package/src/codex/codex-write-lock.ts +386 -0
  200. package/src/codex/convergence-types.ts +614 -0
  201. package/src/codex/convergence.ts +676 -0
  202. package/src/codex/coordinator-doctor.ts +332 -0
  203. package/src/codex/custom-model-catalog-migration.ts +176 -0
  204. package/src/codex/desired-state.ts +230 -0
  205. package/src/codex/desktop-app-restart.ts +355 -0
  206. package/src/codex/features.ts +636 -39
  207. package/src/codex/generation.ts +202 -0
  208. package/src/codex/history-job.ts +436 -0
  209. package/src/codex/history-lock.ts +242 -0
  210. package/src/codex/history-manifest.ts +112 -0
  211. package/src/codex/history-migration-guardian.ts +30 -24
  212. package/src/codex/history-provider.ts +1016 -235
  213. package/src/codex/history-transition.ts +105 -0
  214. package/src/codex/history-worker.ts +223 -0
  215. package/src/codex/inject-coordination.ts +373 -0
  216. package/src/codex/inject.ts +1114 -152
  217. package/src/codex/injected-marker.ts +37 -3
  218. package/src/codex/integration-record.ts +266 -0
  219. package/src/codex/internal/catalog-writer.ts +203 -0
  220. package/src/codex/internal/history-writer.ts +81 -0
  221. package/src/codex/journal.ts +66 -4
  222. package/src/codex/log-guard/inspect.ts +524 -0
  223. package/src/codex/log-guard/lock.ts +150 -0
  224. package/src/codex/log-guard/maintenance.ts +403 -0
  225. package/src/codex/log-guard/path-safety.ts +88 -0
  226. package/src/codex/log-guard/policy.ts +44 -0
  227. package/src/codex/log-guard/processes.ts +205 -0
  228. package/src/codex/log-guard/protection.ts +489 -0
  229. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  230. package/src/codex/main-account-cache.ts +24 -0
  231. package/src/codex/main-account.ts +29 -1
  232. package/src/codex/management-convergence.ts +167 -0
  233. package/src/codex/model-cache.ts +56 -10
  234. package/src/codex/model-entitlements.ts +360 -0
  235. package/src/codex/native-main-admission.ts +47 -0
  236. package/src/codex/native-main-auth-temp.ts +187 -0
  237. package/src/codex/native-main-claim.ts +178 -0
  238. package/src/codex/native-main-lock-file.ts +162 -0
  239. package/src/codex/native-main-owner.ts +329 -0
  240. package/src/codex/native-profile-api.ts +247 -0
  241. package/src/codex/native-profile-manager.ts +1531 -0
  242. package/src/codex/native-profile-processes.ts +121 -0
  243. package/src/codex/native-profile-recovery.ts +99 -0
  244. package/src/codex/native-profile-stage-store.ts +387 -0
  245. package/src/codex/native-profile-startup.ts +622 -0
  246. package/src/codex/native-profile-store.ts +855 -0
  247. package/src/codex/native-profile-types.ts +120 -0
  248. package/src/codex/native-residue.ts +675 -0
  249. package/src/codex/paths.ts +80 -1
  250. package/src/codex/plan-from-token.ts +140 -0
  251. package/src/codex/plan.ts +40 -0
  252. package/src/codex/plugins-doctor.ts +1 -1
  253. package/src/codex/pool-rotation.ts +74 -4
  254. package/src/codex/project-config-warnings.ts +20 -6
  255. package/src/codex/prompt-journal.ts +352 -0
  256. package/src/codex/prompt-layers.ts +1313 -0
  257. package/src/codex/prompt-lock.ts +143 -0
  258. package/src/codex/prompt-text-probe.ts +238 -0
  259. package/src/codex/quota-rejection.ts +298 -0
  260. package/src/codex/quota.ts +264 -21
  261. package/src/codex/refresh.ts +11 -2
  262. package/src/codex/reset-credit-recovery.ts +1044 -0
  263. package/src/codex/routing.ts +514 -94
  264. package/src/codex/runtime.ts +159 -38
  265. package/src/codex/shim.ts +1065 -31
  266. package/src/codex/subagent-model-fallback.ts +437 -43
  267. package/src/codex/sync.ts +191 -2
  268. package/src/codex/transition-state.ts +720 -0
  269. package/src/codex/upstream-host-health.ts +368 -0
  270. package/src/codex/user-identity.ts +557 -0
  271. package/src/codex/warmup.ts +187 -81
  272. package/src/codex/write-coordination.ts +114 -0
  273. package/src/combos/failover.ts +47 -0
  274. package/src/combos/index.ts +4 -0
  275. package/src/combos/request.ts +32 -0
  276. package/src/combos/types.ts +91 -9
  277. package/src/compatibility/index.ts +26 -0
  278. package/src/compatibility/manifest.ts +253 -0
  279. package/src/compatibility/openai-responses.ts +121 -0
  280. package/src/config/atomic-write.ts +219 -0
  281. package/src/config/paths.ts +40 -0
  282. package/src/config/process-state.ts +309 -0
  283. package/src/config/provider-name.ts +24 -0
  284. package/src/config/provider-validation.ts +177 -0
  285. package/src/config/rebase-provenance.ts +68 -0
  286. package/src/config.ts +1713 -709
  287. package/src/generated/compatibility-version.json +3324 -0
  288. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  289. package/src/grok/inject.ts +16 -5
  290. package/src/grok/inspect.ts +45 -0
  291. package/src/grok/sync.ts +2 -2
  292. package/src/images/loop.ts +157 -33
  293. package/src/images/plan.ts +24 -13
  294. package/src/integrations/config-io.ts +269 -0
  295. package/src/integrations/journal.ts +315 -0
  296. package/src/integrations/merge.ts +135 -0
  297. package/src/integrations/mutation-flight.ts +71 -0
  298. package/src/integrations/native/ownership-preflight.ts +202 -0
  299. package/src/integrations/omp-yaml-source.ts +358 -0
  300. package/src/integrations/owned-refresh.ts +74 -0
  301. package/src/integrations/ownership-policy.ts +160 -0
  302. package/src/integrations/ownership.ts +155 -0
  303. package/src/integrations/registry.ts +166 -0
  304. package/src/integrations/serialize.ts +314 -0
  305. package/src/integrations/state.ts +433 -0
  306. package/src/integrations/store.ts +103 -0
  307. package/src/integrations/writer-lock.ts +98 -0
  308. package/src/integrations/writer.ts +715 -0
  309. package/src/lab/artifacts/sanitize.ts +586 -0
  310. package/src/lab/artifacts/secure-fs.ts +475 -0
  311. package/src/lab/artifacts/store.ts +310 -0
  312. package/src/lab/automation/budgets.ts +78 -0
  313. package/src/lab/automation/config-persistence.ts +256 -0
  314. package/src/lab/automation/constants.ts +39 -0
  315. package/src/lab/automation/cooldown.ts +103 -0
  316. package/src/lab/automation/dispatch.ts +211 -0
  317. package/src/lab/automation/index.ts +13 -0
  318. package/src/lab/automation/orchestrator.ts +499 -0
  319. package/src/lab/automation/persistence.ts +512 -0
  320. package/src/lab/automation/planner.ts +371 -0
  321. package/src/lab/automation/policy.ts +136 -0
  322. package/src/lab/automation/queue.ts +191 -0
  323. package/src/lab/automation/recovery.ts +24 -0
  324. package/src/lab/automation/route-context.ts +21 -0
  325. package/src/lab/automation/run-key.ts +44 -0
  326. package/src/lab/automation/runs-query.ts +34 -0
  327. package/src/lab/automation/types.ts +160 -0
  328. package/src/lab/conformance/assertion.ts +325 -0
  329. package/src/lab/conformance/digest.ts +22 -0
  330. package/src/lab/conformance/executor.ts +741 -0
  331. package/src/lab/conformance/fixture-provider.ts +27 -0
  332. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  333. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  334. package/src/lab/conformance/harness-budget.ts +47 -0
  335. package/src/lab/conformance/index.ts +5 -0
  336. package/src/lab/conformance/jcs.ts +64 -0
  337. package/src/lab/conformance/json-pointer.ts +39 -0
  338. package/src/lab/conformance/manifest.ts +180 -0
  339. package/src/lab/conformance/mcp-stub.ts +179 -0
  340. package/src/lab/conformance/negative-controls.ts +164 -0
  341. package/src/lab/conformance/observation.ts +355 -0
  342. package/src/lab/conformance/runner.ts +68 -0
  343. package/src/lab/conformance/sse-normalize.ts +59 -0
  344. package/src/lab/conformance/suite-manifest.ts +78 -0
  345. package/src/lab/conformance/types.ts +214 -0
  346. package/src/lab/constants.ts +126 -0
  347. package/src/lab/digest.ts +64 -0
  348. package/src/lab/events/errors.ts +9 -0
  349. package/src/lab/events/limits.ts +117 -0
  350. package/src/lab/events/types.ts +229 -0
  351. package/src/lab/events/validate.ts +781 -0
  352. package/src/lab/fabric/constants.ts +40 -0
  353. package/src/lab/fabric/executor.ts +492 -0
  354. package/src/lab/fabric/index.ts +80 -0
  355. package/src/lab/fabric/manifest.ts +222 -0
  356. package/src/lab/fabric/observe.ts +489 -0
  357. package/src/lab/fabric/patch.ts +79 -0
  358. package/src/lab/fabric/producer-child.ts +139 -0
  359. package/src/lab/fabric/producer-isolate.ts +276 -0
  360. package/src/lab/fabric/producer-protocol.ts +61 -0
  361. package/src/lab/fabric/scratch.ts +439 -0
  362. package/src/lab/fabric/subject.ts +106 -0
  363. package/src/lab/fabric/types.ts +134 -0
  364. package/src/lab/fabric/verifier.ts +98 -0
  365. package/src/lab/index.ts +54 -0
  366. package/src/lab/ledger/artifact-refs.ts +127 -0
  367. package/src/lab/ledger/invalidation.ts +136 -0
  368. package/src/lab/ledger/purge.ts +310 -0
  369. package/src/lab/ledger/store.ts +532 -0
  370. package/src/lab/live/credential-lease.ts +53 -0
  371. package/src/lab/live/destination.ts +155 -0
  372. package/src/lab/live/executor.ts +336 -0
  373. package/src/lab/live/inert-tools.ts +56 -0
  374. package/src/lab/live/manifest.ts +85 -0
  375. package/src/lab/live/mcp-loopback.ts +57 -0
  376. package/src/lab/live/runner.ts +19 -0
  377. package/src/lab/live/sandbox.ts +61 -0
  378. package/src/lab/live/suite-manifest.ts +41 -0
  379. package/src/lab/live/transport.ts +118 -0
  380. package/src/lab/live/types.ts +197 -0
  381. package/src/lab/observe/from-conformance.ts +301 -0
  382. package/src/lab/observe/from-live.ts +117 -0
  383. package/src/lab/paths.ts +153 -0
  384. package/src/lab/projection/rebuild.ts +495 -0
  385. package/src/lab/projection/schema.ts +135 -0
  386. package/src/lab/projection/verdicts.ts +474 -0
  387. package/src/lab/projection/verification.ts +412 -0
  388. package/src/lab/public/bundle.ts +217 -0
  389. package/src/lab/public/community-authority.ts +175 -0
  390. package/src/lab/public/community-files.ts +29 -0
  391. package/src/lab/public/community.ts +479 -0
  392. package/src/lab/public/file-safety.ts +155 -0
  393. package/src/lab/public/ids.ts +26 -0
  394. package/src/lab/public/index.ts +16 -0
  395. package/src/lab/public/mutation-lock.ts +424 -0
  396. package/src/lab/public/operator.ts +353 -0
  397. package/src/lab/public/origin-purge.ts +79 -0
  398. package/src/lab/public/origin.ts +203 -0
  399. package/src/lab/public/privacy.ts +143 -0
  400. package/src/lab/public/private-file.ts +261 -0
  401. package/src/lab/public/project.ts +124 -0
  402. package/src/lab/public/purge-test-fault.ts +21 -0
  403. package/src/lab/public/purge.ts +223 -0
  404. package/src/lab/public/registry.ts +44 -0
  405. package/src/lab/public/revocation.ts +252 -0
  406. package/src/lab/public/signature.ts +243 -0
  407. package/src/lab/public/storage.ts +105 -0
  408. package/src/lab/public/strict-json.ts +206 -0
  409. package/src/lab/public/time.ts +26 -0
  410. package/src/lab/public/types.ts +172 -0
  411. package/src/lab/public/validate.ts +391 -0
  412. package/src/lab/query/catalog.ts +101 -0
  413. package/src/lab/query/connection.ts +107 -0
  414. package/src/lab/query/constants.ts +4 -0
  415. package/src/lab/query/cursor.ts +132 -0
  416. package/src/lab/query/dto-map.ts +277 -0
  417. package/src/lab/query/errors.ts +22 -0
  418. package/src/lab/query/freshness.ts +53 -0
  419. package/src/lab/query/index.ts +45 -0
  420. package/src/lab/query/latest-observation.ts +59 -0
  421. package/src/lab/query/passive-production.ts +159 -0
  422. package/src/lab/query/queries.ts +444 -0
  423. package/src/lab/query/types.ts +266 -0
  424. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  425. package/src/lab/subject/installation-salt.ts +112 -0
  426. package/src/lab/subject/protocol-subject.ts +80 -0
  427. package/src/lab/subject/route-subject.ts +74 -0
  428. package/src/lib/admin-secrets.ts +24 -0
  429. package/src/lib/app-owned-memory-stores.ts +22 -0
  430. package/src/lib/bounded-body.ts +167 -11
  431. package/src/lib/bun-runtime.ts +125 -12
  432. package/src/lib/bun-stream-caps.ts +13 -9
  433. package/src/lib/codex-restart-contract.ts +120 -0
  434. package/src/lib/config-ownership.ts +26 -2
  435. package/src/lib/destination-policy.ts +65 -1
  436. package/src/lib/errors.ts +80 -5
  437. package/src/lib/fabric-task-execution-authority.ts +7 -0
  438. package/src/lib/fabric-task-host.ts +29 -0
  439. package/src/lib/lab-activation.ts +223 -0
  440. package/src/lib/lab-live-execution-authority.ts +13 -0
  441. package/src/lib/lab-live-host.ts +30 -0
  442. package/src/lib/lab-live-pinned-sender.ts +56 -0
  443. package/src/lib/lab-live-route-production.ts +130 -0
  444. package/src/lib/lab-passive-linker-registration.ts +26 -0
  445. package/src/lib/local-management-attestation.ts +51 -0
  446. package/src/lib/local-management-capability.ts +100 -0
  447. package/src/lib/local-provider-reload-contract.ts +100 -0
  448. package/src/lib/optional-shutdown-hooks.ts +57 -0
  449. package/src/lib/package-tree-integrity.ts +101 -0
  450. package/src/lib/pinned-http.ts +145 -26
  451. package/src/lib/process-control.ts +6 -2
  452. package/src/lib/provider-outbound.ts +49 -9
  453. package/src/lib/redact.ts +419 -3
  454. package/src/lib/self-launch-argv.ts +15 -0
  455. package/src/lib/server-resource-ownership.ts +71 -0
  456. package/src/lib/service-secrets.ts +15 -0
  457. package/src/lib/shadow-call.ts +35 -4
  458. package/src/lib/sse-decoder.ts +41 -0
  459. package/src/lib/state-store-registrations.ts +10 -2
  460. package/src/lib/system-restart-contract.ts +73 -0
  461. package/src/lib/token-estimate.ts +19 -2
  462. package/src/lib/tool-argument-integers.ts +253 -0
  463. package/src/lib/translator-budget.ts +44 -0
  464. package/src/lib/upstream-http-version.ts +57 -0
  465. package/src/lib/upstream-reachability.ts +95 -0
  466. package/src/lib/upstream-retry.ts +156 -3
  467. package/src/lib/windows-atomic-replace.ts +155 -0
  468. package/src/lib/windows-elevation.ts +70 -2
  469. package/src/lib/windows-secret-acl.ts +409 -69
  470. package/src/lib/windows-service-wrappers.ts +72 -0
  471. package/src/lib/windows-text.ts +106 -0
  472. package/src/lib/windows-user-principal.ts +341 -0
  473. package/src/lib/winsw.ts +33 -5
  474. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  475. package/src/oauth/account-import/index.ts +15 -0
  476. package/src/oauth/account-import/parser.ts +83 -0
  477. package/src/oauth/account-import/registry.ts +18 -0
  478. package/src/oauth/account-import/service.ts +75 -0
  479. package/src/oauth/account-import/types.ts +91 -0
  480. package/src/oauth/anthropic.ts +12 -1
  481. package/src/oauth/callback-server.ts +30 -4
  482. package/src/oauth/chatgpt.ts +12 -1
  483. package/src/oauth/cline.ts +203 -0
  484. package/src/oauth/command-code.ts +239 -0
  485. package/src/oauth/cursor.ts +46 -5
  486. package/src/oauth/generic-account-failover.ts +231 -0
  487. package/src/oauth/google-antigravity.ts +35 -3
  488. package/src/oauth/health.ts +20 -12
  489. package/src/oauth/index.ts +462 -71
  490. package/src/oauth/key-providers.ts +25 -0
  491. package/src/oauth/kimi.ts +25 -3
  492. package/src/oauth/kiro.ts +95 -6
  493. package/src/oauth/local-token-detect.ts +13 -2
  494. package/src/oauth/log.ts +3 -1
  495. package/src/oauth/login-cli.ts +88 -28
  496. package/src/oauth/nous.ts +798 -0
  497. package/src/oauth/open-browser-choice.ts +26 -0
  498. package/src/oauth/store.ts +133 -26
  499. package/src/oauth/token-guardian.ts +9 -3
  500. package/src/oauth/types.ts +15 -0
  501. package/src/pi/models.ts +2 -2
  502. package/src/providers/alibaba-region-migration.ts +1 -1
  503. package/src/providers/antigravity-models.ts +521 -31
  504. package/src/providers/auto-compact-budget.ts +65 -0
  505. package/src/providers/base-url-choices.ts +10 -0
  506. package/src/providers/codex-capacity.ts +292 -0
  507. package/src/providers/command-code-efforts.ts +176 -0
  508. package/src/providers/context-cap.ts +26 -8
  509. package/src/providers/cursor-pool.ts +72 -0
  510. package/src/providers/default-aliases.ts +65 -0
  511. package/src/providers/derive.ts +281 -6
  512. package/src/providers/fastwire.ts +507 -0
  513. package/src/providers/free-directory.ts +10 -7
  514. package/src/providers/google-vertex-location.ts +14 -0
  515. package/src/providers/key-failover.ts +71 -3
  516. package/src/providers/label.ts +35 -2
  517. package/src/providers/model-discovery-limits.ts +16 -0
  518. package/src/providers/model-discovery.ts +115 -22
  519. package/src/providers/model-presets.ts +119 -0
  520. package/src/providers/model-rename-migration.ts +255 -0
  521. package/src/providers/model-rename-startup.ts +28 -0
  522. package/src/providers/new-model-policy.ts +146 -0
  523. package/src/providers/openai-sidecar.ts +72 -4
  524. package/src/providers/openai-tier-startup.ts +31 -2
  525. package/src/providers/openai-tiers.ts +119 -4
  526. package/src/providers/openai-virtual-models.ts +1 -0
  527. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  528. package/src/providers/provider-id-rewrite.ts +30 -0
  529. package/src/providers/quota.ts +1379 -40
  530. package/src/providers/registry.ts +1545 -112
  531. package/src/providers/request-pacing.ts +310 -0
  532. package/src/providers/service-tier.ts +277 -0
  533. package/src/providers/slug-codec.ts +94 -6
  534. package/src/providers/static-model-discovery.ts +86 -0
  535. package/src/providers/xai-responses-opt-in.ts +15 -0
  536. package/src/providers/xai-transport.ts +32 -4
  537. package/src/reasoning-effort.ts +68 -3
  538. package/src/responses/apply-patch-envelope.ts +63 -0
  539. package/src/responses/code-mode-helper-compat.ts +50 -0
  540. package/src/responses/compaction.ts +26 -1
  541. package/src/responses/custom-tool-compat.ts +384 -0
  542. package/src/responses/hosted-tool-policy.ts +9 -0
  543. package/src/responses/namespace-tool-compat.ts +435 -0
  544. package/src/responses/parser.ts +225 -38
  545. package/src/responses/provider-continuation.ts +98 -0
  546. package/src/responses/provider-opaque-metadata.ts +73 -0
  547. package/src/responses/reasoning-envelope.ts +9 -1
  548. package/src/responses/reasoning-replay-cache.ts +504 -0
  549. package/src/responses/schema.ts +12 -2
  550. package/src/responses/spill-store.ts +75 -10
  551. package/src/responses/state.ts +659 -31
  552. package/src/responses/thought-signature-replay.ts +364 -0
  553. package/src/responses/tool-search-compat.ts +301 -0
  554. package/src/responses/truncated-stop-reason.ts +60 -0
  555. package/src/responses/turn-termination.ts +107 -0
  556. package/src/router.ts +405 -31
  557. package/src/routing/analytics.ts +379 -0
  558. package/src/routing/capability.ts +244 -0
  559. package/src/routing/compatibility/assemble.ts +73 -0
  560. package/src/routing/compatibility/behavior.ts +278 -0
  561. package/src/routing/compatibility/catalog.ts +99 -0
  562. package/src/routing/compatibility/endpoint.ts +52 -0
  563. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  564. package/src/routing/compatibility/policy.ts +181 -0
  565. package/src/routing/compatibility/provider-slot.ts +56 -0
  566. package/src/routing/compatibility/reader.ts +110 -0
  567. package/src/routing/compatibility/subject.ts +191 -0
  568. package/src/routing/compatibility/types.ts +64 -0
  569. package/src/routing/compatibility/version.ts +104 -0
  570. package/src/routing/cost.ts +77 -0
  571. package/src/routing/evaluator.ts +495 -0
  572. package/src/routing/health.ts +412 -0
  573. package/src/routing/history/cursor.ts +43 -0
  574. package/src/routing/history/indexer.ts +605 -0
  575. package/src/routing/history/schema.ts +72 -0
  576. package/src/routing/profile-namespace.ts +15 -0
  577. package/src/routing/profile.ts +547 -0
  578. package/src/routing/quota.ts +155 -0
  579. package/src/routing/request-evidence.ts +45 -0
  580. package/src/routing/trace.ts +776 -0
  581. package/src/server/adapter-resolve.ts +2 -29
  582. package/src/server/auth-cors.ts +289 -48
  583. package/src/server/background-lifecycle.ts +182 -0
  584. package/src/server/chat-completions.ts +154 -72
  585. package/src/server/chat-native-sse.ts +331 -0
  586. package/src/server/chat-native.ts +445 -0
  587. package/src/server/claude-messages.ts +160 -44
  588. package/src/server/direct-local-http.ts +347 -0
  589. package/src/server/effort-policy.ts +18 -0
  590. package/src/server/github-copilot-responses-repair.ts +338 -0
  591. package/src/server/gui-static.ts +39 -10
  592. package/src/server/images.ts +94 -12
  593. package/src/server/index.ts +1021 -190
  594. package/src/server/lifecycle.ts +336 -14
  595. package/src/server/live.ts +136 -17
  596. package/src/server/local-management-read-client.ts +90 -0
  597. package/src/server/local-provider-reload-client.ts +137 -0
  598. package/src/server/management/agent-settings-routes.ts +433 -116
  599. package/src/server/management/api-key-usage.ts +31 -5
  600. package/src/server/management/body.ts +6 -0
  601. package/src/server/management/codex-prompt-routes.ts +570 -0
  602. package/src/server/management/combo-routes.ts +64 -25
  603. package/src/server/management/config-routes.ts +511 -51
  604. package/src/server/management/context.ts +89 -2
  605. package/src/server/management/integration-routes.ts +498 -0
  606. package/src/server/management/lab-automation-routes.ts +206 -0
  607. package/src/server/management/lab-routes.ts +563 -0
  608. package/src/server/management/logs-usage-routes.ts +127 -52
  609. package/src/server/management/model-routes.ts +461 -133
  610. package/src/server/management/model-rows.ts +167 -0
  611. package/src/server/management/native-integration-routes.ts +770 -0
  612. package/src/server/management/oauth-account-routes.ts +90 -8
  613. package/src/server/management/provider-capability-config.ts +48 -0
  614. package/src/server/management/provider-routes.ts +836 -159
  615. package/src/server/management/request-history-routes.ts +191 -0
  616. package/src/server/management/route-registry.ts +332 -0
  617. package/src/server/management/routing-analytics-routes.ts +74 -0
  618. package/src/server/management/routing-profile-routes.ts +380 -0
  619. package/src/server/management/shared.ts +27 -11
  620. package/src/server/management/sidebar-routes.ts +47 -31
  621. package/src/server/management/storage-log-guard-routes.ts +186 -0
  622. package/src/server/management/sync-response.ts +69 -0
  623. package/src/server/management/system-restart.ts +289 -33
  624. package/src/server/management/system-routes.ts +77 -0
  625. package/src/server/management/usage-summary-cache.ts +9 -1
  626. package/src/server/management/vision-sidecar-options.ts +167 -0
  627. package/src/server/management/web-search-sidecar-options.ts +120 -0
  628. package/src/server/management-api.ts +126 -23
  629. package/src/server/management-auth.ts +220 -5
  630. package/src/server/passive-route-linker.ts +66 -0
  631. package/src/server/port-reclaim.ts +1 -1
  632. package/src/server/ports.ts +41 -1
  633. package/src/server/proxy-liveness.ts +161 -10
  634. package/src/server/readiness.ts +99 -0
  635. package/src/server/relay-eager.ts +221 -54
  636. package/src/server/relay.ts +479 -87
  637. package/src/server/request-decompress.ts +113 -6
  638. package/src/server/request-log-conversation.ts +51 -0
  639. package/src/server/request-log.ts +298 -31
  640. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  641. package/src/server/responses/agent-task-recovery.ts +465 -0
  642. package/src/server/responses/codex-auth-error.ts +55 -0
  643. package/src/server/responses/collaboration.ts +239 -36
  644. package/src/server/responses/combo-stream-preflight.ts +178 -0
  645. package/src/server/responses/compact.ts +444 -72
  646. package/src/server/responses/core.ts +3579 -436
  647. package/src/server/responses/empty-completion-guard.ts +333 -0
  648. package/src/server/responses/encrypted-payload.ts +62 -39
  649. package/src/server/responses/fetch-helpers.ts +89 -99
  650. package/src/server/responses/input-admission.ts +187 -0
  651. package/src/server/responses/pacing-overload.ts +13 -0
  652. package/src/server/responses/passthrough-error.ts +33 -9
  653. package/src/server/responses/policy-fallback.ts +178 -0
  654. package/src/server/responses/responses-field-backfill.ts +343 -0
  655. package/src/server/responses/terminal-guard.ts +26 -5
  656. package/src/server/responses/upstream-error.ts +5 -0
  657. package/src/server/responses/ws-upstream.ts +381 -0
  658. package/src/server/responses-custom-tool-repair.ts +363 -0
  659. package/src/server/responses-item-id-repair.ts +54 -6
  660. package/src/server/responses-json-events.ts +90 -0
  661. package/src/server/responses-model-rewrite.ts +29 -0
  662. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  663. package/src/server/responses-snapshot-repair.ts +621 -0
  664. package/src/server/responses-terminal-repair.ts +363 -0
  665. package/src/server/responses-tool-search-repair.ts +267 -0
  666. package/src/server/responses-undeclared-tool-guard.ts +376 -0
  667. package/src/server/responses.ts +18 -2
  668. package/src/server/search.ts +78 -13
  669. package/src/server/sse-frame-buffer.ts +319 -0
  670. package/src/server/sse-payload-rewrite.ts +110 -22
  671. package/src/server/startup-action-control.ts +8 -1
  672. package/src/server/startup-health-cache.ts +19 -1
  673. package/src/server/system-env.ts +80 -9
  674. package/src/server/ws-bridge.ts +53 -40
  675. package/src/service-manager-probe.ts +892 -0
  676. package/src/service.ts +1153 -94
  677. package/src/sidecar/auth.ts +92 -0
  678. package/src/sidecar/candidates.ts +83 -0
  679. package/src/storage/cleanup.ts +2 -2
  680. package/src/storage/policy-job.ts +14 -4
  681. package/src/storage/policy.ts +88 -23
  682. package/src/storage/scanner.ts +1 -1
  683. package/src/storage/worker-lifecycle.ts +14 -14
  684. package/src/tray/windows-tray.ps1 +83 -9
  685. package/src/tray/windows.ts +43 -16
  686. package/src/types/accounts.ts +37 -0
  687. package/src/types/config.ts +911 -0
  688. package/src/types/provider.ts +614 -0
  689. package/src/types/request.ts +397 -0
  690. package/src/types/tools.ts +236 -0
  691. package/src/types/wire.ts +80 -0
  692. package/src/types.ts +107 -1237
  693. package/src/update/index.ts +37 -23
  694. package/src/update/job.ts +445 -68
  695. package/src/update/notify.ts +12 -6
  696. package/src/update/npm-cache-preflight.d.mts +47 -0
  697. package/src/update/npm-cache-preflight.mjs +201 -0
  698. package/src/update/transactional-install.d.mts +22 -0
  699. package/src/update/transactional-install.mjs +266 -0
  700. package/src/usage/cost.ts +0 -0
  701. package/src/usage/expected-prices.ts +287 -16
  702. package/src/usage/log.ts +666 -50
  703. package/src/usage/summary.ts +388 -17
  704. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  705. package/src/usage/user-cost-overlays.ts +314 -0
  706. package/src/vision/anthropic-describe.ts +10 -6
  707. package/src/vision/backends.ts +97 -0
  708. package/src/vision/describe.ts +27 -16
  709. package/src/vision/eligibility.ts +250 -0
  710. package/src/vision/index.ts +238 -24
  711. package/src/vision/reasoning.ts +55 -0
  712. package/src/vision/routed-describe.ts +175 -0
  713. package/src/vision/timeout-bounds.ts +9 -0
  714. package/src/web-search/anthropic-executor.ts +13 -7
  715. package/src/web-search/backends.ts +108 -0
  716. package/src/web-search/exa-executor.ts +119 -0
  717. package/src/web-search/executor.ts +21 -6
  718. package/src/web-search/gemini-executor.ts +141 -0
  719. package/src/web-search/index.ts +150 -15
  720. package/src/web-search/loop.ts +284 -54
  721. package/src/web-search/parse.ts +125 -30
  722. package/src/web-search/sources.ts +60 -0
  723. package/src/web-search/xai-executor.ts +219 -0
  724. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  725. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  726. package/gui/dist/provider-icons/antigravity.svg +0 -1
  727. package/gui/dist/provider-icons/claude.svg +0 -1
  728. package/gui/dist/provider-icons/copilot.svg +0 -1
  729. package/gui/dist/provider-icons/cursor.svg +0 -2
  730. package/gui/dist/provider-icons/gemini.svg +0 -1
  731. package/gui/dist/provider-icons/grok-color.svg +0 -1
  732. package/gui/dist/provider-icons/kiro.svg +0 -14
  733. package/src/cli/internal-dispatch.ts +0 -20
@@ -18,9 +18,30 @@ export const KEY_LOGIN_PROVIDERS: Record<string, KeyLoginProvider> = deriveKeyLo
18
18
  * `noReasoningModels`, `defaultModel`) onto a provider config being created, for any field the
19
19
  * caller didn't already supply. Lets the vision/reasoning classification actually reach the saved
20
20
  * config (the GUI/API only send adapter/baseUrl/apiKey/defaultModel). No-op for unknown names.
21
+ *
22
+ * `modelSupportsReasoningSummaries` and the verbosity capability are deliberately excluded from
23
+ * what gets persisted. They are
24
+ * registry-only metadata resolved at runtime, and this function feeds a config that is about to
25
+ * be written to disk. Persisting today's registry defaults would freeze them as the user's own
26
+ * overrides: a later registry correction — say we learn a model's backend rejects summary
27
+ * delivery — would never reach anyone who created their provider before the correction, and they
28
+ * would keep getting upstream 400s with no way to know why. Catalog gathering enriches a
29
+ * detached runtime clone, so the defaults still apply where they matter.
21
30
  */
22
31
  export function enrichProviderFromCatalog(name: string, prov: OcxProviderConfig): void {
32
+ const hadOwnSummaries = Object.hasOwn(prov, "modelSupportsReasoningSummaries");
33
+ const submittedSummaries = prov.modelSupportsReasoningSummaries;
34
+ const hadOwnVerbosity = Object.hasOwn(prov, "modelSupportsVerbosity");
35
+ const submittedVerbosity = prov.modelSupportsVerbosity;
36
+ const hadOwnProviderVerbosity = Object.hasOwn(prov, "supportsVerbosity");
37
+ const submittedProviderVerbosity = prov.supportsVerbosity;
23
38
  enrichProviderFromRegistry(name, prov);
39
+ if (hadOwnSummaries) prov.modelSupportsReasoningSummaries = submittedSummaries;
40
+ else delete prov.modelSupportsReasoningSummaries;
41
+ if (hadOwnVerbosity) prov.modelSupportsVerbosity = submittedVerbosity;
42
+ else delete prov.modelSupportsVerbosity;
43
+ if (hadOwnProviderVerbosity) prov.supportsVerbosity = submittedProviderVerbosity;
44
+ else delete prov.supportsVerbosity;
24
45
  }
25
46
 
26
47
  export function isKeyLoginProvider(name: string): boolean {
@@ -52,6 +73,10 @@ export async function validateApiKey(
52
73
  key: string,
53
74
  ): Promise<boolean | "unknown"> {
54
75
  try {
76
+ // A public model catalog cannot prove that the supplied key is valid. Returning unknown keeps
77
+ // the best-effort login flow available without persisting a false-positive validation result.
78
+ if (provider.apiKeyValidation === "unknown") return "unknown";
79
+
55
80
  if (provider.adapter === "anthropic") {
56
81
  const base = provider.baseUrl.replace(/\/v1\/?$/, "");
57
82
  const res = await fetch(`${base}/v1/messages`, {
package/src/oauth/kimi.ts CHANGED
@@ -151,7 +151,21 @@ async function requestDeviceAuthorization(): Promise<{
151
151
  }
152
152
 
153
153
  function parseTokenPayload(payload: TokenResponse, refreshFallback?: string): OAuthCredentials {
154
- if (!payload.access_token || typeof payload.expires_in !== "number") {
154
+ // Number.isFinite is required here: typeof NaN === "number", so the type check
155
+ // alone would let a NaN expires_in through and produce a never-refreshing expiry.
156
+ // Negative durations would stamp an already-past expiry — also malformed.
157
+ // The computed timestamp itself must also stay finite: Number.MAX_VALUE passes
158
+ // Number.isFinite but overflows to Infinity once multiplied by 1000.
159
+ if (
160
+ !payload.access_token
161
+ || typeof payload.expires_in !== "number"
162
+ || !Number.isFinite(payload.expires_in)
163
+ || payload.expires_in < 0
164
+ ) {
165
+ throw new Error("Kimi token response missing required fields");
166
+ }
167
+ const expires = Date.now() + payload.expires_in * 1000 - OAUTH_EXPIRY_SKEW_MS;
168
+ if (!Number.isFinite(expires)) {
155
169
  throw new Error("Kimi token response missing required fields");
156
170
  }
157
171
  const refresh = payload.refresh_token ?? refreshFallback;
@@ -160,7 +174,7 @@ function parseTokenPayload(payload: TokenResponse, refreshFallback?: string): OA
160
174
  return {
161
175
  access: payload.access_token,
162
176
  refresh,
163
- expires: Date.now() + payload.expires_in * 1000 - OAUTH_EXPIRY_SKEW_MS,
177
+ expires,
164
178
  ...identity,
165
179
  };
166
180
  }
@@ -195,7 +209,15 @@ async function pollForToken(deviceCode: string, intervalMs: number, expiresInMs:
195
209
 
196
210
  export async function loginKimi(ctrl: OAuthController): Promise<OAuthCredentials> {
197
211
  const device = await requestDeviceAuthorization();
198
- ctrl.onAuth?.({ url: device.verificationUriComplete, instructions: `Enter code: ${device.userCode}` });
212
+ // `deviceCode` carries the human-typed user code, matching the other device
213
+ // providers. It is also what tells the management login route this is a device
214
+ // flow, so a provider-supplied verification URI is no longer handed to a local
215
+ // browser spawn — the URL stays visible and copyable in every login surface.
216
+ ctrl.onAuth?.({
217
+ url: device.verificationUriComplete,
218
+ instructions: `Enter code: ${device.userCode}`,
219
+ deviceCode: device.userCode,
220
+ });
199
221
  return pollForToken(device.deviceCode, device.intervalMs, device.expiresInMs, ctrl.signal);
200
222
  }
201
223
 
package/src/oauth/kiro.ts CHANGED
@@ -28,6 +28,7 @@ import {
28
28
  } from "./kiro-credentials";
29
29
  import { homedir } from "node:os";
30
30
  import { getAccountSet, saveAccountCredential } from "./store";
31
+ import { KIRO_BUILDER_ID_SERVICE_PROFILE_ARN } from "../adapters/kiro-constants";
31
32
 
32
33
  const DEFAULT_REGION = "us-east-1";
33
34
  const REFRESH_URL = "https://prod.{region}.auth.desktop.kiro.dev/refreshToken";
@@ -172,13 +173,37 @@ async function defaultKiroCliRunner(args: string[], signal?: AbortSignal): Promi
172
173
  }
173
174
  }
174
175
 
175
- async function readKiroCliIdentity(runner: KiroCliRunner, signal?: AbortSignal): Promise<{ email?: string }> {
176
+ /** Kiro profile ARN structure: arn:<partition>:codewhisperer:<region>:<account>:profile/<id> */
177
+ const KIRO_PROFILE_ARN_PATTERN = /^arn:[a-z0-9-]+:codewhisperer:[a-z0-9-]+:\d{12}:profile\/[A-Za-z0-9-]+$/;
178
+ const KIRO_PROFILE_ARN_MAX_LENGTH = 256;
179
+
180
+ function parseKiroProfileArn(value: unknown): string | undefined {
181
+ if (typeof value !== "string") return undefined;
182
+ const trimmed = value.trim();
183
+ if (trimmed.length === 0 || trimmed.length > KIRO_PROFILE_ARN_MAX_LENGTH) return undefined;
184
+ return KIRO_PROFILE_ARN_PATTERN.test(trimmed) ? trimmed : undefined;
185
+ }
186
+
187
+ function profileArnFromWhoami(parsed: Record<string, unknown>): string | undefined {
188
+ // Only narrowly-named documented-ish shapes; never invent an ARN (#993).
189
+ return parseKiroProfileArn(parsed.profileArn)
190
+ ?? parseKiroProfileArn(parsed.profile_arn)
191
+ ?? (parsed.profile && typeof parsed.profile === "object" && !Array.isArray(parsed.profile)
192
+ ? parseKiroProfileArn((parsed.profile as Record<string, unknown>).arn)
193
+ : undefined);
194
+ }
195
+
196
+ async function readKiroCliIdentity(runner: KiroCliRunner, signal?: AbortSignal): Promise<{ email?: string; profileArn?: string }> {
176
197
  try {
177
198
  const result = await runner(["whoami", "--format", "json"], signal);
178
199
  if (result.exitCode !== 0) return {};
179
- const parsed = JSON.parse(result.stdout) as { email?: unknown };
200
+ const parsed = JSON.parse(result.stdout) as Record<string, unknown>;
180
201
  const email = typeof parsed.email === "string" ? parsed.email.trim().toLowerCase() : "";
181
- return email && email.length <= 320 ? { email } : {};
202
+ const profileArn = profileArnFromWhoami(parsed);
203
+ return {
204
+ ...(email && email.length <= 320 ? { email } : {}),
205
+ ...(profileArn ? { profileArn } : {}),
206
+ };
182
207
  } catch {
183
208
  return {};
184
209
  }
@@ -251,14 +276,34 @@ async function oauthCredentialFromImported(
251
276
  runner: KiroCliRunner,
252
277
  signal?: AbortSignal,
253
278
  ): Promise<OAuthCredentials> {
254
- const identity = imported.source === "sqlite" ? await readKiroCliIdentity(runner, signal) : {};
255
- const metadata = metadataFromImported(imported);
279
+ let identity: { email?: string; profileArn?: string } = {};
280
+ if (imported.source === "sqlite") {
281
+ identity = await readKiroCliIdentity(runner, signal);
282
+ // Session-switch race (#993 review): another process may have switched the
283
+ // active Kiro CLI session between the SQLite read and whoami. Accept
284
+ // whoami's identity only when the session token STILL matches the import —
285
+ // refresh token, or access token when refresh is absent.
286
+ if (identity.profileArn !== undefined) {
287
+ const current = readKiroCliSqliteCredential();
288
+ const importedKey = imported.refresh || imported.access;
289
+ const currentKey = current ? current.refresh || current.access : "";
290
+ if (!current || currentKey !== importedKey) identity = {};
291
+ }
292
+ }
293
+ // Builder ID imports often lack a profileArn in SQLite; whoami against the
294
+ // SAME active CLI session can supply it (#993). Imported stays authoritative.
295
+ const resolvedProfileArn = imported.profileArn ?? identity.profileArn;
296
+ const metadata: KiroOAuthMetadata | undefined = (() => {
297
+ const base = metadataFromImported(imported) ?? {};
298
+ if (resolvedProfileArn && !base.profileArn) base.profileArn = resolvedProfileArn;
299
+ return Object.keys(base).length > 0 ? base : undefined;
300
+ })();
256
301
  return {
257
302
  access: imported.access,
258
303
  refresh: imported.refresh,
259
304
  expires: imported.expires,
260
305
  source: imported.source === "json" ? "credential-file" : "local-cli",
261
- ...(imported.profileArn ? { accountId: imported.profileArn } : {}),
306
+ ...(resolvedProfileArn ? { accountId: resolvedProfileArn } : {}),
262
307
  ...(identity.email ? { email: identity.email } : {}),
263
308
  ...(metadata ? { kiro: metadata } : {}),
264
309
  };
@@ -429,6 +474,50 @@ export function resolveKiroProfileArn(account?: Pick<KiroOAuthMetadata, "profile
429
474
  return readImportedKiroCredential()?.profileArn;
430
475
  }
431
476
 
477
+ /**
478
+ * Resolve the profileArn actually SENT upstream, which is not always the account's own.
479
+ *
480
+ * An AWS Builder ID account authenticates through SSO OIDC and never receives an account-scoped
481
+ * profile ARN, so gated models reject its requests with a `profileArn`-demanding
482
+ * `ValidationException`. The Kiro CLI handles this by carrying a fixed service profile on Builder
483
+ * ID requests, and this mirrors that.
484
+ *
485
+ * Deliberately separate from `resolveKiroProfileArn`: that resolver answers "what is this
486
+ * account's profile", and callers that ask it — region inference, account matching, continuation
487
+ * scoping — must keep receiving `undefined` here. Only request construction uses this function.
488
+ *
489
+ * The fallback is gated on `authType === "aws_sso_oidc"` rather than on a missing ARN, so a
490
+ * `kiro_desktop` account whose profile import failed keeps producing its actionable error instead
491
+ * of silently borrowing a service profile that does not describe it.
492
+ */
493
+ export function resolveKiroRequestProfileArn(
494
+ account?: Pick<KiroOAuthMetadata, "profileArn" | "authType">,
495
+ ): string | undefined {
496
+ return resolveKiroRequestProfile(account).profileArn;
497
+ }
498
+
499
+ /**
500
+ * The profileArn to send, together with WHY it was chosen.
501
+ *
502
+ * The request builder must decide the wire envelope from the same evaluation that produced the
503
+ * ARN. Re-deriving "is this Builder ID" from the account context alone would miss the accountless
504
+ * path, where the auth type comes from the locally imported credential instead: the fallback would
505
+ * be sent while the request was shaped as an enterprise IDE call, which is not a combination the
506
+ * vendor client ever produces.
507
+ */
508
+ export function resolveKiroRequestProfile(
509
+ account?: Pick<KiroOAuthMetadata, "profileArn" | "authType">,
510
+ ): { profileArn: string | undefined; builderIdFallback: boolean } {
511
+ const own = resolveKiroProfileArn(account);
512
+ if (own) return { profileArn: own, builderIdFallback: false };
513
+ const authType = account !== undefined
514
+ ? account.authType
515
+ : readImportedKiroCredential()?.authType;
516
+ return authType === "aws_sso_oidc"
517
+ ? { profileArn: KIRO_BUILDER_ID_SERVICE_PROFILE_ARN, builderIdFallback: true }
518
+ : { profileArn: undefined, builderIdFallback: false };
519
+ }
520
+
432
521
  async function kiroTokenRefreshError(response: Response): Promise<KiroTokenRefreshError> {
433
522
  let oauthError: string | undefined;
434
523
  try {
@@ -24,7 +24,10 @@ export function detectGrokCliToken(): OAuthCredentials | null {
24
24
 
25
25
  const accessToken = entry.key as string;
26
26
  const refreshToken = entry.refresh_token as string;
27
- const expiresAt = entry.expires_at ? new Date(entry.expires_at as string).getTime() : 0;
27
+ const parsedExpiresAt = entry.expires_at ? new Date(entry.expires_at as string).getTime() : 0;
28
+ // Guard against unparseable/NaN expiries: a non-finite value must never be treated as
29
+ // "valid forever". Unknown → 0, which forces the refresh-validation path downstream.
30
+ const expiresAt = Number.isFinite(parsedExpiresAt) ? parsedExpiresAt : 0;
28
31
 
29
32
  return {
30
33
  refresh: refreshToken,
@@ -55,6 +58,9 @@ export function shouldAdoptGrokGeneration(
55
58
  now = Date.now(),
56
59
  refreshSkewMs = 60_000,
57
60
  ): boolean {
61
+ // A non-finite disk expiry means we cannot reason about the generation: the credential is
62
+ // either garbage or unknown. Treat it as requiring refresh validation, never as an upgrade.
63
+ if (!Number.isFinite(disk.expires)) return false;
58
64
  if (disk.expires <= now + refreshSkewMs) return false;
59
65
  const bothExpiriesExist = stored.expires > 0 && disk.expires > 0;
60
66
  if (bothExpiriesExist) return disk.expires >= stored.expires;
@@ -108,7 +114,10 @@ export function parseClaudeOauthPayload(raw: string): OAuthCredentials | null {
108
114
  const data = JSON.parse(raw) as { claudeAiOauth?: { accessToken?: string; refreshToken?: string; expiresAt?: number } };
109
115
  const o = data.claudeAiOauth;
110
116
  if (!o?.accessToken || !o?.refreshToken) return null;
111
- return { access: o.accessToken, refresh: o.refreshToken, expires: o.expiresAt ?? 0, source: "local-cli" };
117
+ // Number.isFinite guard: a string/NaN expiresAt must not flow into downstream time
118
+ // comparisons as a "valid forever" value. Unknown → 0 (refresh-validation path).
119
+ const expires = typeof o.expiresAt === "number" && Number.isFinite(o.expiresAt) ? o.expiresAt : 0;
120
+ return { access: o.accessToken, refresh: o.refreshToken, expires, source: "local-cli" };
112
121
  } catch {
113
122
  return null;
114
123
  }
@@ -119,3 +128,5 @@ export function detectClaudeCodeToken(): OAuthCredentials | null {
119
128
  if (!raw) return null;
120
129
  return parseClaudeOauthPayload(raw);
121
130
  }
131
+
132
+ export { detectLocalClineToken as detectClineToken } from "./cline";
package/src/oauth/log.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  // src/oauth/log.ts
2
2
  import { maskAccountId } from "../lib/privacy";
3
+ import { redactSecretString } from "../lib/redact";
3
4
 
4
5
  /** Normalize camelCase / snake_case / kebab-case field names before secret checks. */
5
6
  function normalizeFieldKey(key: string): string {
@@ -20,6 +21,7 @@ const FORBIDDEN_NORMALIZED = new Set([
20
21
  "id_token",
21
22
  "client_secret",
22
23
  "oauth_code",
24
+ "code_verifier",
23
25
  "clientsecret",
24
26
  ]);
25
27
 
@@ -44,5 +46,5 @@ export function logOAuthEvent(
44
46
  if (value === undefined) continue;
45
47
  parts.push(`${key}=${String(value)}`);
46
48
  }
47
- console.info(parts.join(" "));
49
+ console.info(redactSecretString(parts.join(" ")));
48
50
  }
@@ -1,13 +1,22 @@
1
1
  import * as readline from "node:readline";
2
2
  import { openUrl } from "../lib/open-url";
3
3
  import { loadConfig, saveConfig } from "../config";
4
- import { findLiveProxy, probeHostname } from "../server/proxy-liveness";
4
+ import { findLiveProxy } from "../server/proxy-liveness";
5
+ import {
6
+ requestBoundLocalProviderReload,
7
+ type LocalProviderReloadResult,
8
+ } from "../server/local-provider-reload-client";
5
9
  import { isPublicOAuthProvider, listOAuthProviders, runLogin } from "./index";
6
10
  import { KEY_LOGIN_PROVIDERS, isKeyLoginProvider, validateApiKey, type KeyLoginProvider } from "./key-providers";
7
- import type { OcxProviderConfig } from "../types";
11
+ import type { OcxConfig, OcxProviderConfig } from "../types";
8
12
  import { configuredAdminToken } from "../lib/admin-secrets";
9
13
  import { codexAccountNamespaceProviderCollisionError } from "../codex/account-namespace-match";
10
14
 
15
+ const LIVE_RELOAD_PROVIDERS = new Set<string>([
16
+ ...listOAuthProviders(),
17
+ ...Object.keys(KEY_LOGIN_PROVIDERS),
18
+ ]);
19
+
11
20
  export function runningProxyUpdateHeaders(): Headers {
12
21
  const headers = new Headers({ "Content-Type": "application/json" });
13
22
  const adminToken = configuredAdminToken();
@@ -15,34 +24,43 @@ export function runningProxyUpdateHeaders(): Headers {
15
24
  return headers;
16
25
  }
17
26
 
18
- /** Push the new provider into a running proxy's live config so it routes without a restart. */
19
- export async function notifyRunningProxy(name: string, provider: unknown): Promise<void> {
20
- // Identity-checked runtime-port lookup: reaches a fallback-port proxy and avoids
21
- // posting credentials-adjacent config to whatever else answers on config.port.
27
+ /**
28
+ * Ask the attested runtime to reload one already-persisted provider.
29
+ *
30
+ * Returns the outcome instead of swallowing it. A running proxy that predates
31
+ * attested reload — or one whose runtime record no longer matches — cannot adopt
32
+ * the new credential, and the caller has to say so: the credential is on disk, but
33
+ * the live process keeps routing with the old one until it restarts. Silently
34
+ * printing success there is how a login appears to work and then does not.
35
+ */
36
+ export async function notifyRunningProxy(name: string): Promise<LocalProviderReloadResult | null> {
37
+ if (!LIVE_RELOAD_PROVIDERS.has(name)) return null;
22
38
  const live = await findLiveProxy();
23
- if (!live) return;
24
- try {
25
- await fetch(`http://${probeHostname(live.hostname)}:${live.port}/api/providers`, {
26
- method: "POST",
27
- headers: runningProxyUpdateHeaders(),
28
- body: JSON.stringify({ name, provider }),
29
- });
30
- } catch {
31
- /* proxy unreachable; disk config loads on next start */
32
- }
39
+ if (!live) return null;
40
+ return await requestBoundLocalProviderReload(live, name);
33
41
  }
34
42
 
35
43
  /**
36
44
  * After `runLogin()` has persisted the merged provider (including preserved apiKey /
37
- * apiKeyPool / authMode), push that on-disk entry into a running proxy.
38
- *
39
- * Must not send `OAUTH_PROVIDERS[name].providerConfig`: POST /api/providers replaces the
40
- * live entry and saves it, which would drop the preserved key billing state.
45
+ * apiKeyPool / authMode), ask the attested proxy to reload that exact on-disk entry.
46
+ */
47
+ export async function notifyRunningProxyAfterOAuthLogin(name: string): Promise<LocalProviderReloadResult | null> {
48
+ if (!loadConfig().providers[name]) return null;
49
+ return await notifyRunningProxy(name);
50
+ }
51
+
52
+ /**
53
+ * A live proxy was found but could not adopt the credential. `null` means there was
54
+ * nothing to notify (no running proxy, or a provider that never reloads live), which
55
+ * is not a warning-worthy state.
41
56
  */
42
- export async function notifyRunningProxyAfterOAuthLogin(name: string): Promise<void> {
43
- const provider = loadConfig().providers[name];
44
- if (!provider) return;
45
- await notifyRunningProxy(name, provider);
57
+ export function warnIfLiveReloadSkipped(result: LocalProviderReloadResult | null): void {
58
+ if (!result || result.kind === "reloaded") return;
59
+ console.warn(
60
+ `\n⚠️ A proxy is running but could not reload this provider (${result.reason}).`
61
+ + `\n The credential is saved to disk; the running proxy keeps using the previous one.`
62
+ + `\n Restart it to pick this up: ocx restart`,
63
+ );
46
64
  }
47
65
 
48
66
  export async function handleLogin(provider?: string): Promise<void> {
@@ -73,8 +91,9 @@ async function handleOAuthLogin(name: string): Promise<void> {
73
91
  } finally {
74
92
  rl.close();
75
93
  }
76
- await notifyRunningProxyAfterOAuthLogin(name);
94
+ const reload = await notifyRunningProxyAfterOAuthLogin(name);
77
95
  console.log(`\n✅ Logged in to ${name}. Try: ocx sync`);
96
+ warnIfLiveReloadSkipped(reload);
78
97
  }
79
98
 
80
99
  export function providerConfigFromKeyLoginProvider(def: KeyLoginProvider, key: string, baseUrlOverride?: string): OcxProviderConfig {
@@ -102,10 +121,51 @@ export function providerConfigFromKeyLoginProvider(def: KeyLoginProvider, key: s
102
121
  ...(def.noPenaltyModels ? { noPenaltyModels: [...def.noPenaltyModels] } : {}),
103
122
  ...(def.autoToolChoiceOnlyModels ? { autoToolChoiceOnlyModels: [...def.autoToolChoiceOnlyModels] } : {}),
104
123
  ...(def.preserveReasoningContentModels ? { preserveReasoningContentModels: [...def.preserveReasoningContentModels] } : {}),
124
+ ...(def.requiresReasoningPlaceholderModels ? { requiresReasoningPlaceholderModels: [...def.requiresReasoningPlaceholderModels] } : {}),
105
125
  ...(def.escapeBuiltinToolNames !== undefined ? { escapeBuiltinToolNames: def.escapeBuiltinToolNames } : {}),
106
126
  };
107
127
  }
108
128
 
129
+ /**
130
+ * Merge a freshly built key-login provider row with a previously saved row,
131
+ * carrying operator-owned fields the key-provider preset cannot know about.
132
+ * Currently that is the user-configured modelCosts overlay: rotating the API
133
+ * key must not silently revert Logs/Usage estimates to catalog prices.
134
+ */
135
+ export function mergeKeyLoginProviderRow(
136
+ provider: OcxProviderConfig,
137
+ existing: OcxProviderConfig | undefined,
138
+ ): OcxProviderConfig {
139
+ return {
140
+ ...provider,
141
+ ...(existing?.modelCosts !== undefined ? { modelCosts: existing.modelCosts } : {}),
142
+ };
143
+ }
144
+
145
+ /**
146
+ * Commit a fresh key-login provider row: merge operator-owned fields from the
147
+ * existing row (currently the modelCosts overlay), persist the merged row, and
148
+ * push the SAME merged row to a running proxy so its live config cannot diverge
149
+ * from disk (e.g. by replacing the overlay with catalog prices until reload).
150
+ * Returns the merged row that was persisted and notified.
151
+ */
152
+ export async function commitKeyLoginProvider(
153
+ config: OcxConfig,
154
+ name: string,
155
+ provider: OcxProviderConfig,
156
+ onLiveReload?: (result: LocalProviderReloadResult | null) => void,
157
+ ): Promise<OcxProviderConfig> {
158
+ const mergedProvider = mergeKeyLoginProviderRow(provider, config.providers[name]);
159
+ config.providers[name] = mergedProvider;
160
+ saveConfig(config);
161
+ // Evaluate the reload BEFORE the optional call: `onLiveReload?.(await ...)` short-circuits
162
+ // the whole argument list when no callback is supplied, so the reload would never fire for
163
+ // callers that do not care about the outcome.
164
+ const reloadResult = await notifyRunningProxy(name);
165
+ onLiveReload?.(reloadResult);
166
+ return mergedProvider;
167
+ }
168
+
109
169
  async function handleKeyLogin(name: string): Promise<void> {
110
170
  const def = KEY_LOGIN_PROVIDERS[name];
111
171
  const preflightConfig = loadConfig();
@@ -148,10 +208,10 @@ async function handleKeyLogin(name: string): Promise<void> {
148
208
  console.error(`Error: ${commitCollision}.`);
149
209
  process.exit(1);
150
210
  }
151
- config.providers[name] = provider;
152
- saveConfig(config);
153
- await notifyRunningProxy(name, provider);
211
+ let reload: LocalProviderReloadResult | null = null;
212
+ await commitKeyLoginProvider(config, name, provider, result => { reload = result; });
154
213
  console.log(`✅ ${def.label} added. Try: ocx sync`);
214
+ warnIfLiveReloadSkipped(reload);
155
215
  }
156
216
 
157
217
  function cloneRecordOfArrays(input: Record<string, string[]>): Record<string, string[]> {