jeopi-ai 16.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (598) hide show
  1. package/CHANGELOG.md +4347 -0
  2. package/README.md +1193 -0
  3. package/dist/types/api-registry.d.ts +30 -0
  4. package/dist/types/auth-broker/client.d.ts +73 -0
  5. package/dist/types/auth-broker/discover.d.ts +35 -0
  6. package/dist/types/auth-broker/index.d.ts +7 -0
  7. package/dist/types/auth-broker/refresher.d.ts +25 -0
  8. package/dist/types/auth-broker/remote-store.d.ts +102 -0
  9. package/dist/types/auth-broker/server.d.ts +43 -0
  10. package/dist/types/auth-broker/snapshot-cache.d.ts +17 -0
  11. package/dist/types/auth-broker/types.d.ts +107 -0
  12. package/dist/types/auth-broker/wire-schemas.d.ts +411 -0
  13. package/dist/types/auth-gateway/http.d.ts +39 -0
  14. package/dist/types/auth-gateway/index.d.ts +3 -0
  15. package/dist/types/auth-gateway/server.d.ts +36 -0
  16. package/dist/types/auth-gateway/types.d.ts +123 -0
  17. package/dist/types/auth-retry.d.ts +124 -0
  18. package/dist/types/auth-storage.d.ts +1026 -0
  19. package/dist/types/dialect/anthropic.d.ts +15 -0
  20. package/dist/types/dialect/catalog.d.ts +3 -0
  21. package/dist/types/dialect/coercion.d.ts +23 -0
  22. package/dist/types/dialect/deepseek.d.ts +14 -0
  23. package/dist/types/dialect/demotion.d.ts +23 -0
  24. package/dist/types/dialect/examples.d.ts +2 -0
  25. package/dist/types/dialect/factory.d.ts +3 -0
  26. package/dist/types/dialect/fenced-thinking.d.ts +53 -0
  27. package/dist/types/dialect/gemini.d.ts +17 -0
  28. package/dist/types/dialect/gemma.d.ts +15 -0
  29. package/dist/types/dialect/glm.d.ts +9 -0
  30. package/dist/types/dialect/harmony.d.ts +8 -0
  31. package/dist/types/dialect/hermes.d.ts +9 -0
  32. package/dist/types/dialect/history.d.ts +3 -0
  33. package/dist/types/dialect/index.d.ts +11 -0
  34. package/dist/types/dialect/inventory.d.ts +12 -0
  35. package/dist/types/dialect/kimi.d.ts +14 -0
  36. package/dist/types/dialect/minimax.d.ts +3 -0
  37. package/dist/types/dialect/owned-stream.d.ts +4 -0
  38. package/dist/types/dialect/qwen3.d.ts +9 -0
  39. package/dist/types/dialect/rendering.d.ts +45 -0
  40. package/dist/types/dialect/thinking.d.ts +6 -0
  41. package/dist/types/dialect/types.d.ts +69 -0
  42. package/dist/types/dialect/xml.d.ts +9 -0
  43. package/dist/types/error/abort.d.ts +14 -0
  44. package/dist/types/error/auth-classify.d.ts +16 -0
  45. package/dist/types/error/auth.d.ts +27 -0
  46. package/dist/types/error/aws.d.ts +23 -0
  47. package/dist/types/error/classes.d.ts +102 -0
  48. package/dist/types/error/finalize.d.ts +39 -0
  49. package/dist/types/error/flags.d.ts +79 -0
  50. package/dist/types/error/format.d.ts +20 -0
  51. package/dist/types/error/gateway.d.ts +20 -0
  52. package/dist/types/error/index.d.ts +13 -0
  53. package/dist/types/error/oauth.d.ts +43 -0
  54. package/dist/types/error/provider.d.ts +42 -0
  55. package/dist/types/error/rate-limit.d.ts +59 -0
  56. package/dist/types/error/retryable.d.ts +27 -0
  57. package/dist/types/error/validation.d.ts +32 -0
  58. package/dist/types/index.d.ts +49 -0
  59. package/dist/types/provider-details.d.ts +24 -0
  60. package/dist/types/providers/__tests__/google-auth.test.d.ts +1 -0
  61. package/dist/types/providers/__tests__/kimi-code-thinking.test.d.ts +1 -0
  62. package/dist/types/providers/__tests__/openai-codex-error.test.d.ts +1 -0
  63. package/dist/types/providers/amazon-bedrock.d.ts +39 -0
  64. package/dist/types/providers/anthropic-client.d.ts +94 -0
  65. package/dist/types/providers/anthropic-messages-server-schema.d.ts +497 -0
  66. package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
  67. package/dist/types/providers/anthropic-wire.d.ts +318 -0
  68. package/dist/types/providers/anthropic.d.ts +248 -0
  69. package/dist/types/providers/aws-credentials.d.ts +53 -0
  70. package/dist/types/providers/aws-eventstream.d.ts +39 -0
  71. package/dist/types/providers/aws-sigv4.d.ts +55 -0
  72. package/dist/types/providers/azure-openai-responses.d.ts +16 -0
  73. package/dist/types/providers/cursor.d.ts +91 -0
  74. package/dist/types/providers/devin.d.ts +12 -0
  75. package/dist/types/providers/error-message.d.ts +27 -0
  76. package/dist/types/providers/github-copilot-headers.d.ts +40 -0
  77. package/dist/types/providers/gitlab-duo-workflow.d.ts +254 -0
  78. package/dist/types/providers/gitlab-duo.d.ts +27 -0
  79. package/dist/types/providers/google-auth.d.ts +32 -0
  80. package/dist/types/providers/google-gemini-cli.d.ts +118 -0
  81. package/dist/types/providers/google-interactions.d.ts +65 -0
  82. package/dist/types/providers/google-shared.d.ts +203 -0
  83. package/dist/types/providers/google-types.d.ts +155 -0
  84. package/dist/types/providers/google-vertex.d.ts +7 -0
  85. package/dist/types/providers/google.d.ts +4 -0
  86. package/dist/types/providers/grammar.d.ts +1 -0
  87. package/dist/types/providers/kimi.d.ts +27 -0
  88. package/dist/types/providers/mock.d.ts +178 -0
  89. package/dist/types/providers/ollama.d.ts +7 -0
  90. package/dist/types/providers/openai-anthropic-shim.d.ts +31 -0
  91. package/dist/types/providers/openai-chat-server-schema.d.ts +695 -0
  92. package/dist/types/providers/openai-chat-server.d.ts +16 -0
  93. package/dist/types/providers/openai-chat-wire.d.ts +644 -0
  94. package/dist/types/providers/openai-codex/request-transformer.d.ts +54 -0
  95. package/dist/types/providers/openai-codex/response-handler.d.ts +26 -0
  96. package/dist/types/providers/openai-codex-responses.d.ts +108 -0
  97. package/dist/types/providers/openai-completions.d.ts +45 -0
  98. package/dist/types/providers/openai-reasoning-fallback.d.ts +25 -0
  99. package/dist/types/providers/openai-responses-server-schema.d.ts +349 -0
  100. package/dist/types/providers/openai-responses-server.d.ts +17 -0
  101. package/dist/types/providers/openai-responses-wire.d.ts +6065 -0
  102. package/dist/types/providers/openai-responses.d.ts +126 -0
  103. package/dist/types/providers/openai-shared.d.ts +506 -0
  104. package/dist/types/providers/pi-native-client.d.ts +13 -0
  105. package/dist/types/providers/pi-native-server.d.ts +69 -0
  106. package/dist/types/providers/register-builtins.d.ts +32 -0
  107. package/dist/types/providers/synthetic.d.ts +26 -0
  108. package/dist/types/providers/transform-messages.d.ts +11 -0
  109. package/dist/types/providers/vision-guard.d.ts +20 -0
  110. package/dist/types/registry/aimlapi.d.ts +4 -0
  111. package/dist/types/registry/alibaba-coding-plan.d.ts +8 -0
  112. package/dist/types/registry/amazon-bedrock.d.ts +5 -0
  113. package/dist/types/registry/anthropic.d.ts +10 -0
  114. package/dist/types/registry/api-key-login.d.ts +42 -0
  115. package/dist/types/registry/api-key-validation.d.ts +43 -0
  116. package/dist/types/registry/azure.d.ts +4 -0
  117. package/dist/types/registry/cerebras.d.ts +7 -0
  118. package/dist/types/registry/cloudflare-ai-gateway.d.ts +13 -0
  119. package/dist/types/registry/coreweave.d.ts +7 -0
  120. package/dist/types/registry/cursor.d.ts +7 -0
  121. package/dist/types/registry/deepseek.d.ts +8 -0
  122. package/dist/types/registry/derived.d.ts +5 -0
  123. package/dist/types/registry/devin.d.ts +8 -0
  124. package/dist/types/registry/firepass.d.ts +16 -0
  125. package/dist/types/registry/fireworks.d.ts +7 -0
  126. package/dist/types/registry/github-copilot.d.ts +7 -0
  127. package/dist/types/registry/gitlab-duo-workflow.d.ts +10 -0
  128. package/dist/types/registry/gitlab-duo.d.ts +9 -0
  129. package/dist/types/registry/google-antigravity.d.ts +9 -0
  130. package/dist/types/registry/google-gemini-cli.d.ts +9 -0
  131. package/dist/types/registry/google-vertex.d.ts +5 -0
  132. package/dist/types/registry/google.d.ts +4 -0
  133. package/dist/types/registry/groq.d.ts +4 -0
  134. package/dist/types/registry/huggingface.d.ts +7 -0
  135. package/dist/types/registry/index.d.ts +4 -0
  136. package/dist/types/registry/kagi.d.ts +14 -0
  137. package/dist/types/registry/kilo.d.ts +7 -0
  138. package/dist/types/registry/kimi-code.d.ts +7 -0
  139. package/dist/types/registry/litellm.d.ts +13 -0
  140. package/dist/types/registry/llama-cpp.d.ts +8 -0
  141. package/dist/types/registry/lm-studio.d.ts +8 -0
  142. package/dist/types/registry/minimax-code-cn.d.ts +6 -0
  143. package/dist/types/registry/minimax-code.d.ts +6 -0
  144. package/dist/types/registry/minimax.d.ts +4 -0
  145. package/dist/types/registry/mistral.d.ts +4 -0
  146. package/dist/types/registry/moonshot.d.ts +7 -0
  147. package/dist/types/registry/nanogpt.d.ts +7 -0
  148. package/dist/types/registry/nvidia.d.ts +7 -0
  149. package/dist/types/registry/oauth/__tests__/xai-oauth.test.d.ts +1 -0
  150. package/dist/types/registry/oauth/anthropic.d.ts +23 -0
  151. package/dist/types/registry/oauth/callback-server.d.ts +72 -0
  152. package/dist/types/registry/oauth/cursor.d.ts +15 -0
  153. package/dist/types/registry/oauth/devin.d.ts +5 -0
  154. package/dist/types/registry/oauth/github-copilot.d.ts +30 -0
  155. package/dist/types/registry/oauth/gitlab-duo-workflow.d.ts +6 -0
  156. package/dist/types/registry/oauth/gitlab-duo.d.ts +3 -0
  157. package/dist/types/registry/oauth/google-antigravity.d.ts +11 -0
  158. package/dist/types/registry/oauth/google-gemini-cli.d.ts +10 -0
  159. package/dist/types/registry/oauth/google-oauth-shared.d.ts +22 -0
  160. package/dist/types/registry/oauth/index.d.ts +64 -0
  161. package/dist/types/registry/oauth/kimi.d.ts +21 -0
  162. package/dist/types/registry/oauth/minimax-code.d.ts +27 -0
  163. package/dist/types/registry/oauth/openai-codex.d.ts +33 -0
  164. package/dist/types/registry/oauth/opencode.d.ts +18 -0
  165. package/dist/types/registry/oauth/perplexity.d.ts +9 -0
  166. package/dist/types/registry/oauth/pkce.d.ts +8 -0
  167. package/dist/types/registry/oauth/types.d.ts +56 -0
  168. package/dist/types/registry/oauth/wafer.d.ts +1 -0
  169. package/dist/types/registry/oauth/xai-oauth.d.ts +52 -0
  170. package/dist/types/registry/oauth/xiaomi.d.ts +25 -0
  171. package/dist/types/registry/ollama-cloud.d.ts +7 -0
  172. package/dist/types/registry/ollama.d.ts +12 -0
  173. package/dist/types/registry/openai-codex-device.d.ts +8 -0
  174. package/dist/types/registry/openai-codex.d.ts +9 -0
  175. package/dist/types/registry/openai.d.ts +4 -0
  176. package/dist/types/registry/opencode-go.d.ts +6 -0
  177. package/dist/types/registry/opencode-zen.d.ts +6 -0
  178. package/dist/types/registry/openrouter.d.ts +13 -0
  179. package/dist/types/registry/parallel.d.ts +14 -0
  180. package/dist/types/registry/perplexity.d.ts +7 -0
  181. package/dist/types/registry/qianfan.d.ts +7 -0
  182. package/dist/types/registry/qwen-portal.d.ts +7 -0
  183. package/dist/types/registry/registry.d.ts +303 -0
  184. package/dist/types/registry/sakana.d.ts +7 -0
  185. package/dist/types/registry/synthetic.d.ts +6 -0
  186. package/dist/types/registry/tavily.d.ts +14 -0
  187. package/dist/types/registry/together.d.ts +6 -0
  188. package/dist/types/registry/types.d.ts +51 -0
  189. package/dist/types/registry/umans.d.ts +7 -0
  190. package/dist/types/registry/venice.d.ts +13 -0
  191. package/dist/types/registry/vercel-ai-gateway.d.ts +7 -0
  192. package/dist/types/registry/vllm.d.ts +7 -0
  193. package/dist/types/registry/wafer-serverless.d.ts +6 -0
  194. package/dist/types/registry/xai-oauth.d.ts +7 -0
  195. package/dist/types/registry/xai.d.ts +4 -0
  196. package/dist/types/registry/xiaomi-token-plan-ams.d.ts +6 -0
  197. package/dist/types/registry/xiaomi-token-plan-cn.d.ts +6 -0
  198. package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +6 -0
  199. package/dist/types/registry/xiaomi.d.ts +6 -0
  200. package/dist/types/registry/zai.d.ts +7 -0
  201. package/dist/types/registry/zenmux.d.ts +7 -0
  202. package/dist/types/registry/zhipu-coding-plan.d.ts +7 -0
  203. package/dist/types/stream.d.ts +44 -0
  204. package/dist/types/types.d.ts +715 -0
  205. package/dist/types/usage/claude.d.ts +4 -0
  206. package/dist/types/usage/gemini.d.ts +2 -0
  207. package/dist/types/usage/github-copilot.d.ts +7 -0
  208. package/dist/types/usage/google-antigravity.d.ts +15 -0
  209. package/dist/types/usage/kimi.d.ts +2 -0
  210. package/dist/types/usage/minimax-code.d.ts +2 -0
  211. package/dist/types/usage/ollama.d.ts +5 -0
  212. package/dist/types/usage/openai-codex-base-url.d.ts +18 -0
  213. package/dist/types/usage/openai-codex-reset.d.ts +79 -0
  214. package/dist/types/usage/openai-codex.d.ts +3 -0
  215. package/dist/types/usage/opencode-go.d.ts +2 -0
  216. package/dist/types/usage/shared.d.ts +1 -0
  217. package/dist/types/usage/zai.d.ts +2 -0
  218. package/dist/types/usage.d.ts +346 -0
  219. package/dist/types/utils/abort.d.ts +25 -0
  220. package/dist/types/utils/anthropic-auth.d.ts +35 -0
  221. package/dist/types/utils/block-symbols.d.ts +20 -0
  222. package/dist/types/utils/deterministic-id.d.ts +16 -0
  223. package/dist/types/utils/empty-completion-retry.d.ts +21 -0
  224. package/dist/types/utils/event-stream.d.ts +30 -0
  225. package/dist/types/utils/foundry.d.ts +1 -0
  226. package/dist/types/utils/google-validation.d.ts +2 -0
  227. package/dist/types/utils/harmony-leak.d.ts +118 -0
  228. package/dist/types/utils/http-inspector.d.ts +30 -0
  229. package/dist/types/utils/idle-iterator.d.ts +137 -0
  230. package/dist/types/utils/leaked-thinking-stream.d.ts +29 -0
  231. package/dist/types/utils/openai-http.d.ts +54 -0
  232. package/dist/types/utils/openrouter-headers.d.ts +1 -0
  233. package/dist/types/utils/parse-bind.d.ts +23 -0
  234. package/dist/types/utils/provider-response.d.ts +3 -0
  235. package/dist/types/utils/proxy.d.ts +29 -0
  236. package/dist/types/utils/request-debug.d.ts +29 -0
  237. package/dist/types/utils/retry-after.d.ts +4 -0
  238. package/dist/types/utils/retry.d.ts +14 -0
  239. package/dist/types/utils/schema/adapt.d.ts +24 -0
  240. package/dist/types/utils/schema/compatibility.d.ts +30 -0
  241. package/dist/types/utils/schema/dereference.d.ts +11 -0
  242. package/dist/types/utils/schema/draft.d.ts +10 -0
  243. package/dist/types/utils/schema/equality.d.ts +4 -0
  244. package/dist/types/utils/schema/fields.d.ts +54 -0
  245. package/dist/types/utils/schema/index.d.ts +15 -0
  246. package/dist/types/utils/schema/json-schema-validator.d.ts +20 -0
  247. package/dist/types/utils/schema/meta-validator.d.ts +2 -0
  248. package/dist/types/utils/schema/normalize.d.ts +124 -0
  249. package/dist/types/utils/schema/spill.d.ts +8 -0
  250. package/dist/types/utils/schema/stamps.d.ts +17 -0
  251. package/dist/types/utils/schema/strict-tool-validation.d.ts +16 -0
  252. package/dist/types/utils/schema/types.d.ts +4 -0
  253. package/dist/types/utils/schema/typescript.d.ts +18 -0
  254. package/dist/types/utils/schema/wire.d.ts +92 -0
  255. package/dist/types/utils/schema/zod-decontaminate.d.ts +31 -0
  256. package/dist/types/utils/sdk-stream-timeout.d.ts +33 -0
  257. package/dist/types/utils/sse-debug.d.ts +5 -0
  258. package/dist/types/utils/stream-markup-healing.d.ts +87 -0
  259. package/dist/types/utils/thinking-loop.d.ts +102 -0
  260. package/dist/types/utils/tool-call-loop-guard.d.ts +26 -0
  261. package/dist/types/utils/tool-choice.d.ts +50 -0
  262. package/dist/types/utils/validation.d.ts +42 -0
  263. package/dist/types/utils.d.ts +24 -0
  264. package/package.json +139 -0
  265. package/src/api-registry.ts +109 -0
  266. package/src/auth-broker/client.ts +359 -0
  267. package/src/auth-broker/discover.ts +222 -0
  268. package/src/auth-broker/index.ts +7 -0
  269. package/src/auth-broker/refresher.ts +117 -0
  270. package/src/auth-broker/remote-store.ts +657 -0
  271. package/src/auth-broker/server.ts +646 -0
  272. package/src/auth-broker/snapshot-cache.ts +191 -0
  273. package/src/auth-broker/types.ts +130 -0
  274. package/src/auth-broker/wire-schemas.ts +249 -0
  275. package/src/auth-gateway/http.ts +194 -0
  276. package/src/auth-gateway/index.ts +3 -0
  277. package/src/auth-gateway/server.ts +802 -0
  278. package/src/auth-gateway/types.ts +151 -0
  279. package/src/auth-retry.ts +250 -0
  280. package/src/auth-storage.ts +5576 -0
  281. package/src/dialect/anthropic.md +31 -0
  282. package/src/dialect/anthropic.ts +608 -0
  283. package/src/dialect/catalog.ts +29 -0
  284. package/src/dialect/coercion.ts +136 -0
  285. package/src/dialect/deepseek.md +24 -0
  286. package/src/dialect/deepseek.ts +609 -0
  287. package/src/dialect/demotion.ts +36 -0
  288. package/src/dialect/examples.ts +33 -0
  289. package/src/dialect/factory.ts +34 -0
  290. package/src/dialect/fenced-thinking.ts +184 -0
  291. package/src/dialect/gemini.md +44 -0
  292. package/src/dialect/gemini.ts +597 -0
  293. package/src/dialect/gemma.md +33 -0
  294. package/src/dialect/gemma.ts +387 -0
  295. package/src/dialect/glm.md +32 -0
  296. package/src/dialect/glm.ts +456 -0
  297. package/src/dialect/harmony.md +31 -0
  298. package/src/dialect/harmony.ts +346 -0
  299. package/src/dialect/hermes.md +25 -0
  300. package/src/dialect/hermes.ts +206 -0
  301. package/src/dialect/history.ts +81 -0
  302. package/src/dialect/index.ts +15 -0
  303. package/src/dialect/inventory.ts +73 -0
  304. package/src/dialect/kimi.md +24 -0
  305. package/src/dialect/kimi.ts +340 -0
  306. package/src/dialect/minimax.md +31 -0
  307. package/src/dialect/minimax.ts +95 -0
  308. package/src/dialect/owned-stream.ts +470 -0
  309. package/src/dialect/prompt-template.md +12 -0
  310. package/src/dialect/qwen3.md +28 -0
  311. package/src/dialect/qwen3.ts +240 -0
  312. package/src/dialect/rendering.ts +249 -0
  313. package/src/dialect/thinking.ts +122 -0
  314. package/src/dialect/types.ts +57 -0
  315. package/src/dialect/xml.md +22 -0
  316. package/src/dialect/xml.ts +90 -0
  317. package/src/error/abort.ts +18 -0
  318. package/src/error/auth-classify.ts +30 -0
  319. package/src/error/auth.ts +48 -0
  320. package/src/error/aws.ts +31 -0
  321. package/src/error/classes.ts +186 -0
  322. package/src/error/finalize.ts +69 -0
  323. package/src/error/flags.ts +506 -0
  324. package/src/error/format.ts +45 -0
  325. package/src/error/gateway.ts +96 -0
  326. package/src/error/index.ts +13 -0
  327. package/src/error/oauth.ts +58 -0
  328. package/src/error/provider.ts +62 -0
  329. package/src/error/rate-limit.ts +161 -0
  330. package/src/error/retryable.ts +70 -0
  331. package/src/error/validation.ts +44 -0
  332. package/src/index.ts +49 -0
  333. package/src/provider-details.ts +90 -0
  334. package/src/providers/__tests__/google-auth.test.ts +144 -0
  335. package/src/providers/__tests__/kimi-code-thinking.test.ts +112 -0
  336. package/src/providers/__tests__/openai-codex-error.test.ts +84 -0
  337. package/src/providers/amazon-bedrock.ts +1042 -0
  338. package/src/providers/anthropic-client.ts +295 -0
  339. package/src/providers/anthropic-messages-server-schema.ts +252 -0
  340. package/src/providers/anthropic-messages-server.ts +756 -0
  341. package/src/providers/anthropic-wire.ts +318 -0
  342. package/src/providers/anthropic.ts +4078 -0
  343. package/src/providers/aws-credentials.ts +586 -0
  344. package/src/providers/aws-eventstream.ts +181 -0
  345. package/src/providers/aws-sigv4.ts +218 -0
  346. package/src/providers/azure-openai-responses.ts +382 -0
  347. package/src/providers/cursor/proto/agent.proto +3526 -0
  348. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  349. package/src/providers/cursor/proto/buf.yaml +17 -0
  350. package/src/providers/cursor.ts +2695 -0
  351. package/src/providers/devin/proto/buf/validate/validate.proto +468 -0
  352. package/src/providers/devin/proto/buf.gen.yaml +33 -0
  353. package/src/providers/devin/proto/buf.yaml +17 -0
  354. package/src/providers/devin/proto/cel/expr/checked.proto +103 -0
  355. package/src/providers/devin/proto/cel/expr/eval.proto +38 -0
  356. package/src/providers/devin/proto/cel/expr/explain.proto +15 -0
  357. package/src/providers/devin/proto/cel/expr/syntax.proto +113 -0
  358. package/src/providers/devin/proto/cel/expr/value.proto +41 -0
  359. package/src/providers/devin/proto/connectext/grpc/status/v1/status.proto +11 -0
  360. package/src/providers/devin/proto/errorspb/errors.proto +56 -0
  361. package/src/providers/devin/proto/errorspb/hintdetail.proto +7 -0
  362. package/src/providers/devin/proto/errorspb/markers.proto +10 -0
  363. package/src/providers/devin/proto/errorspb/tags.proto +12 -0
  364. package/src/providers/devin/proto/errorspb/testing.proto +6 -0
  365. package/src/providers/devin/proto/exa/analytics_pb/analytics.proto +188 -0
  366. package/src/providers/devin/proto/exa/api_server_pb/api_server.proto +2461 -0
  367. package/src/providers/devin/proto/exa/auth_pb/auth.proto +19 -0
  368. package/src/providers/devin/proto/exa/auto_cascade_common_pb/auto_cascade_common.proto +79 -0
  369. package/src/providers/devin/proto/exa/browser_preview_pb/browser_preview.proto +32 -0
  370. package/src/providers/devin/proto/exa/bug_checker_pb/bug_checker.proto +22 -0
  371. package/src/providers/devin/proto/exa/cascade_plugins_pb/cascade_plugins.proto +262 -0
  372. package/src/providers/devin/proto/exa/chat_client_server_pb/chat_client_server.proto +57 -0
  373. package/src/providers/devin/proto/exa/chat_pb/chat.proto +449 -0
  374. package/src/providers/devin/proto/exa/code_edit/code_edit_pb/code_edit.proto +186 -0
  375. package/src/providers/devin/proto/exa/codeium_common_pb/codeium_common.proto +4157 -0
  376. package/src/providers/devin/proto/exa/context_module_pb/context_module.proto +175 -0
  377. package/src/providers/devin/proto/exa/cortex_pb/cortex.proto +3268 -0
  378. package/src/providers/devin/proto/exa/dev_pb/dev.proto +26 -0
  379. package/src/providers/devin/proto/exa/diff_action_pb/diff_action.proto +75 -0
  380. package/src/providers/devin/proto/exa/eval/pr_eval/datasets_pb/datasets.proto +103 -0
  381. package/src/providers/devin/proto/exa/eval_pb/eval.proto +1315 -0
  382. package/src/providers/devin/proto/exa/extension_server_pb/extension_server.proto +556 -0
  383. package/src/providers/devin/proto/exa/file_system_provider_pb/file_system_provider.proto +75 -0
  384. package/src/providers/devin/proto/exa/index_pb/index.proto +461 -0
  385. package/src/providers/devin/proto/exa/knowledge_base_pb/knowledge_base.proto +144 -0
  386. package/src/providers/devin/proto/exa/language_server_pb/language_server.proto +2385 -0
  387. package/src/providers/devin/proto/exa/model_management_pb/model_management.proto +186 -0
  388. package/src/providers/devin/proto/exa/opensearch_clients_pb/opensearch_clients.proto +503 -0
  389. package/src/providers/devin/proto/exa/product_analytics_pb/product_analytics.proto +37 -0
  390. package/src/providers/devin/proto/exa/prompt_pb/prompt.proto +92 -0
  391. package/src/providers/devin/proto/exa/reactive_component_pb/reactive_component.proto +96 -0
  392. package/src/providers/devin/proto/exa/seat_management_pb/seat_management.proto +2680 -0
  393. package/src/providers/devin/proto/exa/tokenizer_pb/tokenizer.proto +37 -0
  394. package/src/providers/devin/proto/exa/trainer_pb/config.proto +647 -0
  395. package/src/providers/devin/proto/exa/tree_sitter/language_data_pb/language_data.proto +14 -0
  396. package/src/providers/devin/proto/exa/trust_pb/trust.proto +157 -0
  397. package/src/providers/devin/proto/exa/user_analytics_pb/user_analytics.proto +519 -0
  398. package/src/providers/devin/proto/google.golang.org/appengine/internal/base/api_base.proto +28 -0
  399. package/src/providers/devin/proto/google.golang.org/appengine/internal/datastore/datastore_v3.proto +484 -0
  400. package/src/providers/devin/proto/google.golang.org/appengine/internal/log/log_service.proto +136 -0
  401. package/src/providers/devin/proto/google.golang.org/appengine/internal/remote_api/remote_api.proto +42 -0
  402. package/src/providers/devin/proto/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto +61 -0
  403. package/src/providers/devin/proto/grpc/binlog/v1/binarylog.proto +84 -0
  404. package/src/providers/devin/proto/io/prometheus/client/metrics.proto +98 -0
  405. package/src/providers/devin.ts +577 -0
  406. package/src/providers/error-message.ts +21 -0
  407. package/src/providers/github-copilot-headers.ts +141 -0
  408. package/src/providers/gitlab-duo-workflow-chatml-note.md +1 -0
  409. package/src/providers/gitlab-duo-workflow.ts +3058 -0
  410. package/src/providers/gitlab-duo.ts +395 -0
  411. package/src/providers/google-auth.ts +350 -0
  412. package/src/providers/google-gemini-cli.ts +1362 -0
  413. package/src/providers/google-interactions.ts +753 -0
  414. package/src/providers/google-shared.ts +1103 -0
  415. package/src/providers/google-types.ts +180 -0
  416. package/src/providers/google-vertex.ts +183 -0
  417. package/src/providers/google.ts +87 -0
  418. package/src/providers/grammar.ts +70 -0
  419. package/src/providers/kimi.ts +52 -0
  420. package/src/providers/mock.ts +507 -0
  421. package/src/providers/ollama.ts +773 -0
  422. package/src/providers/openai-anthropic-shim.ts +152 -0
  423. package/src/providers/openai-chat-server-schema.ts +242 -0
  424. package/src/providers/openai-chat-server.ts +715 -0
  425. package/src/providers/openai-chat-wire.ts +847 -0
  426. package/src/providers/openai-codex/request-transformer.ts +295 -0
  427. package/src/providers/openai-codex/response-handler.ts +102 -0
  428. package/src/providers/openai-codex-responses.ts +3468 -0
  429. package/src/providers/openai-completions.ts +2173 -0
  430. package/src/providers/openai-reasoning-fallback.ts +269 -0
  431. package/src/providers/openai-responses-reasoning-suppression.md +1 -0
  432. package/src/providers/openai-responses-server-schema.ts +282 -0
  433. package/src/providers/openai-responses-server.ts +1280 -0
  434. package/src/providers/openai-responses-wire.ts +6391 -0
  435. package/src/providers/openai-responses.ts +1022 -0
  436. package/src/providers/openai-shared.ts +2648 -0
  437. package/src/providers/pi-native-client.ts +266 -0
  438. package/src/providers/pi-native-server.ts +242 -0
  439. package/src/providers/register-builtins.ts +475 -0
  440. package/src/providers/synthetic.ts +50 -0
  441. package/src/providers/transform-messages.ts +787 -0
  442. package/src/providers/vision-guard.ts +54 -0
  443. package/src/registry/aimlapi.ts +6 -0
  444. package/src/registry/alibaba-coding-plan.ts +95 -0
  445. package/src/registry/amazon-bedrock.ts +22 -0
  446. package/src/registry/anthropic.ts +26 -0
  447. package/src/registry/api-key-login.ts +112 -0
  448. package/src/registry/api-key-validation.ts +161 -0
  449. package/src/registry/azure.ts +6 -0
  450. package/src/registry/cerebras.ts +23 -0
  451. package/src/registry/cloudflare-ai-gateway.ts +45 -0
  452. package/src/registry/coreweave.ts +40 -0
  453. package/src/registry/cursor.ts +20 -0
  454. package/src/registry/deepseek.ts +46 -0
  455. package/src/registry/derived.ts +9 -0
  456. package/src/registry/devin.ts +15 -0
  457. package/src/registry/firepass.ts +32 -0
  458. package/src/registry/fireworks.ts +28 -0
  459. package/src/registry/github-copilot.ts +22 -0
  460. package/src/registry/gitlab-duo-workflow.ts +20 -0
  461. package/src/registry/gitlab-duo.ts +19 -0
  462. package/src/registry/google-antigravity.ts +22 -0
  463. package/src/registry/google-gemini-cli.ts +22 -0
  464. package/src/registry/google-vertex.ts +38 -0
  465. package/src/registry/google.ts +6 -0
  466. package/src/registry/groq.ts +6 -0
  467. package/src/registry/huggingface.ts +29 -0
  468. package/src/registry/index.ts +4 -0
  469. package/src/registry/kagi.ts +46 -0
  470. package/src/registry/kilo.ts +114 -0
  471. package/src/registry/kimi-code.ts +17 -0
  472. package/src/registry/litellm.ts +45 -0
  473. package/src/registry/llama-cpp.ts +35 -0
  474. package/src/registry/lm-studio.ts +31 -0
  475. package/src/registry/minimax-code-cn.ts +12 -0
  476. package/src/registry/minimax-code.ts +12 -0
  477. package/src/registry/minimax.ts +6 -0
  478. package/src/registry/mistral.ts +6 -0
  479. package/src/registry/moonshot.ts +22 -0
  480. package/src/registry/nanogpt.ts +22 -0
  481. package/src/registry/nvidia.ts +61 -0
  482. package/src/registry/oauth/__tests__/xai-oauth.test.ts +104 -0
  483. package/src/registry/oauth/anthropic.ts +311 -0
  484. package/src/registry/oauth/callback-server.ts +315 -0
  485. package/src/registry/oauth/cursor.ts +171 -0
  486. package/src/registry/oauth/devin.ts +124 -0
  487. package/src/registry/oauth/github-copilot.ts +369 -0
  488. package/src/registry/oauth/gitlab-duo-workflow.ts +146 -0
  489. package/src/registry/oauth/gitlab-duo.ts +222 -0
  490. package/src/registry/oauth/google-antigravity.ts +209 -0
  491. package/src/registry/oauth/google-gemini-cli.ts +273 -0
  492. package/src/registry/oauth/google-oauth-shared.ts +125 -0
  493. package/src/registry/oauth/index.ts +269 -0
  494. package/src/registry/oauth/kimi.ts +289 -0
  495. package/src/registry/oauth/minimax-code.ts +53 -0
  496. package/src/registry/oauth/oauth.html +311 -0
  497. package/src/registry/oauth/openai-codex.ts +364 -0
  498. package/src/registry/oauth/opencode.ts +50 -0
  499. package/src/registry/oauth/perplexity.ts +228 -0
  500. package/src/registry/oauth/pkce.ts +18 -0
  501. package/src/registry/oauth/types.ts +65 -0
  502. package/src/registry/oauth/wafer.ts +24 -0
  503. package/src/registry/oauth/xai-oauth.ts +394 -0
  504. package/src/registry/oauth/xiaomi.ts +211 -0
  505. package/src/registry/ollama-cloud.ts +36 -0
  506. package/src/registry/ollama.ts +43 -0
  507. package/src/registry/openai-codex-device.ts +18 -0
  508. package/src/registry/openai-codex.ts +19 -0
  509. package/src/registry/openai.ts +6 -0
  510. package/src/registry/opencode-go.ts +12 -0
  511. package/src/registry/opencode-zen.ts +12 -0
  512. package/src/registry/openrouter.ts +28 -0
  513. package/src/registry/parallel.ts +45 -0
  514. package/src/registry/perplexity.ts +13 -0
  515. package/src/registry/qianfan.ts +27 -0
  516. package/src/registry/qwen-portal.ts +50 -0
  517. package/src/registry/registry.ts +161 -0
  518. package/src/registry/sakana.ts +22 -0
  519. package/src/registry/synthetic.ts +21 -0
  520. package/src/registry/tavily.ts +45 -0
  521. package/src/registry/together.ts +22 -0
  522. package/src/registry/types.ts +56 -0
  523. package/src/registry/umans.ts +23 -0
  524. package/src/registry/venice.ts +33 -0
  525. package/src/registry/vercel-ai-gateway.ts +38 -0
  526. package/src/registry/vllm.ts +34 -0
  527. package/src/registry/wafer-serverless.ts +12 -0
  528. package/src/registry/xai-oauth.ts +17 -0
  529. package/src/registry/xai.ts +6 -0
  530. package/src/registry/xiaomi-token-plan-ams.ts +12 -0
  531. package/src/registry/xiaomi-token-plan-cn.ts +12 -0
  532. package/src/registry/xiaomi-token-plan-sgp.ts +12 -0
  533. package/src/registry/xiaomi.ts +12 -0
  534. package/src/registry/zai.ts +27 -0
  535. package/src/registry/zenmux.ts +22 -0
  536. package/src/registry/zhipu-coding-plan.ts +27 -0
  537. package/src/stream.ts +1778 -0
  538. package/src/types.ts +856 -0
  539. package/src/usage/claude.ts +485 -0
  540. package/src/usage/gemini.ts +258 -0
  541. package/src/usage/github-copilot.ts +424 -0
  542. package/src/usage/google-antigravity.ts +497 -0
  543. package/src/usage/kimi.ts +271 -0
  544. package/src/usage/minimax-code.ts +30 -0
  545. package/src/usage/ollama.ts +41 -0
  546. package/src/usage/openai-codex-base-url.ts +35 -0
  547. package/src/usage/openai-codex-reset.ts +174 -0
  548. package/src/usage/openai-codex.ts +535 -0
  549. package/src/usage/opencode-go.ts +89 -0
  550. package/src/usage/shared.ts +10 -0
  551. package/src/usage/zai.ts +321 -0
  552. package/src/usage.ts +333 -0
  553. package/src/utils/abort.ts +67 -0
  554. package/src/utils/anthropic-auth.ts +93 -0
  555. package/src/utils/block-symbols.ts +32 -0
  556. package/src/utils/deterministic-id.ts +20 -0
  557. package/src/utils/empty-completion-retry.ts +159 -0
  558. package/src/utils/event-stream.ts +171 -0
  559. package/src/utils/foundry.ts +8 -0
  560. package/src/utils/google-validation.ts +25 -0
  561. package/src/utils/harmony-leak.ts +456 -0
  562. package/src/utils/http-inspector.ts +168 -0
  563. package/src/utils/idle-iterator.ts +473 -0
  564. package/src/utils/leaked-thinking-stream.ts +294 -0
  565. package/src/utils/openai-http.ts +122 -0
  566. package/src/utils/openrouter-headers.ts +12 -0
  567. package/src/utils/parse-bind.ts +56 -0
  568. package/src/utils/provider-response.ts +30 -0
  569. package/src/utils/proxy.ts +240 -0
  570. package/src/utils/request-debug.ts +351 -0
  571. package/src/utils/retry-after.ts +110 -0
  572. package/src/utils/retry.ts +59 -0
  573. package/src/utils/schema/CONSTRAINTS.md +166 -0
  574. package/src/utils/schema/adapt.ts +36 -0
  575. package/src/utils/schema/compatibility.ts +435 -0
  576. package/src/utils/schema/dereference.ts +98 -0
  577. package/src/utils/schema/draft.ts +341 -0
  578. package/src/utils/schema/equality.ts +97 -0
  579. package/src/utils/schema/fields.ts +207 -0
  580. package/src/utils/schema/index.ts +15 -0
  581. package/src/utils/schema/json-schema-validator.ts +595 -0
  582. package/src/utils/schema/meta-validator.ts +167 -0
  583. package/src/utils/schema/normalize.ts +1901 -0
  584. package/src/utils/schema/spill.ts +43 -0
  585. package/src/utils/schema/stamps.ts +109 -0
  586. package/src/utils/schema/strict-tool-validation.ts +117 -0
  587. package/src/utils/schema/types.ts +10 -0
  588. package/src/utils/schema/typescript.ts +198 -0
  589. package/src/utils/schema/wire.ts +789 -0
  590. package/src/utils/schema/zod-decontaminate.ts +331 -0
  591. package/src/utils/sdk-stream-timeout.ts +43 -0
  592. package/src/utils/sse-debug.ts +18 -0
  593. package/src/utils/stream-markup-healing.ts +247 -0
  594. package/src/utils/thinking-loop.ts +552 -0
  595. package/src/utils/tool-call-loop-guard.ts +107 -0
  596. package/src/utils/tool-choice.ts +99 -0
  597. package/src/utils/validation.ts +1507 -0
  598. package/src/utils.ts +171 -0
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Shared OAuth flow for Google-style providers (Gemini CLI, Antigravity).
3
+ *
4
+ * Both providers use the same authorization-code flow shape; only the client
5
+ * credentials, scopes, endpoint constants, and project-discovery logic differ.
6
+ */
7
+ import * as AIError from "../../error";
8
+ import { extractGoogleValidationUrl, formatGoogleValidationRequiredMessage } from "../../utils/google-validation";
9
+ import { OAuthCallbackFlow } from "./callback-server";
10
+ import type { OAuthController, OAuthCredentials } from "./types";
11
+
12
+ export interface GoogleOAuthFlowConfig {
13
+ clientId: string;
14
+ clientSecret: string;
15
+ authUrl: string;
16
+ tokenUrl: string;
17
+ scopes: string[];
18
+ callbackPort: number;
19
+ callbackPath: string;
20
+ discoverProject: (accessToken: string, onProgress?: (message: string) => void) => Promise<string>;
21
+ }
22
+
23
+ async function getUserEmail(accessToken: string): Promise<string | undefined> {
24
+ try {
25
+ const response = await fetch("https://www.googleapis.com/oauth2/v1/userinfo?alt=json", {
26
+ headers: { Authorization: `Bearer ${accessToken}` },
27
+ });
28
+
29
+ if (response.ok) {
30
+ const data = (await response.json()) as { email?: string };
31
+ return data.email;
32
+ }
33
+ } catch {
34
+ // Ignore errors, email is optional
35
+ }
36
+ return undefined;
37
+ }
38
+
39
+ export class GoogleOAuthFlow extends OAuthCallbackFlow {
40
+ private readonly config: GoogleOAuthFlowConfig;
41
+
42
+ constructor(ctrl: OAuthController, config: GoogleOAuthFlowConfig) {
43
+ super(ctrl, {
44
+ preferredPort: config.callbackPort,
45
+ callbackPath: config.callbackPath,
46
+ callbackHostname: "127.0.0.1",
47
+ });
48
+ this.config = config;
49
+ }
50
+
51
+ async generateAuthUrl(state: string, redirectUri: string): Promise<{ url: string; instructions?: string }> {
52
+ const authParams = new URLSearchParams({
53
+ client_id: this.config.clientId,
54
+ response_type: "code",
55
+ redirect_uri: redirectUri,
56
+ scope: this.config.scopes.join(" "),
57
+ state,
58
+ access_type: "offline",
59
+ prompt: "consent",
60
+ });
61
+
62
+ const url = `${this.config.authUrl}?${authParams.toString()}`;
63
+ return { url, instructions: "Complete the sign-in in your browser." };
64
+ }
65
+
66
+ async exchangeToken(code: string, _state: string, redirectUri: string): Promise<OAuthCredentials> {
67
+ this.ctrl.onProgress?.("Exchanging authorization code for tokens...");
68
+
69
+ const tokenResponse = await fetch(this.config.tokenUrl, {
70
+ method: "POST",
71
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
72
+ body: new URLSearchParams({
73
+ client_id: this.config.clientId,
74
+ client_secret: this.config.clientSecret,
75
+ code,
76
+ grant_type: "authorization_code",
77
+ redirect_uri: redirectUri,
78
+ }),
79
+ });
80
+
81
+ if (!tokenResponse.ok) {
82
+ const error = await tokenResponse.text();
83
+ throw new AIError.OAuthError(`Token exchange failed: ${error}`, { kind: "token-exchange" });
84
+ }
85
+
86
+ const tokenData = (await tokenResponse.json()) as {
87
+ access_token: string;
88
+ refresh_token: string;
89
+ expires_in: number;
90
+ };
91
+
92
+ if (!tokenData.refresh_token) {
93
+ throw new AIError.OAuthError("No refresh token received. Please try again.", { kind: "validation" });
94
+ }
95
+
96
+ this.ctrl.onProgress?.("Getting user info...");
97
+ const email = await getUserEmail(tokenData.access_token);
98
+ let projectId: string;
99
+ try {
100
+ projectId = await this.config.discoverProject(tokenData.access_token, this.ctrl.onProgress);
101
+ } catch (err) {
102
+ const validationUrl = extractGoogleValidationUrl(err instanceof Error ? err.message : String(err));
103
+ if (!validationUrl) throw err;
104
+ throw new AIError.OAuthError(formatGoogleValidationRequiredMessage(validationUrl, "sign in again", email), {
105
+ kind: "validation",
106
+ });
107
+ }
108
+
109
+ return {
110
+ refresh: tokenData.refresh_token,
111
+ access: tokenData.access_token,
112
+ expires: Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000,
113
+ projectId,
114
+ email,
115
+ };
116
+ }
117
+ }
118
+
119
+ export async function runGoogleOAuthLogin(
120
+ ctrl: OAuthController,
121
+ config: GoogleOAuthFlowConfig,
122
+ ): Promise<OAuthCredentials> {
123
+ const flow = new GoogleOAuthFlow(ctrl, config);
124
+ return flow.login();
125
+ }
@@ -0,0 +1,269 @@
1
+ // ============================================================================
2
+ // High-level API
3
+ // ============================================================================
4
+
5
+ import * as AIError from "../../error";
6
+ import { getProviderDefinition, PROVIDER_REGISTRY } from "../registry";
7
+ import type {
8
+ OAuthCredentials,
9
+ OAuthProvider,
10
+ OAuthProviderId,
11
+ OAuthProviderInfo,
12
+ OAuthProviderInterface,
13
+ } from "./types";
14
+
15
+ export type * from "./types";
16
+
17
+ const DEVICE_FLOW_CANCEL_MESSAGE = "Login cancelled";
18
+ const DEVICE_FLOW_TIMEOUT_MESSAGE = "Device flow timed out";
19
+ const DEVICE_FLOW_SLOW_DOWN_TIMEOUT_MESSAGE =
20
+ "Device flow timed out after one or more slow_down responses. This is often caused by clock drift in WSL or VM environments. Please sync or restart the VM clock and try again.";
21
+ const MINIMUM_DEVICE_FLOW_INTERVAL_MS = 1000;
22
+ const DEFAULT_DEVICE_FLOW_INTERVAL_SECONDS = 5;
23
+ const SLOW_DOWN_INTERVAL_INCREMENT_MS = 5000;
24
+
25
+ /** Result returned by one OAuth device-code polling attempt. */
26
+ export type OAuthDeviceCodePollResult<T> =
27
+ | { status: "complete"; value: T }
28
+ | { status: "pending" }
29
+ | { status: "slow_down" }
30
+ | { status: "failed"; message: string };
31
+
32
+ /** Options for polling an RFC 8628-style OAuth device-code flow. */
33
+ export interface OAuthDeviceCodeFlowOptions<T> {
34
+ /** Poll the provider once and classify the response. */
35
+ poll(): OAuthDeviceCodePollResult<T> | Promise<OAuthDeviceCodePollResult<T>>;
36
+ /** Provider-requested polling cadence; defaults to RFC 8628's five seconds. */
37
+ intervalSeconds?: number;
38
+ /** Provider-issued expiry window for the device code. */
39
+ expiresInSeconds?: number;
40
+ /** Cancels the flow with the legacy "Login cancelled" error. */
41
+ signal?: AbortSignal;
42
+ }
43
+
44
+ async function abortableDeviceFlowSleep(ms: number, signal: AbortSignal | undefined): Promise<void> {
45
+ if (!signal) {
46
+ await Bun.sleep(ms);
47
+ return;
48
+ }
49
+ if (signal.aborted) {
50
+ throw new AIError.LoginCancelledError(DEVICE_FLOW_CANCEL_MESSAGE);
51
+ }
52
+
53
+ const { promise, resolve, reject } = Promise.withResolvers<void>();
54
+ let timer: Timer | undefined;
55
+ const onAbort = () => {
56
+ if (timer) clearTimeout(timer);
57
+ reject(new AIError.LoginCancelledError(DEVICE_FLOW_CANCEL_MESSAGE));
58
+ };
59
+ timer = setTimeout(() => {
60
+ signal.removeEventListener("abort", onAbort);
61
+ resolve();
62
+ }, ms);
63
+ signal.addEventListener("abort", onAbort, { once: true });
64
+ await promise;
65
+ }
66
+
67
+ /** Poll an OAuth device-code flow until completion, provider failure, timeout, or cancellation. */
68
+ export async function pollOAuthDeviceCodeFlow<T>(options: OAuthDeviceCodeFlowOptions<T>): Promise<T> {
69
+ const deadline =
70
+ typeof options.expiresInSeconds === "number"
71
+ ? Date.now() + options.expiresInSeconds * 1000
72
+ : Number.POSITIVE_INFINITY;
73
+ let intervalMs = Math.max(
74
+ MINIMUM_DEVICE_FLOW_INTERVAL_MS,
75
+ Math.floor((options.intervalSeconds ?? DEFAULT_DEVICE_FLOW_INTERVAL_SECONDS) * 1000),
76
+ );
77
+ let slowDownResponses = 0;
78
+
79
+ while (Date.now() < deadline) {
80
+ if (options.signal?.aborted) {
81
+ throw new AIError.LoginCancelledError(DEVICE_FLOW_CANCEL_MESSAGE);
82
+ }
83
+ const result = await options.poll();
84
+ if (result.status === "complete") {
85
+ return result.value;
86
+ }
87
+ if (result.status === "failed") {
88
+ throw new AIError.OAuthError(result.message, { kind: "polling" });
89
+ }
90
+ if (result.status === "slow_down") {
91
+ slowDownResponses += 1;
92
+ intervalMs = Math.max(MINIMUM_DEVICE_FLOW_INTERVAL_MS, intervalMs + SLOW_DOWN_INTERVAL_INCREMENT_MS);
93
+ }
94
+
95
+ const remainingMs = deadline - Date.now();
96
+ if (remainingMs <= 0) {
97
+ break;
98
+ }
99
+ await abortableDeviceFlowSleep(Math.min(intervalMs, remainingMs), options.signal);
100
+ }
101
+
102
+ throw new AIError.OAuthError(
103
+ slowDownResponses > 0 ? DEVICE_FLOW_SLOW_DOWN_TIMEOUT_MESSAGE : DEVICE_FLOW_TIMEOUT_MESSAGE,
104
+ { kind: "timeout" },
105
+ );
106
+ }
107
+
108
+ const builtInOAuthProviders: OAuthProviderInfo[] = PROVIDER_REGISTRY.filter(
109
+ provider => provider.login && provider.showInLoginList !== false,
110
+ ).map(provider => ({
111
+ id: provider.id,
112
+ name: provider.name,
113
+ available: provider.available ?? true,
114
+ storeCredentialsAs: provider.storeCredentialsAs,
115
+ }));
116
+
117
+ const customOAuthProviders = new Map<string, OAuthProviderInterface>();
118
+
119
+ /**
120
+ * Register a custom OAuth provider.
121
+ */
122
+ export function registerOAuthProvider(provider: OAuthProviderInterface): void {
123
+ customOAuthProviders.set(provider.id, provider);
124
+ }
125
+
126
+ /**
127
+ * Get a custom OAuth provider by ID.
128
+ */
129
+ export function getOAuthProvider(id: OAuthProviderId): OAuthProviderInterface | undefined {
130
+ return customOAuthProviders.get(id);
131
+ }
132
+
133
+ /**
134
+ * Remove all custom OAuth providers registered by a source.
135
+ */
136
+ export function unregisterOAuthProviders(sourceId: string): void {
137
+ for (const [id, provider] of customOAuthProviders.entries()) {
138
+ if (provider.sourceId === sourceId) {
139
+ customOAuthProviders.delete(id);
140
+ }
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Refresh token for any OAuth provider.
146
+ * Saves the new credentials and returns the new access token.
147
+ */
148
+ export async function refreshOAuthToken(
149
+ provider: OAuthProvider,
150
+ credentials: OAuthCredentials,
151
+ ): Promise<OAuthCredentials> {
152
+ if (!credentials) {
153
+ throw new AIError.OAuthError(`No OAuth credentials found for ${provider}`, {
154
+ kind: "validation",
155
+ provider,
156
+ });
157
+ }
158
+ const def = getProviderDefinition(provider);
159
+ if (!def?.login) {
160
+ throw new AIError.OAuthError(`Unknown OAuth provider: ${provider}`, {
161
+ kind: "validation",
162
+ provider,
163
+ });
164
+ }
165
+ // Providers without a real refresher (static bearer tokens / API keys that
166
+ // don't expire) return the credentials unchanged.
167
+ return def.refreshToken ? def.refreshToken(credentials) : credentials;
168
+ }
169
+ function getPerplexityJwtExpiryMs(token: string): number | undefined {
170
+ const parts = token.split(".");
171
+ if (parts.length !== 3) return undefined;
172
+ const payload = parts[1];
173
+ if (!payload) return undefined;
174
+ try {
175
+ const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf8")) as { exp?: unknown };
176
+ if (typeof decoded.exp !== "number" || !Number.isFinite(decoded.exp)) return undefined;
177
+ return decoded.exp * 1000 - 5 * 60_000;
178
+ } catch {
179
+ return undefined;
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Build API-key bytes for a provider from an already-fresh OAuth credential.
185
+ *
186
+ * Refresh is owned by AuthStorage. This helper deliberately refuses expired
187
+ * credentials so it cannot POST broker redaction sentinels to upstream token
188
+ * endpoints as a side channel.
189
+ *
190
+ * For providers that need credential metadata at request time, returns
191
+ * JSON-encoded credentials plus expiry metadata for diagnostics/edge guards.
192
+ * @returns API key string, or null if no credentials
193
+ * @throws Error if the credential is expired and must be refreshed upstream
194
+ */
195
+ export async function getOAuthApiKey(
196
+ provider: OAuthProvider,
197
+ credentials: Record<string, OAuthCredentials>,
198
+ ): Promise<{ newCredentials: OAuthCredentials; apiKey: string } | null> {
199
+ let creds = credentials[provider];
200
+ if (!creds) {
201
+ return null;
202
+ }
203
+
204
+ if (provider === "perplexity") {
205
+ // Perplexity JWTs usually omit `exp` (server-side sessions). Trust the JWT
206
+ // claim when present; otherwise treat the credential as non-expiring rather
207
+ // than honoring a stale stored `expires` (older logins wrote loginTime+1h).
208
+ const NEVER_EXPIRES = 8.64e15;
209
+ const normalizedExpires =
210
+ creds.expires > 0 && creds.expires < 10_000_000_000 ? creds.expires * 1000 : creds.expires;
211
+ const jwtExpiry = getPerplexityJwtExpiryMs(creds.access);
212
+ const expires = jwtExpiry ?? Math.max(normalizedExpires, NEVER_EXPIRES);
213
+ if (expires !== creds.expires) {
214
+ creds = { ...creds, expires };
215
+ }
216
+ }
217
+ // Refresh is the sole responsibility of `AuthStorage` (which calls
218
+ // `refreshOAuthToken` directly with broker-aware single-flighting). If we
219
+ // reach here with an expired credential, the outer pipeline failed to
220
+ // refresh before this call OR the refresh slot is the broker sentinel —
221
+ // either way, posting the credential to a provider endpoint would only
222
+ // trigger a `__remote__`-against-real-provider failure that gets classified
223
+ // as `invalid_grant` and disables the row. Refuse loudly instead.
224
+ if (Date.now() >= creds.expires) {
225
+ if (provider === "perplexity") {
226
+ const jwtExpiry = getPerplexityJwtExpiryMs(creds.access);
227
+ if (jwtExpiry && Date.now() < jwtExpiry) {
228
+ const fallbackCredentials = { ...creds, expires: jwtExpiry };
229
+ return { newCredentials: fallbackCredentials, apiKey: fallbackCredentials.access };
230
+ }
231
+ }
232
+ throw new AIError.OAuthError(
233
+ `OAuth credential for ${provider} is expired and must be refreshed via AuthStorage before getOAuthApiKey is called`,
234
+ { kind: "validation", provider },
235
+ );
236
+ }
237
+ // For providers that need request-time credential metadata, return JSON.
238
+ const needsStructuredApiKey =
239
+ provider === "github-copilot" ||
240
+ provider === "google-gemini-cli" ||
241
+ provider === "google-antigravity" ||
242
+ provider === "alibaba-coding-plan";
243
+ const apiKey = needsStructuredApiKey
244
+ ? JSON.stringify({
245
+ apiEndpoint: creds.apiEndpoint,
246
+ token: creds.access,
247
+ enterpriseUrl: creds.enterpriseUrl,
248
+ projectId: creds.projectId,
249
+ refreshToken: creds.refresh,
250
+ expiresAt: creds.expires,
251
+ email: creds.email,
252
+ accountId: creds.accountId,
253
+ })
254
+ : creds.access;
255
+ return { newCredentials: creds, apiKey };
256
+ }
257
+
258
+ /**
259
+ * Get list of OAuth providers.
260
+ */
261
+ export function getOAuthProviders(): OAuthProviderInfo[] {
262
+ const customProviders = Array.from(customOAuthProviders.values(), provider => ({
263
+ id: provider.id,
264
+ name: provider.name,
265
+ available: true,
266
+ storeCredentialsAs: provider.storeCredentialsAs,
267
+ }));
268
+ return [...builtInOAuthProviders, ...customProviders];
269
+ }
@@ -0,0 +1,289 @@
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 "jeopi-utils";
11
+ import packageJson from "../../../package.json" with { type: "json" };
12
+ import * as AIError from "../../error";
13
+ import type { OAuthController, OAuthCredentials } from "./types";
14
+
15
+ const CLIENT_ID = "17e5f671-d194-4dfb-9706-5516cb48c098";
16
+ const DEFAULT_OAUTH_HOST = "https://auth.kimi.com";
17
+ const DEVICE_ID_FILENAME = "kimi-device-id";
18
+ const DEFAULT_POLL_INTERVAL_MS = 5000;
19
+ const DEFAULT_DEVICE_FLOW_TTL_MS = 15 * 60 * 1000;
20
+ const OAUTH_EXPIRY_SKEW_MS = 5 * 60 * 1000;
21
+
22
+ interface DeviceAuthorizationResponse {
23
+ user_code?: string;
24
+ device_code?: string;
25
+ verification_uri?: string;
26
+ verification_uri_complete?: string;
27
+ expires_in?: number;
28
+ interval?: number;
29
+ }
30
+
31
+ interface TokenResponse {
32
+ access_token?: string;
33
+ refresh_token?: string;
34
+ expires_in?: number;
35
+ scope?: string;
36
+ token_type?: string;
37
+ error?: string;
38
+ error_description?: string;
39
+ interval?: number;
40
+ }
41
+
42
+ function resolveOAuthHost(): string {
43
+ return $env.KIMI_CODE_OAUTH_HOST || $env.KIMI_OAUTH_HOST || DEFAULT_OAUTH_HOST;
44
+ }
45
+
46
+ function formatDeviceModel(system: string, release: string, arch: string): string {
47
+ return [system, release, arch].filter(Boolean).join(" ").trim();
48
+ }
49
+
50
+ function getDeviceModel(): string {
51
+ const platform = os.platform();
52
+ const release = os.release();
53
+ const arch = os.arch();
54
+ if (platform === "darwin") return formatDeviceModel("macOS", release, arch);
55
+ if (platform === "win32") return formatDeviceModel("Windows", release, arch);
56
+ const label = platform === "linux" ? "Linux" : platform;
57
+ return formatDeviceModel(label, release, arch);
58
+ }
59
+
60
+ let getDeviceId = (): string => {
61
+ const deviceIdPath = path.join(getAgentDir(), DEVICE_ID_FILENAME);
62
+ try {
63
+ const existing = fs.readFileSync(deviceIdPath, "utf-8");
64
+ const trimmed = existing.trim();
65
+ if (trimmed) {
66
+ getDeviceId = () => trimmed;
67
+ return trimmed;
68
+ }
69
+ } catch (error) {
70
+ if (!isEnoent(error)) throw error;
71
+ }
72
+
73
+ const deviceId = crypto.randomUUID().replace(/-/g, "");
74
+ fs.writeFileSync(deviceIdPath, `${deviceId}\n`, { mode: 0o600 });
75
+ getDeviceId = () => deviceId;
76
+ return deviceId;
77
+ };
78
+
79
+ function sanitizeHeaderValue(value: string, fallback = ""): string {
80
+ const sanitized = value.replace(/[^\x20-\x7E]/g, "").trim();
81
+ return sanitized || fallback;
82
+ }
83
+
84
+ export let getKimiCommonHeaders = () => {
85
+ const headers = Object.freeze({
86
+ "User-Agent": `KimiCLI/${packageJson.version}`,
87
+ "X-Msh-Platform": "kimi_cli",
88
+ "X-Msh-Version": packageJson.version,
89
+ "X-Msh-Device-Name": sanitizeHeaderValue(os.hostname(), "unknown"),
90
+ "X-Msh-Device-Model": sanitizeHeaderValue(getDeviceModel(), "unknown"),
91
+ "X-Msh-Os-Version": sanitizeHeaderValue(os.version(), "unknown"),
92
+ "X-Msh-Device-Id": sanitizeHeaderValue(getDeviceId(), "unknown"),
93
+ });
94
+ getKimiCommonHeaders = () => headers;
95
+ return headers;
96
+ };
97
+
98
+ async function requestDeviceAuthorization(): Promise<{
99
+ userCode: string;
100
+ deviceCode: string;
101
+ verificationUri: string;
102
+ verificationUriComplete: string;
103
+ expiresInMs: number;
104
+ intervalMs: number;
105
+ }> {
106
+ const response = await fetch(`${resolveOAuthHost()}/api/oauth/device_authorization`, {
107
+ method: "POST",
108
+ headers: {
109
+ "Content-Type": "application/x-www-form-urlencoded",
110
+ ...getKimiCommonHeaders(),
111
+ },
112
+ body: new URLSearchParams({ client_id: CLIENT_ID }),
113
+ });
114
+
115
+ if (!response.ok) {
116
+ const text = await response.text();
117
+ throw new AIError.OAuthError(`Kimi device authorization failed: ${response.status} ${text}`, {
118
+ kind: "device-auth",
119
+ provider: "kimi",
120
+ status: response.status,
121
+ });
122
+ }
123
+
124
+ const payload = (await response.json()) as DeviceAuthorizationResponse;
125
+ const userCode = payload.user_code;
126
+ const deviceCode = payload.device_code;
127
+ const verificationUri = payload.verification_uri;
128
+ const verificationUriComplete = payload.verification_uri_complete;
129
+
130
+ if (!userCode || !deviceCode || !verificationUri) {
131
+ throw new AIError.OAuthError("Kimi device authorization response missing required fields", {
132
+ kind: "validation",
133
+ provider: "kimi",
134
+ });
135
+ }
136
+
137
+ const expiresInMs = typeof payload.expires_in === "number" ? payload.expires_in * 1000 : DEFAULT_DEVICE_FLOW_TTL_MS;
138
+ const intervalMs =
139
+ typeof payload.interval === "number" && payload.interval > 0 ? payload.interval * 1000 : DEFAULT_POLL_INTERVAL_MS;
140
+
141
+ return {
142
+ userCode,
143
+ deviceCode,
144
+ verificationUri,
145
+ verificationUriComplete: verificationUriComplete || verificationUri,
146
+ expiresInMs,
147
+ intervalMs,
148
+ };
149
+ }
150
+
151
+ function parseTokenPayload(payload: TokenResponse, refreshTokenFallback?: string): OAuthCredentials {
152
+ if (!payload.access_token || typeof payload.expires_in !== "number") {
153
+ throw new AIError.OAuthError("Kimi token response missing required fields", {
154
+ kind: "validation",
155
+ provider: "kimi",
156
+ });
157
+ }
158
+
159
+ const refresh = payload.refresh_token ?? refreshTokenFallback;
160
+ if (!refresh) {
161
+ throw new AIError.OAuthError("Kimi token response missing refresh token", {
162
+ kind: "validation",
163
+ provider: "kimi",
164
+ });
165
+ }
166
+
167
+ return {
168
+ access: payload.access_token,
169
+ refresh,
170
+ expires: Date.now() + payload.expires_in * 1000 - OAUTH_EXPIRY_SKEW_MS,
171
+ };
172
+ }
173
+
174
+ async function pollForToken(
175
+ deviceCode: string,
176
+ intervalMs: number,
177
+ expiresInMs: number,
178
+ signal?: AbortSignal,
179
+ ): Promise<OAuthCredentials> {
180
+ const deadline = Date.now() + expiresInMs;
181
+ let waitMs = Math.max(1000, intervalMs);
182
+
183
+ while (Date.now() < deadline) {
184
+ if (signal?.aborted) {
185
+ throw new AIError.LoginCancelledError();
186
+ }
187
+
188
+ const response = await fetch(`${resolveOAuthHost()}/api/oauth/token`, {
189
+ method: "POST",
190
+ headers: {
191
+ "Content-Type": "application/x-www-form-urlencoded",
192
+ ...getKimiCommonHeaders(),
193
+ },
194
+ body: new URLSearchParams({
195
+ client_id: CLIENT_ID,
196
+ device_code: deviceCode,
197
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
198
+ }),
199
+ });
200
+
201
+ const payload = (await response.json()) as TokenResponse;
202
+ if (response.ok && payload.access_token) {
203
+ return parseTokenPayload(payload);
204
+ }
205
+
206
+ const error = payload.error;
207
+ if (error === "authorization_pending") {
208
+ await scheduler.wait(waitMs, { signal });
209
+ continue;
210
+ }
211
+
212
+ if (error === "slow_down") {
213
+ waitMs += 5000;
214
+ const retryAfter = typeof payload.interval === "number" ? payload.interval * 1000 : undefined;
215
+ if (retryAfter && retryAfter > waitMs) waitMs = retryAfter;
216
+ await scheduler.wait(waitMs, { signal });
217
+ continue;
218
+ }
219
+
220
+ if (error === "expired_token") {
221
+ throw new AIError.OAuthError("Kimi device authorization expired", {
222
+ kind: "validation",
223
+ provider: "kimi",
224
+ });
225
+ }
226
+
227
+ if (error === "access_denied") {
228
+ throw new AIError.OAuthError("Kimi device authorization denied", {
229
+ kind: "validation",
230
+ provider: "kimi",
231
+ });
232
+ }
233
+
234
+ const description = payload.error_description ? `: ${payload.error_description}` : "";
235
+ throw new AIError.OAuthError(`Kimi device flow failed: ${error ?? response.status}${description}`, {
236
+ kind: "polling",
237
+ provider: "kimi",
238
+ });
239
+ }
240
+
241
+ throw new AIError.OAuthError("Kimi device flow timed out", {
242
+ kind: "timeout",
243
+ provider: "kimi",
244
+ });
245
+ }
246
+
247
+ /**
248
+ * Login with Kimi Code OAuth (device code flow).
249
+ */
250
+ export async function loginKimi(options: OAuthController): Promise<OAuthCredentials> {
251
+ const device = await requestDeviceAuthorization();
252
+ options.onAuth?.({
253
+ url: device.verificationUriComplete,
254
+ instructions: `Enter code: ${device.userCode}`,
255
+ });
256
+
257
+ return pollForToken(device.deviceCode, device.intervalMs, device.expiresInMs, options.signal);
258
+ }
259
+
260
+ /**
261
+ * Refresh Kimi OAuth token.
262
+ */
263
+ export async function refreshKimiToken(refreshToken: string): Promise<OAuthCredentials> {
264
+ const response = await fetch(`${resolveOAuthHost()}/api/oauth/token`, {
265
+ method: "POST",
266
+ headers: {
267
+ "Content-Type": "application/x-www-form-urlencoded",
268
+ ...getKimiCommonHeaders(),
269
+ },
270
+ body: new URLSearchParams({
271
+ grant_type: "refresh_token",
272
+ refresh_token: refreshToken,
273
+ client_id: CLIENT_ID,
274
+ }),
275
+ });
276
+
277
+ if (!response.ok) {
278
+ const payload = (await response.json().catch(() => undefined)) as TokenResponse | undefined;
279
+ const description = payload?.error_description ? `: ${payload.error_description}` : "";
280
+ throw new AIError.OAuthError(`Kimi token refresh failed: ${response.status}${description}`, {
281
+ kind: "token-refresh",
282
+ provider: "kimi",
283
+ status: response.status,
284
+ });
285
+ }
286
+
287
+ const payload = (await response.json()) as TokenResponse;
288
+ return parseTokenPayload(payload, refreshToken);
289
+ }