@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
@@ -4,16 +4,20 @@ import { ValueSchema } from "@bufbuild/protobuf/wkt";
4
4
  import type { OcxAssistantContentPart, OcxMessage, OcxToolResultMessage } from "../../types";
5
5
  import { namespacedToolName } from "../../types";
6
6
  import type { CursorRunRequest } from "./types";
7
- import { isCursorExternalWireModel } from "./discovery";
7
+ import { cursorNeedsExternalToolContinuation, isCursorExternalWireModel } from "./discovery";
8
+ import { normalizeCursorToolResultText } from "./tool-result-normalize";
8
9
  import { debugProviderDiagnostic } from "../../lib/debug";
9
10
  import {
10
11
  createCursorBlobRequestScope,
12
+ cursorBlobMaxEntryBytes,
11
13
  releaseCursorBlobRequestScope,
12
14
  sealCursorBlobRequestScope,
13
15
  storeCursorBlob,
14
16
  type CursorBlobRequestScopeToken,
15
17
  } from "./native-exec";
18
+ import { buildSelectedContext, CURSOR_VISION_IMAGE_HISTORY_MARKER } from "./images";
16
19
  import { estimateTokens } from "../../lib/token-estimate";
20
+ import { parseDataUrl } from "../image";
17
21
  import {
18
22
  AgentClientMessageSchema,
19
23
  AgentConversationTurnStructureSchema,
@@ -22,10 +26,12 @@ import {
22
26
  ConversationActionSchema,
23
27
  ConversationStepSchema,
24
28
  ConversationStateStructureSchema,
29
+ type ConversationStateStructure,
25
30
  ConversationTurnStructureSchema,
26
31
  McpArgsSchema,
27
32
  McpSuccessSchema,
28
33
  McpTextContentSchema,
34
+ McpImageContentSchema,
29
35
  McpToolCallSchema,
30
36
  McpToolResultContentItemSchema,
31
37
  McpToolResultSchema,
@@ -65,6 +71,14 @@ export const CURSOR_EXTERNAL_ROOT_BLOB_LIMIT = 192;
65
71
  /** Approximate prompt-size guard; tool schemas and protocol framing consume context separately. */
66
72
  export const CURSOR_EXTERNAL_ROOT_BYTE_LIMIT = 512 * 1024;
67
73
 
74
+ /**
75
+ * Action text for external-model tool-result continuations. Native models keep
76
+ * resumeAction; external wire models continue as userMessageAction so the
77
+ * results already stored in history blobs are visible without a ResumeAction.
78
+ */
79
+ export const CURSOR_EXTERNAL_TOOL_CONTINUATION_TEXT =
80
+ "Continue: the requested tool results are provided in the conversation history above.";
81
+
68
82
  /** Runtime timezone for protobuf RequestContextEnv (dynamic, never hardcoded). */
69
83
  function runtimeTimeZone(): string {
70
84
  try {
@@ -119,6 +133,10 @@ function rootBlobCandidate(
119
133
  };
120
134
  }
121
135
 
136
+ function toolResultRootPayload(text: string): { role: "assistant"; content: [{ type: "text"; text: string }] } {
137
+ return { role: "assistant", content: [{ type: "text", text }] };
138
+ }
139
+
122
140
  function truncateToolResultBlob(entry: RootBlobCandidate, maxBytes: number): RootBlobCandidate | null {
123
141
  if (entry.byteLength <= maxBytes) return entry;
124
142
  if (entry.role !== "toolResult" || entry.text === undefined) return null;
@@ -131,7 +149,7 @@ function truncateToolResultBlob(entry: RootBlobCandidate, maxBytes: number): Roo
131
149
  while (end > 0 && end < encoded.byteLength && (encoded[end]! & 0xc0) === 0x80) end -= 1;
132
150
  const truncated = `${decoder.decode(encoded.subarray(0, end))}${marker}`;
133
151
  const result = rootBlobCandidate(
134
- { role: "user", content: [{ type: "text", text: truncated }] },
152
+ toolResultRootPayload(truncated),
135
153
  "toolResult",
136
154
  { messageIndex: entry.messageIndex, text: truncated },
137
155
  );
@@ -140,7 +158,7 @@ function truncateToolResultBlob(entry: RootBlobCandidate, maxBytes: number): Roo
140
158
  keepBytes = Math.max(0, end - (result.byteLength - maxBytes) - 16);
141
159
  }
142
160
  const markerOnly = rootBlobCandidate(
143
- { role: "user", content: [{ type: "text", text: marker.trimStart() }] },
161
+ toolResultRootPayload(marker.trimStart()),
144
162
  "toolResult",
145
163
  { messageIndex: entry.messageIndex, text: marker.trimStart() },
146
164
  );
@@ -170,11 +188,12 @@ function assistantRootText(
170
188
  }
171
189
 
172
190
  // Cursor builds the actual model prompt from rootPromptMessagesJson (turns[] is UI/display metadata),
173
- // so prior history including assistant tool calls and tool results must be replayed here or a
174
- // ResumeAction has nothing model-visible to continue from. The active user message is excluded
175
- // because it travels in the action. Tool results are rendered as user-role text with a marker, and
176
- // each entry is a SHA-256 blob ID (Cursor fetches the bytes back via getBlobArgs). Mirrors the
177
- // danger-pi reference buildRootPromptMessagesJson.
191
+ // so prior history must be replayed here or a ResumeAction has nothing model-visible to continue from.
192
+ // The active user message is excluded because it travels in the action. When the continuation cannot
193
+ // rely on native MCP turn state, tool results stay assistant-role text with a [Tool Result] /
194
+ // [Tool Error] marker so Cursor does not wrap them as `<user_query>` (#1992). Native resume models
195
+ // already carry the paired MCP result on turns[], so that marker is omitted from root replay — Auto
196
+ // few-shot-mimics it as chat text otherwise. Each entry is a SHA-256 blob ID.
178
197
  function rootPromptMessages(request: CursorRunRequest, requestScope: CursorBlobRequestScopeToken): {
179
198
  ids: Uint8Array[];
180
199
  byteLength: number;
@@ -195,6 +214,7 @@ function rootPromptMessages(request: CursorRunRequest, requestScope: CursorBlobR
195
214
  }
196
215
 
197
216
  const externalModel = isCursorExternalWireModel(request.modelId);
217
+ const echoToolResultInRoot = cursorNeedsExternalToolContinuation(request.modelId);
198
218
  const lastRawIsToolResult = messages.at(-1)?.role === "toolResult";
199
219
  const activeUserIndex = lastRawIsToolResult ? -1 : lastActionIndex(messages);
200
220
 
@@ -203,7 +223,7 @@ function rootPromptMessages(request: CursorRunRequest, requestScope: CursorBlobR
203
223
  const message = messages[i];
204
224
  if (!message) continue;
205
225
  if (message.role === "user" || message.role === "developer") {
206
- const text = contentText(message).trim();
226
+ const text = historyContentText(message).trim();
207
227
  // Cursor root replay expects OpenAI-style content parts for historical user messages.
208
228
  // A bare string survives blob hydration but external workers reject the completed replay
209
229
  // before tokenization (`usedTokens: 0`, then invalid_argument).
@@ -226,10 +246,16 @@ function rootPromptMessages(request: CursorRunRequest, requestScope: CursorBlobR
226
246
  }
227
247
  // Assistant tool CALLS are intentionally NOT replayed as visible "[Tool Call]" text here.
228
248
  } else if (message.role === "toolResult") {
229
- const prefix = message.isError ? "[Tool Error]" : "[Tool Result]";
249
+ // Native resume models already receive the paired MCP result through turns[]. Replaying
250
+ // the same payload as assistant-role "[Tool Result]" / "[tool_result]" text teaches Auto
251
+ // to echo that envelope as chat instead of continuing from the structured result.
252
+ if (!echoToolResultInRoot) continue;
253
+ // #1920: the prefix must reflect the NORMALIZED error state (an empty
254
+ // node_repl result is an error even when the runtime said isError=false).
255
+ const prefix = normalizedToolResult(message, contentToText(message.content)).isError ? "[Tool Error]" : "[Tool Result]";
230
256
  const text = `${prefix}\n${toolResultToText(message)}`;
231
257
  entries.push(rootBlobCandidate(
232
- { role: "user", content: [{ type: "text", text }] },
258
+ toolResultRootPayload(text),
233
259
  "toolResult",
234
260
  { messageIndex: i, text },
235
261
  ));
@@ -318,7 +344,7 @@ function contentText(message: OcxMessage): string {
318
344
  .map(part => {
319
345
  if (part.type === "text") return part.text;
320
346
  if (part.type === "thinking") return part.thinking;
321
- if (part.type === "image") return `[image input unsupported by Cursor adapter phase 3: ${part.detail ?? "auto"}]`;
347
+ if (part.type === "image") return undefined;
322
348
  return undefined;
323
349
  })
324
350
  .filter((value): value is string => typeof value === "string" && value.length > 0)
@@ -328,21 +354,216 @@ function contentText(message: OcxMessage): string {
328
354
  function contentToText(content: OcxToolResultMessage["content"]): string {
329
355
  if (typeof content === "string") return content;
330
356
  return content
331
- .map(part => part.type === "text" ? part.text : `[image input unsupported by Cursor adapter phase 3: ${part.detail ?? "auto"}]`)
357
+ .map(part => {
358
+ if (part.type === "text") return part.text;
359
+ if (part.type === "image") return CURSOR_VISION_IMAGE_HISTORY_MARKER;
360
+ return undefined;
361
+ })
362
+ .filter((value): value is string => typeof value === "string" && value.length > 0)
363
+ .join("\n");
364
+ }
365
+
366
+ /** History serializer. Replayed turns are text-only; never embed image bytes. */
367
+ function historyContentText(message: OcxMessage): string {
368
+ if (message.role === "toolResult" || typeof message.content === "string") return contentText(message);
369
+ return message.content
370
+ .map(part => {
371
+ if (part.type === "text") return part.text;
372
+ if (part.type === "thinking") return part.thinking;
373
+ if (part.type === "image") return CURSOR_VISION_IMAGE_HISTORY_MARKER;
374
+ return undefined;
375
+ })
376
+ .filter((value): value is string => typeof value === "string" && value.length > 0)
332
377
  .join("\n");
333
378
  }
334
379
 
380
+ const BASE64_PATTERN = /^[A-Za-z0-9+/]*={0,2}$/;
381
+
382
+ /**
383
+ * Decode a Codex inline image into Cursor wire bytes.
384
+ *
385
+ * `OcxImageContent.imageUrl` is either a `data:` URL or a remote https URL, so this cannot reuse
386
+ * the MCP helper (which takes bare base64 plus a separate mime). It layers strict validation over
387
+ * the shared `parseDataUrl` rather than tightening it, because Anthropic, Google, and Command Code
388
+ * share that parser. `Buffer.from(x, "base64")` accepts many invalid strings silently, so the
389
+ * charset is checked explicitly. Remote URLs are out of scope: `McpImageContent` needs bytes, and
390
+ * fetching here would put network IO inside request construction.
391
+ */
392
+ function decodeInlineImage(imageUrl: string): { bytes: Uint8Array; mimeType: string } | undefined {
393
+ const parsed = parseDataUrl(imageUrl);
394
+ if (!parsed) return undefined;
395
+ const base64 = parsed.base64.trim();
396
+ if (base64.length === 0 || base64.length % 4 !== 0 || !BASE64_PATTERN.test(base64)) return undefined;
397
+ try {
398
+ const bytes = Uint8Array.from(Buffer.from(base64, "base64"));
399
+ if (bytes.length === 0) return undefined;
400
+ return { bytes, mimeType: parsed.mediaType || "application/octet-stream" };
401
+ } catch {
402
+ return undefined;
403
+ }
404
+ }
405
+
406
+ /**
407
+ * A degraded image must never make a step LARGER than the legacy encoding did, or this change
408
+ * could fail admission for a request that previously fit. The old placeholder was
409
+ * `[image input unsupported by Cursor adapter phase 3: <detail>]`; anything we emit in its place
410
+ * is truncated to that budget so the zero-image case is byte-bounded by the pre-change behavior.
411
+ */
412
+ const LEGACY_IMAGE_PLACEHOLDER_BUDGET =
413
+ "[image input unsupported by Cursor adapter phase 3: auto]".length;
414
+
415
+ function imagePlaceholder(reason: string): string {
416
+ const text = `[image omitted: ${reason}]`;
417
+ return text.length <= LEGACY_IMAGE_PLACEHOLDER_BUDGET
418
+ ? text
419
+ : `${text.slice(0, LEGACY_IMAGE_PLACEHOLDER_BUDGET - 1)}]`;
420
+ }
421
+
422
+ type DecodedResultPart =
423
+ | { kind: "text"; text: string }
424
+ | { kind: "image"; bytes: Uint8Array; mimeType: string }
425
+ | { kind: "undecodable" };
426
+
427
+ type NormalizedToolResult = { text: string; isError: boolean };
428
+
429
+ /**
430
+ * Decode a tool result's parts ONCE. `toolCallStep` may re-serialize a step several times while
431
+ * shrinking it to fit blob admission, and decoding base64 on every attempt made that loop
432
+ * quadratic (an audit measured ~3s for 100 images).
433
+ */
434
+ function decodeResultParts(message: OcxToolResultMessage): DecodedResultPart[] | undefined {
435
+ const content = message.content;
436
+ if (typeof content === "string") return undefined;
437
+ return content.map((part): DecodedResultPart => {
438
+ if (part.type === "text") return { kind: "text", text: part.text };
439
+ const decoded = decodeInlineImage(part.imageUrl);
440
+ return decoded ? { kind: "image", ...decoded } : { kind: "undecodable" };
441
+ });
442
+ }
443
+
444
+ function countImages(parts: DecodedResultPart[] | undefined): number {
445
+ return parts ? parts.filter(p => p.kind === "image").length : 0;
446
+ }
447
+
448
+ /**
449
+ * Build the wire content items for a tool result, preserving part order.
450
+ *
451
+ * Images become real `McpImageContent` — the Cursor schema has an image case on
452
+ * `McpToolResultContentItem`, and `native-exec-mcp.ts` already uses it for MCP-invoked tools.
453
+ * Flattening them to placeholder text blinded every screenshot-returning tool (Computer Use,
454
+ * browser QA) that Codex routes through this path.
455
+ */
456
+ function toolResultContentItems(
457
+ message: OcxToolResultMessage,
458
+ decoded?: DecodedResultPart[],
459
+ maxImages = Number.POSITIVE_INFINITY,
460
+ normalizedText?: NormalizedToolResult,
461
+ ) {
462
+ const parts = decoded ?? decodeResultParts(message);
463
+ const textItem = (text: string) => [create(McpToolResultContentItemSchema, {
464
+ content: { case: "text" as const, value: create(McpTextContentSchema, { text }) },
465
+ })];
466
+ if (!parts) {
467
+ const normalized = normalizedText
468
+ ?? normalizedToolResult(message, typeof message.content === "string" ? message.content : "");
469
+ return textItem(normalized.text);
470
+ }
471
+ const normalized = normalizedText ?? normalizedDecodedTextResult(message, parts);
472
+ if (normalized) {
473
+ // #1920/#1866: empty or failure-state Computer Use / node_repl results are
474
+ // normalized before they reach the native wire. Pure-text part arrays use
475
+ // the same newline-joined representation this serializer already emitted;
476
+ // image-bearing and undecodable results stay on the lossless part path.
477
+ return textItem(normalized.text);
478
+ }
479
+ // Images are dropped OLDEST first when the step must shrink: the most recent screenshot is the
480
+ // one the model is reasoning about, so it is the last to go.
481
+ const totalImages = countImages(parts);
482
+ const allowed = Math.max(0, Math.min(totalImages, maxImages));
483
+ let seen = 0;
484
+ // Consecutive text runs are newline-joined into ONE item, exactly as the legacy encoding did.
485
+ // Emitting one protobuf item per part adds per-item framing, which was enough to push a
486
+ // previously admissible step past the blob ceiling (round-3 audit: 1020 -> 1025 bytes at a
487
+ // 1024 limit). A result with no images must serialize identically to before this feature.
488
+ const items: ReturnType<typeof create<typeof McpToolResultContentItemSchema>>[] = [];
489
+ let pendingText: string[] = [];
490
+ const flushText = () => {
491
+ if (pendingText.length === 0) return;
492
+ const text = pendingText.join("\n");
493
+ pendingText = [];
494
+ items.push(create(McpToolResultContentItemSchema, {
495
+ content: { case: "text" as const, value: create(McpTextContentSchema, { text }) },
496
+ }));
497
+ };
498
+ for (const part of parts) {
499
+ if (part.kind === "text") {
500
+ pendingText.push(part.text);
501
+ continue;
502
+ }
503
+ if (part.kind === "undecodable") {
504
+ pendingText.push(imagePlaceholder("no inline data"));
505
+ continue;
506
+ }
507
+ seen++;
508
+ if (seen <= totalImages - allowed) {
509
+ pendingText.push(imagePlaceholder(`${part.bytes.byteLength}B over step limit`));
510
+ continue;
511
+ }
512
+ flushText();
513
+ items.push(create(McpToolResultContentItemSchema, {
514
+ content: { case: "image" as const, value: create(McpImageContentSchema, {
515
+ data: part.bytes,
516
+ mimeType: part.mimeType,
517
+ }) },
518
+ }));
519
+ }
520
+ flushText();
521
+ if (items.length === 0) {
522
+ items.push(create(McpToolResultContentItemSchema, {
523
+ content: { case: "text" as const, value: create(McpTextContentSchema, { text: "" }) },
524
+ }));
525
+ }
526
+ return items;
527
+ }
528
+
335
529
  function toolResultToText(message: OcxToolResultMessage): string {
530
+ const normalized = normalizedToolResult(message, contentToText(message.content));
336
531
  return [
337
532
  "[tool_result]",
338
533
  `call_id: ${message.toolCallId}`,
339
534
  `name: ${namespacedToolName(message.toolNamespace, message.toolName)}`,
340
- `is_error: ${message.isError}`,
535
+ `is_error: ${normalized.isError}`,
341
536
  "output:",
342
- contentToText(message.content),
537
+ normalized.text,
343
538
  ].join("\n");
344
539
  }
345
540
 
541
+ /**
542
+ * Shared #1920 normalization entry: pure-text results only. Image-bearing or
543
+ * encrypted results pass through untouched (their content is not plain text).
544
+ */
545
+ function normalizedToolResult(message: OcxToolResultMessage, text: string): NormalizedToolResult {
546
+ if (message.containsEncryptedContent) return { text, isError: message.isError };
547
+ return normalizeCursorToolResultText(text, {
548
+ toolName: message.toolName,
549
+ toolNamespace: message.toolNamespace,
550
+ isError: message.isError,
551
+ });
552
+ }
553
+
554
+ /**
555
+ * A content-part result is plain text only when every decoded part is text (the empty array is the
556
+ * empty text result). Join it exactly as toolResultContentItems already did, then share the string
557
+ * normalization contract. Any image or undecodable part keeps the existing part-preserving path.
558
+ */
559
+ function normalizedDecodedTextResult(
560
+ message: OcxToolResultMessage,
561
+ parts: DecodedResultPart[],
562
+ ): NormalizedToolResult | undefined {
563
+ if (parts.some(part => part.kind !== "text")) return undefined;
564
+ return normalizedToolResult(message, parts.map(part => part.kind === "text" ? part.text : "").join("\n"));
565
+ }
566
+
346
567
  function argBytes(value: unknown): Uint8Array {
347
568
  try {
348
569
  return toBinary(ValueSchema, fromJson(ValueSchema, value as JsonValue));
@@ -359,7 +580,8 @@ function toolCallStep(
359
580
  const args: Record<string, Uint8Array> = {};
360
581
  for (const [key, value] of Object.entries(part.arguments ?? {})) args[key] = argBytes(value);
361
582
  const toolName = namespacedToolName(part.namespace, part.name);
362
- return storeCursorBlob(toBinary(ConversationStepSchema, create(ConversationStepSchema, {
583
+ const decodedResult = result ? decodeResultParts(result) : undefined;
584
+ const serialize = (maxImages: number): Uint8Array => toBinary(ConversationStepSchema, create(ConversationStepSchema, {
363
585
  message: {
364
586
  case: "toolCall",
365
587
  value: create(ToolCallSchema, {
@@ -373,23 +595,38 @@ function toolCallStep(
373
595
  providerIdentifier: OCX_RESPONSES_TOOL_PROVIDER,
374
596
  args,
375
597
  }),
376
- ...(result ? { result: toolResultPart(result) } : {}),
598
+ ...(result ? { result: toolResultPart(result, decodedResult, maxImages) } : {}),
377
599
  }),
378
600
  },
379
601
  }),
380
602
  },
381
- })), requestScope);
603
+ }));
604
+
605
+ // A step is stored as ONE blob, so its images share an entry with the call's arguments, text,
606
+ // mime strings, and protobuf framing. A byte budget over decoded images alone cannot bound that
607
+ // (an audit reproduced a 448-byte-argument call whose 460-byte image pushed a previously
608
+ // admitted step past the ceiling). Measure the real serialized size instead, then drop images —
609
+ // oldest first, so the most recent screenshot survives — until the step fits.
610
+ const limit = cursorBlobMaxEntryBytes();
611
+ const imageCount = countImages(decodedResult);
612
+ let encoded = serialize(imageCount);
613
+ for (let allowed = imageCount - 1; allowed >= 0 && encoded.byteLength > limit; allowed--) {
614
+ encoded = serialize(allowed);
615
+ }
616
+ return storeCursorBlob(encoded, requestScope);
382
617
  }
383
618
 
384
- function toolResultPart(message: OcxToolResultMessage) {
619
+ function toolResultPart(message: OcxToolResultMessage, decoded?: DecodedResultPart[], maxImages?: number) {
620
+ const parts = decoded ?? decodeResultParts(message);
621
+ const normalized = parts
622
+ ? normalizedDecodedTextResult(message, parts)
623
+ : normalizedToolResult(message, typeof message.content === "string" ? message.content : "");
385
624
  return create(McpToolResultSchema, {
386
625
  result: {
387
626
  case: "success",
388
627
  value: create(McpSuccessSchema, {
389
- isError: message.isError,
390
- content: [create(McpToolResultContentItemSchema, {
391
- content: { case: "text", value: create(McpTextContentSchema, { text: contentToText(message.content) }) },
392
- })],
628
+ isError: normalized?.isError ?? message.isError,
629
+ content: toolResultContentItems(message, parts, maxImages, normalized),
393
630
  }),
394
631
  },
395
632
  });
@@ -481,11 +718,15 @@ function conversationTurns(
481
718
  if (message.role === "toolResult") {
482
719
  if (!current) continue;
483
720
  if (externalModel) {
484
- const prefix = message.isError ? "[Tool Error]" : "[Tool Result]";
721
+ // #1920/#1866: this external-replay site bypasses toolResultToText, so it
722
+ // must consume the normalizer directly — cursor/grok-4.6 is the exact
723
+ // reported repro path for empty Computer Use results.
724
+ const normalized = normalizedToolResult(message, contentToText(message.content));
725
+ const prefix = normalized.isError ? "[Tool Error]" : "[Tool Result]";
485
726
  current.steps.push(storeCursorBlob(toBinary(ConversationStepSchema, create(ConversationStepSchema, {
486
727
  message: {
487
728
  case: "assistantMessage",
488
- value: create(AssistantMessageSchema, { text: `${prefix}\n${contentToText(message.content)}` }),
729
+ value: create(AssistantMessageSchema, { text: `${prefix}\n${normalized.text}` }),
489
730
  },
490
731
  })), requestScope));
491
732
  continue;
@@ -507,8 +748,10 @@ function conversationTurns(
507
748
  flush();
508
749
  current = {
509
750
  userMessage: storeCursorBlob(toBinary(UserMessageSchema, create(UserMessageSchema, {
510
- text: contentText(message),
751
+ text: historyContentText(message),
511
752
  messageId: crypto.randomUUID(),
753
+ selectedContext: buildSelectedContext([], requestScope),
754
+ mode: 1,
512
755
  })), requestScope),
513
756
  steps: [],
514
757
  };
@@ -577,19 +820,36 @@ function buildPreparedCursorRunRequest(
577
820
  const text = lastRole === "user" || lastRole === "developer"
578
821
  ? appendCursorGenericToolUseHint(request.tools, rawText)
579
822
  : rawText;
580
- // Tool-result-only turns resume the remembered Cursor conversation with results in history.
581
823
  const lastRawIsToolResult = request.rawMessages?.at(-1)?.role === "toolResult";
582
- const actionCase = !lastRawIsToolResult && text.trim().length > 0
824
+ const selectedImages = request.selectedImages ?? [];
825
+ // Native models resume the remembered Cursor conversation. External wire
826
+ // models continue as userMessageAction so history-blob tool results stay
827
+ // visible without a ResumeAction. Some native composer ids are also routed
828
+ // through the external continuation path (cursorNeedsExternalToolContinuation)
829
+ // because a bare resumeAction makes them continue exploring with native tools
830
+ // instead of answering (observed on composer-2.5; see discovery.ts).
831
+ const externalToolContinuation = lastRawIsToolResult && cursorNeedsExternalToolContinuation(request.modelId);
832
+ // Image-only active turns (including soft-omitted images) stay userMessageAction.
833
+ const actionCase = (
834
+ externalToolContinuation
835
+ || (!lastRawIsToolResult && (text.trim().length > 0 || selectedImages.length > 0))
836
+ )
583
837
  ? "userMessageAction"
584
838
  : "resumeAction";
839
+ const actionText = externalToolContinuation
840
+ ? CURSOR_EXTERNAL_TOOL_CONTINUATION_TEXT
841
+ : text;
585
842
  const action = create(ConversationActionSchema, {
586
843
  action: actionCase === "userMessageAction"
587
844
  ? {
588
845
  case: "userMessageAction",
589
846
  value: create(UserMessageActionSchema, {
590
847
  userMessage: create(UserMessageSchema, {
591
- text,
848
+ text: actionText,
592
849
  messageId: crypto.randomUUID(),
850
+ selectedContext: buildSelectedContext(selectedImages, requestScope),
851
+ // OmniRoute / cursor-agent always send mode=1 on UserMessage.
852
+ mode: 1,
593
853
  }),
594
854
  requestContext: buildRequestContext(),
595
855
  }),
@@ -601,9 +861,70 @@ function buildPreparedCursorRunRequest(
601
861
  }),
602
862
  },
603
863
  });
604
- const rootPromptMessagesState = rootPromptMessages(request, requestScope);
605
- const rootPromptMessageIds = rootPromptMessagesState.ids;
606
- const turnIds = conversationTurns(request, requestScope, rootPromptMessagesState.historyMessageStart);
864
+ let continuationMode: "full-replay" | "checkpoint" = "full-replay";
865
+ let checkpointInvalidationReason = request.checkpointInvalidationReason;
866
+ let conversationState: ConversationStateStructure | undefined;
867
+ let rootPromptMessagesState: ReturnType<typeof rootPromptMessages> | undefined;
868
+ if (request.checkpointBytes && request.checkpointBytes.byteLength > 0) {
869
+ try {
870
+ conversationState = fromBinary(ConversationStateStructureSchema, request.checkpointBytes);
871
+ continuationMode = "checkpoint";
872
+ const suffixStart = request.checkpointSuffixStart;
873
+ if (
874
+ typeof suffixStart === "number"
875
+ && Number.isSafeInteger(suffixStart)
876
+ && suffixStart >= 0
877
+ && request.rawMessages
878
+ && suffixStart < request.rawMessages.length
879
+ ) {
880
+ const suffixRequest: CursorRunRequest = {
881
+ ...request,
882
+ system: [],
883
+ rawMessages: request.rawMessages.slice(suffixStart),
884
+ };
885
+ const suffixRoots = rootPromptMessages(suffixRequest, requestScope);
886
+ const suffixTurns = conversationTurns(suffixRequest, requestScope, suffixRoots.historyMessageStart);
887
+ const suffixSystemCount = systemPromptBlobs(suffixRequest).length;
888
+ const suffixHistoryIds = suffixRoots.ids.slice(suffixSystemCount);
889
+ const suffixHistorySerialized = suffixRoots.serialized.slice(suffixSystemCount);
890
+ conversationState = create(ConversationStateStructureSchema, {
891
+ ...conversationState,
892
+ rootPromptMessagesJson: [
893
+ ...conversationState.rootPromptMessagesJson,
894
+ ...suffixHistoryIds,
895
+ ],
896
+ turns: [
897
+ ...conversationState.turns,
898
+ ...suffixTurns,
899
+ ],
900
+ });
901
+ rootPromptMessagesState = {
902
+ ids: suffixHistoryIds,
903
+ byteLength: suffixRoots.byteLength,
904
+ historyMessageStart: suffixRoots.historyMessageStart,
905
+ serialized: suffixHistorySerialized,
906
+ };
907
+ }
908
+ } catch {
909
+ checkpointInvalidationReason = "decode_failed";
910
+ }
911
+ }
912
+ if (!conversationState) {
913
+ rootPromptMessagesState = rootPromptMessages(request, requestScope);
914
+ conversationState = create(ConversationStateStructureSchema, {
915
+ rootPromptMessagesJson: rootPromptMessagesState.ids,
916
+ turns: conversationTurns(request, requestScope, rootPromptMessagesState.historyMessageStart),
917
+ todos: [],
918
+ pendingToolCalls: [],
919
+ previousWorkspaceUris: [],
920
+ fileStates: {},
921
+ fileStatesV2: {},
922
+ summaryArchives: [],
923
+ turnTimings: [],
924
+ subagentStates: {},
925
+ readPaths: [],
926
+ });
927
+ }
607
928
  // Hoisted out of the mcp_tools spread below so the estimate can read the same
608
929
  // filtered definitions the wire carries. Both helpers are pure.
609
930
  const visibleTools = cursorToolsForActivePrompt(request.tools, rawText, request.toolChoice);
@@ -615,46 +936,43 @@ function buildPreparedCursorRunRequest(
615
936
  turnType: lastRawIsToolResult ? "tool-continuation" : "initial",
616
937
  externalModel: isCursorExternalWireModel(request.modelId),
617
938
  rawMessages: request.rawMessages?.length ?? 0,
618
- rootBlobs: rootPromptMessageIds.length,
619
- rootBytes: rootPromptMessagesState.byteLength,
620
- turnBlobs: turnIds.length,
939
+ continuationMode,
940
+ checkpointPresent: continuationMode === "checkpoint",
941
+ checkpointBytes: continuationMode === "checkpoint" ? request.checkpointBytes?.byteLength : undefined,
942
+ checkpointInvalidationReason,
943
+ rootBlobs: conversationState.rootPromptMessagesJson.length,
944
+ rootBytes: rootPromptMessagesState?.byteLength ?? 0,
945
+ turnBlobs: conversationState.turns.length,
621
946
  tools: request.tools?.length ?? 0,
622
947
  });
623
948
 
949
+ const requestedModelParameters = [
950
+ ...(request.requestedModelParameters ?? []),
951
+ ...(request.routingLevel ? [{ id: CURSOR_ROUTING_LEVEL_PARAMETER_ID, value: request.routingLevel }] : []),
952
+ ];
953
+ const hasExplicitModelParameters = (request.requestedModelParameters?.length ?? 0) > 0;
624
954
  const runRequest = create(AgentRunRequestSchema, {
625
955
  conversationId: request.conversationId,
626
- conversationState: create(ConversationStateStructureSchema, {
627
- rootPromptMessagesJson: rootPromptMessageIds,
628
- turns: turnIds,
629
- todos: [],
630
- pendingToolCalls: [],
631
- previousWorkspaceUris: [],
632
- fileStates: {},
633
- fileStatesV2: {},
634
- summaryArchives: [],
635
- turnTimings: [],
636
- subagentStates: {},
637
- readPaths: [],
638
- }),
956
+ conversationState,
639
957
  action,
640
- modelDetails: create(ModelDetailsSchema, {
641
- modelId: request.modelId,
642
- displayModelId: request.modelId,
643
- displayName: request.modelId,
644
- displayNameShort: request.modelId,
645
- aliases: [],
646
- }),
647
- // requested_model is currently a Cursor Router-only surface. External model clients still
648
- // send model_details alone; sending both makes external workers reach stepCompleted and then
649
- // reject the turn with invalid_argument.
650
- ...(request.routingLevel ? {
958
+ // Explicit model-picker parameters follow current Cursor clients and use requested_model alone.
959
+ // Keep legacy model_details for flat model ids and the already-live Router path; sending both for
960
+ // a parameterized external model can resolve conflicting selections and end in invalid_argument.
961
+ ...(!hasExplicitModelParameters ? {
962
+ modelDetails: create(ModelDetailsSchema, {
963
+ modelId: request.modelId,
964
+ displayModelId: request.modelId,
965
+ displayName: request.modelId,
966
+ displayNameShort: request.modelId,
967
+ aliases: [],
968
+ }),
969
+ } : {}),
970
+ ...(requestedModelParameters.length > 0 ? {
651
971
  requestedModel: create(RequestedModelSchema, {
652
972
  modelId: request.modelId,
653
973
  maxMode: false,
654
- parameters: [create(RequestedModel_ModelParameterbytesSchema, {
655
- id: CURSOR_ROUTING_LEVEL_PARAMETER_ID,
656
- value: request.routingLevel,
657
- })],
974
+ parameters: requestedModelParameters.map(parameter =>
975
+ create(RequestedModel_ModelParameterbytesSchema, parameter)),
658
976
  }),
659
977
  } : {}),
660
978
  // Mirror the client (Responses) tool definitions into the top-level AgentRunRequest.mcp_tools
@@ -682,8 +1000,8 @@ function buildPreparedCursorRunRequest(
682
1000
  // Same instances that produced `bytes`, so the estimate cannot count history or
683
1001
  // tools the payload dropped — the defect that blocked PR #376.
684
1002
  const modelVisibleParts = [
685
- ...rootPromptMessagesState.serialized,
686
- ...(actionCase === "userMessageAction" ? [text] : []),
1003
+ ...(rootPromptMessagesState?.serialized ?? []),
1004
+ ...(actionCase === "userMessageAction" ? [actionText] : []),
687
1005
  ...mcpToolDefs.map(modelVisibleToolText),
688
1006
  ];
689
1007
  return {