@remodex/rmx 1.0.2

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 (588) hide show
  1. package/AGENTS_INSTALL.md +91 -0
  2. package/LICENSE +21 -0
  3. package/README.md +242 -0
  4. package/assets/architecture.png +0 -0
  5. package/assets/banner.png +0 -0
  6. package/assets/claude-code-models.gif +0 -0
  7. package/assets/codex-app-picker.png +0 -0
  8. package/bin/ocx.mjs +584 -0
  9. package/bin/package-main.mjs +9 -0
  10. package/gui/dist/assets/index-CZqebSPQ.css +1 -0
  11. package/gui/dist/assets/index-CkETtt7P.js +71 -0
  12. package/gui/dist/favicon.png +0 -0
  13. package/gui/dist/fonts/google-sans-cyrillic.woff2 +0 -0
  14. package/gui/dist/fonts/google-sans-latin.woff2 +0 -0
  15. package/gui/dist/icons.svg +24 -0
  16. package/gui/dist/index.html +25 -0
  17. package/gui/dist/logo.png +0 -0
  18. package/gui/dist/provider-icons/alibaba-color.svg +1 -0
  19. package/gui/dist/provider-icons/antigravity-color.svg +1 -0
  20. package/gui/dist/provider-icons/claude-color.svg +1 -0
  21. package/gui/dist/provider-icons/cline-color.svg +16 -0
  22. package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
  23. package/gui/dist/provider-icons/commandcode-color.svg +1 -0
  24. package/gui/dist/provider-icons/copilot-color.svg +1 -0
  25. package/gui/dist/provider-icons/cursor-color.svg +2 -0
  26. package/gui/dist/provider-icons/deepseek-color.svg +1 -0
  27. package/gui/dist/provider-icons/discord.svg +1 -0
  28. package/gui/dist/provider-icons/firepass-color.svg +1 -0
  29. package/gui/dist/provider-icons/fireworks-color.svg +1 -0
  30. package/gui/dist/provider-icons/gemini-color.svg +1 -0
  31. package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
  32. package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
  33. package/gui/dist/provider-icons/grok.svg +1 -0
  34. package/gui/dist/provider-icons/groq-color.svg +1 -0
  35. package/gui/dist/provider-icons/huggingface-color.svg +1 -0
  36. package/gui/dist/provider-icons/kimi-color.svg +1 -0
  37. package/gui/dist/provider-icons/kiro-color.svg +15 -0
  38. package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
  39. package/gui/dist/provider-icons/mistral-color.svg +1 -0
  40. package/gui/dist/provider-icons/moonshot-color.svg +1 -0
  41. package/gui/dist/provider-icons/nvidia-color.svg +1 -0
  42. package/gui/dist/provider-icons/ollama-color.svg +1 -0
  43. package/gui/dist/provider-icons/openai.svg +1 -0
  44. package/gui/dist/provider-icons/opencode.svg +2 -0
  45. package/gui/dist/provider-icons/openrouter-color.svg +1 -0
  46. package/gui/dist/provider-icons/pi.svg +21 -0
  47. package/gui/dist/provider-icons/qianfan-color.svg +1 -0
  48. package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
  49. package/gui/dist/provider-icons/telegram.svg +1 -0
  50. package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
  51. package/gui/dist/provider-icons/vllm-color.svg +1 -0
  52. package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
  53. package/package.json +118 -0
  54. package/src/AGENTS.md +28 -0
  55. package/src/adapters/anthropic-image-guard.ts +251 -0
  56. package/src/adapters/anthropic-image-normalize.ts +518 -0
  57. package/src/adapters/anthropic.ts +1205 -0
  58. package/src/adapters/azure.ts +36 -0
  59. package/src/adapters/base.ts +83 -0
  60. package/src/adapters/client-fingerprint.ts +59 -0
  61. package/src/adapters/command-code.ts +453 -0
  62. package/src/adapters/cursor/arg-codec.ts +38 -0
  63. package/src/adapters/cursor/arg-normalize.ts +104 -0
  64. package/src/adapters/cursor/cursor-errors.ts +165 -0
  65. package/src/adapters/cursor/discovery.ts +276 -0
  66. package/src/adapters/cursor/effort-map.ts +139 -0
  67. package/src/adapters/cursor/exec-policy.ts +88 -0
  68. package/src/adapters/cursor/framing.ts +250 -0
  69. package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
  70. package/src/adapters/cursor/kv-store.ts +52 -0
  71. package/src/adapters/cursor/live-models.ts +153 -0
  72. package/src/adapters/cursor/live-smoke-gate.ts +41 -0
  73. package/src/adapters/cursor/live-transport.ts +1235 -0
  74. package/src/adapters/cursor/mcp-config.ts +42 -0
  75. package/src/adapters/cursor/mcp-manager.ts +333 -0
  76. package/src/adapters/cursor/message-mapper.ts +49 -0
  77. package/src/adapters/cursor/native-exec-common.ts +59 -0
  78. package/src/adapters/cursor/native-exec-desktop.ts +184 -0
  79. package/src/adapters/cursor/native-exec-fs.ts +332 -0
  80. package/src/adapters/cursor/native-exec-mcp.ts +153 -0
  81. package/src/adapters/cursor/native-exec-network.ts +43 -0
  82. package/src/adapters/cursor/native-exec-shell.ts +548 -0
  83. package/src/adapters/cursor/native-exec-tools.ts +118 -0
  84. package/src/adapters/cursor/native-exec.ts +604 -0
  85. package/src/adapters/cursor/protobuf-events.ts +735 -0
  86. package/src/adapters/cursor/protobuf-request.ts +719 -0
  87. package/src/adapters/cursor/request-builder.ts +280 -0
  88. package/src/adapters/cursor/thread-continuity.ts +67 -0
  89. package/src/adapters/cursor/tool-definitions.ts +621 -0
  90. package/src/adapters/cursor/transport-retry.ts +132 -0
  91. package/src/adapters/cursor/transport.ts +57 -0
  92. package/src/adapters/cursor/types.ts +59 -0
  93. package/src/adapters/cursor.ts +196 -0
  94. package/src/adapters/google-antigravity-replay.ts +520 -0
  95. package/src/adapters/google-antigravity-wire.ts +140 -0
  96. package/src/adapters/google-errors.ts +85 -0
  97. package/src/adapters/google-http.ts +100 -0
  98. package/src/adapters/google-tool-schema.ts +173 -0
  99. package/src/adapters/google-truncation.ts +24 -0
  100. package/src/adapters/google-wire-compiler.ts +232 -0
  101. package/src/adapters/google.ts +859 -0
  102. package/src/adapters/identity.ts +77 -0
  103. package/src/adapters/image.ts +23 -0
  104. package/src/adapters/kiro-constants.ts +16 -0
  105. package/src/adapters/kiro-errors.ts +208 -0
  106. package/src/adapters/kiro-events.ts +197 -0
  107. package/src/adapters/kiro-images.ts +129 -0
  108. package/src/adapters/kiro-retry.ts +312 -0
  109. package/src/adapters/kiro-thinking.ts +104 -0
  110. package/src/adapters/kiro-tool-fallback.ts +36 -0
  111. package/src/adapters/kiro-tools.ts +224 -0
  112. package/src/adapters/kiro-truncation.ts +33 -0
  113. package/src/adapters/kiro-wire.ts +129 -0
  114. package/src/adapters/kiro.ts +1924 -0
  115. package/src/adapters/mimo-free.ts +263 -0
  116. package/src/adapters/openai-chat.ts +1265 -0
  117. package/src/adapters/openai-responses.ts +1309 -0
  118. package/src/adapters/run-turn-queue.ts +114 -0
  119. package/src/adapters/tool-catalog-nudge.ts +71 -0
  120. package/src/adapters/upstream-http-error.ts +48 -0
  121. package/src/android-remote/assets.ts +218 -0
  122. package/src/android-remote/attachments.ts +168 -0
  123. package/src/android-remote/auth.ts +237 -0
  124. package/src/android-remote/cloudflare-provisioning.ts +409 -0
  125. package/src/android-remote/cloudflare-secret.ts +106 -0
  126. package/src/android-remote/cloudflare-tunnel.ts +488 -0
  127. package/src/android-remote/cloudflared.ts +286 -0
  128. package/src/android-remote/codex-app-server.ts +565 -0
  129. package/src/android-remote/desktop-history-page.ts +936 -0
  130. package/src/android-remote/desktop-ipc.ts +3643 -0
  131. package/src/android-remote/desktop-ownership-store.ts +98 -0
  132. package/src/android-remote/desktop-project-registration.ts +129 -0
  133. package/src/android-remote/desktop-session-stream.ts +1110 -0
  134. package/src/android-remote/desktop-workspace-state.ts +443 -0
  135. package/src/android-remote/file-change-parser.ts +112 -0
  136. package/src/android-remote/gateway.ts +9108 -0
  137. package/src/android-remote/mutation-store.ts +299 -0
  138. package/src/android-remote/projection.ts +1780 -0
  139. package/src/android-remote/queued-turn-store.ts +248 -0
  140. package/src/android-remote/session-command-recovery.ts +1384 -0
  141. package/src/android-remote/store.ts +466 -0
  142. package/src/android-remote/thread-reconciliation.ts +133 -0
  143. package/src/android-remote/thread-source-paths.ts +307 -0
  144. package/src/android-remote/thread-stream.ts +546 -0
  145. package/src/android-remote/turn-activity.ts +235 -0
  146. package/src/android-remote/user-message-identity.ts +94 -0
  147. package/src/bridge.ts +1793 -0
  148. package/src/chat/inbound.ts +295 -0
  149. package/src/chat/outbound.ts +821 -0
  150. package/src/claude/agents-inject.ts +267 -0
  151. package/src/claude/alias.ts +149 -0
  152. package/src/claude/auth-detect.ts +229 -0
  153. package/src/claude/auth-mode-migration.ts +32 -0
  154. package/src/claude/auth-mode.ts +62 -0
  155. package/src/claude/context-windows.ts +189 -0
  156. package/src/claude/desktop-3p-guard.ts +35 -0
  157. package/src/claude/desktop-3p-paths.ts +84 -0
  158. package/src/claude/desktop-3p.ts +601 -0
  159. package/src/claude/desktop-health.ts +26 -0
  160. package/src/claude/desktop-profile.ts +263 -0
  161. package/src/claude/gateway-cache.ts +70 -0
  162. package/src/claude/inbound-debug.ts +163 -0
  163. package/src/claude/inbound.ts +519 -0
  164. package/src/claude/model-info.ts +154 -0
  165. package/src/claude/outbound.ts +898 -0
  166. package/src/cli/access.ts +108 -0
  167. package/src/cli/account-api.ts +296 -0
  168. package/src/cli/account-auth.ts +250 -0
  169. package/src/cli/account-catalog-refresh.ts +14 -0
  170. package/src/cli/account-extended.ts +476 -0
  171. package/src/cli/account-main.ts +317 -0
  172. package/src/cli/account.ts +297 -0
  173. package/src/cli/agent-driven.ts +70 -0
  174. package/src/cli/agent.ts +184 -0
  175. package/src/cli/catalog-prewarm.ts +27 -0
  176. package/src/cli/claude-desktop.ts +211 -0
  177. package/src/cli/claude.ts +302 -0
  178. package/src/cli/codex-shim-autorestore.ts +45 -0
  179. package/src/cli/codex-shim-readiness.ts +69 -0
  180. package/src/cli/combo.ts +124 -0
  181. package/src/cli/config-command.ts +183 -0
  182. package/src/cli/debug.ts +228 -0
  183. package/src/cli/desktop-first-run.ts +25 -0
  184. package/src/cli/doctor.ts +1022 -0
  185. package/src/cli/export-command.ts +201 -0
  186. package/src/cli/help.ts +370 -0
  187. package/src/cli/index.ts +1565 -0
  188. package/src/cli/init.ts +224 -0
  189. package/src/cli/integrations.ts +225 -0
  190. package/src/cli/interactive-confirm.ts +133 -0
  191. package/src/cli/internal-dispatch.ts +35 -0
  192. package/src/cli/launcher-context.ts +77 -0
  193. package/src/cli/models-runtime.ts +224 -0
  194. package/src/cli/models.ts +340 -0
  195. package/src/cli/observe.ts +170 -0
  196. package/src/cli/opencode.ts +587 -0
  197. package/src/cli/provider-runtime.ts +179 -0
  198. package/src/cli/provider.ts +476 -0
  199. package/src/cli/ready.ts +301 -0
  200. package/src/cli/route-policy.ts +92 -0
  201. package/src/cli/runtime-api.ts +328 -0
  202. package/src/cli/star-prompt.ts +211 -0
  203. package/src/cli/status-oauth.ts +78 -0
  204. package/src/cli/status.ts +321 -0
  205. package/src/cli/system-command.ts +196 -0
  206. package/src/cli/system-restart-client.ts +146 -0
  207. package/src/cli/tray-proxy.ts +205 -0
  208. package/src/cli/v2.ts +200 -0
  209. package/src/cli.ts +10 -0
  210. package/src/clients/config-export.ts +1109 -0
  211. package/src/codex/account-id.ts +34 -0
  212. package/src/codex/account-label.ts +34 -0
  213. package/src/codex/account-lifecycle.ts +172 -0
  214. package/src/codex/account-namespace-match.ts +63 -0
  215. package/src/codex/account-namespaces.ts +195 -0
  216. package/src/codex/account-pause.ts +20 -0
  217. package/src/codex/account-priority.ts +83 -0
  218. package/src/codex/account-runtime-state.ts +31 -0
  219. package/src/codex/account-store.ts +517 -0
  220. package/src/codex/account-usability.ts +40 -0
  221. package/src/codex/admission.ts +263 -0
  222. package/src/codex/app-server-processes.ts +799 -0
  223. package/src/codex/auth-api.ts +2098 -0
  224. package/src/codex/auth-collision.ts +107 -0
  225. package/src/codex/auth-context.ts +480 -0
  226. package/src/codex/autostart-health.ts +156 -0
  227. package/src/codex/catalog/account-models.ts +67 -0
  228. package/src/codex/catalog/aggregation.ts +471 -0
  229. package/src/codex/catalog/bundled.ts +533 -0
  230. package/src/codex/catalog/effort.ts +432 -0
  231. package/src/codex/catalog/filesystem-evidence.ts +302 -0
  232. package/src/codex/catalog/kinds.ts +2 -0
  233. package/src/codex/catalog/metadata.ts +287 -0
  234. package/src/codex/catalog/native-models.ts +7 -0
  235. package/src/codex/catalog/parsing.ts +503 -0
  236. package/src/codex/catalog/provider-fetch.ts +2267 -0
  237. package/src/codex/catalog/sync.ts +1606 -0
  238. package/src/codex/catalog-admission.ts +197 -0
  239. package/src/codex/catalog-refresh-status.ts +87 -0
  240. package/src/codex/catalog-write-serialization.ts +242 -0
  241. package/src/codex/catalog.ts +15 -0
  242. package/src/codex/codex-write-lock.ts +384 -0
  243. package/src/codex/convergence-types.ts +593 -0
  244. package/src/codex/convergence.ts +580 -0
  245. package/src/codex/custom-model-catalog-migration.ts +176 -0
  246. package/src/codex/data/upstream-models.json +830 -0
  247. package/src/codex/desired-state.ts +230 -0
  248. package/src/codex/desktop-client-processes.ts +521 -0
  249. package/src/codex/exec-invocation.ts +22 -0
  250. package/src/codex/features.ts +1091 -0
  251. package/src/codex/generation.ts +202 -0
  252. package/src/codex/history-job.ts +347 -0
  253. package/src/codex/history-lock.ts +242 -0
  254. package/src/codex/history-migration-guardian.ts +115 -0
  255. package/src/codex/history-provider.ts +1075 -0
  256. package/src/codex/history-transition.ts +105 -0
  257. package/src/codex/history-worker.ts +204 -0
  258. package/src/codex/home.ts +206 -0
  259. package/src/codex/inject-coordination.ts +257 -0
  260. package/src/codex/inject.ts +1857 -0
  261. package/src/codex/injected-marker.ts +79 -0
  262. package/src/codex/integration-record.ts +266 -0
  263. package/src/codex/internal/catalog-writer.ts +203 -0
  264. package/src/codex/internal/history-writer.ts +105 -0
  265. package/src/codex/journal.ts +172 -0
  266. package/src/codex/main-account-cache.ts +56 -0
  267. package/src/codex/main-account.ts +40 -0
  268. package/src/codex/management-convergence.ts +114 -0
  269. package/src/codex/model-cache.ts +267 -0
  270. package/src/codex/native-main-admission.ts +47 -0
  271. package/src/codex/native-main-auth-temp.ts +187 -0
  272. package/src/codex/native-main-claim.ts +167 -0
  273. package/src/codex/native-main-lock-file.ts +162 -0
  274. package/src/codex/native-main-owner.ts +329 -0
  275. package/src/codex/native-profile-api.ts +247 -0
  276. package/src/codex/native-profile-manager.ts +1531 -0
  277. package/src/codex/native-profile-processes.ts +121 -0
  278. package/src/codex/native-profile-recovery.ts +99 -0
  279. package/src/codex/native-profile-stage-store.ts +387 -0
  280. package/src/codex/native-profile-startup.ts +348 -0
  281. package/src/codex/native-profile-store.ts +855 -0
  282. package/src/codex/native-profile-types.ts +120 -0
  283. package/src/codex/native-residue.ts +691 -0
  284. package/src/codex/paths.ts +78 -0
  285. package/src/codex/plugins-doctor.ts +242 -0
  286. package/src/codex/pool-rotation.ts +295 -0
  287. package/src/codex/project-config-warnings.ts +426 -0
  288. package/src/codex/prompt-journal.ts +311 -0
  289. package/src/codex/prompt-layers.ts +967 -0
  290. package/src/codex/prompt-lock.ts +143 -0
  291. package/src/codex/provider-adoption.ts +242 -0
  292. package/src/codex/quota-rejection.ts +224 -0
  293. package/src/codex/quota.ts +494 -0
  294. package/src/codex/refresh.ts +60 -0
  295. package/src/codex/routing.ts +1855 -0
  296. package/src/codex/runtime.ts +659 -0
  297. package/src/codex/shim.ts +1215 -0
  298. package/src/codex/subagent-defaults.ts +557 -0
  299. package/src/codex/subagent-model-fallback.ts +560 -0
  300. package/src/codex/sync.ts +238 -0
  301. package/src/codex/transition-state.ts +612 -0
  302. package/src/codex/upstream-host-health.ts +368 -0
  303. package/src/codex/user-identity.ts +374 -0
  304. package/src/codex/warmup.ts +192 -0
  305. package/src/codex/websocket-registry.ts +100 -0
  306. package/src/codex/write-coordination.ts +114 -0
  307. package/src/combos/failover.ts +140 -0
  308. package/src/combos/index.ts +44 -0
  309. package/src/combos/request.ts +64 -0
  310. package/src/combos/resolve.ts +232 -0
  311. package/src/combos/types.ts +392 -0
  312. package/src/config.ts +3270 -0
  313. package/src/generated/model-metadata.ts +144 -0
  314. package/src/github/star-state.ts +203 -0
  315. package/src/grok/inject.ts +540 -0
  316. package/src/grok/inspect.ts +45 -0
  317. package/src/grok/status.ts +127 -0
  318. package/src/grok/sync.ts +66 -0
  319. package/src/images/artifacts.ts +516 -0
  320. package/src/images/fulfill-video.ts +163 -0
  321. package/src/images/fulfill.ts +149 -0
  322. package/src/images/index.ts +4 -0
  323. package/src/images/loop.ts +922 -0
  324. package/src/images/plan.ts +133 -0
  325. package/src/images/synthetic-tool.ts +133 -0
  326. package/src/images/types.ts +41 -0
  327. package/src/images/xai-client.ts +141 -0
  328. package/src/images/xai-video-client.ts +163 -0
  329. package/src/index.ts +22 -0
  330. package/src/integrations/config-io.ts +151 -0
  331. package/src/integrations/journal.ts +315 -0
  332. package/src/integrations/merge.ts +135 -0
  333. package/src/integrations/native/ownership-preflight.ts +202 -0
  334. package/src/integrations/ownership.ts +111 -0
  335. package/src/integrations/registry.ts +108 -0
  336. package/src/integrations/serialize.ts +235 -0
  337. package/src/integrations/state.ts +290 -0
  338. package/src/integrations/store.ts +103 -0
  339. package/src/integrations/writer.ts +492 -0
  340. package/src/lib/abort.ts +146 -0
  341. package/src/lib/admin-secrets.ts +25 -0
  342. package/src/lib/admission.ts +83 -0
  343. package/src/lib/app-owned-memory-stores.ts +173 -0
  344. package/src/lib/app-owned-memory.ts +265 -0
  345. package/src/lib/bounded-body.ts +242 -0
  346. package/src/lib/bun-binary-validator.d.mts +3 -0
  347. package/src/lib/bun-binary-validator.mjs +18 -0
  348. package/src/lib/bun-runtime.ts +184 -0
  349. package/src/lib/bun-stream-caps.ts +127 -0
  350. package/src/lib/config-ownership.ts +438 -0
  351. package/src/lib/crash-guard.ts +344 -0
  352. package/src/lib/debug-log-buffer.ts +83 -0
  353. package/src/lib/debug-settings.ts +108 -0
  354. package/src/lib/debug.ts +31 -0
  355. package/src/lib/destination-policy.ts +316 -0
  356. package/src/lib/errors.ts +364 -0
  357. package/src/lib/eventstream-decoder.ts +253 -0
  358. package/src/lib/gcp-adc.ts +341 -0
  359. package/src/lib/injection-debug-log.ts +58 -0
  360. package/src/lib/local-management-attestation.ts +51 -0
  361. package/src/lib/open-url.ts +25 -0
  362. package/src/lib/pinned-http.ts +182 -0
  363. package/src/lib/privacy.ts +20 -0
  364. package/src/lib/process-control.ts +168 -0
  365. package/src/lib/provider-environment.ts +470 -0
  366. package/src/lib/provider-outbound.ts +203 -0
  367. package/src/lib/provider-url.ts +14 -0
  368. package/src/lib/proxy-env.ts +18 -0
  369. package/src/lib/redact.ts +510 -0
  370. package/src/lib/remodex-home.ts +616 -0
  371. package/src/lib/retry-after.ts +55 -0
  372. package/src/lib/service-secrets.ts +178 -0
  373. package/src/lib/shadow-call.ts +54 -0
  374. package/src/lib/sidecar-tracker.ts +52 -0
  375. package/src/lib/sse-decoder.ts +364 -0
  376. package/src/lib/state-store-registrations.ts +109 -0
  377. package/src/lib/state-store-sweeper.ts +184 -0
  378. package/src/lib/system-restart-contract.ts +73 -0
  379. package/src/lib/test-home-guard.ts +98 -0
  380. package/src/lib/token-estimate.ts +69 -0
  381. package/src/lib/translator-budget.ts +366 -0
  382. package/src/lib/upstream-reachability.ts +91 -0
  383. package/src/lib/upstream-retry.ts +508 -0
  384. package/src/lib/win-exec.ts +115 -0
  385. package/src/lib/win-paths.ts +68 -0
  386. package/src/lib/windows-elevation.ts +705 -0
  387. package/src/lib/windows-secret-acl.ts +817 -0
  388. package/src/lib/windows-user-principal.ts +283 -0
  389. package/src/lib/winsw.ts +402 -0
  390. package/src/model-sources.ts +73 -0
  391. package/src/oauth/anthropic-routing.ts +594 -0
  392. package/src/oauth/anthropic.ts +177 -0
  393. package/src/oauth/callback-server.ts +294 -0
  394. package/src/oauth/chatgpt.ts +150 -0
  395. package/src/oauth/command-code.ts +239 -0
  396. package/src/oauth/cursor.ts +231 -0
  397. package/src/oauth/github-copilot.ts +428 -0
  398. package/src/oauth/google-antigravity.ts +230 -0
  399. package/src/oauth/health.ts +443 -0
  400. package/src/oauth/index.ts +1280 -0
  401. package/src/oauth/key-providers.ts +128 -0
  402. package/src/oauth/kimi.ts +213 -0
  403. package/src/oauth/kiro-credentials.ts +726 -0
  404. package/src/oauth/kiro.ts +621 -0
  405. package/src/oauth/local-token-detect.ts +121 -0
  406. package/src/oauth/log.ts +48 -0
  407. package/src/oauth/login-cli.ts +163 -0
  408. package/src/oauth/pkce.ts +15 -0
  409. package/src/oauth/store.ts +655 -0
  410. package/src/oauth/token-guardian.ts +309 -0
  411. package/src/oauth/types.ts +62 -0
  412. package/src/oauth/xai.ts +241 -0
  413. package/src/providers/alibaba-region-backup.ts +75 -0
  414. package/src/providers/alibaba-region-migration.ts +156 -0
  415. package/src/providers/alibaba-region-startup.ts +36 -0
  416. package/src/providers/antigravity-models.ts +317 -0
  417. package/src/providers/api-keys.ts +140 -0
  418. package/src/providers/base-url-choices.ts +64 -0
  419. package/src/providers/codex-capacity.ts +288 -0
  420. package/src/providers/command-code-efforts.ts +85 -0
  421. package/src/providers/context-cap.ts +73 -0
  422. package/src/providers/derive.ts +451 -0
  423. package/src/providers/free-directory.ts +187 -0
  424. package/src/providers/github-copilot-transport.ts +56 -0
  425. package/src/providers/google-vertex-location.ts +14 -0
  426. package/src/providers/key-failover.ts +271 -0
  427. package/src/providers/kiro-models.ts +67 -0
  428. package/src/providers/label.ts +19 -0
  429. package/src/providers/model-discovery-limits.ts +16 -0
  430. package/src/providers/model-discovery.ts +361 -0
  431. package/src/providers/openai-sidecar.ts +235 -0
  432. package/src/providers/openai-tier-startup.ts +27 -0
  433. package/src/providers/openai-tiers.ts +301 -0
  434. package/src/providers/openai-virtual-models.ts +83 -0
  435. package/src/providers/openrouter-routing.ts +102 -0
  436. package/src/providers/provider-id-rewrite.ts +179 -0
  437. package/src/providers/quota.ts +1942 -0
  438. package/src/providers/reasoning-capabilities.ts +336 -0
  439. package/src/providers/registry.ts +2375 -0
  440. package/src/providers/slug-codec.ts +74 -0
  441. package/src/providers/xai-transport.ts +149 -0
  442. package/src/reasoning-effort.ts +243 -0
  443. package/src/responses/compaction.ts +124 -0
  444. package/src/responses/hosted-tool-policy.ts +9 -0
  445. package/src/responses/parser.ts +714 -0
  446. package/src/responses/reasoning-envelope.ts +60 -0
  447. package/src/responses/reasoning-replay-cache.ts +106 -0
  448. package/src/responses/schema.ts +159 -0
  449. package/src/responses/spill-store.ts +431 -0
  450. package/src/responses/state.ts +1039 -0
  451. package/src/responses/tool-groups.ts +19 -0
  452. package/src/router.ts +802 -0
  453. package/src/routing/analytics.ts +377 -0
  454. package/src/routing/capability.ts +205 -0
  455. package/src/routing/cost.ts +77 -0
  456. package/src/routing/evaluator.ts +444 -0
  457. package/src/routing/health.ts +401 -0
  458. package/src/routing/history/cursor.ts +43 -0
  459. package/src/routing/history/indexer.ts +605 -0
  460. package/src/routing/history/schema.ts +72 -0
  461. package/src/routing/profile-namespace.ts +15 -0
  462. package/src/routing/profile.ts +424 -0
  463. package/src/routing/quota.ts +145 -0
  464. package/src/routing/request-evidence.ts +45 -0
  465. package/src/routing/trace.ts +686 -0
  466. package/src/server/adapter-resolve.ts +83 -0
  467. package/src/server/auth-cors.ts +606 -0
  468. package/src/server/chat-completions.ts +379 -0
  469. package/src/server/claude-messages.ts +980 -0
  470. package/src/server/effort-policy.ts +251 -0
  471. package/src/server/github-copilot-responses-repair.ts +338 -0
  472. package/src/server/gui-static.ts +152 -0
  473. package/src/server/image-retry.ts +42 -0
  474. package/src/server/images.ts +485 -0
  475. package/src/server/index.ts +1633 -0
  476. package/src/server/lifecycle.ts +482 -0
  477. package/src/server/live.ts +609 -0
  478. package/src/server/management/agent-settings-routes.ts +1180 -0
  479. package/src/server/management/android-remote-routes.ts +390 -0
  480. package/src/server/management/api-access.ts +141 -0
  481. package/src/server/management/api-key-usage.ts +167 -0
  482. package/src/server/management/body.ts +35 -0
  483. package/src/server/management/combo-routes.ts +244 -0
  484. package/src/server/management/config-routes.ts +602 -0
  485. package/src/server/management/context.ts +88 -0
  486. package/src/server/management/integration-routes.ts +538 -0
  487. package/src/server/management/logs-usage-routes.ts +516 -0
  488. package/src/server/management/model-routes.ts +519 -0
  489. package/src/server/management/model-rows.ts +143 -0
  490. package/src/server/management/native-integration-routes.ts +781 -0
  491. package/src/server/management/oauth-account-routes.ts +573 -0
  492. package/src/server/management/provider-routes.ts +781 -0
  493. package/src/server/management/request-history-routes.ts +191 -0
  494. package/src/server/management/routing-analytics-routes.ts +74 -0
  495. package/src/server/management/routing-profile-routes.ts +384 -0
  496. package/src/server/management/shared.ts +277 -0
  497. package/src/server/management/sidebar-routes.ts +106 -0
  498. package/src/server/management/sync-response.ts +69 -0
  499. package/src/server/management/system-restart.ts +433 -0
  500. package/src/server/management/system-routes.ts +141 -0
  501. package/src/server/management/usage-summary-cache.ts +86 -0
  502. package/src/server/management-api.ts +269 -0
  503. package/src/server/management-auth.ts +353 -0
  504. package/src/server/memory-watchdog.ts +156 -0
  505. package/src/server/port-reclaim.ts +307 -0
  506. package/src/server/ports.ts +156 -0
  507. package/src/server/proxy-liveness.ts +326 -0
  508. package/src/server/proxy-stop.ts +92 -0
  509. package/src/server/readiness.ts +99 -0
  510. package/src/server/relay-eager.ts +353 -0
  511. package/src/server/relay.ts +1179 -0
  512. package/src/server/request-decompress.ts +132 -0
  513. package/src/server/request-log-conversation.ts +168 -0
  514. package/src/server/request-log.ts +1072 -0
  515. package/src/server/responses/collaboration.ts +409 -0
  516. package/src/server/responses/compact.ts +710 -0
  517. package/src/server/responses/core.ts +3561 -0
  518. package/src/server/responses/encrypted-payload.ts +308 -0
  519. package/src/server/responses/fetch-helpers.ts +171 -0
  520. package/src/server/responses/passthrough-error.ts +78 -0
  521. package/src/server/responses/policy-fallback.ts +152 -0
  522. package/src/server/responses/terminal-guard.ts +230 -0
  523. package/src/server/responses/upstream-error.ts +48 -0
  524. package/src/server/responses-image-gen-repair.ts +132 -0
  525. package/src/server/responses-item-id-repair.ts +272 -0
  526. package/src/server/responses-json-events.ts +52 -0
  527. package/src/server/responses-model-rewrite.ts +29 -0
  528. package/src/server/responses-snapshot-repair.ts +621 -0
  529. package/src/server/responses.ts +10 -0
  530. package/src/server/search.ts +181 -0
  531. package/src/server/sse-frame-buffer.ts +292 -0
  532. package/src/server/sse-payload-rewrite.ts +263 -0
  533. package/src/server/startup-action-control.ts +308 -0
  534. package/src/server/startup-health-cache.ts +119 -0
  535. package/src/server/system-env.ts +418 -0
  536. package/src/server/windows-tcp-drop.ts +184 -0
  537. package/src/server/windows-tray-control.ts +41 -0
  538. package/src/server/ws-bridge.ts +470 -0
  539. package/src/service-manager-probe.ts +824 -0
  540. package/src/service.ts +3011 -0
  541. package/src/stall-timeout.ts +20 -0
  542. package/src/storage/cleanup-job.ts +57 -0
  543. package/src/storage/cleanup.ts +3085 -0
  544. package/src/storage/policy-job.ts +457 -0
  545. package/src/storage/policy-scheduler.ts +40 -0
  546. package/src/storage/policy-worker.ts +59 -0
  547. package/src/storage/policy.ts +527 -0
  548. package/src/storage/restore-job.ts +299 -0
  549. package/src/storage/restore-worker.ts +58 -0
  550. package/src/storage/scanner.ts +238 -0
  551. package/src/storage/storage-mutation-coordinator.ts +139 -0
  552. package/src/storage/worker-lifecycle.ts +215 -0
  553. package/src/tray/assets/opencodex-tray-offline.ico +0 -0
  554. package/src/tray/assets/opencodex-tray-online.ico +0 -0
  555. package/src/tray/assets/opencodex-tray-warning.ico +0 -0
  556. package/src/tray/assets/opencodex-tray.png +0 -0
  557. package/src/tray/windows-tray.ps1 +364 -0
  558. package/src/tray/windows.ts +738 -0
  559. package/src/types.ts +1531 -0
  560. package/src/update/badge.ts +72 -0
  561. package/src/update/desktop-release.ts +1620 -0
  562. package/src/update/index.ts +402 -0
  563. package/src/update/job.ts +1906 -0
  564. package/src/update/notify.ts +261 -0
  565. package/src/update/npm-cache-preflight.d.mts +47 -0
  566. package/src/update/npm-cache-preflight.mjs +201 -0
  567. package/src/update/npm-invocation.d.mts +23 -0
  568. package/src/update/npm-invocation.mjs +94 -0
  569. package/src/update/tray-update-plan.d.mts +18 -0
  570. package/src/update/tray-update-plan.mjs +38 -0
  571. package/src/usage/cost.ts +0 -0
  572. package/src/usage/debug.ts +97 -0
  573. package/src/usage/expected-prices.ts +283 -0
  574. package/src/usage/log.ts +695 -0
  575. package/src/usage/summary.ts +585 -0
  576. package/src/usage/totals.ts +14 -0
  577. package/src/vision/anthropic-describe.ts +185 -0
  578. package/src/vision/describe.ts +127 -0
  579. package/src/vision/index.ts +558 -0
  580. package/src/vision/reasoning.ts +55 -0
  581. package/src/web-search/anthropic-executor.ts +189 -0
  582. package/src/web-search/executor.ts +105 -0
  583. package/src/web-search/format-result.ts +89 -0
  584. package/src/web-search/index.ts +196 -0
  585. package/src/web-search/loop.ts +791 -0
  586. package/src/web-search/parse.ts +235 -0
  587. package/src/web-search/progress-stream.ts +342 -0
  588. package/src/web-search/synthetic-tool.ts +47 -0
@@ -0,0 +1,470 @@
1
+ import type { ServerWebSocket } from "bun";
2
+ import { responsesJsonEventSequence } from "./responses-json-events";
3
+ import { FORWARD_HEADERS } from "../adapters/openai-responses";
4
+ import type { CodexAuthContext } from "../codex/auth-context";
5
+ import { headersForCodexAuthContext } from "../codex/auth-context";
6
+ import type { ResponsesTerminalStatus } from "../bridge";
7
+ import type { DataPlaneAdmission } from "./auth-cors";
8
+ import type { AdmissionLease, AdmissionReservation } from "../lib/admission";
9
+ import { BoundedSseFrameBuffer } from "./sse-frame-buffer";
10
+
11
+ const OPEN = 1;
12
+ type ResponsesTerminalReporter = (status: ResponsesTerminalStatus) => void;
13
+ type ResponsesPayloadObserver = (payload: string) => void;
14
+ const SAFE_RESPONSE_HEADER_EXACT = new Set([
15
+ "retry-after",
16
+ "x-request-id",
17
+ "openai-request-id",
18
+ "x-codex-turn-state",
19
+ "openai-model",
20
+ "x-models-etag",
21
+ "x-reasoning-included",
22
+ ]);
23
+
24
+ export interface WsData {
25
+ headers?: Headers; // base inbound forward headers only; per-turn auth refresh injects current pool tokens
26
+ /**
27
+ * Resolved once at the handshake. Auth is handshake-time only on this path, so
28
+ * the per-frame log contexts have no request headers left to re-resolve from.
29
+ * Optional like every other member here: a socket object can exist before the
30
+ * handshake fills it, and an unattributed frame is preferable to a fabricated
31
+ * attribution.
32
+ */
33
+ admission?: DataPlaneAdmission;
34
+ authContext?: CodexAuthContext; // last resolved account decision for observability/registry cleanup
35
+ cancel?: () => void; // cancels the in-flight stream reader/fetch
36
+ turnId?: number; // monotonically increasing per socket; prevents stale frames after replacement turns
37
+ /** Discriminator: Responses reframing vs transparent live/realtime sideband relay. */
38
+ kind?: "responses" | "live-sideband";
39
+ liveUpstream?: WebSocket;
40
+ liveUpstreamUrl?: string;
41
+ liveUpstreamHeaders?: Record<string, string>;
42
+ livePending?: Array<string | Buffer>;
43
+ liveOpened?: boolean;
44
+ /** Once teardown starts, ignore new client frames until the upstream closes. */
45
+ liveClosing?: boolean;
46
+ /** Schedules one bounded close retry without surrendering native-main ownership. */
47
+ liveCloseFallback?: ReturnType<typeof setTimeout>;
48
+ /** Turn/account ownership retained for the complete sideband socket lifetime. */
49
+ liveTurnAdmissionLease?: AdmissionLease;
50
+ admissionLease?: AdmissionReservation<ServerWebSocket<WsData>>;
51
+ }
52
+
53
+ /**
54
+ * Build the Responses WebSocket upgrade payload.
55
+ *
56
+ * Extracted so the handshake's contract is testable: `server.upgrade` hands its
57
+ * `data` straight to the socket, and a client has no way to read `ws.data` back.
58
+ * A test that only asserts "the socket opened" would still pass if the admission
59
+ * were dropped from the payload, so the payload itself is what gets asserted.
60
+ */
61
+ export function buildResponsesWsData(headers: Headers, admission: DataPlaneAdmission, admissionLease?: AdmissionReservation<ServerWebSocket<WsData>>): WsData {
62
+ // Auth is handshake-time only on this path: the per-frame contexts have no
63
+ // request headers left to re-resolve from, so the decision rides along here.
64
+ return { headers, admission, ...(admissionLease ? { admissionLease } : {}) };
65
+ }
66
+
67
+ export class WsSendDroppedError extends Error {
68
+ constructor() {
69
+ super("websocket send dropped the message");
70
+ }
71
+ }
72
+
73
+ export function selectForwardHeaders(
74
+ headers: Headers,
75
+ codexOverride?: { accessToken: string; chatgptAccountId: string },
76
+ ): Headers {
77
+ const selected = new Headers();
78
+ for (const name of FORWARD_HEADERS) {
79
+ const value = headers.get(name);
80
+ if (value) selected.set(name, value);
81
+ }
82
+ if (codexOverride) {
83
+ selected.set("authorization", `Bearer ${codexOverride.accessToken}`);
84
+ selected.set("chatgpt-account-id", codexOverride.chatgptAccountId);
85
+ }
86
+ return selected;
87
+ }
88
+
89
+ export function selectForwardHeadersForAuthContext(headers: Headers, ctx: CodexAuthContext): Headers {
90
+ return headersForCodexAuthContext(headers, ctx);
91
+ }
92
+
93
+ export function safeResponseHeaders(headers: Headers): Record<string, string> {
94
+ const out: Record<string, string> = {};
95
+ for (const [name, value] of headers) {
96
+ const lower = name.toLowerCase();
97
+ if (
98
+ SAFE_RESPONSE_HEADER_EXACT.has(lower) ||
99
+ lower.startsWith("x-ratelimit-") ||
100
+ /^x-codex(?:-[a-z0-9-]+)?-(primary|secondary|tertiary)-(used-percent|window-minutes|reset-at)$/.test(lower) ||
101
+ /^x-codex(?:-[a-z0-9-]+)?-limit-name$/.test(lower)
102
+ ) {
103
+ out[lower] = value;
104
+ }
105
+ }
106
+ return out;
107
+ }
108
+
109
+ export function buildWarmupCompletionFrames(frame: Record<string, unknown>): string[] {
110
+ const createdAt = Math.floor(Date.now() / 1000);
111
+ const baseResponse: Record<string, unknown> = {
112
+ id: "",
113
+ object: "response",
114
+ created_at: createdAt,
115
+ model: typeof frame.model === "string" ? frame.model : undefined,
116
+ output: [],
117
+ };
118
+ return [
119
+ JSON.stringify({
120
+ type: "response.created",
121
+ sequence_number: 0,
122
+ response: { ...baseResponse, status: "in_progress" },
123
+ }),
124
+ JSON.stringify({
125
+ type: "response.completed",
126
+ sequence_number: 1,
127
+ response: { ...baseResponse, status: "completed" },
128
+ }),
129
+ ];
130
+ }
131
+
132
+ export function sendTextFrame(ws: ServerWebSocket<WsData>, payload: string): void {
133
+ if (ws.readyState !== OPEN) throw new WsSendDroppedError();
134
+ const result = ws.send(payload);
135
+ if (result === 0) throw new WsSendDroppedError();
136
+ // Bun returns -1 when queued with backpressure. That is accepted; a later 0 is the hard failure.
137
+ }
138
+
139
+ export function sendJsonFrame(ws: ServerWebSocket<WsData>, payload: Record<string, unknown>): void {
140
+ sendTextFrame(ws, JSON.stringify(payload));
141
+ }
142
+
143
+ export function buildWsErrorFrame(
144
+ status: number,
145
+ error: Record<string, unknown>,
146
+ headers?: Headers,
147
+ ): Record<string, unknown> {
148
+ return {
149
+ type: "error",
150
+ status,
151
+ error,
152
+ headers: headers ? safeResponseHeaders(headers) : {},
153
+ };
154
+ }
155
+
156
+ function parseSseBlock(block: string): string | null {
157
+ const data: string[] = [];
158
+ for (const line of block.split(/\r?\n/)) {
159
+ if (line.startsWith("data:")) {
160
+ const value = line.slice(5);
161
+ data.push(value.startsWith(" ") ? value.slice(1) : value);
162
+ }
163
+ }
164
+ return data.length > 0 ? data.join("\n") : null;
165
+ }
166
+
167
+ function payloadType(payload: string): string | null {
168
+ try {
169
+ const json = JSON.parse(payload) as { type?: unknown };
170
+ return typeof json.type === "string" ? json.type : null;
171
+ } catch {
172
+ return null;
173
+ }
174
+ }
175
+
176
+ function terminalStatusFromType(type: string): ResponsesTerminalStatus | null {
177
+ switch (type) {
178
+ case "response.completed":
179
+ return "completed";
180
+ case "response.failed":
181
+ return "failed";
182
+ case "response.incomplete":
183
+ return "incomplete";
184
+ default:
185
+ return null;
186
+ }
187
+ }
188
+
189
+ function protocolError(message: string): Record<string, unknown> {
190
+ return {
191
+ type: "protocol_error",
192
+ code: "websocket_protocol_error",
193
+ message,
194
+ };
195
+ }
196
+
197
+ function sendProtocolError(ws: ServerWebSocket<WsData>, status: number, message: string): void {
198
+ sendJsonFrame(ws, buildWsErrorFrame(status, protocolError(message)));
199
+ }
200
+
201
+ export async function pumpResponsesSseToWebSocket(
202
+ ws: ServerWebSocket<WsData>,
203
+ sseStream: ReadableStream<Uint8Array>,
204
+ options: {
205
+ isCurrent?: () => boolean;
206
+ onTerminal?: ResponsesTerminalReporter;
207
+ onSsePayload?: ResponsesPayloadObserver;
208
+ } = {},
209
+ ): Promise<void> {
210
+ const reader = sseStream.getReader();
211
+ const isCurrent = options.isCurrent ?? (() => true);
212
+ let clientCancelled = false;
213
+ let terminalReported = false;
214
+ const reportTerminal = (status: ResponsesTerminalStatus) => {
215
+ if (terminalReported || clientCancelled || !isCurrent()) return;
216
+ terminalReported = true;
217
+ options.onTerminal?.(status);
218
+ };
219
+ const cancel = () => {
220
+ clientCancelled = true;
221
+ void reader.cancel().catch(() => {});
222
+ };
223
+ ws.data.cancel = cancel;
224
+
225
+ const decoder = new TextDecoder();
226
+ const framer = new BoundedSseFrameBuffer();
227
+ let terminalSeen = false;
228
+
229
+ const handlePayload = (payload: string): boolean => {
230
+ if (!isCurrent()) return true;
231
+ if (payload === "[DONE]") return false;
232
+ try {
233
+ options.onSsePayload?.(payload);
234
+ } catch {
235
+ /* payload observation must not affect WebSocket delivery */
236
+ }
237
+ const type = payloadType(payload);
238
+ if (!type) {
239
+ reportTerminal("incomplete");
240
+ sendProtocolError(ws, 502, "Invalid JSON payload in upstream SSE frame");
241
+ terminalSeen = true;
242
+ void reader.cancel().catch(() => {});
243
+ return true;
244
+ }
245
+ if (terminalSeen) return true;
246
+ sendTextFrame(ws, payload);
247
+ const terminalStatus = terminalStatusFromType(type);
248
+ if (terminalStatus) {
249
+ reportTerminal(terminalStatus);
250
+ terminalSeen = true;
251
+ void reader.cancel().catch(() => {});
252
+ return true;
253
+ }
254
+ return false;
255
+ };
256
+
257
+ try {
258
+ while (!terminalSeen) {
259
+ const { done, value } = await reader.read();
260
+ if (done) break;
261
+ for (const frame of framer.feed(value)) {
262
+ const payload = parseSseBlock(decoder.decode(frame.block));
263
+ if (payload && handlePayload(payload)) break;
264
+ }
265
+ }
266
+ const tail = framer.finish();
267
+ if (!terminalSeen && tail.byteLength > 0) {
268
+ const payload = parseSseBlock(decoder.decode(tail));
269
+ if (payload) handlePayload(payload);
270
+ }
271
+ if (!terminalSeen && isCurrent() && !clientCancelled) {
272
+ reportTerminal("incomplete");
273
+ sendProtocolError(ws, 502, "Upstream stream ended before response terminal event");
274
+ }
275
+ } catch (err) {
276
+ framer.dispose();
277
+ if (err instanceof WsSendDroppedError) throw err;
278
+ if (!terminalSeen
279
+ && isCurrent()
280
+ && ws.readyState === OPEN
281
+ && !(err instanceof WsSendDroppedError)) {
282
+ reportTerminal("incomplete");
283
+ try {
284
+ sendProtocolError(ws, 502, err instanceof Error ? err.message : String(err));
285
+ } catch (sendErr) {
286
+ // If delivery is already dropped, there is no useful error frame left
287
+ // to send. Swallow only that expected transport signal; other failures
288
+ // still surface to the caller after the upstream reader is released.
289
+ if (!(sendErr instanceof WsSendDroppedError)) throw sendErr;
290
+ }
291
+ }
292
+ } finally {
293
+ framer.dispose();
294
+ // Framing errors can occur while the upstream body is still live. Always
295
+ // release the reader, even when terminal/send paths already cancelled it.
296
+ void reader.cancel().catch(() => {});
297
+ if (ws.data.cancel === cancel) ws.data.cancel = undefined;
298
+ }
299
+ }
300
+
301
+ export function sendResponsesJsonAsEvents(
302
+ ws: ServerWebSocket<WsData>,
303
+ response: Record<string, unknown>,
304
+ onTerminal?: ResponsesTerminalReporter,
305
+ onPayload?: ResponsesPayloadObserver,
306
+ ): void {
307
+ const sendObservedFrame = (payload: Record<string, unknown>) => {
308
+ const text = JSON.stringify(payload);
309
+ try {
310
+ onPayload?.(text);
311
+ } catch {
312
+ /* payload observation must not affect WebSocket delivery */
313
+ }
314
+ sendTextFrame(ws, text);
315
+ };
316
+ const finalStatus = response.status === "failed" || response.status === "incomplete"
317
+ ? response.status
318
+ : "completed";
319
+ for (const frame of responsesJsonEventSequence(response)) {
320
+ sendObservedFrame(frame);
321
+ }
322
+ onTerminal?.(finalStatus);
323
+ }
324
+
325
+ function errorPayloadFromText(text: string): Record<string, unknown> {
326
+ try {
327
+ const json = JSON.parse(text) as { error?: unknown };
328
+ if (json.error && typeof json.error === "object" && !Array.isArray(json.error)) {
329
+ return json.error as Record<string, unknown>;
330
+ }
331
+ } catch {
332
+ /* fall through */
333
+ }
334
+ return {
335
+ type: "upstream_error",
336
+ message: text ? text.slice(0, 500) : "Upstream request failed",
337
+ };
338
+ }
339
+
340
+ export async function sendResponseToWebSocket(
341
+ ws: ServerWebSocket<WsData>,
342
+ response: Response,
343
+ isCurrent: () => boolean,
344
+ options: {
345
+ onTerminal?: ResponsesTerminalReporter;
346
+ onSsePayload?: ResponsesPayloadObserver;
347
+ } = {},
348
+ ): Promise<void> {
349
+ if (!isCurrent()) {
350
+ await response.body?.cancel().catch(() => {});
351
+ return;
352
+ }
353
+
354
+ if (!response.ok) {
355
+ const text = await response.text().catch(() => "");
356
+ if (!isCurrent()) return;
357
+ sendJsonFrame(ws, buildWsErrorFrame(response.status, errorPayloadFromText(text), response.headers));
358
+ return;
359
+ }
360
+
361
+ const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
362
+ if (!response.body) {
363
+ options.onTerminal?.("incomplete");
364
+ sendJsonFrame(ws, buildWsErrorFrame(502, {
365
+ type: "protocol_error",
366
+ code: "websocket_protocol_error",
367
+ message: `Unexpected successful upstream response without a body (${response.status})`,
368
+ }, response.headers));
369
+ return;
370
+ }
371
+
372
+ if (contentType.includes("text/event-stream")) {
373
+ await pumpResponsesSseToWebSocket(ws, response.body, {
374
+ isCurrent,
375
+ onTerminal: options.onTerminal,
376
+ onSsePayload: options.onSsePayload,
377
+ });
378
+ return;
379
+ }
380
+
381
+ if (contentType.includes("application/json")) {
382
+ const text = await response.text();
383
+ if (!isCurrent()) return;
384
+ const json = JSON.parse(text) as Record<string, unknown>;
385
+ sendResponsesJsonAsEvents(ws, json, options.onTerminal, options.onSsePayload);
386
+ return;
387
+ }
388
+
389
+ const { prefix, stream } = await readBoundedPrefix(response.body);
390
+ if (!isCurrent()) {
391
+ await stream.cancel().catch(() => {});
392
+ return;
393
+ }
394
+ if (looksLikeSse(prefix)) {
395
+ await pumpResponsesSseToWebSocket(ws, stream, {
396
+ isCurrent,
397
+ onTerminal: options.onTerminal,
398
+ onSsePayload: options.onSsePayload,
399
+ });
400
+ return;
401
+ }
402
+
403
+ const text = await new Response(stream).text();
404
+ if (!isCurrent()) return;
405
+ const trimmed = text.trim();
406
+ if (trimmed.startsWith("{")) {
407
+ const json = JSON.parse(trimmed) as Record<string, unknown>;
408
+ sendResponsesJsonAsEvents(ws, json, options.onTerminal, options.onSsePayload);
409
+ return;
410
+ }
411
+
412
+ options.onTerminal?.("incomplete");
413
+ sendJsonFrame(ws, buildWsErrorFrame(502, {
414
+ type: "protocol_error",
415
+ code: "websocket_protocol_error",
416
+ message: `Unexpected successful non-SSE upstream response (${contentType || "missing content-type"})`,
417
+ }, response.headers));
418
+ }
419
+
420
+ export async function readBoundedPrefix(
421
+ body: ReadableStream<Uint8Array>,
422
+ maxBytes = 4096,
423
+ ): Promise<{ prefix: Uint8Array; stream: ReadableStream<Uint8Array> }> {
424
+ const reader = body.getReader();
425
+ const chunks: Uint8Array[] = [];
426
+ let remainder: Uint8Array | undefined;
427
+ let total = 0;
428
+ while (total < maxBytes) {
429
+ const { done, value } = await reader.read();
430
+ if (done) break;
431
+ const take = Math.min(value.byteLength, maxBytes - total);
432
+ if (take > 0) {
433
+ chunks.push(value.slice(0, take));
434
+ total += take;
435
+ }
436
+ if (take < value.byteLength) {
437
+ remainder = value.slice(take);
438
+ break;
439
+ }
440
+ }
441
+ const prefix = new Uint8Array(total);
442
+ let offset = 0;
443
+ for (const chunk of chunks) {
444
+ prefix.set(chunk, offset);
445
+ offset += chunk.byteLength;
446
+ }
447
+ const stream = new ReadableStream<Uint8Array>({
448
+ start(controller) {
449
+ if (prefix.byteLength > 0) controller.enqueue(prefix);
450
+ if (remainder && remainder.byteLength > 0) controller.enqueue(remainder);
451
+ },
452
+ async pull(controller) {
453
+ const { done, value } = await reader.read();
454
+ if (done) {
455
+ controller.close();
456
+ return;
457
+ }
458
+ controller.enqueue(value);
459
+ },
460
+ cancel(reason) {
461
+ return reader.cancel(reason);
462
+ },
463
+ });
464
+ return { prefix, stream };
465
+ }
466
+
467
+ export function looksLikeSse(prefix: Uint8Array): boolean {
468
+ const text = new TextDecoder().decode(prefix);
469
+ return /^\s*(event:|data:)/.test(text);
470
+ }