@iislee/opencodex 2.11.0 → 2.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (675) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +114 -19
  3. package/bin/ocx.mjs +164 -36
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-BF38heuV.js +104 -0
  6. package/gui/dist/assets/index-DMiI18Kv.css +1 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +19 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +376 -52
  44. package/src/adapters/base.ts +54 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +601 -0
  48. package/src/adapters/cursor/checkpoint-store.ts +303 -0
  49. package/src/adapters/cursor/cursor-errors.ts +129 -6
  50. package/src/adapters/cursor/discovery.ts +61 -4
  51. package/src/adapters/cursor/effort-map.ts +27 -3
  52. package/src/adapters/cursor/framing.ts +39 -0
  53. package/src/adapters/cursor/h2-pool.ts +123 -0
  54. package/src/adapters/cursor/http1-bidi.ts +361 -0
  55. package/src/adapters/cursor/images.ts +704 -0
  56. package/src/adapters/cursor/live-models.ts +174 -58
  57. package/src/adapters/cursor/live-transport.ts +609 -170
  58. package/src/adapters/cursor/native-exec-common.ts +23 -2
  59. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  60. package/src/adapters/cursor/native-exec-network.ts +1 -1
  61. package/src/adapters/cursor/native-exec-shell.ts +0 -1
  62. package/src/adapters/cursor/native-exec.ts +101 -14
  63. package/src/adapters/cursor/protobuf-events.ts +829 -11
  64. package/src/adapters/cursor/protobuf-request.ts +383 -65
  65. package/src/adapters/cursor/request-builder.ts +237 -31
  66. package/src/adapters/cursor/tool-definitions.ts +242 -12
  67. package/src/adapters/cursor/tool-result-normalize.ts +92 -0
  68. package/src/adapters/cursor/transport.ts +22 -0
  69. package/src/adapters/cursor/types.ts +28 -1
  70. package/src/adapters/cursor.ts +133 -7
  71. package/src/adapters/google-antigravity-replay.ts +558 -34
  72. package/src/adapters/google-antigravity-wire.ts +43 -10
  73. package/src/adapters/google-http.ts +38 -10
  74. package/src/adapters/google-tool-schema.ts +80 -15
  75. package/src/adapters/google-truncation.ts +11 -0
  76. package/src/adapters/google.ts +618 -74
  77. package/src/adapters/identity.ts +39 -6
  78. package/src/adapters/kiro-errors.ts +11 -0
  79. package/src/adapters/kiro-events.ts +19 -1
  80. package/src/adapters/kiro-thinking.ts +18 -2
  81. package/src/adapters/kiro-tools.ts +10 -1
  82. package/src/adapters/kiro.ts +92 -54
  83. package/src/adapters/mimo-free.ts +17 -0
  84. package/src/adapters/openai-chat-url.ts +11 -0
  85. package/src/adapters/openai-chat.ts +1311 -336
  86. package/src/adapters/openai-responses-url.ts +16 -0
  87. package/src/adapters/openai-responses.ts +830 -56
  88. package/src/adapters/registry.ts +175 -0
  89. package/src/adapters/responses-tool-schema.ts +67 -0
  90. package/src/adapters/tool-call-id.ts +119 -0
  91. package/src/adapters/tool-catalog-nudge.ts +104 -21
  92. package/src/adapters/xai-web-search.ts +185 -0
  93. package/src/bridge.ts +428 -61
  94. package/src/chat/inbound.ts +43 -19
  95. package/src/chat/outbound.ts +82 -26
  96. package/src/claude/agents-inject.ts +32 -9
  97. package/src/claude/context-windows.ts +21 -5
  98. package/src/claude/desktop-3p.ts +243 -9
  99. package/src/claude/gateway-cache.ts +41 -4
  100. package/src/claude/inbound.ts +72 -3
  101. package/src/claude/model-info.ts +38 -15
  102. package/src/claude/outbound.ts +70 -16
  103. package/src/cli/account-api.ts +35 -1
  104. package/src/cli/account-auth.ts +33 -6
  105. package/src/cli/account-catalog-refresh.ts +14 -0
  106. package/src/cli/account-extended.ts +389 -2
  107. package/src/cli/account-main.ts +317 -0
  108. package/src/cli/account.ts +30 -6
  109. package/src/cli/agent.ts +45 -1
  110. package/src/cli/claude-agent-startup-sync.ts +73 -0
  111. package/src/cli/claude-desktop.ts +29 -4
  112. package/src/cli/claude.ts +103 -34
  113. package/src/cli/codex-log-guard-doctor.ts +103 -0
  114. package/src/cli/codex-shim-autorestore.ts +2 -0
  115. package/src/cli/codex-shim-readiness.ts +76 -0
  116. package/src/cli/combo.ts +8 -0
  117. package/src/cli/config-command.ts +74 -10
  118. package/src/cli/dispatch.ts +593 -0
  119. package/src/cli/doctor.ts +315 -43
  120. package/src/cli/ensure-desired-integrations.ts +152 -0
  121. package/src/cli/export-command.ts +46 -20
  122. package/src/cli/help.ts +20 -271
  123. package/src/cli/index.ts +378 -519
  124. package/src/cli/init.ts +4 -17
  125. package/src/cli/integrations.ts +120 -2
  126. package/src/cli/lab.ts +607 -0
  127. package/src/cli/launcher-context.ts +77 -0
  128. package/src/cli/minimax.ts +497 -0
  129. package/src/cli/models-runtime.ts +35 -2
  130. package/src/cli/models.ts +100 -14
  131. package/src/cli/observe.ts +92 -3
  132. package/src/cli/opencode.ts +4 -2
  133. package/src/cli/provider-runtime.ts +18 -1
  134. package/src/cli/provider.ts +24 -3
  135. package/src/cli/ready.ts +301 -0
  136. package/src/cli/registry.ts +437 -0
  137. package/src/cli/root.ts +86 -0
  138. package/src/cli/route-policy.ts +92 -0
  139. package/src/cli/runtime-api.ts +6 -3
  140. package/src/cli/star-prompt.ts +71 -15
  141. package/src/cli/status.ts +10 -3
  142. package/src/cli/system-restart-client.ts +146 -0
  143. package/src/cli/tray-proxy.ts +153 -6
  144. package/src/cli/v2.ts +105 -10
  145. package/src/cli.ts +1 -1
  146. package/src/clients/config-export.ts +1358 -21
  147. package/src/codex/account-label.ts +14 -1
  148. package/src/codex/account-lifecycle.ts +130 -13
  149. package/src/codex/account-namespaces.ts +49 -3
  150. package/src/codex/account-priority.ts +83 -0
  151. package/src/codex/account-store.ts +29 -2
  152. package/src/codex/account-usability.ts +25 -2
  153. package/src/codex/admission.ts +256 -0
  154. package/src/codex/affinity-debug.ts +162 -0
  155. package/src/codex/app-server-processes.ts +493 -106
  156. package/src/codex/app-server-restart-service.ts +232 -0
  157. package/src/codex/auth-api.ts +849 -242
  158. package/src/codex/auth-collision.ts +5 -3
  159. package/src/codex/auth-context.ts +345 -32
  160. package/src/codex/autostart-health.ts +8 -1
  161. package/src/codex/catalog/account-models.ts +67 -0
  162. package/src/codex/catalog/aggregation.ts +68 -10
  163. package/src/codex/catalog/bundled.ts +331 -33
  164. package/src/codex/catalog/effort.ts +121 -30
  165. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  166. package/src/codex/catalog/kinds.ts +2 -0
  167. package/src/codex/catalog/metadata.ts +529 -45
  168. package/src/codex/catalog/native-models.ts +72 -0
  169. package/src/codex/catalog/parsing.ts +224 -30
  170. package/src/codex/catalog/provider-fetch.ts +1460 -134
  171. package/src/codex/catalog/sync.ts +1449 -186
  172. package/src/codex/catalog-admission.ts +199 -0
  173. package/src/codex/catalog-refresh-status.ts +105 -0
  174. package/src/codex/catalog-write-serialization.ts +242 -0
  175. package/src/codex/catalog.ts +6 -3
  176. package/src/codex/codex-write-lock.ts +384 -0
  177. package/src/codex/convergence-types.ts +614 -0
  178. package/src/codex/convergence.ts +651 -0
  179. package/src/codex/coordinator-doctor.ts +332 -0
  180. package/src/codex/custom-model-catalog-migration.ts +176 -0
  181. package/src/codex/desired-state.ts +230 -0
  182. package/src/codex/features.ts +636 -39
  183. package/src/codex/generation.ts +202 -0
  184. package/src/codex/history-job.ts +407 -0
  185. package/src/codex/history-lock.ts +242 -0
  186. package/src/codex/history-migration-guardian.ts +26 -20
  187. package/src/codex/history-provider.ts +231 -28
  188. package/src/codex/history-transition.ts +105 -0
  189. package/src/codex/history-worker.ts +220 -0
  190. package/src/codex/inject-coordination.ts +290 -0
  191. package/src/codex/inject.ts +1073 -152
  192. package/src/codex/injected-marker.ts +37 -3
  193. package/src/codex/integration-record.ts +266 -0
  194. package/src/codex/internal/catalog-writer.ts +203 -0
  195. package/src/codex/internal/history-writer.ts +80 -0
  196. package/src/codex/journal.ts +66 -4
  197. package/src/codex/log-guard/inspect.ts +506 -0
  198. package/src/codex/log-guard/lock.ts +150 -0
  199. package/src/codex/log-guard/maintenance.ts +403 -0
  200. package/src/codex/log-guard/path-safety.ts +88 -0
  201. package/src/codex/log-guard/policy.ts +44 -0
  202. package/src/codex/log-guard/processes.ts +205 -0
  203. package/src/codex/log-guard/protection.ts +489 -0
  204. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  205. package/src/codex/main-account-cache.ts +24 -0
  206. package/src/codex/main-account.ts +29 -1
  207. package/src/codex/management-convergence.ts +167 -0
  208. package/src/codex/model-cache.ts +56 -10
  209. package/src/codex/model-entitlements.ts +353 -0
  210. package/src/codex/native-main-admission.ts +47 -0
  211. package/src/codex/native-main-auth-temp.ts +187 -0
  212. package/src/codex/native-main-claim.ts +178 -0
  213. package/src/codex/native-main-lock-file.ts +162 -0
  214. package/src/codex/native-main-owner.ts +329 -0
  215. package/src/codex/native-profile-api.ts +247 -0
  216. package/src/codex/native-profile-manager.ts +1531 -0
  217. package/src/codex/native-profile-processes.ts +121 -0
  218. package/src/codex/native-profile-recovery.ts +99 -0
  219. package/src/codex/native-profile-stage-store.ts +387 -0
  220. package/src/codex/native-profile-startup.ts +492 -0
  221. package/src/codex/native-profile-store.ts +855 -0
  222. package/src/codex/native-profile-types.ts +120 -0
  223. package/src/codex/native-residue.ts +682 -0
  224. package/src/codex/paths.ts +80 -1
  225. package/src/codex/plan-from-token.ts +140 -0
  226. package/src/codex/plan.ts +40 -0
  227. package/src/codex/plugins-doctor.ts +1 -1
  228. package/src/codex/pool-rotation.ts +74 -4
  229. package/src/codex/project-config-warnings.ts +20 -6
  230. package/src/codex/prompt-journal.ts +352 -0
  231. package/src/codex/prompt-layers.ts +967 -0
  232. package/src/codex/prompt-lock.ts +143 -0
  233. package/src/codex/quota-rejection.ts +298 -0
  234. package/src/codex/quota.ts +175 -13
  235. package/src/codex/refresh.ts +11 -2
  236. package/src/codex/reset-credit-recovery.ts +1044 -0
  237. package/src/codex/routing.ts +505 -94
  238. package/src/codex/runtime.ts +159 -38
  239. package/src/codex/shim.ts +1009 -28
  240. package/src/codex/subagent-model-fallback.ts +350 -35
  241. package/src/codex/sync.ts +191 -2
  242. package/src/codex/transition-state.ts +612 -0
  243. package/src/codex/upstream-host-health.ts +368 -0
  244. package/src/codex/user-identity.ts +557 -0
  245. package/src/codex/warmup.ts +187 -81
  246. package/src/codex/write-coordination.ts +114 -0
  247. package/src/combos/failover.ts +20 -0
  248. package/src/combos/index.ts +4 -0
  249. package/src/combos/request.ts +32 -0
  250. package/src/combos/types.ts +81 -9
  251. package/src/config/provider-name.ts +24 -0
  252. package/src/config.ts +1762 -140
  253. package/src/generated/compatibility-version.json +3164 -0
  254. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  255. package/src/grok/inject.ts +16 -5
  256. package/src/grok/inspect.ts +45 -0
  257. package/src/grok/sync.ts +2 -2
  258. package/src/images/loop.ts +152 -29
  259. package/src/images/plan.ts +23 -13
  260. package/src/integrations/config-io.ts +269 -0
  261. package/src/integrations/journal.ts +315 -0
  262. package/src/integrations/merge.ts +135 -0
  263. package/src/integrations/mutation-flight.ts +71 -0
  264. package/src/integrations/native/ownership-preflight.ts +202 -0
  265. package/src/integrations/omp-yaml-source.ts +358 -0
  266. package/src/integrations/owned-refresh.ts +74 -0
  267. package/src/integrations/ownership.ts +111 -0
  268. package/src/integrations/registry.ts +159 -0
  269. package/src/integrations/serialize.ts +314 -0
  270. package/src/integrations/state.ts +361 -0
  271. package/src/integrations/store.ts +103 -0
  272. package/src/integrations/writer-lock.ts +98 -0
  273. package/src/integrations/writer.ts +691 -0
  274. package/src/lab/artifacts/sanitize.ts +586 -0
  275. package/src/lab/artifacts/secure-fs.ts +475 -0
  276. package/src/lab/artifacts/store.ts +310 -0
  277. package/src/lab/automation/budgets.ts +78 -0
  278. package/src/lab/automation/config-persistence.ts +256 -0
  279. package/src/lab/automation/constants.ts +39 -0
  280. package/src/lab/automation/cooldown.ts +103 -0
  281. package/src/lab/automation/dispatch.ts +211 -0
  282. package/src/lab/automation/index.ts +13 -0
  283. package/src/lab/automation/orchestrator.ts +499 -0
  284. package/src/lab/automation/persistence.ts +512 -0
  285. package/src/lab/automation/planner.ts +371 -0
  286. package/src/lab/automation/policy.ts +136 -0
  287. package/src/lab/automation/queue.ts +191 -0
  288. package/src/lab/automation/recovery.ts +24 -0
  289. package/src/lab/automation/route-context.ts +21 -0
  290. package/src/lab/automation/run-key.ts +44 -0
  291. package/src/lab/automation/runs-query.ts +34 -0
  292. package/src/lab/automation/types.ts +160 -0
  293. package/src/lab/conformance/assertion.ts +325 -0
  294. package/src/lab/conformance/digest.ts +22 -0
  295. package/src/lab/conformance/executor.ts +741 -0
  296. package/src/lab/conformance/fixture-provider.ts +27 -0
  297. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  298. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  299. package/src/lab/conformance/harness-budget.ts +47 -0
  300. package/src/lab/conformance/index.ts +5 -0
  301. package/src/lab/conformance/jcs.ts +64 -0
  302. package/src/lab/conformance/json-pointer.ts +39 -0
  303. package/src/lab/conformance/manifest.ts +180 -0
  304. package/src/lab/conformance/mcp-stub.ts +179 -0
  305. package/src/lab/conformance/negative-controls.ts +164 -0
  306. package/src/lab/conformance/observation.ts +355 -0
  307. package/src/lab/conformance/runner.ts +68 -0
  308. package/src/lab/conformance/sse-normalize.ts +59 -0
  309. package/src/lab/conformance/suite-manifest.ts +78 -0
  310. package/src/lab/conformance/types.ts +214 -0
  311. package/src/lab/constants.ts +126 -0
  312. package/src/lab/digest.ts +64 -0
  313. package/src/lab/events/errors.ts +9 -0
  314. package/src/lab/events/limits.ts +117 -0
  315. package/src/lab/events/types.ts +229 -0
  316. package/src/lab/events/validate.ts +781 -0
  317. package/src/lab/fabric/constants.ts +40 -0
  318. package/src/lab/fabric/executor.ts +492 -0
  319. package/src/lab/fabric/index.ts +80 -0
  320. package/src/lab/fabric/manifest.ts +222 -0
  321. package/src/lab/fabric/observe.ts +489 -0
  322. package/src/lab/fabric/patch.ts +79 -0
  323. package/src/lab/fabric/producer-child.ts +139 -0
  324. package/src/lab/fabric/producer-isolate.ts +276 -0
  325. package/src/lab/fabric/producer-protocol.ts +61 -0
  326. package/src/lab/fabric/scratch.ts +439 -0
  327. package/src/lab/fabric/subject.ts +106 -0
  328. package/src/lab/fabric/types.ts +134 -0
  329. package/src/lab/fabric/verifier.ts +98 -0
  330. package/src/lab/index.ts +54 -0
  331. package/src/lab/ledger/artifact-refs.ts +127 -0
  332. package/src/lab/ledger/invalidation.ts +136 -0
  333. package/src/lab/ledger/purge.ts +310 -0
  334. package/src/lab/ledger/store.ts +532 -0
  335. package/src/lab/live/credential-lease.ts +53 -0
  336. package/src/lab/live/destination.ts +155 -0
  337. package/src/lab/live/executor.ts +336 -0
  338. package/src/lab/live/inert-tools.ts +56 -0
  339. package/src/lab/live/manifest.ts +85 -0
  340. package/src/lab/live/mcp-loopback.ts +57 -0
  341. package/src/lab/live/runner.ts +19 -0
  342. package/src/lab/live/sandbox.ts +61 -0
  343. package/src/lab/live/suite-manifest.ts +41 -0
  344. package/src/lab/live/transport.ts +118 -0
  345. package/src/lab/live/types.ts +197 -0
  346. package/src/lab/observe/from-conformance.ts +301 -0
  347. package/src/lab/observe/from-live.ts +117 -0
  348. package/src/lab/paths.ts +153 -0
  349. package/src/lab/projection/rebuild.ts +495 -0
  350. package/src/lab/projection/schema.ts +135 -0
  351. package/src/lab/projection/verdicts.ts +474 -0
  352. package/src/lab/projection/verification.ts +412 -0
  353. package/src/lab/public/bundle.ts +217 -0
  354. package/src/lab/public/community-authority.ts +175 -0
  355. package/src/lab/public/community-files.ts +29 -0
  356. package/src/lab/public/community.ts +479 -0
  357. package/src/lab/public/file-safety.ts +155 -0
  358. package/src/lab/public/ids.ts +26 -0
  359. package/src/lab/public/index.ts +16 -0
  360. package/src/lab/public/mutation-lock.ts +424 -0
  361. package/src/lab/public/operator.ts +353 -0
  362. package/src/lab/public/origin-purge.ts +79 -0
  363. package/src/lab/public/origin.ts +203 -0
  364. package/src/lab/public/privacy.ts +143 -0
  365. package/src/lab/public/private-file.ts +261 -0
  366. package/src/lab/public/project.ts +124 -0
  367. package/src/lab/public/purge-test-fault.ts +21 -0
  368. package/src/lab/public/purge.ts +223 -0
  369. package/src/lab/public/registry.ts +44 -0
  370. package/src/lab/public/revocation.ts +252 -0
  371. package/src/lab/public/signature.ts +243 -0
  372. package/src/lab/public/storage.ts +105 -0
  373. package/src/lab/public/strict-json.ts +206 -0
  374. package/src/lab/public/time.ts +26 -0
  375. package/src/lab/public/types.ts +172 -0
  376. package/src/lab/public/validate.ts +391 -0
  377. package/src/lab/query/catalog.ts +101 -0
  378. package/src/lab/query/connection.ts +107 -0
  379. package/src/lab/query/constants.ts +4 -0
  380. package/src/lab/query/cursor.ts +132 -0
  381. package/src/lab/query/dto-map.ts +277 -0
  382. package/src/lab/query/errors.ts +22 -0
  383. package/src/lab/query/freshness.ts +53 -0
  384. package/src/lab/query/index.ts +45 -0
  385. package/src/lab/query/latest-observation.ts +59 -0
  386. package/src/lab/query/passive-production.ts +159 -0
  387. package/src/lab/query/queries.ts +444 -0
  388. package/src/lab/query/types.ts +266 -0
  389. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  390. package/src/lab/subject/installation-salt.ts +112 -0
  391. package/src/lab/subject/protocol-subject.ts +80 -0
  392. package/src/lab/subject/route-subject.ts +74 -0
  393. package/src/lib/app-owned-memory-stores.ts +22 -0
  394. package/src/lib/bounded-body.ts +153 -9
  395. package/src/lib/bun-runtime.ts +125 -12
  396. package/src/lib/bun-stream-caps.ts +13 -9
  397. package/src/lib/codex-restart-contract.ts +120 -0
  398. package/src/lib/config-ownership.ts +6 -2
  399. package/src/lib/destination-policy.ts +65 -1
  400. package/src/lib/errors.ts +44 -2
  401. package/src/lib/fabric-task-execution-authority.ts +7 -0
  402. package/src/lib/fabric-task-host.ts +29 -0
  403. package/src/lib/lab-activation.ts +223 -0
  404. package/src/lib/lab-live-execution-authority.ts +13 -0
  405. package/src/lib/lab-live-host.ts +30 -0
  406. package/src/lib/lab-live-pinned-sender.ts +56 -0
  407. package/src/lib/lab-live-route-production.ts +130 -0
  408. package/src/lib/lab-passive-linker-registration.ts +26 -0
  409. package/src/lib/local-management-attestation.ts +51 -0
  410. package/src/lib/local-management-capability.ts +100 -0
  411. package/src/lib/local-provider-reload-contract.ts +100 -0
  412. package/src/lib/optional-shutdown-hooks.ts +57 -0
  413. package/src/lib/pinned-http.ts +145 -26
  414. package/src/lib/process-control.ts +4 -1
  415. package/src/lib/provider-outbound.ts +49 -9
  416. package/src/lib/redact.ts +419 -3
  417. package/src/lib/self-launch-argv.ts +15 -0
  418. package/src/lib/server-resource-ownership.ts +71 -0
  419. package/src/lib/shadow-call.ts +35 -4
  420. package/src/lib/sse-decoder.ts +41 -0
  421. package/src/lib/state-store-registrations.ts +10 -2
  422. package/src/lib/system-restart-contract.ts +73 -0
  423. package/src/lib/token-estimate.ts +19 -2
  424. package/src/lib/tool-argument-integers.ts +202 -0
  425. package/src/lib/translator-budget.ts +44 -0
  426. package/src/lib/upstream-http-version.ts +57 -0
  427. package/src/lib/upstream-reachability.ts +95 -0
  428. package/src/lib/upstream-retry.ts +156 -3
  429. package/src/lib/windows-atomic-replace.ts +155 -0
  430. package/src/lib/windows-elevation.ts +70 -2
  431. package/src/lib/windows-secret-acl.ts +409 -69
  432. package/src/lib/windows-service-wrappers.ts +72 -0
  433. package/src/lib/windows-text.ts +106 -0
  434. package/src/lib/windows-user-principal.ts +341 -0
  435. package/src/lib/winsw.ts +33 -5
  436. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  437. package/src/oauth/account-import/index.ts +15 -0
  438. package/src/oauth/account-import/parser.ts +83 -0
  439. package/src/oauth/account-import/registry.ts +18 -0
  440. package/src/oauth/account-import/service.ts +75 -0
  441. package/src/oauth/account-import/types.ts +91 -0
  442. package/src/oauth/anthropic.ts +12 -1
  443. package/src/oauth/callback-server.ts +8 -2
  444. package/src/oauth/chatgpt.ts +12 -1
  445. package/src/oauth/command-code.ts +239 -0
  446. package/src/oauth/cursor.ts +46 -5
  447. package/src/oauth/google-antigravity.ts +35 -3
  448. package/src/oauth/health.ts +20 -12
  449. package/src/oauth/index.ts +398 -66
  450. package/src/oauth/key-providers.ts +16 -0
  451. package/src/oauth/kimi.ts +16 -2
  452. package/src/oauth/kiro.ts +50 -6
  453. package/src/oauth/local-token-detect.ts +11 -2
  454. package/src/oauth/log.ts +3 -1
  455. package/src/oauth/login-cli.ts +88 -28
  456. package/src/oauth/nous.ts +798 -0
  457. package/src/oauth/store.ts +119 -21
  458. package/src/oauth/token-guardian.ts +9 -3
  459. package/src/pi/models.ts +2 -2
  460. package/src/providers/alibaba-region-migration.ts +1 -1
  461. package/src/providers/antigravity-models.ts +521 -31
  462. package/src/providers/base-url-choices.ts +10 -0
  463. package/src/providers/codex-capacity.ts +292 -0
  464. package/src/providers/command-code-efforts.ts +144 -0
  465. package/src/providers/context-cap.ts +22 -5
  466. package/src/providers/cursor-pool.ts +72 -0
  467. package/src/providers/derive.ts +253 -6
  468. package/src/providers/fastwire.ts +501 -0
  469. package/src/providers/free-directory.ts +10 -7
  470. package/src/providers/google-vertex-location.ts +14 -0
  471. package/src/providers/key-failover.ts +71 -3
  472. package/src/providers/label.ts +1 -1
  473. package/src/providers/model-discovery-limits.ts +16 -0
  474. package/src/providers/model-discovery.ts +115 -22
  475. package/src/providers/model-rename-migration.ts +255 -0
  476. package/src/providers/model-rename-startup.ts +28 -0
  477. package/src/providers/openai-sidecar.ts +72 -4
  478. package/src/providers/openai-tier-startup.ts +31 -2
  479. package/src/providers/openai-tiers.ts +119 -4
  480. package/src/providers/openai-virtual-models.ts +1 -0
  481. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  482. package/src/providers/provider-id-rewrite.ts +29 -0
  483. package/src/providers/quota.ts +1319 -38
  484. package/src/providers/registry.ts +1429 -111
  485. package/src/providers/request-pacing.ts +310 -0
  486. package/src/providers/service-tier.ts +277 -0
  487. package/src/providers/slug-codec.ts +42 -6
  488. package/src/providers/static-model-discovery.ts +86 -0
  489. package/src/providers/xai-responses-opt-in.ts +15 -0
  490. package/src/providers/xai-transport.ts +11 -4
  491. package/src/reasoning-effort.ts +49 -1
  492. package/src/responses/compaction.ts +26 -1
  493. package/src/responses/custom-tool-compat.ts +266 -0
  494. package/src/responses/hosted-tool-policy.ts +9 -0
  495. package/src/responses/namespace-tool-compat.ts +355 -0
  496. package/src/responses/parser.ts +220 -38
  497. package/src/responses/provider-continuation.ts +98 -0
  498. package/src/responses/provider-opaque-metadata.ts +73 -0
  499. package/src/responses/reasoning-envelope.ts +9 -1
  500. package/src/responses/reasoning-replay-cache.ts +426 -0
  501. package/src/responses/schema.ts +7 -1
  502. package/src/responses/spill-store.ts +75 -10
  503. package/src/responses/state.ts +565 -27
  504. package/src/responses/thought-signature-replay.ts +347 -0
  505. package/src/responses/tool-search-compat.ts +301 -0
  506. package/src/responses/truncated-stop-reason.ts +60 -0
  507. package/src/router.ts +366 -30
  508. package/src/routing/analytics.ts +378 -0
  509. package/src/routing/capability.ts +244 -0
  510. package/src/routing/compatibility/assemble.ts +73 -0
  511. package/src/routing/compatibility/behavior.ts +278 -0
  512. package/src/routing/compatibility/catalog.ts +99 -0
  513. package/src/routing/compatibility/endpoint.ts +52 -0
  514. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  515. package/src/routing/compatibility/policy.ts +181 -0
  516. package/src/routing/compatibility/provider-slot.ts +56 -0
  517. package/src/routing/compatibility/reader.ts +110 -0
  518. package/src/routing/compatibility/subject.ts +191 -0
  519. package/src/routing/compatibility/types.ts +64 -0
  520. package/src/routing/compatibility/version.ts +104 -0
  521. package/src/routing/cost.ts +77 -0
  522. package/src/routing/evaluator.ts +495 -0
  523. package/src/routing/health.ts +412 -0
  524. package/src/routing/history/cursor.ts +43 -0
  525. package/src/routing/history/indexer.ts +605 -0
  526. package/src/routing/history/schema.ts +72 -0
  527. package/src/routing/profile-namespace.ts +15 -0
  528. package/src/routing/profile.ts +547 -0
  529. package/src/routing/quota.ts +145 -0
  530. package/src/routing/request-evidence.ts +45 -0
  531. package/src/routing/trace.ts +776 -0
  532. package/src/server/adapter-resolve.ts +2 -29
  533. package/src/server/auth-cors.ts +267 -46
  534. package/src/server/background-lifecycle.ts +182 -0
  535. package/src/server/chat-completions.ts +130 -56
  536. package/src/server/chat-native-sse.ts +331 -0
  537. package/src/server/chat-native.ts +426 -0
  538. package/src/server/claude-messages.ts +159 -43
  539. package/src/server/direct-local-http.ts +347 -0
  540. package/src/server/effort-policy.ts +18 -0
  541. package/src/server/github-copilot-responses-repair.ts +338 -0
  542. package/src/server/gui-static.ts +39 -10
  543. package/src/server/images.ts +94 -12
  544. package/src/server/index.ts +865 -181
  545. package/src/server/lifecycle.ts +284 -13
  546. package/src/server/live.ts +136 -17
  547. package/src/server/local-management-read-client.ts +90 -0
  548. package/src/server/local-provider-reload-client.ts +137 -0
  549. package/src/server/management/agent-settings-routes.ts +398 -103
  550. package/src/server/management/api-key-usage.ts +31 -5
  551. package/src/server/management/body.ts +6 -0
  552. package/src/server/management/combo-routes.ts +62 -24
  553. package/src/server/management/config-routes.ts +464 -51
  554. package/src/server/management/context.ts +80 -2
  555. package/src/server/management/integration-routes.ts +498 -0
  556. package/src/server/management/lab-automation-routes.ts +206 -0
  557. package/src/server/management/lab-routes.ts +563 -0
  558. package/src/server/management/logs-usage-routes.ts +101 -32
  559. package/src/server/management/model-routes.ts +189 -131
  560. package/src/server/management/model-rows.ts +163 -0
  561. package/src/server/management/native-integration-routes.ts +769 -0
  562. package/src/server/management/oauth-account-routes.ts +80 -4
  563. package/src/server/management/provider-capability-config.ts +48 -0
  564. package/src/server/management/provider-routes.ts +764 -157
  565. package/src/server/management/request-history-routes.ts +191 -0
  566. package/src/server/management/routing-analytics-routes.ts +74 -0
  567. package/src/server/management/routing-profile-routes.ts +380 -0
  568. package/src/server/management/shared.ts +27 -11
  569. package/src/server/management/sidebar-routes.ts +47 -31
  570. package/src/server/management/storage-log-guard-routes.ts +186 -0
  571. package/src/server/management/sync-response.ts +69 -0
  572. package/src/server/management/system-restart.ts +288 -32
  573. package/src/server/management/system-routes.ts +77 -0
  574. package/src/server/management/usage-summary-cache.ts +9 -1
  575. package/src/server/management/vision-sidecar-options.ts +167 -0
  576. package/src/server/management/web-search-sidecar-options.ts +120 -0
  577. package/src/server/management-api.ts +115 -14
  578. package/src/server/management-auth.ts +220 -5
  579. package/src/server/passive-route-linker.ts +66 -0
  580. package/src/server/ports.ts +41 -1
  581. package/src/server/proxy-liveness.ts +132 -5
  582. package/src/server/readiness.ts +99 -0
  583. package/src/server/relay-eager.ts +82 -42
  584. package/src/server/relay.ts +236 -76
  585. package/src/server/request-decompress.ts +113 -6
  586. package/src/server/request-log.ts +235 -22
  587. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  588. package/src/server/responses/agent-task-recovery.ts +465 -0
  589. package/src/server/responses/collaboration.ts +204 -35
  590. package/src/server/responses/compact.ts +442 -55
  591. package/src/server/responses/core.ts +2872 -331
  592. package/src/server/responses/empty-completion-guard.ts +276 -0
  593. package/src/server/responses/encrypted-payload.ts +62 -39
  594. package/src/server/responses/fetch-helpers.ts +79 -4
  595. package/src/server/responses/input-admission.ts +185 -0
  596. package/src/server/responses/pacing-overload.ts +13 -0
  597. package/src/server/responses/policy-fallback.ts +178 -0
  598. package/src/server/responses/responses-field-backfill.ts +251 -0
  599. package/src/server/responses/terminal-guard.ts +26 -5
  600. package/src/server/responses/upstream-error.ts +5 -0
  601. package/src/server/responses/ws-upstream.ts +308 -0
  602. package/src/server/responses-custom-tool-repair.ts +282 -0
  603. package/src/server/responses-item-id-repair.ts +54 -6
  604. package/src/server/responses-json-events.ts +90 -0
  605. package/src/server/responses-model-rewrite.ts +29 -0
  606. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  607. package/src/server/responses-snapshot-repair.ts +621 -0
  608. package/src/server/responses-terminal-repair.ts +342 -0
  609. package/src/server/responses-tool-search-repair.ts +267 -0
  610. package/src/server/responses-undeclared-tool-guard.ts +153 -0
  611. package/src/server/responses.ts +18 -2
  612. package/src/server/search.ts +78 -13
  613. package/src/server/sse-frame-buffer.ts +292 -0
  614. package/src/server/sse-payload-rewrite.ts +110 -22
  615. package/src/server/startup-action-control.ts +8 -1
  616. package/src/server/startup-health-cache.ts +19 -1
  617. package/src/server/system-env.ts +80 -9
  618. package/src/server/ws-bridge.ts +39 -38
  619. package/src/service-manager-probe.ts +892 -0
  620. package/src/service.ts +1111 -90
  621. package/src/sidecar/auth.ts +92 -0
  622. package/src/sidecar/candidates.ts +83 -0
  623. package/src/storage/cleanup.ts +2 -2
  624. package/src/storage/scanner.ts +1 -1
  625. package/src/storage/worker-lifecycle.ts +14 -14
  626. package/src/tray/windows-tray.ps1 +83 -9
  627. package/src/tray/windows.ts +43 -16
  628. package/src/types/accounts.ts +37 -0
  629. package/src/types/config.ts +845 -0
  630. package/src/types/provider.ts +545 -0
  631. package/src/types/request.ts +384 -0
  632. package/src/types/tools.ts +131 -0
  633. package/src/types/wire.ts +80 -0
  634. package/src/types.ts +104 -1236
  635. package/src/update/index.ts +32 -19
  636. package/src/update/job.ts +442 -67
  637. package/src/update/notify.ts +12 -6
  638. package/src/update/npm-cache-preflight.d.mts +47 -0
  639. package/src/update/npm-cache-preflight.mjs +201 -0
  640. package/src/update/transactional-install.d.mts +22 -0
  641. package/src/update/transactional-install.mjs +259 -0
  642. package/src/usage/cost.ts +0 -0
  643. package/src/usage/expected-prices.ts +268 -16
  644. package/src/usage/log.ts +606 -41
  645. package/src/usage/summary.ts +177 -9
  646. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  647. package/src/usage/user-cost-overlays.ts +314 -0
  648. package/src/vision/anthropic-describe.ts +10 -6
  649. package/src/vision/backends.ts +97 -0
  650. package/src/vision/describe.ts +9 -3
  651. package/src/vision/eligibility.ts +250 -0
  652. package/src/vision/index.ts +238 -24
  653. package/src/vision/reasoning.ts +55 -0
  654. package/src/vision/routed-describe.ts +175 -0
  655. package/src/vision/timeout-bounds.ts +9 -0
  656. package/src/web-search/anthropic-executor.ts +13 -7
  657. package/src/web-search/backends.ts +108 -0
  658. package/src/web-search/exa-executor.ts +88 -0
  659. package/src/web-search/executor.ts +11 -3
  660. package/src/web-search/gemini-executor.ts +141 -0
  661. package/src/web-search/index.ts +150 -15
  662. package/src/web-search/loop.ts +279 -50
  663. package/src/web-search/parse.ts +125 -30
  664. package/src/web-search/sources.ts +60 -0
  665. package/src/web-search/xai-executor.ts +219 -0
  666. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  667. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  668. package/gui/dist/provider-icons/antigravity.svg +0 -1
  669. package/gui/dist/provider-icons/claude.svg +0 -1
  670. package/gui/dist/provider-icons/copilot.svg +0 -1
  671. package/gui/dist/provider-icons/cursor.svg +0 -2
  672. package/gui/dist/provider-icons/gemini.svg +0 -1
  673. package/gui/dist/provider-icons/grok-color.svg +0 -1
  674. package/gui/dist/provider-icons/kiro.svg +0 -14
  675. package/src/cli/internal-dispatch.ts +0 -20
@@ -0,0 +1,303 @@
1
+ import { createHash } from "node:crypto";
2
+ import { fromBinary } from "@bufbuild/protobuf";
3
+ import { ConversationStateStructureSchema, type ConversationStateStructure } from "./gen/agent_pb";
4
+ import {
5
+ createCursorBlobCheckpointLease,
6
+ pinCursorBlobIdsForCheckpoint,
7
+ releaseCursorBlobRequestScope,
8
+ type CursorBlobRequestScopeToken,
9
+ } from "./native-exec";
10
+
11
+ export const CURSOR_CHECKPOINT_TTL_MS = 15 * 60_000;
12
+ export const CURSOR_CHECKPOINT_MAX_ENTRIES = 64;
13
+ export const CURSOR_CHECKPOINT_MAX_TOTAL_BYTES = 16 * 1024 * 1024;
14
+
15
+ export type CursorCheckpointInvalidationReason =
16
+ | "missing_ref"
17
+ | "expired"
18
+ | "decode_failed"
19
+ | "conversation_changed"
20
+ | "identity_changed"
21
+ | "model_changed"
22
+ | "compaction"
23
+ | "trailing_tool_result"
24
+ | "force_fresh"
25
+ | "upstream_invalid_argument"
26
+ | "lineage_mismatch";
27
+
28
+ export interface CursorCheckpointSnapshot {
29
+ ref: string;
30
+ conversationId: string;
31
+ identityScope: string;
32
+ modelId: string;
33
+ checkpointBytes: Uint8Array;
34
+ createdAt: number;
35
+ lastAccessAt: number;
36
+ blobLease?: CursorBlobRequestScopeToken;
37
+ coveredMessageCount?: number;
38
+ prefixDigest?: string;
39
+ systemDigest?: string;
40
+ }
41
+
42
+ interface CursorCheckpointStore {
43
+ snapshots: Map<string, CursorCheckpointSnapshot>;
44
+ prefixIndex: Map<string, Set<string>>;
45
+ totalBytes: number;
46
+ }
47
+
48
+ const store: CursorCheckpointStore = {
49
+ snapshots: new Map(),
50
+ prefixIndex: new Map(),
51
+ totalBytes: 0,
52
+ };
53
+
54
+ let nowFn = (): number => Date.now();
55
+ let scheduleFn = (fn: () => void, ms: number): ReturnType<typeof setTimeout> => {
56
+ const timer = setTimeout(fn, ms);
57
+ timer.unref?.();
58
+ return timer;
59
+ };
60
+ let clearScheduleFn = (timer: ReturnType<typeof setTimeout>): void => {
61
+ clearTimeout(timer);
62
+ };
63
+ let pruneTimer: ReturnType<typeof setTimeout> | undefined;
64
+
65
+ function now(): number {
66
+ return nowFn();
67
+ }
68
+
69
+ export function installCursorCheckpointClockForTests(input: {
70
+ now?: () => number;
71
+ schedule?: (fn: () => void, ms: number) => ReturnType<typeof setTimeout>;
72
+ clear?: (timer: ReturnType<typeof setTimeout>) => void;
73
+ }): void {
74
+ if (input.now) nowFn = input.now;
75
+ if (input.schedule) scheduleFn = input.schedule;
76
+ if (input.clear) clearScheduleFn = input.clear;
77
+ }
78
+
79
+ export function resetCursorCheckpointClockForTests(): void {
80
+ nowFn = () => Date.now();
81
+ scheduleFn = (fn, ms) => {
82
+ const timer = setTimeout(fn, ms);
83
+ timer.unref?.();
84
+ return timer;
85
+ };
86
+ clearScheduleFn = timer => {
87
+ clearTimeout(timer);
88
+ };
89
+ stopPruneTimer();
90
+ }
91
+
92
+ function stopPruneTimer(): void {
93
+ if (pruneTimer !== undefined) clearScheduleFn(pruneTimer);
94
+ pruneTimer = undefined;
95
+ }
96
+
97
+ function schedulePrune(at = now()): void {
98
+ stopPruneTimer();
99
+ let nextExpiry = Number.POSITIVE_INFINITY;
100
+ for (const snapshot of store.snapshots.values()) {
101
+ nextExpiry = Math.min(nextExpiry, snapshot.lastAccessAt + CURSOR_CHECKPOINT_TTL_MS);
102
+ }
103
+ if (!Number.isFinite(nextExpiry)) return;
104
+ pruneTimer = scheduleFn(() => {
105
+ pruneTimer = undefined;
106
+ prune();
107
+ schedulePrune();
108
+ }, Math.max(0, nextExpiry - at));
109
+ }
110
+
111
+ function prune(at = now()): void {
112
+ for (const [ref, snapshot] of store.snapshots) {
113
+ if (at - snapshot.lastAccessAt > CURSOR_CHECKPOINT_TTL_MS) deleteSnapshot(ref);
114
+ }
115
+ while (store.snapshots.size > CURSOR_CHECKPOINT_MAX_ENTRIES || store.totalBytes > CURSOR_CHECKPOINT_MAX_TOTAL_BYTES) {
116
+ const oldest = store.snapshots.keys().next().value;
117
+ if (oldest === undefined) break;
118
+ deleteSnapshot(oldest);
119
+ }
120
+ schedulePrune(at);
121
+ }
122
+
123
+ function indexPrefix(digest: string | undefined, ref: string): void {
124
+ if (!digest) return;
125
+ const refs = store.prefixIndex.get(digest) ?? new Set<string>();
126
+ refs.add(ref);
127
+ store.prefixIndex.set(digest, refs);
128
+ }
129
+
130
+ function unindexPrefix(digest: string | undefined, ref: string): void {
131
+ if (!digest) return;
132
+ const refs = store.prefixIndex.get(digest);
133
+ if (!refs) return;
134
+ refs.delete(ref);
135
+ if (refs.size === 0) store.prefixIndex.delete(digest);
136
+ }
137
+
138
+ function deleteSnapshot(ref: string): void {
139
+ const existing = store.snapshots.get(ref);
140
+ if (!existing) return;
141
+ if (existing.blobLease) releaseCursorBlobRequestScope(existing.blobLease);
142
+ unindexPrefix(existing.prefixDigest, ref);
143
+ store.snapshots.delete(ref);
144
+ store.totalBytes = Math.max(0, store.totalBytes - existing.checkpointBytes.byteLength);
145
+ }
146
+
147
+ function collectStateBlobIds(state: ConversationStateStructure, ids: Uint8Array[]): void {
148
+ ids.push(
149
+ ...state.rootPromptMessagesJson,
150
+ ...state.turns,
151
+ ...state.turnsOld,
152
+ ...state.todos,
153
+ ...state.summaryArchives,
154
+ );
155
+ if (state.summary) ids.push(state.summary);
156
+ if (state.summaryArchive) ids.push(state.summaryArchive);
157
+ if (state.plan) ids.push(state.plan);
158
+ for (const value of Object.values(state.fileStates)) ids.push(value);
159
+ for (const value of Object.values(state.fileStatesV2)) {
160
+ if (value.content) ids.push(value.content);
161
+ if (value.initialContent) ids.push(value.initialContent);
162
+ }
163
+ for (const nested of Object.values(state.subagentStates)) {
164
+ if (nested.conversationState) collectStateBlobIds(nested.conversationState, ids);
165
+ }
166
+ }
167
+
168
+ function collectCheckpointBlobIds(checkpointBytes: Uint8Array): Uint8Array[] | undefined {
169
+ try {
170
+ const ids: Uint8Array[] = [];
171
+ collectStateBlobIds(fromBinary(ConversationStateStructureSchema, checkpointBytes), ids);
172
+ return ids.filter(id => id.byteLength > 0);
173
+ } catch {
174
+ return undefined;
175
+ }
176
+ }
177
+
178
+ export function cursorCheckpointRefHash(ref: string): string {
179
+ return createHash("sha256").update("ocx:cursor:ckpt-ref:").update(ref).digest("hex").slice(0, 16);
180
+ }
181
+
182
+ export function commitCursorCheckpoint(input: {
183
+ conversationId: string;
184
+ identityScope?: string;
185
+ modelId: string;
186
+ checkpointBytes: Uint8Array;
187
+ coveredMessageCount?: number;
188
+ prefixDigest?: string;
189
+ systemDigest?: string;
190
+ }): string | undefined {
191
+ if (!input.conversationId || !input.modelId || input.checkpointBytes.byteLength === 0) return undefined;
192
+ if (input.checkpointBytes.byteLength > CURSOR_CHECKPOINT_MAX_TOTAL_BYTES) return undefined;
193
+ prune();
194
+ const createdAt = now();
195
+ const ref = createHash("sha256")
196
+ .update("ocx:cursor:ckpt:")
197
+ .update(input.conversationId)
198
+ .update("|")
199
+ .update(input.identityScope?.trim() || "local")
200
+ .update("|")
201
+ .update(input.modelId)
202
+ .update("|")
203
+ .update(String(createdAt))
204
+ .update("|")
205
+ .update(input.checkpointBytes)
206
+ .digest("hex")
207
+ .slice(0, 32);
208
+ const snapshot: CursorCheckpointSnapshot = {
209
+ ref,
210
+ conversationId: input.conversationId,
211
+ identityScope: input.identityScope?.trim() || "local",
212
+ modelId: input.modelId,
213
+ checkpointBytes: input.checkpointBytes.slice(),
214
+ createdAt,
215
+ lastAccessAt: createdAt,
216
+ ...(input.coveredMessageCount !== undefined ? { coveredMessageCount: input.coveredMessageCount } : {}),
217
+ ...(input.prefixDigest ? { prefixDigest: input.prefixDigest } : {}),
218
+ ...(input.systemDigest ? { systemDigest: input.systemDigest } : {}),
219
+ };
220
+ const blobIds = collectCheckpointBlobIds(input.checkpointBytes);
221
+ if (blobIds === undefined) return undefined;
222
+ if (blobIds.length > 0) {
223
+ const lease = createCursorBlobCheckpointLease(ref);
224
+ if (!pinCursorBlobIdsForCheckpoint(blobIds, lease)) {
225
+ releaseCursorBlobRequestScope(lease);
226
+ return undefined;
227
+ }
228
+ snapshot.blobLease = lease;
229
+ }
230
+ deleteSnapshot(ref);
231
+ store.snapshots.set(ref, snapshot);
232
+ store.totalBytes += snapshot.checkpointBytes.byteLength;
233
+ indexPrefix(snapshot.prefixDigest, ref);
234
+ prune(createdAt);
235
+ return store.snapshots.has(ref) ? ref : undefined;
236
+ }
237
+
238
+ export function getCursorCheckpointForPrefix(input: {
239
+ prefixDigest: string;
240
+ systemDigest: string;
241
+ coveredMessageCount: number;
242
+ identityScope?: string;
243
+ modelId: string;
244
+ }): CursorCheckpointSnapshot | undefined {
245
+ prune();
246
+ const refs = store.prefixIndex.get(input.prefixDigest);
247
+ if (!refs || refs.size !== 1) return undefined;
248
+ const [ref] = refs;
249
+ if (!ref) return undefined;
250
+ const snapshot = getCursorCheckpoint(ref);
251
+ if (!snapshot) return undefined;
252
+ const identityScope = input.identityScope?.trim() || "local";
253
+ if (snapshot.systemDigest !== input.systemDigest) return undefined;
254
+ if (snapshot.coveredMessageCount !== input.coveredMessageCount) return undefined;
255
+ if (snapshot.identityScope !== identityScope) return undefined;
256
+ if (snapshot.modelId !== input.modelId) return undefined;
257
+ return snapshot;
258
+ }
259
+
260
+ export function getLatestCursorCheckpoint(
261
+ match: (snapshot: CursorCheckpointSnapshot) => boolean,
262
+ ): CursorCheckpointSnapshot | undefined {
263
+ prune();
264
+ let found: CursorCheckpointSnapshot | undefined;
265
+ for (const snapshot of store.snapshots.values()) {
266
+ if (match(snapshot)) found = snapshot;
267
+ }
268
+ return found ? getCursorCheckpoint(found.ref) : undefined;
269
+ }
270
+
271
+ export function getCursorCheckpoint(ref: string | undefined): CursorCheckpointSnapshot | undefined {
272
+ if (!ref) return undefined;
273
+ prune();
274
+ const snapshot = store.snapshots.get(ref);
275
+ if (!snapshot) return undefined;
276
+ const at = now();
277
+ if (at - snapshot.lastAccessAt > CURSOR_CHECKPOINT_TTL_MS) {
278
+ deleteSnapshot(ref);
279
+ return undefined;
280
+ }
281
+ snapshot.lastAccessAt = at;
282
+ store.snapshots.delete(ref);
283
+ store.snapshots.set(ref, snapshot);
284
+ return snapshot;
285
+ }
286
+
287
+ export function invalidateCursorCheckpoint(ref: string | undefined): void {
288
+ if (!ref) return;
289
+ deleteSnapshot(ref);
290
+ }
291
+
292
+ export function clearCursorCheckpointsForTests(): void {
293
+ stopPruneTimer();
294
+ for (const ref of [...store.snapshots.keys()]) deleteSnapshot(ref);
295
+ store.snapshots.clear();
296
+ store.prefixIndex.clear();
297
+ store.totalBytes = 0;
298
+ resetCursorCheckpointClockForTests();
299
+ }
300
+
301
+ export function cursorCheckpointStoreMetricsForTests(): { count: number; totalBytes: number } {
302
+ return { count: store.snapshots.size, totalBytes: store.totalBytes };
303
+ }
@@ -27,7 +27,56 @@ function errorCode(value: unknown): string {
27
27
  * True when Cursor intentionally cancelled the HTTP/2 stream after a client-tool suspend.
28
28
  * These are expected between multi-turn Responses bridge cycles, not upstream failures.
29
29
  */
30
+ /**
31
+ * A Cursor stream that ended cleanly at the HTTP/2 layer while a client tool call was still
32
+ * open — no `turnEnded`, no error trailer, just EOF. The call's buffered arguments are lost,
33
+ * so the turn is truncated: reporting it as success would hand Codex a turn whose tool call
34
+ * silently never happened. Not retryable — the request is committed once the session connects.
35
+ */
36
+ export class CursorStreamTruncatedError extends Error {
37
+ constructor(
38
+ public readonly openCallIds: readonly string[],
39
+ public readonly framesReceived: number,
40
+ ) {
41
+ super(
42
+ `Cursor stream ended without terminating the turn; ${openCallIds.length} tool call(s) left incomplete `
43
+ + `(${openCallIds.join(", ")}) after ${framesReceived} frame(s). Arguments may be truncated; the call was not committed.`,
44
+ );
45
+ this.name = "CursorStreamTruncatedError";
46
+ }
47
+ }
48
+
49
+ /**
50
+ * A cancel-shaped stream failure that WE did not request. `cancelCursorRun` is the only place
51
+ * that cancels our own stream, and it sets `expectedClose` first, so a cancel arriving without it
52
+ * came from Cursor or the network and is a real transport failure.
53
+ *
54
+ * It carries its own message on purpose. Left as a raw `NGHTTP2_CANCEL` error, the text is
55
+ * re-matched downstream (`classifyCursorError`) and labelled "Cursor stream suspended" — a turn
56
+ * that failed unexpectedly would report an intentional suspension and misdirect diagnosis.
57
+ */
58
+ export class CursorUnexpectedCancelError extends Error {
59
+ /**
60
+ * The originating error's transport code (typically `NGHTTP2_CANCEL`), re-exposed so the
61
+ * per-turn `turn-failed` diagnostic still records how the stream actually died. Wrapping
62
+ * without this made the summary for exactly this failure the one with no code.
63
+ */
64
+ public readonly code?: string;
65
+
66
+ constructor(public readonly cause?: unknown) {
67
+ super("Cursor connection was cancelled by the server before the turn completed");
68
+ this.name = "CursorUnexpectedCancelError";
69
+ const causeCode = errorCode(cause);
70
+ if (causeCode) this.code = causeCode;
71
+ }
72
+ }
73
+
30
74
  export function isCursorBenignCancelError(value: unknown): boolean {
75
+ // An unexpected cancel is never benign, however it is spelled. This class is raised only when
76
+ // the transport knows WE did not request the cancel, so its provenance outranks the code match
77
+ // below — otherwise the adapter would re-decide the same question from the error code alone
78
+ // and swallow a real transport failure (cursor.ts:181).
79
+ if (value instanceof CursorUnexpectedCancelError) return false;
31
80
  const message = errorMessage(value).toLowerCase();
32
81
  const code = errorCode(value).toUpperCase();
33
82
  if (code === "NGHTTP2_CANCEL") return true;
@@ -36,6 +85,21 @@ export function isCursorBenignCancelError(value: unknown): boolean {
36
85
  return false;
37
86
  }
38
87
 
88
+ /**
89
+ * True when the turn was torn down by an `AbortSignal` rather than by a transport fault.
90
+ *
91
+ * This is deliberately NOT part of `isCursorBenignCancelError`: an abort mid-turn is a real
92
+ * failure and must still surface. It is only meaningful in combination with a terminal frame
93
+ * having already been emitted, where it means "the answer landed and then the connection went
94
+ * away" (#1527).
95
+ */
96
+ export function isCursorAbortError(value: unknown): boolean {
97
+ const message = errorMessage(value).toLowerCase();
98
+ if (message.includes("cursor request was aborted")) return true;
99
+ const name = (value as { name?: unknown })?.name;
100
+ return typeof name === "string" && name === "AbortError";
101
+ }
102
+
39
103
  /**
40
104
  * True when Cursor Connect rejected the turn with invalid_argument.
41
105
  * Seen after stepCompleted on brittle external-model continuations.
@@ -48,6 +112,58 @@ export function isCursorInvalidArgumentError(value: unknown): boolean {
48
112
  }
49
113
 
50
114
  const QUOTA_RATE_CUES = ["too many requests", "quota", "rate limit", "rate-limit", "throttl"];
115
+ /**
116
+ * A bare `resource_exhausted` end-stream with no detail beyond a generic error wrapper
117
+ * ("Error" or empty tail) and zero tokens billed is the shape Cursor's backend emits when
118
+ * the request payload exceeded its context window — not when quota ran out (senpi #1009,
119
+ * #1036: same wording, two causes). Quota rejections always carry an explicit rate cue
120
+ * ("too many requests", "quota exhausted"), so the ABSENCE of those cues plus the
121
+ * absence of a size phrase means payload overflow. Classifying it as 429 makes Codex
122
+ * back off instead of compacting, which burns retries on an unfixable-by-retry failure.
123
+ */
124
+ const BARE_RE_TAILS = new Set(["error", "", "resource_exhausted", "resource exhausted"]);
125
+
126
+ /**
127
+ * Size prior for bare resource_exhausted classification (devlog 260, live probe 210):
128
+ * a plan-gated model returns the SAME bare RE shape on a ~20-token prompt that a real
129
+ * payload overflow produces, so the message alone cannot separate "compact and retry"
130
+ * from "this account cannot use this model". When the caller can supply how large the
131
+ * request actually was relative to the model's window, a small request keeps the
132
+ * 429-class mapping; only a plausibly-large one classifies as overflow. Unknown
133
+ * sizes keep today's overflow mapping so the prior only ever REMOVES false overflows
134
+ * it can prove.
135
+ */
136
+ export interface CursorSizeContext {
137
+ estimatedInputTokens?: number;
138
+ contextWindow?: number;
139
+ }
140
+
141
+ const OVERFLOW_MIN_FRACTION = 0.5;
142
+
143
+ function bareReLooksLikeOverflow(context?: CursorSizeContext): boolean {
144
+ if (!context) return true;
145
+ const { estimatedInputTokens, contextWindow } = context;
146
+ if (estimatedInputTokens === undefined || contextWindow === undefined || contextWindow <= 0) return true;
147
+ return estimatedInputTokens >= OVERFLOW_MIN_FRACTION * contextWindow;
148
+ }
149
+
150
+ export function isCursorZeroTokenResourceExhausted(lowerMessage: string): boolean {
151
+ if (!lowerMessage.includes("resource_exhausted") && !lowerMessage.includes("resource exhausted")) return false;
152
+ // Any explicit quota/rate cue wins: this is a real 429.
153
+ if (QUOTA_RATE_CUES.some(cue => lowerMessage.includes(cue))) return false;
154
+ // An explicit size phrase also wins (already handled by the existing classifier).
155
+ if (isCursorRequestTooLargeDetail(lowerMessage)) return false;
156
+ // Extract the tail after the resource_exhausted marker. If it names a specific
157
+ // non-quota, non-size cause, this is NOT bare overflow.
158
+ const idx = Math.max(
159
+ lowerMessage.indexOf("resource_exhausted"),
160
+ lowerMessage.indexOf("resource exhausted"),
161
+ );
162
+ const tail = lowerMessage.slice(idx + "resource_exhausted".length).trim().replace(/^[:\s]+/, "").trim();
163
+ if (!BARE_RE_TAILS.has(tail)) return false;
164
+ return true;
165
+ }
166
+
51
167
  const REQUEST_TOO_LARGE_PATTERNS: (string | RegExp)[] = [
52
168
  "tool catalog too large",
53
169
  "tool registration too large",
@@ -80,7 +196,7 @@ export function isCursorRequestTooLargeDetail(lowerMessage: string): boolean {
80
196
  * The returned prefix string is recognized by `src/lib/errors.ts` `classifyError` keywords,
81
197
  * so bridge-level error mapping produces the right Codex error type (rate_limit, auth, etc.).
82
198
  */
83
- export function classifyCursorError(message: string): string {
199
+ export function classifyCursorError(message: string, sizeContext?: CursorSizeContext): string {
84
200
  const lower = message.toLowerCase();
85
201
 
86
202
  if (isCursorBenignCancelError(message)) return "Cursor stream suspended";
@@ -94,9 +210,16 @@ export function classifyCursorError(message: string): string {
94
210
  // client-fixable 400; everything else surfaces as a 429 so Codex backs off
95
211
  // instead of hammering retries (live evidence: 6x 400 retry storm, devlog
96
212
  // 260723_cursor_context_continuity/000_plan.md).
97
- return isCursorRequestTooLargeDetail(lower)
98
- ? "Cursor resource limit exceeded"
99
- : "Cursor rate limit exceeded";
213
+ if (isCursorRequestTooLargeDetail(lower)) return "Cursor resource limit exceeded";
214
+ // A bare resource_exhausted with no quota cue and no size phrase is payload
215
+ // overflow, not rate limiting. Classifying it as 429 makes Codex back off on a
216
+ // failure that only compaction can fix (senpi #1009 / #1036; research unit T01).
217
+ // Refinement (devlog 260): plan-gated models emit the same bare shape on tiny
218
+ // requests — when the caller proves the request was small, keep the 429 class.
219
+ if (isCursorZeroTokenResourceExhausted(lower)) {
220
+ return bareReLooksLikeOverflow(sizeContext) ? "Cursor context limit exceeded" : "Cursor rate limit exceeded";
221
+ }
222
+ return "Cursor rate limit exceeded";
100
223
  }
101
224
 
102
225
  if (
@@ -156,8 +279,8 @@ export function classifyCursorError(message: string): string {
156
279
  * Produce a user-facing, secret-safe Cursor error message with an actionable category prefix.
157
280
  * Mirrors `safeKiroErrorMessage` / `safeKiroHttpErrorMessage` in kiro-errors.ts.
158
281
  */
159
- export function safeCursorErrorMessage(rawMessage: string): string {
160
- const prefix = classifyCursorError(rawMessage);
282
+ export function safeCursorErrorMessage(rawMessage: string, sizeContext?: CursorSizeContext): string {
283
+ const prefix = classifyCursorError(rawMessage, sizeContext);
161
284
  const detail = sanitize(rawMessage)
162
285
  .replace(/resource[_ ]exhausted/gi, "resource limit exceeded")
163
286
  .slice(0, 500);
@@ -26,10 +26,10 @@ export function inferCursorContextWindow(modelId: string): number {
26
26
  const id = modelId.trim().toLowerCase();
27
27
  if (id.includes("1m")) return CONTEXT_1M;
28
28
  if (id.startsWith("gemini-")) return CONTEXT_1M;
29
- if (id === "glm-5.2") return CONTEXT_1M;
29
+ if (id === "glm-5.3" || id === "glm-5.2") return CONTEXT_1M;
30
30
  if (id.startsWith("gpt-5.6-")) return CONTEXT_1M;
31
31
  if (id.startsWith("gpt-5") || id === "gpt-5-codex") return CONTEXT_272K;
32
- if (id.startsWith("grok-4.5")) return 500_000;
32
+ if (id.startsWith("grok-4.5") || id.startsWith("grok-4.6")) return 500_000;
33
33
  if (id.startsWith("grok-")) return CONTEXT_256K;
34
34
  if (id.includes("claude")) return CONTEXT_200K;
35
35
  return CURSOR_DEFAULT_CONTEXT_WINDOW;
@@ -103,6 +103,28 @@ export const CURSOR_ROUTER_MODEL_IDS = [
103
103
  ...CURSOR_ROUTING_LEVELS.map(level => `${CURSOR_AUTO_MODEL_ID}-${level}`),
104
104
  ] as const;
105
105
 
106
+ /**
107
+ * Cursor models that cannot see images natively. OpenCodex routes them through the vision
108
+ * sidecar (the catalog still advertises image so Codex can attach). Evidence:
109
+ * - Composer family: Cursor staff — text-only; "Model does not support images"
110
+ * - Auto / router modes: Cursor docs omit Images for Auto Cost; staff — pick Claude/GPT for images
111
+ * - glm-5.2: Cursor docs omit Images; Z.ai GLM-5.2 is text-only (vision is GLM-5V)
112
+ * - glm-5.3: same family; seeded as text-only ahead of Cursor's lineup update
113
+ *
114
+ * Composer ids are enumerated explicitly — prefix wildcard matching is deliberately out of
115
+ * scope here; a live-discovered new Composer slug stays native-path until curated. Everyone
116
+ * else in the static seed (Claude, Gemini, GPT, Kimi, Grok) takes SelectedImage. Other
117
+ * live-discovered ids stay unclassified (native path) until curated.
118
+ */
119
+ export const CURSOR_NO_VISION_MODELS = [
120
+ ...CURSOR_ROUTER_MODEL_IDS,
121
+ "composer-1",
122
+ "composer-2.5",
123
+ "composer-2.5-fast",
124
+ "glm-5.2",
125
+ "glm-5.3",
126
+ ] as const;
127
+
106
128
  /** Wire id Cursor Connect expects for the auto-router (GetUsableModels returns `default`, not `auto`). */
107
129
  export const CURSOR_AUTO_WIRE_MODEL_ID = "default";
108
130
 
@@ -146,6 +168,24 @@ export function isCursorExternalWireModel(modelId: string): boolean {
146
168
  return !isCursorNativeWireModel(modelId);
147
169
  }
148
170
 
171
+ /**
172
+ * Native composer models whose tool-result continuation must still be sent as a
173
+ * userMessageAction with the plain "Continue:" text instead of a bare resumeAction.
174
+ *
175
+ * Observed on live Cursor Connect traffic (2026-08-20): `composer-2.5` (the
176
+ * standard, non-fast build) resumes a tool-result turn with server-side native
177
+ * tool calls (read/grep/exec) instead of answering, or completes with zero text
178
+ * (empty `content` + `stop`). `composer-2.5-fast` answers correctly on the same
179
+ * resumeAction path, so only the affected id is listed here. Sending the same
180
+ * continuation as an explicit user message (external path) makes the model
181
+ * answer reliably.
182
+ */
183
+ export function cursorNeedsExternalToolContinuation(modelId: string): boolean {
184
+ if (isCursorExternalWireModel(modelId)) return true;
185
+ const wire = cursorCodexToWireModelId(modelId).trim().toLowerCase();
186
+ return wire === "composer-2.5";
187
+ }
188
+
149
189
  function stripCursorEffortSuffix(wireModelId: string): string {
150
190
  const suffixes = [...CANONICAL_EFFORT_SUFFIXES].sort((a, b) => b.length - a.length);
151
191
  for (const suffix of suffixes) {
@@ -155,6 +195,13 @@ function stripCursorEffortSuffix(wireModelId: string): string {
155
195
  return wireModelId;
156
196
  }
157
197
 
198
+ /** Compare Cursor wire models without effort suffix or the grok cursor- request prefix. */
199
+ export function cursorCheckpointModelAffinityId(modelId: string): string {
200
+ const wire = cursorCodexToWireModelId(modelId).trim().toLowerCase();
201
+ const withoutPrefix = wire.startsWith("cursor-") ? wire.slice("cursor-".length) : wire;
202
+ return stripCursorEffortSuffix(withoutPrefix);
203
+ }
204
+
158
205
  export function isCursorRouterModelId(modelId: string): boolean {
159
206
  return (CURSOR_ROUTER_MODEL_IDS as readonly string[]).includes(modelId);
160
207
  }
@@ -189,10 +236,15 @@ export const CURSOR_STATIC_MODELS: readonly CursorModelInfo[] = normalizeCursorM
189
236
  { id: "claude-4.6-opus", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
190
237
  { id: "claude-4.6-sonnet", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
191
238
  { id: "claude-opus-4-7", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
192
- // opus-4-7-fast: effort-suffix tiers unverified -> no tier picker; sent bare like live-only ids.
193
- { id: "claude-opus-4-7-fast", contextWindow: CONTEXT_200K },
239
+ // Opus Fast families: live GetUsableModels (260822) lists ONLY effort-suffixed wire ids
240
+ // ({base-without-fast}-{effort}-fast; the bare id returns not_found), so every entry
241
+ // carries a tier picker. Live-verified: claude-opus-4-8-high-fast completed a turn.
242
+ // Tiers per the 260822 dump (devlog 260822_senpi_cursor_transfer/300).
243
+ { id: "claude-opus-4-7-fast", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
244
+ { id: "claude-opus-4-8-fast", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
194
245
  { id: "claude-opus-4-8", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
195
246
  { id: "claude-opus-5", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
247
+ { id: "claude-opus-5-fast", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
196
248
  { id: "claude-fable-5", contextWindow: CONTEXT_200K, supportsReasoningEffort: true },
197
249
 
198
250
  { id: "composer-1", contextWindow: CONTEXT_200K },
@@ -233,6 +285,8 @@ export const CURSOR_STATIC_MODELS: readonly CursorModelInfo[] = normalizeCursorM
233
285
  // Conflict resolution (260709): keep the refreshed 1M context + kimi-k2.7-code from de12fc8,
234
286
  // take PR #73's supportsReasoningEffort for glm-5.2 (its effort-map tiers landed with the PR).
235
287
  { id: "glm-5.2", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
288
+ // 260814 preemptive: glm-5.3 seeded ahead of Cursor's lineup update (mirrors glm-5.2).
289
+ { id: "glm-5.3", contextWindow: CONTEXT_1M, supportsReasoningEffort: true },
236
290
  { id: "kimi-k2.7-code", contextWindow: CONTEXT_262K },
237
291
  // kimi-k3: cursor.com/docs/models/kimi-k3; account-verified via GetUsableModels (2026-07-28) —
238
292
  // ships only as effort-suffixed kimi-k3-{low,high,max}, so the tier picker is exposed.
@@ -240,6 +294,9 @@ export const CURSOR_STATIC_MODELS: readonly CursorModelInfo[] = normalizeCursorM
240
294
 
241
295
  { id: "grok-4.5", contextWindow: 500_000, supportsReasoningEffort: true },
242
296
  { id: "grok-4.5-fast", contextWindow: 500_000, supportsReasoningEffort: true },
297
+ // 260813 preemptive: grok-4.6 seeded ahead of Cursor's lineup update (mirrors grok-4.5).
298
+ { id: "grok-4.6", contextWindow: 500_000, supportsReasoningEffort: true },
299
+ { id: "grok-4.6-fast", contextWindow: 500_000, supportsReasoningEffort: true },
243
300
  ]);
244
301
 
245
302
  export function cursorModelIds(models: readonly CursorModelInfo[] = CURSOR_STATIC_MODELS): string[] {
@@ -4,7 +4,7 @@
4
4
  * Cursor model ids encode the reasoning effort as a suffix (`claude-4.6-opus-high`), and the available
5
5
  * tiers differ per model — `claude-4.6-opus` tops out at `-max`, `claude-opus-4-8` at `-xhigh`,
6
6
  * `claude-4.6-sonnet` only has `-medium`, and most `composer`/`gemini` models take no suffix at all.
7
- * Grok Fast puts its mode marker after the effort (`grok-4.5-high-fast`). A bare id for a model that
7
+ * Grok Fast puts its mode marker after the effort (`grok-4.6-xhigh-fast`). A bare id for a model that
8
8
  * requires a suffix is rejected `ERROR_BAD_MODEL_NAME` (devlog 350.105).
9
9
  *
10
10
  * Canonical effort order is always low < medium < high < xhigh < max (max is the top tier, confirmed
@@ -24,10 +24,19 @@ const CURSOR_MODEL_EFFORT_TIERS: Record<string, readonly string[]> = {
24
24
  // against Anthropic's effort ladder docs and Cursor's live model lineup.
25
25
  "claude-fable-5": ["low", "medium", "high", "xhigh", "max"],
26
26
  "claude-opus-4-7": ["low", "medium", "high", "xhigh", "max"],
27
+ // Opus Fast tiers from the 260822 GetUsableModels dump (devlog .../300): the wire
28
+ // exposes {base-without-fast}-{effort}-fast only; suffix derivation at the bottom of
29
+ // this file produces those ids. opus-5-fast has no xhigh/max (non-thinking) yet.
30
+ "claude-opus-4-7-fast": ["low", "medium", "high", "xhigh", "max"],
27
31
  "claude-opus-4-8": ["low", "medium", "high", "xhigh", "max"],
32
+ "claude-opus-4-8-fast": ["low", "medium", "high", "xhigh", "max"],
28
33
  "claude-opus-5": ["low", "medium", "high", "xhigh", "max"],
34
+ "claude-opus-5-fast": ["low", "medium", "high"],
29
35
  "claude-sonnet-5": ["low", "medium", "high", "xhigh", "max"],
30
36
  "glm-5.2": ["high", "max"],
37
+ // 260814 preemptive: glm-5.3 seeded ahead of Cursor's lineup update. Unlike 5.2, Z.AI folds
38
+ // 5.3 efforts into low/high/max (docs.z.ai/devpack/latest-model), so `low` is a real tier.
39
+ "glm-5.3": ["low", "high", "max"],
31
40
  // GetUsableModels (2026-07-28) lists kimi-k3 only as effort-suffixed kimi-k3-{low,high,max};
32
41
  // the bare id returns not_found. Tiers mirror the native Kimi provider's K3 ladder.
33
42
  "kimi-k3": ["low", "high", "max"],
@@ -35,6 +44,9 @@ const CURSOR_MODEL_EFFORT_TIERS: Record<string, readonly string[]> = {
35
44
  // cursor-grok-4.5-{low,medium,high}-fast. The bare Fast id returns not_found.
36
45
  "grok-4.5": ["low", "medium", "high"],
37
46
  "grok-4.5-fast": ["low", "medium", "high"],
47
+ // Cursor's 260813 lineup exposes Grok 4.6 Extra High in both regular and Fast forms.
48
+ "grok-4.6": ["low", "medium", "high", "xhigh"],
49
+ "grok-4.6-fast": ["low", "medium", "high", "xhigh"],
38
50
  "gpt-5.1": ["low", "high"],
39
51
  "gpt-5.1-codex-max": ["low", "medium", "high", "xhigh"],
40
52
  "gpt-5.1-codex-mini": ["low", "high"],
@@ -116,8 +128,9 @@ export function cursorModelHasEffortTiers(baseModelId: string): boolean {
116
128
  }
117
129
 
118
130
  /**
119
- * Compose a Cursor wire id from a Codex-facing base id and effort tier.
120
- * Fast variants put the mode after the effort; other models use the ordinary `{base}-{effort}` form.
131
+ * Compose Cursor's flattened model id from a Codex-facing base id and effort tier. Discovery uses
132
+ * this for the ids returned by GetUsableModels. Parameterized Grok Fast requests bypass the flat id
133
+ * and send the base model plus requested_model parameters instead.
121
134
  */
122
135
  export function cursorWireModelIdWithEffort(baseModelId: string, effortSuffix: string): string {
123
136
  if (baseModelId.endsWith("-fast")) {
@@ -125,3 +138,14 @@ export function cursorWireModelIdWithEffort(baseModelId: string, effortSuffix: s
125
138
  }
126
139
  return `${baseModelId}-${effortSuffix}`;
127
140
  }
141
+
142
+ /**
143
+ * Compose the exact flattened id sent by AgentService/Run. Discovery normalizes Cursor's optional
144
+ * `cursor-` prefix only for catalog matching, but regular Grok 4.5 requests require that prefix on
145
+ * the wire. Keep this separate from {@link cursorWireModelIdWithEffort} so discovery can continue
146
+ * comparing canonical, prefix-free ids. Grok Fast uses requested_model parameters instead.
147
+ */
148
+ export function cursorRequestWireModelIdWithEffort(baseModelId: string, effortSuffix: string): string {
149
+ const flattened = cursorWireModelIdWithEffort(baseModelId, effortSuffix);
150
+ return baseModelId === "grok-4.5" || baseModelId === "grok-4.6" ? `cursor-${flattened}` : flattened;
151
+ }