@vib-rato/ai 0.16.0

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 (525) hide show
  1. package/CHANGELOG.md +3354 -0
  2. package/README.md +1194 -0
  3. package/dist/types/adapter-internals/provider-safety-stop.d.ts +45 -0
  4. package/dist/types/api-registry.d.ts +30 -0
  5. package/dist/types/auth-broker/client.d.ts +80 -0
  6. package/dist/types/auth-broker/index.d.ts +5 -0
  7. package/dist/types/auth-broker/redact.d.ts +7 -0
  8. package/dist/types/auth-broker/refresher.d.ts +25 -0
  9. package/dist/types/auth-broker/remote-store.d.ts +153 -0
  10. package/dist/types/auth-broker/server.d.ts +32 -0
  11. package/dist/types/auth-broker/types.d.ts +132 -0
  12. package/dist/types/auth-broker/wire-schemas.d.ts +555 -0
  13. package/dist/types/auth-gateway/http.d.ts +40 -0
  14. package/dist/types/auth-gateway/index.d.ts +3 -0
  15. package/dist/types/auth-gateway/server.d.ts +70 -0
  16. package/dist/types/auth-gateway/types.d.ts +129 -0
  17. package/dist/types/auth-storage.d.ts +1074 -0
  18. package/dist/types/cli.d.ts +2 -0
  19. package/dist/types/codex-tools.d.ts +4 -0
  20. package/dist/types/context-cap-policy.d.ts +68 -0
  21. package/dist/types/core.d.ts +35 -0
  22. package/dist/types/index.d.ts +55 -0
  23. package/dist/types/model-cache.d.ts +24 -0
  24. package/dist/types/model-manager.d.ts +77 -0
  25. package/dist/types/model-pricing.d.ts +3 -0
  26. package/dist/types/model-retirements.d.ts +6 -0
  27. package/dist/types/model-thinking.d.ts +100 -0
  28. package/dist/types/models.d.ts +21 -0
  29. package/dist/types/openai-completions-compat.d.ts +34 -0
  30. package/dist/types/provider-details.d.ts +24 -0
  31. package/dist/types/provider-models/bundled-references.d.ts +4 -0
  32. package/dist/types/provider-models/descriptors.d.ts +48 -0
  33. package/dist/types/provider-models/google.d.ts +20 -0
  34. package/dist/types/provider-models/index.d.ts +5 -0
  35. package/dist/types/provider-models/ollama.d.ts +7 -0
  36. package/dist/types/provider-models/openai-compat.d.ts +293 -0
  37. package/dist/types/provider-models/special.d.ts +29 -0
  38. package/dist/types/providers/amazon-bedrock.d.ts +60 -0
  39. package/dist/types/providers/anthropic-messages-server-schema.d.ts +450 -0
  40. package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
  41. package/dist/types/providers/anthropic.d.ts +280 -0
  42. package/dist/types/providers/aws-credential-config.d.ts +19 -0
  43. package/dist/types/providers/aws-credentials.d.ts +43 -0
  44. package/dist/types/providers/aws-eventstream.d.ts +38 -0
  45. package/dist/types/providers/aws-sigv4.d.ts +55 -0
  46. package/dist/types/providers/azure-openai-responses.d.ts +22 -0
  47. package/dist/types/providers/composer-discipline.d.ts +32 -0
  48. package/dist/types/providers/cursor/client-version.d.ts +10 -0
  49. package/dist/types/providers/cursor/exec-modern.d.ts +98 -0
  50. package/dist/types/providers/cursor/gen/agent_pb.d.ts +16769 -0
  51. package/dist/types/providers/cursor-pi-args.d.ts +119 -0
  52. package/dist/types/providers/cursor.d.ts +72 -0
  53. package/dist/types/providers/dashscope-token-plan-headers.d.ts +57 -0
  54. package/dist/types/providers/error-message.d.ts +27 -0
  55. package/dist/types/providers/github-copilot-headers.d.ts +40 -0
  56. package/dist/types/providers/gitlab-duo.d.ts +27 -0
  57. package/dist/types/providers/google-auth.d.ts +26 -0
  58. package/dist/types/providers/google-gemini-cli.d.ts +75 -0
  59. package/dist/types/providers/google-gemini-headers.d.ts +43 -0
  60. package/dist/types/providers/google-shared.d.ts +183 -0
  61. package/dist/types/providers/google-types.d.ts +138 -0
  62. package/dist/types/providers/google-vertex.d.ts +11 -0
  63. package/dist/types/providers/google.d.ts +4 -0
  64. package/dist/types/providers/grammar.d.ts +1 -0
  65. package/dist/types/providers/kimi.d.ts +27 -0
  66. package/dist/types/providers/kiro-api-key.d.ts +50 -0
  67. package/dist/types/providers/kiro-codewhisperer.d.ts +11 -0
  68. package/dist/types/providers/mock.d.ts +189 -0
  69. package/dist/types/providers/ollama.d.ts +41 -0
  70. package/dist/types/providers/openai-anthropic-shim.d.ts +31 -0
  71. package/dist/types/providers/openai-bounded-rate-limits.d.ts +3 -0
  72. package/dist/types/providers/openai-chat-server-schema.d.ts +1733 -0
  73. package/dist/types/providers/openai-chat-server.d.ts +16 -0
  74. package/dist/types/providers/openai-codex/constants.d.ts +26 -0
  75. package/dist/types/providers/openai-codex/request-transformer.d.ts +50 -0
  76. package/dist/types/providers/openai-codex/response-handler.d.ts +18 -0
  77. package/dist/types/providers/openai-codex-responses.d.ts +71 -0
  78. package/dist/types/providers/openai-completions-compat.d.ts +6 -0
  79. package/dist/types/providers/openai-completions.d.ts +35 -0
  80. package/dist/types/providers/openai-opencodex-responses.d.ts +10 -0
  81. package/dist/types/providers/openai-request-transform.d.ts +4 -0
  82. package/dist/types/providers/openai-responses-server-schema.d.ts +392 -0
  83. package/dist/types/providers/openai-responses-server.d.ts +17 -0
  84. package/dist/types/providers/openai-responses-shared.d.ts +106 -0
  85. package/dist/types/providers/openai-responses.d.ts +37 -0
  86. package/dist/types/providers/pi-native-client.d.ts +29 -0
  87. package/dist/types/providers/pi-native-server.d.ts +60 -0
  88. package/dist/types/providers/register-builtins.d.ts +59 -0
  89. package/dist/types/providers/synthetic.d.ts +26 -0
  90. package/dist/types/providers/transform-messages.d.ts +33 -0
  91. package/dist/types/providers/vision-guard.d.ts +8 -0
  92. package/dist/types/rate-limit-utils.d.ts +19 -0
  93. package/dist/types/stream.d.ts +45 -0
  94. package/dist/types/types.d.ts +1073 -0
  95. package/dist/types/usage/claude.d.ts +3 -0
  96. package/dist/types/usage/gemini.d.ts +2 -0
  97. package/dist/types/usage/github-copilot.d.ts +7 -0
  98. package/dist/types/usage/google-antigravity.d.ts +2 -0
  99. package/dist/types/usage/grok-cli.d.ts +17 -0
  100. package/dist/types/usage/kimi.d.ts +4 -0
  101. package/dist/types/usage/minimax-code.d.ts +2 -0
  102. package/dist/types/usage/openai-codex.d.ts +3 -0
  103. package/dist/types/usage/shared.d.ts +1 -0
  104. package/dist/types/usage/zai.d.ts +2 -0
  105. package/dist/types/usage.d.ts +264 -0
  106. package/dist/types/utils/abort.d.ts +19 -0
  107. package/dist/types/utils/anthropic-auth.d.ts +39 -0
  108. package/dist/types/utils/block-symbols.d.ts +6 -0
  109. package/dist/types/utils/discovery/antigravity.d.ts +67 -0
  110. package/dist/types/utils/discovery/codex.d.ts +38 -0
  111. package/dist/types/utils/discovery/cursor.d.ts +49 -0
  112. package/dist/types/utils/discovery/gemini.d.ts +25 -0
  113. package/dist/types/utils/discovery/index.d.ts +4 -0
  114. package/dist/types/utils/discovery/openai-compatible.d.ts +81 -0
  115. package/dist/types/utils/event-stream.d.ts +41 -0
  116. package/dist/types/utils/fallback-transport.d.ts +110 -0
  117. package/dist/types/utils/fireworks-model-id.d.ts +10 -0
  118. package/dist/types/utils/foundry.d.ts +11 -0
  119. package/dist/types/utils/h2-fetch.d.ts +22 -0
  120. package/dist/types/utils/http-inspector.d.ts +59 -0
  121. package/dist/types/utils/idle-iterator.d.ts +122 -0
  122. package/dist/types/utils/json-parse.d.ts +98 -0
  123. package/dist/types/utils/oauth/alibaba-token-plan.d.ts +19 -0
  124. package/dist/types/utils/oauth/anthropic.d.ts +41 -0
  125. package/dist/types/utils/oauth/api-key-login.d.ts +38 -0
  126. package/dist/types/utils/oauth/api-key-validation.d.ts +39 -0
  127. package/dist/types/utils/oauth/bizrouter.d.ts +1 -0
  128. package/dist/types/utils/oauth/callback-server.d.ts +80 -0
  129. package/dist/types/utils/oauth/cerebras.d.ts +1 -0
  130. package/dist/types/utils/oauth/cloudflare-ai-gateway.d.ts +18 -0
  131. package/dist/types/utils/oauth/commandcode.d.ts +1 -0
  132. package/dist/types/utils/oauth/cursor.d.ts +15 -0
  133. package/dist/types/utils/oauth/deepinfra.d.ts +1 -0
  134. package/dist/types/utils/oauth/deepseek.d.ts +10 -0
  135. package/dist/types/utils/oauth/firepass.d.ts +1 -0
  136. package/dist/types/utils/oauth/fireworks.d.ts +1 -0
  137. package/dist/types/utils/oauth/fugu.d.ts +1 -0
  138. package/dist/types/utils/oauth/github-copilot.d.ts +38 -0
  139. package/dist/types/utils/oauth/gitlab-duo.d.ts +3 -0
  140. package/dist/types/utils/oauth/glm-zcode.d.ts +71 -0
  141. package/dist/types/utils/oauth/google-antigravity.d.ts +11 -0
  142. package/dist/types/utils/oauth/google-gemini-cli.d.ts +10 -0
  143. package/dist/types/utils/oauth/google-oauth-shared.d.ts +28 -0
  144. package/dist/types/utils/oauth/huggingface.d.ts +19 -0
  145. package/dist/types/utils/oauth/index.d.ts +39 -0
  146. package/dist/types/utils/oauth/kagi.d.ts +17 -0
  147. package/dist/types/utils/oauth/kilo.d.ts +5 -0
  148. package/dist/types/utils/oauth/kimi.d.ts +17 -0
  149. package/dist/types/utils/oauth/kiro.d.ts +71 -0
  150. package/dist/types/utils/oauth/litellm.d.ts +18 -0
  151. package/dist/types/utils/oauth/lm-studio.d.ts +17 -0
  152. package/dist/types/utils/oauth/mara.d.ts +1 -0
  153. package/dist/types/utils/oauth/minimax-code.d.ts +28 -0
  154. package/dist/types/utils/oauth/moonshot.d.ts +1 -0
  155. package/dist/types/utils/oauth/nanogpt.d.ts +1 -0
  156. package/dist/types/utils/oauth/nvidia.d.ts +18 -0
  157. package/dist/types/utils/oauth/ollama-cloud.d.ts +2 -0
  158. package/dist/types/utils/oauth/ollama.d.ts +18 -0
  159. package/dist/types/utils/oauth/openai-codex.d.ts +21 -0
  160. package/dist/types/utils/oauth/opencode.d.ts +18 -0
  161. package/dist/types/utils/oauth/opengateway.d.ts +1 -0
  162. package/dist/types/utils/oauth/openrouter.d.ts +1 -0
  163. package/dist/types/utils/oauth/parallel.d.ts +17 -0
  164. package/dist/types/utils/oauth/perplexity.d.ts +4 -0
  165. package/dist/types/utils/oauth/pkce.d.ts +8 -0
  166. package/dist/types/utils/oauth/qianfan.d.ts +17 -0
  167. package/dist/types/utils/oauth/qwen-portal.d.ts +19 -0
  168. package/dist/types/utils/oauth/sglang.d.ts +16 -0
  169. package/dist/types/utils/oauth/synthetic.d.ts +1 -0
  170. package/dist/types/utils/oauth/tavily.d.ts +17 -0
  171. package/dist/types/utils/oauth/together.d.ts +1 -0
  172. package/dist/types/utils/oauth/types.d.ts +56 -0
  173. package/dist/types/utils/oauth/venice.d.ts +18 -0
  174. package/dist/types/utils/oauth/vercel-ai-gateway.d.ts +18 -0
  175. package/dist/types/utils/oauth/vllm.d.ts +16 -0
  176. package/dist/types/utils/oauth/xai.d.ts +30 -0
  177. package/dist/types/utils/oauth/xiaomi.d.ts +25 -0
  178. package/dist/types/utils/oauth/zai.d.ts +18 -0
  179. package/dist/types/utils/oauth/zenmux.d.ts +1 -0
  180. package/dist/types/utils/overflow.d.ts +14 -0
  181. package/dist/types/utils/parse-bind.d.ts +26 -0
  182. package/dist/types/utils/provider-response.d.ts +6 -0
  183. package/dist/types/utils/provider-safety-stop.d.ts +8 -0
  184. package/dist/types/utils/proxy.d.ts +7 -0
  185. package/dist/types/utils/retry-after.d.ts +3 -0
  186. package/dist/types/utils/retry-budget.d.ts +1 -0
  187. package/dist/types/utils/retry.d.ts +29 -0
  188. package/dist/types/utils/schema/adapt.d.ts +24 -0
  189. package/dist/types/utils/schema/compatibility.d.ts +30 -0
  190. package/dist/types/utils/schema/dereference.d.ts +11 -0
  191. package/dist/types/utils/schema/draft.d.ts +10 -0
  192. package/dist/types/utils/schema/equality.d.ts +4 -0
  193. package/dist/types/utils/schema/fields.d.ts +49 -0
  194. package/dist/types/utils/schema/index.d.ts +14 -0
  195. package/dist/types/utils/schema/json-schema-validator.d.ts +12 -0
  196. package/dist/types/utils/schema/meta-validator.d.ts +2 -0
  197. package/dist/types/utils/schema/normalize.d.ts +93 -0
  198. package/dist/types/utils/schema/root-combinator.d.ts +12 -0
  199. package/dist/types/utils/schema/spill.d.ts +8 -0
  200. package/dist/types/utils/schema/stamps.d.ts +25 -0
  201. package/dist/types/utils/schema/types.d.ts +4 -0
  202. package/dist/types/utils/schema/wire.d.ts +54 -0
  203. package/dist/types/utils/schema/zod-decontaminate.d.ts +31 -0
  204. package/dist/types/utils/sse-debug.d.ts +10 -0
  205. package/dist/types/utils/tool-call-healing.d.ts +80 -0
  206. package/dist/types/utils/tool-choice-capability.d.ts +57 -0
  207. package/dist/types/utils/tool-choice.d.ts +50 -0
  208. package/dist/types/utils/validation.d.ts +17 -0
  209. package/dist/types/utils.d.ts +117 -0
  210. package/package.json +152 -0
  211. package/src/adapter-internals/provider-safety-stop.d.ts +45 -0
  212. package/src/adapter-internals/provider-safety-stop.ts +156 -0
  213. package/src/api-registry.d.ts +30 -0
  214. package/src/api-registry.ts +96 -0
  215. package/src/auth-broker/client.ts +444 -0
  216. package/src/auth-broker/index.ts +5 -0
  217. package/src/auth-broker/redact.ts +39 -0
  218. package/src/auth-broker/refresher.ts +130 -0
  219. package/src/auth-broker/remote-store.ts +1576 -0
  220. package/src/auth-broker/server.ts +764 -0
  221. package/src/auth-broker/types.ts +164 -0
  222. package/src/auth-broker/wire-schemas.ts +261 -0
  223. package/src/auth-gateway/http.ts +198 -0
  224. package/src/auth-gateway/index.ts +3 -0
  225. package/src/auth-gateway/server.ts +1315 -0
  226. package/src/auth-gateway/types.ts +160 -0
  227. package/src/auth-storage.ts +7312 -0
  228. package/src/cli.ts +269 -0
  229. package/src/codex-tools.d.ts +4 -0
  230. package/src/codex-tools.ts +24 -0
  231. package/src/context-cap-policy.d.ts +68 -0
  232. package/src/context-cap-policy.ts +123 -0
  233. package/src/core.ts +44 -0
  234. package/src/index.ts +61 -0
  235. package/src/model-cache.ts +236 -0
  236. package/src/model-manager.ts +744 -0
  237. package/src/model-pricing.d.ts +3 -0
  238. package/src/model-pricing.ts +68 -0
  239. package/src/model-retirements.d.ts +6 -0
  240. package/src/model-retirements.ts +19 -0
  241. package/src/model-thinking.d.ts +100 -0
  242. package/src/model-thinking.ts +1054 -0
  243. package/src/models.d.ts +21 -0
  244. package/src/models.json +94672 -0
  245. package/src/models.json.d.ts +9 -0
  246. package/src/models.ts +126 -0
  247. package/src/openai-completions-compat.d.ts +34 -0
  248. package/src/openai-completions-compat.ts +383 -0
  249. package/src/prompts/composer-bash-policy-recovery.md +1 -0
  250. package/src/prompts/cursor-composer-bash-policy-recovery.md +1 -0
  251. package/src/prompts/cursor-composer-edit-discipline.md +7 -0
  252. package/src/prompts/turn-aborted-guidance.md +4 -0
  253. package/src/provider-details.ts +90 -0
  254. package/src/provider-models/bundled-references.ts +38 -0
  255. package/src/provider-models/descriptors.ts +392 -0
  256. package/src/provider-models/google.ts +92 -0
  257. package/src/provider-models/index.ts +5 -0
  258. package/src/provider-models/ollama.ts +159 -0
  259. package/src/provider-models/openai-compat.ts +2920 -0
  260. package/src/provider-models/special.ts +185 -0
  261. package/src/providers/amazon-bedrock.d.ts +60 -0
  262. package/src/providers/amazon-bedrock.ts +939 -0
  263. package/src/providers/anthropic-messages-server-schema.ts +229 -0
  264. package/src/providers/anthropic-messages-server.ts +839 -0
  265. package/src/providers/anthropic.d.ts +280 -0
  266. package/src/providers/anthropic.ts +4421 -0
  267. package/src/providers/aws-credential-config.d.ts +19 -0
  268. package/src/providers/aws-credential-config.ts +179 -0
  269. package/src/providers/aws-credentials.d.ts +43 -0
  270. package/src/providers/aws-credentials.ts +457 -0
  271. package/src/providers/aws-eventstream.d.ts +38 -0
  272. package/src/providers/aws-eventstream.ts +185 -0
  273. package/src/providers/aws-sigv4.d.ts +55 -0
  274. package/src/providers/aws-sigv4.ts +218 -0
  275. package/src/providers/azure-openai-responses.d.ts +22 -0
  276. package/src/providers/azure-openai-responses.ts +447 -0
  277. package/src/providers/composer-discipline.d.ts +32 -0
  278. package/src/providers/composer-discipline.ts +95 -0
  279. package/src/providers/cursor/client-version.d.ts +10 -0
  280. package/src/providers/cursor/client-version.ts +10 -0
  281. package/src/providers/cursor/exec-modern.d.ts +98 -0
  282. package/src/providers/cursor/exec-modern.ts +497 -0
  283. package/src/providers/cursor/gen/agent_pb.d.ts +16769 -0
  284. package/src/providers/cursor/gen/agent_pb.ts +19780 -0
  285. package/src/providers/cursor/proto/agent.proto +4533 -0
  286. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  287. package/src/providers/cursor/proto/buf.yaml +17 -0
  288. package/src/providers/cursor-pi-args.d.ts +119 -0
  289. package/src/providers/cursor-pi-args.ts +187 -0
  290. package/src/providers/cursor.d.ts +72 -0
  291. package/src/providers/cursor.ts +3396 -0
  292. package/src/providers/dashscope-token-plan-headers.d.ts +57 -0
  293. package/src/providers/dashscope-token-plan-headers.ts +84 -0
  294. package/src/providers/error-message.d.ts +27 -0
  295. package/src/providers/error-message.ts +21 -0
  296. package/src/providers/github-copilot-headers.d.ts +40 -0
  297. package/src/providers/github-copilot-headers.ts +140 -0
  298. package/src/providers/gitlab-duo.d.ts +27 -0
  299. package/src/providers/gitlab-duo.ts +393 -0
  300. package/src/providers/google-auth.d.ts +26 -0
  301. package/src/providers/google-auth.ts +262 -0
  302. package/src/providers/google-gemini-cli.d.ts +75 -0
  303. package/src/providers/google-gemini-cli.ts +969 -0
  304. package/src/providers/google-gemini-headers.d.ts +43 -0
  305. package/src/providers/google-gemini-headers.ts +100 -0
  306. package/src/providers/google-shared.d.ts +183 -0
  307. package/src/providers/google-shared.ts +1105 -0
  308. package/src/providers/google-types.d.ts +138 -0
  309. package/src/providers/google-types.ts +167 -0
  310. package/src/providers/google-vertex.d.ts +11 -0
  311. package/src/providers/google-vertex.ts +124 -0
  312. package/src/providers/google.d.ts +4 -0
  313. package/src/providers/google.ts +41 -0
  314. package/src/providers/grammar.d.ts +1 -0
  315. package/src/providers/grammar.ts +70 -0
  316. package/src/providers/kimi.d.ts +27 -0
  317. package/src/providers/kimi.ts +52 -0
  318. package/src/providers/kiro-api-key.d.ts +50 -0
  319. package/src/providers/kiro-api-key.ts +786 -0
  320. package/src/providers/kiro-codewhisperer.d.ts +11 -0
  321. package/src/providers/kiro-codewhisperer.ts +600 -0
  322. package/src/providers/mock.ts +526 -0
  323. package/src/providers/ollama.d.ts +41 -0
  324. package/src/providers/ollama.ts +645 -0
  325. package/src/providers/openai-anthropic-shim.d.ts +31 -0
  326. package/src/providers/openai-anthropic-shim.ts +156 -0
  327. package/src/providers/openai-bounded-rate-limits.d.ts +3 -0
  328. package/src/providers/openai-bounded-rate-limits.ts +57 -0
  329. package/src/providers/openai-chat-server-schema.ts +254 -0
  330. package/src/providers/openai-chat-server.ts +724 -0
  331. package/src/providers/openai-codex/constants.d.ts +26 -0
  332. package/src/providers/openai-codex/constants.ts +43 -0
  333. package/src/providers/openai-codex/request-transformer.d.ts +50 -0
  334. package/src/providers/openai-codex/request-transformer.ts +219 -0
  335. package/src/providers/openai-codex/response-handler.d.ts +18 -0
  336. package/src/providers/openai-codex/response-handler.ts +111 -0
  337. package/src/providers/openai-codex-responses.d.ts +71 -0
  338. package/src/providers/openai-codex-responses.ts +3288 -0
  339. package/src/providers/openai-completions-compat.d.ts +6 -0
  340. package/src/providers/openai-completions-compat.ts +6 -0
  341. package/src/providers/openai-completions.d.ts +35 -0
  342. package/src/providers/openai-completions.ts +2294 -0
  343. package/src/providers/openai-opencodex-responses.ts +174 -0
  344. package/src/providers/openai-request-transform.d.ts +4 -0
  345. package/src/providers/openai-request-transform.ts +136 -0
  346. package/src/providers/openai-responses-server-schema.ts +290 -0
  347. package/src/providers/openai-responses-server.ts +1268 -0
  348. package/src/providers/openai-responses-shared.d.ts +106 -0
  349. package/src/providers/openai-responses-shared.ts +1253 -0
  350. package/src/providers/openai-responses.d.ts +37 -0
  351. package/src/providers/openai-responses.ts +989 -0
  352. package/src/providers/pi-native-client.d.ts +29 -0
  353. package/src/providers/pi-native-client.ts +243 -0
  354. package/src/providers/pi-native-server.ts +488 -0
  355. package/src/providers/register-builtins.d.ts +59 -0
  356. package/src/providers/register-builtins.ts +544 -0
  357. package/src/providers/synthetic.d.ts +26 -0
  358. package/src/providers/synthetic.ts +50 -0
  359. package/src/providers/transform-messages.d.ts +33 -0
  360. package/src/providers/transform-messages.ts +408 -0
  361. package/src/providers/vision-guard.d.ts +8 -0
  362. package/src/providers/vision-guard.ts +31 -0
  363. package/src/rate-limit-utils.d.ts +19 -0
  364. package/src/rate-limit-utils.ts +102 -0
  365. package/src/stream.d.ts +45 -0
  366. package/src/stream.ts +1306 -0
  367. package/src/types.d.ts +1073 -0
  368. package/src/types.ts +1305 -0
  369. package/src/usage/claude.ts +449 -0
  370. package/src/usage/gemini.ts +250 -0
  371. package/src/usage/github-copilot.ts +421 -0
  372. package/src/usage/google-antigravity.ts +201 -0
  373. package/src/usage/grok-cli.ts +259 -0
  374. package/src/usage/kimi.ts +285 -0
  375. package/src/usage/minimax-code.ts +31 -0
  376. package/src/usage/openai-codex.ts +503 -0
  377. package/src/usage/shared.ts +10 -0
  378. package/src/usage/zai.ts +247 -0
  379. package/src/usage.ts +190 -0
  380. package/src/utils/abort.d.ts +19 -0
  381. package/src/utils/abort.ts +51 -0
  382. package/src/utils/anthropic-auth.ts +95 -0
  383. package/src/utils/block-symbols.d.ts +6 -0
  384. package/src/utils/block-symbols.ts +11 -0
  385. package/src/utils/discovery/antigravity.ts +275 -0
  386. package/src/utils/discovery/codex.ts +362 -0
  387. package/src/utils/discovery/cursor.ts +388 -0
  388. package/src/utils/discovery/gemini.ts +248 -0
  389. package/src/utils/discovery/index.ts +4 -0
  390. package/src/utils/discovery/openai-compatible.ts +379 -0
  391. package/src/utils/event-stream.d.ts +41 -0
  392. package/src/utils/event-stream.ts +269 -0
  393. package/src/utils/fallback-transport.d.ts +110 -0
  394. package/src/utils/fallback-transport.ts +411 -0
  395. package/src/utils/fireworks-model-id.d.ts +10 -0
  396. package/src/utils/fireworks-model-id.ts +30 -0
  397. package/src/utils/foundry.d.ts +11 -0
  398. package/src/utils/foundry.ts +18 -0
  399. package/src/utils/h2-fetch.ts +60 -0
  400. package/src/utils/http-inspector.d.ts +59 -0
  401. package/src/utils/http-inspector.ts +380 -0
  402. package/src/utils/idle-iterator.d.ts +122 -0
  403. package/src/utils/idle-iterator.ts +410 -0
  404. package/src/utils/json-parse.d.ts +98 -0
  405. package/src/utils/json-parse.ts +607 -0
  406. package/src/utils/oauth/alibaba-token-plan.ts +60 -0
  407. package/src/utils/oauth/anthropic.ts +233 -0
  408. package/src/utils/oauth/api-key-login.ts +98 -0
  409. package/src/utils/oauth/api-key-validation.ts +344 -0
  410. package/src/utils/oauth/bizrouter.ts +15 -0
  411. package/src/utils/oauth/callback-server.d.ts +80 -0
  412. package/src/utils/oauth/callback-server.ts +359 -0
  413. package/src/utils/oauth/cerebras.ts +16 -0
  414. package/src/utils/oauth/cloudflare-ai-gateway.ts +48 -0
  415. package/src/utils/oauth/commandcode.ts +17 -0
  416. package/src/utils/oauth/cursor.ts +157 -0
  417. package/src/utils/oauth/deepinfra.ts +15 -0
  418. package/src/utils/oauth/deepseek.ts +53 -0
  419. package/src/utils/oauth/firepass.ts +24 -0
  420. package/src/utils/oauth/fireworks.ts +15 -0
  421. package/src/utils/oauth/fugu.ts +15 -0
  422. package/src/utils/oauth/github-copilot.d.ts +38 -0
  423. package/src/utils/oauth/github-copilot.ts +362 -0
  424. package/src/utils/oauth/gitlab-duo.ts +123 -0
  425. package/src/utils/oauth/glm-zcode.d.ts +71 -0
  426. package/src/utils/oauth/glm-zcode.ts +433 -0
  427. package/src/utils/oauth/google-antigravity.ts +200 -0
  428. package/src/utils/oauth/google-gemini-cli.ts +256 -0
  429. package/src/utils/oauth/google-oauth-shared.ts +110 -0
  430. package/src/utils/oauth/huggingface.ts +62 -0
  431. package/src/utils/oauth/index.ts +558 -0
  432. package/src/utils/oauth/kagi.ts +47 -0
  433. package/src/utils/oauth/kilo.ts +87 -0
  434. package/src/utils/oauth/kimi.d.ts +17 -0
  435. package/src/utils/oauth/kimi.ts +275 -0
  436. package/src/utils/oauth/kiro.ts +448 -0
  437. package/src/utils/oauth/litellm.ts +47 -0
  438. package/src/utils/oauth/lm-studio.ts +38 -0
  439. package/src/utils/oauth/mara.ts +16 -0
  440. package/src/utils/oauth/minimax-code.ts +78 -0
  441. package/src/utils/oauth/moonshot.ts +16 -0
  442. package/src/utils/oauth/nanogpt.ts +15 -0
  443. package/src/utils/oauth/nvidia.ts +70 -0
  444. package/src/utils/oauth/oauth.html +199 -0
  445. package/src/utils/oauth/ollama-cloud.ts +28 -0
  446. package/src/utils/oauth/ollama.ts +47 -0
  447. package/src/utils/oauth/openai-codex.ts +299 -0
  448. package/src/utils/oauth/opencode.ts +49 -0
  449. package/src/utils/oauth/opengateway.ts +15 -0
  450. package/src/utils/oauth/openrouter.ts +16 -0
  451. package/src/utils/oauth/parallel.ts +46 -0
  452. package/src/utils/oauth/perplexity.ts +225 -0
  453. package/src/utils/oauth/pkce.ts +18 -0
  454. package/src/utils/oauth/qianfan.ts +58 -0
  455. package/src/utils/oauth/qwen-portal.ts +60 -0
  456. package/src/utils/oauth/sglang.ts +42 -0
  457. package/src/utils/oauth/synthetic.ts +15 -0
  458. package/src/utils/oauth/tavily.ts +46 -0
  459. package/src/utils/oauth/together.ts +16 -0
  460. package/src/utils/oauth/types.d.ts +56 -0
  461. package/src/utils/oauth/types.ts +122 -0
  462. package/src/utils/oauth/venice.ts +59 -0
  463. package/src/utils/oauth/vercel-ai-gateway.ts +47 -0
  464. package/src/utils/oauth/vllm.ts +42 -0
  465. package/src/utils/oauth/xai.ts +246 -0
  466. package/src/utils/oauth/xiaomi.ts +199 -0
  467. package/src/utils/oauth/zai.ts +60 -0
  468. package/src/utils/oauth/zenmux.ts +15 -0
  469. package/src/utils/overflow.ts +275 -0
  470. package/src/utils/parse-bind.ts +81 -0
  471. package/src/utils/provider-response.d.ts +6 -0
  472. package/src/utils/provider-response.ts +30 -0
  473. package/src/utils/provider-safety-stop.ts +8 -0
  474. package/src/utils/proxy.d.ts +7 -0
  475. package/src/utils/proxy.ts +652 -0
  476. package/src/utils/retry-after.d.ts +3 -0
  477. package/src/utils/retry-after.ts +110 -0
  478. package/src/utils/retry-budget.d.ts +1 -0
  479. package/src/utils/retry-budget.ts +4 -0
  480. package/src/utils/retry.d.ts +29 -0
  481. package/src/utils/retry.ts +67 -0
  482. package/src/utils/schema/CONSTRAINTS.md +164 -0
  483. package/src/utils/schema/adapt.d.ts +24 -0
  484. package/src/utils/schema/adapt.ts +36 -0
  485. package/src/utils/schema/compatibility.d.ts +30 -0
  486. package/src/utils/schema/compatibility.ts +435 -0
  487. package/src/utils/schema/dereference.d.ts +11 -0
  488. package/src/utils/schema/dereference.ts +98 -0
  489. package/src/utils/schema/draft.d.ts +10 -0
  490. package/src/utils/schema/draft.ts +341 -0
  491. package/src/utils/schema/equality.d.ts +4 -0
  492. package/src/utils/schema/equality.ts +97 -0
  493. package/src/utils/schema/fields.d.ts +49 -0
  494. package/src/utils/schema/fields.ts +190 -0
  495. package/src/utils/schema/index.d.ts +14 -0
  496. package/src/utils/schema/index.ts +14 -0
  497. package/src/utils/schema/json-schema-validator.d.ts +12 -0
  498. package/src/utils/schema/json-schema-validator.ts +577 -0
  499. package/src/utils/schema/meta-validator.d.ts +2 -0
  500. package/src/utils/schema/meta-validator.ts +167 -0
  501. package/src/utils/schema/normalize.d.ts +93 -0
  502. package/src/utils/schema/normalize.ts +1588 -0
  503. package/src/utils/schema/root-combinator.d.ts +12 -0
  504. package/src/utils/schema/root-combinator.ts +143 -0
  505. package/src/utils/schema/spill.d.ts +8 -0
  506. package/src/utils/schema/spill.ts +43 -0
  507. package/src/utils/schema/stamps.d.ts +25 -0
  508. package/src/utils/schema/stamps.ts +97 -0
  509. package/src/utils/schema/types.d.ts +4 -0
  510. package/src/utils/schema/types.ts +11 -0
  511. package/src/utils/schema/wire.d.ts +54 -0
  512. package/src/utils/schema/wire.ts +213 -0
  513. package/src/utils/schema/zod-decontaminate.d.ts +31 -0
  514. package/src/utils/schema/zod-decontaminate.ts +331 -0
  515. package/src/utils/sse-debug.d.ts +10 -0
  516. package/src/utils/sse-debug.ts +289 -0
  517. package/src/utils/tool-call-healing.d.ts +80 -0
  518. package/src/utils/tool-call-healing.ts +298 -0
  519. package/src/utils/tool-choice-capability.d.ts +57 -0
  520. package/src/utils/tool-choice-capability.ts +633 -0
  521. package/src/utils/tool-choice.d.ts +50 -0
  522. package/src/utils/tool-choice.ts +99 -0
  523. package/src/utils/validation.ts +1080 -0
  524. package/src/utils.d.ts +117 -0
  525. package/src/utils.ts +523 -0
@@ -0,0 +1,839 @@
1
+ import { logger } from "@vib-rato/utils";
2
+ import { captureRequestHeaders, resolvePromptCacheKey } from "../auth-gateway/http";
3
+ import type {
4
+ AssistantMessage,
5
+ AssistantMessageEventStream,
6
+ Message,
7
+ RedactedThinkingContent,
8
+ StopReason,
9
+ TextContent,
10
+ ThinkingContent,
11
+ Tool,
12
+ ToolCall,
13
+ ToolResultMessage,
14
+ UserMessage,
15
+ } from "../types";
16
+ import { sanitizeJsonStrings } from "../utils";
17
+ import {
18
+ type AnthropicAssistantContentBlock,
19
+ type AnthropicMessage,
20
+ type AnthropicSystem,
21
+ type AnthropicTool,
22
+ type AnthropicToolChoice,
23
+ type AnthropicToolResultContent,
24
+ type AnthropicUserContentBlock,
25
+ anthropicMessagesRequestSchema,
26
+ } from "./anthropic-messages-server-schema";
27
+
28
+ /**
29
+ * Anthropic Messages API (https://docs.anthropic.com/en/api/messages) ↔ pi-ai
30
+ * gateway translation. Inbound: foreign HTTP body → vib Context. Outbound:
31
+ * vib AssistantMessage[Stream] → Anthropic-shaped JSON / SSE.
32
+ */
33
+
34
+ import type { AuthGatewayParsedRequest as ParsedRequest } from "../auth-gateway/types";
35
+
36
+ export type { ParsedRequest };
37
+
38
+ // ---------------------------------------------------------------------------
39
+ // Inbound parsing
40
+ // ---------------------------------------------------------------------------
41
+
42
+ type ImageContentPart = { type: "image"; data: string; mimeType: string };
43
+
44
+ // Dedup noise from unknown-block-type warnings. Module-scoped so the warn
45
+ // fires once per (category, type) pair across the lifetime of the process.
46
+ const WARNED_UNKNOWN_BLOCK_TYPES = new Set<string>();
47
+ function warnUnknownBlockType(category: "user" | "assistant", blockType: string): void {
48
+ const key = `${category}:${blockType}`;
49
+ if (WARNED_UNKNOWN_BLOCK_TYPES.has(key)) return;
50
+ WARNED_UNKNOWN_BLOCK_TYPES.add(key);
51
+ logger.warn("anthropic-messages: unknown content block flattened to text placeholder", {
52
+ category,
53
+ blockType,
54
+ });
55
+ }
56
+
57
+ // pi-ai's `ImageContent` only carries base64 + mimeType. When the inbound
58
+ // uses `url` or `file_id` sources we surface a text placeholder so the
59
+ // downstream provider still sees a sane history; warn once per source kind.
60
+ const WARNED_NON_BASE64_IMAGE_SOURCES = new Set<string>();
61
+ function warnNonBase64ImageSource(sourceType: string): void {
62
+ if (WARNED_NON_BASE64_IMAGE_SOURCES.has(sourceType)) return;
63
+ WARNED_NON_BASE64_IMAGE_SOURCES.add(sourceType);
64
+ logger.warn("anthropic-messages: image source surfaced as text placeholder (pi-ai ImageContent lacks URL channel)", {
65
+ sourceType,
66
+ });
67
+ }
68
+
69
+ // Compact, log-safe stringification for unknown content blocks. Keeps the
70
+ // placeholder informative without dumping multi-KB structures into history.
71
+ function describeUnknownBlock(block: { type: string }): string {
72
+ try {
73
+ const json = JSON.stringify(block);
74
+ if (json !== undefined && json.length <= 200) return `[${block.type}: ${json}]`;
75
+ } catch {
76
+ // fall through
77
+ }
78
+ return `[${block.type}]`;
79
+ }
80
+
81
+ function buildSystemPrompt(raw: AnthropicSystem): string[] | undefined {
82
+ if (raw === undefined) return undefined;
83
+ if (typeof raw === "string") return raw.length > 0 ? [raw] : undefined;
84
+ const parts = raw.map(block => block.text).filter(text => text.length > 0);
85
+ return parts.length > 0 ? [parts.join("\n\n")] : undefined;
86
+ }
87
+
88
+ function makeUserMessage(parts: (TextContent | ImageContentPart)[], timestamp: number): UserMessage {
89
+ return {
90
+ role: "user",
91
+ content: parts.length === 1 && parts[0].type === "text" ? parts[0].text : parts,
92
+ timestamp,
93
+ };
94
+ }
95
+
96
+ function toolResultPartsFromBlocks(
97
+ content: AnthropicToolResultContent[] | string | undefined,
98
+ ): (TextContent | ImageContentPart)[] {
99
+ if (content === undefined) return [];
100
+ if (typeof content === "string") return [{ type: "text", text: content }];
101
+ const out: (TextContent | ImageContentPart)[] = [];
102
+ for (const block of content) {
103
+ if (block.type === "text") {
104
+ out.push({ type: "text", text: block.text });
105
+ continue;
106
+ }
107
+ // block.type === "image" — schema only accepts base64 sources.
108
+ if (block.source.type === "base64") {
109
+ out.push({ type: "image", data: block.source.data, mimeType: block.source.media_type });
110
+ }
111
+ }
112
+ return out;
113
+ }
114
+
115
+ function walkUserContent(
116
+ blocks: string | AnthropicUserContentBlock[],
117
+ timestamp: number,
118
+ ): (UserMessage | ToolResultMessage)[] {
119
+ const messages: (UserMessage | ToolResultMessage)[] = [];
120
+ const userParts: (TextContent | ImageContentPart)[] = [];
121
+ const flush = () => {
122
+ if (userParts.length === 0) return;
123
+ messages.push(makeUserMessage(userParts.splice(0), timestamp));
124
+ };
125
+ if (typeof blocks === "string") {
126
+ if (blocks.length > 0) userParts.push({ type: "text", text: blocks });
127
+ flush();
128
+ return messages;
129
+ }
130
+ for (const block of blocks) {
131
+ if (block.type === "text") {
132
+ userParts.push({ type: "text", text: block.text });
133
+ } else if (block.type === "image") {
134
+ // SDK's typed source covers base64+url; our schema also accepts the
135
+ // forward-compat `file` variant. Narrow against a widened shape so
136
+ // every variant is handled at runtime regardless of SDK lag.
137
+ const source = block.source as {
138
+ type: string;
139
+ data?: string;
140
+ media_type?: string;
141
+ url?: string;
142
+ file_id?: string;
143
+ };
144
+ if (source.type === "base64" && source.data && source.media_type) {
145
+ userParts.push({ type: "image", data: source.data, mimeType: source.media_type });
146
+ } else {
147
+ warnNonBase64ImageSource(source.type);
148
+ const ref =
149
+ source.type === "url" ? (source.url ?? "") : source.type === "file" ? (source.file_id ?? "") : "";
150
+ userParts.push({ type: "text", text: `[image: ${ref}]` });
151
+ }
152
+ } else if (block.type === "tool_result") {
153
+ // Anthropic permits tool_result blocks to follow plain text/image
154
+ // siblings in the same user message. pi-ai's history is a flat
155
+ // sequence of typed messages, so flush the accumulated parts as a
156
+ // separate UserMessage before emitting the ToolResultMessage.
157
+ flush();
158
+ messages.push({
159
+ role: "toolResult",
160
+ toolCallId: block.tool_use_id,
161
+ // Anthropic tool_results don't carry the tool name; downstream can rehydrate.
162
+ toolName: "",
163
+ content: toolResultPartsFromBlocks(block.content as AnthropicToolResultContent[] | string | undefined),
164
+ isError: block.is_error === true,
165
+ timestamp,
166
+ });
167
+ } else {
168
+ // Unknown variant (server_tool_use, mcp_*, document, web_search_tool_result,
169
+ // container_upload, code_execution_*, …). Flatten to a text placeholder
170
+ // so the downstream provider still gets a coherent transcript.
171
+ const unknown = block as { type: string };
172
+ warnUnknownBlockType("user", unknown.type);
173
+ userParts.push({ type: "text", text: describeUnknownBlock(unknown) });
174
+ }
175
+ }
176
+ flush();
177
+ return messages;
178
+ }
179
+
180
+ function walkAssistantContent(
181
+ blocks: string | AnthropicAssistantContentBlock[],
182
+ ): (TextContent | ThinkingContent | RedactedThinkingContent | ToolCall)[] {
183
+ const out: (TextContent | ThinkingContent | RedactedThinkingContent | ToolCall)[] = [];
184
+ if (typeof blocks === "string") {
185
+ if (blocks.length > 0) out.push({ type: "text", text: blocks });
186
+ return out;
187
+ }
188
+ for (const block of blocks) {
189
+ switch (block.type) {
190
+ case "text":
191
+ out.push({ type: "text", text: block.text });
192
+ break;
193
+ case "thinking": {
194
+ const tc: ThinkingContent = { type: "thinking", thinking: block.thinking };
195
+ if (block.signature !== undefined) tc.thinkingSignature = block.signature;
196
+ out.push(tc);
197
+ break;
198
+ }
199
+ case "redacted_thinking":
200
+ out.push({ type: "redactedThinking", data: block.data });
201
+ break;
202
+ case "tool_use":
203
+ out.push({
204
+ type: "toolCall",
205
+ id: block.id,
206
+ name: block.name,
207
+ arguments: block.input ?? {},
208
+ });
209
+ break;
210
+ default: {
211
+ // Unknown assistant variant (server_tool_use, mcp_tool_use, …).
212
+ // Flatten to a text placeholder; warn once per unknown type.
213
+ const unknown = block as { type: string };
214
+ warnUnknownBlockType("assistant", unknown.type);
215
+ out.push({ type: "text", text: describeUnknownBlock(unknown) });
216
+ break;
217
+ }
218
+ }
219
+ }
220
+ return out;
221
+ }
222
+
223
+ function walkTools(tools: AnthropicTool[] | undefined): Tool[] | undefined {
224
+ if (!tools) return undefined;
225
+ return tools.map(tool => ({
226
+ name: tool.name,
227
+ description: tool.description ?? "",
228
+ parameters: tool.input_schema as Record<string, unknown>,
229
+ }));
230
+ }
231
+
232
+ function mapToolChoice(choice: AnthropicToolChoice | undefined): ParsedRequest["options"]["toolChoice"] {
233
+ if (!choice) return undefined;
234
+ switch (choice.type) {
235
+ case "auto":
236
+ return "auto";
237
+ case "any":
238
+ return "required";
239
+ case "none":
240
+ return "none";
241
+ case "tool":
242
+ return { name: choice.name };
243
+ }
244
+ }
245
+
246
+ type AnthropicCacheControl = { type: "ephemeral"; ttl?: "1h" | "5m" };
247
+ type HasCacheControl = { cache_control?: AnthropicCacheControl };
248
+
249
+ function readCacheControl(value: unknown): AnthropicCacheControl | undefined {
250
+ if (value === null || typeof value !== "object") return undefined;
251
+ const cc = (value as HasCacheControl).cache_control;
252
+ if (!cc || typeof cc !== "object" || cc.type !== "ephemeral") return undefined;
253
+ return cc;
254
+ }
255
+
256
+ /**
257
+ * Anthropic clients annotate caching breakpoints per block via
258
+ * `cache_control: { type: "ephemeral", ttl?: "1h"|"5m" }`. pi-ai's
259
+ * `cacheRetention` is per-request, not per-block, and its anthropic provider
260
+ * re-applies breakpoints itself on the rebuilt outbound wire. Scan every
261
+ * block once and return the strongest retention requested: any `ttl: "1h"`
262
+ * promotes the request to "long", anything else ephemeral maps to "short".
263
+ */
264
+ function deriveCacheRetention(data: {
265
+ system?: unknown;
266
+ messages: readonly unknown[];
267
+ tools?: readonly unknown[];
268
+ }): "short" | "long" | undefined {
269
+ let strongest: "short" | "long" | undefined;
270
+ const visit = (cc: AnthropicCacheControl | undefined): void => {
271
+ if (!cc) return;
272
+ if (cc.ttl === "1h") strongest = "long";
273
+ else strongest ??= "short";
274
+ };
275
+ if (Array.isArray(data.system)) {
276
+ for (const block of data.system) visit(readCacheControl(block));
277
+ }
278
+ for (const message of data.messages) {
279
+ if (message === null || typeof message !== "object") continue;
280
+ const content = (message as { content?: unknown }).content;
281
+ if (!Array.isArray(content)) continue;
282
+ for (const block of content) visit(readCacheControl(block));
283
+ }
284
+ if (data.tools) {
285
+ for (const tool of data.tools) visit(readCacheControl(tool));
286
+ }
287
+ return strongest;
288
+ }
289
+
290
+ export function parseRequest(body: unknown, headers?: Headers): ParsedRequest {
291
+ const parsed = anthropicMessagesRequestSchema.safeParse(body);
292
+ if (!parsed.success) {
293
+ throw new Error(`anthropic-messages: ${parsed.error.message}`);
294
+ }
295
+ const data = parsed.data;
296
+
297
+ const now = Date.now();
298
+ const messages: Message[] = [];
299
+ for (const message of data.messages as AnthropicMessage[]) {
300
+ if (message.role === "user") {
301
+ for (const m of walkUserContent(message.content, now)) messages.push(m);
302
+ } else {
303
+ const assistant: AssistantMessage = {
304
+ role: "assistant",
305
+ content: walkAssistantContent(message.content),
306
+ api: "anthropic-messages",
307
+ provider: "anthropic",
308
+ model: data.model,
309
+ usage: emptyUsage(),
310
+ stopReason: "stop",
311
+ timestamp: now,
312
+ };
313
+ messages.push(assistant);
314
+ }
315
+ }
316
+
317
+ const options: ParsedRequest["options"] = {
318
+ maxOutputTokens: data.max_tokens,
319
+ };
320
+ if (data.temperature !== undefined) options.temperature = data.temperature;
321
+ if (data.top_p !== undefined) options.topP = data.top_p;
322
+ if (data.top_k !== undefined) options.topK = data.top_k;
323
+ if (data.stop_sequences) options.stopSequences = data.stop_sequences;
324
+ const toolChoice = mapToolChoice(data.tool_choice as AnthropicToolChoice | undefined);
325
+ if (toolChoice !== undefined) options.toolChoice = toolChoice;
326
+ // `disable_parallel_tool_use === true` means the client wants the model to
327
+ // emit at most one tool call per turn; map to pi-ai's negated boolean.
328
+ // Leave undefined when the field is absent or explicitly `false` so we
329
+ // don't override provider defaults.
330
+ if (data.tool_choice?.disable_parallel_tool_use === true) {
331
+ options.parallelToolCalls = false;
332
+ }
333
+ if (data.thinking) {
334
+ switch (data.thinking.type) {
335
+ case "enabled":
336
+ options.explicitThinkingBudgetTokens = data.thinking.budget_tokens;
337
+ break;
338
+ case "disabled":
339
+ options.disableReasoning = true;
340
+ break;
341
+ case "adaptive":
342
+ if (data.thinking.budget_tokens !== undefined) {
343
+ options.explicitThinkingBudgetTokens = data.thinking.budget_tokens;
344
+ }
345
+ break;
346
+ }
347
+ }
348
+ const cacheRetention = deriveCacheRetention(data);
349
+ if (cacheRetention !== undefined) options.cacheRetention = cacheRetention;
350
+ // Anthropic clients commonly send `metadata: { user_id }`; forward verbatim
351
+ // so downstream providers (and our anthropic-passthrough fast-path) can
352
+ // preserve abuse-tracking signal.
353
+ if (data.metadata !== undefined) {
354
+ options.metadata = data.metadata as Record<string, unknown>;
355
+ }
356
+ const cacheKey = resolvePromptCacheKey(body, headers);
357
+ if (cacheKey !== undefined) options.promptCacheKey = cacheKey;
358
+ // Allow-listed header capture. The gateway's `handleFormatEndpoint`
359
+ // already merges its own pre-capture under whatever the parser sets, but
360
+ // we populate here too so direct callers of `parseRequest` (tests, custom
361
+ // wrappers) see the same surface. `anthropic-version` is the most
362
+ // load-bearing — some downstream Anthropic-API targets reject requests
363
+ // missing it.
364
+ if (headers) {
365
+ const captured = captureRequestHeaders(headers);
366
+ if (Object.keys(captured).length > 0) options.headers = captured;
367
+ }
368
+
369
+ return {
370
+ modelId: data.model,
371
+ context: {
372
+ systemPrompt: buildSystemPrompt(data.system as AnthropicSystem),
373
+ messages,
374
+ tools: walkTools(data.tools as AnthropicTool[] | undefined),
375
+ },
376
+ stream: data.stream === true,
377
+ options,
378
+ };
379
+ }
380
+
381
+ function emptyUsage(): AssistantMessage["usage"] {
382
+ return {
383
+ input: 0,
384
+ output: 0,
385
+ cacheRead: 0,
386
+ cacheWrite: 0,
387
+ totalTokens: 0,
388
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
389
+ };
390
+ }
391
+
392
+ // ---------------------------------------------------------------------------
393
+ // Outbound encoding
394
+ // ---------------------------------------------------------------------------
395
+
396
+ function newMessageId(): string {
397
+ const hex = (globalThis.crypto?.randomUUID?.() ?? randomFallback()).replace(/-/g, "").slice(0, 24);
398
+ return `msg_${hex}`;
399
+ }
400
+
401
+ function randomFallback(): string {
402
+ // Sufficient for tests / environments without crypto.randomUUID
403
+ const buf = new Uint8Array(16);
404
+ for (let i = 0; i < 16; i++) buf[i] = Math.floor(Math.random() * 256);
405
+ const hex = Array.from(buf, b => b.toString(16).padStart(2, "0")).join("");
406
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
407
+ }
408
+
409
+ function mapStopReasonOut(reason: StopReason): "end_turn" | "max_tokens" | "tool_use" {
410
+ switch (reason) {
411
+ case "length":
412
+ return "max_tokens";
413
+ case "toolUse":
414
+ return "tool_use";
415
+ default:
416
+ return "end_turn";
417
+ }
418
+ }
419
+
420
+ /**
421
+ * True when `signature` is one of OUR serialized OpenAI Responses reasoning-item
422
+ * envelopes (produced by the Responses/Codex decoders as
423
+ * `JSON.stringify(reasoningItem)` with `type: "reasoning"`). Such an envelope is
424
+ * NOT a valid Anthropic thinking signature and may embed raw chain-of-thought in
425
+ * `content[]`, so it must never be forwarded on Anthropic egress. Genuine opaque
426
+ * Anthropic signatures and any non-envelope string return false (fail safe).
427
+ */
428
+ function isSerializedResponsesReasoningItem(signature: string): boolean {
429
+ try {
430
+ const parsed: unknown = JSON.parse(signature);
431
+ return (
432
+ typeof parsed === "object" &&
433
+ parsed !== null &&
434
+ !Array.isArray(parsed) &&
435
+ (parsed as { type?: unknown }).type === "reasoning"
436
+ );
437
+ } catch {
438
+ return false;
439
+ }
440
+ }
441
+
442
+ /**
443
+ * A thinking-block signature safe to emit on Anthropic egress: cross-protocol
444
+ * serialized Responses reasoning envelopes are omitted (they can carry raw CoT);
445
+ * genuine opaque Anthropic signatures round-trip unchanged.
446
+ */
447
+ function safeThinkingSignature(signature: string | undefined): string | undefined {
448
+ if (!signature) return undefined;
449
+ if (isSerializedResponsesReasoningItem(signature)) return undefined;
450
+ return signature;
451
+ }
452
+
453
+ function isResponsesFamilyApi(api: AssistantMessage["api"]): boolean {
454
+ return api === "openai-responses" || api === "openai-codex-responses";
455
+ }
456
+
457
+ function safeThinkingText(content: ThinkingContent, api: AssistantMessage["api"]): string | undefined {
458
+ if (isResponsesFamilyApi(api) && content.provenance === undefined) return undefined;
459
+ if (content.provenance === "raw") return undefined;
460
+ if (content.provenance === "mixed") return content.summaryText;
461
+ if (content.provenance === "summary") return content.summaryText ?? content.thinking;
462
+ return content.thinking;
463
+ }
464
+
465
+ function hasRawOrMixedThinking(partial: AssistantMessage, contentIndex: number): boolean {
466
+ const content = partial.content[contentIndex];
467
+ return content?.type === "thinking" && (content.provenance === "raw" || content.provenance === "mixed");
468
+ }
469
+
470
+ /** Responses-family reasoning is untrusted until output_item.done assigns provenance. */
471
+ function hasUnfinalizedResponsesThinking(partial: AssistantMessage, contentIndex: number): boolean {
472
+ const content = partial.content[contentIndex];
473
+ return content?.type !== "thinking" || (isResponsesFamilyApi(partial.api) && content.provenance === undefined);
474
+ }
475
+
476
+ function encodeContentBlocks(message: AssistantMessage): Record<string, unknown>[] {
477
+ const blocks: Record<string, unknown>[] = [];
478
+ for (const c of message.content) {
479
+ switch (c.type) {
480
+ case "text":
481
+ blocks.push({ type: "text", text: c.text });
482
+ break;
483
+ case "thinking": {
484
+ const thinking = safeThinkingText(c, message.api);
485
+ if (thinking === undefined) break;
486
+ const b: Record<string, unknown> = { type: "thinking", thinking };
487
+ const sig = safeThinkingSignature(c.thinkingSignature);
488
+ if (sig) b.signature = sig;
489
+ blocks.push(b);
490
+ break;
491
+ }
492
+ case "redactedThinking":
493
+ blocks.push({ type: "redacted_thinking", data: c.data });
494
+ break;
495
+ case "toolCall":
496
+ blocks.push({ type: "tool_use", id: c.id, name: c.name, input: sanitizeJsonStrings(c.arguments ?? {}) });
497
+ break;
498
+ }
499
+ }
500
+ return blocks;
501
+ }
502
+
503
+ function encodeUsage(message: AssistantMessage): Record<string, unknown> {
504
+ return {
505
+ input_tokens: message.usage.input,
506
+ output_tokens: message.usage.output,
507
+ cache_read_input_tokens: message.usage.cacheRead,
508
+ cache_creation_input_tokens: message.usage.cacheWrite,
509
+ };
510
+ }
511
+
512
+ export function encodeResponse(message: AssistantMessage, requestedModelId: string): Record<string, unknown> {
513
+ if (message.stopReason === "error" || message.stopReason === "aborted") {
514
+ throw new Error(message.errorMessage ?? `anthropic-messages: upstream ${message.stopReason}`);
515
+ }
516
+ return {
517
+ id: message.responseId ?? newMessageId(),
518
+ type: "message",
519
+ role: "assistant",
520
+ model: requestedModelId,
521
+ content: encodeContentBlocks(message),
522
+ stop_reason: mapStopReasonOut(message.stopReason),
523
+ // TODO: surface the matched stop sequence once pi-ai's
524
+ // `AssistantMessage.stopReason` carries the matched string. Intentionally
525
+ // `null` for now (Anthropic schema allows it).
526
+ stop_sequence: null,
527
+ usage: encodeUsage(message),
528
+ };
529
+ }
530
+
531
+ // ---------------------------------------------------------------------------
532
+ // Streaming encoder
533
+ // ---------------------------------------------------------------------------
534
+
535
+ const ENCODER = new TextEncoder();
536
+
537
+ function sseFrame(event: string, data: Record<string, unknown>): Uint8Array {
538
+ return ENCODER.encode(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
539
+ }
540
+
541
+ type BlockKind = "text" | "thinking" | "tool_use";
542
+
543
+ interface OpenBlock {
544
+ index: number;
545
+ kind: BlockKind;
546
+ }
547
+
548
+ export function encodeStream(
549
+ events: AssistantMessageEventStream,
550
+ requestedModelId: string,
551
+ ): ReadableStream<Uint8Array> {
552
+ return new ReadableStream<Uint8Array>({
553
+ async start(controller) {
554
+ const messageId = newMessageId();
555
+ let started = false;
556
+ const open = new Map<number, OpenBlock>();
557
+ // contentIndexes that already streamed a reasoning summary delta, so a
558
+ // final-only reasoning_summary_end does not duplicate streamed summary text.
559
+ const summaryDeltaSeen = new Set<number>();
560
+ // Responses assigns reasoning provenance only at output_item.done. Keep its
561
+ // pre-classification bytes out of this public compatibility stream.
562
+ const pendingThinkingDeltas = new Map<number, string[]>();
563
+
564
+ const ensureStart = (partial: AssistantMessage) => {
565
+ if (started) return;
566
+ started = true;
567
+ controller.enqueue(
568
+ sseFrame("message_start", {
569
+ type: "message_start",
570
+ message: {
571
+ id: messageId,
572
+ type: "message",
573
+ role: "assistant",
574
+ model: requestedModelId,
575
+ content: [],
576
+ stop_reason: null,
577
+ // TODO: same as encodeResponse — surface matched stop sequence
578
+ // once pi-ai propagates it.
579
+ stop_sequence: null,
580
+ usage: encodeUsage(partial),
581
+ },
582
+ }),
583
+ );
584
+ };
585
+
586
+ const closeBlock = (index: number) => {
587
+ if (!open.has(index)) return;
588
+ controller.enqueue(sseFrame("content_block_stop", { type: "content_block_stop", index }));
589
+ open.delete(index);
590
+ };
591
+
592
+ const openThinking = (partial: AssistantMessage, index: number) => {
593
+ if (open.has(index)) return;
594
+ ensureStart(partial);
595
+ open.set(index, { index, kind: "thinking" });
596
+ controller.enqueue(
597
+ sseFrame("content_block_start", {
598
+ type: "content_block_start",
599
+ index,
600
+ content_block: { type: "thinking", thinking: "" },
601
+ }),
602
+ );
603
+ };
604
+
605
+ const writeThinkingDelta = (index: number, thinking: string) => {
606
+ if (thinking.length === 0) return;
607
+ controller.enqueue(
608
+ sseFrame("content_block_delta", {
609
+ type: "content_block_delta",
610
+ index,
611
+ delta: { type: "thinking_delta", thinking },
612
+ }),
613
+ );
614
+ };
615
+
616
+ try {
617
+ for await (const ev of events) {
618
+ switch (ev.type) {
619
+ case "start":
620
+ ensureStart(ev.partial);
621
+ break;
622
+ case "text_start": {
623
+ ensureStart(ev.partial);
624
+ open.set(ev.contentIndex, { index: ev.contentIndex, kind: "text" });
625
+ controller.enqueue(
626
+ sseFrame("content_block_start", {
627
+ type: "content_block_start",
628
+ index: ev.contentIndex,
629
+ content_block: { type: "text", text: "" },
630
+ }),
631
+ );
632
+ break;
633
+ }
634
+ case "text_delta":
635
+ controller.enqueue(
636
+ sseFrame("content_block_delta", {
637
+ type: "content_block_delta",
638
+ index: ev.contentIndex,
639
+ delta: { type: "text_delta", text: ev.delta },
640
+ }),
641
+ );
642
+ break;
643
+ case "text_end":
644
+ closeBlock(ev.contentIndex);
645
+ break;
646
+ case "thinking_start": {
647
+ if (hasRawOrMixedThinking(ev.partial, ev.contentIndex)) break;
648
+ if (hasUnfinalizedResponsesThinking(ev.partial, ev.contentIndex)) {
649
+ pendingThinkingDeltas.set(ev.contentIndex, []);
650
+ break;
651
+ }
652
+ openThinking(ev.partial, ev.contentIndex);
653
+ break;
654
+ }
655
+ case "thinking_delta": {
656
+ if (hasRawOrMixedThinking(ev.partial, ev.contentIndex)) break;
657
+ if (hasUnfinalizedResponsesThinking(ev.partial, ev.contentIndex)) {
658
+ const deltas = pendingThinkingDeltas.get(ev.contentIndex) ?? [];
659
+ deltas.push(ev.delta);
660
+ pendingThinkingDeltas.set(ev.contentIndex, deltas);
661
+ break;
662
+ }
663
+ writeThinkingDelta(ev.contentIndex, ev.delta);
664
+ break;
665
+ }
666
+ case "thinking_end": {
667
+ const unfinalized = hasUnfinalizedResponsesThinking(ev.partial, ev.contentIndex);
668
+ const rawOrMixed = hasRawOrMixedThinking(ev.partial, ev.contentIndex);
669
+ const pending = pendingThinkingDeltas.get(ev.contentIndex);
670
+ pendingThinkingDeltas.delete(ev.contentIndex);
671
+ if (rawOrMixed || unfinalized) {
672
+ closeBlock(ev.contentIndex);
673
+ break;
674
+ }
675
+ if (pending) {
676
+ openThinking(ev.partial, ev.contentIndex);
677
+ for (const delta of pending) writeThinkingDelta(ev.contentIndex, delta);
678
+ }
679
+ const c = ev.partial.content[ev.contentIndex];
680
+ const sig = c?.type === "thinking" ? safeThinkingSignature(c.thinkingSignature) : undefined;
681
+ if (sig) {
682
+ controller.enqueue(
683
+ sseFrame("content_block_delta", {
684
+ type: "content_block_delta",
685
+ index: ev.contentIndex,
686
+ delta: { type: "signature_delta", signature: sig },
687
+ }),
688
+ );
689
+ }
690
+ closeBlock(ev.contentIndex);
691
+ break;
692
+ }
693
+ case "reasoning_summary_start": {
694
+ // Provider-displayable summary reasoning surfaces as this format's
695
+ // native thinking channel. Open the thinking block if a thinking_start
696
+ // did not already (summary-only streams emit no thinking_start).
697
+ if (!open.has(ev.contentIndex)) {
698
+ ensureStart(ev.partial);
699
+ open.set(ev.contentIndex, { index: ev.contentIndex, kind: "thinking" });
700
+ controller.enqueue(
701
+ sseFrame("content_block_start", {
702
+ type: "content_block_start",
703
+ index: ev.contentIndex,
704
+ content_block: { type: "thinking", thinking: "" },
705
+ }),
706
+ );
707
+ }
708
+ break;
709
+ }
710
+ case "reasoning_summary_delta":
711
+ // Only a non-whitespace delta counts as a delivered summary; a bare
712
+ // separator ("\n\n") must not suppress a later final-only end content.
713
+ if (ev.delta.trim().length > 0) summaryDeltaSeen.add(ev.contentIndex);
714
+ controller.enqueue(
715
+ sseFrame("content_block_delta", {
716
+ type: "content_block_delta",
717
+ index: ev.contentIndex,
718
+ delta: { type: "thinking_delta", thinking: ev.delta },
719
+ }),
720
+ );
721
+ break;
722
+ case "reasoning_summary_end": {
723
+ // Final-only summary: text arrives only on the end event with no prior
724
+ // deltas. Ensure the thinking block is open, then surface the content as
725
+ // a thinking_delta (skip when deltas already streamed to avoid dup). The
726
+ // thinking block is closed by the subsequent thinking_end.
727
+ if (ev.content.length > 0 && !summaryDeltaSeen.has(ev.contentIndex)) {
728
+ if (!open.has(ev.contentIndex)) {
729
+ ensureStart(ev.partial);
730
+ open.set(ev.contentIndex, { index: ev.contentIndex, kind: "thinking" });
731
+ controller.enqueue(
732
+ sseFrame("content_block_start", {
733
+ type: "content_block_start",
734
+ index: ev.contentIndex,
735
+ content_block: { type: "thinking", thinking: "" },
736
+ }),
737
+ );
738
+ }
739
+ controller.enqueue(
740
+ sseFrame("content_block_delta", {
741
+ type: "content_block_delta",
742
+ index: ev.contentIndex,
743
+ delta: { type: "thinking_delta", thinking: ev.content },
744
+ }),
745
+ );
746
+ }
747
+ break;
748
+ }
749
+ case "toolcall_start": {
750
+ ensureStart(ev.partial);
751
+ const tc = ev.partial.content[ev.contentIndex] as ToolCall | undefined;
752
+ open.set(ev.contentIndex, { index: ev.contentIndex, kind: "tool_use" });
753
+ controller.enqueue(
754
+ sseFrame("content_block_start", {
755
+ type: "content_block_start",
756
+ index: ev.contentIndex,
757
+ content_block: {
758
+ type: "tool_use",
759
+ id: tc?.id ?? "",
760
+ name: tc?.name ?? "",
761
+ input: {},
762
+ },
763
+ }),
764
+ );
765
+ break;
766
+ }
767
+ case "toolcall_delta":
768
+ controller.enqueue(
769
+ sseFrame("content_block_delta", {
770
+ type: "content_block_delta",
771
+ index: ev.contentIndex,
772
+ delta: { type: "input_json_delta", partial_json: ev.delta },
773
+ }),
774
+ );
775
+ break;
776
+ case "toolcall_end":
777
+ closeBlock(ev.contentIndex);
778
+ break;
779
+ case "done": {
780
+ for (const idx of [...open.keys()]) closeBlock(idx);
781
+ pendingThinkingDeltas.clear();
782
+ controller.enqueue(
783
+ sseFrame("message_delta", {
784
+ type: "message_delta",
785
+ // TODO: surface matched stop sequence once pi-ai
786
+ // propagates it on the `done` event.
787
+ delta: { stop_reason: mapStopReasonOut(ev.reason), stop_sequence: null },
788
+ usage: encodeUsage(ev.message),
789
+ }),
790
+ );
791
+ controller.enqueue(sseFrame("message_stop", { type: "message_stop" }));
792
+ controller.close();
793
+ return;
794
+ }
795
+ case "error": {
796
+ const msg = ev.error.errorMessage ?? "stream error";
797
+ pendingThinkingDeltas.clear();
798
+ controller.enqueue(
799
+ sseFrame("error", { type: "error", error: { type: "api_error", message: msg } }),
800
+ );
801
+ controller.close();
802
+ return;
803
+ }
804
+ }
805
+ }
806
+ // stream ended without explicit done; close gracefully
807
+ pendingThinkingDeltas.clear();
808
+ for (const idx of [...open.keys()]) closeBlock(idx);
809
+ controller.enqueue(sseFrame("message_stop", { type: "message_stop" }));
810
+ controller.close();
811
+ } catch (err) {
812
+ pendingThinkingDeltas.clear();
813
+ controller.enqueue(
814
+ sseFrame("error", {
815
+ type: "error",
816
+ error: { type: "api_error", message: err instanceof Error ? err.message : String(err) },
817
+ }),
818
+ );
819
+ controller.close();
820
+ }
821
+ },
822
+ });
823
+ }
824
+
825
+ // ---------------------------------------------------------------------------
826
+ // Error envelope
827
+ // ---------------------------------------------------------------------------
828
+
829
+ /**
830
+ * Anthropic error envelope: `{ type: "error", error: { type, message } }`.
831
+ * See https://docs.anthropic.com/en/api/errors. Returned as a `Response` so
832
+ * the gateway can hand it straight back to the client without extra wrapping.
833
+ */
834
+ export function formatError(status: number, type: string, message: string): Response {
835
+ return new Response(JSON.stringify({ type: "error", error: { type, message } }), {
836
+ status,
837
+ headers: { "Content-Type": "application/json" },
838
+ });
839
+ }