@bastani/pi-ai 0.9.20-alpha.1 → 0.9.20-alpha.11

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 (445) hide show
  1. package/CHANGELOG.md +83 -1
  2. package/NOTICE.md +1 -1
  3. package/README.md +203 -30
  4. package/dist/api/anthropic-messages.d.ts.map +1 -1
  5. package/dist/api/anthropic-messages.js +255 -97
  6. package/dist/api/anthropic-messages.js.map +1 -1
  7. package/dist/api/azure-openai-responses.d.ts.map +1 -1
  8. package/dist/api/azure-openai-responses.js +21 -6
  9. package/dist/api/azure-openai-responses.js.map +1 -1
  10. package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  11. package/dist/api/bedrock-converse-stream.js +20 -15
  12. package/dist/api/bedrock-converse-stream.js.map +1 -1
  13. package/dist/api/cloudflare-workers-ai-system-one.d.ts +4 -0
  14. package/dist/api/cloudflare-workers-ai-system-one.d.ts.map +1 -0
  15. package/dist/api/cloudflare-workers-ai-system-one.js +43 -0
  16. package/dist/api/cloudflare-workers-ai-system-one.js.map +1 -0
  17. package/dist/api/cloudflare-workers-ai-system-one.lazy.d.ts +3 -0
  18. package/dist/api/cloudflare-workers-ai-system-one.lazy.d.ts.map +1 -0
  19. package/dist/api/cloudflare-workers-ai-system-one.lazy.js +4 -0
  20. package/dist/api/cloudflare-workers-ai-system-one.lazy.js.map +1 -0
  21. package/dist/api/cloudflare.d.ts +2 -0
  22. package/dist/api/cloudflare.d.ts.map +1 -1
  23. package/dist/api/cloudflare.js +2 -0
  24. package/dist/api/cloudflare.js.map +1 -1
  25. package/dist/api/constrained-sampling.d.ts +8 -3
  26. package/dist/api/constrained-sampling.d.ts.map +1 -1
  27. package/dist/api/constrained-sampling.js +29 -11
  28. package/dist/api/constrained-sampling.js.map +1 -1
  29. package/dist/api/google-generative-ai.d.ts.map +1 -1
  30. package/dist/api/google-generative-ai.js +23 -80
  31. package/dist/api/google-generative-ai.js.map +1 -1
  32. package/dist/api/google-shared.d.ts +13 -4
  33. package/dist/api/google-shared.d.ts.map +1 -1
  34. package/dist/api/google-shared.js +54 -4
  35. package/dist/api/google-shared.js.map +1 -1
  36. package/dist/api/google-vertex.d.ts.map +1 -1
  37. package/dist/api/google-vertex.js +26 -65
  38. package/dist/api/google-vertex.js.map +1 -1
  39. package/dist/api/mistral-conversations.d.ts.map +1 -1
  40. package/dist/api/mistral-conversations.js +18 -13
  41. package/dist/api/mistral-conversations.js.map +1 -1
  42. package/dist/api/openai-codex-responses.d.ts.map +1 -1
  43. package/dist/api/openai-codex-responses.js +40 -26
  44. package/dist/api/openai-codex-responses.js.map +1 -1
  45. package/dist/api/openai-completions.d.ts +6 -4
  46. package/dist/api/openai-completions.d.ts.map +1 -1
  47. package/dist/api/openai-completions.js +44 -58
  48. package/dist/api/openai-completions.js.map +1 -1
  49. package/dist/api/openai-responses-shared.d.ts +11 -5
  50. package/dist/api/openai-responses-shared.d.ts.map +1 -1
  51. package/dist/api/openai-responses-shared.js +65 -58
  52. package/dist/api/openai-responses-shared.js.map +1 -1
  53. package/dist/api/openai-responses.d.ts.map +1 -1
  54. package/dist/api/openai-responses.js +15 -19
  55. package/dist/api/openai-responses.js.map +1 -1
  56. package/dist/api/openrouter-images.d.ts +2 -1
  57. package/dist/api/openrouter-images.d.ts.map +1 -1
  58. package/dist/api/openrouter-images.js +1 -0
  59. package/dist/api/openrouter-images.js.map +1 -1
  60. package/dist/api/openrouter-images.lazy.d.ts.map +1 -1
  61. package/dist/api/openrouter-images.lazy.js.map +1 -1
  62. package/dist/api/pi-messages.d.ts +3 -3
  63. package/dist/api/pi-messages.d.ts.map +1 -1
  64. package/dist/api/pi-messages.js +3 -2
  65. package/dist/api/pi-messages.js.map +1 -1
  66. package/dist/api/simple-options.d.ts +3 -3
  67. package/dist/api/simple-options.d.ts.map +1 -1
  68. package/dist/api/simple-options.js +1 -0
  69. package/dist/api/simple-options.js.map +1 -1
  70. package/dist/api/system-one-shared.d.ts +23 -0
  71. package/dist/api/system-one-shared.d.ts.map +1 -0
  72. package/dist/api/system-one-shared.js +170 -0
  73. package/dist/api/system-one-shared.js.map +1 -0
  74. package/dist/api/transform-messages.d.ts.map +1 -1
  75. package/dist/api/transform-messages.js +21 -7
  76. package/dist/api/transform-messages.js.map +1 -1
  77. package/dist/api/typesafe-system-one.d.ts +4 -0
  78. package/dist/api/typesafe-system-one.d.ts.map +1 -0
  79. package/dist/api/typesafe-system-one.js +19 -0
  80. package/dist/api/typesafe-system-one.js.map +1 -0
  81. package/dist/api/typesafe-system-one.lazy.d.ts +3 -0
  82. package/dist/api/typesafe-system-one.lazy.d.ts.map +1 -0
  83. package/dist/api/typesafe-system-one.lazy.js +4 -0
  84. package/dist/api/typesafe-system-one.lazy.js.map +1 -0
  85. package/dist/auth/credential-store.d.ts.map +1 -1
  86. package/dist/auth/credential-store.js +3 -2
  87. package/dist/auth/credential-store.js.map +1 -1
  88. package/dist/auth/oauth/load.d.ts +2 -0
  89. package/dist/auth/oauth/load.d.ts.map +1 -1
  90. package/dist/auth/oauth/load.js +5 -0
  91. package/dist/auth/oauth/load.js.map +1 -1
  92. package/dist/auth/oauth/meta.d.ts +17 -0
  93. package/dist/auth/oauth/meta.d.ts.map +1 -0
  94. package/dist/auth/oauth/meta.js +190 -0
  95. package/dist/auth/oauth/meta.js.map +1 -0
  96. package/dist/auth/resolve.d.ts +6 -8
  97. package/dist/auth/resolve.d.ts.map +1 -1
  98. package/dist/auth/resolve.js +29 -26
  99. package/dist/auth/resolve.js.map +1 -1
  100. package/dist/bun-oauth.d.ts.map +1 -1
  101. package/dist/bun-oauth.js +2 -0
  102. package/dist/bun-oauth.js.map +1 -1
  103. package/dist/compat.d.ts +3 -3
  104. package/dist/compat.d.ts.map +1 -1
  105. package/dist/compat.js +9 -6
  106. package/dist/compat.js.map +1 -1
  107. package/dist/decision-models.d.ts +21 -0
  108. package/dist/decision-models.d.ts.map +1 -0
  109. package/dist/decision-models.generated.d.ts +3 -0
  110. package/dist/decision-models.generated.d.ts.map +1 -0
  111. package/dist/decision-models.generated.js +47 -0
  112. package/dist/decision-models.generated.js.map +1 -0
  113. package/dist/decision-models.js +8 -0
  114. package/dist/decision-models.js.map +1 -0
  115. package/dist/env-api-keys.d.ts +2 -0
  116. package/dist/env-api-keys.d.ts.map +1 -1
  117. package/dist/env-api-keys.js +61 -43
  118. package/dist/env-api-keys.js.map +1 -1
  119. package/dist/image-models.d.ts +19 -8
  120. package/dist/image-models.d.ts.map +1 -1
  121. package/dist/image-models.js +14 -13
  122. package/dist/image-models.js.map +1 -1
  123. package/dist/images-api-registry.d.ts +7 -7
  124. package/dist/images-api-registry.d.ts.map +1 -1
  125. package/dist/images-api-registry.js.map +1 -1
  126. package/dist/images.d.ts +7 -2
  127. package/dist/images.d.ts.map +1 -1
  128. package/dist/images.js +5 -0
  129. package/dist/images.js.map +1 -1
  130. package/dist/index.d.ts +4 -2
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +4 -2
  133. package/dist/index.js.map +1 -1
  134. package/dist/model-catalog.d.ts +25 -9
  135. package/dist/model-catalog.d.ts.map +1 -1
  136. package/dist/model-catalog.js +14 -2
  137. package/dist/model-catalog.js.map +1 -1
  138. package/dist/models-store.d.ts +3 -2
  139. package/dist/models-store.d.ts.map +1 -1
  140. package/dist/models-store.js.map +1 -1
  141. package/dist/models.d.ts +99 -31
  142. package/dist/models.d.ts.map +1 -1
  143. package/dist/models.generated.d.ts +133 -39
  144. package/dist/models.generated.d.ts.map +1 -1
  145. package/dist/models.generated.js +133 -39
  146. package/dist/models.generated.js.map +1 -1
  147. package/dist/models.js +161 -31
  148. package/dist/models.js.map +1 -1
  149. package/dist/providers/all.d.ts +19 -13
  150. package/dist/providers/all.d.ts.map +1 -1
  151. package/dist/providers/all.js +27 -21
  152. package/dist/providers/all.js.map +1 -1
  153. package/dist/providers/amazon-bedrock.models.d.ts +4 -3
  154. package/dist/providers/amazon-bedrock.models.d.ts.map +1 -1
  155. package/dist/providers/amazon-bedrock.models.js +4 -2
  156. package/dist/providers/amazon-bedrock.models.js.map +1 -1
  157. package/dist/providers/ant-ling.models.d.ts +4 -3
  158. package/dist/providers/ant-ling.models.d.ts.map +1 -1
  159. package/dist/providers/ant-ling.models.js +4 -2
  160. package/dist/providers/ant-ling.models.js.map +1 -1
  161. package/dist/providers/anthropic.models.d.ts +4 -3
  162. package/dist/providers/anthropic.models.d.ts.map +1 -1
  163. package/dist/providers/anthropic.models.js +4 -2
  164. package/dist/providers/anthropic.models.js.map +1 -1
  165. package/dist/providers/azure-openai-responses.models.d.ts +4 -3
  166. package/dist/providers/azure-openai-responses.models.d.ts.map +1 -1
  167. package/dist/providers/azure-openai-responses.models.js +4 -2
  168. package/dist/providers/azure-openai-responses.models.js.map +1 -1
  169. package/dist/providers/baseten.models.d.ts +4 -3
  170. package/dist/providers/baseten.models.d.ts.map +1 -1
  171. package/dist/providers/baseten.models.js +4 -2
  172. package/dist/providers/baseten.models.js.map +1 -1
  173. package/dist/providers/cerebras.models.d.ts +4 -3
  174. package/dist/providers/cerebras.models.d.ts.map +1 -1
  175. package/dist/providers/cerebras.models.js +4 -2
  176. package/dist/providers/cerebras.models.js.map +1 -1
  177. package/dist/providers/cloudflare-ai-gateway.models.d.ts +4 -3
  178. package/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -1
  179. package/dist/providers/cloudflare-ai-gateway.models.js +4 -2
  180. package/dist/providers/cloudflare-ai-gateway.models.js.map +1 -1
  181. package/dist/providers/cloudflare-stream.d.ts +6 -2
  182. package/dist/providers/cloudflare-stream.d.ts.map +1 -1
  183. package/dist/providers/cloudflare-stream.js +6 -0
  184. package/dist/providers/cloudflare-stream.js.map +1 -1
  185. package/dist/providers/cloudflare-workers-ai.d.ts.map +1 -1
  186. package/dist/providers/cloudflare-workers-ai.js +10 -3
  187. package/dist/providers/cloudflare-workers-ai.js.map +1 -1
  188. package/dist/providers/cloudflare-workers-ai.models.d.ts +4 -3
  189. package/dist/providers/cloudflare-workers-ai.models.d.ts.map +1 -1
  190. package/dist/providers/cloudflare-workers-ai.models.js +4 -2
  191. package/dist/providers/cloudflare-workers-ai.models.js.map +1 -1
  192. package/dist/providers/data/.manifest.json +1 -1
  193. package/dist/providers/data/amazon-bedrock.json +1 -1
  194. package/dist/providers/data/ant-ling.json +1 -1
  195. package/dist/providers/data/anthropic.json +1 -1
  196. package/dist/providers/data/azure-openai-responses.json +1 -1
  197. package/dist/providers/data/baseten.json +1 -1
  198. package/dist/providers/data/cerebras.json +1 -1
  199. package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  200. package/dist/providers/data/cloudflare-workers-ai.json +1 -1
  201. package/dist/providers/data/deepseek.json +1 -1
  202. package/dist/providers/data/fireworks.json +1 -1
  203. package/dist/providers/data/github-copilot.json +1 -1
  204. package/dist/providers/data/google-vertex.json +1 -1
  205. package/dist/providers/data/google.json +1 -1
  206. package/dist/providers/data/groq.json +1 -1
  207. package/dist/providers/data/huggingface.json +1 -1
  208. package/dist/providers/data/kimi-coding.json +1 -1
  209. package/dist/providers/data/meta.json +1 -0
  210. package/dist/providers/data/minimax-cn.json +1 -1
  211. package/dist/providers/data/minimax.json +1 -1
  212. package/dist/providers/data/mistral.json +1 -1
  213. package/dist/providers/data/moonshotai-cn.json +1 -1
  214. package/dist/providers/data/moonshotai.json +1 -1
  215. package/dist/providers/data/nvidia.json +1 -1
  216. package/dist/providers/data/openai-codex.json +1 -1
  217. package/dist/providers/data/openai.json +1 -1
  218. package/dist/providers/data/opencode-go.json +1 -1
  219. package/dist/providers/data/opencode.json +1 -1
  220. package/dist/providers/data/openrouter.json +1 -1
  221. package/dist/providers/data/qwen-token-plan-cn.json +1 -1
  222. package/dist/providers/data/qwen-token-plan-individual.json +1 -1
  223. package/dist/providers/data/qwen-token-plan.json +1 -1
  224. package/dist/providers/data/radius.json +1 -0
  225. package/dist/providers/data/together.json +1 -1
  226. package/dist/providers/data/typesafe.json +1 -0
  227. package/dist/providers/data/vercel-ai-gateway.json +1 -1
  228. package/dist/providers/data/xai.json +1 -1
  229. package/dist/providers/data/xiaomi-token-plan-ams.json +1 -1
  230. package/dist/providers/data/xiaomi-token-plan-cn.json +1 -1
  231. package/dist/providers/data/xiaomi-token-plan-sgp.json +1 -1
  232. package/dist/providers/data/xiaomi.json +1 -1
  233. package/dist/providers/data/zai-coding-cn.json +1 -1
  234. package/dist/providers/data/zai.json +1 -1
  235. package/dist/providers/deepseek.models.d.ts +4 -3
  236. package/dist/providers/deepseek.models.d.ts.map +1 -1
  237. package/dist/providers/deepseek.models.js +4 -2
  238. package/dist/providers/deepseek.models.js.map +1 -1
  239. package/dist/providers/faux.d.ts +3 -2
  240. package/dist/providers/faux.d.ts.map +1 -1
  241. package/dist/providers/faux.js +12 -11
  242. package/dist/providers/faux.js.map +1 -1
  243. package/dist/providers/fireworks.models.d.ts +4 -3
  244. package/dist/providers/fireworks.models.d.ts.map +1 -1
  245. package/dist/providers/fireworks.models.js +4 -2
  246. package/dist/providers/fireworks.models.js.map +1 -1
  247. package/dist/providers/github-copilot.models.d.ts +4 -3
  248. package/dist/providers/github-copilot.models.d.ts.map +1 -1
  249. package/dist/providers/github-copilot.models.js +4 -2
  250. package/dist/providers/github-copilot.models.js.map +1 -1
  251. package/dist/providers/google-vertex.models.d.ts +4 -3
  252. package/dist/providers/google-vertex.models.d.ts.map +1 -1
  253. package/dist/providers/google-vertex.models.js +4 -2
  254. package/dist/providers/google-vertex.models.js.map +1 -1
  255. package/dist/providers/google.models.d.ts +4 -3
  256. package/dist/providers/google.models.d.ts.map +1 -1
  257. package/dist/providers/google.models.js +4 -2
  258. package/dist/providers/google.models.js.map +1 -1
  259. package/dist/providers/groq.models.d.ts +4 -3
  260. package/dist/providers/groq.models.d.ts.map +1 -1
  261. package/dist/providers/groq.models.js +4 -2
  262. package/dist/providers/groq.models.js.map +1 -1
  263. package/dist/providers/huggingface.models.d.ts +4 -3
  264. package/dist/providers/huggingface.models.d.ts.map +1 -1
  265. package/dist/providers/huggingface.models.js +4 -2
  266. package/dist/providers/huggingface.models.js.map +1 -1
  267. package/dist/providers/images/register-builtins.d.ts +1 -1
  268. package/dist/providers/images/register-builtins.d.ts.map +1 -1
  269. package/dist/providers/images/register-builtins.js.map +1 -1
  270. package/dist/providers/kimi-coding.models.d.ts +4 -3
  271. package/dist/providers/kimi-coding.models.d.ts.map +1 -1
  272. package/dist/providers/kimi-coding.models.js +4 -2
  273. package/dist/providers/kimi-coding.models.js.map +1 -1
  274. package/dist/providers/meta.d.ts +3 -0
  275. package/dist/providers/meta.d.ts.map +1 -0
  276. package/dist/providers/meta.js +24 -0
  277. package/dist/providers/meta.js.map +1 -0
  278. package/dist/providers/meta.models.d.ts +5 -0
  279. package/dist/providers/meta.models.d.ts.map +1 -0
  280. package/dist/providers/meta.models.js +8 -0
  281. package/dist/providers/meta.models.js.map +1 -0
  282. package/dist/providers/minimax-cn.models.d.ts +4 -3
  283. package/dist/providers/minimax-cn.models.d.ts.map +1 -1
  284. package/dist/providers/minimax-cn.models.js +4 -2
  285. package/dist/providers/minimax-cn.models.js.map +1 -1
  286. package/dist/providers/minimax.models.d.ts +4 -3
  287. package/dist/providers/minimax.models.d.ts.map +1 -1
  288. package/dist/providers/minimax.models.js +4 -2
  289. package/dist/providers/minimax.models.js.map +1 -1
  290. package/dist/providers/mistral.models.d.ts +4 -3
  291. package/dist/providers/mistral.models.d.ts.map +1 -1
  292. package/dist/providers/mistral.models.js +4 -2
  293. package/dist/providers/mistral.models.js.map +1 -1
  294. package/dist/providers/moonshotai-cn.models.d.ts +4 -3
  295. package/dist/providers/moonshotai-cn.models.d.ts.map +1 -1
  296. package/dist/providers/moonshotai-cn.models.js +4 -2
  297. package/dist/providers/moonshotai-cn.models.js.map +1 -1
  298. package/dist/providers/moonshotai.models.d.ts +4 -3
  299. package/dist/providers/moonshotai.models.d.ts.map +1 -1
  300. package/dist/providers/moonshotai.models.js +4 -2
  301. package/dist/providers/moonshotai.models.js.map +1 -1
  302. package/dist/providers/nvidia.models.d.ts +4 -3
  303. package/dist/providers/nvidia.models.d.ts.map +1 -1
  304. package/dist/providers/nvidia.models.js +4 -2
  305. package/dist/providers/nvidia.models.js.map +1 -1
  306. package/dist/providers/openai-codex.models.d.ts +4 -3
  307. package/dist/providers/openai-codex.models.d.ts.map +1 -1
  308. package/dist/providers/openai-codex.models.js +4 -2
  309. package/dist/providers/openai-codex.models.js.map +1 -1
  310. package/dist/providers/openai.models.d.ts +4 -3
  311. package/dist/providers/openai.models.d.ts.map +1 -1
  312. package/dist/providers/openai.models.js +4 -2
  313. package/dist/providers/openai.models.js.map +1 -1
  314. package/dist/providers/opencode-go.models.d.ts +4 -3
  315. package/dist/providers/opencode-go.models.d.ts.map +1 -1
  316. package/dist/providers/opencode-go.models.js +4 -2
  317. package/dist/providers/opencode-go.models.js.map +1 -1
  318. package/dist/providers/opencode.models.d.ts +4 -3
  319. package/dist/providers/opencode.models.d.ts.map +1 -1
  320. package/dist/providers/opencode.models.js +4 -2
  321. package/dist/providers/opencode.models.js.map +1 -1
  322. package/dist/providers/openrouter.d.ts.map +1 -1
  323. package/dist/providers/openrouter.js +11 -2
  324. package/dist/providers/openrouter.js.map +1 -1
  325. package/dist/providers/openrouter.models.d.ts +4 -3
  326. package/dist/providers/openrouter.models.d.ts.map +1 -1
  327. package/dist/providers/openrouter.models.js +4 -2
  328. package/dist/providers/openrouter.models.js.map +1 -1
  329. package/dist/providers/qwen-token-plan-cn.models.d.ts +4 -3
  330. package/dist/providers/qwen-token-plan-cn.models.d.ts.map +1 -1
  331. package/dist/providers/qwen-token-plan-cn.models.js +4 -2
  332. package/dist/providers/qwen-token-plan-cn.models.js.map +1 -1
  333. package/dist/providers/qwen-token-plan-individual.models.d.ts +4 -3
  334. package/dist/providers/qwen-token-plan-individual.models.d.ts.map +1 -1
  335. package/dist/providers/qwen-token-plan-individual.models.js +4 -2
  336. package/dist/providers/qwen-token-plan-individual.models.js.map +1 -1
  337. package/dist/providers/qwen-token-plan.models.d.ts +4 -3
  338. package/dist/providers/qwen-token-plan.models.d.ts.map +1 -1
  339. package/dist/providers/qwen-token-plan.models.js +4 -2
  340. package/dist/providers/qwen-token-plan.models.js.map +1 -1
  341. package/dist/providers/radius.d.ts.map +1 -1
  342. package/dist/providers/radius.js +19 -5
  343. package/dist/providers/radius.js.map +1 -1
  344. package/dist/providers/radius.models.d.ts +5 -0
  345. package/dist/providers/radius.models.d.ts.map +1 -0
  346. package/dist/providers/radius.models.js +8 -0
  347. package/dist/providers/radius.models.js.map +1 -0
  348. package/dist/providers/together.models.d.ts +4 -3
  349. package/dist/providers/together.models.d.ts.map +1 -1
  350. package/dist/providers/together.models.js +4 -2
  351. package/dist/providers/together.models.js.map +1 -1
  352. package/dist/providers/typesafe.d.ts +3 -0
  353. package/dist/providers/typesafe.d.ts.map +1 -0
  354. package/dist/providers/typesafe.js +18 -0
  355. package/dist/providers/typesafe.js.map +1 -0
  356. package/dist/providers/typesafe.models.d.ts +5 -0
  357. package/dist/providers/typesafe.models.d.ts.map +1 -0
  358. package/dist/providers/typesafe.models.js +8 -0
  359. package/dist/providers/typesafe.models.js.map +1 -0
  360. package/dist/providers/vercel-ai-gateway.models.d.ts +4 -3
  361. package/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
  362. package/dist/providers/vercel-ai-gateway.models.js +4 -2
  363. package/dist/providers/vercel-ai-gateway.models.js.map +1 -1
  364. package/dist/providers/xai.models.d.ts +4 -3
  365. package/dist/providers/xai.models.d.ts.map +1 -1
  366. package/dist/providers/xai.models.js +4 -2
  367. package/dist/providers/xai.models.js.map +1 -1
  368. package/dist/providers/xiaomi-token-plan-ams.models.d.ts +4 -3
  369. package/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -1
  370. package/dist/providers/xiaomi-token-plan-ams.models.js +4 -2
  371. package/dist/providers/xiaomi-token-plan-ams.models.js.map +1 -1
  372. package/dist/providers/xiaomi-token-plan-cn.models.d.ts +4 -3
  373. package/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -1
  374. package/dist/providers/xiaomi-token-plan-cn.models.js +4 -2
  375. package/dist/providers/xiaomi-token-plan-cn.models.js.map +1 -1
  376. package/dist/providers/xiaomi-token-plan-sgp.models.d.ts +4 -3
  377. package/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -1
  378. package/dist/providers/xiaomi-token-plan-sgp.models.js +4 -2
  379. package/dist/providers/xiaomi-token-plan-sgp.models.js.map +1 -1
  380. package/dist/providers/xiaomi.models.d.ts +4 -3
  381. package/dist/providers/xiaomi.models.d.ts.map +1 -1
  382. package/dist/providers/xiaomi.models.js +4 -2
  383. package/dist/providers/xiaomi.models.js.map +1 -1
  384. package/dist/providers/zai-coding-cn.models.d.ts +4 -3
  385. package/dist/providers/zai-coding-cn.models.d.ts.map +1 -1
  386. package/dist/providers/zai-coding-cn.models.js +4 -2
  387. package/dist/providers/zai-coding-cn.models.js.map +1 -1
  388. package/dist/providers/zai.models.d.ts +4 -3
  389. package/dist/providers/zai.models.d.ts.map +1 -1
  390. package/dist/providers/zai.models.js +4 -2
  391. package/dist/providers/zai.models.js.map +1 -1
  392. package/dist/types.d.ts +227 -51
  393. package/dist/types.d.ts.map +1 -1
  394. package/dist/types.js.map +1 -1
  395. package/dist/utils/diagnostics.d.ts +3 -2
  396. package/dist/utils/diagnostics.d.ts.map +1 -1
  397. package/dist/utils/diagnostics.js.map +1 -1
  398. package/dist/utils/estimate.d.ts +2 -2
  399. package/dist/utils/estimate.d.ts.map +1 -1
  400. package/dist/utils/estimate.js +8 -29
  401. package/dist/utils/estimate.js.map +1 -1
  402. package/dist/utils/headers.d.ts +1 -1
  403. package/dist/utils/headers.d.ts.map +1 -1
  404. package/dist/utils/headers.js +10 -8
  405. package/dist/utils/headers.js.map +1 -1
  406. package/dist/utils/model-operations.d.ts +11 -0
  407. package/dist/utils/model-operations.d.ts.map +1 -0
  408. package/dist/utils/model-operations.js +47 -0
  409. package/dist/utils/model-operations.js.map +1 -0
  410. package/dist/utils/models-error.d.ts +8 -0
  411. package/dist/utils/models-error.d.ts.map +1 -0
  412. package/dist/utils/models-error.js +19 -0
  413. package/dist/utils/models-error.js.map +1 -0
  414. package/dist/utils/overflow.d.ts +1 -0
  415. package/dist/utils/overflow.d.ts.map +1 -1
  416. package/dist/utils/overflow.js +17 -5
  417. package/dist/utils/overflow.js.map +1 -1
  418. package/dist/utils/retry.d.ts.map +1 -1
  419. package/dist/utils/retry.js +2 -0
  420. package/dist/utils/retry.js.map +1 -1
  421. package/dist/utils/text.d.ts +9 -1
  422. package/dist/utils/text.d.ts.map +1 -1
  423. package/dist/utils/text.js +26 -0
  424. package/dist/utils/text.js.map +1 -1
  425. package/dist/utils/transcript.d.ts +84 -0
  426. package/dist/utils/transcript.d.ts.map +1 -0
  427. package/dist/utils/transcript.js +204 -0
  428. package/dist/utils/transcript.js.map +1 -0
  429. package/package.json +4 -4
  430. package/dist/image-models.generated.d.ts +0 -785
  431. package/dist/image-models.generated.d.ts.map +0 -1
  432. package/dist/image-models.generated.js +0 -787
  433. package/dist/image-models.generated.js.map +0 -1
  434. package/dist/images-models.d.ts +0 -95
  435. package/dist/images-models.d.ts.map +0 -1
  436. package/dist/images-models.js +0 -143
  437. package/dist/images-models.js.map +0 -1
  438. package/dist/providers/openrouter-images.d.ts +0 -3
  439. package/dist/providers/openrouter-images.d.ts.map +0 -1
  440. package/dist/providers/openrouter-images.js +0 -22
  441. package/dist/providers/openrouter-images.js.map +0 -1
  442. package/dist/utils/deferred-tools.d.ts +0 -9
  443. package/dist/utils/deferred-tools.d.ts.map +0 -1
  444. package/dist/utils/deferred-tools.js +0 -36
  445. package/dist/utils/deferred-tools.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,9 +1,91 @@
1
1
  # Changelog
2
2
 
3
- This package is a Bastani fork of `@earendil-works/pi-ai`. Upstream history at the audited Pi `main` sync point (`92d8e2d17d4f357788381c49ce2cdb3f4ed1f21c`) lives in [earendil-works/pi](https://github.com/earendil-works/pi/blob/92d8e2d17d4f357788381c49ce2cdb3f4ed1f21c/packages/ai/CHANGELOG.md).
3
+ This package is a Bastani fork of `@earendil-works/pi-ai`. Upstream history at the audited Pi `main` sync point (`d1230ea2000d876b479a69b8b061f9d670f262f5`) lives in [earendil-works/pi](https://github.com/earendil-works/pi/blob/d1230ea2000d876b479a69b8b061f9d670f262f5/packages/ai/CHANGELOG.md).
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.20-alpha.9] - 2026-09-24
8
+
9
+ ### Breaking Changes
10
+
11
+ - Image generation now uses `ImageModel` entries in the regular `Provider` and `Models` collection instead of the separate `ImagesModels`/`ImagesProvider` collection. Replace `createImagesModels()`, `createImagesProvider()`, `builtinImagesModels()`, and `openrouterImagesProvider()` with `createModels()`/`builtinModels()` and `models.getModelOfType("image", ...)`/`models.generateImages()`. The old plural image type names are removed; generated image catalog data now ships alongside chat and classifier entries.
12
+
13
+ ### Added
14
+
15
+ - Added `onProviderStreamEvent` to observe parsed provider stream events before normalization, including provider-specific fields not retained in assistant messages ([#9784](https://github.com/earendil-works/pi/issues/9784)).
16
+ - Added operation-specific model accessors (`getModelsOfType()`, `getModelOfType()`, `getAvailableOfType()`, `getAllModels()`, `getAllAvailable()`), image and classifier dispatch on providers, and `classify()` for structured choice, score, and bool questions. The built-in TypeSafe `jev-latest` classifier uses `TYPESAFE_API_KEY`; OpenRouter image models share OpenRouter authentication. Chat-only reads and models with no `type` continue to mean chat.
17
+ - Added typed JSON catalog variants (`models.all.json` and `providers/{id}.all.json`) alongside the existing chat-only variants for clients that request all operation types.
18
+ - Added Jev classifier models on OpenRouter (`typesafe/jev-1.13`, `~typesafe/jev-latest`) through its TypeSafe-compatible System One endpoint, and on Cloudflare Workers AI (`typesafe/jev`) through the new `cloudflare-workers-ai-system-one` classifier API.
19
+
20
+ ### Fixed
21
+
22
+ - Fixed Claude Opus 5.5 on GitHub Copilot offering thinking levels other than low, medium, high, xhigh, and max when models.dev lists the model before its effort metadata is complete.
23
+ - Fixed 1-hour Anthropic cache writes reported by Vercel AI Gateway in streaming deltas being priced at the 5-minute rate ([#9210](https://github.com/earendil-works/pi/issues/9210)).
24
+ - Rejected malformed TypeSafe classifier answers when the returned choice, score, confidence, or probability falls outside the submitted question's bounds.
25
+ - Fixed Anthropic and Bedrock Claude requests failing with HTTP 400 when a tool opted into `strict: "prefer"` JSON-schema constrained sampling with numeric, string-length, or `maxItems`/`minItems` constraints that Claude's strict mode rejects. These tools now fall back to non-strict tool use, and `strict: "require"` reports the unsupported keyword.
26
+
27
+ ## [0.9.20-alpha.7] - 2026-09-22
28
+
29
+ ### Added
30
+
31
+ - Added Claude Opus 5.5, GPT-6 Sol, and GPT-6 Luna to the GitHub Copilot catalog.
32
+ - Added GPT-6 Sol and GPT-6 Luna for OpenAI API keys and OpenAI Codex subscriptions, with full reasoning-effort, prompt-caching, tool-search, long-context pricing, and official cost metadata.
33
+ - Added `getDecisionModels()` and a generated models.dev decision-model catalog (`type: "decision"`, fetched from `https://models.dev/api.json?type=all` by `npm run generate-decision-models`) listing TypeSafe Jev on the gateways that resell it, with context limits and prices.
34
+ - Added Claude Opus 5.5 to the built-in Anthropic model catalog with adaptive thinking, 1M context, and official pricing metadata.
35
+ - Added Anthropic fast mode for models whose `fastRoute` declares `speed: "fast"`: the Anthropic Messages adapter sends the route's upstream model with `speed: "fast"` and the `fast-mode-2026-02-01` beta, prices responses reporting fast speed at the 2x fast-mode rates, and rejects payload hooks that change the route-owned model or speed.
36
+
37
+ ### Fixed
38
+
39
+ - Fixed Anthropic OAuth requests for Claude Opus 5.5 rejected with `claude_code_version_too_old` by advertising Claude Code version `2.1.280`, the minimum the API requires.
40
+ - Fixed Fast-mode usage costs for GPT-6 models being recorded at standard rates when OpenAI reports the tier as `service_tier: "fast"` instead of `priority`.
41
+ - Fixed Claude Opus 5.5 offering thinking levels other than low, medium, high, xhigh, and max when models.dev lists the model before its effort metadata is complete.
42
+
43
+ ## [0.9.20-alpha.6] - 2026-09-22
44
+
45
+ ### Added
46
+
47
+ - Added Meta provider (Model API key and Muse subscription OAuth) with Muse Spark models.
48
+ - Added model image-input limit and cache-safe resize metadata (`inputLimits`) to the `Model` type and the generated catalog ([#9631](https://github.com/earendil-works/pi/issues/9631)).
49
+ - Added Grok 4.7 to the built-in xAI model catalog with long-context pricing metadata.
50
+
51
+ ### Fixed
52
+
53
+ - Fixed unknown OpenAI-compatible Chat Completions endpoints receiving strict tool schemas unless they explicitly advertise support (`compat.supportsStrictMode` now defaults to `false`), while preserving strict tools for capable built-in models ([#9816](https://github.com/earendil-works/pi/issues/9816)).
54
+ - Fixed image-only user messages being rejected by some OpenAI-compatible providers because they included an empty text part ([#9797](https://github.com/earendil-works/pi/issues/9797)).
55
+
56
+ ## [0.9.20-alpha.4] - 2026-09-20
57
+
58
+ ### Breaking Changes
59
+
60
+ - Provider implementations and direct API modules now consume `TranscriptContext`; use `normalizeContext()` at direct-call boundaries and replay helpers to read prompt/tool state. Durable tool arguments and results use JSON-value types.
61
+
62
+ ### Added
63
+
64
+ - Chronological system messages with named prompt patches and tool additions/removals, including native provider transitions where supported and replay checkpoints elsewhere.
65
+ - A static Radius catalog with authenticated dynamic refresh, refreshed image models, and prompt-cache lifetime metadata for direct Anthropic models.
66
+
67
+ ### Fixed
68
+
69
+ - Derive Gemini thinking levels from model metadata, preserve renamed Anthropic/Vercel unsigned thinking replay and DeepSeek V4 effort, retry Cloudflare 520 and Azure peak-load errors, and scope bodyless overflow detection to Cerebras.
70
+
71
+ - Documented Fireworks deferred tool loading against chronological system-message `toolsAdded`/`toolsRemoved` instead of the removed tool-result `addedToolNames` field.
72
+
73
+ - Request-auth preparation now times out after 15 seconds when OAuth refresh, credential-store reads, or auth derivation ignore cancellation, and late refresh results cannot overwrite stored credentials. The timeout diagnostic is source-neutral and does not instruct you to log in ([#3085](https://github.com/bastani-inc/atomic/issues/3085), [#3087](https://github.com/bastani-inc/atomic/pull/3087)).
74
+ - Bedrock requests now honor explicit `maxRetries`, including zero for a single transport attempt, instead of silently using the AWS SDK retry default. Omitting the option preserves SDK/environment configuration ([#3089](https://github.com/bastani-inc/atomic/issues/3089), [#3090](https://github.com/bastani-inc/atomic/issues/3090)).
75
+ - Kept Kimi Coding models available after the upstream catalog split into regional coding plans, preserving Atomic's existing kimi.com endpoint.
76
+ - Model catalog declarations preserve JSON import attributes for strict NodeNext consumers without requiring `skipLibCheck` ([#3105](https://github.com/bastani-inc/atomic/issues/3105)).
77
+ - Credential screening now recognizes `TYPESAFE_API_KEY` instead of `TYPESAFE_AI_API_KEY`, matching the renamed TypeSafe Jev environment variable.
78
+ - Fixed z.ai `Prompt too long` errors not being recognized as context overflow ([earendil-works/pi#9805](https://github.com/earendil-works/pi/issues/9805)).
79
+ - Fixed Cerebras models advertising unsupported strict tool schemas, which caused HTTP 400 errors when strict and non-strict tools were mixed ([earendil-works/pi#9804](https://github.com/earendil-works/pi/pull/9804) by [@EdenGottlieb](https://github.com/EdenGottlieb)).
80
+
81
+ ## [0.9.20-alpha.3] - 2026-09-16
82
+
83
+ ### Fixed
84
+
85
+ - Fixed OpenAI-compatible Responses errors to identify the actual provider instead of always labeling them as OpenAI errors ([#9298](https://github.com/earendil-works/pi/issues/9298)).
86
+ - Fixed Amazon Bedrock one-hour cache writes being priced at the five-minute rate ([#9457](https://github.com/earendil-works/pi/issues/9457)).
87
+ - Fixed Baseten requests to send session-affinity headers from `sessionId` for automatic prompt-cache routing ([#9629](https://github.com/earendil-works/pi/issues/9629)).
88
+
7
89
  ## [0.9.19] - 2026-09-13
8
90
 
9
91
  Cumulative release of the `0.9.19-alpha.2` through `0.9.19-alpha.4` prereleases. Per-change details remain in the unchanged prerelease sections below.
package/NOTICE.md CHANGED
@@ -6,7 +6,7 @@ monorepo at `packages/ai` and publishes at the same version as `@bastani/atomic`
6
6
 
7
7
  - Upstream package: [`@earendil-works/pi-ai`](https://www.npmjs.com/package/@earendil-works/pi-ai)
8
8
  - Original fork point: `v0.84.2` (`914cf1472e715297caa30db4b9535d534a9eb718`)
9
- - Pi AI fixes and generated image catalog synced through audited upstream `main`: `earendil-works/pi@92d8e2d17d4f357788381c49ce2cdb3f4ed1f21c`
9
+ - Pi AI fixes and generated image catalog synced through audited upstream `main`: `earendil-works/pi@d1230ea2000d876b479a69b8b061f9d670f262f5`
10
10
  - Catalog JSON under `src/providers/data/` is generated at build time from models.dev, matching upstream. It is not committed.
11
11
 
12
12
  Original work is Copyright (c) 2025 Mario Zechner and is licensed under the MIT License.
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # @bastani/pi-ai
2
2
 
3
- Bastani-branded fork of [`@earendil-works/pi-ai`](https://www.npmjs.com/package/@earendil-works/pi-ai) from [earendil-works/pi](https://github.com/earendil-works/pi). Originally forked at **v0.84.2** (`914cf1472e715297caa30db4b9535d534a9eb718`); upstream Pi AI fixes and the generated image catalog are synced through [`92d8e2d17d4f357788381c49ce2cdb3f4ed1f21c`](https://github.com/earendil-works/pi/commit/92d8e2d17d4f357788381c49ce2cdb3f4ed1f21c), the audited Pi `main` sync point. `@bastani/pi-ai` publishes at the same version as Atomic. `npm run build` refreshes the models.dev catalog, same as upstream.
3
+ Bastani-branded fork of [`@earendil-works/pi-ai`](https://www.npmjs.com/package/@earendil-works/pi-ai) from [earendil-works/pi](https://github.com/earendil-works/pi). Originally forked at **v0.84.2** (`914cf1472e715297caa30db4b9535d534a9eb718`); upstream Pi AI fixes and the unified model catalog are synced through [`a328aa89ad6e6dc5c5628ff896769532ed3d29df`](https://github.com/earendil-works/pi/commit/a328aa89ad6e6dc5c5628ff896769532ed3d29df). `@bastani/pi-ai` publishes at the same version as Atomic. `npm run build` refreshes the models.dev catalog, same as upstream.
4
4
 
5
5
  The public API is a drop-in replacement: install `@bastani/pi-ai` and import from `@bastani/pi-ai` instead of `@earendil-works/pi-ai`. See [NOTICE.md](NOTICE.md). This package lives in the Atomic monorepo and publishes from `.github/workflows/publish.yml`. The first npm version must be published by hand so trusted publishing can be attached.
6
6
 
7
7
  Unified LLM API with provider collections, automatic auth resolution, token and cost tracking, and simple context persistence and hand-off to other models mid-session.
8
8
 
9
- **Note**: This library only includes models that support tool calling (function calling), as this is essential for agentic workflows.
9
+ **Note**: The chat catalog only includes models that support tool calling (function calling), as this is essential for agentic workflows. Image and classifier catalogs use their operation-specific capabilities.
10
10
 
11
11
  ## Table of Contents
12
12
 
@@ -32,6 +32,7 @@ Unified LLM API with provider collections, automatic auth resolution, token and
32
32
  - [Complete Event Reference](#complete-event-reference)
33
33
  - [Image Input](#image-input)
34
34
  - [Image Generation](#image-generation)
35
+ - [Classification](#classification)
35
36
  - [Thinking/Reasoning](#thinkingreasoning)
36
37
  - [Unified Interface](#unified-interface-streamsimplecompletesimple)
37
38
  - [Provider-Specific Options](#provider-specific-options-streamcomplete)
@@ -41,12 +42,14 @@ Unified LLM API with provider collections, automatic auth resolution, token and
41
42
  - [Aborting Requests](#aborting-requests)
42
43
  - [Continuing After Abort](#continuing-after-abort)
43
44
  - [Debugging Provider Payloads](#debugging-provider-payloads)
45
+ - [Observing Provider Stream Events](#observing-provider-stream-events)
44
46
  - [Custom Providers](#custom-providers)
45
47
  - [createProvider()](#createprovider)
46
48
  - [Calling API Implementations Directly](#calling-api-implementations-directly)
47
49
  - [OpenAI Compatibility Settings](#openai-compatibility-settings)
48
50
  - [Faux Provider for Tests](#faux-provider-for-tests)
49
51
  - [Cross-Provider Handoffs](#cross-provider-handoffs)
52
+ - [System Messages](#system-messages)
50
53
  - [Context Serialization](#context-serialization)
51
54
  - [Browser Usage](#browser-usage)
52
55
  - [Bundling and Tree Shaking](#bundling-and-tree-shaking)
@@ -64,6 +67,8 @@ Unified LLM API with provider collections, automatic auth resolution, token and
64
67
  - **Ant Ling**
65
68
  - **Azure OpenAI (Responses)**
66
69
  - **OpenAI Codex** (ChatGPT Plus/Pro subscription, requires OAuth, see below)
70
+ - **Radius** (API key or OAuth, with a dynamically refreshed gateway catalog)
71
+ - **TypeSafe** (System One classifier API)
67
72
  - **DeepSeek**
68
73
  - **NVIDIA NIM**
69
74
  - **Anthropic**
@@ -89,6 +94,7 @@ Unified LLM API with provider collections, automatic auth resolution, token and
89
94
  - **OpenCode Go**
90
95
  - **Fireworks** (uses OpenAI- and Anthropic-compatible APIs)
91
96
  - **Kimi For Coding** (Moonshot AI subscription endpoint, uses Anthropic-compatible API)
97
+ - **Meta** (Model API, uses OpenAI Responses-compatible API)
92
98
  - **Qwen Token Plan** (separate Individual and existing catalogs, with a separate China provider)
93
99
  - **Xiaomi MiMo** (defaults to API billing endpoint, with separate Token Plan providers for `cn`/`ams`/`sgp` regions)
94
100
  - **Any OpenAI-compatible API**: Ollama, vLLM, LM Studio, etc.
@@ -275,7 +281,7 @@ Reads are synchronous and return the last-known lists:
275
281
  const providers = models.getProviders(); // registered Provider objects
276
282
  const provider = models.getProvider('anthropic'); // one provider
277
283
 
278
- const all = models.getModels(); // every model across providers
284
+ const all = models.getModels(); // every chat model across providers
279
285
  const anthropicModels = models.getModels('anthropic');
280
286
  const model = models.getModel('anthropic', 'claude-sonnet-4-5');
281
287
 
@@ -288,7 +294,31 @@ for (const m of anthropicModels) {
288
294
  }
289
295
  ```
290
296
 
291
- Dynamically listed models are typed `Model<Api>`. Narrow with the `hasApi()` guard when you need API-specific option typing:
297
+ The unqualified reads `getModels()`/`getModel()`/`getAvailable()` return chat models (`Model<Api>`) usable with `stream()`. The `*OfType` reads return one model type, and `getAllModels()`/`getAllAvailable()` return every type as `AnyModel`:
298
+
299
+ ```typescript
300
+ const images = models.getModelsOfType('image', 'openrouter'); // ImageModel[]
301
+ const flux = models.getModelOfType('image', 'openrouter', 'black-forest-labs/flux.2-pro');
302
+ const jev = models.getModelOfType('classifier', 'typesafe', 'jev-latest');
303
+ const availableImages = await models.getAvailableOfType('image');
304
+ const everything = models.getAllModels(); // AnyModel[]
305
+ ```
306
+
307
+ The model's `type` decides which operation accepts it: chat models stream, `type: "image"` models generate images, and `type: "classifier"` models classify structured state. `type` is optional on chat models, so a model without `type` is a chat model. Do not compare `type` directly; narrow mixed lists with `isModelType()` or read the effective type with `getModelType()`:
308
+
309
+ ```typescript
310
+ import { isModelType } from '@bastani/pi-ai';
311
+
312
+ for (const model of models.getAllModels()) {
313
+ if (isModelType(model, 'image')) {
314
+ // model: ImageModel<ImageApi>
315
+ }
316
+ }
317
+ ```
318
+
319
+ IDs are unique within each provider and type; one upstream model may have separate entries for different operations. On a provider, `getModels()` returns chat models and the optional `getAllModels()` returns every type; providers with only chat models can omit it.
320
+
321
+ Dynamically listed chat models are typed `Model<Api>`. Narrow with the `hasApi()` guard when you need API-specific option typing:
292
322
 
293
323
  ```typescript
294
324
  import { hasApi } from '@bastani/pi-ai';
@@ -305,11 +335,26 @@ if (m && hasApi(m, 'anthropic-messages')) {
305
335
  For tooling that wants the generated built-in catalog with full literal typing (provider and model IDs auto-complete), independent of any collection:
306
336
 
307
337
  ```typescript
308
- import { getBuiltinModel, getBuiltinModels, getBuiltinProviders } from '@bastani/pi-ai/providers/all';
338
+ import {
339
+ getAllBuiltinModels,
340
+ getBuiltinClassifierModel,
341
+ getBuiltinClassifierModels,
342
+ getBuiltinImageModel,
343
+ getBuiltinImageModels,
344
+ getBuiltinModel,
345
+ getBuiltinModels,
346
+ getBuiltinProviders,
347
+ } from '@bastani/pi-ai/providers/all';
309
348
 
310
349
  const model = getBuiltinModel('openai', 'gpt-4o-mini'); // typed Model<'openai-responses'>
350
+ const radius = getBuiltinModel('radius', 'balanced'); // typed Model<'pi-messages'>
351
+ const flux = getBuiltinImageModel('openrouter', 'black-forest-labs/flux.2-pro');
352
+ const jev = getBuiltinClassifierModel('typesafe', 'jev-latest');
311
353
  const providers = getBuiltinProviders();
312
- const anthropic = getBuiltinModels('anthropic');
354
+ const openrouterChat = getBuiltinModels('openrouter'); // Model[]
355
+ const openrouterImages = getBuiltinImageModels('openrouter'); // ImageModel[]
356
+ const typesafeClassifiers = getBuiltinClassifierModels('typesafe'); // ClassifierModel[]
357
+ const openrouterAll = getAllBuiltinModels('openrouter'); // AnyModel[]
313
358
  ```
314
359
 
315
360
  ### Dynamic Providers
@@ -323,7 +368,7 @@ await models.refresh(); // refresh all providers conc
323
368
  const fresh = models.getModel('llamacpp', 'qwen3-30b');
324
369
  ```
325
370
 
326
- Static built-in providers are no-ops for `refresh()`. See [createProvider()](#createprovider) for building a dynamic provider.
371
+ Static built-in providers are no-ops for `refresh()`. Radius ships a public static catalog and overlays cached and freshly fetched `/v1/config` models when refreshed with configured API-key or OAuth auth (`RADIUS_API_KEY` for environment authentication). See [createProvider()](#createprovider) for building a dynamic provider.
327
372
 
328
373
  ## Auth
329
374
 
@@ -420,6 +465,8 @@ Built-in providers resolve these env vars (Node.js; in browsers pass `apiKey` ex
420
465
  | Ant Ling | `ANT_LING_API_KEY` |
421
466
  | Azure OpenAI | `AZURE_OPENAI_API_KEY` + `AZURE_OPENAI_BASE_URL` (e.g. `https://{resource}.ai.azure.com`) or `AZURE_OPENAI_RESOURCE_NAME`. Supports `*.openai.azure.com`, `*.cognitiveservices.azure.com` and `*.ai.azure.com`; root endpoints auto-normalize to `/openai/v1`. Optional: `AZURE_OPENAI_API_VERSION` (default `v1`), `AZURE_OPENAI_DEPLOYMENT_NAME_MAP`. |
422
467
  | Anthropic | `ANTHROPIC_API_KEY` or `ANTHROPIC_OAUTH_TOKEN` |
468
+ | Radius | `RADIUS_API_KEY` |
469
+ | TypeSafe | `TYPESAFE_API_KEY` |
423
470
  | DeepSeek | `DEEPSEEK_API_KEY` |
424
471
  | NVIDIA NIM | `NVIDIA_API_KEY` |
425
472
  | Google | `GEMINI_API_KEY` |
@@ -443,6 +490,7 @@ Built-in providers resolve these env vars (Node.js; in browsers pass `apiKey` ex
443
490
  | Hugging Face | `HF_TOKEN` |
444
491
  | OpenCode Zen / OpenCode Go | `OPENCODE_API_KEY` |
445
492
  | Kimi For Coding | `KIMI_API_KEY` |
493
+ | Meta | `META_API_KEY` |
446
494
  | Qwen Token Plan (existing catalog) | `QWEN_TOKEN_PLAN_API_KEY` |
447
495
  | Qwen Token Plan (Individual) | `QWEN_TOKEN_PLAN_API_KEY` |
448
496
  | Qwen Token Plan (China) | `QWEN_TOKEN_PLAN_CN_API_KEY` |
@@ -577,7 +625,7 @@ context.messages.push({
577
625
 
578
626
  ### Fireworks deferred tools
579
627
 
580
- Fireworks models using the Anthropic Messages API support native deferred tool loading. Keep your discovery tool in `context.tools`, add discovered tool definitions there, and set `addedToolNames` on the discovery tool's result to the names you added. The adapter sends deferred schemas and `tool_reference` blocks while preserving ordinary result text and unsigned thinking during replay.
628
+ Fireworks models using the Anthropic Messages API support native deferred tool loading. Keep your discovery tool in `context.tools`. After the discovery tool result, append a chronological system message with `toolsAdded` containing the newly discovered tool definitions (`toolsRemoved` when tools drop out). The adapter sends deferred schemas and `tool_reference` blocks while preserving ordinary result text and unsigned thinking during replay.
581
629
 
582
630
  Name the discovery tool `ToolSearch` or `tool_search` for Fireworks prompt-prefix deferral. Other discovery names serialize correctly but do not get that prefix optimization. Set `model.compat.supportsToolReferences` to `false` to send ordinary tool schemas instead. This feature does not apply to Fireworks Chat Completions models.
583
631
 
@@ -722,20 +770,19 @@ for (const block of response.content) {
722
770
 
723
771
  ## Image Generation
724
772
 
725
- Image generation uses a separate API surface from text/chat generation, mirroring the chat-side design: an `ImagesModels` collection holds `ImagesProvider`s, reads are sync, and auth resolves through the owning provider. Image generation is a one-shot API: `generateImages()` waits for the provider response and returns the final `AssistantImages` result — do not use the chat/stream APIs for it.
773
+ Image models live in the same `Models` collection and on the same `Provider` as chat models, so one credential per provider covers both. They are typed `ImageModel` with `type: "image"` and are used through `generateImages()`, a one-shot API that waits for the provider response and returns the final `AssistantImages` result. Do not use the chat/stream APIs for them; `stream()` rejects image models.
726
774
 
727
775
  ### Basic Image Generation
728
776
 
729
777
  ```typescript
730
- import { builtinImagesModels } from '@bastani/pi-ai/providers/all';
778
+ import { builtinModels } from '@bastani/pi-ai/providers/all';
731
779
 
732
- // Every built-in image-generation provider; accepts the same options as createModels()
733
- const imagesModels = builtinImagesModels();
780
+ const models = builtinModels();
734
781
 
735
- const model = imagesModels.getModel('openrouter', 'google/gemini-2.5-flash-image')!;
782
+ const model = models.getModelOfType('image', 'openrouter', 'google/gemini-2.5-flash-image')!;
736
783
 
737
784
  // Auth resolves through the provider (OPENROUTER_API_KEY here); explicit apiKey wins
738
- const result = await imagesModels.generateImages(model, {
785
+ const result = await models.generateImages(model, {
739
786
  input: [{ type: 'text', text: 'Generate a red circle on a plain white background.' }]
740
787
  });
741
788
 
@@ -749,7 +796,33 @@ for (const block of result.output) {
749
796
  }
750
797
  ```
751
798
 
752
- Like the chat side, you can build the collection from parts: `createImagesModels({ credentials?, authContext? })`, the `openrouterImagesProvider()` factory from `@bastani/pi-ai/providers/openrouter-images`, and `createImagesProvider({ id, auth, models, refreshModels?, api })` for custom image providers (with `imagesModels.refresh(provider?)` for dynamic lists). Failures never reject — they return an `AssistantImages` with `stopReason: "error"`. The collection's provider-scoped `getAuth(providerId)` works exactly like the chat-side one.
799
+ `generateImages()` accepts only `ImageModel` values. If an upstream model supports both chat and image generation, the catalog contains separate entries with the same provider and ID: `getModel()` returns its chat operation and `getModelOfType('image', ...)` returns its image operation. Failures never reject; they return an `AssistantImages` with `stopReason: "error"`, including unknown providers, unconfigured auth, and providers without an image implementation.
800
+
801
+ A provider declares image support with the `images` option of [`createProvider()`](#createprovider): a map from `model.api` to an implementation with `generateImages()`. Image models go into the same `models` list as chat models. `api` becomes optional when `images` is present, so an image-only provider is just a provider without chat models:
802
+
803
+ ```typescript
804
+ import { createProvider, envApiKeyAuth } from '@bastani/pi-ai';
805
+
806
+ const pixels = createProvider({
807
+ id: 'pixels',
808
+ auth: { apiKey: envApiKeyAuth('Pixels API key', ['PIXELS_API_KEY']) },
809
+ models: [{
810
+ type: 'image',
811
+ id: 'flux-pro',
812
+ name: 'FLUX Pro',
813
+ api: 'pixels-images',
814
+ provider: 'pixels',
815
+ baseUrl: 'https://api.pixels.test/v1',
816
+ input: ['text'],
817
+ output: ['image'],
818
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
819
+ }],
820
+ images: {
821
+ 'pixels-images': { generateImages: async (model, context, options) => { /* ... */ } },
822
+ },
823
+ });
824
+ models.setProvider(pixels);
825
+ ```
753
826
 
754
827
  The old global API (`getImageModel()` / `getImageModels()` / `getImageProviders()` / `generateImages()`) remains available on the [compat entrypoint](#migrating-from-the-old-global-api):
755
828
 
@@ -770,7 +843,7 @@ Some models also support image input:
770
843
  import { readFileSync } from 'fs';
771
844
 
772
845
  const imageBuffer = readFileSync('input.png');
773
- const result = await imagesModels.generateImages(model, {
846
+ const result = await models.generateImages(model, {
774
847
  input: [
775
848
  { type: 'text', text: 'Create a variation of this image with a blue background.' },
776
849
  { type: 'image', data: imageBuffer.toString('base64'), mimeType: 'image/png' }
@@ -781,14 +854,13 @@ const result = await imagesModels.generateImages(model, {
781
854
  Check capabilities on the model metadata:
782
855
 
783
856
  ```typescript
784
- console.log(model.input); // ['text', 'image']
785
- console.log(model.output); // ['image'] or ['image', 'text']
857
+ console.log(model.input); // ['text'] or ['text', 'image']
858
+ console.log(model.output); // ['image'] or ['image', 'text']
786
859
  ```
787
860
 
788
861
  ### Notes and Limitations
789
862
 
790
- - Image models live in `ImagesModels` collections, chat models in `Models` collections; the two are separate surfaces.
791
- - Use `generateImages()`, not the chat/stream APIs.
863
+ - Image models and chat models share `Models` and `Provider`; list them with `getModelsOfType('image')` and run them with `generateImages()`, never the chat/stream APIs.
792
864
  - Image-generation models do not participate in tool calling.
793
865
  - Outputs are returned in `AssistantImages.output` and can include both base64-encoded `ImageContent` blocks and `TextContent` blocks.
794
866
  - Some models return only images, others return images plus text. Check `model.output`.
@@ -797,6 +869,63 @@ console.log(model.output); // ['image'] or ['image', 'text']
797
869
  - If you want a model to analyze images in a conversation or call tools, use the regular chat APIs with a model that supports image input.
798
870
  - At the moment, image generation is available through only one provider, OpenRouter.
799
871
 
872
+ ## Classification
873
+
874
+ Classifier models consume structured JSON state and answer one or more typed questions. They do not use chat or image-generation APIs. TypeSafe's Jev model is available from these built-in providers:
875
+
876
+ | Provider | Model IDs | Auth |
877
+ | --- | --- | --- |
878
+ | `typesafe` | `jev-latest` | `TYPESAFE_API_KEY` |
879
+ | `openrouter` | `typesafe/jev-1.13`, `~typesafe/jev-latest` | `OPENROUTER_API_KEY` or OpenRouter OAuth |
880
+ | `cloudflare-workers-ai` | `typesafe/jev` | `CLOUDFLARE_API_KEY` and `CLOUDFLARE_ACCOUNT_ID` |
881
+
882
+ ```typescript
883
+ import { builtinModels } from '@bastani/pi-ai/providers/all';
884
+
885
+ const models = builtinModels();
886
+ const model = models.getModelOfType('classifier', 'typesafe', 'jev-latest')!;
887
+ const result = await models.classify(model, {
888
+ state: { message: 'The change works perfectly, thanks.' },
889
+ questions: {
890
+ category: {
891
+ type: 'choice',
892
+ instructions: 'Classify the message.',
893
+ criteria: {
894
+ approval: 'The user approves of the result',
895
+ correction: 'The user requests a correction'
896
+ }
897
+ },
898
+ satisfaction: {
899
+ type: 'score',
900
+ instructions: 'Score user satisfaction.',
901
+ criteria: ['dissatisfied', 'neutral', 'satisfied']
902
+ },
903
+ approved: {
904
+ type: 'bool',
905
+ instructions: 'Does the user approve?',
906
+ criteria: { true: 'Approval', false: 'No approval' }
907
+ }
908
+ }
909
+ });
910
+
911
+ console.log(result.answers);
912
+ ```
913
+
914
+ The public contract uses `bool` questions and `{ type: "bool", probability }` answers. The TypeSafe adapter translates those to and from its `noul` wire representation. Like image generation, `classify()` resolves to a result with `stopReason: "error"` instead of rejecting for provider, authentication, or response errors.
915
+
916
+ Custom providers register classifier models and implementations by API ID:
917
+
918
+ ```typescript
919
+ createProvider({
920
+ id: 'classifier-service',
921
+ auth,
922
+ models: [model],
923
+ classifiers: {
924
+ 'classifier-api': { classify: async (model, context, options) => result }
925
+ }
926
+ });
927
+ ```
928
+
800
929
  ## Thinking/Reasoning
801
930
 
802
931
  Many models support thinking/reasoning capabilities where they can show their internal thought process. You can check if a model supports reasoning via the `reasoning` property. If you pass reasoning options to a non-reasoning model, they are silently ignored.
@@ -808,7 +937,7 @@ Many models support thinking/reasoning capabilities where they can show their in
808
937
  const model = models.getModel('anthropic', 'claude-sonnet-4-5')!;
809
938
  // or models.getModel('openai', 'gpt-5-mini');
810
939
  // or models.getModel('google', 'gemini-2.5-flash');
811
- // or models.getModel('xai', 'grok-4.6');
940
+ // or models.getModel('xai', 'grok-4.7');
812
941
 
813
942
  // Check if model supports reasoning
814
943
  if (model.reasoning) {
@@ -1005,11 +1134,30 @@ const response = await models.complete(model, context, {
1005
1134
 
1006
1135
  The callback is supported by `stream`, `complete`, `streamSimple`, and `completeSimple`.
1007
1136
 
1137
+ ### Observing Provider Stream Events
1138
+
1139
+ Use `onProviderStreamEvent` to inspect provider-specific fields that Pi does not include in `AssistantMessage`. The callback receives the parsed event available to the adapter before Pi normalizes it. Treat the event as read-only because mutations can affect normalization. This is not guaranteed to be the original HTTP bytes or SSE frame.
1140
+
1141
+ ```typescript
1142
+ const openRouterModel = models.getModel('openrouter', 'openrouter/auto')!;
1143
+ const response = await models.complete(openRouterModel, context, {
1144
+ headers: { "X-OpenRouter-Metadata": "enabled" },
1145
+ onProviderStreamEvent: (data) => {
1146
+ const chunk = data as Record<string, unknown>;
1147
+ if (chunk.openrouter_metadata) {
1148
+ console.log(chunk.openrouter_metadata);
1149
+ }
1150
+ },
1151
+ });
1152
+ ```
1153
+
1154
+ Callbacks are awaited in stream order, so slow callbacks delay stream consumption and thrown errors fail the request. SDK-backed adapters can expose only fields retained by their SDK.
1155
+
1008
1156
  ## Custom Providers
1009
1157
 
1010
1158
  ### createProvider()
1011
1159
 
1012
- `createProvider()` builds a provider from parts: identity, auth, a model list, and an API implementation. Use it for local inference servers, proxies, or any OpenAI/Anthropic-compatible endpoint:
1160
+ `createProvider()` builds a provider from parts: identity, auth, a model list, and an API implementation (`api` for chat models, `images` for image generation, `classifiers` for classification; at least one is required, see [Image Generation](#image-generation)). Use it for local inference servers, proxies, or any OpenAI/Anthropic-compatible endpoint:
1013
1161
 
1014
1162
  ```typescript
1015
1163
  import { createModels, createProvider, envApiKeyAuth, type Model } from '@bastani/pi-ai';
@@ -1091,7 +1239,7 @@ const tenantGateway = createProvider({
1091
1239
  });
1092
1240
  ```
1093
1241
 
1094
- Dynamic model lists use `fetchModels`. `Models.refresh()` refreshes every configured dynamic provider, passing its effective API-key or refreshed OAuth credential. A `ModelsStore` persists dynamic catalogs; both stores default to in-memory implementations. Its `read`, `write`, and `delete` operations accept optional cancellation, and `Models` binds those waits to the provider refresh signal.
1242
+ Dynamic model lists use `fetchModels`, which can return models of every type. `Models.refresh()` refreshes every configured dynamic provider, passing its effective API-key or refreshed OAuth credential. A `ModelsStore` persists dynamic catalogs; both stores default to in-memory implementations. Its `read`, `write`, and `delete` operations accept optional cancellation, and `Models` binds those waits to the provider refresh signal.
1095
1243
 
1096
1244
  ```typescript
1097
1245
  const models = createModels({ credentials, modelsStore });
@@ -1113,7 +1261,7 @@ for (const [provider, error] of result.errors) console.error(provider, error);
1113
1261
 
1114
1262
  Use `models.refresh({ providers: ['openrouter'] })` to restrict work to selected providers, `models.refresh({ allowNetwork: false })` to restore persisted catalogs without network access, or `models.refresh({ force: true })` to bypass provider freshness checks. Model reads stay synchronous and return the last restored or refreshed list.
1115
1263
 
1116
- `createProvider()` handles dynamic publication and persistence automatically. Handwritten `Provider.refreshModels()` implementations receive the read-only `context.stored` snapshot and publish through `context.publish({ persist?, update? })`. Omit `persist` to leave storage unchanged, pass a `ModelsStoreEntry` to write it, or pass `persist: null` to delete it. Publication is generation-checked; put synchronous in-memory catalog changes in `update` rather than mutating state before publication.
1264
+ `createProvider()` handles dynamic publication and persistence automatically. Handwritten `Provider.refreshModels()` implementations receive the read-only `context.stored` snapshot and publish through `context.publish({ persist?, update? })`. Omit `persist` to leave storage unchanged, pass a `ModelsStoreEntry` to write it, or pass `persist: null` to delete it. `ModelsStoreEntry.models` contains models of every type. Publication is generation-checked; put synchronous in-memory catalog changes in `update` rather than mutating state before publication.
1117
1265
 
1118
1266
  Custom models can carry `headers` (e.g. proxies behind bot detection) and `compat` flags. `Models.getAuth(model)` includes those model headers, and stream methods merge them before explicit request headers and `transformHeaders`. See [OpenAI Compatibility Settings](#openai-compatibility-settings).
1119
1267
 
@@ -1149,12 +1297,13 @@ const ollamaReasoningModel: Model<'openai-completions'> = {
1149
1297
 
1150
1298
  ### Calling API Implementations Directly
1151
1299
 
1152
- The API implementations are importable on their own. Each module exports exactly `stream` and `streamSimple` with that API's full option typing. Direct calls bypass provider auth — pass `apiKey` explicitly:
1300
+ The API implementations are importable on their own. Each module exports exactly `stream` and `streamSimple` with that API's full option typing. Direct calls bypass provider auth and context normalization — pass `apiKey` explicitly and wrap the context in `normalizeContext()`:
1153
1301
 
1154
1302
  ```typescript
1303
+ import { normalizeContext } from '@bastani/pi-ai';
1155
1304
  import { stream } from '@bastani/pi-ai/api/anthropic-messages';
1156
1305
 
1157
- const s = stream(claudeModel, context, {
1306
+ const s = stream(claudeModel, normalizeContext(context), {
1158
1307
  apiKey: process.env.ANTHROPIC_API_KEY,
1159
1308
  thinkingEnabled: true,
1160
1309
  thinkingBudgetTokens: 2048,
@@ -1187,7 +1336,7 @@ interface OpenAICompletionsCompat {
1187
1336
  supportsDeveloperRole?: boolean; // Whether provider supports `developer` role vs `system` (default: true)
1188
1337
  supportsReasoningEffort?: boolean; // Whether provider supports `reasoning_effort` (default: true)
1189
1338
  supportsUsageInStreaming?: boolean; // Whether provider supports `stream_options: { include_usage: true }` (default: true)
1190
- supportsStrictMode?: boolean; // Whether provider supports `strict` in tool definitions (default: true)
1339
+ supportsStrictMode?: boolean; // Whether provider supports `strict` in tool definitions (default: false; enabled in metadata for capable built-in models)
1191
1340
  supportsOpenAIGrammarTools?: boolean; // Whether to emit OpenAI custom Lark/regex grammar tools; false falls back to normal function tools (default: false; the generated catalog enables it for capable models)
1192
1341
  sendSessionAffinityHeaders?: boolean; // Send session-affinity data from `sessionId` (default: true for OpenRouter, false otherwise)
1193
1342
  sessionAffinityFormat?: 'openai' | 'openai-nosession' | 'openrouter'; // Format for session affinity: 'openai' uses `prompt_cache_key`, `session_id`, `x-client-request-id`, and `x-session-affinity`; 'openai-nosession' uses `prompt_cache_key`, `x-client-request-id`, and `x-session-affinity`; 'openrouter' uses `x-session-id` (default: auto-detected)
@@ -1355,6 +1504,25 @@ const geminiResponse = await models.complete(gemini, context);
1355
1504
 
1356
1505
  All providers can handle messages from other providers — text, tool calls and results (including images), thinking blocks (transformed to tagged text), and aborted messages with partial content. This enables flexible workflows: start with a fast model, switch to a more capable one for complex reasoning, or maintain continuity across provider outages.
1357
1506
 
1507
+ ## System Messages
1508
+
1509
+ Public entry points (`Models.stream()`, `streamSimple()`, `complete()`, and `completeSimple()`) accept `Context`. They normalize `systemPrompt` and `tools` into a leading system message. Provider implementations, `ProviderStreams`, and direct API modules receive a `TranscriptContext` containing only `messages`.
1510
+
1511
+ ```typescript
1512
+ interface SystemMessage {
1513
+ role: "system";
1514
+ content: string | TextContent[];
1515
+ sections?: Record<string, string | null>;
1516
+ toolsAdded?: Tool[];
1517
+ toolsRemoved?: ToolReference[];
1518
+ timestamp: number;
1519
+ }
1520
+ ```
1521
+
1522
+ Later system messages append instructions, patch named sections (`null` removes a section), and add or remove tools. Section text is opaque and rendered verbatim, joined by blank lines. `getCurrentSystemPrompt(context.messages)` and `getCurrentTools(context.messages)` replay these changes for custom providers; do not read `context.systemPrompt` or `context.tools` inside provider implementations.
1523
+
1524
+ Models with `supportsMidConvoSystemMessages` receive updates in place. Other models receive the replayed prompt and tools as a leading checkpoint. Anthropic's `supportsMidConvoToolChanges`, OpenAI Responses' `supportsAdditionalTools`/`supportsToolSearch`, and OpenAI Completions' `supportsMidConvoToolAdditions` enable native tool transitions where representable. Unsupported transitions fall back to the current top-level tool list and may invalidate the cached prefix.
1525
+
1358
1526
  ## Context Serialization
1359
1527
 
1360
1528
  The `Context` object can be easily serialized and deserialized using standard JSON methods, making it simple to persist conversations, implement chat history, or transfer contexts between services:
@@ -1577,6 +1745,8 @@ Provider notes:
1577
1745
 
1578
1746
  **OpenAI Codex**: Requires a ChatGPT Plus or Pro subscription. Provides access to GPT-5.x Codex models with extended context windows and reasoning capabilities. The library automatically handles session-based prompt caching when `sessionId` is provided in stream options unless `cacheRetention` is `"none"`. You can set `transport` in stream options to `"sse"`, `"websocket"`, or `"auto"` for Codex Responses transport selection. When using WebSocket with a `sessionId` and cache retention enabled, connections are reused per session and expire after 5 minutes of inactivity.
1579
1747
 
1748
+ Call `cleanupSessionResources(sessionId)` when finished with a Codex session so its pooled WebSocket connection does not keep the process alive. Import it from `@bastani/pi-ai`.
1749
+
1580
1750
  **Azure OpenAI (Responses)**: Uses the Responses API only. Set `AZURE_OPENAI_API_KEY` and either `AZURE_OPENAI_BASE_URL` or `AZURE_OPENAI_RESOURCE_NAME`. `AZURE_OPENAI_BASE_URL` supports both `https://<resource>.openai.azure.com` and `https://<resource>.cognitiveservices.azure.com`; root endpoints are normalized to `.../openai/v1` automatically. Use `AZURE_OPENAI_API_VERSION` (defaults to `v1`) to override the API version if needed. Deployment names are treated as model IDs by default, override with `azureDeploymentName` or `AZURE_OPENAI_DEPLOYMENT_NAME_MAP` using comma-separated `model-id=deployment` pairs (for example `gpt-4o-mini=my-deployment,gpt-4o=prod`). Legacy deployment-based URLs are intentionally unsupported.
1581
1751
 
1582
1752
  **GitHub Copilot**: If you get "The requested model is not supported" error, enable the model manually in VS Code: open Copilot Chat, click the model selector, select the model (warning icon), and click "Enable".
@@ -1604,6 +1774,9 @@ Compat is a strict superset of the root entrypoint, so a file can switch its imp
1604
1774
  | `getEnvApiKey('openai')` | `await models.getAuth(model.provider)` |
1605
1775
  | `streamAnthropic(model, ctx, opts)` | `stream` from `@bastani/pi-ai/api/anthropic-messages`, or a provider in a collection |
1606
1776
  | `registerFauxProvider()` | `fauxProvider()` + `models.setProvider()` |
1777
+ | `getImageModel('openrouter', id)` / `generateImages(model, ctx, { apiKey })` | `models.getModelOfType('image', 'openrouter', id)` / `models.generateImages(model, ctx)` |
1778
+
1779
+ The separate `ImagesModels`/`ImagesProvider` collection that existed briefly (`createImagesModels()`, `createImagesProvider()`, `openrouterImagesProvider()`, `builtinImagesModels()`) is gone: image models now live on the regular provider. Replace `builtinImagesModels()` with `builtinModels()`, `imagesModels.getModel()` with `models.getModelOfType('image', ...)`, and `createImagesProvider({ models, api })` with `createProvider({ models, images })`. The old plural image type names are removed; use `ImageModel` and `ImageApi`, and add `type: "image"` to image model literals.
1607
1780
 
1608
1781
  ## Development
1609
1782
 
@@ -1628,11 +1801,11 @@ Create a new API implementation file (for example `bedrock-converse-stream.ts`)
1628
1801
 
1629
1802
  Add a lazy wrapper `src/api/<api-id>.lazy.ts` (`<name>Api()` via `lazyApi()`) so providers can reference the implementation without importing its SDK. Add any root-level `export type` re-exports in `src/index.ts` that should remain available from `@bastani/pi-ai`.
1630
1803
 
1631
- #### 3. Model Generation (`scripts/generate-models.ts`, `scripts/generate-image-models.ts`)
1804
+ #### 3. Model Generation (`scripts/generate-models.ts`)
1632
1805
 
1633
1806
  - Add logic to fetch and parse models from the provider's source (e.g., models.dev API)
1634
- - Map chat/tool-capable provider model data to the standardized `Model` interface via `scripts/generate-models.ts`; hydration groups the ignored `src/providers/data/<id>.json` values by API, while stable `src/providers/<id>.models.ts` wrappers derive exact model/API types directly from those JSON keys
1635
- - Map image-generation provider model data to the standardized `ImagesModel` interface via `scripts/generate-image-models.ts`
1807
+ - Map chat/tool-capable provider data to `Model`, image-generation data to `ImageModel`, and models.dev `type: "decision"` entries to `ClassifierModel`; hydration groups the ignored `src/providers/data/<id>.json` values by API while stable `src/providers/<id>.models.ts` wrappers derive exact model/API types directly from those JSON keys
1808
+ - Keep model ids unique within each provider and model type; emit separate entries when an upstream model supports multiple operations
1636
1809
  - Handle provider-specific quirks (pricing format, capability flags, model ID transformations)
1637
1810
 
1638
1811
  #### 4. Provider Factory (`src/providers/<id>.ts`)