@iislee/opencodex 2.11.0 → 2.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (733) hide show
  1. package/AGENTS_INSTALL.md +109 -0
  2. package/README.md +117 -22
  3. package/bin/ocx.mjs +245 -88
  4. package/bin/package-main.mjs +1 -1
  5. package/gui/dist/assets/index-Be1sDpWw.css +1 -0
  6. package/gui/dist/assets/index-D4OKgUV4.js +114 -0
  7. package/gui/dist/index.html +2 -2
  8. package/gui/dist/provider-icons/alibaba-color.svg +1 -1
  9. package/gui/dist/provider-icons/antigravity-color.svg +1 -1
  10. package/gui/dist/provider-icons/claude-color.svg +1 -1
  11. package/gui/dist/provider-icons/cline-color.svg +16 -0
  12. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
  13. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  14. package/gui/dist/provider-icons/copilot-color.svg +1 -1
  15. package/gui/dist/provider-icons/cursor-color.svg +1 -1
  16. package/gui/dist/provider-icons/deepseek-color.svg +1 -1
  17. package/gui/dist/provider-icons/firepass-color.svg +1 -1
  18. package/gui/dist/provider-icons/fireworks-color.svg +1 -1
  19. package/gui/dist/provider-icons/gemini-color.svg +1 -1
  20. package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
  21. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
  22. package/gui/dist/provider-icons/grok.svg +1 -1
  23. package/gui/dist/provider-icons/groq-color.svg +1 -1
  24. package/gui/dist/provider-icons/huggingface-color.svg +1 -1
  25. package/gui/dist/provider-icons/kimi-color.svg +1 -1
  26. package/gui/dist/provider-icons/kiro-color.svg +2 -2
  27. package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
  28. package/gui/dist/provider-icons/mistral-color.svg +1 -1
  29. package/gui/dist/provider-icons/moonshot-color.svg +1 -1
  30. package/gui/dist/provider-icons/nvidia-color.svg +1 -1
  31. package/gui/dist/provider-icons/ollama-color.svg +1 -1
  32. package/gui/dist/provider-icons/openai.svg +1 -1
  33. package/gui/dist/provider-icons/opencode.svg +2 -1
  34. package/gui/dist/provider-icons/openrouter-color.svg +1 -1
  35. package/gui/dist/provider-icons/pi.svg +2 -2
  36. package/gui/dist/provider-icons/qianfan-color.svg +1 -1
  37. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
  38. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
  39. package/gui/dist/provider-icons/vllm-color.svg +1 -1
  40. package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
  41. package/package.json +21 -10
  42. package/src/adapters/anthropic-output-schema.ts +137 -0
  43. package/src/adapters/anthropic.ts +475 -62
  44. package/src/adapters/base.ts +82 -7
  45. package/src/adapters/client-fingerprint.ts +18 -12
  46. package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
  47. package/src/adapters/command-code.ts +637 -0
  48. package/src/adapters/cursor/call-id.ts +44 -0
  49. package/src/adapters/cursor/catalog.ts +541 -0
  50. package/src/adapters/cursor/checkpoint-store.ts +308 -0
  51. package/src/adapters/cursor/cursor-errors.ts +144 -6
  52. package/src/adapters/cursor/discovery.ts +122 -14
  53. package/src/adapters/cursor/effort-map.ts +106 -4
  54. package/src/adapters/cursor/envelope-echo.ts +290 -0
  55. package/src/adapters/cursor/framing.ts +39 -0
  56. package/src/adapters/cursor/h2-pool.ts +123 -0
  57. package/src/adapters/cursor/http1-bidi.ts +361 -0
  58. package/src/adapters/cursor/images.ts +704 -0
  59. package/src/adapters/cursor/live-models.ts +180 -59
  60. package/src/adapters/cursor/live-transport.ts +623 -170
  61. package/src/adapters/cursor/message-mapper.ts +4 -1
  62. package/src/adapters/cursor/native-exec-common.ts +23 -2
  63. package/src/adapters/cursor/native-exec-desktop.ts +23 -0
  64. package/src/adapters/cursor/native-exec-fs.ts +10 -7
  65. package/src/adapters/cursor/native-exec-network.ts +1 -1
  66. package/src/adapters/cursor/native-exec-shell.ts +5 -3
  67. package/src/adapters/cursor/native-exec.ts +121 -14
  68. package/src/adapters/cursor/protobuf-events.ts +829 -11
  69. package/src/adapters/cursor/protobuf-request.ts +447 -75
  70. package/src/adapters/cursor/request-builder.ts +271 -35
  71. package/src/adapters/cursor/tool-definitions.ts +252 -12
  72. package/src/adapters/cursor/tool-result-normalize.ts +115 -0
  73. package/src/adapters/cursor/transport.ts +22 -0
  74. package/src/adapters/cursor/types.ts +48 -1
  75. package/src/adapters/cursor.ts +336 -39
  76. package/src/adapters/exec-tool-result-normalize.ts +99 -0
  77. package/src/adapters/google-antigravity-replay.ts +713 -41
  78. package/src/adapters/google-antigravity-wire.ts +48 -10
  79. package/src/adapters/google-errors.ts +44 -12
  80. package/src/adapters/google-http.ts +38 -10
  81. package/src/adapters/google-tool-schema.ts +80 -15
  82. package/src/adapters/google-truncation.ts +11 -0
  83. package/src/adapters/google.ts +742 -86
  84. package/src/adapters/identity.ts +39 -6
  85. package/src/adapters/image.ts +1 -1
  86. package/src/adapters/kiro-constants.ts +27 -0
  87. package/src/adapters/kiro-errors.ts +11 -0
  88. package/src/adapters/kiro-events.ts +19 -1
  89. package/src/adapters/kiro-thinking.ts +18 -2
  90. package/src/adapters/kiro-tools.ts +65 -17
  91. package/src/adapters/kiro.ts +270 -73
  92. package/src/adapters/mimo-free.ts +17 -0
  93. package/src/adapters/openai-chat-url.ts +11 -0
  94. package/src/adapters/openai-chat.ts +1377 -344
  95. package/src/adapters/openai-responses-url.ts +16 -0
  96. package/src/adapters/openai-responses.ts +1164 -64
  97. package/src/adapters/registry.ts +175 -0
  98. package/src/adapters/responses-tool-schema.ts +67 -0
  99. package/src/adapters/run-turn-queue.ts +36 -1
  100. package/src/adapters/tool-call-id.ts +119 -0
  101. package/src/adapters/tool-catalog-nudge.ts +105 -21
  102. package/src/adapters/xai-tool-schema.ts +436 -0
  103. package/src/adapters/xai-web-search.ts +186 -0
  104. package/src/bridge.ts +512 -92
  105. package/src/chat/inbound.ts +57 -20
  106. package/src/chat/outbound.ts +97 -33
  107. package/src/claude/agents-inject.ts +40 -10
  108. package/src/claude/context-windows.ts +37 -14
  109. package/src/claude/desktop-3p.ts +243 -9
  110. package/src/claude/gateway-cache.ts +41 -4
  111. package/src/claude/inbound.ts +72 -3
  112. package/src/claude/model-info.ts +38 -15
  113. package/src/claude/outbound.ts +88 -21
  114. package/src/cli/access.ts +46 -3
  115. package/src/cli/account-api.ts +150 -19
  116. package/src/cli/account-auth.ts +33 -6
  117. package/src/cli/account-catalog-refresh.ts +14 -0
  118. package/src/cli/account-extended.ts +648 -28
  119. package/src/cli/account-main.ts +317 -0
  120. package/src/cli/account.ts +97 -19
  121. package/src/cli/agent.ts +53 -2
  122. package/src/cli/alias.ts +66 -0
  123. package/src/cli/capabilities-command.ts +94 -0
  124. package/src/cli/capabilities.ts +496 -0
  125. package/src/cli/claude-agent-startup-sync.ts +73 -0
  126. package/src/cli/claude-desktop.ts +60 -15
  127. package/src/cli/claude.ts +129 -35
  128. package/src/cli/codex-log-guard-doctor.ts +103 -0
  129. package/src/cli/codex-shim-autorestore.ts +2 -0
  130. package/src/cli/codex-shim-readiness.ts +76 -0
  131. package/src/cli/combo.ts +8 -0
  132. package/src/cli/config-command.ts +74 -10
  133. package/src/cli/dispatch.ts +821 -0
  134. package/src/cli/doctor.ts +440 -56
  135. package/src/cli/ensure-desired-integrations.ts +152 -0
  136. package/src/cli/export-command.ts +46 -20
  137. package/src/cli/help.ts +34 -274
  138. package/src/cli/index.ts +417 -528
  139. package/src/cli/init.ts +5 -17
  140. package/src/cli/inspect.ts +230 -0
  141. package/src/cli/integrations.ts +120 -2
  142. package/src/cli/lab.ts +607 -0
  143. package/src/cli/launcher-context.ts +77 -0
  144. package/src/cli/minimax.ts +497 -0
  145. package/src/cli/models-runtime.ts +130 -2
  146. package/src/cli/models.ts +118 -16
  147. package/src/cli/observe.ts +123 -11
  148. package/src/cli/opencode.ts +4 -2
  149. package/src/cli/provider-runtime.ts +34 -3
  150. package/src/cli/provider.ts +25 -3
  151. package/src/cli/ready.ts +301 -0
  152. package/src/cli/registry.ts +476 -0
  153. package/src/cli/root.ts +86 -0
  154. package/src/cli/route-policy.ts +92 -0
  155. package/src/cli/runtime-api.ts +57 -10
  156. package/src/cli/star-prompt.ts +71 -15
  157. package/src/cli/status.ts +51 -4
  158. package/src/cli/storage.ts +234 -0
  159. package/src/cli/system-command.ts +16 -0
  160. package/src/cli/system-restart-client.ts +146 -0
  161. package/src/cli/tray-proxy.ts +153 -6
  162. package/src/cli/usage-report.ts +184 -0
  163. package/src/cli/v2.ts +137 -18
  164. package/src/cli/version-skew.ts +46 -0
  165. package/src/cli.ts +1 -1
  166. package/src/clients/config-export.ts +1442 -23
  167. package/src/clients/effective-status.ts +30 -2
  168. package/src/clients/probes/cline.ts +81 -0
  169. package/src/codex/account-label.ts +35 -1
  170. package/src/codex/account-lifecycle.ts +130 -13
  171. package/src/codex/account-namespaces.ts +49 -3
  172. package/src/codex/account-pause.ts +2 -1
  173. package/src/codex/account-priority.ts +84 -0
  174. package/src/codex/account-store.ts +29 -2
  175. package/src/codex/account-usability.ts +25 -2
  176. package/src/codex/admission.ts +256 -0
  177. package/src/codex/affinity-debug.ts +162 -0
  178. package/src/codex/app-server-processes.ts +570 -107
  179. package/src/codex/app-server-restart-service.ts +232 -0
  180. package/src/codex/auth-api.ts +893 -246
  181. package/src/codex/auth-collision.ts +5 -3
  182. package/src/codex/auth-context.ts +348 -32
  183. package/src/codex/autostart-health.ts +24 -1
  184. package/src/codex/catalog/account-models.ts +67 -0
  185. package/src/codex/catalog/aggregation.ts +86 -10
  186. package/src/codex/catalog/bundled.ts +331 -33
  187. package/src/codex/catalog/effort.ts +138 -32
  188. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  189. package/src/codex/catalog/kinds.ts +2 -0
  190. package/src/codex/catalog/metadata.ts +555 -45
  191. package/src/codex/catalog/native-models.ts +75 -0
  192. package/src/codex/catalog/parsing.ts +269 -30
  193. package/src/codex/catalog/provider-fetch.ts +1626 -144
  194. package/src/codex/catalog/sync.ts +1576 -187
  195. package/src/codex/catalog-admission.ts +199 -0
  196. package/src/codex/catalog-refresh-status.ts +105 -0
  197. package/src/codex/catalog-write-serialization.ts +242 -0
  198. package/src/codex/catalog.ts +6 -3
  199. package/src/codex/codex-write-lock.ts +386 -0
  200. package/src/codex/convergence-types.ts +614 -0
  201. package/src/codex/convergence.ts +676 -0
  202. package/src/codex/coordinator-doctor.ts +332 -0
  203. package/src/codex/custom-model-catalog-migration.ts +176 -0
  204. package/src/codex/desired-state.ts +230 -0
  205. package/src/codex/desktop-app-restart.ts +355 -0
  206. package/src/codex/features.ts +636 -39
  207. package/src/codex/generation.ts +202 -0
  208. package/src/codex/history-job.ts +436 -0
  209. package/src/codex/history-lock.ts +242 -0
  210. package/src/codex/history-manifest.ts +112 -0
  211. package/src/codex/history-migration-guardian.ts +30 -24
  212. package/src/codex/history-provider.ts +1016 -235
  213. package/src/codex/history-transition.ts +105 -0
  214. package/src/codex/history-worker.ts +223 -0
  215. package/src/codex/inject-coordination.ts +373 -0
  216. package/src/codex/inject.ts +1114 -152
  217. package/src/codex/injected-marker.ts +37 -3
  218. package/src/codex/integration-record.ts +266 -0
  219. package/src/codex/internal/catalog-writer.ts +203 -0
  220. package/src/codex/internal/history-writer.ts +81 -0
  221. package/src/codex/journal.ts +66 -4
  222. package/src/codex/log-guard/inspect.ts +524 -0
  223. package/src/codex/log-guard/lock.ts +150 -0
  224. package/src/codex/log-guard/maintenance.ts +403 -0
  225. package/src/codex/log-guard/path-safety.ts +88 -0
  226. package/src/codex/log-guard/policy.ts +44 -0
  227. package/src/codex/log-guard/processes.ts +205 -0
  228. package/src/codex/log-guard/protection.ts +489 -0
  229. package/src/codex/log-guard/sqlite-errors.ts +9 -0
  230. package/src/codex/main-account-cache.ts +24 -0
  231. package/src/codex/main-account.ts +29 -1
  232. package/src/codex/management-convergence.ts +167 -0
  233. package/src/codex/model-cache.ts +56 -10
  234. package/src/codex/model-entitlements.ts +360 -0
  235. package/src/codex/native-main-admission.ts +47 -0
  236. package/src/codex/native-main-auth-temp.ts +187 -0
  237. package/src/codex/native-main-claim.ts +178 -0
  238. package/src/codex/native-main-lock-file.ts +162 -0
  239. package/src/codex/native-main-owner.ts +329 -0
  240. package/src/codex/native-profile-api.ts +247 -0
  241. package/src/codex/native-profile-manager.ts +1531 -0
  242. package/src/codex/native-profile-processes.ts +121 -0
  243. package/src/codex/native-profile-recovery.ts +99 -0
  244. package/src/codex/native-profile-stage-store.ts +387 -0
  245. package/src/codex/native-profile-startup.ts +622 -0
  246. package/src/codex/native-profile-store.ts +855 -0
  247. package/src/codex/native-profile-types.ts +120 -0
  248. package/src/codex/native-residue.ts +675 -0
  249. package/src/codex/paths.ts +80 -1
  250. package/src/codex/plan-from-token.ts +140 -0
  251. package/src/codex/plan.ts +40 -0
  252. package/src/codex/plugins-doctor.ts +1 -1
  253. package/src/codex/pool-rotation.ts +74 -4
  254. package/src/codex/project-config-warnings.ts +20 -6
  255. package/src/codex/prompt-journal.ts +352 -0
  256. package/src/codex/prompt-layers.ts +1313 -0
  257. package/src/codex/prompt-lock.ts +143 -0
  258. package/src/codex/prompt-text-probe.ts +238 -0
  259. package/src/codex/quota-rejection.ts +298 -0
  260. package/src/codex/quota.ts +264 -21
  261. package/src/codex/refresh.ts +11 -2
  262. package/src/codex/reset-credit-recovery.ts +1044 -0
  263. package/src/codex/routing.ts +514 -94
  264. package/src/codex/runtime.ts +159 -38
  265. package/src/codex/shim.ts +1065 -31
  266. package/src/codex/subagent-model-fallback.ts +437 -43
  267. package/src/codex/sync.ts +191 -2
  268. package/src/codex/transition-state.ts +720 -0
  269. package/src/codex/upstream-host-health.ts +368 -0
  270. package/src/codex/user-identity.ts +557 -0
  271. package/src/codex/warmup.ts +187 -81
  272. package/src/codex/write-coordination.ts +114 -0
  273. package/src/combos/failover.ts +47 -0
  274. package/src/combos/index.ts +4 -0
  275. package/src/combos/request.ts +32 -0
  276. package/src/combos/types.ts +91 -9
  277. package/src/compatibility/index.ts +26 -0
  278. package/src/compatibility/manifest.ts +253 -0
  279. package/src/compatibility/openai-responses.ts +121 -0
  280. package/src/config/atomic-write.ts +219 -0
  281. package/src/config/paths.ts +40 -0
  282. package/src/config/process-state.ts +309 -0
  283. package/src/config/provider-name.ts +24 -0
  284. package/src/config/provider-validation.ts +177 -0
  285. package/src/config/rebase-provenance.ts +68 -0
  286. package/src/config.ts +1713 -709
  287. package/src/generated/compatibility-version.json +3324 -0
  288. package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
  289. package/src/grok/inject.ts +16 -5
  290. package/src/grok/inspect.ts +45 -0
  291. package/src/grok/sync.ts +2 -2
  292. package/src/images/loop.ts +157 -33
  293. package/src/images/plan.ts +24 -13
  294. package/src/integrations/config-io.ts +269 -0
  295. package/src/integrations/journal.ts +315 -0
  296. package/src/integrations/merge.ts +135 -0
  297. package/src/integrations/mutation-flight.ts +71 -0
  298. package/src/integrations/native/ownership-preflight.ts +202 -0
  299. package/src/integrations/omp-yaml-source.ts +358 -0
  300. package/src/integrations/owned-refresh.ts +74 -0
  301. package/src/integrations/ownership-policy.ts +160 -0
  302. package/src/integrations/ownership.ts +155 -0
  303. package/src/integrations/registry.ts +166 -0
  304. package/src/integrations/serialize.ts +314 -0
  305. package/src/integrations/state.ts +433 -0
  306. package/src/integrations/store.ts +103 -0
  307. package/src/integrations/writer-lock.ts +98 -0
  308. package/src/integrations/writer.ts +715 -0
  309. package/src/lab/artifacts/sanitize.ts +586 -0
  310. package/src/lab/artifacts/secure-fs.ts +475 -0
  311. package/src/lab/artifacts/store.ts +310 -0
  312. package/src/lab/automation/budgets.ts +78 -0
  313. package/src/lab/automation/config-persistence.ts +256 -0
  314. package/src/lab/automation/constants.ts +39 -0
  315. package/src/lab/automation/cooldown.ts +103 -0
  316. package/src/lab/automation/dispatch.ts +211 -0
  317. package/src/lab/automation/index.ts +13 -0
  318. package/src/lab/automation/orchestrator.ts +499 -0
  319. package/src/lab/automation/persistence.ts +512 -0
  320. package/src/lab/automation/planner.ts +371 -0
  321. package/src/lab/automation/policy.ts +136 -0
  322. package/src/lab/automation/queue.ts +191 -0
  323. package/src/lab/automation/recovery.ts +24 -0
  324. package/src/lab/automation/route-context.ts +21 -0
  325. package/src/lab/automation/run-key.ts +44 -0
  326. package/src/lab/automation/runs-query.ts +34 -0
  327. package/src/lab/automation/types.ts +160 -0
  328. package/src/lab/conformance/assertion.ts +325 -0
  329. package/src/lab/conformance/digest.ts +22 -0
  330. package/src/lab/conformance/executor.ts +741 -0
  331. package/src/lab/conformance/fixture-provider.ts +27 -0
  332. package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
  333. package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
  334. package/src/lab/conformance/harness-budget.ts +47 -0
  335. package/src/lab/conformance/index.ts +5 -0
  336. package/src/lab/conformance/jcs.ts +64 -0
  337. package/src/lab/conformance/json-pointer.ts +39 -0
  338. package/src/lab/conformance/manifest.ts +180 -0
  339. package/src/lab/conformance/mcp-stub.ts +179 -0
  340. package/src/lab/conformance/negative-controls.ts +164 -0
  341. package/src/lab/conformance/observation.ts +355 -0
  342. package/src/lab/conformance/runner.ts +68 -0
  343. package/src/lab/conformance/sse-normalize.ts +59 -0
  344. package/src/lab/conformance/suite-manifest.ts +78 -0
  345. package/src/lab/conformance/types.ts +214 -0
  346. package/src/lab/constants.ts +126 -0
  347. package/src/lab/digest.ts +64 -0
  348. package/src/lab/events/errors.ts +9 -0
  349. package/src/lab/events/limits.ts +117 -0
  350. package/src/lab/events/types.ts +229 -0
  351. package/src/lab/events/validate.ts +781 -0
  352. package/src/lab/fabric/constants.ts +40 -0
  353. package/src/lab/fabric/executor.ts +492 -0
  354. package/src/lab/fabric/index.ts +80 -0
  355. package/src/lab/fabric/manifest.ts +222 -0
  356. package/src/lab/fabric/observe.ts +489 -0
  357. package/src/lab/fabric/patch.ts +79 -0
  358. package/src/lab/fabric/producer-child.ts +139 -0
  359. package/src/lab/fabric/producer-isolate.ts +276 -0
  360. package/src/lab/fabric/producer-protocol.ts +61 -0
  361. package/src/lab/fabric/scratch.ts +439 -0
  362. package/src/lab/fabric/subject.ts +106 -0
  363. package/src/lab/fabric/types.ts +134 -0
  364. package/src/lab/fabric/verifier.ts +98 -0
  365. package/src/lab/index.ts +54 -0
  366. package/src/lab/ledger/artifact-refs.ts +127 -0
  367. package/src/lab/ledger/invalidation.ts +136 -0
  368. package/src/lab/ledger/purge.ts +310 -0
  369. package/src/lab/ledger/store.ts +532 -0
  370. package/src/lab/live/credential-lease.ts +53 -0
  371. package/src/lab/live/destination.ts +155 -0
  372. package/src/lab/live/executor.ts +336 -0
  373. package/src/lab/live/inert-tools.ts +56 -0
  374. package/src/lab/live/manifest.ts +85 -0
  375. package/src/lab/live/mcp-loopback.ts +57 -0
  376. package/src/lab/live/runner.ts +19 -0
  377. package/src/lab/live/sandbox.ts +61 -0
  378. package/src/lab/live/suite-manifest.ts +41 -0
  379. package/src/lab/live/transport.ts +118 -0
  380. package/src/lab/live/types.ts +197 -0
  381. package/src/lab/observe/from-conformance.ts +301 -0
  382. package/src/lab/observe/from-live.ts +117 -0
  383. package/src/lab/paths.ts +153 -0
  384. package/src/lab/projection/rebuild.ts +495 -0
  385. package/src/lab/projection/schema.ts +135 -0
  386. package/src/lab/projection/verdicts.ts +474 -0
  387. package/src/lab/projection/verification.ts +412 -0
  388. package/src/lab/public/bundle.ts +217 -0
  389. package/src/lab/public/community-authority.ts +175 -0
  390. package/src/lab/public/community-files.ts +29 -0
  391. package/src/lab/public/community.ts +479 -0
  392. package/src/lab/public/file-safety.ts +155 -0
  393. package/src/lab/public/ids.ts +26 -0
  394. package/src/lab/public/index.ts +16 -0
  395. package/src/lab/public/mutation-lock.ts +424 -0
  396. package/src/lab/public/operator.ts +353 -0
  397. package/src/lab/public/origin-purge.ts +79 -0
  398. package/src/lab/public/origin.ts +203 -0
  399. package/src/lab/public/privacy.ts +143 -0
  400. package/src/lab/public/private-file.ts +261 -0
  401. package/src/lab/public/project.ts +124 -0
  402. package/src/lab/public/purge-test-fault.ts +21 -0
  403. package/src/lab/public/purge.ts +223 -0
  404. package/src/lab/public/registry.ts +44 -0
  405. package/src/lab/public/revocation.ts +252 -0
  406. package/src/lab/public/signature.ts +243 -0
  407. package/src/lab/public/storage.ts +105 -0
  408. package/src/lab/public/strict-json.ts +206 -0
  409. package/src/lab/public/time.ts +26 -0
  410. package/src/lab/public/types.ts +172 -0
  411. package/src/lab/public/validate.ts +391 -0
  412. package/src/lab/query/catalog.ts +101 -0
  413. package/src/lab/query/connection.ts +107 -0
  414. package/src/lab/query/constants.ts +4 -0
  415. package/src/lab/query/cursor.ts +132 -0
  416. package/src/lab/query/dto-map.ts +277 -0
  417. package/src/lab/query/errors.ts +22 -0
  418. package/src/lab/query/freshness.ts +53 -0
  419. package/src/lab/query/index.ts +45 -0
  420. package/src/lab/query/latest-observation.ts +59 -0
  421. package/src/lab/query/passive-production.ts +159 -0
  422. package/src/lab/query/queries.ts +444 -0
  423. package/src/lab/query/types.ts +266 -0
  424. package/src/lab/subject/behavior-fingerprint.ts +77 -0
  425. package/src/lab/subject/installation-salt.ts +112 -0
  426. package/src/lab/subject/protocol-subject.ts +80 -0
  427. package/src/lab/subject/route-subject.ts +74 -0
  428. package/src/lib/admin-secrets.ts +24 -0
  429. package/src/lib/app-owned-memory-stores.ts +22 -0
  430. package/src/lib/bounded-body.ts +167 -11
  431. package/src/lib/bun-runtime.ts +125 -12
  432. package/src/lib/bun-stream-caps.ts +13 -9
  433. package/src/lib/codex-restart-contract.ts +120 -0
  434. package/src/lib/config-ownership.ts +26 -2
  435. package/src/lib/destination-policy.ts +65 -1
  436. package/src/lib/errors.ts +80 -5
  437. package/src/lib/fabric-task-execution-authority.ts +7 -0
  438. package/src/lib/fabric-task-host.ts +29 -0
  439. package/src/lib/lab-activation.ts +223 -0
  440. package/src/lib/lab-live-execution-authority.ts +13 -0
  441. package/src/lib/lab-live-host.ts +30 -0
  442. package/src/lib/lab-live-pinned-sender.ts +56 -0
  443. package/src/lib/lab-live-route-production.ts +130 -0
  444. package/src/lib/lab-passive-linker-registration.ts +26 -0
  445. package/src/lib/local-management-attestation.ts +51 -0
  446. package/src/lib/local-management-capability.ts +100 -0
  447. package/src/lib/local-provider-reload-contract.ts +100 -0
  448. package/src/lib/optional-shutdown-hooks.ts +57 -0
  449. package/src/lib/package-tree-integrity.ts +101 -0
  450. package/src/lib/pinned-http.ts +145 -26
  451. package/src/lib/process-control.ts +6 -2
  452. package/src/lib/provider-outbound.ts +49 -9
  453. package/src/lib/redact.ts +419 -3
  454. package/src/lib/self-launch-argv.ts +15 -0
  455. package/src/lib/server-resource-ownership.ts +71 -0
  456. package/src/lib/service-secrets.ts +15 -0
  457. package/src/lib/shadow-call.ts +35 -4
  458. package/src/lib/sse-decoder.ts +41 -0
  459. package/src/lib/state-store-registrations.ts +10 -2
  460. package/src/lib/system-restart-contract.ts +73 -0
  461. package/src/lib/token-estimate.ts +19 -2
  462. package/src/lib/tool-argument-integers.ts +253 -0
  463. package/src/lib/translator-budget.ts +44 -0
  464. package/src/lib/upstream-http-version.ts +57 -0
  465. package/src/lib/upstream-reachability.ts +95 -0
  466. package/src/lib/upstream-retry.ts +156 -3
  467. package/src/lib/windows-atomic-replace.ts +155 -0
  468. package/src/lib/windows-elevation.ts +70 -2
  469. package/src/lib/windows-secret-acl.ts +409 -69
  470. package/src/lib/windows-service-wrappers.ts +72 -0
  471. package/src/lib/windows-text.ts +106 -0
  472. package/src/lib/windows-user-principal.ts +341 -0
  473. package/src/lib/winsw.ts +33 -5
  474. package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
  475. package/src/oauth/account-import/index.ts +15 -0
  476. package/src/oauth/account-import/parser.ts +83 -0
  477. package/src/oauth/account-import/registry.ts +18 -0
  478. package/src/oauth/account-import/service.ts +75 -0
  479. package/src/oauth/account-import/types.ts +91 -0
  480. package/src/oauth/anthropic.ts +12 -1
  481. package/src/oauth/callback-server.ts +30 -4
  482. package/src/oauth/chatgpt.ts +12 -1
  483. package/src/oauth/cline.ts +203 -0
  484. package/src/oauth/command-code.ts +239 -0
  485. package/src/oauth/cursor.ts +46 -5
  486. package/src/oauth/generic-account-failover.ts +231 -0
  487. package/src/oauth/google-antigravity.ts +35 -3
  488. package/src/oauth/health.ts +20 -12
  489. package/src/oauth/index.ts +462 -71
  490. package/src/oauth/key-providers.ts +25 -0
  491. package/src/oauth/kimi.ts +25 -3
  492. package/src/oauth/kiro.ts +95 -6
  493. package/src/oauth/local-token-detect.ts +13 -2
  494. package/src/oauth/log.ts +3 -1
  495. package/src/oauth/login-cli.ts +88 -28
  496. package/src/oauth/nous.ts +798 -0
  497. package/src/oauth/open-browser-choice.ts +26 -0
  498. package/src/oauth/store.ts +133 -26
  499. package/src/oauth/token-guardian.ts +9 -3
  500. package/src/oauth/types.ts +15 -0
  501. package/src/pi/models.ts +2 -2
  502. package/src/providers/alibaba-region-migration.ts +1 -1
  503. package/src/providers/antigravity-models.ts +521 -31
  504. package/src/providers/auto-compact-budget.ts +65 -0
  505. package/src/providers/base-url-choices.ts +10 -0
  506. package/src/providers/codex-capacity.ts +292 -0
  507. package/src/providers/command-code-efforts.ts +176 -0
  508. package/src/providers/context-cap.ts +26 -8
  509. package/src/providers/cursor-pool.ts +72 -0
  510. package/src/providers/default-aliases.ts +65 -0
  511. package/src/providers/derive.ts +281 -6
  512. package/src/providers/fastwire.ts +507 -0
  513. package/src/providers/free-directory.ts +10 -7
  514. package/src/providers/google-vertex-location.ts +14 -0
  515. package/src/providers/key-failover.ts +71 -3
  516. package/src/providers/label.ts +35 -2
  517. package/src/providers/model-discovery-limits.ts +16 -0
  518. package/src/providers/model-discovery.ts +115 -22
  519. package/src/providers/model-presets.ts +119 -0
  520. package/src/providers/model-rename-migration.ts +255 -0
  521. package/src/providers/model-rename-startup.ts +28 -0
  522. package/src/providers/new-model-policy.ts +146 -0
  523. package/src/providers/openai-sidecar.ts +72 -4
  524. package/src/providers/openai-tier-startup.ts +31 -2
  525. package/src/providers/openai-tiers.ts +119 -4
  526. package/src/providers/openai-virtual-models.ts +1 -0
  527. package/src/providers/opencode-zen-rate-limit.ts +102 -0
  528. package/src/providers/provider-id-rewrite.ts +30 -0
  529. package/src/providers/quota.ts +1379 -40
  530. package/src/providers/registry.ts +1545 -112
  531. package/src/providers/request-pacing.ts +310 -0
  532. package/src/providers/service-tier.ts +277 -0
  533. package/src/providers/slug-codec.ts +94 -6
  534. package/src/providers/static-model-discovery.ts +86 -0
  535. package/src/providers/xai-responses-opt-in.ts +15 -0
  536. package/src/providers/xai-transport.ts +32 -4
  537. package/src/reasoning-effort.ts +68 -3
  538. package/src/responses/apply-patch-envelope.ts +63 -0
  539. package/src/responses/code-mode-helper-compat.ts +50 -0
  540. package/src/responses/compaction.ts +26 -1
  541. package/src/responses/custom-tool-compat.ts +384 -0
  542. package/src/responses/hosted-tool-policy.ts +9 -0
  543. package/src/responses/namespace-tool-compat.ts +435 -0
  544. package/src/responses/parser.ts +225 -38
  545. package/src/responses/provider-continuation.ts +98 -0
  546. package/src/responses/provider-opaque-metadata.ts +73 -0
  547. package/src/responses/reasoning-envelope.ts +9 -1
  548. package/src/responses/reasoning-replay-cache.ts +504 -0
  549. package/src/responses/schema.ts +12 -2
  550. package/src/responses/spill-store.ts +75 -10
  551. package/src/responses/state.ts +659 -31
  552. package/src/responses/thought-signature-replay.ts +364 -0
  553. package/src/responses/tool-search-compat.ts +301 -0
  554. package/src/responses/truncated-stop-reason.ts +60 -0
  555. package/src/responses/turn-termination.ts +107 -0
  556. package/src/router.ts +405 -31
  557. package/src/routing/analytics.ts +379 -0
  558. package/src/routing/capability.ts +244 -0
  559. package/src/routing/compatibility/assemble.ts +73 -0
  560. package/src/routing/compatibility/behavior.ts +278 -0
  561. package/src/routing/compatibility/catalog.ts +99 -0
  562. package/src/routing/compatibility/endpoint.ts +52 -0
  563. package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
  564. package/src/routing/compatibility/policy.ts +181 -0
  565. package/src/routing/compatibility/provider-slot.ts +56 -0
  566. package/src/routing/compatibility/reader.ts +110 -0
  567. package/src/routing/compatibility/subject.ts +191 -0
  568. package/src/routing/compatibility/types.ts +64 -0
  569. package/src/routing/compatibility/version.ts +104 -0
  570. package/src/routing/cost.ts +77 -0
  571. package/src/routing/evaluator.ts +495 -0
  572. package/src/routing/health.ts +412 -0
  573. package/src/routing/history/cursor.ts +43 -0
  574. package/src/routing/history/indexer.ts +605 -0
  575. package/src/routing/history/schema.ts +72 -0
  576. package/src/routing/profile-namespace.ts +15 -0
  577. package/src/routing/profile.ts +547 -0
  578. package/src/routing/quota.ts +155 -0
  579. package/src/routing/request-evidence.ts +45 -0
  580. package/src/routing/trace.ts +776 -0
  581. package/src/server/adapter-resolve.ts +2 -29
  582. package/src/server/auth-cors.ts +289 -48
  583. package/src/server/background-lifecycle.ts +182 -0
  584. package/src/server/chat-completions.ts +154 -72
  585. package/src/server/chat-native-sse.ts +331 -0
  586. package/src/server/chat-native.ts +445 -0
  587. package/src/server/claude-messages.ts +160 -44
  588. package/src/server/direct-local-http.ts +347 -0
  589. package/src/server/effort-policy.ts +18 -0
  590. package/src/server/github-copilot-responses-repair.ts +338 -0
  591. package/src/server/gui-static.ts +39 -10
  592. package/src/server/images.ts +94 -12
  593. package/src/server/index.ts +1021 -190
  594. package/src/server/lifecycle.ts +336 -14
  595. package/src/server/live.ts +136 -17
  596. package/src/server/local-management-read-client.ts +90 -0
  597. package/src/server/local-provider-reload-client.ts +137 -0
  598. package/src/server/management/agent-settings-routes.ts +433 -116
  599. package/src/server/management/api-key-usage.ts +31 -5
  600. package/src/server/management/body.ts +6 -0
  601. package/src/server/management/codex-prompt-routes.ts +570 -0
  602. package/src/server/management/combo-routes.ts +64 -25
  603. package/src/server/management/config-routes.ts +511 -51
  604. package/src/server/management/context.ts +89 -2
  605. package/src/server/management/integration-routes.ts +498 -0
  606. package/src/server/management/lab-automation-routes.ts +206 -0
  607. package/src/server/management/lab-routes.ts +563 -0
  608. package/src/server/management/logs-usage-routes.ts +127 -52
  609. package/src/server/management/model-routes.ts +461 -133
  610. package/src/server/management/model-rows.ts +167 -0
  611. package/src/server/management/native-integration-routes.ts +770 -0
  612. package/src/server/management/oauth-account-routes.ts +90 -8
  613. package/src/server/management/provider-capability-config.ts +48 -0
  614. package/src/server/management/provider-routes.ts +836 -159
  615. package/src/server/management/request-history-routes.ts +191 -0
  616. package/src/server/management/route-registry.ts +332 -0
  617. package/src/server/management/routing-analytics-routes.ts +74 -0
  618. package/src/server/management/routing-profile-routes.ts +380 -0
  619. package/src/server/management/shared.ts +27 -11
  620. package/src/server/management/sidebar-routes.ts +47 -31
  621. package/src/server/management/storage-log-guard-routes.ts +186 -0
  622. package/src/server/management/sync-response.ts +69 -0
  623. package/src/server/management/system-restart.ts +289 -33
  624. package/src/server/management/system-routes.ts +77 -0
  625. package/src/server/management/usage-summary-cache.ts +9 -1
  626. package/src/server/management/vision-sidecar-options.ts +167 -0
  627. package/src/server/management/web-search-sidecar-options.ts +120 -0
  628. package/src/server/management-api.ts +126 -23
  629. package/src/server/management-auth.ts +220 -5
  630. package/src/server/passive-route-linker.ts +66 -0
  631. package/src/server/port-reclaim.ts +1 -1
  632. package/src/server/ports.ts +41 -1
  633. package/src/server/proxy-liveness.ts +161 -10
  634. package/src/server/readiness.ts +99 -0
  635. package/src/server/relay-eager.ts +221 -54
  636. package/src/server/relay.ts +479 -87
  637. package/src/server/request-decompress.ts +113 -6
  638. package/src/server/request-log-conversation.ts +51 -0
  639. package/src/server/request-log.ts +298 -31
  640. package/src/server/responses/agent-task-recovery-cache.ts +143 -0
  641. package/src/server/responses/agent-task-recovery.ts +465 -0
  642. package/src/server/responses/codex-auth-error.ts +55 -0
  643. package/src/server/responses/collaboration.ts +239 -36
  644. package/src/server/responses/combo-stream-preflight.ts +178 -0
  645. package/src/server/responses/compact.ts +444 -72
  646. package/src/server/responses/core.ts +3579 -436
  647. package/src/server/responses/empty-completion-guard.ts +333 -0
  648. package/src/server/responses/encrypted-payload.ts +62 -39
  649. package/src/server/responses/fetch-helpers.ts +89 -99
  650. package/src/server/responses/input-admission.ts +187 -0
  651. package/src/server/responses/pacing-overload.ts +13 -0
  652. package/src/server/responses/passthrough-error.ts +33 -9
  653. package/src/server/responses/policy-fallback.ts +178 -0
  654. package/src/server/responses/responses-field-backfill.ts +343 -0
  655. package/src/server/responses/terminal-guard.ts +26 -5
  656. package/src/server/responses/upstream-error.ts +5 -0
  657. package/src/server/responses/ws-upstream.ts +381 -0
  658. package/src/server/responses-custom-tool-repair.ts +363 -0
  659. package/src/server/responses-item-id-repair.ts +54 -6
  660. package/src/server/responses-json-events.ts +90 -0
  661. package/src/server/responses-model-rewrite.ts +29 -0
  662. package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
  663. package/src/server/responses-snapshot-repair.ts +621 -0
  664. package/src/server/responses-terminal-repair.ts +363 -0
  665. package/src/server/responses-tool-search-repair.ts +267 -0
  666. package/src/server/responses-undeclared-tool-guard.ts +376 -0
  667. package/src/server/responses.ts +18 -2
  668. package/src/server/search.ts +78 -13
  669. package/src/server/sse-frame-buffer.ts +319 -0
  670. package/src/server/sse-payload-rewrite.ts +110 -22
  671. package/src/server/startup-action-control.ts +8 -1
  672. package/src/server/startup-health-cache.ts +19 -1
  673. package/src/server/system-env.ts +80 -9
  674. package/src/server/ws-bridge.ts +53 -40
  675. package/src/service-manager-probe.ts +892 -0
  676. package/src/service.ts +1153 -94
  677. package/src/sidecar/auth.ts +92 -0
  678. package/src/sidecar/candidates.ts +83 -0
  679. package/src/storage/cleanup.ts +2 -2
  680. package/src/storage/policy-job.ts +14 -4
  681. package/src/storage/policy.ts +88 -23
  682. package/src/storage/scanner.ts +1 -1
  683. package/src/storage/worker-lifecycle.ts +14 -14
  684. package/src/tray/windows-tray.ps1 +83 -9
  685. package/src/tray/windows.ts +43 -16
  686. package/src/types/accounts.ts +37 -0
  687. package/src/types/config.ts +911 -0
  688. package/src/types/provider.ts +614 -0
  689. package/src/types/request.ts +397 -0
  690. package/src/types/tools.ts +236 -0
  691. package/src/types/wire.ts +80 -0
  692. package/src/types.ts +107 -1237
  693. package/src/update/index.ts +37 -23
  694. package/src/update/job.ts +445 -68
  695. package/src/update/notify.ts +12 -6
  696. package/src/update/npm-cache-preflight.d.mts +47 -0
  697. package/src/update/npm-cache-preflight.mjs +201 -0
  698. package/src/update/transactional-install.d.mts +22 -0
  699. package/src/update/transactional-install.mjs +266 -0
  700. package/src/usage/cost.ts +0 -0
  701. package/src/usage/expected-prices.ts +287 -16
  702. package/src/usage/log.ts +666 -50
  703. package/src/usage/summary.ts +388 -17
  704. package/src/usage/user-cost-overlay-reconciler.ts +313 -0
  705. package/src/usage/user-cost-overlays.ts +314 -0
  706. package/src/vision/anthropic-describe.ts +10 -6
  707. package/src/vision/backends.ts +97 -0
  708. package/src/vision/describe.ts +27 -16
  709. package/src/vision/eligibility.ts +250 -0
  710. package/src/vision/index.ts +238 -24
  711. package/src/vision/reasoning.ts +55 -0
  712. package/src/vision/routed-describe.ts +175 -0
  713. package/src/vision/timeout-bounds.ts +9 -0
  714. package/src/web-search/anthropic-executor.ts +13 -7
  715. package/src/web-search/backends.ts +108 -0
  716. package/src/web-search/exa-executor.ts +119 -0
  717. package/src/web-search/executor.ts +21 -6
  718. package/src/web-search/gemini-executor.ts +141 -0
  719. package/src/web-search/index.ts +150 -15
  720. package/src/web-search/loop.ts +284 -54
  721. package/src/web-search/parse.ts +125 -30
  722. package/src/web-search/sources.ts +60 -0
  723. package/src/web-search/xai-executor.ts +219 -0
  724. package/gui/dist/assets/index-DTpMHS4F.js +0 -67
  725. package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
  726. package/gui/dist/provider-icons/antigravity.svg +0 -1
  727. package/gui/dist/provider-icons/claude.svg +0 -1
  728. package/gui/dist/provider-icons/copilot.svg +0 -1
  729. package/gui/dist/provider-icons/cursor.svg +0 -2
  730. package/gui/dist/provider-icons/gemini.svg +0 -1
  731. package/gui/dist/provider-icons/grok-color.svg +0 -1
  732. package/gui/dist/provider-icons/kiro.svg +0 -14
  733. package/src/cli/internal-dispatch.ts +0 -20
@@ -3,19 +3,42 @@ import type { AdapterEvent, OcxProviderConfig } from "../types";
3
3
  import type { ProviderAdapter } from "./base";
4
4
  import { isTranslatorBudgetExceededError } from "../lib/translator-budget";
5
5
  import { cursorExecDeniedMessage, cursorRequestDeclaresFullAccess } from "./cursor/exec-policy";
6
- import { isCursorBenignCancelError, isCursorInvalidArgumentError, safeCursorErrorMessage } from "./cursor/cursor-errors";
7
- import { isCursorExternalWireModel } from "./cursor/discovery";
6
+ import { isCursorBenignCancelError, isCursorInvalidArgumentError, safeCursorErrorMessage, type CursorSizeContext } from "./cursor/cursor-errors";
7
+ import { cursorCheckpointModelAffinityId, inferCursorContextWindow, isCursorExternalWireModel } from "./cursor/discovery";
8
8
  import { createCursorKvStore, type CursorKvStore } from "./cursor/kv-store";
9
9
  import { mapCursorServerMessage } from "./cursor/message-mapper";
10
- import { createCursorRequest } from "./cursor/request-builder";
10
+ import {
11
+ createCursorRequest,
12
+ cursorClientThreadOwner,
13
+ cursorCoveredPrefixDigest,
14
+ cursorInstructionDigest,
15
+ } from "./cursor/request-builder";
11
16
  import {
12
17
  createLiveCursorTransport,
13
18
  CursorMissingCredentialError,
14
19
  rekeyCursorContextUsage,
15
20
  resolveCursorToken,
21
+ capturedCursorCheckpointBytes,
16
22
  } from "./cursor/live-transport";
23
+ import {
24
+ commitCursorCheckpoint,
25
+ cursorCheckpointRefHash,
26
+ invalidateCursorCheckpoint,
27
+ } from "./cursor/checkpoint-store";
28
+ import { debugProviderDiagnostic } from "../lib/debug";
29
+ import { estimateTokens } from "../lib/token-estimate";
17
30
  import { rememberCursorThreadConversation } from "./cursor/thread-continuity";
18
31
  import { runCursorTurnWithRetry } from "./cursor/transport-retry";
32
+ import { cursorRequestHasShellAlias, cursorRequestUsesCodeMode } from "./cursor/tool-definitions";
33
+ import {
34
+ CURSOR_ECHO_RETRY_CONTINUATION_TEXT,
35
+ CURSOR_ROUTING_COMMENTARY_RETRY_TEXT,
36
+ CursorEnvelopeEchoSniffer,
37
+ CursorMidstreamEchoObserver,
38
+ CursorRoutingCommentaryError,
39
+ CursorRoutingCommentarySniffer,
40
+ CursorToolResultEchoError,
41
+ } from "./cursor/envelope-echo";
19
42
  import {
20
43
  createDisabledCursorTransport,
21
44
  CursorTransportDisabledError,
@@ -42,16 +65,29 @@ export interface CursorAdapterDeps {
42
65
  rekeyContextUsage?: (fromConversationId: string, toConversationId: string) => void;
43
66
  }
44
67
 
45
- function safeCursorTransportError(err: unknown): string {
68
+ function safeCursorTransportError(err: unknown, sizeContext?: CursorSizeContext): string {
46
69
  if (err instanceof CursorTransportDisabledError) return CURSOR_TRANSPORT_DISABLED_MESSAGE;
47
70
  if (err instanceof CursorMissingCredentialError) {
48
71
  return "Cursor live transport is enabled, but no Cursor access token is configured. Set provider.apiKey or OPENCODEX_CURSOR_TEST_TOKEN.";
49
72
  }
50
73
  const message = err instanceof Error ? err.message : typeof err === "string" ? err : undefined;
51
- if (message) return safeCursorErrorMessage(message);
74
+ if (message) return safeCursorErrorMessage(message, sizeContext);
52
75
  return "Cursor upstream error: transport failed before completion.";
53
76
  }
54
77
 
78
+ /**
79
+ * Size prior for bare resource_exhausted classification (devlog 260): a rough input
80
+ * estimate over the outgoing text vs the model's context window. Only used to keep
81
+ * SMALL requests on the 429 class — unknown/large stays on the overflow mapping.
82
+ */
83
+ function cursorRequestSizeContext(request: { modelId: string; system: string[]; messages: { content: string }[] }): CursorSizeContext {
84
+ const text = [...request.system, ...request.messages.map(message => message.content)].join("\n");
85
+ return {
86
+ estimatedInputTokens: estimateTokens(text, request.modelId),
87
+ contextWindow: inferCursorContextWindow(request.modelId),
88
+ };
89
+ }
90
+
55
91
  export function createCursorAdapter(provider: OcxProviderConfig, deps: CursorAdapterDeps = {}): ProviderAdapter {
56
92
  return {
57
93
  name: "cursor",
@@ -77,6 +113,9 @@ export function createCursorAdapter(provider: OcxProviderConfig, deps: CursorAda
77
113
  emit({ type: "error", message: "Cursor turn was aborted before start." });
78
114
  return;
79
115
  }
116
+ // Captured after createCursorRequest so the catch block can apply the bare-RE
117
+ // size prior (devlog 260) even though `request` is scoped inside the try.
118
+ let requestSizeContext: CursorSizeContext | undefined;
80
119
  try {
81
120
  const makeTransport = deps.createTransport ?? createLiveCursorTransport;
82
121
  const kv = deps.kv ?? createCursorKvStore({}, incoming.translatorBudget);
@@ -96,8 +135,10 @@ export function createCursorAdapter(provider: OcxProviderConfig, deps: CursorAda
96
135
  /* Missing credential is handled by the live transport path below. */
97
136
  }
98
137
  }
138
+ const inheritedCheckpointRef = _parsed._providerContinuation?.cursor?.checkpointRef;
99
139
  const previousConversationId = _parsed._cursorConversationId;
100
140
  let request = createCursorRequest(_parsed);
141
+ requestSizeContext = cursorRequestSizeContext(request);
101
142
  // The builder may derive a stable provider id from the client thread when Responses state
102
143
  // is unavailable. Rekey only existing state; there is nothing to migrate on a fresh turn,
103
144
  // and isolated helper/compaction turns must never inherit or donate the parent's usage state.
@@ -112,8 +153,115 @@ export function createCursorAdapter(provider: OcxProviderConfig, deps: CursorAda
112
153
  let emittedOutput = false;
113
154
  let replayUnsafe = false;
114
155
  const lastRawIsToolResult = _parsed.context.messages.at(-1)?.role === "toolResult";
156
+ let completedNormally = false;
157
+ let lastTransport: { captured?: Uint8Array } | undefined;
158
+ let emittedClientTool = false;
159
+ // Ordering proof for tool-suspended checkpoints: true only when the newest captured
160
+ // checkpoint bytes arrived AFTER the turn emitted a client tool call, i.e. upstream
161
+ // serialized its suspended-on-tool-call state. Only that snapshot can safely resume
162
+ // with the covered-prefix + trailing-toolResult path (devlog 260826 050).
163
+ let capturedAfterClientTool = false;
164
+
165
+ const commitCapturedCheckpoint = (activeRequest: ReturnType<typeof createCursorRequest>): void => {
166
+ const toolSuspendedCommit =
167
+ emittedClientTool
168
+ && capturedAfterClientTool
169
+ && isCursorExternalWireModel(activeRequest.modelId);
170
+ if (
171
+ replayUnsafe
172
+ || (emittedClientTool && !toolSuspendedCommit)
173
+ || activeRequest.contextUsageStoreCheckpoints === false
174
+ || !lastTransport?.captured
175
+ || lastTransport.captured.byteLength === 0
176
+ ) {
177
+ // Refusal diagnostics (devlog 260826 050/080): name the exact guard so a live
178
+ // missing_ref chain can be attributed without instrumented rebuilds.
179
+ debugProviderDiagnostic("cursor", "checkpoint-commit-refused", {
180
+ replayUnsafe,
181
+ emittedClientTool,
182
+ capturedAfterClientTool,
183
+ externalModel: isCursorExternalWireModel(activeRequest.modelId),
184
+ storeCheckpoints: activeRequest.contextUsageStoreCheckpoints !== false,
185
+ capturedBytes: lastTransport?.captured?.byteLength ?? 0,
186
+ });
187
+ return;
188
+ }
189
+ const previousRef = _parsed._providerContinuation?.cursor?.checkpointRef;
190
+ const coveredMessageCount = _parsed.context.messages.length;
191
+ const checkpointRef = commitCursorCheckpoint({
192
+ conversationId: activeRequest.conversationId,
193
+ identityScope: _parsed._cursorIdentityScope,
194
+ modelId: cursorCheckpointModelAffinityId(activeRequest.modelId),
195
+ checkpointBytes: lastTransport.captured,
196
+ coveredMessageCount,
197
+ prefixDigest: cursorCoveredPrefixDigest(_parsed, coveredMessageCount),
198
+ systemDigest: cursorInstructionDigest(_parsed),
199
+ });
200
+ if (!checkpointRef) return;
201
+ if (previousRef && previousRef !== checkpointRef) invalidateCursorCheckpoint(previousRef);
202
+ _parsed._providerContinuation = {
203
+ ...(_parsed._providerContinuation ?? {}),
204
+ cursor: {
205
+ ...(_parsed._providerContinuation?.cursor ?? {}),
206
+ conversationId: activeRequest.conversationId,
207
+ // A tool-suspended checkpoint is only usable by the immediate trailing-toolResult
208
+ // continuation; the request-builder guard keys on checkpointUsable=false for that.
209
+ checkpointUsable: !toolSuspendedCommit,
210
+ checkpointRef,
211
+ },
212
+ };
213
+ debugProviderDiagnostic("cursor", "checkpoint-continuation", {
214
+ mode: activeRequest.continuationMode ?? "full-replay",
215
+ conversationHash: activeRequest.conversationId.slice(0, 16),
216
+ checkpointRefHash: cursorCheckpointRefHash(checkpointRef),
217
+ checkpointBytes: lastTransport.captured.byteLength,
218
+ wireModel: activeRequest.modelId,
219
+ ...(toolSuspendedCommit ? { toolSuspended: true } : {}),
220
+ });
221
+ };
115
222
 
116
223
  const runOnce = async (activeRequest: ReturnType<typeof createCursorRequest>) => {
224
+ // Envelope echo quarantine (devlog 260826 gap-10): external full-replay continuations
225
+ // whose trailing input is a tool result sometimes ECHO the replayed "[Tool Result]"
226
+ // envelope as assistant text (kimi-k3 ~30-40% of multi-round probes). Hold the first
227
+ // text deltas until they provably diverge from the markers; a completed marker turns
228
+ // the turn into a retryable semantic failure BEFORE any client-visible delta escapes.
229
+ // Armed for ANY external turn whose replayed history contains a tool result — echo
230
+ // priming was observed live on user-action rounds too (the envelope lives in the
231
+ // flattened history regardless of which role ends the input).
232
+ const armEchoSniffer =
233
+ isCursorExternalWireModel(activeRequest.modelId)
234
+ && (_parsed.context.messages ?? []).some(message => message.role === "toolResult");
235
+ const echoSniffer = armEchoSniffer ? new CursorEnvelopeEchoSniffer() : undefined;
236
+ // Mid-stream observer (devlog 260828 F1/F2): diagnostic-only; armed with the
237
+ // prefix sniffer because both fire on flattened tool-result replay priming.
238
+ const midstreamObserver = armEchoSniffer ? new CursorMidstreamEchoObserver() : undefined;
239
+ const armRoutingCommentarySniffer =
240
+ isCursorExternalWireModel(activeRequest.modelId)
241
+ && (
242
+ cursorRequestUsesCodeMode(activeRequest.tools, activeRequest.toolChoice)
243
+ || cursorRequestHasShellAlias(activeRequest.tools)
244
+ );
245
+ const routingCommentarySniffer = armRoutingCommentarySniffer
246
+ ? new CursorRoutingCommentarySniffer()
247
+ : undefined;
248
+ let guardHeld: AdapterEvent[] = [];
249
+ // Exactly-once observation: every client-bound text delta passes through here
250
+ // exactly once — held deltas only on release, ordinary deltas at emit time.
251
+ const emitTextObserved = (event: AdapterEvent): void => {
252
+ if (event.type === "text_delta") midstreamObserver?.feed(event.text);
253
+ emit(event);
254
+ };
255
+ const releaseGuardHeld = () => {
256
+ for (const held of guardHeld) {
257
+ if (held.type !== "heartbeat") emittedOutput = true;
258
+ emitTextObserved(held);
259
+ }
260
+ guardHeld = [];
261
+ };
262
+ const guardsSettled = () =>
263
+ (!echoSniffer || echoSniffer.settled)
264
+ && (!routingCommentarySniffer || routingCommentarySniffer.settled);
117
265
  await runCursorTurnWithRetry(
118
266
  makeTransport,
119
267
  {
@@ -121,6 +269,8 @@ export function createCursorAdapter(provider: OcxProviderConfig, deps: CursorAda
121
269
  headers: incoming.headers,
122
270
  translatorBudget: incoming.translatorBudget,
123
271
  requestDeclaresFullAccess: cursorRequestDeclaresFullAccess(activeRequest),
272
+ sessionId: activeRequest.conversationId,
273
+ ...(incoming.providerFetch ? { fetch: incoming.providerFetch } : {}),
124
274
  },
125
275
  activeRequest,
126
276
  incoming.abortSignal,
@@ -130,15 +280,89 @@ export function createCursorAdapter(provider: OcxProviderConfig, deps: CursorAda
130
280
  return;
131
281
  }
132
282
  if (message.type === "local_side_effect") replayUnsafe = true;
133
- const events = mapCursorServerMessage(message, {
134
- kv,
135
- writeClient: clientMessage => {
136
- void activeTransport.writeClient(clientMessage);
137
- },
138
- });
139
- for (const event of events) {
283
+ if (message.type === "done") completedNormally = true;
284
+ if (message.type === "tool_call_end") emittedClientTool = true;
285
+ const captured = capturedCursorCheckpointBytes(activeTransport);
286
+ if (captured) {
287
+ if (captured !== lastTransport?.captured) capturedAfterClientTool = emittedClientTool;
288
+ lastTransport = { captured };
289
+ }
290
+ const events = mapCursorServerMessage(message, {
291
+ kv,
292
+ writeClient: clientMessage => {
293
+ void activeTransport.writeClient(clientMessage);
294
+ },
295
+ });
296
+ for (const event of events) {
297
+ if (!guardsSettled()) {
298
+ if (event.type === "text_delta") {
299
+ guardHeld.push(event);
300
+ if (echoSniffer && !echoSniffer.settled) {
301
+ const decision = echoSniffer.feed(event.text);
302
+ if (decision.kind === "echo") {
303
+ guardHeld = [];
304
+ throw new CursorToolResultEchoError(decision.marker);
305
+ }
306
+ }
307
+ if (routingCommentarySniffer && !routingCommentarySniffer.settled) {
308
+ const decision = routingCommentarySniffer.feed(event.text);
309
+ if (decision.kind === "hallucination") {
310
+ guardHeld = [];
311
+ throw new CursorRoutingCommentaryError();
312
+ }
313
+ }
314
+ if (guardsSettled()) releaseGuardHeld();
315
+ continue;
316
+ } else if (event.type === "thinking_delta" || event.type === "heartbeat") {
317
+ // Reasoning before first text stays ordered; liveness still passes through.
318
+ if (event.type === "thinking_delta") {
319
+ guardHeld.push(event);
320
+ continue;
321
+ }
322
+ } else {
323
+ // A tool call, done, or error closes the text quarantine. Re-check the full
324
+ // held first line before release so a fragmented routing claim cannot leak.
325
+ echoSniffer?.finish();
326
+ const routingDecision = routingCommentarySniffer?.finish();
327
+ if (routingDecision?.kind === "hallucination") {
328
+ guardHeld = [];
329
+ throw new CursorRoutingCommentaryError();
330
+ }
331
+ releaseGuardHeld();
332
+ }
333
+ }
140
334
  if (event.type !== "heartbeat") emittedOutput = true;
141
- emit(event);
335
+ if (event.type === "done") {
336
+ for (const finding of midstreamObserver?.findings() ?? []) {
337
+ debugProviderDiagnostic("cursor", "midstream-envelope-echo", {
338
+ wireModel: activeRequest.modelId,
339
+ conversationHash: activeRequest.conversationId.slice(0, 16),
340
+ marker: finding.marker,
341
+ offset: finding.offset,
342
+ callIdCorrupt: finding.callIdCorrupt,
343
+ });
344
+ }
345
+ commitCapturedCheckpoint(activeRequest);
346
+ const inheritedCursor = _parsed._providerContinuation?.cursor;
347
+ const isolatedOrCompaction =
348
+ _parsed._cursorIsolateConversation === true
349
+ || activeRequest.contextUsageStoreCheckpoints === false;
350
+ const providerState = inheritedCursor
351
+ ? {
352
+ cursor: isolatedOrCompaction
353
+ ? {
354
+ conversationId: activeRequest.conversationId,
355
+ ...(inheritedCursor.checkpointUsable !== undefined
356
+ ? { checkpointUsable: inheritedCursor.checkpointUsable }
357
+ : {}),
358
+ }
359
+ : { ...inheritedCursor, conversationId: activeRequest.conversationId },
360
+ }
361
+ : undefined;
362
+ emit(providerState ? { ...event, providerState } : event);
363
+ } else {
364
+ emitTextObserved(event);
365
+ }
142
366
  }
143
367
  },
144
368
  );
@@ -147,35 +371,108 @@ export function createCursorAdapter(provider: OcxProviderConfig, deps: CursorAda
147
371
  try {
148
372
  await runOnce(request);
149
373
  } catch (err) {
150
- // One-shot fallback for external-model Connect invalid_argument before any
151
- // non-heartbeat output. Retries apply only to safe plain-user turns; tool-result
152
- // resumes, local exec/MCP side effects, and already-emitted output fail closed.
374
+ const outputGuardRetryText =
375
+ err instanceof CursorToolResultEchoError
376
+ ? CURSOR_ECHO_RETRY_CONTINUATION_TEXT
377
+ : err instanceof CursorRoutingCommentaryError
378
+ ? CURSOR_ROUTING_COMMENTARY_RETRY_TEXT
379
+ : undefined;
380
+ // One-shot corrective retry for guarded external output (devlog 260826 gap-10/11).
381
+ // The quarantine guarantees no client-visible delta escaped, so a fresh-conversation
382
+ // retry is safe. A second rejection propagates as an error rather than looping.
153
383
  if (
154
- !isCursorInvalidArgumentError(err)
155
- || !isCursorExternalWireModel(request.modelId)
156
- || lastRawIsToolResult
157
- || emittedOutput
158
- || replayUnsafe
159
- || incoming.abortSignal?.aborted
384
+ outputGuardRetryText
385
+ && !emittedOutput
386
+ && !replayUnsafe
387
+ && !incoming.abortSignal?.aborted
160
388
  ) {
161
- throw err;
162
- }
163
- const failedConversationId = request.conversationId;
164
- _parsed._cursorConversationId = undefined;
165
- request = createCursorRequest(_parsed, { forceFreshConversation: true });
166
- rekeyContextUsage(failedConversationId, request.conversationId);
167
- _parsed._cursorConversationId = request.conversationId;
168
- // Persist recovery for store:false clients that only send a parent thread id, so the
169
- // next turn does not recompute the stale deterministic thread hash. Isolated helper /
170
- // compaction turns must not park their throwaway id under the parent thread key.
171
- if (_parsed._clientThreadId && _parsed._cursorIsolateConversation !== true) {
172
- rememberCursorThreadConversation(
173
- _parsed._clientThreadId,
174
- request.conversationId,
175
- _parsed._cursorIdentityScope,
389
+ debugProviderDiagnostic(
390
+ "cursor",
391
+ err instanceof CursorToolResultEchoError
392
+ ? "envelope-echo-retry"
393
+ : "routing-commentary-retry",
394
+ {
395
+ wireModel: request.modelId,
396
+ conversationHash: request.conversationId.slice(0, 16),
397
+ },
176
398
  );
399
+ const echoedConversationId = request.conversationId;
400
+ lastTransport = undefined;
401
+ _parsed._cursorConversationId = undefined;
402
+ request = {
403
+ ...createCursorRequest(_parsed, { forceFreshConversation: true }),
404
+ echoRetryContinuationText: outputGuardRetryText,
405
+ };
406
+ rekeyContextUsage(echoedConversationId, request.conversationId);
407
+ _parsed._cursorConversationId = request.conversationId;
408
+ const echoThreadOwner = cursorClientThreadOwner(_parsed);
409
+ if (echoThreadOwner && _parsed._cursorIsolateConversation !== true) {
410
+ rememberCursorThreadConversation(
411
+ echoThreadOwner,
412
+ request.conversationId,
413
+ _parsed._cursorIdentityScope,
414
+ );
415
+ }
416
+ await runOnce(request);
417
+ } else {
418
+ // One-shot fallback for external-model Connect invalid_argument before any
419
+ // non-heartbeat output. Retries apply only to safe plain-user turns; tool-result
420
+ // resumes, local exec/MCP side effects, and already-emitted output fail closed.
421
+ if (
422
+ !isCursorInvalidArgumentError(err)
423
+ || !isCursorExternalWireModel(request.modelId)
424
+ || lastRawIsToolResult
425
+ || emittedOutput
426
+ || replayUnsafe
427
+ || incoming.abortSignal?.aborted
428
+ ) {
429
+ throw err;
430
+ }
431
+ const failedConversationId = request.conversationId;
432
+ lastTransport = undefined;
433
+ _parsed._cursorConversationId = undefined;
434
+ request = createCursorRequest(_parsed, { forceFreshConversation: true });
435
+ rekeyContextUsage(failedConversationId, request.conversationId);
436
+ _parsed._cursorConversationId = request.conversationId;
437
+ // Persist recovery for store:false clients that send any stable Cursor thread owner, so
438
+ // the next turn does not recompute the stale deterministic thread hash. Isolated helper /
439
+ // compaction turns must not park their throwaway id under the parent or Desktop owner.
440
+ const threadOwner = cursorClientThreadOwner(_parsed);
441
+ if (threadOwner && _parsed._cursorIsolateConversation !== true) {
442
+ rememberCursorThreadConversation(
443
+ threadOwner,
444
+ request.conversationId,
445
+ _parsed._cursorIdentityScope,
446
+ );
447
+ }
448
+ await runOnce(request);
449
+ }
450
+ }
451
+ if (
452
+ request.checkpointInvalidationReason
453
+ && request.checkpointInvalidationReason !== "missing_ref"
454
+ ) {
455
+ invalidateCursorCheckpoint(inheritedCheckpointRef);
456
+ debugProviderDiagnostic("cursor", "checkpoint-invalidated", {
457
+ reason: request.checkpointInvalidationReason,
458
+ });
459
+ } else if (!completedNormally && request.checkpointInvalidationReason) {
460
+ debugProviderDiagnostic("cursor", "checkpoint-invalidated", {
461
+ reason: request.checkpointInvalidationReason,
462
+ });
463
+ }
464
+ if (
465
+ _parsed._cursorIsolateConversation === true
466
+ || request.contextUsageStoreCheckpoints === false
467
+ ) {
468
+ const inherited = _parsed._providerContinuation?.cursor;
469
+ if (inherited) {
470
+ const { checkpointRef: _ignoredCheckpointRef, ...cursorWithoutCheckpointRef } = inherited;
471
+ _parsed._providerContinuation = {
472
+ ...(_parsed._providerContinuation ?? {}),
473
+ cursor: cursorWithoutCheckpointRef,
474
+ };
177
475
  }
178
- await runOnce(request);
179
476
  }
180
477
  } catch (err) {
181
478
  if (isCursorBenignCancelError(err)) return;
@@ -184,7 +481,7 @@ export function createCursorAdapter(provider: OcxProviderConfig, deps: CursorAda
184
481
  type: "error",
185
482
  message: isTranslatorBudgetExceededError(err)
186
483
  ? "upstream translation buffer exceeded the safe limit"
187
- : safeCursorTransportError(err),
484
+ : safeCursorTransportError(err, requestSizeContext),
188
485
  ...(isTranslatorBudgetExceededError(err)
189
486
  ? { status: 502, errorType: "upstream_error", code: "translation_buffer_limit" }
190
487
  : {}),
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Provider-neutral empty-exec-output normalization.
3
+ *
4
+ * A code-mode `exec` cell that never calls `text()`/`notify()` returns nothing: the last
5
+ * expression value is NOT echoed automatically. The routed model reads a blank tool result,
6
+ * concludes its earlier output was lost, and burns turns re-running the same call or restarting
7
+ * the task from scratch. Naming that state explicitly is what breaks the loop.
8
+ *
9
+ * This module owns the shared detection so every adapter reports the same thing. Cursor keeps its
10
+ * own wrapper (`normalizeCursorToolResultText`) for Computer Use precedence and isError policy;
11
+ * Kiro consumes this helper directly.
12
+ */
13
+
14
+ /**
15
+ * Matches exec wrappers whose only payload is an empty-output marker.
16
+ *
17
+ * `Script failed` is deliberately NOT in this set. A failed cell with no captured output is still
18
+ * a FAILURE, and the success guidance below ("not a blocked tool", "do not re-run") would erase the
19
+ * only signal that anything went wrong — reachable through Responses history, where
20
+ * `function_call_output` is parsed with `isError: false`. Cursor keeps its own broader regex for
21
+ * Computer Use, where a failed wrapper is separately marked `isError`.
22
+ */
23
+ export const EMPTY_EXEC_OUTPUT_REGEX = /^(?:(?:Script completed|Command finished|Execution finished)[^\n]*\n+)?(?:Wall time[^\n]*\n+)?(?:Output:\s*)?(?:<empty>)?\s*$/;
24
+
25
+ /** Wrapper for a cell that FAILED without emitting output: empty, but not a success. */
26
+ export const FAILED_EXEC_OUTPUT_REGEX = /^Script failed[^\n]*\n*(?:Wall time[^\n]*\n*)?(?:Output:\s*)?(?:<empty>)?\s*$/;
27
+
28
+ /** Guidance for a failed cell whose output was empty: the failure must survive normalization. */
29
+ export const FAILED_EXEC_OUTPUT_MESSAGE =
30
+ "[exec failed with no captured output: the cell raised before emitting anything. This is a real failure, not an empty success — inspect the call for a thrown error or syntax problem before retrying.]";
31
+
32
+ /**
33
+ * The guidance itself. Worded to close all three wrong conclusions a model draws from a blank
34
+ * result: that context was lost, that the tool is blocked, and that retrying will differ.
35
+ */
36
+ export const EMPTY_EXEC_OUTPUT_MESSAGE =
37
+ "[empty output: the exec cell completed but emitted nothing. This is NOT lost context and NOT a blocked tool — in code mode call text(...) or notify(...) on any value you need to see (a bare await tools.exec_command(...) is not echoed automatically); in shell mode the command simply printed nothing. Do not re-run the same call expecting different output.]";
38
+
39
+ /**
40
+ * The SAME rule stated BEFORE the first call, for the code-mode tool-catalog nudge.
41
+ *
42
+ * `EMPTY_EXEC_OUTPUT_MESSAGE` above is a repair: it fires only after a model has already spent a
43
+ * call and read a blank result. That recovers the turn but cannot prevent the wasted round trip,
44
+ * and the model still has to guess whether its command failed or its output was merely dropped.
45
+ * Stating the echo rule up front removes the failure instead of explaining it afterwards.
46
+ *
47
+ * Kept beside the recovery text on purpose: the two are one pair guarding one defect, and wording
48
+ * that drifts apart is how a model gets told two different things about the same isolate.
49
+ */
50
+ export const CODE_MODE_RESULT_ECHO_SENTENCE =
51
+ "Nothing in the isolate is echoed automatically: a bare trailing `await tools.<name>(...)` or final expression value is DISCARDED, and the cell reports empty output. Pass anything you need to read to `text(...)` (or `notify(...)`) in the same cell — for example `text(JSON.stringify(await tools.exec_command({cmd: \"ls\"})))` — and treat an empty result as your own missing `text(...)` call rather than a failed command or lost context.";
52
+
53
+ /**
54
+ * Codex exec / shell-bridge tool names (flat and MCP-prefixed display aliases). An empty result
55
+ * here is almost always a code-mode cell that never called text()/notify().
56
+ */
57
+ export function isCodexExecBridgeTool(toolName?: string, toolNamespace?: string): boolean {
58
+ if (toolNamespace && toolNamespace.includes("opencodex-responses")) return true;
59
+ if (!toolName) return false;
60
+ const lower = toolName.toLowerCase();
61
+ return (
62
+ lower === "exec"
63
+ || lower === "exec_command"
64
+ || lower === "shell_command"
65
+ // Codex CLI/desktop native tool names: the multi-round "이전 출력이 비어 있어 처음부터"
66
+ // restart loop reproduced via codex exec because `shell` was not in this set
67
+ // (devlog 260826 gap-8 QA round 2).
68
+ || lower === "shell"
69
+ || lower === "local_shell"
70
+ || lower === "container.exec"
71
+ || lower.startsWith("mcp_opencodex-responses_")
72
+ || lower.startsWith("mcp__opencodex-responses__")
73
+ );
74
+ }
75
+
76
+ /** True when this result is an exec-bridge call that produced no usable output. */
77
+ export function isEmptyExecToolResult(
78
+ text: string,
79
+ options: { toolName?: string; toolNamespace?: string } = {},
80
+ ): boolean {
81
+ return isCodexExecBridgeTool(options.toolName, options.toolNamespace)
82
+ && EMPTY_EXEC_OUTPUT_REGEX.test(text.trim());
83
+ }
84
+
85
+ /**
86
+ * Returns the guidance text when this is an empty exec-bridge result, else `undefined` so the
87
+ * caller keeps its own fallback. Undefined rather than the original text: an adapter must be able
88
+ * to tell "not my case" from "normalized to the same string".
89
+ */
90
+ export function normalizeEmptyExecToolResultText(
91
+ text: string,
92
+ options: { toolName?: string; toolNamespace?: string } = {},
93
+ ): string | undefined {
94
+ if (!isCodexExecBridgeTool(options.toolName, options.toolNamespace)) return undefined;
95
+ const trimmed = text.trim();
96
+ // Failure first: a failed wrapper must never be described as an empty success.
97
+ if (FAILED_EXEC_OUTPUT_REGEX.test(trimmed)) return FAILED_EXEC_OUTPUT_MESSAGE;
98
+ return EMPTY_EXEC_OUTPUT_REGEX.test(trimmed) ? EMPTY_EXEC_OUTPUT_MESSAGE : undefined;
99
+ }