@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,211 @@
1
+ /**
2
+ * Xiaomi MiMo login flow.
3
+ *
4
+ * Xiaomi MiMo provides OpenAI-compatible models via
5
+ * https://api.xiaomimimo.com/v1.
6
+ *
7
+ * Standard Xiaomi login opens the pay-as-you-go API key console. Token Plan
8
+ * login opens plan management so users copy the regional `tp-...` key.
9
+ */
10
+
11
+ import * as AIError from "../../error";
12
+ import type { FetchImpl } from "../../types";
13
+ import type { OAuthController } from "./types";
14
+
15
+ const PROVIDER_ID = "xiaomi";
16
+ const PROVIDER_NAME = "Xiaomi MiMo";
17
+ const STANDARD_AUTH_URL = "https://platform.xiaomimimo.com/#/console/api-keys";
18
+ const TOKEN_PLAN_AUTH_URL = "https://platform.xiaomimimo.com/console/plan-manage";
19
+ const STANDARD_API_BASE_URL = "https://api.xiaomimimo.com/v1";
20
+ const TOKEN_PLAN_KEY_PREFIX = "tp-";
21
+ const STANDARD_VALIDATION_MODEL = "mimo-v2.5";
22
+ const TOKEN_PLAN_VALIDATION_MODEL = "mimo-v2.5";
23
+ const TOKEN_PLAN_SGP_API_BASE_URL = "https://token-plan-sgp.xiaomimimo.com/v1";
24
+ const TOKEN_PLAN_AMS_API_BASE_URL = "https://token-plan-ams.xiaomimimo.com/v1";
25
+ const TOKEN_PLAN_CN_API_BASE_URL = "https://token-plan-cn.xiaomimimo.com/v1";
26
+
27
+ /** Region codes accepted by the Xiaomi Token Plan login flow. */
28
+ export type XiaomiTokenPlanRegion = "sgp" | "ams" | "cn";
29
+
30
+ type XiaomiValidationEndpoint = {
31
+ baseUrl: string;
32
+ model: string;
33
+ };
34
+
35
+ const TOKEN_PLAN_VALIDATION_ENDPOINTS: Record<XiaomiTokenPlanRegion, XiaomiValidationEndpoint> = {
36
+ sgp: { baseUrl: TOKEN_PLAN_SGP_API_BASE_URL, model: TOKEN_PLAN_VALIDATION_MODEL },
37
+ ams: { baseUrl: TOKEN_PLAN_AMS_API_BASE_URL, model: TOKEN_PLAN_VALIDATION_MODEL },
38
+ cn: { baseUrl: TOKEN_PLAN_CN_API_BASE_URL, model: TOKEN_PLAN_VALIDATION_MODEL },
39
+ };
40
+
41
+ const TOKEN_PLAN_REGION_NAMES: Record<XiaomiTokenPlanRegion, string> = {
42
+ sgp: "Singapore",
43
+ ams: "Europe",
44
+ cn: "China",
45
+ };
46
+
47
+ function isTokenPlanKey(apiKey: string): boolean {
48
+ return apiKey.startsWith(TOKEN_PLAN_KEY_PREFIX);
49
+ }
50
+
51
+ const VALIDATION_TIMEOUT_MS = 15_000;
52
+
53
+ async function validateXiaomiApiKey(
54
+ apiKey: string,
55
+ tokenPlanRegion: XiaomiTokenPlanRegion | undefined,
56
+ signal?: AbortSignal,
57
+ fetchOverride?: FetchImpl,
58
+ ): Promise<void> {
59
+ const fetchImpl = fetchOverride ?? fetch;
60
+ // Region-specific Token Plan logins must validate against the selected
61
+ // cluster. Generic Xiaomi login keeps the historical SGP → AMS → CN fallback.
62
+ const endpoints = tokenPlanRegion
63
+ ? [TOKEN_PLAN_VALIDATION_ENDPOINTS[tokenPlanRegion]]
64
+ : isTokenPlanKey(apiKey)
65
+ ? [
66
+ TOKEN_PLAN_VALIDATION_ENDPOINTS.sgp,
67
+ TOKEN_PLAN_VALIDATION_ENDPOINTS.ams,
68
+ TOKEN_PLAN_VALIDATION_ENDPOINTS.cn,
69
+ ]
70
+ : [{ baseUrl: STANDARD_API_BASE_URL, model: STANDARD_VALIDATION_MODEL }];
71
+
72
+ let lastError: Error | null = null;
73
+
74
+ for (const ep of endpoints) {
75
+ // Fresh timeout per endpoint so SGP→AMS fallback works after a regional
76
+ // timeout: a shared AbortSignal.timeout would stay aborted and instantly
77
+ // abort the AMS fetch.
78
+ const timeoutSignal = AbortSignal.timeout(VALIDATION_TIMEOUT_MS);
79
+ const requestSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
80
+ try {
81
+ const response = await fetchImpl(`${ep.baseUrl}/chat/completions`, {
82
+ method: "POST",
83
+ headers: {
84
+ "Content-Type": "application/json",
85
+ Authorization: `Bearer ${apiKey}`,
86
+ },
87
+ body: JSON.stringify({
88
+ model: ep.model,
89
+ max_tokens: 1,
90
+ messages: [{ role: "user", content: "ping" }],
91
+ }),
92
+ signal: requestSignal,
93
+ });
94
+
95
+ if (response.ok) {
96
+ return;
97
+ }
98
+
99
+ // 401 means this endpoint didn't accept the key; try the next one
100
+ if (response.status === 401) {
101
+ let details = "";
102
+ try {
103
+ details = (await response.text()).trim();
104
+ } catch {
105
+ // ignore body parse errors, status is enough
106
+ }
107
+ lastError = new AIError.OAuthError(
108
+ details
109
+ ? `${PROVIDER_NAME} API key validation failed (${response.status}): ${details}`
110
+ : `${PROVIDER_NAME} API key validation failed (${response.status})`,
111
+ { kind: "validation", provider: PROVIDER_ID, status: response.status },
112
+ );
113
+ continue;
114
+ }
115
+
116
+ // Non-auth errors are real failures
117
+ let details = "";
118
+ try {
119
+ details = (await response.text()).trim();
120
+ } catch {
121
+ // ignore body parse errors, status is enough
122
+ }
123
+ const message = details
124
+ ? `${PROVIDER_NAME} API key validation failed (${response.status}): ${details}`
125
+ : `${PROVIDER_NAME} API key validation failed (${response.status})`;
126
+ throw new AIError.OAuthError(message, {
127
+ kind: "validation",
128
+ provider: PROVIDER_ID,
129
+ status: response.status,
130
+ });
131
+ } catch (e) {
132
+ // Only re-throw AbortError when the caller explicitly cancelled.
133
+ // Timeout aborts (from AbortSignal.timeout) should fall through to
134
+ // the next endpoint so SGP→AMS fallback works during regional outages.
135
+ if (e instanceof DOMException && e.name === "AbortError" && signal?.aborted) {
136
+ throw e;
137
+ }
138
+ lastError = e instanceof Error ? e : new Error(String(e));
139
+ }
140
+ }
141
+ throw (
142
+ lastError ??
143
+ new AIError.OAuthError(`${PROVIDER_NAME} API key validation failed`, {
144
+ kind: "validation",
145
+ provider: PROVIDER_ID,
146
+ })
147
+ );
148
+ }
149
+
150
+ /**
151
+ * Login to Xiaomi MiMo.
152
+ *
153
+ * Opens browser to API keys page, prompts user to paste their API key.
154
+ * Returns the API key directly (not OAuthCredentials - this isn't OAuth).
155
+ */
156
+ export async function loginXiaomi(options: OAuthController): Promise<string> {
157
+ const fetchImpl = options.fetch ?? fetch;
158
+ if (!options.onPrompt) {
159
+ throw new AIError.OnPromptRequiredError(PROVIDER_NAME);
160
+ }
161
+ options.onAuth?.({
162
+ url: STANDARD_AUTH_URL,
163
+ instructions: "Copy your API key from the Xiaomi MiMo console",
164
+ });
165
+ const apiKey = await options.onPrompt({
166
+ message: "Paste your Xiaomi API key (sk-... or token-plan tp-...)",
167
+ placeholder: "sk-... or tp-...",
168
+ });
169
+ if (options.signal?.aborted) {
170
+ throw new AIError.LoginCancelledError();
171
+ }
172
+ const trimmed = apiKey.trim();
173
+ if (!trimmed) {
174
+ throw new AIError.ApiKeyRequiredError();
175
+ }
176
+
177
+ options.onProgress?.(`Validating ${PROVIDER_ID} API key...`);
178
+ await validateXiaomiApiKey(trimmed, undefined, options.signal, fetchImpl);
179
+ return trimmed;
180
+ }
181
+
182
+ /**
183
+ * Login to a regional Xiaomi Token Plan endpoint.
184
+ *
185
+ * Prompts for a token-plan API key and validates it against the selected region.
186
+ */
187
+ export async function loginXiaomiTokenPlan(options: OAuthController, region: XiaomiTokenPlanRegion): Promise<string> {
188
+ const fetchImpl = options.fetch ?? fetch;
189
+ if (!options.onPrompt) {
190
+ throw new AIError.OnPromptRequiredError(`Xiaomi Token Plan (${TOKEN_PLAN_REGION_NAMES[region]})`);
191
+ }
192
+ options.onAuth?.({
193
+ url: TOKEN_PLAN_AUTH_URL,
194
+ instructions: `Copy your token-plan API key for the ${TOKEN_PLAN_REGION_NAMES[region]} region`,
195
+ });
196
+ const apiKey = await options.onPrompt({
197
+ message: `Paste your Xiaomi Token Plan ${TOKEN_PLAN_REGION_NAMES[region]} API key (tp-...)`,
198
+ placeholder: "tp-...",
199
+ });
200
+ if (options.signal?.aborted) {
201
+ throw new AIError.LoginCancelledError();
202
+ }
203
+ const trimmed = apiKey.trim();
204
+ if (!trimmed) {
205
+ throw new AIError.ApiKeyRequiredError();
206
+ }
207
+
208
+ options.onProgress?.(`Validating Xiaomi Token Plan (${TOKEN_PLAN_REGION_NAMES[region]}) API key...`);
209
+ await validateXiaomiApiKey(trimmed, region, options.signal, fetchImpl);
210
+ return trimmed;
211
+ }
@@ -0,0 +1,285 @@
1
+ /**
2
+ * Z.ai / GLM OAuth flow (GLM Coding Plan · Sign in)
3
+ *
4
+ * Mirrors ZCode's desktop "Individual Plan" browser sign-in: an
5
+ * authorization-code flow (no PKCE) against chat.z.ai, a JSON token exchange
6
+ * that yields a short-lived OAuth access token, and a business-API sequence
7
+ * that provisions a durable `id.secret` API key. The minted key is placed in
8
+ * {@link OAuthCredentials.access}; `getOAuthApiKey` returns it verbatim as the
9
+ * request bearer for the `zai` provider, so no dialect change is needed.
10
+ */
11
+
12
+ import * as AIError from "../../error";
13
+ import type { FetchImpl } from "../../types";
14
+ import { OAuthCallbackFlow } from "./callback-server";
15
+ import type { OAuthController, OAuthCredentials } from "./types";
16
+
17
+ const env = (key: string): string | undefined => {
18
+ const value = process.env[key];
19
+ return typeof value === "string" && value.length > 0 ? value : undefined;
20
+ };
21
+
22
+ const CLIENT_ID = env("ZAI_OAUTH_CLIENT_ID") ?? "client_P8X5CMWmlaRO9gyO-KSqtg";
23
+ const AUTHORIZE_URL = env("ZAI_OAUTH_AUTHORIZE_URL") ?? "https://chat.z.ai/api/oauth/authorize";
24
+ const TOKEN_URL = env("ZAI_OAUTH_TOKEN_URL") ?? "https://zcode.z.ai/api/v1/oauth/token";
25
+ const BIZ_BASE = env("ZAI_BIZ_BASE") ?? "https://api.z.ai";
26
+ /** Business-login endpoint: exchanges the OAuth access token for a biz token. */
27
+ const BUSINESS_LOGIN_URL = env("ZAI_BUSINESS_LOGIN_URL") ?? "https://api.z.ai/api/auth/z/login";
28
+ /** OMP's own key name so sign-in never mutates ZCode's `zcode-api-key`. */
29
+ const KEY_NAME = "oh-my-pi";
30
+ const CALLBACK_PORT = 54548;
31
+ const CALLBACK_PATH = "/callback";
32
+ /** Durable minted key never expires; matches the perplexity NEVER_EXPIRES sentinel. */
33
+ const NEVER_EXPIRES = 8.64e15;
34
+
35
+ function formatErrorDetails(error: unknown): string {
36
+ if (error instanceof Error) {
37
+ return error.message;
38
+ }
39
+ return String(error);
40
+ }
41
+
42
+ /**
43
+ * Z.ai's `{ code, msg, data, success }` envelope. The OAuth token endpoint
44
+ * signals success with `code: 0`; the biz endpoints (`api.z.ai`) use
45
+ * `code: 200` / `success: true`. Accept both; throw `msg` on failure. Bodies
46
+ * without a status wrapper pass through unchanged.
47
+ */
48
+ function isSuccessCode(code: unknown): boolean {
49
+ if (code == null) return true;
50
+ if (typeof code === "number") return code === 0 || code === 200;
51
+ if (typeof code === "string") return code === "0" || code === "200";
52
+ return false;
53
+ }
54
+
55
+ function unwrapEnvelope(body: unknown, operation: string): unknown {
56
+ if (body && typeof body === "object" && ("code" in body || "success" in body)) {
57
+ const envelope = body as { code?: unknown; msg?: string; data?: unknown; success?: unknown };
58
+ if (envelope.success === false || !isSuccessCode(envelope.code)) {
59
+ throw new AIError.OAuthError(`Z.ai ${operation} failed: ${envelope.msg ?? `code ${String(envelope.code)}`}`, {
60
+ kind: "token-exchange",
61
+ provider: "zai",
62
+ });
63
+ }
64
+ return "data" in envelope ? envelope.data : envelope;
65
+ }
66
+ return body;
67
+ }
68
+
69
+ async function getJson(url: string, headers: Record<string, string>, fetchImpl: FetchImpl): Promise<unknown> {
70
+ const response = await fetchImpl(url, {
71
+ method: "GET",
72
+ headers,
73
+ signal: AbortSignal.timeout(30_000),
74
+ });
75
+ const responseBody = await response.text();
76
+ if (!response.ok) {
77
+ throw new AIError.ProviderHttpError(
78
+ `HTTP request failed. status=${response.status}; url=${url}; body=${responseBody}`,
79
+ response.status,
80
+ );
81
+ }
82
+ return responseBody.length > 0 ? JSON.parse(responseBody) : undefined;
83
+ }
84
+
85
+ async function postJson(
86
+ url: string,
87
+ body: Record<string, string | number>,
88
+ headers: Record<string, string>,
89
+ fetchImpl: FetchImpl,
90
+ ): Promise<unknown> {
91
+ const response = await fetchImpl(url, {
92
+ method: "POST",
93
+ headers: { ...headers, "Content-Type": "application/json" },
94
+ body: JSON.stringify(body),
95
+ signal: AbortSignal.timeout(30_000),
96
+ });
97
+ const responseBody = await response.text();
98
+ if (!response.ok) {
99
+ throw new AIError.ProviderHttpError(
100
+ `HTTP request failed. status=${response.status}; url=${url}; body=${responseBody}`,
101
+ response.status,
102
+ );
103
+ }
104
+ return responseBody.length > 0 ? JSON.parse(responseBody) : undefined;
105
+ }
106
+
107
+ /** Coerce an api_keys list response (bare array or common wrapper shapes) to an array. */
108
+ function asKeyArray(value: unknown): Array<Record<string, unknown>> {
109
+ if (Array.isArray(value)) return value as Array<Record<string, unknown>>;
110
+ if (value && typeof value === "object") {
111
+ const record = value as Record<string, unknown>;
112
+ for (const field of ["list", "keys", "apiKeys", "records"]) {
113
+ if (Array.isArray(record[field])) return record[field] as Array<Record<string, unknown>>;
114
+ }
115
+ }
116
+ return [];
117
+ }
118
+
119
+ function trimmedString(value: unknown): string | undefined {
120
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
121
+ }
122
+
123
+ /**
124
+ * Exchange the short-lived OAuth access token for a durable biz token via
125
+ * ZCode's business-login endpoint. The biz APIs reject the raw OAuth token;
126
+ * they require this token.
127
+ */
128
+ async function businessLogin(oauthAccessToken: string, fetchImpl: FetchImpl): Promise<string> {
129
+ const data = unwrapEnvelope(
130
+ await postJson(BUSINESS_LOGIN_URL, { token: oauthAccessToken }, {}, fetchImpl),
131
+ "business login",
132
+ ) as { access_token?: unknown; accessToken?: unknown } | undefined;
133
+ const bizToken = trimmedString(data?.access_token) ?? trimmedString(data?.accessToken);
134
+ if (!bizToken) {
135
+ throw new AIError.OAuthError("Z.ai business login returned no access token", {
136
+ kind: "token-exchange",
137
+ provider: "zai",
138
+ });
139
+ }
140
+ return bizToken;
141
+ }
142
+
143
+ interface ZaiProject {
144
+ projectId?: unknown;
145
+ isDefault?: unknown;
146
+ }
147
+ interface ZaiOrganization {
148
+ organizationId?: unknown;
149
+ isDefault?: unknown;
150
+ projects?: ZaiProject[];
151
+ }
152
+
153
+ /**
154
+ * Provision the durable Z.ai API key from a short-lived OAuth access token,
155
+ * mirroring ZCode: business-login → resolve default org/project from
156
+ * `getCustomerInfo` → find/create the OMP-named key → obtain its secret →
157
+ * return `${apiKey}.${secretKey}` (the 49-char durable key).
158
+ */
159
+ async function mintZaiApiKey(oauthAccessToken: string, fetchImpl: FetchImpl): Promise<string> {
160
+ const bizToken = await businessLogin(oauthAccessToken, fetchImpl);
161
+ const auth = { Authorization: `Bearer ${bizToken}` };
162
+
163
+ const customer = unwrapEnvelope(
164
+ await getJson(`${BIZ_BASE}/api/biz/customer/getCustomerInfo`, auth, fetchImpl),
165
+ "customer lookup",
166
+ ) as { organizations?: ZaiOrganization[] } | undefined;
167
+ const orgs = Array.isArray(customer?.organizations) ? customer.organizations : [];
168
+ const org = orgs.find(o => o?.isDefault) ?? orgs[0];
169
+ const projects = Array.isArray(org?.projects) ? org.projects : [];
170
+ const project = projects.find(p => p?.isDefault) ?? projects[0];
171
+ const organizationId = trimmedString(org?.organizationId);
172
+ const projectId = trimmedString(project?.projectId);
173
+ if (!organizationId || !projectId) {
174
+ throw new AIError.OAuthError("Z.ai key provisioning failed: no organization/project on account", {
175
+ kind: "token-exchange",
176
+ provider: "zai",
177
+ });
178
+ }
179
+
180
+ const keysUrl = `${BIZ_BASE}/api/biz/v1/organization/${organizationId}/projects/${projectId}/api_keys`;
181
+ const existing = asKeyArray(unwrapEnvelope(await getJson(keysUrl, auth, fetchImpl), "api key list")).find(
182
+ key => key.name === KEY_NAME,
183
+ );
184
+ const keyRecord =
185
+ existing ??
186
+ (unwrapEnvelope(await postJson(keysUrl, { name: KEY_NAME }, auth, fetchImpl), "api key create") as
187
+ | Record<string, unknown>
188
+ | undefined);
189
+
190
+ const apiKey = trimmedString(keyRecord?.apiKey);
191
+ if (!apiKey) {
192
+ throw new AIError.OAuthError("Z.ai key provisioning returned no apiKey", {
193
+ kind: "token-exchange",
194
+ provider: "zai",
195
+ });
196
+ }
197
+
198
+ // Always fetch the secret via the copy endpoint: list entries mask it
199
+ // (`*****abcd`) and the create response's inline secret is not reliable
200
+ // across account states, whereas copy always returns the full secret.
201
+ const copied = unwrapEnvelope(
202
+ await getJson(`${keysUrl}/copy/${encodeURIComponent(apiKey)}`, auth, fetchImpl),
203
+ "api key copy",
204
+ ) as { secretKey?: unknown } | undefined;
205
+ const secretKey = trimmedString(copied?.secretKey);
206
+ if (!secretKey) {
207
+ throw new AIError.OAuthError("Z.ai key provisioning returned no secretKey", {
208
+ kind: "token-exchange",
209
+ provider: "zai",
210
+ });
211
+ }
212
+
213
+ return `${apiKey}.${secretKey}`;
214
+ }
215
+
216
+ export class ZaiOAuthFlow extends OAuthCallbackFlow {
217
+ #fetch: FetchImpl;
218
+
219
+ constructor(ctrl: OAuthController) {
220
+ super(ctrl, CALLBACK_PORT, CALLBACK_PATH);
221
+ this.#fetch = ctrl.fetch ?? fetch;
222
+ }
223
+
224
+ async generateAuthUrl(state: string, redirectUri: string): Promise<{ url: string; instructions?: string }> {
225
+ // No PKCE: matches ZCode's authorize request verbatim.
226
+ const authParams = new URLSearchParams({
227
+ redirect_uri: redirectUri,
228
+ response_type: "code",
229
+ client_id: CLIENT_ID,
230
+ state,
231
+ });
232
+ return {
233
+ url: `${AUTHORIZE_URL}?${authParams.toString()}`,
234
+ instructions:
235
+ "Complete Z.ai login in your browser. If the browser cannot reach this machine, paste the final redirect URL or authorization code when prompted.",
236
+ };
237
+ }
238
+
239
+ async exchangeToken(code: string, state: string, redirectUri: string): Promise<OAuthCredentials> {
240
+ if (this.ctrl.signal?.aborted) {
241
+ throw new AIError.LoginCancelledError(`OAuth callback cancelled: ${this.ctrl.signal.reason}`);
242
+ }
243
+
244
+ let body: unknown;
245
+ try {
246
+ // Non-standard token body (no grant_type/code_verifier): matches ZCode.
247
+ body = await postJson(TOKEN_URL, { provider: "zai", code, redirect_uri: redirectUri, state }, {}, this.#fetch);
248
+ } catch (error) {
249
+ throw new AIError.OAuthError(
250
+ `Token exchange request failed. url=${TOKEN_URL}; redirect_uri=${redirectUri}; details=${formatErrorDetails(error)}`,
251
+ { kind: "token-exchange", provider: "zai", cause: error },
252
+ );
253
+ }
254
+
255
+ const data = unwrapEnvelope(body, "token exchange") as
256
+ | { zai?: { access_token?: unknown }; user?: { email?: unknown; id?: unknown } }
257
+ | undefined;
258
+ const oauthAccessToken = trimmedString(data?.zai?.access_token);
259
+ if (!oauthAccessToken) {
260
+ throw new AIError.OAuthError("Z.ai token response missing access token", {
261
+ kind: "validation",
262
+ provider: "zai",
263
+ });
264
+ }
265
+
266
+ const mintedKey = await mintZaiApiKey(oauthAccessToken, this.#fetch);
267
+
268
+ return {
269
+ access: mintedKey,
270
+ refresh: "",
271
+ expires: NEVER_EXPIRES,
272
+ email: typeof data?.user?.email === "string" ? data.user.email : undefined,
273
+ accountId:
274
+ typeof data?.user?.id === "string" || typeof data?.user?.id === "number" ? String(data.user.id) : undefined,
275
+ };
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Login with Z.ai OAuth (GLM Coding Plan).
281
+ */
282
+ export async function loginZaiOAuth(ctrl: OAuthController): Promise<OAuthCredentials> {
283
+ const flow = new ZaiOAuthFlow(ctrl);
284
+ return flow.login();
285
+ }
@@ -0,0 +1,36 @@
1
+ import * as AIError from "../error";
2
+ import type { OAuthController, OAuthLoginCallbacks } from "./oauth/types";
3
+ import type { ProviderDefinition } from "./types";
4
+
5
+ const OLLAMA_CLOUD_KEYS_URL = "https://ollama.com/settings/keys";
6
+
7
+ export async function loginOllamaCloud(options: OAuthController): Promise<string> {
8
+ if (options.signal?.aborted) {
9
+ throw new AIError.LoginCancelledError();
10
+ }
11
+ if (!options.onPrompt) {
12
+ throw new AIError.ConfigurationError("Interactive prompt is required for Ollama Cloud login");
13
+ }
14
+ options.onAuth?.({
15
+ url: OLLAMA_CLOUD_KEYS_URL,
16
+ instructions: "Create an Ollama Cloud API key, then paste it here.",
17
+ });
18
+ const apiKey = await options.onPrompt({
19
+ message: "Paste your Ollama Cloud API key",
20
+ placeholder: "ollama-cloud-api-key",
21
+ });
22
+ if (options.signal?.aborted) {
23
+ throw new AIError.LoginCancelledError();
24
+ }
25
+ const trimmed = apiKey.trim();
26
+ if (!trimmed) {
27
+ throw new AIError.ApiKeyRequiredError("Ollama Cloud API key is required");
28
+ }
29
+ return trimmed;
30
+ }
31
+
32
+ export const ollamaCloudProvider = {
33
+ id: "ollama-cloud",
34
+ name: "Ollama Cloud",
35
+ login: (cb: OAuthLoginCallbacks) => loginOllamaCloud(cb),
36
+ } as const satisfies ProviderDefinition;
@@ -0,0 +1,43 @@
1
+ import * as AIError from "../error";
2
+ import type { OAuthController } from "./oauth/types";
3
+ import type { ProviderDefinition } from "./types";
4
+
5
+ const OLLAMA_DOCS_URL = "https://github.com/ollama/ollama/blob/main/docs/api.md";
6
+
7
+ /**
8
+ * Login to Ollama.
9
+ *
10
+ * Returns a trimmed API key/token string. Empty string means local no-auth mode.
11
+ */
12
+ export async function loginOllama(options: OAuthController): Promise<string> {
13
+ if (options.signal?.aborted) {
14
+ throw new AIError.LoginCancelledError();
15
+ }
16
+ if (!options.onPrompt) {
17
+ return "";
18
+ }
19
+
20
+ options.onAuth?.({
21
+ url: OLLAMA_DOCS_URL,
22
+ instructions:
23
+ "Optional: paste an Ollama API key/token for authenticated hosts. Leave empty for local no-auth mode.",
24
+ });
25
+
26
+ const apiKey = await options.onPrompt({
27
+ message: "Paste your Ollama API key/token (optional)",
28
+ placeholder: "ollama-local",
29
+ allowEmpty: true,
30
+ });
31
+
32
+ if (options.signal?.aborted) {
33
+ throw new AIError.LoginCancelledError();
34
+ }
35
+
36
+ return apiKey.trim();
37
+ }
38
+
39
+ export const ollamaProvider = {
40
+ id: "ollama",
41
+ name: "Ollama (Local OpenAI-compatible)",
42
+ login: loginOllama,
43
+ } as const satisfies ProviderDefinition;
@@ -0,0 +1,18 @@
1
+ import type { OAuthCredentials, OAuthLoginCallbacks } from "./oauth/types";
2
+ import type { ProviderDefinition } from "./types";
3
+
4
+ export const openaiCodexDeviceProvider = {
5
+ id: "openai-codex-device",
6
+ name: "ChatGPT Plus/Pro (Codex, headless/device)",
7
+ login: async (cb: OAuthLoginCallbacks) => {
8
+ // Lazy import: keep heavy OAuth flow modules out of the eager registry graph.
9
+ const { loginOpenAICodexDevice } = await import("./oauth/openai-codex");
10
+ return loginOpenAICodexDevice(cb);
11
+ },
12
+ refreshToken: async (credentials: OAuthCredentials) => {
13
+ // Lazy import: keep heavy OAuth flow modules out of the eager registry graph.
14
+ const { refreshOpenAICodexToken } = await import("./oauth/openai-codex");
15
+ return refreshOpenAICodexToken(credentials.refresh);
16
+ },
17
+ storeCredentialsAs: "openai-codex",
18
+ } as const satisfies ProviderDefinition;
@@ -0,0 +1,19 @@
1
+ import type { OAuthCredentials, OAuthLoginCallbacks } from "./oauth/types";
2
+ import type { ProviderDefinition } from "./types";
3
+
4
+ export const openaiCodexProvider = {
5
+ id: "openai-codex",
6
+ name: "ChatGPT Plus/Pro (Codex Subscription)",
7
+ login: async (cb: OAuthLoginCallbacks) => {
8
+ // Lazy import: keep heavy OAuth flow modules out of the eager registry graph.
9
+ const { loginOpenAICodex } = await import("./oauth/openai-codex");
10
+ return loginOpenAICodex(cb);
11
+ },
12
+ refreshToken: async (credentials: OAuthCredentials) => {
13
+ // Lazy import: keep heavy OAuth flow modules out of the eager registry graph.
14
+ const { refreshOpenAICodexToken } = await import("./oauth/openai-codex");
15
+ return refreshOpenAICodexToken(credentials.refresh);
16
+ },
17
+ callbackPort: 1455,
18
+ pasteCodeFlow: true,
19
+ } as const satisfies ProviderDefinition;
@@ -0,0 +1,6 @@
1
+ import type { ProviderDefinition } from "./types";
2
+
3
+ export const openaiProvider = {
4
+ id: "openai",
5
+ name: "OpenAI",
6
+ } as const satisfies ProviderDefinition;
@@ -0,0 +1,12 @@
1
+ import type { OAuthLoginCallbacks } from "./oauth/types";
2
+ import type { ProviderDefinition } from "./types";
3
+
4
+ export const opencodeGoProvider = {
5
+ id: "opencode-go",
6
+ name: "OpenCode Go",
7
+ login: async (cb: OAuthLoginCallbacks) => {
8
+ // Lazy import: keep heavy OAuth flow modules out of the eager registry graph.
9
+ const { loginOpenCode } = await import("./oauth/opencode");
10
+ return loginOpenCode(cb);
11
+ },
12
+ } as const satisfies ProviderDefinition;
@@ -0,0 +1,12 @@
1
+ import type { OAuthLoginCallbacks } from "./oauth/types";
2
+ import type { ProviderDefinition } from "./types";
3
+
4
+ export const opencodeZenProvider = {
5
+ id: "opencode-zen",
6
+ name: "OpenCode Zen",
7
+ login: async (cb: OAuthLoginCallbacks) => {
8
+ // Lazy import: keep heavy OAuth flow modules out of the eager registry graph.
9
+ const { loginOpenCode } = await import("./oauth/opencode");
10
+ return loginOpenCode(cb);
11
+ },
12
+ } as const satisfies ProviderDefinition;
@@ -0,0 +1,28 @@
1
+ import { createApiKeyLogin } from "./api-key-login";
2
+ import type { OAuthLoginCallbacks } from "./oauth/types";
3
+ import type { ProviderDefinition } from "./types";
4
+
5
+ /** OpenRouter login flow (API key paste, validated via /auth/key).
6
+ *
7
+ * `/api/v1/models` is public and returns 200 for any bearer (including bogus),
8
+ * so it cannot validate auth. `/api/v1/auth/key` is the canonical "who am I"
9
+ * endpoint — 200 for valid keys, 401 otherwise.
10
+ */
11
+ export const loginOpenRouter = createApiKeyLogin({
12
+ providerLabel: "OpenRouter",
13
+ authUrl: "https://openrouter.ai/keys",
14
+ instructions: "Create or copy your OpenRouter API key",
15
+ promptMessage: "Paste your OpenRouter API key",
16
+ placeholder: "sk-or-...",
17
+ validation: {
18
+ kind: "models-endpoint",
19
+ provider: "OpenRouter",
20
+ modelsUrl: "https://openrouter.ai/api/v1/auth/key",
21
+ },
22
+ });
23
+
24
+ export const openrouterProvider = {
25
+ id: "openrouter",
26
+ name: "OpenRouter",
27
+ login: (cb: OAuthLoginCallbacks) => loginOpenRouter(cb),
28
+ } as const satisfies ProviderDefinition;