@gajae-code/ai 0.1.1

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 (349) hide show
  1. package/CHANGELOG.md +2644 -0
  2. package/README.md +1181 -0
  3. package/dist/types/api-registry.d.ts +30 -0
  4. package/dist/types/auth-broker/client.d.ts +66 -0
  5. package/dist/types/auth-broker/index.d.ts +5 -0
  6. package/dist/types/auth-broker/refresher.d.ts +25 -0
  7. package/dist/types/auth-broker/remote-store.d.ts +96 -0
  8. package/dist/types/auth-broker/server.d.ts +32 -0
  9. package/dist/types/auth-broker/types.d.ts +105 -0
  10. package/dist/types/auth-broker/wire-schemas.d.ts +412 -0
  11. package/dist/types/auth-gateway/http.d.ts +39 -0
  12. package/dist/types/auth-gateway/index.d.ts +3 -0
  13. package/dist/types/auth-gateway/server.d.ts +17 -0
  14. package/dist/types/auth-gateway/types.d.ts +115 -0
  15. package/dist/types/auth-storage.d.ts +641 -0
  16. package/dist/types/cli.d.ts +2 -0
  17. package/dist/types/index.d.ts +49 -0
  18. package/dist/types/model-cache.d.ts +17 -0
  19. package/dist/types/model-manager.d.ts +62 -0
  20. package/dist/types/model-thinking.d.ts +71 -0
  21. package/dist/types/models.d.ts +12 -0
  22. package/dist/types/provider-details.d.ts +24 -0
  23. package/dist/types/provider-models/bundled-references.d.ts +4 -0
  24. package/dist/types/provider-models/descriptors.d.ts +48 -0
  25. package/dist/types/provider-models/google.d.ts +20 -0
  26. package/dist/types/provider-models/index.d.ts +5 -0
  27. package/dist/types/provider-models/ollama.d.ts +7 -0
  28. package/dist/types/provider-models/openai-compat.d.ts +237 -0
  29. package/dist/types/provider-models/special.d.ts +16 -0
  30. package/dist/types/providers/amazon-bedrock.d.ts +36 -0
  31. package/dist/types/providers/anthropic-messages-server-schema.d.ts +450 -0
  32. package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
  33. package/dist/types/providers/anthropic.d.ts +188 -0
  34. package/dist/types/providers/aws-credentials.d.ts +43 -0
  35. package/dist/types/providers/aws-eventstream.d.ts +38 -0
  36. package/dist/types/providers/aws-sigv4.d.ts +55 -0
  37. package/dist/types/providers/azure-openai-responses.d.ts +15 -0
  38. package/dist/types/providers/cursor/gen/agent_pb.d.ts +13022 -0
  39. package/dist/types/providers/cursor.d.ts +42 -0
  40. package/dist/types/providers/error-message.d.ts +27 -0
  41. package/dist/types/providers/github-copilot-headers.d.ts +40 -0
  42. package/dist/types/providers/gitlab-duo.d.ts +27 -0
  43. package/dist/types/providers/google-auth.d.ts +24 -0
  44. package/dist/types/providers/google-gemini-cli.d.ts +72 -0
  45. package/dist/types/providers/google-gemini-headers.d.ts +18 -0
  46. package/dist/types/providers/google-shared.d.ts +163 -0
  47. package/dist/types/providers/google-types.d.ts +138 -0
  48. package/dist/types/providers/google-vertex.d.ts +7 -0
  49. package/dist/types/providers/google.d.ts +4 -0
  50. package/dist/types/providers/grammar.d.ts +1 -0
  51. package/dist/types/providers/kimi.d.ts +27 -0
  52. package/dist/types/providers/mock.d.ts +175 -0
  53. package/dist/types/providers/ollama.d.ts +6 -0
  54. package/dist/types/providers/openai-anthropic-shim.d.ts +31 -0
  55. package/dist/types/providers/openai-chat-server-schema.d.ts +814 -0
  56. package/dist/types/providers/openai-chat-server.d.ts +16 -0
  57. package/dist/types/providers/openai-codex/constants.d.ts +26 -0
  58. package/dist/types/providers/openai-codex/request-transformer.d.ts +49 -0
  59. package/dist/types/providers/openai-codex/response-handler.d.ts +17 -0
  60. package/dist/types/providers/openai-codex-responses.d.ts +67 -0
  61. package/dist/types/providers/openai-completions-compat.d.ts +25 -0
  62. package/dist/types/providers/openai-completions.d.ts +33 -0
  63. package/dist/types/providers/openai-responses-server-schema.d.ts +392 -0
  64. package/dist/types/providers/openai-responses-server.d.ts +17 -0
  65. package/dist/types/providers/openai-responses-shared.d.ts +89 -0
  66. package/dist/types/providers/openai-responses.d.ts +32 -0
  67. package/dist/types/providers/pi-native-client.d.ts +13 -0
  68. package/dist/types/providers/pi-native-server.d.ts +68 -0
  69. package/dist/types/providers/register-builtins.d.ts +31 -0
  70. package/dist/types/providers/synthetic.d.ts +26 -0
  71. package/dist/types/providers/transform-messages.d.ts +12 -0
  72. package/dist/types/providers/vision-guard.d.ts +8 -0
  73. package/dist/types/rate-limit-utils.d.ts +19 -0
  74. package/dist/types/stream.d.ts +24 -0
  75. package/dist/types/types.d.ts +746 -0
  76. package/dist/types/usage/claude.d.ts +3 -0
  77. package/dist/types/usage/gemini.d.ts +2 -0
  78. package/dist/types/usage/github-copilot.d.ts +7 -0
  79. package/dist/types/usage/google-antigravity.d.ts +2 -0
  80. package/dist/types/usage/kimi.d.ts +2 -0
  81. package/dist/types/usage/minimax-code.d.ts +2 -0
  82. package/dist/types/usage/openai-codex.d.ts +3 -0
  83. package/dist/types/usage/shared.d.ts +1 -0
  84. package/dist/types/usage/zai.d.ts +2 -0
  85. package/dist/types/usage.d.ts +258 -0
  86. package/dist/types/utils/abort.d.ts +19 -0
  87. package/dist/types/utils/anthropic-auth.d.ts +31 -0
  88. package/dist/types/utils/discovery/antigravity.d.ts +61 -0
  89. package/dist/types/utils/discovery/codex.d.ts +38 -0
  90. package/dist/types/utils/discovery/cursor.d.ts +23 -0
  91. package/dist/types/utils/discovery/gemini.d.ts +25 -0
  92. package/dist/types/utils/discovery/index.d.ts +4 -0
  93. package/dist/types/utils/discovery/openai-compatible.d.ts +72 -0
  94. package/dist/types/utils/event-stream.d.ts +28 -0
  95. package/dist/types/utils/fireworks-model-id.d.ts +10 -0
  96. package/dist/types/utils/foundry.d.ts +1 -0
  97. package/dist/types/utils/h2-fetch.d.ts +22 -0
  98. package/dist/types/utils/http-inspector.d.ts +31 -0
  99. package/dist/types/utils/idle-iterator.d.ts +67 -0
  100. package/dist/types/utils/json-parse.d.ts +10 -0
  101. package/dist/types/utils/oauth/alibaba-coding-plan.d.ts +18 -0
  102. package/dist/types/utils/oauth/anthropic.d.ts +22 -0
  103. package/dist/types/utils/oauth/api-key-login.d.ts +35 -0
  104. package/dist/types/utils/oauth/api-key-validation.d.ts +27 -0
  105. package/dist/types/utils/oauth/callback-server.d.ts +57 -0
  106. package/dist/types/utils/oauth/cerebras.d.ts +1 -0
  107. package/dist/types/utils/oauth/cloudflare-ai-gateway.d.ts +18 -0
  108. package/dist/types/utils/oauth/cursor.d.ts +15 -0
  109. package/dist/types/utils/oauth/deepseek.d.ts +10 -0
  110. package/dist/types/utils/oauth/firepass.d.ts +1 -0
  111. package/dist/types/utils/oauth/fireworks.d.ts +1 -0
  112. package/dist/types/utils/oauth/github-copilot.d.ts +38 -0
  113. package/dist/types/utils/oauth/gitlab-duo.d.ts +3 -0
  114. package/dist/types/utils/oauth/google-antigravity.d.ts +11 -0
  115. package/dist/types/utils/oauth/google-gemini-cli.d.ts +10 -0
  116. package/dist/types/utils/oauth/google-oauth-shared.d.ts +28 -0
  117. package/dist/types/utils/oauth/huggingface.d.ts +19 -0
  118. package/dist/types/utils/oauth/index.d.ts +38 -0
  119. package/dist/types/utils/oauth/kagi.d.ts +17 -0
  120. package/dist/types/utils/oauth/kilo.d.ts +5 -0
  121. package/dist/types/utils/oauth/kimi.d.ts +21 -0
  122. package/dist/types/utils/oauth/litellm.d.ts +18 -0
  123. package/dist/types/utils/oauth/lm-studio.d.ts +17 -0
  124. package/dist/types/utils/oauth/minimax-code.d.ts +28 -0
  125. package/dist/types/utils/oauth/moonshot.d.ts +1 -0
  126. package/dist/types/utils/oauth/nanogpt.d.ts +1 -0
  127. package/dist/types/utils/oauth/nvidia.d.ts +18 -0
  128. package/dist/types/utils/oauth/ollama-cloud.d.ts +2 -0
  129. package/dist/types/utils/oauth/ollama.d.ts +18 -0
  130. package/dist/types/utils/oauth/openai-codex.d.ts +21 -0
  131. package/dist/types/utils/oauth/opencode.d.ts +18 -0
  132. package/dist/types/utils/oauth/parallel.d.ts +17 -0
  133. package/dist/types/utils/oauth/perplexity.d.ts +9 -0
  134. package/dist/types/utils/oauth/pkce.d.ts +8 -0
  135. package/dist/types/utils/oauth/qianfan.d.ts +17 -0
  136. package/dist/types/utils/oauth/qwen-portal.d.ts +19 -0
  137. package/dist/types/utils/oauth/synthetic.d.ts +1 -0
  138. package/dist/types/utils/oauth/tavily.d.ts +17 -0
  139. package/dist/types/utils/oauth/together.d.ts +1 -0
  140. package/dist/types/utils/oauth/types.d.ts +44 -0
  141. package/dist/types/utils/oauth/venice.d.ts +18 -0
  142. package/dist/types/utils/oauth/vercel-ai-gateway.d.ts +18 -0
  143. package/dist/types/utils/oauth/vllm.d.ts +16 -0
  144. package/dist/types/utils/oauth/xiaomi.d.ts +19 -0
  145. package/dist/types/utils/oauth/zai.d.ts +18 -0
  146. package/dist/types/utils/oauth/zenmux.d.ts +1 -0
  147. package/dist/types/utils/overflow.d.ts +54 -0
  148. package/dist/types/utils/parse-bind.d.ts +23 -0
  149. package/dist/types/utils/provider-response.d.ts +3 -0
  150. package/dist/types/utils/retry-after.d.ts +3 -0
  151. package/dist/types/utils/retry.d.ts +26 -0
  152. package/dist/types/utils/schema/adapt.d.ts +24 -0
  153. package/dist/types/utils/schema/compatibility.d.ts +30 -0
  154. package/dist/types/utils/schema/dereference.d.ts +11 -0
  155. package/dist/types/utils/schema/draft.d.ts +10 -0
  156. package/dist/types/utils/schema/equality.d.ts +4 -0
  157. package/dist/types/utils/schema/fields.d.ts +49 -0
  158. package/dist/types/utils/schema/index.d.ts +13 -0
  159. package/dist/types/utils/schema/json-schema-validator.d.ts +12 -0
  160. package/dist/types/utils/schema/meta-validator.d.ts +2 -0
  161. package/dist/types/utils/schema/normalize.d.ts +93 -0
  162. package/dist/types/utils/schema/spill.d.ts +8 -0
  163. package/dist/types/utils/schema/stamps.d.ts +25 -0
  164. package/dist/types/utils/schema/types.d.ts +4 -0
  165. package/dist/types/utils/schema/wire.d.ts +54 -0
  166. package/dist/types/utils/schema/zod-decontaminate.d.ts +31 -0
  167. package/dist/types/utils/sse-debug.d.ts +10 -0
  168. package/dist/types/utils/tool-call-healing.d.ts +71 -0
  169. package/dist/types/utils/tool-choice.d.ts +50 -0
  170. package/dist/types/utils/validation.d.ts +17 -0
  171. package/dist/types/utils.d.ts +28 -0
  172. package/package.json +146 -0
  173. package/src/api-registry.ts +96 -0
  174. package/src/auth-broker/client.ts +358 -0
  175. package/src/auth-broker/index.ts +5 -0
  176. package/src/auth-broker/refresher.ts +127 -0
  177. package/src/auth-broker/remote-store.ts +623 -0
  178. package/src/auth-broker/server.ts +644 -0
  179. package/src/auth-broker/types.ts +127 -0
  180. package/src/auth-broker/wire-schemas.ts +200 -0
  181. package/src/auth-gateway/http.ts +194 -0
  182. package/src/auth-gateway/index.ts +3 -0
  183. package/src/auth-gateway/server.ts +717 -0
  184. package/src/auth-gateway/types.ts +134 -0
  185. package/src/auth-storage.ts +4104 -0
  186. package/src/cli.ts +262 -0
  187. package/src/index.ts +54 -0
  188. package/src/model-cache.ts +129 -0
  189. package/src/model-manager.ts +450 -0
  190. package/src/model-thinking.ts +691 -0
  191. package/src/models.json +73853 -0
  192. package/src/models.json.d.ts +9 -0
  193. package/src/models.ts +56 -0
  194. package/src/prompts/turn-aborted-guidance.md +4 -0
  195. package/src/provider-details.ts +90 -0
  196. package/src/provider-models/bundled-references.ts +38 -0
  197. package/src/provider-models/descriptors.ts +308 -0
  198. package/src/provider-models/google.ts +91 -0
  199. package/src/provider-models/index.ts +5 -0
  200. package/src/provider-models/ollama.ts +153 -0
  201. package/src/provider-models/openai-compat.ts +2275 -0
  202. package/src/provider-models/special.ts +67 -0
  203. package/src/providers/amazon-bedrock.ts +849 -0
  204. package/src/providers/anthropic-messages-server-schema.ts +229 -0
  205. package/src/providers/anthropic-messages-server.ts +677 -0
  206. package/src/providers/anthropic.ts +2696 -0
  207. package/src/providers/aws-credentials.ts +501 -0
  208. package/src/providers/aws-eventstream.ts +185 -0
  209. package/src/providers/aws-sigv4.ts +218 -0
  210. package/src/providers/azure-openai-responses.ts +337 -0
  211. package/src/providers/cursor/gen/agent_pb.ts +15274 -0
  212. package/src/providers/cursor/proto/agent.proto +3526 -0
  213. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  214. package/src/providers/cursor/proto/buf.yaml +17 -0
  215. package/src/providers/cursor.ts +2561 -0
  216. package/src/providers/error-message.ts +21 -0
  217. package/src/providers/github-copilot-headers.ts +140 -0
  218. package/src/providers/gitlab-duo.ts +372 -0
  219. package/src/providers/google-auth.ts +252 -0
  220. package/src/providers/google-gemini-cli.ts +795 -0
  221. package/src/providers/google-gemini-headers.ts +41 -0
  222. package/src/providers/google-shared.ts +902 -0
  223. package/src/providers/google-types.ts +167 -0
  224. package/src/providers/google-vertex.ts +88 -0
  225. package/src/providers/google.ts +41 -0
  226. package/src/providers/grammar.ts +70 -0
  227. package/src/providers/kimi.ts +52 -0
  228. package/src/providers/mock.ts +500 -0
  229. package/src/providers/ollama.ts +544 -0
  230. package/src/providers/openai-anthropic-shim.ts +138 -0
  231. package/src/providers/openai-chat-server-schema.ts +243 -0
  232. package/src/providers/openai-chat-server.ts +628 -0
  233. package/src/providers/openai-codex/constants.ts +43 -0
  234. package/src/providers/openai-codex/request-transformer.ts +161 -0
  235. package/src/providers/openai-codex/response-handler.ts +81 -0
  236. package/src/providers/openai-codex-responses.ts +2598 -0
  237. package/src/providers/openai-completions-compat.ts +279 -0
  238. package/src/providers/openai-completions.ts +1853 -0
  239. package/src/providers/openai-responses-server-schema.ts +290 -0
  240. package/src/providers/openai-responses-server.ts +1183 -0
  241. package/src/providers/openai-responses-shared.ts +800 -0
  242. package/src/providers/openai-responses.ts +621 -0
  243. package/src/providers/pi-native-client.ts +228 -0
  244. package/src/providers/pi-native-server.ts +210 -0
  245. package/src/providers/register-builtins.ts +412 -0
  246. package/src/providers/synthetic.ts +50 -0
  247. package/src/providers/transform-messages.ts +309 -0
  248. package/src/providers/vision-guard.ts +31 -0
  249. package/src/rate-limit-utils.ts +84 -0
  250. package/src/stream.ts +895 -0
  251. package/src/types.ts +884 -0
  252. package/src/usage/claude.ts +431 -0
  253. package/src/usage/gemini.ts +250 -0
  254. package/src/usage/github-copilot.ts +421 -0
  255. package/src/usage/google-antigravity.ts +201 -0
  256. package/src/usage/kimi.ts +271 -0
  257. package/src/usage/minimax-code.ts +31 -0
  258. package/src/usage/openai-codex.ts +503 -0
  259. package/src/usage/shared.ts +10 -0
  260. package/src/usage/zai.ts +247 -0
  261. package/src/usage.ts +183 -0
  262. package/src/utils/abort.ts +51 -0
  263. package/src/utils/anthropic-auth.ts +87 -0
  264. package/src/utils/discovery/antigravity.ts +261 -0
  265. package/src/utils/discovery/codex.ts +371 -0
  266. package/src/utils/discovery/cursor.ts +306 -0
  267. package/src/utils/discovery/gemini.ts +248 -0
  268. package/src/utils/discovery/index.ts +4 -0
  269. package/src/utils/discovery/openai-compatible.ts +224 -0
  270. package/src/utils/event-stream.ts +142 -0
  271. package/src/utils/fireworks-model-id.ts +30 -0
  272. package/src/utils/foundry.ts +8 -0
  273. package/src/utils/h2-fetch.ts +60 -0
  274. package/src/utils/http-inspector.ts +176 -0
  275. package/src/utils/idle-iterator.ts +250 -0
  276. package/src/utils/json-parse.ts +148 -0
  277. package/src/utils/oauth/alibaba-coding-plan.ts +59 -0
  278. package/src/utils/oauth/anthropic.ts +200 -0
  279. package/src/utils/oauth/api-key-login.ts +87 -0
  280. package/src/utils/oauth/api-key-validation.ts +92 -0
  281. package/src/utils/oauth/callback-server.ts +276 -0
  282. package/src/utils/oauth/cerebras.ts +16 -0
  283. package/src/utils/oauth/cloudflare-ai-gateway.ts +48 -0
  284. package/src/utils/oauth/cursor.ts +157 -0
  285. package/src/utils/oauth/deepseek.ts +53 -0
  286. package/src/utils/oauth/firepass.ts +24 -0
  287. package/src/utils/oauth/fireworks.ts +15 -0
  288. package/src/utils/oauth/github-copilot.ts +362 -0
  289. package/src/utils/oauth/gitlab-duo.ts +123 -0
  290. package/src/utils/oauth/google-antigravity.ts +200 -0
  291. package/src/utils/oauth/google-gemini-cli.ts +256 -0
  292. package/src/utils/oauth/google-oauth-shared.ts +110 -0
  293. package/src/utils/oauth/huggingface.ts +62 -0
  294. package/src/utils/oauth/index.ts +444 -0
  295. package/src/utils/oauth/kagi.ts +47 -0
  296. package/src/utils/oauth/kilo.ts +87 -0
  297. package/src/utils/oauth/kimi.ts +254 -0
  298. package/src/utils/oauth/litellm.ts +47 -0
  299. package/src/utils/oauth/lm-studio.ts +38 -0
  300. package/src/utils/oauth/minimax-code.ts +78 -0
  301. package/src/utils/oauth/moonshot.ts +16 -0
  302. package/src/utils/oauth/nanogpt.ts +15 -0
  303. package/src/utils/oauth/nvidia.ts +70 -0
  304. package/src/utils/oauth/oauth.html +199 -0
  305. package/src/utils/oauth/ollama-cloud.ts +28 -0
  306. package/src/utils/oauth/ollama.ts +47 -0
  307. package/src/utils/oauth/openai-codex.ts +299 -0
  308. package/src/utils/oauth/opencode.ts +49 -0
  309. package/src/utils/oauth/parallel.ts +46 -0
  310. package/src/utils/oauth/perplexity.ts +206 -0
  311. package/src/utils/oauth/pkce.ts +18 -0
  312. package/src/utils/oauth/qianfan.ts +58 -0
  313. package/src/utils/oauth/qwen-portal.ts +60 -0
  314. package/src/utils/oauth/synthetic.ts +16 -0
  315. package/src/utils/oauth/tavily.ts +46 -0
  316. package/src/utils/oauth/together.ts +16 -0
  317. package/src/utils/oauth/types.ts +94 -0
  318. package/src/utils/oauth/venice.ts +59 -0
  319. package/src/utils/oauth/vercel-ai-gateway.ts +47 -0
  320. package/src/utils/oauth/vllm.ts +40 -0
  321. package/src/utils/oauth/xiaomi.ts +137 -0
  322. package/src/utils/oauth/zai.ts +60 -0
  323. package/src/utils/oauth/zenmux.ts +15 -0
  324. package/src/utils/overflow.ts +137 -0
  325. package/src/utils/parse-bind.ts +54 -0
  326. package/src/utils/provider-response.ts +30 -0
  327. package/src/utils/retry-after.ts +110 -0
  328. package/src/utils/retry.ts +54 -0
  329. package/src/utils/schema/CONSTRAINTS.md +164 -0
  330. package/src/utils/schema/adapt.ts +36 -0
  331. package/src/utils/schema/compatibility.ts +435 -0
  332. package/src/utils/schema/dereference.ts +98 -0
  333. package/src/utils/schema/draft.ts +341 -0
  334. package/src/utils/schema/equality.ts +97 -0
  335. package/src/utils/schema/fields.ts +190 -0
  336. package/src/utils/schema/index.ts +13 -0
  337. package/src/utils/schema/json-schema-validator.ts +577 -0
  338. package/src/utils/schema/meta-validator.ts +167 -0
  339. package/src/utils/schema/normalize.ts +1588 -0
  340. package/src/utils/schema/spill.ts +43 -0
  341. package/src/utils/schema/stamps.ts +97 -0
  342. package/src/utils/schema/types.ts +11 -0
  343. package/src/utils/schema/wire.ts +213 -0
  344. package/src/utils/schema/zod-decontaminate.ts +331 -0
  345. package/src/utils/sse-debug.ts +289 -0
  346. package/src/utils/tool-call-healing.ts +271 -0
  347. package/src/utils/tool-choice.ts +99 -0
  348. package/src/utils/validation.ts +1019 -0
  349. package/src/utils.ts +166 -0
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Kimi Code OAuth flow (device authorization grant)
3
+ */
4
+
5
+ import * as crypto from "node:crypto";
6
+ import * as fs from "node:fs";
7
+ import * as os from "node:os";
8
+ import * as path from "node:path";
9
+ import { scheduler } from "node:timers/promises";
10
+ import { $env, getAgentDir, isEnoent } from "@gajae-code/utils";
11
+ import packageJson from "../../../package.json" with { type: "json" };
12
+ import type { OAuthController, OAuthCredentials } from "./types";
13
+
14
+ const CLIENT_ID = "17e5f671-d194-4dfb-9706-5516cb48c098";
15
+ const DEFAULT_OAUTH_HOST = "https://auth.kimi.com";
16
+ const DEVICE_ID_FILENAME = "kimi-device-id";
17
+ const DEFAULT_POLL_INTERVAL_MS = 5000;
18
+ const DEFAULT_DEVICE_FLOW_TTL_MS = 15 * 60 * 1000;
19
+ const OAUTH_EXPIRY_SKEW_MS = 5 * 60 * 1000;
20
+
21
+ interface DeviceAuthorizationResponse {
22
+ user_code?: string;
23
+ device_code?: string;
24
+ verification_uri?: string;
25
+ verification_uri_complete?: string;
26
+ expires_in?: number;
27
+ interval?: number;
28
+ }
29
+
30
+ interface TokenResponse {
31
+ access_token?: string;
32
+ refresh_token?: string;
33
+ expires_in?: number;
34
+ scope?: string;
35
+ token_type?: string;
36
+ error?: string;
37
+ error_description?: string;
38
+ interval?: number;
39
+ }
40
+
41
+ function resolveOAuthHost(): string {
42
+ return $env.KIMI_CODE_OAUTH_HOST || $env.KIMI_OAUTH_HOST || DEFAULT_OAUTH_HOST;
43
+ }
44
+
45
+ function formatDeviceModel(system: string, release: string, arch: string): string {
46
+ return [system, release, arch].filter(Boolean).join(" ").trim();
47
+ }
48
+
49
+ function getDeviceModel(): string {
50
+ const platform = os.platform();
51
+ const release = os.release();
52
+ const arch = os.arch();
53
+ if (platform === "darwin") return formatDeviceModel("macOS", release, arch);
54
+ if (platform === "win32") return formatDeviceModel("Windows", release, arch);
55
+ const label = platform === "linux" ? "Linux" : platform;
56
+ return formatDeviceModel(label, release, arch);
57
+ }
58
+
59
+ let getDeviceId = (): string => {
60
+ const deviceIdPath = path.join(getAgentDir(), DEVICE_ID_FILENAME);
61
+ try {
62
+ const existing = fs.readFileSync(deviceIdPath, "utf-8");
63
+ const trimmed = existing.trim();
64
+ if (trimmed) {
65
+ getDeviceId = () => trimmed;
66
+ return trimmed;
67
+ }
68
+ } catch (error) {
69
+ if (!isEnoent(error)) throw error;
70
+ }
71
+
72
+ const deviceId = crypto.randomUUID().replace(/-/g, "");
73
+ fs.writeFileSync(deviceIdPath, `${deviceId}\n`, { mode: 0o600 });
74
+ getDeviceId = () => deviceId;
75
+ return deviceId;
76
+ };
77
+
78
+ export let getKimiCommonHeaders = () => {
79
+ const headers = Object.freeze({
80
+ "User-Agent": `KimiCLI/${packageJson.version}`,
81
+ "X-Msh-Platform": "kimi_cli",
82
+ "X-Msh-Version": packageJson.version,
83
+ "X-Msh-Device-Name": os.hostname(),
84
+ "X-Msh-Device-Model": getDeviceModel(),
85
+ "X-Msh-Os-Version": os.version(),
86
+ "X-Msh-Device-Id": getDeviceId(),
87
+ });
88
+ getKimiCommonHeaders = () => headers;
89
+ return headers;
90
+ };
91
+
92
+ async function requestDeviceAuthorization(): Promise<{
93
+ userCode: string;
94
+ deviceCode: string;
95
+ verificationUri: string;
96
+ verificationUriComplete: string;
97
+ expiresInMs: number;
98
+ intervalMs: number;
99
+ }> {
100
+ const response = await fetch(`${resolveOAuthHost()}/api/oauth/device_authorization`, {
101
+ method: "POST",
102
+ headers: {
103
+ "Content-Type": "application/x-www-form-urlencoded",
104
+ ...getKimiCommonHeaders(),
105
+ },
106
+ body: new URLSearchParams({ client_id: CLIENT_ID }),
107
+ });
108
+
109
+ if (!response.ok) {
110
+ const text = await response.text();
111
+ throw new Error(`Kimi device authorization failed: ${response.status} ${text}`);
112
+ }
113
+
114
+ const payload = (await response.json()) as DeviceAuthorizationResponse;
115
+ const userCode = payload.user_code;
116
+ const deviceCode = payload.device_code;
117
+ const verificationUri = payload.verification_uri;
118
+ const verificationUriComplete = payload.verification_uri_complete;
119
+
120
+ if (!userCode || !deviceCode || !verificationUri) {
121
+ throw new Error("Kimi device authorization response missing required fields");
122
+ }
123
+
124
+ const expiresInMs = typeof payload.expires_in === "number" ? payload.expires_in * 1000 : DEFAULT_DEVICE_FLOW_TTL_MS;
125
+ const intervalMs =
126
+ typeof payload.interval === "number" && payload.interval > 0 ? payload.interval * 1000 : DEFAULT_POLL_INTERVAL_MS;
127
+
128
+ return {
129
+ userCode,
130
+ deviceCode,
131
+ verificationUri,
132
+ verificationUriComplete: verificationUriComplete || verificationUri,
133
+ expiresInMs,
134
+ intervalMs,
135
+ };
136
+ }
137
+
138
+ function parseTokenPayload(payload: TokenResponse, refreshTokenFallback?: string): OAuthCredentials {
139
+ if (!payload.access_token || typeof payload.expires_in !== "number") {
140
+ throw new Error("Kimi token response missing required fields");
141
+ }
142
+
143
+ const refresh = payload.refresh_token ?? refreshTokenFallback;
144
+ if (!refresh) {
145
+ throw new Error("Kimi token response missing refresh token");
146
+ }
147
+
148
+ return {
149
+ access: payload.access_token,
150
+ refresh,
151
+ expires: Date.now() + payload.expires_in * 1000 - OAUTH_EXPIRY_SKEW_MS,
152
+ };
153
+ }
154
+
155
+ async function pollForToken(
156
+ deviceCode: string,
157
+ intervalMs: number,
158
+ expiresInMs: number,
159
+ signal?: AbortSignal,
160
+ ): Promise<OAuthCredentials> {
161
+ const deadline = Date.now() + expiresInMs;
162
+ let waitMs = Math.max(1000, intervalMs);
163
+
164
+ while (Date.now() < deadline) {
165
+ if (signal?.aborted) {
166
+ throw new Error("Login cancelled");
167
+ }
168
+
169
+ const response = await fetch(`${resolveOAuthHost()}/api/oauth/token`, {
170
+ method: "POST",
171
+ headers: {
172
+ "Content-Type": "application/x-www-form-urlencoded",
173
+ ...getKimiCommonHeaders(),
174
+ },
175
+ body: new URLSearchParams({
176
+ client_id: CLIENT_ID,
177
+ device_code: deviceCode,
178
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
179
+ }),
180
+ });
181
+
182
+ const payload = (await response.json()) as TokenResponse;
183
+ if (response.ok && payload.access_token) {
184
+ return parseTokenPayload(payload);
185
+ }
186
+
187
+ const error = payload.error;
188
+ if (error === "authorization_pending") {
189
+ await scheduler.wait(waitMs, { signal });
190
+ continue;
191
+ }
192
+
193
+ if (error === "slow_down") {
194
+ waitMs += 5000;
195
+ const retryAfter = typeof payload.interval === "number" ? payload.interval * 1000 : undefined;
196
+ if (retryAfter && retryAfter > waitMs) waitMs = retryAfter;
197
+ await scheduler.wait(waitMs, { signal });
198
+ continue;
199
+ }
200
+
201
+ if (error === "expired_token") {
202
+ throw new Error("Kimi device authorization expired");
203
+ }
204
+
205
+ if (error === "access_denied") {
206
+ throw new Error("Kimi device authorization denied");
207
+ }
208
+
209
+ const description = payload.error_description ? `: ${payload.error_description}` : "";
210
+ throw new Error(`Kimi device flow failed: ${error ?? response.status}${description}`);
211
+ }
212
+
213
+ throw new Error("Kimi device flow timed out");
214
+ }
215
+
216
+ /**
217
+ * Login with Kimi Code OAuth (device code flow).
218
+ */
219
+ export async function loginKimi(options: OAuthController): Promise<OAuthCredentials> {
220
+ const device = await requestDeviceAuthorization();
221
+ options.onAuth?.({
222
+ url: device.verificationUriComplete,
223
+ instructions: `Enter code: ${device.userCode}`,
224
+ });
225
+
226
+ return pollForToken(device.deviceCode, device.intervalMs, device.expiresInMs, options.signal);
227
+ }
228
+
229
+ /**
230
+ * Refresh Kimi OAuth token.
231
+ */
232
+ export async function refreshKimiToken(refreshToken: string): Promise<OAuthCredentials> {
233
+ const response = await fetch(`${resolveOAuthHost()}/api/oauth/token`, {
234
+ method: "POST",
235
+ headers: {
236
+ "Content-Type": "application/x-www-form-urlencoded",
237
+ ...getKimiCommonHeaders(),
238
+ },
239
+ body: new URLSearchParams({
240
+ grant_type: "refresh_token",
241
+ refresh_token: refreshToken,
242
+ client_id: CLIENT_ID,
243
+ }),
244
+ });
245
+
246
+ if (!response.ok) {
247
+ const payload = (await response.json().catch(() => undefined)) as TokenResponse | undefined;
248
+ const description = payload?.error_description ? `: ${payload.error_description}` : "";
249
+ throw new Error(`Kimi token refresh failed: ${response.status}${description}`);
250
+ }
251
+
252
+ const payload = (await response.json()) as TokenResponse;
253
+ return parseTokenPayload(payload, refreshToken);
254
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * LiteLLM login flow.
3
+ *
4
+ * LiteLLM is an OpenAI-compatible proxy that routes requests to many upstream providers.
5
+ *
6
+ * This is not OAuth - it's a simple API key flow:
7
+ * 1. Open browser to LiteLLM docs/dashboard
8
+ * 2. User copies their LiteLLM 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://docs.litellm.ai/docs/proxy/deploy";
15
+
16
+ /**
17
+ * Login to LiteLLM.
18
+ *
19
+ * Opens browser to LiteLLM setup docs, prompts user to paste their API key.
20
+ * Returns the API key directly (not OAuthCredentials - this isn't OAuth).
21
+ */
22
+ export async function loginLiteLLM(options: OAuthController): Promise<string> {
23
+ if (!options.onPrompt) {
24
+ throw new Error("LiteLLM login requires onPrompt callback");
25
+ }
26
+
27
+ options.onAuth?.({
28
+ url: AUTH_URL,
29
+ instructions: "Run LiteLLM proxy (default http://localhost:4000/v1), then copy your master key or virtual key",
30
+ });
31
+
32
+ const apiKey = await options.onPrompt({
33
+ message: "Paste your LiteLLM API key (master key or virtual key)",
34
+ placeholder: "sk-...",
35
+ });
36
+
37
+ if (options.signal?.aborted) {
38
+ throw new Error("Login cancelled");
39
+ }
40
+
41
+ const trimmed = apiKey.trim();
42
+ if (!trimmed) {
43
+ throw new Error("API key is required");
44
+ }
45
+
46
+ return trimmed;
47
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * LM Studio login flow.
3
+ *
4
+ * LM Studio provides an OpenAI-compatible API at a local base URL.
5
+ * It usually runs unauthenticated but can be configured to require a bearer token.
6
+ *
7
+ * This flow stores an API-key-style credential used by `/login` and auth storage.
8
+ */
9
+
10
+ import type { OAuthController, OAuthProvider } from "./types";
11
+
12
+ const PROVIDER_ID: OAuthProvider = "lm-studio";
13
+ export const DEFAULT_LOCAL_TOKEN = "lm-studio-local";
14
+
15
+ /**
16
+ * Login to LM Studio.
17
+ *
18
+ * Opens LM Studio API docs, prompts for an optional token,
19
+ * and returns a stored key value.
20
+ */
21
+ export async function loginLmStudio(options: OAuthController): Promise<string> {
22
+ if (!options.onPrompt) {
23
+ throw new Error(`${PROVIDER_ID} login requires onPrompt callback`);
24
+ }
25
+
26
+ const apiKey = await options.onPrompt({
27
+ message: "Optional: Paste LM Studio API key (to customize endpoint URL, set LM_STUDIO_BASE_URL env var)",
28
+ placeholder: DEFAULT_LOCAL_TOKEN,
29
+ allowEmpty: true,
30
+ });
31
+
32
+ if (options.signal?.aborted) {
33
+ throw new Error("Login cancelled");
34
+ }
35
+
36
+ const trimmed = apiKey.trim();
37
+ return trimmed || DEFAULT_LOCAL_TOKEN;
38
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * MiniMax Coding Plan login flow.
3
+ *
4
+ * MiniMax Coding Plan is a subscription service that provides access to
5
+ * MiniMax models (M2, M2.1) through an OpenAI-compatible API.
6
+ *
7
+ * This is not OAuth - it's a simple API key flow:
8
+ * 1. Open browser to https://platform.minimax.io/subscribe/coding-plan
9
+ * 2. User subscribes and copies their API key
10
+ * 3. User pastes the API key back into the CLI
11
+ *
12
+ * International: https://api.minimax.io/v1
13
+ * China: https://api.minimaxi.com/v1
14
+ */
15
+
16
+ import { validateOpenAICompatibleApiKey } from "./api-key-validation";
17
+ import type { OAuthController } from "./types";
18
+
19
+ const AUTH_URL = "https://platform.minimax.io/subscribe/coding-plan";
20
+ const API_BASE_URL_INTL = "https://api.minimax.io/v1";
21
+ const API_BASE_URL_CN = "https://api.minimaxi.com/v1";
22
+ const VALIDATION_MODEL = "MiniMax-M2";
23
+
24
+ /**
25
+ * Login to MiniMax Coding Plan (international).
26
+ *
27
+ * Opens browser to subscription page, prompts user to paste their API key.
28
+ * Returns the API key directly (not OAuthCredentials - this isn't OAuth).
29
+ */
30
+ export async function loginMiniMaxCode(options: OAuthController): Promise<string> {
31
+ return loginMiniMaxCodeWithBaseUrl(options, API_BASE_URL_INTL, "MiniMax Coding Plan");
32
+ }
33
+
34
+ async function loginMiniMaxCodeWithBaseUrl(
35
+ options: OAuthController,
36
+ baseUrl: string,
37
+ providerName: string,
38
+ ): Promise<string> {
39
+ if (!options.onPrompt) {
40
+ throw new Error("MiniMax Coding Plan login requires onPrompt callback");
41
+ }
42
+ // Open browser to subscription page
43
+ options.onAuth?.({
44
+ url: AUTH_URL,
45
+ instructions: "Subscribe to Coding Plan and copy your API key",
46
+ });
47
+ // Prompt user to paste their API key
48
+ const apiKey = await options.onPrompt({
49
+ message: "Paste your MiniMax Coding Plan API key",
50
+ placeholder: "sk-...",
51
+ });
52
+ if (options.signal?.aborted) {
53
+ throw new Error("Login cancelled");
54
+ }
55
+ const trimmed = apiKey.trim();
56
+ if (!trimmed) {
57
+ throw new Error("API key is required");
58
+ }
59
+
60
+ options.onProgress?.("Validating API key...");
61
+ await validateOpenAICompatibleApiKey({
62
+ provider: providerName,
63
+ apiKey: trimmed,
64
+ baseUrl,
65
+ model: VALIDATION_MODEL,
66
+ signal: options.signal,
67
+ });
68
+ return trimmed;
69
+ }
70
+
71
+ /**
72
+ * Login to MiniMax Coding Plan (China).
73
+ *
74
+ * Same flow as international but uses China endpoint.
75
+ */
76
+ export async function loginMiniMaxCodeCn(options: OAuthController): Promise<string> {
77
+ return loginMiniMaxCodeWithBaseUrl(options, API_BASE_URL_CN, "MiniMax Coding Plan (China)");
78
+ }
@@ -0,0 +1,16 @@
1
+ /** Moonshot login flow (API key paste against https://api.moonshot.ai/v1). */
2
+ import { createApiKeyLogin } from "./api-key-login";
3
+
4
+ export const loginMoonshot = createApiKeyLogin({
5
+ providerLabel: "Moonshot",
6
+ authUrl: "https://platform.moonshot.ai/console/api-keys",
7
+ instructions: "Copy your API key from the Moonshot dashboard",
8
+ promptMessage: "Paste your Moonshot API key",
9
+ placeholder: "sk-...",
10
+ validation: {
11
+ kind: "chat-completions",
12
+ provider: "moonshot",
13
+ baseUrl: "https://api.moonshot.ai/v1",
14
+ model: "kimi-k2.5",
15
+ },
16
+ });
@@ -0,0 +1,15 @@
1
+ /** NanoGPT login flow (API key paste, validated via /models). */
2
+ import { createApiKeyLogin } from "./api-key-login";
3
+
4
+ export const loginNanoGPT = createApiKeyLogin({
5
+ providerLabel: "NanoGPT",
6
+ authUrl: "https://nano-gpt.com/api",
7
+ instructions: "Create or copy your NanoGPT API key",
8
+ promptMessage: "Paste your NanoGPT API key",
9
+ placeholder: "sk-...",
10
+ validation: {
11
+ kind: "models-endpoint",
12
+ provider: "NanoGPT",
13
+ modelsUrl: "https://nano-gpt.com/api/v1/models",
14
+ },
15
+ });
@@ -0,0 +1,70 @@
1
+ /**
2
+ * NVIDIA login flow.
3
+ *
4
+ * NVIDIA provides OpenAI-compatible models via https://integrate.api.nvidia.com/v1.
5
+ *
6
+ * This is not OAuth - it's a simple API key flow:
7
+ * 1. Open browser to NVIDIA NGC catalog
8
+ * 2. User copies their API key
9
+ * 3. User pastes the API key into the CLI
10
+ */
11
+
12
+ import { validateOpenAICompatibleApiKey } from "./api-key-validation";
13
+ import type { OAuthController } from "./types";
14
+
15
+ const AUTH_URL = "https://org.ngc.nvidia.com/setup/personal-keys";
16
+ const API_BASE_URL = "https://integrate.api.nvidia.com/v1";
17
+ const VALIDATION_MODEL = "nvidia/llama-3.1-nemotron-70b-instruct";
18
+ const PROVIDER_ID = "nvidia";
19
+
20
+ /**
21
+ * Login to NVIDIA.
22
+ *
23
+ * Opens browser to NVIDIA dashboard, prompts user to paste their API key.
24
+ * Returns the API key directly (not OAuthCredentials - this isn't OAuth).
25
+ */
26
+ export async function loginNvidia(options: OAuthController): Promise<string> {
27
+ if (!options.onPrompt) {
28
+ throw new Error("NVIDIA login requires onPrompt callback");
29
+ }
30
+
31
+ options.onAuth?.({
32
+ url: AUTH_URL,
33
+ instructions: "Copy your API key from NVIDIA NGC Personal Keys",
34
+ });
35
+
36
+ const apiKey = await options.onPrompt({
37
+ message: "Paste your NVIDIA API key",
38
+ placeholder: "nvapi-...",
39
+ });
40
+
41
+ if (options.signal?.aborted) {
42
+ throw new Error("Login cancelled");
43
+ }
44
+
45
+ const trimmed = apiKey.trim();
46
+ if (!trimmed) {
47
+ throw new Error("API key is required");
48
+ }
49
+
50
+ options.onProgress?.("Validating API key (optional)...");
51
+ try {
52
+ await validateOpenAICompatibleApiKey({
53
+ provider: PROVIDER_ID,
54
+ apiKey: trimmed,
55
+ baseUrl: API_BASE_URL,
56
+ model: VALIDATION_MODEL,
57
+ signal: options.signal,
58
+ });
59
+ } catch (error) {
60
+ const message = error instanceof Error ? error.message : String(error);
61
+ const statusMatch = message.match(/\((\d{3})\)/);
62
+ const statusCode = statusMatch?.[1];
63
+ if (statusCode === "401" || statusCode === "403") {
64
+ throw error;
65
+ }
66
+ options.onProgress?.("Skipping NVIDIA validation endpoint; continuing with provided API key.");
67
+ }
68
+
69
+ return trimmed;
70
+ }