jeopi-ai 16.2.13

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 (598) hide show
  1. package/CHANGELOG.md +4347 -0
  2. package/README.md +1193 -0
  3. package/dist/types/api-registry.d.ts +30 -0
  4. package/dist/types/auth-broker/client.d.ts +73 -0
  5. package/dist/types/auth-broker/discover.d.ts +35 -0
  6. package/dist/types/auth-broker/index.d.ts +7 -0
  7. package/dist/types/auth-broker/refresher.d.ts +25 -0
  8. package/dist/types/auth-broker/remote-store.d.ts +102 -0
  9. package/dist/types/auth-broker/server.d.ts +43 -0
  10. package/dist/types/auth-broker/snapshot-cache.d.ts +17 -0
  11. package/dist/types/auth-broker/types.d.ts +107 -0
  12. package/dist/types/auth-broker/wire-schemas.d.ts +411 -0
  13. package/dist/types/auth-gateway/http.d.ts +39 -0
  14. package/dist/types/auth-gateway/index.d.ts +3 -0
  15. package/dist/types/auth-gateway/server.d.ts +36 -0
  16. package/dist/types/auth-gateway/types.d.ts +123 -0
  17. package/dist/types/auth-retry.d.ts +124 -0
  18. package/dist/types/auth-storage.d.ts +1026 -0
  19. package/dist/types/dialect/anthropic.d.ts +15 -0
  20. package/dist/types/dialect/catalog.d.ts +3 -0
  21. package/dist/types/dialect/coercion.d.ts +23 -0
  22. package/dist/types/dialect/deepseek.d.ts +14 -0
  23. package/dist/types/dialect/demotion.d.ts +23 -0
  24. package/dist/types/dialect/examples.d.ts +2 -0
  25. package/dist/types/dialect/factory.d.ts +3 -0
  26. package/dist/types/dialect/fenced-thinking.d.ts +53 -0
  27. package/dist/types/dialect/gemini.d.ts +17 -0
  28. package/dist/types/dialect/gemma.d.ts +15 -0
  29. package/dist/types/dialect/glm.d.ts +9 -0
  30. package/dist/types/dialect/harmony.d.ts +8 -0
  31. package/dist/types/dialect/hermes.d.ts +9 -0
  32. package/dist/types/dialect/history.d.ts +3 -0
  33. package/dist/types/dialect/index.d.ts +11 -0
  34. package/dist/types/dialect/inventory.d.ts +12 -0
  35. package/dist/types/dialect/kimi.d.ts +14 -0
  36. package/dist/types/dialect/minimax.d.ts +3 -0
  37. package/dist/types/dialect/owned-stream.d.ts +4 -0
  38. package/dist/types/dialect/qwen3.d.ts +9 -0
  39. package/dist/types/dialect/rendering.d.ts +45 -0
  40. package/dist/types/dialect/thinking.d.ts +6 -0
  41. package/dist/types/dialect/types.d.ts +69 -0
  42. package/dist/types/dialect/xml.d.ts +9 -0
  43. package/dist/types/error/abort.d.ts +14 -0
  44. package/dist/types/error/auth-classify.d.ts +16 -0
  45. package/dist/types/error/auth.d.ts +27 -0
  46. package/dist/types/error/aws.d.ts +23 -0
  47. package/dist/types/error/classes.d.ts +102 -0
  48. package/dist/types/error/finalize.d.ts +39 -0
  49. package/dist/types/error/flags.d.ts +79 -0
  50. package/dist/types/error/format.d.ts +20 -0
  51. package/dist/types/error/gateway.d.ts +20 -0
  52. package/dist/types/error/index.d.ts +13 -0
  53. package/dist/types/error/oauth.d.ts +43 -0
  54. package/dist/types/error/provider.d.ts +42 -0
  55. package/dist/types/error/rate-limit.d.ts +59 -0
  56. package/dist/types/error/retryable.d.ts +27 -0
  57. package/dist/types/error/validation.d.ts +32 -0
  58. package/dist/types/index.d.ts +49 -0
  59. package/dist/types/provider-details.d.ts +24 -0
  60. package/dist/types/providers/__tests__/google-auth.test.d.ts +1 -0
  61. package/dist/types/providers/__tests__/kimi-code-thinking.test.d.ts +1 -0
  62. package/dist/types/providers/__tests__/openai-codex-error.test.d.ts +1 -0
  63. package/dist/types/providers/amazon-bedrock.d.ts +39 -0
  64. package/dist/types/providers/anthropic-client.d.ts +94 -0
  65. package/dist/types/providers/anthropic-messages-server-schema.d.ts +497 -0
  66. package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
  67. package/dist/types/providers/anthropic-wire.d.ts +318 -0
  68. package/dist/types/providers/anthropic.d.ts +248 -0
  69. package/dist/types/providers/aws-credentials.d.ts +53 -0
  70. package/dist/types/providers/aws-eventstream.d.ts +39 -0
  71. package/dist/types/providers/aws-sigv4.d.ts +55 -0
  72. package/dist/types/providers/azure-openai-responses.d.ts +16 -0
  73. package/dist/types/providers/cursor.d.ts +91 -0
  74. package/dist/types/providers/devin.d.ts +12 -0
  75. package/dist/types/providers/error-message.d.ts +27 -0
  76. package/dist/types/providers/github-copilot-headers.d.ts +40 -0
  77. package/dist/types/providers/gitlab-duo-workflow.d.ts +254 -0
  78. package/dist/types/providers/gitlab-duo.d.ts +27 -0
  79. package/dist/types/providers/google-auth.d.ts +32 -0
  80. package/dist/types/providers/google-gemini-cli.d.ts +118 -0
  81. package/dist/types/providers/google-interactions.d.ts +65 -0
  82. package/dist/types/providers/google-shared.d.ts +203 -0
  83. package/dist/types/providers/google-types.d.ts +155 -0
  84. package/dist/types/providers/google-vertex.d.ts +7 -0
  85. package/dist/types/providers/google.d.ts +4 -0
  86. package/dist/types/providers/grammar.d.ts +1 -0
  87. package/dist/types/providers/kimi.d.ts +27 -0
  88. package/dist/types/providers/mock.d.ts +178 -0
  89. package/dist/types/providers/ollama.d.ts +7 -0
  90. package/dist/types/providers/openai-anthropic-shim.d.ts +31 -0
  91. package/dist/types/providers/openai-chat-server-schema.d.ts +695 -0
  92. package/dist/types/providers/openai-chat-server.d.ts +16 -0
  93. package/dist/types/providers/openai-chat-wire.d.ts +644 -0
  94. package/dist/types/providers/openai-codex/request-transformer.d.ts +54 -0
  95. package/dist/types/providers/openai-codex/response-handler.d.ts +26 -0
  96. package/dist/types/providers/openai-codex-responses.d.ts +108 -0
  97. package/dist/types/providers/openai-completions.d.ts +45 -0
  98. package/dist/types/providers/openai-reasoning-fallback.d.ts +25 -0
  99. package/dist/types/providers/openai-responses-server-schema.d.ts +349 -0
  100. package/dist/types/providers/openai-responses-server.d.ts +17 -0
  101. package/dist/types/providers/openai-responses-wire.d.ts +6065 -0
  102. package/dist/types/providers/openai-responses.d.ts +126 -0
  103. package/dist/types/providers/openai-shared.d.ts +506 -0
  104. package/dist/types/providers/pi-native-client.d.ts +13 -0
  105. package/dist/types/providers/pi-native-server.d.ts +69 -0
  106. package/dist/types/providers/register-builtins.d.ts +32 -0
  107. package/dist/types/providers/synthetic.d.ts +26 -0
  108. package/dist/types/providers/transform-messages.d.ts +11 -0
  109. package/dist/types/providers/vision-guard.d.ts +20 -0
  110. package/dist/types/registry/aimlapi.d.ts +4 -0
  111. package/dist/types/registry/alibaba-coding-plan.d.ts +8 -0
  112. package/dist/types/registry/amazon-bedrock.d.ts +5 -0
  113. package/dist/types/registry/anthropic.d.ts +10 -0
  114. package/dist/types/registry/api-key-login.d.ts +42 -0
  115. package/dist/types/registry/api-key-validation.d.ts +43 -0
  116. package/dist/types/registry/azure.d.ts +4 -0
  117. package/dist/types/registry/cerebras.d.ts +7 -0
  118. package/dist/types/registry/cloudflare-ai-gateway.d.ts +13 -0
  119. package/dist/types/registry/coreweave.d.ts +7 -0
  120. package/dist/types/registry/cursor.d.ts +7 -0
  121. package/dist/types/registry/deepseek.d.ts +8 -0
  122. package/dist/types/registry/derived.d.ts +5 -0
  123. package/dist/types/registry/devin.d.ts +8 -0
  124. package/dist/types/registry/firepass.d.ts +16 -0
  125. package/dist/types/registry/fireworks.d.ts +7 -0
  126. package/dist/types/registry/github-copilot.d.ts +7 -0
  127. package/dist/types/registry/gitlab-duo-workflow.d.ts +10 -0
  128. package/dist/types/registry/gitlab-duo.d.ts +9 -0
  129. package/dist/types/registry/google-antigravity.d.ts +9 -0
  130. package/dist/types/registry/google-gemini-cli.d.ts +9 -0
  131. package/dist/types/registry/google-vertex.d.ts +5 -0
  132. package/dist/types/registry/google.d.ts +4 -0
  133. package/dist/types/registry/groq.d.ts +4 -0
  134. package/dist/types/registry/huggingface.d.ts +7 -0
  135. package/dist/types/registry/index.d.ts +4 -0
  136. package/dist/types/registry/kagi.d.ts +14 -0
  137. package/dist/types/registry/kilo.d.ts +7 -0
  138. package/dist/types/registry/kimi-code.d.ts +7 -0
  139. package/dist/types/registry/litellm.d.ts +13 -0
  140. package/dist/types/registry/llama-cpp.d.ts +8 -0
  141. package/dist/types/registry/lm-studio.d.ts +8 -0
  142. package/dist/types/registry/minimax-code-cn.d.ts +6 -0
  143. package/dist/types/registry/minimax-code.d.ts +6 -0
  144. package/dist/types/registry/minimax.d.ts +4 -0
  145. package/dist/types/registry/mistral.d.ts +4 -0
  146. package/dist/types/registry/moonshot.d.ts +7 -0
  147. package/dist/types/registry/nanogpt.d.ts +7 -0
  148. package/dist/types/registry/nvidia.d.ts +7 -0
  149. package/dist/types/registry/oauth/__tests__/xai-oauth.test.d.ts +1 -0
  150. package/dist/types/registry/oauth/anthropic.d.ts +23 -0
  151. package/dist/types/registry/oauth/callback-server.d.ts +72 -0
  152. package/dist/types/registry/oauth/cursor.d.ts +15 -0
  153. package/dist/types/registry/oauth/devin.d.ts +5 -0
  154. package/dist/types/registry/oauth/github-copilot.d.ts +30 -0
  155. package/dist/types/registry/oauth/gitlab-duo-workflow.d.ts +6 -0
  156. package/dist/types/registry/oauth/gitlab-duo.d.ts +3 -0
  157. package/dist/types/registry/oauth/google-antigravity.d.ts +11 -0
  158. package/dist/types/registry/oauth/google-gemini-cli.d.ts +10 -0
  159. package/dist/types/registry/oauth/google-oauth-shared.d.ts +22 -0
  160. package/dist/types/registry/oauth/index.d.ts +64 -0
  161. package/dist/types/registry/oauth/kimi.d.ts +21 -0
  162. package/dist/types/registry/oauth/minimax-code.d.ts +27 -0
  163. package/dist/types/registry/oauth/openai-codex.d.ts +33 -0
  164. package/dist/types/registry/oauth/opencode.d.ts +18 -0
  165. package/dist/types/registry/oauth/perplexity.d.ts +9 -0
  166. package/dist/types/registry/oauth/pkce.d.ts +8 -0
  167. package/dist/types/registry/oauth/types.d.ts +56 -0
  168. package/dist/types/registry/oauth/wafer.d.ts +1 -0
  169. package/dist/types/registry/oauth/xai-oauth.d.ts +52 -0
  170. package/dist/types/registry/oauth/xiaomi.d.ts +25 -0
  171. package/dist/types/registry/ollama-cloud.d.ts +7 -0
  172. package/dist/types/registry/ollama.d.ts +12 -0
  173. package/dist/types/registry/openai-codex-device.d.ts +8 -0
  174. package/dist/types/registry/openai-codex.d.ts +9 -0
  175. package/dist/types/registry/openai.d.ts +4 -0
  176. package/dist/types/registry/opencode-go.d.ts +6 -0
  177. package/dist/types/registry/opencode-zen.d.ts +6 -0
  178. package/dist/types/registry/openrouter.d.ts +13 -0
  179. package/dist/types/registry/parallel.d.ts +14 -0
  180. package/dist/types/registry/perplexity.d.ts +7 -0
  181. package/dist/types/registry/qianfan.d.ts +7 -0
  182. package/dist/types/registry/qwen-portal.d.ts +7 -0
  183. package/dist/types/registry/registry.d.ts +303 -0
  184. package/dist/types/registry/sakana.d.ts +7 -0
  185. package/dist/types/registry/synthetic.d.ts +6 -0
  186. package/dist/types/registry/tavily.d.ts +14 -0
  187. package/dist/types/registry/together.d.ts +6 -0
  188. package/dist/types/registry/types.d.ts +51 -0
  189. package/dist/types/registry/umans.d.ts +7 -0
  190. package/dist/types/registry/venice.d.ts +13 -0
  191. package/dist/types/registry/vercel-ai-gateway.d.ts +7 -0
  192. package/dist/types/registry/vllm.d.ts +7 -0
  193. package/dist/types/registry/wafer-serverless.d.ts +6 -0
  194. package/dist/types/registry/xai-oauth.d.ts +7 -0
  195. package/dist/types/registry/xai.d.ts +4 -0
  196. package/dist/types/registry/xiaomi-token-plan-ams.d.ts +6 -0
  197. package/dist/types/registry/xiaomi-token-plan-cn.d.ts +6 -0
  198. package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +6 -0
  199. package/dist/types/registry/xiaomi.d.ts +6 -0
  200. package/dist/types/registry/zai.d.ts +7 -0
  201. package/dist/types/registry/zenmux.d.ts +7 -0
  202. package/dist/types/registry/zhipu-coding-plan.d.ts +7 -0
  203. package/dist/types/stream.d.ts +44 -0
  204. package/dist/types/types.d.ts +715 -0
  205. package/dist/types/usage/claude.d.ts +4 -0
  206. package/dist/types/usage/gemini.d.ts +2 -0
  207. package/dist/types/usage/github-copilot.d.ts +7 -0
  208. package/dist/types/usage/google-antigravity.d.ts +15 -0
  209. package/dist/types/usage/kimi.d.ts +2 -0
  210. package/dist/types/usage/minimax-code.d.ts +2 -0
  211. package/dist/types/usage/ollama.d.ts +5 -0
  212. package/dist/types/usage/openai-codex-base-url.d.ts +18 -0
  213. package/dist/types/usage/openai-codex-reset.d.ts +79 -0
  214. package/dist/types/usage/openai-codex.d.ts +3 -0
  215. package/dist/types/usage/opencode-go.d.ts +2 -0
  216. package/dist/types/usage/shared.d.ts +1 -0
  217. package/dist/types/usage/zai.d.ts +2 -0
  218. package/dist/types/usage.d.ts +346 -0
  219. package/dist/types/utils/abort.d.ts +25 -0
  220. package/dist/types/utils/anthropic-auth.d.ts +35 -0
  221. package/dist/types/utils/block-symbols.d.ts +20 -0
  222. package/dist/types/utils/deterministic-id.d.ts +16 -0
  223. package/dist/types/utils/empty-completion-retry.d.ts +21 -0
  224. package/dist/types/utils/event-stream.d.ts +30 -0
  225. package/dist/types/utils/foundry.d.ts +1 -0
  226. package/dist/types/utils/google-validation.d.ts +2 -0
  227. package/dist/types/utils/harmony-leak.d.ts +118 -0
  228. package/dist/types/utils/http-inspector.d.ts +30 -0
  229. package/dist/types/utils/idle-iterator.d.ts +137 -0
  230. package/dist/types/utils/leaked-thinking-stream.d.ts +29 -0
  231. package/dist/types/utils/openai-http.d.ts +54 -0
  232. package/dist/types/utils/openrouter-headers.d.ts +1 -0
  233. package/dist/types/utils/parse-bind.d.ts +23 -0
  234. package/dist/types/utils/provider-response.d.ts +3 -0
  235. package/dist/types/utils/proxy.d.ts +29 -0
  236. package/dist/types/utils/request-debug.d.ts +29 -0
  237. package/dist/types/utils/retry-after.d.ts +4 -0
  238. package/dist/types/utils/retry.d.ts +14 -0
  239. package/dist/types/utils/schema/adapt.d.ts +24 -0
  240. package/dist/types/utils/schema/compatibility.d.ts +30 -0
  241. package/dist/types/utils/schema/dereference.d.ts +11 -0
  242. package/dist/types/utils/schema/draft.d.ts +10 -0
  243. package/dist/types/utils/schema/equality.d.ts +4 -0
  244. package/dist/types/utils/schema/fields.d.ts +54 -0
  245. package/dist/types/utils/schema/index.d.ts +15 -0
  246. package/dist/types/utils/schema/json-schema-validator.d.ts +20 -0
  247. package/dist/types/utils/schema/meta-validator.d.ts +2 -0
  248. package/dist/types/utils/schema/normalize.d.ts +124 -0
  249. package/dist/types/utils/schema/spill.d.ts +8 -0
  250. package/dist/types/utils/schema/stamps.d.ts +17 -0
  251. package/dist/types/utils/schema/strict-tool-validation.d.ts +16 -0
  252. package/dist/types/utils/schema/types.d.ts +4 -0
  253. package/dist/types/utils/schema/typescript.d.ts +18 -0
  254. package/dist/types/utils/schema/wire.d.ts +92 -0
  255. package/dist/types/utils/schema/zod-decontaminate.d.ts +31 -0
  256. package/dist/types/utils/sdk-stream-timeout.d.ts +33 -0
  257. package/dist/types/utils/sse-debug.d.ts +5 -0
  258. package/dist/types/utils/stream-markup-healing.d.ts +87 -0
  259. package/dist/types/utils/thinking-loop.d.ts +102 -0
  260. package/dist/types/utils/tool-call-loop-guard.d.ts +26 -0
  261. package/dist/types/utils/tool-choice.d.ts +50 -0
  262. package/dist/types/utils/validation.d.ts +42 -0
  263. package/dist/types/utils.d.ts +24 -0
  264. package/package.json +139 -0
  265. package/src/api-registry.ts +109 -0
  266. package/src/auth-broker/client.ts +359 -0
  267. package/src/auth-broker/discover.ts +222 -0
  268. package/src/auth-broker/index.ts +7 -0
  269. package/src/auth-broker/refresher.ts +117 -0
  270. package/src/auth-broker/remote-store.ts +657 -0
  271. package/src/auth-broker/server.ts +646 -0
  272. package/src/auth-broker/snapshot-cache.ts +191 -0
  273. package/src/auth-broker/types.ts +130 -0
  274. package/src/auth-broker/wire-schemas.ts +249 -0
  275. package/src/auth-gateway/http.ts +194 -0
  276. package/src/auth-gateway/index.ts +3 -0
  277. package/src/auth-gateway/server.ts +802 -0
  278. package/src/auth-gateway/types.ts +151 -0
  279. package/src/auth-retry.ts +250 -0
  280. package/src/auth-storage.ts +5576 -0
  281. package/src/dialect/anthropic.md +31 -0
  282. package/src/dialect/anthropic.ts +608 -0
  283. package/src/dialect/catalog.ts +29 -0
  284. package/src/dialect/coercion.ts +136 -0
  285. package/src/dialect/deepseek.md +24 -0
  286. package/src/dialect/deepseek.ts +609 -0
  287. package/src/dialect/demotion.ts +36 -0
  288. package/src/dialect/examples.ts +33 -0
  289. package/src/dialect/factory.ts +34 -0
  290. package/src/dialect/fenced-thinking.ts +184 -0
  291. package/src/dialect/gemini.md +44 -0
  292. package/src/dialect/gemini.ts +597 -0
  293. package/src/dialect/gemma.md +33 -0
  294. package/src/dialect/gemma.ts +387 -0
  295. package/src/dialect/glm.md +32 -0
  296. package/src/dialect/glm.ts +456 -0
  297. package/src/dialect/harmony.md +31 -0
  298. package/src/dialect/harmony.ts +346 -0
  299. package/src/dialect/hermes.md +25 -0
  300. package/src/dialect/hermes.ts +206 -0
  301. package/src/dialect/history.ts +81 -0
  302. package/src/dialect/index.ts +15 -0
  303. package/src/dialect/inventory.ts +73 -0
  304. package/src/dialect/kimi.md +24 -0
  305. package/src/dialect/kimi.ts +340 -0
  306. package/src/dialect/minimax.md +31 -0
  307. package/src/dialect/minimax.ts +95 -0
  308. package/src/dialect/owned-stream.ts +470 -0
  309. package/src/dialect/prompt-template.md +12 -0
  310. package/src/dialect/qwen3.md +28 -0
  311. package/src/dialect/qwen3.ts +240 -0
  312. package/src/dialect/rendering.ts +249 -0
  313. package/src/dialect/thinking.ts +122 -0
  314. package/src/dialect/types.ts +57 -0
  315. package/src/dialect/xml.md +22 -0
  316. package/src/dialect/xml.ts +90 -0
  317. package/src/error/abort.ts +18 -0
  318. package/src/error/auth-classify.ts +30 -0
  319. package/src/error/auth.ts +48 -0
  320. package/src/error/aws.ts +31 -0
  321. package/src/error/classes.ts +186 -0
  322. package/src/error/finalize.ts +69 -0
  323. package/src/error/flags.ts +506 -0
  324. package/src/error/format.ts +45 -0
  325. package/src/error/gateway.ts +96 -0
  326. package/src/error/index.ts +13 -0
  327. package/src/error/oauth.ts +58 -0
  328. package/src/error/provider.ts +62 -0
  329. package/src/error/rate-limit.ts +161 -0
  330. package/src/error/retryable.ts +70 -0
  331. package/src/error/validation.ts +44 -0
  332. package/src/index.ts +49 -0
  333. package/src/provider-details.ts +90 -0
  334. package/src/providers/__tests__/google-auth.test.ts +144 -0
  335. package/src/providers/__tests__/kimi-code-thinking.test.ts +112 -0
  336. package/src/providers/__tests__/openai-codex-error.test.ts +84 -0
  337. package/src/providers/amazon-bedrock.ts +1042 -0
  338. package/src/providers/anthropic-client.ts +295 -0
  339. package/src/providers/anthropic-messages-server-schema.ts +252 -0
  340. package/src/providers/anthropic-messages-server.ts +756 -0
  341. package/src/providers/anthropic-wire.ts +318 -0
  342. package/src/providers/anthropic.ts +4078 -0
  343. package/src/providers/aws-credentials.ts +586 -0
  344. package/src/providers/aws-eventstream.ts +181 -0
  345. package/src/providers/aws-sigv4.ts +218 -0
  346. package/src/providers/azure-openai-responses.ts +382 -0
  347. package/src/providers/cursor/proto/agent.proto +3526 -0
  348. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  349. package/src/providers/cursor/proto/buf.yaml +17 -0
  350. package/src/providers/cursor.ts +2695 -0
  351. package/src/providers/devin/proto/buf/validate/validate.proto +468 -0
  352. package/src/providers/devin/proto/buf.gen.yaml +33 -0
  353. package/src/providers/devin/proto/buf.yaml +17 -0
  354. package/src/providers/devin/proto/cel/expr/checked.proto +103 -0
  355. package/src/providers/devin/proto/cel/expr/eval.proto +38 -0
  356. package/src/providers/devin/proto/cel/expr/explain.proto +15 -0
  357. package/src/providers/devin/proto/cel/expr/syntax.proto +113 -0
  358. package/src/providers/devin/proto/cel/expr/value.proto +41 -0
  359. package/src/providers/devin/proto/connectext/grpc/status/v1/status.proto +11 -0
  360. package/src/providers/devin/proto/errorspb/errors.proto +56 -0
  361. package/src/providers/devin/proto/errorspb/hintdetail.proto +7 -0
  362. package/src/providers/devin/proto/errorspb/markers.proto +10 -0
  363. package/src/providers/devin/proto/errorspb/tags.proto +12 -0
  364. package/src/providers/devin/proto/errorspb/testing.proto +6 -0
  365. package/src/providers/devin/proto/exa/analytics_pb/analytics.proto +188 -0
  366. package/src/providers/devin/proto/exa/api_server_pb/api_server.proto +2461 -0
  367. package/src/providers/devin/proto/exa/auth_pb/auth.proto +19 -0
  368. package/src/providers/devin/proto/exa/auto_cascade_common_pb/auto_cascade_common.proto +79 -0
  369. package/src/providers/devin/proto/exa/browser_preview_pb/browser_preview.proto +32 -0
  370. package/src/providers/devin/proto/exa/bug_checker_pb/bug_checker.proto +22 -0
  371. package/src/providers/devin/proto/exa/cascade_plugins_pb/cascade_plugins.proto +262 -0
  372. package/src/providers/devin/proto/exa/chat_client_server_pb/chat_client_server.proto +57 -0
  373. package/src/providers/devin/proto/exa/chat_pb/chat.proto +449 -0
  374. package/src/providers/devin/proto/exa/code_edit/code_edit_pb/code_edit.proto +186 -0
  375. package/src/providers/devin/proto/exa/codeium_common_pb/codeium_common.proto +4157 -0
  376. package/src/providers/devin/proto/exa/context_module_pb/context_module.proto +175 -0
  377. package/src/providers/devin/proto/exa/cortex_pb/cortex.proto +3268 -0
  378. package/src/providers/devin/proto/exa/dev_pb/dev.proto +26 -0
  379. package/src/providers/devin/proto/exa/diff_action_pb/diff_action.proto +75 -0
  380. package/src/providers/devin/proto/exa/eval/pr_eval/datasets_pb/datasets.proto +103 -0
  381. package/src/providers/devin/proto/exa/eval_pb/eval.proto +1315 -0
  382. package/src/providers/devin/proto/exa/extension_server_pb/extension_server.proto +556 -0
  383. package/src/providers/devin/proto/exa/file_system_provider_pb/file_system_provider.proto +75 -0
  384. package/src/providers/devin/proto/exa/index_pb/index.proto +461 -0
  385. package/src/providers/devin/proto/exa/knowledge_base_pb/knowledge_base.proto +144 -0
  386. package/src/providers/devin/proto/exa/language_server_pb/language_server.proto +2385 -0
  387. package/src/providers/devin/proto/exa/model_management_pb/model_management.proto +186 -0
  388. package/src/providers/devin/proto/exa/opensearch_clients_pb/opensearch_clients.proto +503 -0
  389. package/src/providers/devin/proto/exa/product_analytics_pb/product_analytics.proto +37 -0
  390. package/src/providers/devin/proto/exa/prompt_pb/prompt.proto +92 -0
  391. package/src/providers/devin/proto/exa/reactive_component_pb/reactive_component.proto +96 -0
  392. package/src/providers/devin/proto/exa/seat_management_pb/seat_management.proto +2680 -0
  393. package/src/providers/devin/proto/exa/tokenizer_pb/tokenizer.proto +37 -0
  394. package/src/providers/devin/proto/exa/trainer_pb/config.proto +647 -0
  395. package/src/providers/devin/proto/exa/tree_sitter/language_data_pb/language_data.proto +14 -0
  396. package/src/providers/devin/proto/exa/trust_pb/trust.proto +157 -0
  397. package/src/providers/devin/proto/exa/user_analytics_pb/user_analytics.proto +519 -0
  398. package/src/providers/devin/proto/google.golang.org/appengine/internal/base/api_base.proto +28 -0
  399. package/src/providers/devin/proto/google.golang.org/appengine/internal/datastore/datastore_v3.proto +484 -0
  400. package/src/providers/devin/proto/google.golang.org/appengine/internal/log/log_service.proto +136 -0
  401. package/src/providers/devin/proto/google.golang.org/appengine/internal/remote_api/remote_api.proto +42 -0
  402. package/src/providers/devin/proto/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto +61 -0
  403. package/src/providers/devin/proto/grpc/binlog/v1/binarylog.proto +84 -0
  404. package/src/providers/devin/proto/io/prometheus/client/metrics.proto +98 -0
  405. package/src/providers/devin.ts +577 -0
  406. package/src/providers/error-message.ts +21 -0
  407. package/src/providers/github-copilot-headers.ts +141 -0
  408. package/src/providers/gitlab-duo-workflow-chatml-note.md +1 -0
  409. package/src/providers/gitlab-duo-workflow.ts +3058 -0
  410. package/src/providers/gitlab-duo.ts +395 -0
  411. package/src/providers/google-auth.ts +350 -0
  412. package/src/providers/google-gemini-cli.ts +1362 -0
  413. package/src/providers/google-interactions.ts +753 -0
  414. package/src/providers/google-shared.ts +1103 -0
  415. package/src/providers/google-types.ts +180 -0
  416. package/src/providers/google-vertex.ts +183 -0
  417. package/src/providers/google.ts +87 -0
  418. package/src/providers/grammar.ts +70 -0
  419. package/src/providers/kimi.ts +52 -0
  420. package/src/providers/mock.ts +507 -0
  421. package/src/providers/ollama.ts +773 -0
  422. package/src/providers/openai-anthropic-shim.ts +152 -0
  423. package/src/providers/openai-chat-server-schema.ts +242 -0
  424. package/src/providers/openai-chat-server.ts +715 -0
  425. package/src/providers/openai-chat-wire.ts +847 -0
  426. package/src/providers/openai-codex/request-transformer.ts +295 -0
  427. package/src/providers/openai-codex/response-handler.ts +102 -0
  428. package/src/providers/openai-codex-responses.ts +3468 -0
  429. package/src/providers/openai-completions.ts +2173 -0
  430. package/src/providers/openai-reasoning-fallback.ts +269 -0
  431. package/src/providers/openai-responses-reasoning-suppression.md +1 -0
  432. package/src/providers/openai-responses-server-schema.ts +282 -0
  433. package/src/providers/openai-responses-server.ts +1280 -0
  434. package/src/providers/openai-responses-wire.ts +6391 -0
  435. package/src/providers/openai-responses.ts +1022 -0
  436. package/src/providers/openai-shared.ts +2648 -0
  437. package/src/providers/pi-native-client.ts +266 -0
  438. package/src/providers/pi-native-server.ts +242 -0
  439. package/src/providers/register-builtins.ts +475 -0
  440. package/src/providers/synthetic.ts +50 -0
  441. package/src/providers/transform-messages.ts +787 -0
  442. package/src/providers/vision-guard.ts +54 -0
  443. package/src/registry/aimlapi.ts +6 -0
  444. package/src/registry/alibaba-coding-plan.ts +95 -0
  445. package/src/registry/amazon-bedrock.ts +22 -0
  446. package/src/registry/anthropic.ts +26 -0
  447. package/src/registry/api-key-login.ts +112 -0
  448. package/src/registry/api-key-validation.ts +161 -0
  449. package/src/registry/azure.ts +6 -0
  450. package/src/registry/cerebras.ts +23 -0
  451. package/src/registry/cloudflare-ai-gateway.ts +45 -0
  452. package/src/registry/coreweave.ts +40 -0
  453. package/src/registry/cursor.ts +20 -0
  454. package/src/registry/deepseek.ts +46 -0
  455. package/src/registry/derived.ts +9 -0
  456. package/src/registry/devin.ts +15 -0
  457. package/src/registry/firepass.ts +32 -0
  458. package/src/registry/fireworks.ts +28 -0
  459. package/src/registry/github-copilot.ts +22 -0
  460. package/src/registry/gitlab-duo-workflow.ts +20 -0
  461. package/src/registry/gitlab-duo.ts +19 -0
  462. package/src/registry/google-antigravity.ts +22 -0
  463. package/src/registry/google-gemini-cli.ts +22 -0
  464. package/src/registry/google-vertex.ts +38 -0
  465. package/src/registry/google.ts +6 -0
  466. package/src/registry/groq.ts +6 -0
  467. package/src/registry/huggingface.ts +29 -0
  468. package/src/registry/index.ts +4 -0
  469. package/src/registry/kagi.ts +46 -0
  470. package/src/registry/kilo.ts +114 -0
  471. package/src/registry/kimi-code.ts +17 -0
  472. package/src/registry/litellm.ts +45 -0
  473. package/src/registry/llama-cpp.ts +35 -0
  474. package/src/registry/lm-studio.ts +31 -0
  475. package/src/registry/minimax-code-cn.ts +12 -0
  476. package/src/registry/minimax-code.ts +12 -0
  477. package/src/registry/minimax.ts +6 -0
  478. package/src/registry/mistral.ts +6 -0
  479. package/src/registry/moonshot.ts +22 -0
  480. package/src/registry/nanogpt.ts +22 -0
  481. package/src/registry/nvidia.ts +61 -0
  482. package/src/registry/oauth/__tests__/xai-oauth.test.ts +104 -0
  483. package/src/registry/oauth/anthropic.ts +311 -0
  484. package/src/registry/oauth/callback-server.ts +315 -0
  485. package/src/registry/oauth/cursor.ts +171 -0
  486. package/src/registry/oauth/devin.ts +124 -0
  487. package/src/registry/oauth/github-copilot.ts +369 -0
  488. package/src/registry/oauth/gitlab-duo-workflow.ts +146 -0
  489. package/src/registry/oauth/gitlab-duo.ts +222 -0
  490. package/src/registry/oauth/google-antigravity.ts +209 -0
  491. package/src/registry/oauth/google-gemini-cli.ts +273 -0
  492. package/src/registry/oauth/google-oauth-shared.ts +125 -0
  493. package/src/registry/oauth/index.ts +269 -0
  494. package/src/registry/oauth/kimi.ts +289 -0
  495. package/src/registry/oauth/minimax-code.ts +53 -0
  496. package/src/registry/oauth/oauth.html +311 -0
  497. package/src/registry/oauth/openai-codex.ts +364 -0
  498. package/src/registry/oauth/opencode.ts +50 -0
  499. package/src/registry/oauth/perplexity.ts +228 -0
  500. package/src/registry/oauth/pkce.ts +18 -0
  501. package/src/registry/oauth/types.ts +65 -0
  502. package/src/registry/oauth/wafer.ts +24 -0
  503. package/src/registry/oauth/xai-oauth.ts +394 -0
  504. package/src/registry/oauth/xiaomi.ts +211 -0
  505. package/src/registry/ollama-cloud.ts +36 -0
  506. package/src/registry/ollama.ts +43 -0
  507. package/src/registry/openai-codex-device.ts +18 -0
  508. package/src/registry/openai-codex.ts +19 -0
  509. package/src/registry/openai.ts +6 -0
  510. package/src/registry/opencode-go.ts +12 -0
  511. package/src/registry/opencode-zen.ts +12 -0
  512. package/src/registry/openrouter.ts +28 -0
  513. package/src/registry/parallel.ts +45 -0
  514. package/src/registry/perplexity.ts +13 -0
  515. package/src/registry/qianfan.ts +27 -0
  516. package/src/registry/qwen-portal.ts +50 -0
  517. package/src/registry/registry.ts +161 -0
  518. package/src/registry/sakana.ts +22 -0
  519. package/src/registry/synthetic.ts +21 -0
  520. package/src/registry/tavily.ts +45 -0
  521. package/src/registry/together.ts +22 -0
  522. package/src/registry/types.ts +56 -0
  523. package/src/registry/umans.ts +23 -0
  524. package/src/registry/venice.ts +33 -0
  525. package/src/registry/vercel-ai-gateway.ts +38 -0
  526. package/src/registry/vllm.ts +34 -0
  527. package/src/registry/wafer-serverless.ts +12 -0
  528. package/src/registry/xai-oauth.ts +17 -0
  529. package/src/registry/xai.ts +6 -0
  530. package/src/registry/xiaomi-token-plan-ams.ts +12 -0
  531. package/src/registry/xiaomi-token-plan-cn.ts +12 -0
  532. package/src/registry/xiaomi-token-plan-sgp.ts +12 -0
  533. package/src/registry/xiaomi.ts +12 -0
  534. package/src/registry/zai.ts +27 -0
  535. package/src/registry/zenmux.ts +22 -0
  536. package/src/registry/zhipu-coding-plan.ts +27 -0
  537. package/src/stream.ts +1778 -0
  538. package/src/types.ts +856 -0
  539. package/src/usage/claude.ts +485 -0
  540. package/src/usage/gemini.ts +258 -0
  541. package/src/usage/github-copilot.ts +424 -0
  542. package/src/usage/google-antigravity.ts +497 -0
  543. package/src/usage/kimi.ts +271 -0
  544. package/src/usage/minimax-code.ts +30 -0
  545. package/src/usage/ollama.ts +41 -0
  546. package/src/usage/openai-codex-base-url.ts +35 -0
  547. package/src/usage/openai-codex-reset.ts +174 -0
  548. package/src/usage/openai-codex.ts +535 -0
  549. package/src/usage/opencode-go.ts +89 -0
  550. package/src/usage/shared.ts +10 -0
  551. package/src/usage/zai.ts +321 -0
  552. package/src/usage.ts +333 -0
  553. package/src/utils/abort.ts +67 -0
  554. package/src/utils/anthropic-auth.ts +93 -0
  555. package/src/utils/block-symbols.ts +32 -0
  556. package/src/utils/deterministic-id.ts +20 -0
  557. package/src/utils/empty-completion-retry.ts +159 -0
  558. package/src/utils/event-stream.ts +171 -0
  559. package/src/utils/foundry.ts +8 -0
  560. package/src/utils/google-validation.ts +25 -0
  561. package/src/utils/harmony-leak.ts +456 -0
  562. package/src/utils/http-inspector.ts +168 -0
  563. package/src/utils/idle-iterator.ts +473 -0
  564. package/src/utils/leaked-thinking-stream.ts +294 -0
  565. package/src/utils/openai-http.ts +122 -0
  566. package/src/utils/openrouter-headers.ts +12 -0
  567. package/src/utils/parse-bind.ts +56 -0
  568. package/src/utils/provider-response.ts +30 -0
  569. package/src/utils/proxy.ts +240 -0
  570. package/src/utils/request-debug.ts +351 -0
  571. package/src/utils/retry-after.ts +110 -0
  572. package/src/utils/retry.ts +59 -0
  573. package/src/utils/schema/CONSTRAINTS.md +166 -0
  574. package/src/utils/schema/adapt.ts +36 -0
  575. package/src/utils/schema/compatibility.ts +435 -0
  576. package/src/utils/schema/dereference.ts +98 -0
  577. package/src/utils/schema/draft.ts +341 -0
  578. package/src/utils/schema/equality.ts +97 -0
  579. package/src/utils/schema/fields.ts +207 -0
  580. package/src/utils/schema/index.ts +15 -0
  581. package/src/utils/schema/json-schema-validator.ts +595 -0
  582. package/src/utils/schema/meta-validator.ts +167 -0
  583. package/src/utils/schema/normalize.ts +1901 -0
  584. package/src/utils/schema/spill.ts +43 -0
  585. package/src/utils/schema/stamps.ts +109 -0
  586. package/src/utils/schema/strict-tool-validation.ts +117 -0
  587. package/src/utils/schema/types.ts +10 -0
  588. package/src/utils/schema/typescript.ts +198 -0
  589. package/src/utils/schema/wire.ts +789 -0
  590. package/src/utils/schema/zod-decontaminate.ts +331 -0
  591. package/src/utils/sdk-stream-timeout.ts +43 -0
  592. package/src/utils/sse-debug.ts +18 -0
  593. package/src/utils/stream-markup-healing.ts +247 -0
  594. package/src/utils/thinking-loop.ts +552 -0
  595. package/src/utils/tool-call-loop-guard.ts +107 -0
  596. package/src/utils/tool-choice.ts +99 -0
  597. package/src/utils/validation.ts +1507 -0
  598. package/src/utils.ts +171 -0
@@ -0,0 +1,1022 @@
1
+ import { hostMatchesUrl } from "jeopi-catalog/hosts";
2
+ import { $flag, logger, structuredCloneJSON } from "jeopi-utils";
3
+ import * as AIError from "../error";
4
+ import { getEnvApiKey } from "../stream";
5
+ import type {
6
+ AssistantMessage,
7
+ CacheRetention,
8
+ Context,
9
+ Model,
10
+ OpenAICompat,
11
+ ProviderSessionState,
12
+ RawSseEvent,
13
+ ServiceTier,
14
+ StreamFunction,
15
+ StreamOptions,
16
+ Tool,
17
+ ToolChoice,
18
+ } from "../types";
19
+ import {
20
+ createOpenAIResponsesHistoryPayload,
21
+ normalizeSystemPrompts,
22
+ resolveCacheRetention,
23
+ sanitizeOpenAIResponsesHistoryItemsForReplay,
24
+ } from "../utils";
25
+ import { createAbortSourceTracker } from "../utils/abort";
26
+ import { withEmptyCompletionRetry } from "../utils/empty-completion-retry";
27
+ import { AssistantMessageEventStream } from "../utils/event-stream";
28
+ import type { RawHttpRequestDump } from "../utils/http-inspector";
29
+ import {
30
+ getOpenAIStreamFirstEventTimeoutMs,
31
+ getOpenAIStreamIdleTimeoutMs,
32
+ iterateWithIdleTimeout,
33
+ } from "../utils/idle-iterator";
34
+ import { OpenAIHttpError, postOpenAIStream } from "../utils/openai-http";
35
+ import { notifyProviderResponse } from "../utils/provider-response";
36
+ import { callWithCopilotModelRetry } from "../utils/retry";
37
+ import {
38
+ adaptSchemaForStrict,
39
+ findStrictToolSchemaViolation,
40
+ NO_STRICT,
41
+ sanitizeSchemaForOpenAIResponses,
42
+ toolWireSchema,
43
+ } from "../utils/schema";
44
+ import {
45
+ isForcedToolChoice,
46
+ mapToOpenAIResponsesToolChoice,
47
+ type OpenAIResponsesToolChoice,
48
+ } from "../utils/tool-choice";
49
+ import { compactGrammarDefinition } from "./grammar";
50
+ import {
51
+ applyOpenAIReasoningEffortFallback,
52
+ clearOpenAIReasoningEffortFallbackState,
53
+ createOpenAIReasoningEffortFallbackKey,
54
+ createOpenAIReasoningEffortFallbackState,
55
+ getOpenAIReasoningEffortFallback,
56
+ type OpenAIReasoningEffortFallback,
57
+ type OpenAIReasoningEffortFallbackState,
58
+ rememberOpenAIReasoningEffortFallback,
59
+ resolveOpenAIReasoningEffortFallback,
60
+ } from "./openai-reasoning-fallback";
61
+ import type {
62
+ Tool as OpenAITool,
63
+ ResponseCreateParamsStreaming,
64
+ ResponseInput,
65
+ ResponseStreamEvent,
66
+ } from "./openai-responses-wire";
67
+ import {
68
+ applyCommonResponsesSamplingParams,
69
+ applyOpenAIExtraBody,
70
+ applyOpenAIGatewayRouting,
71
+ applyResponsesCompatPolicy,
72
+ applyWireModelIdTransform,
73
+ buildResponsesDeltaInput,
74
+ buildResponsesInput,
75
+ clearOpenAIStrictToolsState,
76
+ createInitialResponsesAssistantMessage,
77
+ createOpenAIStrictToolsState,
78
+ disableStrictToolsForScope,
79
+ getOpenAIResponsesPromptCacheKey,
80
+ getOpenAIResponsesRoutingSessionId,
81
+ getOpenAIStrictToolsScope,
82
+ getOpenRouterResponsesSessionId,
83
+ isCompiledGrammarTooLargeStrictError,
84
+ isOpenAIResponsesProgressEvent,
85
+ isOpenRouterAnthropicModel,
86
+ isStrictToolsDisabledForScope,
87
+ type OpenAIStrictToolsScope,
88
+ type OpenAIStrictToolsState,
89
+ processResponsesStream,
90
+ resolveOpenAICompatPolicy,
91
+ resolveOpenAIOutputTokenParam,
92
+ resolveOpenAIRequestSetup,
93
+ shouldRetryWithoutStrictTools,
94
+ } from "./openai-shared";
95
+
96
+ // OpenAI Responses-specific options
97
+ export interface OpenAIResponsesOptions extends StreamOptions {
98
+ reasoning?: "minimal" | "low" | "medium" | "high" | "xhigh";
99
+ reasoningSummary?: "auto" | "detailed" | "concise" | null;
100
+ serviceTier?: ServiceTier;
101
+ textVerbosity?: "low" | "medium" | "high";
102
+ toolChoice?: ToolChoice;
103
+ openrouterVariant?: string;
104
+ maxTokensExplicit?: boolean;
105
+ disableReasoning?: boolean;
106
+ /**
107
+ * Stateful turns: chain via `previous_response_id` + delta input instead of
108
+ * replaying the full transcript. Forces `store: true` (the platform only
109
+ * resolves stored responses). Defaults ON against the official OpenAI API
110
+ * and OFF for other Responses endpoints; `PI_OPENAI_STATEFUL` overrides the
111
+ * default, and `false` here vetoes everything. Requires `sessionId` +
112
+ * `providerSessionState`. Falls back to a full replay whenever history
113
+ * mutates or the server reports a stale id.
114
+ */
115
+ statefulResponses?: boolean;
116
+ /**
117
+ * Override catalog compat for strict tool call/result pairing when building
118
+ * Responses API inputs. Default behavior is catalog compat; this is only for
119
+ * debugging/adapter wrappers.
120
+ */
121
+ strictResponsesPairing?: boolean;
122
+ /**
123
+ * Override catalog compat for `include: ["reasoning.encrypted_content"]`.
124
+ * Default behavior is catalog compat; this is only for debugging/adapter wrappers.
125
+ */
126
+ includeEncryptedReasoning?: boolean;
127
+ /**
128
+ * Override catalog compat for stripping `type: "reasoning"` items from
129
+ * replayed conversation history before request encoding. Default behavior is
130
+ * catalog compat; this is only for debugging/adapter wrappers.
131
+ */
132
+ filterReasoningHistory?: boolean;
133
+ /**
134
+ * Override catalog compat for suppressing the `reasoning.effort` wire param.
135
+ * Default behavior is catalog compat; this is only for debugging/adapter wrappers.
136
+ */
137
+ omitReasoningEffort?: boolean;
138
+ /**
139
+ * Extra request headers merged onto the model/copilot defaults. Used by
140
+ * adapter wrappers to inject provider-specific
141
+ * routing or cache hints.
142
+ */
143
+ headers?: Record<string, string>;
144
+ /**
145
+ * Extra body fields merged into the Responses request payload. Used by
146
+ * adapter wrappers to inject provider-specific body keys (e.g.,
147
+ * prompt_cache_key for prompt-cache routing).
148
+ */
149
+ extraBody?: Record<string, unknown>;
150
+ }
151
+
152
+ const OPENAI_RESPONSES_PROVIDER_SESSION_STATE_PREFIX = "openai-responses:";
153
+ const OPENAI_RESPONSES_FIRST_EVENT_TIMEOUT_MESSAGE =
154
+ "OpenAI responses stream timed out while waiting for the first event";
155
+ /** Consecutive stale-previous-response failures before chaining is disabled for the session. */
156
+ const OPENAI_RESPONSES_CHAIN_STALE_FAILURE_LIMIT = 3;
157
+
158
+ interface OpenAIResponsesProviderSessionState
159
+ extends ProviderSessionState,
160
+ OpenAIStrictToolsState,
161
+ OpenAIReasoningEffortFallbackState {
162
+ nativeHistoryReplayWarmed: boolean;
163
+ /** Stateful `previous_response_id` chain baselines, keyed by baseUrl/model/session. */
164
+ chains: Map<string, OpenAIResponsesChainState>;
165
+ }
166
+
167
+ interface OpenAIResponsesChainState {
168
+ /**
169
+ * Wire params of the last successful turn, with per-turn trailing
170
+ * scaffolding stripped from `input` (never carries previous_response_id).
171
+ */
172
+ lastParams?: OpenAIResponsesSamplingParams;
173
+ lastResponseId?: string;
174
+ /** Output items of the last response, in replay-sanitized form (matches next-turn input). */
175
+ lastResponseItems?: ResponseInput;
176
+ canAppend: boolean;
177
+ /** Consecutive stale-previous-response failures; reset on a successful chained completion. */
178
+ staleFailures: number;
179
+ /** Set once chaining is judged unsupported for this session (circuit breaker). */
180
+ disabled: boolean;
181
+ }
182
+
183
+ function createOpenAIResponsesProviderSessionState(): OpenAIResponsesProviderSessionState {
184
+ const strictToolsState = createOpenAIStrictToolsState();
185
+ const reasoningEffortFallbackState = createOpenAIReasoningEffortFallbackState();
186
+ const state: OpenAIResponsesProviderSessionState = {
187
+ ...strictToolsState,
188
+ ...reasoningEffortFallbackState,
189
+ nativeHistoryReplayWarmed: false,
190
+ chains: new Map(),
191
+ close: () => {
192
+ state.nativeHistoryReplayWarmed = false;
193
+ state.chains.clear();
194
+ clearOpenAIStrictToolsState(state);
195
+ clearOpenAIReasoningEffortFallbackState(state);
196
+ },
197
+ };
198
+ return state;
199
+ }
200
+
201
+ function getOpenAIResponsesProviderSessionState(
202
+ model: Model<"openai-responses">,
203
+ providerSessionState: Map<string, ProviderSessionState> | undefined,
204
+ ): OpenAIResponsesProviderSessionState | undefined {
205
+ if (!providerSessionState) return undefined;
206
+ const key = `${OPENAI_RESPONSES_PROVIDER_SESSION_STATE_PREFIX}${model.provider}`;
207
+ const existing = providerSessionState.get(key) as OpenAIResponsesProviderSessionState | undefined;
208
+ if (existing) return existing;
209
+ const created = createOpenAIResponsesProviderSessionState();
210
+ providerSessionState.set(key, created);
211
+ return created;
212
+ }
213
+
214
+ function isOpenAIResponsesStatefulEnabled(
215
+ options: OpenAIResponsesOptions | undefined,
216
+ baseUrl: string | undefined,
217
+ ): boolean {
218
+ if (options?.statefulResponses === false) return false;
219
+ if (options?.statefulResponses === true) return true;
220
+ // Default ON only against the official OpenAI API: chaining forces
221
+ // `store: true`, and third-party /v1/responses proxies routinely ignore or
222
+ // reject `previous_response_id`. An unset baseUrl means the default
223
+ // endpoint (api.openai.com).
224
+ return $flag("PI_OPENAI_STATEFUL", !baseUrl || hostMatchesUrl(baseUrl, "openai"));
225
+ }
226
+
227
+ function getOpenAIResponsesChainState(
228
+ providerSessionState: OpenAIResponsesProviderSessionState,
229
+ model: Model<"openai-responses">,
230
+ resolvedBaseUrl: string | undefined,
231
+ sessionId: string,
232
+ ): OpenAIResponsesChainState {
233
+ const key = `${resolvedBaseUrl ?? model.baseUrl ?? ""}\u0000${model.id}\u0000${sessionId}`;
234
+ const existing = providerSessionState.chains.get(key);
235
+ if (existing) return existing;
236
+ const created: OpenAIResponsesChainState = { canAppend: false, staleFailures: 0, disabled: false };
237
+ providerSessionState.chains.set(key, created);
238
+ return created;
239
+ }
240
+
241
+ function resetOpenAIResponsesChainState(state: OpenAIResponsesChainState): void {
242
+ state.canAppend = false;
243
+ state.lastParams = undefined;
244
+ state.lastResponseId = undefined;
245
+ state.lastResponseItems = undefined;
246
+ }
247
+
248
+ interface OpenAIResponsesChainedParams {
249
+ params: OpenAIResponsesSamplingParams;
250
+ /** Set iff the params carry previous_response_id (delta request). */
251
+ previousResponseId?: string;
252
+ }
253
+
254
+ /**
255
+ * Shape the next turn's request: when the session's append baseline is intact
256
+ * (same options, strict history prefix), chain via `previous_response_id` +
257
+ * delta-only `input`; otherwise break the chain and replay the full transcript.
258
+ *
259
+ * The prefix check runs on the wire form of the conversation arguments alone:
260
+ * per-turn trailing scaffolding is excluded from both sides and re-appended to
261
+ * the delta, so a decoration that trails every request can never masquerade as
262
+ * a history mutation.
263
+ */
264
+ function buildOpenAIResponsesChainedParams(
265
+ params: OpenAIResponsesSamplingParams,
266
+ trailingScaffoldingItems: number,
267
+ chain: OpenAIResponsesChainState,
268
+ ): OpenAIResponsesChainedParams {
269
+ const historyParams =
270
+ trailingScaffoldingItems > 0 && Array.isArray(params.input)
271
+ ? { ...params, input: params.input.slice(0, params.input.length - trailingScaffoldingItems) }
272
+ : params;
273
+ const deltaInput = chain.canAppend
274
+ ? buildResponsesDeltaInput(chain.lastParams, chain.lastResponseItems, historyParams)
275
+ : null;
276
+ if (deltaInput && deltaInput.length > 0 && chain.lastResponseId) {
277
+ const scaffolding =
278
+ historyParams !== params && Array.isArray(params.input)
279
+ ? params.input.slice(params.input.length - trailingScaffoldingItems)
280
+ : [];
281
+ return {
282
+ params: { ...params, previous_response_id: chain.lastResponseId, input: [...deltaInput, ...scaffolding] },
283
+ previousResponseId: chain.lastResponseId,
284
+ };
285
+ }
286
+ if (chain.canAppend) {
287
+ // History mutated or options changed — break the chain and replay in full.
288
+ resetOpenAIResponsesChainState(chain);
289
+ }
290
+ return { params };
291
+ }
292
+
293
+ function isOpenAIResponsesStalePreviousResponseError(error: unknown): boolean {
294
+ if (!(error instanceof Error)) return false;
295
+ if ((error as { code?: string }).code === "previous_response_not_found") return true;
296
+ // "unsupported" covers endpoints that reject the parameter outright
297
+ // (e.g. "Unsupported parameter: previous_response_id").
298
+ return (
299
+ /previous[ _]?response/i.test(error.message) &&
300
+ /not[ _]?found|invalid|expired|stale|unsupported/i.test(error.message)
301
+ );
302
+ }
303
+
304
+ function registerOpenAIResponsesChainStaleFailure(chain: OpenAIResponsesChainState, error: unknown): void {
305
+ resetOpenAIResponsesChainState(chain);
306
+ chain.staleFailures += 1;
307
+ if (chain.staleFailures >= OPENAI_RESPONSES_CHAIN_STALE_FAILURE_LIMIT) {
308
+ chain.disabled = true;
309
+ }
310
+ logger.debug("OpenAI responses previous_response_id rejected; falling back to full context", {
311
+ error: error instanceof Error ? error.message : String(error),
312
+ consecutiveFailures: chain.staleFailures,
313
+ disabled: chain.disabled,
314
+ });
315
+ }
316
+
317
+ /**
318
+ * One-shot ZDR signal: the org will never resolve a stored response, so skip
319
+ * the staleFailures counter and disable chaining immediately for this session.
320
+ */
321
+ function markOpenAIResponsesChainZeroDataRetention(chain: OpenAIResponsesChainState, error: unknown): void {
322
+ resetOpenAIResponsesChainState(chain);
323
+ chain.disabled = true;
324
+ chain.staleFailures = OPENAI_RESPONSES_CHAIN_STALE_FAILURE_LIMIT;
325
+ logger.debug("OpenAI responses chaining disabled (Zero Data Retention)", {
326
+ error: error instanceof Error ? error.message : String(error),
327
+ });
328
+ }
329
+
330
+ type OpenRouterAnthropicCacheControl = { type: "ephemeral"; ttl?: "1h" };
331
+
332
+ type OpenAIResponsesSamplingParams = ResponseCreateParamsStreaming & {
333
+ top_p?: number;
334
+ top_k?: number;
335
+ min_p?: number;
336
+ presence_penalty?: number;
337
+ repetition_penalty?: number;
338
+ session_id?: string;
339
+ stream_options?: { include_obfuscation?: boolean };
340
+ provider?: OpenAICompat["openRouterRouting"];
341
+ reasoning?: { effort?: string } | { enabled: false };
342
+ cache_control?: OpenRouterAnthropicCacheControl;
343
+ };
344
+
345
+ function maybeAddOpenRouterAnthropicCacheControl(
346
+ params: OpenAIResponsesSamplingParams,
347
+ model: Model<"openai-responses">,
348
+ cacheRetention: CacheRetention,
349
+ ): void {
350
+ if (cacheRetention === "none" || !isOpenRouterAnthropicModel(model)) return;
351
+ if (params.cache_control != null) return;
352
+ params.cache_control = cacheRetention === "long" ? { type: "ephemeral", ttl: "1h" } : { type: "ephemeral" };
353
+ }
354
+
355
+ /**
356
+ * Generate function for OpenAI Responses API
357
+ */
358
+ const streamOpenAIResponsesOnce = (
359
+ model: Model<"openai-responses">,
360
+ context: Context,
361
+ options?: OpenAIResponsesOptions,
362
+ ): AssistantMessageEventStream => {
363
+ const stream = new AssistantMessageEventStream();
364
+
365
+ // Start async processing
366
+ (async () => {
367
+ const startTime = performance.now();
368
+ let firstTokenTime: number | undefined;
369
+
370
+ const output: AssistantMessage = createInitialResponsesAssistantMessage(model.api, model.provider, model.id);
371
+ let rawRequestDump: RawHttpRequestDump | undefined;
372
+ let chainState: OpenAIResponsesChainState | undefined;
373
+ let sentPreviousResponseId: string | undefined;
374
+ const abortTracker = createAbortSourceTracker(options?.signal);
375
+ const firstEventTimeoutAbortError = new AIError.StreamTimeoutError(OPENAI_RESPONSES_FIRST_EVENT_TIMEOUT_MESSAGE);
376
+ const { requestAbortController, requestSignal } = abortTracker;
377
+ const onSseEvent = options?.onSseEvent;
378
+ const rawSseObserver = onSseEvent
379
+ ? (event: RawSseEvent) => {
380
+ if (!event.event && event.data && event.data !== "[DONE]") {
381
+ try {
382
+ const parsed = JSON.parse(event.data);
383
+ const resolvedEvent =
384
+ typeof parsed.type === "string"
385
+ ? parsed.type
386
+ : typeof parsed.object === "string"
387
+ ? parsed.object
388
+ : null;
389
+ if (resolvedEvent) {
390
+ event.event = resolvedEvent;
391
+ event.raw = [`event: ${resolvedEvent}`, ...event.raw];
392
+ }
393
+ } catch {}
394
+ }
395
+ onSseEvent(event, model);
396
+ }
397
+ : undefined;
398
+
399
+ try {
400
+ // Keep request routing on `sessionId` while allowing callers to pin a
401
+ // stable prompt-cache key independently. Side-channel calls use this to
402
+ // avoid perturbing provider conversation state without cold-starting the cache.
403
+ const routingSessionId = getOpenAIResponsesRoutingSessionId(options);
404
+ const promptCacheSessionId = getOpenAIResponsesPromptCacheKey(options);
405
+ const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
406
+ const { headers, copilotPremiumRequests, baseUrl } = resolveOpenAIRequestSetup(model, {
407
+ apiKey,
408
+ extraHeaders: options?.headers,
409
+ initiatorOverride: options?.initiatorOverride,
410
+ messages: context.messages,
411
+ openAISessionId: routingSessionId,
412
+ promptCacheSessionId,
413
+ });
414
+ const premiumRequestsTotal = copilotPremiumRequests;
415
+ const providerSessionState = getOpenAIResponsesProviderSessionState(model, options?.providerSessionState);
416
+ const strictToolsScope = getOpenAIStrictToolsScope(model, baseUrl);
417
+ const builtParams = buildParams(model, context, options, providerSessionState, strictToolsScope);
418
+ const params = builtParams.params;
419
+ const { trailingScaffoldingItems } = builtParams;
420
+ let activeParams = params;
421
+ let activeTrailingScaffoldingItems = trailingScaffoldingItems;
422
+ const resolvedBaseUrl = (baseUrl ?? "https://api.openai.com/v1").replace(/\/+$/, "");
423
+ const requestReasoningEffortFallbacks = new Map<string, OpenAIReasoningEffortFallback>();
424
+ const attemptedReasoningEffortFallbacks = new Set<string>();
425
+ let pendingReasoningEffortFallback: { key: string; fallback: OpenAIReasoningEffortFallback } | undefined;
426
+ let activeReasoningEffortFallbackKey: string | undefined;
427
+ let activeRequestParams: OpenAIResponsesSamplingParams | undefined;
428
+ const applyReasoningEffortFallbackForRequest = (requestParams: OpenAIResponsesSamplingParams): string => {
429
+ const fallbackKey = createOpenAIReasoningEffortFallbackKey(
430
+ "responses",
431
+ resolvedBaseUrl,
432
+ typeof requestParams.model === "string" ? requestParams.model : model.id,
433
+ );
434
+ const requestReasoningEffortFallback = requestReasoningEffortFallbacks.has(fallbackKey)
435
+ ? requestReasoningEffortFallbacks.get(fallbackKey)
436
+ : getOpenAIReasoningEffortFallback(providerSessionState, fallbackKey);
437
+ if (requestReasoningEffortFallback !== undefined) {
438
+ applyOpenAIReasoningEffortFallback(requestParams, requestReasoningEffortFallback);
439
+ }
440
+ return fallbackKey;
441
+ };
442
+ if (isOpenAIResponsesStatefulEnabled(options, baseUrl) && routingSessionId && providerSessionState) {
443
+ chainState = getOpenAIResponsesChainState(providerSessionState, model, baseUrl, routingSessionId);
444
+ if (!chainState.disabled) {
445
+ // Platform `previous_response_id` chaining only resolves stored responses.
446
+ params.store = true;
447
+ }
448
+ }
449
+ applyReasoningEffortFallbackForRequest(params);
450
+ let chained: OpenAIResponsesChainedParams =
451
+ chainState && !chainState.disabled
452
+ ? buildOpenAIResponsesChainedParams(params, trailingScaffoldingItems, chainState)
453
+ : { params };
454
+ sentPreviousResponseId = chained.previousResponseId;
455
+ const idleTimeoutMs =
456
+ options?.streamIdleTimeoutMs ?? getOpenAIStreamIdleTimeoutMs(model.compat.streamIdleTimeoutMs);
457
+ const firstEventTimeoutMs =
458
+ options?.streamFirstEventTimeoutMs ?? getOpenAIStreamFirstEventTimeoutMs(idleTimeoutMs);
459
+ const requestTimeoutMs =
460
+ firstEventTimeoutMs !== undefined && firstEventTimeoutMs > 0 ? firstEventTimeoutMs : undefined;
461
+ const requestUrl = `${resolvedBaseUrl}/responses`;
462
+ const applyPayloadReplacement = async (requestParams: OpenAIResponsesSamplingParams) => {
463
+ const replacementPayload = await options?.onPayload?.(requestParams, model);
464
+ const payload =
465
+ replacementPayload !== undefined ? (replacementPayload as OpenAIResponsesSamplingParams) : requestParams;
466
+ applyReasoningEffortFallbackForRequest(payload);
467
+ return payload;
468
+ };
469
+ chained = { ...chained, params: await applyPayloadReplacement(chained.params) };
470
+ rawRequestDump = {
471
+ provider: model.provider,
472
+ api: output.api,
473
+ model: model.id,
474
+ method: "POST",
475
+ url: requestUrl,
476
+ body: chained.params,
477
+ };
478
+ const openResponsesStream = (requestParams: OpenAIResponsesSamplingParams) => {
479
+ activeReasoningEffortFallbackKey = createOpenAIReasoningEffortFallbackKey(
480
+ "responses",
481
+ resolvedBaseUrl,
482
+ typeof requestParams.model === "string" ? requestParams.model : model.id,
483
+ );
484
+ activeRequestParams = requestParams;
485
+ return callWithCopilotModelRetry(
486
+ async () => {
487
+ let requestTimeout: NodeJS.Timeout | undefined;
488
+ if (requestTimeoutMs !== undefined) {
489
+ requestTimeout = setTimeout(
490
+ () => abortTracker.abortLocally(firstEventTimeoutAbortError),
491
+ requestTimeoutMs,
492
+ );
493
+ }
494
+ try {
495
+ const headersWithTimeout = { ...headers };
496
+ if (requestTimeoutMs !== undefined) {
497
+ headersWithTimeout["X-Stainless-Timeout"] = Math.floor(requestTimeoutMs / 1000).toString();
498
+ }
499
+ const { events, response, requestId } = await postOpenAIStream<ResponseStreamEvent>({
500
+ url: requestUrl,
501
+ headers: headersWithTimeout,
502
+ body: requestParams,
503
+ signal: requestSignal,
504
+ fetch: options?.fetch,
505
+ // With a first-event watchdog armed, transport retries must
506
+ // not silently extend the caller's deadline.
507
+ maxAttempts: requestTimeoutMs !== undefined ? 1 : undefined,
508
+ onSseEvent: rawSseObserver,
509
+ });
510
+ // Disarm the first-event watchdog as soon as headers arrive — a slow
511
+ // onResponse callback must not abort an already-connected stream.
512
+ if (requestTimeout !== undefined) {
513
+ clearTimeout(requestTimeout);
514
+ requestTimeout = undefined;
515
+ }
516
+ await notifyProviderResponse(options, response, model, requestId);
517
+ return events;
518
+ } finally {
519
+ if (requestTimeout !== undefined) clearTimeout(requestTimeout);
520
+ }
521
+ },
522
+ { provider: model.provider, signal: requestSignal },
523
+ );
524
+ };
525
+ let openaiStream: AsyncIterable<ResponseStreamEvent>;
526
+ let strictRetryAvailable = true;
527
+ let activeStrictToolsApplied = builtParams.strictToolsApplied;
528
+ let forceDisableStrictTools = false;
529
+ while (true) {
530
+ try {
531
+ openaiStream = await openResponsesStream(chained.params);
532
+ if (pendingReasoningEffortFallback) {
533
+ rememberOpenAIReasoningEffortFallback(
534
+ providerSessionState,
535
+ pendingReasoningEffortFallback.key,
536
+ pendingReasoningEffortFallback.fallback,
537
+ );
538
+ pendingReasoningEffortFallback = undefined;
539
+ }
540
+ break;
541
+ } catch (error) {
542
+ const capturedErrorResponse = error instanceof OpenAIHttpError ? error.captured : undefined;
543
+ const reasoningEffortFallback =
544
+ activeReasoningEffortFallbackKey && activeRequestParams && !requestSignal.aborted
545
+ ? resolveOpenAIReasoningEffortFallback(error, capturedErrorResponse, activeRequestParams, {
546
+ explicitDisable: options?.disableReasoning === true && options.reasoning === undefined,
547
+ })
548
+ : undefined;
549
+ if (reasoningEffortFallback !== undefined && activeReasoningEffortFallbackKey) {
550
+ const retryMarker = `${activeReasoningEffortFallbackKey}:${String(reasoningEffortFallback)}`;
551
+ if (attemptedReasoningEffortFallbacks.has(retryMarker)) throw error;
552
+ attemptedReasoningEffortFallbacks.add(retryMarker);
553
+ requestReasoningEffortFallbacks.set(activeReasoningEffortFallbackKey, reasoningEffortFallback);
554
+ applyOpenAIReasoningEffortFallback(chained.params, reasoningEffortFallback);
555
+ applyOpenAIReasoningEffortFallback(activeParams, reasoningEffortFallback);
556
+ rawRequestDump.body = chained.params;
557
+ pendingReasoningEffortFallback = {
558
+ key: activeReasoningEffortFallbackKey,
559
+ fallback: reasoningEffortFallback,
560
+ };
561
+ continue;
562
+ }
563
+ const compiledGrammarTooLarge =
564
+ isOpenRouterAnthropicModel(model) &&
565
+ isCompiledGrammarTooLargeStrictError(error, capturedErrorResponse);
566
+ const canRetryWithoutStrictTools =
567
+ strictRetryAvailable &&
568
+ !requestSignal.aborted &&
569
+ (compiledGrammarTooLarge ||
570
+ shouldRetryWithoutStrictTools(
571
+ error,
572
+ capturedErrorResponse,
573
+ activeStrictToolsApplied,
574
+ context.tools,
575
+ ));
576
+ if (canRetryWithoutStrictTools) {
577
+ strictRetryAvailable = false;
578
+ forceDisableStrictTools = true;
579
+ disableStrictToolsForScope(providerSessionState, strictToolsScope);
580
+ const fallbackBuilt = buildParams(
581
+ model,
582
+ context,
583
+ options,
584
+ providerSessionState,
585
+ strictToolsScope,
586
+ true,
587
+ );
588
+ const fallbackParams = fallbackBuilt.params;
589
+ if (chainState && !chainState.disabled) fallbackParams.store = true;
590
+ let fallbackChained: OpenAIResponsesChainedParams =
591
+ chainState && !chainState.disabled
592
+ ? buildOpenAIResponsesChainedParams(
593
+ fallbackParams,
594
+ fallbackBuilt.trailingScaffoldingItems,
595
+ chainState,
596
+ )
597
+ : { params: fallbackParams };
598
+ sentPreviousResponseId = fallbackChained.previousResponseId;
599
+ fallbackChained = {
600
+ ...fallbackChained,
601
+ params: await applyPayloadReplacement(fallbackChained.params),
602
+ };
603
+ chained = fallbackChained;
604
+ rawRequestDump.body = chained.params;
605
+ activeParams = fallbackParams;
606
+ activeTrailingScaffoldingItems = fallbackBuilt.trailingScaffoldingItems;
607
+ activeStrictToolsApplied = fallbackBuilt.strictToolsApplied;
608
+ continue;
609
+ }
610
+ if (!chainState || !sentPreviousResponseId || requestSignal.aborted) {
611
+ throw error;
612
+ }
613
+ const zdrRejection =
614
+ error instanceof Error &&
615
+ /previous[ _]?response/i.test(error.message) &&
616
+ /zero[ _-]?data[ _-]?retention/i.test(error.message);
617
+ if (!zdrRejection && !isOpenAIResponsesStalePreviousResponseError(error)) {
618
+ throw error;
619
+ }
620
+ // Server rejected the chain baseline: reset, count the failure (or
621
+ // disable categorically on ZDR), and retry once with the full
622
+ // transcript. Structurally cannot loop — the retry carries no
623
+ // previous_response_id.
624
+ if (zdrRejection) {
625
+ markOpenAIResponsesChainZeroDataRetention(chainState, error);
626
+ // ZDR orgs cannot store responses; the retry uses `store: false`.
627
+ } else {
628
+ registerOpenAIResponsesChainStaleFailure(chainState, error);
629
+ }
630
+ sentPreviousResponseId = undefined;
631
+ const currentBuilt = buildParams(
632
+ model,
633
+ context,
634
+ options,
635
+ providerSessionState,
636
+ strictToolsScope,
637
+ forceDisableStrictTools,
638
+ );
639
+ const currentParams = currentBuilt.params;
640
+ // Only ZDR forces `store: false` (the org never persists responses). A
641
+ // non-ZDR stale baseline is transient, so keep storing: the full-context
642
+ // retry must be chainable next turn, and the consecutive stale-failure
643
+ // breaker only trips when each retry stores and the next turn re-chains.
644
+ currentParams.store = !zdrRejection;
645
+ const retryParams = await applyPayloadReplacement(currentParams);
646
+ chained = { params: retryParams };
647
+ rawRequestDump.body = retryParams;
648
+ activeParams = currentParams;
649
+ activeTrailingScaffoldingItems = currentBuilt.trailingScaffoldingItems;
650
+ activeStrictToolsApplied = currentBuilt.strictToolsApplied;
651
+ }
652
+ }
653
+ if (premiumRequestsTotal !== undefined) output.usage.premiumRequests = premiumRequestsTotal;
654
+ stream.push({ type: "start", partial: output });
655
+
656
+ const nativeOutputItems: Array<Record<string, unknown>> = [];
657
+ let sawTerminalResponseEvent = false;
658
+ const timedOpenaiStream = iterateWithIdleTimeout(openaiStream, {
659
+ idleTimeoutMs,
660
+ firstItemTimeoutMs: firstEventTimeoutMs,
661
+ firstItemErrorMessage: OPENAI_RESPONSES_FIRST_EVENT_TIMEOUT_MESSAGE,
662
+ errorMessage: "OpenAI responses stream stalled while waiting for the next event",
663
+ onFirstItemTimeout: () => abortTracker.abortLocally(firstEventTimeoutAbortError),
664
+ onIdle: () => requestAbortController.abort(),
665
+ abortSignal: options?.signal,
666
+ isProgressItem: isOpenAIResponsesProgressEvent,
667
+ });
668
+ await processResponsesStream(timedOpenaiStream, output, stream, model, {
669
+ onFirstToken: () => {
670
+ if (!firstTokenTime) firstTokenTime = performance.now();
671
+ },
672
+ onOutputItemDone: item => {
673
+ // `processResponsesStream` hands over a private clone already; no
674
+ // second deep copy needed (reasoning items carry multi-KB blobs).
675
+ nativeOutputItems.push(item as unknown as Record<string, unknown>);
676
+ },
677
+ onCompleted: () => {
678
+ sawTerminalResponseEvent = true;
679
+ },
680
+ requestServiceTier: options?.serviceTier,
681
+ });
682
+
683
+ const localAbortReason = abortTracker.getLocalAbortReason();
684
+ if (localAbortReason) {
685
+ throw localAbortReason;
686
+ }
687
+ if (abortTracker.wasCallerAbort()) {
688
+ throw new AIError.AbortError();
689
+ }
690
+
691
+ // Detect premature stream closure: the HTTP stream ended without the
692
+ // provider sending `response.completed` or `response.incomplete`.
693
+ // Custom/proxy providers may drop the connection mid-stream; without
694
+ // this guard the incomplete output is silently surfaced as a successful
695
+ // "stop".
696
+ if (!sawTerminalResponseEvent) {
697
+ throw new AIError.ProviderResponseError(
698
+ "OpenAI responses stream closed before a terminal response event was received",
699
+ { provider: model.provider, kind: "incomplete-stream" },
700
+ );
701
+ }
702
+
703
+ if (output.stopReason === "aborted" || output.stopReason === "error") {
704
+ throw new AIError.ProviderResponseError(output.errorMessage ?? "An unknown error occurred", {
705
+ provider: model.provider,
706
+ kind: "runtime",
707
+ });
708
+ }
709
+
710
+ output.providerPayload = createOpenAIResponsesHistoryPayload(model.provider, nativeOutputItems);
711
+ if (providerSessionState) providerSessionState.nativeHistoryReplayWarmed = true;
712
+ if (chainState) {
713
+ chainState.lastParams = structuredCloneJSON(
714
+ activeTrailingScaffoldingItems > 0 && Array.isArray(activeParams.input)
715
+ ? {
716
+ ...activeParams,
717
+ input: activeParams.input.slice(0, activeParams.input.length - activeTrailingScaffoldingItems),
718
+ }
719
+ : activeParams,
720
+ );
721
+ if (output.responseId) {
722
+ chainState.lastResponseId = output.responseId;
723
+ chainState.lastResponseItems = sanitizeOpenAIResponsesHistoryItemsForReplay(
724
+ structuredCloneJSON(nativeOutputItems),
725
+ );
726
+ chainState.canAppend = true;
727
+ // Only a successful CHAINED completion clears the stale counter — a
728
+ // full-context success must not mask categorical rejection.
729
+ if (sentPreviousResponseId) chainState.staleFailures = 0;
730
+ } else {
731
+ // Without a response id the append baseline cannot be trusted.
732
+ chainState.canAppend = false;
733
+ }
734
+ }
735
+
736
+ output.duration = performance.now() - startTime;
737
+ if (firstTokenTime) output.ttft = firstTokenTime - startTime;
738
+ stream.push({ type: "done", reason: output.stopReason, message: output });
739
+ stream.end();
740
+ } catch (error) {
741
+ if (chainState) resetOpenAIResponsesChainState(chainState);
742
+ const capturedErrorResponse = error instanceof OpenAIHttpError ? error.captured : undefined;
743
+ const result = await AIError.finalize(error, {
744
+ api: model.api,
745
+ provider: model.provider,
746
+ abortTracker,
747
+ rawRequestDump,
748
+ capturedErrorResponse,
749
+ });
750
+ output.stopReason = result.stopReason;
751
+ output.errorStatus = result.status;
752
+ output.errorId = result.id;
753
+ output.errorMessage = result.message;
754
+ // Some providers via OpenRouter include extra details here.
755
+ const rawMetadata = (error as { error?: { metadata?: { raw?: string } } })?.error?.metadata?.raw;
756
+ if (rawMetadata) output.errorMessage += `\n${rawMetadata}`;
757
+ output.duration = performance.now() - startTime;
758
+ if (firstTokenTime) output.ttft = firstTokenTime - startTime;
759
+ stream.push({ type: "error", reason: output.stopReason, error: output });
760
+ stream.end();
761
+ }
762
+ })();
763
+
764
+ return stream;
765
+ };
766
+
767
+ /**
768
+ * Public entry: wrap the single-attempt Responses streamer with bounded
769
+ * empty-completion retries — a `response.completed` carrying no content/usage
770
+ * would otherwise stall the agent loop. Shared with the OpenAI-completions and
771
+ * Anthropic providers via `withEmptyCompletionRetry`.
772
+ */
773
+ export const streamOpenAIResponses: StreamFunction<"openai-responses"> = (model, context, options) =>
774
+ withEmptyCompletionRetry(model, context, options, streamOpenAIResponsesOnce);
775
+
776
+ function isOfficialOpenAIResponsesEndpoint(model: Model<"openai-responses">): boolean {
777
+ if (model.provider !== "openai") return false;
778
+ if (!model.baseUrl) return true;
779
+ try {
780
+ return new URL(model.baseUrl).hostname === "api.openai.com";
781
+ } catch {
782
+ return false;
783
+ }
784
+ }
785
+
786
+ export function buildParams(
787
+ model: Model<"openai-responses">,
788
+ context: Context,
789
+ options: OpenAIResponsesOptions | undefined,
790
+ providerSessionState: OpenAIResponsesProviderSessionState | undefined,
791
+ strictToolsScope?: OpenAIStrictToolsScope,
792
+ disableStrictToolsOverride = false,
793
+ ): { params: OpenAIResponsesSamplingParams; trailingScaffoldingItems: number; strictToolsApplied: boolean } {
794
+ const policy = resolveOpenAICompatPolicy(model, {
795
+ endpoint: "responses",
796
+ reasoning: options?.reasoning,
797
+ disableReasoning: options?.disableReasoning,
798
+ toolChoice: options?.toolChoice,
799
+ strictResponsesPairing: options?.strictResponsesPairing,
800
+ includeEncryptedReasoning: options?.includeEncryptedReasoning,
801
+ filterReasoningHistory: options?.filterReasoningHistory,
802
+ omitReasoningEffort: options?.omitReasoningEffort,
803
+ });
804
+ const strictResponsesPairing = policy.tools.strictResponsesPairing;
805
+ const shouldReplayNativeHistory = providerSessionState?.nativeHistoryReplayWarmed ?? true;
806
+ const messages = buildResponsesInput({
807
+ model,
808
+ context,
809
+ strictResponsesPairing,
810
+ supportsImageDetailOriginal: model.compat.supportsImageDetailOriginal,
811
+ nativeHistory: {
812
+ replay: shouldReplayNativeHistory,
813
+ filterReasoning: policy.reasoning.filterReasoningHistory,
814
+ },
815
+ includeThinkingSignatures: shouldReplayNativeHistory && !policy.reasoning.filterReasoningHistory,
816
+ repairOrphanOutputs: true,
817
+ });
818
+
819
+ const systemPrompts = normalizeSystemPrompts(context.systemPrompt);
820
+ let systemInstructions: string | undefined;
821
+ if (systemPrompts.length > 0) {
822
+ const needsDeveloperRole = policy.messages.systemRole === "developer";
823
+ if (needsDeveloperRole) {
824
+ // Reasoning models on known OpenAI-compatible endpoints require the
825
+ // `developer` role. Send all system prompts inline in `input`.
826
+ messages.unshift(
827
+ ...systemPrompts.map(systemPrompt => ({ role: "developer" as const, content: systemPrompt })),
828
+ );
829
+ } else {
830
+ // All other endpoints (including third-party /v1/responses proxies) use
831
+ // the canonical top-level `instructions` field so that proxies that
832
+ // reject `input[{role:"system"}]` work out of the box.
833
+ systemInstructions = systemPrompts.join("\n\n");
834
+ }
835
+ }
836
+
837
+ const cacheRetention = resolveCacheRetention(options?.cacheRetention);
838
+ const promptCacheKey = getOpenAIResponsesPromptCacheKey(options);
839
+ const modelId = applyWireModelIdTransform(
840
+ model.requestModelId ?? model.id,
841
+ model.compat.wireModelIdMode,
842
+ options?.openrouterVariant,
843
+ );
844
+ const params: OpenAIResponsesSamplingParams = {
845
+ model: modelId,
846
+ input: messages,
847
+ instructions: systemInstructions,
848
+ stream: true,
849
+ prompt_cache_key: promptCacheKey,
850
+ prompt_cache_retention: promptCacheKey
851
+ ? cacheRetention === "long" && model.compat.supportsLongPromptCacheRetention
852
+ ? "24h"
853
+ : undefined
854
+ : undefined,
855
+ // Gateway routing: OpenRouter-only Responses wire field for sticky upstream
856
+ // routing + observability grouping; no equivalent on direct OpenAI.
857
+ session_id: model.compat.isOpenRouterHost ? getOpenRouterResponsesSessionId(options) : undefined,
858
+ store: false,
859
+ stream_options: model.compat.supportsObfuscationOptOut ? { include_obfuscation: false } : undefined,
860
+ };
861
+ maybeAddOpenRouterAnthropicCacheControl(params, model, cacheRetention);
862
+ const outputToken = resolveOpenAIOutputTokenParam({
863
+ field: "max_output_tokens",
864
+ maxTokens: options?.maxTokens,
865
+ maxTokensExplicit: options?.maxTokensExplicit ?? options?.maxTokens !== undefined,
866
+ modelMaxTokens: model.maxTokens,
867
+ omitMaxOutputTokens: model.omitMaxOutputTokens ?? false,
868
+ isOpenRouterHost: model.compat.isOpenRouterHost,
869
+ alwaysSendMaxTokens: model.compat.alwaysSendMaxTokens,
870
+ });
871
+
872
+ applyCommonResponsesSamplingParams(params, { ...options, maxTokens: outputToken?.value }, model);
873
+ if (options?.textVerbosity && isOfficialOpenAIResponsesEndpoint(model)) {
874
+ params.text = { ...params.text, verbosity: options.textVerbosity };
875
+ }
876
+ // TODO: openai responses has no top-level `stop`/`stop_sequences`; surface via reasoning.stop?
877
+ // `StreamOptions.stopSequences` is intentionally dropped for this provider.
878
+ // TODO: openai responses has no top-level `frequency_penalty` field as of the current SDK;
879
+ // `StreamOptions.frequencyPenalty` is intentionally dropped for this provider.
880
+
881
+ let strictToolsApplied = false;
882
+ if (context.tools) {
883
+ const disableStrictTools =
884
+ disableStrictToolsOverride || isStrictToolsDisabledForScope(providerSessionState, strictToolsScope);
885
+ const strictMode = !disableStrictTools && model.compat.supportsStrictMode;
886
+ params.tools = convertTools(context.tools, strictMode, model);
887
+ strictToolsApplied = params.tools.some(t => (t as { strict?: boolean }).strict === true);
888
+ if (options?.toolChoice) {
889
+ // Map tool_choice against the tools that survived quarantine, not the
890
+ // original list: a forced choice for a dropped tool — or "required" when
891
+ // every tool was dropped — would otherwise send a tool_choice with no
892
+ // matching tool, which the provider rejects just like the bad schema did (#2652).
893
+ const emittedNames = new Set(
894
+ params.tools.map(t => (t as { name?: string }).name).filter((n): n is string => n !== undefined),
895
+ );
896
+ const survivingTools =
897
+ params.tools.length === context.tools.length
898
+ ? context.tools
899
+ : context.tools.filter(t => emittedNames.has(t.customWireName ?? t.name));
900
+ const toolChoice = mapOpenAIResponsesToolChoiceForTools(options.toolChoice, survivingTools, model);
901
+ if (toolChoice !== undefined && params.tools.length > 0) {
902
+ params.tool_choice = toolChoice;
903
+ }
904
+ }
905
+ }
906
+
907
+ const reasoningPolicy = resolveOpenAICompatPolicy(model, {
908
+ endpoint: "responses",
909
+ reasoning: options?.reasoning,
910
+ disableReasoning: options?.disableReasoning,
911
+ toolChoice: params.tool_choice,
912
+ strictResponsesPairing: options?.strictResponsesPairing,
913
+ includeEncryptedReasoning: options?.includeEncryptedReasoning,
914
+ filterReasoningHistory: options?.filterReasoningHistory,
915
+ omitReasoningEffort: options?.omitReasoningEffort,
916
+ });
917
+ const trailingScaffoldingItems = applyResponsesCompatPolicy(params, messages, reasoningPolicy, {
918
+ reasoningSummary: options?.reasoningSummary,
919
+ mapEffort: effort =>
920
+ model.compat.reasoningEffortMap?.[effort as NonNullable<OpenAIResponsesOptions["reasoning"]>] ??
921
+ model.thinking?.effortMap?.[effort as NonNullable<OpenAIResponsesOptions["reasoning"]>] ??
922
+ effort,
923
+ });
924
+
925
+ applyOpenAIGatewayRouting(params, model.compat);
926
+
927
+ applyOpenAIExtraBody(params, options?.extraBody);
928
+
929
+ return { params, trailingScaffoldingItems, strictToolsApplied };
930
+ }
931
+
932
+ /**
933
+ * Whether this model should get the OpenAI custom-tool grammar variant
934
+ * for `apply_patch`. The generated model catalog sets
935
+ * `model.applyPatchToolType` for first-party GPT-5 Responses models; this
936
+ * runtime path only consumes that metadata.
937
+ * @internal Exported for tests.
938
+ */
939
+ export function supportsFreeformApplyPatch(
940
+ model: Model<"openai-responses" | "azure-openai-responses" | "openai-codex-responses">,
941
+ ): boolean {
942
+ return model.applyPatchToolType === "freeform";
943
+ }
944
+
945
+ /** @internal Exported for tests. */
946
+ export function mapOpenAIResponsesToolChoiceForTools(
947
+ choice: ToolChoice | undefined,
948
+ tools: Tool[],
949
+ model: Model<"openai-responses">,
950
+ ): OpenAIResponsesToolChoice {
951
+ if (!model.compat.supportsToolChoice) return undefined;
952
+ if (isForcedToolChoice(choice) && !model.compat.supportsForcedToolChoice) {
953
+ return "auto";
954
+ }
955
+ const mapped = mapToOpenAIResponsesToolChoice(choice);
956
+ if (!mapped || typeof mapped === "string" || mapped.type !== "function") {
957
+ return mapped;
958
+ }
959
+
960
+ const directTool = tools.find(tool => tool.name === mapped.name);
961
+ const customTool = supportsFreeformApplyPatch(model)
962
+ ? tools.find(tool => tool.customFormat && (tool.name === mapped.name || tool.customWireName === mapped.name))
963
+ : undefined;
964
+ const offeredTool = customTool ?? directTool;
965
+ if (!offeredTool) {
966
+ return undefined;
967
+ }
968
+ return customTool ? { type: "custom", name: customTool.customWireName ?? customTool.name } : mapped;
969
+ }
970
+
971
+ /** @internal Exported for tests. */
972
+ export function convertTools(
973
+ tools: Tool[],
974
+ strictMode: boolean,
975
+ model: Model<"openai-responses" | "azure-openai-responses" | "openai-codex-responses">,
976
+ onQuarantine: (toolName: string, schemaPath: string) => void = (toolName, schemaPath) =>
977
+ logger.warn(
978
+ `Tool "${toolName}" omitted from the openai-responses request: its parameter schema is invalid for this provider at ${schemaPath} (an enum/const value cannot match its declared type). Other tools are unaffected.`,
979
+ ),
980
+ ): OpenAITool[] {
981
+ const allowFreeform = supportsFreeformApplyPatch(model);
982
+ const out: OpenAITool[] = [];
983
+ for (const tool of tools) {
984
+ if (allowFreeform && tool.customFormat) {
985
+ out.push({
986
+ type: "custom",
987
+ // Tool advertises its wire-level name (e.g. `apply_patch`) — the
988
+ // agent-loop dispatcher will match incoming calls by either the
989
+ // internal `name` or `customWireName`.
990
+ name: tool.customWireName ?? tool.name,
991
+ description: tool.description || "",
992
+ format: {
993
+ type: "grammar",
994
+ syntax: tool.customFormat.syntax,
995
+ definition: compactGrammarDefinition(tool.customFormat.syntax, tool.customFormat.definition),
996
+ },
997
+ } as unknown as OpenAITool);
998
+ continue;
999
+ }
1000
+ const strict = !NO_STRICT && strictMode && tool.strict !== false;
1001
+ const baseParameters = toolWireSchema(tool);
1002
+ const responseParameters = sanitizeSchemaForOpenAIResponses(baseParameters);
1003
+ const { schema: parameters, strict: effectiveStrict } = adaptSchemaForStrict(responseParameters, strict);
1004
+ // Quarantine a tool whose emitted schema carries a provider-rejecting
1005
+ // enum/const-vs-type contradiction: dropping just that tool keeps the rest
1006
+ // of the request valid instead of letting one bad MCP schema 400 the whole
1007
+ // turn (#2652). Other tools and built-ins are unaffected.
1008
+ const violation = findStrictToolSchemaViolation(parameters);
1009
+ if (violation) {
1010
+ onQuarantine(tool.name, violation);
1011
+ continue;
1012
+ }
1013
+ out.push({
1014
+ type: "function",
1015
+ name: tool.name,
1016
+ description: tool.description || "",
1017
+ parameters,
1018
+ ...(effectiveStrict && { strict: true }),
1019
+ } as OpenAITool);
1020
+ }
1021
+ return out;
1022
+ }