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,506 @@
1
+ import { isUnexpectedSocketCloseMessage } from "jeopi-utils";
2
+ import type { Api, AssistantMessage } from "../types";
3
+ import {
4
+ AnthropicConnectionError,
5
+ AnthropicConnectionTimeoutError,
6
+ ProviderHttpError,
7
+ STREAM_ENVELOPE_ERROR_PREFIX,
8
+ } from "./classes";
9
+ import { isOpaqueStatusBody, matchesUsageLimitText, parseRateLimitReason } from "./rate-limit";
10
+
11
+ export const Flag = {
12
+ Class: 0x1000,
13
+ ThinkingLoop: 0x0001_0000,
14
+ Transient: 0x0002_0000,
15
+ Timeout: 0x0004_0000,
16
+ UsageLimit: 0x0008_0000,
17
+ StaleResponsesItem: 0x0010_0000,
18
+ MalformedFunctionCall: 0x0020_0000,
19
+ ProviderFinishError: 0x0040_0000,
20
+ ContextOverflow: 0x0080_0000,
21
+ AuthFailed: 0x0100_0000,
22
+ SilentAbort: 0x0200_0000,
23
+ UserInterrupt: 0x0400_0000,
24
+ Abort: 0x0800_0000,
25
+ /** Anthropic strict-tool grammar too large / schema too complex to compile (400). */
26
+ Grammar: 0x1000_0000,
27
+ /** Anthropic model/account does not support fast mode / the `speed` parameter. */
28
+ FastModeUnsupported: 0x2000_0000,
29
+ /** OAuth refresh failed definitively — the stored grant is dead, re-login required. */
30
+ OAuthExpiry: 0x4000_0000,
31
+ } as const;
32
+
33
+ export type Flag = (typeof Flag)[keyof typeof Flag];
34
+
35
+ const KIND_MASK =
36
+ Flag.ThinkingLoop |
37
+ Flag.Transient |
38
+ Flag.Timeout |
39
+ Flag.UsageLimit |
40
+ Flag.StaleResponsesItem |
41
+ Flag.MalformedFunctionCall |
42
+ Flag.ProviderFinishError |
43
+ Flag.ContextOverflow |
44
+ Flag.AuthFailed |
45
+ Flag.SilentAbort |
46
+ Flag.UserInterrupt |
47
+ Flag.Abort |
48
+ Flag.Grammar |
49
+ Flag.FastModeUnsupported |
50
+ Flag.OAuthExpiry;
51
+
52
+ const RETRIABLE_KINDS =
53
+ Flag.Transient | Flag.UsageLimit | Flag.ThinkingLoop | Flag.StaleResponsesItem | Flag.ProviderFinishError;
54
+
55
+ const OVERFLOW_PATTERNS = [
56
+ /prompt is too long/i, // Anthropic
57
+ /input is too long for requested model/i, // Amazon Bedrock
58
+ /exceeds the context window/i, // OpenAI (Completions & Responses API)
59
+ /input token count.*exceeds the maximum/i, // Google (Gemini)
60
+ /maximum prompt length is \d+/i, // xAI (Grok)
61
+ /reduce the length of the messages/i, // Groq
62
+ /maximum context length is \d+ tokens/i, // OpenRouter (all backends)
63
+ /exceeds the limit of \d+/i, // GitHub Copilot
64
+ /exceeds the available context size/i, // llama.cpp server
65
+ /requested tokens?.*exceed.*context (window|length|size)/i, // llama.cpp / OpenAI-compatible local servers
66
+ /context (window|length|size).*(exceeded|overflow|too small)/i, // Generic local server variants
67
+ /(prompt|input).*(too long|too large).*(context|n_ctx)/i, // llama.cpp phrasing variants
68
+ /requested tokens?.*(exceeds?|greater than).*(n_ctx|context)/i, // llama.cpp n_ctx variants
69
+ /greater than the context length/i, // LM Studio
70
+ /context window exceeds limit/i, // MiniMax
71
+ /exceeded model token limit/i, // Kimi For Coding
72
+ /context[_ ]length[_ ]exceeded/i, // Generic fallback
73
+ /too many tokens/i, // Generic fallback
74
+ /token limit exceeded/i, // Generic fallback
75
+ /request_too_large/i, // Anthropic 413 (request body too large)
76
+ /request exceeds the maximum size/i, // Anthropic 413 variant
77
+ /payload too large/i, // Generic HTTP 413 variant
78
+ /entity too large/i, // Generic HTTP 413 variant
79
+ /\b413\b.*\b(request|payload|entity)\b.*\btoo large\b/i, // "413 Request Entity Too Large" variants
80
+ /model_context_window_exceeded/i, // z.ai non-standard finish_reason surfaced as error text
81
+ /prompt filled the context window/i, // Ollama OpenAI-compatible empty length completion
82
+ ];
83
+
84
+ const OVERFLOW_NO_BODY_PATTERN = /\b4(00|13)\s*(status code)?\s*\(no body\)/i;
85
+ const TIMEOUT_PATTERN = /\b(?:operation\s+)?timed?\s*out\b|\btimeout\b|\bstream stall\b/i;
86
+ const TRANSIENT_ENVELOPE_PATTERN = /anthropic stream envelope error:/i;
87
+ const TRANSIENT_ENVELOPE_BEFORE_START_PATTERN = /before message_start/i;
88
+ export const STREAM_READ_ERROR_PATTERN = /stream[_ -]?read[_ -]?error/i;
89
+ export const TRANSIENT_TRANSPORT_PATTERN =
90
+ /overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|retry your request|network.?error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|upstream.?request.?failed|reset before headers|socket hang up|timed? out|timeout|terminated|retry delay|stream stall|no error details in response|HTTP2(?:StreamReset|RefusedStream|EnhanceYourCalm)|malformed.?function.?call/i;
91
+ const AUTH_FAILURE_PATTERN =
92
+ /\b(?:401|403|unauthorized|forbidden|authentication|auth[_ ]?unavailable|no auth available|(?:invalid|no)[_ ]?api[_ ]?key)\b/i;
93
+ const MALFORMED_FUNCTION_CALL_PATTERN = /\bmalformed.?function.?call\b/i;
94
+ const PROVIDER_FINISH_ERROR_PATTERN = /\bProvider (?:returned error finish_reason|finish_reason:\s*error)\b/i;
95
+ const STALE_RESPONSE_ITEM_PATTERNS = [/\bItem with id ['"][^'"]+['"] not found\.?/i, /previous[ _]?response/i] as const;
96
+ const STALE_RESPONSE_ITEM_DETAIL_PATTERN = /not[ _]?found|invalid|expired|stale|zero[ _-]?data[ _-]?retention/i;
97
+ /**
98
+ * Local llama.cpp / Ollama deterministic tool-call argument JSON parse failure.
99
+ * The model emitted invalid JSON in a tool call and the server returned HTTP 500
100
+ * with this exact text — replaying the same prompt yields the same malformed
101
+ * output, so callers strip {@link Flag.Transient} when this matches.
102
+ */
103
+ export const LLAMA_CPP_TOOL_CALL_PARSE_PATTERN =
104
+ /failed to parse tool call arguments as json|\[json\.exception\.parse_error\.101\]/i;
105
+
106
+ // Copilot routing flap: HTTP 400 `model_not_supported` (structural code on the
107
+ // error, also surfaced in text). Treated as transient — a retry usually lands
108
+ // on a backend that has the model.
109
+ const COPILOT_MODEL_NOT_SUPPORTED_PATTERN = /model_not_supported/i;
110
+ // Anthropic strict-tool grammar too large / schema too complex (400 invalid_request_error).
111
+ const GRAMMAR_TOO_LARGE_PATTERN = /compiled grammar/i;
112
+ const GRAMMAR_TOO_LARGE_DETAIL_PATTERN = /too large/i;
113
+ const SCHEMA_TOO_COMPLEX_PATTERN = /schema/i;
114
+ const SCHEMA_TOO_COMPLEX_DETAIL_PATTERN = /too complex/i;
115
+ const SCHEMA_COMPILE_PATTERN = /compil/i;
116
+ const INVALID_REQUEST_PATTERN = /invalid_request_error/i;
117
+ // Anthropic fast-mode unsupported: 400 rejecting `speed`, or 429 rate_limit_error
118
+ // because the account lacks the extra-usage entitlement fast mode requires.
119
+ const FAST_MODE_SPEED_PARAM_PATTERN = /\bspeed\b/i;
120
+ const FAST_MODE_NOT_SUPPORTED_PATTERN = /not support/i;
121
+ const FAST_MODE_RATE_LIMIT_PATTERN = /rate_limit_error/i;
122
+ const FAST_MODE_ENTITLEMENT_PATTERN = /fast mode/i;
123
+ // Definitive OAuth refresh failure — the stored grant/client is dead.
124
+ const OAUTH_DEFINITIVE_FAILURE_PATTERN =
125
+ /invalid_grant|invalid_token|unauthorized_client|\brevoked\b|refresh[\s_]?token.*expired/i;
126
+ const OAUTH_TRANSIENT_FAILURE_PATTERN =
127
+ /timeout|network|fetch failed|ECONN(?:REFUSED|RESET)|ETIMEDOUT|EAI_AGAIN|socket hang up|\b(?:408|425|429|5\d{2})\b|rate.?limit|too many requests|temporar|unavailable|forbidden|permission_denied|cloudflare|captcha/i;
128
+ const OAUTH_HTTP_AUTH_PATTERN = /\b401\b/;
129
+
130
+ function matchesGrammarTooLarge(message: string, errorStatus: number | undefined): boolean {
131
+ if (errorStatus !== 400) return false;
132
+ if (!INVALID_REQUEST_PATTERN.test(message)) return false;
133
+ const grammarTooLarge = GRAMMAR_TOO_LARGE_PATTERN.test(message) && GRAMMAR_TOO_LARGE_DETAIL_PATTERN.test(message);
134
+ const schemaTooComplex =
135
+ SCHEMA_TOO_COMPLEX_PATTERN.test(message) &&
136
+ SCHEMA_TOO_COMPLEX_DETAIL_PATTERN.test(message) &&
137
+ SCHEMA_COMPILE_PATTERN.test(message);
138
+ return grammarTooLarge || schemaTooComplex;
139
+ }
140
+
141
+ function matchesFastModeUnsupported(message: string, errorStatus: number | undefined): boolean {
142
+ if (errorStatus !== 400 && errorStatus !== 429) return false;
143
+ if (
144
+ errorStatus === 400 &&
145
+ INVALID_REQUEST_PATTERN.test(message) &&
146
+ FAST_MODE_SPEED_PARAM_PATTERN.test(message) &&
147
+ FAST_MODE_NOT_SUPPORTED_PATTERN.test(message)
148
+ ) {
149
+ return true;
150
+ }
151
+ return (
152
+ errorStatus === 429 && FAST_MODE_RATE_LIMIT_PATTERN.test(message) && FAST_MODE_ENTITLEMENT_PATTERN.test(message)
153
+ );
154
+ }
155
+
156
+ /** Whether an OAuth refresh error message means the grant is definitively dead. */
157
+ export function isOAuthExpiry(errorMessage: string): boolean {
158
+ if (OAUTH_DEFINITIVE_FAILURE_PATTERN.test(errorMessage)) return true;
159
+ return OAUTH_HTTP_AUTH_PATTERN.test(errorMessage) && !OAUTH_TRANSIENT_FAILURE_PATTERN.test(errorMessage);
160
+ }
161
+
162
+ const ERROR_KIND_LABELS: readonly [Flag, string][] = [
163
+ [Flag.ThinkingLoop, "thinking-loop"],
164
+ [Flag.Transient, "transient"],
165
+ [Flag.Timeout, "timeout"],
166
+ [Flag.UsageLimit, "usage-limit"],
167
+ [Flag.StaleResponsesItem, "stale-responses-item"],
168
+ [Flag.MalformedFunctionCall, "malformed-function-call"],
169
+ [Flag.ProviderFinishError, "provider-finish-error"],
170
+ [Flag.ContextOverflow, "context-overflow"],
171
+ [Flag.AuthFailed, "auth-failed"],
172
+ [Flag.SilentAbort, "silent-abort"],
173
+ [Flag.UserInterrupt, "user-interrupt"],
174
+ [Flag.Abort, "abort"],
175
+ ];
176
+
177
+ const STATUS_MESSAGE_PATTERNS = [
178
+ /\bstatus(?:_code)?[:=]\s*(\d{3})\b/i,
179
+ /\bstatus\s+(\d{3})\b/i,
180
+ /\bHTTP\s+(\d{3})\b/i,
181
+ /\b(?:error|failed)\s*[:=]?\s*(\d{3})\b/i,
182
+ /(?:^|\s)(\d{3})\s+(?:[A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)/,
183
+ ] as const;
184
+
185
+ export function create(...flags: number[]): number {
186
+ let bits = 0;
187
+ for (const f of flags) bits |= f;
188
+ return bits | Flag.Class;
189
+ }
190
+
191
+ export function is(id: number | undefined, flag: Flag): boolean {
192
+ return ((id ?? 0) & flag) !== 0;
193
+ }
194
+
195
+ export function retriable(id: number | undefined, opts?: { replayUnsafe?: boolean }): boolean {
196
+ if (is(id, Flag.MalformedFunctionCall)) return true;
197
+ if (opts?.replayUnsafe) return false;
198
+ return ((id ?? 0) & RETRIABLE_KINDS) !== 0;
199
+ }
200
+
201
+ function isClassified(id: number | undefined): boolean {
202
+ return ((id ?? 0) & Flag.Class) !== 0;
203
+ }
204
+
205
+ function statusFromId(id: number | undefined): number | undefined {
206
+ return id && !isClassified(id) ? id : undefined;
207
+ }
208
+
209
+ export function status(error: unknown): number | undefined {
210
+ return statusInternal(error, 0);
211
+ }
212
+
213
+ function statusInternal(error: unknown, depth: number): number | undefined {
214
+ if (depth > 2 || error === undefined || error === null) return undefined;
215
+ if (typeof error === "object") {
216
+ const errObj = error as Record<string, unknown>;
217
+
218
+ if (typeof errObj.status === "number" && errObj.status >= 100 && errObj.status <= 599) {
219
+ return errObj.status;
220
+ }
221
+ if (typeof errObj.statusCode === "number" && errObj.statusCode >= 100 && errObj.statusCode <= 599) {
222
+ return errObj.statusCode;
223
+ }
224
+ if (typeof errObj.response === "object" && errObj.response !== null) {
225
+ const resp = errObj.response as Record<string, unknown>;
226
+ if (typeof resp.status === "number" && resp.status >= 100 && resp.status <= 599) {
227
+ return resp.status;
228
+ }
229
+ }
230
+
231
+ if ("cause" in errObj) {
232
+ const nested = statusInternal(errObj.cause, depth + 1);
233
+ if (nested !== undefined) return nested;
234
+ }
235
+ }
236
+
237
+ if (error instanceof Error || (typeof error === "object" && error !== null && "message" in error)) {
238
+ const message = (error as { message: string }).message;
239
+ if (typeof message === "string") {
240
+ for (const pattern of STATUS_MESSAGE_PATTERNS) {
241
+ const match = pattern.exec(message);
242
+ if (match) {
243
+ const code = parseInt(match[1], 10);
244
+ if (code >= 100 && code <= 599) return code;
245
+ }
246
+ }
247
+ }
248
+ }
249
+ return undefined;
250
+ }
251
+
252
+ export function isStreamReadErrorText(text: string): boolean {
253
+ return STREAM_READ_ERROR_PATTERN.test(text);
254
+ }
255
+
256
+ function isTransientErrorText(text: string): boolean {
257
+ return (
258
+ isUnexpectedSocketCloseMessage(text) ||
259
+ isStreamReadErrorText(text) ||
260
+ (TRANSIENT_ENVELOPE_PATTERN.test(text) && TRANSIENT_ENVELOPE_BEFORE_START_PATTERN.test(text)) ||
261
+ TRANSIENT_TRANSPORT_PATTERN.test(text)
262
+ );
263
+ }
264
+
265
+ function isTimeoutText(text: string): boolean {
266
+ return TIMEOUT_PATTERN.test(text);
267
+ }
268
+
269
+ function isAuthFailureText(text: string): boolean {
270
+ return AUTH_FAILURE_PATTERN.test(text);
271
+ }
272
+
273
+ function isStaleResponsesText(text: string): boolean {
274
+ return (
275
+ STALE_RESPONSE_ITEM_PATTERNS[0].test(text) ||
276
+ (STALE_RESPONSE_ITEM_PATTERNS[1].test(text) && STALE_RESPONSE_ITEM_DETAIL_PATTERN.test(text))
277
+ );
278
+ }
279
+
280
+ function isMalformedFunctionCallText(text: string): boolean {
281
+ return MALFORMED_FUNCTION_CALL_PATTERN.test(text);
282
+ }
283
+
284
+ function isProviderFinishErrorText(text: string): boolean {
285
+ return PROVIDER_FINISH_ERROR_PATTERN.test(text);
286
+ }
287
+
288
+ function matchesOverflowText(text: string): boolean {
289
+ return OVERFLOW_PATTERNS.some(p => p.test(text)) || OVERFLOW_NO_BODY_PATTERN.test(text);
290
+ }
291
+
292
+ function classifyText(errorMessage: string | undefined, errorStatus: number | undefined, api?: Api): number {
293
+ let kinds = 0;
294
+ if (errorMessage) {
295
+ if (matchesOverflowText(errorMessage)) kinds |= Flag.ContextOverflow;
296
+ if (isMalformedFunctionCallText(errorMessage)) kinds |= Flag.MalformedFunctionCall;
297
+ if (isProviderFinishErrorText(errorMessage)) kinds |= Flag.ProviderFinishError;
298
+ if (isAuthFailureText(errorMessage)) kinds |= Flag.AuthFailed;
299
+
300
+ const statusClean = errorStatus ? errorStatus : (status({ message: errorMessage }) ?? undefined);
301
+ const cleanMessage = errorMessage;
302
+ const isOpaque = isOpaqueStatusBody(cleanMessage);
303
+
304
+ const isLimitStatus = statusClean === 429;
305
+ if (
306
+ matchesUsageLimitText(cleanMessage) ||
307
+ (isLimitStatus && (isOpaque || parseRateLimitReason(cleanMessage) === "QUOTA_EXHAUSTED"))
308
+ ) {
309
+ kinds |= Flag.UsageLimit;
310
+ }
311
+
312
+ if (isTimeoutText(errorMessage)) kinds |= Flag.Transient | Flag.Timeout;
313
+ else if (isTransientErrorText(errorMessage)) kinds |= Flag.Transient;
314
+ if ((api === "openai-responses" || api === "openai-codex-responses") && isStaleResponsesText(errorMessage)) {
315
+ kinds |= Flag.StaleResponsesItem;
316
+ }
317
+
318
+ // Copilot per-client routing flap is transient.
319
+ if (statusClean === 400 && COPILOT_MODEL_NOT_SUPPORTED_PATTERN.test(cleanMessage)) kinds |= Flag.Transient;
320
+ if (matchesGrammarTooLarge(cleanMessage, statusClean)) kinds |= Flag.Grammar;
321
+ if (matchesFastModeUnsupported(cleanMessage, statusClean)) kinds |= Flag.FastModeUnsupported;
322
+ }
323
+ if (kinds !== 0) return create(kinds);
324
+ const fallbackStatus = errorStatus ?? (errorMessage ? status({ message: errorMessage }) : undefined);
325
+ if (fallbackStatus === 401 || fallbackStatus === 403) return create(Flag.AuthFailed);
326
+ return fallbackStatus ?? 0;
327
+ }
328
+
329
+ export function classify(error: unknown, api?: Api): number {
330
+ let kinds = 0;
331
+ const seen = new Set<object>();
332
+ let link: unknown = error;
333
+ while (link !== undefined && link !== null) {
334
+ if (typeof link === "object") {
335
+ if (seen.has(link)) break;
336
+ seen.add(link);
337
+
338
+ if ("errorId" in link && typeof (link as { errorId: unknown }).errorId === "number") {
339
+ kinds |= (link as { errorId: number }).errorId & KIND_MASK;
340
+ }
341
+ }
342
+
343
+ if (link instanceof AnthropicConnectionTimeoutError) {
344
+ kinds |= Flag.Timeout | Flag.Transient;
345
+ } else if (link instanceof AnthropicConnectionError) {
346
+ kinds |= Flag.Transient;
347
+ } else if (
348
+ typeof link === "object" &&
349
+ "name" in link &&
350
+ (link as { name: string }).name === "CodexWebSocketTransportError"
351
+ ) {
352
+ kinds |= Flag.Transient;
353
+ } else if (
354
+ link instanceof Error &&
355
+ link.name === "CodexProviderStreamError" &&
356
+ "retryable" in link &&
357
+ (link as { retryable: unknown }).retryable === true
358
+ ) {
359
+ kinds |= Flag.Transient;
360
+ } else if (link instanceof ProviderHttpError) {
361
+ let linkKinds = 0;
362
+ const { status: codeStatus, code } = link;
363
+ if (code === "usage_limit_reached" || code === "insufficient_quota") {
364
+ linkKinds |= Flag.UsageLimit;
365
+ }
366
+ if (code === "overloaded_error" || code === "rate_limit_error") {
367
+ linkKinds |= Flag.Transient;
368
+ }
369
+ if (codeStatus === 401 || codeStatus === 403) {
370
+ linkKinds |= Flag.AuthFailed;
371
+ } else if (codeStatus === 429) {
372
+ if ((linkKinds & Flag.UsageLimit) === 0) {
373
+ linkKinds |= Flag.Transient;
374
+ }
375
+ } else if (codeStatus >= 500) {
376
+ linkKinds |= Flag.Transient;
377
+ }
378
+ kinds |= linkKinds;
379
+ }
380
+
381
+ let linkMessage: string | undefined;
382
+ if (link instanceof Error) {
383
+ linkMessage = link.message;
384
+ } else if (typeof link === "string") {
385
+ linkMessage = link;
386
+ } else if (
387
+ typeof link === "object" &&
388
+ "message" in link &&
389
+ typeof (link as { message: unknown }).message === "string"
390
+ ) {
391
+ linkMessage = (link as { message: string }).message;
392
+ }
393
+
394
+ const textId = classifyText(linkMessage, status(link), api);
395
+ kinds |= textId & KIND_MASK;
396
+
397
+ link = typeof link === "object" && "cause" in link ? (link as { cause: unknown }).cause : undefined;
398
+ }
399
+
400
+ return kinds !== 0 ? create(kinds) : (status(error) ?? 0);
401
+ }
402
+
403
+ /**
404
+ * Whether an error (or message string) classifies as an account usage/quota
405
+ * limit — the persistent, credential-rotation-worthy kind. This is the public
406
+ * accessor for {@link Flag.UsageLimit}; prefer it over re-running message
407
+ * regexes at call sites.
408
+ */
409
+ export function isUsageLimit(error: unknown, api?: Api): boolean {
410
+ return is(classify(error, api), Flag.UsageLimit);
411
+ }
412
+
413
+ /**
414
+ * Anthropic strict-tool grammar too large / schema too complex to compile.
415
+ * Accessor for {@link Flag.Grammar}.
416
+ */
417
+ export function isGrammarError(error: unknown): boolean {
418
+ return is(classify(error), Flag.Grammar);
419
+ }
420
+
421
+ /**
422
+ * Anthropic model/account does not support fast mode / the `speed` parameter.
423
+ * Accessor for {@link Flag.FastModeUnsupported}.
424
+ */
425
+ export function isFastModeUnsupported(error: unknown): boolean {
426
+ return is(classify(error), Flag.FastModeUnsupported);
427
+ }
428
+
429
+ /**
430
+ * GitHub Copilot 400 `model_not_supported` routing flap — transient. Reads the
431
+ * structural `code` (and falls back to {@link Flag.Transient} text classification).
432
+ */
433
+ export function isCopilotTransientModelError(error: unknown): boolean {
434
+ if (status(error) === 400 && error && typeof error === "object") {
435
+ const info = error as { code?: unknown; error?: { code?: unknown } | null };
436
+ const code = typeof info.code === "string" ? info.code : info.error?.code;
437
+ if (code === "model_not_supported") return true;
438
+ }
439
+ return false;
440
+ }
441
+
442
+ export function classifyMessage(message: {
443
+ api?: Api;
444
+ errorId?: number;
445
+ errorMessage?: string;
446
+ errorStatus?: number;
447
+ }): number {
448
+ const existingId = message.errorId;
449
+ const currentStatus = message.errorStatus ?? statusFromId(existingId);
450
+ const textId = classifyText(message.errorMessage, currentStatus, message.api);
451
+
452
+ let kinds = ((existingId ?? 0) | textId) & KIND_MASK;
453
+ if (message.errorMessage && LLAMA_CPP_TOOL_CALL_PARSE_PATTERN.test(message.errorMessage)) {
454
+ // Deterministic local-model tool-call JSON parse failure: HTTP 500 is misleading
455
+ // because the same prompt reproduces the same malformed output, so the agent-level
456
+ // auto-retry would loop. Strip Transient so the recovery message surfaces immediately.
457
+ kinds &= ~Flag.Transient;
458
+ }
459
+ const id = kinds !== 0 ? create(kinds) : (statusFromId(textId) ?? statusFromId(existingId) ?? currentStatus ?? 0);
460
+
461
+ message.errorId = id;
462
+ return id;
463
+ }
464
+
465
+ export function attach<E extends object>(error: E, id: number): E {
466
+ Object.defineProperty(error, "errorId", { value: id, enumerable: false, configurable: true });
467
+ return error;
468
+ }
469
+
470
+ export function isContextOverflow(message: AssistantMessage, contextWindow?: number): boolean {
471
+ if (is(message.errorId, Flag.ContextOverflow)) return true;
472
+ if (contextWindow) {
473
+ const inputTokens = message.usage.input + message.usage.cacheRead + message.usage.cacheWrite;
474
+ if (inputTokens > contextWindow) return true;
475
+ }
476
+ return message.stopReason === "error" && !!message.errorMessage && matchesOverflowText(message.errorMessage);
477
+ }
478
+
479
+ export function stringify(id: number | undefined): string {
480
+ if (!id) return "none";
481
+ if (!isClassified(id)) return `status:${id}`;
482
+ const labels = ERROR_KIND_LABELS.filter(([kind]) => is(id, kind)).map(([, label]) => label);
483
+ return labels.length > 0 ? labels.join("|") : `classified:0x${id.toString(16)}`;
484
+ }
485
+
486
+ const STREAM_PARSE_TRUNCATION_PATTERN =
487
+ /unterminated string|unexpected end of json input|unexpected end of data|unexpected eof|end of file|eof while parsing|truncated/i;
488
+ const STREAM_EVENT_ORDER_PATTERN = /stream event order|before message_start/i;
489
+
490
+ /** Transient stream corruption where the response was truncated mid-JSON. */
491
+ export function isTransientStreamParseError(error: unknown): boolean {
492
+ return error instanceof Error && STREAM_PARSE_TRUNCATION_PATTERN.test(error.message);
493
+ }
494
+
495
+ /** Any malformed stream-envelope error (prefix-tagged or out-of-order events). */
496
+ export function isStreamEnvelopeError(error: unknown): boolean {
497
+ return (
498
+ error instanceof Error &&
499
+ (error.message.includes(STREAM_ENVELOPE_ERROR_PREFIX) || STREAM_EVENT_ORDER_PATTERN.test(error.message))
500
+ );
501
+ }
502
+
503
+ /** Stream-envelope errors safe to retry against the provider (event ordering only). */
504
+ export function isRetryableStreamEnvelopeError(error: unknown): boolean {
505
+ return error instanceof Error && STREAM_EVENT_ORDER_PATTERN.test(error.message);
506
+ }
@@ -0,0 +1,45 @@
1
+ import {
2
+ type CapturedHttpErrorResponse,
3
+ finalizeErrorMessage,
4
+ type RawHttpRequestDump,
5
+ rewriteCopilotError,
6
+ } from "../utils/http-inspector";
7
+ import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
8
+ import { LLAMA_CPP_TOOL_CALL_PARSE_PATTERN } from "./flags";
9
+
10
+ function rewriteOllamaToolCallJsonError(message: string): string {
11
+ if (!LLAMA_CPP_TOOL_CALL_PARSE_PATTERN.test(message)) return message;
12
+ return `Local Ollama model emitted malformed tool-call JSON and llama.cpp rejected it (HTTP 500). This is usually a deterministic model-output failure after context degradation, not a transient server outage; reload the model or reduce context, then retry.\n${message}`;
13
+ }
14
+
15
+ /** Inputs that steer {@link formatMessage}'s formatter selection. */
16
+ export interface FormatMessageOptions {
17
+ /** When present, the raw request is dumped into the message for 400-class failures. */
18
+ rawRequestDump?: RawHttpRequestDump;
19
+ /** Captured non-2xx response body, appended to the message when available. */
20
+ capturedErrorResponse?: CapturedHttpErrorResponse;
21
+ /** Provider id; gates provider-specific user-facing rewrites. */
22
+ provider?: string;
23
+ }
24
+
25
+ /**
26
+ * Format a provider error into a user-facing message, unifying the three
27
+ * formatters: lightweight retry-after extraction, the raw-dump finalizer, and
28
+ * the copilot rewrite.
29
+ *
30
+ * Selection is driven by inputs, not a mode flag: a `rawRequestDump` routes
31
+ * through {@link finalizeErrorMessage} (retry-after + raw dump + captured body),
32
+ * otherwise the lightweight {@link formatErrorMessageWithRetryAfter} is used.
33
+ */
34
+ export async function formatMessage(error: unknown, opts: FormatMessageOptions = {}): Promise<string> {
35
+ let message = opts.rawRequestDump
36
+ ? await finalizeErrorMessage(error, opts.rawRequestDump, opts.capturedErrorResponse)
37
+ : formatErrorMessageWithRetryAfter(error);
38
+ if (opts.provider === "github-copilot") {
39
+ message = rewriteCopilotError(message, error, opts.provider);
40
+ }
41
+ if (opts.provider === "ollama") {
42
+ message = rewriteOllamaToolCallJsonError(message);
43
+ }
44
+ return message;
45
+ }
@@ -0,0 +1,96 @@
1
+ import { isUsageLimit } from "./flags";
2
+
3
+ /** A gateway-facing classification of an arbitrary upstream/internal error. */
4
+ export interface GatewayErrorClassification {
5
+ status: number;
6
+ type: string;
7
+ message: string;
8
+ }
9
+
10
+ /**
11
+ * Classify an upstream / gateway-internal error into a status code and a
12
+ * format-neutral type. The order is intentional:
13
+ *
14
+ * 1. Honour an explicit numeric `status` property on the thrown error.
15
+ * 2. Parse a status code embedded in the message string. Provider errors
16
+ * virtually always carry one (`Google API error (400): …`, `HTTP 429`,
17
+ * `status=503`) and the embedded value is authoritative.
18
+ * 3. Fall through to **word-boundaried** substring heuristics. The old
19
+ * `lower.includes("rate")` test famously matched `GenerateContentRequest`,
20
+ * surfacing every Google 400 as a 429 `rate_limit_error`. The patterns here
21
+ * all require boundaries so they don't collide with provider field names.
22
+ */
23
+ export function classifyGatewayError(err: unknown): GatewayErrorClassification {
24
+ const message = err instanceof Error ? err.message : String(err);
25
+
26
+ // 1. Custom pi-ai errors may attach a numeric `status` property.
27
+ const statusProp =
28
+ typeof err === "object" && err !== null && typeof (err as { status?: unknown }).status === "number"
29
+ ? (err as { status: number }).status | 0
30
+ : undefined;
31
+ if (statusProp !== undefined) return bucketStatus(statusProp, message);
32
+
33
+ if (err instanceof Error && err.name === "AbortError") return { status: 499, type: "request_aborted", message };
34
+
35
+ // 2. Status code embedded in the message. Requires a contextual keyword
36
+ // (`HTTP`, `API error`, `status`, …) or a leading `(NNN)` token so we
37
+ // don't trip on incidental three-digit numbers ("took 200ms").
38
+ const embedded = extractEmbeddedStatus(message);
39
+ if (embedded !== undefined) return bucketStatus(embedded, message);
40
+
41
+ // 3. Word-boundaried substring heuristics.
42
+ if (/\baborted\b|\babort signal\b/i.test(message)) {
43
+ return { status: 499, type: "request_aborted", message };
44
+ }
45
+ if (
46
+ // Match rate-limit phrasings before auth wording: some providers
47
+ // describe throttling as "unauthorized due to rate limit".
48
+ // Keep boundaries so this does not collide with
49
+ // `GenerateContentRequest`, `accelerate`, `iterate`, `deprecated`, etc.
50
+ /\brate[- _]?limit(?:s|ed|ing)?\b|\bquota(?:_exceeded| exceeded)?\b|\btoo[- _]many[- _]requests\b/i.test(
51
+ message,
52
+ ) ||
53
+ // Usage-limit phrasings emit no embedded status. Codex friendly text
54
+ // reads "You have hit your ChatGPT usage limit … Try again in ~158
55
+ // min."; the central usage-limit classifier already encodes every known
56
+ // provider variant, so reuse it instead of forking the regex. Without
57
+ // this branch the classifier falls through to the default
58
+ // 502/upstream_error, which is what callers saw when their account
59
+ // hit its cap.
60
+ isUsageLimit(message)
61
+ ) {
62
+ return { status: 429, type: "rate_limit_error", message };
63
+ }
64
+ if (/\b(?:unauthorized|forbidden)\b/i.test(message)) {
65
+ return { status: 401, type: "authentication_error", message };
66
+ }
67
+ if (/\b(?:unsupported|invalid_request|invalid request|bad request|malformed)\b/i.test(message)) {
68
+ return { status: 400, type: "invalid_request_error", message };
69
+ }
70
+ return { status: 502, type: "upstream_error", message };
71
+ }
72
+
73
+ function bucketStatus(status: number, message: string): GatewayErrorClassification {
74
+ if (status === 401 || status === 403) return { status, type: "authentication_error", message };
75
+ if (status === 429) return { status, type: "rate_limit_error", message };
76
+ if (status >= 400 && status < 500) return { status, type: "invalid_request_error", message };
77
+ if (status >= 500) return { status, type: "upstream_error", message };
78
+ return { status: 502, type: "upstream_error", message };
79
+ }
80
+
81
+ /**
82
+ * Pull a status code from common error-message shapes. Returns undefined when
83
+ * no contextual keyword is present, so we never guess at incidental numbers.
84
+ */
85
+ function extractEmbeddedStatus(message: string): number | undefined {
86
+ // `Google API error (400)`, `OpenAI API error (429): …`, `(503)`
87
+ // `HTTP 429: too many requests`
88
+ // `status: 503`, `status_code=429`, `status=400`
89
+ const re = /(?:\bHTTP\b|\bAPI error\b|\bstatus(?:[- _]?code)?\b)\s*[:=]?\s*\(?\s*(\d{3})\b|\((\d{3})\)/i;
90
+ const m = message.match(re);
91
+ if (!m) return undefined;
92
+ const raw = m[1] ?? m[2];
93
+ if (!raw) return undefined;
94
+ const code = Number.parseInt(raw, 10);
95
+ return Number.isFinite(code) && code >= 100 && code < 600 ? code : undefined;
96
+ }
@@ -0,0 +1,13 @@
1
+ export * from "./abort";
2
+ export * from "./auth";
3
+ export * from "./auth-classify";
4
+ export * from "./aws";
5
+ export * from "./classes";
6
+ export * from "./finalize";
7
+ export * from "./flags";
8
+ export * from "./format";
9
+ export * from "./gateway";
10
+ export * from "./oauth";
11
+ export * from "./provider";
12
+ export * from "./retryable";
13
+ export * from "./validation";