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,315 @@
1
+ /**
2
+ * Abstract base class for OAuth flows with local callback servers.
3
+ *
4
+ * Handles:
5
+ * - Port allocation (tries expected port, falls back to random)
6
+ * - Callback server setup and request handling
7
+ * - Common OAuth flow logic
8
+ *
9
+ * Providers extend this and implement:
10
+ * - generateAuthUrl(): Build provider-specific authorization URL
11
+ * - exchangeToken(): Exchange authorization code for tokens
12
+ */
13
+ import * as AIError from "../../error";
14
+ import templateHtml from "./oauth.html" with { type: "text" };
15
+ import type { OAuthController, OAuthCredentials } from "./types";
16
+
17
+ const DEFAULT_TIMEOUT = 300_000;
18
+ const DEFAULT_HOSTNAME = "localhost";
19
+ const CALLBACK_PATH = "/callback";
20
+
21
+ export type CallbackResult = { code: string; state: string };
22
+
23
+ export interface OAuthCallbackFlowOptions {
24
+ preferredPort: number;
25
+ callbackPath?: string;
26
+ callbackHostname?: string;
27
+ /** Exact redirect URI advertised to the provider; disables port fallback. */
28
+ redirectUri?: string;
29
+ /**
30
+ * Whether the flow may bind to a random port when {@link preferredPort} is
31
+ * unavailable. Defaults to `true` so historical AI-provider flows (which
32
+ * pick uncommon ports and tolerate any loopback callback) keep working.
33
+ *
34
+ * Set to `false` for providers that validate the redirect URI against a
35
+ * registered callback — silently advertising a random-port URI would be
36
+ * rejected by the authorization server, leaving the browser on an opaque
37
+ * 500 page and the local callback waiting until the 5-minute timeout fires.
38
+ * With fallback disabled, {@link OAuthCallbackFlow.login} throws a
39
+ * {@link AIError.ConfigurationError} immediately so the caller can surface
40
+ * an actionable message before opening the browser.
41
+ */
42
+ allowPortFallback?: boolean;
43
+ }
44
+
45
+ /**
46
+ * Abstract base class for OAuth flows with local callback servers.
47
+ */
48
+ export abstract class OAuthCallbackFlow {
49
+ ctrl: OAuthController;
50
+ preferredPort: number;
51
+ callbackPath: string;
52
+ callbackHostname: string;
53
+ redirectUri?: string;
54
+ allowPortFallback: boolean;
55
+ #callbackResolve?: (result: CallbackResult) => void;
56
+ #callbackReject?: (error: string) => void;
57
+
58
+ constructor(
59
+ ctrl: OAuthController,
60
+ preferredPortOrOptions: number | OAuthCallbackFlowOptions,
61
+ callbackPath: string = CALLBACK_PATH,
62
+ ) {
63
+ this.ctrl = ctrl;
64
+ if (typeof preferredPortOrOptions === "number") {
65
+ this.preferredPort = preferredPortOrOptions;
66
+ this.callbackPath = callbackPath;
67
+ this.callbackHostname = DEFAULT_HOSTNAME;
68
+ this.allowPortFallback = true;
69
+ return;
70
+ }
71
+
72
+ this.preferredPort = preferredPortOrOptions.preferredPort;
73
+ this.callbackPath = preferredPortOrOptions.callbackPath ?? CALLBACK_PATH;
74
+ this.callbackHostname = preferredPortOrOptions.callbackHostname ?? DEFAULT_HOSTNAME;
75
+ this.redirectUri = preferredPortOrOptions.redirectUri;
76
+ this.allowPortFallback = preferredPortOrOptions.allowPortFallback ?? true;
77
+ }
78
+
79
+ /**
80
+ * Generate provider-specific authorization URL.
81
+ * @param state - CSRF state token
82
+ * @param redirectUri - The actual redirect URI to use (may differ from expected if port fallback occurred)
83
+ * @returns Authorization URL and optional instructions
84
+ */
85
+ abstract generateAuthUrl(state: string, redirectUri: string): Promise<{ url: string; instructions?: string }>;
86
+
87
+ /**
88
+ * Exchange authorization code for OAuth tokens.
89
+ * @param code - Authorization code from callback
90
+ * @param state - CSRF state token
91
+ * @param redirectUri - The actual redirect URI used (must match authorization request)
92
+ * @returns OAuth credentials
93
+ */
94
+ abstract exchangeToken(code: string, state: string, redirectUri: string): Promise<OAuthCredentials>;
95
+
96
+ /**
97
+ * Generate CSRF state token. Override if provider needs custom state generation.
98
+ */
99
+ generateState(): string {
100
+ const bytes = new Uint8Array(16);
101
+ crypto.getRandomValues(bytes);
102
+ return Array.from(bytes)
103
+ .map(value => value.toString(16).padStart(2, "0"))
104
+ .join("");
105
+ }
106
+
107
+ #loginCancelledError(): AIError.LoginCancelledError {
108
+ return new AIError.LoginCancelledError(`OAuth callback cancelled: ${this.ctrl.signal?.reason}`);
109
+ }
110
+
111
+ #throwIfCancelled(): void {
112
+ if (this.ctrl.signal?.aborted) throw this.#loginCancelledError();
113
+ }
114
+
115
+ /**
116
+ * Execute the OAuth login flow.
117
+ */
118
+ async login(): Promise<OAuthCredentials> {
119
+ const state = this.generateState();
120
+ this.#throwIfCancelled();
121
+
122
+ // Start callback server first to get actual redirect URI
123
+ const { server, redirectUri } = await this.#startCallbackServer(state);
124
+
125
+ try {
126
+ this.#throwIfCancelled();
127
+ // Generate auth URL with the ACTUAL redirect URI (may differ from expected if port was busy)
128
+ const { url: authUrl, instructions } = await this.generateAuthUrl(state, redirectUri);
129
+ this.#throwIfCancelled();
130
+
131
+ // Notify controller that auth is ready
132
+ this.ctrl.onAuth?.({ url: authUrl, instructions });
133
+ this.ctrl.onProgress?.("Waiting for browser authentication...");
134
+
135
+ // Wait for callback or manual input
136
+ const { code } = await this.#waitForCallback(state);
137
+ this.#throwIfCancelled();
138
+
139
+ this.ctrl.onProgress?.("Exchanging authorization code for tokens...");
140
+
141
+ return await this.exchangeToken(code, state, redirectUri);
142
+ } finally {
143
+ server.stop();
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Start callback server, trying preferred port first, falling back to random.
149
+ */
150
+ async #startCallbackServer(expectedState: string): Promise<{ server: Bun.Server<unknown>; redirectUri: string }> {
151
+ try {
152
+ const server = this.#createServer(this.preferredPort, expectedState);
153
+ if (this.redirectUri) {
154
+ return { server, redirectUri: this.redirectUri };
155
+ }
156
+ const redirectUri = `http://${this.callbackHostname}:${this.preferredPort}${this.callbackPath}`;
157
+ return { server, redirectUri };
158
+ } catch (cause) {
159
+ if (this.redirectUri) {
160
+ throw new AIError.ConfigurationError(
161
+ `OAuth callback port ${this.preferredPort} is in use, but oauth.redirectUri (${this.redirectUri}) requires this exact port. Free port ${this.preferredPort} (e.g. stop the process bound to it) and retry, or change oauth.redirectUri to point at an available port.`,
162
+ { cause },
163
+ );
164
+ }
165
+ if (!this.allowPortFallback) {
166
+ throw new AIError.ConfigurationError(
167
+ `OAuth callback port ${this.preferredPort} is in use. The OAuth provider validates redirect URIs against its registered callback, so falling back to a random port would be rejected. Free port ${this.preferredPort} (e.g. stop the process bound to it) and retry, or set oauth.callbackPort/oauth.redirectUri to a port the provider has registered.`,
168
+ { cause },
169
+ );
170
+ }
171
+ const server = this.#createServer(0, expectedState);
172
+ const actualPort = server.port;
173
+ const redirectUri = `http://${this.callbackHostname}:${actualPort}${this.callbackPath}`;
174
+ this.ctrl.onProgress?.(`Preferred port ${this.preferredPort} unavailable, using port ${actualPort}`);
175
+ return { server, redirectUri };
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Create HTTP server for OAuth callback.
181
+ */
182
+ #createServer(port: number, expectedState: string): Bun.Server<unknown> {
183
+ const hostname = this.callbackHostname === DEFAULT_HOSTNAME ? undefined : this.callbackHostname;
184
+ return Bun.serve({
185
+ ...(hostname === undefined ? {} : { hostname }),
186
+ port,
187
+ reusePort: false,
188
+ fetch: req => this.#handleCallback(req, expectedState),
189
+ });
190
+ }
191
+
192
+ /**
193
+ * Handle OAuth callback HTTP request.
194
+ */
195
+ #handleCallback(req: Request, expectedState: string): Response {
196
+ const url = new URL(req.url);
197
+
198
+ if (url.pathname !== this.callbackPath) {
199
+ return new Response("Not Found", { status: 404 });
200
+ }
201
+
202
+ const code = url.searchParams.get("code");
203
+ const state = url.searchParams.get("state") || "";
204
+ const error = url.searchParams.get("error") || "";
205
+ const errorDescription = url.searchParams.get("error_description") || error;
206
+
207
+ type OkState = { ok: true; code: string; state: string };
208
+ type ErrorState = { ok?: false; error?: string };
209
+ let resultState: OkState | ErrorState;
210
+
211
+ if (error) {
212
+ resultState = { ok: false, error: `Authorization failed: ${errorDescription}` };
213
+ } else if (!code) {
214
+ resultState = { ok: false, error: "Missing authorization code" };
215
+ } else if (expectedState && state !== expectedState) {
216
+ resultState = { ok: false, error: "State mismatch - possible CSRF attack" };
217
+ } else {
218
+ resultState = { ok: true, code, state };
219
+ }
220
+
221
+ // Signal to waitForCallback - capture refs before they could be cleared
222
+ const resolve = this.#callbackResolve;
223
+ const reject = this.#callbackReject;
224
+ queueMicrotask(() => {
225
+ if (resultState.ok) {
226
+ resolve?.({ code: resultState.code, state: resultState.state });
227
+ } else {
228
+ reject?.(resultState.error ?? "Unknown error");
229
+ }
230
+ });
231
+
232
+ return new Response(
233
+ (templateHtml as unknown as string).replaceAll("__OAUTH_STATE__", JSON.stringify(resultState)),
234
+ {
235
+ status: resultState.ok ? 200 : 500,
236
+ headers: { "Content-Type": "text/html" },
237
+ },
238
+ );
239
+ }
240
+
241
+ /**
242
+ * Wait for OAuth callback or manual input (whichever comes first).
243
+ */
244
+ #waitForCallback(expectedState: string): Promise<CallbackResult> {
245
+ const timeoutSignal = AbortSignal.timeout(DEFAULT_TIMEOUT);
246
+ const signal = this.ctrl.signal ? AbortSignal.any([this.ctrl.signal, timeoutSignal]) : timeoutSignal;
247
+ if (signal.aborted) return Promise.reject(this.#loginCancelledError());
248
+
249
+ const callback = Promise.withResolvers<CallbackResult>();
250
+ this.#callbackResolve = callback.resolve;
251
+ this.#callbackReject = callback.reject;
252
+
253
+ signal.addEventListener("abort", () => {
254
+ this.#callbackResolve = undefined;
255
+ this.#callbackReject = undefined;
256
+ callback.reject(new AIError.LoginCancelledError(`OAuth callback cancelled: ${signal.reason}`));
257
+ });
258
+ const callbackPromise = callback.promise;
259
+
260
+ // Manual input race (if supported)
261
+ if (this.ctrl.onManualCodeInput) {
262
+ const requestManualInput = this.ctrl.onManualCodeInput;
263
+ const manualPromise = (async (): Promise<CallbackResult> => {
264
+ while (true) {
265
+ const result = await Promise.race([
266
+ callbackPromise,
267
+ requestManualInput()
268
+ .then((input): CallbackResult | null => {
269
+ const parsed = parseCallbackInput(input);
270
+ if (!parsed.code) return null;
271
+ if (expectedState && parsed.state && parsed.state !== expectedState) return null;
272
+ return { code: parsed.code, state: parsed.state ?? "" };
273
+ })
274
+ .catch((): CallbackResult | null => null),
275
+ ]);
276
+ if (result) return result;
277
+ }
278
+ })();
279
+
280
+ return Promise.race([callbackPromise, manualPromise]);
281
+ }
282
+
283
+ return callbackPromise;
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Parse a redirect URL or code string to extract code and state.
289
+ */
290
+ export function parseCallbackInput(input: string): { code?: string; state?: string } {
291
+ const value = input.trim();
292
+ if (!value) return {};
293
+
294
+ try {
295
+ const url = new URL(value);
296
+ return {
297
+ code: url.searchParams.get("code") ?? undefined,
298
+ state: url.searchParams.get("state") ?? undefined,
299
+ };
300
+ } catch {
301
+ // Not a URL - check for query string format
302
+ }
303
+
304
+ if (value.includes("code=")) {
305
+ const params = new URLSearchParams(value.replace(/^[?#]/, ""));
306
+ return {
307
+ code: params.get("code") ?? undefined,
308
+ state: params.get("state") ?? undefined,
309
+ };
310
+ }
311
+
312
+ // Assume raw code, possibly with state after #
313
+ const [code, state] = value.split("#", 2);
314
+ return { code, state };
315
+ }
@@ -0,0 +1,171 @@
1
+ import * as AIError from "../../error";
2
+ import { generatePKCE } from "./pkce";
3
+ import type { OAuthCredentials } from "./types";
4
+
5
+ const CURSOR_LOGIN_URL = "https://cursor.com/loginDeepControl";
6
+ const CURSOR_POLL_URL = "https://api2.cursor.sh/auth/poll";
7
+ const CURSOR_REFRESH_URL = "https://api2.cursor.sh/auth/exchange_user_api_key";
8
+
9
+ const POLL_MAX_ATTEMPTS = 150;
10
+ const POLL_BASE_DELAY = 1000;
11
+ const POLL_MAX_DELAY = 10000;
12
+ const POLL_BACKOFF_MULTIPLIER = 1.2;
13
+
14
+ export interface CursorAuthParams {
15
+ verifier: string;
16
+ challenge: string;
17
+ uuid: string;
18
+ loginUrl: string;
19
+ }
20
+
21
+ export async function generateCursorAuthParams(): Promise<CursorAuthParams> {
22
+ const { verifier, challenge } = await generatePKCE();
23
+ const uuid = crypto.randomUUID();
24
+
25
+ const params = new URLSearchParams({
26
+ challenge,
27
+ uuid,
28
+ mode: "login",
29
+ redirectTarget: "cli",
30
+ });
31
+
32
+ const loginUrl = `${CURSOR_LOGIN_URL}?${params.toString()}`;
33
+
34
+ return { verifier, challenge, uuid, loginUrl };
35
+ }
36
+
37
+ export async function pollCursorAuth(
38
+ uuid: string,
39
+ verifier: string,
40
+ ): Promise<{ accessToken: string; refreshToken: string }> {
41
+ let delay = POLL_BASE_DELAY;
42
+ let consecutiveErrors = 0;
43
+
44
+ for (let attempt = 0; attempt < POLL_MAX_ATTEMPTS; attempt++) {
45
+ await Bun.sleep(delay);
46
+
47
+ try {
48
+ const response = await fetch(`${CURSOR_POLL_URL}?uuid=${uuid}&verifier=${verifier}`);
49
+
50
+ if (response.status === 404) {
51
+ consecutiveErrors = 0;
52
+ delay = Math.min(delay * POLL_BACKOFF_MULTIPLIER, POLL_MAX_DELAY);
53
+ continue;
54
+ }
55
+
56
+ if (response.ok) {
57
+ const data = (await response.json()) as {
58
+ accessToken: string;
59
+ refreshToken: string;
60
+ };
61
+ return {
62
+ accessToken: data.accessToken,
63
+ refreshToken: data.refreshToken,
64
+ };
65
+ }
66
+
67
+ throw new AIError.OAuthError(`Poll failed: ${response.status}`, {
68
+ kind: "polling",
69
+ provider: "cursor",
70
+ status: response.status,
71
+ });
72
+ } catch {
73
+ consecutiveErrors++;
74
+ if (consecutiveErrors >= 3) {
75
+ throw new AIError.OAuthError("Too many consecutive errors during Cursor auth polling", {
76
+ kind: "polling",
77
+ provider: "cursor",
78
+ });
79
+ }
80
+ }
81
+ }
82
+
83
+ throw new AIError.OAuthError("Cursor authentication polling timeout", {
84
+ kind: "timeout",
85
+ provider: "cursor",
86
+ });
87
+ }
88
+
89
+ export async function loginCursor(
90
+ onAuthUrl: (url: string) => void,
91
+ onPollStart?: () => void,
92
+ ): Promise<OAuthCredentials> {
93
+ const { verifier, uuid, loginUrl } = await generateCursorAuthParams();
94
+
95
+ onAuthUrl(loginUrl);
96
+ onPollStart?.();
97
+
98
+ const { accessToken, refreshToken } = await pollCursorAuth(uuid, verifier);
99
+
100
+ const expiresAt = getTokenExpiry(accessToken);
101
+
102
+ return {
103
+ access: accessToken,
104
+ refresh: refreshToken,
105
+ expires: expiresAt,
106
+ };
107
+ }
108
+
109
+ export async function refreshCursorToken(apiKeyOrRefreshToken: string): Promise<OAuthCredentials> {
110
+ const response = await fetch(CURSOR_REFRESH_URL, {
111
+ method: "POST",
112
+ headers: {
113
+ Authorization: `Bearer ${apiKeyOrRefreshToken}`,
114
+ "Content-Type": "application/json",
115
+ },
116
+ body: "{}",
117
+ });
118
+
119
+ if (!response.ok) {
120
+ const error = await response.text();
121
+ throw new AIError.OAuthError(`Cursor token refresh failed: ${error}`, {
122
+ kind: "token-refresh",
123
+ provider: "cursor",
124
+ });
125
+ }
126
+
127
+ const data = (await response.json()) as {
128
+ accessToken: string;
129
+ refreshToken: string;
130
+ };
131
+
132
+ const expiresAt = getTokenExpiry(data.accessToken);
133
+
134
+ return {
135
+ access: data.accessToken,
136
+ refresh: data.refreshToken || apiKeyOrRefreshToken,
137
+ expires: expiresAt,
138
+ };
139
+ }
140
+
141
+ function getTokenExpiry(token: string): number {
142
+ try {
143
+ const parts = token.split(".");
144
+ if (parts.length !== 3) {
145
+ return Date.now() + 3600 * 1000;
146
+ }
147
+ const payload = parts[1];
148
+ if (!payload) {
149
+ return Date.now() + 3600 * 1000;
150
+ }
151
+ const decoded = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
152
+ if (decoded && typeof decoded === "object" && typeof decoded.exp === "number") {
153
+ return decoded.exp * 1000 - 5 * 60 * 1000;
154
+ }
155
+ } catch {
156
+ // Ignore parsing errors
157
+ }
158
+ return Date.now() + 3600 * 1000;
159
+ }
160
+
161
+ export function isCursorTokenExpiringSoon(token: string, thresholdSeconds = 300): boolean {
162
+ try {
163
+ const [, payload] = token.split(".");
164
+ if (!payload) return true;
165
+ const decoded = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
166
+ const currentTime = Math.floor(Date.now() / 1000);
167
+ return decoded.exp - currentTime < thresholdSeconds;
168
+ } catch {
169
+ return true;
170
+ }
171
+ }
@@ -0,0 +1,124 @@
1
+ import * as AIError from "../../error";
2
+ import { OAuthCallbackFlow } from "./callback-server";
3
+ import { generatePKCE } from "./pkce";
4
+ import type { OAuthController, OAuthCredentials } from "./types";
5
+
6
+ type FetchFunction = NonNullable<OAuthController["fetch"]>;
7
+
8
+ const DEVIN_WEBAPP_URL = "https://app.devin.ai";
9
+ const DEVIN_API_URL = "https://api.devin.ai";
10
+ const CALLBACK_PORT = 59653;
11
+ const CALLBACK_PATH = "/callback";
12
+ const TOKEN_PATH = "/auth/cli/token";
13
+ const FALLBACK_EXPIRES_MS = 365 * 24 * 60 * 60 * 1000;
14
+
15
+ interface DevinPKCEParams {
16
+ verifier: string;
17
+ challenge: string;
18
+ }
19
+
20
+ export async function loginDevin(ctrl: OAuthController): Promise<OAuthCredentials> {
21
+ const flow = new DevinOAuthFlow(ctrl);
22
+ return flow.login();
23
+ }
24
+
25
+ class DevinOAuthFlow extends OAuthCallbackFlow {
26
+ #pkce?: DevinPKCEParams;
27
+
28
+ constructor(ctrl: OAuthController) {
29
+ super(ctrl, {
30
+ preferredPort: CALLBACK_PORT,
31
+ callbackPath: CALLBACK_PATH,
32
+ callbackHostname: "127.0.0.1",
33
+ });
34
+ }
35
+
36
+ generateState(): string {
37
+ return crypto.randomUUID();
38
+ }
39
+
40
+ async generateAuthUrl(state: string, redirectUri: string): Promise<{ url: string; instructions?: string }> {
41
+ this.#pkce = await generatePKCE();
42
+ const params = new URLSearchParams({
43
+ redirect_uri: redirectUri,
44
+ state,
45
+ prompt: "select_account",
46
+ code_challenge: this.#pkce.challenge,
47
+ code_challenge_method: "S256",
48
+ });
49
+
50
+ return {
51
+ url: `${DEVIN_WEBAPP_URL}/auth/cli/continue?${params.toString()}`,
52
+ instructions: "Sign in to Devin in your browser.",
53
+ };
54
+ }
55
+
56
+ async exchangeToken(code: string): Promise<OAuthCredentials> {
57
+ if (!this.#pkce) {
58
+ throw new AIError.OAuthError("Devin PKCE verifier was not initialized", {
59
+ kind: "configuration",
60
+ provider: "devin",
61
+ });
62
+ }
63
+ const token = await exchangeDevinCliToken(code, this.#pkce.verifier, this.ctrl.fetch);
64
+
65
+ return {
66
+ access: token,
67
+ refresh: token,
68
+ expires: getTokenExpiry(token),
69
+ apiEndpoint: DEVIN_API_URL,
70
+ enterpriseUrl: DEVIN_WEBAPP_URL,
71
+ };
72
+ }
73
+ }
74
+
75
+ export async function exchangeDevinCliToken(
76
+ authorizationCode: string,
77
+ codeVerifier: string,
78
+ fetchImpl: FetchFunction = fetch,
79
+ ): Promise<string> {
80
+ const response = await fetchImpl(`${DEVIN_API_URL}${TOKEN_PATH}`, {
81
+ method: "POST",
82
+ headers: {
83
+ Accept: "application/json",
84
+ "Content-Type": "application/json",
85
+ },
86
+ body: JSON.stringify({
87
+ code: authorizationCode,
88
+ code_verifier: codeVerifier,
89
+ }),
90
+ });
91
+
92
+ if (!response.ok) {
93
+ const error = await response.text();
94
+ throw new AIError.OAuthError(`Devin CLI token exchange failed: ${response.status} ${error}`.trim(), {
95
+ kind: "token-exchange",
96
+ provider: "devin",
97
+ status: response.status,
98
+ });
99
+ }
100
+
101
+ const data = (await response.json()) as { token?: unknown };
102
+ if (typeof data.token !== "string" || data.token.length === 0) {
103
+ throw new AIError.OAuthError("Devin CLI token exchange returned an empty token", {
104
+ kind: "validation",
105
+ provider: "devin",
106
+ });
107
+ }
108
+ return data.token;
109
+ }
110
+
111
+ function getTokenExpiry(token: string): number {
112
+ try {
113
+ const [, payload] = token.split(".");
114
+ if (payload) {
115
+ const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf8")) as { exp?: unknown };
116
+ if (typeof decoded.exp === "number" && Number.isFinite(decoded.exp)) {
117
+ return decoded.exp * 1000 - 5 * 60 * 1000;
118
+ }
119
+ }
120
+ } catch {
121
+ // Ignore malformed non-JWT tokens and use a conservative long-lived fallback.
122
+ }
123
+ return Date.now() + FALLBACK_EXPIRES_MS;
124
+ }