@linxiraos/pi-ai 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (639) hide show
  1. package/CHANGELOG.md +5066 -0
  2. package/README.md +1195 -0
  3. package/dist/types/api-registry.d.ts +30 -0
  4. package/dist/types/auth/sqlite-credential-store.d.ts +117 -0
  5. package/dist/types/auth-broker/client.d.ts +93 -0
  6. package/dist/types/auth-broker/discover.d.ts +39 -0
  7. package/dist/types/auth-broker/index.d.ts +7 -0
  8. package/dist/types/auth-broker/refresher.d.ts +25 -0
  9. package/dist/types/auth-broker/remote-store.d.ts +136 -0
  10. package/dist/types/auth-broker/server.d.ts +48 -0
  11. package/dist/types/auth-broker/snapshot-cache.d.ts +17 -0
  12. package/dist/types/auth-broker/types.d.ts +152 -0
  13. package/dist/types/auth-broker/wire-schema-resource.d.ts +53 -0
  14. package/dist/types/auth-broker/wire-schemas.d.ts +5 -0
  15. package/dist/types/auth-gateway/http.d.ts +56 -0
  16. package/dist/types/auth-gateway/index.d.ts +3 -0
  17. package/dist/types/auth-gateway/server.d.ts +36 -0
  18. package/dist/types/auth-gateway/types.d.ts +127 -0
  19. package/dist/types/auth-retry.d.ts +150 -0
  20. package/dist/types/auth-storage.d.ts +1258 -0
  21. package/dist/types/dialect/anthropic.d.ts +15 -0
  22. package/dist/types/dialect/catalog.d.ts +3 -0
  23. package/dist/types/dialect/coercion.d.ts +23 -0
  24. package/dist/types/dialect/deepseek.d.ts +14 -0
  25. package/dist/types/dialect/demotion.d.ts +30 -0
  26. package/dist/types/dialect/examples.d.ts +18 -0
  27. package/dist/types/dialect/factory.d.ts +3 -0
  28. package/dist/types/dialect/fenced-thinking.d.ts +53 -0
  29. package/dist/types/dialect/gemini.d.ts +17 -0
  30. package/dist/types/dialect/gemma.d.ts +15 -0
  31. package/dist/types/dialect/glm.d.ts +9 -0
  32. package/dist/types/dialect/harmony.d.ts +8 -0
  33. package/dist/types/dialect/hermes.d.ts +9 -0
  34. package/dist/types/dialect/history.d.ts +3 -0
  35. package/dist/types/dialect/index.d.ts +11 -0
  36. package/dist/types/dialect/inventory.d.ts +9 -0
  37. package/dist/types/dialect/kimi.d.ts +14 -0
  38. package/dist/types/dialect/minimax.d.ts +3 -0
  39. package/dist/types/dialect/owned-stream.d.ts +4 -0
  40. package/dist/types/dialect/qwen3.d.ts +9 -0
  41. package/dist/types/dialect/rendering.d.ts +54 -0
  42. package/dist/types/dialect/thinking.d.ts +6 -0
  43. package/dist/types/dialect/types.d.ts +68 -0
  44. package/dist/types/dialect/xml.d.ts +9 -0
  45. package/dist/types/error/abort.d.ts +14 -0
  46. package/dist/types/error/auth-classify.d.ts +20 -0
  47. package/dist/types/error/auth.d.ts +27 -0
  48. package/dist/types/error/aws.d.ts +27 -0
  49. package/dist/types/error/classes.d.ts +106 -0
  50. package/dist/types/error/finalize.d.ts +39 -0
  51. package/dist/types/error/flags.d.ts +94 -0
  52. package/dist/types/error/format.d.ts +20 -0
  53. package/dist/types/error/gateway.d.ts +20 -0
  54. package/dist/types/error/index.d.ts +14 -0
  55. package/dist/types/error/oauth.d.ts +43 -0
  56. package/dist/types/error/provider.d.ts +42 -0
  57. package/dist/types/error/rate-limit.d.ts +80 -0
  58. package/dist/types/error/retryable.d.ts +27 -0
  59. package/dist/types/error/validation.d.ts +32 -0
  60. package/dist/types/index.d.ts +51 -0
  61. package/dist/types/provider-details.d.ts +24 -0
  62. package/dist/types/providers/amazon-bedrock.d.ts +39 -0
  63. package/dist/types/providers/anthropic-client.d.ts +106 -0
  64. package/dist/types/providers/anthropic-messages-server-schema.d.ts +937 -0
  65. package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
  66. package/dist/types/providers/anthropic-wire.d.ts +345 -0
  67. package/dist/types/providers/anthropic.d.ts +261 -0
  68. package/dist/types/providers/aws-credentials.d.ts +48 -0
  69. package/dist/types/providers/aws-eventstream.d.ts +39 -0
  70. package/dist/types/providers/aws-sigv4.d.ts +55 -0
  71. package/dist/types/providers/azure-openai-responses.d.ts +16 -0
  72. package/dist/types/providers/bedrock-mantle.d.ts +13 -0
  73. package/dist/types/providers/claude-code-fingerprint.d.ts +19 -0
  74. package/dist/types/providers/cowork-fetch.d.ts +3 -0
  75. package/dist/types/providers/cursor/exec-modern.d.ts +98 -0
  76. package/dist/types/providers/cursor-pi-args.d.ts +105 -0
  77. package/dist/types/providers/cursor.d.ts +221 -0
  78. package/dist/types/providers/devin.d.ts +12 -0
  79. package/dist/types/providers/error-message.d.ts +25 -0
  80. package/dist/types/providers/github-copilot-headers.d.ts +40 -0
  81. package/dist/types/providers/gitlab-duo-workflow.d.ts +254 -0
  82. package/dist/types/providers/gitlab-duo.d.ts +27 -0
  83. package/dist/types/providers/google-auth.d.ts +24 -0
  84. package/dist/types/providers/google-gemini-cli.d.ts +120 -0
  85. package/dist/types/providers/google-shared.d.ts +203 -0
  86. package/dist/types/providers/google-types.d.ts +155 -0
  87. package/dist/types/providers/google-vertex.d.ts +7 -0
  88. package/dist/types/providers/google.d.ts +4 -0
  89. package/dist/types/providers/grammar.d.ts +1 -0
  90. package/dist/types/providers/kimi.d.ts +27 -0
  91. package/dist/types/providers/mock.d.ts +179 -0
  92. package/dist/types/providers/ollama.d.ts +8 -0
  93. package/dist/types/providers/openai-anthropic-shim.d.ts +35 -0
  94. package/dist/types/providers/openai-chat-server-schema.d.ts +1311 -0
  95. package/dist/types/providers/openai-chat-server.d.ts +16 -0
  96. package/dist/types/providers/openai-chat-wire.d.ts +669 -0
  97. package/dist/types/providers/openai-codex/request-transformer.d.ts +109 -0
  98. package/dist/types/providers/openai-codex/response-handler.d.ts +26 -0
  99. package/dist/types/providers/openai-codex-responses.d.ts +238 -0
  100. package/dist/types/providers/openai-completions.d.ts +48 -0
  101. package/dist/types/providers/openai-reasoning-fallback.d.ts +25 -0
  102. package/dist/types/providers/openai-responses-server-schema.d.ts +1314 -0
  103. package/dist/types/providers/openai-responses-server.d.ts +17 -0
  104. package/dist/types/providers/openai-responses-wire.d.ts +6099 -0
  105. package/dist/types/providers/openai-responses.d.ts +131 -0
  106. package/dist/types/providers/openai-shared.d.ts +624 -0
  107. package/dist/types/providers/pi-native-client.d.ts +13 -0
  108. package/dist/types/providers/pi-native-server.d.ts +69 -0
  109. package/dist/types/providers/register-builtins.d.ts +37 -0
  110. package/dist/types/providers/synthetic.d.ts +26 -0
  111. package/dist/types/providers/transform-messages.d.ts +32 -0
  112. package/dist/types/providers/vision-guard.d.ts +20 -0
  113. package/dist/types/registry/aiand.d.ts +7 -0
  114. package/dist/types/registry/aimlapi.d.ts +4 -0
  115. package/dist/types/registry/alibaba-coding-plan.d.ts +8 -0
  116. package/dist/types/registry/alibaba-token-plan.d.ts +18 -0
  117. package/dist/types/registry/amazon-bedrock.d.ts +5 -0
  118. package/dist/types/registry/anthropic.d.ts +10 -0
  119. package/dist/types/registry/api-key-login.d.ts +42 -0
  120. package/dist/types/registry/api-key-validation.d.ts +43 -0
  121. package/dist/types/registry/aws.d.ts +13 -0
  122. package/dist/types/registry/azure.d.ts +4 -0
  123. package/dist/types/registry/baseten.d.ts +7 -0
  124. package/dist/types/registry/bedrock-mantle.d.ts +22 -0
  125. package/dist/types/registry/cerebras.d.ts +7 -0
  126. package/dist/types/registry/cloudflare-ai-gateway.d.ts +13 -0
  127. package/dist/types/registry/coreweave.d.ts +7 -0
  128. package/dist/types/registry/cursor.d.ts +7 -0
  129. package/dist/types/registry/deepseek.d.ts +8 -0
  130. package/dist/types/registry/derived.d.ts +5 -0
  131. package/dist/types/registry/devin.d.ts +8 -0
  132. package/dist/types/registry/exa.d.ts +8 -0
  133. package/dist/types/registry/firepass.d.ts +16 -0
  134. package/dist/types/registry/fireworks.d.ts +7 -0
  135. package/dist/types/registry/github-copilot.d.ts +7 -0
  136. package/dist/types/registry/gitlab-duo-workflow.d.ts +10 -0
  137. package/dist/types/registry/gitlab-duo.d.ts +9 -0
  138. package/dist/types/registry/gmi-cloud.d.ts +7 -0
  139. package/dist/types/registry/google-antigravity.d.ts +9 -0
  140. package/dist/types/registry/google-gemini-cli.d.ts +9 -0
  141. package/dist/types/registry/google-vertex.d.ts +5 -0
  142. package/dist/types/registry/google.d.ts +4 -0
  143. package/dist/types/registry/groq.d.ts +4 -0
  144. package/dist/types/registry/huggingface.d.ts +7 -0
  145. package/dist/types/registry/index.d.ts +4 -0
  146. package/dist/types/registry/kagi.d.ts +14 -0
  147. package/dist/types/registry/kilo.d.ts +7 -0
  148. package/dist/types/registry/kimi-code.d.ts +7 -0
  149. package/dist/types/registry/litellm.d.ts +13 -0
  150. package/dist/types/registry/llama-cpp.d.ts +8 -0
  151. package/dist/types/registry/lm-studio.d.ts +8 -0
  152. package/dist/types/registry/meta.d.ts +7 -0
  153. package/dist/types/registry/minimax-code-cn.d.ts +6 -0
  154. package/dist/types/registry/minimax-code.d.ts +6 -0
  155. package/dist/types/registry/minimax.d.ts +4 -0
  156. package/dist/types/registry/mistral.d.ts +4 -0
  157. package/dist/types/registry/moonshot.d.ts +7 -0
  158. package/dist/types/registry/nanogpt.d.ts +7 -0
  159. package/dist/types/registry/novita.d.ts +6 -0
  160. package/dist/types/registry/nvidia.d.ts +7 -0
  161. package/dist/types/registry/oauth/anthropic-constants.d.ts +12 -0
  162. package/dist/types/registry/oauth/anthropic.d.ts +24 -0
  163. package/dist/types/registry/oauth/callback-server.d.ts +74 -0
  164. package/dist/types/registry/oauth/cursor.d.ts +16 -0
  165. package/dist/types/registry/oauth/device-code.d.ts +25 -0
  166. package/dist/types/registry/oauth/devin.d.ts +5 -0
  167. package/dist/types/registry/oauth/github-copilot.d.ts +30 -0
  168. package/dist/types/registry/oauth/gitlab-duo-workflow.d.ts +6 -0
  169. package/dist/types/registry/oauth/gitlab-duo.d.ts +3 -0
  170. package/dist/types/registry/oauth/google-antigravity.d.ts +11 -0
  171. package/dist/types/registry/oauth/google-gemini-cli.d.ts +22 -0
  172. package/dist/types/registry/oauth/google-oauth-shared.d.ts +56 -0
  173. package/dist/types/registry/oauth/index.d.ts +45 -0
  174. package/dist/types/registry/oauth/kimi.d.ts +21 -0
  175. package/dist/types/registry/oauth/minimax-code.d.ts +27 -0
  176. package/dist/types/registry/oauth/openai-codex.d.ts +33 -0
  177. package/dist/types/registry/oauth/opencode.d.ts +18 -0
  178. package/dist/types/registry/oauth/perplexity.d.ts +9 -0
  179. package/dist/types/registry/oauth/pkce.d.ts +8 -0
  180. package/dist/types/registry/oauth/types.d.ts +87 -0
  181. package/dist/types/registry/oauth/wafer.d.ts +1 -0
  182. package/dist/types/registry/oauth/xai-oauth.d.ts +46 -0
  183. package/dist/types/registry/oauth/xiaomi.d.ts +25 -0
  184. package/dist/types/registry/oauth/zai.d.ts +25 -0
  185. package/dist/types/registry/ollama-cloud.d.ts +7 -0
  186. package/dist/types/registry/ollama.d.ts +12 -0
  187. package/dist/types/registry/openai-codex-device.d.ts +8 -0
  188. package/dist/types/registry/openai-codex.d.ts +9 -0
  189. package/dist/types/registry/openai.d.ts +4 -0
  190. package/dist/types/registry/opencode-go.d.ts +6 -0
  191. package/dist/types/registry/opencode-zen.d.ts +6 -0
  192. package/dist/types/registry/openrouter.d.ts +13 -0
  193. package/dist/types/registry/parallel.d.ts +14 -0
  194. package/dist/types/registry/perplexity.d.ts +7 -0
  195. package/dist/types/registry/qianfan.d.ts +7 -0
  196. package/dist/types/registry/qwen-portal.d.ts +7 -0
  197. package/dist/types/registry/registry.d.ts +367 -0
  198. package/dist/types/registry/sakana.d.ts +7 -0
  199. package/dist/types/registry/siliconflow-cn.d.ts +7 -0
  200. package/dist/types/registry/siliconflow.d.ts +7 -0
  201. package/dist/types/registry/synthetic.d.ts +6 -0
  202. package/dist/types/registry/tavily.d.ts +14 -0
  203. package/dist/types/registry/together.d.ts +6 -0
  204. package/dist/types/registry/types.d.ts +75 -0
  205. package/dist/types/registry/umans.d.ts +7 -0
  206. package/dist/types/registry/venice.d.ts +13 -0
  207. package/dist/types/registry/vercel-ai-gateway.d.ts +7 -0
  208. package/dist/types/registry/vllm.d.ts +7 -0
  209. package/dist/types/registry/wafer-serverless.d.ts +6 -0
  210. package/dist/types/registry/xai-oauth.d.ts +7 -0
  211. package/dist/types/registry/xai.d.ts +7 -0
  212. package/dist/types/registry/xiaomi-token-plan-ams.d.ts +6 -0
  213. package/dist/types/registry/xiaomi-token-plan-cn.d.ts +6 -0
  214. package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +6 -0
  215. package/dist/types/registry/xiaomi.d.ts +6 -0
  216. package/dist/types/registry/zai.d.ts +15 -0
  217. package/dist/types/registry/zenmux.d.ts +7 -0
  218. package/dist/types/registry/zhipu-coding-plan.d.ts +7 -0
  219. package/dist/types/stream.d.ts +46 -0
  220. package/dist/types/types.d.ts +1064 -0
  221. package/dist/types/usage/alibaba-token-plan.d.ts +3 -0
  222. package/dist/types/usage/claude.d.ts +4 -0
  223. package/dist/types/usage/cursor.d.ts +4 -0
  224. package/dist/types/usage/gemini.d.ts +2 -0
  225. package/dist/types/usage/github-copilot.d.ts +7 -0
  226. package/dist/types/usage/google-antigravity.d.ts +15 -0
  227. package/dist/types/usage/kimi.d.ts +2 -0
  228. package/dist/types/usage/minimax-code.d.ts +3 -0
  229. package/dist/types/usage/ollama.d.ts +5 -0
  230. package/dist/types/usage/openai-codex-base-url.d.ts +18 -0
  231. package/dist/types/usage/openai-codex-reset.d.ts +88 -0
  232. package/dist/types/usage/openai-codex.d.ts +10 -0
  233. package/dist/types/usage/opencode-go.d.ts +2 -0
  234. package/dist/types/usage/shared.d.ts +1 -0
  235. package/dist/types/usage/synthetic.d.ts +2 -0
  236. package/dist/types/usage/umans.d.ts +2 -0
  237. package/dist/types/usage/xai-oauth.d.ts +12 -0
  238. package/dist/types/usage/zai.d.ts +3 -0
  239. package/dist/types/usage.d.ts +527 -0
  240. package/dist/types/utils/abort.d.ts +25 -0
  241. package/dist/types/utils/anthropic-auth.d.ts +35 -0
  242. package/dist/types/utils/aws-profile.d.ts +17 -0
  243. package/dist/types/utils/block-symbols.d.ts +62 -0
  244. package/dist/types/utils/deterministic-id.d.ts +16 -0
  245. package/dist/types/utils/empty-completion-retry.d.ts +21 -0
  246. package/dist/types/utils/event-stream.d.ts +39 -0
  247. package/dist/types/utils/foundry.d.ts +1 -0
  248. package/dist/types/utils/google-validation.d.ts +2 -0
  249. package/dist/types/utils/harmony-leak.d.ts +135 -0
  250. package/dist/types/utils/http-inspector.d.ts +49 -0
  251. package/dist/types/utils/idle-iterator.d.ts +149 -0
  252. package/dist/types/utils/leaked-thinking-stream.d.ts +33 -0
  253. package/dist/types/utils/openai-http.d.ts +48 -0
  254. package/dist/types/utils/openrouter-headers.d.ts +1 -0
  255. package/dist/types/utils/parse-bind.d.ts +23 -0
  256. package/dist/types/utils/provider-response.d.ts +3 -0
  257. package/dist/types/utils/proxy.d.ts +39 -0
  258. package/dist/types/utils/request-debug.d.ts +29 -0
  259. package/dist/types/utils/retry-after.d.ts +4 -0
  260. package/dist/types/utils/retry.d.ts +14 -0
  261. package/dist/types/utils/schema/adapt.d.ts +24 -0
  262. package/dist/types/utils/schema/compatibility.d.ts +30 -0
  263. package/dist/types/utils/schema/dereference.d.ts +11 -0
  264. package/dist/types/utils/schema/draft.d.ts +10 -0
  265. package/dist/types/utils/schema/equality.d.ts +4 -0
  266. package/dist/types/utils/schema/fields.d.ts +54 -0
  267. package/dist/types/utils/schema/index.d.ts +14 -0
  268. package/dist/types/utils/schema/json-schema-validator.d.ts +20 -0
  269. package/dist/types/utils/schema/meta-validator.d.ts +2 -0
  270. package/dist/types/utils/schema/normalize.d.ts +153 -0
  271. package/dist/types/utils/schema/spill.d.ts +8 -0
  272. package/dist/types/utils/schema/stamps.d.ts +17 -0
  273. package/dist/types/utils/schema/strict-tool-validation.d.ts +16 -0
  274. package/dist/types/utils/schema/types.d.ts +4 -0
  275. package/dist/types/utils/schema/typescript.d.ts +24 -0
  276. package/dist/types/utils/schema/wire.d.ts +52 -0
  277. package/dist/types/utils/sdk-stream-timeout.d.ts +33 -0
  278. package/dist/types/utils/sse-debug.d.ts +5 -0
  279. package/dist/types/utils/stream-markup-healing.d.ts +87 -0
  280. package/dist/types/utils/thinking-loop.d.ts +102 -0
  281. package/dist/types/utils/tool-call-loop-guard.d.ts +26 -0
  282. package/dist/types/utils/tool-choice.d.ts +52 -0
  283. package/dist/types/utils/validation.d.ts +28 -0
  284. package/dist/types/utils.d.ts +57 -0
  285. package/package.json +138 -0
  286. package/src/api-registry.ts +109 -0
  287. package/src/auth/sqlite-credential-store.ts +2066 -0
  288. package/src/auth-broker/client.ts +471 -0
  289. package/src/auth-broker/discover.ts +310 -0
  290. package/src/auth-broker/index.ts +7 -0
  291. package/src/auth-broker/refresher.ts +117 -0
  292. package/src/auth-broker/remote-store.ts +1332 -0
  293. package/src/auth-broker/server.ts +898 -0
  294. package/src/auth-broker/snapshot-cache.ts +200 -0
  295. package/src/auth-broker/types.ts +193 -0
  296. package/src/auth-broker/wire-schema-resource.ts +487 -0
  297. package/src/auth-broker/wire-schemas.ts +43 -0
  298. package/src/auth-gateway/http.ts +227 -0
  299. package/src/auth-gateway/index.ts +3 -0
  300. package/src/auth-gateway/server.ts +836 -0
  301. package/src/auth-gateway/types.ts +153 -0
  302. package/src/auth-retry.ts +401 -0
  303. package/src/auth-storage.ts +6540 -0
  304. package/src/dialect/anthropic.md +31 -0
  305. package/src/dialect/anthropic.ts +608 -0
  306. package/src/dialect/catalog.ts +29 -0
  307. package/src/dialect/coercion.ts +136 -0
  308. package/src/dialect/deepseek.md +24 -0
  309. package/src/dialect/deepseek.ts +609 -0
  310. package/src/dialect/demotion.ts +40 -0
  311. package/src/dialect/examples.ts +71 -0
  312. package/src/dialect/factory.ts +34 -0
  313. package/src/dialect/fenced-thinking.ts +184 -0
  314. package/src/dialect/gemini.md +44 -0
  315. package/src/dialect/gemini.ts +583 -0
  316. package/src/dialect/gemma.md +33 -0
  317. package/src/dialect/gemma.ts +387 -0
  318. package/src/dialect/glm.md +32 -0
  319. package/src/dialect/glm.ts +579 -0
  320. package/src/dialect/harmony.md +31 -0
  321. package/src/dialect/harmony.ts +345 -0
  322. package/src/dialect/hermes.md +25 -0
  323. package/src/dialect/hermes.ts +206 -0
  324. package/src/dialect/history.ts +81 -0
  325. package/src/dialect/index.ts +15 -0
  326. package/src/dialect/inventory.ts +30 -0
  327. package/src/dialect/kimi.md +24 -0
  328. package/src/dialect/kimi.ts +340 -0
  329. package/src/dialect/minimax.md +31 -0
  330. package/src/dialect/minimax.ts +95 -0
  331. package/src/dialect/owned-stream.ts +481 -0
  332. package/src/dialect/prompt-template.md +12 -0
  333. package/src/dialect/qwen3.md +28 -0
  334. package/src/dialect/qwen3.ts +240 -0
  335. package/src/dialect/rendering.ts +304 -0
  336. package/src/dialect/thinking.ts +292 -0
  337. package/src/dialect/types.ts +56 -0
  338. package/src/dialect/xml.md +22 -0
  339. package/src/dialect/xml.ts +90 -0
  340. package/src/error/abort.ts +18 -0
  341. package/src/error/auth-classify.ts +47 -0
  342. package/src/error/auth.ts +48 -0
  343. package/src/error/aws.ts +35 -0
  344. package/src/error/classes.ts +281 -0
  345. package/src/error/finalize.ts +69 -0
  346. package/src/error/flags.ts +602 -0
  347. package/src/error/format.ts +45 -0
  348. package/src/error/gateway.ts +96 -0
  349. package/src/error/index.ts +14 -0
  350. package/src/error/oauth.ts +58 -0
  351. package/src/error/provider.ts +63 -0
  352. package/src/error/rate-limit.ts +303 -0
  353. package/src/error/retryable.ts +70 -0
  354. package/src/error/validation.ts +44 -0
  355. package/src/index.ts +51 -0
  356. package/src/provider-details.ts +90 -0
  357. package/src/providers/amazon-bedrock.ts +1064 -0
  358. package/src/providers/anthropic-client.ts +317 -0
  359. package/src/providers/anthropic-messages-server-schema.ts +252 -0
  360. package/src/providers/anthropic-messages-server.ts +818 -0
  361. package/src/providers/anthropic-wire.ts +359 -0
  362. package/src/providers/anthropic.ts +4539 -0
  363. package/src/providers/aws-credentials.ts +772 -0
  364. package/src/providers/aws-eventstream.ts +181 -0
  365. package/src/providers/aws-sigv4.ts +218 -0
  366. package/src/providers/azure-openai-responses.ts +438 -0
  367. package/src/providers/bedrock-mantle.ts +110 -0
  368. package/src/providers/claude-code-fingerprint.ts +20 -0
  369. package/src/providers/cowork-fetch.ts +201 -0
  370. package/src/providers/cursor/exec-modern.ts +496 -0
  371. package/src/providers/cursor/proto/agent.proto +4533 -0
  372. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  373. package/src/providers/cursor/proto/buf.yaml +17 -0
  374. package/src/providers/cursor-pi-args.ts +165 -0
  375. package/src/providers/cursor.ts +4689 -0
  376. package/src/providers/devin/proto/buf/validate/validate.proto +468 -0
  377. package/src/providers/devin/proto/buf.gen.yaml +33 -0
  378. package/src/providers/devin/proto/buf.yaml +17 -0
  379. package/src/providers/devin/proto/cel/expr/checked.proto +103 -0
  380. package/src/providers/devin/proto/cel/expr/eval.proto +38 -0
  381. package/src/providers/devin/proto/cel/expr/explain.proto +15 -0
  382. package/src/providers/devin/proto/cel/expr/syntax.proto +113 -0
  383. package/src/providers/devin/proto/cel/expr/value.proto +41 -0
  384. package/src/providers/devin/proto/connectext/grpc/status/v1/status.proto +11 -0
  385. package/src/providers/devin/proto/errorspb/errors.proto +56 -0
  386. package/src/providers/devin/proto/errorspb/hintdetail.proto +7 -0
  387. package/src/providers/devin/proto/errorspb/markers.proto +10 -0
  388. package/src/providers/devin/proto/errorspb/tags.proto +12 -0
  389. package/src/providers/devin/proto/errorspb/testing.proto +6 -0
  390. package/src/providers/devin/proto/exa/analytics_pb/analytics.proto +188 -0
  391. package/src/providers/devin/proto/exa/api_server_pb/api_server.proto +2461 -0
  392. package/src/providers/devin/proto/exa/auth_pb/auth.proto +19 -0
  393. package/src/providers/devin/proto/exa/auto_cascade_common_pb/auto_cascade_common.proto +79 -0
  394. package/src/providers/devin/proto/exa/browser_preview_pb/browser_preview.proto +32 -0
  395. package/src/providers/devin/proto/exa/bug_checker_pb/bug_checker.proto +22 -0
  396. package/src/providers/devin/proto/exa/cascade_plugins_pb/cascade_plugins.proto +262 -0
  397. package/src/providers/devin/proto/exa/chat_client_server_pb/chat_client_server.proto +57 -0
  398. package/src/providers/devin/proto/exa/chat_pb/chat.proto +449 -0
  399. package/src/providers/devin/proto/exa/code_edit/code_edit_pb/code_edit.proto +186 -0
  400. package/src/providers/devin/proto/exa/codeium_common_pb/codeium_common.proto +4157 -0
  401. package/src/providers/devin/proto/exa/context_module_pb/context_module.proto +175 -0
  402. package/src/providers/devin/proto/exa/cortex_pb/cortex.proto +3268 -0
  403. package/src/providers/devin/proto/exa/dev_pb/dev.proto +26 -0
  404. package/src/providers/devin/proto/exa/diff_action_pb/diff_action.proto +75 -0
  405. package/src/providers/devin/proto/exa/eval/pr_eval/datasets_pb/datasets.proto +103 -0
  406. package/src/providers/devin/proto/exa/eval_pb/eval.proto +1315 -0
  407. package/src/providers/devin/proto/exa/extension_server_pb/extension_server.proto +556 -0
  408. package/src/providers/devin/proto/exa/file_system_provider_pb/file_system_provider.proto +75 -0
  409. package/src/providers/devin/proto/exa/index_pb/index.proto +461 -0
  410. package/src/providers/devin/proto/exa/knowledge_base_pb/knowledge_base.proto +144 -0
  411. package/src/providers/devin/proto/exa/language_server_pb/language_server.proto +2385 -0
  412. package/src/providers/devin/proto/exa/model_management_pb/model_management.proto +186 -0
  413. package/src/providers/devin/proto/exa/opensearch_clients_pb/opensearch_clients.proto +503 -0
  414. package/src/providers/devin/proto/exa/product_analytics_pb/product_analytics.proto +37 -0
  415. package/src/providers/devin/proto/exa/prompt_pb/prompt.proto +92 -0
  416. package/src/providers/devin/proto/exa/reactive_component_pb/reactive_component.proto +96 -0
  417. package/src/providers/devin/proto/exa/seat_management_pb/seat_management.proto +2680 -0
  418. package/src/providers/devin/proto/exa/tokenizer_pb/tokenizer.proto +37 -0
  419. package/src/providers/devin/proto/exa/trainer_pb/config.proto +647 -0
  420. package/src/providers/devin/proto/exa/tree_sitter/language_data_pb/language_data.proto +14 -0
  421. package/src/providers/devin/proto/exa/trust_pb/trust.proto +157 -0
  422. package/src/providers/devin/proto/exa/user_analytics_pb/user_analytics.proto +519 -0
  423. package/src/providers/devin/proto/google.golang.org/appengine/internal/base/api_base.proto +28 -0
  424. package/src/providers/devin/proto/google.golang.org/appengine/internal/datastore/datastore_v3.proto +484 -0
  425. package/src/providers/devin/proto/google.golang.org/appengine/internal/log/log_service.proto +136 -0
  426. package/src/providers/devin/proto/google.golang.org/appengine/internal/remote_api/remote_api.proto +42 -0
  427. package/src/providers/devin/proto/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto +61 -0
  428. package/src/providers/devin/proto/grpc/binlog/v1/binarylog.proto +84 -0
  429. package/src/providers/devin/proto/io/prometheus/client/metrics.proto +98 -0
  430. package/src/providers/devin.ts +679 -0
  431. package/src/providers/error-message.ts +23 -0
  432. package/src/providers/github-copilot-headers.ts +141 -0
  433. package/src/providers/gitlab-duo-workflow-chatml-note.md +1 -0
  434. package/src/providers/gitlab-duo-workflow.ts +3135 -0
  435. package/src/providers/gitlab-duo.ts +399 -0
  436. package/src/providers/google-auth.ts +330 -0
  437. package/src/providers/google-gemini-cli.ts +1370 -0
  438. package/src/providers/google-shared.ts +1122 -0
  439. package/src/providers/google-types.ts +180 -0
  440. package/src/providers/google-vertex.ts +135 -0
  441. package/src/providers/google.ts +47 -0
  442. package/src/providers/grammar.ts +70 -0
  443. package/src/providers/kimi.ts +51 -0
  444. package/src/providers/mock.ts +514 -0
  445. package/src/providers/ollama.ts +776 -0
  446. package/src/providers/openai-anthropic-shim.ts +166 -0
  447. package/src/providers/openai-chat-server-schema.ts +243 -0
  448. package/src/providers/openai-chat-server.ts +752 -0
  449. package/src/providers/openai-chat-wire.ts +859 -0
  450. package/src/providers/openai-codex/request-transformer.ts +491 -0
  451. package/src/providers/openai-codex/response-handler.ts +102 -0
  452. package/src/providers/openai-codex-responses.ts +4716 -0
  453. package/src/providers/openai-completions.ts +2389 -0
  454. package/src/providers/openai-reasoning-fallback.ts +269 -0
  455. package/src/providers/openai-responses-server-schema.ts +397 -0
  456. package/src/providers/openai-responses-server.ts +1466 -0
  457. package/src/providers/openai-responses-wire.ts +6416 -0
  458. package/src/providers/openai-responses.ts +1393 -0
  459. package/src/providers/openai-shared.ts +3500 -0
  460. package/src/providers/pi-native-client.ts +275 -0
  461. package/src/providers/pi-native-server.ts +245 -0
  462. package/src/providers/register-builtins.ts +503 -0
  463. package/src/providers/synthetic.ts +50 -0
  464. package/src/providers/transform-messages.ts +1083 -0
  465. package/src/providers/vision-guard.ts +54 -0
  466. package/src/registry/aiand.ts +22 -0
  467. package/src/registry/aimlapi.ts +6 -0
  468. package/src/registry/alibaba-coding-plan.ts +104 -0
  469. package/src/registry/alibaba-token-plan.ts +125 -0
  470. package/src/registry/amazon-bedrock.ts +22 -0
  471. package/src/registry/anthropic.ts +26 -0
  472. package/src/registry/api-key-login.ts +115 -0
  473. package/src/registry/api-key-validation.ts +145 -0
  474. package/src/registry/aws.ts +57 -0
  475. package/src/registry/azure.ts +6 -0
  476. package/src/registry/baseten.ts +22 -0
  477. package/src/registry/bedrock-mantle.ts +34 -0
  478. package/src/registry/cerebras.ts +23 -0
  479. package/src/registry/cloudflare-ai-gateway.ts +45 -0
  480. package/src/registry/coreweave.ts +40 -0
  481. package/src/registry/cursor.ts +20 -0
  482. package/src/registry/deepseek.ts +46 -0
  483. package/src/registry/derived.ts +9 -0
  484. package/src/registry/devin.ts +15 -0
  485. package/src/registry/exa.ts +19 -0
  486. package/src/registry/firepass.ts +32 -0
  487. package/src/registry/fireworks.ts +28 -0
  488. package/src/registry/github-copilot.ts +22 -0
  489. package/src/registry/gitlab-duo-workflow.ts +20 -0
  490. package/src/registry/gitlab-duo.ts +19 -0
  491. package/src/registry/gmi-cloud.ts +22 -0
  492. package/src/registry/google-antigravity.ts +22 -0
  493. package/src/registry/google-gemini-cli.ts +22 -0
  494. package/src/registry/google-vertex.ts +38 -0
  495. package/src/registry/google.ts +6 -0
  496. package/src/registry/groq.ts +6 -0
  497. package/src/registry/huggingface.ts +29 -0
  498. package/src/registry/index.ts +4 -0
  499. package/src/registry/kagi.ts +46 -0
  500. package/src/registry/kilo.ts +114 -0
  501. package/src/registry/kimi-code.ts +17 -0
  502. package/src/registry/litellm.ts +45 -0
  503. package/src/registry/llama-cpp.ts +35 -0
  504. package/src/registry/lm-studio.ts +31 -0
  505. package/src/registry/meta.ts +22 -0
  506. package/src/registry/minimax-code-cn.ts +12 -0
  507. package/src/registry/minimax-code.ts +12 -0
  508. package/src/registry/minimax.ts +6 -0
  509. package/src/registry/mistral.ts +6 -0
  510. package/src/registry/moonshot.ts +28 -0
  511. package/src/registry/nanogpt.ts +22 -0
  512. package/src/registry/novita.ts +25 -0
  513. package/src/registry/nvidia.ts +61 -0
  514. package/src/registry/oauth/anthropic-constants.ts +12 -0
  515. package/src/registry/oauth/anthropic.ts +346 -0
  516. package/src/registry/oauth/callback-server.ts +438 -0
  517. package/src/registry/oauth/cursor.ts +187 -0
  518. package/src/registry/oauth/device-code.ts +92 -0
  519. package/src/registry/oauth/devin.ts +124 -0
  520. package/src/registry/oauth/github-copilot.ts +369 -0
  521. package/src/registry/oauth/gitlab-duo-workflow.ts +146 -0
  522. package/src/registry/oauth/gitlab-duo.ts +222 -0
  523. package/src/registry/oauth/google-antigravity.ts +225 -0
  524. package/src/registry/oauth/google-gemini-cli.ts +297 -0
  525. package/src/registry/oauth/google-oauth-shared.ts +211 -0
  526. package/src/registry/oauth/index.ts +187 -0
  527. package/src/registry/oauth/kimi.ts +297 -0
  528. package/src/registry/oauth/minimax-code.ts +53 -0
  529. package/src/registry/oauth/oauth.html +317 -0
  530. package/src/registry/oauth/openai-codex.ts +384 -0
  531. package/src/registry/oauth/opencode.ts +50 -0
  532. package/src/registry/oauth/perplexity.ts +228 -0
  533. package/src/registry/oauth/pkce.ts +18 -0
  534. package/src/registry/oauth/types.ts +96 -0
  535. package/src/registry/oauth/wafer.ts +24 -0
  536. package/src/registry/oauth/xai-oauth.ts +559 -0
  537. package/src/registry/oauth/xiaomi.ts +211 -0
  538. package/src/registry/oauth/zai.ts +285 -0
  539. package/src/registry/ollama-cloud.ts +36 -0
  540. package/src/registry/ollama.ts +43 -0
  541. package/src/registry/openai-codex-device.ts +18 -0
  542. package/src/registry/openai-codex.ts +19 -0
  543. package/src/registry/openai.ts +6 -0
  544. package/src/registry/opencode-go.ts +12 -0
  545. package/src/registry/opencode-zen.ts +12 -0
  546. package/src/registry/openrouter.ts +28 -0
  547. package/src/registry/parallel.ts +45 -0
  548. package/src/registry/perplexity.ts +13 -0
  549. package/src/registry/qianfan.ts +27 -0
  550. package/src/registry/qwen-portal.ts +50 -0
  551. package/src/registry/registry.ts +182 -0
  552. package/src/registry/sakana.ts +22 -0
  553. package/src/registry/siliconflow-cn.ts +22 -0
  554. package/src/registry/siliconflow.ts +22 -0
  555. package/src/registry/synthetic.ts +21 -0
  556. package/src/registry/tavily.ts +45 -0
  557. package/src/registry/together.ts +22 -0
  558. package/src/registry/types.ts +86 -0
  559. package/src/registry/umans.ts +23 -0
  560. package/src/registry/venice.ts +33 -0
  561. package/src/registry/vercel-ai-gateway.ts +38 -0
  562. package/src/registry/vllm.ts +34 -0
  563. package/src/registry/wafer-serverless.ts +12 -0
  564. package/src/registry/xai-oauth.ts +17 -0
  565. package/src/registry/xai.ts +22 -0
  566. package/src/registry/xiaomi-token-plan-ams.ts +12 -0
  567. package/src/registry/xiaomi-token-plan-cn.ts +12 -0
  568. package/src/registry/xiaomi-token-plan-sgp.ts +12 -0
  569. package/src/registry/xiaomi.ts +12 -0
  570. package/src/registry/zai.ts +41 -0
  571. package/src/registry/zenmux.ts +22 -0
  572. package/src/registry/zhipu-coding-plan.ts +27 -0
  573. package/src/stream.ts +1944 -0
  574. package/src/types.ts +1243 -0
  575. package/src/usage/alibaba-token-plan.ts +230 -0
  576. package/src/usage/claude.ts +830 -0
  577. package/src/usage/cursor.ts +335 -0
  578. package/src/usage/gemini.ts +258 -0
  579. package/src/usage/github-copilot.ts +424 -0
  580. package/src/usage/google-antigravity.ts +497 -0
  581. package/src/usage/kimi.ts +277 -0
  582. package/src/usage/minimax-code.ts +291 -0
  583. package/src/usage/ollama.ts +41 -0
  584. package/src/usage/openai-codex-base-url.ts +35 -0
  585. package/src/usage/openai-codex-reset.ts +205 -0
  586. package/src/usage/openai-codex.ts +627 -0
  587. package/src/usage/opencode-go.ts +89 -0
  588. package/src/usage/shared.ts +10 -0
  589. package/src/usage/synthetic.ts +180 -0
  590. package/src/usage/umans.ts +192 -0
  591. package/src/usage/xai-oauth.ts +414 -0
  592. package/src/usage/zai.ts +370 -0
  593. package/src/usage.ts +411 -0
  594. package/src/utils/abort.ts +67 -0
  595. package/src/utils/anthropic-auth.ts +93 -0
  596. package/src/utils/aws-profile.ts +88 -0
  597. package/src/utils/block-symbols.ts +78 -0
  598. package/src/utils/deterministic-id.ts +20 -0
  599. package/src/utils/empty-completion-retry.ts +161 -0
  600. package/src/utils/event-stream.ts +202 -0
  601. package/src/utils/foundry.ts +8 -0
  602. package/src/utils/google-validation.ts +25 -0
  603. package/src/utils/harmony-leak.ts +500 -0
  604. package/src/utils/http-inspector.ts +196 -0
  605. package/src/utils/idle-iterator.ts +531 -0
  606. package/src/utils/leaked-thinking-stream.ts +483 -0
  607. package/src/utils/openai-http.ts +119 -0
  608. package/src/utils/openrouter-headers.ts +12 -0
  609. package/src/utils/parse-bind.ts +56 -0
  610. package/src/utils/provider-response.ts +30 -0
  611. package/src/utils/proxy.ts +314 -0
  612. package/src/utils/request-debug.ts +351 -0
  613. package/src/utils/retry-after.ts +121 -0
  614. package/src/utils/retry.ts +77 -0
  615. package/src/utils/schema/CONSTRAINTS.md +168 -0
  616. package/src/utils/schema/adapt.ts +36 -0
  617. package/src/utils/schema/compatibility.ts +435 -0
  618. package/src/utils/schema/dereference.ts +98 -0
  619. package/src/utils/schema/draft.ts +341 -0
  620. package/src/utils/schema/equality.ts +97 -0
  621. package/src/utils/schema/fields.ts +210 -0
  622. package/src/utils/schema/index.ts +14 -0
  623. package/src/utils/schema/json-schema-validator.ts +595 -0
  624. package/src/utils/schema/meta-validator.ts +167 -0
  625. package/src/utils/schema/normalize.ts +2314 -0
  626. package/src/utils/schema/spill.ts +43 -0
  627. package/src/utils/schema/stamps.ts +109 -0
  628. package/src/utils/schema/strict-tool-validation.ts +117 -0
  629. package/src/utils/schema/types.ts +10 -0
  630. package/src/utils/schema/typescript.ts +212 -0
  631. package/src/utils/schema/wire.ts +662 -0
  632. package/src/utils/sdk-stream-timeout.ts +43 -0
  633. package/src/utils/sse-debug.ts +18 -0
  634. package/src/utils/stream-markup-healing.ts +247 -0
  635. package/src/utils/thinking-loop.ts +552 -0
  636. package/src/utils/tool-call-loop-guard.ts +107 -0
  637. package/src/utils/tool-choice.ts +101 -0
  638. package/src/utils/validation.ts +1932 -0
  639. package/src/utils.ts +492 -0
@@ -0,0 +1,438 @@
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
+ * Path served by {@link OAuthCallbackFlow} that 302-redirects to the pending
22
+ * authorization URL. Kept out of {@link OAuthCallbackFlowOptions} because it
23
+ * lives on the loopback callback server alongside {@link CALLBACK_PATH} and
24
+ * must never clash with a provider-registered redirect URI (all known
25
+ * providers register `/callback`-shaped paths).
26
+ */
27
+ const LAUNCH_PATH = "/launch";
28
+
29
+ export type CallbackResult = { code: string; state: string };
30
+
31
+ export interface OAuthCallbackFlowOptions {
32
+ preferredPort: number;
33
+ callbackPath?: string;
34
+ callbackHostname?: string;
35
+ /** Exact redirect URI advertised to the provider; disables port fallback. */
36
+ redirectUri?: string;
37
+ /**
38
+ * Whether the flow may bind to a random port when {@link preferredPort} is
39
+ * unavailable. Defaults to `true` so historical AI-provider flows (which
40
+ * pick uncommon ports and tolerate any loopback callback) keep working.
41
+ *
42
+ * Set to `false` for providers that validate the redirect URI against a
43
+ * registered callback — silently advertising a random-port URI would be
44
+ * rejected by the authorization server, leaving the browser on an opaque
45
+ * 500 page and the local callback waiting until the 5-minute timeout fires.
46
+ * With fallback disabled, {@link OAuthCallbackFlow.login} throws a
47
+ * {@link AIError.ConfigurationError} immediately so the caller can surface
48
+ * an actionable message before opening the browser.
49
+ */
50
+ allowPortFallback?: boolean;
51
+ /** Skip the local callback server entirely; the user pastes the code or redirect URL back. */
52
+ manualInputOnly?: boolean;
53
+ }
54
+
55
+ /**
56
+ * Abstract base class for OAuth flows with local callback servers.
57
+ */
58
+ export abstract class OAuthCallbackFlow {
59
+ ctrl: OAuthController;
60
+ preferredPort: number;
61
+ callbackPath: string;
62
+ callbackHostname: string;
63
+ redirectUri?: string;
64
+ allowPortFallback: boolean;
65
+ #manualInputOnly: boolean;
66
+ #callbackResolve?: (result: CallbackResult) => void;
67
+ #callbackReject?: (error: Error) => void;
68
+ /**
69
+ * Authorization URL the `/launch` route currently redirects to. Set by
70
+ * {@link login} after {@link generateAuthUrl} and before {@link OAuthController.onAuth}
71
+ * fires, cleared when the server stops. `undefined` before the flow reaches
72
+ * that point and after it finishes, so `/launch` returns 503 rather than
73
+ * a stale URL.
74
+ */
75
+ #pendingAuthUrl?: string;
76
+
77
+ constructor(
78
+ ctrl: OAuthController,
79
+ preferredPortOrOptions: number | OAuthCallbackFlowOptions,
80
+ callbackPath: string = CALLBACK_PATH,
81
+ ) {
82
+ this.ctrl = ctrl;
83
+ if (typeof preferredPortOrOptions === "number") {
84
+ this.preferredPort = preferredPortOrOptions;
85
+ this.callbackPath = callbackPath;
86
+ this.callbackHostname = DEFAULT_HOSTNAME;
87
+ this.allowPortFallback = true;
88
+ this.#manualInputOnly = false;
89
+ return;
90
+ }
91
+
92
+ this.preferredPort = preferredPortOrOptions.preferredPort;
93
+ this.callbackPath = preferredPortOrOptions.callbackPath ?? CALLBACK_PATH;
94
+ this.callbackHostname = preferredPortOrOptions.callbackHostname ?? DEFAULT_HOSTNAME;
95
+ this.redirectUri = preferredPortOrOptions.redirectUri;
96
+ this.allowPortFallback = preferredPortOrOptions.allowPortFallback ?? true;
97
+ this.#manualInputOnly = preferredPortOrOptions.manualInputOnly ?? false;
98
+ }
99
+
100
+ /**
101
+ * Generate provider-specific authorization URL.
102
+ * @param state - CSRF state token
103
+ * @param redirectUri - The actual redirect URI to use (may differ from expected if port fallback occurred)
104
+ * @returns Authorization URL and optional instructions
105
+ */
106
+ abstract generateAuthUrl(state: string, redirectUri: string): Promise<{ url: string; instructions?: string }>;
107
+
108
+ /**
109
+ * Exchange authorization code for OAuth tokens.
110
+ * @param code - Authorization code from callback
111
+ * @param state - CSRF state token
112
+ * @param redirectUri - The actual redirect URI used (must match authorization request)
113
+ * @returns OAuth credentials
114
+ */
115
+ abstract exchangeToken(code: string, state: string, redirectUri: string): Promise<OAuthCredentials>;
116
+
117
+ /**
118
+ * Generate CSRF state token. Override if provider needs custom state generation.
119
+ */
120
+ generateState(): string {
121
+ const bytes = new Uint8Array(16);
122
+ crypto.getRandomValues(bytes);
123
+ return Array.from(bytes)
124
+ .map(value => value.toString(16).padStart(2, "0"))
125
+ .join("");
126
+ }
127
+
128
+ #loginCancelledError(): AIError.LoginCancelledError {
129
+ return new AIError.LoginCancelledError(`OAuth callback cancelled: ${this.ctrl.signal?.reason}`);
130
+ }
131
+
132
+ #throwIfCancelled(): void {
133
+ if (this.ctrl.signal?.aborted) throw this.#loginCancelledError();
134
+ }
135
+
136
+ /**
137
+ * Execute the OAuth login flow.
138
+ */
139
+ async login(): Promise<OAuthCredentials> {
140
+ const state = this.generateState();
141
+ this.#throwIfCancelled();
142
+
143
+ // Start callback server first to get actual redirect URI. Manual-only
144
+ // flows never bind a server — the advertised redirect URI is fixed and
145
+ // the user pastes the code/redirect URL back instead.
146
+ const { server, redirectUri, launchUrl } = this.#manualInputOnly
147
+ ? { server: undefined, redirectUri: this.#buildRedirectUri(), launchUrl: undefined }
148
+ : await this.#startCallbackServer(state);
149
+
150
+ try {
151
+ this.#throwIfCancelled();
152
+ // Generate auth URL with the ACTUAL redirect URI (may differ from expected if port was busy)
153
+ const { url: authUrl, instructions } = await this.generateAuthUrl(state, redirectUri);
154
+ this.#throwIfCancelled();
155
+
156
+ // Publish the auth URL to the `/launch` route BEFORE handing it to
157
+ // callers. `onAuth` immediately renders a UI that advertises the
158
+ // launch URL as a copy target, so `/launch` must already resolve if
159
+ // the user clicks/pastes it during the same render pass.
160
+ this.#pendingAuthUrl = authUrl;
161
+
162
+ // Notify controller that auth is ready
163
+ this.ctrl.onAuth?.({ url: authUrl, launchUrl, instructions });
164
+ this.ctrl.onProgress?.(
165
+ this.#manualInputOnly
166
+ ? "Waiting for pasted authorization code..."
167
+ : "Waiting for browser authentication...",
168
+ );
169
+
170
+ const { code } = await this.#waitForCallback(state);
171
+ this.#throwIfCancelled();
172
+
173
+ this.ctrl.onProgress?.("Exchanging authorization code for tokens...");
174
+
175
+ return await this.exchangeToken(code, state, redirectUri);
176
+ } finally {
177
+ this.#pendingAuthUrl = undefined;
178
+ server?.stop();
179
+ }
180
+ }
181
+
182
+ #buildRedirectUri(): string {
183
+ return this.redirectUri ?? `http://${this.callbackHostname}:${this.preferredPort}${this.callbackPath}`;
184
+ }
185
+
186
+ /**
187
+ * Start callback server, trying preferred port first, falling back to random.
188
+ * `launchUrl` is `undefined` when the caller configured `callbackPath` to
189
+ * collide with {@link LAUNCH_PATH} — the callback handler resolves the real
190
+ * callback in that case, so advertising a self-redirecting URL would be
191
+ * incorrect.
192
+ */
193
+ async #startCallbackServer(
194
+ expectedState: string,
195
+ ): Promise<{ server: Bun.Server<unknown>; redirectUri: string; launchUrl: string | undefined }> {
196
+ try {
197
+ const server = this.#createServer(this.preferredPort, expectedState);
198
+ // `preferredPort: 0` opts into a random port — read the actual bound
199
+ // port from the server so both the redirect URI and launch URL point at
200
+ // a reachable socket, not the sentinel.
201
+ const actualPort = this.#resolveServerPort(server);
202
+ const launchUrl = this.#launchUrlIfSafe(actualPort);
203
+ if (this.redirectUri) {
204
+ return { server, redirectUri: this.redirectUri, launchUrl };
205
+ }
206
+ const redirectUri = `http://${this.callbackHostname}:${actualPort}${this.callbackPath}`;
207
+ return { server, redirectUri, launchUrl };
208
+ } catch (cause) {
209
+ if (this.redirectUri) {
210
+ throw new AIError.ConfigurationError(
211
+ `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.`,
212
+ { cause },
213
+ );
214
+ }
215
+ if (!this.allowPortFallback) {
216
+ throw new AIError.ConfigurationError(
217
+ `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.`,
218
+ { cause },
219
+ );
220
+ }
221
+ const server = this.#createServer(0, expectedState);
222
+ const actualPort = this.#resolveServerPort(server);
223
+ const redirectUri = `http://${this.callbackHostname}:${actualPort}${this.callbackPath}`;
224
+ const launchUrl = this.#launchUrlIfSafe(actualPort);
225
+ this.ctrl.onProgress?.(`Preferred port ${this.preferredPort} unavailable, using port ${actualPort}`);
226
+ return { server, redirectUri, launchUrl };
227
+ }
228
+ }
229
+
230
+ /**
231
+ * Read the numeric port a callback server bound to. `Bun.Server.port` is
232
+ * declared `number | undefined` because Unix-socket servers have no port,
233
+ * but every callback flow uses TCP; a missing port here indicates a
234
+ * configuration error rather than a fallback case.
235
+ */
236
+ #resolveServerPort(server: Bun.Server<unknown>): number {
237
+ const port = server.port;
238
+ if (typeof port !== "number") {
239
+ throw new AIError.ConfigurationError(
240
+ "OAuth callback server bound to a non-TCP endpoint; expected a numeric port. Check `oauth.callbackPort`/`oauth.redirectUri`.",
241
+ );
242
+ }
243
+ return port;
244
+ }
245
+
246
+ /**
247
+ * Build the `/launch` URL served by the callback server bound to `port`, or
248
+ * `undefined` when it must not be advertised:
249
+ * - the configured `callbackPath` (or a `redirectUri` whose pathname
250
+ * resolves to {@link LAUNCH_PATH}) would collide with the launch route;
251
+ * - the flow's `redirectUri` never returns to this loopback server: fixed
252
+ * non-loopback hosts, or custom schemes like GitLab Duo's `vscode://`
253
+ * URI — which `new URL` parses without complaint, so a scheme/host check
254
+ * is required, not just the parse failure path. Advertising a localhost
255
+ * `/launch` target for such flows misrepresents the callback endpoint
256
+ * and hands remote users a URL that resolves nowhere.
257
+ * Kept short (~30 chars) so UIs can advertise it as a
258
+ * viewport-truncation-safe copy target for the full authorization URL.
259
+ */
260
+ #launchUrlIfSafe(port: number): string | undefined {
261
+ if (this.callbackPath === LAUNCH_PATH) return undefined;
262
+ if (this.redirectUri) {
263
+ try {
264
+ const parsed = new URL(this.redirectUri);
265
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return undefined;
266
+ if (parsed.hostname !== "localhost" && parsed.hostname !== "127.0.0.1" && parsed.hostname !== "[::1]") {
267
+ return undefined;
268
+ }
269
+ if (parsed.pathname === LAUNCH_PATH) return undefined;
270
+ } catch {
271
+ // A redirectUri even WHATWG URL cannot parse certainly does not
272
+ // return to this server — never advertise a launch URL for it.
273
+ return undefined;
274
+ }
275
+ }
276
+ return `http://${this.callbackHostname}:${port}${LAUNCH_PATH}`;
277
+ }
278
+
279
+ /**
280
+ * Create HTTP server for OAuth callback.
281
+ */
282
+ #createServer(port: number, expectedState: string): Bun.Server<unknown> {
283
+ const hostname = this.callbackHostname === DEFAULT_HOSTNAME ? "127.0.0.1" : this.callbackHostname;
284
+ return Bun.serve({
285
+ hostname,
286
+ port,
287
+ reusePort: false,
288
+ fetch: req => this.#handleCallback(req, expectedState),
289
+ });
290
+ }
291
+
292
+ /**
293
+ * Handle OAuth callback HTTP request. Two routes on the same loopback server:
294
+ * - `callbackPath` (default `/callback`) — the provider redirect target.
295
+ * - {@link LAUNCH_PATH} (`/launch`) — 302 to the pending authorization URL so
296
+ * viewport-safe copy targets can survive TUI truncation.
297
+ *
298
+ * `callbackPath` wins any collision: an OMP config that pins the provider
299
+ * redirect at `/launch` (via `oauth.callbackPath` or a loopback
300
+ * `oauth.redirectUri`) must resolve the callback normally rather than
301
+ * self-redirect. `#startCallbackServer` also suppresses `launchUrl` in that
302
+ * case, so the launch route is never advertised when it would collide.
303
+ */
304
+ #handleCallback(req: Request, expectedState: string): Response {
305
+ const url = new URL(req.url);
306
+
307
+ if (url.pathname !== this.callbackPath) {
308
+ if (url.pathname === LAUNCH_PATH) {
309
+ const pending = this.#pendingAuthUrl;
310
+ if (!pending) {
311
+ return new Response("OAuth launch URL is no longer active", { status: 503 });
312
+ }
313
+ return Response.redirect(pending, 302);
314
+ }
315
+ return new Response("Not Found", { status: 404 });
316
+ }
317
+
318
+ const code = url.searchParams.get("code");
319
+ const state = url.searchParams.get("state") || "";
320
+ const error = url.searchParams.get("error") || "";
321
+ const errorDescription = url.searchParams.get("error_description") || error;
322
+
323
+ type OkState = { ok: true; code: string; state: string };
324
+ type ErrorState = { ok?: false; error?: string };
325
+ let resultState: OkState | ErrorState;
326
+
327
+ if (error) {
328
+ resultState = { ok: false, error: `Authorization failed: ${errorDescription}` };
329
+ } else if (!code) {
330
+ resultState = { ok: false, error: "Missing authorization code" };
331
+ } else if (expectedState && state !== expectedState) {
332
+ resultState = { ok: false, error: "State mismatch - possible CSRF attack" };
333
+ } else {
334
+ resultState = { ok: true, code, state };
335
+ }
336
+
337
+ if (resultState.ok) {
338
+ const resolve = this.#callbackResolve;
339
+ queueMicrotask(() => {
340
+ resolve?.({ code: resultState.code, state: resultState.state });
341
+ });
342
+ } else if (error && (!expectedState || state === expectedState)) {
343
+ // The redirect carries our state nonce, so it came from the genuine
344
+ // authorization flow (e.g. the user denied the consent screen).
345
+ // Surface the denial now instead of leaving the login waiting for
346
+ // the 5-minute timeout. Errors WITHOUT the expected state stay
347
+ // ignored — any local process can forge those (#4106).
348
+ const reject = this.#callbackReject;
349
+ const message = resultState.error ?? `Authorization failed: ${errorDescription}`;
350
+ queueMicrotask(() => {
351
+ reject?.(new AIError.OAuthError(message, { kind: "device-auth" }));
352
+ });
353
+ }
354
+
355
+ return new Response(
356
+ (templateHtml as unknown as string).replaceAll("__OAUTH_STATE__", JSON.stringify(resultState)),
357
+ {
358
+ status: resultState.ok ? 200 : 500,
359
+ headers: { "Content-Type": "text/html" },
360
+ },
361
+ );
362
+ }
363
+
364
+ /**
365
+ * Wait for OAuth callback or manual input (whichever comes first).
366
+ */
367
+ #waitForCallback(expectedState: string): Promise<CallbackResult> {
368
+ const timeoutSignal = AbortSignal.timeout(DEFAULT_TIMEOUT);
369
+ const signal = this.ctrl.signal ? AbortSignal.any([this.ctrl.signal, timeoutSignal]) : timeoutSignal;
370
+ if (signal.aborted) return Promise.reject(this.#loginCancelledError());
371
+
372
+ const callback = Promise.withResolvers<CallbackResult>();
373
+ this.#callbackResolve = callback.resolve;
374
+ this.#callbackReject = callback.reject;
375
+
376
+ signal.addEventListener("abort", () => {
377
+ this.#callbackResolve = undefined;
378
+ this.#callbackReject = undefined;
379
+ callback.reject(new AIError.LoginCancelledError(`OAuth callback cancelled: ${signal.reason}`));
380
+ });
381
+ const callbackPromise = callback.promise;
382
+
383
+ // Manual input race (if supported)
384
+ if (this.ctrl.onManualCodeInput) {
385
+ const requestManualInput = this.ctrl.onManualCodeInput;
386
+ const manualPromise = (async (): Promise<CallbackResult> => {
387
+ while (true) {
388
+ const result = await Promise.race([
389
+ callbackPromise,
390
+ requestManualInput()
391
+ .then((input): CallbackResult | null => {
392
+ const parsed = parseCallbackInput(input);
393
+ if (!parsed.code) return null;
394
+ if (expectedState && parsed.state && parsed.state !== expectedState) return null;
395
+ return { code: parsed.code, state: parsed.state ?? "" };
396
+ })
397
+ .catch((): CallbackResult | null => null),
398
+ ]);
399
+ if (result) return result;
400
+ }
401
+ })();
402
+
403
+ return Promise.race([callbackPromise, manualPromise]);
404
+ }
405
+
406
+ return callbackPromise;
407
+ }
408
+ }
409
+
410
+ /**
411
+ * Parse a redirect URL or code string to extract code and state.
412
+ */
413
+ export function parseCallbackInput(input: string): { code?: string; state?: string } {
414
+ const value = input.trim();
415
+ if (!value) return {};
416
+
417
+ try {
418
+ const url = new URL(value);
419
+ return {
420
+ code: url.searchParams.get("code") ?? undefined,
421
+ state: url.searchParams.get("state") ?? undefined,
422
+ };
423
+ } catch {
424
+ // Not a URL - check for query string format
425
+ }
426
+
427
+ if (value.includes("code=")) {
428
+ const params = new URLSearchParams(value.replace(/^[?#]/, ""));
429
+ return {
430
+ code: params.get("code") ?? undefined,
431
+ state: params.get("state") ?? undefined,
432
+ };
433
+ }
434
+
435
+ // Assume raw code, possibly with state after #
436
+ const [code, state] = value.split("#", 2);
437
+ return { code, state };
438
+ }
@@ -0,0 +1,187 @@
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 decodeCursorAccessTokenPayload(token: string): unknown | undefined {
142
+ const parts = token.split(".");
143
+ if (parts.length !== 3) return undefined;
144
+ const payload = parts[1];
145
+ if (!payload) return undefined;
146
+ return JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));
147
+ }
148
+
149
+ export function extractCursorAccessTokenUserId(accessToken: string): string | undefined {
150
+ try {
151
+ const payload = decodeCursorAccessTokenPayload(accessToken);
152
+ if (!payload || typeof payload !== "object" || !("sub" in payload) || typeof payload.sub !== "string") {
153
+ return undefined;
154
+ }
155
+ const { sub } = payload;
156
+ const parts = sub.split("|");
157
+ const userId = (parts.length > 1 ? parts[1] : sub).trim();
158
+ return userId || undefined;
159
+ } catch {
160
+ return undefined;
161
+ }
162
+ }
163
+
164
+ function getTokenExpiry(token: string): number {
165
+ try {
166
+ const decoded = decodeCursorAccessTokenPayload(token);
167
+ if (decoded && typeof decoded === "object" && "exp" in decoded && typeof decoded.exp === "number") {
168
+ return decoded.exp * 1000 - 5 * 60 * 1000;
169
+ }
170
+ } catch {
171
+ // Ignore parsing errors
172
+ }
173
+ return Date.now() + 3600 * 1000;
174
+ }
175
+
176
+ export function isCursorTokenExpiringSoon(token: string, thresholdSeconds = 300): boolean {
177
+ try {
178
+ const decoded = decodeCursorAccessTokenPayload(token);
179
+ if (!decoded || typeof decoded !== "object" || !("exp" in decoded) || typeof decoded.exp !== "number") {
180
+ return true;
181
+ }
182
+ const currentTime = Math.floor(Date.now() / 1000);
183
+ return decoded.exp - currentTime < thresholdSeconds;
184
+ } catch {
185
+ return true;
186
+ }
187
+ }