@draht/ai 2026.5.12 → 2026.7.7-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (611) hide show
  1. package/dist/api/anthropic-messages.d.ts +71 -0
  2. package/dist/api/anthropic-messages.d.ts.map +1 -0
  3. package/dist/api/anthropic-messages.js +972 -0
  4. package/dist/api/anthropic-messages.js.map +1 -0
  5. package/dist/api/anthropic-messages.lazy.d.ts +3 -0
  6. package/dist/api/anthropic-messages.lazy.d.ts.map +1 -0
  7. package/dist/api/anthropic-messages.lazy.js +3 -0
  8. package/dist/api/anthropic-messages.lazy.js.map +1 -0
  9. package/dist/api/azure-openai-responses.d.ts +15 -0
  10. package/dist/api/azure-openai-responses.d.ts.map +1 -0
  11. package/dist/api/azure-openai-responses.js +222 -0
  12. package/dist/api/azure-openai-responses.js.map +1 -0
  13. package/dist/api/azure-openai-responses.lazy.d.ts +3 -0
  14. package/dist/api/azure-openai-responses.lazy.d.ts.map +1 -0
  15. package/dist/api/azure-openai-responses.lazy.js +3 -0
  16. package/dist/api/azure-openai-responses.lazy.js.map +1 -0
  17. package/dist/api/bedrock-converse-stream.d.ts +38 -0
  18. package/dist/api/bedrock-converse-stream.d.ts.map +1 -0
  19. package/dist/api/bedrock-converse-stream.js +876 -0
  20. package/dist/api/bedrock-converse-stream.js.map +1 -0
  21. package/dist/api/bedrock-converse-stream.lazy.d.ts +9 -0
  22. package/dist/api/bedrock-converse-stream.lazy.d.ts.map +1 -0
  23. package/dist/api/bedrock-converse-stream.lazy.js +30 -0
  24. package/dist/api/bedrock-converse-stream.lazy.js.map +1 -0
  25. package/dist/api/cloudflare.d.ts +9 -0
  26. package/dist/api/cloudflare.d.ts.map +1 -0
  27. package/dist/api/cloudflare.js +9 -0
  28. package/dist/api/cloudflare.js.map +1 -0
  29. package/dist/{providers → api}/github-copilot-headers.d.ts +1 -1
  30. package/dist/api/github-copilot-headers.d.ts.map +1 -0
  31. package/dist/api/github-copilot-headers.js.map +1 -0
  32. package/dist/api/google-generative-ai.d.ts +13 -0
  33. package/dist/api/google-generative-ai.d.ts.map +1 -0
  34. package/dist/api/google-generative-ai.js +407 -0
  35. package/dist/api/google-generative-ai.js.map +1 -0
  36. package/dist/api/google-generative-ai.lazy.d.ts +3 -0
  37. package/dist/api/google-generative-ai.lazy.d.ts.map +1 -0
  38. package/dist/api/google-generative-ai.lazy.js +3 -0
  39. package/dist/api/google-generative-ai.lazy.js.map +1 -0
  40. package/dist/{providers → api}/google-shared.d.ts +8 -3
  41. package/dist/api/google-shared.d.ts.map +1 -0
  42. package/dist/{providers → api}/google-shared.js +34 -17
  43. package/dist/api/google-shared.js.map +1 -0
  44. package/dist/api/google-vertex.d.ts +15 -0
  45. package/dist/api/google-vertex.d.ts.map +1 -0
  46. package/dist/api/google-vertex.js +456 -0
  47. package/dist/api/google-vertex.js.map +1 -0
  48. package/dist/api/google-vertex.lazy.d.ts +3 -0
  49. package/dist/api/google-vertex.lazy.d.ts.map +1 -0
  50. package/dist/api/google-vertex.lazy.js +3 -0
  51. package/dist/api/google-vertex.lazy.js.map +1 -0
  52. package/dist/api/lazy.d.ts +15 -0
  53. package/dist/api/lazy.d.ts.map +1 -0
  54. package/dist/api/lazy.js +59 -0
  55. package/dist/api/lazy.js.map +1 -0
  56. package/dist/api/mistral-conversations.d.ts +25 -0
  57. package/dist/api/mistral-conversations.d.ts.map +1 -0
  58. package/dist/api/mistral-conversations.js +555 -0
  59. package/dist/api/mistral-conversations.js.map +1 -0
  60. package/dist/api/mistral-conversations.lazy.d.ts +3 -0
  61. package/dist/api/mistral-conversations.lazy.d.ts.map +1 -0
  62. package/dist/api/mistral-conversations.lazy.js +3 -0
  63. package/dist/api/mistral-conversations.lazy.js.map +1 -0
  64. package/dist/api/openai-codex-responses.d.ts +30 -0
  65. package/dist/api/openai-codex-responses.d.ts.map +1 -0
  66. package/dist/api/openai-codex-responses.js +1228 -0
  67. package/dist/api/openai-codex-responses.js.map +1 -0
  68. package/dist/api/openai-codex-responses.lazy.d.ts +3 -0
  69. package/dist/api/openai-codex-responses.lazy.d.ts.map +1 -0
  70. package/dist/api/openai-codex-responses.lazy.js +3 -0
  71. package/dist/api/openai-codex-responses.lazy.js.map +1 -0
  72. package/dist/api/openai-completions.d.ts +19 -0
  73. package/dist/api/openai-completions.d.ts.map +1 -0
  74. package/dist/api/openai-completions.js +1061 -0
  75. package/dist/api/openai-completions.js.map +1 -0
  76. package/dist/api/openai-completions.lazy.d.ts +3 -0
  77. package/dist/api/openai-completions.lazy.d.ts.map +1 -0
  78. package/dist/api/openai-completions.lazy.js +3 -0
  79. package/dist/api/openai-completions.lazy.js.map +1 -0
  80. package/dist/api/openai-prompt-cache.d.ts +3 -0
  81. package/dist/api/openai-prompt-cache.d.ts.map +1 -0
  82. package/dist/api/openai-prompt-cache.js +10 -0
  83. package/dist/api/openai-prompt-cache.js.map +1 -0
  84. package/dist/{providers → api}/openai-responses-shared.d.ts +3 -2
  85. package/dist/api/openai-responses-shared.d.ts.map +1 -0
  86. package/dist/{providers → api}/openai-responses-shared.js +201 -189
  87. package/dist/api/openai-responses-shared.js.map +1 -0
  88. package/dist/{providers → api}/openai-responses.d.ts +3 -3
  89. package/dist/api/openai-responses.d.ts.map +1 -0
  90. package/dist/api/openai-responses.js +229 -0
  91. package/dist/api/openai-responses.js.map +1 -0
  92. package/dist/api/openai-responses.lazy.d.ts +3 -0
  93. package/dist/api/openai-responses.lazy.d.ts.map +1 -0
  94. package/dist/api/openai-responses.lazy.js +3 -0
  95. package/dist/api/openai-responses.lazy.js.map +1 -0
  96. package/dist/api/openrouter-images.d.ts +3 -0
  97. package/dist/api/openrouter-images.d.ts.map +1 -0
  98. package/dist/api/openrouter-images.js +126 -0
  99. package/dist/api/openrouter-images.js.map +1 -0
  100. package/dist/api/openrouter-images.lazy.d.ts +3 -0
  101. package/dist/api/openrouter-images.lazy.d.ts.map +1 -0
  102. package/dist/api/openrouter-images.lazy.js +4 -0
  103. package/dist/api/openrouter-images.lazy.js.map +1 -0
  104. package/dist/api/simple-options.d.ts +14 -0
  105. package/dist/api/simple-options.d.ts.map +1 -0
  106. package/dist/{providers → api}/simple-options.js +20 -4
  107. package/dist/api/simple-options.js.map +1 -0
  108. package/dist/{providers → api}/transform-messages.d.ts +1 -1
  109. package/dist/api/transform-messages.d.ts.map +1 -0
  110. package/dist/{providers → api}/transform-messages.js +66 -34
  111. package/dist/api/transform-messages.js.map +1 -0
  112. package/dist/auth/context.d.ts +7 -0
  113. package/dist/auth/context.d.ts.map +1 -0
  114. package/dist/auth/context.js +42 -0
  115. package/dist/auth/context.js.map +1 -0
  116. package/dist/auth/credential-store.d.ts +16 -0
  117. package/dist/auth/credential-store.d.ts.map +1 -0
  118. package/dist/auth/credential-store.js +37 -0
  119. package/dist/auth/credential-store.js.map +1 -0
  120. package/dist/auth/helpers.d.ts +20 -0
  121. package/dist/auth/helpers.d.ts.map +1 -0
  122. package/dist/auth/helpers.js +46 -0
  123. package/dist/auth/helpers.js.map +1 -0
  124. package/dist/auth/resolve.d.ts +26 -0
  125. package/dist/auth/resolve.d.ts.map +1 -0
  126. package/dist/auth/resolve.js +101 -0
  127. package/dist/auth/resolve.js.map +1 -0
  128. package/dist/auth/types.d.ts +180 -0
  129. package/dist/auth/types.d.ts.map +1 -0
  130. package/dist/auth/types.js +2 -0
  131. package/dist/auth/types.js.map +1 -0
  132. package/dist/bedrock-provider.d.ts +2 -2
  133. package/dist/bedrock-provider.d.ts.map +1 -1
  134. package/dist/bedrock-provider.js +3 -3
  135. package/dist/bedrock-provider.js.map +1 -1
  136. package/dist/cli.d.ts.map +1 -1
  137. package/dist/cli.js +14 -0
  138. package/dist/cli.js.map +1 -1
  139. package/dist/compat.d.ts +65 -0
  140. package/dist/compat.d.ts.map +1 -0
  141. package/dist/compat.js +182 -0
  142. package/dist/compat.js.map +1 -0
  143. package/dist/env-api-keys.d.ts +12 -3
  144. package/dist/env-api-keys.d.ts.map +1 -1
  145. package/dist/env-api-keys.js +77 -39
  146. package/dist/env-api-keys.js.map +1 -1
  147. package/dist/image-models.d.ts +10 -0
  148. package/dist/image-models.d.ts.map +1 -0
  149. package/dist/image-models.generated.d.ts +530 -0
  150. package/dist/image-models.generated.d.ts.map +1 -0
  151. package/dist/image-models.generated.js +532 -0
  152. package/dist/image-models.generated.js.map +1 -0
  153. package/dist/image-models.js +23 -0
  154. package/dist/image-models.js.map +1 -0
  155. package/dist/images-api-registry.d.ts +14 -0
  156. package/dist/images-api-registry.d.ts.map +1 -0
  157. package/dist/images-api-registry.js +22 -0
  158. package/dist/images-api-registry.js.map +1 -0
  159. package/dist/images-models.d.ts +93 -0
  160. package/dist/images-models.d.ts.map +1 -0
  161. package/dist/images-models.js +141 -0
  162. package/dist/images-models.js.map +1 -0
  163. package/dist/images.d.ts +4 -0
  164. package/dist/images.d.ts.map +1 -0
  165. package/dist/images.js +14 -0
  166. package/dist/images.js.map +1 -0
  167. package/dist/index.d.ts +30 -25
  168. package/dist/index.d.ts.map +1 -1
  169. package/dist/index.js +10 -5
  170. package/dist/index.js.map +1 -1
  171. package/dist/legacy-api-aliases.d.ts +42 -0
  172. package/dist/legacy-api-aliases.d.ts.map +1 -0
  173. package/dist/legacy-api-aliases.js +49 -0
  174. package/dist/legacy-api-aliases.js.map +1 -0
  175. package/dist/models.d.ts +136 -15
  176. package/dist/models.d.ts.map +1 -1
  177. package/dist/models.generated.d.ts +8182 -2013
  178. package/dist/models.generated.d.ts.map +1 -1
  179. package/dist/models.generated.js +70 -14888
  180. package/dist/models.generated.js.map +1 -1
  181. package/dist/models.js +218 -24
  182. package/dist/models.js.map +1 -1
  183. package/dist/oauth.d.ts +1 -1
  184. package/dist/oauth.d.ts.map +1 -1
  185. package/dist/oauth.js.map +1 -1
  186. package/dist/providers/all.d.ts +21 -0
  187. package/dist/providers/all.d.ts.map +1 -0
  188. package/dist/providers/all.js +114 -0
  189. package/dist/providers/all.js.map +1 -0
  190. package/dist/providers/amazon-bedrock.d.ts +2 -19
  191. package/dist/providers/amazon-bedrock.d.ts.map +1 -1
  192. package/dist/providers/amazon-bedrock.js +33 -649
  193. package/dist/providers/amazon-bedrock.js.map +1 -1
  194. package/dist/providers/amazon-bedrock.models.d.ts +1875 -0
  195. package/dist/providers/amazon-bedrock.models.d.ts.map +1 -0
  196. package/dist/providers/amazon-bedrock.models.js +1829 -0
  197. package/dist/providers/amazon-bedrock.models.js.map +1 -0
  198. package/dist/providers/ant-ling.d.ts +3 -0
  199. package/dist/providers/ant-ling.d.ts.map +1 -0
  200. package/dist/providers/ant-ling.js +15 -0
  201. package/dist/providers/ant-ling.js.map +1 -0
  202. package/dist/providers/ant-ling.models.d.ts +86 -0
  203. package/dist/providers/ant-ling.models.d.ts.map +1 -0
  204. package/dist/providers/ant-ling.models.js +60 -0
  205. package/dist/providers/ant-ling.models.js.map +1 -0
  206. package/dist/providers/anthropic.d.ts +2 -39
  207. package/dist/providers/anthropic.d.ts.map +1 -1
  208. package/dist/providers/anthropic.js +17 -771
  209. package/dist/providers/anthropic.js.map +1 -1
  210. package/dist/providers/anthropic.models.d.ts +274 -0
  211. package/dist/providers/anthropic.models.d.ts.map +1 -0
  212. package/dist/providers/anthropic.models.js +253 -0
  213. package/dist/providers/anthropic.models.js.map +1 -0
  214. package/dist/providers/azure-openai-responses.d.ts +2 -14
  215. package/dist/providers/azure-openai-responses.d.ts.map +1 -1
  216. package/dist/providers/azure-openai-responses.js +11 -173
  217. package/dist/providers/azure-openai-responses.js.map +1 -1
  218. package/dist/providers/azure-openai-responses.models.d.ts +804 -0
  219. package/dist/providers/azure-openai-responses.models.d.ts.map +1 -0
  220. package/dist/providers/azure-openai-responses.models.js +743 -0
  221. package/dist/providers/azure-openai-responses.models.js.map +1 -0
  222. package/dist/providers/cerebras.d.ts +3 -0
  223. package/dist/providers/cerebras.d.ts.map +1 -0
  224. package/dist/providers/cerebras.js +15 -0
  225. package/dist/providers/cerebras.js.map +1 -0
  226. package/dist/providers/cerebras.models.d.ts +66 -0
  227. package/dist/providers/cerebras.models.d.ts.map +1 -0
  228. package/dist/providers/cerebras.models.js +59 -0
  229. package/dist/providers/cerebras.models.js.map +1 -0
  230. package/dist/providers/cloudflare-ai-gateway.d.ts +3 -0
  231. package/dist/providers/cloudflare-ai-gateway.d.ts.map +1 -0
  232. package/dist/providers/cloudflare-ai-gateway.js +20 -0
  233. package/dist/providers/cloudflare-ai-gateway.js.map +1 -0
  234. package/dist/providers/cloudflare-ai-gateway.models.d.ts +786 -0
  235. package/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -0
  236. package/dist/providers/cloudflare-ai-gateway.models.js +684 -0
  237. package/dist/providers/cloudflare-ai-gateway.models.js.map +1 -0
  238. package/dist/providers/cloudflare-auth.d.ts +4 -0
  239. package/dist/providers/cloudflare-auth.d.ts.map +1 -0
  240. package/dist/providers/cloudflare-auth.js +85 -0
  241. package/dist/providers/cloudflare-auth.js.map +1 -0
  242. package/dist/providers/cloudflare-workers-ai.d.ts +3 -0
  243. package/dist/providers/cloudflare-workers-ai.d.ts.map +1 -0
  244. package/dist/providers/cloudflare-workers-ai.js +14 -0
  245. package/dist/providers/cloudflare-workers-ai.js.map +1 -0
  246. package/dist/providers/cloudflare-workers-ai.models.d.ts +302 -0
  247. package/dist/providers/cloudflare-workers-ai.models.d.ts.map +1 -0
  248. package/dist/providers/cloudflare-workers-ai.models.js +239 -0
  249. package/dist/providers/cloudflare-workers-ai.models.js.map +1 -0
  250. package/dist/providers/deepseek.d.ts +3 -0
  251. package/dist/providers/deepseek.d.ts.map +1 -0
  252. package/dist/providers/deepseek.js +15 -0
  253. package/dist/providers/deepseek.js.map +1 -0
  254. package/dist/providers/deepseek.models.d.ts +63 -0
  255. package/dist/providers/deepseek.models.d.ts.map +1 -0
  256. package/dist/providers/deepseek.models.js +43 -0
  257. package/dist/providers/deepseek.models.js.map +1 -0
  258. package/dist/providers/faux.d.ts +43 -2
  259. package/dist/providers/faux.d.ts.map +1 -1
  260. package/dist/providers/faux.js +35 -7
  261. package/dist/providers/faux.js.map +1 -1
  262. package/dist/providers/fireworks.d.ts +3 -0
  263. package/dist/providers/fireworks.d.ts.map +1 -0
  264. package/dist/providers/fireworks.js +19 -0
  265. package/dist/providers/fireworks.js.map +1 -0
  266. package/dist/providers/fireworks.models.d.ts +381 -0
  267. package/dist/providers/fireworks.models.d.ts.map +1 -0
  268. package/dist/providers/fireworks.models.js +295 -0
  269. package/dist/providers/fireworks.models.js.map +1 -0
  270. package/dist/providers/github-copilot.d.ts +3 -0
  271. package/dist/providers/github-copilot.d.ts.map +1 -0
  272. package/dist/providers/github-copilot.js +25 -0
  273. package/dist/providers/github-copilot.js.map +1 -0
  274. package/dist/providers/github-copilot.models.d.ts +698 -0
  275. package/dist/providers/github-copilot.models.d.ts.map +1 -0
  276. package/dist/providers/github-copilot.models.js +483 -0
  277. package/dist/providers/github-copilot.models.js.map +1 -0
  278. package/dist/providers/google-vertex.d.ts +2 -14
  279. package/dist/providers/google-vertex.d.ts.map +1 -1
  280. package/dist/providers/google-vertex.js +30 -414
  281. package/dist/providers/google-vertex.js.map +1 -1
  282. package/dist/providers/google-vertex.models.d.ts +202 -0
  283. package/dist/providers/google-vertex.models.d.ts.map +1 -0
  284. package/dist/providers/google-vertex.models.js +182 -0
  285. package/dist/providers/google-vertex.models.js.map +1 -0
  286. package/dist/providers/google.d.ts +2 -12
  287. package/dist/providers/google.d.ts.map +1 -1
  288. package/dist/providers/google.js +12 -396
  289. package/dist/providers/google.js.map +1 -1
  290. package/dist/providers/google.models.d.ts +328 -0
  291. package/dist/providers/google.models.d.ts.map +1 -0
  292. package/dist/providers/google.models.js +288 -0
  293. package/dist/providers/google.models.js.map +1 -0
  294. package/dist/providers/groq.d.ts +3 -0
  295. package/dist/providers/groq.d.ts.map +1 -0
  296. package/dist/providers/groq.js +15 -0
  297. package/dist/providers/groq.js.map +1 -0
  298. package/dist/providers/groq.models.d.ts +128 -0
  299. package/dist/providers/groq.models.d.ts.map +1 -0
  300. package/dist/providers/groq.models.js +125 -0
  301. package/dist/providers/groq.models.js.map +1 -0
  302. package/dist/providers/huggingface.d.ts +3 -0
  303. package/dist/providers/huggingface.d.ts.map +1 -0
  304. package/dist/providers/huggingface.js +15 -0
  305. package/dist/providers/huggingface.js.map +1 -0
  306. package/dist/providers/huggingface.models.d.ts +983 -0
  307. package/dist/providers/huggingface.models.d.ts.map +1 -0
  308. package/dist/providers/huggingface.models.js +887 -0
  309. package/dist/providers/huggingface.models.js.map +1 -0
  310. package/dist/providers/images/register-builtins.d.ts +4 -0
  311. package/dist/providers/images/register-builtins.d.ts.map +1 -0
  312. package/dist/providers/images/register-builtins.js +34 -0
  313. package/dist/providers/images/register-builtins.js.map +1 -0
  314. package/dist/providers/kimi-coding.d.ts +3 -0
  315. package/dist/providers/kimi-coding.d.ts.map +1 -0
  316. package/dist/providers/kimi-coding.js +15 -0
  317. package/dist/providers/kimi-coding.js.map +1 -0
  318. package/dist/providers/kimi-coding.models.d.ts +63 -0
  319. package/dist/providers/kimi-coding.models.d.ts.map +1 -0
  320. package/dist/providers/kimi-coding.models.js +59 -0
  321. package/dist/providers/kimi-coding.models.js.map +1 -0
  322. package/dist/providers/minimax-cn.d.ts +3 -0
  323. package/dist/providers/minimax-cn.d.ts.map +1 -0
  324. package/dist/providers/minimax-cn.js +15 -0
  325. package/dist/providers/minimax-cn.js.map +1 -0
  326. package/dist/providers/minimax-cn.models.d.ts +54 -0
  327. package/dist/providers/minimax-cn.models.d.ts.map +1 -0
  328. package/dist/providers/minimax-cn.models.js +56 -0
  329. package/dist/providers/minimax-cn.models.js.map +1 -0
  330. package/dist/providers/minimax.d.ts +3 -0
  331. package/dist/providers/minimax.d.ts.map +1 -0
  332. package/dist/providers/minimax.js +15 -0
  333. package/dist/providers/minimax.js.map +1 -0
  334. package/dist/providers/minimax.models.d.ts +54 -0
  335. package/dist/providers/minimax.models.d.ts.map +1 -0
  336. package/dist/providers/minimax.models.js +56 -0
  337. package/dist/providers/minimax.models.js.map +1 -0
  338. package/dist/providers/mistral.d.ts +2 -21
  339. package/dist/providers/mistral.d.ts.map +1 -1
  340. package/dist/providers/mistral.js +12 -498
  341. package/dist/providers/mistral.js.map +1 -1
  342. package/dist/providers/mistral.models.d.ts +513 -0
  343. package/dist/providers/mistral.models.d.ts.map +1 -0
  344. package/dist/providers/mistral.models.js +515 -0
  345. package/dist/providers/mistral.models.js.map +1 -0
  346. package/dist/providers/moonshotai-cn.d.ts +3 -0
  347. package/dist/providers/moonshotai-cn.d.ts.map +1 -0
  348. package/dist/providers/moonshotai-cn.js +15 -0
  349. package/dist/providers/moonshotai-cn.js.map +1 -0
  350. package/dist/providers/moonshotai-cn.models.d.ts +234 -0
  351. package/dist/providers/moonshotai-cn.models.d.ts.map +1 -0
  352. package/dist/providers/moonshotai-cn.models.js +169 -0
  353. package/dist/providers/moonshotai-cn.models.js.map +1 -0
  354. package/dist/providers/moonshotai.d.ts +3 -0
  355. package/dist/providers/moonshotai.d.ts.map +1 -0
  356. package/dist/providers/moonshotai.js +15 -0
  357. package/dist/providers/moonshotai.js.map +1 -0
  358. package/dist/providers/moonshotai.models.d.ts +234 -0
  359. package/dist/providers/moonshotai.models.d.ts.map +1 -0
  360. package/dist/providers/moonshotai.models.js +169 -0
  361. package/dist/providers/moonshotai.models.js.map +1 -0
  362. package/dist/providers/nvidia.d.ts +3 -0
  363. package/dist/providers/nvidia.d.ts.map +1 -0
  364. package/dist/providers/nvidia.js +15 -0
  365. package/dist/providers/nvidia.js.map +1 -0
  366. package/dist/providers/nvidia.models.d.ts +563 -0
  367. package/dist/providers/nvidia.models.d.ts.map +1 -0
  368. package/dist/providers/nvidia.models.js +385 -0
  369. package/dist/providers/nvidia.models.js.map +1 -0
  370. package/dist/providers/openai-codex.d.ts +3 -0
  371. package/dist/providers/openai-codex.d.ts.map +1 -0
  372. package/dist/providers/openai-codex.js +18 -0
  373. package/dist/providers/openai-codex.js.map +1 -0
  374. package/dist/providers/openai-codex.models.d.ts +87 -0
  375. package/dist/providers/openai-codex.models.d.ts.map +1 -0
  376. package/dist/providers/openai-codex.models.js +77 -0
  377. package/dist/providers/openai-codex.models.js.map +1 -0
  378. package/dist/providers/openai.d.ts +3 -0
  379. package/dist/providers/openai.d.ts.map +1 -0
  380. package/dist/providers/openai.js +15 -0
  381. package/dist/providers/openai.js.map +1 -0
  382. package/dist/providers/openai.models.d.ts +805 -0
  383. package/dist/providers/openai.models.d.ts.map +1 -0
  384. package/dist/providers/openai.models.js +743 -0
  385. package/dist/providers/openai.models.js.map +1 -0
  386. package/dist/providers/opencode-go.d.ts +3 -0
  387. package/dist/providers/opencode-go.d.ts.map +1 -0
  388. package/dist/providers/opencode-go.js +18 -0
  389. package/dist/providers/opencode-go.js.map +1 -0
  390. package/dist/providers/opencode-go.models.d.ts +309 -0
  391. package/dist/providers/opencode-go.models.d.ts.map +1 -0
  392. package/dist/providers/opencode-go.models.js +240 -0
  393. package/dist/providers/opencode-go.models.js.map +1 -0
  394. package/dist/providers/opencode.d.ts +3 -0
  395. package/dist/providers/opencode.d.ts.map +1 -0
  396. package/dist/providers/opencode.js +22 -0
  397. package/dist/providers/opencode.js.map +1 -0
  398. package/dist/providers/opencode.models.d.ts +1086 -0
  399. package/dist/providers/opencode.models.d.ts.map +1 -0
  400. package/dist/providers/opencode.models.js +906 -0
  401. package/dist/providers/opencode.models.js.map +1 -0
  402. package/dist/providers/openrouter-images.d.ts +3 -0
  403. package/dist/providers/openrouter-images.d.ts.map +1 -0
  404. package/dist/providers/openrouter-images.js +14 -0
  405. package/dist/providers/openrouter-images.js.map +1 -0
  406. package/dist/providers/openrouter.d.ts +3 -0
  407. package/dist/providers/openrouter.d.ts.map +1 -0
  408. package/dist/providers/openrouter.js +15 -0
  409. package/dist/providers/openrouter.js.map +1 -0
  410. package/dist/providers/openrouter.models.d.ts +5528 -0
  411. package/dist/providers/openrouter.models.d.ts.map +1 -0
  412. package/dist/providers/openrouter.models.js +4742 -0
  413. package/dist/providers/openrouter.models.js.map +1 -0
  414. package/dist/providers/together.d.ts +3 -0
  415. package/dist/providers/together.d.ts.map +1 -0
  416. package/dist/providers/together.js +15 -0
  417. package/dist/providers/together.js.map +1 -0
  418. package/dist/providers/together.models.d.ts +598 -0
  419. package/dist/providers/together.models.d.ts.map +1 -0
  420. package/dist/providers/together.models.js +380 -0
  421. package/dist/providers/together.models.js.map +1 -0
  422. package/dist/providers/vercel-ai-gateway.d.ts +3 -0
  423. package/dist/providers/vercel-ai-gateway.d.ts.map +1 -0
  424. package/dist/providers/vercel-ai-gateway.js +15 -0
  425. package/dist/providers/vercel-ai-gateway.js.map +1 -0
  426. package/dist/providers/vercel-ai-gateway.models.d.ts +3254 -0
  427. package/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -0
  428. package/dist/providers/vercel-ai-gateway.models.js +3206 -0
  429. package/dist/providers/vercel-ai-gateway.models.js.map +1 -0
  430. package/dist/providers/xai.d.ts +3 -0
  431. package/dist/providers/xai.d.ts.map +1 -0
  432. package/dist/providers/xai.js +15 -0
  433. package/dist/providers/xai.js.map +1 -0
  434. package/dist/providers/xai.models.d.ts +157 -0
  435. package/dist/providers/xai.models.d.ts.map +1 -0
  436. package/dist/providers/xai.models.js +131 -0
  437. package/dist/providers/xai.models.js.map +1 -0
  438. package/dist/providers/xiaomi-token-plan-ams.d.ts +3 -0
  439. package/dist/providers/xiaomi-token-plan-ams.d.ts.map +1 -0
  440. package/dist/providers/xiaomi-token-plan-ams.js +15 -0
  441. package/dist/providers/xiaomi-token-plan-ams.js.map +1 -0
  442. package/dist/providers/xiaomi-token-plan-ams.models.d.ts +108 -0
  443. package/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -0
  444. package/dist/providers/xiaomi-token-plan-ams.models.js +95 -0
  445. package/dist/providers/xiaomi-token-plan-ams.models.js.map +1 -0
  446. package/dist/providers/xiaomi-token-plan-cn.d.ts +3 -0
  447. package/dist/providers/xiaomi-token-plan-cn.d.ts.map +1 -0
  448. package/dist/providers/xiaomi-token-plan-cn.js +15 -0
  449. package/dist/providers/xiaomi-token-plan-cn.js.map +1 -0
  450. package/dist/providers/xiaomi-token-plan-cn.models.d.ts +108 -0
  451. package/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -0
  452. package/dist/providers/xiaomi-token-plan-cn.models.js +95 -0
  453. package/dist/providers/xiaomi-token-plan-cn.models.js.map +1 -0
  454. package/dist/providers/xiaomi-token-plan-sgp.d.ts +3 -0
  455. package/dist/providers/xiaomi-token-plan-sgp.d.ts.map +1 -0
  456. package/dist/providers/xiaomi-token-plan-sgp.js +15 -0
  457. package/dist/providers/xiaomi-token-plan-sgp.js.map +1 -0
  458. package/dist/providers/xiaomi-token-plan-sgp.models.d.ts +108 -0
  459. package/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -0
  460. package/dist/providers/xiaomi-token-plan-sgp.models.js +95 -0
  461. package/dist/providers/xiaomi-token-plan-sgp.models.js.map +1 -0
  462. package/dist/providers/xiaomi.d.ts +3 -0
  463. package/dist/providers/xiaomi.d.ts.map +1 -0
  464. package/dist/providers/xiaomi.js +15 -0
  465. package/dist/providers/xiaomi.js.map +1 -0
  466. package/dist/providers/xiaomi.models.d.ts +129 -0
  467. package/dist/providers/xiaomi.models.d.ts.map +1 -0
  468. package/dist/providers/xiaomi.models.js +113 -0
  469. package/dist/providers/xiaomi.models.js.map +1 -0
  470. package/dist/providers/zai-coding-cn.d.ts +3 -0
  471. package/dist/providers/zai-coding-cn.d.ts.map +1 -0
  472. package/dist/providers/zai-coding-cn.js +15 -0
  473. package/dist/providers/zai-coding-cn.js.map +1 -0
  474. package/dist/providers/zai-coding-cn.models.d.ts +153 -0
  475. package/dist/providers/zai-coding-cn.models.d.ts.map +1 -0
  476. package/dist/providers/zai-coding-cn.models.js +114 -0
  477. package/dist/providers/zai-coding-cn.models.js.map +1 -0
  478. package/dist/providers/zai.d.ts +3 -0
  479. package/dist/providers/zai.d.ts.map +1 -0
  480. package/dist/providers/zai.js +15 -0
  481. package/dist/providers/zai.js.map +1 -0
  482. package/dist/providers/zai.models.d.ts +153 -0
  483. package/dist/providers/zai.models.d.ts.map +1 -0
  484. package/dist/providers/zai.models.js +114 -0
  485. package/dist/providers/zai.models.js.map +1 -0
  486. package/dist/session-resources.d.ts +4 -0
  487. package/dist/session-resources.d.ts.map +1 -0
  488. package/dist/session-resources.js +22 -0
  489. package/dist/session-resources.js.map +1 -0
  490. package/dist/types.d.ts +262 -18
  491. package/dist/types.d.ts.map +1 -1
  492. package/dist/types.js.map +1 -1
  493. package/dist/utils/abort-signals.d.ts +6 -0
  494. package/dist/utils/abort-signals.d.ts.map +1 -0
  495. package/dist/utils/abort-signals.js +34 -0
  496. package/dist/utils/abort-signals.js.map +1 -0
  497. package/dist/utils/diagnostics.d.ts +19 -0
  498. package/dist/utils/diagnostics.d.ts.map +1 -0
  499. package/dist/utils/diagnostics.js +25 -0
  500. package/dist/utils/diagnostics.js.map +1 -0
  501. package/dist/utils/error-body.d.ts +25 -0
  502. package/dist/utils/error-body.d.ts.map +1 -0
  503. package/dist/utils/error-body.js +109 -0
  504. package/dist/utils/error-body.js.map +1 -0
  505. package/dist/utils/estimate.d.ts +17 -0
  506. package/dist/utils/estimate.d.ts.map +1 -0
  507. package/dist/utils/estimate.js +95 -0
  508. package/dist/utils/estimate.js.map +1 -0
  509. package/dist/utils/event-stream.d.ts +3 -3
  510. package/dist/utils/event-stream.d.ts.map +1 -1
  511. package/dist/utils/event-stream.js +2 -2
  512. package/dist/utils/event-stream.js.map +1 -1
  513. package/dist/utils/headers.d.ts +4 -0
  514. package/dist/utils/headers.d.ts.map +1 -0
  515. package/dist/utils/headers.js +18 -0
  516. package/dist/utils/headers.js.map +1 -0
  517. package/dist/utils/json-parse.d.ts +8 -1
  518. package/dist/utils/json-parse.d.ts.map +1 -1
  519. package/dist/utils/json-parse.js +89 -5
  520. package/dist/utils/json-parse.js.map +1 -1
  521. package/dist/utils/node-http-proxy.d.ts +4 -0
  522. package/dist/utils/node-http-proxy.d.ts.map +1 -0
  523. package/dist/utils/node-http-proxy.js +92 -0
  524. package/dist/utils/node-http-proxy.js.map +1 -0
  525. package/dist/utils/oauth/anthropic.d.ts +3 -1
  526. package/dist/utils/oauth/anthropic.d.ts.map +1 -1
  527. package/dist/utils/oauth/anthropic.js +33 -1
  528. package/dist/utils/oauth/anthropic.js.map +1 -1
  529. package/dist/utils/oauth/device-code.d.ts +23 -0
  530. package/dist/utils/oauth/device-code.d.ts.map +1 -0
  531. package/dist/utils/oauth/device-code.js +69 -0
  532. package/dist/utils/oauth/device-code.js.map +1 -0
  533. package/dist/utils/oauth/github-copilot.d.ts +5 -3
  534. package/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  535. package/dist/utils/oauth/github-copilot.js +158 -79
  536. package/dist/utils/oauth/github-copilot.js.map +1 -1
  537. package/dist/utils/oauth/index.d.ts +8 -11
  538. package/dist/utils/oauth/index.d.ts.map +1 -1
  539. package/dist/utils/oauth/index.js +2 -11
  540. package/dist/utils/oauth/index.js.map +1 -1
  541. package/dist/utils/oauth/load.d.ts +5 -0
  542. package/dist/utils/oauth/load.d.ts.map +1 -0
  543. package/dist/utils/oauth/load.js +22 -0
  544. package/dist/utils/oauth/load.js.map +1 -0
  545. package/dist/utils/oauth/openai-codex.d.ts +13 -2
  546. package/dist/utils/oauth/openai-codex.d.ts.map +1 -1
  547. package/dist/utils/oauth/openai-codex.js +237 -73
  548. package/dist/utils/oauth/openai-codex.js.map +1 -1
  549. package/dist/utils/oauth/types.d.ts +18 -1
  550. package/dist/utils/oauth/types.d.ts.map +1 -1
  551. package/dist/utils/oauth/types.js.map +1 -1
  552. package/dist/utils/overflow.d.ts +8 -3
  553. package/dist/utils/overflow.d.ts.map +1 -1
  554. package/dist/utils/overflow.js +29 -3
  555. package/dist/utils/overflow.js.map +1 -1
  556. package/dist/utils/provider-env.d.ts +7 -0
  557. package/dist/utils/provider-env.d.ts.map +1 -0
  558. package/dist/utils/provider-env.js +44 -0
  559. package/dist/utils/provider-env.js.map +1 -0
  560. package/dist/utils/retry.d.ts +12 -0
  561. package/dist/utils/retry.d.ts.map +1 -0
  562. package/dist/utils/retry.js +87 -0
  563. package/dist/utils/retry.js.map +1 -0
  564. package/dist/utils/typebox-helpers.d.ts +1 -1
  565. package/dist/utils/typebox-helpers.d.ts.map +1 -1
  566. package/dist/utils/typebox-helpers.js +1 -1
  567. package/dist/utils/typebox-helpers.js.map +1 -1
  568. package/dist/utils/validation.d.ts +1 -1
  569. package/dist/utils/validation.d.ts.map +1 -1
  570. package/dist/utils/validation.js +230 -41
  571. package/dist/utils/validation.js.map +1 -1
  572. package/package.json +24 -44
  573. package/dist/api-registry.d.ts +0 -20
  574. package/dist/api-registry.d.ts.map +0 -1
  575. package/dist/api-registry.js +0 -44
  576. package/dist/api-registry.js.map +0 -1
  577. package/dist/providers/github-copilot-headers.d.ts.map +0 -1
  578. package/dist/providers/github-copilot-headers.js.map +0 -1
  579. package/dist/providers/google-gemini-cli.d.ts +0 -74
  580. package/dist/providers/google-gemini-cli.d.ts.map +0 -1
  581. package/dist/providers/google-gemini-cli.js +0 -776
  582. package/dist/providers/google-gemini-cli.js.map +0 -1
  583. package/dist/providers/google-shared.d.ts.map +0 -1
  584. package/dist/providers/google-shared.js.map +0 -1
  585. package/dist/providers/openai-codex-responses.d.ts +0 -9
  586. package/dist/providers/openai-codex-responses.d.ts.map +0 -1
  587. package/dist/providers/openai-codex-responses.js +0 -741
  588. package/dist/providers/openai-codex-responses.js.map +0 -1
  589. package/dist/providers/openai-completions.d.ts +0 -15
  590. package/dist/providers/openai-completions.d.ts.map +0 -1
  591. package/dist/providers/openai-completions.js +0 -760
  592. package/dist/providers/openai-completions.js.map +0 -1
  593. package/dist/providers/openai-responses-shared.d.ts.map +0 -1
  594. package/dist/providers/openai-responses-shared.js.map +0 -1
  595. package/dist/providers/openai-responses.d.ts.map +0 -1
  596. package/dist/providers/openai-responses.js +0 -190
  597. package/dist/providers/openai-responses.js.map +0 -1
  598. package/dist/providers/register-builtins.d.ts +0 -38
  599. package/dist/providers/register-builtins.d.ts.map +0 -1
  600. package/dist/providers/register-builtins.js +0 -261
  601. package/dist/providers/register-builtins.js.map +0 -1
  602. package/dist/providers/simple-options.d.ts +0 -13
  603. package/dist/providers/simple-options.d.ts.map +0 -1
  604. package/dist/providers/simple-options.js.map +0 -1
  605. package/dist/providers/transform-messages.d.ts.map +0 -1
  606. package/dist/providers/transform-messages.js.map +0 -1
  607. package/dist/stream.d.ts +0 -8
  608. package/dist/stream.d.ts.map +0 -1
  609. package/dist/stream.js +0 -27
  610. package/dist/stream.js.map +0 -1
  611. /package/dist/{providers → api}/github-copilot-headers.js +0 -0
@@ -1,3 +1,41 @@
1
+ const NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
2
+ const NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
3
+ function replaceImagesWithPlaceholder(content, placeholder) {
4
+ const result = [];
5
+ let previousWasPlaceholder = false;
6
+ for (const block of content) {
7
+ if (block.type === "image") {
8
+ if (!previousWasPlaceholder) {
9
+ result.push({ type: "text", text: placeholder });
10
+ }
11
+ previousWasPlaceholder = true;
12
+ continue;
13
+ }
14
+ result.push(block);
15
+ previousWasPlaceholder = block.text === placeholder;
16
+ }
17
+ return result;
18
+ }
19
+ function downgradeUnsupportedImages(messages, model) {
20
+ if (model.input.includes("image")) {
21
+ return messages;
22
+ }
23
+ return messages.map((msg) => {
24
+ if (msg.role === "user" && Array.isArray(msg.content)) {
25
+ return {
26
+ ...msg,
27
+ content: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER),
28
+ };
29
+ }
30
+ if (msg.role === "toolResult") {
31
+ return {
32
+ ...msg,
33
+ content: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER),
34
+ };
35
+ }
36
+ return msg;
37
+ });
38
+ }
1
39
  /**
2
40
  * Normalize tool call ID for cross-provider compatibility.
3
41
  * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
@@ -6,8 +44,12 @@
6
44
  export function transformMessages(messages, model, normalizeToolCallId) {
7
45
  // Build a map of original tool call IDs to normalized IDs
8
46
  const toolCallIdMap = new Map();
9
- // First pass: transform messages (thinking blocks, tool call ID normalization)
10
- const transformed = messages.map((msg) => {
47
+ // Normalize null/undefined content from untyped callers (custom tools, hand-built
48
+ // histories, old session files) so downstream code can rely on the type contract.
49
+ const normalizedMessages = messages.map((msg) => (msg.content == null ? { ...msg, content: [] } : msg));
50
+ const imageAwareMessages = downgradeUnsupportedImages(normalizedMessages, model);
51
+ // First pass: transform messages (unsupported image downgrade, thinking blocks, tool call ID normalization)
52
+ const transformed = imageAwareMessages.map((msg) => {
11
53
  // User messages pass through unchanged
12
54
  if (msg.role === "user") {
13
55
  return msg;
@@ -85,26 +127,29 @@ export function transformMessages(messages, model, normalizeToolCallId) {
85
127
  const result = [];
86
128
  let pendingToolCalls = [];
87
129
  let existingToolResultIds = new Set();
130
+ const insertSyntheticToolResults = () => {
131
+ if (pendingToolCalls.length > 0) {
132
+ for (const tc of pendingToolCalls) {
133
+ if (!existingToolResultIds.has(tc.id)) {
134
+ result.push({
135
+ role: "toolResult",
136
+ toolCallId: tc.id,
137
+ toolName: tc.name,
138
+ content: [{ type: "text", text: "No result provided" }],
139
+ isError: true,
140
+ timestamp: Date.now(),
141
+ });
142
+ }
143
+ }
144
+ pendingToolCalls = [];
145
+ existingToolResultIds = new Set();
146
+ }
147
+ };
88
148
  for (let i = 0; i < transformed.length; i++) {
89
149
  const msg = transformed[i];
90
150
  if (msg.role === "assistant") {
91
151
  // If we have pending orphaned tool calls from a previous assistant, insert synthetic results now
92
- if (pendingToolCalls.length > 0) {
93
- for (const tc of pendingToolCalls) {
94
- if (!existingToolResultIds.has(tc.id)) {
95
- result.push({
96
- role: "toolResult",
97
- toolCallId: tc.id,
98
- toolName: tc.name,
99
- content: [{ type: "text", text: "No result provided" }],
100
- isError: true,
101
- timestamp: Date.now(),
102
- });
103
- }
104
- }
105
- pendingToolCalls = [];
106
- existingToolResultIds = new Set();
107
- }
152
+ insertSyntheticToolResults();
108
153
  // Skip errored/aborted assistant messages entirely.
109
154
  // These are incomplete turns that shouldn't be replayed:
110
155
  // - May have partial content (reasoning without message, incomplete tool calls)
@@ -128,28 +173,15 @@ export function transformMessages(messages, model, normalizeToolCallId) {
128
173
  }
129
174
  else if (msg.role === "user") {
130
175
  // User message interrupts tool flow - insert synthetic results for orphaned calls
131
- if (pendingToolCalls.length > 0) {
132
- for (const tc of pendingToolCalls) {
133
- if (!existingToolResultIds.has(tc.id)) {
134
- result.push({
135
- role: "toolResult",
136
- toolCallId: tc.id,
137
- toolName: tc.name,
138
- content: [{ type: "text", text: "No result provided" }],
139
- isError: true,
140
- timestamp: Date.now(),
141
- });
142
- }
143
- }
144
- pendingToolCalls = [];
145
- existingToolResultIds = new Set();
146
- }
176
+ insertSyntheticToolResults();
147
177
  result.push(msg);
148
178
  }
149
179
  else {
150
180
  result.push(msg);
151
181
  }
152
182
  }
183
+ // If the conversation ends with unresolved tool calls, synthesize results now.
184
+ insertSyntheticToolResults();
153
185
  return result;
154
186
  }
155
187
  //# sourceMappingURL=transform-messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-messages.js","sourceRoot":"","sources":["../../src/api/transform-messages.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tApi,\n\tAssistantMessage,\n\tImageContent,\n\tMessage,\n\tModel,\n\tTextContent,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.ts\";\n\nconst NON_VISION_USER_IMAGE_PLACEHOLDER = \"(image omitted: model does not support images)\";\nconst NON_VISION_TOOL_IMAGE_PLACEHOLDER = \"(tool image omitted: model does not support images)\";\n\nfunction replaceImagesWithPlaceholder(content: (TextContent | ImageContent)[], placeholder: string): TextContent[] {\n\tconst result: TextContent[] = [];\n\tlet previousWasPlaceholder = false;\n\n\tfor (const block of content) {\n\t\tif (block.type === \"image\") {\n\t\t\tif (!previousWasPlaceholder) {\n\t\t\t\tresult.push({ type: \"text\", text: placeholder });\n\t\t\t}\n\t\t\tpreviousWasPlaceholder = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult.push(block);\n\t\tpreviousWasPlaceholder = block.text === placeholder;\n\t}\n\n\treturn result;\n}\n\nfunction downgradeUnsupportedImages<TApi extends Api>(messages: Message[], model: Model<TApi>): Message[] {\n\tif (model.input.includes(\"image\")) {\n\t\treturn messages;\n\t}\n\n\treturn messages.map((msg) => {\n\t\tif (msg.role === \"user\" && Array.isArray(msg.content)) {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\tif (msg.role === \"toolResult\") {\n\t\t\treturn {\n\t\t\t\t...msg,\n\t\t\t\tcontent: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER),\n\t\t\t};\n\t\t}\n\n\t\treturn msg;\n\t});\n}\n\n/**\n * Normalize tool call ID for cross-provider compatibility.\n * OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.\n * Anthropic APIs require IDs matching ^[a-zA-Z0-9_-]+$ (max 64 chars).\n */\nexport function transformMessages<TApi extends Api>(\n\tmessages: Message[],\n\tmodel: Model<TApi>,\n\tnormalizeToolCallId?: (id: string, model: Model<TApi>, source: AssistantMessage) => string,\n): Message[] {\n\t// Build a map of original tool call IDs to normalized IDs\n\tconst toolCallIdMap = new Map<string, string>();\n\t// Normalize null/undefined content from untyped callers (custom tools, hand-built\n\t// histories, old session files) so downstream code can rely on the type contract.\n\tconst normalizedMessages = messages.map((msg) => (msg.content == null ? { ...msg, content: [] } : msg));\n\tconst imageAwareMessages = downgradeUnsupportedImages(normalizedMessages, model);\n\n\t// First pass: transform messages (unsupported image downgrade, thinking blocks, tool call ID normalization)\n\tconst transformed = imageAwareMessages.map((msg) => {\n\t\t// User messages pass through unchanged\n\t\tif (msg.role === \"user\") {\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Handle toolResult messages - normalize toolCallId if we have a mapping\n\t\tif (msg.role === \"toolResult\") {\n\t\t\tconst normalizedId = toolCallIdMap.get(msg.toolCallId);\n\t\t\tif (normalizedId && normalizedId !== msg.toolCallId) {\n\t\t\t\treturn { ...msg, toolCallId: normalizedId };\n\t\t\t}\n\t\t\treturn msg;\n\t\t}\n\n\t\t// Assistant messages need transformation check\n\t\tif (msg.role === \"assistant\") {\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tconst isSameModel =\n\t\t\t\tassistantMsg.provider === model.provider &&\n\t\t\t\tassistantMsg.api === model.api &&\n\t\t\t\tassistantMsg.model === model.id;\n\n\t\t\tconst transformedContent = assistantMsg.content.flatMap((block) => {\n\t\t\t\tif (block.type === \"thinking\") {\n\t\t\t\t\t// Redacted thinking is opaque encrypted content, only valid for the same model.\n\t\t\t\t\t// Drop it for cross-model to avoid API errors.\n\t\t\t\t\tif (block.redacted) {\n\t\t\t\t\t\treturn isSameModel ? block : [];\n\t\t\t\t\t}\n\t\t\t\t\t// For same model: keep thinking blocks with signatures (needed for replay)\n\t\t\t\t\t// even if the thinking text is empty (OpenAI encrypted reasoning)\n\t\t\t\t\tif (isSameModel && block.thinkingSignature) return block;\n\t\t\t\t\t// Skip empty thinking blocks, convert others to plain text\n\t\t\t\t\tif (!block.thinking || block.thinking.trim() === \"\") return [];\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.thinking,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (isSameModel) return block;\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: block.text,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tif (block.type === \"toolCall\") {\n\t\t\t\t\tconst toolCall = block as ToolCall;\n\t\t\t\t\tlet normalizedToolCall: ToolCall = toolCall;\n\n\t\t\t\t\tif (!isSameModel && toolCall.thoughtSignature) {\n\t\t\t\t\t\tnormalizedToolCall = { ...toolCall };\n\t\t\t\t\t\tdelete (normalizedToolCall as { thoughtSignature?: string }).thoughtSignature;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!isSameModel && normalizeToolCallId) {\n\t\t\t\t\t\tconst normalizedId = normalizeToolCallId(toolCall.id, model, assistantMsg);\n\t\t\t\t\t\tif (normalizedId !== toolCall.id) {\n\t\t\t\t\t\t\ttoolCallIdMap.set(toolCall.id, normalizedId);\n\t\t\t\t\t\t\tnormalizedToolCall = { ...normalizedToolCall, id: normalizedId };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn normalizedToolCall;\n\t\t\t\t}\n\n\t\t\t\treturn block;\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\t...assistantMsg,\n\t\t\t\tcontent: transformedContent,\n\t\t\t};\n\t\t}\n\t\treturn msg;\n\t});\n\n\t// Second pass: insert synthetic empty tool results for orphaned tool calls\n\t// This preserves thinking signatures and satisfies API requirements\n\tconst result: Message[] = [];\n\tlet pendingToolCalls: ToolCall[] = [];\n\tlet existingToolResultIds = new Set<string>();\n\tconst insertSyntheticToolResults = () => {\n\t\tif (pendingToolCalls.length > 0) {\n\t\t\tfor (const tc of pendingToolCalls) {\n\t\t\t\tif (!existingToolResultIds.has(tc.id)) {\n\t\t\t\t\tresult.push({\n\t\t\t\t\t\trole: \"toolResult\",\n\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\ttoolName: tc.name,\n\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No result provided\" }],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t} as ToolResultMessage);\n\t\t\t\t}\n\t\t\t}\n\t\t\tpendingToolCalls = [];\n\t\t\texistingToolResultIds = new Set();\n\t\t}\n\t};\n\n\tfor (let i = 0; i < transformed.length; i++) {\n\t\tconst msg = transformed[i];\n\n\t\tif (msg.role === \"assistant\") {\n\t\t\t// If we have pending orphaned tool calls from a previous assistant, insert synthetic results now\n\t\t\tinsertSyntheticToolResults();\n\n\t\t\t// Skip errored/aborted assistant messages entirely.\n\t\t\t// These are incomplete turns that shouldn't be replayed:\n\t\t\t// - May have partial content (reasoning without message, incomplete tool calls)\n\t\t\t// - Replaying them can cause API errors (e.g., OpenAI \"reasoning without following item\")\n\t\t\t// - The model should retry from the last valid state\n\t\t\tconst assistantMsg = msg as AssistantMessage;\n\t\t\tif (assistantMsg.stopReason === \"error\" || assistantMsg.stopReason === \"aborted\") {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Track tool calls from this assistant message\n\t\t\tconst toolCalls = assistantMsg.content.filter((b) => b.type === \"toolCall\") as ToolCall[];\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tpendingToolCalls = toolCalls;\n\t\t\t\texistingToolResultIds = new Set();\n\t\t\t}\n\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\texistingToolResultIds.add(msg.toolCallId);\n\t\t\tresult.push(msg);\n\t\t} else if (msg.role === \"user\") {\n\t\t\t// User message interrupts tool flow - insert synthetic results for orphaned calls\n\t\t\tinsertSyntheticToolResults();\n\t\t\tresult.push(msg);\n\t\t} else {\n\t\t\tresult.push(msg);\n\t\t}\n\t}\n\n\t// If the conversation ends with unresolved tool calls, synthesize results now.\n\tinsertSyntheticToolResults();\n\n\treturn result;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { AuthContext } from "./types.ts";
2
+ /**
3
+ * Default auth context: env vars from `process.env` (undefined in browsers),
4
+ * file existence via node:fs (always false in browsers).
5
+ */
6
+ export declare function defaultProviderAuthContext(): AuthContext;
7
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/auth/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAkB9C;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,WAAW,CAsBxD","sourcesContent":["import type { AuthContext } from \"./types.ts\";\n\ninterface NodeFsModule {\n\taccess(path: string): Promise<void>;\n}\n\ninterface NodeOsModule {\n\thomedir(): string;\n}\n\n// Variable specifier so browser bundlers do not try to resolve node builtins.\nconst importNodeModule = (specifier: string): Promise<unknown> => import(specifier);\n\nfunction getProcessEnv(): Record<string, string | undefined> | undefined {\n\tconst proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n\treturn proc?.env;\n}\n\n/**\n * Default auth context: env vars from `process.env` (undefined in browsers),\n * file existence via node:fs (always false in browsers).\n */\nexport function defaultProviderAuthContext(): AuthContext {\n\treturn {\n\t\tasync env(name: string): Promise<string | undefined> {\n\t\t\tconst value = getProcessEnv()?.[name];\n\t\t\treturn typeof value === \"string\" && value.trim().length > 0 ? value : undefined;\n\t\t},\n\n\t\tasync fileExists(path: string): Promise<boolean> {\n\t\t\ttry {\n\t\t\t\tconst fs = (await importNodeModule(\"node:fs/promises\")) as NodeFsModule;\n\t\t\t\tlet resolved = path;\n\t\t\t\tif (resolved.startsWith(\"~\")) {\n\t\t\t\t\tconst os = (await importNodeModule(\"node:os\")) as NodeOsModule;\n\t\t\t\t\tresolved = os.homedir() + resolved.slice(1);\n\t\t\t\t}\n\t\t\t\tawait fs.access(resolved);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,42 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ // Variable specifier so browser bundlers do not try to resolve node builtins.
10
+ const importNodeModule = (specifier) => import(__rewriteRelativeImportExtension(specifier));
11
+ function getProcessEnv() {
12
+ const proc = globalThis.process;
13
+ return proc?.env;
14
+ }
15
+ /**
16
+ * Default auth context: env vars from `process.env` (undefined in browsers),
17
+ * file existence via node:fs (always false in browsers).
18
+ */
19
+ export function defaultProviderAuthContext() {
20
+ return {
21
+ async env(name) {
22
+ const value = getProcessEnv()?.[name];
23
+ return typeof value === "string" && value.trim().length > 0 ? value : undefined;
24
+ },
25
+ async fileExists(path) {
26
+ try {
27
+ const fs = (await importNodeModule("node:fs/promises"));
28
+ let resolved = path;
29
+ if (resolved.startsWith("~")) {
30
+ const os = (await importNodeModule("node:os"));
31
+ resolved = os.homedir() + resolved.slice(1);
32
+ }
33
+ await fs.access(resolved);
34
+ return true;
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ },
40
+ };
41
+ }
42
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/auth/context.ts"],"names":[],"mappings":";;;;;;;;AAUA,8EAA8E;AAC9E,MAAM,gBAAgB,GAAG,CAAC,SAAiB,EAAoB,EAAE,CAAC,MAAM,kCAAC,SAAS,EAAC,CAAC;AAEpF,SAAS,aAAa,GAAmD;IACxE,MAAM,IAAI,GAAI,UAAyE,CAAC,OAAO,CAAC;IAChG,OAAO,IAAI,EAAE,GAAG,CAAC;AAAA,CACjB;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B,GAAgB;IACzD,OAAO;QACN,KAAK,CAAC,GAAG,CAAC,IAAY,EAA+B;YACpD,MAAM,KAAK,GAAG,aAAa,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;YACtC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QAAA,CAChF;QAED,KAAK,CAAC,UAAU,CAAC,IAAY,EAAoB;YAChD,IAAI,CAAC;gBACJ,MAAM,EAAE,GAAG,CAAC,MAAM,gBAAgB,CAAC,kBAAkB,CAAC,CAAiB,CAAC;gBACxE,IAAI,QAAQ,GAAG,IAAI,CAAC;gBACpB,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC9B,MAAM,EAAE,GAAG,CAAC,MAAM,gBAAgB,CAAC,SAAS,CAAC,CAAiB,CAAC;oBAC/D,QAAQ,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC7C,CAAC;gBACD,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC1B,OAAO,IAAI,CAAC;YACb,CAAC;YAAC,MAAM,CAAC;gBACR,OAAO,KAAK,CAAC;YACd,CAAC;QAAA,CACD;KACD,CAAC;AAAA,CACF","sourcesContent":["import type { AuthContext } from \"./types.ts\";\n\ninterface NodeFsModule {\n\taccess(path: string): Promise<void>;\n}\n\ninterface NodeOsModule {\n\thomedir(): string;\n}\n\n// Variable specifier so browser bundlers do not try to resolve node builtins.\nconst importNodeModule = (specifier: string): Promise<unknown> => import(specifier);\n\nfunction getProcessEnv(): Record<string, string | undefined> | undefined {\n\tconst proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n\treturn proc?.env;\n}\n\n/**\n * Default auth context: env vars from `process.env` (undefined in browsers),\n * file existence via node:fs (always false in browsers).\n */\nexport function defaultProviderAuthContext(): AuthContext {\n\treturn {\n\t\tasync env(name: string): Promise<string | undefined> {\n\t\t\tconst value = getProcessEnv()?.[name];\n\t\t\treturn typeof value === \"string\" && value.trim().length > 0 ? value : undefined;\n\t\t},\n\n\t\tasync fileExists(path: string): Promise<boolean> {\n\t\t\ttry {\n\t\t\t\tconst fs = (await importNodeModule(\"node:fs/promises\")) as NodeFsModule;\n\t\t\t\tlet resolved = path;\n\t\t\t\tif (resolved.startsWith(\"~\")) {\n\t\t\t\t\tconst os = (await importNodeModule(\"node:os\")) as NodeOsModule;\n\t\t\t\t\tresolved = os.homedir() + resolved.slice(1);\n\t\t\t\t}\n\t\t\t\tawait fs.access(resolved);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,16 @@
1
+ import type { Credential, CredentialStore } from "./types.ts";
2
+ /**
3
+ * Default in-memory credential store. Apps inject persistent stores.
4
+ * Keyed by `Provider.id`, one credential per provider; see `CredentialStore`.
5
+ * Writes are serialized per provider through a promise chain.
6
+ */
7
+ export declare class InMemoryCredentialStore implements CredentialStore {
8
+ private credentials;
9
+ private chains;
10
+ /** Serialize tasks per provider id. */
11
+ private enqueue;
12
+ read(providerId: string): Promise<Credential | undefined>;
13
+ modify(providerId: string, fn: (current: Credential | undefined) => Promise<Credential | undefined>): Promise<Credential | undefined>;
14
+ delete(providerId: string): Promise<void>;
15
+ }
16
+ //# sourceMappingURL=credential-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-store.d.ts","sourceRoot":"","sources":["../../src/auth/credential-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE9D;;;;GAIG;AACH,qBAAa,uBAAwB,YAAW,eAAe;IAC9D,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,MAAM,CAAuC;IAErD,uCAAuC;IACvC,OAAO,CAAC,OAAO;IAaT,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAE9D;IAED,MAAM,CACL,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,GACtE,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAOjC;IAED,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxC;CACD","sourcesContent":["import type { Credential, CredentialStore } from \"./types.ts\";\n\n/**\n * Default in-memory credential store. Apps inject persistent stores.\n * Keyed by `Provider.id`, one credential per provider; see `CredentialStore`.\n * Writes are serialized per provider through a promise chain.\n */\nexport class InMemoryCredentialStore implements CredentialStore {\n\tprivate credentials = new Map<string, Credential>();\n\tprivate chains = new Map<string, Promise<unknown>>();\n\n\t/** Serialize tasks per provider id. */\n\tprivate enqueue<T>(providerId: string, task: () => Promise<T>): Promise<T> {\n\t\tconst previous = this.chains.get(providerId) ?? Promise.resolve();\n\t\tconst next = (async () => {\n\t\t\tawait previous.catch(() => {});\n\t\t\treturn task();\n\t\t})();\n\t\tthis.chains.set(\n\t\t\tproviderId,\n\t\t\tnext.catch(() => {}),\n\t\t);\n\t\treturn next;\n\t}\n\n\tasync read(providerId: string): Promise<Credential | undefined> {\n\t\treturn this.credentials.get(providerId);\n\t}\n\n\tmodify(\n\t\tproviderId: string,\n\t\tfn: (current: Credential | undefined) => Promise<Credential | undefined>,\n\t): Promise<Credential | undefined> {\n\t\treturn this.enqueue(providerId, async () => {\n\t\t\tconst current = this.credentials.get(providerId);\n\t\t\tconst next = await fn(current);\n\t\t\tif (next !== undefined) this.credentials.set(providerId, next);\n\t\t\treturn next ?? current;\n\t\t});\n\t}\n\n\tdelete(providerId: string): Promise<void> {\n\t\treturn this.enqueue(providerId, async () => {\n\t\t\tthis.credentials.delete(providerId);\n\t\t});\n\t}\n}\n"]}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Default in-memory credential store. Apps inject persistent stores.
3
+ * Keyed by `Provider.id`, one credential per provider; see `CredentialStore`.
4
+ * Writes are serialized per provider through a promise chain.
5
+ */
6
+ export class InMemoryCredentialStore {
7
+ credentials = new Map();
8
+ chains = new Map();
9
+ /** Serialize tasks per provider id. */
10
+ enqueue(providerId, task) {
11
+ const previous = this.chains.get(providerId) ?? Promise.resolve();
12
+ const next = (async () => {
13
+ await previous.catch(() => { });
14
+ return task();
15
+ })();
16
+ this.chains.set(providerId, next.catch(() => { }));
17
+ return next;
18
+ }
19
+ async read(providerId) {
20
+ return this.credentials.get(providerId);
21
+ }
22
+ modify(providerId, fn) {
23
+ return this.enqueue(providerId, async () => {
24
+ const current = this.credentials.get(providerId);
25
+ const next = await fn(current);
26
+ if (next !== undefined)
27
+ this.credentials.set(providerId, next);
28
+ return next ?? current;
29
+ });
30
+ }
31
+ delete(providerId) {
32
+ return this.enqueue(providerId, async () => {
33
+ this.credentials.delete(providerId);
34
+ });
35
+ }
36
+ }
37
+ //# sourceMappingURL=credential-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-store.js","sourceRoot":"","sources":["../../src/auth/credential-store.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,OAAO,uBAAuB;IAC3B,WAAW,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC5C,MAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;IAErD,uCAAuC;IAC/B,OAAO,CAAI,UAAkB,EAAE,IAAsB,EAAc;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAClE,MAAM,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;YACzB,MAAM,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC,CAAC;YAC/B,OAAO,IAAI,EAAE,CAAC;QAAA,CACd,CAAC,EAAE,CAAC;QACL,IAAI,CAAC,MAAM,CAAC,GAAG,CACd,UAAU,EACV,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC,CACpB,CAAC;QACF,OAAO,IAAI,CAAC;IAAA,CACZ;IAED,KAAK,CAAC,IAAI,CAAC,UAAkB,EAAmC;QAC/D,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAAA,CACxC;IAED,MAAM,CACL,UAAkB,EAClB,EAAwE,EACtC;QAClC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC;YAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACjD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC;YAC/B,IAAI,IAAI,KAAK,SAAS;gBAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;YAC/D,OAAO,IAAI,IAAI,OAAO,CAAC;QAAA,CACvB,CAAC,CAAC;IAAA,CACH;IAED,MAAM,CAAC,UAAkB,EAAiB;QACzC,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC;YAC3C,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAAA,CACpC,CAAC,CAAC;IAAA,CACH;CACD","sourcesContent":["import type { Credential, CredentialStore } from \"./types.ts\";\n\n/**\n * Default in-memory credential store. Apps inject persistent stores.\n * Keyed by `Provider.id`, one credential per provider; see `CredentialStore`.\n * Writes are serialized per provider through a promise chain.\n */\nexport class InMemoryCredentialStore implements CredentialStore {\n\tprivate credentials = new Map<string, Credential>();\n\tprivate chains = new Map<string, Promise<unknown>>();\n\n\t/** Serialize tasks per provider id. */\n\tprivate enqueue<T>(providerId: string, task: () => Promise<T>): Promise<T> {\n\t\tconst previous = this.chains.get(providerId) ?? Promise.resolve();\n\t\tconst next = (async () => {\n\t\t\tawait previous.catch(() => {});\n\t\t\treturn task();\n\t\t})();\n\t\tthis.chains.set(\n\t\t\tproviderId,\n\t\t\tnext.catch(() => {}),\n\t\t);\n\t\treturn next;\n\t}\n\n\tasync read(providerId: string): Promise<Credential | undefined> {\n\t\treturn this.credentials.get(providerId);\n\t}\n\n\tmodify(\n\t\tproviderId: string,\n\t\tfn: (current: Credential | undefined) => Promise<Credential | undefined>,\n\t): Promise<Credential | undefined> {\n\t\treturn this.enqueue(providerId, async () => {\n\t\t\tconst current = this.credentials.get(providerId);\n\t\t\tconst next = await fn(current);\n\t\t\tif (next !== undefined) this.credentials.set(providerId, next);\n\t\t\treturn next ?? current;\n\t\t});\n\t}\n\n\tdelete(providerId: string): Promise<void> {\n\t\treturn this.enqueue(providerId, async () => {\n\t\t\tthis.credentials.delete(providerId);\n\t\t});\n\t}\n}\n"]}
@@ -0,0 +1,20 @@
1
+ import type { ApiKeyAuth, OAuthAuth } from "./types.ts";
2
+ /**
3
+ * Standard api-key auth: a stored credential key wins, otherwise the first
4
+ * set env var resolves. Includes a `login` that prompts for the key.
5
+ * Providers with non-standard resolution (provider env, ambient files, IAM)
6
+ * write their own `ApiKeyAuth`.
7
+ */
8
+ export declare function envApiKeyAuth(name: string, envVars: readonly string[]): ApiKeyAuth;
9
+ /**
10
+ * Wraps a dynamically imported `OAuthAuth` so provider definitions can
11
+ * advertise OAuth without importing the implementation. The flow loads on
12
+ * first `login`/`refresh`/`toAuth` call; callers keep Node-only flow code out
13
+ * of bundles by loading through a bundler-opaque dynamic import (variable
14
+ * specifier, see the bedrock lazy wrapper).
15
+ */
16
+ export declare function lazyOAuth(input: {
17
+ name: string;
18
+ load: () => Promise<OAuthAuth>;
19
+ }): OAuthAuth;
20
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/auth/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAExD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAgBlF;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,CAAA;CAAE,GAAG,SAAS,CAY5F","sourcesContent":["import type { ApiKeyAuth, OAuthAuth } from \"./types.ts\";\n\n/**\n * Standard api-key auth: a stored credential key wins, otherwise the first\n * set env var resolves. Includes a `login` that prompts for the key.\n * Providers with non-standard resolution (provider env, ambient files, IAM)\n * write their own `ApiKeyAuth`.\n */\nexport function envApiKeyAuth(name: string, envVars: readonly string[]): ApiKeyAuth {\n\treturn {\n\t\tname,\n\t\tlogin: async (callbacks) => {\n\t\t\tconst key = await callbacks.prompt({ type: \"secret\", message: `Enter ${name}` });\n\t\t\treturn { type: \"api_key\", key };\n\t\t},\n\t\tresolve: async ({ ctx, credential }) => {\n\t\t\tif (credential?.key) return { auth: { apiKey: credential.key }, source: \"stored credential\" };\n\t\t\tfor (const envVar of envVars) {\n\t\t\t\tconst value = await ctx.env(envVar);\n\t\t\t\tif (value) return { auth: { apiKey: value }, source: envVar };\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n\n/**\n * Wraps a dynamically imported `OAuthAuth` so provider definitions can\n * advertise OAuth without importing the implementation. The flow loads on\n * first `login`/`refresh`/`toAuth` call; callers keep Node-only flow code out\n * of bundles by loading through a bundler-opaque dynamic import (variable\n * specifier, see the bedrock lazy wrapper).\n */\nexport function lazyOAuth(input: { name: string; load: () => Promise<OAuthAuth> }): OAuthAuth {\n\tlet promise: Promise<OAuthAuth> | undefined;\n\tconst loaded = () => {\n\t\tpromise ??= input.load();\n\t\treturn promise;\n\t};\n\treturn {\n\t\tname: input.name,\n\t\tlogin: async (callbacks) => (await loaded()).login(callbacks),\n\t\trefresh: async (credential) => (await loaded()).refresh(credential),\n\t\ttoAuth: async (credential) => (await loaded()).toAuth(credential),\n\t};\n}\n"]}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Standard api-key auth: a stored credential key wins, otherwise the first
3
+ * set env var resolves. Includes a `login` that prompts for the key.
4
+ * Providers with non-standard resolution (provider env, ambient files, IAM)
5
+ * write their own `ApiKeyAuth`.
6
+ */
7
+ export function envApiKeyAuth(name, envVars) {
8
+ return {
9
+ name,
10
+ login: async (callbacks) => {
11
+ const key = await callbacks.prompt({ type: "secret", message: `Enter ${name}` });
12
+ return { type: "api_key", key };
13
+ },
14
+ resolve: async ({ ctx, credential }) => {
15
+ if (credential?.key)
16
+ return { auth: { apiKey: credential.key }, source: "stored credential" };
17
+ for (const envVar of envVars) {
18
+ const value = await ctx.env(envVar);
19
+ if (value)
20
+ return { auth: { apiKey: value }, source: envVar };
21
+ }
22
+ return undefined;
23
+ },
24
+ };
25
+ }
26
+ /**
27
+ * Wraps a dynamically imported `OAuthAuth` so provider definitions can
28
+ * advertise OAuth without importing the implementation. The flow loads on
29
+ * first `login`/`refresh`/`toAuth` call; callers keep Node-only flow code out
30
+ * of bundles by loading through a bundler-opaque dynamic import (variable
31
+ * specifier, see the bedrock lazy wrapper).
32
+ */
33
+ export function lazyOAuth(input) {
34
+ let promise;
35
+ const loaded = () => {
36
+ promise ??= input.load();
37
+ return promise;
38
+ };
39
+ return {
40
+ name: input.name,
41
+ login: async (callbacks) => (await loaded()).login(callbacks),
42
+ refresh: async (credential) => (await loaded()).refresh(credential),
43
+ toAuth: async (credential) => (await loaded()).toAuth(credential),
44
+ };
45
+ }
46
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/auth/helpers.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAA0B,EAAc;IACnF,OAAO;QACN,IAAI;QACJ,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,IAAI,EAAE,EAAE,CAAC,CAAC;YACjF,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;QAAA,CAChC;QACD,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;YACvC,IAAI,UAAU,EAAE,GAAG;gBAAE,OAAO,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;YAC9F,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC9B,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACpC,IAAI,KAAK;oBAAE,OAAO,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;YAC/D,CAAC;YACD,OAAO,SAAS,CAAC;QAAA,CACjB;KACD,CAAC;AAAA,CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,KAAuD,EAAa;IAC7F,IAAI,OAAuC,CAAC;IAC5C,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC;QACpB,OAAO,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC;IAAA,CACf,CAAC;IACF,OAAO;QACN,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;QAC7D,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;QACnE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;KACjE,CAAC;AAAA,CACF","sourcesContent":["import type { ApiKeyAuth, OAuthAuth } from \"./types.ts\";\n\n/**\n * Standard api-key auth: a stored credential key wins, otherwise the first\n * set env var resolves. Includes a `login` that prompts for the key.\n * Providers with non-standard resolution (provider env, ambient files, IAM)\n * write their own `ApiKeyAuth`.\n */\nexport function envApiKeyAuth(name: string, envVars: readonly string[]): ApiKeyAuth {\n\treturn {\n\t\tname,\n\t\tlogin: async (callbacks) => {\n\t\t\tconst key = await callbacks.prompt({ type: \"secret\", message: `Enter ${name}` });\n\t\t\treturn { type: \"api_key\", key };\n\t\t},\n\t\tresolve: async ({ ctx, credential }) => {\n\t\t\tif (credential?.key) return { auth: { apiKey: credential.key }, source: \"stored credential\" };\n\t\t\tfor (const envVar of envVars) {\n\t\t\t\tconst value = await ctx.env(envVar);\n\t\t\t\tif (value) return { auth: { apiKey: value }, source: envVar };\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\t};\n}\n\n/**\n * Wraps a dynamically imported `OAuthAuth` so provider definitions can\n * advertise OAuth without importing the implementation. The flow loads on\n * first `login`/`refresh`/`toAuth` call; callers keep Node-only flow code out\n * of bundles by loading through a bundler-opaque dynamic import (variable\n * specifier, see the bedrock lazy wrapper).\n */\nexport function lazyOAuth(input: { name: string; load: () => Promise<OAuthAuth> }): OAuthAuth {\n\tlet promise: Promise<OAuthAuth> | undefined;\n\tconst loaded = () => {\n\t\tpromise ??= input.load();\n\t\treturn promise;\n\t};\n\treturn {\n\t\tname: input.name,\n\t\tlogin: async (callbacks) => (await loaded()).login(callbacks),\n\t\trefresh: async (credential) => (await loaded()).refresh(credential),\n\t\ttoAuth: async (credential) => (await loaded()).toAuth(credential),\n\t};\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import type { Api, ImagesApi, ImagesModel, Model, ProviderEnv } from "../types.ts";
2
+ import type { AuthContext, AuthResult, CredentialStore, ProviderAuth } from "./types.ts";
3
+ export type ModelsErrorCode = "model_source" | "model_validation" | "provider" | "stream" | "auth" | "oauth";
4
+ export interface AuthResolutionOverrides {
5
+ apiKey?: string;
6
+ env?: ProviderEnv;
7
+ }
8
+ export declare class ModelsError extends Error {
9
+ readonly code: ModelsErrorCode;
10
+ constructor(code: ModelsErrorCode, message: string, options?: {
11
+ cause?: unknown;
12
+ });
13
+ }
14
+ /** Model shape auth resolution receives: chat or image-generation models. */
15
+ export type AuthModel = Model<Api> | ImagesModel<ImagesApi>;
16
+ /**
17
+ * Auth resolution shared by the `Models` and `ImagesModels` collections.
18
+ * A stored credential owns the provider: ambient/env is consulted only when
19
+ * nothing is stored. No silent env fallback after a failed refresh or for a
20
+ * credential type without a matching handler.
21
+ */
22
+ export declare function resolveProviderAuth(provider: {
23
+ id: string;
24
+ auth: ProviderAuth;
25
+ }, model: AuthModel, credentials: CredentialStore, authContext: AuthContext, overrides?: AuthResolutionOverrides): Promise<AuthResult | undefined>;
26
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/auth/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,KAAK,EAGX,WAAW,EACX,UAAU,EAEV,eAAe,EAGf,YAAY,EACZ,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,kBAAkB,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAE7G,MAAM,WAAW,uBAAuB;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,WAAW,CAAC;CAClB;AAED,qBAAa,WAAY,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAE/B,YAAY,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAIhF;CACD;AAED,6EAA6E;AAC7E,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;AAE5D;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACxC,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,EAC5C,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,eAAe,EAC5B,WAAW,EAAE,WAAW,EACxB,SAAS,CAAC,EAAE,uBAAuB,GACjC,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAyBjC","sourcesContent":["import type { Api, ImagesApi, ImagesModel, Model, ProviderEnv } from \"../types.ts\";\nimport type {\n\tApiKeyAuth,\n\tApiKeyCredential,\n\tAuthContext,\n\tAuthResult,\n\tCredential,\n\tCredentialStore,\n\tOAuthAuth,\n\tOAuthCredential,\n\tProviderAuth,\n} from \"./types.ts\";\n\nexport type ModelsErrorCode = \"model_source\" | \"model_validation\" | \"provider\" | \"stream\" | \"auth\" | \"oauth\";\n\nexport interface AuthResolutionOverrides {\n\tapiKey?: string;\n\tenv?: ProviderEnv;\n}\n\nexport class ModelsError extends Error {\n\treadonly code: ModelsErrorCode;\n\n\tconstructor(code: ModelsErrorCode, message: string, options?: { cause?: unknown }) {\n\t\tsuper(message, options);\n\t\tthis.name = \"ModelsError\";\n\t\tthis.code = code;\n\t}\n}\n\n/** Model shape auth resolution receives: chat or image-generation models. */\nexport type AuthModel = Model<Api> | ImagesModel<ImagesApi>;\n\n/**\n * Auth resolution shared by the `Models` and `ImagesModels` collections.\n * A stored credential owns the provider: ambient/env is consulted only when\n * nothing is stored. No silent env fallback after a failed refresh or for a\n * credential type without a matching handler.\n */\nexport async function resolveProviderAuth(\n\tprovider: { id: string; auth: ProviderAuth },\n\tmodel: AuthModel,\n\tcredentials: CredentialStore,\n\tauthContext: AuthContext,\n\toverrides?: AuthResolutionOverrides,\n): Promise<AuthResult | undefined> {\n\tconst requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;\n\n\tif (overrides?.apiKey !== undefined && provider.auth.apiKey) {\n\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, model, {\n\t\t\ttype: \"api_key\",\n\t\t\tkey: overrides.apiKey,\n\t\t\tenv: overrides.env,\n\t\t});\n\t}\n\n\tconst stored = await readCredential(credentials, provider.id);\n\tif (stored) {\n\t\tif (stored.type === \"oauth\" && provider.auth.oauth) {\n\t\t\treturn resolveStoredOAuth(credentials, provider.id, provider.auth.oauth, stored);\n\t\t}\n\t\tif (stored.type === \"api_key\" && provider.auth.apiKey) {\n\t\t\tconst credential = overrides?.env ? { ...stored, env: { ...stored.env, ...overrides.env } } : stored;\n\t\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, model, credential);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t// Ambient (env vars, AWS profiles, ADC files).\n\treturn provider.auth.apiKey ? resolveApiKey(requestAuthContext, provider.auth.apiKey, model, undefined) : undefined;\n}\n\nfunction overlayEnvAuthContext(base: AuthContext, env: ProviderEnv): AuthContext {\n\treturn {\n\t\tenv: async (name) => env[name] || (await base.env(name)),\n\t\tfileExists: (path) => base.fileExists(path),\n\t};\n}\n\n/**\n * OAuth resolution with double-checked locking (same pattern as today's\n * AuthStorage): valid tokens cost zero locks; expired tokens lock, re-check\n * expiry under the lock, refresh once globally, and persist the rotated\n * credential before release.\n */\nasync function resolveStoredOAuth(\n\tcredentials: CredentialStore,\n\tproviderId: string,\n\toauth: OAuthAuth,\n\tstored: OAuthCredential,\n): Promise<AuthResult | undefined> {\n\tlet credential = stored;\n\n\tif (Date.now() >= credential.expires) {\n\t\t// Optimistic check said expired; the authoritative check runs under the lock.\n\t\tlet post: Credential | undefined;\n\t\ttry {\n\t\t\tpost = await credentials.modify(providerId, async (current) => {\n\t\t\t\tif (current?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\t\t\tif (Date.now() < current.expires) return undefined; // another process/request refreshed\n\t\t\t\ttry {\n\t\t\t\t\treturn await oauth.refresh(current);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new ModelsError(\"oauth\", `OAuth refresh failed for ${providerId}`, { cause: error });\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error instanceof ModelsError) throw error;\n\t\t\tthrow new ModelsError(\"auth\", `Credential store modify failed for ${providerId}`, { cause: error });\n\t\t}\n\t\tif (post?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\tcredential = post;\n\t}\n\n\ttry {\n\t\treturn { auth: await oauth.toAuth(credential), source: \"OAuth\" };\n\t} catch (error) {\n\t\tthrow new ModelsError(\"oauth\", `OAuth auth derivation failed for ${providerId}`, { cause: error });\n\t}\n}\n\nasync function resolveApiKey(\n\tauthContext: AuthContext,\n\tapiKey: ApiKeyAuth,\n\tmodel: AuthModel,\n\tcredential: ApiKeyCredential | undefined,\n): Promise<AuthResult | undefined> {\n\ttry {\n\t\treturn await apiKey.resolve({ model, ctx: authContext, credential });\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `API key auth failed for provider ${model.provider}`, { cause: error });\n\t}\n}\n\nasync function readCredential(credentials: CredentialStore, providerId: string): Promise<Credential | undefined> {\n\ttry {\n\t\treturn await credentials.read(providerId);\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `Credential store read failed for ${providerId}`, { cause: error });\n\t}\n}\n"]}
@@ -0,0 +1,101 @@
1
+ export class ModelsError extends Error {
2
+ code;
3
+ constructor(code, message, options) {
4
+ super(message, options);
5
+ this.name = "ModelsError";
6
+ this.code = code;
7
+ }
8
+ }
9
+ /**
10
+ * Auth resolution shared by the `Models` and `ImagesModels` collections.
11
+ * A stored credential owns the provider: ambient/env is consulted only when
12
+ * nothing is stored. No silent env fallback after a failed refresh or for a
13
+ * credential type without a matching handler.
14
+ */
15
+ export async function resolveProviderAuth(provider, model, credentials, authContext, overrides) {
16
+ const requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;
17
+ if (overrides?.apiKey !== undefined && provider.auth.apiKey) {
18
+ return resolveApiKey(requestAuthContext, provider.auth.apiKey, model, {
19
+ type: "api_key",
20
+ key: overrides.apiKey,
21
+ env: overrides.env,
22
+ });
23
+ }
24
+ const stored = await readCredential(credentials, provider.id);
25
+ if (stored) {
26
+ if (stored.type === "oauth" && provider.auth.oauth) {
27
+ return resolveStoredOAuth(credentials, provider.id, provider.auth.oauth, stored);
28
+ }
29
+ if (stored.type === "api_key" && provider.auth.apiKey) {
30
+ const credential = overrides?.env ? { ...stored, env: { ...stored.env, ...overrides.env } } : stored;
31
+ return resolveApiKey(requestAuthContext, provider.auth.apiKey, model, credential);
32
+ }
33
+ return undefined;
34
+ }
35
+ // Ambient (env vars, AWS profiles, ADC files).
36
+ return provider.auth.apiKey ? resolveApiKey(requestAuthContext, provider.auth.apiKey, model, undefined) : undefined;
37
+ }
38
+ function overlayEnvAuthContext(base, env) {
39
+ return {
40
+ env: async (name) => env[name] || (await base.env(name)),
41
+ fileExists: (path) => base.fileExists(path),
42
+ };
43
+ }
44
+ /**
45
+ * OAuth resolution with double-checked locking (same pattern as today's
46
+ * AuthStorage): valid tokens cost zero locks; expired tokens lock, re-check
47
+ * expiry under the lock, refresh once globally, and persist the rotated
48
+ * credential before release.
49
+ */
50
+ async function resolveStoredOAuth(credentials, providerId, oauth, stored) {
51
+ let credential = stored;
52
+ if (Date.now() >= credential.expires) {
53
+ // Optimistic check said expired; the authoritative check runs under the lock.
54
+ let post;
55
+ try {
56
+ post = await credentials.modify(providerId, async (current) => {
57
+ if (current?.type !== "oauth")
58
+ return undefined; // logged out meanwhile
59
+ if (Date.now() < current.expires)
60
+ return undefined; // another process/request refreshed
61
+ try {
62
+ return await oauth.refresh(current);
63
+ }
64
+ catch (error) {
65
+ throw new ModelsError("oauth", `OAuth refresh failed for ${providerId}`, { cause: error });
66
+ }
67
+ });
68
+ }
69
+ catch (error) {
70
+ if (error instanceof ModelsError)
71
+ throw error;
72
+ throw new ModelsError("auth", `Credential store modify failed for ${providerId}`, { cause: error });
73
+ }
74
+ if (post?.type !== "oauth")
75
+ return undefined; // logged out meanwhile
76
+ credential = post;
77
+ }
78
+ try {
79
+ return { auth: await oauth.toAuth(credential), source: "OAuth" };
80
+ }
81
+ catch (error) {
82
+ throw new ModelsError("oauth", `OAuth auth derivation failed for ${providerId}`, { cause: error });
83
+ }
84
+ }
85
+ async function resolveApiKey(authContext, apiKey, model, credential) {
86
+ try {
87
+ return await apiKey.resolve({ model, ctx: authContext, credential });
88
+ }
89
+ catch (error) {
90
+ throw new ModelsError("auth", `API key auth failed for provider ${model.provider}`, { cause: error });
91
+ }
92
+ }
93
+ async function readCredential(credentials, providerId) {
94
+ try {
95
+ return await credentials.read(providerId);
96
+ }
97
+ catch (error) {
98
+ throw new ModelsError("auth", `Credential store read failed for ${providerId}`, { cause: error });
99
+ }
100
+ }
101
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/auth/resolve.ts"],"names":[],"mappings":"AAoBA,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC5B,IAAI,CAAkB;IAE/B,YAAY,IAAqB,EAAE,OAAe,EAAE,OAA6B,EAAE;QAClF,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAAA,CACjB;CACD;AAKD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,QAA4C,EAC5C,KAAgB,EAChB,WAA4B,EAC5B,WAAwB,EACxB,SAAmC,EACD;IAClC,MAAM,kBAAkB,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;IAE5G,IAAI,SAAS,EAAE,MAAM,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7D,OAAO,aAAa,CAAC,kBAAkB,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE;YACrE,IAAI,EAAE,SAAS;YACf,GAAG,EAAE,SAAS,CAAC,MAAM;YACrB,GAAG,EAAE,SAAS,CAAC,GAAG;SAClB,CAAC,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC9D,IAAI,MAAM,EAAE,CAAC;QACZ,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACpD,OAAO,kBAAkB,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACvD,MAAM,UAAU,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;YACrG,OAAO,aAAa,CAAC,kBAAkB,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QACnF,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,+CAA+C;IAC/C,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,kBAAkB,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CACpH;AAED,SAAS,qBAAqB,CAAC,IAAiB,EAAE,GAAgB,EAAe;IAChF,OAAO;QACN,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxD,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;KAC3C,CAAC;AAAA,CACF;AAED;;;;;GAKG;AACH,KAAK,UAAU,kBAAkB,CAChC,WAA4B,EAC5B,UAAkB,EAClB,KAAgB,EAChB,MAAuB,EACW;IAClC,IAAI,UAAU,GAAG,MAAM,CAAC;IAExB,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACtC,8EAA8E;QAC9E,IAAI,IAA4B,CAAC;QACjC,IAAI,CAAC;YACJ,IAAI,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC;gBAC9D,IAAI,OAAO,EAAE,IAAI,KAAK,OAAO;oBAAE,OAAO,SAAS,CAAC,CAAC,uBAAuB;gBACxE,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO;oBAAE,OAAO,SAAS,CAAC,CAAC,oCAAoC;gBACxF,IAAI,CAAC;oBACJ,OAAO,MAAM,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACrC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE,4BAA4B,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC5F,CAAC;YAAA,CACD,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,KAAK,YAAY,WAAW;gBAAE,MAAM,KAAK,CAAC;YAC9C,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,sCAAsC,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACrG,CAAC;QACD,IAAI,IAAI,EAAE,IAAI,KAAK,OAAO;YAAE,OAAO,SAAS,CAAC,CAAC,uBAAuB;QACrE,UAAU,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,IAAI,CAAC;QACJ,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAClE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE,oCAAoC,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACpG,CAAC;AAAA,CACD;AAED,KAAK,UAAU,aAAa,CAC3B,WAAwB,EACxB,MAAkB,EAClB,KAAgB,EAChB,UAAwC,EACN;IAClC,IAAI,CAAC;QACJ,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;IACtE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,oCAAoC,KAAK,CAAC,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACvG,CAAC;AAAA,CACD;AAED,KAAK,UAAU,cAAc,CAAC,WAA4B,EAAE,UAAkB,EAAmC;IAChH,IAAI,CAAC;QACJ,OAAO,MAAM,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,oCAAoC,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACnG,CAAC;AAAA,CACD","sourcesContent":["import type { Api, ImagesApi, ImagesModel, Model, ProviderEnv } from \"../types.ts\";\nimport type {\n\tApiKeyAuth,\n\tApiKeyCredential,\n\tAuthContext,\n\tAuthResult,\n\tCredential,\n\tCredentialStore,\n\tOAuthAuth,\n\tOAuthCredential,\n\tProviderAuth,\n} from \"./types.ts\";\n\nexport type ModelsErrorCode = \"model_source\" | \"model_validation\" | \"provider\" | \"stream\" | \"auth\" | \"oauth\";\n\nexport interface AuthResolutionOverrides {\n\tapiKey?: string;\n\tenv?: ProviderEnv;\n}\n\nexport class ModelsError extends Error {\n\treadonly code: ModelsErrorCode;\n\n\tconstructor(code: ModelsErrorCode, message: string, options?: { cause?: unknown }) {\n\t\tsuper(message, options);\n\t\tthis.name = \"ModelsError\";\n\t\tthis.code = code;\n\t}\n}\n\n/** Model shape auth resolution receives: chat or image-generation models. */\nexport type AuthModel = Model<Api> | ImagesModel<ImagesApi>;\n\n/**\n * Auth resolution shared by the `Models` and `ImagesModels` collections.\n * A stored credential owns the provider: ambient/env is consulted only when\n * nothing is stored. No silent env fallback after a failed refresh or for a\n * credential type without a matching handler.\n */\nexport async function resolveProviderAuth(\n\tprovider: { id: string; auth: ProviderAuth },\n\tmodel: AuthModel,\n\tcredentials: CredentialStore,\n\tauthContext: AuthContext,\n\toverrides?: AuthResolutionOverrides,\n): Promise<AuthResult | undefined> {\n\tconst requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;\n\n\tif (overrides?.apiKey !== undefined && provider.auth.apiKey) {\n\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, model, {\n\t\t\ttype: \"api_key\",\n\t\t\tkey: overrides.apiKey,\n\t\t\tenv: overrides.env,\n\t\t});\n\t}\n\n\tconst stored = await readCredential(credentials, provider.id);\n\tif (stored) {\n\t\tif (stored.type === \"oauth\" && provider.auth.oauth) {\n\t\t\treturn resolveStoredOAuth(credentials, provider.id, provider.auth.oauth, stored);\n\t\t}\n\t\tif (stored.type === \"api_key\" && provider.auth.apiKey) {\n\t\t\tconst credential = overrides?.env ? { ...stored, env: { ...stored.env, ...overrides.env } } : stored;\n\t\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, model, credential);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t// Ambient (env vars, AWS profiles, ADC files).\n\treturn provider.auth.apiKey ? resolveApiKey(requestAuthContext, provider.auth.apiKey, model, undefined) : undefined;\n}\n\nfunction overlayEnvAuthContext(base: AuthContext, env: ProviderEnv): AuthContext {\n\treturn {\n\t\tenv: async (name) => env[name] || (await base.env(name)),\n\t\tfileExists: (path) => base.fileExists(path),\n\t};\n}\n\n/**\n * OAuth resolution with double-checked locking (same pattern as today's\n * AuthStorage): valid tokens cost zero locks; expired tokens lock, re-check\n * expiry under the lock, refresh once globally, and persist the rotated\n * credential before release.\n */\nasync function resolveStoredOAuth(\n\tcredentials: CredentialStore,\n\tproviderId: string,\n\toauth: OAuthAuth,\n\tstored: OAuthCredential,\n): Promise<AuthResult | undefined> {\n\tlet credential = stored;\n\n\tif (Date.now() >= credential.expires) {\n\t\t// Optimistic check said expired; the authoritative check runs under the lock.\n\t\tlet post: Credential | undefined;\n\t\ttry {\n\t\t\tpost = await credentials.modify(providerId, async (current) => {\n\t\t\t\tif (current?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\t\t\tif (Date.now() < current.expires) return undefined; // another process/request refreshed\n\t\t\t\ttry {\n\t\t\t\t\treturn await oauth.refresh(current);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new ModelsError(\"oauth\", `OAuth refresh failed for ${providerId}`, { cause: error });\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error instanceof ModelsError) throw error;\n\t\t\tthrow new ModelsError(\"auth\", `Credential store modify failed for ${providerId}`, { cause: error });\n\t\t}\n\t\tif (post?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\tcredential = post;\n\t}\n\n\ttry {\n\t\treturn { auth: await oauth.toAuth(credential), source: \"OAuth\" };\n\t} catch (error) {\n\t\tthrow new ModelsError(\"oauth\", `OAuth auth derivation failed for ${providerId}`, { cause: error });\n\t}\n}\n\nasync function resolveApiKey(\n\tauthContext: AuthContext,\n\tapiKey: ApiKeyAuth,\n\tmodel: AuthModel,\n\tcredential: ApiKeyCredential | undefined,\n): Promise<AuthResult | undefined> {\n\ttry {\n\t\treturn await apiKey.resolve({ model, ctx: authContext, credential });\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `API key auth failed for provider ${model.provider}`, { cause: error });\n\t}\n}\n\nasync function readCredential(credentials: CredentialStore, providerId: string): Promise<Credential | undefined> {\n\ttry {\n\t\treturn await credentials.read(providerId);\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `Credential store read failed for ${providerId}`, { cause: error });\n\t}\n}\n"]}