blackriver-gateway 3.8.46

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 (2415) hide show
  1. package/.env.example +2070 -0
  2. package/@omniroute/opencode-plugin/LICENSE +21 -0
  3. package/@omniroute/opencode-plugin/README.md +296 -0
  4. package/@omniroute/opencode-plugin/package-lock.json +1930 -0
  5. package/@omniroute/opencode-plugin/package.json +73 -0
  6. package/@omniroute/opencode-plugin/src/index.ts +4685 -0
  7. package/@omniroute/opencode-plugin/src/logger.ts +74 -0
  8. package/@omniroute/opencode-plugin/src/naming.ts +301 -0
  9. package/@omniroute/opencode-plugin/tsconfig.json +20 -0
  10. package/@omniroute/opencode-plugin/tsup.config.ts +20 -0
  11. package/@omniroute/opencode-provider/LICENSE +21 -0
  12. package/@omniroute/opencode-provider/README.md +156 -0
  13. package/@omniroute/opencode-provider/package-lock.json +1514 -0
  14. package/@omniroute/opencode-provider/package.json +63 -0
  15. package/@omniroute/opencode-provider/src/index.ts +908 -0
  16. package/@omniroute/opencode-provider/tsconfig.json +20 -0
  17. package/@omniroute/opencode-provider/tsup.config.ts +18 -0
  18. package/LICENSE +22 -0
  19. package/README.md +1265 -0
  20. package/bin/_ops-common.sh +70 -0
  21. package/bin/cli/CONVENTIONS.md +224 -0
  22. package/bin/cli/README.md +146 -0
  23. package/bin/cli/api-commands/agent-skills.mjs +70 -0
  24. package/bin/cli/api-commands/agentbridge.mjs +155 -0
  25. package/bin/cli/api-commands/api-keys.mjs +42 -0
  26. package/bin/cli/api-commands/audio.mjs +40 -0
  27. package/bin/cli/api-commands/chat.mjs +58 -0
  28. package/bin/cli/api-commands/cli-tools.mjs +361 -0
  29. package/bin/cli/api-commands/cloud.mjs +81 -0
  30. package/bin/cli/api-commands/combos.mjs +69 -0
  31. package/bin/cli/api-commands/compression.mjs +128 -0
  32. package/bin/cli/api-commands/embedded-services.mjs +202 -0
  33. package/bin/cli/api-commands/embeddings.mjs +42 -0
  34. package/bin/cli/api-commands/fallback.mjs +49 -0
  35. package/bin/cli/api-commands/images.mjs +42 -0
  36. package/bin/cli/api-commands/memory.mjs +251 -0
  37. package/bin/cli/api-commands/messages.mjs +40 -0
  38. package/bin/cli/api-commands/models.mjs +89 -0
  39. package/bin/cli/api-commands/moderations.mjs +24 -0
  40. package/bin/cli/api-commands/oauth.mjs +114 -0
  41. package/bin/cli/api-commands/playground.mjs +83 -0
  42. package/bin/cli/api-commands/pricing.mjs +44 -0
  43. package/bin/cli/api-commands/provider-nodes.mjs +62 -0
  44. package/bin/cli/api-commands/providers.mjs +148 -0
  45. package/bin/cli/api-commands/quota.mjs +154 -0
  46. package/bin/cli/api-commands/registry.mjs +75 -0
  47. package/bin/cli/api-commands/rerank.mjs +24 -0
  48. package/bin/cli/api-commands/responses.mjs +24 -0
  49. package/bin/cli/api-commands/settings.mjs +228 -0
  50. package/bin/cli/api-commands/system.mjs +320 -0
  51. package/bin/cli/api-commands/telemetry.mjs +26 -0
  52. package/bin/cli/api-commands/traffic-inspector.mjs +307 -0
  53. package/bin/cli/api-commands/translator.mjs +65 -0
  54. package/bin/cli/api-commands/usage.mjs +117 -0
  55. package/bin/cli/api.mjs +269 -0
  56. package/bin/cli/commands/a2a.mjs +323 -0
  57. package/bin/cli/commands/audit.mjs +203 -0
  58. package/bin/cli/commands/autostart.mjs +57 -0
  59. package/bin/cli/commands/backup.mjs +469 -0
  60. package/bin/cli/commands/batches.mjs +235 -0
  61. package/bin/cli/commands/cache.mjs +102 -0
  62. package/bin/cli/commands/chat.mjs +162 -0
  63. package/bin/cli/commands/cloud.mjs +233 -0
  64. package/bin/cli/commands/combo.mjs +361 -0
  65. package/bin/cli/commands/completion.mjs +346 -0
  66. package/bin/cli/commands/compression.mjs +247 -0
  67. package/bin/cli/commands/config.mjs +351 -0
  68. package/bin/cli/commands/configure.mjs +180 -0
  69. package/bin/cli/commands/connect.mjs +132 -0
  70. package/bin/cli/commands/context-eng.mjs +182 -0
  71. package/bin/cli/commands/contexts.mjs +271 -0
  72. package/bin/cli/commands/cost.mjs +144 -0
  73. package/bin/cli/commands/dashboard.mjs +65 -0
  74. package/bin/cli/commands/doctor.mjs +527 -0
  75. package/bin/cli/commands/env.mjs +100 -0
  76. package/bin/cli/commands/eval.mjs +278 -0
  77. package/bin/cli/commands/files.mjs +144 -0
  78. package/bin/cli/commands/health.mjs +123 -0
  79. package/bin/cli/commands/keys.mjs +599 -0
  80. package/bin/cli/commands/launch-codex.mjs +201 -0
  81. package/bin/cli/commands/launch.mjs +155 -0
  82. package/bin/cli/commands/login.mjs +192 -0
  83. package/bin/cli/commands/logs.mjs +183 -0
  84. package/bin/cli/commands/mcp.mjs +273 -0
  85. package/bin/cli/commands/memory.mjs +244 -0
  86. package/bin/cli/commands/models.mjs +92 -0
  87. package/bin/cli/commands/nodes.mjs +177 -0
  88. package/bin/cli/commands/oauth.mjs +258 -0
  89. package/bin/cli/commands/oneproxy.mjs +120 -0
  90. package/bin/cli/commands/open.mjs +75 -0
  91. package/bin/cli/commands/openapi.mjs +168 -0
  92. package/bin/cli/commands/plugin.mjs +219 -0
  93. package/bin/cli/commands/policy.mjs +216 -0
  94. package/bin/cli/commands/pricing.mjs +123 -0
  95. package/bin/cli/commands/provider-cmd.mjs +18 -0
  96. package/bin/cli/commands/providers.mjs +706 -0
  97. package/bin/cli/commands/quota.mjs +100 -0
  98. package/bin/cli/commands/redis.mjs +294 -0
  99. package/bin/cli/commands/registry.mjs +162 -0
  100. package/bin/cli/commands/repl.mjs +19 -0
  101. package/bin/cli/commands/reset-encrypted-columns.mjs +88 -0
  102. package/bin/cli/commands/resilience.mjs +208 -0
  103. package/bin/cli/commands/restart.mjs +25 -0
  104. package/bin/cli/commands/runtime.mjs +98 -0
  105. package/bin/cli/commands/serve.mjs +426 -0
  106. package/bin/cli/commands/sessions.mjs +108 -0
  107. package/bin/cli/commands/setup-aider.mjs +146 -0
  108. package/bin/cli/commands/setup-claude.mjs +219 -0
  109. package/bin/cli/commands/setup-cline.mjs +160 -0
  110. package/bin/cli/commands/setup-codex.mjs +387 -0
  111. package/bin/cli/commands/setup-continue.mjs +173 -0
  112. package/bin/cli/commands/setup-crush.mjs +148 -0
  113. package/bin/cli/commands/setup-cursor.mjs +108 -0
  114. package/bin/cli/commands/setup-goose.mjs +150 -0
  115. package/bin/cli/commands/setup-kilo.mjs +178 -0
  116. package/bin/cli/commands/setup-open-code.mjs +398 -0
  117. package/bin/cli/commands/setup-opencode.mjs +129 -0
  118. package/bin/cli/commands/setup-qwen.mjs +156 -0
  119. package/bin/cli/commands/setup-roo.mjs +172 -0
  120. package/bin/cli/commands/setup.mjs +211 -0
  121. package/bin/cli/commands/simulate.mjs +125 -0
  122. package/bin/cli/commands/skills.mjs +373 -0
  123. package/bin/cli/commands/status.mjs +95 -0
  124. package/bin/cli/commands/stop.mjs +96 -0
  125. package/bin/cli/commands/stream.mjs +166 -0
  126. package/bin/cli/commands/sync.mjs +230 -0
  127. package/bin/cli/commands/tags.mjs +116 -0
  128. package/bin/cli/commands/telemetry.mjs +74 -0
  129. package/bin/cli/commands/test-provider.mjs +242 -0
  130. package/bin/cli/commands/tokens.mjs +118 -0
  131. package/bin/cli/commands/translator.mjs +131 -0
  132. package/bin/cli/commands/tray.mjs +36 -0
  133. package/bin/cli/commands/tunnel.mjs +347 -0
  134. package/bin/cli/commands/update.mjs +194 -0
  135. package/bin/cli/commands/usage.mjs +331 -0
  136. package/bin/cli/commands/webhooks.mjs +196 -0
  137. package/bin/cli/contexts.mjs +60 -0
  138. package/bin/cli/data-dir.mjs +59 -0
  139. package/bin/cli/encryption.mjs +67 -0
  140. package/bin/cli/i18n.mjs +106 -0
  141. package/bin/cli/io.mjs +83 -0
  142. package/bin/cli/locales/ar.json +32 -0
  143. package/bin/cli/locales/az.json +32 -0
  144. package/bin/cli/locales/bg.json +32 -0
  145. package/bin/cli/locales/bn.json +5 -0
  146. package/bin/cli/locales/cs.json +32 -0
  147. package/bin/cli/locales/da.json +32 -0
  148. package/bin/cli/locales/de.json +32 -0
  149. package/bin/cli/locales/en.json +1289 -0
  150. package/bin/cli/locales/es.json +32 -0
  151. package/bin/cli/locales/fa.json +32 -0
  152. package/bin/cli/locales/fi.json +32 -0
  153. package/bin/cli/locales/fr.json +32 -0
  154. package/bin/cli/locales/gu.json +5 -0
  155. package/bin/cli/locales/he.json +5 -0
  156. package/bin/cli/locales/hi.json +32 -0
  157. package/bin/cli/locales/hu.json +32 -0
  158. package/bin/cli/locales/id.json +32 -0
  159. package/bin/cli/locales/in.json +5 -0
  160. package/bin/cli/locales/it.json +32 -0
  161. package/bin/cli/locales/ja.json +32 -0
  162. package/bin/cli/locales/ko.json +32 -0
  163. package/bin/cli/locales/mr.json +5 -0
  164. package/bin/cli/locales/ms.json +5 -0
  165. package/bin/cli/locales/nl.json +32 -0
  166. package/bin/cli/locales/no.json +32 -0
  167. package/bin/cli/locales/phi.json +5 -0
  168. package/bin/cli/locales/pl.json +32 -0
  169. package/bin/cli/locales/pt-BR.json +1286 -0
  170. package/bin/cli/locales/pt.json +32 -0
  171. package/bin/cli/locales/ro.json +32 -0
  172. package/bin/cli/locales/ru.json +32 -0
  173. package/bin/cli/locales/sk.json +32 -0
  174. package/bin/cli/locales/sv.json +32 -0
  175. package/bin/cli/locales/sw.json +5 -0
  176. package/bin/cli/locales/ta.json +5 -0
  177. package/bin/cli/locales/te.json +5 -0
  178. package/bin/cli/locales/th.json +32 -0
  179. package/bin/cli/locales/tr.json +32 -0
  180. package/bin/cli/locales/uk-UA.json +32 -0
  181. package/bin/cli/locales/ur.json +5 -0
  182. package/bin/cli/locales/vi.json +32 -0
  183. package/bin/cli/locales/zh-CN.json +1262 -0
  184. package/bin/cli/output.mjs +200 -0
  185. package/bin/cli/plugins.mjs +90 -0
  186. package/bin/cli/program.mjs +40 -0
  187. package/bin/cli/provider-catalog.mjs +175 -0
  188. package/bin/cli/provider-store.mjs +312 -0
  189. package/bin/cli/provider-test.mjs +181 -0
  190. package/bin/cli/runtime/index.mjs +19 -0
  191. package/bin/cli/runtime/magicBytes.mjs +47 -0
  192. package/bin/cli/runtime/nativeDeps.mjs +137 -0
  193. package/bin/cli/runtime/processSupervisor.mjs +136 -0
  194. package/bin/cli/runtime/sqliteRuntime.mjs +129 -0
  195. package/bin/cli/runtime/supervisorPolicy.mjs +56 -0
  196. package/bin/cli/runtime/trayRuntime.ts +94 -0
  197. package/bin/cli/runtime.mjs +61 -0
  198. package/bin/cli/schemas/output-schemas.mjs +56 -0
  199. package/bin/cli/scripts/generate-locales.mjs +911 -0
  200. package/bin/cli/settings-store.mjs +45 -0
  201. package/bin/cli/spinner.mjs +30 -0
  202. package/bin/cli/sqlite.mjs +158 -0
  203. package/bin/cli/tray/autostart.mjs +410 -0
  204. package/bin/cli/tray/autostart.ts +18 -0
  205. package/bin/cli/tray/icon.png +0 -0
  206. package/bin/cli/tray/index.mjs +28 -0
  207. package/bin/cli/tray/tray.ps1 +99 -0
  208. package/bin/cli/tray/tray.ts +186 -0
  209. package/bin/cli/tray/traySystray.mjs +135 -0
  210. package/bin/cli/tray/trayWin.ts +91 -0
  211. package/bin/cli/tray/trayWindows.mjs +75 -0
  212. package/bin/cli/tui/Dashboard.jsx +70 -0
  213. package/bin/cli/tui/EvalWatch.jsx +171 -0
  214. package/bin/cli/tui/InterfaceMenu.jsx +55 -0
  215. package/bin/cli/tui/OAuthFlow.jsx +193 -0
  216. package/bin/cli/tui/ProvidersTestAll.jsx +190 -0
  217. package/bin/cli/tui/Repl.jsx +392 -0
  218. package/bin/cli/tui/session.mjs +54 -0
  219. package/bin/cli/tui/tabs/Combos.jsx +47 -0
  220. package/bin/cli/tui/tabs/Cost.jsx +52 -0
  221. package/bin/cli/tui/tabs/Health.jsx +53 -0
  222. package/bin/cli/tui/tabs/Keys.jsx +48 -0
  223. package/bin/cli/tui/tabs/Logs.jsx +60 -0
  224. package/bin/cli/tui/tabs/Overview.jsx +80 -0
  225. package/bin/cli/tui/tabs/Providers.jsx +48 -0
  226. package/bin/cli/tui-components/CodeBlock.jsx +15 -0
  227. package/bin/cli/tui-components/ConfirmDialog.jsx +40 -0
  228. package/bin/cli/tui-components/DataTable.jsx +50 -0
  229. package/bin/cli/tui-components/HeaderSwr.jsx +25 -0
  230. package/bin/cli/tui-components/KeyMaskedDisplay.jsx +12 -0
  231. package/bin/cli/tui-components/MarkdownView.jsx +13 -0
  232. package/bin/cli/tui-components/MenuSelect.jsx +38 -0
  233. package/bin/cli/tui-components/MultilineInput.jsx +18 -0
  234. package/bin/cli/tui-components/ProgressBar.jsx +15 -0
  235. package/bin/cli/tui-components/Sparkline.jsx +15 -0
  236. package/bin/cli/tui-components/StatusBadge.jsx +17 -0
  237. package/bin/cli/tui-components/TokenCounter.jsx +18 -0
  238. package/bin/cli/tui-components/theme.jsx +11 -0
  239. package/bin/cli/utils/cliToken.mjs +22 -0
  240. package/bin/cli/utils/clipboard.mjs +35 -0
  241. package/bin/cli/utils/environment.mjs +50 -0
  242. package/bin/cli/utils/pid.mjs +110 -0
  243. package/bin/cli/utils/storageKeyProvision.mjs +31 -0
  244. package/bin/cold-start-bench.sh +82 -0
  245. package/bin/mcp-server.mjs +71 -0
  246. package/bin/nodeRuntimeSupport.mjs +84 -0
  247. package/bin/omniroute.mjs +237 -0
  248. package/bin/reset-password.mjs +137 -0
  249. package/bin/restore-data.sh +64 -0
  250. package/bin/restore-policies.sh +77 -0
  251. package/bin/rollback.sh +102 -0
  252. package/bin/snapshot-data.sh +61 -0
  253. package/open-sse/config/agyModels.ts +157 -0
  254. package/open-sse/config/anthropicHeaders.ts +127 -0
  255. package/open-sse/config/antigravityModelAliases.ts +309 -0
  256. package/open-sse/config/antigravityUpstream.ts +20 -0
  257. package/open-sse/config/audioRegistry.ts +547 -0
  258. package/open-sse/config/azureAi.ts +49 -0
  259. package/open-sse/config/bedrock.ts +196 -0
  260. package/open-sse/config/cliFingerprints.ts +405 -0
  261. package/open-sse/config/codexClient.ts +49 -0
  262. package/open-sse/config/codexIdentity.ts +87 -0
  263. package/open-sse/config/codexInstructions.ts +122 -0
  264. package/open-sse/config/codexQuotaScopes.ts +87 -0
  265. package/open-sse/config/constants.ts +281 -0
  266. package/open-sse/config/contextEditing.ts +156 -0
  267. package/open-sse/config/credentialLoader.ts +123 -0
  268. package/open-sse/config/datarobot.ts +69 -0
  269. package/open-sse/config/defaultThinkingSignature.ts +8 -0
  270. package/open-sse/config/embeddingRegistry.ts +434 -0
  271. package/open-sse/config/errorConfig.ts +201 -0
  272. package/open-sse/config/freeModelCatalog.data.ts +467 -0
  273. package/open-sse/config/freeModelCatalog.ts +142 -0
  274. package/open-sse/config/freeTierCatalog.ts +101 -0
  275. package/open-sse/config/geminiRateLimits.json +34 -0
  276. package/open-sse/config/glmProvider.ts +488 -0
  277. package/open-sse/config/imageRegistry.ts +752 -0
  278. package/open-sse/config/maritalk.ts +18 -0
  279. package/open-sse/config/mediaServiceKinds.ts +70 -0
  280. package/open-sse/config/moderationRegistry.ts +89 -0
  281. package/open-sse/config/musicRegistry.ts +115 -0
  282. package/open-sse/config/oci.ts +44 -0
  283. package/open-sse/config/ocrRegistry.ts +82 -0
  284. package/open-sse/config/ollamaModels.ts +28 -0
  285. package/open-sse/config/providerErrorRules.ts +218 -0
  286. package/open-sse/config/providerFieldStrips.ts +42 -0
  287. package/open-sse/config/providerHeaderProfiles.ts +188 -0
  288. package/open-sse/config/providerModels.ts +199 -0
  289. package/open-sse/config/providerPluginManifest.ts +186 -0
  290. package/open-sse/config/providerPluginManifestRegistry.ts +31 -0
  291. package/open-sse/config/providerPluginManifestUrl.ts +26 -0
  292. package/open-sse/config/providerRegistry.ts +257 -0
  293. package/open-sse/config/providers/index.ts +377 -0
  294. package/open-sse/config/providers/registry/adapta-web/index.ts +20 -0
  295. package/open-sse/config/providers/registry/agentrouter/index.ts +24 -0
  296. package/open-sse/config/providers/registry/agy/index.ts +28 -0
  297. package/open-sse/config/providers/registry/ai21/index.ts +13 -0
  298. package/open-sse/config/providers/registry/aimlapi/index.ts +21 -0
  299. package/open-sse/config/providers/registry/alibaba/cn/index.ts +15 -0
  300. package/open-sse/config/providers/registry/alibaba/index.ts +15 -0
  301. package/open-sse/config/providers/registry/anthropic/index.ts +52 -0
  302. package/open-sse/config/providers/registry/antigravity/index.ts +28 -0
  303. package/open-sse/config/providers/registry/api-airforce/index.ts +57 -0
  304. package/open-sse/config/providers/registry/auggie/index.ts +38 -0
  305. package/open-sse/config/providers/registry/bai/index.ts +14 -0
  306. package/open-sse/config/providers/registry/baichuan/index.ts +20 -0
  307. package/open-sse/config/providers/registry/baidu/index.ts +31 -0
  308. package/open-sse/config/providers/registry/bailian-coding-plan/index.ts +27 -0
  309. package/open-sse/config/providers/registry/baseten/index.ts +13 -0
  310. package/open-sse/config/providers/registry/bazaarlink/index.ts +48 -0
  311. package/open-sse/config/providers/registry/bedrock/index.ts +49 -0
  312. package/open-sse/config/providers/registry/blackbox/index.ts +25 -0
  313. package/open-sse/config/providers/registry/blackbox/web/index.ts +19 -0
  314. package/open-sse/config/providers/registry/bluesminds/index.ts +39 -0
  315. package/open-sse/config/providers/registry/byteplus/index.ts +21 -0
  316. package/open-sse/config/providers/registry/bytez/index.ts +17 -0
  317. package/open-sse/config/providers/registry/cerebras/index.ts +16 -0
  318. package/open-sse/config/providers/registry/charm-hyper/index.ts +14 -0
  319. package/open-sse/config/providers/registry/chatgpt-web/index.ts +23 -0
  320. package/open-sse/config/providers/registry/chipotle/index.ts +14 -0
  321. package/open-sse/config/providers/registry/chutes/index.ts +12 -0
  322. package/open-sse/config/providers/registry/claude/index.ts +102 -0
  323. package/open-sse/config/providers/registry/claude/web/index.ts +16 -0
  324. package/open-sse/config/providers/registry/cline/index.ts +45 -0
  325. package/open-sse/config/providers/registry/clinepass/index.ts +47 -0
  326. package/open-sse/config/providers/registry/cloudflare-ai/index.ts +33 -0
  327. package/open-sse/config/providers/registry/codebuddy-cn/index.ts +151 -0
  328. package/open-sse/config/providers/registry/codestral/index.ts +13 -0
  329. package/open-sse/config/providers/registry/codex/index.ts +115 -0
  330. package/open-sse/config/providers/registry/cohere/index.ts +28 -0
  331. package/open-sse/config/providers/registry/command-code/index.ts +143 -0
  332. package/open-sse/config/providers/registry/copilot-m365-web/index.ts +12 -0
  333. package/open-sse/config/providers/registry/copilot-web/index.ts +16 -0
  334. package/open-sse/config/providers/registry/coze/index.ts +12 -0
  335. package/open-sse/config/providers/registry/crof/index.ts +38 -0
  336. package/open-sse/config/providers/registry/cursor/index.ts +111 -0
  337. package/open-sse/config/providers/registry/databricks/index.ts +13 -0
  338. package/open-sse/config/providers/registry/deepinfra/index.ts +13 -0
  339. package/open-sse/config/providers/registry/deepseek/index.ts +15 -0
  340. package/open-sse/config/providers/registry/deepseek/web/index.ts +35 -0
  341. package/open-sse/config/providers/registry/devin-cli/index.ts +68 -0
  342. package/open-sse/config/providers/registry/dgrid/index.ts +15 -0
  343. package/open-sse/config/providers/registry/dify/index.ts +12 -0
  344. package/open-sse/config/providers/registry/digitalocean/index.ts +11 -0
  345. package/open-sse/config/providers/registry/dit/index.ts +41 -0
  346. package/open-sse/config/providers/registry/doubao/index.ts +28 -0
  347. package/open-sse/config/providers/registry/doubao/web/index.ts +15 -0
  348. package/open-sse/config/providers/registry/duckduckgo-web/index.ts +19 -0
  349. package/open-sse/config/providers/registry/factory/index.ts +33 -0
  350. package/open-sse/config/providers/registry/featherless-ai/index.ts +13 -0
  351. package/open-sse/config/providers/registry/fireworks/index.ts +35 -0
  352. package/open-sse/config/providers/registry/freeaiapikey/index.ts +38 -0
  353. package/open-sse/config/providers/registry/freemodel-dev/index.ts +19 -0
  354. package/open-sse/config/providers/registry/friendliai/index.ts +16 -0
  355. package/open-sse/config/providers/registry/galadriel/index.ts +13 -0
  356. package/open-sse/config/providers/registry/gemini/index.ts +63 -0
  357. package/open-sse/config/providers/registry/gemini/web/index.ts +16 -0
  358. package/open-sse/config/providers/registry/gigachat/index.ts +13 -0
  359. package/open-sse/config/providers/registry/github/index.ts +161 -0
  360. package/open-sse/config/providers/registry/github/models/index.ts +38 -0
  361. package/open-sse/config/providers/registry/gitlab-duo/index.ts +29 -0
  362. package/open-sse/config/providers/registry/gitlawb/gmi/index.ts +19 -0
  363. package/open-sse/config/providers/registry/gitlawb/index.ts +18 -0
  364. package/open-sse/config/providers/registry/glhf/index.ts +12 -0
  365. package/open-sse/config/providers/registry/glm/cn/index.ts +17 -0
  366. package/open-sse/config/providers/registry/glm/index.ts +16 -0
  367. package/open-sse/config/providers/registry/glm/t/index.ts +16 -0
  368. package/open-sse/config/providers/registry/grok-cli/index.ts +32 -0
  369. package/open-sse/config/providers/registry/grok-web/index.ts +18 -0
  370. package/open-sse/config/providers/registry/groq/index.ts +25 -0
  371. package/open-sse/config/providers/registry/hackclub/index.ts +19 -0
  372. package/open-sse/config/providers/registry/haiper/index.ts +15 -0
  373. package/open-sse/config/providers/registry/hcnsec/index.ts +11 -0
  374. package/open-sse/config/providers/registry/heroku/index.ts +13 -0
  375. package/open-sse/config/providers/registry/huggingchat/index.ts +143 -0
  376. package/open-sse/config/providers/registry/huggingface/index.ts +20 -0
  377. package/open-sse/config/providers/registry/hyperbolic/index.ts +21 -0
  378. package/open-sse/config/providers/registry/ideogram/index.ts +15 -0
  379. package/open-sse/config/providers/registry/iflytek/index.ts +21 -0
  380. package/open-sse/config/providers/registry/inclusionai/index.ts +12 -0
  381. package/open-sse/config/providers/registry/inference-net/index.ts +13 -0
  382. package/open-sse/config/providers/registry/inner-ai/index.ts +43 -0
  383. package/open-sse/config/providers/registry/kenari/index.ts +14 -0
  384. package/open-sse/config/providers/registry/kie/index.ts +27 -0
  385. package/open-sse/config/providers/registry/kilo-gateway/index.ts +21 -0
  386. package/open-sse/config/providers/registry/kilocode/index.ts +43 -0
  387. package/open-sse/config/providers/registry/kimi/coding/index.ts +17 -0
  388. package/open-sse/config/providers/registry/kimi/coding-apikey/index.ts +9 -0
  389. package/open-sse/config/providers/registry/kimi/index.ts +17 -0
  390. package/open-sse/config/providers/registry/kimi/web/index.ts +27 -0
  391. package/open-sse/config/providers/registry/kiro/index.ts +50 -0
  392. package/open-sse/config/providers/registry/kluster/index.ts +12 -0
  393. package/open-sse/config/providers/registry/lambda-ai/index.ts +13 -0
  394. package/open-sse/config/providers/registry/leonardo/index.ts +15 -0
  395. package/open-sse/config/providers/registry/liquid/index.ts +12 -0
  396. package/open-sse/config/providers/registry/llamagate/index.ts +13 -0
  397. package/open-sse/config/providers/registry/llm7/index.ts +27 -0
  398. package/open-sse/config/providers/registry/longcat/index.ts +24 -0
  399. package/open-sse/config/providers/registry/maritalk/index.ts +13 -0
  400. package/open-sse/config/providers/registry/meta-llama/index.ts +13 -0
  401. package/open-sse/config/providers/registry/mimocode/index.ts +16 -0
  402. package/open-sse/config/providers/registry/minimax/cn/index.ts +24 -0
  403. package/open-sse/config/providers/registry/minimax/index.ts +24 -0
  404. package/open-sse/config/providers/registry/mistral/index.ts +18 -0
  405. package/open-sse/config/providers/registry/modal/index.ts +12 -0
  406. package/open-sse/config/providers/registry/modelscope/index.ts +24 -0
  407. package/open-sse/config/providers/registry/monsterapi/index.ts +17 -0
  408. package/open-sse/config/providers/registry/moonshot/index.ts +13 -0
  409. package/open-sse/config/providers/registry/morph/index.ts +13 -0
  410. package/open-sse/config/providers/registry/muse-spark-web/index.ts +24 -0
  411. package/open-sse/config/providers/registry/nanogpt/index.ts +13 -0
  412. package/open-sse/config/providers/registry/nebius/index.ts +9 -0
  413. package/open-sse/config/providers/registry/nlpcloud/index.ts +19 -0
  414. package/open-sse/config/providers/registry/nous-research/index.ts +15 -0
  415. package/open-sse/config/providers/registry/novita/index.ts +15 -0
  416. package/open-sse/config/providers/registry/nscale/index.ts +13 -0
  417. package/open-sse/config/providers/registry/nube/index.ts +17 -0
  418. package/open-sse/config/providers/registry/nvidia/index.ts +36 -0
  419. package/open-sse/config/providers/registry/ollama-cloud/index.ts +27 -0
  420. package/open-sse/config/providers/registry/openadapter/index.ts +25 -0
  421. package/open-sse/config/providers/registry/openai/index.ts +43 -0
  422. package/open-sse/config/providers/registry/opencode/go/index.ts +61 -0
  423. package/open-sse/config/providers/registry/opencode/index.ts +51 -0
  424. package/open-sse/config/providers/registry/opencode/zen/index.ts +98 -0
  425. package/open-sse/config/providers/registry/openrouter/index.ts +17 -0
  426. package/open-sse/config/providers/registry/orcarouter/index.ts +87 -0
  427. package/open-sse/config/providers/registry/ovhcloud/index.ts +13 -0
  428. package/open-sse/config/providers/registry/perplexity/index.ts +22 -0
  429. package/open-sse/config/providers/registry/perplexity/web/index.ts +23 -0
  430. package/open-sse/config/providers/registry/pioneer/index.ts +41 -0
  431. package/open-sse/config/providers/registry/pollinations/index.ts +51 -0
  432. package/open-sse/config/providers/registry/predibase/index.ts +13 -0
  433. package/open-sse/config/providers/registry/publicai/index.ts +13 -0
  434. package/open-sse/config/providers/registry/puter/index.ts +70 -0
  435. package/open-sse/config/providers/registry/qianfan/index.ts +18 -0
  436. package/open-sse/config/providers/registry/qiniu/index.ts +15 -0
  437. package/open-sse/config/providers/registry/qoder/index.ts +37 -0
  438. package/open-sse/config/providers/registry/qwen/index.ts +25 -0
  439. package/open-sse/config/providers/registry/qwen/web/index.ts +24 -0
  440. package/open-sse/config/providers/registry/reka/index.ts +18 -0
  441. package/open-sse/config/providers/registry/requesty/index.ts +11 -0
  442. package/open-sse/config/providers/registry/sambanova/index.ts +13 -0
  443. package/open-sse/config/providers/registry/scaleway/index.ts +20 -0
  444. package/open-sse/config/providers/registry/sensenova/index.ts +27 -0
  445. package/open-sse/config/providers/registry/siliconflow/index.ts +84 -0
  446. package/open-sse/config/providers/registry/snowflake/index.ts +13 -0
  447. package/open-sse/config/providers/registry/sparkdesk/index.ts +20 -0
  448. package/open-sse/config/providers/registry/stepfun/index.ts +20 -0
  449. package/open-sse/config/providers/registry/sumopod/index.ts +15 -0
  450. package/open-sse/config/providers/registry/suno/index.ts +18 -0
  451. package/open-sse/config/providers/registry/synthetic/index.ts +21 -0
  452. package/open-sse/config/providers/registry/t3-web/index.ts +45 -0
  453. package/open-sse/config/providers/registry/tencent/index.ts +25 -0
  454. package/open-sse/config/providers/registry/theoldllm/index.ts +51 -0
  455. package/open-sse/config/providers/registry/together/index.ts +20 -0
  456. package/open-sse/config/providers/registry/tokenrouter/index.ts +44 -0
  457. package/open-sse/config/providers/registry/trae/index.ts +24 -0
  458. package/open-sse/config/providers/registry/udio/index.ts +12 -0
  459. package/open-sse/config/providers/registry/uncloseai/index.ts +19 -0
  460. package/open-sse/config/providers/registry/upstage/index.ts +13 -0
  461. package/open-sse/config/providers/registry/v0-vercel/index.ts +13 -0
  462. package/open-sse/config/providers/registry/venice/index.ts +13 -0
  463. package/open-sse/config/providers/registry/veoaifree-web/index.ts +15 -0
  464. package/open-sse/config/providers/registry/vercel-ai-gateway/index.ts +13 -0
  465. package/open-sse/config/providers/registry/vertex/index.ts +33 -0
  466. package/open-sse/config/providers/registry/vertex/partner/index.ts +22 -0
  467. package/open-sse/config/providers/registry/volcengine/index.ts +13 -0
  468. package/open-sse/config/providers/registry/wafer/index.ts +19 -0
  469. package/open-sse/config/providers/registry/wandb/index.ts +13 -0
  470. package/open-sse/config/providers/registry/windsurf/index.ts +119 -0
  471. package/open-sse/config/providers/registry/x5lab/index.ts +15 -0
  472. package/open-sse/config/providers/registry/xai/index.ts +18 -0
  473. package/open-sse/config/providers/registry/xiaomi-mimo/index.ts +13 -0
  474. package/open-sse/config/providers/registry/yi/index.ts +12 -0
  475. package/open-sse/config/providers/registry/yuanbao-web/index.ts +37 -0
  476. package/open-sse/config/providers/registry/zai/index.ts +28 -0
  477. package/open-sse/config/providers/registry/zed-hosted/index.ts +35 -0
  478. package/open-sse/config/providers/registry/zenmux/index.ts +87 -0
  479. package/open-sse/config/providers/registry/zenmux-free/index.ts +40 -0
  480. package/open-sse/config/providers/shared.ts +766 -0
  481. package/open-sse/config/registryUtils.ts +134 -0
  482. package/open-sse/config/rerankRegistry.ts +196 -0
  483. package/open-sse/config/runway.ts +39 -0
  484. package/open-sse/config/sap.ts +58 -0
  485. package/open-sse/config/searchRegistry.ts +317 -0
  486. package/open-sse/config/toolCloaking.ts +253 -0
  487. package/open-sse/config/videoRegistry.ts +229 -0
  488. package/open-sse/config/watsonx.ts +43 -0
  489. package/open-sse/executors/adapta-web.ts +564 -0
  490. package/open-sse/executors/antigravity/sseCollect.ts +148 -0
  491. package/open-sse/executors/antigravity.ts +1716 -0
  492. package/open-sse/executors/antigravityUpstreamError.ts +25 -0
  493. package/open-sse/executors/auggie.ts +573 -0
  494. package/open-sse/executors/azure-openai.ts +48 -0
  495. package/open-sse/executors/base/headers.ts +93 -0
  496. package/open-sse/executors/base/reasoningEffort.ts +160 -0
  497. package/open-sse/executors/base.ts +1315 -0
  498. package/open-sse/executors/bedrock.ts +714 -0
  499. package/open-sse/executors/blackbox-web.ts +708 -0
  500. package/open-sse/executors/chatgpt-web/models.ts +133 -0
  501. package/open-sse/executors/chatgpt-web.ts +3107 -0
  502. package/open-sse/executors/chatgptWebErrors.ts +18 -0
  503. package/open-sse/executors/chatgptWebTools.ts +127 -0
  504. package/open-sse/executors/chipotle.ts +432 -0
  505. package/open-sse/executors/claude-web/payload.ts +230 -0
  506. package/open-sse/executors/claude-web-with-auto-refresh.ts +117 -0
  507. package/open-sse/executors/claude-web.ts +833 -0
  508. package/open-sse/executors/claudeIdentity.ts +445 -0
  509. package/open-sse/executors/cliproxyapi.ts +466 -0
  510. package/open-sse/executors/cloudflare-ai.ts +97 -0
  511. package/open-sse/executors/codebuddy-cn.ts +53 -0
  512. package/open-sse/executors/codex/quota.ts +114 -0
  513. package/open-sse/executors/codex/tools.ts +165 -0
  514. package/open-sse/executors/codex.ts +1270 -0
  515. package/open-sse/executors/commandCode.ts +716 -0
  516. package/open-sse/executors/copilot-m365-connection.ts +271 -0
  517. package/open-sse/executors/copilot-m365-frames.ts +279 -0
  518. package/open-sse/executors/copilot-m365-web.ts +341 -0
  519. package/open-sse/executors/copilot-web.ts +722 -0
  520. package/open-sse/executors/cursor/composer.ts +53 -0
  521. package/open-sse/executors/cursor/prompt.ts +75 -0
  522. package/open-sse/executors/cursor.ts +1465 -0
  523. package/open-sse/executors/deepseek-web/stream-format.ts +44 -0
  524. package/open-sse/executors/deepseek-web-with-auto-refresh.ts +184 -0
  525. package/open-sse/executors/deepseek-web.ts +1123 -0
  526. package/open-sse/executors/default/urlNormalizers.ts +64 -0
  527. package/open-sse/executors/default.ts +873 -0
  528. package/open-sse/executors/devin-cli.ts +470 -0
  529. package/open-sse/executors/doubao-web.ts +665 -0
  530. package/open-sse/executors/duckduckgo-web/challenge.ts +151 -0
  531. package/open-sse/executors/duckduckgo-web.ts +782 -0
  532. package/open-sse/executors/firecrawl-fetch.ts +177 -0
  533. package/open-sse/executors/forceResponsesUpstream.ts +60 -0
  534. package/open-sse/executors/gemini-business.ts +446 -0
  535. package/open-sse/executors/gemini-web.ts +413 -0
  536. package/open-sse/executors/github.ts +376 -0
  537. package/open-sse/executors/gitlab.ts +793 -0
  538. package/open-sse/executors/gitlabResponses.ts +191 -0
  539. package/open-sse/executors/glm.ts +520 -0
  540. package/open-sse/executors/grok-cli.ts +253 -0
  541. package/open-sse/executors/grok-web/native-tools.ts +182 -0
  542. package/open-sse/executors/grok-web/text-cleanup.ts +137 -0
  543. package/open-sse/executors/grok-web/tool-bridge.ts +666 -0
  544. package/open-sse/executors/grok-web/types.ts +47 -0
  545. package/open-sse/executors/grok-web.ts +883 -0
  546. package/open-sse/executors/huggingchat/jsonlStream.ts +221 -0
  547. package/open-sse/executors/huggingchat.ts +593 -0
  548. package/open-sse/executors/index.ts +232 -0
  549. package/open-sse/executors/inner-ai.ts +764 -0
  550. package/open-sse/executors/jina-reader-fetch.ts +119 -0
  551. package/open-sse/executors/kie.ts +109 -0
  552. package/open-sse/executors/kimi-web.ts +455 -0
  553. package/open-sse/executors/kimi.ts +133 -0
  554. package/open-sse/executors/kiro/eventstream.ts +192 -0
  555. package/open-sse/executors/kiro.ts +821 -0
  556. package/open-sse/executors/kiroThinking.ts +116 -0
  557. package/open-sse/executors/lmarena.ts +511 -0
  558. package/open-sse/executors/mimocode.ts +560 -0
  559. package/open-sse/executors/muse-spark-web/response-parser.ts +383 -0
  560. package/open-sse/executors/muse-spark-web.ts +928 -0
  561. package/open-sse/executors/ninerouter.ts +212 -0
  562. package/open-sse/executors/nlpcloud.ts +546 -0
  563. package/open-sse/executors/opencode.ts +336 -0
  564. package/open-sse/executors/perplexity-web/protocol.ts +503 -0
  565. package/open-sse/executors/perplexity-web.ts +545 -0
  566. package/open-sse/executors/poe-web.ts +158 -0
  567. package/open-sse/executors/pollinations.ts +119 -0
  568. package/open-sse/executors/puter.ts +59 -0
  569. package/open-sse/executors/qoder.ts +416 -0
  570. package/open-sse/executors/qwen-web.ts +474 -0
  571. package/open-sse/executors/t3-chat-web.ts +582 -0
  572. package/open-sse/executors/tavily-fetch.ts +103 -0
  573. package/open-sse/executors/theoldllm.ts +354 -0
  574. package/open-sse/executors/tinyfish-fetch.ts +131 -0
  575. package/open-sse/executors/trae.ts +481 -0
  576. package/open-sse/executors/v0-vercel-web.ts +164 -0
  577. package/open-sse/executors/venice-web.ts +165 -0
  578. package/open-sse/executors/veoaifree-web.ts +397 -0
  579. package/open-sse/executors/vertex.ts +208 -0
  580. package/open-sse/executors/vertexMedia.ts +341 -0
  581. package/open-sse/executors/windsurf.ts +706 -0
  582. package/open-sse/executors/xai.ts +94 -0
  583. package/open-sse/executors/yuanbao-web.ts +504 -0
  584. package/open-sse/executors/zed-hosted.ts +364 -0
  585. package/open-sse/executors/zenmux-free.ts +283 -0
  586. package/open-sse/handlers/audioSpeech.ts +1060 -0
  587. package/open-sse/handlers/audioTranscription.ts +554 -0
  588. package/open-sse/handlers/audioTranslation.ts +135 -0
  589. package/open-sse/handlers/chatCore/attemptLogging.ts +210 -0
  590. package/open-sse/handlers/chatCore/backgroundRedirect.ts +41 -0
  591. package/open-sse/handlers/chatCore/cacheUsageMeta.ts +65 -0
  592. package/open-sse/handlers/chatCore/cavemanOutputAnalytics.ts +47 -0
  593. package/open-sse/handlers/chatCore/claudeClassifierCompat.ts +99 -0
  594. package/open-sse/handlers/chatCore/claudeEffortVariant.ts +62 -0
  595. package/open-sse/handlers/chatCore/claudeMessageTypes.ts +15 -0
  596. package/open-sse/handlers/chatCore/claudeSystemRole.ts +48 -0
  597. package/open-sse/handlers/chatCore/claudeToolDefaults.ts +27 -0
  598. package/open-sse/handlers/chatCore/claudeUpstreamMessages.ts +143 -0
  599. package/open-sse/handlers/chatCore/clientUsageBuffer.ts +54 -0
  600. package/open-sse/handlers/chatCore/clineResponseEnvelope.ts +25 -0
  601. package/open-sse/handlers/chatCore/codexFailover.ts +41 -0
  602. package/open-sse/handlers/chatCore/codexQuota.ts +85 -0
  603. package/open-sse/handlers/chatCore/comboContextCache.ts +63 -0
  604. package/open-sse/handlers/chatCore/compressionAnalyticsWrite.ts +149 -0
  605. package/open-sse/handlers/chatCore/compressionCacheStats.ts +53 -0
  606. package/open-sse/handlers/chatCore/compressionComboPredicates.ts +41 -0
  607. package/open-sse/handlers/chatCore/compressionSettings.ts +35 -0
  608. package/open-sse/handlers/chatCore/compressionUsageReceipt.ts +27 -0
  609. package/open-sse/handlers/chatCore/contextEditingTelemetry.ts +40 -0
  610. package/open-sse/handlers/chatCore/cooldownClassification.ts +26 -0
  611. package/open-sse/handlers/chatCore/executionCredentials.ts +72 -0
  612. package/open-sse/handlers/chatCore/executorClientHeaders.ts +36 -0
  613. package/open-sse/handlers/chatCore/executorHelpers.ts +151 -0
  614. package/open-sse/handlers/chatCore/executorProxy.ts +117 -0
  615. package/open-sse/handlers/chatCore/failureUsage.ts +41 -0
  616. package/open-sse/handlers/chatCore/gamificationEvent.ts +28 -0
  617. package/open-sse/handlers/chatCore/headers.ts +65 -0
  618. package/open-sse/handlers/chatCore/idempotency.ts +65 -0
  619. package/open-sse/handlers/chatCore/jsonBodyToSse.ts +161 -0
  620. package/open-sse/handlers/chatCore/keyHealth.ts +113 -0
  621. package/open-sse/handlers/chatCore/logTruncation.ts +93 -0
  622. package/open-sse/handlers/chatCore/memoryExtraction.ts +131 -0
  623. package/open-sse/handlers/chatCore/memorySkillsInjection.ts +165 -0
  624. package/open-sse/handlers/chatCore/nonStreamingJsonResponse.ts +16 -0
  625. package/open-sse/handlers/chatCore/nonStreamingResponseBody.ts +155 -0
  626. package/open-sse/handlers/chatCore/nonStreamingResponseHeaders.ts +46 -0
  627. package/open-sse/handlers/chatCore/nonStreamingResponseParse.ts +135 -0
  628. package/open-sse/handlers/chatCore/nonStreamingSse.ts +171 -0
  629. package/open-sse/handlers/chatCore/nonStreamingUsageStats.ts +90 -0
  630. package/open-sse/handlers/chatCore/outputStyleTelemetry.ts +53 -0
  631. package/open-sse/handlers/chatCore/passthroughHelpers.ts +83 -0
  632. package/open-sse/handlers/chatCore/passthroughToolNames.ts +65 -0
  633. package/open-sse/handlers/chatCore/pluginOnRequest.ts +65 -0
  634. package/open-sse/handlers/chatCore/pluginOnResponse.ts +34 -0
  635. package/open-sse/handlers/chatCore/postCallGuardrailContext.ts +47 -0
  636. package/open-sse/handlers/chatCore/quotaShareConsumption.ts +41 -0
  637. package/open-sse/handlers/chatCore/requestFormat.ts +111 -0
  638. package/open-sse/handlers/chatCore/requestSetup.ts +51 -0
  639. package/open-sse/handlers/chatCore/responseHeaders.ts +138 -0
  640. package/open-sse/handlers/chatCore/sanitization.ts +63 -0
  641. package/open-sse/handlers/chatCore/semanticCache.ts +98 -0
  642. package/open-sse/handlers/chatCore/semanticCacheStore.ts +73 -0
  643. package/open-sse/handlers/chatCore/serviceTier.ts +70 -0
  644. package/open-sse/handlers/chatCore/skillsFormat.ts +33 -0
  645. package/open-sse/handlers/chatCore/stageTrace.ts +30 -0
  646. package/open-sse/handlers/chatCore/streamErrorResult.ts +58 -0
  647. package/open-sse/handlers/chatCore/streamFinalize.ts +48 -0
  648. package/open-sse/handlers/chatCore/streamingCost.ts +37 -0
  649. package/open-sse/handlers/chatCore/streamingPipeline.ts +99 -0
  650. package/open-sse/handlers/chatCore/streamingQuotaShare.ts +54 -0
  651. package/open-sse/handlers/chatCore/streamingResponseHeaders.ts +39 -0
  652. package/open-sse/handlers/chatCore/streamingSemanticCacheStore.ts +95 -0
  653. package/open-sse/handlers/chatCore/streamingUsageStats.ts +79 -0
  654. package/open-sse/handlers/chatCore/targetFormat.ts +34 -0
  655. package/open-sse/handlers/chatCore/telemetryHelpers.ts +78 -0
  656. package/open-sse/handlers/chatCore/upstreamBody.ts +168 -0
  657. package/open-sse/handlers/chatCore/upstreamExecuteHeaders.ts +71 -0
  658. package/open-sse/handlers/chatCore/upstreamTimeouts.ts +158 -0
  659. package/open-sse/handlers/chatCore.ts +4452 -0
  660. package/open-sse/handlers/embeddings.ts +378 -0
  661. package/open-sse/handlers/imageGeneration/providers/chatgptWeb.ts +187 -0
  662. package/open-sse/handlers/imageGeneration/providers/comfyUI.ts +116 -0
  663. package/open-sse/handlers/imageGeneration/providers/haiper.ts +120 -0
  664. package/open-sse/handlers/imageGeneration/providers/huggingface.ts +90 -0
  665. package/open-sse/handlers/imageGeneration/providers/hyperbolic.ts +100 -0
  666. package/open-sse/handlers/imageGeneration/providers/ideogram.ts +96 -0
  667. package/open-sse/handlers/imageGeneration/providers/imagen3.ts +136 -0
  668. package/open-sse/handlers/imageGeneration/providers/leonardo.ts +140 -0
  669. package/open-sse/handlers/imageGeneration/providers/nvidiaNim.ts +286 -0
  670. package/open-sse/handlers/imageGeneration/providers/sdWebUI.ts +94 -0
  671. package/open-sse/handlers/imageGeneration.ts +2880 -0
  672. package/open-sse/handlers/moderations.ts +82 -0
  673. package/open-sse/handlers/musicGeneration.ts +640 -0
  674. package/open-sse/handlers/ocr.ts +79 -0
  675. package/open-sse/handlers/rerank.ts +210 -0
  676. package/open-sse/handlers/responseSanitizer/reasoning.ts +149 -0
  677. package/open-sse/handlers/responseSanitizer.ts +1086 -0
  678. package/open-sse/handlers/responseTranslator.ts +640 -0
  679. package/open-sse/handlers/responsesHandler.ts +92 -0
  680. package/open-sse/handlers/search.ts +1545 -0
  681. package/open-sse/handlers/sseParser.ts +825 -0
  682. package/open-sse/handlers/usageExtractor.ts +93 -0
  683. package/open-sse/handlers/videoGeneration/googleFlow.ts +219 -0
  684. package/open-sse/handlers/videoGeneration/googleFlowHandler.ts +145 -0
  685. package/open-sse/handlers/videoGeneration.ts +1264 -0
  686. package/open-sse/handlers/webFetch.ts +130 -0
  687. package/open-sse/index.ts +170 -0
  688. package/open-sse/lib/deepseek-pow-solver.cjs +3 -0
  689. package/open-sse/lib/deepseek-pow.ts +189 -0
  690. package/open-sse/lib/sha3_wasm_bg.wasm +0 -0
  691. package/open-sse/mcp-server/README.md +611 -0
  692. package/open-sse/mcp-server/audit.ts +478 -0
  693. package/open-sse/mcp-server/catalog.ts +290 -0
  694. package/open-sse/mcp-server/descriptionCompressor.ts +243 -0
  695. package/open-sse/mcp-server/httpAuthContext.ts +42 -0
  696. package/open-sse/mcp-server/httpTransport.ts +306 -0
  697. package/open-sse/mcp-server/index.ts +19 -0
  698. package/open-sse/mcp-server/mcpCallerIdentity.ts +53 -0
  699. package/open-sse/mcp-server/runtimeHeartbeat.ts +162 -0
  700. package/open-sse/mcp-server/schemas/a2a.ts +203 -0
  701. package/open-sse/mcp-server/schemas/audit.ts +121 -0
  702. package/open-sse/mcp-server/schemas/index.ts +116 -0
  703. package/open-sse/mcp-server/schemas/pickFastestModel.ts +110 -0
  704. package/open-sse/mcp-server/schemas/toolDefinition.ts +31 -0
  705. package/open-sse/mcp-server/schemas/toolSearch.ts +37 -0
  706. package/open-sse/mcp-server/schemas/tools.ts +1481 -0
  707. package/open-sse/mcp-server/scopeEnforcement.ts +135 -0
  708. package/open-sse/mcp-server/server.ts +1370 -0
  709. package/open-sse/mcp-server/toolCardinality.ts +254 -0
  710. package/open-sse/mcp-server/toolSearch/catalog.ts +98 -0
  711. package/open-sse/mcp-server/toolSearch/handler.ts +18 -0
  712. package/open-sse/mcp-server/toolSearch/index.ts +5 -0
  713. package/open-sse/mcp-server/toolSearch/register.ts +36 -0
  714. package/open-sse/mcp-server/toolSearch/search.ts +96 -0
  715. package/open-sse/mcp-server/toolSearch/signature.ts +92 -0
  716. package/open-sse/mcp-server/tools/advancedTools.ts +1119 -0
  717. package/open-sse/mcp-server/tools/agentSkillTools.ts +83 -0
  718. package/open-sse/mcp-server/tools/compressionTools.ts +451 -0
  719. package/open-sse/mcp-server/tools/gamificationTools.ts +148 -0
  720. package/open-sse/mcp-server/tools/githubSkillTools.ts +141 -0
  721. package/open-sse/mcp-server/tools/memoryTools.ts +137 -0
  722. package/open-sse/mcp-server/tools/notionTools.ts +106 -0
  723. package/open-sse/mcp-server/tools/obsidianTools.ts +327 -0
  724. package/open-sse/mcp-server/tools/pickFastestModel.ts +293 -0
  725. package/open-sse/mcp-server/tools/pluginTools.ts +216 -0
  726. package/open-sse/mcp-server/tools/poolTools.ts +205 -0
  727. package/open-sse/mcp-server/tools/skillTools.ts +119 -0
  728. package/open-sse/package.json +17 -0
  729. package/open-sse/services/AGENTS.md +78 -0
  730. package/open-sse/services/accountFallback.ts +1863 -0
  731. package/open-sse/services/accountSelector.ts +80 -0
  732. package/open-sse/services/accountSemaphore.ts +367 -0
  733. package/open-sse/services/antigravity429Engine.ts +178 -0
  734. package/open-sse/services/antigravityClientProfile.ts +167 -0
  735. package/open-sse/services/antigravityCredits.ts +68 -0
  736. package/open-sse/services/antigravityHeaderScrub.ts +75 -0
  737. package/open-sse/services/antigravityHeaders.ts +121 -0
  738. package/open-sse/services/antigravityIdentity.ts +127 -0
  739. package/open-sse/services/antigravityObfuscation.ts +64 -0
  740. package/open-sse/services/antigravityProjectBootstrap.ts +145 -0
  741. package/open-sse/services/antigravityQuotaFamily.ts +56 -0
  742. package/open-sse/services/antigravityVersion.ts +163 -0
  743. package/open-sse/services/apiKeyRotator.ts +385 -0
  744. package/open-sse/services/autoCombo/autoPrefix.ts +61 -0
  745. package/open-sse/services/autoCombo/builtinCatalog.ts +126 -0
  746. package/open-sse/services/autoCombo/complexityRouter.ts +111 -0
  747. package/open-sse/services/autoCombo/engine.ts +314 -0
  748. package/open-sse/services/autoCombo/index.ts +18 -0
  749. package/open-sse/services/autoCombo/modePacks.ts +105 -0
  750. package/open-sse/services/autoCombo/modelFamily.ts +95 -0
  751. package/open-sse/services/autoCombo/paidModelFilter.ts +44 -0
  752. package/open-sse/services/autoCombo/persistence.ts +124 -0
  753. package/open-sse/services/autoCombo/pipelineRouter.ts +418 -0
  754. package/open-sse/services/autoCombo/providerDiversity.ts +170 -0
  755. package/open-sse/services/autoCombo/providerRegistryAccessor.ts +9 -0
  756. package/open-sse/services/autoCombo/requestControls.ts +80 -0
  757. package/open-sse/services/autoCombo/routerStrategy.ts +375 -0
  758. package/open-sse/services/autoCombo/scoring.ts +242 -0
  759. package/open-sse/services/autoCombo/selfHealing.ts +167 -0
  760. package/open-sse/services/autoCombo/speedRanking.ts +327 -0
  761. package/open-sse/services/autoCombo/suffixComposition.ts +147 -0
  762. package/open-sse/services/autoCombo/taskFitness.ts +407 -0
  763. package/open-sse/services/autoCombo/virtualFactory.ts +446 -0
  764. package/open-sse/services/autoRefreshDaemon.ts +206 -0
  765. package/open-sse/services/backgroundTaskDetector.ts +263 -0
  766. package/open-sse/services/bailianQuotaFetcher.ts +333 -0
  767. package/open-sse/services/batchProcessor.ts +914 -0
  768. package/open-sse/services/bedrock.ts +160 -0
  769. package/open-sse/services/browserBackedChat.ts +849 -0
  770. package/open-sse/services/browserPool.ts +501 -0
  771. package/open-sse/services/ccBridgeTransforms.ts +581 -0
  772. package/open-sse/services/ccWireImageBuiltins.ts +26 -0
  773. package/open-sse/services/chatgptImageCache.ts +143 -0
  774. package/open-sse/services/chatgptTlsClient.ts +628 -0
  775. package/open-sse/services/claudeAdaptiveThinking.ts +52 -0
  776. package/open-sse/services/claudeCodeCCH.ts +49 -0
  777. package/open-sse/services/claudeCodeCompatible.ts +1198 -0
  778. package/open-sse/services/claudeCodeCompatibleBeta.ts +23 -0
  779. package/open-sse/services/claudeCodeCompatibleThinkingDisplay.ts +34 -0
  780. package/open-sse/services/claudeCodeConstraints.ts +144 -0
  781. package/open-sse/services/claudeCodeExtraRemap.ts +18 -0
  782. package/open-sse/services/claudeCodeFingerprint.ts +46 -0
  783. package/open-sse/services/claudeCodeObfuscation.ts +116 -0
  784. package/open-sse/services/claudeCodeToolRemapper.ts +339 -0
  785. package/open-sse/services/claudeHaikuConstraints.ts +88 -0
  786. package/open-sse/services/claudeTlsClient.ts +590 -0
  787. package/open-sse/services/claudeTurnstileSolver.ts +206 -0
  788. package/open-sse/services/claudeUsageCooldown.ts +51 -0
  789. package/open-sse/services/claudeWebAutoRefresh.ts +224 -0
  790. package/open-sse/services/clinepassModels.ts +76 -0
  791. package/open-sse/services/cloudCodeHeaders.ts +41 -0
  792. package/open-sse/services/cloudCodeThinking.ts +71 -0
  793. package/open-sse/services/codeAssistSubscription.ts +83 -0
  794. package/open-sse/services/codexQuotaFetcher.ts +523 -0
  795. package/open-sse/services/codexUsageQuotas.ts +270 -0
  796. package/open-sse/services/codexVerbosity.ts +59 -0
  797. package/open-sse/services/combo/applyStrategyOrdering.ts +226 -0
  798. package/open-sse/services/combo/autoConfig.ts +62 -0
  799. package/open-sse/services/combo/autoStrategy.ts +475 -0
  800. package/open-sse/services/combo/comboCompatFallback.ts +82 -0
  801. package/open-sse/services/combo/comboCooldownRetry.ts +237 -0
  802. package/open-sse/services/combo/comboData.ts +24 -0
  803. package/open-sse/services/combo/comboPredicates.ts +211 -0
  804. package/open-sse/services/combo/comboSetup.ts +135 -0
  805. package/open-sse/services/combo/comboStructure.ts +766 -0
  806. package/open-sse/services/combo/concurrencyCaps.ts +76 -0
  807. package/open-sse/services/combo/context.ts +46 -0
  808. package/open-sse/services/combo/fingerprintExpansion.ts +105 -0
  809. package/open-sse/services/combo/headroomRanking.ts +91 -0
  810. package/open-sse/services/combo/providerWildcard.ts +253 -0
  811. package/open-sse/services/combo/quotaExhaustionCutoff.ts +140 -0
  812. package/open-sse/services/combo/quotaScoring.ts +311 -0
  813. package/open-sse/services/combo/quotaShareConcurrency.ts +74 -0
  814. package/open-sse/services/combo/quotaShareInflight.ts +133 -0
  815. package/open-sse/services/combo/quotaShareStrategy.ts +349 -0
  816. package/open-sse/services/combo/quotaStrategies.ts +647 -0
  817. package/open-sse/services/combo/resolveAutoStrategy.ts +334 -0
  818. package/open-sse/services/combo/responseValidation.ts +206 -0
  819. package/open-sse/services/combo/rrState.ts +98 -0
  820. package/open-sse/services/combo/runtimeUnits.ts +269 -0
  821. package/open-sse/services/combo/sessionStickiness.ts +301 -0
  822. package/open-sse/services/combo/shadowRouting.ts +179 -0
  823. package/open-sse/services/combo/targetExhaustion.ts +160 -0
  824. package/open-sse/services/combo/targetSorters.ts +174 -0
  825. package/open-sse/services/combo/targetTimeoutRunner.ts +91 -0
  826. package/open-sse/services/combo/types.ts +175 -0
  827. package/open-sse/services/combo/validateQuality.ts +445 -0
  828. package/open-sse/services/combo.ts +3085 -0
  829. package/open-sse/services/comboAgentMiddleware.ts +214 -0
  830. package/open-sse/services/comboConfig.ts +248 -0
  831. package/open-sse/services/comboManifestMetrics.ts +13 -0
  832. package/open-sse/services/comboMetrics.ts +480 -0
  833. package/open-sse/services/compression/adaptiveCompression/computeTarget.ts +31 -0
  834. package/open-sse/services/compression/adaptiveCompression/ladder.ts +59 -0
  835. package/open-sse/services/compression/adaptiveCompression/resolveAdaptivePlan.ts +104 -0
  836. package/open-sse/services/compression/adaptiveCompression/types.ts +61 -0
  837. package/open-sse/services/compression/aggressive.ts +204 -0
  838. package/open-sse/services/compression/bodyAdapter.ts +354 -0
  839. package/open-sse/services/compression/cacheAwareConfig.ts +60 -0
  840. package/open-sse/services/compression/cachingAware.ts +130 -0
  841. package/open-sse/services/compression/caveman.ts +602 -0
  842. package/open-sse/services/compression/cavemanRules.ts +432 -0
  843. package/open-sse/services/compression/deriveDefaultPlan.ts +59 -0
  844. package/open-sse/services/compression/diffHelper.ts +219 -0
  845. package/open-sse/services/compression/engineBreakdown.ts +29 -0
  846. package/open-sse/services/compression/engineCatalog.ts +91 -0
  847. package/open-sse/services/compression/engines/cavemanAdapter.ts +454 -0
  848. package/open-sse/services/compression/engines/ccr/ccrQuery.ts +110 -0
  849. package/open-sse/services/compression/engines/ccr/index.ts +460 -0
  850. package/open-sse/services/compression/engines/headroom/encoderComparison.ts +72 -0
  851. package/open-sse/services/compression/engines/headroom/gcf/decode_generic.ts +711 -0
  852. package/open-sse/services/compression/engines/headroom/gcf/generic.ts +332 -0
  853. package/open-sse/services/compression/engines/headroom/gcf/index.ts +9 -0
  854. package/open-sse/services/compression/engines/headroom/gcf/scalar.ts +336 -0
  855. package/open-sse/services/compression/engines/headroom/index.ts +286 -0
  856. package/open-sse/services/compression/engines/headroom/smartcrusher.ts +255 -0
  857. package/open-sse/services/compression/engines/headroom/tabular.ts +263 -0
  858. package/open-sse/services/compression/engines/headroom/toon.ts +43 -0
  859. package/open-sse/services/compression/engines/index.ts +42 -0
  860. package/open-sse/services/compression/engines/ionizer/index.ts +124 -0
  861. package/open-sse/services/compression/engines/ionizer/sample.ts +200 -0
  862. package/open-sse/services/compression/engines/llm/index.ts +346 -0
  863. package/open-sse/services/compression/engines/llmlingua/constants.ts +55 -0
  864. package/open-sse/services/compression/engines/llmlingua/index.ts +474 -0
  865. package/open-sse/services/compression/engines/llmlingua/modelStore.ts +67 -0
  866. package/open-sse/services/compression/engines/llmlingua/onnxWorker.ts +117 -0
  867. package/open-sse/services/compression/engines/llmlingua/ultraEntry.ts +109 -0
  868. package/open-sse/services/compression/engines/llmlingua/worker.ts +373 -0
  869. package/open-sse/services/compression/engines/mcpAccessibility/collapseRepeated.ts +121 -0
  870. package/open-sse/services/compression/engines/mcpAccessibility/constants.ts +63 -0
  871. package/open-sse/services/compression/engines/mcpAccessibility/index.ts +52 -0
  872. package/open-sse/services/compression/engines/readLifecycle/index.ts +299 -0
  873. package/open-sse/services/compression/engines/registry.ts +87 -0
  874. package/open-sse/services/compression/engines/relevance/configSchema.ts +63 -0
  875. package/open-sse/services/compression/engines/relevance/index.ts +185 -0
  876. package/open-sse/services/compression/engines/relevance/scorer.ts +85 -0
  877. package/open-sse/services/compression/engines/rtk/codeStripper.ts +145 -0
  878. package/open-sse/services/compression/engines/rtk/commandDetector.ts +482 -0
  879. package/open-sse/services/compression/engines/rtk/configSchema.ts +117 -0
  880. package/open-sse/services/compression/engines/rtk/deduplicator.ts +37 -0
  881. package/open-sse/services/compression/engines/rtk/discover.ts +150 -0
  882. package/open-sse/services/compression/engines/rtk/filterLoader.ts +245 -0
  883. package/open-sse/services/compression/engines/rtk/filterSchema.ts +207 -0
  884. package/open-sse/services/compression/engines/rtk/filters/aws.json +34 -0
  885. package/open-sse/services/compression/engines/rtk/filters/biome.json +35 -0
  886. package/open-sse/services/compression/engines/rtk/filters/build-eslint.json +37 -0
  887. package/open-sse/services/compression/engines/rtk/filters/build-typescript.json +33 -0
  888. package/open-sse/services/compression/engines/rtk/filters/build-vite.json +41 -0
  889. package/open-sse/services/compression/engines/rtk/filters/build-webpack.json +34 -0
  890. package/open-sse/services/compression/engines/rtk/filters/bundle-install.json +35 -0
  891. package/open-sse/services/compression/engines/rtk/filters/composer.json +81 -0
  892. package/open-sse/services/compression/engines/rtk/filters/curl.json +34 -0
  893. package/open-sse/services/compression/engines/rtk/filters/df.json +34 -0
  894. package/open-sse/services/compression/engines/rtk/filters/docker-build.json +78 -0
  895. package/open-sse/services/compression/engines/rtk/filters/docker-logs.json +42 -0
  896. package/open-sse/services/compression/engines/rtk/filters/docker-ps.json +33 -0
  897. package/open-sse/services/compression/engines/rtk/filters/dotnet.json +47 -0
  898. package/open-sse/services/compression/engines/rtk/filters/du.json +33 -0
  899. package/open-sse/services/compression/engines/rtk/filters/error-stacktrace.json +41 -0
  900. package/open-sse/services/compression/engines/rtk/filters/gcloud.json +34 -0
  901. package/open-sse/services/compression/engines/rtk/filters/generic-output.json +32 -0
  902. package/open-sse/services/compression/engines/rtk/filters/gh.json +98 -0
  903. package/open-sse/services/compression/engines/rtk/filters/git-branch.json +45 -0
  904. package/open-sse/services/compression/engines/rtk/filters/git-diff.json +33 -0
  905. package/open-sse/services/compression/engines/rtk/filters/git-log.json +33 -0
  906. package/open-sse/services/compression/engines/rtk/filters/git-status.json +40 -0
  907. package/open-sse/services/compression/engines/rtk/filters/golangci-lint.json +34 -0
  908. package/open-sse/services/compression/engines/rtk/filters/gradle.json +47 -0
  909. package/open-sse/services/compression/engines/rtk/filters/json-output.json +40 -0
  910. package/open-sse/services/compression/engines/rtk/filters/kubectl.json +99 -0
  911. package/open-sse/services/compression/engines/rtk/filters/make.json +38 -0
  912. package/open-sse/services/compression/engines/rtk/filters/mypy.json +34 -0
  913. package/open-sse/services/compression/engines/rtk/filters/npm-audit.json +43 -0
  914. package/open-sse/services/compression/engines/rtk/filters/npm-install.json +41 -0
  915. package/open-sse/services/compression/engines/rtk/filters/nx.json +34 -0
  916. package/open-sse/services/compression/engines/rtk/filters/pip.json +41 -0
  917. package/open-sse/services/compression/engines/rtk/filters/playwright.json +42 -0
  918. package/open-sse/services/compression/engines/rtk/filters/poetry-install.json +35 -0
  919. package/open-sse/services/compression/engines/rtk/filters/prettier.json +40 -0
  920. package/open-sse/services/compression/engines/rtk/filters/ps.json +34 -0
  921. package/open-sse/services/compression/engines/rtk/filters/rsync.json +33 -0
  922. package/open-sse/services/compression/engines/rtk/filters/rubocop.json +34 -0
  923. package/open-sse/services/compression/engines/rtk/filters/ruff.json +40 -0
  924. package/open-sse/services/compression/engines/rtk/filters/shell-find.json +33 -0
  925. package/open-sse/services/compression/engines/rtk/filters/shell-grep.json +37 -0
  926. package/open-sse/services/compression/engines/rtk/filters/shell-ls.json +33 -0
  927. package/open-sse/services/compression/engines/rtk/filters/ssh.json +43 -0
  928. package/open-sse/services/compression/engines/rtk/filters/systemctl-status.json +43 -0
  929. package/open-sse/services/compression/engines/rtk/filters/terraform-plan.json +34 -0
  930. package/open-sse/services/compression/engines/rtk/filters/test-cargo.json +42 -0
  931. package/open-sse/services/compression/engines/rtk/filters/test-go.json +41 -0
  932. package/open-sse/services/compression/engines/rtk/filters/test-jest.json +43 -0
  933. package/open-sse/services/compression/engines/rtk/filters/test-pytest.json +41 -0
  934. package/open-sse/services/compression/engines/rtk/filters/test-vitest.json +43 -0
  935. package/open-sse/services/compression/engines/rtk/filters/tofu-plan.json +34 -0
  936. package/open-sse/services/compression/engines/rtk/filters/turbo.json +34 -0
  937. package/open-sse/services/compression/engines/rtk/filters/uv-sync.json +35 -0
  938. package/open-sse/services/compression/engines/rtk/filters/wget.json +34 -0
  939. package/open-sse/services/compression/engines/rtk/grouper.ts +99 -0
  940. package/open-sse/services/compression/engines/rtk/index.ts +706 -0
  941. package/open-sse/services/compression/engines/rtk/learn.ts +290 -0
  942. package/open-sse/services/compression/engines/rtk/lineFilter.ts +178 -0
  943. package/open-sse/services/compression/engines/rtk/rawOutput.ts +208 -0
  944. package/open-sse/services/compression/engines/rtk/renderers/gitDiff.ts +39 -0
  945. package/open-sse/services/compression/engines/rtk/renderers/index.ts +50 -0
  946. package/open-sse/services/compression/engines/rtk/renderers/structuredTable.ts +96 -0
  947. package/open-sse/services/compression/engines/rtk/renderers/terraformPlan.ts +40 -0
  948. package/open-sse/services/compression/engines/rtk/renderers/testGreen.ts +70 -0
  949. package/open-sse/services/compression/engines/rtk/renderers/types.ts +13 -0
  950. package/open-sse/services/compression/engines/rtk/smartTruncate.ts +67 -0
  951. package/open-sse/services/compression/engines/rtk/splitCompositeCommand.ts +111 -0
  952. package/open-sse/services/compression/engines/rtk/verify.ts +107 -0
  953. package/open-sse/services/compression/engines/session-dedup/fuzzy.ts +153 -0
  954. package/open-sse/services/compression/engines/session-dedup/index.ts +435 -0
  955. package/open-sse/services/compression/engines/types.ts +77 -0
  956. package/open-sse/services/compression/entrypointWrap.ts +43 -0
  957. package/open-sse/services/compression/eval/aggregate.ts +62 -0
  958. package/open-sse/services/compression/eval/corpus.ts +45 -0
  959. package/open-sse/services/compression/eval/costMeter.ts +31 -0
  960. package/open-sse/services/compression/eval/executorModelClient.ts +44 -0
  961. package/open-sse/services/compression/eval/fidelityCheck.ts +61 -0
  962. package/open-sse/services/compression/eval/grader.ts +27 -0
  963. package/open-sse/services/compression/eval/judge.ts +68 -0
  964. package/open-sse/services/compression/eval/report.ts +44 -0
  965. package/open-sse/services/compression/eval/runner.ts +135 -0
  966. package/open-sse/services/compression/eval/savings.ts +30 -0
  967. package/open-sse/services/compression/eval/seedCorpus.ts +60 -0
  968. package/open-sse/services/compression/eval/types.ts +65 -0
  969. package/open-sse/services/compression/fidelityGate.ts +124 -0
  970. package/open-sse/services/compression/fidelityGateStep.ts +44 -0
  971. package/open-sse/services/compression/hardBudget.ts +196 -0
  972. package/open-sse/services/compression/harness/benchmark.ts +318 -0
  973. package/open-sse/services/compression/harness/budgetGate.ts +62 -0
  974. package/open-sse/services/compression/harness/index.ts +52 -0
  975. package/open-sse/services/compression/harness/measure.ts +98 -0
  976. package/open-sse/services/compression/harness/replay.ts +72 -0
  977. package/open-sse/services/compression/harness/runner.ts +58 -0
  978. package/open-sse/services/compression/index.ts +165 -0
  979. package/open-sse/services/compression/languageDetector.ts +51 -0
  980. package/open-sse/services/compression/lite.ts +241 -0
  981. package/open-sse/services/compression/messageContent.ts +89 -0
  982. package/open-sse/services/compression/outputMode.ts +175 -0
  983. package/open-sse/services/compression/outputStyles/apply.ts +135 -0
  984. package/open-sse/services/compression/outputStyles/backCompat.ts +29 -0
  985. package/open-sse/services/compression/outputStyles/catalog.ts +76 -0
  986. package/open-sse/services/compression/outputStyles/telemetry.ts +50 -0
  987. package/open-sse/services/compression/pipelineEngineBreaker.ts +139 -0
  988. package/open-sse/services/compression/pipelineGuards.ts +45 -0
  989. package/open-sse/services/compression/planResolution.ts +128 -0
  990. package/open-sse/services/compression/prefixFreeze.ts +124 -0
  991. package/open-sse/services/compression/preservation.ts +0 -0
  992. package/open-sse/services/compression/preserveSystemPromptMode.ts +72 -0
  993. package/open-sse/services/compression/progressiveAging.ts +145 -0
  994. package/open-sse/services/compression/quantumLock/index.ts +17 -0
  995. package/open-sse/services/compression/quantumLock/quantumLock.ts +58 -0
  996. package/open-sse/services/compression/quantumLock/quantumLockStep.ts +72 -0
  997. package/open-sse/services/compression/quantumLock/quantumPatterns.ts +80 -0
  998. package/open-sse/services/compression/quantumLock/strategyWrap.ts +72 -0
  999. package/open-sse/services/compression/resolveCompressionPlan.ts +28 -0
  1000. package/open-sse/services/compression/resultMemo.ts +83 -0
  1001. package/open-sse/services/compression/riskGate/index.ts +3 -0
  1002. package/open-sse/services/compression/riskGate/riskGate.ts +136 -0
  1003. package/open-sse/services/compression/riskGate/riskGateStep.ts +115 -0
  1004. package/open-sse/services/compression/riskGate/riskPatterns.ts +61 -0
  1005. package/open-sse/services/compression/riskGate/strategyWrap.ts +44 -0
  1006. package/open-sse/services/compression/ruleLoader.ts +273 -0
  1007. package/open-sse/services/compression/rules/_schema.json +31 -0
  1008. package/open-sse/services/compression/rules/de/context.json +38 -0
  1009. package/open-sse/services/compression/rules/de/dedup.json +38 -0
  1010. package/open-sse/services/compression/rules/de/filler.json +70 -0
  1011. package/open-sse/services/compression/rules/de/structural.json +30 -0
  1012. package/open-sse/services/compression/rules/de/ultra.json +107 -0
  1013. package/open-sse/services/compression/rules/en/context.json +88 -0
  1014. package/open-sse/services/compression/rules/en/dedup.json +38 -0
  1015. package/open-sse/services/compression/rules/en/filler.json +129 -0
  1016. package/open-sse/services/compression/rules/en/structural.json +102 -0
  1017. package/open-sse/services/compression/rules/en/ultra.json +107 -0
  1018. package/open-sse/services/compression/rules/es/context.json +87 -0
  1019. package/open-sse/services/compression/rules/es/dedup.json +38 -0
  1020. package/open-sse/services/compression/rules/es/filler.json +110 -0
  1021. package/open-sse/services/compression/rules/es/structural.json +105 -0
  1022. package/open-sse/services/compression/rules/es/ultra.json +107 -0
  1023. package/open-sse/services/compression/rules/fr/context.json +38 -0
  1024. package/open-sse/services/compression/rules/fr/dedup.json +38 -0
  1025. package/open-sse/services/compression/rules/fr/filler.json +70 -0
  1026. package/open-sse/services/compression/rules/fr/structural.json +30 -0
  1027. package/open-sse/services/compression/rules/fr/ultra.json +107 -0
  1028. package/open-sse/services/compression/rules/id/context.json +113 -0
  1029. package/open-sse/services/compression/rules/id/dedup.json +38 -0
  1030. package/open-sse/services/compression/rules/id/filler.json +138 -0
  1031. package/open-sse/services/compression/rules/id/structural.json +111 -0
  1032. package/open-sse/services/compression/rules/id/ultra.json +252 -0
  1033. package/open-sse/services/compression/rules/ja/context.json +38 -0
  1034. package/open-sse/services/compression/rules/ja/dedup.json +38 -0
  1035. package/open-sse/services/compression/rules/ja/filler.json +70 -0
  1036. package/open-sse/services/compression/rules/ja/structural.json +30 -0
  1037. package/open-sse/services/compression/rules/ja/ultra.json +86 -0
  1038. package/open-sse/services/compression/rules/pt-BR/context.json +69 -0
  1039. package/open-sse/services/compression/rules/pt-BR/dedup.json +51 -0
  1040. package/open-sse/services/compression/rules/pt-BR/filler.json +151 -0
  1041. package/open-sse/services/compression/rules/pt-BR/structural.json +78 -0
  1042. package/open-sse/services/compression/rules/pt-BR/ultra.json +192 -0
  1043. package/open-sse/services/compression/rules/zh/dedup.json +38 -0
  1044. package/open-sse/services/compression/rules/zh/filler.json +54 -0
  1045. package/open-sse/services/compression/rules/zh/ultra.json +55 -0
  1046. package/open-sse/services/compression/stackedStepCore.ts +87 -0
  1047. package/open-sse/services/compression/stats.ts +59 -0
  1048. package/open-sse/services/compression/strategySelector.ts +1007 -0
  1049. package/open-sse/services/compression/summarizer.ts +244 -0
  1050. package/open-sse/services/compression/toolResultCompressor.ts +283 -0
  1051. package/open-sse/services/compression/types.ts +479 -0
  1052. package/open-sse/services/compression/ultra.ts +321 -0
  1053. package/open-sse/services/compression/ultraHeuristic.ts +157 -0
  1054. package/open-sse/services/compression/validation.ts +432 -0
  1055. package/open-sse/services/contextHandoff.ts +770 -0
  1056. package/open-sse/services/contextManager.ts +617 -0
  1057. package/open-sse/services/credentialGate.ts +84 -0
  1058. package/open-sse/services/crofUsageFetcher.ts +182 -0
  1059. package/open-sse/services/cursorSessionManager.ts +208 -0
  1060. package/open-sse/services/deepseekQuotaFetcher.ts +244 -0
  1061. package/open-sse/services/deviceTracker.ts +307 -0
  1062. package/open-sse/services/emergencyFallback.ts +162 -0
  1063. package/open-sse/services/errorClassifier.ts +198 -0
  1064. package/open-sse/services/evalRouting.ts +276 -0
  1065. package/open-sse/services/freeWebSearch.ts +154 -0
  1066. package/open-sse/services/fusion.ts +337 -0
  1067. package/open-sse/services/geminiRateLimitTracker.ts +145 -0
  1068. package/open-sse/services/geminiThoughtSignatureStore.ts +329 -0
  1069. package/open-sse/services/genericQuotaFetcher.ts +215 -0
  1070. package/open-sse/services/gigachatAuth.ts +113 -0
  1071. package/open-sse/services/githubCopilotModels.ts +162 -0
  1072. package/open-sse/services/gpt5SamplingGuard.ts +81 -0
  1073. package/open-sse/services/grokTlsClient.ts +607 -0
  1074. package/open-sse/services/hfModelSuggestions.ts +63 -0
  1075. package/open-sse/services/inAppLoginService.ts +256 -0
  1076. package/open-sse/services/intentClassifier.ts +665 -0
  1077. package/open-sse/services/ipFilter.ts +340 -0
  1078. package/open-sse/services/keyGroupAuth.ts +84 -0
  1079. package/open-sse/services/kiroModels.ts +195 -0
  1080. package/open-sse/services/manifestAdapter.ts +134 -0
  1081. package/open-sse/services/mimoThinking.ts +54 -0
  1082. package/open-sse/services/model.ts +738 -0
  1083. package/open-sse/services/modelCapabilities.ts +5 -0
  1084. package/open-sse/services/modelDeprecation.ts +173 -0
  1085. package/open-sse/services/modelFamilyFallback.ts +240 -0
  1086. package/open-sse/services/modelStrip.ts +60 -0
  1087. package/open-sse/services/modelscopePolicy.ts +97 -0
  1088. package/open-sse/services/opencodeOllamaUsage.ts +562 -0
  1089. package/open-sse/services/opencodeQuotaFetcher.ts +351 -0
  1090. package/open-sse/services/payloadRules.ts +474 -0
  1091. package/open-sse/services/perplexityTlsClient.ts +593 -0
  1092. package/open-sse/services/pipeline.ts +189 -0
  1093. package/open-sse/services/provider.ts +460 -0
  1094. package/open-sse/services/providerCooldownTracker.ts +198 -0
  1095. package/open-sse/services/providerCostData.ts +52 -0
  1096. package/open-sse/services/providerDefaultRateLimit.ts +94 -0
  1097. package/open-sse/services/providerRequestDefaults.ts +88 -0
  1098. package/open-sse/services/proxyAutoSelector.ts +58 -0
  1099. package/open-sse/services/qoderCli.ts +987 -0
  1100. package/open-sse/services/qoderCliResolve.ts +111 -0
  1101. package/open-sse/services/quotaFetchThrottle.ts +118 -0
  1102. package/open-sse/services/quotaMonitor.ts +377 -0
  1103. package/open-sse/services/quotaPreflight.ts +349 -0
  1104. package/open-sse/services/qwenThinking.ts +44 -0
  1105. package/open-sse/services/rateLimitManager/headers.ts +94 -0
  1106. package/open-sse/services/rateLimitManager.ts +945 -0
  1107. package/open-sse/services/rateLimitSemaphore.ts +231 -0
  1108. package/open-sse/services/reasoningCache.ts +514 -0
  1109. package/open-sse/services/reasoningTokenBuffer.ts +50 -0
  1110. package/open-sse/services/refreshSerializer.ts +131 -0
  1111. package/open-sse/services/requestDedup.ts +127 -0
  1112. package/open-sse/services/responseModelEcho.ts +79 -0
  1113. package/open-sse/services/responsesInputSanitizer.ts +145 -0
  1114. package/open-sse/services/retryAfterJson.ts +44 -0
  1115. package/open-sse/services/roleNormalizer.ts +283 -0
  1116. package/open-sse/services/searchCache.ts +150 -0
  1117. package/open-sse/services/sessionManager.ts +380 -0
  1118. package/open-sse/services/sessionPool/fingerprintRotator.ts +126 -0
  1119. package/open-sse/services/sessionPool/index.ts +28 -0
  1120. package/open-sse/services/sessionPool/poolRegistry.ts +93 -0
  1121. package/open-sse/services/sessionPool/session.ts +119 -0
  1122. package/open-sse/services/sessionPool/sessionFactory.ts +57 -0
  1123. package/open-sse/services/sessionPool/sessionPool.ts +326 -0
  1124. package/open-sse/services/sessionPool/types.ts +100 -0
  1125. package/open-sse/services/sessionPool/webExecutorWrapper.ts +132 -0
  1126. package/open-sse/services/signatureCache.ts +189 -0
  1127. package/open-sse/services/slidingWindowLimiter.ts +84 -0
  1128. package/open-sse/services/specificityDetector.ts +89 -0
  1129. package/open-sse/services/specificityRules.ts +257 -0
  1130. package/open-sse/services/specificityTypes.ts +43 -0
  1131. package/open-sse/services/streamRecovery.ts +545 -0
  1132. package/open-sse/services/systemPrompt.ts +187 -0
  1133. package/open-sse/services/systemTransforms.ts +532 -0
  1134. package/open-sse/services/taskAwareRouter.ts +326 -0
  1135. package/open-sse/services/taskAwareRouting.ts +553 -0
  1136. package/open-sse/services/thinkingBudget.ts +391 -0
  1137. package/open-sse/services/tierConfig.ts +124 -0
  1138. package/open-sse/services/tierDefaults.json +26 -0
  1139. package/open-sse/services/tierResolver.ts +144 -0
  1140. package/open-sse/services/tierTypes.ts +40 -0
  1141. package/open-sse/services/tlsClientProxy.ts +30 -0
  1142. package/open-sse/services/tokenExtractionConfig.ts +398 -0
  1143. package/open-sse/services/tokenLimitCounter.ts +342 -0
  1144. package/open-sse/services/tokenRefresh.ts +2180 -0
  1145. package/open-sse/services/toolLatencyTracker.ts +89 -0
  1146. package/open-sse/services/toolLimitDetector.ts +87 -0
  1147. package/open-sse/services/toolSchemaSanitizer.ts +165 -0
  1148. package/open-sse/services/usage/antigravity.ts +794 -0
  1149. package/open-sse/services/usage/claude.ts +216 -0
  1150. package/open-sse/services/usage/codebuddy-cn.ts +199 -0
  1151. package/open-sse/services/usage/codex.ts +75 -0
  1152. package/open-sse/services/usage/cursor.ts +161 -0
  1153. package/open-sse/services/usage/glm.ts +220 -0
  1154. package/open-sse/services/usage/kimi.ts +209 -0
  1155. package/open-sse/services/usage/kiro.ts +243 -0
  1156. package/open-sse/services/usage/minimax.ts +346 -0
  1157. package/open-sse/services/usage/quota.ts +85 -0
  1158. package/open-sse/services/usage/scalars.ts +75 -0
  1159. package/open-sse/services/usage.ts +1058 -0
  1160. package/open-sse/services/volumeDetector.ts +224 -0
  1161. package/open-sse/services/webSearchFallback.ts +246 -0
  1162. package/open-sse/services/webSearchRouting.ts +68 -0
  1163. package/open-sse/services/webSessionPoolHealth.ts +287 -0
  1164. package/open-sse/services/wildcardRouter.ts +136 -0
  1165. package/open-sse/services/workflowFSM.ts +340 -0
  1166. package/open-sse/shared/zedAuth.ts +535 -0
  1167. package/open-sse/transformer/responsesTransformer.ts +667 -0
  1168. package/open-sse/translator/bootstrap.ts +27 -0
  1169. package/open-sse/translator/deepseekWebTools.ts +486 -0
  1170. package/open-sse/translator/formats.ts +12 -0
  1171. package/open-sse/translator/helpers/claudeHelper.ts +563 -0
  1172. package/open-sse/translator/helpers/geminiHelper.ts +657 -0
  1173. package/open-sse/translator/helpers/geminiToolsSanitizer.ts +255 -0
  1174. package/open-sse/translator/helpers/jsonUtil.ts +18 -0
  1175. package/open-sse/translator/helpers/maxTokensHelper.ts +21 -0
  1176. package/open-sse/translator/helpers/openaiHelper.ts +244 -0
  1177. package/open-sse/translator/helpers/responsesApiHelper.ts +9 -0
  1178. package/open-sse/translator/helpers/schemaCoercion.ts +408 -0
  1179. package/open-sse/translator/helpers/toolCallHelper.ts +224 -0
  1180. package/open-sse/translator/helpers/toolCallShim.ts +113 -0
  1181. package/open-sse/translator/image/sizeMapper.ts +22 -0
  1182. package/open-sse/translator/index.ts +614 -0
  1183. package/open-sse/translator/paramSupport.ts +70 -0
  1184. package/open-sse/translator/registry.ts +41 -0
  1185. package/open-sse/translator/request/antigravity-to-openai.ts +357 -0
  1186. package/open-sse/translator/request/claude-to-gemini.ts +236 -0
  1187. package/open-sse/translator/request/claude-to-openai.ts +534 -0
  1188. package/open-sse/translator/request/gemini-to-openai.ts +193 -0
  1189. package/open-sse/translator/request/openai-responses/helpers.ts +69 -0
  1190. package/open-sse/translator/request/openai-responses/toResponses.ts +357 -0
  1191. package/open-sse/translator/request/openai-responses.ts +533 -0
  1192. package/open-sse/translator/request/openai-to-claude/thinkingBudget.ts +89 -0
  1193. package/open-sse/translator/request/openai-to-claude/toolResultAdjacency.ts +106 -0
  1194. package/open-sse/translator/request/openai-to-claude.ts +747 -0
  1195. package/open-sse/translator/request/openai-to-cursor.ts +226 -0
  1196. package/open-sse/translator/request/openai-to-gemini/helpers.ts +142 -0
  1197. package/open-sse/translator/request/openai-to-gemini.ts +753 -0
  1198. package/open-sse/translator/request/openai-to-kiro/messageHelpers.ts +109 -0
  1199. package/open-sse/translator/request/openai-to-kiro.ts +889 -0
  1200. package/open-sse/translator/response/claude-to-openai.ts +327 -0
  1201. package/open-sse/translator/response/cursor-to-openai.ts +30 -0
  1202. package/open-sse/translator/response/gemini-to-claude.ts +199 -0
  1203. package/open-sse/translator/response/gemini-to-openai.ts +765 -0
  1204. package/open-sse/translator/response/kiro-to-openai.ts +211 -0
  1205. package/open-sse/translator/response/openai-responses/pureHelpers.ts +92 -0
  1206. package/open-sse/translator/response/openai-responses.ts +1011 -0
  1207. package/open-sse/translator/response/openai-to-antigravity.ts +145 -0
  1208. package/open-sse/translator/response/openai-to-claude.ts +289 -0
  1209. package/open-sse/translator/response/openai-to-gemini-sse.ts +431 -0
  1210. package/open-sse/translator/webTools.ts +531 -0
  1211. package/open-sse/tsconfig.json +25 -0
  1212. package/open-sse/types.d.ts +139 -0
  1213. package/open-sse/utils/agentGoalPolicy.ts +112 -0
  1214. package/open-sse/utils/aiSdkCompat.ts +179 -0
  1215. package/open-sse/utils/anthropicHost.ts +25 -0
  1216. package/open-sse/utils/awsSigV4.ts +139 -0
  1217. package/open-sse/utils/bypassHandler.ts +300 -0
  1218. package/open-sse/utils/cacheControlPolicy.ts +374 -0
  1219. package/open-sse/utils/claudeCodeMetaRequests.ts +87 -0
  1220. package/open-sse/utils/clinepassEnvelope.ts +59 -0
  1221. package/open-sse/utils/comfyuiClient.ts +126 -0
  1222. package/open-sse/utils/composerToolCalls.ts +307 -0
  1223. package/open-sse/utils/cors.ts +13 -0
  1224. package/open-sse/utils/cursorAgentProtobuf/wire.ts +143 -0
  1225. package/open-sse/utils/cursorAgentProtobuf.ts +1400 -0
  1226. package/open-sse/utils/cursorChecksum.ts +139 -0
  1227. package/open-sse/utils/cursorImages.ts +354 -0
  1228. package/open-sse/utils/cursorVersionDetector.ts +74 -0
  1229. package/open-sse/utils/diagnostics.ts +288 -0
  1230. package/open-sse/utils/earlyStreamKeepalive.ts +228 -0
  1231. package/open-sse/utils/error.ts +515 -0
  1232. package/open-sse/utils/estimateSize.ts +35 -0
  1233. package/open-sse/utils/finishReason.ts +36 -0
  1234. package/open-sse/utils/flattenToolHistory.ts +116 -0
  1235. package/open-sse/utils/headers.ts +61 -0
  1236. package/open-sse/utils/heapPressure.ts +81 -0
  1237. package/open-sse/utils/jsonToSse.ts +127 -0
  1238. package/open-sse/utils/keepaliveThreshold.ts +62 -0
  1239. package/open-sse/utils/kieTask.ts +127 -0
  1240. package/open-sse/utils/kiroSanitizer.ts +127 -0
  1241. package/open-sse/utils/logger.ts +190 -0
  1242. package/open-sse/utils/networkProxy.ts +75 -0
  1243. package/open-sse/utils/noThinkingAlias.ts +153 -0
  1244. package/open-sse/utils/number.ts +4 -0
  1245. package/open-sse/utils/ollamaTransform.ts +122 -0
  1246. package/open-sse/utils/opencodeHeaders.ts +98 -0
  1247. package/open-sse/utils/passthroughTailProcessor.ts +299 -0
  1248. package/open-sse/utils/progressTracker.ts +112 -0
  1249. package/open-sse/utils/providerRequestLogging.ts +272 -0
  1250. package/open-sse/utils/proxyDispatcher.ts +507 -0
  1251. package/open-sse/utils/proxyDispatcherCache.ts +124 -0
  1252. package/open-sse/utils/proxyFallback.ts +418 -0
  1253. package/open-sse/utils/proxyFamily.ts +24 -0
  1254. package/open-sse/utils/proxyFamilyResolve.ts +39 -0
  1255. package/open-sse/utils/proxyFetch.ts +666 -0
  1256. package/open-sse/utils/publicCreds.ts +215 -0
  1257. package/open-sse/utils/reasoningContentInjector.ts +73 -0
  1258. package/open-sse/utils/reasoningFields.ts +72 -0
  1259. package/open-sse/utils/requestLogger.ts +386 -0
  1260. package/open-sse/utils/responsesInputNormalization.ts +94 -0
  1261. package/open-sse/utils/responsesStatePolicy.ts +75 -0
  1262. package/open-sse/utils/responsesStreamHelpers.ts +166 -0
  1263. package/open-sse/utils/setupPolyfill.ts +33 -0
  1264. package/open-sse/utils/sha3-512.ts +164 -0
  1265. package/open-sse/utils/sleep.ts +9 -0
  1266. package/open-sse/utils/socksConnectorWithFamily.ts +89 -0
  1267. package/open-sse/utils/sseHeartbeat.ts +119 -0
  1268. package/open-sse/utils/stream.ts +2791 -0
  1269. package/open-sse/utils/streamFailureFinalization.ts +174 -0
  1270. package/open-sse/utils/streamHandler.ts +680 -0
  1271. package/open-sse/utils/streamHelpers.ts +460 -0
  1272. package/open-sse/utils/streamPayloadCollector.ts +700 -0
  1273. package/open-sse/utils/streamReadiness.ts +385 -0
  1274. package/open-sse/utils/streamReadinessPolicy.ts +132 -0
  1275. package/open-sse/utils/textualToolCall.ts +112 -0
  1276. package/open-sse/utils/thinkCloseMarker.ts +77 -0
  1277. package/open-sse/utils/thinkTagParser.ts +146 -0
  1278. package/open-sse/utils/tlsClient.ts +243 -0
  1279. package/open-sse/utils/toolCallArguments.ts +32 -0
  1280. package/open-sse/utils/toolSources.ts +69 -0
  1281. package/open-sse/utils/upstreamResponseHeaders.ts +47 -0
  1282. package/open-sse/utils/urlSanitize.ts +24 -0
  1283. package/open-sse/utils/usageTracking.ts +596 -0
  1284. package/package.json +393 -0
  1285. package/scripts/build/build-next-isolated.mjs +322 -0
  1286. package/scripts/build/colocateOptionals.mjs +144 -0
  1287. package/scripts/build/native-binary-compat.mjs +167 -0
  1288. package/scripts/build/postinstall.mjs +357 -0
  1289. package/scripts/build/postinstallSupport.mjs +45 -0
  1290. package/scripts/build/runtime-env.mjs +140 -0
  1291. package/scripts/build/sync-env.mjs +3 -0
  1292. package/scripts/check/check-supported-node-runtime.ts +20 -0
  1293. package/scripts/dev/responses-ws-proxy.mjs +907 -0
  1294. package/scripts/dev/sync-env.mjs +362 -0
  1295. package/scripts/dev/tls-options.mjs +92 -0
  1296. package/scripts/postinstall.mjs +27 -0
  1297. package/src/domain/assessment/assessor.ts +206 -0
  1298. package/src/domain/assessment/categorizer.ts +118 -0
  1299. package/src/domain/assessment/index.ts +24 -0
  1300. package/src/domain/assessment/migration.ts +111 -0
  1301. package/src/domain/assessment/selfHealer.ts +261 -0
  1302. package/src/domain/assessment/types.ts +361 -0
  1303. package/src/domain/comboResolver.ts +106 -0
  1304. package/src/domain/configAudit.ts +285 -0
  1305. package/src/domain/connectionModelRules.ts +82 -0
  1306. package/src/domain/costRules.ts +631 -0
  1307. package/src/domain/degradation.ts +253 -0
  1308. package/src/domain/fallbackPolicy.ts +160 -0
  1309. package/src/domain/lockoutPolicy.ts +208 -0
  1310. package/src/domain/modelAvailability.ts +41 -0
  1311. package/src/domain/omnirouteResponseMeta.ts +202 -0
  1312. package/src/domain/pipeline.ts +307 -0
  1313. package/src/domain/policyEngine.ts +195 -0
  1314. package/src/domain/prompts.ts +103 -0
  1315. package/src/domain/providerExpiration.ts +255 -0
  1316. package/src/domain/quotaCache.ts +553 -0
  1317. package/src/domain/responses.ts +139 -0
  1318. package/src/domain/tagRouter.ts +64 -0
  1319. package/src/domain/types.ts +123 -0
  1320. package/src/lib/a2a/README.md +748 -0
  1321. package/src/lib/a2a/routingLogger.ts +67 -0
  1322. package/src/lib/a2a/skills/costAnalysis.ts +162 -0
  1323. package/src/lib/a2a/skills/healthReport.ts +155 -0
  1324. package/src/lib/a2a/skills/listCapabilities.ts +72 -0
  1325. package/src/lib/a2a/skills/providerDiscovery.ts +202 -0
  1326. package/src/lib/a2a/skills/quotaManagement.ts +121 -0
  1327. package/src/lib/a2a/skills/smartRouting.ts +89 -0
  1328. package/src/lib/a2a/streaming.ts +149 -0
  1329. package/src/lib/a2a/taskExecution.ts +64 -0
  1330. package/src/lib/a2a/taskManager.ts +240 -0
  1331. package/src/lib/accessTokens/scopes.ts +51 -0
  1332. package/src/lib/acp/index.ts +11 -0
  1333. package/src/lib/acp/manager.ts +202 -0
  1334. package/src/lib/acp/registry.ts +384 -0
  1335. package/src/lib/agentSkills/catalog.ts +256 -0
  1336. package/src/lib/agentSkills/cliRegistryParser.ts +242 -0
  1337. package/src/lib/agentSkills/generator.ts +367 -0
  1338. package/src/lib/agentSkills/openapiParser.ts +201 -0
  1339. package/src/lib/agentSkills/schemas.ts +36 -0
  1340. package/src/lib/agentSkills/types.ts +101 -0
  1341. package/src/lib/api/comboErrorResponse.ts +80 -0
  1342. package/src/lib/api/errorResponse.ts +54 -0
  1343. package/src/lib/api/modelTestRunner.ts +390 -0
  1344. package/src/lib/api/proxyRegistryRouteHandlers.ts +142 -0
  1345. package/src/lib/api/requireCliToolsAuth.ts +5 -0
  1346. package/src/lib/api/requireManagementAuth.ts +118 -0
  1347. package/src/lib/api/serverErrorMessage.ts +36 -0
  1348. package/src/lib/apiBridgeServer.ts +233 -0
  1349. package/src/lib/apiKeyExposure.ts +19 -0
  1350. package/src/lib/arenaEloSync.ts +564 -0
  1351. package/src/lib/audit/activityIcons.ts +69 -0
  1352. package/src/lib/audit/highLevelActions.ts +57 -0
  1353. package/src/lib/audit/timeline.ts +132 -0
  1354. package/src/lib/auth/managementPassword.ts +117 -0
  1355. package/src/lib/batches/costEstimator.ts +130 -0
  1356. package/src/lib/batches/csvToJsonl.ts +248 -0
  1357. package/src/lib/batches/dispatch.ts +53 -0
  1358. package/src/lib/batches/retryFailed.ts +77 -0
  1359. package/src/lib/batches/schemas.ts +38 -0
  1360. package/src/lib/batches/types.ts +78 -0
  1361. package/src/lib/batches/validateJsonl.ts +154 -0
  1362. package/src/lib/benchmarks.ts +33 -0
  1363. package/src/lib/build-profile/featureDisabled.ts +23 -0
  1364. package/src/lib/cacheControlSettings.ts +25 -0
  1365. package/src/lib/cacheLayer.ts +220 -0
  1366. package/src/lib/catalog/openrouterCatalog.ts +177 -0
  1367. package/src/lib/cli-helper/claudeProfileAutoSync.ts +92 -0
  1368. package/src/lib/cli-helper/codexProfileAutoSync.ts +80 -0
  1369. package/src/lib/cli-helper/config-generator/claude.ts +25 -0
  1370. package/src/lib/cli-helper/config-generator/cline.ts +23 -0
  1371. package/src/lib/cli-helper/config-generator/codex.ts +34 -0
  1372. package/src/lib/cli-helper/config-generator/continue.ts +37 -0
  1373. package/src/lib/cli-helper/config-generator/hermes-agent.ts +210 -0
  1374. package/src/lib/cli-helper/config-generator/hermes.ts +47 -0
  1375. package/src/lib/cli-helper/config-generator/hermesHome.ts +40 -0
  1376. package/src/lib/cli-helper/config-generator/index.ts +124 -0
  1377. package/src/lib/cli-helper/config-generator/kilocode.ts +23 -0
  1378. package/src/lib/cli-helper/config-generator/opencode.ts +443 -0
  1379. package/src/lib/cli-helper/doctor/checks.ts +41 -0
  1380. package/src/lib/cli-helper/log-streamer.ts +78 -0
  1381. package/src/lib/cli-helper/tool-detector.ts +165 -0
  1382. package/src/lib/cliTools/batchStatusCache.ts +47 -0
  1383. package/src/lib/cliTools/checkToolConfigStatus.ts +112 -0
  1384. package/src/lib/cloudAgent/agents/codex.ts +148 -0
  1385. package/src/lib/cloudAgent/agents/cursor.ts +205 -0
  1386. package/src/lib/cloudAgent/agents/devin.ts +137 -0
  1387. package/src/lib/cloudAgent/agents/jules.ts +354 -0
  1388. package/src/lib/cloudAgent/api.ts +86 -0
  1389. package/src/lib/cloudAgent/baseAgent.ts +98 -0
  1390. package/src/lib/cloudAgent/credentials.ts +89 -0
  1391. package/src/lib/cloudAgent/db.ts +145 -0
  1392. package/src/lib/cloudAgent/index.ts +8 -0
  1393. package/src/lib/cloudAgent/julesApi.ts +7 -0
  1394. package/src/lib/cloudAgent/registry.ts +29 -0
  1395. package/src/lib/cloudAgent/types.ts +90 -0
  1396. package/src/lib/cloudSync.stub.ts +31 -0
  1397. package/src/lib/cloudSync.ts +210 -0
  1398. package/src/lib/cloudflaredTunnel.ts +933 -0
  1399. package/src/lib/combos/autoPromote.ts +92 -0
  1400. package/src/lib/combos/builderDraft.ts +242 -0
  1401. package/src/lib/combos/builderOptions.ts +681 -0
  1402. package/src/lib/combos/compositeTiers.ts +200 -0
  1403. package/src/lib/combos/controlCenter.ts +271 -0
  1404. package/src/lib/combos/intelligentRouting.ts +192 -0
  1405. package/src/lib/combos/steps.ts +322 -0
  1406. package/src/lib/combos/testHealth.ts +190 -0
  1407. package/src/lib/compliance/index.ts +637 -0
  1408. package/src/lib/compliance/noLog.ts +86 -0
  1409. package/src/lib/compliance/providerAudit.ts +98 -0
  1410. package/src/lib/compression/judgeModelClient.ts +43 -0
  1411. package/src/lib/config/hotReload.ts +115 -0
  1412. package/src/lib/config/runtimeSettings.ts +551 -0
  1413. package/src/lib/consoleInterceptor.ts +136 -0
  1414. package/src/lib/container.ts +122 -0
  1415. package/src/lib/contextWindowResolver.ts +147 -0
  1416. package/src/lib/copilot/codegraphKnowledge.ts +229 -0
  1417. package/src/lib/copilot/engine.ts +372 -0
  1418. package/src/lib/copilot/systemPrompt.ts +189 -0
  1419. package/src/lib/copilot/tools.ts +415 -0
  1420. package/src/lib/credentialHealth/cache.ts +206 -0
  1421. package/src/lib/credentialHealth/scheduler.ts +328 -0
  1422. package/src/lib/dataPaths.ts +122 -0
  1423. package/src/lib/db/AGENTS.md +70 -0
  1424. package/src/lib/db/_rowTypes.ts +45 -0
  1425. package/src/lib/db/accessTokens.ts +183 -0
  1426. package/src/lib/db/adapters/betterSqliteAdapter.ts +58 -0
  1427. package/src/lib/db/adapters/driverFactory.ts +98 -0
  1428. package/src/lib/db/adapters/nodeSqliteAdapter.ts +60 -0
  1429. package/src/lib/db/adapters/nodeSqliteShared.ts +148 -0
  1430. package/src/lib/db/adapters/sqljsAdapter.ts +232 -0
  1431. package/src/lib/db/adapters/types.ts +34 -0
  1432. package/src/lib/db/agentBridgeBypass.ts +81 -0
  1433. package/src/lib/db/agentBridgeMappings.ts +47 -0
  1434. package/src/lib/db/agentBridgeState.ts +115 -0
  1435. package/src/lib/db/apiKeyColumnFallbacks.ts +47 -0
  1436. package/src/lib/db/apiKeyContextSources.ts +107 -0
  1437. package/src/lib/db/apiKeyGroups.ts +318 -0
  1438. package/src/lib/db/apiKeyUsageLimitFields.ts +65 -0
  1439. package/src/lib/db/apiKeys/modelPermissions.ts +122 -0
  1440. package/src/lib/db/apiKeys/rowParsers.ts +161 -0
  1441. package/src/lib/db/apiKeys/types.ts +21 -0
  1442. package/src/lib/db/apiKeys.ts +1492 -0
  1443. package/src/lib/db/backup.ts +708 -0
  1444. package/src/lib/db/batches.ts +450 -0
  1445. package/src/lib/db/callLogStats.ts +235 -0
  1446. package/src/lib/db/caseMapping.ts +80 -0
  1447. package/src/lib/db/cleanup.ts +584 -0
  1448. package/src/lib/db/cliToolState.ts +159 -0
  1449. package/src/lib/db/comboForecast.ts +119 -0
  1450. package/src/lib/db/combos.ts +339 -0
  1451. package/src/lib/db/commandCodeAuth.ts +209 -0
  1452. package/src/lib/db/compression.ts +780 -0
  1453. package/src/lib/db/compressionAnalytics.ts +661 -0
  1454. package/src/lib/db/compressionCacheStats.ts +112 -0
  1455. package/src/lib/db/compressionCombos.ts +491 -0
  1456. package/src/lib/db/compressionRunTelemetry.ts +126 -0
  1457. package/src/lib/db/contextHandoffs.ts +233 -0
  1458. package/src/lib/db/core.ts +1520 -0
  1459. package/src/lib/db/creditBalance.ts +92 -0
  1460. package/src/lib/db/databaseSettings.ts +309 -0
  1461. package/src/lib/db/detailedLogs.ts +170 -0
  1462. package/src/lib/db/discovery.ts +97 -0
  1463. package/src/lib/db/discoveryResults.ts +176 -0
  1464. package/src/lib/db/domainState.ts +630 -0
  1465. package/src/lib/db/encryption.ts +327 -0
  1466. package/src/lib/db/evals.ts +786 -0
  1467. package/src/lib/db/featureFlags.ts +82 -0
  1468. package/src/lib/db/files.ts +170 -0
  1469. package/src/lib/db/freeProxies.ts +360 -0
  1470. package/src/lib/db/gamification.ts +613 -0
  1471. package/src/lib/db/healthCheck.ts +565 -0
  1472. package/src/lib/db/inspectorCustomHosts.ts +88 -0
  1473. package/src/lib/db/inspectorSessions.ts +161 -0
  1474. package/src/lib/db/jsonMigration.ts +321 -0
  1475. package/src/lib/db/memoryVec.ts +138 -0
  1476. package/src/lib/db/middleware.ts +239 -0
  1477. package/src/lib/db/migrationRunner/constants.ts +118 -0
  1478. package/src/lib/db/migrationRunner.ts +1069 -0
  1479. package/src/lib/db/migrations/001_initial_schema.sql +226 -0
  1480. package/src/lib/db/migrations/002_mcp_a2a_tables.sql +95 -0
  1481. package/src/lib/db/migrations/003_provider_node_custom_paths.sql +5 -0
  1482. package/src/lib/db/migrations/004_proxy_registry.sql +31 -0
  1483. package/src/lib/db/migrations/005_combo_agent_fields.sql +19 -0
  1484. package/src/lib/db/migrations/006_detailed_request_logs.sql +42 -0
  1485. package/src/lib/db/migrations/007_search_request_type.sql +4 -0
  1486. package/src/lib/db/migrations/008_registered_keys.sql +65 -0
  1487. package/src/lib/db/migrations/009_requested_model.sql +9 -0
  1488. package/src/lib/db/migrations/010_model_combo_mappings.sql +19 -0
  1489. package/src/lib/db/migrations/011_webhooks.sql +15 -0
  1490. package/src/lib/db/migrations/012_fix_token_input_cache_tokens.sql +15 -0
  1491. package/src/lib/db/migrations/013_quota_snapshots.sql +19 -0
  1492. package/src/lib/db/migrations/014_unified_log_artifacts.sql +15 -0
  1493. package/src/lib/db/migrations/015_create_memories.sql +22 -0
  1494. package/src/lib/db/migrations/016_create_skills.sql +37 -0
  1495. package/src/lib/db/migrations/017_version_manager_upstream_proxy.sql +56 -0
  1496. package/src/lib/db/migrations/018_call_logs_detailed_tokens.sql +6 -0
  1497. package/src/lib/db/migrations/019_context_handoffs.sql +28 -0
  1498. package/src/lib/db/migrations/020_combo_sort_order.sql +16 -0
  1499. package/src/lib/db/migrations/021_combo_call_log_targets.sql +5 -0
  1500. package/src/lib/db/migrations/022_add_memory_fts5.sql +33 -0
  1501. package/src/lib/db/migrations/023_fix_memory_fts_uuid.sql +55 -0
  1502. package/src/lib/db/migrations/024_create_sync_tokens.sql +15 -0
  1503. package/src/lib/db/migrations/025_call_logs_summary_storage.sql +145 -0
  1504. package/src/lib/db/migrations/027_skill_mode_and_metadata.sql +10 -0
  1505. package/src/lib/db/migrations/028_create_files_and_batches.sql +51 -0
  1506. package/src/lib/db/migrations/029_provider_connection_max_concurrent.sql +10 -0
  1507. package/src/lib/db/migrations/030_create_eval_runs.sql +28 -0
  1508. package/src/lib/db/migrations/031_create_eval_suites.sql +27 -0
  1509. package/src/lib/db/migrations/032_apikey_lifecycle.sql +24 -0
  1510. package/src/lib/db/migrations/033_create_reasoning_cache.sql +27 -0
  1511. package/src/lib/db/migrations/034_compression_settings.sql +10 -0
  1512. package/src/lib/db/migrations/035_standard_compression_config.sql +9 -0
  1513. package/src/lib/db/migrations/036_aggressive_compression.sql +4 -0
  1514. package/src/lib/db/migrations/037_ultra_compression.sql +6 -0
  1515. package/src/lib/db/migrations/038_compression_analytics.sql +13 -0
  1516. package/src/lib/db/migrations/039_compression_cache_stats.sql +15 -0
  1517. package/src/lib/db/migrations/040_oneproxy_proxy_fields.sql +24 -0
  1518. package/src/lib/db/migrations/041_compression_receipts.sql +18 -0
  1519. package/src/lib/db/migrations/042_compression_combos.sql +43 -0
  1520. package/src/lib/db/migrations/043_default_compression_combo_pipeline.sql +12 -0
  1521. package/src/lib/db/migrations/044_usage_history_api_key_backfill.sql +27 -0
  1522. package/src/lib/db/migrations/045_compression_tokens.sql +4 -0
  1523. package/src/lib/db/migrations/046_database_settings.sql +44 -0
  1524. package/src/lib/db/migrations/047_aggregation_tables.sql +44 -0
  1525. package/src/lib/db/migrations/048_summary_indexes.sql +29 -0
  1526. package/src/lib/db/migrations/049_compression_analytics_indexes.sql +10 -0
  1527. package/src/lib/db/migrations/050_session_account_affinity.sql +11 -0
  1528. package/src/lib/db/migrations/051_hot_path_db_indexes.sql +10 -0
  1529. package/src/lib/db/migrations/052_api_key_combo_throttle.sql +4 -0
  1530. package/src/lib/db/migrations/053_remove_status_from_files.sql +2 -0
  1531. package/src/lib/db/migrations/054_usage_history_service_tier.sql +4 -0
  1532. package/src/lib/db/migrations/056_mcp_accessibility_compression.sql +8 -0
  1533. package/src/lib/db/migrations/057_provider_connection_quota_window_thresholds.sql +14 -0
  1534. package/src/lib/db/migrations/058_command_code_auth_sessions.sql +19 -0
  1535. package/src/lib/db/migrations/059_manifest_routing.sql +21 -0
  1536. package/src/lib/db/migrations/060_create_gamification.sql +94 -0
  1537. package/src/lib/db/migrations/061_cloud_agent_credentials.sql +9 -0
  1538. package/src/lib/db/migrations/062_usage_history_combo_strategy.sql +4 -0
  1539. package/src/lib/db/migrations/063_add_last_model_to_handoffs.sql +7 -0
  1540. package/src/lib/db/migrations/064_create_session_model_history.sql +19 -0
  1541. package/src/lib/db/migrations/065_middleware_hooks.sql +45 -0
  1542. package/src/lib/db/migrations/066_api_key_groups.sql +47 -0
  1543. package/src/lib/db/migrations/067_relay_proxies.sql +56 -0
  1544. package/src/lib/db/migrations/068_free_proxies.sql +52 -0
  1545. package/src/lib/db/migrations/069_webhook_deliveries.sql +15 -0
  1546. package/src/lib/db/migrations/070_webhooks_kind_metadata.sql +3 -0
  1547. package/src/lib/db/migrations/071_services.sql +19 -0
  1548. package/src/lib/db/migrations/072_free_proxies_fk.sql +27 -0
  1549. package/src/lib/db/migrations/073_per_model_token_limits.sql +61 -0
  1550. package/src/lib/db/migrations/074_discovery_results.sql +20 -0
  1551. package/src/lib/db/migrations/075_api_key_self_service_usage_scopes.sql +51 -0
  1552. package/src/lib/db/migrations/076_create_plugins.sql +31 -0
  1553. package/src/lib/db/migrations/077_api_key_stream_default_mode.sql +3 -0
  1554. package/src/lib/db/migrations/078_quota_consumption.sql +24 -0
  1555. package/src/lib/db/migrations/079_provider_plans.sql +19 -0
  1556. package/src/lib/db/migrations/080_agent_bridge.sql +24 -0
  1557. package/src/lib/db/migrations/081_inspector_custom_hosts.sql +11 -0
  1558. package/src/lib/db/migrations/082_inspector_sessions.sql +18 -0
  1559. package/src/lib/db/migrations/083_memory_vec.sql +26 -0
  1560. package/src/lib/db/migrations/084_playground_presets.sql +15 -0
  1561. package/src/lib/db/migrations/085_quota_pools.sql +39 -0
  1562. package/src/lib/db/migrations/086_api_key_allowed_quotas.sql +8 -0
  1563. package/src/lib/db/migrations/087_quota_pool_connections.sql +21 -0
  1564. package/src/lib/db/migrations/088_quota_groups.sql +28 -0
  1565. package/src/lib/db/migrations/089_add_disable_non_public_to_api_keys.sql +3 -0
  1566. package/src/lib/db/migrations/090_plugin_metrics.sql +9 -0
  1567. package/src/lib/db/migrations/091_plugin_analytics.sql +23 -0
  1568. package/src/lib/db/migrations/092_api_key_context_sources.sql +13 -0
  1569. package/src/lib/db/migrations/093_proxy_enable_toggles.sql +17 -0
  1570. package/src/lib/db/migrations/094_per_key_proxy_toggles.sql +12 -0
  1571. package/src/lib/db/migrations/095_provider_node_custom_headers.sql +5 -0
  1572. package/src/lib/db/migrations/096_sync_context_cache_protection.sql +9 -0
  1573. package/src/lib/db/migrations/097_model_intelligence.sql +25 -0
  1574. package/src/lib/db/migrations/098_clear_semantic_cache_for_key_isolation.sql +4 -0
  1575. package/src/lib/db/migrations/099_proxy_family.sql +5 -0
  1576. package/src/lib/db/migrations/100_cli_access_tokens.sql +18 -0
  1577. package/src/lib/db/migrations/101_api_key_usage_limits.sql +4 -0
  1578. package/src/lib/db/migrations/102_compression_engines_map.sql +5 -0
  1579. package/src/lib/db/migrations/103_strip_legacy_combo_config_keys.sql +54 -0
  1580. package/src/lib/db/migrations/104_normalize_database_cache_size.sql +10 -0
  1581. package/src/lib/db/migrations/105_usage_history_endpoint.sql +6 -0
  1582. package/src/lib/db/migrations/106_quota_allocation_model_caps.sql +32 -0
  1583. package/src/lib/db/migrations/107_quota_combos_quota_share_strategy.sql +25 -0
  1584. package/src/lib/db/migrations/108_provider_quota_reset_events.sql +26 -0
  1585. package/src/lib/db/migrations/109_call_logs_correlation_id.sql +2 -0
  1586. package/src/lib/db/migrations/110_model_context_overrides.sql +17 -0
  1587. package/src/lib/db/migrations/111_memory_typed_decay.sql +10 -0
  1588. package/src/lib/db/migrations/112_batch_item_checkpoints.sql +18 -0
  1589. package/src/lib/db/migrations/113_provider_node_icon_url.sql +5 -0
  1590. package/src/lib/db/migrations/114_mux_service_seed.sql +12 -0
  1591. package/src/lib/db/migrations/115_bifrost_service.sql +9 -0
  1592. package/src/lib/db/migrations/116_call_logs_reasoning_source.sql +13 -0
  1593. package/src/lib/db/migrations/117_proxy_pool_rotation.sql +53 -0
  1594. package/src/lib/db/modelComboMappings.ts +255 -0
  1595. package/src/lib/db/modelContextOverrides.ts +133 -0
  1596. package/src/lib/db/modelIntelligence.ts +232 -0
  1597. package/src/lib/db/models/aliases.ts +61 -0
  1598. package/src/lib/db/models/compat.ts +249 -0
  1599. package/src/lib/db/models/mitmAlias.ts +32 -0
  1600. package/src/lib/db/models/shared.ts +19 -0
  1601. package/src/lib/db/models.ts +936 -0
  1602. package/src/lib/db/notion.ts +48 -0
  1603. package/src/lib/db/obsidian.ts +283 -0
  1604. package/src/lib/db/oneproxy.ts +293 -0
  1605. package/src/lib/db/optimizationSettings.ts +284 -0
  1606. package/src/lib/db/playgroundPresets.ts +167 -0
  1607. package/src/lib/db/pluginMetrics.ts +88 -0
  1608. package/src/lib/db/plugins.ts +280 -0
  1609. package/src/lib/db/prompts.ts +302 -0
  1610. package/src/lib/db/providerLimits.ts +131 -0
  1611. package/src/lib/db/providerNodeSelect.ts +48 -0
  1612. package/src/lib/db/providerPlans.ts +149 -0
  1613. package/src/lib/db/providerStats.ts +68 -0
  1614. package/src/lib/db/providers/columns.ts +116 -0
  1615. package/src/lib/db/providers/nodes.ts +169 -0
  1616. package/src/lib/db/providers/rateLimit.ts +198 -0
  1617. package/src/lib/db/providers.ts +803 -0
  1618. package/src/lib/db/proxies/mappers.ts +181 -0
  1619. package/src/lib/db/proxies/types.ts +78 -0
  1620. package/src/lib/db/proxies.ts +1176 -0
  1621. package/src/lib/db/proxyLogs.ts +35 -0
  1622. package/src/lib/db/quotaConsumption.ts +274 -0
  1623. package/src/lib/db/quotaGroups.ts +147 -0
  1624. package/src/lib/db/quotaModelCaps.ts +128 -0
  1625. package/src/lib/db/quotaPools.ts +548 -0
  1626. package/src/lib/db/quotaResetEvents.ts +334 -0
  1627. package/src/lib/db/quotaSnapshots.ts +209 -0
  1628. package/src/lib/db/readCache.ts +202 -0
  1629. package/src/lib/db/reasoningCache.ts +276 -0
  1630. package/src/lib/db/recovery.ts +33 -0
  1631. package/src/lib/db/registeredKeys.ts +532 -0
  1632. package/src/lib/db/relayProxies.ts +364 -0
  1633. package/src/lib/db/schemaColumns.ts +226 -0
  1634. package/src/lib/db/secrets.ts +28 -0
  1635. package/src/lib/db/semanticCache.ts +117 -0
  1636. package/src/lib/db/serviceModels.ts +79 -0
  1637. package/src/lib/db/sessionAccountAffinity.ts +212 -0
  1638. package/src/lib/db/settings/cacheMetrics.ts +235 -0
  1639. package/src/lib/db/settings/lkgp.ts +49 -0
  1640. package/src/lib/db/settings/pricing.ts +254 -0
  1641. package/src/lib/db/settings/shared.ts +9 -0
  1642. package/src/lib/db/settings.ts +661 -0
  1643. package/src/lib/db/skills.ts +62 -0
  1644. package/src/lib/db/stateReset.ts +30 -0
  1645. package/src/lib/db/stats.ts +71 -0
  1646. package/src/lib/db/syncTokens.ts +163 -0
  1647. package/src/lib/db/tierConfig.ts +88 -0
  1648. package/src/lib/db/tokenLimits.ts +295 -0
  1649. package/src/lib/db/upstreamProxy.ts +247 -0
  1650. package/src/lib/db/usageAnalytics/sources.ts +208 -0
  1651. package/src/lib/db/usageAnalytics.ts +723 -0
  1652. package/src/lib/db/usageLogs.ts +94 -0
  1653. package/src/lib/db/usageSummary.ts +18 -0
  1654. package/src/lib/db/vacuumScheduler.ts +326 -0
  1655. package/src/lib/db/versionManager.ts +377 -0
  1656. package/src/lib/db/webSessionDedup.ts +57 -0
  1657. package/src/lib/db/webhookDeliveries.ts +77 -0
  1658. package/src/lib/db/webhooks.ts +178 -0
  1659. package/src/lib/discovery/index.ts +137 -0
  1660. package/src/lib/display/names.ts +73 -0
  1661. package/src/lib/display/useProviderNodeMap.ts +68 -0
  1662. package/src/lib/docsI18nPath.ts +33 -0
  1663. package/src/lib/docsSanitizer.ts +42 -0
  1664. package/src/lib/embeddings/familyGuard.ts +24 -0
  1665. package/src/lib/embeddings/service.ts +288 -0
  1666. package/src/lib/env/runtimeEnv.ts +166 -0
  1667. package/src/lib/evals/evalRunner/builtinSuites.ts +676 -0
  1668. package/src/lib/evals/evalRunner.ts +301 -0
  1669. package/src/lib/evals/runtime.ts +311 -0
  1670. package/src/lib/events/eventBus.ts +148 -0
  1671. package/src/lib/events/types.ts +181 -0
  1672. package/src/lib/freeProviderRankings.ts +340 -0
  1673. package/src/lib/freeProxyProviders/index.ts +24 -0
  1674. package/src/lib/freeProxyProviders/iplocate.ts +107 -0
  1675. package/src/lib/freeProxyProviders/oneproxy.ts +127 -0
  1676. package/src/lib/freeProxyProviders/proxifly.ts +143 -0
  1677. package/src/lib/freeProxyProviders/types.ts +33 -0
  1678. package/src/lib/freeProxyProviders/webshare.ts +148 -0
  1679. package/src/lib/gamification/antiCheat.ts +160 -0
  1680. package/src/lib/gamification/badges.ts +542 -0
  1681. package/src/lib/gamification/events.ts +187 -0
  1682. package/src/lib/gamification/index.ts +37 -0
  1683. package/src/lib/gamification/invites.ts +127 -0
  1684. package/src/lib/gamification/leaderboard.ts +64 -0
  1685. package/src/lib/gamification/notifications.ts +118 -0
  1686. package/src/lib/gamification/servers.ts +179 -0
  1687. package/src/lib/gamification/sharing.ts +56 -0
  1688. package/src/lib/gamification/streaks.ts +164 -0
  1689. package/src/lib/gamification/xp.ts +152 -0
  1690. package/src/lib/gracefulShutdown.ts +151 -0
  1691. package/src/lib/guardrails/base.ts +65 -0
  1692. package/src/lib/guardrails/index.ts +4 -0
  1693. package/src/lib/guardrails/piiMasker.ts +208 -0
  1694. package/src/lib/guardrails/promptInjection.ts +285 -0
  1695. package/src/lib/guardrails/registry.ts +282 -0
  1696. package/src/lib/guardrails/visionBridge.ts +237 -0
  1697. package/src/lib/guardrails/visionBridgeHelpers.ts +499 -0
  1698. package/src/lib/guardrails/visionBridgeRouter.ts +271 -0
  1699. package/src/lib/headroom/detect.ts +214 -0
  1700. package/src/lib/headroom/process.ts +177 -0
  1701. package/src/lib/idempotencyLayer.ts +105 -0
  1702. package/src/lib/images/imageRouteModel.ts +168 -0
  1703. package/src/lib/initCloudSync.ts +52 -0
  1704. package/src/lib/inspector/agentBridgeMaintenanceApi.ts +70 -0
  1705. package/src/lib/inspector/captureState.ts +90 -0
  1706. package/src/lib/inspector/configPortability.ts +86 -0
  1707. package/src/lib/inspector/harExport.ts +188 -0
  1708. package/src/lib/inspector/matchesTrafficFilter.ts +37 -0
  1709. package/src/lib/inspector/secretMask.ts +6 -0
  1710. package/src/lib/inspector/tproxyCaptureApi.ts +60 -0
  1711. package/src/lib/ipUtils.ts +94 -0
  1712. package/src/lib/jobs/budgetResetJob.ts +40 -0
  1713. package/src/lib/jobs/reasoningCacheCleanupJob.ts +40 -0
  1714. package/src/lib/localDb.ts +797 -0
  1715. package/src/lib/localHealthCheck.ts +267 -0
  1716. package/src/lib/logEnv.ts +164 -0
  1717. package/src/lib/logPayloads.ts +110 -0
  1718. package/src/lib/logRotation.ts +206 -0
  1719. package/src/lib/machineToken.ts +53 -0
  1720. package/src/lib/memory/cache.ts +76 -0
  1721. package/src/lib/memory/embedding/cache.ts +77 -0
  1722. package/src/lib/memory/embedding/index.ts +281 -0
  1723. package/src/lib/memory/embedding/remote.ts +95 -0
  1724. package/src/lib/memory/embedding/staticPotion.ts +253 -0
  1725. package/src/lib/memory/embedding/transformersLocal.ts +153 -0
  1726. package/src/lib/memory/embedding/types.ts +40 -0
  1727. package/src/lib/memory/extraction.ts +195 -0
  1728. package/src/lib/memory/injection.ts +211 -0
  1729. package/src/lib/memory/qdrant.ts +521 -0
  1730. package/src/lib/memory/reindex.ts +102 -0
  1731. package/src/lib/memory/retrieval/scoring.ts +104 -0
  1732. package/src/lib/memory/retrieval.ts +1072 -0
  1733. package/src/lib/memory/schemas.ts +39 -0
  1734. package/src/lib/memory/settings.ts +184 -0
  1735. package/src/lib/memory/store.ts +621 -0
  1736. package/src/lib/memory/summarization.ts +202 -0
  1737. package/src/lib/memory/typedDecay.ts +245 -0
  1738. package/src/lib/memory/types.ts +45 -0
  1739. package/src/lib/memory/vectorStore.ts +425 -0
  1740. package/src/lib/memory/verify.ts +56 -0
  1741. package/src/lib/middleware/cliTokenAuth.ts +91 -0
  1742. package/src/lib/middleware/registry.ts +432 -0
  1743. package/src/lib/middleware/types.ts +129 -0
  1744. package/src/lib/modelAliasSeed.ts +82 -0
  1745. package/src/lib/modelCapabilities.ts +481 -0
  1746. package/src/lib/modelMetadataRegistry.ts +574 -0
  1747. package/src/lib/modelsDevSync/transform.ts +279 -0
  1748. package/src/lib/modelsDevSync.ts +677 -0
  1749. package/src/lib/monitoring/comboHealthAutopilot.ts +494 -0
  1750. package/src/lib/monitoring/observability.ts +336 -0
  1751. package/src/lib/monitoring/providerHealthAutopilot.ts +743 -0
  1752. package/src/lib/monitoring/providerHealthMatrix.ts +621 -0
  1753. package/src/lib/ngrokTunnel.ts +142 -0
  1754. package/src/lib/notion/api.ts +247 -0
  1755. package/src/lib/oauth/codexDeviceFlow.ts +316 -0
  1756. package/src/lib/oauth/config/index.ts +31 -0
  1757. package/src/lib/oauth/connectionPersistence.ts +114 -0
  1758. package/src/lib/oauth/constants/oauth.ts +494 -0
  1759. package/src/lib/oauth/credentialBlob.ts +105 -0
  1760. package/src/lib/oauth/deviceFlowTickets.ts +110 -0
  1761. package/src/lib/oauth/gitlab.ts +103 -0
  1762. package/src/lib/oauth/pasteCredentials.ts +51 -0
  1763. package/src/lib/oauth/providers/agy.ts +15 -0
  1764. package/src/lib/oauth/providers/antigravity.ts +159 -0
  1765. package/src/lib/oauth/providers/claude.ts +170 -0
  1766. package/src/lib/oauth/providers/cline.ts +91 -0
  1767. package/src/lib/oauth/providers/codebuddy-cn.ts +123 -0
  1768. package/src/lib/oauth/providers/codex.ts +214 -0
  1769. package/src/lib/oauth/providers/cursor.ts +15 -0
  1770. package/src/lib/oauth/providers/github.ts +89 -0
  1771. package/src/lib/oauth/providers/gitlab-duo.ts +124 -0
  1772. package/src/lib/oauth/providers/grok-cli.ts +155 -0
  1773. package/src/lib/oauth/providers/index.ts +59 -0
  1774. package/src/lib/oauth/providers/kilocode.ts +77 -0
  1775. package/src/lib/oauth/providers/kimi-coding.ts +135 -0
  1776. package/src/lib/oauth/providers/kiro.ts +185 -0
  1777. package/src/lib/oauth/providers/qoder.ts +81 -0
  1778. package/src/lib/oauth/providers/qwen.ts +82 -0
  1779. package/src/lib/oauth/providers/trae.ts +78 -0
  1780. package/src/lib/oauth/providers/windsurf.ts +64 -0
  1781. package/src/lib/oauth/providers/zed-hosted.ts +89 -0
  1782. package/src/lib/oauth/providers/zed.ts +35 -0
  1783. package/src/lib/oauth/providers.ts +278 -0
  1784. package/src/lib/oauth/services/codexImport.ts +222 -0
  1785. package/src/lib/oauth/services/cursor.ts +219 -0
  1786. package/src/lib/oauth/services/kiro.ts +441 -0
  1787. package/src/lib/oauth/utils/agyAuthImport.ts +259 -0
  1788. package/src/lib/oauth/utils/banner.ts +62 -0
  1789. package/src/lib/oauth/utils/claudeAuthFile.ts +334 -0
  1790. package/src/lib/oauth/utils/claudeAuthImport.ts +259 -0
  1791. package/src/lib/oauth/utils/claudeAuthZipExtract.ts +5 -0
  1792. package/src/lib/oauth/utils/cliProxyAuthImport.ts +142 -0
  1793. package/src/lib/oauth/utils/codexAuthFile.ts +352 -0
  1794. package/src/lib/oauth/utils/codexAuthImport.ts +294 -0
  1795. package/src/lib/oauth/utils/codexAuthZipExtract.ts +5 -0
  1796. package/src/lib/oauth/utils/jsonZipExtract.ts +89 -0
  1797. package/src/lib/oauth/utils/pkce.ts +37 -0
  1798. package/src/lib/oauth/utils/server.ts +122 -0
  1799. package/src/lib/oauth/utils/ui.ts +47 -0
  1800. package/src/lib/obsidian/api.ts +390 -0
  1801. package/src/lib/obsidianSync.ts +110 -0
  1802. package/src/lib/oneproxyRotator.ts +19 -0
  1803. package/src/lib/oneproxySync.ts +182 -0
  1804. package/src/lib/piiSanitizer.ts +416 -0
  1805. package/src/lib/playground/codeExport.ts +408 -0
  1806. package/src/lib/playground/promptImprover.ts +147 -0
  1807. package/src/lib/playground/streamMetrics.ts +61 -0
  1808. package/src/lib/playground/types.ts +114 -0
  1809. package/src/lib/plugins/devMode.ts +65 -0
  1810. package/src/lib/plugins/doctor.ts +138 -0
  1811. package/src/lib/plugins/errors.ts +38 -0
  1812. package/src/lib/plugins/hooks.ts +322 -0
  1813. package/src/lib/plugins/index.ts +72 -0
  1814. package/src/lib/plugins/loader.ts +326 -0
  1815. package/src/lib/plugins/logger.ts +50 -0
  1816. package/src/lib/plugins/manager.ts +579 -0
  1817. package/src/lib/plugins/manifest.ts +213 -0
  1818. package/src/lib/plugins/marketplace.ts +202 -0
  1819. package/src/lib/plugins/pluginWorker.ts +246 -0
  1820. package/src/lib/plugins/sandbox.ts +29 -0
  1821. package/src/lib/plugins/scanner.ts +110 -0
  1822. package/src/lib/plugins/sdk.ts +88 -0
  1823. package/src/lib/plugins/signing.ts +34 -0
  1824. package/src/lib/plugins/testRunner.ts +95 -0
  1825. package/src/lib/plugins/watcher.ts +90 -0
  1826. package/src/lib/pricingSync.ts +456 -0
  1827. package/src/lib/promptCache/index.ts +1 -0
  1828. package/src/lib/promptCache/prefixAnalyzer.ts +81 -0
  1829. package/src/lib/providerModels/cursorAgent.ts +166 -0
  1830. package/src/lib/providerModels/geminiModelsParser.ts +91 -0
  1831. package/src/lib/providerModels/managedAvailableModels.ts +165 -0
  1832. package/src/lib/providerModels/managedModelImport.ts +349 -0
  1833. package/src/lib/providerModels/modelDiscovery.ts +151 -0
  1834. package/src/lib/providers/catalog.ts +246 -0
  1835. package/src/lib/providers/claudeExtraUsage.ts +160 -0
  1836. package/src/lib/providers/claudeFastMode.ts +75 -0
  1837. package/src/lib/providers/codexConnectionDefaults.ts +85 -0
  1838. package/src/lib/providers/codexFastTier.ts +210 -0
  1839. package/src/lib/providers/imageValidation.ts +160 -0
  1840. package/src/lib/providers/managedAvailableModels.ts +21 -0
  1841. package/src/lib/providers/modelListingCapability.ts +26 -0
  1842. package/src/lib/providers/nvidiaValidationModel.ts +24 -0
  1843. package/src/lib/providers/requestDefaults.ts +318 -0
  1844. package/src/lib/providers/serviceKindIndex.ts +0 -0
  1845. package/src/lib/providers/staticModels.ts +170 -0
  1846. package/src/lib/providers/validation/anthropicFormat.ts +319 -0
  1847. package/src/lib/providers/validation/audioMiscProviders.ts +582 -0
  1848. package/src/lib/providers/validation/cloudProviders.ts +669 -0
  1849. package/src/lib/providers/validation/cozeError.ts +56 -0
  1850. package/src/lib/providers/validation/directChatProbe.ts +47 -0
  1851. package/src/lib/providers/validation/embeddingProviders.ts +143 -0
  1852. package/src/lib/providers/validation/headers.ts +122 -0
  1853. package/src/lib/providers/validation/metaAi.ts +117 -0
  1854. package/src/lib/providers/validation/openaiFormat.ts +500 -0
  1855. package/src/lib/providers/validation/searchProviders.ts +199 -0
  1856. package/src/lib/providers/validation/transport.ts +109 -0
  1857. package/src/lib/providers/validation/urlHelpers.ts +114 -0
  1858. package/src/lib/providers/validation/webProvidersA.ts +808 -0
  1859. package/src/lib/providers/validation/webProvidersB.ts +536 -0
  1860. package/src/lib/providers/validation.ts +772 -0
  1861. package/src/lib/providers/webCookieAuth.ts +157 -0
  1862. package/src/lib/providers/xai/thinking.ts +127 -0
  1863. package/src/lib/providers/xai/translators/claude.ts +368 -0
  1864. package/src/lib/providers/xai/translators/gemini.ts +371 -0
  1865. package/src/lib/providers/xai/translators/openai-chat.ts +310 -0
  1866. package/src/lib/providers/xai/translators/openai-responses.ts +77 -0
  1867. package/src/lib/proxyEgress.ts +388 -0
  1868. package/src/lib/proxyHealth/decision.ts +77 -0
  1869. package/src/lib/proxyHealth/scheduler.ts +207 -0
  1870. package/src/lib/proxyHealth/statusPolicy.ts +41 -0
  1871. package/src/lib/proxyHealth.ts +173 -0
  1872. package/src/lib/proxyLogger.ts +240 -0
  1873. package/src/lib/proxyRelay/cloudflareWorkerScript.ts +107 -0
  1874. package/src/lib/quota/QuotaStore.ts +23 -0
  1875. package/src/lib/quota/accountBuckets.ts +225 -0
  1876. package/src/lib/quota/burnRate.ts +111 -0
  1877. package/src/lib/quota/connectionProvider.ts +32 -0
  1878. package/src/lib/quota/connectionRecovery.ts +303 -0
  1879. package/src/lib/quota/dimensions.ts +61 -0
  1880. package/src/lib/quota/enforce.ts +401 -0
  1881. package/src/lib/quota/fairShare.ts +186 -0
  1882. package/src/lib/quota/planRegistry.ts +107 -0
  1883. package/src/lib/quota/planResolver.ts +78 -0
  1884. package/src/lib/quota/quotaCombos.ts +414 -0
  1885. package/src/lib/quota/quotaKey.ts +202 -0
  1886. package/src/lib/quota/quotaModelNaming.ts +84 -0
  1887. package/src/lib/quota/redisQuotaStore.ts +352 -0
  1888. package/src/lib/quota/saturationSignals.ts +559 -0
  1889. package/src/lib/quota/spendRecorder.ts +131 -0
  1890. package/src/lib/quota/sqliteQuotaStore.ts +282 -0
  1891. package/src/lib/quota/storeFactory.ts +124 -0
  1892. package/src/lib/quota/types.ts +94 -0
  1893. package/src/lib/resilience/modelLockoutSettings.ts +95 -0
  1894. package/src/lib/resilience/settings/normalize.ts +359 -0
  1895. package/src/lib/resilience/settings/types.ts +182 -0
  1896. package/src/lib/resilience/settings.ts +386 -0
  1897. package/src/lib/runtime/ports.ts +32 -0
  1898. package/src/lib/search/executeWebSearch.ts +270 -0
  1899. package/src/lib/security/localEndpoints.ts +82 -0
  1900. package/src/lib/semanticCache.ts +377 -0
  1901. package/src/lib/services/ServiceSupervisor.ts +243 -0
  1902. package/src/lib/services/apiKey.ts +40 -0
  1903. package/src/lib/services/bootstrap.ts +133 -0
  1904. package/src/lib/services/embedPath.ts +19 -0
  1905. package/src/lib/services/embedWsProxy.ts +285 -0
  1906. package/src/lib/services/healthCheck.ts +79 -0
  1907. package/src/lib/services/htmlRewriter.ts +185 -0
  1908. package/src/lib/services/installers/bifrost.ts +145 -0
  1909. package/src/lib/services/installers/cliproxy.ts +116 -0
  1910. package/src/lib/services/installers/mux.ts +178 -0
  1911. package/src/lib/services/installers/ninerouter.stub.ts +17 -0
  1912. package/src/lib/services/installers/ninerouter.ts +157 -0
  1913. package/src/lib/services/installers/utils.ts +167 -0
  1914. package/src/lib/services/modelSync.ts +105 -0
  1915. package/src/lib/services/portProbe.ts +104 -0
  1916. package/src/lib/services/registry.ts +42 -0
  1917. package/src/lib/services/reverseProxy.ts +180 -0
  1918. package/src/lib/services/ringBuffer.ts +91 -0
  1919. package/src/lib/services/types.ts +50 -0
  1920. package/src/lib/settingsCache.ts +62 -0
  1921. package/src/lib/skills/a2a.ts +34 -0
  1922. package/src/lib/skills/builtin/browser.ts +22 -0
  1923. package/src/lib/skills/builtins.ts +493 -0
  1924. package/src/lib/skills/custom.ts +41 -0
  1925. package/src/lib/skills/executor.ts +196 -0
  1926. package/src/lib/skills/githubCollector.ts +426 -0
  1927. package/src/lib/skills/hybrid.ts +67 -0
  1928. package/src/lib/skills/injection.ts +307 -0
  1929. package/src/lib/skills/interception.ts +343 -0
  1930. package/src/lib/skills/providerSettings.ts +14 -0
  1931. package/src/lib/skills/registry.ts +398 -0
  1932. package/src/lib/skills/sandbox.ts +178 -0
  1933. package/src/lib/skills/schemas.ts +43 -0
  1934. package/src/lib/skills/skillssh.ts +73 -0
  1935. package/src/lib/skills/types.ts +61 -0
  1936. package/src/lib/source.ts +7 -0
  1937. package/src/lib/spend/batchWriter.ts +208 -0
  1938. package/src/lib/sseTextTransform.ts +346 -0
  1939. package/src/lib/streamingPiiTransform.ts +350 -0
  1940. package/src/lib/sync/bundle.ts +208 -0
  1941. package/src/lib/sync/tokens.ts +107 -0
  1942. package/src/lib/system/autoUpdate.ts +400 -0
  1943. package/src/lib/system/globalPackagePath.ts +49 -0
  1944. package/src/lib/system/versionCheck.ts +163 -0
  1945. package/src/lib/tailscaleTunnel.ts +1201 -0
  1946. package/src/lib/tokenHealthCheck.ts +829 -0
  1947. package/src/lib/toolPolicy.ts +150 -0
  1948. package/src/lib/translator/streamTransform.ts +27 -0
  1949. package/src/lib/translatorEvents.ts +40 -0
  1950. package/src/lib/usage/aggregateHistory.ts +212 -0
  1951. package/src/lib/usage/apiKeySelfService.ts +420 -0
  1952. package/src/lib/usage/apiKeyUsageLimits.ts +578 -0
  1953. package/src/lib/usage/callLogArtifacts.ts +337 -0
  1954. package/src/lib/usage/callLogs/format.ts +129 -0
  1955. package/src/lib/usage/callLogs.ts +928 -0
  1956. package/src/lib/usage/callLogsBoundedQueries.ts +42 -0
  1957. package/src/lib/usage/codexResetCredits.ts +355 -0
  1958. package/src/lib/usage/comboForecast.ts +441 -0
  1959. package/src/lib/usage/comboHealth.ts +545 -0
  1960. package/src/lib/usage/comboHealthDashboard.ts +109 -0
  1961. package/src/lib/usage/comboScoringInspector.ts +416 -0
  1962. package/src/lib/usage/completedRequestDetails.ts +103 -0
  1963. package/src/lib/usage/costCalculator.ts +279 -0
  1964. package/src/lib/usage/fetcher.ts +483 -0
  1965. package/src/lib/usage/flatRateProviders.ts +59 -0
  1966. package/src/lib/usage/internalUsageCommand.ts +788 -0
  1967. package/src/lib/usage/migrations.ts +471 -0
  1968. package/src/lib/usage/pendingRequestScope.ts +26 -0
  1969. package/src/lib/usage/providerLimits/quotaNormalize.ts +72 -0
  1970. package/src/lib/usage/providerLimits.ts +997 -0
  1971. package/src/lib/usage/providerWindowCosts.ts +571 -0
  1972. package/src/lib/usage/resilienceExplain.ts +468 -0
  1973. package/src/lib/usage/routeExplain.ts +747 -0
  1974. package/src/lib/usage/tokenAccounting.ts +212 -0
  1975. package/src/lib/usage/usageEvents.ts +91 -0
  1976. package/src/lib/usage/usageHistory/helpers.ts +85 -0
  1977. package/src/lib/usage/usageHistory.ts +916 -0
  1978. package/src/lib/usage/usageStats.ts +581 -0
  1979. package/src/lib/usageAnalytics.ts +372 -0
  1980. package/src/lib/usageDb.ts +38 -0
  1981. package/src/lib/versionManager/binaryManager.ts +240 -0
  1982. package/src/lib/versionManager/healthMonitor.ts +71 -0
  1983. package/src/lib/versionManager/index.ts +155 -0
  1984. package/src/lib/versionManager/processManager.ts +155 -0
  1985. package/src/lib/versionManager/releaseChecker.ts +98 -0
  1986. package/src/lib/vscode/familyFirstModelIds.ts +92 -0
  1987. package/src/lib/vscode/modelPresentation.ts +132 -0
  1988. package/src/lib/vscode/reasoningMetadata.ts +183 -0
  1989. package/src/lib/vscode/serviceTierVariants.ts +202 -0
  1990. package/src/lib/vscode/tokenizedRequest.ts +79 -0
  1991. package/src/lib/webhookDispatcher.ts +221 -0
  1992. package/src/lib/webhooks/eventDescriptions.ts +76 -0
  1993. package/src/lib/webhooks/integrations/discord.ts +49 -0
  1994. package/src/lib/webhooks/integrations/slack.ts +45 -0
  1995. package/src/lib/webhooks/integrations/telegram.ts +67 -0
  1996. package/src/lib/ws/handshake.ts +129 -0
  1997. package/src/lib/zed-oauth/confirmedAccounts.ts +38 -0
  1998. package/src/lib/zed-oauth/credentialFingerprint.ts +23 -0
  1999. package/src/lib/zed-oauth/dockerDetect.ts +38 -0
  2000. package/src/lib/zed-oauth/importUtils.ts +46 -0
  2001. package/src/lib/zed-oauth/keychain-reader.stub.ts +28 -0
  2002. package/src/lib/zed-oauth/keychain-reader.ts +231 -0
  2003. package/src/mitm/_internal/bypass.cjs +170 -0
  2004. package/src/mitm/_internal/forwardTarget.cjs +55 -0
  2005. package/src/mitm/_internal/ingest.cjs +82 -0
  2006. package/src/mitm/cert/generate.ts +41 -0
  2007. package/src/mitm/cert/install.stub.ts +23 -0
  2008. package/src/mitm/cert/install.ts +440 -0
  2009. package/src/mitm/dataDir.ts +41 -0
  2010. package/src/mitm/detection/antigravity.ts +33 -0
  2011. package/src/mitm/detection/claudeCode.ts +25 -0
  2012. package/src/mitm/detection/codex.ts +25 -0
  2013. package/src/mitm/detection/copilot.ts +39 -0
  2014. package/src/mitm/detection/cursor.ts +31 -0
  2015. package/src/mitm/detection/index.ts +53 -0
  2016. package/src/mitm/detection/kiro.ts +30 -0
  2017. package/src/mitm/detection/openCode.ts +32 -0
  2018. package/src/mitm/detection/zed.ts +26 -0
  2019. package/src/mitm/dns/dnsConfig.ts +242 -0
  2020. package/src/mitm/dns/provision.ts +92 -0
  2021. package/src/mitm/handlers/antigravity.ts +192 -0
  2022. package/src/mitm/handlers/base.ts +333 -0
  2023. package/src/mitm/handlers/claudeCode.ts +56 -0
  2024. package/src/mitm/handlers/codex.ts +55 -0
  2025. package/src/mitm/handlers/copilot.ts +55 -0
  2026. package/src/mitm/handlers/cursor.ts +55 -0
  2027. package/src/mitm/handlers/kiro.ts +58 -0
  2028. package/src/mitm/handlers/openCode.ts +55 -0
  2029. package/src/mitm/handlers/trae.ts +24 -0
  2030. package/src/mitm/handlers/zed.ts +55 -0
  2031. package/src/mitm/inspector/agentBridgeHook.ts +137 -0
  2032. package/src/mitm/inspector/buffer.ts +201 -0
  2033. package/src/mitm/inspector/contextKey.ts +98 -0
  2034. package/src/mitm/inspector/conversationNormalizer.ts +393 -0
  2035. package/src/mitm/inspector/diagnostics.ts +67 -0
  2036. package/src/mitm/inspector/httpProxyServer.ts +272 -0
  2037. package/src/mitm/inspector/kindDetector.ts +87 -0
  2038. package/src/mitm/inspector/llmMetadataExtractor.ts +183 -0
  2039. package/src/mitm/inspector/pricing.ts +57 -0
  2040. package/src/mitm/inspector/processAttribution.ts +107 -0
  2041. package/src/mitm/inspector/sseMerger.ts +316 -0
  2042. package/src/mitm/inspector/systemProxyConfig.ts +316 -0
  2043. package/src/mitm/inspector/types.ts +112 -0
  2044. package/src/mitm/manager.runtime.ts +5 -0
  2045. package/src/mitm/manager.stub.ts +44 -0
  2046. package/src/mitm/manager.ts +762 -0
  2047. package/src/mitm/maskSecrets.ts +31 -0
  2048. package/src/mitm/passthrough.ts +76 -0
  2049. package/src/mitm/sanitizeHeaders.ts +61 -0
  2050. package/src/mitm/server.cjs +786 -0
  2051. package/src/mitm/socketTimeouts.ts +24 -0
  2052. package/src/mitm/systemCommands.ts +280 -0
  2053. package/src/mitm/targets/antigravity.ts +85 -0
  2054. package/src/mitm/targets/claudeCode.ts +37 -0
  2055. package/src/mitm/targets/codex.ts +30 -0
  2056. package/src/mitm/targets/copilot.ts +32 -0
  2057. package/src/mitm/targets/cursor.ts +33 -0
  2058. package/src/mitm/targets/index.ts +75 -0
  2059. package/src/mitm/targets/kiro.ts +64 -0
  2060. package/src/mitm/targets/openCode.ts +34 -0
  2061. package/src/mitm/targets/trae.ts +32 -0
  2062. package/src/mitm/targets/zed.ts +32 -0
  2063. package/src/mitm/tproxy/caTrust.ts +120 -0
  2064. package/src/mitm/tproxy/captureManager.ts +118 -0
  2065. package/src/mitm/tproxy/captureMode.ts +226 -0
  2066. package/src/mitm/tproxy/commands.ts +122 -0
  2067. package/src/mitm/tproxy/dynamicCert.ts +119 -0
  2068. package/src/mitm/tproxy/native/README.md +55 -0
  2069. package/src/mitm/tproxy/native/binding.gyp +9 -0
  2070. package/src/mitm/tproxy/native/transparent.c +147 -0
  2071. package/src/mitm/tproxy/setup.ts +68 -0
  2072. package/src/mitm/tproxy/tlsCapture.ts +368 -0
  2073. package/src/mitm/tproxy/transparentSocket.ts +131 -0
  2074. package/src/mitm/types.ts +75 -0
  2075. package/src/mitm/upstreamTrust.ts +40 -0
  2076. package/src/models/index.ts +29 -0
  2077. package/src/server/auth/loginGuard.ts +130 -0
  2078. package/src/server/authz/accessScopes.ts +62 -0
  2079. package/src/server/authz/accessTokenAuth.ts +67 -0
  2080. package/src/server/authz/assertAuth.ts +88 -0
  2081. package/src/server/authz/classify.ts +135 -0
  2082. package/src/server/authz/context.ts +44 -0
  2083. package/src/server/authz/csrf.ts +85 -0
  2084. package/src/server/authz/headers.ts +76 -0
  2085. package/src/server/authz/peerStamp.ts +99 -0
  2086. package/src/server/authz/pipeline.ts +370 -0
  2087. package/src/server/authz/policies/clientApi.ts +72 -0
  2088. package/src/server/authz/policies/management.ts +298 -0
  2089. package/src/server/authz/policies/public.ts +9 -0
  2090. package/src/server/authz/routeGuard.ts +233 -0
  2091. package/src/server/authz/types.ts +77 -0
  2092. package/src/server/cors/origins.ts +172 -0
  2093. package/src/server/origin/publicOrigin.ts +270 -0
  2094. package/src/server/ws/liveServer.ts +630 -0
  2095. package/src/server/ws/liveServerAllowList.ts +106 -0
  2096. package/src/server/ws/types.ts +57 -0
  2097. package/src/shared/components/Avatar.tsx +81 -0
  2098. package/src/shared/components/Badge.tsx +68 -0
  2099. package/src/shared/components/Breadcrumbs.tsx +103 -0
  2100. package/src/shared/components/Button.tsx +85 -0
  2101. package/src/shared/components/Card.tsx +141 -0
  2102. package/src/shared/components/Checkbox.tsx +38 -0
  2103. package/src/shared/components/CloudSyncStatus.tsx +104 -0
  2104. package/src/shared/components/Collapsible.tsx +93 -0
  2105. package/src/shared/components/CollapsibleSection.tsx +66 -0
  2106. package/src/shared/components/ColumnToggle.tsx +100 -0
  2107. package/src/shared/components/CommandPalette.tsx +375 -0
  2108. package/src/shared/components/ConsoleLogViewer.tsx +326 -0
  2109. package/src/shared/components/CursorAuthModal.tsx +198 -0
  2110. package/src/shared/components/DataTable.tsx +195 -0
  2111. package/src/shared/components/DegradationBadge.tsx +41 -0
  2112. package/src/shared/components/DistributeProxiesButton.tsx +74 -0
  2113. package/src/shared/components/EmptyState.tsx +121 -0
  2114. package/src/shared/components/ErrorPageScaffold.tsx +91 -0
  2115. package/src/shared/components/FilterBar.tsx +197 -0
  2116. package/src/shared/components/Footer.tsx +169 -0
  2117. package/src/shared/components/Header.tsx +284 -0
  2118. package/src/shared/components/InfoTooltip.tsx +34 -0
  2119. package/src/shared/components/Input.tsx +155 -0
  2120. package/src/shared/components/KiroAuthModal.tsx +425 -0
  2121. package/src/shared/components/KiroOAuthWrapper.tsx +116 -0
  2122. package/src/shared/components/KiroSocialOAuthModal.tsx +202 -0
  2123. package/src/shared/components/LanguageSelector.tsx +106 -0
  2124. package/src/shared/components/LinkifiedText.tsx +30 -0
  2125. package/src/shared/components/Loading.tsx +128 -0
  2126. package/src/shared/components/LocaleAutoDetect.tsx +43 -0
  2127. package/src/shared/components/MaintenanceBanner.tsx +87 -0
  2128. package/src/shared/components/ManualConfigModal.tsx +51 -0
  2129. package/src/shared/components/Modal.tsx +240 -0
  2130. package/src/shared/components/ModelRoutingSection.tsx +323 -0
  2131. package/src/shared/components/ModelSelectModal.tsx +618 -0
  2132. package/src/shared/components/MonacoEditor.tsx +23 -0
  2133. package/src/shared/components/NavigationProgress.tsx +105 -0
  2134. package/src/shared/components/NoAuthAccountCard.tsx +539 -0
  2135. package/src/shared/components/NoAuthProviderCard.tsx +40 -0
  2136. package/src/shared/components/NoAuthProviderToggle.tsx +36 -0
  2137. package/src/shared/components/NotificationToast.tsx +206 -0
  2138. package/src/shared/components/OAuthModal.tsx +992 -0
  2139. package/src/shared/components/OmniRouteLogo.tsx +86 -0
  2140. package/src/shared/components/PresetSlider.tsx +64 -0
  2141. package/src/shared/components/PricingModal.tsx +211 -0
  2142. package/src/shared/components/ProviderIcon.tsx +263 -0
  2143. package/src/shared/components/ProviderTestSlideOver.tsx +560 -0
  2144. package/src/shared/components/ProxyConfigModal.tsx +781 -0
  2145. package/src/shared/components/ProxyLogDetail.tsx +192 -0
  2146. package/src/shared/components/ProxyLogger.tsx +573 -0
  2147. package/src/shared/components/PwaRegister.tsx +22 -0
  2148. package/src/shared/components/RequestLoggerDetail.tsx +797 -0
  2149. package/src/shared/components/RequestLoggerV2.tsx +1628 -0
  2150. package/src/shared/components/RiskNoticeModal.tsx +81 -0
  2151. package/src/shared/components/SegmentedControl.tsx +69 -0
  2152. package/src/shared/components/Select.tsx +110 -0
  2153. package/src/shared/components/Sidebar.tsx +726 -0
  2154. package/src/shared/components/SkillsConceptCard.tsx +84 -0
  2155. package/src/shared/components/SystemMonitor.tsx +179 -0
  2156. package/src/shared/components/Textarea.tsx +29 -0
  2157. package/src/shared/components/ThemeProvider.tsx +14 -0
  2158. package/src/shared/components/ThemeToggle.tsx +52 -0
  2159. package/src/shared/components/Toggle.tsx +102 -0
  2160. package/src/shared/components/TokenHealthBadge.tsx +113 -0
  2161. package/src/shared/components/Tooltip.tsx +193 -0
  2162. package/src/shared/components/TraeAuthModal.tsx +334 -0
  2163. package/src/shared/components/UsageAnalytics.tsx +414 -0
  2164. package/src/shared/components/UsageStats.tsx +693 -0
  2165. package/src/shared/components/analytics/ApiKeyFilterDropdown.tsx +205 -0
  2166. package/src/shared/components/analytics/CustomRangePicker.tsx +195 -0
  2167. package/src/shared/components/analytics/TimeRangeSelector.tsx +49 -0
  2168. package/src/shared/components/analytics/chartColors.ts +12 -0
  2169. package/src/shared/components/analytics/charts.tsx +1023 -0
  2170. package/src/shared/components/analytics/index.tsx +28 -0
  2171. package/src/shared/components/analytics/rechartsCore.tsx +85 -0
  2172. package/src/shared/components/analytics/rechartsDonuts.tsx +195 -0
  2173. package/src/shared/components/analytics/rechartsUsageCharts.tsx +312 -0
  2174. package/src/shared/components/cli/CliComparisonCard.tsx +82 -0
  2175. package/src/shared/components/cli/CliConceptCard.tsx +58 -0
  2176. package/src/shared/components/cli/CliToolCard.tsx +152 -0
  2177. package/src/shared/components/cli/index.ts +8 -0
  2178. package/src/shared/components/compression/CompressionPipelineEditor.tsx +175 -0
  2179. package/src/shared/components/compression/EngineConfigForm.tsx +78 -0
  2180. package/src/shared/components/compression/EngineConfigPage.tsx +411 -0
  2181. package/src/shared/components/compression/compressionPipelineModel.ts +78 -0
  2182. package/src/shared/components/docs/APIReference.stories.tsx +35 -0
  2183. package/src/shared/components/docs/APIReference.tsx +83 -0
  2184. package/src/shared/components/docs/Callout.stories.tsx +40 -0
  2185. package/src/shared/components/docs/Callout.tsx +38 -0
  2186. package/src/shared/components/docs/CodeBlock.stories.tsx +25 -0
  2187. package/src/shared/components/docs/CodeBlock.tsx +52 -0
  2188. package/src/shared/components/docs/DocsBreadcrumbs.stories.tsx +20 -0
  2189. package/src/shared/components/docs/DocsBreadcrumbs.tsx +46 -0
  2190. package/src/shared/components/docs/DocsSidebar.stories.tsx +31 -0
  2191. package/src/shared/components/docs/DocsSidebar.tsx +77 -0
  2192. package/src/shared/components/docs/DocsThemeProvider.tsx +21 -0
  2193. package/src/shared/components/docs/Tabs.stories.tsx +26 -0
  2194. package/src/shared/components/docs/Tabs.tsx +50 -0
  2195. package/src/shared/components/docs/tokens.ts +38 -0
  2196. package/src/shared/components/flow/FlowCanvas.tsx +151 -0
  2197. package/src/shared/components/flow/StatusDot.tsx +36 -0
  2198. package/src/shared/components/flow/edgeStyles.ts +32 -0
  2199. package/src/shared/components/index.tsx +49 -0
  2200. package/src/shared/components/layouts/AuthLayout.tsx +28 -0
  2201. package/src/shared/components/layouts/DashboardLayout.tsx +131 -0
  2202. package/src/shared/components/layouts/index.tsx +3 -0
  2203. package/src/shared/components/lobeProviderIcons.ts +488 -0
  2204. package/src/shared/components/logTableStyles.ts +7 -0
  2205. package/src/shared/components/modelSelectModalHelpers.ts +75 -0
  2206. package/src/shared/components/oauthBlobSubmit.ts +42 -0
  2207. package/src/shared/components/proxyAssignment.ts +40 -0
  2208. package/src/shared/components/requestLoggerPreferences.ts +44 -0
  2209. package/src/shared/components/requestLoggerSignature.ts +56 -0
  2210. package/src/shared/constants/agentSkills.ts +457 -0
  2211. package/src/shared/constants/antigravityClientProfile.ts +29 -0
  2212. package/src/shared/constants/apiKeyPolicyScopes.ts +5 -0
  2213. package/src/shared/constants/appConfig.ts +12 -0
  2214. package/src/shared/constants/batch.ts +1 -0
  2215. package/src/shared/constants/batchEndpoints.ts +11 -0
  2216. package/src/shared/constants/bodySize.ts +39 -0
  2217. package/src/shared/constants/cliCompatProviders.ts +88 -0
  2218. package/src/shared/constants/cliTools.ts +862 -0
  2219. package/src/shared/constants/clientIdentityProfiles.ts +89 -0
  2220. package/src/shared/constants/colors.ts +147 -0
  2221. package/src/shared/constants/comboConfigMode.ts +9 -0
  2222. package/src/shared/constants/config.ts +44 -0
  2223. package/src/shared/constants/dashboardCsrf.ts +1 -0
  2224. package/src/shared/constants/endpointCategories.ts +133 -0
  2225. package/src/shared/constants/errorCodes.ts +245 -0
  2226. package/src/shared/constants/featureFlagDefinitions.ts +495 -0
  2227. package/src/shared/constants/headers.ts +16 -0
  2228. package/src/shared/constants/homeWidgets.ts +5 -0
  2229. package/src/shared/constants/index.ts +4 -0
  2230. package/src/shared/constants/managementScopes.ts +31 -0
  2231. package/src/shared/constants/mcpScopes.ts +78 -0
  2232. package/src/shared/constants/mitmToolHosts.ts +31 -0
  2233. package/src/shared/constants/modal.ts +5 -0
  2234. package/src/shared/constants/modelCompat.ts +9 -0
  2235. package/src/shared/constants/modelSpecs.ts +607 -0
  2236. package/src/shared/constants/models.ts +40 -0
  2237. package/src/shared/constants/openRouterPreset.ts +11 -0
  2238. package/src/shared/constants/pricing/default-pricing.ts +16 -0
  2239. package/src/shared/constants/pricing/frontier-labs.ts +386 -0
  2240. package/src/shared/constants/pricing/inference-hosts.ts +208 -0
  2241. package/src/shared/constants/pricing/oauth-subscriptions.ts +599 -0
  2242. package/src/shared/constants/pricing/regional.ts +168 -0
  2243. package/src/shared/constants/pricing/shared-tiers.ts +162 -0
  2244. package/src/shared/constants/pricing.ts +40 -0
  2245. package/src/shared/constants/providers/apikey/enterprise-cloud.ts +214 -0
  2246. package/src/shared/constants/providers/apikey/frontier-labs.ts +253 -0
  2247. package/src/shared/constants/providers/apikey/gateways.ts +662 -0
  2248. package/src/shared/constants/providers/apikey/index.ts +21 -0
  2249. package/src/shared/constants/providers/apikey/inference-hosts.ts +328 -0
  2250. package/src/shared/constants/providers/apikey/regional.ts +372 -0
  2251. package/src/shared/constants/providers/apikey/specialty-media.ts +266 -0
  2252. package/src/shared/constants/providers/audio.ts +71 -0
  2253. package/src/shared/constants/providers/cloud-agent.ts +36 -0
  2254. package/src/shared/constants/providers/local.ts +162 -0
  2255. package/src/shared/constants/providers/noauth.ts +123 -0
  2256. package/src/shared/constants/providers/oauth.ts +231 -0
  2257. package/src/shared/constants/providers/search.ts +125 -0
  2258. package/src/shared/constants/providers/system.ts +16 -0
  2259. package/src/shared/constants/providers/upstream-proxy.ts +36 -0
  2260. package/src/shared/constants/providers/web-cookie.ts +364 -0
  2261. package/src/shared/constants/providers.ts +449 -0
  2262. package/src/shared/constants/publicApiRoutes.ts +62 -0
  2263. package/src/shared/constants/responsesPreviousResponseId.ts +5 -0
  2264. package/src/shared/constants/routingStrategies.ts +216 -0
  2265. package/src/shared/constants/selfServiceScopes.ts +20 -0
  2266. package/src/shared/constants/serviceKinds.ts +34 -0
  2267. package/src/shared/constants/sidebarGroupVisibility.ts +31 -0
  2268. package/src/shared/constants/sidebarVisibility/sections.ts +769 -0
  2269. package/src/shared/constants/sidebarVisibility/types.ts +161 -0
  2270. package/src/shared/constants/sidebarVisibility.ts +291 -0
  2271. package/src/shared/constants/spawnCapablePrefixes.ts +35 -0
  2272. package/src/shared/constants/statusColors.ts +17 -0
  2273. package/src/shared/constants/upstreamHeaders.ts +42 -0
  2274. package/src/shared/constants/visionBridgeDefaults.ts +88 -0
  2275. package/src/shared/constants/visionModels.ts +68 -0
  2276. package/src/shared/contracts/quota.ts +138 -0
  2277. package/src/shared/hooks/cli/useToolBatchStatuses.ts +54 -0
  2278. package/src/shared/hooks/index.ts +3 -0
  2279. package/src/shared/hooks/useCopyToClipboard.ts +38 -0
  2280. package/src/shared/hooks/useDisplayBaseUrl.ts +49 -0
  2281. package/src/shared/hooks/useElectron.ts +197 -0
  2282. package/src/shared/hooks/useTheme.ts +59 -0
  2283. package/src/shared/http/apiErrorMessage.ts +19 -0
  2284. package/src/shared/lib/persistLocale.ts +19 -0
  2285. package/src/shared/middleware/bodySizeGuard.ts +97 -0
  2286. package/src/shared/middleware/chatBodyAdmission.ts +161 -0
  2287. package/src/shared/middleware/correlationId.ts +43 -0
  2288. package/src/shared/network/outboundUrlGuard.ts +276 -0
  2289. package/src/shared/network/remoteImageFetch.ts +182 -0
  2290. package/src/shared/network/safeOutboundFetch.ts +372 -0
  2291. package/src/shared/providers/webSessionCredentials.ts +308 -0
  2292. package/src/shared/reasoning/effortStandardization.ts +124 -0
  2293. package/src/shared/schemas/agentBridge.ts +37 -0
  2294. package/src/shared/schemas/cliCatalog.ts +66 -0
  2295. package/src/shared/schemas/inspector.ts +47 -0
  2296. package/src/shared/schemas/memory.ts +142 -0
  2297. package/src/shared/schemas/playground.ts +67 -0
  2298. package/src/shared/schemas/qdrant.ts +39 -0
  2299. package/src/shared/schemas/quota.ts +61 -0
  2300. package/src/shared/schemas/searchTools.ts +39 -0
  2301. package/src/shared/schemas/validation.ts +154 -0
  2302. package/src/shared/services/apiKeyResolver.ts +44 -0
  2303. package/src/shared/services/backupService.ts +233 -0
  2304. package/src/shared/services/claudeCliConfig.ts +17 -0
  2305. package/src/shared/services/cliRuntime.ts +1099 -0
  2306. package/src/shared/services/cloudSyncScheduler.ts +135 -0
  2307. package/src/shared/services/droidCustomModels.ts +118 -0
  2308. package/src/shared/services/initializeCloudSync.ts +31 -0
  2309. package/src/shared/services/loginShellPath.ts +87 -0
  2310. package/src/shared/services/modelSyncScheduler.ts +225 -0
  2311. package/src/shared/services/opencodeConfig.ts +140 -0
  2312. package/src/shared/services/providerLimitsSyncScheduler.ts +72 -0
  2313. package/src/shared/types/cliBatchStatus.ts +18 -0
  2314. package/src/shared/types/index.ts +3 -0
  2315. package/src/shared/types/pagination.ts +61 -0
  2316. package/src/shared/types/utilization.ts +405 -0
  2317. package/src/shared/utils/a11yAudit.ts +140 -0
  2318. package/src/shared/utils/api.ts +112 -0
  2319. package/src/shared/utils/apiAuth.ts +354 -0
  2320. package/src/shared/utils/apiKey.ts +92 -0
  2321. package/src/shared/utils/apiKeyPolicy.ts +680 -0
  2322. package/src/shared/utils/apiResponse.ts +79 -0
  2323. package/src/shared/utils/bulkApiKeyParser.ts +113 -0
  2324. package/src/shared/utils/circuitBreaker.ts +611 -0
  2325. package/src/shared/utils/classify429.ts +253 -0
  2326. package/src/shared/utils/cliCompat.ts +5 -0
  2327. package/src/shared/utils/clineAuth.ts +62 -0
  2328. package/src/shared/utils/clipboard.ts +49 -0
  2329. package/src/shared/utils/cloud.ts +41 -0
  2330. package/src/shared/utils/cn.ts +12 -0
  2331. package/src/shared/utils/codexBaseUrl.ts +32 -0
  2332. package/src/shared/utils/codexConfig.ts +30 -0
  2333. package/src/shared/utils/compressionHeaderEcho.ts +59 -0
  2334. package/src/shared/utils/cors.ts +24 -0
  2335. package/src/shared/utils/costEstimator.ts +126 -0
  2336. package/src/shared/utils/dashboardCsrf.ts +196 -0
  2337. package/src/shared/utils/featureFlags.ts +113 -0
  2338. package/src/shared/utils/fetchError.ts +26 -0
  2339. package/src/shared/utils/fetchTimeout.ts +78 -0
  2340. package/src/shared/utils/formatting.ts +183 -0
  2341. package/src/shared/utils/freeModels.ts +112 -0
  2342. package/src/shared/utils/index.ts +39 -0
  2343. package/src/shared/utils/inputSanitizer.ts +339 -0
  2344. package/src/shared/utils/linkify.ts +54 -0
  2345. package/src/shared/utils/logRedaction.ts +108 -0
  2346. package/src/shared/utils/logger.ts +173 -0
  2347. package/src/shared/utils/machine.ts +5 -0
  2348. package/src/shared/utils/machineId.ts +167 -0
  2349. package/src/shared/utils/maskEmail.ts +77 -0
  2350. package/src/shared/utils/modelCatalogSearch.ts +84 -0
  2351. package/src/shared/utils/noAuthProviders.ts +79 -0
  2352. package/src/shared/utils/nodeRuntimeSupport.ts +112 -0
  2353. package/src/shared/utils/parseApiKeys.ts +41 -0
  2354. package/src/shared/utils/providerDisplayLabel.ts +41 -0
  2355. package/src/shared/utils/providerHints.ts +73 -0
  2356. package/src/shared/utils/providerModelAliases.ts +68 -0
  2357. package/src/shared/utils/rateLimiter.ts +243 -0
  2358. package/src/shared/utils/releaseNotes.ts +53 -0
  2359. package/src/shared/utils/requestId.ts +102 -0
  2360. package/src/shared/utils/requestTelemetry.ts +189 -0
  2361. package/src/shared/utils/requestTimeout.ts +64 -0
  2362. package/src/shared/utils/resolveOmniRouteBaseUrl.ts +24 -0
  2363. package/src/shared/utils/runtimeTimeouts.ts +257 -0
  2364. package/src/shared/utils/secretsValidator.ts +135 -0
  2365. package/src/shared/utils/secureRandom.ts +66 -0
  2366. package/src/shared/utils/serviceTierLabels.ts +42 -0
  2367. package/src/shared/utils/shuffleDeck.ts +147 -0
  2368. package/src/shared/utils/sidebarRouteMatch.ts +43 -0
  2369. package/src/shared/utils/streamTracker.ts +187 -0
  2370. package/src/shared/utils/structuredLogger.ts +219 -0
  2371. package/src/shared/utils/tiktokenCounter.ts +21 -0
  2372. package/src/shared/utils/turkishText.ts +66 -0
  2373. package/src/shared/utils/upstreamError.ts +112 -0
  2374. package/src/shared/validation/compressionConfigSchemas.ts +234 -0
  2375. package/src/shared/validation/freeProxySchemas.ts +111 -0
  2376. package/src/shared/validation/helpers.ts +117 -0
  2377. package/src/shared/validation/oneproxySchemas.ts +14 -0
  2378. package/src/shared/validation/providerSchema.ts +51 -0
  2379. package/src/shared/validation/providerSpecificData.ts +354 -0
  2380. package/src/shared/validation/schemas/apiV1.ts +297 -0
  2381. package/src/shared/validation/schemas/auth.ts +200 -0
  2382. package/src/shared/validation/schemas/cli.ts +86 -0
  2383. package/src/shared/validation/schemas/cloud.ts +53 -0
  2384. package/src/shared/validation/schemas/combo.ts +373 -0
  2385. package/src/shared/validation/schemas/evals.ts +86 -0
  2386. package/src/shared/validation/schemas/gemini.ts +59 -0
  2387. package/src/shared/validation/schemas/keys.ts +144 -0
  2388. package/src/shared/validation/schemas/misc.ts +203 -0
  2389. package/src/shared/validation/schemas/payloadRules.ts +64 -0
  2390. package/src/shared/validation/schemas/pricing.ts +40 -0
  2391. package/src/shared/validation/schemas/provider.ts +430 -0
  2392. package/src/shared/validation/schemas/proxy.ts +243 -0
  2393. package/src/shared/validation/schemas/routing.ts +88 -0
  2394. package/src/shared/validation/schemas/settings.ts +267 -0
  2395. package/src/shared/validation/schemas/translator.ts +44 -0
  2396. package/src/shared/validation/schemas.ts +18 -0
  2397. package/src/shared/validation/settingsSchemas.ts +396 -0
  2398. package/src/sse/handlers/chat.ts +1750 -0
  2399. package/src/sse/handlers/chatHelpers.ts +859 -0
  2400. package/src/sse/handlers/requestBody.ts +24 -0
  2401. package/src/sse/handlers/resolveRoutingModel.ts +17 -0
  2402. package/src/sse/services/auth.ts +2446 -0
  2403. package/src/sse/services/cooldownAwareRetry.ts +162 -0
  2404. package/src/sse/services/model.ts +254 -0
  2405. package/src/sse/services/noAuthProviderSettings.ts +18 -0
  2406. package/src/sse/services/noAuthProxyResolution.ts +111 -0
  2407. package/src/sse/services/sessionAffinityPin.ts +247 -0
  2408. package/src/sse/services/streamState.ts +218 -0
  2409. package/src/sse/services/tokenRefresh.ts +275 -0
  2410. package/src/sse/utils/logger.ts +37 -0
  2411. package/src/types/databaseSettings.ts +124 -0
  2412. package/src/types/global.d.ts +122 -0
  2413. package/src/types/index.ts +10 -0
  2414. package/src/types/provider.ts +9 -0
  2415. package/src/types/sqljs.d.ts +32 -0
@@ -0,0 +1,3107 @@
1
+ /**
2
+ * ChatGptWebExecutor — ChatGPT Web Session Provider
3
+ *
4
+ * Routes requests through chatgpt.com's internal SSE API using a Plus/Pro
5
+ * subscription session cookie, translating between OpenAI chat completions
6
+ * format and ChatGPT's internal protocol.
7
+ *
8
+ * Auth pipeline (per request):
9
+ * 1. exchangeSession() GET /api/auth/session cookie → JWT accessToken (cached ~5min)
10
+ * 2. prepareChatRequirements() POST /backend-api/sentinel/chat-requirements
11
+ * → { proofofwork.seed, difficulty, persona }
12
+ * 3. solveProofOfWork() SHA3-512 hash loop → "gAAAAAB…" sentinel proof token
13
+ * 4. fetch /backend-api/conversation with Bearer + sentinel-proof-token + browser UA
14
+ *
15
+ * Response is the standard ChatGPT SSE format (cumulative `parts[0]` strings, not deltas).
16
+ */
17
+
18
+ import { BaseExecutor, type ExecuteInput, type ProviderCredentials } from "./base.ts";
19
+ import { describeChatGptWebHttpError } from "./chatgptWebErrors.ts";
20
+ import { prepareToolMessages } from "../translator/webTools.ts";
21
+ import { buildToolModeResponse } from "./chatgptWebTools.ts";
22
+ import { createHash, randomUUID, randomBytes } from "node:crypto";
23
+ import { sha3_512Hex } from "../utils/sha3-512.ts";
24
+ import {
25
+ tlsFetchChatGpt,
26
+ TlsClientUnavailableError,
27
+ type TlsFetchResult,
28
+ } from "../services/chatgptTlsClient.ts";
29
+ import {
30
+ storeChatGptImage,
31
+ getChatGptImageConversationContext,
32
+ __resetChatGptImageCacheForTesting,
33
+ type ChatGptImageConversationContext,
34
+ } from "../services/chatgptImageCache.ts";
35
+ import { isThinkingCapableModel, resolveChatGptModel } from "./chatgpt-web/models.ts";
36
+
37
+ // ─── Constants ──────────────────────────────────────────────────────────────
38
+
39
+ const CHATGPT_BASE = "https://chatgpt.com";
40
+ const SESSION_URL = `${CHATGPT_BASE}/api/auth/session`;
41
+ const SENTINEL_PREPARE_URL = `${CHATGPT_BASE}/backend-api/sentinel/chat-requirements/prepare`;
42
+ const SENTINEL_CR_URL = `${CHATGPT_BASE}/backend-api/sentinel/chat-requirements`;
43
+ const CONV_URL = `${CHATGPT_BASE}/backend-api/f/conversation`;
44
+ const USER_LAST_USED_MODEL_CONFIG_URL = `${CHATGPT_BASE}/backend-api/settings/user_last_used_model_config`;
45
+
46
+ const DEFAULT_PRO_POLL_TIMEOUT_MS = 20 * 60_000;
47
+ const DEFAULT_PRO_POLL_INTERVAL_MS = 4_000;
48
+
49
+ const CHATGPT_USER_AGENT =
50
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:152.0) Gecko/20100101 Firefox/152.0";
51
+
52
+ // Captured from a real chatgpt.com browser session (April 2026).
53
+ const OAI_CLIENT_VERSION = "prod-81e0c5cdf6140e8c5db714d613337f4aeab94029";
54
+ const OAI_CLIENT_BUILD_NUMBER = "6128297";
55
+
56
+ // Per-cookie device ID. The browser stores a persistent `oai-did` cookie that
57
+ // uniquely identifies the device for OpenAI's risk model — we derive a stable
58
+ // UUID from a hash of the session cookie so that each account/connection gets
59
+ // its own device id, but it doesn't change between requests.
60
+ const deviceIdCache = new Map<string, string>();
61
+ function deviceIdFor(cookie: string): string {
62
+ const key = cookieKey(cookie);
63
+ let id = deviceIdCache.get(key);
64
+ if (!id) {
65
+ // Synthesize a UUID v4-shaped string from a SHA-256 of the cookie. Stable,
66
+ // deterministic per cookie, no PII (the cookie's already secret).
67
+ // Not a password hash — SHA-256 is used to derive a stable UUID from the
68
+ // session cookie for device-id fingerprinting. The output is a cache key.
69
+ const h = createHash("sha256").update(cookie).digest("hex"); // lgtm[js/insufficient-password-hash]
70
+ id =
71
+ `${h.slice(0, 8)}-${h.slice(8, 12)}-4${h.slice(13, 16)}-` +
72
+ `${((parseInt(h.slice(16, 17), 16) & 0x3) | 0x8).toString(16)}${h.slice(17, 20)}-` +
73
+ h.slice(20, 32);
74
+ if (deviceIdCache.size >= 200) {
75
+ const first = deviceIdCache.keys().next().value;
76
+ if (first) deviceIdCache.delete(first);
77
+ }
78
+ deviceIdCache.set(key, id);
79
+ }
80
+ return id;
81
+ }
82
+
83
+ // OmniRoute model ID → ChatGPT internal slug. The public ChatGPT Web catalog
84
+ // keeps OmniRoute's historical dot-form IDs (e.g. "gpt-5.5-pro"), while
85
+ // ChatGPT's backend routes use dash-form slugs (e.g. "gpt-5-5-pro"). The slug
86
+ // catalog comes from /backend-api/models on a logged-in account;
87
+ // "gpt-5-4-t-mini" is ChatGPT's abbreviated slug for "GPT-5.4 Thinking Mini".
88
+
89
+ // ─── Browser-like default headers ──────────────────────────────────────────
90
+
91
+ function browserHeaders(): Record<string, string> {
92
+ return {
93
+ Accept: "*/*",
94
+ "Accept-Language": "en-US,en;q=0.9",
95
+ "Cache-Control": "no-cache",
96
+ Origin: CHATGPT_BASE,
97
+ Pragma: "no-cache",
98
+ Referer: `${CHATGPT_BASE}/`,
99
+ "Sec-Fetch-Dest": "empty",
100
+ "Sec-Fetch-Mode": "cors",
101
+ "Sec-Fetch-Site": "same-origin",
102
+ "User-Agent": CHATGPT_USER_AGENT,
103
+ };
104
+ }
105
+
106
+ /** Headers ChatGPT's web client sends on backend-api requests. */
107
+ function oaiHeaders(sessionId: string, deviceId: string): Record<string, string> {
108
+ return {
109
+ "OAI-Language": "en-US",
110
+ "OAI-Device-Id": deviceId,
111
+ "OAI-Client-Version": OAI_CLIENT_VERSION,
112
+ "OAI-Client-Build-Number": OAI_CLIENT_BUILD_NUMBER,
113
+ "OAI-Session-Id": sessionId,
114
+ };
115
+ }
116
+
117
+ // ─── Session token cache ────────────────────────────────────────────────────
118
+
119
+ interface TokenEntry {
120
+ accessToken: string;
121
+ accountId: string | null;
122
+ expiresAt: number;
123
+ refreshedCookie?: string;
124
+ }
125
+
126
+ const TOKEN_TTL_MS = 5 * 60 * 1000; // 5min — accessTokens are short-lived
127
+ const tokenCache = new Map<string, TokenEntry>();
128
+
129
+ function cookieKey(cookie: string): string {
130
+ // SHA-256 prefix (64 bits). Used as the Map key for tokenCache and
131
+ // warmupCache; the previous 32-bit FNV-1a was small enough that a
132
+ // birthday-paradox collision could surface one user's cached accessToken
133
+ // to another's request. 64 bits is overkill for the 200-entry cache but
134
+ // costs essentially nothing.
135
+ // Not a password hash — SHA-256 is used to derive a short, collision-resistant
136
+ // cache key from the session cookie. The output is a map lookup key.
137
+ return createHash("sha256").update(cookie).digest("hex").slice(0, 16); // lgtm[js/insufficient-password-hash]
138
+ }
139
+
140
+ function tokenLookup(cookie: string): TokenEntry | null {
141
+ const entry = tokenCache.get(cookieKey(cookie));
142
+ if (!entry) return null;
143
+ if (Date.now() >= entry.expiresAt) {
144
+ tokenCache.delete(cookieKey(cookie));
145
+ return null;
146
+ }
147
+ return entry;
148
+ }
149
+
150
+ const TOKEN_CACHE_MAX = 200;
151
+
152
+ function tokenStore(cookie: string, entry: TokenEntry): void {
153
+ // Bound the cache to TOKEN_CACHE_MAX entries (FIFO). Same shape as the
154
+ // image cache and warmup cache — drop the oldest before inserting.
155
+ if (tokenCache.size >= TOKEN_CACHE_MAX && !tokenCache.has(cookieKey(cookie))) {
156
+ const firstKey = tokenCache.keys().next().value;
157
+ if (firstKey) tokenCache.delete(firstKey);
158
+ }
159
+ tokenCache.set(cookieKey(cookie), entry);
160
+ }
161
+
162
+ // Conversation continuity is intentionally not cached. Open WebUI and most
163
+ // OpenAI-API-style clients re-send the full history each turn, so each
164
+ // request just starts a fresh conversation. Temporary Chat mode is the
165
+ // default; it gets disabled per-request only for image-gen prompts, since
166
+ // that mode rejects the image_gen tool.
167
+
168
+ // ─── /api/auth/session — exchange cookie for JWT ────────────────────────────
169
+
170
+ interface SessionResponse {
171
+ accessToken?: string;
172
+ expires?: string;
173
+ user?: { id?: string };
174
+ }
175
+
176
+ // Session-token family — NextAuth uses one of these depending on token size:
177
+ // __Secure-next-auth.session-token (unchunked, < 4KB)
178
+ // __Secure-next-auth.session-token.0 (chunked, first piece)
179
+ // __Secure-next-auth.session-token.N (chunked, additional pieces)
180
+ // Rotation can change the shape (unchunked → chunked or vice versa). When
181
+ // that happens, every old family member must be dropped — keeping the stale
182
+ // variant alongside the new one would send both, and depending on parser
183
+ // precedence the server could read the stale value and fail auth.
184
+ const SESSION_TOKEN_FAMILY_RE = /^__Secure-next-auth\.session-token(?:\.\d+)?$/;
185
+
186
+ /**
187
+ * Merge any rotated session-token chunks from a Set-Cookie response into the
188
+ * original cookie blob, preserving every other cookie the caller pasted
189
+ * (cf_clearance, __cf_bm, _cfuvid, _puid, ...). Returns null if no rotation
190
+ * occurred or the rotated chunks match what's already there.
191
+ *
192
+ * Returning only the matched session-token chunks here was a bug: when the
193
+ * caller pastes a full DevTools Cookie line (the recommended form), the
194
+ * Cloudflare cookies are required for subsequent requests, and dropping
195
+ * them re-triggers `cf-mitigated: challenge`.
196
+ */
197
+ function mergeRefreshedCookie(
198
+ originalCookie: string,
199
+ setCookieHeader: string | null
200
+ ): string | null {
201
+ if (!setCookieHeader) return null;
202
+ const matches = Array.from(
203
+ setCookieHeader.matchAll(/(__Secure-next-auth\.session-token(?:\.\d+)?)=([^;,\s]+)/g)
204
+ );
205
+ if (matches.length === 0) return null;
206
+
207
+ const refreshed = new Map<string, string>();
208
+ for (const m of matches) refreshed.set(m[1], m[2]);
209
+
210
+ let blob = originalCookie.trim();
211
+ if (/^cookie\s*:\s*/i.test(blob)) blob = blob.replace(/^cookie\s*:\s*/i, "");
212
+
213
+ // Bare value (no `=`): the original was just the session-token contents.
214
+ // Replace with the new chunked form.
215
+ if (!/=/.test(blob)) {
216
+ return Array.from(refreshed, ([k, v]) => `${k}=${v}`).join("; ");
217
+ }
218
+
219
+ const pairs = blob.split(/;\s*/).filter(Boolean);
220
+ const result: string[] = [];
221
+ let mutated = false;
222
+ let droppedStale = false;
223
+ for (const pair of pairs) {
224
+ const eqIdx = pair.indexOf("=");
225
+ if (eqIdx < 0) {
226
+ result.push(pair);
227
+ continue;
228
+ }
229
+ const name = pair.slice(0, eqIdx).trim();
230
+ const value = pair.slice(eqIdx + 1);
231
+ // Drop ALL session-token-family members from the original — we'll
232
+ // append the refreshed set below. This handles unchunked→chunked and
233
+ // chunked→unchunked rotations, where keeping the old name would leave
234
+ // the stale token visible alongside the new one.
235
+ if (SESSION_TOKEN_FAMILY_RE.test(name)) {
236
+ if (!refreshed.has(name) || refreshed.get(name) !== value) mutated = true;
237
+ droppedStale = true;
238
+ continue;
239
+ }
240
+ result.push(`${name}=${value}`);
241
+ }
242
+ // Append the full refreshed family.
243
+ for (const [name, value] of refreshed) {
244
+ result.push(`${name}=${value}`);
245
+ }
246
+ if (!droppedStale) mutated = true; // refreshed chunks were entirely new
247
+ return mutated ? result.join("; ") : null;
248
+ }
249
+
250
+ /**
251
+ * Build the Cookie header value from whatever the user pasted.
252
+ *
253
+ * Accepts:
254
+ * - A bare value: "eyJhbGc..." → prepended with __Secure-next-auth.session-token=
255
+ * - An unchunked cookie line: "__Secure-next-auth.session-token=eyJ..."
256
+ * - A chunked cookie line: "__Secure-next-auth.session-token.0=...; __Secure-next-auth.session-token.1=..."
257
+ * - The full DevTools cookie header: "Cookie: __Secure-next-auth.session-token.0=...; cf_clearance=..."
258
+ *
259
+ * If the user pastes a chunked token, we pass the cookies through verbatim —
260
+ * NextAuth's server reassembles them on its side.
261
+ */
262
+ function buildSessionCookieHeader(rawInput: string): string {
263
+ let s = rawInput.trim();
264
+ if (/^cookie\s*:\s*/i.test(s)) s = s.replace(/^cookie\s*:\s*/i, "");
265
+ if (/__Secure-next-auth\.session-token(?:\.\d+)?\s*=/.test(s)) {
266
+ return s;
267
+ }
268
+ return `__Secure-next-auth.session-token=${s}`;
269
+ }
270
+
271
+ async function exchangeSession(
272
+ cookie: string,
273
+ signal: AbortSignal | null | undefined
274
+ ): Promise<TokenEntry> {
275
+ const cached = tokenLookup(cookie);
276
+ if (cached) return cached;
277
+
278
+ const headers: Record<string, string> = {
279
+ ...browserHeaders(),
280
+ Accept: "application/json",
281
+ Cookie: buildSessionCookieHeader(cookie),
282
+ };
283
+
284
+ const response = await tlsFetchChatGpt(SESSION_URL, {
285
+ method: "GET",
286
+ headers,
287
+ timeoutMs: 30_000,
288
+ signal,
289
+ });
290
+
291
+ if (response.status === 401 || response.status === 403) {
292
+ throw new SessionAuthError("Invalid session cookie");
293
+ }
294
+ if (response.status >= 400) {
295
+ throw new Error(`Session exchange failed (HTTP ${response.status})`);
296
+ }
297
+
298
+ const refreshed = mergeRefreshedCookie(cookie, response.headers.get("set-cookie"));
299
+ let data: SessionResponse = {};
300
+ try {
301
+ data = JSON.parse(response.text || "{}");
302
+ } catch {
303
+ console.warn("[chatgpt-web] session response JSON parse failed");
304
+ /* empty body or non-JSON */
305
+ }
306
+ if (!data.accessToken) {
307
+ throw new SessionAuthError("Session response missing accessToken — cookie likely expired");
308
+ }
309
+
310
+ const expiresAt = data.expires ? new Date(data.expires).getTime() : Date.now() + TOKEN_TTL_MS;
311
+ const entry: TokenEntry = {
312
+ accessToken: data.accessToken,
313
+ accountId: data.user?.id ?? null,
314
+ expiresAt: Math.min(expiresAt, Date.now() + TOKEN_TTL_MS),
315
+ refreshedCookie: refreshed ?? undefined,
316
+ };
317
+ tokenStore(cookie, entry);
318
+ return entry;
319
+ }
320
+
321
+ class SessionAuthError extends Error {
322
+ constructor(message: string) {
323
+ super(message);
324
+ this.name = "SessionAuthError";
325
+ }
326
+ }
327
+
328
+ // ─── /backend-api/sentinel/chat-requirements ────────────────────────────────
329
+
330
+ interface ChatRequirements {
331
+ /** Returned by /chat-requirements (the "real" chat requirements token). */
332
+ token?: string;
333
+ /** Returned by /chat-requirements/prepare (sent as a prerequisite header). */
334
+ prepare_token?: string;
335
+ persona?: string;
336
+ proofofwork?: {
337
+ required?: boolean;
338
+ seed?: string;
339
+ difficulty?: string;
340
+ };
341
+ turnstile?: {
342
+ required?: boolean;
343
+ dx?: string;
344
+ };
345
+ }
346
+
347
+ // ─── Session warmup ────────────────────────────────────────────────────────
348
+ // Mimics chatgpt.com's page-load fetch sequence so Sentinel sees a "warm"
349
+ // browsing session. Cached per (cookie, access-token) pair for 60s to avoid
350
+ // hammering the warmup endpoints on every chat completion.
351
+
352
+ const warmupCache = new Map<string, number>();
353
+ const WARMUP_TTL_MS = 60_000;
354
+ const WARMUP_CACHE_MAX = 200;
355
+
356
+ async function runSessionWarmup(
357
+ accessToken: string,
358
+ accountId: string | null,
359
+ sessionId: string,
360
+ deviceId: string,
361
+ cookie: string,
362
+ signal: AbortSignal | null | undefined,
363
+ log: { debug?: (tag: string, msg: string) => void } | null | undefined
364
+ ): Promise<void> {
365
+ const key = cookieKey(cookie) + ":" + accessToken.slice(-8);
366
+ const now = Date.now();
367
+ const last = warmupCache.get(key);
368
+ if (last && now - last < WARMUP_TTL_MS) return;
369
+ // Bound the cache: drop the oldest entry once we hit the cap. Map iteration
370
+ // order is insertion order, so the first key is the oldest.
371
+ if (warmupCache.size >= WARMUP_CACHE_MAX && !warmupCache.has(key)) {
372
+ const first = warmupCache.keys().next().value;
373
+ if (first) warmupCache.delete(first);
374
+ }
375
+ warmupCache.set(key, now);
376
+
377
+ const headers: Record<string, string> = {
378
+ ...browserHeaders(),
379
+ ...oaiHeaders(sessionId, deviceId),
380
+ Accept: "*/*",
381
+ Authorization: `Bearer ${accessToken}`,
382
+ Cookie: buildSessionCookieHeader(cookie),
383
+ Priority: "u=1, i",
384
+ };
385
+ if (accountId) headers["chatgpt-account-id"] = accountId;
386
+
387
+ const urls = [
388
+ `${CHATGPT_BASE}/backend-api/me`,
389
+ `${CHATGPT_BASE}/backend-api/conversations?offset=0&limit=28&order=updated`,
390
+ `${CHATGPT_BASE}/backend-api/models?history_and_training_disabled=false`,
391
+ ];
392
+
393
+ for (const url of urls) {
394
+ try {
395
+ const r = await tlsFetchChatGpt(url, {
396
+ method: "GET",
397
+ headers,
398
+ timeoutMs: 15_000,
399
+ signal,
400
+ });
401
+ log?.debug?.("CGPT-WEB", `warmup ${url.split("/backend-api/")[1]} → ${r.status}`);
402
+ } catch (err) {
403
+ log?.debug?.(
404
+ "CGPT-WEB",
405
+ `warmup ${url} failed: ${err instanceof Error ? err.message : String(err)}`
406
+ );
407
+ }
408
+ }
409
+ }
410
+
411
+ // ─── Thinking-effort preference (PATCH user_last_used_model_config) ────────
412
+ // chatgpt.com has two thinking levels for its dedicated thinking-models:
413
+ // • standard — default, faster
414
+ // • extended — longer reasoning budget
415
+ // The browser sets the level by PATCHing `/backend-api/settings/user_last_used_model_config`
416
+ // once, then issues the conversation request — the conversation endpoint itself
417
+ // has no `thinking_effort` field; the server reads the user's stored preference
418
+ // at routing time. We mirror that handshake when an OpenAI-style request
419
+ // includes `reasoning_effort` (or a direct `providerSpecificData.thinkingEffort`
420
+ // override).
421
+ //
422
+ // Cached per (cookie, slug, effort): the preference persists server-side, so
423
+ // re-PATCHing the same combination is wasted bytes. Refreshed on TTL expiry or
424
+ // whenever the caller switches efforts.
425
+
426
+ const thinkingEffortCache = new Map<string, number>();
427
+ const THINKING_EFFORT_TTL_MS = 5 * 60 * 1000;
428
+ const THINKING_EFFORT_CACHE_MAX = 400;
429
+
430
+ function configuredProPollTimeoutMs(): number {
431
+ const raw = Number(process.env.OMNIROUTE_CGPT_WEB_PRO_TIMEOUT_MS);
432
+ if (!Number.isFinite(raw) || raw <= 0) return DEFAULT_PRO_POLL_TIMEOUT_MS;
433
+ return Math.floor(raw);
434
+ }
435
+
436
+ function configuredProPollIntervalMs(): number {
437
+ const raw = Number(process.env.OMNIROUTE_CGPT_WEB_PRO_POLL_INTERVAL_MS);
438
+ if (!Number.isFinite(raw) || raw <= 0) return DEFAULT_PRO_POLL_INTERVAL_MS;
439
+ return Math.floor(raw);
440
+ }
441
+
442
+ async function setUserThinkingEffort(
443
+ modelSlug: string,
444
+ effort: "standard" | "extended",
445
+ accessToken: string,
446
+ accountId: string | null,
447
+ sessionId: string,
448
+ deviceId: string,
449
+ cookie: string,
450
+ signal: AbortSignal | null | undefined,
451
+ log:
452
+ | {
453
+ debug?: (tag: string, msg: string) => void;
454
+ warn?: (tag: string, msg: string) => void;
455
+ }
456
+ | null
457
+ | undefined
458
+ ): Promise<void> {
459
+ const cacheKey = `${cookieKey(cookie)}:${modelSlug}:${effort}`;
460
+ const now = Date.now();
461
+ const last = thinkingEffortCache.get(cacheKey);
462
+ if (last && now - last < THINKING_EFFORT_TTL_MS) {
463
+ log?.debug?.("CGPT-WEB", `thinking_effort cached (${modelSlug}=${effort}) — skip PATCH`);
464
+ return;
465
+ }
466
+ if (thinkingEffortCache.size >= THINKING_EFFORT_CACHE_MAX && !thinkingEffortCache.has(cacheKey)) {
467
+ const first = thinkingEffortCache.keys().next().value;
468
+ if (first) thinkingEffortCache.delete(first);
469
+ }
470
+
471
+ const url =
472
+ `${USER_LAST_USED_MODEL_CONFIG_URL}` +
473
+ `?model_slug=${encodeURIComponent(modelSlug)}` +
474
+ `&thinking_effort=${encodeURIComponent(effort)}`;
475
+ const headers: Record<string, string> = {
476
+ ...browserHeaders(),
477
+ ...oaiHeaders(sessionId, deviceId),
478
+ Accept: "application/json",
479
+ Authorization: `Bearer ${accessToken}`,
480
+ Cookie: buildSessionCookieHeader(cookie),
481
+ Priority: "u=4",
482
+ };
483
+ if (accountId) headers["chatgpt-account-id"] = accountId;
484
+
485
+ try {
486
+ const r = await tlsFetchChatGpt(url, {
487
+ method: "PATCH",
488
+ headers,
489
+ timeoutMs: 15_000,
490
+ signal,
491
+ });
492
+ if (r.status >= 400) {
493
+ log?.warn?.(
494
+ "CGPT-WEB",
495
+ `thinking_effort PATCH ${r.status} for ${modelSlug}=${effort} (continuing)`
496
+ );
497
+ return;
498
+ }
499
+ thinkingEffortCache.set(cacheKey, now);
500
+ log?.debug?.("CGPT-WEB", `thinking_effort PATCH OK (${modelSlug}=${effort})`);
501
+ } catch (err) {
502
+ log?.warn?.(
503
+ "CGPT-WEB",
504
+ `thinking_effort PATCH failed: ${err instanceof Error ? err.message : String(err)}`
505
+ );
506
+ }
507
+ }
508
+
509
+ async function prepareChatRequirements(
510
+ accessToken: string,
511
+ accountId: string | null,
512
+ sessionId: string,
513
+ deviceId: string,
514
+ cookie: string,
515
+ dplInfo: { dpl: string; scriptSrc: string },
516
+ signal: AbortSignal | null | undefined,
517
+ log?: { warn?: (tag: string, msg: string) => void } | null
518
+ ): Promise<ChatRequirements> {
519
+ const config = buildPrekeyConfig(CHATGPT_USER_AGENT, dplInfo.dpl, dplInfo.scriptSrc);
520
+ const prekey = await buildPrepareToken(config, log);
521
+
522
+ const headers: Record<string, string> = {
523
+ ...browserHeaders(),
524
+ ...oaiHeaders(sessionId, deviceId),
525
+ "Content-Type": "application/json",
526
+ Authorization: `Bearer ${accessToken}`,
527
+ Cookie: buildSessionCookieHeader(cookie),
528
+ Priority: "u=1, i",
529
+ };
530
+ if (accountId) headers["chatgpt-account-id"] = accountId;
531
+
532
+ // Stage 1: POST /chat-requirements/prepare → { prepare_token, ... }
533
+ const prepResp = await tlsFetchChatGpt(SENTINEL_PREPARE_URL, {
534
+ method: "POST",
535
+ headers,
536
+ body: JSON.stringify({ p: prekey }),
537
+ timeoutMs: 30_000,
538
+ signal,
539
+ });
540
+ if (prepResp.status === 401 || prepResp.status === 403) {
541
+ throw new SentinelBlockedError(`Sentinel /prepare blocked (HTTP ${prepResp.status})`);
542
+ }
543
+ if (prepResp.status >= 400) {
544
+ throw new Error(`Sentinel /prepare failed (HTTP ${prepResp.status})`);
545
+ }
546
+ let prepData: ChatRequirements = {};
547
+ try {
548
+ prepData = JSON.parse(prepResp.text || "{}") as ChatRequirements;
549
+ } catch {
550
+ console.warn("[chatgpt-web] chat requirements prep JSON parse failed");
551
+ /* keep empty */
552
+ }
553
+ // Stage 2: POST /chat-requirements with the prepare_token in the body. This
554
+ // is the call that actually returns the chat-requirements-token used on the
555
+ // conversation request.
556
+ if (!prepData.prepare_token) {
557
+ return prepData; // pass through whatever we got — caller handles missing fields
558
+ }
559
+
560
+ const crBody: Record<string, unknown> = { p: prekey, prepare_token: prepData.prepare_token };
561
+ const crResp = await tlsFetchChatGpt(SENTINEL_CR_URL, {
562
+ method: "POST",
563
+ headers,
564
+ body: JSON.stringify(crBody),
565
+ timeoutMs: 30_000,
566
+ signal,
567
+ });
568
+ if (crResp.status === 401 || crResp.status === 403) {
569
+ throw new SentinelBlockedError(`Sentinel /chat-requirements blocked (HTTP ${crResp.status})`);
570
+ }
571
+ if (crResp.status >= 400) {
572
+ // Fall back to whatever /prepare returned — some accounts may not need stage 2.
573
+ return prepData;
574
+ }
575
+ try {
576
+ const crData = JSON.parse(crResp.text || "{}") as ChatRequirements;
577
+ // Merge: prepare_token from stage 1, everything else from stage 2.
578
+ return { ...crData, prepare_token: prepData.prepare_token };
579
+ } catch {
580
+ console.warn("[chatgpt-web] chat requirements response JSON parse failed");
581
+ return prepData;
582
+ }
583
+ }
584
+
585
+ class SentinelBlockedError extends Error {
586
+ constructor(message: string) {
587
+ super(message);
588
+ this.name = "SentinelBlockedError";
589
+ }
590
+ }
591
+
592
+ // ─── Proof-of-work solver ──────────────────────────────────────────────────
593
+ // Mimics the openai-sentinel / chat2api algorithm. The browser sends a base64-encoded
594
+ // JSON config string; the server combines it with a seed and expects a SHA3-512 hash
595
+ // whose hex-prefix is ≤ the difficulty target.
596
+ //
597
+ // Reference: github.com/leetanshaj/openai-sentinel, github.com/lanqian528/chat2api
598
+ // Returns "gAAAAAB" + base64 of the winning config (server-recognised prefix).
599
+
600
+ // ─── DPL / script-src cache (warmup) ────────────────────────────────────────
601
+ // Sentinel's prekey check inspects whether config[5]/config[6] reference a real
602
+ // chatgpt.com deployment (DPL hash + a script URL from the HTML). We GET / once
603
+ // per hour to scrape these — same trick chat2api uses.
604
+
605
+ interface DplInfo {
606
+ dpl: string;
607
+ scriptSrc: string;
608
+ expiresAt: number;
609
+ }
610
+ let dplCache: DplInfo | null = null;
611
+ const DPL_TTL_MS = 60 * 60 * 1000;
612
+
613
+ async function fetchDpl(
614
+ cookie: string,
615
+ signal: AbortSignal | null | undefined
616
+ ): Promise<{ dpl: string; scriptSrc: string }> {
617
+ if (dplCache && Date.now() < dplCache.expiresAt) {
618
+ return { dpl: dplCache.dpl, scriptSrc: dplCache.scriptSrc };
619
+ }
620
+ const headers: Record<string, string> = {
621
+ ...browserHeaders(),
622
+ Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
623
+ Cookie: buildSessionCookieHeader(cookie),
624
+ };
625
+ const response = await tlsFetchChatGpt(`${CHATGPT_BASE}/`, {
626
+ method: "GET",
627
+ headers,
628
+ timeoutMs: 20_000,
629
+ signal,
630
+ });
631
+ const html = response.text || "";
632
+ const dplMatch = html.match(/data-build="([^"]+)"/);
633
+ const dpl = dplMatch ? `dpl=${dplMatch[1]}` : `dpl=${OAI_CLIENT_VERSION.replace(/^prod-/, "")}`;
634
+ const scriptMatch = html.match(/<script[^>]+src="(https?:\/\/[^"]*\.js[^"]*)"/);
635
+ const scriptSrc =
636
+ scriptMatch?.[1] ?? `${CHATGPT_BASE}/_next/static/chunks/webpack-${randomHex(16)}.js`;
637
+ dplCache = { dpl, scriptSrc, expiresAt: Date.now() + DPL_TTL_MS };
638
+ return { dpl, scriptSrc };
639
+ }
640
+
641
+ function randomHex(n: number): string {
642
+ return randomBytes(Math.ceil(n / 2))
643
+ .toString("hex")
644
+ .slice(0, n);
645
+ }
646
+
647
+ // ─── Browser fingerprint key lists (used in prekey config[10..12]) ─────────
648
+ // Chosen to look like real navigator/document/window inspection. The unicode
649
+ // MINUS SIGN (U+2212) in the navigator strings matches what `Object.toString()`
650
+ // produces in real browsers — Sentinel checks for it.
651
+
652
+ const NAVIGATOR_KEYS = [
653
+ "webdriver−false",
654
+ "geolocation",
655
+ "languages",
656
+ "language",
657
+ "platform",
658
+ "userAgent",
659
+ "vendor",
660
+ "hardwareConcurrency",
661
+ "deviceMemory",
662
+ "permissions",
663
+ "plugins",
664
+ "mediaDevices",
665
+ ];
666
+
667
+ const DOCUMENT_KEYS = [
668
+ "_reactListeningkfj3eavmks",
669
+ "_reactListeningo743lnnpvdg",
670
+ "location",
671
+ "scrollingElement",
672
+ "documentElement",
673
+ ];
674
+
675
+ const WINDOW_KEYS = [
676
+ "webpackChunk_N_E",
677
+ "__NEXT_DATA__",
678
+ "chrome",
679
+ "history",
680
+ "screen",
681
+ "navigation",
682
+ "scrollX",
683
+ "scrollY",
684
+ ];
685
+
686
+ function pick<T>(arr: readonly T[]): T {
687
+ return arr[Math.floor(Math.random() * arr.length)];
688
+ }
689
+
690
+ function buildPrekeyConfig(userAgent: string, dpl: string, scriptSrc: string): unknown[] {
691
+ const screenSizes = [3000, 4000, 3120, 4160] as const;
692
+ const cores = [8, 16, 24, 32] as const;
693
+ const dateStr = new Date().toString();
694
+ const perfNow = performance.now();
695
+ const epochOffset = Date.now() - perfNow;
696
+
697
+ return [
698
+ pick(screenSizes),
699
+ dateStr,
700
+ 4294705152,
701
+ 0, // mutated by solver
702
+ userAgent,
703
+ scriptSrc,
704
+ dpl,
705
+ "en-US",
706
+ "en-US,en",
707
+ 0, // mutated by solver
708
+ pick(NAVIGATOR_KEYS),
709
+ pick(DOCUMENT_KEYS),
710
+ pick(WINDOW_KEYS),
711
+ perfNow,
712
+ randomUUID(),
713
+ "",
714
+ pick(cores),
715
+ epochOffset,
716
+ ];
717
+ }
718
+
719
+ /**
720
+ * Build the `p` (prekey) value sent in the chat-requirements POST body.
721
+ *
722
+ * Format: "<prefix>" + base64(JSON(config)), with a PoW solver loop mutating
723
+ * config[3] to find a hash whose hex prefix is ≤ the target difficulty.
724
+ * Mirrors chat2api / openai-sentinel.
725
+ * - prepare: prefix="gAAAAAC", seed="" (target "0fffff")
726
+ * - chat-requirements: prefix="gAAAAAB", seed=<server seed> (target=difficulty)
727
+ *
728
+ * Submitting an unsolved token still works on low-friction accounts, so we
729
+ * fall back to that after exhausting the iteration budget — but emit a warn
730
+ * log so production can see when it happens.
731
+ */
732
+ // PoW solvers run up to 100k–500k SHA3-512 hashes. To avoid blocking the
733
+ // Node event loop on a busy server, we yield with `setImmediate` every
734
+ // POW_YIELD_EVERY iterations — roughly every ~5ms of work — so concurrent
735
+ // requests and I/O still get scheduled. Wall time is approximately the same
736
+ // as the synchronous version; what changes is fairness, not throughput.
737
+ const POW_YIELD_EVERY = 1000;
738
+
739
+ function yieldToEventLoop(): Promise<void> {
740
+ return new Promise((resolve) => setImmediate(resolve));
741
+ }
742
+
743
+ interface PowOptions {
744
+ config: unknown[];
745
+ seed: string;
746
+ target: string;
747
+ prefix: string;
748
+ maxIter: number;
749
+ label: string;
750
+ log?: { warn?: (tag: string, msg: string) => void } | null;
751
+ }
752
+
753
+ async function solvePow(opts: PowOptions): Promise<string> {
754
+ const cfg = [...opts.config];
755
+ for (let i = 0; i < opts.maxIter; i++) {
756
+ if (i > 0 && i % POW_YIELD_EVERY === 0) await yieldToEventLoop();
757
+ cfg[3] = i;
758
+ const json = JSON.stringify(cfg);
759
+ const b64 = Buffer.from(json).toString("base64");
760
+ // Portable SHA3-512 — pure-JS fallback under Electron/BoringSSL (#5531).
761
+ const hash = sha3_512Hex(opts.seed + b64);
762
+ if (opts.target && hash.slice(0, opts.target.length) <= opts.target) {
763
+ return `${opts.prefix}${b64}`;
764
+ }
765
+ }
766
+ opts.log?.warn?.(
767
+ "CGPT-WEB",
768
+ `PoW (${opts.label}) exhausted ${opts.maxIter} iterations against target=${opts.target || "<empty>"}; submitting unsolved token (Sentinel may reject)`
769
+ );
770
+ const b64 = Buffer.from(JSON.stringify(cfg)).toString("base64");
771
+ return `${opts.prefix}${b64}`;
772
+ }
773
+
774
+ async function buildPrepareToken(
775
+ config: unknown[],
776
+ log?: { warn?: (tag: string, msg: string) => void } | null
777
+ ): Promise<string> {
778
+ return solvePow({
779
+ config,
780
+ seed: "",
781
+ target: "0fffff",
782
+ prefix: "gAAAAAC",
783
+ maxIter: 100_000,
784
+ label: "prepare",
785
+ log,
786
+ });
787
+ }
788
+
789
+ async function solveProofOfWork(
790
+ seed: string,
791
+ difficulty: string,
792
+ config: unknown[],
793
+ log?: { warn?: (tag: string, msg: string) => void } | null
794
+ ): Promise<string> {
795
+ return solvePow({
796
+ config,
797
+ seed,
798
+ target: (difficulty || "").toLowerCase(),
799
+ prefix: "gAAAAAB",
800
+ maxIter: 500_000,
801
+ label: "conversation",
802
+ log,
803
+ });
804
+ }
805
+
806
+ // ─── OpenAI → ChatGPT message translation ───────────────────────────────────
807
+
808
+ interface ParsedMessages {
809
+ systemMsg: string;
810
+ history: Array<{ role: string; content: string }>;
811
+ currentMsg: string;
812
+ latestImageContext: ChatGptImageConversationContext | null;
813
+ }
814
+
815
+ /**
816
+ * Strip embedded `data:image/...` URIs out of message content so prior
817
+ * generated images don't get fed back into chatgpt.com on the next turn.
818
+ *
819
+ * Why: when image generation succeeds we emit `![image](data:image/png;base64,...)`
820
+ * — frequently 2–4 MB. Chat clients (Open WebUI, OpenAI-style apps) replay
821
+ * the full conversation history on the next request, so without this strip
822
+ * we'd send megabytes of base64 back upstream. chatgpt.com responds with an
823
+ * empty body when that happens (verified: 502 "ChatGPT returned empty
824
+ * response body" on the very next turn after an image gen succeeds), and
825
+ * even if it didn't, a single inlined image is well past the model's context
826
+ * limit. Replacing with a short placeholder keeps semantic continuity
827
+ * without the bytes.
828
+ */
829
+ const DATA_URI_IMAGE_RE = /!\[([^\]]*)\]\(data:image\/[^)]+\)/g;
830
+ const CACHED_IMAGE_URL_RE = /\/v1\/chatgpt-web\/image\/([a-f0-9]{16,64})(?=[)\s"'<>]|$)/gi;
831
+
832
+ function stripInlinedImages(content: string): string {
833
+ return content.replace(DATA_URI_IMAGE_RE, (_, alt) =>
834
+ alt ? `[${alt}: generated image]` : "[generated image]"
835
+ );
836
+ }
837
+
838
+ function findCachedImageContext(content: string): ChatGptImageConversationContext | null {
839
+ let latest: ChatGptImageConversationContext | null = null;
840
+ // String.prototype.matchAll consumes a fresh iterator and ignores the
841
+ // regex's lastIndex, so no manual reset is required.
842
+ for (const match of content.matchAll(CACHED_IMAGE_URL_RE)) {
843
+ const id = match[1];
844
+ const context = getChatGptImageConversationContext(id);
845
+ if (context) latest = context;
846
+ }
847
+ return latest;
848
+ }
849
+
850
+ function parseOpenAIMessages(messages: Array<Record<string, unknown>>): ParsedMessages {
851
+ let systemMsg = "";
852
+ const history: Array<{ role: string; content: string }> = [];
853
+ let latestImageContext: ChatGptImageConversationContext | null = null;
854
+
855
+ for (const msg of messages) {
856
+ let role = String(msg.role || "user");
857
+ if (role === "developer") role = "system";
858
+
859
+ let content = "";
860
+ if (typeof msg.content === "string") {
861
+ content = msg.content;
862
+ } else if (Array.isArray(msg.content)) {
863
+ content = (msg.content as Array<Record<string, unknown>>)
864
+ .filter((c) => c.type === "text")
865
+ .map((c) => String(c.text || ""))
866
+ .join(" ");
867
+ }
868
+ content = stripInlinedImages(content);
869
+ const imageContext = findCachedImageContext(content);
870
+ if (imageContext) latestImageContext = imageContext;
871
+ if (!content.trim()) continue;
872
+
873
+ if (role === "system") {
874
+ systemMsg += (systemMsg ? "\n" : "") + content;
875
+ } else if (role === "user" || role === "assistant") {
876
+ history.push({ role, content });
877
+ }
878
+ }
879
+
880
+ let currentMsg = "";
881
+ if (history.length > 0 && history[history.length - 1].role === "user") {
882
+ currentMsg = history.pop()!.content;
883
+ }
884
+
885
+ return { systemMsg, history, currentMsg, latestImageContext };
886
+ }
887
+
888
+ interface ChatGptMessage {
889
+ id: string;
890
+ author: { role: string };
891
+ content: { content_type: "text"; parts: string[] };
892
+ }
893
+
894
+ /**
895
+ * Cheap heuristic: does the last user turn look like an image-generation
896
+ * request? Used to decide whether to disable Temporary Chat mode.
897
+ *
898
+ * Why a heuristic instead of always disabling Temporary Chat: when
899
+ * `history_and_training_disabled: false`, every conversation gets saved to
900
+ * the user's chatgpt.com history. For text-only chats that's noise — a
901
+ * dozen "OmniRoute" entries clutter the sidebar and can interact with
902
+ * ChatGPT's memory. We pay that cost only when the user actually wants an
903
+ * image, since Temporary Chat refuses image_gen with the message
904
+ * "I cannot generate images in this chat".
905
+ *
906
+ * False positives (text chat misclassified as image) → unnecessary history
907
+ * entry. False negatives (image request misclassified as text) → ChatGPT
908
+ * refuses image_gen and the user retries. Tuning leans toward false
909
+ * positives (we'd rather pollute history than refuse image generation).
910
+ */
911
+ const IMAGE_GEN_REGEXES: RegExp[] = [
912
+ // verb + (anything within 40 chars) + image-noun
913
+ /\b(?:generate|create|make|draw|paint|render|produce|design|sketch|illustrate|show me)\b[\s\S]{0,40}\b(?:image|picture|photo|photograph|drawing|illustration|sketch|painting|portrait|logo|icon|art|artwork|wallpaper|render|graphic)\b/i,
914
+ // image-noun + "of" — "image of a kitten", "picture of mountains"
915
+ /\b(?:image|picture|photo|photograph|illustration|drawing|painting|render)\s+of\b/i,
916
+ // direct verb + a/an article — "draw a kitten", "paint an apple"
917
+ /\b(?:draw|paint|sketch|render|illustrate)\s+(?:me\s+)?(?:a|an|some|the)\s+\w+/i,
918
+ // explicit slash command users sometimes type — "/imagine ..."
919
+ /^\s*\/(?:image|imagine|img|draw|paint)\b/im,
920
+ ];
921
+
922
+ /**
923
+ * Markers Open WebUI uses for its background tool prompts (follow-up
924
+ * suggestions, title generation, tag categorization). These prompts embed
925
+ * the prior conversation in `<chat_history>` blocks and frequently quote
926
+ * the user's earlier "generate an image of..." request — which would
927
+ * trip the image-gen regex below. Skip them so we don't unnecessarily
928
+ * disable Temporary Chat and trigger image_gen on background tasks.
929
+ *
930
+ * Catching just one of these markers is enough; tool prompts always
931
+ * include several together.
932
+ */
933
+ const OPENWEBUI_TOOL_PROMPT_MARKERS = [
934
+ /<chat_history>/i,
935
+ /^### Task:/im,
936
+ /\bJSON format:\s*\{/i,
937
+ /\bfollow_?ups\b.*\barray of strings\b/i,
938
+ ];
939
+
940
+ const OPENWEBUI_IMAGE_CONTEXT_MARKERS = [
941
+ /<context>\s*The requested image has been (?:created|edited and created) by the system successfully/i,
942
+ /<context>\s*The requested image has been edited and created and is now being shown to the user/i,
943
+ /<context>\s*Image generation was attempted but failed/i,
944
+ ];
945
+
946
+ function hasOpenWebUIImageContext(parsed: ParsedMessages): boolean {
947
+ return OPENWEBUI_IMAGE_CONTEXT_MARKERS.some((re) => re.test(parsed.systemMsg));
948
+ }
949
+
950
+ function looksLikeImageGenRequest(parsed: ParsedMessages): boolean {
951
+ // Inspect only the latest user turn — historical turns are irrelevant
952
+ // (and could trigger false positives if the user mentioned an image
953
+ // generated previously).
954
+ const text = parsed.currentMsg.trim();
955
+ if (!text) return false;
956
+ if (OPENWEBUI_TOOL_PROMPT_MARKERS.some((re) => re.test(text))) return false;
957
+ if (hasOpenWebUIImageContext(parsed)) return false;
958
+ return IMAGE_GEN_REGEXES.some((re) => re.test(text));
959
+ }
960
+
961
+ const IMAGE_EDIT_REGEXES: RegExp[] = [
962
+ /\b(?:edit|adjust|modify|change|update|alter|revise|retouch|fix)\b[\s\S]{0,120}\b(?:it|image|picture|photo|lighting|background|style|color|colour|composition|scene|time of day)\b/i,
963
+ /\b(?:make|turn|set|switch)\s+(?:it|the\s+(?:image|picture|photo|scene))\b[\s\S]{0,120}\b/i,
964
+ /\b(?:add|remove|replace)\b[\s\S]{0,120}\b(?:it|image|picture|photo|background|sky|person|object|text|logo)\b/i,
965
+ /\b(?:brighter|darker|night|daytime|time of day|sunset|sunrise|morning|evening|lighting|relight|background|style)\b/i,
966
+ /^\s*(?:now|then|also)\b[\s\S]{0,120}\b(?:make|turn|change|adjust|add|remove|replace|edit)\b/i,
967
+ ];
968
+
969
+ function looksLikeImageEditRequest(parsed: ParsedMessages): boolean {
970
+ if (!parsed.latestImageContext) return false;
971
+ const text = parsed.currentMsg.trim();
972
+ if (!text) return false;
973
+ if (OPENWEBUI_TOOL_PROMPT_MARKERS.some((re) => re.test(text))) return false;
974
+ if (hasOpenWebUIImageContext(parsed)) return false;
975
+ return IMAGE_EDIT_REGEXES.some((re) => re.test(text));
976
+ }
977
+
978
+ function buildConversationBody(
979
+ parsed: ParsedMessages,
980
+ modelSlug: string,
981
+ parentMessageId: string,
982
+ options: {
983
+ // Keep text/API calls in Temporary Chat so they do not clutter the user's
984
+ // chatgpt.com history. Disable Temporary Chat only when ChatGPT needs a
985
+ // durable image conversation (image generation/editing).
986
+ persistConversation: boolean;
987
+ thinkingEffort: "standard" | "extended" | null;
988
+ continuation?: ChatGptImageConversationContext | null;
989
+ }
990
+ ): Record<string, unknown> {
991
+ // Critical: do NOT send prior turns as separate `assistant` and `user`
992
+ // messages in the `messages` array. ChatGPT's web API ("action: next")
993
+ // treats those as in-progress turns and the model will literally CONTINUE
994
+ // a prior assistant response in the new generation — observed as
995
+ // `[1] -> [12] -> [1123]` across three turns.
996
+ //
997
+ // Instead, fold all prior history into the system message and send only
998
+ // the current user message as a single new turn. The model then sees a
999
+ // single prompt with full context and responds fresh.
1000
+ const systemParts: string[] = [];
1001
+ if (parsed.systemMsg.trim()) {
1002
+ systemParts.push(parsed.systemMsg.trim());
1003
+ }
1004
+ const continuation = options.continuation ?? null;
1005
+
1006
+ if (!continuation && parsed.history.length > 0) {
1007
+ const formatted = parsed.history
1008
+ .map((h) => `${h.role === "assistant" ? "Assistant" : "User"}: ${h.content}`)
1009
+ .join("\n\n");
1010
+ systemParts.push(
1011
+ `Prior conversation (for context — answer only the new user message below):\n\n${formatted}`
1012
+ );
1013
+ }
1014
+
1015
+ const messages: ChatGptMessage[] = [];
1016
+ if (systemParts.length > 0) {
1017
+ messages.push({
1018
+ id: randomUUID(),
1019
+ author: { role: "system" },
1020
+ content: { content_type: "text", parts: [systemParts.join("\n\n")] },
1021
+ });
1022
+ }
1023
+
1024
+ const currentUserContent = hasOpenWebUIImageContext(parsed)
1025
+ ? "Briefly acknowledge the image result described in the system context. Do not generate, edit, or request another image."
1026
+ : parsed.currentMsg || "";
1027
+
1028
+ messages.push({
1029
+ id: randomUUID(),
1030
+ author: { role: "user" },
1031
+ content: { content_type: "text", parts: [currentUserContent] },
1032
+ });
1033
+
1034
+ return {
1035
+ action: "next",
1036
+ messages,
1037
+ model: modelSlug,
1038
+ // Text-only API-style requests start fresh because clients replay full
1039
+ // history. Generated-image edits are the exception: ChatGPT needs the
1040
+ // original conversation node to adjust the actual image, not just a
1041
+ // markdown URL echoed back in a synthetic history block.
1042
+ conversation_id: continuation?.conversationId ?? null,
1043
+ parent_message_id: continuation?.parentMessageId ?? parentMessageId,
1044
+ timezone_offset_min: -new Date().getTimezoneOffset(),
1045
+ // Temporary Chat is the default. Disable it only for image generation /
1046
+ // image edits, where ChatGPT needs durable conversation state for tools.
1047
+ history_and_training_disabled: !options.persistConversation,
1048
+ suggestions: [],
1049
+ websocket_request_id: randomUUID(),
1050
+ conversation_mode: { kind: "primary_assistant" },
1051
+ supports_buffering: true,
1052
+ force_parallel_switch: "auto",
1053
+ paragen_cot_summary_display_override: "allow",
1054
+ ...(options.thinkingEffort ? { thinking_effort: options.thinkingEffort } : {}),
1055
+ };
1056
+ }
1057
+
1058
+ // ─── ChatGPT SSE parsing ────────────────────────────────────────────────────
1059
+
1060
+ interface ChatGptStreamEvent {
1061
+ message?: {
1062
+ id?: string;
1063
+ author?: { role?: string };
1064
+ content?: { content_type?: string; parts?: unknown[] };
1065
+ status?: string;
1066
+ metadata?: Record<string, unknown>;
1067
+ };
1068
+ conversation_id?: string;
1069
+ error?: string | { message?: string; code?: string };
1070
+ type?: string;
1071
+ v?: unknown;
1072
+ }
1073
+
1074
+ /**
1075
+ * A part inside `content.parts` for a `multimodal_text` content_type.
1076
+ * ChatGPT puts image references in a part with content_type "image_asset_pointer"
1077
+ * and an asset_pointer like "file-service://file-XXXX" (final) or
1078
+ * "sediment://..." (in-progress preview).
1079
+ */
1080
+ interface ImageAssetPart {
1081
+ content_type?: string;
1082
+ asset_pointer?: string;
1083
+ width?: number;
1084
+ height?: number;
1085
+ metadata?: Record<string, unknown>;
1086
+ }
1087
+
1088
+ async function* readChatGptSseEvents(
1089
+ body: ReadableStream<Uint8Array>,
1090
+ signal?: AbortSignal | null
1091
+ ): AsyncGenerator<ChatGptStreamEvent> {
1092
+ const reader = body.getReader();
1093
+ const decoder = new TextDecoder();
1094
+ let buffer = "";
1095
+ let dataLines: string[] = [];
1096
+ let eventName: string | null = null;
1097
+
1098
+ function flush(): ChatGptStreamEvent | null | "done" {
1099
+ if (dataLines.length === 0) {
1100
+ eventName = null;
1101
+ return null;
1102
+ }
1103
+ const payload = dataLines.join("\n");
1104
+ dataLines = [];
1105
+ const sseEventName = eventName;
1106
+ eventName = null;
1107
+ const trimmed = payload.trim();
1108
+ if (!trimmed || trimmed === "[DONE]") return "done";
1109
+ try {
1110
+ const parsed = JSON.parse(trimmed) as ChatGptStreamEvent;
1111
+ if (sseEventName && !parsed.type) parsed.type = sseEventName;
1112
+ return parsed;
1113
+ } catch {
1114
+ console.warn("[chatgpt-web] stream event JSON parse failed");
1115
+ return null;
1116
+ }
1117
+ }
1118
+
1119
+ try {
1120
+ while (true) {
1121
+ if (signal?.aborted) return;
1122
+ const { value, done } = await reader.read();
1123
+ if (done) break;
1124
+ buffer += decoder.decode(value, { stream: true });
1125
+
1126
+ while (true) {
1127
+ const idx = buffer.indexOf("\n");
1128
+ if (idx < 0) break;
1129
+ const rawLine = buffer.slice(0, idx);
1130
+ buffer = buffer.slice(idx + 1);
1131
+ const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
1132
+
1133
+ if (line === "") {
1134
+ const parsed = flush();
1135
+ if (parsed === "done") return;
1136
+ if (parsed) yield parsed;
1137
+ continue;
1138
+ }
1139
+ if (line.startsWith("event:")) {
1140
+ eventName = line.slice(6).trim();
1141
+ } else if (line.startsWith("data:")) {
1142
+ dataLines.push(line.slice(5).trimStart());
1143
+ }
1144
+ }
1145
+ }
1146
+
1147
+ buffer += decoder.decode();
1148
+ if (buffer.trim().startsWith("data:")) {
1149
+ dataLines.push(buffer.trim().slice(5).trimStart());
1150
+ }
1151
+ const tail = flush();
1152
+ if (tail && tail !== "done") yield tail;
1153
+ } finally {
1154
+ reader.releaseLock();
1155
+ }
1156
+ }
1157
+
1158
+ // ─── Content extraction ─────────────────────────────────────────────────────
1159
+ // ChatGPT SSE chunks contain CUMULATIVE content (full text so far in `parts[0]`),
1160
+ // not deltas. Diff against the emitted length to produce incremental tokens —
1161
+ // same pattern perplexity-web.ts uses for markdown blocks (lines 386-397).
1162
+
1163
+ interface ContentChunk {
1164
+ delta?: string;
1165
+ answer?: string;
1166
+ conversationId?: string;
1167
+ messageId?: string;
1168
+ error?: string;
1169
+ done?: boolean;
1170
+ /** Image asset pointers seen on the current message (e.g. file-service://file-abc). */
1171
+ imagePointers?: ImagePointerRef[];
1172
+ /**
1173
+ * True if the assistant invoked the async image_gen tool (we saw a task id
1174
+ * in metadata or `turn_use_case: "image gen"` in server_ste_metadata).
1175
+ * Set on the final `done: true` chunk so the caller can decide to poll the
1176
+ * conversation endpoint for the actual image.
1177
+ */
1178
+ imageGenAsync?: boolean;
1179
+ /** True when ChatGPT handed the turn off to a long-running worker. */
1180
+ handoff?: boolean;
1181
+ }
1182
+
1183
+ interface ImagePointerRef {
1184
+ pointer: string;
1185
+ messageId?: string;
1186
+ }
1187
+
1188
+ /**
1189
+ * Pull image asset pointers out of a multimodal_text parts array.
1190
+ *
1191
+ * For text-only messages parts is `["text..."]` and this returns `[]`. For
1192
+ * `image_gen` tool output, parts looks like:
1193
+ * [
1194
+ * { content_type: "image_asset_pointer",
1195
+ * asset_pointer: "file-service://file-abc..." or "sediment://..." }
1196
+ * ]
1197
+ * We collect every asset_pointer seen so the caller can resolve them once
1198
+ * the stream terminates.
1199
+ */
1200
+ function extractImagePointers(parts: unknown[]): string[] {
1201
+ const out: string[] = [];
1202
+ for (const p of parts) {
1203
+ if (!p || typeof p !== "object") continue;
1204
+ const obj = p as ImageAssetPart;
1205
+ if (obj.content_type === "image_asset_pointer" && typeof obj.asset_pointer === "string") {
1206
+ out.push(obj.asset_pointer);
1207
+ }
1208
+ }
1209
+ return out;
1210
+ }
1211
+
1212
+ async function* extractContent(
1213
+ eventStream: ReadableStream<Uint8Array>,
1214
+ signal?: AbortSignal | null
1215
+ ): AsyncGenerator<ContentChunk> {
1216
+ // ChatGPT may echo prior assistant turns at the start of the stream with
1217
+ // status: "finished_successfully" and full content, before sending the new
1218
+ // generation. If we emit those bytes downstream, streaming consumers see
1219
+ // the previous answer prepended to the new one (visible in Open WebUI as
1220
+ // run-on output across turns). Strategy: only emit deltas after we've seen
1221
+ // status === "in_progress" for the current message id (i.e., it's being
1222
+ // generated live in this stream). Echoes always arrive already finished
1223
+ // and never transition through in_progress, so they get suppressed. An
1224
+ // end-of-stream fallback handles the rare case where a real turn arrives
1225
+ // as a single already-finished event (instant/cached responses).
1226
+ let conversationId: string | null = null;
1227
+ let currentId: string | null = null;
1228
+ let currentParts = "";
1229
+ let emittedLen = 0;
1230
+ let isLive = false;
1231
+ // Dedupe pointers across echoes / repeated events. Order-preserving Set.
1232
+ const imagePointers = new Map<string, ImagePointerRef>();
1233
+ // True if we observed signals the assistant kicked off the async image_gen
1234
+ // tool (see ContentChunk.imageGenAsync). The actual image arrives later via
1235
+ // WebSocket / polling — caller handles that.
1236
+ let imageGenAsync = false;
1237
+ let handoff = false;
1238
+
1239
+ for await (const event of readChatGptSseEvents(eventStream, signal)) {
1240
+ if (event.error) {
1241
+ const msg =
1242
+ typeof event.error === "string"
1243
+ ? event.error
1244
+ : event.error.message || "ChatGPT stream error";
1245
+ yield { error: msg, done: true };
1246
+ return;
1247
+ }
1248
+
1249
+ if (event.conversation_id) conversationId = event.conversation_id;
1250
+
1251
+ if (event.type === "stream_handoff") {
1252
+ handoff = true;
1253
+ yield {
1254
+ conversationId: conversationId ?? undefined,
1255
+ handoff: true,
1256
+ };
1257
+ continue;
1258
+ }
1259
+
1260
+ // Detect image_gen on top-level "server_ste_metadata" events. These don't
1261
+ // have a `message` field so the post-message guard would skip them, but
1262
+ // they're the most reliable signal — `turn_use_case: "image gen"`.
1263
+ //
1264
+ // Originally we also accepted `meta.tool_invoked === true`, but ChatGPT
1265
+ // sets that flag for ANY internal tool the assistant uses (reasoning
1266
+ // chains, web search, calc, file_search, etc.). That made plain text
1267
+ // turns spuriously emit the "Generating image…" placeholder + 30s
1268
+ // WebSocket wait. Image gen has a more specific signal we can rely on:
1269
+ // either `turn_use_case === "image gen"` here, or an `image_gen_task_id`
1270
+ // on a tool-role message (handled below).
1271
+ if (event.type === "server_ste_metadata") {
1272
+ const meta = (event as Record<string, unknown>).metadata as
1273
+ Record<string, unknown> | undefined;
1274
+ if (meta && meta.turn_use_case === "image gen") {
1275
+ imageGenAsync = true;
1276
+ }
1277
+ }
1278
+
1279
+ const m = event.message;
1280
+ if (!m) continue;
1281
+
1282
+ // Tool messages with `image_gen_task_id` in metadata (the "Processing
1283
+ // image..." card) confirm the async image_gen flow. We don't surface the
1284
+ // tool message itself as text — it's just a placeholder — but we mark
1285
+ // imageGenAsync so the executor knows to poll for the final image.
1286
+ if (m.metadata && typeof m.metadata.image_gen_task_id === "string") {
1287
+ imageGenAsync = true;
1288
+ }
1289
+
1290
+ if (m.author?.role !== "assistant") continue;
1291
+
1292
+ const id = m.id ?? null;
1293
+ const status = m.status ?? "";
1294
+
1295
+ if (id && id !== currentId) {
1296
+ currentId = id;
1297
+ currentParts = "";
1298
+ emittedLen = 0;
1299
+ isLive = false;
1300
+ }
1301
+
1302
+ if (status === "in_progress") {
1303
+ isLive = true;
1304
+ }
1305
+
1306
+ const parts = m.content?.parts ?? [];
1307
+ if (parts.length === 0) continue;
1308
+
1309
+ // Image asset pointers: only collect once the message is finalized
1310
+ // (status === "finished_successfully"). The same pointer may also appear
1311
+ // on echoed prior turns at the head of the stream; that's fine — the Set
1312
+ // dedupes, and the resolver in the executor produces the same URL either
1313
+ // way. We could restrict to isLive-only to avoid resolving echoes, but
1314
+ // that makes single-event instant responses (no in_progress phase) lose
1315
+ // their image. Letting echoes through is harmless for correctness; the
1316
+ // executor resolves each unique pointer at most once.
1317
+ if (status === "finished_successfully" || status === "" || isLive) {
1318
+ for (const ptr of extractImagePointers(parts)) {
1319
+ const existing = imagePointers.get(ptr);
1320
+ imagePointers.set(
1321
+ ptr,
1322
+ existing?.messageId ? existing : { pointer: ptr, ...(id ? { messageId: id } : {}) }
1323
+ );
1324
+ }
1325
+ }
1326
+
1327
+ const cumulative = parts.map((p) => (typeof p === "string" ? p : "")).join("");
1328
+ if (cumulative.length > currentParts.length) {
1329
+ currentParts = cumulative;
1330
+ }
1331
+
1332
+ if (isLive && currentParts.length > emittedLen) {
1333
+ const delta = currentParts.slice(emittedLen);
1334
+ emittedLen = currentParts.length;
1335
+ yield {
1336
+ delta,
1337
+ answer: currentParts,
1338
+ conversationId: conversationId ?? undefined,
1339
+ messageId: currentId ?? undefined,
1340
+ };
1341
+ }
1342
+ }
1343
+
1344
+ // End-of-stream fallback: if we never observed status === "in_progress"
1345
+ // for the current id (single-event reply, cached/instant response), emit
1346
+ // the accumulated content now so the consumer doesn't get an empty stream.
1347
+ if (!isLive && currentParts.length > emittedLen) {
1348
+ yield {
1349
+ delta: currentParts.slice(emittedLen),
1350
+ answer: currentParts,
1351
+ conversationId: conversationId ?? undefined,
1352
+ messageId: currentId ?? undefined,
1353
+ };
1354
+ }
1355
+
1356
+ yield {
1357
+ delta: "",
1358
+ answer: currentParts,
1359
+ conversationId: conversationId ?? undefined,
1360
+ messageId: currentId ?? undefined,
1361
+ imagePointers: imagePointers.size > 0 ? Array.from(imagePointers.values()) : undefined,
1362
+ imageGenAsync,
1363
+ handoff,
1364
+ done: true,
1365
+ };
1366
+ }
1367
+
1368
+ // ─── Long-running Pro handoff polling ──────────────────────────────────────
1369
+
1370
+ interface ChatGptDetailMessage {
1371
+ id?: string;
1372
+ author?: { role?: string };
1373
+ content?: {
1374
+ content_type?: string;
1375
+ parts?: unknown[];
1376
+ text?: string;
1377
+ };
1378
+ status?: string;
1379
+ end_turn?: boolean;
1380
+ create_time?: number;
1381
+ update_time?: number;
1382
+ metadata?: Record<string, unknown>;
1383
+ }
1384
+
1385
+ interface ChatGptConversationDetail {
1386
+ mapping?: Record<string, { message?: ChatGptDetailMessage | null }>;
1387
+ }
1388
+
1389
+ interface FinalAssistantAnswer {
1390
+ text: string;
1391
+ messageId?: string;
1392
+ finished: boolean;
1393
+ }
1394
+
1395
+ function textFromContentPart(part: unknown): string {
1396
+ if (typeof part === "string") return part;
1397
+ if (!part || typeof part !== "object") return "";
1398
+ const obj = part as Record<string, unknown>;
1399
+ for (const key of ["text", "content", "summary"]) {
1400
+ const value = obj[key];
1401
+ if (typeof value === "string") return value;
1402
+ }
1403
+ return "";
1404
+ }
1405
+
1406
+ function detailMessageText(message: ChatGptDetailMessage): string {
1407
+ const content = message.content;
1408
+ if (!content) return "";
1409
+ if (typeof content.text === "string") return content.text;
1410
+ const parts = content.parts ?? [];
1411
+ return parts.map(textFromContentPart).join("");
1412
+ }
1413
+
1414
+ function extractFinalAssistantAnswer(
1415
+ detail: ChatGptConversationDetail
1416
+ ): FinalAssistantAnswer | null {
1417
+ const nodes = Object.values(detail.mapping ?? {});
1418
+ let best: (FinalAssistantAnswer & { sort: number }) | null = null;
1419
+
1420
+ for (const node of nodes) {
1421
+ const message = node.message;
1422
+ if (!message || message.author?.role !== "assistant") continue;
1423
+ if (message.metadata?.is_visually_hidden === true) continue;
1424
+ const contentType = message.content?.content_type ?? "";
1425
+ if (contentType.includes("thought") || contentType.includes("reasoning")) continue;
1426
+
1427
+ const text = detailMessageText(message).trim();
1428
+ if (!text) continue;
1429
+ const finished = message.status === "finished_successfully" && message.end_turn !== false;
1430
+ const sort = message.update_time ?? message.create_time ?? 0;
1431
+ if (
1432
+ !best ||
1433
+ (finished && (!best.finished || sort >= best.sort)) ||
1434
+ (!finished && !best.finished && sort >= best.sort)
1435
+ ) {
1436
+ best = { text, messageId: message.id, finished, sort };
1437
+ }
1438
+ }
1439
+
1440
+ if (!best) return null;
1441
+ return { text: best.text, messageId: best.messageId, finished: best.finished };
1442
+ }
1443
+
1444
+ function delayWithAbort(ms: number, signal?: AbortSignal | null): Promise<void> {
1445
+ if (ms <= 0) return Promise.resolve();
1446
+ if (signal?.aborted) return Promise.resolve();
1447
+ return new Promise((resolve) => {
1448
+ const timer = setTimeout(() => {
1449
+ signal?.removeEventListener("abort", onAbort);
1450
+ resolve();
1451
+ }, ms);
1452
+ const onAbort = () => {
1453
+ clearTimeout(timer);
1454
+ signal?.removeEventListener("abort", onAbort);
1455
+ resolve();
1456
+ };
1457
+ signal?.addEventListener("abort", onAbort, { once: true });
1458
+ });
1459
+ }
1460
+
1461
+ function decodeUtf8DataUrl(text: string): string {
1462
+ const marker = ";base64,";
1463
+ if (!text.startsWith("data:") || !text.includes(marker)) return text;
1464
+ const base64 = text.slice(text.indexOf(marker) + marker.length);
1465
+ return new TextDecoder().decode(Buffer.from(base64, "base64"));
1466
+ }
1467
+
1468
+ interface ConversationDetailFetchResult {
1469
+ detail: ChatGptConversationDetail | null;
1470
+ terminal: boolean;
1471
+ }
1472
+
1473
+ async function fetchConversationDetail(
1474
+ conversationId: string,
1475
+ ctx: ResolverContext
1476
+ ): Promise<ConversationDetailFetchResult> {
1477
+ const url = `${CHATGPT_BASE}/backend-api/conversation/${encodeURIComponent(conversationId)}`;
1478
+ const headers: Record<string, string> = {
1479
+ ...browserHeaders(),
1480
+ ...oaiHeaders(ctx.sessionId, ctx.deviceId),
1481
+ Accept: "application/json",
1482
+ Authorization: `Bearer ${ctx.accessToken}`,
1483
+ Cookie: buildSessionCookieHeader(ctx.cookie),
1484
+ };
1485
+ if (ctx.accountId) headers["chatgpt-account-id"] = ctx.accountId;
1486
+
1487
+ try {
1488
+ const response = await tlsFetchChatGpt(url, {
1489
+ method: "GET",
1490
+ headers,
1491
+ timeoutMs: 30_000,
1492
+ signal: ctx.signal,
1493
+ // The native tls-client text path can surface UTF-8 JSON as mojibake
1494
+ // (e.g. 👉 becomes 👉). Ask for raw bytes and decode as UTF-8 here so
1495
+ // the final answer appended after Pro stream_handoff preserves Unicode.
1496
+ byteResponse: true,
1497
+ });
1498
+ if (response.status >= 400) {
1499
+ ctx.log?.warn?.(
1500
+ "CGPT-WEB",
1501
+ `conversation poll ${response.status}: ${(response.text || "").slice(0, 300)}`
1502
+ );
1503
+ return { detail: null, terminal: [401, 403, 404].includes(response.status) };
1504
+ }
1505
+ if (!response.text) return { detail: null, terminal: false };
1506
+ return {
1507
+ detail: JSON.parse(decodeUtf8DataUrl(response.text)) as ChatGptConversationDetail,
1508
+ terminal: false,
1509
+ };
1510
+ } catch (err) {
1511
+ ctx.log?.warn?.(
1512
+ "CGPT-WEB",
1513
+ `conversation poll failed: ${err instanceof Error ? err.message : String(err)}`
1514
+ );
1515
+ return { detail: null, terminal: false };
1516
+ }
1517
+ }
1518
+
1519
+ async function pollForFinalAssistantAnswer(
1520
+ conversationId: string,
1521
+ ctx: ResolverContext
1522
+ ): Promise<FinalAssistantAnswer | null> {
1523
+ const started = Date.now();
1524
+ const timeoutMs = configuredProPollTimeoutMs();
1525
+ const intervalMs = configuredProPollIntervalMs();
1526
+ let last: FinalAssistantAnswer | null = null;
1527
+ let terminalPollFailure = false;
1528
+
1529
+ while (!ctx.signal?.aborted && Date.now() - started < timeoutMs) {
1530
+ const { detail, terminal } = await fetchConversationDetail(conversationId, ctx);
1531
+ if (detail) {
1532
+ const answer = extractFinalAssistantAnswer(detail);
1533
+ if (answer) {
1534
+ last = answer;
1535
+ if (answer.finished) return answer;
1536
+ }
1537
+ }
1538
+ if (terminal) {
1539
+ terminalPollFailure = true;
1540
+ break;
1541
+ }
1542
+ const remaining = timeoutMs - (Date.now() - started);
1543
+ if (remaining <= 0) break;
1544
+ await delayWithAbort(Math.min(intervalMs, remaining), ctx.signal);
1545
+ }
1546
+
1547
+ if (last) {
1548
+ ctx.log?.warn?.(
1549
+ "CGPT-WEB",
1550
+ terminalPollFailure
1551
+ ? `conversation poll stopped before finished_successfully; returning latest assistant text for ${conversationId}`
1552
+ : `conversation poll timed out before finished_successfully; returning latest assistant text for ${conversationId}`
1553
+ );
1554
+ } else {
1555
+ ctx.log?.warn?.(
1556
+ "CGPT-WEB",
1557
+ terminalPollFailure
1558
+ ? `conversation poll stopped without assistant text for ${conversationId}`
1559
+ : `conversation poll timed out without assistant text for ${conversationId}`
1560
+ );
1561
+ }
1562
+ return last;
1563
+ }
1564
+
1565
+ // ─── OpenAI SSE format ──────────────────────────────────────────────────────
1566
+
1567
+ function sseChunk(data: unknown): string {
1568
+ return `data: ${JSON.stringify(data)}\n\n`;
1569
+ }
1570
+
1571
+ /**
1572
+ * Resolves a ChatGPT asset_pointer to a downloadable URL, given the live
1573
+ * conversation_id (needed for sediment:// pointers). Returns null on failure
1574
+ * so the caller can decide whether to surface a placeholder or skip silently.
1575
+ */
1576
+ type ImageResolver = (
1577
+ assetPointer: string,
1578
+ conversationId: string | null,
1579
+ parentMessageId?: string | null
1580
+ ) => Promise<string | null>;
1581
+
1582
+ /**
1583
+ * True when ChatGPT emitted an image asset pointer (the image WAS generated
1584
+ * upstream) but none of the pointers could be resolved to a downloadable URL
1585
+ * — so the assistant text carries no image markdown. Lets callers surface an
1586
+ * accurate "generated but not retrievable" error instead of the misleading
1587
+ * "no image was produced". Escalated mesh report: image visible in the ChatGPT
1588
+ * chat but returned to OmniRoute as a bare "completed without image markdown".
1589
+ */
1590
+ export function detectImageResolutionFailure(
1591
+ pointerCount: number,
1592
+ resolvedCount: number
1593
+ ): boolean {
1594
+ return pointerCount > 0 && resolvedCount === 0;
1595
+ }
1596
+
1597
+ /** Build the final markdown block for a list of resolved image URLs. */
1598
+ function imageMarkdown(urls: string[]): string {
1599
+ if (urls.length === 0) return "";
1600
+ // Two leading newlines → ensure separation from any prior text the model
1601
+ // produced ("Here is your kitten:\n\n![image](...)"). One image per line.
1602
+ return "\n\n" + urls.map((u) => `![image](${u})`).join("\n\n");
1603
+ }
1604
+
1605
+ async function resolveImagePointers(
1606
+ pointers: ImagePointerRef[] | undefined,
1607
+ conversationId: string | null,
1608
+ resolver: ImageResolver | null,
1609
+ log?: { warn?: (tag: string, msg: string) => void } | null,
1610
+ fallbackParentMessageId?: string | null
1611
+ ): Promise<string[]> {
1612
+ if (!pointers || pointers.length === 0 || !resolver) return [];
1613
+ const urls: string[] = [];
1614
+ for (const ref of pointers) {
1615
+ try {
1616
+ const url = await resolver(
1617
+ ref.pointer,
1618
+ conversationId,
1619
+ ref.messageId ?? fallbackParentMessageId
1620
+ );
1621
+ if (url) urls.push(url);
1622
+ } catch (err) {
1623
+ log?.warn?.(
1624
+ "CGPT-WEB",
1625
+ `Image resolve failed (${ref.pointer}): ${err instanceof Error ? err.message : String(err)}`
1626
+ );
1627
+ }
1628
+ }
1629
+ return urls;
1630
+ }
1631
+
1632
+ function buildStreamingResponse(
1633
+ eventStream: ReadableStream<Uint8Array>,
1634
+ model: string,
1635
+ cid: string,
1636
+ created: number,
1637
+ resolver: ImageResolver | null,
1638
+ // Optional poller for async image_gen — when ChatGPT processes the request
1639
+ // out-of-band ("Lots of people are creating images right now"), the SSE
1640
+ // stream finishes without an image_asset_pointer. The executor passes a
1641
+ // closure here that knows how to poll the conversation endpoint.
1642
+ pollAsyncImage: ((conversationId: string) => Promise<ImagePointerRef[]>) | null,
1643
+ // Optional poller for GPT-5.5 Pro's stream_handoff path. Inline text keeps
1644
+ // streaming as-is; once ChatGPT hands off, we append the final assistant
1645
+ // answer fetched from the conversation detail endpoint. Text requests stay
1646
+ // in Temporary Chat, so these polls should not create sidebar/history items.
1647
+ pollFinalAnswer: ((conversationId: string) => Promise<FinalAssistantAnswer | null>) | null,
1648
+ log: { warn?: (tag: string, msg: string) => void } | null,
1649
+ signal?: AbortSignal | null
1650
+ ): ReadableStream<Uint8Array> {
1651
+ const encoder = new TextEncoder();
1652
+
1653
+ return new ReadableStream(
1654
+ {
1655
+ async start(controller) {
1656
+ try {
1657
+ controller.enqueue(
1658
+ encoder.encode(
1659
+ sseChunk({
1660
+ id: cid,
1661
+ object: "chat.completion.chunk",
1662
+ created,
1663
+ model,
1664
+ system_fingerprint: null,
1665
+ choices: [
1666
+ { index: 0, delta: { role: "assistant" }, finish_reason: null, logprobs: null },
1667
+ ],
1668
+ })
1669
+ )
1670
+ );
1671
+
1672
+ let conversationId: string | null = null;
1673
+ let imagePointers: ImagePointerRef[] | undefined;
1674
+ let imageGenAsync = false;
1675
+ let handoff = false;
1676
+ let emittedText = "";
1677
+ let polledFinalAnswer = "";
1678
+ let parentCandidateMessageId: string | null = null;
1679
+
1680
+ const emitTextDelta = (content: string): void => {
1681
+ const cleaned = cleanChatGptText(content);
1682
+ if (!cleaned) return;
1683
+ emittedText += cleaned;
1684
+ controller.enqueue(
1685
+ encoder.encode(
1686
+ sseChunk({
1687
+ id: cid,
1688
+ object: "chat.completion.chunk",
1689
+ created,
1690
+ model,
1691
+ system_fingerprint: null,
1692
+ choices: [
1693
+ {
1694
+ index: 0,
1695
+ delta: { content: cleaned },
1696
+ finish_reason: null,
1697
+ logprobs: null,
1698
+ },
1699
+ ],
1700
+ })
1701
+ )
1702
+ );
1703
+ };
1704
+
1705
+ const appendFinalAnswer = (text: string): void => {
1706
+ const cleaned = cleanChatGptText(text);
1707
+ const finalTrimmed = cleaned.trim();
1708
+ if (!finalTrimmed) return;
1709
+ const emittedTrimmed = emittedText.trim();
1710
+ if (emittedTrimmed === finalTrimmed || emittedTrimmed.endsWith(finalTrimmed)) return;
1711
+ const prefix = emittedTrimmed && !emittedText.endsWith("\n") ? "\n\n" : "";
1712
+ emitTextDelta(`${prefix}${cleaned}`);
1713
+ };
1714
+
1715
+ // Heartbeat: long async work (Pro polling, WebSocket image-gen,
1716
+ // 2-3 MB image fetch) leaves the SSE quiet and Open WebUI times out
1717
+ // at ~30s (`disconnect: ResponseAborted`). SSE comments and empty
1718
+ // `delta:{}` chunks are both filtered upstream
1719
+ // (`hasValuableContent` in open-sse/utils/streamHelpers.ts), so
1720
+ // heartbeats are zero-width-space content deltas (`"​"`): they pass
1721
+ // the filter and render invisibly.
1722
+ const startHeartbeat = (intervalMs = 5_000): (() => void) => {
1723
+ const heartbeatChunk = sseChunk({
1724
+ id: cid,
1725
+ object: "chat.completion.chunk",
1726
+ created,
1727
+ model,
1728
+ system_fingerprint: null,
1729
+ choices: [{ index: 0, delta: { content: "​" }, finish_reason: null, logprobs: null }],
1730
+ });
1731
+ const timer = setInterval(() => {
1732
+ try {
1733
+ controller.enqueue(encoder.encode(heartbeatChunk));
1734
+ } catch {
1735
+ // Controller may already be closed if the client disconnected
1736
+ // — just stop firing.
1737
+ console.warn("[chatgpt-web] heartbeat enqueue failed - controller closed");
1738
+ clearInterval(timer);
1739
+ }
1740
+ }, intervalMs);
1741
+ return () => clearInterval(timer);
1742
+ };
1743
+
1744
+ for await (const chunk of extractContent(eventStream, signal)) {
1745
+ if (chunk.conversationId) conversationId = chunk.conversationId;
1746
+ if (chunk.messageId) parentCandidateMessageId = chunk.messageId;
1747
+ if (chunk.handoff) handoff = true;
1748
+ if (chunk.error) {
1749
+ controller.enqueue(
1750
+ encoder.encode(
1751
+ sseChunk({
1752
+ id: cid,
1753
+ object: "chat.completion.chunk",
1754
+ created,
1755
+ model,
1756
+ system_fingerprint: null,
1757
+ choices: [
1758
+ {
1759
+ index: 0,
1760
+ delta: { content: `[Error: ${chunk.error}]` },
1761
+ finish_reason: null,
1762
+ logprobs: null,
1763
+ },
1764
+ ],
1765
+ })
1766
+ )
1767
+ );
1768
+ break;
1769
+ }
1770
+
1771
+ if (chunk.done) {
1772
+ imagePointers = chunk.imagePointers;
1773
+ imageGenAsync = chunk.imageGenAsync ?? false;
1774
+ handoff = handoff || (chunk.handoff ?? false);
1775
+ if (chunk.messageId) parentCandidateMessageId = chunk.messageId;
1776
+ break;
1777
+ }
1778
+
1779
+ if (chunk.delta) {
1780
+ emitTextDelta(chunk.delta);
1781
+ }
1782
+ }
1783
+
1784
+ if (pollFinalAnswer && conversationId && handoff) {
1785
+ const stopHb = startHeartbeat();
1786
+ try {
1787
+ const polled = await pollFinalAnswer(conversationId);
1788
+ if (polled?.text) {
1789
+ polledFinalAnswer = polled.text;
1790
+ if (polled.messageId) parentCandidateMessageId = polled.messageId;
1791
+ }
1792
+ } finally {
1793
+ stopHb();
1794
+ }
1795
+ }
1796
+
1797
+ if (polledFinalAnswer) {
1798
+ appendFinalAnswer(polledFinalAnswer);
1799
+ }
1800
+
1801
+ // Async image_gen ends the SSE with a "Processing image..."
1802
+ // placeholder; poll the conversation endpoint in the background for
1803
+ // the final pointer (only when in-stream pointers are empty).
1804
+ if (
1805
+ imageGenAsync &&
1806
+ conversationId &&
1807
+ (!imagePointers || imagePointers.length === 0) &&
1808
+ pollAsyncImage
1809
+ ) {
1810
+ // Tell the user something is happening — long polls otherwise
1811
+ // look like a hang on the client side. The "..." plus a typing
1812
+ // cue renders nicely in Open WebUI.
1813
+ controller.enqueue(
1814
+ encoder.encode(
1815
+ sseChunk({
1816
+ id: cid,
1817
+ object: "chat.completion.chunk",
1818
+ created,
1819
+ model,
1820
+ system_fingerprint: null,
1821
+ choices: [
1822
+ {
1823
+ index: 0,
1824
+ delta: { content: "_Generating image…_\n\n" },
1825
+ finish_reason: null,
1826
+ logprobs: null,
1827
+ },
1828
+ ],
1829
+ })
1830
+ )
1831
+ );
1832
+ const stopHb = startHeartbeat();
1833
+ try {
1834
+ const polled = await pollAsyncImage(conversationId);
1835
+ if (polled.length > 0) imagePointers = polled;
1836
+ } catch (err) {
1837
+ log?.warn?.(
1838
+ "CGPT-WEB",
1839
+ `Async image poll failed: ${err instanceof Error ? err.message : String(err)}`
1840
+ );
1841
+ } finally {
1842
+ stopHb();
1843
+ }
1844
+ }
1845
+
1846
+ // Resolve and append any image markdown after the text deltas finish
1847
+ // streaming. Downloading and caching the image bytes can take 1-3
1848
+ // seconds for big images, so keep the heartbeat running here too.
1849
+ const stopHb2 = startHeartbeat();
1850
+ let urls: string[] = [];
1851
+ try {
1852
+ urls = await resolveImagePointers(
1853
+ imagePointers,
1854
+ conversationId,
1855
+ resolver,
1856
+ log,
1857
+ parentCandidateMessageId
1858
+ );
1859
+ } finally {
1860
+ stopHb2();
1861
+ }
1862
+ // Bail out cleanly if the client disconnected during the wait —
1863
+ // any further enqueue throws "Invalid state: Controller is
1864
+ // already closed". Better to no-op than to surface that as a
1865
+ // server error.
1866
+ if (signal?.aborted) return;
1867
+ const mdBlock = imageMarkdown(urls);
1868
+ const safeEnqueue = (bytes: Uint8Array): boolean => {
1869
+ try {
1870
+ controller.enqueue(bytes);
1871
+ return true;
1872
+ } catch {
1873
+ console.warn("[chatgpt-web] controller enqueue failed");
1874
+ return false;
1875
+ }
1876
+ };
1877
+ // The image markdown is now a small URL (we cache the bytes in
1878
+ // memory and serve them at /v1/chatgpt-web/image/<id>), so a
1879
+ // single SSE chunk is fine — no aiohttp LineTooLong concerns
1880
+ // and the markdown renderer in Open WebUI sees the URL whole
1881
+ // and renders an `<img>` immediately.
1882
+ if (mdBlock) {
1883
+ if (
1884
+ !safeEnqueue(
1885
+ encoder.encode(
1886
+ sseChunk({
1887
+ id: cid,
1888
+ object: "chat.completion.chunk",
1889
+ created,
1890
+ model,
1891
+ system_fingerprint: null,
1892
+ choices: [
1893
+ {
1894
+ index: 0,
1895
+ delta: { content: mdBlock },
1896
+ finish_reason: null,
1897
+ logprobs: null,
1898
+ },
1899
+ ],
1900
+ })
1901
+ )
1902
+ )
1903
+ )
1904
+ return;
1905
+ }
1906
+
1907
+ if (
1908
+ !safeEnqueue(
1909
+ encoder.encode(
1910
+ sseChunk({
1911
+ id: cid,
1912
+ object: "chat.completion.chunk",
1913
+ created,
1914
+ model,
1915
+ system_fingerprint: null,
1916
+ choices: [{ index: 0, delta: {}, finish_reason: "stop", logprobs: null }],
1917
+ })
1918
+ )
1919
+ )
1920
+ )
1921
+ return;
1922
+ safeEnqueue(encoder.encode("data: [DONE]\n\n"));
1923
+ } catch (err) {
1924
+ controller.enqueue(
1925
+ encoder.encode(
1926
+ sseChunk({
1927
+ id: cid,
1928
+ object: "chat.completion.chunk",
1929
+ created,
1930
+ model,
1931
+ system_fingerprint: null,
1932
+ choices: [
1933
+ {
1934
+ index: 0,
1935
+ delta: {
1936
+ content: `[Stream error: ${err instanceof Error ? err.message : String(err)}]`,
1937
+ },
1938
+ finish_reason: "stop",
1939
+ logprobs: null,
1940
+ },
1941
+ ],
1942
+ })
1943
+ )
1944
+ );
1945
+ controller.enqueue(encoder.encode("data: [DONE]\n\n"));
1946
+ } finally {
1947
+ try {
1948
+ controller.close();
1949
+ } catch {}
1950
+ }
1951
+ },
1952
+ },
1953
+ { highWaterMark: 16384 }
1954
+ );
1955
+ }
1956
+
1957
+ async function buildNonStreamingResponse(
1958
+ eventStream: ReadableStream<Uint8Array>,
1959
+ model: string,
1960
+ cid: string,
1961
+ created: number,
1962
+ currentMsg: string,
1963
+ resolver: ImageResolver | null,
1964
+ pollAsyncImage: ((conversationId: string) => Promise<ImagePointerRef[]>) | null,
1965
+ pollFinalAnswer: ((conversationId: string) => Promise<FinalAssistantAnswer | null>) | null,
1966
+ log: { warn?: (tag: string, msg: string) => void } | null,
1967
+ signal?: AbortSignal | null
1968
+ ): Promise<Response> {
1969
+ let fullAnswer = "";
1970
+ let conversationId: string | null = null;
1971
+ let imagePointers: ImagePointerRef[] | undefined;
1972
+ let imageGenAsync = false;
1973
+ let handoff = false;
1974
+ let parentCandidateMessageId: string | null = null;
1975
+
1976
+ for await (const chunk of extractContent(eventStream, signal)) {
1977
+ if (chunk.conversationId) conversationId = chunk.conversationId;
1978
+ if (chunk.messageId) parentCandidateMessageId = chunk.messageId;
1979
+ if (chunk.handoff) handoff = true;
1980
+ if (chunk.error) {
1981
+ return new Response(
1982
+ JSON.stringify({
1983
+ error: { message: chunk.error, type: "upstream_error", code: "CHATGPT_ERROR" },
1984
+ }),
1985
+ { status: 502, headers: { "Content-Type": "application/json" } }
1986
+ );
1987
+ }
1988
+ if (chunk.done) {
1989
+ fullAnswer = chunk.answer || fullAnswer;
1990
+ imagePointers = chunk.imagePointers;
1991
+ imageGenAsync = chunk.imageGenAsync ?? false;
1992
+ handoff = handoff || (chunk.handoff ?? false);
1993
+ if (chunk.messageId) parentCandidateMessageId = chunk.messageId;
1994
+ break;
1995
+ }
1996
+ if (chunk.answer) fullAnswer = chunk.answer;
1997
+ }
1998
+
1999
+ if (pollFinalAnswer && conversationId && (handoff || !fullAnswer.trim())) {
2000
+ const polled = await pollFinalAnswer(conversationId);
2001
+ if (polled?.text) {
2002
+ fullAnswer = polled.text;
2003
+ if (polled.messageId) parentCandidateMessageId = polled.messageId;
2004
+ }
2005
+ }
2006
+
2007
+ fullAnswer = cleanChatGptText(fullAnswer);
2008
+
2009
+ // Async image gen: SSE ended with "Processing image..." — poll for the
2010
+ // final pointer the same way the streaming path does.
2011
+ if (
2012
+ imageGenAsync &&
2013
+ conversationId &&
2014
+ (!imagePointers || imagePointers.length === 0) &&
2015
+ pollAsyncImage
2016
+ ) {
2017
+ try {
2018
+ const polled = await pollAsyncImage(conversationId);
2019
+ if (polled.length > 0) imagePointers = polled;
2020
+ } catch (err) {
2021
+ log?.warn?.(
2022
+ "CGPT-WEB",
2023
+ `Async image poll failed: ${err instanceof Error ? err.message : String(err)}`
2024
+ );
2025
+ }
2026
+ }
2027
+
2028
+ const urls = await resolveImagePointers(
2029
+ imagePointers,
2030
+ conversationId,
2031
+ resolver,
2032
+ log,
2033
+ parentCandidateMessageId
2034
+ );
2035
+ // The image genuinely exists upstream but no pointer resolved to a URL
2036
+ // (unknown asset scheme, download 403/expired, oversize). Flag it so the
2037
+ // image-generation handler can report an accurate "generated but not
2038
+ // retrievable" error instead of the misleading "no image markdown" 502.
2039
+ const imageResolutionFailed = detectImageResolutionFailure(
2040
+ imagePointers?.length ?? 0,
2041
+ urls.length
2042
+ );
2043
+ if (imageResolutionFailed && log?.warn) {
2044
+ const schemes = (imagePointers ?? [])
2045
+ .map((p) => p.pointer.split("://")[0] || p.pointer.slice(0, 24))
2046
+ .join(", ");
2047
+ log.warn(
2048
+ "CGPT-WEB",
2049
+ `Image generated upstream but no asset pointer resolved (schemes: ${schemes}) — surfacing as unretrievable`
2050
+ );
2051
+ }
2052
+ fullAnswer += imageMarkdown(urls);
2053
+ const promptTokens = Math.ceil(currentMsg.length / 4);
2054
+ const completionTokens = Math.ceil(fullAnswer.length / 4);
2055
+
2056
+ return new Response(
2057
+ JSON.stringify({
2058
+ id: cid,
2059
+ object: "chat.completion",
2060
+ created,
2061
+ model,
2062
+ system_fingerprint: null,
2063
+ ...(imageResolutionFailed ? { x_image_resolution_failed: true } : {}),
2064
+ choices: [
2065
+ {
2066
+ index: 0,
2067
+ message: { role: "assistant", content: fullAnswer },
2068
+ finish_reason: "stop",
2069
+ logprobs: null,
2070
+ },
2071
+ ],
2072
+ usage: {
2073
+ prompt_tokens: promptTokens,
2074
+ completion_tokens: completionTokens,
2075
+ total_tokens: promptTokens + completionTokens,
2076
+ },
2077
+ }),
2078
+ { status: 200, headers: { "Content-Type": "application/json" } }
2079
+ );
2080
+ }
2081
+
2082
+ // ─── Error response helpers ─────────────────────────────────────────────────
2083
+
2084
+ function errorResponse(status: number, message: string, code?: string): Response {
2085
+ return new Response(
2086
+ JSON.stringify({ error: { message, type: "upstream_error", ...(code ? { code } : {}) } }),
2087
+ { status, headers: { "Content-Type": "application/json" } }
2088
+ );
2089
+ }
2090
+
2091
+ function normalizePublicBaseUrl(value?: string | null): string | null {
2092
+ const trimmed = value?.trim();
2093
+ if (!trimmed) return null;
2094
+ return trimmed.replace(/\/+$/, "").replace(/\/v1$/i, "");
2095
+ }
2096
+
2097
+ function firstForwardedValue(value?: string | null): string | null {
2098
+ const first = value?.split(",")[0]?.trim();
2099
+ return first || null;
2100
+ }
2101
+
2102
+ function isLocalBaseUrl(baseUrl: string): boolean {
2103
+ try {
2104
+ const host = new URL(baseUrl).hostname.toLowerCase();
2105
+ return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "0.0.0.0";
2106
+ } catch {
2107
+ console.warn("[chatgpt-web] URL parse failed, falling back to regex");
2108
+ return /\b(?:localhost|127\.0\.0\.1|0\.0\.0\.0)\b/i.test(baseUrl);
2109
+ }
2110
+ }
2111
+
2112
+ function deriveHeaderBaseUrl(clientHeaders?: Record<string, string> | null): string | null {
2113
+ const headers = clientHeaders ?? {};
2114
+ const lower: Record<string, string> = {};
2115
+ for (const [k, v] of Object.entries(headers)) lower[k.toLowerCase()] = v;
2116
+
2117
+ const forwardedHost = firstForwardedValue(lower["x-forwarded-host"]);
2118
+ const forwardedProto = firstForwardedValue(lower["x-forwarded-proto"]);
2119
+ const host = forwardedHost || firstForwardedValue(lower["host"]);
2120
+ if (!host) return null;
2121
+
2122
+ // Default to http for IPs, localhost, and explicit host:port values where
2123
+ // TLS is not a safe assumption. Reverse proxies can override via
2124
+ // x-forwarded-proto, and deployments can force the exact value with
2125
+ // OMNIROUTE_PUBLIC_BASE_URL.
2126
+ const isPlain =
2127
+ host.includes("localhost") ||
2128
+ /^\d+\.\d+\.\d+\.\d+(:\d+)?$/.test(host) ||
2129
+ host.endsWith(".local") ||
2130
+ host.includes(":");
2131
+ const proto = forwardedProto || (isPlain ? "http" : "https");
2132
+ return `${proto}://${host}`;
2133
+ }
2134
+
2135
+ /**
2136
+ * Build the absolute base URL the client should use to fetch our cached
2137
+ * images at /v1/chatgpt-web/image/<id>. The most reliable value is an
2138
+ * explicit browser-facing origin because relay clients such as Open WebUI
2139
+ * often reach OmniRoute from a container while the user's browser needs a
2140
+ * LAN, tunnel, or reverse-proxy URL.
2141
+ */
2142
+ function derivePublicBaseUrl(
2143
+ clientHeaders?: Record<string, string> | null,
2144
+ log?: { debug?: (tag: string, msg: string) => void }
2145
+ ): string {
2146
+ const explicitPublicBase = normalizePublicBaseUrl(process.env.OMNIROUTE_PUBLIC_BASE_URL);
2147
+ if (explicitPublicBase) {
2148
+ log?.debug?.("CGPT-WEB", `derivePublicBaseUrl: using OMNIROUTE_PUBLIC_BASE_URL`);
2149
+ return explicitPublicBase;
2150
+ }
2151
+
2152
+ const headerBase = deriveHeaderBaseUrl(clientHeaders);
2153
+ const configuredBase =
2154
+ normalizePublicBaseUrl(process.env.OMNIROUTE_BASE_URL) ||
2155
+ normalizePublicBaseUrl(process.env.NEXT_PUBLIC_BASE_URL);
2156
+
2157
+ log?.debug?.(
2158
+ "CGPT-WEB",
2159
+ `derivePublicBaseUrl: configured=${configuredBase ?? "-"} header=${headerBase ?? "-"}`
2160
+ );
2161
+
2162
+ if (configuredBase && (!headerBase || !isLocalBaseUrl(configuredBase))) return configuredBase;
2163
+ if (headerBase) return headerBase;
2164
+ if (configuredBase) return configuredBase;
2165
+
2166
+ return `http://localhost:${process.env.PORT || 20128}`;
2167
+ }
2168
+
2169
+ // ─── Image asset resolution ────────────────────────────────────────────────
2170
+ // ChatGPT's image_gen tool emits `image_asset_pointer` parts whose
2171
+ // `asset_pointer` is one of:
2172
+ //
2173
+ // file-service://file-XXXX → resolved via /backend-api/files/{id}/download
2174
+ // sediment://file-XXXX → resolved via /backend-api/conversation/{conv_id}/attachment/{id}/download
2175
+ //
2176
+ // Both endpoints return JSON `{ download_url: "<azure-blob-sas-url>", ... }`.
2177
+ // The signed URL has a limited lifetime (typically a few hours), but that's
2178
+ // usually sufficient for the user to view the image in their UI right after
2179
+ // generation. Persistent storage can be layered on later if needed.
2180
+
2181
+ const FILE_SERVICE_PREFIX = "file-service://";
2182
+ const SEDIMENT_PREFIX = "sediment://";
2183
+
2184
+ interface ResolverContext {
2185
+ accessToken: string;
2186
+ accountId: string | null;
2187
+ sessionId: string;
2188
+ deviceId: string;
2189
+ cookie: string;
2190
+ signal?: AbortSignal | null;
2191
+ log?: { debug?: (tag: string, msg: string) => void; warn?: (tag: string, msg: string) => void };
2192
+ /**
2193
+ * Absolute base URL that downstream clients should use to fetch cached
2194
+ * images served by /v1/chatgpt-web/image/<id>. Derived from the inbound
2195
+ * request host so the URL is reachable from whatever network the client
2196
+ * came in on (localhost, Tailscale, cloudflared tunnel, etc.).
2197
+ */
2198
+ publicBaseUrl: string;
2199
+ }
2200
+
2201
+ async function fetchDownloadUrl(endpoint: string, ctx: ResolverContext): Promise<string | null> {
2202
+ const headers: Record<string, string> = {
2203
+ ...browserHeaders(),
2204
+ ...oaiHeaders(ctx.sessionId, ctx.deviceId),
2205
+ Accept: "application/json",
2206
+ Authorization: `Bearer ${ctx.accessToken}`,
2207
+ Cookie: buildSessionCookieHeader(ctx.cookie),
2208
+ };
2209
+ if (ctx.accountId) headers["chatgpt-account-id"] = ctx.accountId;
2210
+
2211
+ const response = await tlsFetchChatGpt(endpoint, {
2212
+ method: "GET",
2213
+ headers,
2214
+ timeoutMs: 30_000,
2215
+ signal: ctx.signal,
2216
+ });
2217
+ if (response.status !== 200) {
2218
+ ctx.log?.warn?.(
2219
+ "CGPT-WEB",
2220
+ `Image download URL fetch failed (${response.status}) for ${endpoint}`
2221
+ );
2222
+ return null;
2223
+ }
2224
+ let parsed: { download_url?: string } = {};
2225
+ try {
2226
+ parsed = JSON.parse(response.text || "{}");
2227
+ } catch {
2228
+ console.warn("[chatgpt-web] image download URL parse failed");
2229
+ return null;
2230
+ }
2231
+ return parsed.download_url ?? null;
2232
+ }
2233
+
2234
+ /**
2235
+ * Download a chatgpt.com signed image URL and re-serve it from OmniRoute's
2236
+ * short-lived image cache. The URLs returned by /files/<id>/download and
2237
+ * /conversation/<cid>/attachment/<fid>/download point at chatgpt.com's
2238
+ * estuary endpoint, which 403s for any request without the user's session
2239
+ * cookie. Downstream clients (Open WebUI, OpenAI-compatible apps) won't
2240
+ * have those cookies, so we download once via the authenticated TLS client
2241
+ * and return a browser-fetchable OmniRoute URL.
2242
+ */
2243
+ const IMAGE_DOWNLOAD_MAX_BYTES = 8 * 1024 * 1024;
2244
+
2245
+ async function imageUrlToCachedImageUrl(
2246
+ signedUrl: string,
2247
+ ctx: ResolverContext,
2248
+ imageContext?: ChatGptImageConversationContext
2249
+ ): Promise<string | null> {
2250
+ const headers: Record<string, string> = {
2251
+ ...browserHeaders(),
2252
+ Accept: "image/*,*/*;q=0.8",
2253
+ Authorization: `Bearer ${ctx.accessToken}`,
2254
+ Cookie: buildSessionCookieHeader(ctx.cookie),
2255
+ };
2256
+ if (ctx.accountId) headers["chatgpt-account-id"] = ctx.accountId;
2257
+
2258
+ let response: TlsFetchResult;
2259
+ try {
2260
+ response = await tlsFetchChatGpt(signedUrl, {
2261
+ method: "GET",
2262
+ headers,
2263
+ timeoutMs: 60_000,
2264
+ signal: ctx.signal,
2265
+ // Required for binary payloads — the underlying tls-client returns
2266
+ // bytes as a `data:<mime>;base64,...` string when this is true.
2267
+ // Without it, raw image bytes get mangled by UTF-8 decoding.
2268
+ byteResponse: true,
2269
+ });
2270
+ } catch (err) {
2271
+ ctx.log?.warn?.(
2272
+ "CGPT-WEB",
2273
+ `Image fetch failed: ${err instanceof Error ? err.message : String(err)}`
2274
+ );
2275
+ return null;
2276
+ }
2277
+
2278
+ if (response.status !== 200) {
2279
+ ctx.log?.warn?.(
2280
+ "CGPT-WEB",
2281
+ `Image fetch returned HTTP ${response.status} (${(response.text || "").slice(0, 120)})`
2282
+ );
2283
+ return null;
2284
+ }
2285
+
2286
+ if (response.text == null || response.text.length === 0) return null;
2287
+
2288
+ // tls-client-node already returns binary bodies as a "data:<mime>;base64,..."
2289
+ // string (see node_modules/tls-client-node/dist/response.js — its bytes()
2290
+ // method splits on the comma to extract base64). Decode back into bytes
2291
+ // so we can hand them to the cache.
2292
+ let bytes: Buffer;
2293
+ let mime: string;
2294
+ if (/^data:[^;]{1,256};base64,/.test(response.text)) {
2295
+ const commaIdx = response.text.indexOf(",");
2296
+ const header = response.text.slice(5, commaIdx); // strip "data:"
2297
+ mime = header.split(";")[0] || "image/png";
2298
+ bytes = Buffer.from(response.text.slice(commaIdx + 1), "base64");
2299
+ } else {
2300
+ // Plain-text body (shouldn't happen for binary downloads with
2301
+ // byteResponse:true, but handle defensively).
2302
+ bytes = Buffer.from(response.text, "binary");
2303
+ mime = response.headers.get("content-type")?.split(";")[0]?.trim() || "image/png";
2304
+ }
2305
+ if (bytes.length === 0 || bytes.length > IMAGE_DOWNLOAD_MAX_BYTES) {
2306
+ if (bytes.length > IMAGE_DOWNLOAD_MAX_BYTES) {
2307
+ ctx.log?.warn?.(
2308
+ "CGPT-WEB",
2309
+ `Image too large to cache (${bytes.length} bytes > ${IMAGE_DOWNLOAD_MAX_BYTES}); skipping`
2310
+ );
2311
+ }
2312
+ return null;
2313
+ }
2314
+ // Cache the image and return a stable HTTP URL pointing at our own
2315
+ // /v1/chatgpt-web/image/<id> route. Streaming the raw base64 back via
2316
+ // SSE deltas works but Open WebUI's progressive markdown renderer shows
2317
+ // each chunk as plain text mid-stream — the user sees megabytes of
2318
+ // base64 scroll past before the image renders. URL-based delivery
2319
+ // produces a small markdown delta and renders instantly when the
2320
+ // browser fetches the URL.
2321
+ const id = storeChatGptImage(bytes, mime, undefined, imageContext);
2322
+ return `${ctx.publicBaseUrl}/v1/chatgpt-web/image/${id}`;
2323
+ }
2324
+
2325
+ /**
2326
+ * Resolve the async image_gen result by registering a WebSocket with
2327
+ * chatgpt.com and listening for the image_asset_pointer.
2328
+ *
2329
+ * Background: when chatgpt.com is busy ("Lots of people are creating images
2330
+ * right now") the image_gen tool defers — the initial SSE finishes with a
2331
+ * "Processing image..." placeholder and the real image arrives over a
2332
+ * WebSocket pubsub. (We checked: the conversation tree at
2333
+ * `/backend-api/conversation/{id}` is NOT updated when the image lands, so
2334
+ * polling that endpoint does nothing.)
2335
+ *
2336
+ * Flow:
2337
+ * 1. POST /backend-api/register-websocket → { wss_url, expires_at, ... }
2338
+ * 2. Open the wss_url with the standard WebSocket client.
2339
+ * Auth lives in the URL (signed access token), so we don't need the
2340
+ * TLS-impersonation transport here.
2341
+ * 3. Each WS message is JSON like { type: "wss-message", data: { ...
2342
+ * conversation event ... } }. The conversation event has the same
2343
+ * shape as the SSE events from /backend-api/f/conversation.
2344
+ * 4. Watch for assistant messages with multimodal_text + image_asset_pointer
2345
+ * OR a `message_stream_complete` for the conversation. Resolve when
2346
+ * either pointer arrives or the timeout fires.
2347
+ */
2348
+ async function registerWebSocket(ctx: ResolverContext): Promise<string | null> {
2349
+ // chatgpt.com migrated from POST /backend-api/register-websocket to a
2350
+ // GET-only endpoint under /backend-api/celsius/ws/user. The response shape
2351
+ // also changed from `{ wss_url }` → `{ websocket_url }`. Newer codebases
2352
+ // (g4f, etc.) all hit the celsius path; the legacy path now 404s.
2353
+ // Keep the legacy path as a fallback for older deployments.
2354
+ const candidates = [
2355
+ { url: `${CHATGPT_BASE}/backend-api/celsius/ws/user`, method: "GET" as const },
2356
+ { url: `${CHATGPT_BASE}/backend-api/register-websocket`, method: "POST" as const },
2357
+ ];
2358
+ const headers: Record<string, string> = {
2359
+ ...browserHeaders(),
2360
+ ...oaiHeaders(ctx.sessionId, ctx.deviceId),
2361
+ Accept: "application/json",
2362
+ Authorization: `Bearer ${ctx.accessToken}`,
2363
+ Cookie: buildSessionCookieHeader(ctx.cookie),
2364
+ };
2365
+ if (ctx.accountId) headers["chatgpt-account-id"] = ctx.accountId;
2366
+
2367
+ for (const { url, method } of candidates) {
2368
+ let r: TlsFetchResult;
2369
+ try {
2370
+ r = await tlsFetchChatGpt(url, {
2371
+ method,
2372
+ headers,
2373
+ body: method === "POST" ? "" : undefined,
2374
+ timeoutMs: 30_000,
2375
+ signal: ctx.signal,
2376
+ });
2377
+ } catch (err) {
2378
+ ctx.log?.warn?.(
2379
+ "CGPT-WEB",
2380
+ `register-websocket fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`
2381
+ );
2382
+ continue;
2383
+ }
2384
+ if (r.status === 200) {
2385
+ try {
2386
+ const data = JSON.parse(r.text || "{}") as {
2387
+ websocket_url?: string;
2388
+ wss_url?: string;
2389
+ };
2390
+ const ws = data.websocket_url ?? data.wss_url;
2391
+ if (ws) {
2392
+ ctx.log?.debug?.("CGPT-WEB", `Got WebSocket URL via ${url}`);
2393
+ return ws;
2394
+ }
2395
+ } catch {
2396
+ console.warn("[chatgpt-web] WebSocket URL parse failed, falling through");
2397
+ /* fall through */
2398
+ }
2399
+ }
2400
+ ctx.log?.warn?.(
2401
+ "CGPT-WEB",
2402
+ `register-websocket via ${url} → ${r.status}: ${(r.text || "").slice(0, 200)}`
2403
+ );
2404
+ }
2405
+ return null;
2406
+ }
2407
+
2408
+ interface WsWaitOutcome {
2409
+ pointers: ImagePointerRef[];
2410
+ /** True if the connection emitted an error event. Used by the retry layer
2411
+ * to decide whether a transport blip is worth a second attempt. */
2412
+ errored: boolean;
2413
+ /** True if any frame (message or open) was actually received from the
2414
+ * server. A retry is most valuable when the connection died before
2415
+ * exchanging any data. */
2416
+ gotAnyMessage: boolean;
2417
+ }
2418
+
2419
+ async function waitForImageViaWebSocket(
2420
+ wssUrl: string,
2421
+ conversationId: string,
2422
+ timeoutMs: number,
2423
+ ctx: ResolverContext
2424
+ ): Promise<WsWaitOutcome> {
2425
+ return new Promise((resolve) => {
2426
+ const found = new Map<string, ImagePointerRef>();
2427
+ let resolved = false;
2428
+ let errored = false;
2429
+ let gotAnyMessage = false;
2430
+ const finish = () => {
2431
+ if (resolved) return;
2432
+ resolved = true;
2433
+ try {
2434
+ ws.close();
2435
+ } catch {
2436
+ console.warn("[chatgpt-web] ws.close failed");
2437
+ /* ignore */
2438
+ }
2439
+ resolve({
2440
+ pointers: Array.from(found.values()),
2441
+ errored,
2442
+ gotAnyMessage,
2443
+ });
2444
+ };
2445
+ const ws = new WebSocket(wssUrl);
2446
+ const timer = setTimeout(() => {
2447
+ ctx.log?.warn?.("CGPT-WEB", `WebSocket image wait timed out after ${timeoutMs}ms`);
2448
+ finish();
2449
+ }, timeoutMs);
2450
+ const onAbort = () => {
2451
+ ctx.log?.debug?.("CGPT-WEB", "WebSocket aborted by client");
2452
+ finish();
2453
+ };
2454
+ ctx.signal?.addEventListener?.("abort", onAbort);
2455
+ ws.onopen = () => {
2456
+ gotAnyMessage = true;
2457
+ ctx.log?.debug?.("CGPT-WEB", "WebSocket open — waiting for image events");
2458
+ };
2459
+ ws.onerror = (e) => {
2460
+ errored = true;
2461
+ ctx.log?.warn?.("CGPT-WEB", `WebSocket error: ${(e as ErrorEvent).message ?? "unknown"}`);
2462
+ };
2463
+ ws.onclose = () => {
2464
+ clearTimeout(timer);
2465
+ ctx.signal?.removeEventListener?.("abort", onAbort);
2466
+ finish();
2467
+ };
2468
+ ws.onmessage = (event) => {
2469
+ gotAnyMessage = true;
2470
+ let payload: unknown;
2471
+ const raw = typeof event.data === "string" ? event.data : event.data.toString();
2472
+ try {
2473
+ payload = JSON.parse(raw);
2474
+ } catch {
2475
+ console.warn("[chatgpt-web] WebSocket event JSON parse failed");
2476
+ return;
2477
+ }
2478
+ // chatgpt.com's celsius WS frames look like:
2479
+ // { type: "conversation-update",
2480
+ // payload: { conversation_id: "...",
2481
+ // update_content: { message: { ... }, ... } } }
2482
+ // Older deployments wrapped the conversation event directly as { data }.
2483
+ const obj = payload as Record<string, unknown>;
2484
+ const candidates: ChatGptStreamEvent[] = [];
2485
+ const innerPayload = obj.payload as Record<string, unknown> | undefined;
2486
+ const updateContent = innerPayload?.update_content as Record<string, unknown> | undefined;
2487
+ if (updateContent?.message) {
2488
+ candidates.push({
2489
+ message: updateContent.message as ChatGptStreamEvent["message"],
2490
+ conversation_id: innerPayload?.conversation_id as string | undefined,
2491
+ });
2492
+ }
2493
+ if (innerPayload?.message) {
2494
+ candidates.push({
2495
+ message: innerPayload.message as ChatGptStreamEvent["message"],
2496
+ conversation_id: innerPayload.conversation_id as string | undefined,
2497
+ });
2498
+ }
2499
+ if ((obj.data as { message?: unknown } | undefined)?.message) {
2500
+ candidates.push(obj.data as ChatGptStreamEvent);
2501
+ }
2502
+
2503
+ for (const data of candidates) {
2504
+ if (data?.conversation_id && data.conversation_id !== conversationId) continue;
2505
+ const m = data?.message;
2506
+ // The async image_gen result arrives as a TOOL-role message
2507
+ // ({"author":{"role":"tool","name":"t2uay3k.sj1i4kz"}}), so we
2508
+ // accept tool messages here too — extractImagePointers does the
2509
+ // actual content_type filtering.
2510
+ if (Array.isArray(m?.content?.parts)) {
2511
+ for (const ptr of extractImagePointers(m.content?.parts ?? [])) {
2512
+ const existing = found.get(ptr);
2513
+ found.set(
2514
+ ptr,
2515
+ existing?.messageId
2516
+ ? existing
2517
+ : { pointer: ptr, ...(m?.id ? { messageId: m.id } : {}) }
2518
+ );
2519
+ }
2520
+ }
2521
+ if (m?.metadata && typeof m.metadata === "object") {
2522
+ const md = m.metadata as Record<string, unknown>;
2523
+ const ptr = (md.asset_pointer ?? md.image_asset_pointer) as string | undefined;
2524
+ if (typeof ptr === "string") {
2525
+ const existing = found.get(ptr);
2526
+ found.set(
2527
+ ptr,
2528
+ existing?.messageId
2529
+ ? existing
2530
+ : { pointer: ptr, ...(m?.id ? { messageId: m.id } : {}) }
2531
+ );
2532
+ }
2533
+ }
2534
+ }
2535
+ if (found.size > 0) finish();
2536
+ };
2537
+ });
2538
+ }
2539
+
2540
+ // Default 3-minute wait for the async image_gen tool to produce an image
2541
+ // pointer over the celsius WebSocket. Tunable so deployments can stretch
2542
+ // during chatgpt.com queue-deep windows ("Lots of people are creating
2543
+ // images right now") without code changes.
2544
+ const DEFAULT_ASYNC_IMAGE_TIMEOUT_MS = 180_000;
2545
+
2546
+ function configuredAsyncImageTimeoutMs(): number {
2547
+ const raw = Number(process.env.OMNIROUTE_CGPT_WEB_IMAGE_TIMEOUT_MS);
2548
+ if (!Number.isFinite(raw) || raw <= 0) return DEFAULT_ASYNC_IMAGE_TIMEOUT_MS;
2549
+ return Math.floor(raw);
2550
+ }
2551
+
2552
+ async function pollForAsyncImage(
2553
+ conversationId: string,
2554
+ ctx: ResolverContext,
2555
+ opts: { timeoutMs?: number } = {}
2556
+ ): Promise<ImagePointerRef[]> {
2557
+ const totalTimeoutMs = opts.timeoutMs ?? configuredAsyncImageTimeoutMs();
2558
+ const deadline = Date.now() + totalTimeoutMs;
2559
+
2560
+ // One reconnect attempt on transport error: the WS endpoint is signed and
2561
+ // short-lived, and a network blip during the long wait would otherwise
2562
+ // lose the image entirely. The deadline is shared across attempts so we
2563
+ // never exceed the caller's budget.
2564
+ for (let attempt = 0; attempt < 2; attempt++) {
2565
+ const remaining = deadline - Date.now();
2566
+ if (remaining <= 0) break;
2567
+ const wssUrl = await registerWebSocket(ctx);
2568
+ if (!wssUrl) {
2569
+ ctx.log?.warn?.(
2570
+ "CGPT-WEB",
2571
+ attempt === 0
2572
+ ? "Could not register WebSocket — async image gen not retrievable"
2573
+ : `WebSocket re-registration failed on retry attempt ${attempt + 1}`
2574
+ );
2575
+ if (attempt === 0) continue; // try again — registration can be flaky
2576
+ return [];
2577
+ }
2578
+ ctx.log?.debug?.(
2579
+ "CGPT-WEB",
2580
+ `Registered WebSocket for async image (attempt ${attempt + 1}, ${remaining}ms remaining)`
2581
+ );
2582
+ const outcome = await waitForImageViaWebSocket(wssUrl, conversationId, remaining, ctx);
2583
+ if (outcome.pointers.length > 0) return outcome.pointers;
2584
+ if (ctx.signal?.aborted) return [];
2585
+ // Only retry when the connection died before producing anything useful.
2586
+ // A clean close with no pointers (e.g., upstream cancellation) shouldn't
2587
+ // burn a second attempt — the result would be the same.
2588
+ if (!outcome.errored || outcome.gotAnyMessage) return [];
2589
+ ctx.log?.warn?.(
2590
+ "CGPT-WEB",
2591
+ `WebSocket attempt ${attempt + 1} ended in transport error before any frame; retrying`
2592
+ );
2593
+ }
2594
+ return [];
2595
+ }
2596
+
2597
+ function makeImageResolver(ctx: ResolverContext): ImageResolver {
2598
+ // Cache resolutions across the same request — the same pointer can show up
2599
+ // on multiple SSE events (in-progress + finished_successfully). One HTTP
2600
+ // round-trip per unique pointer is enough.
2601
+ const cache = new Map<string, string | null>();
2602
+
2603
+ return async (assetPointer, conversationId, parentMessageId) => {
2604
+ if (cache.has(assetPointer)) return cache.get(assetPointer) ?? null;
2605
+
2606
+ let fileId: string | null = null;
2607
+ if (assetPointer.startsWith(FILE_SERVICE_PREFIX)) {
2608
+ fileId = assetPointer.slice(FILE_SERVICE_PREFIX.length);
2609
+ } else if (assetPointer.startsWith(SEDIMENT_PREFIX)) {
2610
+ fileId = assetPointer.slice(SEDIMENT_PREFIX.length);
2611
+ } else {
2612
+ ctx.log?.warn?.("CGPT-WEB", `Unknown asset_pointer scheme: ${assetPointer}`);
2613
+ }
2614
+
2615
+ let signedUrl: string | null = null;
2616
+ if (fileId) {
2617
+ // Both endpoints return a chatgpt.com estuary URL signed for the
2618
+ // user's current session — that URL 403s without the cookie, so
2619
+ // downstream clients can't fetch it directly. We download once via
2620
+ // the authenticated TLS client and expose the bytes through
2621
+ // OmniRoute's short-lived image cache.
2622
+ //
2623
+ // /files/{id}/download is the historical path. It works for
2624
+ // chat-uploaded files and the older image_gen output format
2625
+ // (`file-XXXX`). Newer image-edit results from continued
2626
+ // conversations land with a `file_00000000XXXX` shape that 422s on
2627
+ // /files/{id}/download — they're conversation-scoped attachments
2628
+ // and only resolve through /conversation/{cid}/attachment/{fid}/
2629
+ // download. We try /files first because it's cheaper and works for
2630
+ // the common case, then fall through.
2631
+ signedUrl = await fetchDownloadUrl(
2632
+ `${CHATGPT_BASE}/backend-api/files/${encodeURIComponent(fileId)}/download`,
2633
+ ctx
2634
+ );
2635
+ if (!signedUrl && conversationId) {
2636
+ signedUrl = await fetchDownloadUrl(
2637
+ `${CHATGPT_BASE}/backend-api/conversation/${encodeURIComponent(conversationId)}/attachment/${encodeURIComponent(fileId)}/download`,
2638
+ ctx
2639
+ );
2640
+ }
2641
+ }
2642
+
2643
+ let finalUrl: string | null = null;
2644
+ if (signedUrl) {
2645
+ // chatgpt.com signed URLs require the user's session cookie to fetch,
2646
+ // so we materialize the bytes into our own cache and emit an OmniRoute
2647
+ // URL. If that fails (oversize, network error, etc.) we return null —
2648
+ // never the signed URL — because handing it back would emit broken
2649
+ // markdown that 403s for the client. Better to drop the image silently
2650
+ // than render a broken link.
2651
+ finalUrl = await imageUrlToCachedImageUrl(
2652
+ signedUrl,
2653
+ ctx,
2654
+ conversationId && parentMessageId ? { conversationId, parentMessageId } : undefined
2655
+ );
2656
+ }
2657
+ cache.set(assetPointer, finalUrl);
2658
+ if (finalUrl) {
2659
+ const preview = finalUrl.startsWith("data:")
2660
+ ? `data:... (${finalUrl.length} chars)`
2661
+ : finalUrl.slice(0, 80) + "...";
2662
+ ctx.log?.debug?.("CGPT-WEB", `Resolved ${assetPointer} → ${preview}`);
2663
+ }
2664
+ return finalUrl;
2665
+ };
2666
+ }
2667
+
2668
+ // ─── Executor ───────────────────────────────────────────────────────────────
2669
+
2670
+ export class ChatGptWebExecutor extends BaseExecutor {
2671
+ constructor() {
2672
+ super("chatgpt-web", { id: "chatgpt-web", baseUrl: CONV_URL });
2673
+ }
2674
+
2675
+ async execute({
2676
+ model,
2677
+ body,
2678
+ stream,
2679
+ credentials,
2680
+ signal,
2681
+ log,
2682
+ onCredentialsRefreshed,
2683
+ clientHeaders,
2684
+ }: ExecuteInput) {
2685
+ const messages = (body as Record<string, unknown> | null)?.messages as
2686
+ Array<Record<string, unknown>> | undefined;
2687
+ if (!messages || !Array.isArray(messages) || messages.length === 0) {
2688
+ return {
2689
+ response: errorResponse(400, "Missing or empty messages array"),
2690
+ url: CONV_URL,
2691
+ headers: {},
2692
+ transformedBody: body,
2693
+ };
2694
+ }
2695
+
2696
+ // Tool-call emulation (#5240): inject a `<tool>` contract when `tools` are
2697
+ // present; parsed back on the response side. Mirrors qwen-web/perplexity-web.
2698
+ const { hasTools, requestedTools, effectiveMessages } = prepareToolMessages(
2699
+ (body || {}) as Record<string, unknown>,
2700
+ messages as Array<{ role: string; content: unknown }>
2701
+ );
2702
+
2703
+ if (!credentials.apiKey) {
2704
+ return {
2705
+ response: errorResponse(
2706
+ 401,
2707
+ "ChatGPT auth failed — paste your __Secure-next-auth.session-token cookie value."
2708
+ ),
2709
+ url: CONV_URL,
2710
+ headers: {},
2711
+ transformedBody: body,
2712
+ };
2713
+ }
2714
+
2715
+ // Pass the user's pasted cookie blob through to exchangeSession; the helper
2716
+ // accepts bare values, unchunked cookies, chunked (.0/.1) cookies, and full
2717
+ // "Cookie: ..." DevTools lines.
2718
+ const cookie = credentials.apiKey;
2719
+
2720
+ // 1. Token exchange
2721
+ let tokenEntry: TokenEntry;
2722
+ try {
2723
+ tokenEntry = await exchangeSession(cookie, signal);
2724
+ } catch (err) {
2725
+ if (err instanceof SessionAuthError) {
2726
+ log?.warn?.("CGPT-WEB", err.message);
2727
+ return {
2728
+ response: errorResponse(
2729
+ 401,
2730
+ "ChatGPT auth failed — re-paste your __Secure-next-auth.session-token cookie from chatgpt.com.",
2731
+ "HTTP_401"
2732
+ ),
2733
+ url: SESSION_URL,
2734
+ headers: {},
2735
+ transformedBody: body,
2736
+ };
2737
+ }
2738
+ log?.error?.(
2739
+ "CGPT-WEB",
2740
+ `Session exchange failed: ${err instanceof Error ? err.message : String(err)}`
2741
+ );
2742
+ return {
2743
+ response: errorResponse(
2744
+ 502,
2745
+ `ChatGPT session exchange failed: ${err instanceof Error ? err.message : String(err)}`
2746
+ ),
2747
+ url: SESSION_URL,
2748
+ headers: {},
2749
+ transformedBody: body,
2750
+ };
2751
+ }
2752
+
2753
+ // Surface any rotated cookie back to the caller so the DB credential is refreshed.
2754
+ if (tokenEntry.refreshedCookie && tokenEntry.refreshedCookie !== cookie) {
2755
+ const updated: ProviderCredentials = { ...credentials, apiKey: tokenEntry.refreshedCookie };
2756
+ try {
2757
+ await onCredentialsRefreshed?.(updated);
2758
+ } catch (err) {
2759
+ log?.warn?.(
2760
+ "CGPT-WEB",
2761
+ `Failed to persist refreshed cookie: ${err instanceof Error ? err.message : String(err)}`
2762
+ );
2763
+ }
2764
+ }
2765
+
2766
+ // 2a. Warmup — GET / to scrape DPL + script src so the prekey looks legit.
2767
+ let dplInfo: { dpl: string; scriptSrc: string };
2768
+ try {
2769
+ dplInfo = await fetchDpl(cookie, signal);
2770
+ } catch (err) {
2771
+ log?.warn?.(
2772
+ "CGPT-WEB",
2773
+ `DPL warmup failed (continuing with fallback): ${err instanceof Error ? err.message : String(err)}`
2774
+ );
2775
+ dplInfo = {
2776
+ dpl: `dpl=${OAI_CLIENT_VERSION.replace(/^prod-/, "")}`,
2777
+ scriptSrc: `${CHATGPT_BASE}/_next/static/chunks/webpack-${randomHex(16)}.js`,
2778
+ };
2779
+ }
2780
+
2781
+ // 2a'. Browser-like session warmup. Sentinel scores the session by whether
2782
+ // the client recently hit /me, /conversations, /models — same as a real
2783
+ // browser does on page load. Failures here are non-fatal; the worst case
2784
+ // is Sentinel still escalates to Turnstile.
2785
+ const sessionId = randomUUID();
2786
+ const deviceId = deviceIdFor(cookie);
2787
+ await runSessionWarmup(
2788
+ tokenEntry.accessToken,
2789
+ tokenEntry.accountId,
2790
+ sessionId,
2791
+ deviceId,
2792
+ cookie,
2793
+ signal,
2794
+ log
2795
+ );
2796
+
2797
+ // 2a''. Resolve model + effort and apply thinking-effort preference for
2798
+ // thinking-capable models. Dedicated thinking models mirror the browser's
2799
+ // user-config PATCH; GPT-5.5 Pro sends the effort with the conversation
2800
+ // body because the Pro standard/extended budget is part of that turn.
2801
+ const resolvedModel = resolveChatGptModel(model, body, credentials.providerSpecificData);
2802
+ const modelSlug = resolvedModel.slug;
2803
+ const requestedEffort = resolvedModel.effort;
2804
+ if (requestedEffort && isThinkingCapableModel(model, modelSlug)) {
2805
+ await setUserThinkingEffort(
2806
+ modelSlug,
2807
+ requestedEffort,
2808
+ tokenEntry.accessToken,
2809
+ tokenEntry.accountId,
2810
+ sessionId,
2811
+ deviceId,
2812
+ cookie,
2813
+ signal,
2814
+ log
2815
+ );
2816
+ }
2817
+
2818
+ // 2b. Sentinel chat-requirements
2819
+ let reqs: ChatRequirements;
2820
+ try {
2821
+ reqs = await prepareChatRequirements(
2822
+ tokenEntry.accessToken,
2823
+ tokenEntry.accountId,
2824
+ sessionId,
2825
+ deviceId,
2826
+ cookie,
2827
+ dplInfo,
2828
+ signal,
2829
+ log
2830
+ );
2831
+ } catch (err) {
2832
+ if (err instanceof SentinelBlockedError) {
2833
+ log?.warn?.("CGPT-WEB", err.message);
2834
+ return {
2835
+ response: errorResponse(
2836
+ 403,
2837
+ "ChatGPT blocked the request (Sentinel/Turnstile required). Try again later or open chatgpt.com in a browser to refresh state.",
2838
+ "SENTINEL_BLOCKED"
2839
+ ),
2840
+ url: SENTINEL_PREPARE_URL,
2841
+ headers: {},
2842
+ transformedBody: body,
2843
+ };
2844
+ }
2845
+ log?.error?.(
2846
+ "CGPT-WEB",
2847
+ `Sentinel failed: ${err instanceof Error ? err.message : String(err)}`
2848
+ );
2849
+ return {
2850
+ response: errorResponse(
2851
+ 502,
2852
+ `ChatGPT sentinel failed: ${err instanceof Error ? err.message : String(err)}`
2853
+ ),
2854
+ url: SENTINEL_PREPARE_URL,
2855
+ headers: {},
2856
+ transformedBody: body,
2857
+ };
2858
+ }
2859
+
2860
+ log?.debug?.(
2861
+ "CGPT-WEB",
2862
+ `sentinel: token=${reqs.token ? "y" : "n"} pow=${reqs.proofofwork?.required ? "y" : "n"} turnstile=${reqs.turnstile?.required ? "y" : "n"}`
2863
+ );
2864
+
2865
+ // Optional: if a turnstile token was supplied via providerSpecificData,
2866
+ // pass it through. Otherwise, send the request anyway — sometimes Sentinel
2867
+ // reports turnstile.required even when the conversation endpoint accepts
2868
+ // requests without it.
2869
+ const turnstileToken =
2870
+ typeof credentials.providerSpecificData?.turnstileToken === "string"
2871
+ ? credentials.providerSpecificData.turnstileToken
2872
+ : null;
2873
+
2874
+ // 3. Solve PoW (if required) — reuses the same browser-fingerprint config
2875
+ // shape as the prekey, just with the server-provided seed + difficulty.
2876
+ let proofToken: string | null = null;
2877
+ if (reqs.proofofwork?.required && reqs.proofofwork.seed && reqs.proofofwork.difficulty) {
2878
+ const powConfig = buildPrekeyConfig(CHATGPT_USER_AGENT, dplInfo.dpl, dplInfo.scriptSrc);
2879
+ proofToken = await solveProofOfWork(
2880
+ reqs.proofofwork.seed,
2881
+ reqs.proofofwork.difficulty,
2882
+ powConfig,
2883
+ log
2884
+ );
2885
+ }
2886
+
2887
+ // 4. Build conversation request
2888
+ const parsed = parseOpenAIMessages(effectiveMessages);
2889
+ if (!parsed.currentMsg.trim() && parsed.history.length === 0) {
2890
+ return {
2891
+ response: errorResponse(400, "Empty user message"),
2892
+ url: CONV_URL,
2893
+ headers: {},
2894
+ transformedBody: body,
2895
+ };
2896
+ }
2897
+
2898
+ // Toggle Temporary Chat off only when ChatGPT needs a durable image
2899
+ // conversation. Text requests, including GPT-5.5 Pro, stay temporary so
2900
+ // they do not show up in the user's chatgpt.com sidebar/history.
2901
+ const imageEdit = looksLikeImageEditRequest(parsed);
2902
+ const continuation = imageEdit ? parsed.latestImageContext : null;
2903
+ const forImageGen = looksLikeImageGenRequest(parsed) || imageEdit;
2904
+ const persistConversation = forImageGen || !!continuation;
2905
+ if (forImageGen) {
2906
+ log?.debug?.(
2907
+ "CGPT-WEB",
2908
+ continuation
2909
+ ? "Image edit intent detected — continuing saved image conversation"
2910
+ : "Image-gen intent detected — disabling Temporary Chat for this turn"
2911
+ );
2912
+ } else if (resolvedModel.isPro) {
2913
+ log?.debug?.("CGPT-WEB", "GPT-5.5 Pro text request — keeping Temporary Chat enabled");
2914
+ }
2915
+
2916
+ const parentMessageId = continuation?.parentMessageId ?? randomUUID();
2917
+ const cgptBody = buildConversationBody(parsed, modelSlug, parentMessageId, {
2918
+ persistConversation,
2919
+ thinkingEffort: requestedEffort,
2920
+ continuation,
2921
+ });
2922
+
2923
+ const headers: Record<string, string> = {
2924
+ ...browserHeaders(),
2925
+ ...oaiHeaders(sessionId, deviceId),
2926
+ "Content-Type": "application/json",
2927
+ Accept: "text/event-stream",
2928
+ Authorization: `Bearer ${tokenEntry.accessToken}`,
2929
+ Cookie: buildSessionCookieHeader(cookie),
2930
+ };
2931
+ if (tokenEntry.accountId) headers["chatgpt-account-id"] = tokenEntry.accountId;
2932
+ if (reqs.token) headers["openai-sentinel-chat-requirements-token"] = reqs.token;
2933
+ if (reqs.prepare_token)
2934
+ headers["openai-sentinel-chat-requirements-prepare-token"] = reqs.prepare_token;
2935
+ if (proofToken) headers["openai-sentinel-proof-token"] = proofToken;
2936
+ if (turnstileToken) headers["openai-sentinel-turnstile-token"] = turnstileToken;
2937
+
2938
+ log?.info?.("CGPT-WEB", `Conversation request → ${modelSlug} (pow=${!!proofToken})`);
2939
+
2940
+ let response: TlsFetchResult;
2941
+ try {
2942
+ response = await tlsFetchChatGpt(CONV_URL, {
2943
+ method: "POST",
2944
+ headers,
2945
+ body: JSON.stringify(cgptBody),
2946
+ timeoutMs: 120_000, // generations can take a while
2947
+ signal,
2948
+ // For real-time streaming, ask the TLS client to write the body to
2949
+ // a temp file and surface it as a ReadableStream as it arrives —
2950
+ // otherwise long generations buffer entirely before the client sees
2951
+ // anything (and the downstream HTTP request can time out).
2952
+ stream,
2953
+ });
2954
+ } catch (err) {
2955
+ log?.error?.("CGPT-WEB", `Fetch failed: ${err instanceof Error ? err.message : String(err)}`);
2956
+ const code = err instanceof TlsClientUnavailableError ? "TLS_UNAVAILABLE" : undefined;
2957
+ return {
2958
+ response: errorResponse(
2959
+ 502,
2960
+ `ChatGPT connection failed: ${err instanceof Error ? err.message : String(err)}`,
2961
+ code
2962
+ ),
2963
+ url: CONV_URL,
2964
+ headers,
2965
+ transformedBody: cgptBody,
2966
+ };
2967
+ }
2968
+
2969
+ if (response.status >= 400) {
2970
+ const status = response.status;
2971
+ // Log the upstream body on 4xx/5xx — error responses are small and the
2972
+ // upstream message is much more useful than our wrapper. Goes through
2973
+ // the executor logger so it respects the application's log config.
2974
+ log?.warn?.("CGPT-WEB", `conv ${status}: ${(response.text || "").slice(0, 400)}`);
2975
+ const errMsg = describeChatGptWebHttpError(status);
2976
+ if (status === 401 || status === 403) {
2977
+ tokenCache.delete(cookieKey(cookie));
2978
+ }
2979
+ log?.warn?.("CGPT-WEB", errMsg);
2980
+ return {
2981
+ response: errorResponse(status, errMsg, `HTTP_${status}`),
2982
+ url: CONV_URL,
2983
+ headers,
2984
+ transformedBody: cgptBody,
2985
+ };
2986
+ }
2987
+
2988
+ // For streaming requests the TLS client returns a ReadableStream that
2989
+ // tails the temp file as it's written. For non-streaming requests, it
2990
+ // returns the full body as text — wrap that in a one-shot stream so the
2991
+ // existing SSE parser can consume it uniformly.
2992
+ let bodyStream: ReadableStream<Uint8Array>;
2993
+ if (response.body) {
2994
+ bodyStream = response.body;
2995
+ } else if (response.text) {
2996
+ bodyStream = stringToStream(response.text);
2997
+ } else {
2998
+ return {
2999
+ response: errorResponse(502, "ChatGPT returned empty response body"),
3000
+ url: CONV_URL,
3001
+ headers,
3002
+ transformedBody: cgptBody,
3003
+ };
3004
+ }
3005
+
3006
+ const cid = `chatcmpl-cgpt-${crypto.randomUUID().slice(0, 12)}`;
3007
+ const created = Math.floor(Date.now() / 1000);
3008
+
3009
+ const resolverCtx: ResolverContext = {
3010
+ accessToken: tokenEntry.accessToken,
3011
+ accountId: tokenEntry.accountId,
3012
+ sessionId,
3013
+ deviceId,
3014
+ cookie,
3015
+ signal,
3016
+ log,
3017
+ publicBaseUrl: derivePublicBaseUrl(clientHeaders, log),
3018
+ };
3019
+ const imageResolver = makeImageResolver(resolverCtx);
3020
+ const pollAsyncImage = (conversationId: string) =>
3021
+ pollForAsyncImage(conversationId, resolverCtx);
3022
+ const pollFinalAnswer = resolvedModel.isPro
3023
+ ? (conversationId: string) => pollForFinalAssistantAnswer(conversationId, resolverCtx)
3024
+ : null;
3025
+
3026
+ // Tool mode buffers (no live streaming) and is gated off the image-gen path.
3027
+ const toolMode = hasTools && !forImageGen;
3028
+
3029
+ let finalResponse: Response;
3030
+ if (stream && !toolMode) {
3031
+ const sseStream = buildStreamingResponse(
3032
+ bodyStream,
3033
+ model,
3034
+ cid,
3035
+ created,
3036
+ imageResolver,
3037
+ pollAsyncImage,
3038
+ pollFinalAnswer,
3039
+ log,
3040
+ signal
3041
+ );
3042
+ finalResponse = new Response(sseStream, {
3043
+ status: 200,
3044
+ headers: {
3045
+ "Content-Type": "text/event-stream",
3046
+ "Cache-Control": "no-cache",
3047
+ "X-Accel-Buffering": "no",
3048
+ },
3049
+ });
3050
+ } else {
3051
+ finalResponse = await buildNonStreamingResponse(
3052
+ bodyStream,
3053
+ model,
3054
+ cid,
3055
+ created,
3056
+ parsed.currentMsg,
3057
+ imageResolver,
3058
+ pollAsyncImage,
3059
+ pollFinalAnswer,
3060
+ log,
3061
+ signal
3062
+ );
3063
+ if (toolMode) {
3064
+ finalResponse = await buildToolModeResponse(finalResponse, requestedTools, stream, {
3065
+ cid,
3066
+ created,
3067
+ model,
3068
+ });
3069
+ }
3070
+ }
3071
+
3072
+ return { response: finalResponse, url: CONV_URL, headers, transformedBody: cgptBody };
3073
+ }
3074
+ }
3075
+
3076
+ // Strip ChatGPT's internal entity markup. The browser renders these as proper
3077
+ // inline citations / chips via JS; for a plain text completion we just want
3078
+ // the human-readable form.
3079
+ // entity["city","Paris","capital of France"] → Paris
3080
+ // entity["…","value", …] → value
3081
+ const ENTITY_RE = /entity\["[^"]*","([^"]*)"[^\]]*\]/g;
3082
+
3083
+ function cleanChatGptText(text: string): string {
3084
+ return text.replace(ENTITY_RE, "$1");
3085
+ }
3086
+
3087
+ function stringToStream(text: string): ReadableStream<Uint8Array> {
3088
+ const encoder = new TextEncoder();
3089
+ return new ReadableStream<Uint8Array>({
3090
+ start(controller) {
3091
+ controller.enqueue(encoder.encode(text));
3092
+ controller.close();
3093
+ },
3094
+ });
3095
+ }
3096
+
3097
+ // Test-only: clear caches between tests
3098
+ export function __resetChatGptWebCachesForTesting(): void {
3099
+ tokenCache.clear();
3100
+ warmupCache.clear();
3101
+ thinkingEffortCache.clear();
3102
+ deviceIdCache.clear();
3103
+ __resetChatGptImageCacheForTesting();
3104
+ dplCache = null;
3105
+ }
3106
+
3107
+ export const __derivePublicBaseUrlForTesting = derivePublicBaseUrl;