@gajae-code/ai 0.1.1

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 (349) hide show
  1. package/CHANGELOG.md +2644 -0
  2. package/README.md +1181 -0
  3. package/dist/types/api-registry.d.ts +30 -0
  4. package/dist/types/auth-broker/client.d.ts +66 -0
  5. package/dist/types/auth-broker/index.d.ts +5 -0
  6. package/dist/types/auth-broker/refresher.d.ts +25 -0
  7. package/dist/types/auth-broker/remote-store.d.ts +96 -0
  8. package/dist/types/auth-broker/server.d.ts +32 -0
  9. package/dist/types/auth-broker/types.d.ts +105 -0
  10. package/dist/types/auth-broker/wire-schemas.d.ts +412 -0
  11. package/dist/types/auth-gateway/http.d.ts +39 -0
  12. package/dist/types/auth-gateway/index.d.ts +3 -0
  13. package/dist/types/auth-gateway/server.d.ts +17 -0
  14. package/dist/types/auth-gateway/types.d.ts +115 -0
  15. package/dist/types/auth-storage.d.ts +641 -0
  16. package/dist/types/cli.d.ts +2 -0
  17. package/dist/types/index.d.ts +49 -0
  18. package/dist/types/model-cache.d.ts +17 -0
  19. package/dist/types/model-manager.d.ts +62 -0
  20. package/dist/types/model-thinking.d.ts +71 -0
  21. package/dist/types/models.d.ts +12 -0
  22. package/dist/types/provider-details.d.ts +24 -0
  23. package/dist/types/provider-models/bundled-references.d.ts +4 -0
  24. package/dist/types/provider-models/descriptors.d.ts +48 -0
  25. package/dist/types/provider-models/google.d.ts +20 -0
  26. package/dist/types/provider-models/index.d.ts +5 -0
  27. package/dist/types/provider-models/ollama.d.ts +7 -0
  28. package/dist/types/provider-models/openai-compat.d.ts +237 -0
  29. package/dist/types/provider-models/special.d.ts +16 -0
  30. package/dist/types/providers/amazon-bedrock.d.ts +36 -0
  31. package/dist/types/providers/anthropic-messages-server-schema.d.ts +450 -0
  32. package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
  33. package/dist/types/providers/anthropic.d.ts +188 -0
  34. package/dist/types/providers/aws-credentials.d.ts +43 -0
  35. package/dist/types/providers/aws-eventstream.d.ts +38 -0
  36. package/dist/types/providers/aws-sigv4.d.ts +55 -0
  37. package/dist/types/providers/azure-openai-responses.d.ts +15 -0
  38. package/dist/types/providers/cursor/gen/agent_pb.d.ts +13022 -0
  39. package/dist/types/providers/cursor.d.ts +42 -0
  40. package/dist/types/providers/error-message.d.ts +27 -0
  41. package/dist/types/providers/github-copilot-headers.d.ts +40 -0
  42. package/dist/types/providers/gitlab-duo.d.ts +27 -0
  43. package/dist/types/providers/google-auth.d.ts +24 -0
  44. package/dist/types/providers/google-gemini-cli.d.ts +72 -0
  45. package/dist/types/providers/google-gemini-headers.d.ts +18 -0
  46. package/dist/types/providers/google-shared.d.ts +163 -0
  47. package/dist/types/providers/google-types.d.ts +138 -0
  48. package/dist/types/providers/google-vertex.d.ts +7 -0
  49. package/dist/types/providers/google.d.ts +4 -0
  50. package/dist/types/providers/grammar.d.ts +1 -0
  51. package/dist/types/providers/kimi.d.ts +27 -0
  52. package/dist/types/providers/mock.d.ts +175 -0
  53. package/dist/types/providers/ollama.d.ts +6 -0
  54. package/dist/types/providers/openai-anthropic-shim.d.ts +31 -0
  55. package/dist/types/providers/openai-chat-server-schema.d.ts +814 -0
  56. package/dist/types/providers/openai-chat-server.d.ts +16 -0
  57. package/dist/types/providers/openai-codex/constants.d.ts +26 -0
  58. package/dist/types/providers/openai-codex/request-transformer.d.ts +49 -0
  59. package/dist/types/providers/openai-codex/response-handler.d.ts +17 -0
  60. package/dist/types/providers/openai-codex-responses.d.ts +67 -0
  61. package/dist/types/providers/openai-completions-compat.d.ts +25 -0
  62. package/dist/types/providers/openai-completions.d.ts +33 -0
  63. package/dist/types/providers/openai-responses-server-schema.d.ts +392 -0
  64. package/dist/types/providers/openai-responses-server.d.ts +17 -0
  65. package/dist/types/providers/openai-responses-shared.d.ts +89 -0
  66. package/dist/types/providers/openai-responses.d.ts +32 -0
  67. package/dist/types/providers/pi-native-client.d.ts +13 -0
  68. package/dist/types/providers/pi-native-server.d.ts +68 -0
  69. package/dist/types/providers/register-builtins.d.ts +31 -0
  70. package/dist/types/providers/synthetic.d.ts +26 -0
  71. package/dist/types/providers/transform-messages.d.ts +12 -0
  72. package/dist/types/providers/vision-guard.d.ts +8 -0
  73. package/dist/types/rate-limit-utils.d.ts +19 -0
  74. package/dist/types/stream.d.ts +24 -0
  75. package/dist/types/types.d.ts +746 -0
  76. package/dist/types/usage/claude.d.ts +3 -0
  77. package/dist/types/usage/gemini.d.ts +2 -0
  78. package/dist/types/usage/github-copilot.d.ts +7 -0
  79. package/dist/types/usage/google-antigravity.d.ts +2 -0
  80. package/dist/types/usage/kimi.d.ts +2 -0
  81. package/dist/types/usage/minimax-code.d.ts +2 -0
  82. package/dist/types/usage/openai-codex.d.ts +3 -0
  83. package/dist/types/usage/shared.d.ts +1 -0
  84. package/dist/types/usage/zai.d.ts +2 -0
  85. package/dist/types/usage.d.ts +258 -0
  86. package/dist/types/utils/abort.d.ts +19 -0
  87. package/dist/types/utils/anthropic-auth.d.ts +31 -0
  88. package/dist/types/utils/discovery/antigravity.d.ts +61 -0
  89. package/dist/types/utils/discovery/codex.d.ts +38 -0
  90. package/dist/types/utils/discovery/cursor.d.ts +23 -0
  91. package/dist/types/utils/discovery/gemini.d.ts +25 -0
  92. package/dist/types/utils/discovery/index.d.ts +4 -0
  93. package/dist/types/utils/discovery/openai-compatible.d.ts +72 -0
  94. package/dist/types/utils/event-stream.d.ts +28 -0
  95. package/dist/types/utils/fireworks-model-id.d.ts +10 -0
  96. package/dist/types/utils/foundry.d.ts +1 -0
  97. package/dist/types/utils/h2-fetch.d.ts +22 -0
  98. package/dist/types/utils/http-inspector.d.ts +31 -0
  99. package/dist/types/utils/idle-iterator.d.ts +67 -0
  100. package/dist/types/utils/json-parse.d.ts +10 -0
  101. package/dist/types/utils/oauth/alibaba-coding-plan.d.ts +18 -0
  102. package/dist/types/utils/oauth/anthropic.d.ts +22 -0
  103. package/dist/types/utils/oauth/api-key-login.d.ts +35 -0
  104. package/dist/types/utils/oauth/api-key-validation.d.ts +27 -0
  105. package/dist/types/utils/oauth/callback-server.d.ts +57 -0
  106. package/dist/types/utils/oauth/cerebras.d.ts +1 -0
  107. package/dist/types/utils/oauth/cloudflare-ai-gateway.d.ts +18 -0
  108. package/dist/types/utils/oauth/cursor.d.ts +15 -0
  109. package/dist/types/utils/oauth/deepseek.d.ts +10 -0
  110. package/dist/types/utils/oauth/firepass.d.ts +1 -0
  111. package/dist/types/utils/oauth/fireworks.d.ts +1 -0
  112. package/dist/types/utils/oauth/github-copilot.d.ts +38 -0
  113. package/dist/types/utils/oauth/gitlab-duo.d.ts +3 -0
  114. package/dist/types/utils/oauth/google-antigravity.d.ts +11 -0
  115. package/dist/types/utils/oauth/google-gemini-cli.d.ts +10 -0
  116. package/dist/types/utils/oauth/google-oauth-shared.d.ts +28 -0
  117. package/dist/types/utils/oauth/huggingface.d.ts +19 -0
  118. package/dist/types/utils/oauth/index.d.ts +38 -0
  119. package/dist/types/utils/oauth/kagi.d.ts +17 -0
  120. package/dist/types/utils/oauth/kilo.d.ts +5 -0
  121. package/dist/types/utils/oauth/kimi.d.ts +21 -0
  122. package/dist/types/utils/oauth/litellm.d.ts +18 -0
  123. package/dist/types/utils/oauth/lm-studio.d.ts +17 -0
  124. package/dist/types/utils/oauth/minimax-code.d.ts +28 -0
  125. package/dist/types/utils/oauth/moonshot.d.ts +1 -0
  126. package/dist/types/utils/oauth/nanogpt.d.ts +1 -0
  127. package/dist/types/utils/oauth/nvidia.d.ts +18 -0
  128. package/dist/types/utils/oauth/ollama-cloud.d.ts +2 -0
  129. package/dist/types/utils/oauth/ollama.d.ts +18 -0
  130. package/dist/types/utils/oauth/openai-codex.d.ts +21 -0
  131. package/dist/types/utils/oauth/opencode.d.ts +18 -0
  132. package/dist/types/utils/oauth/parallel.d.ts +17 -0
  133. package/dist/types/utils/oauth/perplexity.d.ts +9 -0
  134. package/dist/types/utils/oauth/pkce.d.ts +8 -0
  135. package/dist/types/utils/oauth/qianfan.d.ts +17 -0
  136. package/dist/types/utils/oauth/qwen-portal.d.ts +19 -0
  137. package/dist/types/utils/oauth/synthetic.d.ts +1 -0
  138. package/dist/types/utils/oauth/tavily.d.ts +17 -0
  139. package/dist/types/utils/oauth/together.d.ts +1 -0
  140. package/dist/types/utils/oauth/types.d.ts +44 -0
  141. package/dist/types/utils/oauth/venice.d.ts +18 -0
  142. package/dist/types/utils/oauth/vercel-ai-gateway.d.ts +18 -0
  143. package/dist/types/utils/oauth/vllm.d.ts +16 -0
  144. package/dist/types/utils/oauth/xiaomi.d.ts +19 -0
  145. package/dist/types/utils/oauth/zai.d.ts +18 -0
  146. package/dist/types/utils/oauth/zenmux.d.ts +1 -0
  147. package/dist/types/utils/overflow.d.ts +54 -0
  148. package/dist/types/utils/parse-bind.d.ts +23 -0
  149. package/dist/types/utils/provider-response.d.ts +3 -0
  150. package/dist/types/utils/retry-after.d.ts +3 -0
  151. package/dist/types/utils/retry.d.ts +26 -0
  152. package/dist/types/utils/schema/adapt.d.ts +24 -0
  153. package/dist/types/utils/schema/compatibility.d.ts +30 -0
  154. package/dist/types/utils/schema/dereference.d.ts +11 -0
  155. package/dist/types/utils/schema/draft.d.ts +10 -0
  156. package/dist/types/utils/schema/equality.d.ts +4 -0
  157. package/dist/types/utils/schema/fields.d.ts +49 -0
  158. package/dist/types/utils/schema/index.d.ts +13 -0
  159. package/dist/types/utils/schema/json-schema-validator.d.ts +12 -0
  160. package/dist/types/utils/schema/meta-validator.d.ts +2 -0
  161. package/dist/types/utils/schema/normalize.d.ts +93 -0
  162. package/dist/types/utils/schema/spill.d.ts +8 -0
  163. package/dist/types/utils/schema/stamps.d.ts +25 -0
  164. package/dist/types/utils/schema/types.d.ts +4 -0
  165. package/dist/types/utils/schema/wire.d.ts +54 -0
  166. package/dist/types/utils/schema/zod-decontaminate.d.ts +31 -0
  167. package/dist/types/utils/sse-debug.d.ts +10 -0
  168. package/dist/types/utils/tool-call-healing.d.ts +71 -0
  169. package/dist/types/utils/tool-choice.d.ts +50 -0
  170. package/dist/types/utils/validation.d.ts +17 -0
  171. package/dist/types/utils.d.ts +28 -0
  172. package/package.json +146 -0
  173. package/src/api-registry.ts +96 -0
  174. package/src/auth-broker/client.ts +358 -0
  175. package/src/auth-broker/index.ts +5 -0
  176. package/src/auth-broker/refresher.ts +127 -0
  177. package/src/auth-broker/remote-store.ts +623 -0
  178. package/src/auth-broker/server.ts +644 -0
  179. package/src/auth-broker/types.ts +127 -0
  180. package/src/auth-broker/wire-schemas.ts +200 -0
  181. package/src/auth-gateway/http.ts +194 -0
  182. package/src/auth-gateway/index.ts +3 -0
  183. package/src/auth-gateway/server.ts +717 -0
  184. package/src/auth-gateway/types.ts +134 -0
  185. package/src/auth-storage.ts +4104 -0
  186. package/src/cli.ts +262 -0
  187. package/src/index.ts +54 -0
  188. package/src/model-cache.ts +129 -0
  189. package/src/model-manager.ts +450 -0
  190. package/src/model-thinking.ts +691 -0
  191. package/src/models.json +73853 -0
  192. package/src/models.json.d.ts +9 -0
  193. package/src/models.ts +56 -0
  194. package/src/prompts/turn-aborted-guidance.md +4 -0
  195. package/src/provider-details.ts +90 -0
  196. package/src/provider-models/bundled-references.ts +38 -0
  197. package/src/provider-models/descriptors.ts +308 -0
  198. package/src/provider-models/google.ts +91 -0
  199. package/src/provider-models/index.ts +5 -0
  200. package/src/provider-models/ollama.ts +153 -0
  201. package/src/provider-models/openai-compat.ts +2275 -0
  202. package/src/provider-models/special.ts +67 -0
  203. package/src/providers/amazon-bedrock.ts +849 -0
  204. package/src/providers/anthropic-messages-server-schema.ts +229 -0
  205. package/src/providers/anthropic-messages-server.ts +677 -0
  206. package/src/providers/anthropic.ts +2696 -0
  207. package/src/providers/aws-credentials.ts +501 -0
  208. package/src/providers/aws-eventstream.ts +185 -0
  209. package/src/providers/aws-sigv4.ts +218 -0
  210. package/src/providers/azure-openai-responses.ts +337 -0
  211. package/src/providers/cursor/gen/agent_pb.ts +15274 -0
  212. package/src/providers/cursor/proto/agent.proto +3526 -0
  213. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  214. package/src/providers/cursor/proto/buf.yaml +17 -0
  215. package/src/providers/cursor.ts +2561 -0
  216. package/src/providers/error-message.ts +21 -0
  217. package/src/providers/github-copilot-headers.ts +140 -0
  218. package/src/providers/gitlab-duo.ts +372 -0
  219. package/src/providers/google-auth.ts +252 -0
  220. package/src/providers/google-gemini-cli.ts +795 -0
  221. package/src/providers/google-gemini-headers.ts +41 -0
  222. package/src/providers/google-shared.ts +902 -0
  223. package/src/providers/google-types.ts +167 -0
  224. package/src/providers/google-vertex.ts +88 -0
  225. package/src/providers/google.ts +41 -0
  226. package/src/providers/grammar.ts +70 -0
  227. package/src/providers/kimi.ts +52 -0
  228. package/src/providers/mock.ts +500 -0
  229. package/src/providers/ollama.ts +544 -0
  230. package/src/providers/openai-anthropic-shim.ts +138 -0
  231. package/src/providers/openai-chat-server-schema.ts +243 -0
  232. package/src/providers/openai-chat-server.ts +628 -0
  233. package/src/providers/openai-codex/constants.ts +43 -0
  234. package/src/providers/openai-codex/request-transformer.ts +161 -0
  235. package/src/providers/openai-codex/response-handler.ts +81 -0
  236. package/src/providers/openai-codex-responses.ts +2598 -0
  237. package/src/providers/openai-completions-compat.ts +279 -0
  238. package/src/providers/openai-completions.ts +1853 -0
  239. package/src/providers/openai-responses-server-schema.ts +290 -0
  240. package/src/providers/openai-responses-server.ts +1183 -0
  241. package/src/providers/openai-responses-shared.ts +800 -0
  242. package/src/providers/openai-responses.ts +621 -0
  243. package/src/providers/pi-native-client.ts +228 -0
  244. package/src/providers/pi-native-server.ts +210 -0
  245. package/src/providers/register-builtins.ts +412 -0
  246. package/src/providers/synthetic.ts +50 -0
  247. package/src/providers/transform-messages.ts +309 -0
  248. package/src/providers/vision-guard.ts +31 -0
  249. package/src/rate-limit-utils.ts +84 -0
  250. package/src/stream.ts +895 -0
  251. package/src/types.ts +884 -0
  252. package/src/usage/claude.ts +431 -0
  253. package/src/usage/gemini.ts +250 -0
  254. package/src/usage/github-copilot.ts +421 -0
  255. package/src/usage/google-antigravity.ts +201 -0
  256. package/src/usage/kimi.ts +271 -0
  257. package/src/usage/minimax-code.ts +31 -0
  258. package/src/usage/openai-codex.ts +503 -0
  259. package/src/usage/shared.ts +10 -0
  260. package/src/usage/zai.ts +247 -0
  261. package/src/usage.ts +183 -0
  262. package/src/utils/abort.ts +51 -0
  263. package/src/utils/anthropic-auth.ts +87 -0
  264. package/src/utils/discovery/antigravity.ts +261 -0
  265. package/src/utils/discovery/codex.ts +371 -0
  266. package/src/utils/discovery/cursor.ts +306 -0
  267. package/src/utils/discovery/gemini.ts +248 -0
  268. package/src/utils/discovery/index.ts +4 -0
  269. package/src/utils/discovery/openai-compatible.ts +224 -0
  270. package/src/utils/event-stream.ts +142 -0
  271. package/src/utils/fireworks-model-id.ts +30 -0
  272. package/src/utils/foundry.ts +8 -0
  273. package/src/utils/h2-fetch.ts +60 -0
  274. package/src/utils/http-inspector.ts +176 -0
  275. package/src/utils/idle-iterator.ts +250 -0
  276. package/src/utils/json-parse.ts +148 -0
  277. package/src/utils/oauth/alibaba-coding-plan.ts +59 -0
  278. package/src/utils/oauth/anthropic.ts +200 -0
  279. package/src/utils/oauth/api-key-login.ts +87 -0
  280. package/src/utils/oauth/api-key-validation.ts +92 -0
  281. package/src/utils/oauth/callback-server.ts +276 -0
  282. package/src/utils/oauth/cerebras.ts +16 -0
  283. package/src/utils/oauth/cloudflare-ai-gateway.ts +48 -0
  284. package/src/utils/oauth/cursor.ts +157 -0
  285. package/src/utils/oauth/deepseek.ts +53 -0
  286. package/src/utils/oauth/firepass.ts +24 -0
  287. package/src/utils/oauth/fireworks.ts +15 -0
  288. package/src/utils/oauth/github-copilot.ts +362 -0
  289. package/src/utils/oauth/gitlab-duo.ts +123 -0
  290. package/src/utils/oauth/google-antigravity.ts +200 -0
  291. package/src/utils/oauth/google-gemini-cli.ts +256 -0
  292. package/src/utils/oauth/google-oauth-shared.ts +110 -0
  293. package/src/utils/oauth/huggingface.ts +62 -0
  294. package/src/utils/oauth/index.ts +444 -0
  295. package/src/utils/oauth/kagi.ts +47 -0
  296. package/src/utils/oauth/kilo.ts +87 -0
  297. package/src/utils/oauth/kimi.ts +254 -0
  298. package/src/utils/oauth/litellm.ts +47 -0
  299. package/src/utils/oauth/lm-studio.ts +38 -0
  300. package/src/utils/oauth/minimax-code.ts +78 -0
  301. package/src/utils/oauth/moonshot.ts +16 -0
  302. package/src/utils/oauth/nanogpt.ts +15 -0
  303. package/src/utils/oauth/nvidia.ts +70 -0
  304. package/src/utils/oauth/oauth.html +199 -0
  305. package/src/utils/oauth/ollama-cloud.ts +28 -0
  306. package/src/utils/oauth/ollama.ts +47 -0
  307. package/src/utils/oauth/openai-codex.ts +299 -0
  308. package/src/utils/oauth/opencode.ts +49 -0
  309. package/src/utils/oauth/parallel.ts +46 -0
  310. package/src/utils/oauth/perplexity.ts +206 -0
  311. package/src/utils/oauth/pkce.ts +18 -0
  312. package/src/utils/oauth/qianfan.ts +58 -0
  313. package/src/utils/oauth/qwen-portal.ts +60 -0
  314. package/src/utils/oauth/synthetic.ts +16 -0
  315. package/src/utils/oauth/tavily.ts +46 -0
  316. package/src/utils/oauth/together.ts +16 -0
  317. package/src/utils/oauth/types.ts +94 -0
  318. package/src/utils/oauth/venice.ts +59 -0
  319. package/src/utils/oauth/vercel-ai-gateway.ts +47 -0
  320. package/src/utils/oauth/vllm.ts +40 -0
  321. package/src/utils/oauth/xiaomi.ts +137 -0
  322. package/src/utils/oauth/zai.ts +60 -0
  323. package/src/utils/oauth/zenmux.ts +15 -0
  324. package/src/utils/overflow.ts +137 -0
  325. package/src/utils/parse-bind.ts +54 -0
  326. package/src/utils/provider-response.ts +30 -0
  327. package/src/utils/retry-after.ts +110 -0
  328. package/src/utils/retry.ts +54 -0
  329. package/src/utils/schema/CONSTRAINTS.md +164 -0
  330. package/src/utils/schema/adapt.ts +36 -0
  331. package/src/utils/schema/compatibility.ts +435 -0
  332. package/src/utils/schema/dereference.ts +98 -0
  333. package/src/utils/schema/draft.ts +341 -0
  334. package/src/utils/schema/equality.ts +97 -0
  335. package/src/utils/schema/fields.ts +190 -0
  336. package/src/utils/schema/index.ts +13 -0
  337. package/src/utils/schema/json-schema-validator.ts +577 -0
  338. package/src/utils/schema/meta-validator.ts +167 -0
  339. package/src/utils/schema/normalize.ts +1588 -0
  340. package/src/utils/schema/spill.ts +43 -0
  341. package/src/utils/schema/stamps.ts +97 -0
  342. package/src/utils/schema/types.ts +11 -0
  343. package/src/utils/schema/wire.ts +213 -0
  344. package/src/utils/schema/zod-decontaminate.ts +331 -0
  345. package/src/utils/sse-debug.ts +289 -0
  346. package/src/utils/tool-call-healing.ts +271 -0
  347. package/src/utils/tool-choice.ts +99 -0
  348. package/src/utils/validation.ts +1019 -0
  349. package/src/utils.ts +166 -0
@@ -0,0 +1,279 @@
1
+ import type { Model, OpenAICompat } from "../types";
2
+
3
+ type OpenAIReasoningEffort = "minimal" | "low" | "medium" | "high" | "xhigh";
4
+ type ResolvedToolStrictMode = NonNullable<OpenAICompat["toolStrictMode"]> | "mixed";
5
+
6
+ export type ResolvedOpenAICompat = Required<
7
+ Omit<OpenAICompat, "openRouterRouting" | "vercelGatewayRouting" | "extraBody" | "toolStrictMode">
8
+ > & {
9
+ openRouterRouting?: OpenAICompat["openRouterRouting"];
10
+ vercelGatewayRouting?: OpenAICompat["vercelGatewayRouting"];
11
+ extraBody?: OpenAICompat["extraBody"];
12
+ toolStrictMode: ResolvedToolStrictMode;
13
+ };
14
+
15
+ function detectStrictModeSupport(provider: string, baseUrl: string): boolean {
16
+ if (
17
+ provider === "openai" ||
18
+ provider === "openrouter" ||
19
+ provider === "cerebras" ||
20
+ provider === "together" ||
21
+ provider === "github-copilot" ||
22
+ provider === "zenmux"
23
+ ) {
24
+ return true;
25
+ }
26
+
27
+ const normalizedBaseUrl = baseUrl.toLowerCase();
28
+ return (
29
+ normalizedBaseUrl.includes("api.openai.com") ||
30
+ normalizedBaseUrl.includes(".openai.azure.com") ||
31
+ normalizedBaseUrl.includes("models.inference.ai.azure.com") ||
32
+ normalizedBaseUrl.includes("api.cerebras.ai") ||
33
+ normalizedBaseUrl.includes("api.together.xyz") ||
34
+ normalizedBaseUrl.includes("openrouter.ai") ||
35
+ normalizedBaseUrl.includes("api.deepseek.com") ||
36
+ normalizedBaseUrl.includes("deepseek.com")
37
+ );
38
+ }
39
+
40
+ /**
41
+ * Detect compatibility settings from provider and baseUrl for known providers.
42
+ * Provider takes precedence over URL-based detection since it's explicitly configured.
43
+ * @param model - The model configuration
44
+ * @param resolvedBaseUrl - Optional resolved base URL (e.g., after GitHub Copilot proxy-ep resolution).
45
+ * If provided, this takes precedence over model.baseUrl for URL-based checks.
46
+ */
47
+ export function detectOpenAICompat(model: Model<"openai-completions">, resolvedBaseUrl?: string): ResolvedOpenAICompat {
48
+ const provider = model.provider;
49
+ // Use resolvedBaseUrl if provided (e.g., after GitHub Copilot proxy-ep resolution)
50
+ const baseUrl = resolvedBaseUrl ?? model.baseUrl;
51
+
52
+ const isCerebras = provider === "cerebras" || baseUrl.includes("cerebras.ai");
53
+ const isZai = provider === "zai" || baseUrl.includes("api.z.ai");
54
+ const isKilo = provider === "kilo" || baseUrl.includes("api.kilo.ai");
55
+ const isKimiModel = model.id.includes("moonshotai/kimi") || /(^|\/)kimi[-.]/i.test(model.id);
56
+ const isMoonshotKimi =
57
+ isKimiModel &&
58
+ (provider === "moonshot" ||
59
+ provider === "kimi-code" ||
60
+ baseUrl.includes("api.moonshot.ai") ||
61
+ baseUrl.includes("api.kimi.com"));
62
+ const isAnthropicModel =
63
+ provider === "anthropic" ||
64
+ baseUrl.includes("api.anthropic.com") ||
65
+ /(^|\/)claude[-.]/i.test(model.id) ||
66
+ /(^|\/)anthropic\//i.test(model.id);
67
+ const isAlibaba = provider === "alibaba-coding-plan" || baseUrl.includes("dashscope");
68
+ const isQwen = model.id.toLowerCase().includes("qwen");
69
+ // DeepSeek V4 (and other reasoning-capable DeepSeek models) reject follow-up requests in
70
+ // thinking mode unless prior assistant tool-call turns include `reasoning_content`. The
71
+ // upstream model is reachable through many OpenAI-compat hosts (api.deepseek.com, Deepinfra,
72
+ // Kilo, NVIDIA NIM, Zenmux, OpenRouter, …), so we match by model id/name as well as by
73
+ // provider/baseUrl. The flag is gated by `model.reasoning` because the invariant only
74
+ // applies when thinking mode is actually engaged.
75
+ const lowerId = model.id.toLowerCase();
76
+ const lowerName = (model.name ?? "").toLowerCase();
77
+ const isDeepseekFamily =
78
+ provider === "deepseek" ||
79
+ baseUrl.includes("deepseek.com") ||
80
+ lowerId.includes("deepseek") ||
81
+ lowerName.includes("deepseek");
82
+ const isDirectDeepseekApi = provider === "deepseek" || baseUrl.includes("api.deepseek.com");
83
+ const isDirectDeepseekReasoning = isDirectDeepseekApi && isDeepseekFamily && Boolean(model.reasoning);
84
+ const isNonStandard =
85
+ isCerebras ||
86
+ provider === "xai" ||
87
+ baseUrl.includes("api.x.ai") ||
88
+ provider === "mistral" ||
89
+ baseUrl.includes("mistral.ai") ||
90
+ baseUrl.includes("chutes.ai") ||
91
+ baseUrl.includes("deepseek.com") ||
92
+ baseUrl.includes("fireworks.ai") ||
93
+ isAlibaba ||
94
+ isZai ||
95
+ isKilo ||
96
+ isQwen ||
97
+ provider === "opencode-zen" ||
98
+ provider === "opencode-go" ||
99
+ baseUrl.includes("opencode.ai");
100
+ const isOpenCodeProvider = provider === "opencode-go" || provider === "opencode-zen";
101
+
102
+ const useMaxTokens =
103
+ provider === "mistral" ||
104
+ baseUrl.includes("mistral.ai") ||
105
+ baseUrl.includes("chutes.ai") ||
106
+ baseUrl.includes("fireworks.ai") ||
107
+ isDirectDeepseekApi;
108
+ const isGrok = provider === "xai" || baseUrl.includes("api.x.ai");
109
+ const isMistral = provider === "mistral" || baseUrl.includes("mistral.ai");
110
+
111
+ // Hosts whose chat-completions endpoints are known to accept multiple
112
+ // leading `system`/`developer` messages (preferred for KV-cache reuse).
113
+ // Anything outside this allowlist defaults to coalescing because
114
+ // strict chat templates (Qwen 3.5+ via vLLM, MiniMax, etc.) reject
115
+ // follow-up system messages with a 400.
116
+ const isOpenAIHost = provider === "openai" || baseUrl.includes("api.openai.com");
117
+ const isAzureHost =
118
+ provider === "azure" ||
119
+ baseUrl.includes(".openai.azure.com") ||
120
+ baseUrl.includes("models.inference.ai.azure.com") ||
121
+ baseUrl.includes("azure.com/openai");
122
+ const isOpenRouter = provider === "openrouter" || baseUrl.includes("openrouter.ai");
123
+ const isTogether = provider === "together" || baseUrl.includes("api.together.xyz");
124
+ const isFireworks = baseUrl.includes("fireworks.ai");
125
+ const isGroqHost = provider === "groq" || baseUrl.includes("api.groq.com");
126
+ const isCopilotHost = provider === "github-copilot";
127
+ const isZenmuxHost = provider === "zenmux";
128
+ // Endpoints that MUST receive a single system block. MiniMax's OpenAI
129
+ // endpoint returns error 2013 on multiple system messages; Alibaba's
130
+ // Dashscope and Qwen Portal serve Qwen models whose chat template
131
+ // raises "System message must be at the beginning" if any system
132
+ // message appears past index 0.
133
+ const isMiniMaxHost =
134
+ provider === "minimax-code" ||
135
+ provider === "minimax-code-cn" ||
136
+ baseUrl.includes("api.minimax.io") ||
137
+ baseUrl.includes("api.minimaxi.com");
138
+ const isQwenPortal = provider === "qwen-portal" || baseUrl.includes("portal.qwen.ai");
139
+ const supportsMultipleSystemMessagesDefault =
140
+ !isMiniMaxHost &&
141
+ !isAlibaba &&
142
+ !isQwenPortal &&
143
+ (isOpenAIHost ||
144
+ isAzureHost ||
145
+ isOpenRouter ||
146
+ isCerebras ||
147
+ isTogether ||
148
+ isFireworks ||
149
+ isGroqHost ||
150
+ isDeepseekFamily ||
151
+ isMistral ||
152
+ isGrok ||
153
+ isZai ||
154
+ isCopilotHost ||
155
+ isZenmuxHost);
156
+
157
+ const reasoningEffortMap: NonNullable<OpenAICompat["reasoningEffortMap"]> =
158
+ provider === "groq" && model.id === "qwen/qwen3-32b"
159
+ ? ({
160
+ minimal: "default",
161
+ low: "default",
162
+ medium: "default",
163
+ high: "default",
164
+ xhigh: "default",
165
+ } satisfies Partial<Record<OpenAIReasoningEffort, string>>)
166
+ : isDeepseekFamily && model.reasoning
167
+ ? ({
168
+ minimal: "high",
169
+ low: "high",
170
+ medium: "high",
171
+ high: "high",
172
+ xhigh: "max",
173
+ } satisfies Partial<Record<OpenAIReasoningEffort, string>>)
174
+ : isFireworks
175
+ ? ({
176
+ // Fireworks' OpenAI-compatible endpoint rejects OpenAI's
177
+ // `minimal` literal but accepts `none` for the lowest setting.
178
+ minimal: "none",
179
+ } satisfies Partial<Record<OpenAIReasoningEffort, string>>)
180
+ : {};
181
+
182
+ return {
183
+ supportsStore: !isNonStandard,
184
+ supportsDeveloperRole: !isNonStandard,
185
+ supportsMultipleSystemMessages: supportsMultipleSystemMessagesDefault,
186
+ supportsReasoningEffort: !isGrok && !isZai,
187
+ reasoningEffortMap,
188
+ supportsUsageInStreaming: !isCerebras,
189
+ disableReasoningOnForcedToolChoice: isKimiModel || isAnthropicModel,
190
+ disableReasoningOnToolChoice: isDeepseekFamily && Boolean(model.reasoning) && !isOpenRouter,
191
+ supportsToolChoice: !isDirectDeepseekReasoning,
192
+ maxTokensField: useMaxTokens ? "max_tokens" : "max_completion_tokens",
193
+ requiresToolResultName: isMistral,
194
+ requiresAssistantAfterToolResult: false,
195
+ requiresThinkingAsText: isMistral,
196
+ requiresMistralToolIds: isMistral,
197
+ thinkingFormat:
198
+ isZai || isMoonshotKimi
199
+ ? "zai"
200
+ : provider === "openrouter" || baseUrl.includes("openrouter.ai")
201
+ ? "openrouter"
202
+ : isAlibaba || isQwen
203
+ ? "qwen"
204
+ : "openai",
205
+ reasoningContentField: "reasoning_content",
206
+ // Backends that 400 follow-up requests when prior assistant tool-call turns lack `reasoning_content`:
207
+ // - Kimi: documented invariant on its native API.
208
+ // - Any reasoning-capable model reached through OpenRouter: DeepSeek V4 Pro and similar enforce
209
+ // this server-side whenever the request is in thinking mode. We can't translate Anthropic's
210
+ // redacted/encrypted reasoning into DeepSeek's plaintext form, so cross-provider continuations
211
+ // rely on a placeholder — see `convertMessages` for the placeholder injection.
212
+ // - OpenCode-Go and OpenCode-Zen handle reasoning content internally and reject
213
+ // `reasoning_content` in client-sent messages — exclude them even for Kimi models.
214
+ requiresReasoningContentForToolCalls:
215
+ (isKimiModel && !isOpenCodeProvider) ||
216
+ (isDeepseekFamily && Boolean(model.reasoning)) ||
217
+ ((provider === "openrouter" || baseUrl.includes("openrouter.ai")) && Boolean(model.reasoning)),
218
+ // DeepSeek V4 rejects synthetic reasoning_content placeholders (".") on tool-call turns.
219
+ // Kimi and OpenRouter accept them when actual reasoning is unavailable.
220
+ allowsSyntheticReasoningContentForToolCalls: !isDeepseekFamily || !model.reasoning,
221
+ requiresAssistantContentForToolCalls: isKimiModel || isDirectDeepseekReasoning,
222
+ openRouterRouting: undefined,
223
+ vercelGatewayRouting: undefined,
224
+ supportsStrictMode: detectStrictModeSupport(provider, baseUrl),
225
+ extraBody: isDirectDeepseekReasoning ? { thinking: { type: "enabled" } } : undefined,
226
+ toolStrictMode: isCerebras ? "all_strict" : "mixed",
227
+ };
228
+ }
229
+
230
+ /**
231
+ * Resolve compatibility settings by layering explicit model.compat overrides onto
232
+ * the detected defaults. This is the canonical compat view for both metadata and transport.
233
+ * @param model - The model configuration
234
+ * @param resolvedBaseUrl - Optional resolved base URL (e.g., after GitHub Copilot proxy-ep resolution).
235
+ * If provided, this takes precedence over model.baseUrl for URL-based checks.
236
+ */
237
+ export function resolveOpenAICompat(
238
+ model: Model<"openai-completions">,
239
+ resolvedBaseUrl?: string,
240
+ ): ResolvedOpenAICompat {
241
+ const detected = detectOpenAICompat(model, resolvedBaseUrl);
242
+ if (!model.compat) {
243
+ return detected;
244
+ }
245
+
246
+ return {
247
+ supportsStore: model.compat.supportsStore ?? detected.supportsStore,
248
+ supportsDeveloperRole: model.compat.supportsDeveloperRole ?? detected.supportsDeveloperRole,
249
+ supportsMultipleSystemMessages:
250
+ model.compat.supportsMultipleSystemMessages ?? detected.supportsMultipleSystemMessages,
251
+ supportsReasoningEffort: model.compat.supportsReasoningEffort ?? detected.supportsReasoningEffort,
252
+ reasoningEffortMap: { ...detected.reasoningEffortMap, ...(model.compat.reasoningEffortMap ?? {}) },
253
+ supportsUsageInStreaming: model.compat.supportsUsageInStreaming ?? detected.supportsUsageInStreaming,
254
+ supportsToolChoice: model.compat.supportsToolChoice ?? detected.supportsToolChoice,
255
+ maxTokensField: model.compat.maxTokensField ?? detected.maxTokensField,
256
+ requiresToolResultName: model.compat.requiresToolResultName ?? detected.requiresToolResultName,
257
+ requiresAssistantAfterToolResult:
258
+ model.compat.requiresAssistantAfterToolResult ?? detected.requiresAssistantAfterToolResult,
259
+ requiresThinkingAsText: model.compat.requiresThinkingAsText ?? detected.requiresThinkingAsText,
260
+ requiresMistralToolIds: model.compat.requiresMistralToolIds ?? detected.requiresMistralToolIds,
261
+ thinkingFormat: model.compat.thinkingFormat ?? detected.thinkingFormat,
262
+ reasoningContentField: model.compat.reasoningContentField ?? detected.reasoningContentField,
263
+ requiresReasoningContentForToolCalls:
264
+ model.compat.requiresReasoningContentForToolCalls ?? detected.requiresReasoningContentForToolCalls,
265
+ allowsSyntheticReasoningContentForToolCalls:
266
+ model.compat.allowsSyntheticReasoningContentForToolCalls ??
267
+ detected.allowsSyntheticReasoningContentForToolCalls,
268
+ requiresAssistantContentForToolCalls:
269
+ model.compat.requiresAssistantContentForToolCalls ?? detected.requiresAssistantContentForToolCalls,
270
+ disableReasoningOnForcedToolChoice:
271
+ model.compat.disableReasoningOnForcedToolChoice ?? detected.disableReasoningOnForcedToolChoice,
272
+ disableReasoningOnToolChoice: model.compat.disableReasoningOnToolChoice ?? detected.disableReasoningOnToolChoice,
273
+ openRouterRouting: model.compat.openRouterRouting ?? detected.openRouterRouting,
274
+ vercelGatewayRouting: model.compat.vercelGatewayRouting ?? detected.vercelGatewayRouting,
275
+ supportsStrictMode: model.compat.supportsStrictMode ?? detected.supportsStrictMode,
276
+ extraBody: model.compat.extraBody ?? detected.extraBody,
277
+ toolStrictMode: model.compat.toolStrictMode ?? detected.toolStrictMode,
278
+ };
279
+ }