@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
@@ -168,6 +168,45 @@ export function decodeAvailableConnectFrames(
168
168
  }
169
169
  }
170
170
 
171
+ /**
172
+ * Cursor-based sibling of decodeAvailableConnectFrames for callers that keep
173
+ * their own raw backlog: consumes complete frames from the FRONT of `input`
174
+ * and reports how many bytes were consumed (headers included) instead of
175
+ * materializing a remainder copy, and hands payload VIEWS (not copies) back so
176
+ * the caller can transfer the already-charged bytes to the frame lifecycle
177
+ * instead of reserving a second copy. The caller advances its own cursor by
178
+ * `consumedBytes` and never pays an O(backlog) copy per drain.
179
+ */
180
+ export function consumeConnectFrames(
181
+ input: Uint8Array,
182
+ maxPayloadBytes = MAX_CONNECT_FRAME_PAYLOAD_BYTES,
183
+ availableFrameSlots = Number.POSITIVE_INFINITY,
184
+ ): { frames: ConnectFrame[]; consumedBytes: number } {
185
+ const planned: InspectedConnectFrame[] = [];
186
+ let offset = 0;
187
+ while (offset < input.length && planned.length < availableFrameSlots) {
188
+ const inspected = inspectConnectFrame(input, offset, maxPayloadBytes);
189
+ if (!inspected) break;
190
+ planned.push(inspected);
191
+ offset += inspected.readBytes;
192
+ }
193
+ // Zero-copy handoff for large payloads: VIEWS into the caller's backlog
194
+ // buffer (safe: append-only at its end, compaction/growth replace the
195
+ // buffer, a consumed region is never mutated in place). Small payloads are
196
+ // COPIED instead — a small view would pin the whole backlog buffer (up to
197
+ // 32 MiB) alive while the frame waits in the work queue.
198
+ const COPY_PIN_THRESHOLD_BYTES = 64 * 1024;
199
+ const frames = planned.map(({ flags, length, payloadStart }) => ({
200
+ flags,
201
+ payload: length <= COPY_PIN_THRESHOLD_BYTES
202
+ ? input.slice(payloadStart, payloadStart + length)
203
+ : input.subarray(payloadStart, payloadStart + length),
204
+ compressed: isConnectFrameCompressed(flags),
205
+ endStream: isConnectFrameEndStream(flags),
206
+ }));
207
+ return { frames, consumedBytes: offset };
208
+ }
209
+
171
210
  function inspectConnectFrame(
172
211
  input: Uint8Array,
173
212
  offset: number,
@@ -0,0 +1,123 @@
1
+ import http2 from "node:http2";
2
+ import { registerOptionalShutdownHook } from "../../lib/optional-shutdown-hooks";
3
+
4
+ const DEFAULT_MAX_SESSIONS = 8;
5
+ const SESSION_CLOSE_TIMEOUT_MS = 2_000;
6
+
7
+ interface PoolEntry {
8
+ readonly session: http2.ClientHttp2Session;
9
+ readonly streams: Set<http2.ClientHttp2Stream>;
10
+ usable: boolean;
11
+ }
12
+
13
+ /**
14
+ * HTTP/2 connection pool for Cursor Connect DISCOVERY calls (GetUsableModels).
15
+ * Sessions are keyed by origin (scheme+host+port) and reused to avoid fresh
16
+ * TCP+TLS per call. The Run path deliberately dials its own session: Run
17
+ * streams are long-lived bidi whose lifecycle/EOF semantics are owned by
18
+ * live-transport (see devlog 260822_senpi_cursor_transfer/190 — Run-path
19
+ * pooling is a separate, deliberate unit if ever taken).
20
+ */
21
+ export class CursorH2SessionPool {
22
+ private readonly entries = new Map<string, PoolEntry>();
23
+ private closed = false;
24
+
25
+ constructor(private readonly maxSessions = DEFAULT_MAX_SESSIONS) {}
26
+
27
+ /**
28
+ * Lazily registered on first use so a process that never talks to Cursor registers
29
+ * nothing (optional-subsystem doctrine). The seam is synchronous and best-effort;
30
+ * shutdown() is fire-and-forget there because lifecycle's drainAndShutdown runs
31
+ * under its own absolute deadline.
32
+ */
33
+ private armShutdownHook: (() => void) | undefined = () => {
34
+ this.armShutdownHook = undefined;
35
+ registerOptionalShutdownHook("cursor-h2-pool", () => { void this.shutdown(); });
36
+ };
37
+
38
+ request(
39
+ url: string,
40
+ headers: http2.OutgoingHttpHeaders,
41
+ ): http2.ClientHttp2Stream {
42
+ if (this.closed) throw new Error("Cursor H2 session pool is closed");
43
+ this.armShutdownHook?.();
44
+ const origin = new URL(url).origin;
45
+ const entry = this.usableEntry(origin) ?? this.createEntry(origin);
46
+ try {
47
+ const stream = entry.session.request(headers);
48
+ entry.streams.add(stream);
49
+ stream.once("close", () => { entry.streams.delete(stream); });
50
+ return stream;
51
+ } catch (error) {
52
+ this.drain(entry, true);
53
+ throw error;
54
+ }
55
+ }
56
+
57
+ async shutdown(): Promise<void> {
58
+ if (this.closed) return;
59
+ this.closed = true;
60
+ const pending: Promise<void>[] = [];
61
+ for (const entry of [...this.entries.values()]) {
62
+ for (const stream of [...entry.streams]) stream.destroy();
63
+ entry.session.close();
64
+ if (entry.session.destroyed) continue;
65
+ pending.push(new Promise<void>(resolve => {
66
+ const timer = setTimeout(resolve, SESSION_CLOSE_TIMEOUT_MS);
67
+ timer.unref?.();
68
+ entry.session.once("close", () => { clearTimeout(timer); resolve(); });
69
+ }));
70
+ }
71
+ this.entries.clear();
72
+ await Promise.all(pending);
73
+ }
74
+
75
+ get size(): number { return this.entries.size; }
76
+
77
+ private usableEntry(origin: string): PoolEntry | undefined {
78
+ const entry = this.entries.get(origin);
79
+ if (!entry) return undefined;
80
+ if (entry.usable && !entry.session.closed && !entry.session.destroyed) return entry;
81
+ this.drain(entry, false);
82
+ return undefined;
83
+ }
84
+
85
+ private createEntry(origin: string): PoolEntry {
86
+ const session = http2.connect(origin);
87
+ const entry: PoolEntry = {
88
+ session,
89
+ streams: new Set(),
90
+ usable: true,
91
+ };
92
+ this.entries.set(origin, entry);
93
+ session.once("goaway", () => { this.drain(entry, true); });
94
+ session.on("error", () => { this.drain(entry, false); });
95
+ session.once("close", () => {
96
+ // Identity check: a stale close event from an old session must not evict
97
+ // a healthy replacement entry that was created after drain() removed the old one.
98
+ if (this.entries.get(origin) === entry) this.entries.delete(origin);
99
+ });
100
+ // Enforce bound: evict oldest when over capacity.
101
+ while (this.entries.size > this.maxSessions) {
102
+ const oldest = this.entries.keys().next().value;
103
+ if (!oldest || oldest === origin) break;
104
+ const old = this.entries.get(oldest);
105
+ if (old) this.drain(old, true);
106
+ }
107
+ return entry;
108
+ }
109
+
110
+ private drain(entry: PoolEntry, closeSession: boolean): void {
111
+ entry.usable = false;
112
+ for (const stream of [...entry.streams]) stream.destroy();
113
+ entry.streams.clear();
114
+ if (closeSession) entry.session.close();
115
+ // Remove from map by finding the matching key.
116
+ for (const [key, value] of this.entries) {
117
+ if (value === entry) { this.entries.delete(key); break; }
118
+ }
119
+ }
120
+ }
121
+
122
+ /** Shared singleton pool for all Cursor adapter H2 traffic. */
123
+ export const cursorH2Pool = new CursorH2SessionPool();
@@ -0,0 +1,361 @@
1
+ import { create, toBinary } from "@bufbuild/protobuf";
2
+ import type { TranslatorBudget } from "../../lib/translator-budget";
3
+ import { CURSOR_MAX_EFFECTIVE_CONNECT_PAYLOAD_BYTES } from "../../lib/translator-budget";
4
+ import { readBoundedResponseBytes } from "../../lib/bounded-body";
5
+ import { withUpstreamHttpVersionValue } from "../../lib/upstream-http-version";
6
+ import { isPreConnectReachabilityError } from "../../lib/upstream-reachability";
7
+ import { BidiRequestIdSchema } from "./gen/agent_pb";
8
+ import { consumeConnectFrames, encodeConnectFrame } from "./framing";
9
+
10
+ const CURSOR_RUN_SSE_PATH = "/agent.v1.AgentService/RunSSE";
11
+ const CURSOR_BIDI_APPEND_PATH = "/aiserver.v1.BidiService/BidiAppend";
12
+ const CURSOR_HTTP1_APPEND_TIMEOUT_MS = 30_000;
13
+ const CURSOR_HTTP1_APPEND_RESPONSE_MAX_BYTES = 64 * 1024;
14
+ const HEX = "0123456789abcdef";
15
+
16
+ export interface CursorHttp1BidiCallbacks {
17
+ onCommitted(): void;
18
+ onData(chunk: Uint8Array): void;
19
+ onEnd(): void;
20
+ onError(error: Error): void;
21
+ }
22
+
23
+ export interface CursorHttp1BidiOptions {
24
+ baseUrl: string;
25
+ token: string;
26
+ clientVersion: string;
27
+ sessionId: string;
28
+ requestId: string;
29
+ translatorBudget: TranslatorBudget;
30
+ callbacks: CursorHttp1BidiCallbacks;
31
+ fetch?: typeof globalThis.fetch;
32
+ }
33
+
34
+ interface PendingAppend {
35
+ payload: Uint8Array;
36
+ seqno: bigint;
37
+ rawBytesCharged: boolean;
38
+ }
39
+
40
+ function varintLength(value: bigint): number {
41
+ let length = 1;
42
+ for (let current = value; current >= 0x80n; current >>= 7n) length += 1;
43
+ return length;
44
+ }
45
+
46
+ function writeVarint(target: Uint8Array, offset: number, value: bigint): number {
47
+ let current = value;
48
+ while (current >= 0x80n) {
49
+ target[offset++] = Number(current & 0x7fn) | 0x80;
50
+ current >>= 7n;
51
+ }
52
+ target[offset++] = Number(current);
53
+ return offset;
54
+ }
55
+
56
+ function requestIdMessageBytes(requestId: string): Uint8Array {
57
+ const value = new TextEncoder().encode(requestId);
58
+ const message = new Uint8Array(1 + varintLength(BigInt(value.byteLength)) + value.byteLength);
59
+ let offset = 0;
60
+ message[offset++] = 0x0a; // field 1, string request_id
61
+ offset = writeVarint(message, offset, BigInt(value.byteLength));
62
+ message.set(value, offset);
63
+ return message;
64
+ }
65
+
66
+ /** Exact encoded size of Cursor's aiserver.v1.BidiAppendRequest hex fallback shape. */
67
+ export function cursorBidiAppendRequestSize(payloadBytes: number, requestId: string, seqno: bigint): number {
68
+ const hexBytes = payloadBytes * 2;
69
+ const requestIdBytes = requestIdMessageBytes(requestId).byteLength;
70
+ return (hexBytes > 0 ? 1 + varintLength(BigInt(hexBytes)) + hexBytes : 0)
71
+ + 1 + varintLength(BigInt(requestIdBytes)) + requestIdBytes
72
+ + (seqno > 0n ? 1 + varintLength(seqno) : 0);
73
+ }
74
+
75
+ /**
76
+ * Encode the compatibility request used by Cursor when HTTP/2 is disabled.
77
+ * The public client defaults to field 1's hexadecimal data when its binary-append
78
+ * feature gate is unavailable, so OpenCodex uses that backwards-compatible shape.
79
+ */
80
+ export function encodeCursorBidiAppendRequest(
81
+ payload: Uint8Array,
82
+ requestId: string,
83
+ seqno: bigint,
84
+ ): Uint8Array {
85
+ const requestIdBytes = requestIdMessageBytes(requestId);
86
+ const output = new Uint8Array(cursorBidiAppendRequestSize(payload.byteLength, requestId, seqno));
87
+ let offset = 0;
88
+ if (payload.byteLength > 0) {
89
+ const hexBytes = payload.byteLength * 2;
90
+ output[offset++] = 0x0a; // field 1, string data
91
+ offset = writeVarint(output, offset, BigInt(hexBytes));
92
+ for (const byte of payload) {
93
+ output[offset++] = HEX.charCodeAt(byte >>> 4);
94
+ output[offset++] = HEX.charCodeAt(byte & 0x0f);
95
+ }
96
+ }
97
+ output[offset++] = 0x12; // field 2, BidiRequestId request_id
98
+ offset = writeVarint(output, offset, BigInt(requestIdBytes.byteLength));
99
+ output.set(requestIdBytes, offset);
100
+ offset += requestIdBytes.byteLength;
101
+ if (seqno > 0n) {
102
+ output[offset++] = 0x18; // field 3, int64 append_seqno
103
+ offset = writeVarint(output, offset, seqno);
104
+ }
105
+ return output;
106
+ }
107
+
108
+ function cursorHttp1Error(operation: "RunSSE" | "BidiAppend", status: number): Error {
109
+ return new Error(`Cursor HTTP/1.1 ${operation} failed with HTTP ${status || "unknown"}`);
110
+ }
111
+
112
+ function asError(error: unknown): Error {
113
+ return error instanceof Error ? error : new Error(String(error));
114
+ }
115
+
116
+ /** Bun accepts Uint8Array request bodies; TypeScript's DOM BodyInit omits that runtime shape. */
117
+ function bunFetchBody(bytes: Uint8Array): BodyInit {
118
+ return bytes as unknown as BodyInit;
119
+ }
120
+
121
+ /**
122
+ * Cursor's HTTP/1.1 compatibility bridge: a server-streaming RunSSE request carries
123
+ * output, while each client message is posted separately through BidiAppend.
124
+ */
125
+ export class CursorHttp1BidiConnection {
126
+ private readonly abortController = new AbortController();
127
+ private readonly fetchImpl: typeof globalThis.fetch;
128
+ private readonly runSseReady: Promise<void>;
129
+ private resolveRunSseReady!: () => void;
130
+ private rejectRunSseReady!: (reason?: unknown) => void;
131
+ private appendChain: Promise<void> = Promise.resolve();
132
+ private nextAppendSeqno = 0n;
133
+ private committed = false;
134
+ private paused = false;
135
+ private resumeWaiters: Array<() => void> = [];
136
+ private terminal = false;
137
+ private closed = false;
138
+ destroyed = false;
139
+
140
+ constructor(private readonly options: CursorHttp1BidiOptions) {
141
+ this.fetchImpl = options.fetch ?? globalThis.fetch;
142
+ this.runSseReady = new Promise<void>((resolve, reject) => {
143
+ this.resolveRunSseReady = resolve;
144
+ this.rejectRunSseReady = reject;
145
+ });
146
+ // A RunSSE failure can happen before the first append reaches its await; observe it here so
147
+ // the readiness promise never becomes an unhandled rejection.
148
+ void this.runSseReady.catch(() => undefined);
149
+ }
150
+
151
+ start(): void {
152
+ void this.runSse().catch(error => {
153
+ this.rejectRunSseReady(error);
154
+ this.fail(asError(error));
155
+ });
156
+ }
157
+
158
+ write(frameBytes: Uint8Array): boolean {
159
+ if (this.closed || this.terminal) return false;
160
+ let frame;
161
+ try {
162
+ const decoded = consumeConnectFrames(frameBytes, CURSOR_MAX_EFFECTIVE_CONNECT_PAYLOAD_BYTES, 2);
163
+ if (decoded.frames.length !== 1 || decoded.consumedBytes !== frameBytes.byteLength) {
164
+ throw new Error("Cursor HTTP/1.1 append requires exactly one complete Connect frame");
165
+ }
166
+ frame = decoded.frames[0]!;
167
+ if (frame.flags !== 0) throw new Error(`Cursor HTTP/1.1 append does not support Connect flags ${frame.flags}`);
168
+ this.options.translatorBudget.chargeRetained(frame.payload.byteLength, { kind: "request_copies" });
169
+ } catch (error) {
170
+ this.fail(asError(error));
171
+ return false;
172
+ }
173
+
174
+ const pending: PendingAppend = {
175
+ payload: frame.payload,
176
+ seqno: this.nextAppendSeqno++,
177
+ rawBytesCharged: true,
178
+ };
179
+ this.appendChain = this.appendChain
180
+ .then(() => this.postAppend(pending))
181
+ .catch(error => this.fail(asError(error)))
182
+ .finally(() => {
183
+ if (!pending.rawBytesCharged) return;
184
+ pending.rawBytesCharged = false;
185
+ this.options.translatorBudget.releaseRetained(pending.payload.byteLength, { kind: "request_copies" });
186
+ });
187
+ return true;
188
+ }
189
+
190
+ pause(): void {
191
+ this.paused = true;
192
+ }
193
+
194
+ resume(): void {
195
+ if (!this.paused) return;
196
+ this.paused = false;
197
+ const waiters = this.resumeWaiters;
198
+ this.resumeWaiters = [];
199
+ for (const resume of waiters) resume();
200
+ }
201
+
202
+ close(): void {
203
+ if (this.closed) return;
204
+ this.closed = true;
205
+ this.destroyed = true;
206
+ this.resume();
207
+ const reason = new DOMException("Cursor HTTP/1.1 connection closed", "AbortError");
208
+ this.rejectRunSseReady(reason);
209
+ this.abortController.abort(reason);
210
+ queueMicrotask(() => this.finish());
211
+ }
212
+
213
+ destroy(): void {
214
+ this.close();
215
+ }
216
+
217
+ private commonHeaders(contentType: string): Headers {
218
+ return new Headers({
219
+ "content-type": contentType,
220
+ "connect-protocol-version": "1",
221
+ authorization: `Bearer ${this.options.token}`,
222
+ "x-ghost-mode": "true",
223
+ "x-cursor-client-version": this.options.clientVersion,
224
+ "x-cursor-client-type": "cli",
225
+ "x-request-id": this.options.requestId,
226
+ "x-session-id": this.options.sessionId,
227
+ });
228
+ }
229
+
230
+ private requestUrl(path: string): string {
231
+ const url = new URL(path, this.options.baseUrl);
232
+ if (url.protocol !== "https:") {
233
+ throw new Error("Cursor HTTP/1.1 transport requires an HTTPS base URL");
234
+ }
235
+ return url.toString();
236
+ }
237
+
238
+ private http1Init(url: string, init: RequestInit): RequestInit {
239
+ return withUpstreamHttpVersionValue(url, init, "http1.1") ?? init;
240
+ }
241
+
242
+ private markCommitted(): void {
243
+ if (this.committed) return;
244
+ this.committed = true;
245
+ this.options.callbacks.onCommitted();
246
+ }
247
+
248
+ private async runSse(): Promise<void> {
249
+ const url = this.requestUrl(CURSOR_RUN_SSE_PATH);
250
+ const requestId = toBinary(BidiRequestIdSchema, create(BidiRequestIdSchema, {
251
+ requestId: this.options.requestId,
252
+ }));
253
+ const response = await this.fetchImpl(url, this.http1Init(url, {
254
+ method: "POST",
255
+ headers: this.commonHeaders("application/connect+proto"),
256
+ body: bunFetchBody(encodeConnectFrame(requestId)),
257
+ redirect: "manual",
258
+ signal: this.abortController.signal,
259
+ }));
260
+ if (response.status !== 200) {
261
+ void response.body?.cancel().catch(() => undefined);
262
+ throw cursorHttp1Error("RunSSE", response.status);
263
+ }
264
+ if (!response.body) throw new Error("Cursor HTTP/1.1 RunSSE returned no response body");
265
+ // Cursor has accepted the request id once RunSSE returns successful headers. Do not race the
266
+ // first BidiAppend ahead of that registration.
267
+ this.resolveRunSseReady();
268
+ const reader = response.body.getReader();
269
+ try {
270
+ while (!this.closed && !this.terminal) {
271
+ await this.waitWhilePaused();
272
+ if (this.closed || this.terminal) break;
273
+ const { value, done } = await reader.read();
274
+ if (done) break;
275
+ if (value && value.byteLength > 0) this.options.callbacks.onData(value);
276
+ }
277
+ this.finish();
278
+ } finally {
279
+ try { reader.releaseLock(); } catch { /* a pending abort may still own it */ }
280
+ }
281
+ }
282
+
283
+ private async postAppend(pending: PendingAppend): Promise<void> {
284
+ if (this.closed || this.terminal) return;
285
+ await this.runSseReady;
286
+ if (this.closed || this.terminal) return;
287
+ const encodedBytes = cursorBidiAppendRequestSize(
288
+ pending.payload.byteLength,
289
+ this.options.requestId,
290
+ pending.seqno,
291
+ );
292
+ const reservation = this.options.translatorBudget.reserveTransient(encodedBytes, { kind: "request_copies" });
293
+ let body: Uint8Array;
294
+ try {
295
+ body = encodeCursorBidiAppendRequest(pending.payload, this.options.requestId, pending.seqno);
296
+ } catch (error) {
297
+ reservation.release();
298
+ throw error;
299
+ }
300
+ if (pending.rawBytesCharged) {
301
+ pending.rawBytesCharged = false;
302
+ this.options.translatorBudget.releaseRetained(pending.payload.byteLength, { kind: "request_copies" });
303
+ }
304
+ try {
305
+ const url = this.requestUrl(CURSOR_BIDI_APPEND_PATH);
306
+ const timeout = AbortSignal.timeout(CURSOR_HTTP1_APPEND_TIMEOUT_MS);
307
+ const signal = AbortSignal.any([this.abortController.signal, timeout]);
308
+ let response: Response;
309
+ try {
310
+ response = await this.fetchImpl(url, this.http1Init(url, {
311
+ method: "POST",
312
+ headers: this.commonHeaders("application/proto"),
313
+ body: bunFetchBody(body),
314
+ redirect: "manual",
315
+ signal,
316
+ }));
317
+ } catch (error) {
318
+ // A proven DNS/TCP pre-connect failure means no append bytes reached Cursor and replay is
319
+ // safe. Every ambiguous rejection stays conservative: the server may have accepted the
320
+ // append before the response path failed, so suppress replay exactly as the h2 path does.
321
+ if (!isPreConnectReachabilityError(error)) this.markCommitted();
322
+ throw error;
323
+ }
324
+ this.markCommitted();
325
+ if (response.status !== 200) {
326
+ void response.body?.cancel().catch(() => undefined);
327
+ throw cursorHttp1Error("BidiAppend", response.status);
328
+ }
329
+ const result = await readBoundedResponseBytes(response, {
330
+ maxBytes: CURSOR_HTTP1_APPEND_RESPONSE_MAX_BYTES,
331
+ signal,
332
+ });
333
+ if (result.oversized) throw new Error("Cursor HTTP/1.1 BidiAppend response exceeds 64 KiB");
334
+ } finally {
335
+ reservation.release();
336
+ }
337
+ }
338
+
339
+ private waitWhilePaused(): Promise<void> {
340
+ if (!this.paused) return Promise.resolve();
341
+ return new Promise(resolve => this.resumeWaiters.push(resolve));
342
+ }
343
+
344
+ private fail(error: Error): void {
345
+ if (this.terminal) return;
346
+ this.terminal = true;
347
+ this.destroyed = true;
348
+ this.resume();
349
+ this.rejectRunSseReady(error);
350
+ if (!this.abortController.signal.aborted) this.abortController.abort(error);
351
+ this.options.callbacks.onError(error);
352
+ }
353
+
354
+ private finish(): void {
355
+ if (this.terminal) return;
356
+ this.terminal = true;
357
+ this.destroyed = true;
358
+ this.resume();
359
+ this.options.callbacks.onEnd();
360
+ }
361
+ }