@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
@@ -1,11 +1,20 @@
1
1
  import { baseProviderLabel } from "../providers/label";
2
2
  import { canonicalAntigravityUsageModel } from "../providers/antigravity-models";
3
3
  import { usageDisplayTotalTokens } from "./totals";
4
- import type { PersistedUsageEntry, UsageStatus } from "./log";
5
- import { estimateComboCost, estimateRequestCost, effectiveServiceTier } from "./cost";
4
+ import { isCodexUsageAccountLogLabel, type PersistedUsageEntry, type UsageStatus } from "./log";
5
+ import { estimateAttemptCost, estimateComboCost, estimateRequestCost, serviceTierContext } from "./cost";
6
6
 
7
- export type UsageRange = "7d" | "30d" | "all";
8
- export type UsageSurface = "all" | "codex" | "claude" | "grok";
7
+ /**
8
+ * Canonical range members. The warm-up loop in the management usage route
9
+ * iterates this constant rather than its own literal: the two used to be
10
+ * written separately, and a subset literal type-checks perfectly happily, so a
11
+ * range added to the union but forgotten in the loop was never warmed and
12
+ * never invalidated alongside its siblings.
13
+ */
14
+ export const USAGE_RANGES = ["today", "7d", "30d", "all"] as const;
15
+ export type UsageRange = typeof USAGE_RANGES[number];
16
+ export const USAGE_SURFACES = ["all", "codex", "claude", "grok"] as const;
17
+ export type UsageSurface = typeof USAGE_SURFACES[number];
9
18
 
10
19
  export interface UsageSummaryTotals {
11
20
  requests: number;
@@ -40,6 +49,8 @@ export interface UsageDay {
40
49
  measuredRequests: number;
41
50
  reportedRequests: number;
42
51
  totalTokens: number;
52
+ /** Display-time estimated cost for this local day, summed from its model rows. */
53
+ estimatedCostUsd: number;
43
54
  models: UsageDayModel[];
44
55
  }
45
56
 
@@ -49,6 +60,8 @@ export interface UsageDayModel {
49
60
  requests: number;
50
61
  attemptCount: number;
51
62
  totalTokens: number;
63
+ /** Display-time estimated cost attributed to this provider/model on this day. */
64
+ estimatedCostUsd: number;
52
65
  }
53
66
 
54
67
  export interface UsageModel {
@@ -79,6 +92,28 @@ export interface UsageProvider {
79
92
  estimatedCostUsd?: number;
80
93
  }
81
94
 
95
+ export interface UsageAccount {
96
+ accountLogLabel: string;
97
+ ambiguous: boolean;
98
+ requests: number;
99
+ attemptCount: number;
100
+ measuredAttempts: number;
101
+ reportedAttempts: number;
102
+ estimatedAttempts: number;
103
+ unmeteredAttempts: number;
104
+ inputTokens: number;
105
+ outputTokens: number;
106
+ cacheReadInputTokens: number;
107
+ cacheCreationInputTokens: number;
108
+ reasoningOutputTokens: number;
109
+ totalTokens: number;
110
+ usageCoverageRatio: number;
111
+ estimatedCostUsd?: number;
112
+ pricedAttempts: number;
113
+ unpricedAttempts: number;
114
+ priceCoverageRatio: number;
115
+ }
116
+
82
117
  export interface UsageSummary {
83
118
  range: UsageRange;
84
119
  surface: UsageSurface;
@@ -88,6 +123,27 @@ export interface UsageSummary {
88
123
  days: UsageDay[];
89
124
  models: UsageModel[];
90
125
  providers: UsageProvider[];
126
+ accounts: UsageAccount[];
127
+ }
128
+
129
+ /**
130
+ * Echo of an applied provider/model projection.
131
+ *
132
+ * Present only on a filtered response so a consumer can distinguish "no rows
133
+ * matched" from "no traffic in this window", and can tell that the totals it
134
+ * is reading are a projection rather than the whole window.
135
+ */
136
+ export interface UsageFilterEcho {
137
+ provider: string | null;
138
+ model: string | null;
139
+ matched: boolean;
140
+ /**
141
+ * True when a retained row came from a combo attribution. Cost partitions
142
+ * cleanly across attempts, but a combo request is counted once per
143
+ * participating model, so a filtered REQUEST count can exceed the number of
144
+ * distinct requests. Cost is unaffected.
145
+ */
146
+ comboOverlap: boolean;
91
147
  }
92
148
 
93
149
  const DAY_MS = 86_400_000;
@@ -104,6 +160,10 @@ function retainedBreakdownRows<T>(
104
160
  }
105
161
 
106
162
  export function parseRange(input: string | null | undefined): UsageRange {
163
+ // `1d` normalises here rather than becoming a second union member: a second
164
+ // member would need its own cache slot, its own grid arm and its own test
165
+ // matrix for no user-visible gain.
166
+ if (input === "today" || input === "1d") return "today";
107
167
  if (input === "7d" || input === "30d" || input === "all") return input;
108
168
  return "30d";
109
169
  }
@@ -113,9 +173,28 @@ export function parseUsageSurface(input: string | null | undefined): UsageSurfac
113
173
  return "all";
114
174
  }
115
175
 
116
- function rangeWindow(range: UsageRange, now: number): { since: number | null; days: number } {
117
- if (range === "7d") return { since: now - 7 * DAY_MS, days: 7 };
118
- if (range === "30d") return { since: now - 30 * DAY_MS, days: 30 };
176
+ function startOfLocalDay(ts: number): number {
177
+ const d = new Date(ts);
178
+ d.setHours(0, 0, 0, 0);
179
+ return d.getTime();
180
+ }
181
+
182
+ export function rangeWindow(range: UsageRange, now: number): { since: number | null; days: number } {
183
+ // Handled before the others because the fallthrough below is the `all`
184
+ // window: a range that reaches it is silently reported as all-time history,
185
+ // which for a cost surface is a plausible-looking wrong answer rather than a
186
+ // visible failure.
187
+ if (range === "today") return { since: startOfLocalDay(now), days: 1 };
188
+ if (range === "7d") {
189
+ const start = new Date(startOfLocalDay(now));
190
+ start.setDate(start.getDate() - 6);
191
+ return { since: start.getTime(), days: 7 };
192
+ }
193
+ if (range === "30d") {
194
+ const start = new Date(startOfLocalDay(now));
195
+ start.setDate(start.getDate() - 29);
196
+ return { since: start.getTime(), days: 30 };
197
+ }
119
198
  return { since: null, days: 0 };
120
199
  }
121
200
 
@@ -286,7 +365,7 @@ function addEstimatedCost(
286
365
  totals.unmeteredRequests += 1;
287
366
  return;
288
367
  }
289
- const tier = effectiveServiceTier(entry);
368
+ const tier = serviceTierContext(entry);
290
369
  const estimate = entry.attempts?.length
291
370
  ? estimateComboCost(entry.attempts, undefined, tier)
292
371
  : estimateRequestCost({ provider: entry.provider, model: entry.model, usage: entry.usage, usageStatus: entry.usageStatus, serviceTier: tier });
@@ -298,6 +377,33 @@ function addEstimatedCost(
298
377
  totals.estimatedCostUsd += estimate.cost.total;
299
378
  }
300
379
 
380
+ /**
381
+ * Per-attribution cost for one entry, keyed by `provider/model`.
382
+ *
383
+ * Mirrors the attribution branch in {@link buildModels}: a combo request is
384
+ * priced per attempt and each attempt's cost belongs to its own model, so cost
385
+ * partitions across models rather than being counted once per participant. A
386
+ * single-target request contributes its whole cost to the entry's own model.
387
+ */
388
+ function dayAttributionCosts(entry: PersistedUsageEntry): Map<string, number> {
389
+ const costs = new Map<string, number>();
390
+ const tier = serviceTierContext(entry);
391
+ const estimate = entry.attempts?.length
392
+ ? estimateComboCost(entry.attempts, undefined, tier)
393
+ : estimateRequestCost({ provider: entry.provider, model: entry.model, usage: entry.usage, usageStatus: entry.usageStatus, serviceTier: tier });
394
+ if (!estimate) return costs;
395
+ const add = (provider: string, model: string, amount: number): void => {
396
+ const key = usageModelKey(baseProviderLabel(provider), antigravityUsageModel(provider, model));
397
+ costs.set(key, (costs.get(key) ?? 0) + amount);
398
+ };
399
+ if (entry.attempts?.length && estimate.attempts) {
400
+ for (const attempt of estimate.attempts) add(attempt.provider, attempt.model, attempt.cost.total);
401
+ } else {
402
+ add(entry.provider, entry.model, estimate.cost.total);
403
+ }
404
+ return costs;
405
+ }
406
+
301
407
  function buildDayGrid(range: UsageRange, since: number | null, now: number, entries: PersistedUsageEntry[]): UsageDay[] {
302
408
  const window = rangeWindow(range, now);
303
409
  const days = range === "all" ? dayCountForAllRange(entries, now) : window.days;
@@ -306,14 +412,14 @@ function buildDayGrid(range: UsageRange, since: number | null, now: number, entr
306
412
  // render a per-model stacked bar with a hover tooltip without a second pass over the entries.
307
413
  const dayModels = new Map<string, Map<string, UsageDayModel>>();
308
414
  const dayModelRequests = new Map<string, Set<string>>();
309
- const bumpDayModel = (dayKey: string, attribution: UsageAttribution): void => {
415
+ const bumpDayModel = (dayKey: string, attribution: UsageAttribution, costUsd: number): void => {
310
416
  let models = dayModels.get(dayKey);
311
417
  if (!models) { models = new Map(); dayModels.set(dayKey, models); }
312
418
  const providerKey = baseProviderLabel(attribution.provider);
313
419
  const mKey = usageModelKey(providerKey, attribution.model);
314
420
  let m = models.get(mKey);
315
421
  if (!m) {
316
- m = { model: attribution.model, provider: providerKey, requests: 0, attemptCount: 0, totalTokens: 0 };
422
+ m = { model: attribution.model, provider: providerKey, requests: 0, attemptCount: 0, totalTokens: 0, estimatedCostUsd: 0 };
317
423
  models.set(mKey, m);
318
424
  }
319
425
  const requestKey = `${dayKey}\0${mKey}`;
@@ -323,23 +429,44 @@ function buildDayGrid(range: UsageRange, since: number | null, now: number, entr
323
429
  m.requests = requests.size;
324
430
  m.attemptCount += 1;
325
431
  m.totalTokens += usageDisplayTotalTokens(attribution.usage, attribution.totalTokens) ?? 0;
432
+ m.estimatedCostUsd += costUsd;
326
433
  };
434
+ const startOfToday = startOfLocalDay(now);
327
435
  for (let i = days - 1; i >= 0; i--) {
328
- const key = localDateKey(now - i * DAY_MS);
329
- grid.set(key, { date: key, requests: 0, measuredRequests: 0, reportedRequests: 0, totalTokens: 0, models: [] });
436
+ const d = new Date(startOfToday);
437
+ d.setDate(d.getDate() - i);
438
+ const key = localDateKey(d.getTime());
439
+ grid.set(key, { date: key, requests: 0, measuredRequests: 0, reportedRequests: 0, totalTokens: 0, estimatedCostUsd: 0, models: [] });
330
440
  }
331
441
  for (const entry of entries) {
332
442
  const key = localDateKey(entry.timestamp);
333
443
  let day = grid.get(key);
334
444
  if (!day) {
335
- day = { date: key, requests: 0, measuredRequests: 0, reportedRequests: 0, totalTokens: 0, models: [] };
445
+ day = { date: key, requests: 0, measuredRequests: 0, reportedRequests: 0, totalTokens: 0, estimatedCostUsd: 0, models: [] };
336
446
  grid.set(key, day);
337
447
  }
338
448
  day.requests += 1;
339
449
  if (isMeasuredStatus(entry.usageStatus)) day.measuredRequests += 1;
340
450
  if (entry.usageStatus === "reported") day.reportedRequests += 1;
341
451
  day.totalTokens += usageDisplayTotalTokens(entry.usage, entry.totalTokens) ?? 0;
342
- for (const attribution of usageAttributions(entry)) bumpDayModel(key, attribution);
452
+ // Price through the same seam buildModels uses: combo attempts are priced
453
+ // per attempt and attributed to their own model, everything else to the
454
+ // entry's model. Re-deriving a price here would make days[] disagree with
455
+ // models[] for exactly the combo traffic where nobody would notice.
456
+ const attributionCosts = dayAttributionCosts(entry);
457
+ for (const attribution of usageAttributions(entry)) {
458
+ const attributionKey = usageModelKey(baseProviderLabel(attribution.provider), attribution.model);
459
+ // Spend each key's cost ONCE. `attributionCosts` already holds the SUM of every
460
+ // attempt that shares a provider/model key, while `usageAttributions` yields one
461
+ // entry per attempt — so a retry onto the same model would otherwise add that
462
+ // pair's total twice and double the day against `summary.estimatedCostUsd`.
463
+ // Deleting on read keeps the first attribution carrying the group's cost and gives
464
+ // its siblings zero, which is what `buildModels` already does per attempt.
465
+ const costUsd = attributionCosts.get(attributionKey) ?? 0;
466
+ attributionCosts.delete(attributionKey);
467
+ bumpDayModel(key, attribution, costUsd);
468
+ day.estimatedCostUsd += costUsd;
469
+ }
343
470
  }
344
471
  void since;
345
472
  const out = [...grid.values()].sort((a, b) => a.date.localeCompare(b.date));
@@ -351,13 +478,15 @@ function buildDayGrid(range: UsageRange, since: number | null, now: number, entr
351
478
  const requests = new Set<string>();
352
479
  let attemptCount = 0;
353
480
  let totalTokens = 0;
481
+ let estimatedCostUsd = 0;
354
482
  for (const model of overflow) {
355
483
  attemptCount += model.attemptCount;
356
484
  totalTokens += model.totalTokens;
485
+ estimatedCostUsd += model.estimatedCostUsd;
357
486
  const requestKey = `${day.date}\0${usageModelKey(model.provider, model.model)}`;
358
487
  for (const requestId of dayModelRequests.get(requestKey) ?? []) requests.add(requestId);
359
488
  }
360
- return { model: "other", provider: "other", requests: requests.size, attemptCount, totalTokens };
489
+ return { model: "other", provider: "other", requests: requests.size, attemptCount, totalTokens, estimatedCostUsd };
361
490
  });
362
491
  }
363
492
  }
@@ -415,7 +544,7 @@ function buildModels(entries: PersistedUsageEntry[], totalTokens: number): Usage
415
544
  }
416
545
  // Accumulate per-model estimated cost
417
546
  for (const entry of entries) {
418
- const tier = effectiveServiceTier(entry);
547
+ const tier = serviceTierContext(entry);
419
548
  const estimate = entry.attempts?.length
420
549
  ? estimateComboCost(entry.attempts, undefined, tier)
421
550
  : estimateRequestCost({ provider: entry.provider, model: entry.model, usage: entry.usage, usageStatus: entry.usageStatus, serviceTier: tier });
@@ -524,7 +653,7 @@ function buildProviders(entries: PersistedUsageEntry[], totalTokens: number): Us
524
653
  }
525
654
  }
526
655
  for (const entry of entries) {
527
- const tier = effectiveServiceTier(entry);
656
+ const tier = serviceTierContext(entry);
528
657
  const estimate = entry.attempts?.length
529
658
  ? estimateComboCost(entry.attempts, undefined, tier)
530
659
  : estimateRequestCost({ provider: entry.provider, model: entry.model, usage: entry.usage, usageStatus: entry.usageStatus, serviceTier: tier });
@@ -547,6 +676,143 @@ function buildProviders(entries: PersistedUsageEntry[], totalTokens: number): Us
547
676
  return providers.sort((a, b) => b.requests - a.requests);
548
677
  }
549
678
 
679
+ const LEGACY_AMBIGUOUS_ACCOUNT_LABEL = "legacy-ambiguous";
680
+
681
+ function legacyCodexAccountLabel(provider: string): string | null {
682
+ if (baseProviderLabel(provider) !== "openai") return null;
683
+ const suffix = provider.match(/-(main|p[a-f0-9]{6})$/)?.[1];
684
+ return suffix ?? LEGACY_AMBIGUOUS_ACCOUNT_LABEL;
685
+ }
686
+
687
+ /**
688
+ * An explicitly stamped label of EITHER family is authoritative for any provider (#2699).
689
+ *
690
+ * No `o`-label branch is needed here: `isCodexUsageAccountLogLabel` now accepts both families,
691
+ * and adding a second predicate call would be a no-op guarded by a comment claiming otherwise.
692
+ *
693
+ * The legacy fallback stays openai-only on purpose. It infers an account from the PROVIDER
694
+ * string, and inferring for a non-Codex row would merge unrelated accounts under one label --
695
+ * so an unlabeled xai row is dropped from the account table rather than guessed at.
696
+ */
697
+ function accountLabelForAttribution(provider: string, explicit: unknown): string | null {
698
+ if (isCodexUsageAccountLogLabel(explicit)) return explicit;
699
+ return legacyCodexAccountLabel(provider);
700
+ }
701
+
702
+ function buildAccounts(entries: PersistedUsageEntry[]): UsageAccount[] {
703
+ const byLabel = new Map<string, UsageAccount>();
704
+ const requestIds = new Map<string, Set<string>>();
705
+
706
+ const add = (input: {
707
+ requestId: string;
708
+ provider: string;
709
+ accountLogLabel?: string;
710
+ usageStatus: UsageStatus;
711
+ usage?: PersistedUsageEntry["usage"];
712
+ totalTokens?: number;
713
+ estimate: ReturnType<typeof estimateRequestCost>;
714
+ }): void => {
715
+ const label = accountLabelForAttribution(input.provider, input.accountLogLabel);
716
+ if (!label) return;
717
+ let row = byLabel.get(label);
718
+ if (!row) {
719
+ row = {
720
+ accountLogLabel: label,
721
+ ambiguous: label === LEGACY_AMBIGUOUS_ACCOUNT_LABEL,
722
+ requests: 0,
723
+ attemptCount: 0,
724
+ measuredAttempts: 0,
725
+ reportedAttempts: 0,
726
+ estimatedAttempts: 0,
727
+ unmeteredAttempts: 0,
728
+ inputTokens: 0,
729
+ outputTokens: 0,
730
+ cacheReadInputTokens: 0,
731
+ cacheCreationInputTokens: 0,
732
+ reasoningOutputTokens: 0,
733
+ totalTokens: 0,
734
+ usageCoverageRatio: 0,
735
+ pricedAttempts: 0,
736
+ unpricedAttempts: 0,
737
+ priceCoverageRatio: 0,
738
+ };
739
+ byLabel.set(label, row);
740
+ requestIds.set(label, new Set());
741
+ }
742
+ requestIds.get(label)!.add(input.requestId);
743
+ row.requests = requestIds.get(label)!.size;
744
+ row.attemptCount += 1;
745
+ const measured = input.usage !== undefined && isMeasuredStatus(input.usageStatus);
746
+ if (!measured) {
747
+ row.unmeteredAttempts += 1;
748
+ return;
749
+ }
750
+
751
+ row.measuredAttempts += 1;
752
+ if (input.usageStatus === "reported") row.reportedAttempts += 1;
753
+ else if (input.usageStatus === "estimated") row.estimatedAttempts += 1;
754
+ row.inputTokens += input.usage!.inputTokens;
755
+ row.outputTokens += input.usage!.outputTokens;
756
+ const creation = input.usage!.cacheCreationInputTokens;
757
+ const read = typeof input.usage!.cacheReadInputTokens === "number"
758
+ ? input.usage!.cacheReadInputTokens
759
+ : typeof input.usage!.cachedInputTokens === "number" && typeof creation === "number"
760
+ ? Math.max(0, input.usage!.cachedInputTokens - creation)
761
+ : input.usage!.cachedInputTokens;
762
+ if (typeof read === "number") row.cacheReadInputTokens += read;
763
+ if (typeof creation === "number") row.cacheCreationInputTokens += creation;
764
+ if (typeof input.usage!.reasoningOutputTokens === "number") {
765
+ row.reasoningOutputTokens += input.usage!.reasoningOutputTokens;
766
+ }
767
+ row.totalTokens += usageDisplayTotalTokens(input.usage, input.totalTokens) ?? 0;
768
+ if (input.estimate) {
769
+ row.pricedAttempts += 1;
770
+ row.estimatedCostUsd = (row.estimatedCostUsd ?? 0) + input.estimate.cost.total;
771
+ } else {
772
+ row.unpricedAttempts += 1;
773
+ }
774
+ };
775
+
776
+ for (const entry of entries) {
777
+ const tier = serviceTierContext(entry);
778
+ if (entry.attempts?.length) {
779
+ for (const attempt of entry.attempts) {
780
+ add({
781
+ requestId: entry.requestId,
782
+ provider: attempt.provider,
783
+ ...(attempt.accountLogLabel ? { accountLogLabel: attempt.accountLogLabel } : {}),
784
+ usageStatus: attempt.usageStatus,
785
+ ...(attempt.usage ? { usage: attempt.usage } : {}),
786
+ ...(attempt.totalTokens !== undefined ? { totalTokens: attempt.totalTokens } : {}),
787
+ estimate: estimateAttemptCost(attempt, undefined, tier),
788
+ });
789
+ }
790
+ continue;
791
+ }
792
+ add({
793
+ requestId: entry.requestId,
794
+ provider: entry.provider,
795
+ ...(entry.accountLogLabel ? { accountLogLabel: entry.accountLogLabel } : {}),
796
+ usageStatus: entry.usageStatus,
797
+ ...(entry.usage ? { usage: entry.usage } : {}),
798
+ ...(entry.totalTokens !== undefined ? { totalTokens: entry.totalTokens } : {}),
799
+ estimate: estimateRequestCost({
800
+ provider: entry.provider,
801
+ model: entry.model,
802
+ usage: entry.usage,
803
+ usageStatus: entry.usageStatus,
804
+ serviceTier: tier,
805
+ }),
806
+ });
807
+ }
808
+
809
+ for (const row of byLabel.values()) {
810
+ row.usageCoverageRatio = row.attemptCount === 0 ? 0 : row.measuredAttempts / row.attemptCount;
811
+ row.priceCoverageRatio = row.measuredAttempts === 0 ? 0 : row.pricedAttempts / row.measuredAttempts;
812
+ }
813
+ return [...byLabel.values()].sort((a, b) => b.totalTokens - a.totalTokens);
814
+ }
815
+
550
816
  export function summarizeUsage(
551
817
  entries: PersistedUsageEntry[],
552
818
  range: UsageRange,
@@ -581,5 +847,110 @@ export function summarizeUsage(
581
847
  days: buildDayGrid(range, since, now, filteredEntries),
582
848
  models: buildModels(filteredEntries, totals.totalTokens),
583
849
  providers: buildProviders(filteredEntries, totals.totalTokens),
850
+ accounts: buildAccounts(filteredEntries),
851
+ };
852
+ }
853
+
854
+ function normalizeFilterValue(input: string | null | undefined): string | null {
855
+ const trimmed = typeof input === "string" ? input.trim() : "";
856
+ return trimmed === "" ? null : trimmed.toLowerCase();
857
+ }
858
+
859
+ /**
860
+ * Narrow an already-summarised window to one provider and/or model.
861
+ *
862
+ * Deliberately a projection over a finished summary rather than a parameter to
863
+ * {@link summarizeUsage}. The management route caches summaries under
864
+ * `range:surface` and warms that key space as a cross-product; a filtered
865
+ * summary that reached either would be served to the next UNFILTERED caller,
866
+ * the dashboard included. Keeping the filter outside the producer makes that
867
+ * mistake unrepresentable rather than merely discouraged.
868
+ *
869
+ * Totals are recomputed from the retained rows. For combo traffic a request is
870
+ * counted once per participating model, so a filtered request count can exceed
871
+ * the number of distinct requests; `comboOverlap` reports when that is
872
+ * possible. Cost is unaffected — combo cost is attributed per attempt, so it
873
+ * partitions across models rather than repeating.
874
+ *
875
+ * `accounts` is emptied whenever a filter is active: account rows are not
876
+ * provider-partitioned in a way this projection could honestly re-derive, and
877
+ * unfiltered account totals sitting beside filtered model totals would invite
878
+ * exactly the wrong reading.
879
+ */
880
+ export function projectUsageSummary<T extends UsageSummary>(
881
+ summary: T,
882
+ filter: { provider?: string | null; model?: string | null },
883
+ entries?: PersistedUsageEntry[],
884
+ ): T & { filter?: UsageFilterEcho } {
885
+ const provider = normalizeFilterValue(filter.provider);
886
+ const model = normalizeFilterValue(filter.model);
887
+ if (provider === null && model === null) return summary;
888
+
889
+ // Re-summarise from the entries the summary was built from, rather than
890
+ // projecting over its rows.
891
+ //
892
+ // Projecting rows looked cheaper and was wrong in three ways that only show
893
+ // up together: breakdown rows past MAX_USAGE_MODEL_BREAKDOWN_ROWS are
894
+ // collapsed into a synthetic "other" row, so a provider living only in that
895
+ // tail is unfindable and reports matched:false despite real usage; a
896
+ // provider row is a whole-provider aggregate, so a model filter kept the
897
+ // provider's OTHER models in providers[] while models[] and the totals
898
+ // excluded them, contradicting itself inside one response; and a model row
899
+ // carries a single optional cost, so priced/unpriced/unmetered counts could
900
+ // only be guessed per model rather than counted per request.
901
+ //
902
+ // The entries are already in hand on every path that filters, so the honest
903
+ // computation is also the simple one.
904
+ const matches = (rowProvider: string, rowModel: string): boolean => {
905
+ if (provider !== null && baseProviderLabel(rowProvider).toLowerCase() !== provider) return false;
906
+ if (model !== null && rowModel.toLowerCase() !== model) return false;
907
+ return true;
908
+ };
909
+
910
+ // Narrow to matching ATTRIBUTIONS, not matching entries.
911
+ //
912
+ // Keeping a whole combo entry because one of its attempts matched drags the
913
+ // other attempts' tokens and cost into the filtered totals: a two-attempt
914
+ // combo filtered to its cheap model reported the expensive model's spend
915
+ // too. Rewriting the entry down to its matching attempts is what makes the
916
+ // filtered numbers mean what the flag says.
917
+ const source = entries ?? [];
918
+ let comboOverlap = false;
919
+ const filtered: PersistedUsageEntry[] = [];
920
+ for (const entry of source) {
921
+ if (!entry.attempts?.length) {
922
+ if (matches(entry.provider, antigravityUsageModel(entry.provider, entry.model))) filtered.push(entry);
923
+ continue;
924
+ }
925
+ const attempts = entry.attempts.filter(a => matches(a.provider, antigravityUsageModel(a.provider, a.model)));
926
+ if (attempts.length === 0) continue;
927
+ // A combo is still counted once per participating model, so a filtered
928
+ // request count can exceed the number of distinct requests. That is the
929
+ // documented overlap, and it is why comboOverlap exists.
930
+ if (entry.attempts.length > 1) comboOverlap = true;
931
+ filtered.push({ ...entry, attempts });
932
+ }
933
+
934
+ const projected = summarizeUsage(filtered, summary.range, summary.generatedAt, summary.surface);
935
+ // matched reflects usage inside the requested WINDOW, not anywhere in the
936
+ // log: summarizeUsage applies the range and surface predicates, and the CLI
937
+ // uses this flag to decide between a table and "no usage recorded".
938
+ const matched = projected.summary.requests > 0;
939
+ // A combo entry survives the entry filter as a whole, so its non-matching
940
+ // attributions can still appear as rows. Drop those so every row in the
941
+ // response satisfies the filter the caller asked for.
942
+ const models = projected.models.filter(row => matches(row.provider, row.model));
943
+ const retainedProviders = new Set(models.map(row => row.provider));
944
+ return {
945
+ ...summary,
946
+ summary: projected.summary,
947
+ days: projected.days.map(day => ({ ...day, models: day.models.filter(row => matches(row.provider, row.model)) })),
948
+ models,
949
+ providers: projected.providers.filter(row => retainedProviders.has(row.provider)),
950
+ // Account rows are not provider-partitioned in a way this projection could
951
+ // honestly re-derive, and unfiltered account totals sitting beside filtered
952
+ // model totals would invite exactly the wrong reading.
953
+ accounts: [],
954
+ filter: { provider, model, matched, comboOverlap },
584
955
  };
585
956
  }