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,715 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { type } from "arktype";
3
+ import { resolvePromptCacheKey } from "../auth-gateway/http";
4
+ /**
5
+ * Parsed inbound OpenAI chat-completions request, ready to feed into pi-ai
6
+ * `stream(model, context, options)`.
7
+ */
8
+ import type { AuthGatewayStreamControl, AuthGatewayParsedRequest as ParsedRequest } from "../auth-gateway/types";
9
+ import * as AIError from "../error";
10
+ import type {
11
+ AssistantMessage,
12
+ AssistantMessageEventStream,
13
+ Context,
14
+ ImageContent,
15
+ Message,
16
+ ServiceTier,
17
+ StopReason,
18
+ TextContent,
19
+ Tool,
20
+ ToolCall,
21
+ ToolResultMessage,
22
+ TSchema,
23
+ } from "../types";
24
+ import {
25
+ type OpenAIChatContentPart,
26
+ type OpenAIChatMessage,
27
+ type OpenAIChatTool,
28
+ type OpenAIChatToolCall,
29
+ type OpenAIChatToolChoice,
30
+ openaiChatRequestSchema,
31
+ } from "./openai-chat-server-schema";
32
+
33
+ export type { ParsedRequest };
34
+
35
+ type ReasoningEffort = NonNullable<ParsedRequest["options"]["reasoning"]>;
36
+
37
+ function isReasoningEffort(value: unknown): value is ReasoningEffort {
38
+ return value === "minimal" || value === "low" || value === "medium" || value === "high" || value === "xhigh";
39
+ }
40
+
41
+ function isServiceTier(value: unknown): value is ServiceTier {
42
+ return value === "auto" || value === "default" || value === "flex" || value === "scale" || value === "priority";
43
+ }
44
+
45
+ // ---------------------------------------------------------------------------
46
+ // parseRequest
47
+ // ---------------------------------------------------------------------------
48
+
49
+ export function parseRequest(body: unknown, headers?: Headers): ParsedRequest {
50
+ // Header capture is centralized in `auth-gateway/server.ts` (allow-listed
51
+ // headers like openai-organization/openai-project/openai-beta/x-stainless-*
52
+ // land on `options.headers` automatically). We consult `headers` here too
53
+ // for `resolvePromptCacheKey` to pull a cache identity out of inbound
54
+ // vendor-neutral headers when the body doesn't carry one.
55
+ const parsed = openaiChatRequestSchema(body);
56
+ if (parsed instanceof type.errors) {
57
+ throw new AIError.ValidationError(`openai-chat: ${parsed.summary}`);
58
+ }
59
+ const data = parsed;
60
+
61
+ const now = Date.now();
62
+ const systemParts: string[] = [];
63
+ const messages: Message[] = [];
64
+ // Map of `tool_call_id` → function name, populated as we walk assistant
65
+ // turns. The OpenAI wire spec drops `name` from `role:"tool"` messages,
66
+ // but downstream providers (notably Google: `functionResponse.name` is
67
+ // required) need it. We back-resolve from the matching call. If the
68
+ // client did send a wire `name` we still prefer that (forward-compat).
69
+ const toolNamesById = new Map<string, string>();
70
+
71
+ for (const m of data.messages as OpenAIChatMessage[]) {
72
+ switch (m.role) {
73
+ case "system": {
74
+ const text = stringifyContent(m.content);
75
+ if (text.length > 0) systemParts.push(text);
76
+ break;
77
+ }
78
+ case "developer":
79
+ messages.push({ role: "developer", content: parseUserLikeContent(m.content), timestamp: now });
80
+ break;
81
+ case "user":
82
+ messages.push({ role: "user", content: parseUserLikeContent(m.content), timestamp: now });
83
+ break;
84
+ case "assistant":
85
+ if (m.tool_calls) {
86
+ for (const raw of m.tool_calls) {
87
+ if (raw.type !== undefined && raw.type !== "function") continue;
88
+ const fn = (raw as { function?: { name?: string } }).function;
89
+ if (raw.id && fn?.name) toolNamesById.set(raw.id, fn.name);
90
+ }
91
+ }
92
+ messages.push(
93
+ buildAssistantMessage(
94
+ (m.content ?? undefined) as string | OpenAIChatContentPart[] | undefined,
95
+ m.tool_calls,
96
+ (m as { reasoning_content?: string | null }).reasoning_content ?? undefined,
97
+ data.model,
98
+ now,
99
+ ),
100
+ );
101
+ break;
102
+ case "tool": {
103
+ // Prefer the wire `name` when present; otherwise back-resolve from
104
+ // the assistant `tool_calls` map. Falls through to "" only when no
105
+ // prior call shares this id, which is the well-known broken case.
106
+ const wireName = (m as { name?: string }).name;
107
+ const resolvedName = wireName ?? (m.tool_call_id ? toolNamesById.get(m.tool_call_id) : undefined);
108
+ pushToolResultMessages(messages, m.content, m.tool_call_id, resolvedName, now);
109
+ break;
110
+ }
111
+ case "function": {
112
+ // Legacy `function` role (pre-tools API): the message carries the tool's
113
+ // name on `name` and its output on `content`. Translate to a canonical
114
+ // `toolResult` with a synthetic id (no original id on the wire).
115
+ const fn = m as { role: "function"; name: string; content: string | null };
116
+ pushToolResultMessages(messages, fn.content ?? "", undefined, fn.name, now);
117
+ break;
118
+ }
119
+ }
120
+ }
121
+
122
+ const tools = data.tools ? buildTools(data.tools as OpenAIChatTool[]) : undefined;
123
+
124
+ const context: Context = {
125
+ messages,
126
+ ...(systemParts.length > 0 ? { systemPrompt: [systemParts.join("\n\n")] } : {}),
127
+ ...(tools ? { tools } : {}),
128
+ };
129
+
130
+ // Prefer max_completion_tokens (newer) over max_tokens.
131
+ const maxOutputTokens = data.max_completion_tokens ?? data.max_tokens;
132
+ const stopSequences = normalizeStop(data.stop);
133
+ // Schema accepts the Anthropic-style {type:'tool', name} variant that the SDK
134
+ // union doesn't model; the normalizer collapses it to a plain name lookup.
135
+ const toolChoice = normalizeToolChoice(data.tool_choice as Parameters<typeof normalizeToolChoice>[0]);
136
+ const includeStreamingUsage = data.stream_options?.include_usage === true;
137
+
138
+ // `includeStreamingUsage` is the one genuinely-opaque flag — the streaming
139
+ // encoder reads it later off `options.extra`. Everything else now lives on
140
+ // a typed field; `extra` stays undefined when only typed values are set.
141
+ const extra: Record<string, unknown> = {};
142
+ let hasExtra = false;
143
+ if (includeStreamingUsage) {
144
+ extra.includeStreamingUsage = true;
145
+ hasExtra = true;
146
+ }
147
+
148
+ const options: ParsedRequest["options"] = {};
149
+ if (maxOutputTokens !== undefined) options.maxOutputTokens = maxOutputTokens;
150
+ if (data.temperature !== undefined) options.temperature = data.temperature;
151
+ if (data.top_p !== undefined) options.topP = data.top_p;
152
+ if (stopSequences) options.stopSequences = stopSequences;
153
+ if (toolChoice !== undefined) options.toolChoice = toolChoice;
154
+ if (data.presence_penalty !== undefined) options.presencePenalty = data.presence_penalty;
155
+ if (data.frequency_penalty !== undefined) options.frequencyPenalty = data.frequency_penalty;
156
+ if (data.seed !== undefined) options.seed = data.seed;
157
+ if (data.logit_bias !== undefined) options.logitBias = data.logit_bias;
158
+ if (data.user !== undefined) options.user = data.user;
159
+ if (data.response_format !== undefined) options.responseFormat = data.response_format;
160
+ if (data.parallel_tool_calls !== undefined) options.parallelToolCalls = data.parallel_tool_calls;
161
+ if (data.reasoning_effort !== undefined && isReasoningEffort(data.reasoning_effort)) {
162
+ options.reasoning = data.reasoning_effort;
163
+ }
164
+ if (data.service_tier !== undefined && isServiceTier(data.service_tier)) {
165
+ options.serviceTier = data.service_tier;
166
+ }
167
+ if (data.metadata !== undefined) options.metadata = data.metadata;
168
+ const cacheKey = resolvePromptCacheKey(body, headers);
169
+ if (cacheKey !== undefined) options.promptCacheKey = cacheKey;
170
+ if (hasExtra) options.extra = extra;
171
+
172
+ return {
173
+ modelId: data.model,
174
+ context,
175
+ stream: data.stream === true,
176
+ options,
177
+ };
178
+ }
179
+
180
+ function stringifyContent(content: string | OpenAIChatContentPart[] | undefined): string {
181
+ if (content === undefined) return "";
182
+ if (typeof content === "string") return content;
183
+ const out: string[] = [];
184
+ for (const part of content) {
185
+ if (part.type === "text") out.push(part.text);
186
+ }
187
+ return out.join("");
188
+ }
189
+
190
+ function parseUserLikeContent(
191
+ content: string | OpenAIChatContentPart[] | undefined,
192
+ ): string | (TextContent | ImageContent)[] {
193
+ if (content === undefined) return "";
194
+ if (typeof content === "string") return content;
195
+ const parts: (TextContent | ImageContent)[] = [];
196
+ for (const part of content) {
197
+ if (part.type === "text") {
198
+ parts.push({ type: "text", text: part.text });
199
+ continue;
200
+ }
201
+ if (part.type !== "image_url") continue;
202
+ // input_audio / file / refusal / unknown-type parts are accepted by the
203
+ // schema for forward-compat but dropped here — pi-ai's canonical user
204
+ // content only models text and image today.
205
+ const url = typeof part.image_url === "string" ? part.image_url : part.image_url.url;
206
+ const decoded = decodeDataUri(url);
207
+ if (decoded) {
208
+ parts.push({ type: "image", data: decoded.data, mimeType: decoded.mimeType });
209
+ } else {
210
+ // No image fetcher available in the gateway; surface as a text placeholder so
211
+ // downstream providers still receive a coherent message.
212
+ parts.push({ type: "text", text: `[image: ${url}]` });
213
+ }
214
+ }
215
+ return parts;
216
+ }
217
+
218
+ function decodeDataUri(url: string): { data: string; mimeType: string } | undefined {
219
+ if (!url.startsWith("data:")) return undefined;
220
+ const comma = url.indexOf(",");
221
+ if (comma < 0) return undefined;
222
+ const header = url.slice(5, comma);
223
+ const payload = url.slice(comma + 1);
224
+ const isBase64 = header.endsWith(";base64");
225
+ const mimeType = (isBase64 ? header.slice(0, -";base64".length) : header) || "application/octet-stream";
226
+ const data = isBase64 ? payload : Buffer.from(decodeURIComponent(payload), "utf8").toString("base64");
227
+ return { data, mimeType };
228
+ }
229
+
230
+ function buildAssistantMessage(
231
+ content: string | OpenAIChatContentPart[] | undefined,
232
+ toolCalls: OpenAIChatToolCall[] | undefined,
233
+ reasoningContent: string | undefined,
234
+ modelId: string,
235
+ now: number,
236
+ ): AssistantMessage {
237
+ const parts: AssistantMessage["content"] = [];
238
+ if (reasoningContent !== undefined && reasoningContent.length > 0) {
239
+ // Replayed reasoning channel. The signature names the wire field so
240
+ // completions providers that demand exact `reasoning_content` replay
241
+ // (DeepSeek/Kimi) echo the model's actual reasoning back verbatim.
242
+ parts.push({ type: "thinking", thinking: reasoningContent, thinkingSignature: "reasoning_content" });
243
+ }
244
+ const text = stringifyContent(content);
245
+ if (text.length > 0) parts.push({ type: "text", text });
246
+ if (toolCalls) {
247
+ for (const raw of toolCalls) {
248
+ // Schema only accepts type:"function" (or omitted); narrow the SDK
249
+ // union here so the custom-tool variant doesn't trip TS.
250
+ if (raw.type !== undefined && raw.type !== "function") continue;
251
+ const fn = (raw as { function: { name: string; arguments: string } }).function;
252
+ const argsStr = fn.arguments;
253
+ let args: Record<string, unknown> = {};
254
+ if (argsStr.length > 0) {
255
+ try {
256
+ const v: unknown = JSON.parse(argsStr);
257
+ args =
258
+ v && typeof v === "object" && !Array.isArray(v) ? (v as Record<string, unknown>) : { __raw: argsStr };
259
+ } catch {
260
+ args = { __raw: argsStr };
261
+ }
262
+ }
263
+ const call: ToolCall = { type: "toolCall", id: raw.id, name: fn.name, arguments: args };
264
+ parts.push(call);
265
+ }
266
+ }
267
+ return {
268
+ role: "assistant",
269
+ content: parts,
270
+ api: "openai-completions",
271
+ provider: "openai",
272
+ model: modelId,
273
+ usage: {
274
+ input: 0,
275
+ output: 0,
276
+ cacheRead: 0,
277
+ cacheWrite: 0,
278
+ totalTokens: 0,
279
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
280
+ },
281
+ stopReason: "stop",
282
+ timestamp: now,
283
+ };
284
+ }
285
+
286
+ /**
287
+ * Walk a wire `tool` (or legacy `function`) message into canonical messages.
288
+ * Tool-result content may carry images alongside text; pi-ai's
289
+ * `ToolResultMessage` accepts both, but most downstream providers ignore
290
+ * images on tool results. To mirror Rust's `encode_messages` behavior we
291
+ * keep text inside the tool-result message and hoist any image parts into a
292
+ * follow-up `user` message so they still reach the model.
293
+ */
294
+ function pushToolResultMessages(
295
+ messages: Message[],
296
+ content: string | OpenAIChatContentPart[] | undefined | null,
297
+ toolCallId: string | undefined,
298
+ toolName: string | undefined,
299
+ now: number,
300
+ ): void {
301
+ const textParts: TextContent[] = [];
302
+ const imageParts: ImageContent[] = [];
303
+
304
+ if (typeof content === "string") {
305
+ if (content.length > 0) textParts.push({ type: "text", text: content });
306
+ } else if (Array.isArray(content)) {
307
+ for (const part of content) {
308
+ if (part.type === "text") {
309
+ textParts.push({ type: "text", text: part.text });
310
+ continue;
311
+ }
312
+ if (part.type !== "image_url") continue;
313
+ const url = typeof part.image_url === "string" ? part.image_url : part.image_url.url;
314
+ const decoded = decodeDataUri(url);
315
+ if (decoded) {
316
+ imageParts.push({ type: "image", data: decoded.data, mimeType: decoded.mimeType });
317
+ } else {
318
+ // No fetcher available; degrade gracefully to a text placeholder.
319
+ textParts.push({ type: "text", text: `[image: ${url}]` });
320
+ }
321
+ }
322
+ }
323
+
324
+ const toolMsg: ToolResultMessage = {
325
+ role: "toolResult",
326
+ toolCallId: toolCallId ?? "",
327
+ // OpenAI's `tool` role omits the tool name on the wire; the legacy
328
+ // `function` role supplies it. Downstream providers tolerate empty.
329
+ toolName: toolName ?? "",
330
+ content: textParts.length > 0 ? textParts : [{ type: "text", text: "" }],
331
+ isError: false,
332
+ timestamp: now,
333
+ };
334
+ messages.push(toolMsg);
335
+
336
+ if (imageParts.length > 0) {
337
+ messages.push({
338
+ role: "user",
339
+ content: imageParts,
340
+ timestamp: now,
341
+ });
342
+ }
343
+ }
344
+
345
+ function buildTools(tools: OpenAIChatTool[]): Tool[] | undefined {
346
+ if (tools.length === 0) return undefined;
347
+ const out: Tool[] = [];
348
+ for (const t of tools) {
349
+ if (t.type !== "function") continue;
350
+ out.push({
351
+ name: t.function.name,
352
+ description: t.function.description ?? "",
353
+ parameters: (t.function.parameters ?? {}) as Record<string, unknown> as TSchema,
354
+ });
355
+ }
356
+ return out;
357
+ }
358
+
359
+ function normalizeStop(value: string | string[] | undefined): string[] | undefined {
360
+ if (value === undefined) return undefined;
361
+ if (typeof value === "string") return [value];
362
+ return value.length > 0 ? value : undefined;
363
+ }
364
+
365
+ function normalizeToolChoice(value: OpenAIChatToolChoice | undefined): ParsedRequest["options"]["toolChoice"] {
366
+ if (value === undefined) return undefined;
367
+ if (value === "auto" || value === "none" || value === "required") return value;
368
+ if (typeof value === "object" && value !== null) {
369
+ // OpenAI canonical: { type: 'function', function: { name } }
370
+ if ("function" in value && value.function) return { name: value.function.name };
371
+ // Anthropic-style passthrough (schema-allowed): { type: 'tool', name }
372
+ const anthropicLike = value as unknown as { type?: string; name?: string };
373
+ if (anthropicLike.type === "tool" && typeof anthropicLike.name === "string") {
374
+ return { name: anthropicLike.name };
375
+ }
376
+ }
377
+ return undefined;
378
+ }
379
+
380
+ // ---------------------------------------------------------------------------
381
+ // encodeResponse (non-streaming)
382
+ // ---------------------------------------------------------------------------
383
+
384
+ export function encodeResponse(message: AssistantMessage, requestedModelId: string): Record<string, unknown> {
385
+ const { text, reasoning, toolCalls } = flattenAssistant(message);
386
+
387
+ const responseMessage: Record<string, unknown> = {
388
+ role: "assistant",
389
+ content: text.length > 0 ? text : null,
390
+ // pi-ai does not surface real refusals yet; emit `null` so SDKs that
391
+ // probe `.refusal` see the documented field shape rather than missing.
392
+ refusal: null,
393
+ };
394
+ if (reasoning.length > 0) {
395
+ // DeepSeek-style / o-series reasoning channel.
396
+ responseMessage.reasoning_content = reasoning;
397
+ }
398
+ if (toolCalls.length > 0) {
399
+ responseMessage.tool_calls = toolCalls.map(tc => ({
400
+ id: tc.id,
401
+ type: "function",
402
+ function: { name: tc.name, arguments: stringifyArgs(tc.arguments) },
403
+ }));
404
+ }
405
+
406
+ return {
407
+ id: makeId(),
408
+ object: "chat.completion",
409
+ created: Math.floor(Date.now() / 1000),
410
+ model: requestedModelId,
411
+ // Real OpenAI always emits this key, even when the value is null. Mirror
412
+ // the contract so probing SDKs do not throw on a missing field.
413
+ system_fingerprint: null,
414
+ choices: [
415
+ {
416
+ index: 0,
417
+ message: responseMessage,
418
+ finish_reason: mapFinishReason(message.stopReason, toolCalls.length > 0),
419
+ logprobs: null,
420
+ },
421
+ ],
422
+ usage: buildUsage(message),
423
+ };
424
+ }
425
+
426
+ function buildUsage(message: AssistantMessage): Record<string, unknown> {
427
+ const promptTokens = message.usage.input + message.usage.cacheRead + message.usage.cacheWrite;
428
+ const usage: Record<string, unknown> = {
429
+ prompt_tokens: promptTokens,
430
+ completion_tokens: message.usage.output,
431
+ total_tokens: promptTokens + message.usage.output,
432
+ prompt_tokens_details: { cached_tokens: message.usage.cacheRead },
433
+ };
434
+ if (message.usage.reasoningTokens !== undefined) {
435
+ usage.completion_tokens_details = { reasoning_tokens: message.usage.reasoningTokens };
436
+ }
437
+ return usage;
438
+ }
439
+
440
+ function flattenAssistant(message: AssistantMessage): {
441
+ text: string;
442
+ reasoning: string;
443
+ toolCalls: ToolCall[];
444
+ } {
445
+ let text = "";
446
+ let reasoning = "";
447
+ const toolCalls: ToolCall[] = [];
448
+ for (const part of message.content) {
449
+ switch (part.type) {
450
+ case "text":
451
+ text += part.text;
452
+ break;
453
+ case "thinking":
454
+ reasoning += part.thinking;
455
+ break;
456
+ case "redactedThinking":
457
+ // Opaque blob — surface verbatim on the reasoning channel so the
458
+ // concatenation round-trips through clients that just echo it.
459
+ reasoning += part.data;
460
+ break;
461
+ case "toolCall":
462
+ toolCalls.push(part);
463
+ break;
464
+ }
465
+ }
466
+ return { text, reasoning, toolCalls };
467
+ }
468
+
469
+ function isOnlyRaw(args: Record<string, unknown>): boolean {
470
+ for (const k in args) {
471
+ if (k !== "__raw") return false;
472
+ }
473
+ return true;
474
+ }
475
+
476
+ function stringifyArgs(args: Record<string, unknown>): string {
477
+ // `__raw` is our fallback marker for un-parseable inbound args; preserve it verbatim on the way out.
478
+ if (typeof args.__raw === "string" && isOnlyRaw(args)) return args.__raw;
479
+ try {
480
+ return JSON.stringify(args);
481
+ } catch {
482
+ return "{}";
483
+ }
484
+ }
485
+
486
+ function mapFinishReason(reason: StopReason, hasToolCalls: boolean): string {
487
+ if (reason === "toolUse" || (hasToolCalls && reason === "stop")) return "tool_calls";
488
+ if (reason === "length") return "length";
489
+ // pi-ai's StopReason does not currently carry a content-filter signal;
490
+ // when it does, map it to "content_filter" here.
491
+ return "stop";
492
+ }
493
+
494
+ function makeId(): string {
495
+ return `chatcmpl-${randomUUID()}`;
496
+ }
497
+
498
+ // ---------------------------------------------------------------------------
499
+ // encodeStream (SSE)
500
+ // ---------------------------------------------------------------------------
501
+
502
+ export function encodeStream(
503
+ events: AssistantMessageEventStream,
504
+ requestedModelId: string,
505
+ options?: ParsedRequest["options"],
506
+ control?: AuthGatewayStreamControl,
507
+ ): ReadableStream<Uint8Array> {
508
+ const encoder = new TextEncoder();
509
+ const id = makeId();
510
+ const created = Math.floor(Date.now() / 1000);
511
+ const includeUsage = options?.extra?.includeStreamingUsage === true;
512
+ let cancelled = control?.signal?.aborted === true;
513
+ const markCancelled = () => {
514
+ cancelled = true;
515
+ };
516
+ control?.signal?.addEventListener("abort", markCancelled, { once: true });
517
+
518
+ const baseChunk = (delta: Record<string, unknown>, finishReason: string | null) => ({
519
+ id,
520
+ object: "chat.completion.chunk",
521
+ created,
522
+ model: requestedModelId,
523
+ system_fingerprint: null,
524
+ choices: [{ index: 0, delta, finish_reason: finishReason, logprobs: null }],
525
+ ...(includeUsage ? { usage: null } : {}),
526
+ });
527
+
528
+ const writeSse = (controller: ReadableStreamDefaultController<Uint8Array>, payload: unknown): void => {
529
+ if (!cancelled) controller.enqueue(encoder.encode(`data: ${JSON.stringify(payload)}\n\n`));
530
+ };
531
+
532
+ const writeUsage = (controller: ReadableStreamDefaultController<Uint8Array>, message: AssistantMessage): void => {
533
+ writeSse(controller, {
534
+ id,
535
+ object: "chat.completion.chunk",
536
+ created,
537
+ model: requestedModelId,
538
+ system_fingerprint: null,
539
+ choices: [],
540
+ usage: buildUsage(message),
541
+ });
542
+ };
543
+
544
+ return new ReadableStream<Uint8Array>({
545
+ async start(controller) {
546
+ // contentIndex (from pi-ai events) -> tool_calls index on the wire.
547
+ const toolIndexByContentIndex = new Map<number, number>();
548
+ // wire index -> id/name emitted on the start chunk, to detect late-arriving
549
+ // upstream id/name that needs a corrective chunk before the finish.
550
+ const sentToolMeta = new Map<number, { id: string; name: string }>();
551
+ let nextToolIndex = 0;
552
+ let hasToolCalls = false;
553
+ let finishReason: string = "stop";
554
+
555
+ try {
556
+ if (cancelled) {
557
+ controller.close();
558
+ return;
559
+ }
560
+ // Initial role chunk.
561
+ writeSse(controller, baseChunk({ role: "assistant" }, null));
562
+
563
+ for await (const event of events) {
564
+ if (cancelled) return;
565
+ switch (event.type) {
566
+ case "text_delta":
567
+ if (event.delta.length > 0) {
568
+ writeSse(controller, baseChunk({ content: event.delta }, null));
569
+ }
570
+ break;
571
+
572
+ case "thinking_delta":
573
+ // DeepSeek-style / o-series reasoning channel. Clients that don't
574
+ // understand it ignore the unknown delta key.
575
+ if (event.delta.length > 0) {
576
+ writeSse(controller, baseChunk({ reasoning_content: event.delta }, null));
577
+ }
578
+ break;
579
+
580
+ case "toolcall_start": {
581
+ hasToolCalls = true;
582
+ const idx = nextToolIndex++;
583
+ toolIndexByContentIndex.set(event.contentIndex, idx);
584
+ const partial = event.partial.content[event.contentIndex];
585
+ const call = partial && partial.type === "toolCall" ? partial : undefined;
586
+ sentToolMeta.set(idx, { id: call?.id ?? "", name: call?.name ?? "" });
587
+ writeSse(
588
+ controller,
589
+ baseChunk(
590
+ {
591
+ tool_calls: [
592
+ {
593
+ index: idx,
594
+ id: call?.id ?? "",
595
+ type: "function",
596
+ function: { name: call?.name ?? "", arguments: "" },
597
+ },
598
+ ],
599
+ },
600
+ null,
601
+ ),
602
+ );
603
+ break;
604
+ }
605
+
606
+ case "toolcall_delta": {
607
+ const idx = toolIndexByContentIndex.get(event.contentIndex);
608
+ if (idx === undefined) break;
609
+ writeSse(
610
+ controller,
611
+ baseChunk({ tool_calls: [{ index: idx, function: { arguments: event.delta } }] }, null),
612
+ );
613
+ break;
614
+ }
615
+
616
+ case "toolcall_end": {
617
+ const idx = toolIndexByContentIndex.get(event.contentIndex);
618
+ if (idx === undefined) break;
619
+ const sent = sentToolMeta.get(idx);
620
+ if (sent === undefined) break;
621
+ // Upstream completions providers can receive the real id/name in a
622
+ // later chunk than toolcall_start. Emit a corrective chunk only when
623
+ // the streamed value was empty: accumulating clients concatenate
624
+ // string fields, so "" + value is the only safe correction.
625
+ const correctId = sent.id === "" && event.toolCall.id !== "" ? event.toolCall.id : undefined;
626
+ const correctName =
627
+ sent.name === "" && event.toolCall.name !== "" ? event.toolCall.name : undefined;
628
+ if (correctId !== undefined || correctName !== undefined) {
629
+ writeSse(
630
+ controller,
631
+ baseChunk(
632
+ {
633
+ tool_calls: [
634
+ {
635
+ index: idx,
636
+ ...(correctId !== undefined ? { id: correctId } : {}),
637
+ ...(correctName !== undefined ? { function: { name: correctName } } : {}),
638
+ },
639
+ ],
640
+ },
641
+ null,
642
+ ),
643
+ );
644
+ }
645
+ break;
646
+ }
647
+
648
+ case "done":
649
+ finishReason =
650
+ event.reason === "toolUse"
651
+ ? "tool_calls"
652
+ : event.reason === "length"
653
+ ? "length"
654
+ : hasToolCalls
655
+ ? "tool_calls"
656
+ : "stop";
657
+ writeSse(controller, baseChunk({}, finishReason));
658
+ if (includeUsage) writeUsage(controller, event.message);
659
+ controller.enqueue(encoder.encode("data: [DONE]\n\n"));
660
+ controller.close();
661
+ return;
662
+
663
+ case "error": {
664
+ const msg = event.error.errorMessage ?? "stream error";
665
+ writeSse(controller, { error: { message: msg, type: "upstream_error" } });
666
+ controller.close();
667
+ return;
668
+ }
669
+
670
+ // Drop start / *_start and text/thinking *_end — chat-completions
671
+ // wire only surfaces deltas and the terminal finish_reason.
672
+ default:
673
+ break;
674
+ }
675
+ }
676
+
677
+ // Stream ended without a terminal `done` (defensive). Close gracefully.
678
+ if (!cancelled) {
679
+ writeSse(controller, baseChunk({}, hasToolCalls ? "tool_calls" : "stop"));
680
+ controller.enqueue(encoder.encode("data: [DONE]\n\n"));
681
+ controller.close();
682
+ }
683
+ } catch (err) {
684
+ if (!cancelled) {
685
+ const msg = err instanceof Error ? err.message : String(err);
686
+ writeSse(controller, { error: { message: msg, type: "upstream_error" } });
687
+ controller.close();
688
+ }
689
+ } finally {
690
+ control?.signal?.removeEventListener("abort", markCancelled);
691
+ }
692
+ },
693
+ cancel(reason) {
694
+ cancelled = true;
695
+ control?.signal?.removeEventListener("abort", markCancelled);
696
+ control?.onCancel?.(reason);
697
+ },
698
+ });
699
+ }
700
+
701
+ // ---------------------------------------------------------------------------
702
+ // formatError
703
+ // ---------------------------------------------------------------------------
704
+
705
+ /**
706
+ * OpenAI chat-completions error envelope:
707
+ * `{ error: { message, type } }`
708
+ * Matches the shape the official SDK auto-parses into `APIError`.
709
+ */
710
+ export function formatError(status: number, type: string, message: string): Response {
711
+ return new Response(JSON.stringify({ error: { message, type } }), {
712
+ status,
713
+ headers: { "Content-Type": "application/json" },
714
+ });
715
+ }