@aryee337/aery-ai 0.2.28 → 0.2.29

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 (417) hide show
  1. package/CHANGELOG.md +2914 -0
  2. package/README.md +614 -813
  3. package/package.json +140 -105
  4. package/src/api-registry.ts +96 -0
  5. package/src/auth-broker/client.ts +358 -0
  6. package/src/auth-broker/index.ts +5 -0
  7. package/src/auth-broker/refresher.ts +117 -0
  8. package/src/auth-broker/remote-store.ts +623 -0
  9. package/src/auth-broker/server.ts +644 -0
  10. package/src/auth-broker/types.ts +127 -0
  11. package/src/auth-broker/wire-schemas.ts +200 -0
  12. package/src/auth-gateway/http.ts +194 -0
  13. package/src/auth-gateway/index.ts +3 -0
  14. package/src/auth-gateway/server.ts +818 -0
  15. package/src/auth-gateway/types.ts +143 -0
  16. package/src/auth-storage.ts +4422 -0
  17. package/src/index.ts +54 -0
  18. package/src/model-cache.ts +129 -0
  19. package/src/model-manager.ts +469 -0
  20. package/src/model-thinking.ts +782 -0
  21. package/src/models.json +83530 -0
  22. package/src/models.json.d.ts +9 -0
  23. package/src/models.ts +56 -0
  24. package/src/prompts/turn-aborted-guidance.md +4 -0
  25. package/src/provider-details.ts +90 -0
  26. package/src/provider-models/bundled-references.ts +38 -0
  27. package/src/provider-models/descriptors.ts +355 -0
  28. package/src/provider-models/google.ts +88 -0
  29. package/src/provider-models/index.ts +5 -0
  30. package/src/provider-models/ollama.ts +153 -0
  31. package/src/provider-models/openai-compat.ts +2817 -0
  32. package/src/provider-models/special.ts +67 -0
  33. package/src/providers/aery-native-client.ts +228 -0
  34. package/src/providers/aery-native-server.ts +212 -0
  35. package/src/providers/amazon-bedrock.ts +873 -0
  36. package/src/providers/anthropic-client.ts +318 -0
  37. package/src/providers/anthropic-messages-server-schema.ts +243 -0
  38. package/src/providers/anthropic-messages-server.ts +683 -0
  39. package/src/providers/anthropic-wire.ts +268 -0
  40. package/src/providers/anthropic.ts +3094 -0
  41. package/src/providers/aws-credentials.ts +501 -0
  42. package/src/providers/aws-eventstream.ts +185 -0
  43. package/src/providers/aws-sigv4.ts +218 -0
  44. package/src/providers/azure-openai-responses.ts +361 -0
  45. package/src/providers/cursor/gen/agent_pb.ts +15274 -0
  46. package/src/providers/cursor/proto/agent.proto +3526 -0
  47. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  48. package/src/providers/cursor/proto/buf.yaml +17 -0
  49. package/src/providers/cursor.ts +2621 -0
  50. package/src/providers/error-message.ts +21 -0
  51. package/src/providers/github-copilot-headers.ts +140 -0
  52. package/src/providers/gitlab-duo.ts +372 -0
  53. package/src/providers/google-auth.ts +252 -0
  54. package/src/providers/google-gemini-cli.ts +809 -0
  55. package/src/providers/google-gemini-headers.ts +41 -0
  56. package/src/providers/google-shared.ts +917 -0
  57. package/src/providers/google-types.ts +167 -0
  58. package/src/providers/google-vertex.ts +91 -0
  59. package/src/providers/google.ts +41 -0
  60. package/src/providers/grammar.ts +70 -0
  61. package/src/providers/kimi.ts +52 -0
  62. package/src/providers/mock.ts +496 -0
  63. package/src/providers/ollama.ts +644 -0
  64. package/src/providers/openai-anthropic-shim.ts +138 -0
  65. package/src/providers/openai-chat-server-schema.ts +252 -0
  66. package/src/providers/openai-chat-server.ts +647 -0
  67. package/src/providers/openai-codex/constants.ts +43 -0
  68. package/src/providers/openai-codex/request-transformer.ts +161 -0
  69. package/src/providers/openai-codex/response-handler.ts +81 -0
  70. package/src/providers/openai-codex-responses.ts +3018 -0
  71. package/src/providers/openai-completions-compat.ts +300 -0
  72. package/src/providers/openai-completions.ts +1979 -0
  73. package/src/providers/openai-responses-server-schema.ts +290 -0
  74. package/src/providers/openai-responses-server.ts +1183 -0
  75. package/src/providers/openai-responses-shared.ts +873 -0
  76. package/src/providers/openai-responses.ts +679 -0
  77. package/src/providers/register-builtins.ts +436 -0
  78. package/src/providers/synthetic.ts +50 -0
  79. package/src/providers/transform-messages.ts +382 -0
  80. package/src/providers/vision-guard.ts +31 -0
  81. package/src/providers/xai-responses.ts +82 -0
  82. package/src/rate-limit-utils.ts +84 -0
  83. package/src/stream.ts +1065 -0
  84. package/src/types.ts +944 -0
  85. package/src/usage/claude.ts +482 -0
  86. package/src/usage/gemini.ts +250 -0
  87. package/src/usage/github-copilot.ts +421 -0
  88. package/src/usage/google-antigravity.ts +201 -0
  89. package/src/usage/kimi.ts +271 -0
  90. package/src/usage/minimax-code.ts +31 -0
  91. package/src/usage/openai-codex.ts +503 -0
  92. package/src/usage/shared.ts +10 -0
  93. package/src/usage/zai.ts +247 -0
  94. package/src/usage.ts +185 -0
  95. package/src/utils/abort.ts +51 -0
  96. package/src/utils/abortable-iterator.ts +69 -0
  97. package/src/utils/anthropic-auth.ts +93 -0
  98. package/src/utils/discovery/antigravity.ts +261 -0
  99. package/src/utils/discovery/codex.ts +371 -0
  100. package/src/utils/discovery/cursor.ts +306 -0
  101. package/src/utils/discovery/gemini.ts +248 -0
  102. package/src/utils/discovery/index.ts +4 -0
  103. package/src/utils/discovery/openai-compatible.ts +224 -0
  104. package/src/utils/event-stream.ts +142 -0
  105. package/src/utils/fireworks-model-id.ts +30 -0
  106. package/src/utils/foundry.ts +8 -0
  107. package/src/utils/http-inspector.ts +176 -0
  108. package/src/utils/idle-iterator.ts +267 -0
  109. package/src/utils/json-parse.ts +182 -0
  110. package/src/utils/oauth/__tests__/xai-oauth.test.ts +107 -0
  111. package/src/utils/oauth/alibaba-coding-plan.ts +59 -0
  112. package/src/utils/oauth/anthropic.ts +273 -0
  113. package/src/utils/oauth/api-key-login.ts +87 -0
  114. package/src/utils/oauth/api-key-validation.ts +92 -0
  115. package/src/utils/oauth/callback-server.ts +276 -0
  116. package/src/utils/oauth/cerebras.ts +16 -0
  117. package/src/utils/oauth/cloudflare-ai-gateway.ts +48 -0
  118. package/src/utils/oauth/cursor.ts +157 -0
  119. package/src/utils/oauth/deepseek.ts +53 -0
  120. package/src/utils/oauth/firepass.ts +24 -0
  121. package/src/utils/oauth/fireworks.ts +15 -0
  122. package/src/utils/oauth/github-copilot.ts +362 -0
  123. package/src/utils/oauth/gitlab-duo.ts +123 -0
  124. package/src/utils/oauth/google-antigravity.ts +200 -0
  125. package/src/utils/oauth/google-gemini-cli.ts +256 -0
  126. package/src/utils/oauth/google-oauth-shared.ts +110 -0
  127. package/src/utils/oauth/huggingface.ts +62 -0
  128. package/src/utils/oauth/index.ts +484 -0
  129. package/src/utils/oauth/kagi.ts +47 -0
  130. package/src/utils/oauth/kilo.ts +87 -0
  131. package/src/utils/oauth/kimi.ts +254 -0
  132. package/src/utils/oauth/litellm.ts +47 -0
  133. package/src/utils/oauth/lm-studio.ts +38 -0
  134. package/src/utils/oauth/minimax-code.ts +78 -0
  135. package/src/utils/oauth/moonshot.ts +23 -0
  136. package/src/utils/oauth/nanogpt.ts +15 -0
  137. package/src/utils/oauth/nvidia.ts +70 -0
  138. package/src/utils/oauth/oauth.html +203 -0
  139. package/src/utils/oauth/ollama-cloud.ts +28 -0
  140. package/src/utils/oauth/ollama.ts +47 -0
  141. package/src/utils/oauth/openai-codex.ts +299 -0
  142. package/src/utils/oauth/opencode.ts +49 -0
  143. package/src/utils/oauth/openrouter.ts +20 -0
  144. package/src/utils/oauth/parallel.ts +46 -0
  145. package/src/utils/oauth/perplexity.ts +206 -0
  146. package/src/utils/oauth/pkce.ts +18 -0
  147. package/src/utils/oauth/qianfan.ts +58 -0
  148. package/src/utils/oauth/qwen-portal.ts +60 -0
  149. package/src/utils/oauth/synthetic.ts +15 -0
  150. package/src/utils/oauth/tavily.ts +46 -0
  151. package/src/utils/oauth/together.ts +16 -0
  152. package/src/utils/oauth/types.ts +99 -0
  153. package/src/utils/oauth/venice.ts +59 -0
  154. package/src/utils/oauth/vercel-ai-gateway.ts +47 -0
  155. package/src/utils/oauth/vllm.ts +40 -0
  156. package/src/utils/oauth/wafer.ts +50 -0
  157. package/src/utils/oauth/xai-oauth.ts +342 -0
  158. package/src/utils/oauth/xiaomi.ts +139 -0
  159. package/src/utils/oauth/zai.ts +60 -0
  160. package/src/utils/oauth/zenmux.ts +15 -0
  161. package/src/utils/oauth/zhipu.ts +60 -0
  162. package/src/utils/overflow.ts +137 -0
  163. package/src/utils/parse-bind.ts +54 -0
  164. package/src/utils/provider-response.ts +30 -0
  165. package/src/utils/request-debug.ts +336 -0
  166. package/src/utils/retry-after.ts +110 -0
  167. package/src/utils/retry.ts +54 -0
  168. package/src/utils/schema/CONSTRAINTS.md +164 -0
  169. package/src/utils/schema/adapt.ts +36 -0
  170. package/src/utils/schema/compatibility.ts +435 -0
  171. package/src/utils/schema/dereference.ts +98 -0
  172. package/src/utils/schema/draft.ts +341 -0
  173. package/src/utils/schema/equality.ts +97 -0
  174. package/src/utils/schema/fields.ts +191 -0
  175. package/src/utils/schema/index.ts +13 -0
  176. package/src/utils/schema/json-schema-validator.ts +577 -0
  177. package/src/utils/schema/meta-validator.ts +167 -0
  178. package/src/utils/schema/normalize.ts +1588 -0
  179. package/src/utils/schema/spill.ts +43 -0
  180. package/src/utils/schema/stamps.ts +97 -0
  181. package/src/utils/schema/types.ts +10 -0
  182. package/src/utils/schema/wire.ts +293 -0
  183. package/src/utils/schema/zod-decontaminate.ts +331 -0
  184. package/src/utils/sdk-stream-timeout.ts +43 -0
  185. package/src/utils/sse-debug.ts +289 -0
  186. package/src/utils/stream-markup-healing.ts +612 -0
  187. package/src/utils/tool-choice.ts +99 -0
  188. package/src/utils/validation.ts +1024 -0
  189. package/src/utils.ts +166 -0
  190. package/dist/api-registry.d.ts +0 -20
  191. package/dist/api-registry.d.ts.map +0 -1
  192. package/dist/api-registry.js +0 -44
  193. package/dist/api-registry.js.map +0 -1
  194. package/dist/bedrock-provider.d.ts +0 -5
  195. package/dist/bedrock-provider.d.ts.map +0 -1
  196. package/dist/bedrock-provider.js +0 -6
  197. package/dist/bedrock-provider.js.map +0 -1
  198. package/dist/cli.d.ts +0 -3
  199. package/dist/cli.d.ts.map +0 -1
  200. package/dist/cli.js +0 -130
  201. package/dist/cli.js.map +0 -1
  202. package/dist/env-api-keys.d.ts +0 -18
  203. package/dist/env-api-keys.d.ts.map +0 -1
  204. package/dist/env-api-keys.js +0 -178
  205. package/dist/env-api-keys.js.map +0 -1
  206. package/dist/image-models.d.ts +0 -10
  207. package/dist/image-models.d.ts.map +0 -1
  208. package/dist/image-models.generated.d.ts +0 -440
  209. package/dist/image-models.generated.d.ts.map +0 -1
  210. package/dist/image-models.generated.js +0 -442
  211. package/dist/image-models.generated.js.map +0 -1
  212. package/dist/image-models.js +0 -23
  213. package/dist/image-models.js.map +0 -1
  214. package/dist/images-api-registry.d.ts +0 -14
  215. package/dist/images-api-registry.d.ts.map +0 -1
  216. package/dist/images-api-registry.js +0 -22
  217. package/dist/images-api-registry.js.map +0 -1
  218. package/dist/images.d.ts +0 -4
  219. package/dist/images.d.ts.map +0 -1
  220. package/dist/images.js +0 -14
  221. package/dist/images.js.map +0 -1
  222. package/dist/index.d.ts +0 -32
  223. package/dist/index.d.ts.map +0 -1
  224. package/dist/index.js +0 -20
  225. package/dist/index.js.map +0 -1
  226. package/dist/models.d.ts +0 -18
  227. package/dist/models.d.ts.map +0 -1
  228. package/dist/models.generated.d.ts +0 -17707
  229. package/dist/models.generated.d.ts.map +0 -1
  230. package/dist/models.generated.js +0 -16561
  231. package/dist/models.generated.js.map +0 -1
  232. package/dist/models.js +0 -71
  233. package/dist/models.js.map +0 -1
  234. package/dist/oauth.d.ts +0 -2
  235. package/dist/oauth.d.ts.map +0 -1
  236. package/dist/oauth.js +0 -2
  237. package/dist/oauth.js.map +0 -1
  238. package/dist/providers/aery-error-formatting.d.ts +0 -13
  239. package/dist/providers/aery-error-formatting.d.ts.map +0 -1
  240. package/dist/providers/aery-error-formatting.js +0 -112
  241. package/dist/providers/aery-error-formatting.js.map +0 -1
  242. package/dist/providers/amazon-bedrock.d.ts +0 -38
  243. package/dist/providers/amazon-bedrock.d.ts.map +0 -1
  244. package/dist/providers/amazon-bedrock.js +0 -763
  245. package/dist/providers/amazon-bedrock.js.map +0 -1
  246. package/dist/providers/anthropic.d.ts +0 -71
  247. package/dist/providers/anthropic.d.ts.map +0 -1
  248. package/dist/providers/anthropic.js +0 -949
  249. package/dist/providers/anthropic.js.map +0 -1
  250. package/dist/providers/azure-openai-responses.d.ts +0 -15
  251. package/dist/providers/azure-openai-responses.d.ts.map +0 -1
  252. package/dist/providers/azure-openai-responses.js +0 -225
  253. package/dist/providers/azure-openai-responses.js.map +0 -1
  254. package/dist/providers/cloudflare.d.ts +0 -13
  255. package/dist/providers/cloudflare.d.ts.map +0 -1
  256. package/dist/providers/cloudflare.js +0 -26
  257. package/dist/providers/cloudflare.js.map +0 -1
  258. package/dist/providers/faux.d.ts +0 -56
  259. package/dist/providers/faux.d.ts.map +0 -1
  260. package/dist/providers/faux.js +0 -368
  261. package/dist/providers/faux.js.map +0 -1
  262. package/dist/providers/github-copilot-headers.d.ts +0 -8
  263. package/dist/providers/github-copilot-headers.d.ts.map +0 -1
  264. package/dist/providers/github-copilot-headers.js +0 -29
  265. package/dist/providers/github-copilot-headers.js.map +0 -1
  266. package/dist/providers/google-gemini-cli.d.ts +0 -74
  267. package/dist/providers/google-gemini-cli.d.ts.map +0 -1
  268. package/dist/providers/google-gemini-cli.js +0 -779
  269. package/dist/providers/google-gemini-cli.js.map +0 -1
  270. package/dist/providers/google-shared.d.ts +0 -70
  271. package/dist/providers/google-shared.d.ts.map +0 -1
  272. package/dist/providers/google-shared.js +0 -329
  273. package/dist/providers/google-shared.js.map +0 -1
  274. package/dist/providers/google-vertex.d.ts +0 -15
  275. package/dist/providers/google-vertex.d.ts.map +0 -1
  276. package/dist/providers/google-vertex.js +0 -442
  277. package/dist/providers/google-vertex.js.map +0 -1
  278. package/dist/providers/google.d.ts +0 -13
  279. package/dist/providers/google.d.ts.map +0 -1
  280. package/dist/providers/google.js +0 -400
  281. package/dist/providers/google.js.map +0 -1
  282. package/dist/providers/images/openrouter.d.ts +0 -3
  283. package/dist/providers/images/openrouter.d.ts.map +0 -1
  284. package/dist/providers/images/openrouter.js +0 -129
  285. package/dist/providers/images/openrouter.js.map +0 -1
  286. package/dist/providers/images/register-builtins.d.ts +0 -4
  287. package/dist/providers/images/register-builtins.d.ts.map +0 -1
  288. package/dist/providers/images/register-builtins.js +0 -34
  289. package/dist/providers/images/register-builtins.js.map +0 -1
  290. package/dist/providers/mistral.d.ts +0 -25
  291. package/dist/providers/mistral.d.ts.map +0 -1
  292. package/dist/providers/mistral.js +0 -535
  293. package/dist/providers/mistral.js.map +0 -1
  294. package/dist/providers/openai-codex-responses.d.ts +0 -30
  295. package/dist/providers/openai-codex-responses.d.ts.map +0 -1
  296. package/dist/providers/openai-codex-responses.js +0 -1090
  297. package/dist/providers/openai-codex-responses.js.map +0 -1
  298. package/dist/providers/openai-completions.d.ts +0 -19
  299. package/dist/providers/openai-completions.d.ts.map +0 -1
  300. package/dist/providers/openai-completions.js +0 -950
  301. package/dist/providers/openai-completions.js.map +0 -1
  302. package/dist/providers/openai-prompt-cache.d.ts +0 -3
  303. package/dist/providers/openai-prompt-cache.d.ts.map +0 -1
  304. package/dist/providers/openai-prompt-cache.js +0 -10
  305. package/dist/providers/openai-prompt-cache.js.map +0 -1
  306. package/dist/providers/openai-responses-shared.d.ts +0 -18
  307. package/dist/providers/openai-responses-shared.d.ts.map +0 -1
  308. package/dist/providers/openai-responses-shared.js +0 -492
  309. package/dist/providers/openai-responses-shared.js.map +0 -1
  310. package/dist/providers/openai-responses.d.ts +0 -13
  311. package/dist/providers/openai-responses.d.ts.map +0 -1
  312. package/dist/providers/openai-responses.js +0 -237
  313. package/dist/providers/openai-responses.js.map +0 -1
  314. package/dist/providers/register-builtins.d.ts +0 -38
  315. package/dist/providers/register-builtins.d.ts.map +0 -1
  316. package/dist/providers/register-builtins.js +0 -278
  317. package/dist/providers/register-builtins.js.map +0 -1
  318. package/dist/providers/simple-options.d.ts +0 -8
  319. package/dist/providers/simple-options.d.ts.map +0 -1
  320. package/dist/providers/simple-options.js +0 -41
  321. package/dist/providers/simple-options.js.map +0 -1
  322. package/dist/providers/transform-messages.d.ts +0 -8
  323. package/dist/providers/transform-messages.d.ts.map +0 -1
  324. package/dist/providers/transform-messages.js +0 -184
  325. package/dist/providers/transform-messages.js.map +0 -1
  326. package/dist/session-resources.d.ts +0 -4
  327. package/dist/session-resources.d.ts.map +0 -1
  328. package/dist/session-resources.js +0 -22
  329. package/dist/session-resources.js.map +0 -1
  330. package/dist/stream.d.ts +0 -8
  331. package/dist/stream.d.ts.map +0 -1
  332. package/dist/stream.js +0 -27
  333. package/dist/stream.js.map +0 -1
  334. package/dist/types.d.ts +0 -498
  335. package/dist/types.d.ts.map +0 -1
  336. package/dist/types.js +0 -2
  337. package/dist/types.js.map +0 -1
  338. package/dist/utils/diagnostics.d.ts +0 -19
  339. package/dist/utils/diagnostics.d.ts.map +0 -1
  340. package/dist/utils/diagnostics.js +0 -25
  341. package/dist/utils/diagnostics.js.map +0 -1
  342. package/dist/utils/event-stream.d.ts +0 -21
  343. package/dist/utils/event-stream.d.ts.map +0 -1
  344. package/dist/utils/event-stream.js +0 -81
  345. package/dist/utils/event-stream.js.map +0 -1
  346. package/dist/utils/hash.d.ts +0 -3
  347. package/dist/utils/hash.d.ts.map +0 -1
  348. package/dist/utils/hash.js +0 -14
  349. package/dist/utils/hash.js.map +0 -1
  350. package/dist/utils/headers.d.ts +0 -2
  351. package/dist/utils/headers.d.ts.map +0 -1
  352. package/dist/utils/headers.js +0 -8
  353. package/dist/utils/headers.js.map +0 -1
  354. package/dist/utils/json-parse.d.ts +0 -16
  355. package/dist/utils/json-parse.d.ts.map +0 -1
  356. package/dist/utils/json-parse.js +0 -113
  357. package/dist/utils/json-parse.js.map +0 -1
  358. package/dist/utils/node-http-proxy.d.ts +0 -10
  359. package/dist/utils/node-http-proxy.d.ts.map +0 -1
  360. package/dist/utils/node-http-proxy.js +0 -97
  361. package/dist/utils/node-http-proxy.js.map +0 -1
  362. package/dist/utils/oauth/anthropic.d.ts +0 -25
  363. package/dist/utils/oauth/anthropic.d.ts.map +0 -1
  364. package/dist/utils/oauth/anthropic.js +0 -335
  365. package/dist/utils/oauth/anthropic.js.map +0 -1
  366. package/dist/utils/oauth/device-code.d.ts +0 -19
  367. package/dist/utils/oauth/device-code.d.ts.map +0 -1
  368. package/dist/utils/oauth/device-code.js +0 -55
  369. package/dist/utils/oauth/device-code.js.map +0 -1
  370. package/dist/utils/oauth/github-copilot.d.ts +0 -30
  371. package/dist/utils/oauth/github-copilot.d.ts.map +0 -1
  372. package/dist/utils/oauth/github-copilot.js +0 -268
  373. package/dist/utils/oauth/github-copilot.js.map +0 -1
  374. package/dist/utils/oauth/google-antigravity.d.ts +0 -26
  375. package/dist/utils/oauth/google-antigravity.d.ts.map +0 -1
  376. package/dist/utils/oauth/google-antigravity.js +0 -377
  377. package/dist/utils/oauth/google-antigravity.js.map +0 -1
  378. package/dist/utils/oauth/google-gemini-cli.d.ts +0 -26
  379. package/dist/utils/oauth/google-gemini-cli.d.ts.map +0 -1
  380. package/dist/utils/oauth/google-gemini-cli.js +0 -482
  381. package/dist/utils/oauth/google-gemini-cli.js.map +0 -1
  382. package/dist/utils/oauth/index.d.ts +0 -63
  383. package/dist/utils/oauth/index.d.ts.map +0 -1
  384. package/dist/utils/oauth/index.js +0 -131
  385. package/dist/utils/oauth/index.js.map +0 -1
  386. package/dist/utils/oauth/oauth-page.d.ts +0 -3
  387. package/dist/utils/oauth/oauth-page.d.ts.map +0 -1
  388. package/dist/utils/oauth/oauth-page.js +0 -105
  389. package/dist/utils/oauth/oauth-page.js.map +0 -1
  390. package/dist/utils/oauth/openai-codex.d.ts +0 -34
  391. package/dist/utils/oauth/openai-codex.d.ts.map +0 -1
  392. package/dist/utils/oauth/openai-codex.js +0 -385
  393. package/dist/utils/oauth/openai-codex.js.map +0 -1
  394. package/dist/utils/oauth/pkce.d.ts +0 -13
  395. package/dist/utils/oauth/pkce.d.ts.map +0 -1
  396. package/dist/utils/oauth/pkce.js +0 -31
  397. package/dist/utils/oauth/pkce.js.map +0 -1
  398. package/dist/utils/oauth/types.d.ts +0 -64
  399. package/dist/utils/oauth/types.d.ts.map +0 -1
  400. package/dist/utils/oauth/types.js +0 -2
  401. package/dist/utils/oauth/types.js.map +0 -1
  402. package/dist/utils/overflow.d.ts +0 -56
  403. package/dist/utils/overflow.d.ts.map +0 -1
  404. package/dist/utils/overflow.js +0 -151
  405. package/dist/utils/overflow.js.map +0 -1
  406. package/dist/utils/sanitize-unicode.d.ts +0 -22
  407. package/dist/utils/sanitize-unicode.d.ts.map +0 -1
  408. package/dist/utils/sanitize-unicode.js +0 -26
  409. package/dist/utils/sanitize-unicode.js.map +0 -1
  410. package/dist/utils/typebox-helpers.d.ts +0 -17
  411. package/dist/utils/typebox-helpers.d.ts.map +0 -1
  412. package/dist/utils/typebox-helpers.js +0 -21
  413. package/dist/utils/typebox-helpers.js.map +0 -1
  414. package/dist/utils/validation.d.ts +0 -18
  415. package/dist/utils/validation.d.ts.map +0 -1
  416. package/dist/utils/validation.js +0 -281
  417. package/dist/utils/validation.js.map +0 -1
@@ -0,0 +1,276 @@
1
+ /**
2
+ * Abstract base class for OAuth flows with local callback servers.
3
+ *
4
+ * Handles:
5
+ * - Port allocation (tries expected port, falls back to random)
6
+ * - Callback server setup and request handling
7
+ * - Common OAuth flow logic
8
+ *
9
+ * Providers extend this and implement:
10
+ * - generateAuthUrl(): Build provider-specific authorization URL
11
+ * - exchangeToken(): Exchange authorization code for tokens
12
+ */
13
+ import templateHtml from "./oauth.html" with { type: "text" };
14
+ import type { OAuthController, OAuthCredentials } from "./types";
15
+
16
+ const DEFAULT_TIMEOUT = 300_000;
17
+ const DEFAULT_HOSTNAME = "localhost";
18
+ const CALLBACK_PATH = "/callback";
19
+
20
+ export type CallbackResult = { code: string; state: string };
21
+
22
+ export interface OAuthCallbackFlowOptions {
23
+ preferredPort: number;
24
+ callbackPath?: string;
25
+ callbackHostname?: string;
26
+ /** Exact redirect URI advertised to the provider; disables port fallback. */
27
+ redirectUri?: string;
28
+ }
29
+
30
+ /**
31
+ * Abstract base class for OAuth flows with local callback servers.
32
+ */
33
+ export abstract class OAuthCallbackFlow {
34
+ ctrl: OAuthController;
35
+ preferredPort: number;
36
+ callbackPath: string;
37
+ callbackHostname: string;
38
+ redirectUri?: string;
39
+ #callbackResolve?: (result: CallbackResult) => void;
40
+ #callbackReject?: (error: string) => void;
41
+
42
+ constructor(
43
+ ctrl: OAuthController,
44
+ preferredPortOrOptions: number | OAuthCallbackFlowOptions,
45
+ callbackPath: string = CALLBACK_PATH,
46
+ ) {
47
+ this.ctrl = ctrl;
48
+ if (typeof preferredPortOrOptions === "number") {
49
+ this.preferredPort = preferredPortOrOptions;
50
+ this.callbackPath = callbackPath;
51
+ this.callbackHostname = DEFAULT_HOSTNAME;
52
+ return;
53
+ }
54
+
55
+ this.preferredPort = preferredPortOrOptions.preferredPort;
56
+ this.callbackPath = preferredPortOrOptions.callbackPath ?? CALLBACK_PATH;
57
+ this.callbackHostname = preferredPortOrOptions.callbackHostname ?? DEFAULT_HOSTNAME;
58
+ this.redirectUri = preferredPortOrOptions.redirectUri;
59
+ }
60
+
61
+ /**
62
+ * Generate provider-specific authorization URL.
63
+ * @param state - CSRF state token
64
+ * @param redirectUri - The actual redirect URI to use (may differ from expected if port fallback occurred)
65
+ * @returns Authorization URL and optional instructions
66
+ */
67
+ abstract generateAuthUrl(state: string, redirectUri: string): Promise<{ url: string; instructions?: string }>;
68
+
69
+ /**
70
+ * Exchange authorization code for OAuth tokens.
71
+ * @param code - Authorization code from callback
72
+ * @param state - CSRF state token
73
+ * @param redirectUri - The actual redirect URI used (must match authorization request)
74
+ * @returns OAuth credentials
75
+ */
76
+ abstract exchangeToken(code: string, state: string, redirectUri: string): Promise<OAuthCredentials>;
77
+
78
+ /**
79
+ * Generate CSRF state token. Override if provider needs custom state generation.
80
+ */
81
+ generateState(): string {
82
+ const bytes = new Uint8Array(16);
83
+ crypto.getRandomValues(bytes);
84
+ return Array.from(bytes)
85
+ .map(value => value.toString(16).padStart(2, "0"))
86
+ .join("");
87
+ }
88
+
89
+ /**
90
+ * Execute the OAuth login flow.
91
+ */
92
+ async login(): Promise<OAuthCredentials> {
93
+ const state = this.generateState();
94
+
95
+ // Start callback server first to get actual redirect URI
96
+ const { server, redirectUri } = await this.#startCallbackServer(state);
97
+
98
+ try {
99
+ // Generate auth URL with the ACTUAL redirect URI (may differ from expected if port was busy)
100
+ const { url: authUrl, instructions } = await this.generateAuthUrl(state, redirectUri);
101
+
102
+ // Notify controller that auth is ready
103
+ this.ctrl.onAuth?.({ url: authUrl, instructions });
104
+ this.ctrl.onProgress?.("Waiting for browser authentication...");
105
+
106
+ // Wait for callback or manual input
107
+ const { code } = await this.#waitForCallback(state);
108
+
109
+ this.ctrl.onProgress?.("Exchanging authorization code for tokens...");
110
+
111
+ return await this.exchangeToken(code, state, redirectUri);
112
+ } finally {
113
+ server.stop();
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Start callback server, trying preferred port first, falling back to random.
119
+ */
120
+ async #startCallbackServer(expectedState: string): Promise<{ server: Bun.Server<unknown>; redirectUri: string }> {
121
+ try {
122
+ const server = this.#createServer(this.preferredPort, expectedState);
123
+ if (this.redirectUri) {
124
+ return { server, redirectUri: this.redirectUri };
125
+ }
126
+ const redirectUri = `http://${this.callbackHostname}:${this.preferredPort}${this.callbackPath}`;
127
+ return { server, redirectUri };
128
+ } catch {
129
+ if (this.redirectUri) {
130
+ throw new Error(
131
+ `OAuth callback port ${this.preferredPort} unavailable; cannot fall back to a random port when oauth.redirectUri is set`,
132
+ );
133
+ }
134
+ const server = this.#createServer(0, expectedState);
135
+ const actualPort = server.port;
136
+ const redirectUri = `http://${this.callbackHostname}:${actualPort}${this.callbackPath}`;
137
+ this.ctrl.onProgress?.(`Preferred port ${this.preferredPort} unavailable, using port ${actualPort}`);
138
+ return { server, redirectUri };
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Create HTTP server for OAuth callback.
144
+ */
145
+ #createServer(port: number, expectedState: string): Bun.Server<unknown> {
146
+ return Bun.serve({
147
+ hostname: this.callbackHostname,
148
+ port,
149
+ reusePort: false,
150
+ fetch: req => this.#handleCallback(req, expectedState),
151
+ });
152
+ }
153
+
154
+ /**
155
+ * Handle OAuth callback HTTP request.
156
+ */
157
+ #handleCallback(req: Request, expectedState: string): Response {
158
+ const url = new URL(req.url);
159
+
160
+ if (url.pathname !== this.callbackPath) {
161
+ return new Response("Not Found", { status: 404 });
162
+ }
163
+
164
+ const code = url.searchParams.get("code");
165
+ const state = url.searchParams.get("state") || "";
166
+ const error = url.searchParams.get("error") || "";
167
+ const errorDescription = url.searchParams.get("error_description") || error;
168
+
169
+ type OkState = { ok: true; code: string; state: string };
170
+ type ErrorState = { ok?: false; error?: string };
171
+ let resultState: OkState | ErrorState;
172
+
173
+ if (error) {
174
+ resultState = { ok: false, error: `Authorization failed: ${errorDescription}` };
175
+ } else if (!code) {
176
+ resultState = { ok: false, error: "Missing authorization code" };
177
+ } else if (expectedState && state !== expectedState) {
178
+ resultState = { ok: false, error: "State mismatch - possible CSRF attack" };
179
+ } else {
180
+ resultState = { ok: true, code, state };
181
+ }
182
+
183
+ // Signal to waitForCallback - capture refs before they could be cleared
184
+ const resolve = this.#callbackResolve;
185
+ const reject = this.#callbackReject;
186
+ queueMicrotask(() => {
187
+ if (resultState.ok) {
188
+ resolve?.({ code: resultState.code, state: resultState.state });
189
+ } else {
190
+ reject?.(resultState.error ?? "Unknown error");
191
+ }
192
+ });
193
+
194
+ return new Response(
195
+ (templateHtml as unknown as string).replaceAll("__OAUTH_STATE__", JSON.stringify(resultState)),
196
+ {
197
+ status: resultState.ok ? 200 : 500,
198
+ headers: { "Content-Type": "text/html" },
199
+ },
200
+ );
201
+ }
202
+
203
+ /**
204
+ * Wait for OAuth callback or manual input (whichever comes first).
205
+ */
206
+ #waitForCallback(expectedState: string): Promise<CallbackResult> {
207
+ const timeoutSignal = AbortSignal.timeout(DEFAULT_TIMEOUT);
208
+ const signal = this.ctrl.signal ? AbortSignal.any([this.ctrl.signal, timeoutSignal]) : timeoutSignal;
209
+
210
+ const callbackPromise = new Promise<CallbackResult>((resolve, reject) => {
211
+ this.#callbackResolve = resolve;
212
+ this.#callbackReject = reject;
213
+
214
+ signal.addEventListener("abort", () => {
215
+ this.#callbackResolve = undefined;
216
+ this.#callbackReject = undefined;
217
+ reject(new Error(`OAuth callback cancelled: ${signal.reason}`));
218
+ });
219
+ });
220
+
221
+ // Manual input race (if supported)
222
+ if (this.ctrl.onManualCodeInput) {
223
+ const requestManualInput = this.ctrl.onManualCodeInput;
224
+ const manualPromise = (async (): Promise<CallbackResult> => {
225
+ while (true) {
226
+ const result = await Promise.race([
227
+ callbackPromise,
228
+ requestManualInput()
229
+ .then((input): CallbackResult | null => {
230
+ const parsed = parseCallbackInput(input);
231
+ if (!parsed.code) return null;
232
+ if (expectedState && parsed.state && parsed.state !== expectedState) return null;
233
+ return { code: parsed.code, state: parsed.state ?? "" };
234
+ })
235
+ .catch((): CallbackResult | null => null),
236
+ ]);
237
+ if (result) return result;
238
+ }
239
+ })();
240
+
241
+ return Promise.race([callbackPromise, manualPromise]);
242
+ }
243
+
244
+ return callbackPromise;
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Parse a redirect URL or code string to extract code and state.
250
+ */
251
+ export function parseCallbackInput(input: string): { code?: string; state?: string } {
252
+ const value = input.trim();
253
+ if (!value) return {};
254
+
255
+ try {
256
+ const url = new URL(value);
257
+ return {
258
+ code: url.searchParams.get("code") ?? undefined,
259
+ state: url.searchParams.get("state") ?? undefined,
260
+ };
261
+ } catch {
262
+ // Not a URL - check for query string format
263
+ }
264
+
265
+ if (value.includes("code=")) {
266
+ const params = new URLSearchParams(value.replace(/^[?#]/, ""));
267
+ return {
268
+ code: params.get("code") ?? undefined,
269
+ state: params.get("state") ?? undefined,
270
+ };
271
+ }
272
+
273
+ // Assume raw code, possibly with state after #
274
+ const [code, state] = value.split("#", 2);
275
+ return { code, state };
276
+ }
@@ -0,0 +1,16 @@
1
+ /** Cerebras login flow (API key paste against https://api.cerebras.ai/v1). */
2
+ import { createApiKeyLogin } from "./api-key-login";
3
+
4
+ export const loginCerebras = createApiKeyLogin({
5
+ providerLabel: "Cerebras",
6
+ authUrl: "https://cloud.cerebras.ai/platform/",
7
+ instructions: "Copy your API key from the Cerebras dashboard",
8
+ promptMessage: "Paste your Cerebras API key",
9
+ placeholder: "csk-...",
10
+ validation: {
11
+ kind: "chat-completions",
12
+ provider: "Cerebras",
13
+ baseUrl: "https://api.cerebras.ai/v1",
14
+ model: "gpt-oss-120b",
15
+ },
16
+ });
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Cloudflare AI Gateway login flow.
3
+ *
4
+ * Cloudflare AI Gateway proxies upstream model providers.
5
+ *
6
+ * This is not OAuth - it's a simple API key flow:
7
+ * 1. Open Cloudflare AI Gateway docs/dashboard
8
+ * 2. User copies their Cloudflare AI Gateway token/API key
9
+ * 3. User pastes the API key into the CLI
10
+ */
11
+
12
+ import type { OAuthController } from "./types";
13
+
14
+ const AUTH_URL = "https://developers.cloudflare.com/ai-gateway/configuration/authentication/";
15
+
16
+ /**
17
+ * Login to Cloudflare AI Gateway.
18
+ *
19
+ * Opens browser to Cloudflare AI Gateway authentication docs and prompts for a gateway token/API key.
20
+ * Returns the API key directly (not OAuthCredentials - this isn't OAuth).
21
+ */
22
+ export async function loginCloudflareAiGateway(options: OAuthController): Promise<string> {
23
+ if (!options.onPrompt) {
24
+ throw new Error("Cloudflare AI Gateway login requires onPrompt callback");
25
+ }
26
+
27
+ options.onAuth?.({
28
+ url: AUTH_URL,
29
+ instructions:
30
+ "Copy your Cloudflare AI Gateway token/API key. Configure account/gateway base URL in models config.",
31
+ });
32
+
33
+ const apiKey = await options.onPrompt({
34
+ message: "Paste your Cloudflare AI Gateway token/API key",
35
+ placeholder: "cf-aig-...",
36
+ });
37
+
38
+ if (options.signal?.aborted) {
39
+ throw new Error("Login cancelled");
40
+ }
41
+
42
+ const trimmed = apiKey.trim();
43
+ if (!trimmed) {
44
+ throw new Error("API key is required");
45
+ }
46
+
47
+ return trimmed;
48
+ }
@@ -0,0 +1,157 @@
1
+ import { generatePKCE } from "./pkce";
2
+ import type { OAuthCredentials } from "./types";
3
+
4
+ const CURSOR_LOGIN_URL = "https://cursor.com/loginDeepControl";
5
+ const CURSOR_POLL_URL = "https://api2.cursor.sh/auth/poll";
6
+ const CURSOR_REFRESH_URL = "https://api2.cursor.sh/auth/exchange_user_api_key";
7
+
8
+ const POLL_MAX_ATTEMPTS = 150;
9
+ const POLL_BASE_DELAY = 1000;
10
+ const POLL_MAX_DELAY = 10000;
11
+ const POLL_BACKOFF_MULTIPLIER = 1.2;
12
+
13
+ export interface CursorAuthParams {
14
+ verifier: string;
15
+ challenge: string;
16
+ uuid: string;
17
+ loginUrl: string;
18
+ }
19
+
20
+ export async function generateCursorAuthParams(): Promise<CursorAuthParams> {
21
+ const { verifier, challenge } = await generatePKCE();
22
+ const uuid = crypto.randomUUID();
23
+
24
+ const params = new URLSearchParams({
25
+ challenge,
26
+ uuid,
27
+ mode: "login",
28
+ redirectTarget: "cli",
29
+ });
30
+
31
+ const loginUrl = `${CURSOR_LOGIN_URL}?${params.toString()}`;
32
+
33
+ return { verifier, challenge, uuid, loginUrl };
34
+ }
35
+
36
+ export async function pollCursorAuth(
37
+ uuid: string,
38
+ verifier: string,
39
+ ): Promise<{ accessToken: string; refreshToken: string }> {
40
+ let delay = POLL_BASE_DELAY;
41
+ let consecutiveErrors = 0;
42
+
43
+ for (let attempt = 0; attempt < POLL_MAX_ATTEMPTS; attempt++) {
44
+ await Bun.sleep(delay);
45
+
46
+ try {
47
+ const response = await fetch(`${CURSOR_POLL_URL}?uuid=${uuid}&verifier=${verifier}`);
48
+
49
+ if (response.status === 404) {
50
+ consecutiveErrors = 0;
51
+ delay = Math.min(delay * POLL_BACKOFF_MULTIPLIER, POLL_MAX_DELAY);
52
+ continue;
53
+ }
54
+
55
+ if (response.ok) {
56
+ const data = (await response.json()) as {
57
+ accessToken: string;
58
+ refreshToken: string;
59
+ };
60
+ return {
61
+ accessToken: data.accessToken,
62
+ refreshToken: data.refreshToken,
63
+ };
64
+ }
65
+
66
+ throw new Error(`Poll failed: ${response.status}`);
67
+ } catch {
68
+ consecutiveErrors++;
69
+ if (consecutiveErrors >= 3) {
70
+ throw new Error("Too many consecutive errors during Cursor auth polling");
71
+ }
72
+ }
73
+ }
74
+
75
+ throw new Error("Cursor authentication polling timeout");
76
+ }
77
+
78
+ export async function loginCursor(
79
+ onAuthUrl: (url: string) => void,
80
+ onPollStart?: () => void,
81
+ ): Promise<OAuthCredentials> {
82
+ const { verifier, uuid, loginUrl } = await generateCursorAuthParams();
83
+
84
+ onAuthUrl(loginUrl);
85
+ onPollStart?.();
86
+
87
+ const { accessToken, refreshToken } = await pollCursorAuth(uuid, verifier);
88
+
89
+ const expiresAt = getTokenExpiry(accessToken);
90
+
91
+ return {
92
+ access: accessToken,
93
+ refresh: refreshToken,
94
+ expires: expiresAt,
95
+ };
96
+ }
97
+
98
+ export async function refreshCursorToken(apiKeyOrRefreshToken: string): Promise<OAuthCredentials> {
99
+ const response = await fetch(CURSOR_REFRESH_URL, {
100
+ method: "POST",
101
+ headers: {
102
+ Authorization: `Bearer ${apiKeyOrRefreshToken}`,
103
+ "Content-Type": "application/json",
104
+ },
105
+ body: "{}",
106
+ });
107
+
108
+ if (!response.ok) {
109
+ const error = await response.text();
110
+ throw new Error(`Cursor token refresh failed: ${error}`);
111
+ }
112
+
113
+ const data = (await response.json()) as {
114
+ accessToken: string;
115
+ refreshToken: string;
116
+ };
117
+
118
+ const expiresAt = getTokenExpiry(data.accessToken);
119
+
120
+ return {
121
+ access: data.accessToken,
122
+ refresh: data.refreshToken || apiKeyOrRefreshToken,
123
+ expires: expiresAt,
124
+ };
125
+ }
126
+
127
+ function getTokenExpiry(token: string): number {
128
+ try {
129
+ const parts = token.split(".");
130
+ if (parts.length !== 3) {
131
+ return Date.now() + 3600 * 1000;
132
+ }
133
+ const payload = parts[1];
134
+ if (!payload) {
135
+ return Date.now() + 3600 * 1000;
136
+ }
137
+ const decoded = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
138
+ if (decoded && typeof decoded === "object" && typeof decoded.exp === "number") {
139
+ return decoded.exp * 1000 - 5 * 60 * 1000;
140
+ }
141
+ } catch {
142
+ // Ignore parsing errors
143
+ }
144
+ return Date.now() + 3600 * 1000;
145
+ }
146
+
147
+ export function isCursorTokenExpiringSoon(token: string, thresholdSeconds = 300): boolean {
148
+ try {
149
+ const [, payload] = token.split(".");
150
+ if (!payload) return true;
151
+ const decoded = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
152
+ const currentTime = Math.floor(Date.now() / 1000);
153
+ return decoded.exp - currentTime < thresholdSeconds;
154
+ } catch {
155
+ return true;
156
+ }
157
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * DeepSeek login flow (API key paste against https://api.deepseek.com).
3
+ *
4
+ * Validation hits `GET /v1/models` so it authenticates the key without
5
+ * depending on a specific model being enabled on the account. The previous
6
+ * implementation issued a chat-completion against `deepseek-v4-pro`, which
7
+ * 404s for accounts without that preview model even when the key is valid.
8
+ */
9
+ import { createApiKeyLogin } from "./api-key-login";
10
+ import type { OAuthController, OAuthPrompt } from "./types";
11
+
12
+ const innerLogin = createApiKeyLogin({
13
+ providerLabel: "DeepSeek",
14
+ authUrl: "https://platform.deepseek.com/api_keys",
15
+ instructions: "Create or copy your API key from the DeepSeek dashboard",
16
+ promptMessage: "Paste your DeepSeek API key",
17
+ placeholder: "sk-...",
18
+ validation: {
19
+ kind: "models-endpoint",
20
+ provider: "deepseek",
21
+ modelsUrl: "https://api.deepseek.com/v1/models",
22
+ },
23
+ });
24
+
25
+ /**
26
+ * Normalize a pasted DeepSeek API key.
27
+ *
28
+ * Users frequently copy keys out of `curl` snippets that include the
29
+ * `Authorization: Bearer …` prefix. Strip it so validation does not fail
30
+ * with a confusing 401, and reject obviously empty input early.
31
+ */
32
+ export function normalizeDeepSeekApiKey(raw: string): string {
33
+ const trimmed = raw.trim();
34
+ if (!trimmed) {
35
+ return trimmed; // let the shared factory throw the canonical "API key is required"
36
+ }
37
+ const stripped = trimmed.replace(/^bearer\b\s*/i, "");
38
+ if (!stripped) {
39
+ throw new Error("DeepSeek API key is empty after stripping Bearer prefix");
40
+ }
41
+ return stripped;
42
+ }
43
+
44
+ export const loginDeepSeek = async (options: OAuthController): Promise<string> => {
45
+ const userOnPrompt = options.onPrompt;
46
+ const wrapped: OAuthController = userOnPrompt
47
+ ? {
48
+ ...options,
49
+ onPrompt: async (prompt: OAuthPrompt) => normalizeDeepSeekApiKey(await userOnPrompt(prompt)),
50
+ }
51
+ : options;
52
+ return innerLogin(wrapped);
53
+ };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Fire Pass login flow.
3
+ *
4
+ * Fire Pass is a Fireworks subscription product whose dedicated `fpk_…` API
5
+ * keys are scoped to the `accounts/fireworks/routers/kimi-k2p6-turbo` router
6
+ * (Kimi K2.6 Turbo). The key does NOT authorize `/v1/models`, so validation
7
+ * pings the chat completions endpoint with the router id directly.
8
+ * See https://docs.fireworks.ai/firepass.
9
+ */
10
+ import { createApiKeyLogin } from "./api-key-login";
11
+
12
+ export const loginFirepass = createApiKeyLogin({
13
+ providerLabel: "Fire Pass",
14
+ authUrl: "https://app.fireworks.ai/settings/users/api-keys",
15
+ instructions: "Create a dedicated Fire Pass API key in the Fireworks dashboard",
16
+ promptMessage: "Paste your Fire Pass API key",
17
+ placeholder: "fpk_...",
18
+ validation: {
19
+ kind: "chat-completions",
20
+ provider: "Fire Pass",
21
+ baseUrl: "https://api.fireworks.ai/inference/v1",
22
+ model: "accounts/fireworks/routers/kimi-k2p6-turbo",
23
+ },
24
+ });
@@ -0,0 +1,15 @@
1
+ /** Fireworks login flow (API key paste against https://api.fireworks.ai/inference/v1). */
2
+ import { createApiKeyLogin } from "./api-key-login";
3
+
4
+ export const loginFireworks = createApiKeyLogin({
5
+ providerLabel: "Fireworks",
6
+ authUrl: "https://app.fireworks.ai/settings/users/api-keys",
7
+ instructions: "Create or copy your Fireworks API key",
8
+ promptMessage: "Paste your Fireworks API key",
9
+ placeholder: "fw_...",
10
+ validation: {
11
+ kind: "models-endpoint",
12
+ provider: "Fireworks",
13
+ modelsUrl: "https://api.fireworks.ai/inference/v1/models",
14
+ },
15
+ });