@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
@@ -2,19 +2,25 @@ import { existsSync, readFileSync } from "node:fs";
2
2
  import type { ResponsesTerminalStatus } from "../bridge";
3
3
  import {
4
4
  classifyError,
5
+ CYBER_POLICY_ERROR_CODE,
5
6
  httpStatusFromTerminalError as httpStatusFromClassifiedTerminalError,
6
7
  isClientClosedMessage,
8
+ isCyberPolicyCode,
7
9
  } from "../lib/errors";
8
10
  import { CODEX_CONFIG_PATH, readRootTomlString } from "../codex/paths";
9
11
  import { readCodexCatalogPath } from "../codex/catalog";
10
- import type { OcxUsage } from "../types";
12
+ import type { AttemptTierOutcome, OcxUsage } from "../types";
13
+ import { normalizeRouteDecisionTrace, type RouteDecisionTraceV1 } from "../routing/trace";
11
14
  import type { AdapterRequest } from "../adapters/base";
12
- import { redactSecretString } from "../lib/redact";
15
+ import type { AdapterTierMetadata } from "../providers/fastwire";
16
+ import { redactSecretString, sanitizeLogMetadataString } from "../lib/redact";
13
17
  import {
14
18
  appendUsageEntry,
15
19
  isKnownAdmissionKind,
16
20
  isKnownInboundProtocol,
17
21
  isKnownUsageSurface,
22
+ isCodexUsageAccountLogLabel,
23
+ isValidReasoningWireValue,
18
24
  readRecentUsageEntries,
19
25
  usageForFinalLog,
20
26
  usageStatusForFinalLog,
@@ -33,6 +39,10 @@ import {
33
39
  } from "../usage/debug";
34
40
  import { matchesLogConversationId } from "./request-log-conversation";
35
41
  import { enforceAppOwnedMemoryBudget, type RetainedStoreSnapshot } from "../lib/app-owned-memory";
42
+ import { capEstimateAtContextWindow } from "../lib/token-estimate";
43
+ import { inferCursorContextWindow } from "../adapters/cursor/discovery";
44
+ import { KIRO_MODEL_CONTEXT_WINDOWS, normalizeKiroModelId } from "../providers/kiro-models";
45
+ import { modelRecordValue } from "../reasoning-effort";
36
46
 
37
47
  export interface RequestLogContext {
38
48
  model: string;
@@ -52,20 +62,29 @@ export interface RequestLogContext {
52
62
  * product: widening that enum would merge Responses and Chat Completions,
53
63
  * since both leave it undefined. */
54
64
  inboundProtocol?: "responses" | "chat" | "messages";
65
+ /** Stable non-PII Codex Pool account identity for durable usage attribution. */
66
+ accountLogLabel?: string;
55
67
  requestedModel?: string;
68
+ /** Original bare helper model when the opt-in shadow-call route rewrote this request. */
69
+ shadowCallRewrittenFrom?: string;
56
70
  /** Internal structural combo identity; omitted from RequestLogEntry/JSONL. */
57
71
  comboId?: string;
58
72
  requestedEffort?: string;
59
73
  effectiveEffort?: string;
60
74
  reasoningWireField?: string;
61
- reasoningWireValue?: string | number;
75
+ reasoningWireValue?: string | number | boolean;
76
+ callerServiceTier?: string;
62
77
  requestedServiceTier?: string;
63
78
  requestedSpeedLabel?: string;
64
79
  configuredServiceTier?: string;
65
80
  configuredSpeedLabel?: string;
66
81
  modelSupportsServiceTier?: boolean;
67
82
  responseServiceTier?: string;
83
+ /** Final-attempt tier summary; attempt rows remain the accounting source of truth. */
84
+ tierOutcome?: AttemptTierOutcome;
68
85
  resolvedModel?: string;
86
+ /** Internal: client-facing response metadata must not replace the physical routed model. */
87
+ preserveResolvedModelFromRoute?: boolean;
69
88
  usage?: OcxUsage;
70
89
  usageLogInputTokens?: number;
71
90
  attempts?: PersistedUsageAttempt[];
@@ -73,6 +92,8 @@ export interface RequestLogContext {
73
92
  activeAttempt?: PersistedUsageAttempt;
74
93
  /** Internal wall-clock origin for the committed final attempt; never persisted. */
75
94
  activeAttemptStartedAt?: number;
95
+ /** Internal adapter response observer paired with activeAttempt.tierOutcome. */
96
+ activeTierMetadata?: AdapterTierMetadata;
76
97
  usageDebugBodyKind?: UsageDebugBodyKind;
77
98
  usageDebugBodySample?: string;
78
99
  usageDebugContentType?: string;
@@ -90,11 +111,15 @@ export interface RequestLogContext {
90
111
  upstreamError?: string;
91
112
  /** HTTP status derived from a terminal `response.failed` SSE payload (429/401/503/etc.). */
92
113
  terminalHttpStatus?: number;
114
+ /** Recognized structured terminal code whose exact identity must survive status mapping. */
115
+ terminalErrorCode?: typeof CYBER_POLICY_ERROR_CODE;
93
116
  /** Structured reason from `response.incomplete`; internal-only input to log classification. */
94
117
  terminalIncompleteReason?: string;
95
118
  affinity?: "reused" | "new_bind" | "rebound" | "cleared";
96
119
  transportPhase?: "pre_headers" | "mid_stream" | "terminal_sse";
97
120
  terminalSource?: "upstream" | "synthetic";
121
+ /** Bounded route-decision trace (RI-01); never contains secrets. */
122
+ routeDecision?: RouteDecisionTraceV1;
98
123
  }
99
124
 
100
125
  export interface RequestLogEntry {
@@ -115,19 +140,24 @@ export interface RequestLogEntry {
115
140
  * product: widening that enum would merge Responses and Chat Completions,
116
141
  * since both leave it undefined. */
117
142
  inboundProtocol?: "responses" | "chat" | "messages";
143
+ accountLogLabel?: string;
118
144
  /** Best-effort chat/session correlation for Logs grouping (#330). */
119
145
  conversationId?: string;
120
146
  requestedModel?: string;
147
+ /** Original bare helper model when the opt-in shadow-call route rewrote this request. */
148
+ shadowCallRewrittenFrom?: string;
121
149
  requestedEffort?: string;
122
150
  effectiveEffort?: string;
123
151
  reasoningWireField?: string;
124
- reasoningWireValue?: string | number;
152
+ reasoningWireValue?: string | number | boolean;
153
+ callerServiceTier?: string;
125
154
  requestedServiceTier?: string;
126
155
  requestedSpeedLabel?: string;
127
156
  configuredServiceTier?: string;
128
157
  configuredSpeedLabel?: string;
129
158
  modelSupportsServiceTier?: boolean;
130
159
  responseServiceTier?: string;
160
+ tierOutcome?: AttemptTierOutcome;
131
161
  resolvedModel?: string;
132
162
  status: number;
133
163
  durationMs: number;
@@ -146,6 +176,8 @@ export interface RequestLogEntry {
146
176
  transportPhase?: "pre_headers" | "mid_stream" | "terminal_sse";
147
177
  /** Whether the terminal came from a real upstream SSE event or a proxy synthetic tail. */
148
178
  terminalSource?: "upstream" | "synthetic";
179
+ /** Bounded route-decision trace (RI-01); never contains secrets. */
180
+ routeDecision?: RouteDecisionTraceV1;
149
181
  }
150
182
 
151
183
  const requestLog: RequestLogEntry[] = [];
@@ -214,6 +246,7 @@ function asCloseReason(value: string | undefined): RequestLogEntry["closeReason"
214
246
  export function requestLogEntryFromPersistedUsage(entry: PersistedUsageEntry): RequestLogEntry {
215
247
  const terminalStatus = asTerminalStatus(entry.terminalStatus);
216
248
  const closeReason = asCloseReason(entry.closeReason);
249
+ const routeDecision = normalizeRouteDecisionTraceForLog(entry.routeDecision);
217
250
  return {
218
251
  requestId: entry.requestId,
219
252
  timestamp: entry.timestamp,
@@ -222,11 +255,18 @@ export function requestLogEntryFromPersistedUsage(entry: PersistedUsageEntry): R
222
255
  ...(entry.firstOutputMs !== undefined ? { firstOutputMs: entry.firstOutputMs } : {}),
223
256
  ...(isKnownUsageSurface(entry.surface) ? { surface: entry.surface } : {}),
224
257
  ...(entry.conversationId ? { conversationId: entry.conversationId } : {}),
258
+ ...(isCodexUsageAccountLogLabel(entry.accountLogLabel)
259
+ ? { accountLogLabel: entry.accountLogLabel }
260
+ : {}),
225
261
  ...(entry.requestedModel ? { requestedModel: entry.requestedModel } : {}),
262
+ ...(entry.shadowCallRewrittenFrom
263
+ ? { shadowCallRewrittenFrom: entry.shadowCallRewrittenFrom }
264
+ : {}),
226
265
  ...(entry.requestedEffort ? { requestedEffort: entry.requestedEffort } : {}),
227
266
  ...(entry.effectiveEffort ? { effectiveEffort: entry.effectiveEffort } : {}),
228
267
  ...(entry.reasoningWireField ? { reasoningWireField: entry.reasoningWireField } : {}),
229
268
  ...(entry.reasoningWireValue !== undefined ? { reasoningWireValue: entry.reasoningWireValue } : {}),
269
+ ...(entry.callerServiceTier ? { callerServiceTier: entry.callerServiceTier } : {}),
230
270
  ...(entry.requestedServiceTier ? { requestedServiceTier: entry.requestedServiceTier } : {}),
231
271
  ...(entry.requestedSpeedLabel ? { requestedSpeedLabel: entry.requestedSpeedLabel } : {}),
232
272
  ...(entry.configuredServiceTier ? { configuredServiceTier: entry.configuredServiceTier } : {}),
@@ -235,6 +275,7 @@ export function requestLogEntryFromPersistedUsage(entry: PersistedUsageEntry): R
235
275
  ? { modelSupportsServiceTier: entry.modelSupportsServiceTier }
236
276
  : {}),
237
277
  ...(entry.responseServiceTier ? { responseServiceTier: entry.responseServiceTier } : {}),
278
+ ...(entry.tierOutcome ? { tierOutcome: entry.tierOutcome } : {}),
238
279
  ...(entry.resolvedModel ? { resolvedModel: entry.resolvedModel } : {}),
239
280
  status: entry.status,
240
281
  durationMs: entry.durationMs,
@@ -245,10 +286,22 @@ export function requestLogEntryFromPersistedUsage(entry: PersistedUsageEntry): R
245
286
  usageStatus: entry.usageStatus,
246
287
  ...(entry.usage ? { usage: entry.usage } : {}),
247
288
  ...(entry.totalTokens !== undefined ? { totalTokens: entry.totalTokens } : {}),
248
- ...(entry.attempts?.length ? { attempts: entry.attempts } : {}),
289
+ ...(entry.attempts !== undefined ? { attempts: entry.attempts } : {}),
290
+ ...(routeDecision ? { routeDecision } : {}),
249
291
  };
250
292
  }
251
293
 
294
+ /**
295
+ * Hydration guard: persisted traces are re-normalized before they enter the
296
+ * in-memory ring buffer so a hand-edited or corrupt row cannot poison the DTO.
297
+ * A row that fails validation is dropped, never forwarded unvalidated.
298
+ */
299
+ function normalizeRouteDecisionTraceForLog(
300
+ entry: RouteDecisionTraceV1 | undefined,
301
+ ): RouteDecisionTraceV1 | null {
302
+ return entry ? normalizeRouteDecisionTrace(entry) : null;
303
+ }
304
+
252
305
  /**
253
306
  * Seed the in-memory Logs ring buffer from usage.jsonl so GUI /api/logs survives
254
307
  * `ocx stop` / `ocx start` (process restart). Idempotent per process; no-ops when
@@ -281,6 +334,20 @@ export function hydrateRequestLogsFromDisk(
281
334
  }
282
335
 
283
336
  export function addRequestLog(entry: RequestLogEntry) {
337
+ // Sanitize ONCE, at the ingress, and use that one value for both destinations.
338
+ //
339
+ // `addFinalRequestLog` is not the only way in: `addRequestLog` is exported and callable
340
+ // directly, and it retained the caller's entry verbatim in the in-memory ring while only the
341
+ // field-by-field disk projection below saw a sanitized value. That split let `/api/logs`
342
+ // serve a raw upstream-supplied marker — a newline in it can forge a record boundary in a
343
+ // line-oriented viewer — while `usage.jsonl` looked clean, which is the worst shape for a
344
+ // sanitization bug because the safe surface is the one you check.
345
+ const shadowCallRewrittenFrom = sanitizeLogMetadataString(entry.shadowCallRewrittenFrom);
346
+ const retained: RequestLogEntry = shadowCallRewrittenFrom === entry.shadowCallRewrittenFrom
347
+ ? entry
348
+ : { ...entry, ...(shadowCallRewrittenFrom ? { shadowCallRewrittenFrom } : {}) };
349
+ if (!shadowCallRewrittenFrom && retained !== entry) delete retained.shadowCallRewrittenFrom;
350
+ entry = retained;
284
351
  retainRequestLogEntry(entry);
285
352
  try {
286
353
  // Failure diagnostics survive the 200-entry ring buffer by riding the persisted
@@ -306,13 +373,20 @@ export function addRequestLog(entry: RequestLogEntry) {
306
373
  ...(entry.apiKeyId ? { apiKeyId: entry.apiKeyId } : {}),
307
374
  ...(isKnownAdmissionKind(entry.admissionKind) ? { admissionKind: entry.admissionKind } : {}),
308
375
  ...(isKnownInboundProtocol(entry.inboundProtocol) ? { inboundProtocol: entry.inboundProtocol } : {}),
376
+ ...(isCodexUsageAccountLogLabel(entry.accountLogLabel)
377
+ ? { accountLogLabel: entry.accountLogLabel }
378
+ : {}),
309
379
  ...(entry.conversationId ? { conversationId: entry.conversationId } : {}),
310
380
  ...(entry.resolvedModel ? { resolvedModel: entry.resolvedModel } : {}),
311
381
  ...(entry.requestedModel ? { requestedModel: entry.requestedModel } : {}),
382
+ ...(entry.shadowCallRewrittenFrom
383
+ ? { shadowCallRewrittenFrom: entry.shadowCallRewrittenFrom }
384
+ : {}),
312
385
  ...(entry.requestedEffort ? { requestedEffort: entry.requestedEffort } : {}),
313
386
  ...(entry.effectiveEffort ? { effectiveEffort: entry.effectiveEffort } : {}),
314
387
  ...(entry.reasoningWireField ? { reasoningWireField: entry.reasoningWireField } : {}),
315
388
  ...(entry.reasoningWireValue !== undefined ? { reasoningWireValue: entry.reasoningWireValue } : {}),
389
+ ...(entry.callerServiceTier ? { callerServiceTier: entry.callerServiceTier } : {}),
316
390
  ...(entry.requestedServiceTier ? { requestedServiceTier: entry.requestedServiceTier } : {}),
317
391
  ...(entry.requestedSpeedLabel ? { requestedSpeedLabel: entry.requestedSpeedLabel } : {}),
318
392
  ...(entry.configuredServiceTier ? { configuredServiceTier: entry.configuredServiceTier } : {}),
@@ -321,14 +395,16 @@ export function addRequestLog(entry: RequestLogEntry) {
321
395
  ? { modelSupportsServiceTier: entry.modelSupportsServiceTier }
322
396
  : {}),
323
397
  ...(entry.responseServiceTier ? { responseServiceTier: entry.responseServiceTier } : {}),
398
+ ...(entry.tierOutcome ? { tierOutcome: entry.tierOutcome } : {}),
324
399
  status: entry.status,
325
400
  durationMs: entry.durationMs,
326
401
  ...(entry.firstOutputMs !== undefined ? { firstOutputMs: entry.firstOutputMs } : {}),
327
402
  usageStatus: entry.usageStatus,
328
403
  ...(entry.usage ? { usage: entry.usage } : {}),
329
404
  ...(entry.totalTokens !== undefined ? { totalTokens: entry.totalTokens } : {}),
330
- ...(entry.attempts?.length ? { attempts: entry.attempts } : {}),
405
+ ...(entry.attempts !== undefined ? { attempts: entry.attempts } : {}),
331
406
  ...failureDiagnostics,
407
+ ...(entry.routeDecision ? { routeDecision: entry.routeDecision } : {}),
332
408
  });
333
409
  } catch {
334
410
  /* request logging must never fail a user request */
@@ -399,12 +475,11 @@ export function recordAdapterReasoning(
399
475
  const reasoning = raw as Record<string, unknown>;
400
476
  if (typeof reasoning.effectiveEffort !== "string" || !reasoning.effectiveEffort
401
477
  || (reasoning.wireField !== "reasoning_effort"
478
+ && reasoning.wireField !== "reasoning.enabled"
479
+ && reasoning.wireField !== "reasoning.effort"
402
480
  && reasoning.wireField !== "thinking_budget"
403
481
  && reasoning.wireField !== "thinking.type")
404
- || (!(typeof reasoning.wireValue === "string" && reasoning.wireValue)
405
- && !(typeof reasoning.wireValue === "number"
406
- && Number.isFinite(reasoning.wireValue)
407
- && reasoning.wireValue >= 0))) {
482
+ || !isValidReasoningWireValue(reasoning.wireField, reasoning.wireValue)) {
408
483
  return;
409
484
  }
410
485
 
@@ -425,12 +500,55 @@ export function recordAdapterReasoning(
425
500
  }
426
501
  }
427
502
 
428
- export function requestLogErrorCode(status: number, upstreamError?: string): string | undefined {
503
+ /** Attach the serializing adapter's tier observation to the active durable attempt. */
504
+ export function recordAdapterTier(
505
+ logCtx: RequestLogContext,
506
+ request: AdapterRequest,
507
+ ): void {
508
+ recordAdapterTierMetadata(logCtx, request.tierLog);
509
+ }
510
+
511
+ /** Attach adapter-owned metadata for transports that expose no AdapterRequest (runTurn). */
512
+ export function recordAdapterTierMetadata(
513
+ logCtx: RequestLogContext,
514
+ metadata: AdapterTierMetadata | undefined,
515
+ ): void {
516
+ delete logCtx.tierOutcome;
517
+ delete logCtx.activeTierMetadata;
518
+ const attempt = logCtx.activeAttempt;
519
+ if (attempt) delete attempt.tierOutcome;
520
+
521
+ try {
522
+ const outcome = metadata?.outcome;
523
+ if (!metadata || !outcome) return;
524
+ logCtx.tierOutcome = outcome;
525
+ logCtx.activeTierMetadata = metadata;
526
+ if (attempt) attempt.tierOutcome = outcome;
527
+ } catch {
528
+ // Request logging is best-effort and must not affect request delivery.
529
+ }
530
+ }
531
+
532
+ export function requestLogErrorCode(
533
+ status: number,
534
+ upstreamError?: string,
535
+ terminalErrorCode?: string,
536
+ ): string | undefined {
429
537
  if (status >= 200 && status < 400) return undefined;
538
+ // A structured terminal code is authoritative even when the provider message is localized,
539
+ // generic, or absent. Only preserve the one narrowly recognized policy code here: broadly
540
+ // forwarding arbitrary upstream codes would change unrelated request-log taxonomy.
541
+ if (isCyberPolicyCode(terminalErrorCode)) return CYBER_POLICY_ERROR_CODE;
542
+ const classifiedCode = upstreamError?.trim()
543
+ ? classifyError(status, "upstream_error", upstreamError).code
544
+ : undefined;
430
545
  // Defense in depth: mid-stream web-search aborts used to land as 502 with this message.
431
- if (status === 499 || (upstreamError?.trim() && classifyError(status, "upstream_error", upstreamError).code === "client_closed_request")) {
546
+ if (status === 499 || classifiedCode === "client_closed_request") {
432
547
  return "client_closed_request";
433
548
  }
549
+ // Keep the high-confidence message fallback for runtimes/providers that stripped the
550
+ // structured code before emitting response.failed.
551
+ if (classifiedCode === CYBER_POLICY_ERROR_CODE) return CYBER_POLICY_ERROR_CODE;
434
552
  if (status === 400 || status === 409) return "invalid_request_error";
435
553
  if (status === 401) return "invalid_api_key";
436
554
  if (status === 403) {
@@ -493,9 +611,19 @@ export function applyResponseLogMetadata(logCtx: RequestLogContext, payload: unk
493
611
  : payload;
494
612
  if (!source || typeof source !== "object") return;
495
613
  const model = (source as { model?: unknown }).model;
496
- if (typeof model === "string" && model.trim()) logCtx.resolvedModel = model;
614
+ if (
615
+ !logCtx.preserveResolvedModelFromRoute
616
+ && typeof model === "string"
617
+ && model.trim()
618
+ ) logCtx.resolvedModel = model;
497
619
  const serviceTier = (source as { service_tier?: unknown }).service_tier;
498
- if (typeof serviceTier === "string" && serviceTier.trim()) logCtx.responseServiceTier = serviceTier;
620
+ if (typeof serviceTier === "string" && serviceTier.trim()) {
621
+ const sanitized = sanitizeLogMetadataString(serviceTier);
622
+ if (sanitized) logCtx.responseServiceTier = sanitized;
623
+ logCtx.activeTierMetadata?.observeResponseServiceTier(serviceTier);
624
+ } else if (Object.prototype.hasOwnProperty.call(source, "service_tier")) {
625
+ logCtx.activeTierMetadata?.observeResponseServiceTier(serviceTier);
626
+ }
499
627
  const usage = usageFromResponsesPayload((source as { usage?: unknown }).usage);
500
628
  if (usage && !logCtx.usageFromBridge) {
501
629
  logCtx.usage = usage;
@@ -561,6 +689,7 @@ export function inspectResponseLogJson(logCtx: RequestLogContext, text: string):
561
689
  try {
562
690
  applyResponseLogMetadata(logCtx, JSON.parse(text));
563
691
  } catch {
692
+ logCtx.activeTierMetadata?.markResponseUnparseable();
564
693
  /* body may not be JSON; request log metadata is best-effort only */
565
694
  }
566
695
  captureUpstreamError(logCtx, text);
@@ -591,6 +720,7 @@ export function inspectResponseLogSsePayloadParsed(
591
720
  const debugEnabled = isUsageDebugEnabled();
592
721
  const sseAlreadyMarked = logCtx.usageDebugBodyKind === "sse";
593
722
  if (parsed !== undefined) applyResponseLogMetadata(logCtx, parsed);
723
+ else logCtx.activeTierMetadata?.markResponseUnparseable();
594
724
  captureUpstreamErrorParsed(logCtx, payload, parsed);
595
725
  if (debugEnabled) {
596
726
  if (!sseAlreadyMarked) {
@@ -694,9 +824,17 @@ function captureTerminalHttpStatus(
694
824
  if (json.type !== "response.failed") return;
695
825
  const error = json.response?.error;
696
826
  if (!error || typeof error !== "object") return;
827
+ const terminalCode = error.code === null || typeof error.code === "string"
828
+ ? error.code
829
+ : undefined;
830
+ if (isCyberPolicyCode(terminalCode)) {
831
+ logCtx.terminalErrorCode = CYBER_POLICY_ERROR_CODE;
832
+ } else {
833
+ delete logCtx.terminalErrorCode;
834
+ }
697
835
  logCtx.terminalHttpStatus = httpStatusFromTerminalError({
698
836
  type: typeof error.type === "string" ? error.type : undefined,
699
- code: error.code === null || typeof error.code === "string" ? error.code : undefined,
837
+ code: terminalCode,
700
838
  message: typeof error.message === "string" ? error.message : undefined,
701
839
  });
702
840
  }
@@ -752,7 +890,11 @@ export function addFinalRequestLog(
752
890
  const effectiveStatus = status >= 500 && logCtx.upstreamError && isClientClosedMessage(logCtx.upstreamError)
753
891
  ? 499
754
892
  : status;
755
- const errorCode = requestLogErrorCode(effectiveStatus, logCtx.upstreamError);
893
+ const errorCode = requestLogErrorCode(
894
+ effectiveStatus,
895
+ logCtx.upstreamError,
896
+ logCtx.terminalErrorCode,
897
+ );
756
898
  // A response.failed whose classified status is 499 is still a client cancel, not an upstream
757
899
  // terminal failure — keep /api/logs closeReason aligned with that.
758
900
  const closeReason = effectiveStatus === 499
@@ -765,22 +907,34 @@ export function addFinalRequestLog(
765
907
  Date.now() - (logCtx.activeAttemptStartedAt ?? start),
766
908
  logCtx.usage,
767
909
  );
910
+ // The final row and its active physical attempt describe the same terminal. Preserve the
911
+ // semantic code on both so detailed attempt telemetry cannot regress to a generic status code.
912
+ if (errorCode) logCtx.activeAttempt.errorCode = errorCode;
913
+ else delete logCtx.activeAttempt.errorCode;
768
914
  }
769
915
  const existing = finalizedUsage(
770
916
  logCtx.providerAdapter ?? logCtx.provider,
771
917
  logCtx.usage,
772
918
  logCtx.usageLogInputTokens,
919
+ contextWindowForModel(logCtx.providerAdapter ?? logCtx.provider, logCtx.model),
773
920
  );
774
921
  const attempts = logCtx.attempts?.map(attempt => ({
775
922
  ...attempt,
776
923
  recoveryKinds: [...attempt.recoveryKinds],
777
924
  ...(attempt.usage ? { usage: { ...attempt.usage } } : {}),
925
+ ...(attempt.tierOutcome ? { tierOutcome: { ...attempt.tierOutcome } } : {}),
778
926
  }));
779
927
  const isCombo = logCtx.comboId !== undefined && (attempts?.length ?? 0) > 0;
780
928
  const aggregate = isCombo ? aggregateAttemptUsage(attempts ?? []) : null;
781
929
  const loggedUsage = aggregate?.usage ?? existing.usage;
782
930
  const usageStatus = aggregate?.status ?? existing.status;
783
931
  const totalTokens = aggregate?.totalTokens ?? existing.totalTokens;
932
+ // Sanitize at the logging layer, not only at the one call site that populates this today.
933
+ // The value originates in an upstream-supplied model id, so an unsanitized newline would
934
+ // let a single field forge a record boundary in any line-oriented log viewer. Doing it here
935
+ // means a future caller cannot reintroduce the hole by forgetting to sanitize first, and
936
+ // the in-memory /api/logs row matches what usage.jsonl already stores.
937
+ const shadowCallRewrittenFrom = sanitizeLogMetadataString(logCtx.shadowCallRewrittenFrom);
784
938
  addLog({
785
939
  requestId,
786
940
  timestamp: start,
@@ -790,18 +944,26 @@ export function addFinalRequestLog(
790
944
  ...(logCtx.apiKeyId ? { apiKeyId: logCtx.apiKeyId } : {}),
791
945
  ...(logCtx.admissionKind ? { admissionKind: logCtx.admissionKind } : {}),
792
946
  ...(logCtx.inboundProtocol ? { inboundProtocol: logCtx.inboundProtocol } : {}),
947
+ ...(isCodexUsageAccountLogLabel(logCtx.accountLogLabel)
948
+ ? { accountLogLabel: logCtx.accountLogLabel }
949
+ : {}),
793
950
  ...(logCtx.conversationId ? { conversationId: logCtx.conversationId } : {}),
794
951
  ...(logCtx.requestedModel ? { requestedModel: logCtx.requestedModel } : {}),
952
+ ...(shadowCallRewrittenFrom ? { shadowCallRewrittenFrom } : {}),
795
953
  ...(logCtx.requestedEffort ? { requestedEffort: logCtx.requestedEffort } : {}),
796
954
  ...(logCtx.effectiveEffort ? { effectiveEffort: logCtx.effectiveEffort } : {}),
797
955
  ...(logCtx.reasoningWireField ? { reasoningWireField: logCtx.reasoningWireField } : {}),
798
956
  ...(logCtx.reasoningWireValue !== undefined ? { reasoningWireValue: logCtx.reasoningWireValue } : {}),
957
+ ...(logCtx.callerServiceTier ? { callerServiceTier: logCtx.callerServiceTier } : {}),
799
958
  ...(logCtx.requestedServiceTier ? { requestedServiceTier: logCtx.requestedServiceTier } : {}),
800
959
  ...(logCtx.requestedSpeedLabel ? { requestedSpeedLabel: logCtx.requestedSpeedLabel } : {}),
801
960
  ...(logCtx.configuredServiceTier ? { configuredServiceTier: logCtx.configuredServiceTier } : {}),
802
961
  ...(logCtx.configuredSpeedLabel ? { configuredSpeedLabel: logCtx.configuredSpeedLabel } : {}),
803
962
  ...(logCtx.modelSupportsServiceTier !== undefined ? { modelSupportsServiceTier: logCtx.modelSupportsServiceTier } : {}),
804
963
  ...(logCtx.responseServiceTier ? { responseServiceTier: logCtx.responseServiceTier } : {}),
964
+ ...((attempts?.at(-1)?.tierOutcome ?? logCtx.tierOutcome)
965
+ ? { tierOutcome: attempts?.at(-1)?.tierOutcome ?? { ...logCtx.tierOutcome! } }
966
+ : {}),
805
967
  ...(logCtx.resolvedModel ? { resolvedModel: logCtx.resolvedModel } : {}),
806
968
  status: effectiveStatus,
807
969
  durationMs: Date.now() - start,
@@ -813,10 +975,11 @@ export function addFinalRequestLog(
813
975
  usageStatus,
814
976
  ...(loggedUsage ? { usage: loggedUsage } : {}),
815
977
  ...(totalTokens !== undefined ? { totalTokens } : {}),
816
- ...(attempts?.length ? { attempts } : {}),
978
+ ...(attempts !== undefined ? { attempts } : {}),
817
979
  ...(logCtx.affinity ? { affinity: logCtx.affinity } : {}),
818
980
  ...(logCtx.transportPhase ? { transportPhase: logCtx.transportPhase } : {}),
819
981
  ...(logCtx.terminalSource ? { terminalSource: logCtx.terminalSource } : {}),
982
+ ...(logCtx.routeDecision ? { routeDecision: logCtx.routeDecision } : {}),
820
983
  });
821
984
  if (isUsageDebugEnabled()) {
822
985
  appendUsageDebug({
@@ -887,27 +1050,69 @@ interface FinalizedUsageResult {
887
1050
  totalTokens?: number;
888
1051
  }
889
1052
 
1053
+ /**
1054
+ * Context window for the routed model, used to cap the token estimate (codex-router PR #140):
1055
+ * a request the provider answered cannot have exceeded the window, so the estimate must never
1056
+ * claim it did. The family is picked by the route ADAPTER, not the model id alone, because
1057
+ * claude-family ids are shared between Kiro and Cursor with different windows. Kiro "auto" is
1058
+ * a router with no fixed window and is never guessed; unknown adapters/models stay uncapped.
1059
+ */
1060
+ function contextWindowForModel(adapter: string, modelId: string | undefined): number | undefined {
1061
+ if (!modelId) return undefined;
1062
+ if (adapter === "kiro" || adapter.startsWith("kiro-")) {
1063
+ const normalized = normalizeKiroModelId(modelId);
1064
+ if (normalized === "auto") return undefined;
1065
+ return modelRecordValue(KIRO_MODEL_CONTEXT_WINDOWS, modelId)
1066
+ ?? modelRecordValue(KIRO_MODEL_CONTEXT_WINDOWS, normalized);
1067
+ }
1068
+ if (adapter === "cursor" || adapter.startsWith("cursor-")) {
1069
+ return inferCursorContextWindow(modelId);
1070
+ }
1071
+ return undefined;
1072
+ }
1073
+
890
1074
  function finalizedUsage(
891
1075
  adapter: string,
892
1076
  usage: OcxUsage | undefined,
893
1077
  inputTokenEstimate: number | undefined,
1078
+ contextWindow: number | undefined,
894
1079
  ): FinalizedUsageResult {
1080
+ // The ESTIMATE itself is capped at the model's context window (codex-router PR #140). The
1081
+ // combined value below keeps its max(inputTokens, estimate) behavior — a provider-reported
1082
+ // positive count is never reduced by this cap, only the estimate that could substitute it.
895
1083
  const estimate = typeof inputTokenEstimate === "number"
896
1084
  && Number.isFinite(inputTokenEstimate)
897
1085
  && inputTokenEstimate >= 0
898
- ? inputTokenEstimate
1086
+ ? capEstimateAtContextWindow(inputTokenEstimate, contextWindow)
899
1087
  : undefined;
900
1088
  const finalUsage = usageForFinalLog(adapter, usage);
901
1089
  const usageFallback = !finalUsage && estimate !== undefined
902
1090
  ? { inputTokens: estimate, outputTokens: 0, estimated: true }
903
1091
  : undefined;
904
- const loggedUsage = finalUsage && estimate !== undefined
1092
+ const combinedInputTokens = finalUsage && estimate !== undefined
1093
+ ? Math.max(finalUsage.inputTokens, estimate)
1094
+ : undefined;
1095
+ const loggedUsage = finalUsage && combinedInputTokens !== undefined
905
1096
  ? {
906
1097
  ...finalUsage,
907
- inputTokens: Math.max(finalUsage.inputTokens, estimate),
1098
+ inputTokens: combinedInputTokens,
1099
+ totalTokens: combinedInputTokens + finalUsage.outputTokens,
908
1100
  estimated: true,
909
1101
  }
910
- : (finalUsage ?? usageFallback);
1102
+ : finalUsage
1103
+ // When the adapter alone produced an estimated count and no local estimate
1104
+ // exists, cap it at the context window — an adapter estimate above the window
1105
+ // misleads the usage dashboard. The combined branch (above) already caps the
1106
+ // ESTIMATE via capEstimateAtContextWindow, and Math.max preserves a real
1107
+ // provider-reported count, so it needs no further reduction.
1108
+ ? (finalUsage.estimated && contextWindow !== undefined && finalUsage.inputTokens > contextWindow
1109
+ ? {
1110
+ ...finalUsage,
1111
+ inputTokens: contextWindow,
1112
+ totalTokens: contextWindow + finalUsage.outputTokens,
1113
+ }
1114
+ : finalUsage)
1115
+ : usageFallback;
911
1116
  const totalTokens = usageTotalTokens(loggedUsage);
912
1117
  return {
913
1118
  status: usageStatusForFinalLog(loggedUsage),
@@ -939,10 +1144,12 @@ export function sealRequestAttemptIdentity(
939
1144
  attempt: PersistedUsageAttempt | undefined,
940
1145
  provider: string,
941
1146
  adapter: string,
1147
+ accountLogLabel?: string,
942
1148
  ): void {
943
1149
  if (!attempt) return;
944
1150
  attempt.provider = provider;
945
1151
  attempt.adapter = adapter;
1152
+ if (isCodexUsageAccountLogLabel(accountLogLabel)) attempt.accountLogLabel = accountLogLabel;
946
1153
  }
947
1154
 
948
1155
  export function noteAttemptSend(
@@ -955,7 +1162,12 @@ export function noteAttemptSend(
955
1162
  if (typeof inputTokenEstimate === "number"
956
1163
  && Number.isFinite(inputTokenEstimate)
957
1164
  && inputTokenEstimate >= 0) {
958
- attempt.inputTokenEstimate = inputTokenEstimate;
1165
+ // Store the ESTIMATE field already capped at the model's window (codex-router PR #140):
1166
+ // what gets persisted, and later merged into usage, never claims a count above the window.
1167
+ attempt.inputTokenEstimate = capEstimateAtContextWindow(
1168
+ inputTokenEstimate,
1169
+ contextWindowForModel(attempt.adapter, attempt.model),
1170
+ );
959
1171
  }
960
1172
  if (recovery && !attempt.recoveryKinds.includes(recovery)) {
961
1173
  attempt.recoveryKinds.push(recovery);
@@ -972,6 +1184,7 @@ export function finishRequestAttempt(
972
1184
  attempt.adapter,
973
1185
  usage ?? attempt.usage,
974
1186
  attempt.inputTokenEstimate,
1187
+ contextWindowForModel(attempt.adapter, attempt.model),
975
1188
  );
976
1189
  attempt.status = status;
977
1190
  attempt.durationMs = Math.max(0, durationMs);