@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,251 @@
1
+ /**
2
+ * Hard reasoning-effort caps (devlog/260710_subagent_effort_intercept).
3
+ *
4
+ * Prompt-side effort designation (injectionEffort) is advisory only: codex-rs inherits the
5
+ * parent's effective effort when spawn_agent carries no model/effort args
6
+ * (multi_agents_common.rs resolve defaults), rejects overrides on full-history forks, and a
7
+ * non-empty agent-role file rebuilds the child Config and silently drops spawn-time
8
+ * model/effort. So a session whose config default is ultra leaks max-tier children whenever
9
+ * the parent model spawns bare. This module is the enforcement path: it rewrites the effort
10
+ * of proxied turns at the single choke point every HTTP/WS turn passes through
11
+ * (handleResponses), using the same dual-shape rewrite contract as nativeEffortClamp —
12
+ * parsed.options.reasoning feeds routed adapters, _rawBody.reasoning.effort feeds the
13
+ * ChatGPT passthrough serializer.
14
+ */
15
+ import type { OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../types";
16
+ import { modelInList } from "../types";
17
+ import {
18
+ codexEffortRank,
19
+ configuredDefaultReasoningEffort,
20
+ configuredReasoningEfforts,
21
+ isCodexReasoningEffort,
22
+ modelRecordValue,
23
+ reasoningControlKindFor,
24
+ } from "../reasoning-effort";
25
+ import { catalogModelEfforts } from "../codex/catalog";
26
+
27
+ /**
28
+ * True when the request carries codex-rs's spawned-child markers, matched EXACTLY.
29
+ * Source of truth (openai/codex @ 6138909d): every collab-spawned child turn sends
30
+ * `x-openai-subagent: collab_spawn` (core/src/responses_metadata.rs) and embeds
31
+ * `"subagent_kind":"thread_spawn"` in the JSON `x-codex-turn-metadata` compatibility
32
+ * header. Both are checked: the WS bridge rebuilds internal requests from the
33
+ * FORWARD_HEADERS allowlist, so either header alone is sufficient evidence.
34
+ *
35
+ * Exact matching matters: upstream emits `x-openai-subagent` for OTHER internal
36
+ * turn categories too (review, compact, memory_consolidation, arbitrary "other"
37
+ * sources — responses_metadata.rs subagent_source). Those are maintenance turns,
38
+ * not spawned children, and must never trip subagentEffortCap.
39
+ */
40
+ export function isThreadSpawnRequest(headers: Headers): boolean {
41
+ if (headers.get("x-openai-subagent") === "collab_spawn") return true;
42
+ const turnMeta = headers.get("x-codex-turn-metadata");
43
+ if (!turnMeta) return false;
44
+ try {
45
+ const parsed = JSON.parse(turnMeta) as { subagent_kind?: unknown };
46
+ return parsed.subagent_kind === "thread_spawn";
47
+ } catch {
48
+ return false;
49
+ }
50
+ }
51
+
52
+ /** The effective ceiling for this turn, or undefined when no configured cap applies. */
53
+ export function effortCapFor(config: OcxConfig, subagent: boolean): string | undefined {
54
+ const caps: string[] = [];
55
+ if (config.effortCap && isCodexReasoningEffort(config.effortCap)) caps.push(config.effortCap);
56
+ if (subagent && config.subagentEffortCap && isCodexReasoningEffort(config.subagentEffortCap)) {
57
+ caps.push(config.subagentEffortCap);
58
+ }
59
+ if (caps.length === 0) return undefined;
60
+ return caps.reduce((low, cap) => (codexEffortRank(cap) < codexEffortRank(low) ? cap : low));
61
+ }
62
+
63
+ /**
64
+ * Whether the effort caps apply to this turn at all. Caps are a V2-surface feature
65
+ * (v1 sub-agents are pinned via explicit spawn args + injectionEffort prompting, so
66
+ * the ultra-default leak this module intercepts is v2-specific):
67
+ * - compaction turns are maintenance, not agent turns: they bypass caps entirely so
68
+ * native /v1/responses/compact (forwarded, never enters handleResponses) and routed
69
+ * compaction (synthesized internal request) get identical cap semantics.
70
+ * - multiAgentMode "v1" disables caps entirely (mirrors the GUI hiding the panel).
71
+ * - a main turn qualifies when its own tool list carries the v2 collab surface.
72
+ * - a CHILD turn is admitted by its spawned-child markers (isThreadSpawnRequest)
73
+ * REGARDLESS of tool surface: depth-limited leaves carry no collab tools (surface
74
+ * null) while children below the spawn-depth limit retain collab tools (spec_plan.rs
75
+ * leaf guard), so tool sniffing alone would cap siblings inconsistently.
76
+ * - a v1-surface MAIN turn (no child markers) never qualifies.
77
+ */
78
+ export function effortCapAppliesTo(
79
+ surface: "v1" | "v2" | null,
80
+ headers: Headers,
81
+ config: OcxConfig,
82
+ compaction = false,
83
+ ): boolean {
84
+ if (compaction) return false;
85
+ if (config.multiAgentMode === "v1") return false;
86
+ return surface === "v2" || isThreadSpawnRequest(headers);
87
+ }
88
+
89
+ /**
90
+ * The routed model's supported effort ladder for cap resolution, from the ROUTE's
91
+ * registry-merged provider (router.ts routedProviderConfig) — the persisted
92
+ * config.providers entry misses registry seeds, and bare ids can route via
93
+ * defaultModel/model-list/default-provider, so no "/" heuristic anywhere.
94
+ *
95
+ * - `[]` -> the model intentionally exposes no effort control (noReasoningModels or
96
+ * an explicitly empty configured ladder): cap resolution strips.
97
+ * - list -> sanitized + healed ladder (configuredReasoningEfforts).
98
+ * - undefined -> unknown. Includes the raw-nonempty-but-non-rankable case (e.g. a
99
+ * thinking-toggle ladder of ["enabled"]): sanitizing would flatten it to []
100
+ * and mis-classify it as "no effort control", so it stays unknown.
101
+ *
102
+ * Catalog fallback fires only for the ChatGPT-backend native passthrough IDENTITY
103
+ * (adapter "openai-responses" + authMode "forward", the fresh-install `openai`
104
+ * provider shape): the injected catalog is authoritative exactly for models Codex
105
+ * validates against that backend. A custom responses provider (key mode) serving a
106
+ * native-looking bare id must NOT inherit the unrelated native ladder.
107
+ */
108
+ export function supportedLadderFor(route: { provider: OcxProviderConfig; modelId: string }): string[] | undefined {
109
+ const { provider, modelId } = route;
110
+ if (modelInList(provider.noReasoningModels, modelId)) return [];
111
+ const control = reasoningControlKindFor(provider, modelId);
112
+ if (control === "unsupported") return [];
113
+ if (control === "unknown" || control === "automatic" || control === "toggle") return undefined;
114
+ const raw = modelRecordValue(provider.modelReasoningEfforts, modelId) ?? provider.reasoningEfforts;
115
+ if (raw !== undefined) {
116
+ const sanitized = configuredReasoningEfforts(provider, modelId) ?? [];
117
+ if (sanitized.length === 0 && raw.length > 0) return undefined;
118
+ return sanitized;
119
+ }
120
+ if (provider.adapter === "openai-responses" && provider.authMode === "forward") {
121
+ const efforts = catalogModelEfforts([modelId]).get(modelId);
122
+ if (efforts && efforts.length > 0) return efforts;
123
+ }
124
+ return undefined;
125
+ }
126
+
127
+ function writeReasoningEffort(parsed: OcxParsedRequest, effort: string | undefined): void {
128
+ parsed.options.reasoning = effort;
129
+ const raw = parsed._rawBody as { reasoning?: unknown } | undefined;
130
+ if (!raw) return;
131
+ const reasoning = raw.reasoning && typeof raw.reasoning === "object" && !Array.isArray(raw.reasoning)
132
+ ? raw.reasoning as Record<string, unknown>
133
+ : undefined;
134
+ if (effort === undefined) {
135
+ if (reasoning) delete reasoning.effort;
136
+ return;
137
+ }
138
+ raw.reasoning = { ...(reasoning ?? {}), effort };
139
+ }
140
+
141
+ /**
142
+ * Apply the resolved provider/model reasoning contract before any adapter sees the request.
143
+ * Unknown, unsupported, and automatic models receive no guessed effort parameter; effort models
144
+ * accept only their exact ladder; toggle models keep the caller's off/on intent for their owning
145
+ * adapter to serialize.
146
+ */
147
+ export function applyReasoningCapability(
148
+ parsed: OcxParsedRequest,
149
+ route: { provider: OcxProviderConfig; modelId: string },
150
+ ): { from: string; to: string } | null {
151
+ const { provider, modelId } = route;
152
+ const control = reasoningControlKindFor(provider, modelId);
153
+ if (control === undefined) return null;
154
+ const requested = parsed.options.reasoning;
155
+
156
+ if (control === "unknown" || control === "unsupported" || control === "automatic") {
157
+ if (!requested) return null;
158
+ writeReasoningEffort(parsed, undefined);
159
+ return { from: requested, to: control === "automatic" ? "auto" : "none" };
160
+ }
161
+ if (control === "toggle") return null;
162
+
163
+ const supported = configuredReasoningEfforts(provider, modelId) ?? [];
164
+ const required = modelRecordValue(provider.modelReasoningRequired, modelId) === true;
165
+ let effective: string | undefined;
166
+ if (!requested || requested === "none") {
167
+ effective = requested === "none" && supported.includes("none")
168
+ ? "none"
169
+ : required
170
+ ? configuredDefaultReasoningEffort(provider, modelId) ?? supported.find(value => value !== "none")
171
+ : undefined;
172
+ } else {
173
+ const boundary = requested === "ultra" ? "max" : requested;
174
+ if (supported.includes(boundary)) {
175
+ effective = boundary;
176
+ } else {
177
+ const requestedRank = codexEffortRank(boundary);
178
+ const ranked = supported
179
+ .filter(isCodexReasoningEffort)
180
+ .map(value => ({ value, rank: codexEffortRank(value) }))
181
+ .filter(value => value.rank >= 0)
182
+ .sort((a, b) => a.rank - b.rank);
183
+ effective = ranked.filter(value => value.rank <= requestedRank).at(-1)?.value
184
+ ?? ranked[0]?.value;
185
+ }
186
+ }
187
+ if (effective === requested) return null;
188
+ if (requested === "ultra" && effective === "max") {
189
+ writeReasoningEffort(parsed, effective);
190
+ return { from: requested, to: effective };
191
+ }
192
+ writeReasoningEffort(parsed, effective);
193
+ return { from: requested ?? "unset", to: effective ?? "none" };
194
+ }
195
+
196
+ /**
197
+ * Resolve the configured cap against the model's supported ladder. Returns the effective
198
+ * ceiling rung, or null when the turn must be STRIPPED of its effort entirely. The cap
199
+ * NEVER raises: when rankable rungs exist but none sits at or below the cap, the model
200
+ * cannot run within the ceiling, so the effort is stripped and the provider default
201
+ * applies (never a rung above the cap).
202
+ */
203
+ export function resolveCappedEffort(cap: string, supported: readonly string[] | undefined): string | null {
204
+ if (supported === undefined) return cap;
205
+ const rankable = supported.filter(isCodexReasoningEffort);
206
+ if (rankable.length === 0) {
207
+ // Nonempty but non-rankable (e.g. ["enabled"]) -> unknown ladder, cap as-is.
208
+ // Genuinely empty -> no effort control at all -> strip.
209
+ return supported.length > 0 ? cap : null;
210
+ }
211
+ const capRank = codexEffortRank(cap);
212
+ let best: string | null = null;
213
+ for (const rung of rankable) {
214
+ const rank = codexEffortRank(rung);
215
+ if (rank <= capRank && (best === null || rank > codexEffortRank(best))) best = rung;
216
+ }
217
+ return best;
218
+ }
219
+
220
+ /**
221
+ * Cap the turn's reasoning effort in BOTH request shapes. Non-strip resolution only
222
+ * lowers: efforts at or below the resolved ceiling (and non-ladder/absent efforts) pass
223
+ * untouched. Strip resolution (model exposes no effort control, or no supported rung
224
+ * fits under the cap) removes whatever effort is present — regardless of its rank —
225
+ * from both shapes while preserving `reasoning.summary`. Returns the applied rewrite
226
+ * for request-log annotation (`to: "none"` on strip), or null when nothing changed.
227
+ */
228
+ export function applyEffortCap(
229
+ parsed: OcxParsedRequest,
230
+ headers: Headers,
231
+ config: OcxConfig,
232
+ supported?: readonly string[] | undefined,
233
+ ): { from: string; to: string; subagent: boolean } | null {
234
+ const subagent = isThreadSpawnRequest(headers);
235
+ const cap = effortCapFor(config, subagent);
236
+ if (!cap) return null;
237
+ const resolved = resolveCappedEffort(cap, supported);
238
+ const requested = parsed.options.reasoning;
239
+ const raw = parsed._rawBody as { reasoning?: { effort?: string } } | undefined;
240
+ if (resolved === null) {
241
+ if (!requested) return null;
242
+ parsed.options.reasoning = undefined;
243
+ if (raw?.reasoning && typeof raw.reasoning === "object") delete raw.reasoning.effort;
244
+ return { from: requested, to: "none", subagent };
245
+ }
246
+ if (!requested || !isCodexReasoningEffort(requested)) return null;
247
+ if (codexEffortRank(requested) <= codexEffortRank(resolved)) return null;
248
+ parsed.options.reasoning = resolved;
249
+ if (raw?.reasoning && typeof raw.reasoning === "object") raw.reasoning.effort = resolved;
250
+ return { from: requested, to: resolved, subagent };
251
+ }
@@ -0,0 +1,338 @@
1
+ /**
2
+ * Client-facing repair for GitHub Copilot's `vscode-chat` Responses stream.
3
+ *
4
+ * Copilot can rotate opaque response/item ids between lifecycle events, expose
5
+ * provider-private reasoning ciphertext, and attach per-delta obfuscation
6
+ * padding while the authoritative complete tool input arrives on `.done`.
7
+ * Stock Responses clients cannot reconcile that dialect. This stateful block
8
+ * rewrite emits one coherent Responses SSE stream while the inspection branch
9
+ * keeps the raw upstream snapshot for provider replay.
10
+ */
11
+ import {
12
+ TranslatorBudgetExceededError,
13
+ type TranslatorBudget,
14
+ } from "../lib/translator-budget";
15
+ import {
16
+ replaceSseDataPayload,
17
+ sseDataPayload,
18
+ type SseBlockRewrite,
19
+ } from "./sse-payload-rewrite";
20
+
21
+ const MAX_TRACKED_ITEMS = 256;
22
+ const MAX_TRACKED_DEFERRED_CALLS = 256;
23
+ const RETAINED_STATE_LIMIT_BYTES = 256 * 1024;
24
+
25
+ type JsonRecord = Record<string, unknown>;
26
+
27
+ type TrackedItem = {
28
+ id: string;
29
+ type?: string;
30
+ encryptedReasoning: boolean;
31
+ };
32
+
33
+ type DeferredCallKind = "function" | "custom";
34
+
35
+ function isRecord(value: unknown): value is JsonRecord {
36
+ return typeof value === "object" && value !== null && !Array.isArray(value);
37
+ }
38
+
39
+ function outputIndexOf(value: unknown): number | undefined {
40
+ return typeof value === "number" && Number.isInteger(value) && value >= 0
41
+ ? value
42
+ : undefined;
43
+ }
44
+
45
+ function byteLength(value: unknown): number {
46
+ return Buffer.byteLength(JSON.stringify(value), "utf8");
47
+ }
48
+
49
+ function blockNewline(block: string): "\r\n" | "\n" {
50
+ return block.includes("\r\n") ? "\r\n" : "\n";
51
+ }
52
+
53
+ /** Keep a named SSE block's `event:` field aligned with its JSON `type`. */
54
+ function withEventName(block: string, eventName: string): string {
55
+ const newline = blockNewline(block);
56
+ const lines = block.split(/\r?\n/);
57
+ let replaced = false;
58
+ const rewritten = lines.flatMap((line) => {
59
+ if (!line.startsWith("event:")) return [line];
60
+ if (replaced) return [];
61
+ replaced = true;
62
+ return [`event: ${eventName}`];
63
+ });
64
+ if (!replaced) {
65
+ const dataIndex = rewritten.findIndex(line => line.startsWith("data:"));
66
+ rewritten.splice(dataIndex >= 0 ? dataIndex : 0, 0, `event: ${eventName}`);
67
+ }
68
+ return rewritten.join(newline);
69
+ }
70
+
71
+ function rewriteJsonBlock(block: string, event: JsonRecord): string {
72
+ const type = typeof event.type === "string" ? event.type : "message";
73
+ return withEventName(replaceSseDataPayload(block, JSON.stringify(event)), type);
74
+ }
75
+
76
+ function syntheticJsonBlock(template: string, event: JsonRecord): string {
77
+ const newline = blockNewline(template);
78
+ const type = typeof event.type === "string" ? event.type : "message";
79
+ return `event: ${type}${newline}data: ${JSON.stringify(event)}`;
80
+ }
81
+
82
+ function callKindForDelta(type: unknown): DeferredCallKind | undefined {
83
+ if (type === "response.function_call_arguments.delta") return "function";
84
+ if (type === "response.custom_tool_call_input.delta") return "custom";
85
+ return undefined;
86
+ }
87
+
88
+ function callKindForDone(type: unknown): DeferredCallKind | undefined {
89
+ if (type === "response.function_call_arguments.done") return "function";
90
+ if (type === "response.custom_tool_call_input.done") return "custom";
91
+ return undefined;
92
+ }
93
+
94
+ function callKey(kind: DeferredCallKind, outputIndex: number): string {
95
+ return `${kind}:${outputIndex}`;
96
+ }
97
+
98
+ function deltaTypeFor(kind: DeferredCallKind): string {
99
+ return kind === "function"
100
+ ? "response.function_call_arguments.delta"
101
+ : "response.custom_tool_call_input.delta";
102
+ }
103
+
104
+ function completeValueFor(kind: DeferredCallKind, event: JsonRecord): string {
105
+ const value = kind === "function" ? event.arguments : event.input;
106
+ return typeof value === "string" ? value : "";
107
+ }
108
+
109
+ /**
110
+ * Create one provider-scoped block rewrite per upstream response.
111
+ *
112
+ * Retained ids and pending-call markers are charged to the request translator
113
+ * budget and hard-capped. `dispose` releases them on terminal, EOF, cancel, or
114
+ * relay failure through the shared block-rewrite lifecycle.
115
+ */
116
+ export function createGithubCopilotResponsesBlockRewrite(
117
+ budget?: TranslatorBudget,
118
+ ): SseBlockRewrite {
119
+ const items = new Map<number, TrackedItem>();
120
+ const deferredCalls = new Map<string, number>();
121
+ let responseId: string | undefined;
122
+ let itemStateBytes = 0;
123
+ let callStateBytes = 0;
124
+ let nextSequenceNumber = 0;
125
+ let itemTrackingTainted = false;
126
+ let disposed = false;
127
+
128
+ const ensureStateLimit = (nextBytes: number): void => {
129
+ if (itemStateBytes + callStateBytes + nextBytes > RETAINED_STATE_LIMIT_BYTES) {
130
+ throw new TranslatorBudgetExceededError("item_ids", RETAINED_STATE_LIMIT_BYTES);
131
+ }
132
+ };
133
+
134
+ const chargeItemState = (bytes: number): void => {
135
+ ensureStateLimit(bytes);
136
+ budget?.chargeRetained(bytes, { kind: "item_ids" });
137
+ itemStateBytes += bytes;
138
+ };
139
+
140
+ const chargeCallState = (bytes: number): void => {
141
+ ensureStateLimit(bytes);
142
+ budget?.chargeRetained(bytes, { kind: "retained_collectors" });
143
+ callStateBytes += bytes;
144
+ };
145
+
146
+ const releaseDeferredCall = (key: string): boolean => {
147
+ const bytes = deferredCalls.get(key);
148
+ if (bytes === undefined) return false;
149
+ deferredCalls.delete(key);
150
+ callStateBytes -= bytes;
151
+ budget?.releaseRetained(bytes, { kind: "retained_collectors" });
152
+ return true;
153
+ };
154
+
155
+ const rememberResponseId = (candidate: string): string => {
156
+ if (responseId !== undefined) return responseId;
157
+ const bytes = byteLength(candidate);
158
+ chargeItemState(bytes);
159
+ responseId = candidate;
160
+ return candidate;
161
+ };
162
+
163
+ const rememberItem = (
164
+ outputIndex: number,
165
+ candidateId: string,
166
+ itemType?: string,
167
+ encryptedReasoning = false,
168
+ ): TrackedItem => {
169
+ const existing = items.get(outputIndex);
170
+ if (existing) {
171
+ if (existing.type === undefined && itemType !== undefined) {
172
+ const extra = byteLength(itemType);
173
+ chargeItemState(extra);
174
+ existing.type = itemType;
175
+ }
176
+ existing.encryptedReasoning ||= encryptedReasoning;
177
+ return existing;
178
+ }
179
+ if (itemTrackingTainted || items.size >= MAX_TRACKED_ITEMS) {
180
+ // Keep relaying client-visible events after the count cap, but stop
181
+ // retaining new output-index mappings. The current event still receives
182
+ // the provider id, while earlier retained mappings remain available for
183
+ // stable ids. Byte-budget failures stay hard failures.
184
+ itemTrackingTainted = true;
185
+ return { id: candidateId, type: itemType, encryptedReasoning };
186
+ }
187
+ chargeItemState(byteLength([outputIndex, candidateId, itemType ?? null]));
188
+ const tracked = { id: candidateId, type: itemType, encryptedReasoning };
189
+ items.set(outputIndex, tracked);
190
+ return tracked;
191
+ };
192
+
193
+ const rememberDeferredCall = (key: string): void => {
194
+ if (deferredCalls.has(key)) return;
195
+ if (deferredCalls.size >= MAX_TRACKED_DEFERRED_CALLS) {
196
+ throw new TranslatorBudgetExceededError("retained_collectors", RETAINED_STATE_LIMIT_BYTES);
197
+ }
198
+ const bytes = byteLength(key);
199
+ chargeCallState(bytes);
200
+ deferredCalls.set(key, bytes);
201
+ };
202
+
203
+ const sanitizeReasoningItem = (
204
+ item: JsonRecord,
205
+ tracked: TrackedItem,
206
+ ): void => {
207
+ if (item.type !== "reasoning") return;
208
+ const encrypted = typeof item.encrypted_content === "string";
209
+ tracked.encryptedReasoning ||= encrypted;
210
+ if (encrypted) delete item.encrypted_content;
211
+ if (tracked.encryptedReasoning) {
212
+ const summary = Array.isArray(item.summary) ? item.summary : [];
213
+ const hasPlaintextSummary = summary.some(part =>
214
+ isRecord(part)
215
+ && part.type === "summary_text"
216
+ && typeof part.text === "string"
217
+ && part.text.length > 0);
218
+ if (!hasPlaintextSummary) item.summary = [{ type: "summary_text", text: "" }];
219
+ if (!Array.isArray(item.content)) item.content = [];
220
+ }
221
+ };
222
+
223
+ const normalizeNestedItem = (item: JsonRecord, outputIndex: number): void => {
224
+ const candidateId = typeof item.id === "string" ? item.id : undefined;
225
+ if (candidateId === undefined) return;
226
+ const itemType = typeof item.type === "string" ? item.type : undefined;
227
+ const tracked = rememberItem(
228
+ outputIndex,
229
+ candidateId,
230
+ itemType,
231
+ itemType === "reasoning" && typeof item.encrypted_content === "string",
232
+ );
233
+ item.id = tracked.id;
234
+ sanitizeReasoningItem(item, tracked);
235
+ };
236
+
237
+ const normalizeSequence = (event: JsonRecord): void => {
238
+ if (typeof event.sequence_number !== "number" || !Number.isFinite(event.sequence_number)) return;
239
+ event.sequence_number = nextSequenceNumber++;
240
+ };
241
+
242
+ const dispose = (): void => {
243
+ if (disposed) return;
244
+ disposed = true;
245
+ if (itemStateBytes > 0) budget?.releaseRetained(itemStateBytes, { kind: "item_ids" });
246
+ if (callStateBytes > 0) budget?.releaseRetained(callStateBytes, { kind: "retained_collectors" });
247
+ items.clear();
248
+ deferredCalls.clear();
249
+ responseId = undefined;
250
+ itemStateBytes = 0;
251
+ callStateBytes = 0;
252
+ itemTrackingTainted = false;
253
+ };
254
+
255
+ const rewrite: SseBlockRewrite = (block) => {
256
+ const payload = sseDataPayload(block);
257
+ if (payload === null || payload === "[DONE]") return [block];
258
+
259
+ let event: unknown;
260
+ try {
261
+ event = JSON.parse(payload);
262
+ } catch {
263
+ return [block];
264
+ }
265
+ if (!isRecord(event)) return [block];
266
+
267
+ if (typeof event.obfuscation === "string") delete event.obfuscation;
268
+
269
+ const type = event.type;
270
+ const outputIndex = outputIndexOf(event.output_index);
271
+ const deltaKind = callKindForDelta(type);
272
+ const deferToolDelta = deltaKind !== undefined
273
+ && outputIndex !== undefined;
274
+
275
+ if (isRecord(event.response) && typeof event.response.id === "string") {
276
+ event.response.id = rememberResponseId(event.response.id);
277
+ }
278
+
279
+ if (outputIndex !== undefined && isRecord(event.item)) {
280
+ normalizeNestedItem(event.item, outputIndex);
281
+ }
282
+ // A deferred delta is not client-visible, so it must not establish the
283
+ // public item id if a malformed provider sends it before output_item.added.
284
+ if (!deferToolDelta && outputIndex !== undefined && typeof event.item_id === "string") {
285
+ const tracked = rememberItem(outputIndex, event.item_id);
286
+ event.item_id = tracked.id;
287
+ }
288
+
289
+ if (type === "response.completed" && isRecord(event.response) && Array.isArray(event.response.output)) {
290
+ event.response.output.forEach((item, index) => {
291
+ if (isRecord(item)) normalizeNestedItem(item, index);
292
+ });
293
+ }
294
+
295
+ if (typeof type === "string" && type.startsWith("response.reasoning")) {
296
+ if (typeof event.encrypted_content === "string") delete event.encrypted_content;
297
+ // `encrypted_content` is opaque replay state; summary delta/text fields
298
+ // are a separate, potentially readable part of the public Responses
299
+ // contract and must survive when Copilot provides them.
300
+ }
301
+
302
+ if (deferToolDelta) {
303
+ rememberDeferredCall(callKey(deltaKind, outputIndex));
304
+ // The OpenAI `obfuscation` field is padding, not a decryption key. Defer
305
+ // every Copilot tool fragment anyway: mixed padded/unpadded fragments and
306
+ // rotating ids cannot then produce duplicate or irreconcilable input.
307
+ // `.done` carries the authoritative complete value, which is emitted as
308
+ // one canonical delta immediately before the original `.done` event.
309
+ return [];
310
+ }
311
+
312
+ const emitted: Array<{ event: JsonRecord; synthetic: boolean }> = [];
313
+ const doneKind = callKindForDone(type);
314
+ if (doneKind !== undefined && outputIndex !== undefined) {
315
+ const key = callKey(doneKind, outputIndex);
316
+ if (releaseDeferredCall(key)) {
317
+ emitted.push({
318
+ synthetic: true,
319
+ event: {
320
+ type: deltaTypeFor(doneKind),
321
+ output_index: outputIndex,
322
+ ...(typeof event.item_id === "string" ? { item_id: event.item_id } : {}),
323
+ ...(typeof event.sequence_number === "number" ? { sequence_number: event.sequence_number } : {}),
324
+ delta: completeValueFor(doneKind, event),
325
+ },
326
+ });
327
+ }
328
+ }
329
+ emitted.push({ event, synthetic: false });
330
+
331
+ for (const entry of emitted) normalizeSequence(entry.event);
332
+ return emitted.map(entry => entry.synthetic
333
+ ? syntheticJsonBlock(block, entry.event)
334
+ : rewriteJsonBlock(block, entry.event));
335
+ };
336
+ rewrite.dispose = dispose;
337
+ return rewrite;
338
+ }