@linxiraos/pi-ai 1.0.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 (639) hide show
  1. package/CHANGELOG.md +5066 -0
  2. package/README.md +1195 -0
  3. package/dist/types/api-registry.d.ts +30 -0
  4. package/dist/types/auth/sqlite-credential-store.d.ts +117 -0
  5. package/dist/types/auth-broker/client.d.ts +93 -0
  6. package/dist/types/auth-broker/discover.d.ts +39 -0
  7. package/dist/types/auth-broker/index.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 +136 -0
  10. package/dist/types/auth-broker/server.d.ts +48 -0
  11. package/dist/types/auth-broker/snapshot-cache.d.ts +17 -0
  12. package/dist/types/auth-broker/types.d.ts +152 -0
  13. package/dist/types/auth-broker/wire-schema-resource.d.ts +53 -0
  14. package/dist/types/auth-broker/wire-schemas.d.ts +5 -0
  15. package/dist/types/auth-gateway/http.d.ts +56 -0
  16. package/dist/types/auth-gateway/index.d.ts +3 -0
  17. package/dist/types/auth-gateway/server.d.ts +36 -0
  18. package/dist/types/auth-gateway/types.d.ts +127 -0
  19. package/dist/types/auth-retry.d.ts +150 -0
  20. package/dist/types/auth-storage.d.ts +1258 -0
  21. package/dist/types/dialect/anthropic.d.ts +15 -0
  22. package/dist/types/dialect/catalog.d.ts +3 -0
  23. package/dist/types/dialect/coercion.d.ts +23 -0
  24. package/dist/types/dialect/deepseek.d.ts +14 -0
  25. package/dist/types/dialect/demotion.d.ts +30 -0
  26. package/dist/types/dialect/examples.d.ts +18 -0
  27. package/dist/types/dialect/factory.d.ts +3 -0
  28. package/dist/types/dialect/fenced-thinking.d.ts +53 -0
  29. package/dist/types/dialect/gemini.d.ts +17 -0
  30. package/dist/types/dialect/gemma.d.ts +15 -0
  31. package/dist/types/dialect/glm.d.ts +9 -0
  32. package/dist/types/dialect/harmony.d.ts +8 -0
  33. package/dist/types/dialect/hermes.d.ts +9 -0
  34. package/dist/types/dialect/history.d.ts +3 -0
  35. package/dist/types/dialect/index.d.ts +11 -0
  36. package/dist/types/dialect/inventory.d.ts +9 -0
  37. package/dist/types/dialect/kimi.d.ts +14 -0
  38. package/dist/types/dialect/minimax.d.ts +3 -0
  39. package/dist/types/dialect/owned-stream.d.ts +4 -0
  40. package/dist/types/dialect/qwen3.d.ts +9 -0
  41. package/dist/types/dialect/rendering.d.ts +54 -0
  42. package/dist/types/dialect/thinking.d.ts +6 -0
  43. package/dist/types/dialect/types.d.ts +68 -0
  44. package/dist/types/dialect/xml.d.ts +9 -0
  45. package/dist/types/error/abort.d.ts +14 -0
  46. package/dist/types/error/auth-classify.d.ts +20 -0
  47. package/dist/types/error/auth.d.ts +27 -0
  48. package/dist/types/error/aws.d.ts +27 -0
  49. package/dist/types/error/classes.d.ts +106 -0
  50. package/dist/types/error/finalize.d.ts +39 -0
  51. package/dist/types/error/flags.d.ts +94 -0
  52. package/dist/types/error/format.d.ts +20 -0
  53. package/dist/types/error/gateway.d.ts +20 -0
  54. package/dist/types/error/index.d.ts +14 -0
  55. package/dist/types/error/oauth.d.ts +43 -0
  56. package/dist/types/error/provider.d.ts +42 -0
  57. package/dist/types/error/rate-limit.d.ts +80 -0
  58. package/dist/types/error/retryable.d.ts +27 -0
  59. package/dist/types/error/validation.d.ts +32 -0
  60. package/dist/types/index.d.ts +51 -0
  61. package/dist/types/provider-details.d.ts +24 -0
  62. package/dist/types/providers/amazon-bedrock.d.ts +39 -0
  63. package/dist/types/providers/anthropic-client.d.ts +106 -0
  64. package/dist/types/providers/anthropic-messages-server-schema.d.ts +937 -0
  65. package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
  66. package/dist/types/providers/anthropic-wire.d.ts +345 -0
  67. package/dist/types/providers/anthropic.d.ts +261 -0
  68. package/dist/types/providers/aws-credentials.d.ts +48 -0
  69. package/dist/types/providers/aws-eventstream.d.ts +39 -0
  70. package/dist/types/providers/aws-sigv4.d.ts +55 -0
  71. package/dist/types/providers/azure-openai-responses.d.ts +16 -0
  72. package/dist/types/providers/bedrock-mantle.d.ts +13 -0
  73. package/dist/types/providers/claude-code-fingerprint.d.ts +19 -0
  74. package/dist/types/providers/cowork-fetch.d.ts +3 -0
  75. package/dist/types/providers/cursor/exec-modern.d.ts +98 -0
  76. package/dist/types/providers/cursor-pi-args.d.ts +105 -0
  77. package/dist/types/providers/cursor.d.ts +221 -0
  78. package/dist/types/providers/devin.d.ts +12 -0
  79. package/dist/types/providers/error-message.d.ts +25 -0
  80. package/dist/types/providers/github-copilot-headers.d.ts +40 -0
  81. package/dist/types/providers/gitlab-duo-workflow.d.ts +254 -0
  82. package/dist/types/providers/gitlab-duo.d.ts +27 -0
  83. package/dist/types/providers/google-auth.d.ts +24 -0
  84. package/dist/types/providers/google-gemini-cli.d.ts +120 -0
  85. package/dist/types/providers/google-shared.d.ts +203 -0
  86. package/dist/types/providers/google-types.d.ts +155 -0
  87. package/dist/types/providers/google-vertex.d.ts +7 -0
  88. package/dist/types/providers/google.d.ts +4 -0
  89. package/dist/types/providers/grammar.d.ts +1 -0
  90. package/dist/types/providers/kimi.d.ts +27 -0
  91. package/dist/types/providers/mock.d.ts +179 -0
  92. package/dist/types/providers/ollama.d.ts +8 -0
  93. package/dist/types/providers/openai-anthropic-shim.d.ts +35 -0
  94. package/dist/types/providers/openai-chat-server-schema.d.ts +1311 -0
  95. package/dist/types/providers/openai-chat-server.d.ts +16 -0
  96. package/dist/types/providers/openai-chat-wire.d.ts +669 -0
  97. package/dist/types/providers/openai-codex/request-transformer.d.ts +109 -0
  98. package/dist/types/providers/openai-codex/response-handler.d.ts +26 -0
  99. package/dist/types/providers/openai-codex-responses.d.ts +238 -0
  100. package/dist/types/providers/openai-completions.d.ts +48 -0
  101. package/dist/types/providers/openai-reasoning-fallback.d.ts +25 -0
  102. package/dist/types/providers/openai-responses-server-schema.d.ts +1314 -0
  103. package/dist/types/providers/openai-responses-server.d.ts +17 -0
  104. package/dist/types/providers/openai-responses-wire.d.ts +6099 -0
  105. package/dist/types/providers/openai-responses.d.ts +131 -0
  106. package/dist/types/providers/openai-shared.d.ts +624 -0
  107. package/dist/types/providers/pi-native-client.d.ts +13 -0
  108. package/dist/types/providers/pi-native-server.d.ts +69 -0
  109. package/dist/types/providers/register-builtins.d.ts +37 -0
  110. package/dist/types/providers/synthetic.d.ts +26 -0
  111. package/dist/types/providers/transform-messages.d.ts +32 -0
  112. package/dist/types/providers/vision-guard.d.ts +20 -0
  113. package/dist/types/registry/aiand.d.ts +7 -0
  114. package/dist/types/registry/aimlapi.d.ts +4 -0
  115. package/dist/types/registry/alibaba-coding-plan.d.ts +8 -0
  116. package/dist/types/registry/alibaba-token-plan.d.ts +18 -0
  117. package/dist/types/registry/amazon-bedrock.d.ts +5 -0
  118. package/dist/types/registry/anthropic.d.ts +10 -0
  119. package/dist/types/registry/api-key-login.d.ts +42 -0
  120. package/dist/types/registry/api-key-validation.d.ts +43 -0
  121. package/dist/types/registry/aws.d.ts +13 -0
  122. package/dist/types/registry/azure.d.ts +4 -0
  123. package/dist/types/registry/baseten.d.ts +7 -0
  124. package/dist/types/registry/bedrock-mantle.d.ts +22 -0
  125. package/dist/types/registry/cerebras.d.ts +7 -0
  126. package/dist/types/registry/cloudflare-ai-gateway.d.ts +13 -0
  127. package/dist/types/registry/coreweave.d.ts +7 -0
  128. package/dist/types/registry/cursor.d.ts +7 -0
  129. package/dist/types/registry/deepseek.d.ts +8 -0
  130. package/dist/types/registry/derived.d.ts +5 -0
  131. package/dist/types/registry/devin.d.ts +8 -0
  132. package/dist/types/registry/exa.d.ts +8 -0
  133. package/dist/types/registry/firepass.d.ts +16 -0
  134. package/dist/types/registry/fireworks.d.ts +7 -0
  135. package/dist/types/registry/github-copilot.d.ts +7 -0
  136. package/dist/types/registry/gitlab-duo-workflow.d.ts +10 -0
  137. package/dist/types/registry/gitlab-duo.d.ts +9 -0
  138. package/dist/types/registry/gmi-cloud.d.ts +7 -0
  139. package/dist/types/registry/google-antigravity.d.ts +9 -0
  140. package/dist/types/registry/google-gemini-cli.d.ts +9 -0
  141. package/dist/types/registry/google-vertex.d.ts +5 -0
  142. package/dist/types/registry/google.d.ts +4 -0
  143. package/dist/types/registry/groq.d.ts +4 -0
  144. package/dist/types/registry/huggingface.d.ts +7 -0
  145. package/dist/types/registry/index.d.ts +4 -0
  146. package/dist/types/registry/kagi.d.ts +14 -0
  147. package/dist/types/registry/kilo.d.ts +7 -0
  148. package/dist/types/registry/kimi-code.d.ts +7 -0
  149. package/dist/types/registry/litellm.d.ts +13 -0
  150. package/dist/types/registry/llama-cpp.d.ts +8 -0
  151. package/dist/types/registry/lm-studio.d.ts +8 -0
  152. package/dist/types/registry/meta.d.ts +7 -0
  153. package/dist/types/registry/minimax-code-cn.d.ts +6 -0
  154. package/dist/types/registry/minimax-code.d.ts +6 -0
  155. package/dist/types/registry/minimax.d.ts +4 -0
  156. package/dist/types/registry/mistral.d.ts +4 -0
  157. package/dist/types/registry/moonshot.d.ts +7 -0
  158. package/dist/types/registry/nanogpt.d.ts +7 -0
  159. package/dist/types/registry/novita.d.ts +6 -0
  160. package/dist/types/registry/nvidia.d.ts +7 -0
  161. package/dist/types/registry/oauth/anthropic-constants.d.ts +12 -0
  162. package/dist/types/registry/oauth/anthropic.d.ts +24 -0
  163. package/dist/types/registry/oauth/callback-server.d.ts +74 -0
  164. package/dist/types/registry/oauth/cursor.d.ts +16 -0
  165. package/dist/types/registry/oauth/device-code.d.ts +25 -0
  166. package/dist/types/registry/oauth/devin.d.ts +5 -0
  167. package/dist/types/registry/oauth/github-copilot.d.ts +30 -0
  168. package/dist/types/registry/oauth/gitlab-duo-workflow.d.ts +6 -0
  169. package/dist/types/registry/oauth/gitlab-duo.d.ts +3 -0
  170. package/dist/types/registry/oauth/google-antigravity.d.ts +11 -0
  171. package/dist/types/registry/oauth/google-gemini-cli.d.ts +22 -0
  172. package/dist/types/registry/oauth/google-oauth-shared.d.ts +56 -0
  173. package/dist/types/registry/oauth/index.d.ts +45 -0
  174. package/dist/types/registry/oauth/kimi.d.ts +21 -0
  175. package/dist/types/registry/oauth/minimax-code.d.ts +27 -0
  176. package/dist/types/registry/oauth/openai-codex.d.ts +33 -0
  177. package/dist/types/registry/oauth/opencode.d.ts +18 -0
  178. package/dist/types/registry/oauth/perplexity.d.ts +9 -0
  179. package/dist/types/registry/oauth/pkce.d.ts +8 -0
  180. package/dist/types/registry/oauth/types.d.ts +87 -0
  181. package/dist/types/registry/oauth/wafer.d.ts +1 -0
  182. package/dist/types/registry/oauth/xai-oauth.d.ts +46 -0
  183. package/dist/types/registry/oauth/xiaomi.d.ts +25 -0
  184. package/dist/types/registry/oauth/zai.d.ts +25 -0
  185. package/dist/types/registry/ollama-cloud.d.ts +7 -0
  186. package/dist/types/registry/ollama.d.ts +12 -0
  187. package/dist/types/registry/openai-codex-device.d.ts +8 -0
  188. package/dist/types/registry/openai-codex.d.ts +9 -0
  189. package/dist/types/registry/openai.d.ts +4 -0
  190. package/dist/types/registry/opencode-go.d.ts +6 -0
  191. package/dist/types/registry/opencode-zen.d.ts +6 -0
  192. package/dist/types/registry/openrouter.d.ts +13 -0
  193. package/dist/types/registry/parallel.d.ts +14 -0
  194. package/dist/types/registry/perplexity.d.ts +7 -0
  195. package/dist/types/registry/qianfan.d.ts +7 -0
  196. package/dist/types/registry/qwen-portal.d.ts +7 -0
  197. package/dist/types/registry/registry.d.ts +367 -0
  198. package/dist/types/registry/sakana.d.ts +7 -0
  199. package/dist/types/registry/siliconflow-cn.d.ts +7 -0
  200. package/dist/types/registry/siliconflow.d.ts +7 -0
  201. package/dist/types/registry/synthetic.d.ts +6 -0
  202. package/dist/types/registry/tavily.d.ts +14 -0
  203. package/dist/types/registry/together.d.ts +6 -0
  204. package/dist/types/registry/types.d.ts +75 -0
  205. package/dist/types/registry/umans.d.ts +7 -0
  206. package/dist/types/registry/venice.d.ts +13 -0
  207. package/dist/types/registry/vercel-ai-gateway.d.ts +7 -0
  208. package/dist/types/registry/vllm.d.ts +7 -0
  209. package/dist/types/registry/wafer-serverless.d.ts +6 -0
  210. package/dist/types/registry/xai-oauth.d.ts +7 -0
  211. package/dist/types/registry/xai.d.ts +7 -0
  212. package/dist/types/registry/xiaomi-token-plan-ams.d.ts +6 -0
  213. package/dist/types/registry/xiaomi-token-plan-cn.d.ts +6 -0
  214. package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +6 -0
  215. package/dist/types/registry/xiaomi.d.ts +6 -0
  216. package/dist/types/registry/zai.d.ts +15 -0
  217. package/dist/types/registry/zenmux.d.ts +7 -0
  218. package/dist/types/registry/zhipu-coding-plan.d.ts +7 -0
  219. package/dist/types/stream.d.ts +46 -0
  220. package/dist/types/types.d.ts +1064 -0
  221. package/dist/types/usage/alibaba-token-plan.d.ts +3 -0
  222. package/dist/types/usage/claude.d.ts +4 -0
  223. package/dist/types/usage/cursor.d.ts +4 -0
  224. package/dist/types/usage/gemini.d.ts +2 -0
  225. package/dist/types/usage/github-copilot.d.ts +7 -0
  226. package/dist/types/usage/google-antigravity.d.ts +15 -0
  227. package/dist/types/usage/kimi.d.ts +2 -0
  228. package/dist/types/usage/minimax-code.d.ts +3 -0
  229. package/dist/types/usage/ollama.d.ts +5 -0
  230. package/dist/types/usage/openai-codex-base-url.d.ts +18 -0
  231. package/dist/types/usage/openai-codex-reset.d.ts +88 -0
  232. package/dist/types/usage/openai-codex.d.ts +10 -0
  233. package/dist/types/usage/opencode-go.d.ts +2 -0
  234. package/dist/types/usage/shared.d.ts +1 -0
  235. package/dist/types/usage/synthetic.d.ts +2 -0
  236. package/dist/types/usage/umans.d.ts +2 -0
  237. package/dist/types/usage/xai-oauth.d.ts +12 -0
  238. package/dist/types/usage/zai.d.ts +3 -0
  239. package/dist/types/usage.d.ts +527 -0
  240. package/dist/types/utils/abort.d.ts +25 -0
  241. package/dist/types/utils/anthropic-auth.d.ts +35 -0
  242. package/dist/types/utils/aws-profile.d.ts +17 -0
  243. package/dist/types/utils/block-symbols.d.ts +62 -0
  244. package/dist/types/utils/deterministic-id.d.ts +16 -0
  245. package/dist/types/utils/empty-completion-retry.d.ts +21 -0
  246. package/dist/types/utils/event-stream.d.ts +39 -0
  247. package/dist/types/utils/foundry.d.ts +1 -0
  248. package/dist/types/utils/google-validation.d.ts +2 -0
  249. package/dist/types/utils/harmony-leak.d.ts +135 -0
  250. package/dist/types/utils/http-inspector.d.ts +49 -0
  251. package/dist/types/utils/idle-iterator.d.ts +149 -0
  252. package/dist/types/utils/leaked-thinking-stream.d.ts +33 -0
  253. package/dist/types/utils/openai-http.d.ts +48 -0
  254. package/dist/types/utils/openrouter-headers.d.ts +1 -0
  255. package/dist/types/utils/parse-bind.d.ts +23 -0
  256. package/dist/types/utils/provider-response.d.ts +3 -0
  257. package/dist/types/utils/proxy.d.ts +39 -0
  258. package/dist/types/utils/request-debug.d.ts +29 -0
  259. package/dist/types/utils/retry-after.d.ts +4 -0
  260. package/dist/types/utils/retry.d.ts +14 -0
  261. package/dist/types/utils/schema/adapt.d.ts +24 -0
  262. package/dist/types/utils/schema/compatibility.d.ts +30 -0
  263. package/dist/types/utils/schema/dereference.d.ts +11 -0
  264. package/dist/types/utils/schema/draft.d.ts +10 -0
  265. package/dist/types/utils/schema/equality.d.ts +4 -0
  266. package/dist/types/utils/schema/fields.d.ts +54 -0
  267. package/dist/types/utils/schema/index.d.ts +14 -0
  268. package/dist/types/utils/schema/json-schema-validator.d.ts +20 -0
  269. package/dist/types/utils/schema/meta-validator.d.ts +2 -0
  270. package/dist/types/utils/schema/normalize.d.ts +153 -0
  271. package/dist/types/utils/schema/spill.d.ts +8 -0
  272. package/dist/types/utils/schema/stamps.d.ts +17 -0
  273. package/dist/types/utils/schema/strict-tool-validation.d.ts +16 -0
  274. package/dist/types/utils/schema/types.d.ts +4 -0
  275. package/dist/types/utils/schema/typescript.d.ts +24 -0
  276. package/dist/types/utils/schema/wire.d.ts +52 -0
  277. package/dist/types/utils/sdk-stream-timeout.d.ts +33 -0
  278. package/dist/types/utils/sse-debug.d.ts +5 -0
  279. package/dist/types/utils/stream-markup-healing.d.ts +87 -0
  280. package/dist/types/utils/thinking-loop.d.ts +102 -0
  281. package/dist/types/utils/tool-call-loop-guard.d.ts +26 -0
  282. package/dist/types/utils/tool-choice.d.ts +52 -0
  283. package/dist/types/utils/validation.d.ts +28 -0
  284. package/dist/types/utils.d.ts +57 -0
  285. package/package.json +138 -0
  286. package/src/api-registry.ts +109 -0
  287. package/src/auth/sqlite-credential-store.ts +2066 -0
  288. package/src/auth-broker/client.ts +471 -0
  289. package/src/auth-broker/discover.ts +310 -0
  290. package/src/auth-broker/index.ts +7 -0
  291. package/src/auth-broker/refresher.ts +117 -0
  292. package/src/auth-broker/remote-store.ts +1332 -0
  293. package/src/auth-broker/server.ts +898 -0
  294. package/src/auth-broker/snapshot-cache.ts +200 -0
  295. package/src/auth-broker/types.ts +193 -0
  296. package/src/auth-broker/wire-schema-resource.ts +487 -0
  297. package/src/auth-broker/wire-schemas.ts +43 -0
  298. package/src/auth-gateway/http.ts +227 -0
  299. package/src/auth-gateway/index.ts +3 -0
  300. package/src/auth-gateway/server.ts +836 -0
  301. package/src/auth-gateway/types.ts +153 -0
  302. package/src/auth-retry.ts +401 -0
  303. package/src/auth-storage.ts +6540 -0
  304. package/src/dialect/anthropic.md +31 -0
  305. package/src/dialect/anthropic.ts +608 -0
  306. package/src/dialect/catalog.ts +29 -0
  307. package/src/dialect/coercion.ts +136 -0
  308. package/src/dialect/deepseek.md +24 -0
  309. package/src/dialect/deepseek.ts +609 -0
  310. package/src/dialect/demotion.ts +40 -0
  311. package/src/dialect/examples.ts +71 -0
  312. package/src/dialect/factory.ts +34 -0
  313. package/src/dialect/fenced-thinking.ts +184 -0
  314. package/src/dialect/gemini.md +44 -0
  315. package/src/dialect/gemini.ts +583 -0
  316. package/src/dialect/gemma.md +33 -0
  317. package/src/dialect/gemma.ts +387 -0
  318. package/src/dialect/glm.md +32 -0
  319. package/src/dialect/glm.ts +579 -0
  320. package/src/dialect/harmony.md +31 -0
  321. package/src/dialect/harmony.ts +345 -0
  322. package/src/dialect/hermes.md +25 -0
  323. package/src/dialect/hermes.ts +206 -0
  324. package/src/dialect/history.ts +81 -0
  325. package/src/dialect/index.ts +15 -0
  326. package/src/dialect/inventory.ts +30 -0
  327. package/src/dialect/kimi.md +24 -0
  328. package/src/dialect/kimi.ts +340 -0
  329. package/src/dialect/minimax.md +31 -0
  330. package/src/dialect/minimax.ts +95 -0
  331. package/src/dialect/owned-stream.ts +481 -0
  332. package/src/dialect/prompt-template.md +12 -0
  333. package/src/dialect/qwen3.md +28 -0
  334. package/src/dialect/qwen3.ts +240 -0
  335. package/src/dialect/rendering.ts +304 -0
  336. package/src/dialect/thinking.ts +292 -0
  337. package/src/dialect/types.ts +56 -0
  338. package/src/dialect/xml.md +22 -0
  339. package/src/dialect/xml.ts +90 -0
  340. package/src/error/abort.ts +18 -0
  341. package/src/error/auth-classify.ts +47 -0
  342. package/src/error/auth.ts +48 -0
  343. package/src/error/aws.ts +35 -0
  344. package/src/error/classes.ts +281 -0
  345. package/src/error/finalize.ts +69 -0
  346. package/src/error/flags.ts +602 -0
  347. package/src/error/format.ts +45 -0
  348. package/src/error/gateway.ts +96 -0
  349. package/src/error/index.ts +14 -0
  350. package/src/error/oauth.ts +58 -0
  351. package/src/error/provider.ts +63 -0
  352. package/src/error/rate-limit.ts +303 -0
  353. package/src/error/retryable.ts +70 -0
  354. package/src/error/validation.ts +44 -0
  355. package/src/index.ts +51 -0
  356. package/src/provider-details.ts +90 -0
  357. package/src/providers/amazon-bedrock.ts +1064 -0
  358. package/src/providers/anthropic-client.ts +317 -0
  359. package/src/providers/anthropic-messages-server-schema.ts +252 -0
  360. package/src/providers/anthropic-messages-server.ts +818 -0
  361. package/src/providers/anthropic-wire.ts +359 -0
  362. package/src/providers/anthropic.ts +4539 -0
  363. package/src/providers/aws-credentials.ts +772 -0
  364. package/src/providers/aws-eventstream.ts +181 -0
  365. package/src/providers/aws-sigv4.ts +218 -0
  366. package/src/providers/azure-openai-responses.ts +438 -0
  367. package/src/providers/bedrock-mantle.ts +110 -0
  368. package/src/providers/claude-code-fingerprint.ts +20 -0
  369. package/src/providers/cowork-fetch.ts +201 -0
  370. package/src/providers/cursor/exec-modern.ts +496 -0
  371. package/src/providers/cursor/proto/agent.proto +4533 -0
  372. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  373. package/src/providers/cursor/proto/buf.yaml +17 -0
  374. package/src/providers/cursor-pi-args.ts +165 -0
  375. package/src/providers/cursor.ts +4689 -0
  376. package/src/providers/devin/proto/buf/validate/validate.proto +468 -0
  377. package/src/providers/devin/proto/buf.gen.yaml +33 -0
  378. package/src/providers/devin/proto/buf.yaml +17 -0
  379. package/src/providers/devin/proto/cel/expr/checked.proto +103 -0
  380. package/src/providers/devin/proto/cel/expr/eval.proto +38 -0
  381. package/src/providers/devin/proto/cel/expr/explain.proto +15 -0
  382. package/src/providers/devin/proto/cel/expr/syntax.proto +113 -0
  383. package/src/providers/devin/proto/cel/expr/value.proto +41 -0
  384. package/src/providers/devin/proto/connectext/grpc/status/v1/status.proto +11 -0
  385. package/src/providers/devin/proto/errorspb/errors.proto +56 -0
  386. package/src/providers/devin/proto/errorspb/hintdetail.proto +7 -0
  387. package/src/providers/devin/proto/errorspb/markers.proto +10 -0
  388. package/src/providers/devin/proto/errorspb/tags.proto +12 -0
  389. package/src/providers/devin/proto/errorspb/testing.proto +6 -0
  390. package/src/providers/devin/proto/exa/analytics_pb/analytics.proto +188 -0
  391. package/src/providers/devin/proto/exa/api_server_pb/api_server.proto +2461 -0
  392. package/src/providers/devin/proto/exa/auth_pb/auth.proto +19 -0
  393. package/src/providers/devin/proto/exa/auto_cascade_common_pb/auto_cascade_common.proto +79 -0
  394. package/src/providers/devin/proto/exa/browser_preview_pb/browser_preview.proto +32 -0
  395. package/src/providers/devin/proto/exa/bug_checker_pb/bug_checker.proto +22 -0
  396. package/src/providers/devin/proto/exa/cascade_plugins_pb/cascade_plugins.proto +262 -0
  397. package/src/providers/devin/proto/exa/chat_client_server_pb/chat_client_server.proto +57 -0
  398. package/src/providers/devin/proto/exa/chat_pb/chat.proto +449 -0
  399. package/src/providers/devin/proto/exa/code_edit/code_edit_pb/code_edit.proto +186 -0
  400. package/src/providers/devin/proto/exa/codeium_common_pb/codeium_common.proto +4157 -0
  401. package/src/providers/devin/proto/exa/context_module_pb/context_module.proto +175 -0
  402. package/src/providers/devin/proto/exa/cortex_pb/cortex.proto +3268 -0
  403. package/src/providers/devin/proto/exa/dev_pb/dev.proto +26 -0
  404. package/src/providers/devin/proto/exa/diff_action_pb/diff_action.proto +75 -0
  405. package/src/providers/devin/proto/exa/eval/pr_eval/datasets_pb/datasets.proto +103 -0
  406. package/src/providers/devin/proto/exa/eval_pb/eval.proto +1315 -0
  407. package/src/providers/devin/proto/exa/extension_server_pb/extension_server.proto +556 -0
  408. package/src/providers/devin/proto/exa/file_system_provider_pb/file_system_provider.proto +75 -0
  409. package/src/providers/devin/proto/exa/index_pb/index.proto +461 -0
  410. package/src/providers/devin/proto/exa/knowledge_base_pb/knowledge_base.proto +144 -0
  411. package/src/providers/devin/proto/exa/language_server_pb/language_server.proto +2385 -0
  412. package/src/providers/devin/proto/exa/model_management_pb/model_management.proto +186 -0
  413. package/src/providers/devin/proto/exa/opensearch_clients_pb/opensearch_clients.proto +503 -0
  414. package/src/providers/devin/proto/exa/product_analytics_pb/product_analytics.proto +37 -0
  415. package/src/providers/devin/proto/exa/prompt_pb/prompt.proto +92 -0
  416. package/src/providers/devin/proto/exa/reactive_component_pb/reactive_component.proto +96 -0
  417. package/src/providers/devin/proto/exa/seat_management_pb/seat_management.proto +2680 -0
  418. package/src/providers/devin/proto/exa/tokenizer_pb/tokenizer.proto +37 -0
  419. package/src/providers/devin/proto/exa/trainer_pb/config.proto +647 -0
  420. package/src/providers/devin/proto/exa/tree_sitter/language_data_pb/language_data.proto +14 -0
  421. package/src/providers/devin/proto/exa/trust_pb/trust.proto +157 -0
  422. package/src/providers/devin/proto/exa/user_analytics_pb/user_analytics.proto +519 -0
  423. package/src/providers/devin/proto/google.golang.org/appengine/internal/base/api_base.proto +28 -0
  424. package/src/providers/devin/proto/google.golang.org/appengine/internal/datastore/datastore_v3.proto +484 -0
  425. package/src/providers/devin/proto/google.golang.org/appengine/internal/log/log_service.proto +136 -0
  426. package/src/providers/devin/proto/google.golang.org/appengine/internal/remote_api/remote_api.proto +42 -0
  427. package/src/providers/devin/proto/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto +61 -0
  428. package/src/providers/devin/proto/grpc/binlog/v1/binarylog.proto +84 -0
  429. package/src/providers/devin/proto/io/prometheus/client/metrics.proto +98 -0
  430. package/src/providers/devin.ts +679 -0
  431. package/src/providers/error-message.ts +23 -0
  432. package/src/providers/github-copilot-headers.ts +141 -0
  433. package/src/providers/gitlab-duo-workflow-chatml-note.md +1 -0
  434. package/src/providers/gitlab-duo-workflow.ts +3135 -0
  435. package/src/providers/gitlab-duo.ts +399 -0
  436. package/src/providers/google-auth.ts +330 -0
  437. package/src/providers/google-gemini-cli.ts +1370 -0
  438. package/src/providers/google-shared.ts +1122 -0
  439. package/src/providers/google-types.ts +180 -0
  440. package/src/providers/google-vertex.ts +135 -0
  441. package/src/providers/google.ts +47 -0
  442. package/src/providers/grammar.ts +70 -0
  443. package/src/providers/kimi.ts +51 -0
  444. package/src/providers/mock.ts +514 -0
  445. package/src/providers/ollama.ts +776 -0
  446. package/src/providers/openai-anthropic-shim.ts +166 -0
  447. package/src/providers/openai-chat-server-schema.ts +243 -0
  448. package/src/providers/openai-chat-server.ts +752 -0
  449. package/src/providers/openai-chat-wire.ts +859 -0
  450. package/src/providers/openai-codex/request-transformer.ts +491 -0
  451. package/src/providers/openai-codex/response-handler.ts +102 -0
  452. package/src/providers/openai-codex-responses.ts +4716 -0
  453. package/src/providers/openai-completions.ts +2389 -0
  454. package/src/providers/openai-reasoning-fallback.ts +269 -0
  455. package/src/providers/openai-responses-server-schema.ts +397 -0
  456. package/src/providers/openai-responses-server.ts +1466 -0
  457. package/src/providers/openai-responses-wire.ts +6416 -0
  458. package/src/providers/openai-responses.ts +1393 -0
  459. package/src/providers/openai-shared.ts +3500 -0
  460. package/src/providers/pi-native-client.ts +275 -0
  461. package/src/providers/pi-native-server.ts +245 -0
  462. package/src/providers/register-builtins.ts +503 -0
  463. package/src/providers/synthetic.ts +50 -0
  464. package/src/providers/transform-messages.ts +1083 -0
  465. package/src/providers/vision-guard.ts +54 -0
  466. package/src/registry/aiand.ts +22 -0
  467. package/src/registry/aimlapi.ts +6 -0
  468. package/src/registry/alibaba-coding-plan.ts +104 -0
  469. package/src/registry/alibaba-token-plan.ts +125 -0
  470. package/src/registry/amazon-bedrock.ts +22 -0
  471. package/src/registry/anthropic.ts +26 -0
  472. package/src/registry/api-key-login.ts +115 -0
  473. package/src/registry/api-key-validation.ts +145 -0
  474. package/src/registry/aws.ts +57 -0
  475. package/src/registry/azure.ts +6 -0
  476. package/src/registry/baseten.ts +22 -0
  477. package/src/registry/bedrock-mantle.ts +34 -0
  478. package/src/registry/cerebras.ts +23 -0
  479. package/src/registry/cloudflare-ai-gateway.ts +45 -0
  480. package/src/registry/coreweave.ts +40 -0
  481. package/src/registry/cursor.ts +20 -0
  482. package/src/registry/deepseek.ts +46 -0
  483. package/src/registry/derived.ts +9 -0
  484. package/src/registry/devin.ts +15 -0
  485. package/src/registry/exa.ts +19 -0
  486. package/src/registry/firepass.ts +32 -0
  487. package/src/registry/fireworks.ts +28 -0
  488. package/src/registry/github-copilot.ts +22 -0
  489. package/src/registry/gitlab-duo-workflow.ts +20 -0
  490. package/src/registry/gitlab-duo.ts +19 -0
  491. package/src/registry/gmi-cloud.ts +22 -0
  492. package/src/registry/google-antigravity.ts +22 -0
  493. package/src/registry/google-gemini-cli.ts +22 -0
  494. package/src/registry/google-vertex.ts +38 -0
  495. package/src/registry/google.ts +6 -0
  496. package/src/registry/groq.ts +6 -0
  497. package/src/registry/huggingface.ts +29 -0
  498. package/src/registry/index.ts +4 -0
  499. package/src/registry/kagi.ts +46 -0
  500. package/src/registry/kilo.ts +114 -0
  501. package/src/registry/kimi-code.ts +17 -0
  502. package/src/registry/litellm.ts +45 -0
  503. package/src/registry/llama-cpp.ts +35 -0
  504. package/src/registry/lm-studio.ts +31 -0
  505. package/src/registry/meta.ts +22 -0
  506. package/src/registry/minimax-code-cn.ts +12 -0
  507. package/src/registry/minimax-code.ts +12 -0
  508. package/src/registry/minimax.ts +6 -0
  509. package/src/registry/mistral.ts +6 -0
  510. package/src/registry/moonshot.ts +28 -0
  511. package/src/registry/nanogpt.ts +22 -0
  512. package/src/registry/novita.ts +25 -0
  513. package/src/registry/nvidia.ts +61 -0
  514. package/src/registry/oauth/anthropic-constants.ts +12 -0
  515. package/src/registry/oauth/anthropic.ts +346 -0
  516. package/src/registry/oauth/callback-server.ts +438 -0
  517. package/src/registry/oauth/cursor.ts +187 -0
  518. package/src/registry/oauth/device-code.ts +92 -0
  519. package/src/registry/oauth/devin.ts +124 -0
  520. package/src/registry/oauth/github-copilot.ts +369 -0
  521. package/src/registry/oauth/gitlab-duo-workflow.ts +146 -0
  522. package/src/registry/oauth/gitlab-duo.ts +222 -0
  523. package/src/registry/oauth/google-antigravity.ts +225 -0
  524. package/src/registry/oauth/google-gemini-cli.ts +297 -0
  525. package/src/registry/oauth/google-oauth-shared.ts +211 -0
  526. package/src/registry/oauth/index.ts +187 -0
  527. package/src/registry/oauth/kimi.ts +297 -0
  528. package/src/registry/oauth/minimax-code.ts +53 -0
  529. package/src/registry/oauth/oauth.html +317 -0
  530. package/src/registry/oauth/openai-codex.ts +384 -0
  531. package/src/registry/oauth/opencode.ts +50 -0
  532. package/src/registry/oauth/perplexity.ts +228 -0
  533. package/src/registry/oauth/pkce.ts +18 -0
  534. package/src/registry/oauth/types.ts +96 -0
  535. package/src/registry/oauth/wafer.ts +24 -0
  536. package/src/registry/oauth/xai-oauth.ts +559 -0
  537. package/src/registry/oauth/xiaomi.ts +211 -0
  538. package/src/registry/oauth/zai.ts +285 -0
  539. package/src/registry/ollama-cloud.ts +36 -0
  540. package/src/registry/ollama.ts +43 -0
  541. package/src/registry/openai-codex-device.ts +18 -0
  542. package/src/registry/openai-codex.ts +19 -0
  543. package/src/registry/openai.ts +6 -0
  544. package/src/registry/opencode-go.ts +12 -0
  545. package/src/registry/opencode-zen.ts +12 -0
  546. package/src/registry/openrouter.ts +28 -0
  547. package/src/registry/parallel.ts +45 -0
  548. package/src/registry/perplexity.ts +13 -0
  549. package/src/registry/qianfan.ts +27 -0
  550. package/src/registry/qwen-portal.ts +50 -0
  551. package/src/registry/registry.ts +182 -0
  552. package/src/registry/sakana.ts +22 -0
  553. package/src/registry/siliconflow-cn.ts +22 -0
  554. package/src/registry/siliconflow.ts +22 -0
  555. package/src/registry/synthetic.ts +21 -0
  556. package/src/registry/tavily.ts +45 -0
  557. package/src/registry/together.ts +22 -0
  558. package/src/registry/types.ts +86 -0
  559. package/src/registry/umans.ts +23 -0
  560. package/src/registry/venice.ts +33 -0
  561. package/src/registry/vercel-ai-gateway.ts +38 -0
  562. package/src/registry/vllm.ts +34 -0
  563. package/src/registry/wafer-serverless.ts +12 -0
  564. package/src/registry/xai-oauth.ts +17 -0
  565. package/src/registry/xai.ts +22 -0
  566. package/src/registry/xiaomi-token-plan-ams.ts +12 -0
  567. package/src/registry/xiaomi-token-plan-cn.ts +12 -0
  568. package/src/registry/xiaomi-token-plan-sgp.ts +12 -0
  569. package/src/registry/xiaomi.ts +12 -0
  570. package/src/registry/zai.ts +41 -0
  571. package/src/registry/zenmux.ts +22 -0
  572. package/src/registry/zhipu-coding-plan.ts +27 -0
  573. package/src/stream.ts +1944 -0
  574. package/src/types.ts +1243 -0
  575. package/src/usage/alibaba-token-plan.ts +230 -0
  576. package/src/usage/claude.ts +830 -0
  577. package/src/usage/cursor.ts +335 -0
  578. package/src/usage/gemini.ts +258 -0
  579. package/src/usage/github-copilot.ts +424 -0
  580. package/src/usage/google-antigravity.ts +497 -0
  581. package/src/usage/kimi.ts +277 -0
  582. package/src/usage/minimax-code.ts +291 -0
  583. package/src/usage/ollama.ts +41 -0
  584. package/src/usage/openai-codex-base-url.ts +35 -0
  585. package/src/usage/openai-codex-reset.ts +205 -0
  586. package/src/usage/openai-codex.ts +627 -0
  587. package/src/usage/opencode-go.ts +89 -0
  588. package/src/usage/shared.ts +10 -0
  589. package/src/usage/synthetic.ts +180 -0
  590. package/src/usage/umans.ts +192 -0
  591. package/src/usage/xai-oauth.ts +414 -0
  592. package/src/usage/zai.ts +370 -0
  593. package/src/usage.ts +411 -0
  594. package/src/utils/abort.ts +67 -0
  595. package/src/utils/anthropic-auth.ts +93 -0
  596. package/src/utils/aws-profile.ts +88 -0
  597. package/src/utils/block-symbols.ts +78 -0
  598. package/src/utils/deterministic-id.ts +20 -0
  599. package/src/utils/empty-completion-retry.ts +161 -0
  600. package/src/utils/event-stream.ts +202 -0
  601. package/src/utils/foundry.ts +8 -0
  602. package/src/utils/google-validation.ts +25 -0
  603. package/src/utils/harmony-leak.ts +500 -0
  604. package/src/utils/http-inspector.ts +196 -0
  605. package/src/utils/idle-iterator.ts +531 -0
  606. package/src/utils/leaked-thinking-stream.ts +483 -0
  607. package/src/utils/openai-http.ts +119 -0
  608. package/src/utils/openrouter-headers.ts +12 -0
  609. package/src/utils/parse-bind.ts +56 -0
  610. package/src/utils/provider-response.ts +30 -0
  611. package/src/utils/proxy.ts +314 -0
  612. package/src/utils/request-debug.ts +351 -0
  613. package/src/utils/retry-after.ts +121 -0
  614. package/src/utils/retry.ts +77 -0
  615. package/src/utils/schema/CONSTRAINTS.md +168 -0
  616. package/src/utils/schema/adapt.ts +36 -0
  617. package/src/utils/schema/compatibility.ts +435 -0
  618. package/src/utils/schema/dereference.ts +98 -0
  619. package/src/utils/schema/draft.ts +341 -0
  620. package/src/utils/schema/equality.ts +97 -0
  621. package/src/utils/schema/fields.ts +210 -0
  622. package/src/utils/schema/index.ts +14 -0
  623. package/src/utils/schema/json-schema-validator.ts +595 -0
  624. package/src/utils/schema/meta-validator.ts +167 -0
  625. package/src/utils/schema/normalize.ts +2314 -0
  626. package/src/utils/schema/spill.ts +43 -0
  627. package/src/utils/schema/stamps.ts +109 -0
  628. package/src/utils/schema/strict-tool-validation.ts +117 -0
  629. package/src/utils/schema/types.ts +10 -0
  630. package/src/utils/schema/typescript.ts +212 -0
  631. package/src/utils/schema/wire.ts +662 -0
  632. package/src/utils/sdk-stream-timeout.ts +43 -0
  633. package/src/utils/sse-debug.ts +18 -0
  634. package/src/utils/stream-markup-healing.ts +247 -0
  635. package/src/utils/thinking-loop.ts +552 -0
  636. package/src/utils/tool-call-loop-guard.ts +107 -0
  637. package/src/utils/tool-choice.ts +101 -0
  638. package/src/utils/validation.ts +1932 -0
  639. package/src/utils.ts +492 -0
@@ -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,14 @@
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 "./rate-limit";
13
+ export * from "./retryable";
14
+ export * from "./validation";
@@ -0,0 +1,58 @@
1
+ import { attach, create, Flag } from "./flags";
2
+
3
+ /**
4
+ * What stage of an OAuth / device-code login flow failed. Discriminates the
5
+ * single {@link OAuthError} class so login flows don't each mint a bespoke
6
+ * error type.
7
+ */
8
+ export type OAuthErrorKind =
9
+ /** Token-exchange / refresh / discovery HTTP response was non-2xx or unparseable. */
10
+ | "http"
11
+ /** Response body was missing required fields (token, account id, endpoints, …). */
12
+ | "validation"
13
+ /** Authorization-code → token exchange failed. */
14
+ | "token-exchange"
15
+ /** Refresh-token grant failed. */
16
+ | "token-refresh"
17
+ /** Device-code / authorization polling failed (server error, too many retries). */
18
+ | "polling"
19
+ /** The flow exceeded its deadline (device-code expiry, polling timeout). */
20
+ | "timeout"
21
+ /** Device authorization was denied or cancelled by the user/provider. */
22
+ | "device-auth"
23
+ /** Misconfiguration (bad redirect URI, missing projectId, callback bind, …). */
24
+ | "configuration"
25
+ /** Cloud project provisioning / onboarding (loadCodeAssist, onboardUser). */
26
+ | "provisioning"
27
+ /** OIDC / endpoint discovery failed. */
28
+ | "discovery";
29
+
30
+ export interface OAuthErrorOptions {
31
+ kind?: OAuthErrorKind;
32
+ provider?: string;
33
+ status?: number;
34
+ cause?: unknown;
35
+ }
36
+
37
+ /**
38
+ * A failure inside an interactive OAuth / device-code login flow. The `kind`
39
+ * pinpoints the stage. Timeout/polling are classified transient; everything
40
+ * else is a hard auth failure so the credential layer does not silently retry.
41
+ */
42
+ export class OAuthError extends Error {
43
+ readonly kind: OAuthErrorKind;
44
+ readonly provider: string | undefined;
45
+ readonly status: number | undefined;
46
+
47
+ constructor(message: string, options: OAuthErrorOptions = {}) {
48
+ super(message, options.cause === undefined ? undefined : { cause: options.cause });
49
+ this.name = "OAuthError";
50
+ this.kind = options.kind ?? "http";
51
+ this.provider = options.provider;
52
+ this.status = options.status;
53
+ attach(
54
+ this,
55
+ this.kind === "timeout" || this.kind === "polling" ? create(Flag.Transient) : create(Flag.AuthFailed),
56
+ );
57
+ }
58
+ }
@@ -0,0 +1,63 @@
1
+ import { ProviderHttpError } from "./classes";
2
+ import { attach, create, Flag } from "./flags";
3
+
4
+ /** Which part of a provider exchange produced a non-HTTP error. */
5
+ export type ProviderResponseErrorKind =
6
+ /** Stream closed before a terminal completion/response event. */
7
+ | "incomplete-stream"
8
+ /** Terminal event carried an error / unexpected stop reason. */
9
+ | "output"
10
+ /** Response body was empty/missing when content was required. */
11
+ | "empty-body"
12
+ /** Malformed wire envelope (unexpected message ordering / shape). */
13
+ | "envelope"
14
+ /** Content was blocked by a provider safety filter. */
15
+ | "content-blocked"
16
+ /** Runtime/namespace resolution or other provider-internal failure. */
17
+ | "runtime";
18
+
19
+ export interface ProviderResponseErrorOptions {
20
+ provider?: string;
21
+ kind?: ProviderResponseErrorKind;
22
+ cause?: unknown;
23
+ }
24
+
25
+ /**
26
+ * A non-HTTP provider failure: a truncated stream, an error stop reason, an
27
+ * empty body, a malformed envelope, or a runtime fault. For non-2xx HTTP
28
+ * responses use {@link ProviderHttpError} (or a provider subclass) instead.
29
+ */
30
+ export class ProviderResponseError extends Error {
31
+ readonly provider: string | undefined;
32
+ readonly kind: ProviderResponseErrorKind;
33
+
34
+ constructor(message: string, options: ProviderResponseErrorOptions = {}) {
35
+ super(message, options.cause === undefined ? undefined : { cause: options.cause });
36
+ this.name = "ProviderResponseError";
37
+ this.provider = options.provider;
38
+ this.kind = options.kind ?? "output";
39
+ // A safety filter block is terminal and intentionally non-retryable.
40
+ if (this.kind === "content-blocked") attach(this, create(Flag.ContentBlocked));
41
+ // An incomplete stream (connection dropped / truncated before any terminal
42
+ // event) or an empty body never produced any content — the request didn't
43
+ // complete, so it is safe to retry and eligible for model fallback. The
44
+ // retry layer's replay-unsafe guard still blocks a retry when partial tool
45
+ // output was already emitted.
46
+ else if (this.kind === "incomplete-stream" || this.kind === "empty-body") attach(this, create(Flag.Transient));
47
+ }
48
+ }
49
+
50
+ /** Non-2xx response from the Devin API. */
51
+ export class DevinApiError extends ProviderHttpError {
52
+ override readonly name = "DevinApiError";
53
+ }
54
+
55
+ /** Non-2xx response from the GitLab Duo direct-access API. */
56
+ export class GitLabDuoApiError extends ProviderHttpError {
57
+ override readonly name = "GitLabDuoApiError";
58
+ }
59
+
60
+ /** Non-2xx response from the GitLab Duo Workflow API. */
61
+ export class GitLabDuoWorkflowApiError extends ProviderHttpError {
62
+ override readonly name = "GitLabDuoWorkflowApiError";
63
+ }
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Rate limit reason classification and backoff calculation utilities.
3
+ * Ported from opencode-antigravity-auth plugin for consistency.
4
+ */
5
+
6
+ export type RateLimitReason =
7
+ | "QUOTA_EXHAUSTED"
8
+ | "RATE_LIMIT_EXCEEDED"
9
+ | "CONCURRENT_LIMIT"
10
+ | "MODEL_CAPACITY_EXHAUSTED"
11
+ | "SERVER_ERROR"
12
+ | "UNKNOWN";
13
+
14
+ const QUOTA_EXHAUSTED_BACKOFF_MS = 30 * 60 * 1000; // 30 min
15
+ const RATE_LIMIT_EXCEEDED_BACKOFF_MS = 30 * 1000; // 30s
16
+ const CONCURRENT_LIMIT_BACKOFF_MS = 5 * 1000; // 5s
17
+ const MODEL_CAPACITY_BASE_MS = 45 * 1000; // 45s base
18
+ const MODEL_CAPACITY_JITTER_MS = 30 * 1000; // ±15s
19
+ const SERVER_ERROR_BACKOFF_MS = 20 * 1000; // 20s
20
+
21
+ const ACCOUNT_RATE_LIMIT_PATTERN =
22
+ /\baccount(?:'s)?\b[^\n]{0,80}\brate.?limit\b|\brate.?limit\b[^\n]{0,80}\baccount\b/i;
23
+ const INSUFFICIENT_BALANCE_PATTERN = /insufficient.?balance/i;
24
+ const SPEND_LIMIT_PATTERN = /spend.?limit/i;
25
+ const SUBSCRIPTION_CAP_PATTERN =
26
+ /\b(?:subscription|plan|membership)\b[^\n]{0,80}\b(?:rate.?limits?|quota|cap)\b|\b(?:rate.?limits?|quota|cap)\b[^\n]{0,80}\b(?:subscription|plan|membership)\b/i;
27
+ const TRANSIENT_INTERVAL_RATE_LIMIT_PATTERN = /\bper\s+(?:second|minute)\b/i;
28
+
29
+ function matchesSubscriptionCapText(errorMessage: string): boolean {
30
+ return SUBSCRIPTION_CAP_PATTERN.test(errorMessage) && !TRANSIENT_INTERVAL_RATE_LIMIT_PATTERN.test(errorMessage);
31
+ }
32
+ const OPENROUTER_DAILY_FREE_LIMIT_PATTERN = /\bfree[-_ ]models[-_ ]per[-_ ]day\b/i;
33
+ // gRPC/Connect end-streams carry the status as its name (`resource_exhausted`),
34
+ // while HTTP bodies use the phrase ("resource exhausted"). Strip either form
35
+ // before classifying explicit details; an otherwise opaque status is transient
36
+ // model capacity, while quota/rate-limit/server wording remains authoritative.
37
+ const RESOURCE_EXHAUSTED_PATTERN = /resource.?exhausted/gi;
38
+ const CONCURRENT_LIMIT_PATTERN =
39
+ // Require an actual cap signal near "concurrent". "Too many concurrent
40
+ // requests" is itself a cap signal; bare feature rejections such as
41
+ // "concurrent invocation is not supported" remain excluded.
42
+ /\btoo many\s+concurren\w*\s+(?:requests?|invocations?)\b|\bconcurren\w*\b[^\n]{0,60}\b(?:limit|quota|exceed\w*|reach\w*)\b|\b(?:limit|quota|exceed\w*|reach\w*)\b[^\n]{0,60}\bconcurren\w*\b|\bconcurren[a-z]*[-_](?:[a-z]+[_-])*(?:limit|quota|exceed\w*|reach\w*)/i;
43
+ const ACCOUNT_SCOPED_403_PATTERN =
44
+ // The bare "limit will reset" / "will reset in" phrasing also appears on
45
+ // statusless per-minute transients ("Rate limit will reset in 30 seconds"),
46
+ // so gate the reset-window alternative on account-specific wording (Devin's
47
+ // "Your limit will reset in …"); the overall/account qualifiers arm above
48
+ // already covers the rest.
49
+ /\b(?:overall|account|organization|team|workspace)\b[^\n]{0,40}\b(?:message |request )?rate.?limit\b|\byour\b[^\n]{0,30}\b(?:limit )?will reset\b/i;
50
+ // Simplified Chinese account-quota exhaustion phrasing. Zhipu Coding Plan
51
+ // returns e.g. "429 已达到 5 小时的使用上限。您的限额将在 2026-08-06 20:06:00 重置。"
52
+ // (type=1308) when the 5h window is spent; other CN providers use 额度已用完 /
53
+ // 配额已耗尽 / 余额不足. These are persistent account-local caps that must
54
+ // rotate to a sibling credential, not transient rate limits, so they are
55
+ // matched before the RATE_LIMIT_EXCEEDED branch. The 上限 arm is anchored on
56
+ // the 使用 token: a rate/concurrency cap phrased as 每分钟请求数已达上限 /
57
+ // 并发请求数已达上限 / 速率达到上限 (no 使用) must NOT match, or it would burn a
58
+ // healthy sibling credential as a false quota. "速率限制" is absent for the
59
+ // same reason.
60
+ const CN_QUOTA_EXHAUSTED_PATTERN = /使用.{0,30}?上限|(?:额度|配额)已?(?:用|耗)(?:完|尽)|限额.{0,30}重置|余额不足/;
61
+ // Simplified Chinese rate/concurrency caps can contain both 使用 and 上限, but
62
+ // remain transient rather than account quota exhaustion.
63
+ const CN_TRANSIENT_CAP_PATTERN =
64
+ /速率.{0,30}上限|频率.{0,30}上限|每分钟.{0,30}上限|并发.{0,30}上限|使用.{0,30}(?:速率|频率|每分钟|并发).{0,30}上限/;
65
+ // Common Simplified Chinese throttle phrasing. Consulted by
66
+ // isOpaqueStatusBody so CN transients stay in the provider backoff lane instead
67
+ // of rotating through the opaque-429 fallback.
68
+ const CN_THROTTLE_PATTERN = /速率(?:限制|过快)|频率(?:过高|过快)|过于频繁|稍后[重再]试/;
69
+
70
+ /**
71
+ * Classify a rate-limit error message into a reason category.
72
+ * Priority order: explicit details in a resource-exhausted error > QUOTA
73
+ * (Antigravity "quota will reset") > CONCURRENT_LIMIT > MODEL_CAPACITY >
74
+ * QUOTA (account) > RATE_LIMIT > QUOTA (generic) > SERVER_ERROR > bare resource-exhausted > UNKNOWN.
75
+ *
76
+ * Bare "resource exhausted" / "resource_exhausted" maps to MODEL_CAPACITY (transient, short wait).
77
+ * Explicit details such as "quota exceeded" retain their normal classification.
78
+ */
79
+ export function parseRateLimitReason(errorMessage: string): RateLimitReason {
80
+ const lowerWithStatus = errorMessage.toLowerCase();
81
+ const lower = lowerWithStatus.replace(RESOURCE_EXHAUSTED_PATTERN, "");
82
+ const hasResourceExhaustedStatus = lower !== lowerWithStatus;
83
+
84
+ // Antigravity / Cloud Code Assist surface multi-hour daily-quota exhaustion as
85
+ // "You have exhausted your capacity on this model. Your quota will reset after …".
86
+ // The literal "capacity" used to pre-empt the QUOTA branch even though "quota
87
+ // will reset" is the long-wait signal — short-circuit here before the
88
+ // MODEL_CAPACITY fallthrough so credential rotation (not 60s backoff) kicks in.
89
+ if (lower.includes("quota will reset") || lower.includes("exhausted your capacity")) {
90
+ return "QUOTA_EXHAUSTED";
91
+ }
92
+
93
+ // Simplified Chinese quota-exhaustion phrasing (Zhipu Coding Plan and other
94
+ // CN providers). Must precede the MODEL_CAPACITY / RATE_LIMIT branches so an
95
+ // account-local cap rotates instead of backing off as a transient.
96
+ if (CN_QUOTA_EXHAUSTED_PATTERN.test(errorMessage) && !CN_TRANSIENT_CAP_PATTERN.test(errorMessage)) {
97
+ return "QUOTA_EXHAUSTED";
98
+ }
99
+
100
+ if (CONCURRENT_LIMIT_PATTERN.test(errorMessage)) {
101
+ return "CONCURRENT_LIMIT";
102
+ }
103
+
104
+ if (lower.includes("capacity") || lower.includes("overloaded") || lower.includes("529") || lower.includes("503")) {
105
+ return "MODEL_CAPACITY_EXHAUSTED";
106
+ }
107
+
108
+ if (ACCOUNT_RATE_LIMIT_PATTERN.test(errorMessage)) {
109
+ return "QUOTA_EXHAUSTED";
110
+ }
111
+
112
+ if (SPEND_LIMIT_PATTERN.test(errorMessage)) {
113
+ return "QUOTA_EXHAUSTED";
114
+ }
115
+
116
+ if (matchesSubscriptionCapText(errorMessage)) {
117
+ return "QUOTA_EXHAUSTED";
118
+ }
119
+
120
+ if (OPENROUTER_DAILY_FREE_LIMIT_PATTERN.test(errorMessage)) {
121
+ return "QUOTA_EXHAUSTED";
122
+ }
123
+
124
+ if (
125
+ lower.includes("per minute") ||
126
+ lower.includes("rate limit") ||
127
+ lower.includes("too many requests") ||
128
+ lower.includes("presque")
129
+ ) {
130
+ return "RATE_LIMIT_EXCEEDED";
131
+ }
132
+
133
+ if (
134
+ lower.includes("exhausted") ||
135
+ lower.includes("quota") ||
136
+ lower.includes("usage limit") ||
137
+ // xAI SuperGrok: HTTP 403 "run out of credits" / spending-limit is an
138
+ // account-local cap — rotate, don't treat as auth failure.
139
+ lower.includes("run out of credits") ||
140
+ lower.includes("out of credits") ||
141
+ lower.includes("spending-limit") ||
142
+ lower.includes("spending limit") ||
143
+ INSUFFICIENT_BALANCE_PATTERN.test(errorMessage)
144
+ ) {
145
+ return "QUOTA_EXHAUSTED";
146
+ }
147
+
148
+ if (lower.includes("500") || lower.includes("internal error") || lower.includes("internal server error")) {
149
+ return "SERVER_ERROR";
150
+ }
151
+
152
+ if (hasResourceExhaustedStatus) {
153
+ return "MODEL_CAPACITY_EXHAUSTED";
154
+ }
155
+
156
+ return "UNKNOWN";
157
+ }
158
+
159
+ /**
160
+ * Calculate backoff delay in ms for a given rate limit reason.
161
+ * MODEL_CAPACITY gets jitter to prevent thundering herd.
162
+ */
163
+ export function calculateRateLimitBackoffMs(reason: RateLimitReason): number {
164
+ switch (reason) {
165
+ case "QUOTA_EXHAUSTED":
166
+ return QUOTA_EXHAUSTED_BACKOFF_MS;
167
+ case "RATE_LIMIT_EXCEEDED":
168
+ return RATE_LIMIT_EXCEEDED_BACKOFF_MS;
169
+ case "CONCURRENT_LIMIT":
170
+ return CONCURRENT_LIMIT_BACKOFF_MS;
171
+ case "MODEL_CAPACITY_EXHAUSTED":
172
+ return MODEL_CAPACITY_BASE_MS + Math.random() * MODEL_CAPACITY_JITTER_MS;
173
+ case "SERVER_ERROR":
174
+ return SERVER_ERROR_BACKOFF_MS;
175
+ default:
176
+ return QUOTA_EXHAUSTED_BACKOFF_MS; // conservative default
177
+ }
178
+ }
179
+
180
+ /** Detect usage/quota limit errors in error messages (persistent, requires credential switch). */
181
+ const USAGE_LIMIT_PATTERN =
182
+ /usage.?limit|usage_limit_reached|usage_not_included|limit_reached|quota.?(?:exceeded|reached|insufficient)|额度不足|额度耗尽|resource.?exhausted|exhausted your capacity|quota will reset|insufficient.?(?:balance|quota)|balance.?exhausted|run out of credits|out of credits|spending[- _]?limit|personal-team-blocked/i;
183
+
184
+ /**
185
+ * HTTP status codes that, absent richer body classification, represent an
186
+ * account-local usage cap rather than a bad credential or a transient blip.
187
+ * HTTP 402 Payment Required is categorically an account-billing cap (xAI
188
+ * Grok Build "usage balance exhausted", DeepSeek "Insufficient Balance",
189
+ * OpenRouter credit exhaustion) — never a transient blip or bad credential.
190
+ * Always combine with {@link isUsageLimitOutcome} when a message is available
191
+ * — a 429 carrying transient rate-limit wording is NOT a usage cap.
192
+ */
193
+ export function isUsageLimitStatus(status: number | undefined): boolean {
194
+ return status === 429 || status === 402;
195
+ }
196
+
197
+ /**
198
+ * Returns true for failures that should burn one credential and rotate to a
199
+ * sibling account. Decision tree:
200
+ *
201
+ * 1. Body matches {@link isUsageLimitError} (Codex `usage_limit_reached`,
202
+ * Anthropic account rate-limit, Google `resource_exhausted`, OpenAI
203
+ * `insufficient_quota`, …) → rotate.
204
+ * 2. Status is not a usage-limit status (429/402) → backoff (caller's domain).
205
+ * 3. Body is absent or {@link isOpaqueStatusBody opaque} (just the status,
206
+ * empty JSON, HTTP framing only) → rotate conservatively: the server
207
+ * gave us nothing else to go on.
208
+ * 4. Body has content → defer to {@link parseRateLimitReason}. `QUOTA_EXHAUSTED`
209
+ * rotates; for the categorical 402 billing cap a `CONCURRENT_LIMIT` body
210
+ * also rotates (the cap is concurrent-worded but the status is still an
211
+ * exhausted billing cap). `RATE_LIMIT_EXCEEDED` (`Too many requests`,
212
+ * per-minute caps), `MODEL_CAPACITY_EXHAUSTED` (`Service overloaded`),
213
+ * `SERVER_ERROR`, and `UNKNOWN` (`Please retry in 5s`) stay in the
214
+ * provider's own backoff layer so transient 429s don't burn sibling
215
+ * credentials.
216
+ */
217
+ export function isUsageLimitOutcome(status: number | undefined, message: string | undefined): boolean {
218
+ // Concurrency caps are shed-and-backoff, not credential-rotatable — but only
219
+ // for quota-worded 429 / other statuses. HTTP 402 is categorically an
220
+ // account-billing cap, so a 402 whose body happens to mention concurrency is
221
+ // still an exhausted billing cap and must rotate; gate the exclusion on the
222
+ // status not being that categorical billing cap.
223
+ const isBillingCapStatus = status === 402;
224
+ if (isConcurrencyCapExclusion(status, message)) return false;
225
+ if (message && matchesUsageLimitText(message)) return true;
226
+ // A 403 is normally an auth failure, but several providers deliver an
227
+ // account-scoped cap with it (Devin/Codeium Connect `permission_denied`,
228
+ // GitHub Copilot). Devin's end-of-stream Connect trailer carries no HTTP
229
+ // status at all (it arrives as a `permission_denied` ValidationError), so
230
+ // accept an undefined status too — but only when the body names a cap that
231
+ // resets, never on a bare 403, which stays an auth failure.
232
+ if ((status === 403 || status === undefined) && message && isAccountScopedCapText(message)) return true;
233
+ if (!isUsageLimitStatus(status)) return false;
234
+ if (!message || isOpaqueStatusBody(message)) return true;
235
+ const reason = parseRateLimitReason(message);
236
+ // For the categorical 402 billing cap a concurrency-worded body is still an
237
+ // exhausted cap (rotate); for 429 / other only QUOTA_EXHAUSTED rotates.
238
+ return reason === "QUOTA_EXHAUSTED" || (isBillingCapStatus && reason === "CONCURRENT_LIMIT");
239
+ }
240
+
241
+ /**
242
+ * A usage-limit status body is opaque when it carries no signal beyond the
243
+ * status itself — empty, whitespace-only, the status digits with HTTP/JSON
244
+ * framing, or generic punctuation. Anything else (retry hints, capacity
245
+ * wording, error descriptions) is informative enough to defer to the
246
+ * classifier.
247
+ */
248
+ export function isOpaqueStatusBody(message: string): boolean {
249
+ const cleaned = message
250
+ .replace(/\b(?:429|402)\b/g, "")
251
+ .replace(/\b(?:http|https|status|error|code|response|message)\b/gi, "");
252
+ // A body is informative when the text classifier can act on it. Any Latin
253
+ // word or Simplified Chinese phrasing the classifier recognizes (quota
254
+ // exhaustion or a throttle) defers to parseRateLimitReason; a body that
255
+ // is only status digits / HTTP framing is opaque and rotates conservatively.
256
+ // A Han-only body the classifier cannot interpret (e.g. Japanese Kanji
257
+ // quota text, since Japanese is out of scope) must stay opaque so the
258
+ // opaque-429 fallback still rotates. This keeps the exception scoped to
259
+ // text we actually classify, rather than to any Han ideograph.
260
+ return (
261
+ !/[a-z\d]{3,}/i.test(cleaned) &&
262
+ !CN_QUOTA_EXHAUSTED_PATTERN.test(cleaned) &&
263
+ !CN_TRANSIENT_CAP_PATTERN.test(cleaned) &&
264
+ !CN_THROTTLE_PATTERN.test(cleaned)
265
+ );
266
+ }
267
+
268
+ /**
269
+ * Internal text matcher for usage/quota-limit phrasing. NOT part of the public
270
+ * API — callers classify through {@link import("./flags").isUsageLimit} (the
271
+ * flag accessor). `flags.ts` consumes this to populate `Flag.UsageLimit`, and
272
+ * {@link isUsageLimitOutcome} uses it for the account-rotation decision.
273
+ */
274
+ export function matchesUsageLimitText(errorMessage: string): boolean {
275
+ return (
276
+ USAGE_LIMIT_PATTERN.test(errorMessage) ||
277
+ (CN_QUOTA_EXHAUSTED_PATTERN.test(errorMessage) && !CN_TRANSIENT_CAP_PATTERN.test(errorMessage)) ||
278
+ SPEND_LIMIT_PATTERN.test(errorMessage) ||
279
+ ACCOUNT_RATE_LIMIT_PATTERN.test(errorMessage) ||
280
+ matchesSubscriptionCapText(errorMessage) ||
281
+ OPENROUTER_DAILY_FREE_LIMIT_PATTERN.test(errorMessage)
282
+ );
283
+ }
284
+
285
+ /**
286
+ * Account-scoped cap phrasing delivered on a 403 (or a statusless Connect
287
+ * trailer): "Reached overall message rate limit", "Your limit will reset in …".
288
+ * Kept separate from {@link matchesUsageLimitText} because the bare wording is
289
+ * ambiguous without the 403 / statusless-account context; consumed by both
290
+ * {@link isUsageLimitOutcome} (rotation decision) and `flags.ts` (Flag.UsageLimit).
291
+ */
292
+ export function isAccountScopedCapText(message: string): boolean {
293
+ return ACCOUNT_SCOPED_403_PATTERN.test(message);
294
+ }
295
+
296
+ /**
297
+ * A concurrency cap on a non-billing status is shed-and-backoff, not
298
+ * credential-rotatable. This mirrors the exclusion in {@link isUsageLimitOutcome}
299
+ * for the 403 auth-retry entry points. A 402 remains a categorical billing cap.
300
+ */
301
+ export function isConcurrencyCapExclusion(status: number | undefined, message: string | undefined): boolean {
302
+ return message !== undefined && parseRateLimitReason(message) === "CONCURRENT_LIMIT" && status !== 402;
303
+ }
@@ -0,0 +1,70 @@
1
+ import { isRetryableError, isUnexpectedSocketCloseMessage } from "@linxiraos/pi-utils";
2
+ import {
3
+ isRetryableStreamEnvelopeError,
4
+ isTransientStreamParseError,
5
+ isUsageLimit,
6
+ status,
7
+ TRANSIENT_TRANSPORT_PATTERN,
8
+ } from "./flags";
9
+
10
+ /**
11
+ * Whether a numeric HTTP status is in the canonical transient/retryable set:
12
+ * 408 (Request Timeout), 429 (Too Many Requests), and any 5xx.
13
+ *
14
+ * This is a pure predicate over a status code already in hand — distinct from
15
+ * {@link classify}, which inspects a whole error (including message text) and
16
+ * may match more. Use this when you only have a `status: number`.
17
+ */
18
+ export function isTransientStatus(status: number | undefined): boolean {
19
+ return status !== undefined && (status === 408 || status === 429 || status >= 500);
20
+ }
21
+
22
+ // Provider-stream transient phrasings not covered by the shared
23
+ // TRANSIENT_TRANSPORT_PATTERN (TLS record corruption, HTTP/2 peer stream
24
+ // errors, upstream code 1302). The shared pattern already covers rate-limit /
25
+ // overloaded / 5xx / timeout / first-event wording.
26
+ const PROVIDER_TRANSIENT_EXTRA_PATTERN = /bad record mac|stream error.*received from peer|1302/i;
27
+
28
+ function isTransientTransportMessage(message: string): boolean {
29
+ return message.includes("tls: bad record mac") || message.includes("type=server_error");
30
+ }
31
+
32
+ /** Hook for provider-specific transient detection that the error module must not import directly. */
33
+ export interface ProviderRetryableHooks {
34
+ /** Provider id of the failing request, used to gate provider-specific checks. */
35
+ provider?: string;
36
+ /** Provider-specific transient predicate (e.g. Copilot model-availability 400s). */
37
+ isProviderTransient?: (error: Error) => boolean;
38
+ }
39
+
40
+ /**
41
+ * Whether a provider stream error should be retried against the same credential.
42
+ *
43
+ * Account-level usage/quota limits are deliberately treated as **non**-retryable
44
+ * here — they are owned by the credential-rotation layer (auth-gateway /
45
+ * `streamSimple` a/b/c policy), not this seconds-scale provider backoff.
46
+ *
47
+ * Provider-specific transient cases are injected via {@link ProviderRetryableHooks}
48
+ * so this stays free of provider imports.
49
+ */
50
+ export function isProviderRetryableError(error: unknown, hooks: ProviderRetryableHooks = {}): boolean {
51
+ if (!(error instanceof Error)) return false;
52
+ if (hooks.isProviderTransient?.(error)) return true;
53
+ if (isUsageLimit(error)) return false;
54
+ const httpStatus = status(error);
55
+ if (httpStatus !== undefined && httpStatus >= 400 && httpStatus < 500 && httpStatus !== 408 && httpStatus !== 429) {
56
+ return false;
57
+ }
58
+ const msg = error.message.toLowerCase();
59
+ if (
60
+ isUnexpectedSocketCloseMessage(msg) ||
61
+ isTransientTransportMessage(msg) ||
62
+ TRANSIENT_TRANSPORT_PATTERN.test(msg) ||
63
+ PROVIDER_TRANSIENT_EXTRA_PATTERN.test(msg) ||
64
+ isTransientStreamParseError(error) ||
65
+ isRetryableStreamEnvelopeError(error)
66
+ ) {
67
+ return true;
68
+ }
69
+ return isRetryableError(error);
70
+ }
@@ -0,0 +1,44 @@
1
+ import { attach, create, Flag } from "./flags";
2
+
3
+ /**
4
+ * Caller-supplied input failed validation before/while building a provider
5
+ * request: bad request body, malformed tool arguments, unsupported content
6
+ * type, a schema that cannot be normalized, an unknown tool, etc.
7
+ *
8
+ * This is a programmer/config/contract error, not a transient provider fault —
9
+ * it is never retried.
10
+ */
11
+ export class ValidationError extends Error {
12
+ constructor(message: string, options?: { cause?: unknown }) {
13
+ super(message, options?.cause === undefined ? undefined : { cause: options.cause });
14
+ this.name = "ValidationError";
15
+ }
16
+ }
17
+
18
+ /** A referenced tool was not found in the active tool set. */
19
+ export class ToolNotFoundError extends ValidationError {
20
+ constructor(toolName: string) {
21
+ super(`Tool "${toolName}" not found`);
22
+ this.name = "ToolNotFoundError";
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Provider/auth configuration was missing or malformed (env var pointing at a
28
+ * missing file, missing projectId, bad bind string, mTLS half-configured, …).
29
+ */
30
+ export class ConfigurationError extends Error {
31
+ constructor(message: string, options?: { cause?: unknown }) {
32
+ super(message, options?.cause === undefined ? undefined : { cause: options.cause });
33
+ this.name = "ConfigurationError";
34
+ }
35
+ }
36
+
37
+ /** A request was abandoned because it exceeded a stream/idle/first-event deadline. */
38
+ export class StreamTimeoutError extends Error {
39
+ constructor(message = "Request timed out.", options?: { cause?: unknown }) {
40
+ super(message, options?.cause === undefined ? undefined : { cause: options.cause });
41
+ this.name = "StreamTimeoutError";
42
+ attach(this, create(Flag.Transient, Flag.Timeout));
43
+ }
44
+ }