@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
@@ -7,12 +7,25 @@ import { McpToolDefinitionSchema, McpToolsSchema, type McpToolDefinition } from
7
7
  export const OCX_RESPONSES_TOOL_PROVIDER = "opencodex-responses";
8
8
  export const CODEX_EXEC_COMMAND_TOOL = "exec_command";
9
9
  export const CODEX_SHELL_COMMAND_TOOL = "shell_command";
10
+ /** Codex Desktop unified-exec client tool. Companion of `wait`; not an `exec_command` schema alias. */
11
+ export const CODEX_UNIFIED_EXEC_TOOL = "exec";
12
+ export const CODEX_WAIT_TOOL = "wait";
10
13
  export const CODEX_APPLY_PATCH_TOOL = "apply_patch";
14
+ export const CURSOR_EDIT_FILE_TOOL = "edit_file";
15
+ export const CURSOR_MULTI_EDIT_TOOL = "multi_edit";
16
+ export const CURSOR_STRUCTURED_EDIT_TOOLS = [CURSOR_EDIT_FILE_TOOL, CURSOR_MULTI_EDIT_TOOL] as const;
11
17
  export const CURSOR_EXEC_COMMAND_TOOL = CODEX_EXEC_COMMAND_TOOL;
12
18
  export const CODEX_SHELL_BRIDGE_TOOL_NAMES = [CODEX_EXEC_COMMAND_TOOL, CODEX_SHELL_COMMAND_TOOL] as const;
13
19
  export const CURSOR_SHELL_ALIAS_SYSTEM_NOTE =
14
- 'Shell commands use the Codex shell bridge tool shown in this turn\'s catalog (`shell_command` or `exec_command`) with JSON arguments like {"cmd":"..."}. The long `mcp_opencodex-responses_*` display name is the same tool. Prefer it over Cursor-native Shell; never say native shell is blocked.';
20
+ 'Shell commands use the Codex shell bridge tool shown in this turn\'s catalog (`shell_command` or `exec_command`) with JSON arguments like {"cmd":"..."}. The long `mcp_opencodex-responses_*` display name is the same tool. Prefer it over Cursor-native Shell.';
15
21
  const NEIGHBOR_AGENT_TOOL_NAMES = ["Read", "Grep", "Glob", "Bash", "LS"] as const;
22
+ const NEIGHBOR_AGENT_TOOL_ALIASES: Record<(typeof NEIGHBOR_AGENT_TOOL_NAMES)[number], readonly string[]> = {
23
+ Read: ["read", "read_file"],
24
+ Grep: ["grep"],
25
+ Glob: ["glob", "find"],
26
+ Bash: ["bash", "shell"],
27
+ LS: ["ls"],
28
+ };
16
29
 
17
30
  export const CURSOR_GENERIC_TOOL_USE_USER_HINT = [
18
31
  "For generic tool-use/count demos, satisfy the request with repeated Codex shell bridge calls (`shell_command` or `exec_command`) for harmless commands.",
@@ -23,8 +36,7 @@ export const CURSOR_GENERIC_TOOL_USE_USER_HINT = [
23
36
  "The Cursor bridge may suspend after the first returned bridge tool call, so emit sibling calls together before any result is needed.",
24
37
  "If parallel emission is unavailable, continue with separate shell-bridge calls until the requested count has returned.",
25
38
  "Do not use `tool_search`, external MCP, or resource discovery just to pad the count unless explicitly asked.",
26
- "Do not suggest or switch to neighboring-agent tools such as `Grep`, `Read`, `Glob`, `Bash`, or `LS` unless this turn's catalog lists those exact names.",
27
- "Never tell the user that shell or read access is blocked, disabled, or denied unless the Codex shell bridge tool itself fails. Do not narrate Cursor-native Shell/Read routing.",
39
+ "Do not suggest or switch to neighboring-agent tools such as `Grep`, `Read`, `Glob`, `Bash`, or `LS` unless this turn's catalog lists those exact names or an equivalent listed client tool.",
28
40
  ].join(" ");
29
41
 
30
42
  export const CURSOR_EXEC_COMMAND_INPUT_SCHEMA = {
@@ -41,6 +53,47 @@ export const CURSOR_EXEC_COMMAND_INPUT_SCHEMA = {
41
53
  additionalProperties: false,
42
54
  } as const;
43
55
 
56
+ /**
57
+ * Structured single-replacement schema advertised to Cursor models in addition to the freeform
58
+ * `apply_patch` tool. Cursor-trained models reliably emit exact-match replacements (the native
59
+ * Edit shape) but cannot produce Codex's freeform patch grammar, so every file edit attempt on the
60
+ * Cursor route produced malformed `apply_patch` payloads that the Codex client rejected locally
61
+ * (#1017). Calls to this tool are converted server-side into a valid apply_patch payload.
62
+ */
63
+ export const CURSOR_EDIT_FILE_INPUT_SCHEMA = {
64
+ type: "object",
65
+ properties: {
66
+ file_path: { type: "string", description: "Path of the file to edit, relative to the workspace root." },
67
+ old_string: { type: "string", description: "Exact text to replace. Must match the current file content, including line breaks." },
68
+ new_string: { type: "string", description: "Replacement text. Empty removes the matched text." },
69
+ },
70
+ required: ["file_path", "old_string", "new_string"],
71
+ additionalProperties: false,
72
+ } as const;
73
+
74
+ /** Structured multi-replacement schema; mirrors Cursor's native MultiEdit shape. */
75
+ export const CURSOR_MULTI_EDIT_INPUT_SCHEMA = {
76
+ type: "object",
77
+ properties: {
78
+ file_path: { type: "string", description: "Path of the file to edit, relative to the workspace root." },
79
+ edits: {
80
+ type: "array",
81
+ items: {
82
+ type: "object",
83
+ properties: {
84
+ old_string: { type: "string", description: "Exact text to replace. Must match the current file content, including line breaks." },
85
+ new_string: { type: "string", description: "Replacement text. Empty removes the matched text." },
86
+ },
87
+ required: ["old_string", "new_string"],
88
+ additionalProperties: false,
89
+ },
90
+ description: "Ordered replacement edits for this file. Each old_string must match the current file content.",
91
+ },
92
+ },
93
+ required: ["file_path", "edits"],
94
+ additionalProperties: false,
95
+ } as const;
96
+
44
97
  /**
45
98
  * Responses/Codex-side schema used ONLY for arg-key normalization after Cursor returns a call.
46
99
  * Cursor models are trained to emit `cmd`; Codex `shell_command` / `exec_command` validate
@@ -123,6 +176,59 @@ export function isBareCodexShellBridgeTool(tool: Pick<OcxTool, "namespace" | "na
123
176
  return !tool.namespace && isCodexShellBridgeToolName(tool.name);
124
177
  }
125
178
 
179
+ function isCursorResponsesProvider(namespace: string | undefined): boolean {
180
+ return !namespace || namespace === OCX_RESPONSES_TOOL_PROVIDER;
181
+ }
182
+
183
+ const CURSOR_EXECUTION_PATH_TOOL_NAMES = [
184
+ CODEX_UNIFIED_EXEC_TOOL,
185
+ CODEX_EXEC_COMMAND_TOOL,
186
+ CODEX_SHELL_COMMAND_TOOL,
187
+ ] as const;
188
+
189
+ /** True for the Codex execution path that must survive Cursor transport truncation. */
190
+ export function isCursorExecutionPathTool(tool: Pick<OcxTool, "namespace" | "name">): boolean {
191
+ return isCursorResponsesProvider(tool.namespace)
192
+ && (CURSOR_EXECUTION_PATH_TOOL_NAMES as readonly string[]).includes(tool.name);
193
+ }
194
+
195
+ /** `wait` only resumes a yielded exec cell; it is unusable without an execution-path tool. */
196
+ export function isCursorWaitTool(tool: Pick<OcxTool, "namespace" | "name">): boolean {
197
+ return isCursorResponsesProvider(tool.namespace) && tool.name === CODEX_WAIT_TOOL;
198
+ }
199
+
200
+ /**
201
+ * True for Codex's unified-exec "code mode" tool: a freeform `exec` whose body is JavaScript
202
+ * evaluated in a V8 isolate, not a shell command string.
203
+ */
204
+ export function isCursorCodeModeExecTool(
205
+ tool: Pick<OcxTool, "namespace" | "name" | "freeform">,
206
+ ): boolean {
207
+ return isCursorResponsesProvider(tool.namespace)
208
+ && tool.name === CODEX_UNIFIED_EXEC_TOOL
209
+ && tool.freeform === true;
210
+ }
211
+
212
+ /**
213
+ * Codex code mode advertises ONE freeform `exec` tool and no bare shell bridge. Shell, file
214
+ * edits, and MCP calls are reachable only as nested `tools.<name>(...)` helpers described inside
215
+ * that tool's own description, so a flat catalog scan cannot see them.
216
+ *
217
+ * This matters because the shell-bridge guidance below is written for a flat catalog. Emitting
218
+ * "call \`exec_command\`" into a code-mode turn names a top-level tool that does not exist: the
219
+ * model calls it, gets nothing back, and burns turns rediscovering the real contract from error
220
+ * messages (empty output until \`text()\` is called, \`require is not defined\` because the isolate
221
+ * is not Node, \`apply_patch\` rejected because it too is only a nested helper here).
222
+ */
223
+ export function cursorRequestUsesCodeMode(
224
+ tools: readonly Pick<OcxTool, "namespace" | "name" | "freeform">[] | undefined,
225
+ toolChoice?: OcxRequestOptions["toolChoice"],
226
+ ): boolean {
227
+ const catalog = tools ?? [];
228
+ const visible = catalog.filter(tool => cursorToolAllowedByChoice(tool, toolChoice, catalog));
229
+ return visible.some(isCursorCodeModeExecTool) && !visible.some(isBareCodexShellBridgeTool);
230
+ }
231
+
126
232
  /** @deprecated Prefer isBareCodexShellBridgeTool; kept for older call sites/tests. */
127
233
  function isBareCodexExecCommandTool(tool: Pick<OcxTool, "namespace" | "name">): boolean {
128
234
  return isBareCodexShellBridgeTool(tool);
@@ -132,6 +238,12 @@ export function cursorRequestHasShellAlias(tools: readonly Pick<OcxTool, "namesp
132
238
  return tools?.some(isBareCodexExecCommandTool) ?? false;
133
239
  }
134
240
 
241
+ function cursorRequestHasExecutionPath(
242
+ tools: readonly Pick<OcxTool, "namespace" | "name">[] | undefined,
243
+ ): boolean {
244
+ return tools?.some(isCursorExecutionPathTool) ?? false;
245
+ }
246
+
135
247
  export function cursorRequestAdvertisesApplyPatch(
136
248
  tools: readonly Pick<OcxTool, "namespace" | "name" | "freeform">[] | undefined,
137
249
  toolChoice?: OcxRequestOptions["toolChoice"],
@@ -140,6 +252,73 @@ export function cursorRequestAdvertisesApplyPatch(
140
252
  return catalog.some(tool => !tool.namespace && tool.name === CODEX_APPLY_PATCH_TOOL && tool.freeform === true && cursorToolAllowedByChoice(tool, toolChoice, catalog));
141
253
  }
142
254
 
255
+ export function isCursorStructuredEditToolName(name: string): boolean {
256
+ return (CURSOR_STRUCTURED_EDIT_TOOLS as readonly string[]).includes(name);
257
+ }
258
+
259
+ /** Internal provenance gate for synthetic edits after prompt filtering and catalog budgeting. */
260
+ export function isCursorSyntheticStructuredEditTool(
261
+ tool: Pick<OcxTool, "namespace" | "name" | "cursorStructuredEdit">,
262
+ ): boolean {
263
+ return !tool.namespace && tool.cursorStructuredEdit === true && isCursorStructuredEditToolName(tool.name);
264
+ }
265
+
266
+ /**
267
+ * Synthetic structured edit tools for the Cursor route (#1017).
268
+ *
269
+ * Codex exposes `apply_patch` as a freeform custom tool whose body must be the exact Codex patch
270
+ * grammar (`*** Begin Patch` envelope, `@@` hunks, `-`/`+` prefixes). Cursor-trained models are
271
+ * trained on exact-match edit tools instead and emit malformed patch text on every attempt, which
272
+ * the Codex client then rejects locally ("invalid hunk"). When the request advertises the freeform
273
+ * `apply_patch` tool, also advertise Cursor-native-shaped `edit_file` / `multi_edit` tools; the
274
+ * adapter converts their exact-match replacements into a valid apply_patch payload (see
275
+ * protobuf-events.translateStructuredEditCall).
276
+ *
277
+ * Never widened when the caller pinned an explicit tool choice: a forced `apply_patch` selection
278
+ * must not gain sibling tools the client did not ask for.
279
+ */
280
+ export function cursorStructuredEditTools(
281
+ tools: readonly Pick<OcxTool, "namespace" | "name" | "freeform">[] | undefined,
282
+ toolChoice?: OcxRequestOptions["toolChoice"],
283
+ ): OcxTool[] {
284
+ if (!cursorRequestAdvertisesApplyPatch(tools, toolChoice)) return [];
285
+ if (toolChoice && toolChoice !== "auto" && toolChoice !== "required") return [];
286
+ // Never shadow an already-advertised bare tool with the same name (a client catalog could
287
+ // legitimately expose its own `edit_file` / `multi_edit` MCP-style tools).
288
+ const existingBareNames = new Set(
289
+ (tools ?? []).filter(tool => !tool.namespace).map(tool => tool.name),
290
+ );
291
+ const candidates: OcxTool[] = [
292
+ {
293
+ name: CURSOR_EDIT_FILE_TOOL,
294
+ cursorStructuredEdit: true,
295
+ description:
296
+ "Replace one block of text in a file. OpenCodex converts the replacement into a Codex apply_patch change. Copy old_string and new_string with their exact leading whitespace — Codex may locate a line after trimming indent, but it writes new_string verbatim, so stripped indent silently corrupts the file. An empty old_string with a non-empty new_string creates a new file (Add File). If the same text appears more than once, the first match is updated. Matching is line-based, so an edit cannot add or remove only the file's final newline, and old_string/new_string that are identical after line normalization are rejected as a no-op.",
297
+ parameters: { ...CURSOR_EDIT_FILE_INPUT_SCHEMA },
298
+ },
299
+ {
300
+ name: CURSOR_MULTI_EDIT_TOOL,
301
+ cursorStructuredEdit: true,
302
+ description:
303
+ "Apply several text replacements to one file. OpenCodex converts them into one Codex apply_patch change. Copy each old_string/new_string with exact leading whitespace. If a later edit's old_string is the text after an earlier replacement, OpenCodex folds those edits into one original-file hunk. Independent edits stay separate hunks. An empty old_string with a non-empty new_string creates a new file (Add File); do not mix that with an independent Update on the same path. If the same text appears more than once, the first match is updated. Matching is line-based, so an edit cannot add or remove only the file's final newline, and identical old/new after line normalization are rejected as a no-op.",
304
+ parameters: { ...CURSOR_MULTI_EDIT_INPUT_SCHEMA },
305
+ },
306
+ ];
307
+ return candidates.filter(tool => !existingBareNames.has(tool.name));
308
+ }
309
+
310
+ /**
311
+ * True when this request actually advertises the synthetic structured edit tools (`edit_file` /
312
+ * `multi_edit`) — i.e. a freeform `apply_patch` is advertised, no tool-choice pin blocks widening,
313
+ * and neither name is shadowed by an existing bare tool in the client catalog.
314
+ */
315
+ export function cursorRequestAdvertisesStructuredEdits(
316
+ tools: readonly Pick<OcxTool, "namespace" | "name" | "freeform">[] | undefined,
317
+ toolChoice?: OcxRequestOptions["toolChoice"],
318
+ ): boolean {
319
+ return cursorStructuredEditTools(tools, toolChoice).length > 0;
320
+ }
321
+
143
322
  export function cursorToolWireName(tool: Pick<OcxTool, "namespace" | "name">): string {
144
323
  return namespacedToolName(tool.namespace, tool.name);
145
324
  }
@@ -157,6 +336,26 @@ export function normalizeCursorWireName(name: string): string {
157
336
  return name.startsWith(CURSOR_MCP_DISPLAY_PREFIX) ? name.slice(CURSOR_MCP_DISPLAY_PREFIX.length) : name;
158
337
  }
159
338
 
339
+ /**
340
+ * #2305: some models emit a TEXTUAL pseudo tool call ("[TOOL_CALL]name[ARGS]{...}")
341
+ * instead of a real frame, using Cursor's display alias as the name. Text-mode clients
342
+ * (Pi) parse that text and then cannot dispatch the undeclared display name. Rewrite the
343
+ * display alias to the advertised wire name ONLY inside the marker pair — prose that
344
+ * merely mentions the alias stays untouched, and the scope guard is the exact
345
+ * `mcp_${OCX_RESPONSES_TOOL_PROVIDER}_` prefix, never generic `mcp_`.
346
+ * Known limit (recorded in devlog 230): a marker split across two streaming deltas is
347
+ * not rewritten; tail-buffering is deferred until a live trace shows split markers.
348
+ */
349
+ const CURSOR_TEXT_TOOL_MARKER = new RegExp(
350
+ String.raw`\[TOOL_CALL\](${CURSOR_MCP_DISPLAY_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[^\[\]]+)\[ARGS\]`,
351
+ "g",
352
+ );
353
+
354
+ export function normalizeCursorTextToolMarkers(text: string): string {
355
+ if (!text.includes(CURSOR_MCP_DISPLAY_PREFIX)) return text;
356
+ return text.replace(CURSOR_TEXT_TOOL_MARKER, (_match, name: string) => `[TOOL_CALL]${normalizeCursorWireName(name)}[ARGS]`);
357
+ }
358
+
160
359
  export function responsesToolNameFromCursorWire(name: string, cursorToolNameMap?: ReadonlyMap<string, string>): string {
161
360
  const normalized = normalizeCursorWireName(name);
162
361
  if (!cursorToolNameMap) return normalized;
@@ -286,7 +485,7 @@ export function shouldUseNativeExecOnlyForGenericToolUse(
286
485
  text: string,
287
486
  ): boolean {
288
487
  const trimmed = text.trim();
289
- if (trimmed.length === 0 || !cursorRequestHasShellAlias(tools) || !isGenericToolUseCountDemoPrompt(trimmed)) return false;
488
+ if (trimmed.length === 0 || !cursorRequestHasExecutionPath(tools) || !isGenericToolUseCountDemoPrompt(trimmed)) return false;
290
489
  return !/\b(?:mcp|resource|resources|tool_search|plugin|plugins|app connector|github)\b/i.test(trimmed)
291
490
  && !/(?:리소스|플러그인|깃허브|github)/i.test(trimmed);
292
491
  }
@@ -297,7 +496,7 @@ export function cursorToolsForActivePrompt<T extends Pick<OcxTool, "namespace" |
297
496
  toolChoice?: OcxRequestOptions["toolChoice"],
298
497
  ): readonly T[] | undefined {
299
498
  if (!shouldUseNativeExecOnlyForGenericToolUse(tools, activeText)) return tools;
300
- const execTools = tools?.filter(isBareCodexExecCommandTool);
499
+ const execTools = tools?.filter(isCursorExecutionPathTool);
301
500
  const catalog = tools ?? [];
302
501
  if (execTools?.length && !execTools.some(tool => cursorToolAllowedByChoice(tool, toolChoice, catalog))) return tools;
303
502
  return execTools && execTools.length > 0 ? execTools : tools;
@@ -352,7 +551,12 @@ export function nonEmptyShellBridgeCommandFromArgs(
352
551
  }
353
552
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return undefined;
354
553
  const record = parsed as Record<string, unknown>;
355
- for (const key of shellBridgeRequiredCommandKeys(toolName, schema)) {
554
+ const requiredKeys = shellBridgeRequiredCommandKeys(toolName, schema);
555
+ const candidateKeys = new Set<"cmd" | "command">([
556
+ ...requiredKeys,
557
+ requiredKeys.includes("cmd") ? "command" : "cmd",
558
+ ]);
559
+ for (const key of candidateKeys) {
356
560
  const value = record[key];
357
561
  if (typeof value === "string" && value.trim().length > 0) return value.trim();
358
562
  }
@@ -385,9 +589,14 @@ function quotedNames(names: readonly string[]): string {
385
589
  return names.map(name => `\`${name}\``).join(", ");
386
590
  }
387
591
 
592
+ function advertisedCoversNeighbor(wireNames: readonly string[], neighbor: (typeof NEIGHBOR_AGENT_TOOL_NAMES)[number]): boolean {
593
+ const advertised = new Set(wireNames.map(name => name.toLowerCase()));
594
+ if (advertised.has(neighbor.toLowerCase())) return true;
595
+ return NEIGHBOR_AGENT_TOOL_ALIASES[neighbor].some(alias => advertised.has(alias.toLowerCase()));
596
+ }
597
+
388
598
  function unavailableNeighborAgentToolNames(wireNames: readonly string[]): string[] {
389
- const advertised = new Set(wireNames);
390
- return NEIGHBOR_AGENT_TOOL_NAMES.filter(name => !advertised.has(name));
599
+ return NEIGHBOR_AGENT_TOOL_NAMES.filter(name => !advertisedCoversNeighbor(wireNames, name));
391
600
  }
392
601
 
393
602
  function discoveryToolLabel(wireNames: readonly string[]): string | undefined {
@@ -413,14 +622,25 @@ export function buildCursorToolGuidanceSystemNote(
413
622
  const listedNames = quotedNames(wireNames);
414
623
  const shellBridgeNames = wireNames.filter(isCodexShellBridgeToolName);
415
624
  const hasBareExec = shellBridgeNames.length > 0;
625
+ const codeMode = cursorRequestUsesCodeMode(tools, toolChoice);
626
+ // Code mode describes how the freeform exec tool works; it does not suppress the rest of the
627
+ // catalog. A turn can advertise freeform `exec` AND ordinary top-level tools at once, and
628
+ // telling the model those are "not separate top-level tools" would make it refuse tools that
629
+ // are right there in its catalog. Name the ones that stay callable instead.
630
+ const codeModeOtherTopLevelNames = codeMode
631
+ ? wireNames.filter(name => name !== CODEX_UNIFIED_EXEC_TOOL && !isCodexShellBridgeToolName(name))
632
+ : [];
416
633
  const shellBridgeLabel = quotedNames(shellBridgeNames.length > 0 ? shellBridgeNames : [...CODEX_SHELL_BRIDGE_TOOL_NAMES]);
417
634
  const hasApplyPatch = cursorRequestAdvertisesApplyPatch(tools, toolChoice);
635
+ const structuredEditNames = tools
636
+ ?.filter(tool => !tool.namespace && isCursorStructuredEditToolName(tool.name))
637
+ .map(tool => tool.name) ?? [];
418
638
  const discoveryTools = discoveryToolLabel(wireNames);
419
639
  const unavailableNeighborNames = unavailableNeighborAgentToolNames(wireNames);
420
640
  // Host-shell-neutral: the Codex client executes bridge commands, and may differ from
421
641
  // the OpenCodex proxy OS (LAN/SSH remote-proxy). Always cover PowerShell 5.1 pitfalls.
422
642
  const hostShellNote = hasBareExec
423
- ? "Match shell syntax to the Codex client host that runs the bridge (not only the proxy OS). Windows PowerShell 5.1: no CMD `cd /d`, no bash heredocs (`<<EOF`); `&&`/`||` are unsupported parser errors — prefer the bridge working-directory argument for directory changes, and use `if ($?) { ... }` for success-gated follow-up steps; do not treat `;` as a substitute for `&&`. POSIX: use portable commands. After a shell failure, make at most one corrected bridge attempt, then report the error and stop — do not repeat equivalent failing commands."
643
+ ? "Match shell syntax to the Codex client host that runs the bridge (not only the proxy OS). Windows PowerShell 5.1: no CMD `cd /d`, no bash heredocs (`<<EOF`); `&&`/`||` are unsupported parser errors — prefer the bridge working-directory argument for directory changes, and use `if ($?) { ... }` for success-gated follow-up steps; do not treat `;` as a substitute for `&&`. POSIX: use portable commands (`cat`/`ls`/`rg`); never emit Get-Content or Get-ChildItem unless the host shell is PowerShell. After a shell failure, make at most one corrected bridge attempt, then report the error and stop — do not repeat equivalent failing commands."
424
644
  : undefined;
425
645
  const notes = [
426
646
  `Cursor tool calls: available tool names are exactly ${listedNames}.`,
@@ -428,6 +648,14 @@ export function buildCursorToolGuidanceSystemNote(
428
648
  unavailableNeighborNames.length > 0
429
649
  ? `This turn does not expose neighboring-agent tool names ${quotedNames(unavailableNeighborNames)}; do not call or suggest them unless the catalog lists them.`
430
650
  : undefined,
651
+ // Code mode: shell/edit/MCP live inside freeform `exec` as nested helpers. Without this the
652
+ // model probes for a top-level shell tool that is not there.
653
+ codeMode
654
+ ? `\`${CODEX_UNIFIED_EXEC_TOOL}\` is Codex code mode: its body is JavaScript evaluated in a V8 isolate, not a shell command and not Node. Shell, file edits, and MCP are nested helpers called INSIDE that body as \`await tools.<name>(...)\`, for example \`await tools.exec_command({cmd: \"ls\"})\`. Read the tool description and the isolate global \`ALL_TOOLS\` (not \`tools.ALL_TOOLS\`) for helpers this turn provides; absence from the top-level catalog or from \`exec\`'s description is not absence. Those nested helpers are not themselves top-level tools, so do not call \`exec_command\` or \`shell_command\` at the top level here${codeModeOtherTopLevelNames.length > 0 ? `; every other tool this turn lists, including ${quotedNames(codeModeOtherTopLevelNames)}, remains callable at the top level as usual` : ""}.`
655
+ : undefined,
656
+ codeMode
657
+ ? "In code mode the isolate returns nothing on its own: call `text(...)` (or `notify(...)`) on any value you need to see, or the call completes with empty output. There is no `require`, no `module`, and no filesystem or network globals; reach the host only through the nested helpers."
658
+ : undefined,
431
659
  hasBareExec
432
660
  ? `${shellBridgeLabel} is the Codex Responses shell bridge for this turn, exposed through Cursor's tool protocol; it is not an external MCP server tool. \`shell_command\` and \`exec_command\` are aliases of the same bridge.`
433
661
  : undefined,
@@ -435,7 +663,7 @@ export function buildCursorToolGuidanceSystemNote(
435
663
  ? "Your tool list may display it under a longer `mcp_opencodex-responses_shell_command` / `mcp_opencodex-responses_exec_command` name; those are the SAME tool — call whichever your list shows, and do not comment on the naming difference to the user."
436
664
  : undefined,
437
665
  hasBareExec
438
- ? "Never tell the user that shell or read access is blocked, disabled, or denied unless the Codex shell bridge tool itself fails. Prefer the bridge over Cursor-native Shell/Read; do not narrate phrases like \"Native shell access is blocked\" silently call `shell_command` / `exec_command`."
666
+ ? `Prefer the Codex shell bridge over Cursor-native Shell/Read. If a Cursor-native file read, directory listing, grep, or shell operation is rejected, continue with the listed catalog tool ${shellBridgeLabel}.`
439
667
  : undefined,
440
668
  hostShellNote,
441
669
  "Cursor product features (Chronicle, screen recording, Notes, Plans, background agents) are available only if this turn's catalog lists a matching tool; do not offer or promise them otherwise.",
@@ -443,7 +671,9 @@ export function buildCursorToolGuidanceSystemNote(
443
671
  ? `For file read/search/listing, use ${shellBridgeLabel} when no more specific listed tool is available.`
444
672
  : undefined,
445
673
  hasApplyPatch
446
- ? "For file edits, use the `apply_patch` tool, not built-in file write/delete tools."
674
+ ? structuredEditNames.length > 0
675
+ ? `For file edits, prefer the structured edit tools ${quotedNames(structuredEditNames)} — they take replacements that OpenCodex converts into Codex \`apply_patch\` changes. Include exact leading whitespace in old_string/new_string. Use \`apply_patch\` directly only with a \`*** Begin Patch\` envelope and bare \`@@\` hunks (never git-style \`@@ -n,m +n,m @@\`); never emit patch-like plain text as tool arguments.`
676
+ : "For file edits, use the `apply_patch` tool, not built-in file write/delete tools."
447
677
  : undefined,
448
678
  hasBareExec
449
679
  ? "For tool-count demos, each counted tool must be a separate Codex shell-bridge invocation/result; do not collapse several requested tools into one chained shell command."
@@ -457,7 +687,7 @@ export function buildCursorToolGuidanceSystemNote(
457
687
  : undefined,
458
688
  "Do not count or report a tool call unless a tool result was actually returned.",
459
689
  hasBareExec
460
- ? `If a Cursor-native file read, directory listing, grep, or shell operation is rejected by the runtime, silently use ${shellBridgeLabel} with an equivalent host-shell-safe command (POSIX: \`cat\`/\`ls\`/\`rg\`; Windows PowerShell: \`Get-Content\`/\`Get-ChildItem\`/\`Select-String\`). Do not tell the user access is blocked. For file edits, use \`apply_patch\` when available.`
690
+ ? `If a Cursor-native file read, directory listing, grep, or shell operation is rejected by the runtime, use ${shellBridgeLabel} with an equivalent host-shell-safe command (POSIX: \`cat\`/\`ls\`/\`rg\`; Windows PowerShell: \`Get-Content\`/\`Get-ChildItem\`/\`Select-String\`). For file edits, use ${structuredEditNames.length > 0 ? `the structured edit tools (${quotedNames(structuredEditNames)}) or ` : ""}\`apply_patch\` when available.`
461
691
  : undefined,
462
692
  ].filter((note): note is string => typeof note === "string");
463
693
  return notes.join(" ");
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Cursor tool-result normalization for Computer Use / node_repl surfaces (#1920/#1866).
3
+ *
4
+ * Scoped re-implementation of PR #1920 per the 260818 campaign disposition
5
+ * (REDESIGN-SMALL: "apply formatted.text at native toolResultPart + decode test").
6
+ * Only empty-output and known-failure-state normalization ships here; screenshot
7
+ * stripping and AXTree text compaction from the original PR are deliberately out
8
+ * of scope (the native path already bounds step size by real serialized bytes,
9
+ * dropping images oldest-first — see toolCallStep in protobuf-request.ts).
10
+ */
11
+
12
+ const COMPUTER_USE_TOOL_NAMES = new Set([
13
+ "node_repl",
14
+ "node_repl__js",
15
+ "mcp__node_repl__js",
16
+ "get_app_state",
17
+ "list_apps",
18
+ "screenshot",
19
+ "computer_use",
20
+ ]);
21
+
22
+ function isNodeReplOrComputerUseTool(toolName?: string, toolNamespace?: string): boolean {
23
+ if (toolNamespace && (toolNamespace === "mcp__node_repl" || toolNamespace.includes("node_repl") || toolNamespace.includes("computer_use"))) {
24
+ return true;
25
+ }
26
+ if (!toolName) return false;
27
+ const lower = toolName.toLowerCase();
28
+ if (COMPUTER_USE_TOOL_NAMES.has(lower)) return true;
29
+ return lower.startsWith("mcp__node_repl") || lower.startsWith("mcp__computer_use");
30
+ }
31
+
32
+ /** Failure states the Computer Use / node_repl runtime reports as PLAIN TEXT inside a non-error result. */
33
+ const RUNTIME_FAILURE_GUIDANCE: ReadonlyArray<{ marker: string; guidance: string }> = [
34
+ {
35
+ marker: "SkyComputerUseError",
36
+ guidance: "The Computer Use runtime rejected this action. Re-check application state with get_app_state before retrying.",
37
+ },
38
+ {
39
+ marker: "sky is not defined",
40
+ guidance: "The sky binding is unavailable in this context; Computer Use calls only work inside the privileged node_repl session.",
41
+ },
42
+ {
43
+ marker: "has already been declared",
44
+ guidance: "The node_repl session keeps earlier declarations; rename the variable or use var/reassignment instead of redeclaring.",
45
+ },
46
+ {
47
+ marker: "unsupported import in exec",
48
+ guidance: "Imports are not available in this exec context; use the injected globals instead.",
49
+ },
50
+ ];
51
+
52
+ /** Matches exec wrappers whose only payload is an empty-output marker. */
53
+ const EMPTY_EXEC_OUTPUT_REGEX = /^(?:(?:Script completed|Script failed|Command finished|Execution finished)[^\n]*\n+)?(?:Wall time[^\n]*\n+)?(?:Output:\s*)?(?:<empty>)?\s*$/;
54
+
55
+ export interface NormalizedToolResultText {
56
+ text: string;
57
+ isError: boolean;
58
+ /** True when normalization changed either field (lets callers skip work on the common path). */
59
+ changed: boolean;
60
+ }
61
+
62
+ /**
63
+ * Normalize a Cursor-bound tool-result TEXT payload:
64
+ * - blank / empty-exec-wrapper output on Computer Use or node_repl tools becomes an
65
+ * actionable error instead of an empty string the model silently accepts;
66
+ * - known runtime failure states reported as plain text are marked isError with a
67
+ * one-line recovery hint appended.
68
+ * Everything else passes through byte-identical.
69
+ */
70
+ export function normalizeCursorToolResultText(
71
+ text: string,
72
+ options: { toolName?: string; toolNamespace?: string; isError?: boolean } = {},
73
+ ): NormalizedToolResultText {
74
+ const isError = options.isError === true;
75
+ const computerUse = isNodeReplOrComputerUseTool(options.toolName, options.toolNamespace);
76
+ if (computerUse && EMPTY_EXEC_OUTPUT_REGEX.test(text.trim())) {
77
+ return {
78
+ text: "[empty output: the tool ran but produced no stdout or return value. Verify application state with get_app_state, or make the script emit output.]",
79
+ isError: true,
80
+ changed: true,
81
+ };
82
+ }
83
+ if (!isError) {
84
+ for (const { marker, guidance } of RUNTIME_FAILURE_GUIDANCE) {
85
+ if (text.includes(marker)) {
86
+ return { text: `${text}\n[recovery: ${guidance}]`, isError: true, changed: true };
87
+ }
88
+ }
89
+ }
90
+ return { text, isError, changed: false };
91
+ }
92
+
@@ -12,16 +12,33 @@ export interface CursorTransport {
12
12
  * accepted is never replayed. Absent (undefined) is treated as "committed" — safe by default.
13
13
  */
14
14
  requestCommitted?(): boolean;
15
+ /**
16
+ * Last ConversationStateStructure captured from conversationCheckpointUpdate on this transport.
17
+ * Test and adapter seams use this instead of reaching into LiveCursorTransport.
18
+ */
19
+ capturedConversationCheckpoint?(): Uint8Array | undefined;
15
20
  }
16
21
 
17
22
  export interface CursorTransportFactoryInput {
18
23
  provider: OcxProviderConfig;
19
24
  translatorBudget: TranslatorBudget;
20
25
  headers?: Headers;
26
+ /** Router-prepared fetch that preserves provider overrides and per-request pacing. */
27
+ fetch?: typeof globalThis.fetch;
21
28
  /** Pre-first-frame deadline (dial + first server frame). Defaults to 30s when omitted. */
22
29
  firstFrameTimeoutMs?: number;
23
30
  /** Grace (ms) between close() and the force-destroy fallback after a first-frame timeout. Defaults to 1s. */
24
31
  timeoutDestroyGraceMs?: number;
32
+ /**
33
+ * T04 watchdog: maximum inbound decoded-frame silence (ms) after the first frame before the
34
+ * turn is failed. Defaults to 30s.
35
+ */
36
+ streamSilenceFailMs?: number;
37
+ /**
38
+ * T04 watchdog: maximum heartbeat/checkpoint-only traffic (ms) without turn progress before
39
+ * the turn is failed. Defaults to 90s.
40
+ */
41
+ streamHeartbeatOnlyFailMs?: number;
25
42
  /**
26
43
  * Grace window (ms) before a drained client-tool turn is finalized, so a sibling tool call
27
44
  * announced in a later receive chunk can revoke a premature finalize. Defaults to 50ms.
@@ -33,6 +50,11 @@ export interface CursorTransportFactoryInput {
33
50
  * native local exec authorization because the text is caller-controlled.
34
51
  */
35
52
  requestDeclaresFullAccess?: boolean;
53
+ /**
54
+ * Stable Cursor Connect `x-session-id` across transport rebuilds for the same
55
+ * client thread. Distinct from the per-transport native-exec/shell owner.
56
+ */
57
+ sessionId?: string;
36
58
  }
37
59
 
38
60
  export type CursorTransportFactory = (input: CursorTransportFactoryInput) => CursorTransport;
@@ -1,15 +1,30 @@
1
1
  import type { OcxUsage } from "../../types";
2
2
  import type { OcxMessage, OcxRequestOptions, OcxTool } from "../../types";
3
3
  import type { CursorRoutingLevel } from "./discovery";
4
+ import type { CursorCheckpointInvalidationReason } from "./checkpoint-store";
5
+ import type { ResolvedCursorImage } from "./images";
6
+
7
+ export interface CursorRequestedModelParameter {
8
+ id: string;
9
+ value: string;
10
+ }
4
11
 
5
12
  export interface CursorRunRequest {
6
13
  modelId: string;
14
+ /** Cursor model-picker parameters encoded through AgentRunRequest.requested_model. */
15
+ requestedModelParameters?: readonly CursorRequestedModelParameter[];
7
16
  /** Cursor Router optimization parameter; valid only while modelId is the `default` wire model. */
8
17
  routingLevel?: CursorRoutingLevel;
9
18
  conversationId: string;
10
19
  system: string[];
11
20
  messages: CursorRequestMessage[];
12
- rawMessages?: OcxMessage[];
21
+ rawMessages?: readonly OcxMessage[];
22
+ /**
23
+ * Images for the active user/developer turn. Encoded as SelectedImage blobIdWithData refs under
24
+ * UserMessage.selected_context (bytes live in the request-scoped KV store for getBlobArgs
25
+ * hydration). History stays text-only. data: URLs only in this slice.
26
+ */
27
+ selectedImages?: readonly ResolvedCursorImage[];
13
28
  tools?: OcxTool[];
14
29
  toolChoice?: OcxRequestOptions["toolChoice"];
15
30
  parallelToolCalls?: boolean;
@@ -24,6 +39,18 @@ export interface CursorRunRequest {
24
39
  * pre-compaction history being summarized and must not become the next turn's carry-forward total.
25
40
  */
26
41
  contextUsageStoreCheckpoints?: boolean;
42
+ /**
43
+ * Reuse a previously captured ConversationStateStructure instead of rebuilding historical
44
+ * root/turn blobs. Absent means the existing full-replay path.
45
+ */
46
+ checkpointBytes?: Uint8Array;
47
+ continuationMode?: "full-replay" | "checkpoint";
48
+ checkpointInvalidationReason?: CursorCheckpointInvalidationReason;
49
+ /**
50
+ * When set with checkpointBytes, only this suffix of rawMessages is replayed onto the
51
+ * decoded ConversationStateStructure. Used for tool-result continuations.
52
+ */
53
+ checkpointSuffixStart?: number;
27
54
  }
28
55
 
29
56
  export interface CursorRequestMessage {