@bastani/pi-ai 0.9.20-alpha.8 → 0.9.20

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 (370) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +172 -24
  3. package/dist/api/anthropic-messages.d.ts.map +1 -1
  4. package/dist/api/anthropic-messages.js +9 -3
  5. package/dist/api/anthropic-messages.js.map +1 -1
  6. package/dist/api/azure-openai-responses.d.ts.map +1 -1
  7. package/dist/api/azure-openai-responses.js +4 -1
  8. package/dist/api/azure-openai-responses.js.map +1 -1
  9. package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
  10. package/dist/api/bedrock-converse-stream.js +5 -3
  11. package/dist/api/bedrock-converse-stream.js.map +1 -1
  12. package/dist/api/cloudflare-workers-ai-system-one.d.ts +4 -0
  13. package/dist/api/cloudflare-workers-ai-system-one.d.ts.map +1 -0
  14. package/dist/api/cloudflare-workers-ai-system-one.js +43 -0
  15. package/dist/api/cloudflare-workers-ai-system-one.js.map +1 -0
  16. package/dist/api/cloudflare-workers-ai-system-one.lazy.d.ts +3 -0
  17. package/dist/api/cloudflare-workers-ai-system-one.lazy.d.ts.map +1 -0
  18. package/dist/api/cloudflare-workers-ai-system-one.lazy.js +4 -0
  19. package/dist/api/cloudflare-workers-ai-system-one.lazy.js.map +1 -0
  20. package/dist/api/cloudflare.d.ts +2 -0
  21. package/dist/api/cloudflare.d.ts.map +1 -1
  22. package/dist/api/cloudflare.js +2 -0
  23. package/dist/api/cloudflare.js.map +1 -1
  24. package/dist/api/constrained-sampling.d.ts +8 -3
  25. package/dist/api/constrained-sampling.d.ts.map +1 -1
  26. package/dist/api/constrained-sampling.js +29 -11
  27. package/dist/api/constrained-sampling.js.map +1 -1
  28. package/dist/api/google-generative-ai.d.ts.map +1 -1
  29. package/dist/api/google-generative-ai.js +1 -0
  30. package/dist/api/google-generative-ai.js.map +1 -1
  31. package/dist/api/google-vertex.d.ts.map +1 -1
  32. package/dist/api/google-vertex.js +1 -0
  33. package/dist/api/google-vertex.js.map +1 -1
  34. package/dist/api/mistral-conversations.d.ts.map +1 -1
  35. package/dist/api/mistral-conversations.js +3 -2
  36. package/dist/api/mistral-conversations.js.map +1 -1
  37. package/dist/api/openai-codex-responses.d.ts.map +1 -1
  38. package/dist/api/openai-codex-responses.js +20 -4
  39. package/dist/api/openai-codex-responses.js.map +1 -1
  40. package/dist/api/openai-completions.d.ts.map +1 -1
  41. package/dist/api/openai-completions.js +1 -0
  42. package/dist/api/openai-completions.js.map +1 -1
  43. package/dist/api/openai-responses-shared.d.ts +2 -1
  44. package/dist/api/openai-responses-shared.d.ts.map +1 -1
  45. package/dist/api/openai-responses-shared.js +1 -0
  46. package/dist/api/openai-responses-shared.js.map +1 -1
  47. package/dist/api/openai-responses.d.ts.map +1 -1
  48. package/dist/api/openai-responses.js +1 -0
  49. package/dist/api/openai-responses.js.map +1 -1
  50. package/dist/api/openrouter-images.d.ts +2 -1
  51. package/dist/api/openrouter-images.d.ts.map +1 -1
  52. package/dist/api/openrouter-images.js +1 -0
  53. package/dist/api/openrouter-images.js.map +1 -1
  54. package/dist/api/openrouter-images.lazy.d.ts.map +1 -1
  55. package/dist/api/openrouter-images.lazy.js.map +1 -1
  56. package/dist/api/pi-messages.d.ts.map +1 -1
  57. package/dist/api/pi-messages.js +1 -0
  58. package/dist/api/pi-messages.js.map +1 -1
  59. package/dist/api/simple-options.d.ts.map +1 -1
  60. package/dist/api/simple-options.js +1 -0
  61. package/dist/api/simple-options.js.map +1 -1
  62. package/dist/api/system-one-shared.d.ts +23 -0
  63. package/dist/api/system-one-shared.d.ts.map +1 -0
  64. package/dist/api/system-one-shared.js +170 -0
  65. package/dist/api/system-one-shared.js.map +1 -0
  66. package/dist/api/typesafe-system-one.d.ts +4 -0
  67. package/dist/api/typesafe-system-one.d.ts.map +1 -0
  68. package/dist/api/typesafe-system-one.js +19 -0
  69. package/dist/api/typesafe-system-one.js.map +1 -0
  70. package/dist/api/typesafe-system-one.lazy.d.ts +3 -0
  71. package/dist/api/typesafe-system-one.lazy.d.ts.map +1 -0
  72. package/dist/api/typesafe-system-one.lazy.js +4 -0
  73. package/dist/api/typesafe-system-one.lazy.js.map +1 -0
  74. package/dist/auth/resolve.d.ts +2 -8
  75. package/dist/auth/resolve.d.ts.map +1 -1
  76. package/dist/auth/resolve.js +3 -19
  77. package/dist/auth/resolve.js.map +1 -1
  78. package/dist/env-api-keys.d.ts.map +1 -1
  79. package/dist/env-api-keys.js +1 -0
  80. package/dist/env-api-keys.js.map +1 -1
  81. package/dist/image-models.d.ts +19 -8
  82. package/dist/image-models.d.ts.map +1 -1
  83. package/dist/image-models.js +14 -13
  84. package/dist/image-models.js.map +1 -1
  85. package/dist/images-api-registry.d.ts +7 -7
  86. package/dist/images-api-registry.d.ts.map +1 -1
  87. package/dist/images-api-registry.js.map +1 -1
  88. package/dist/images.d.ts +7 -2
  89. package/dist/images.d.ts.map +1 -1
  90. package/dist/images.js +5 -0
  91. package/dist/images.js.map +1 -1
  92. package/dist/index.d.ts +0 -1
  93. package/dist/index.d.ts.map +1 -1
  94. package/dist/index.js +0 -1
  95. package/dist/index.js.map +1 -1
  96. package/dist/model-catalog.d.ts +25 -9
  97. package/dist/model-catalog.d.ts.map +1 -1
  98. package/dist/model-catalog.js +14 -2
  99. package/dist/model-catalog.js.map +1 -1
  100. package/dist/models-store.d.ts +3 -2
  101. package/dist/models-store.d.ts.map +1 -1
  102. package/dist/models-store.js.map +1 -1
  103. package/dist/models.d.ts +95 -28
  104. package/dist/models.d.ts.map +1 -1
  105. package/dist/models.generated.d.ts +131 -41
  106. package/dist/models.generated.d.ts.map +1 -1
  107. package/dist/models.generated.js +131 -41
  108. package/dist/models.generated.js.map +1 -1
  109. package/dist/models.js +155 -28
  110. package/dist/models.js.map +1 -1
  111. package/dist/providers/all.d.ts +19 -13
  112. package/dist/providers/all.d.ts.map +1 -1
  113. package/dist/providers/all.js +25 -21
  114. package/dist/providers/all.js.map +1 -1
  115. package/dist/providers/amazon-bedrock.models.d.ts +4 -2
  116. package/dist/providers/amazon-bedrock.models.d.ts.map +1 -1
  117. package/dist/providers/amazon-bedrock.models.js +4 -2
  118. package/dist/providers/amazon-bedrock.models.js.map +1 -1
  119. package/dist/providers/ant-ling.models.d.ts +4 -2
  120. package/dist/providers/ant-ling.models.d.ts.map +1 -1
  121. package/dist/providers/ant-ling.models.js +4 -2
  122. package/dist/providers/ant-ling.models.js.map +1 -1
  123. package/dist/providers/anthropic.models.d.ts +4 -2
  124. package/dist/providers/anthropic.models.d.ts.map +1 -1
  125. package/dist/providers/anthropic.models.js +4 -2
  126. package/dist/providers/anthropic.models.js.map +1 -1
  127. package/dist/providers/azure-openai-responses.models.d.ts +4 -2
  128. package/dist/providers/azure-openai-responses.models.d.ts.map +1 -1
  129. package/dist/providers/azure-openai-responses.models.js +4 -2
  130. package/dist/providers/azure-openai-responses.models.js.map +1 -1
  131. package/dist/providers/baseten.models.d.ts +4 -2
  132. package/dist/providers/baseten.models.d.ts.map +1 -1
  133. package/dist/providers/baseten.models.js +4 -2
  134. package/dist/providers/baseten.models.js.map +1 -1
  135. package/dist/providers/cerebras.models.d.ts +4 -2
  136. package/dist/providers/cerebras.models.d.ts.map +1 -1
  137. package/dist/providers/cerebras.models.js +4 -2
  138. package/dist/providers/cerebras.models.js.map +1 -1
  139. package/dist/providers/cloudflare-ai-gateway.models.d.ts +4 -2
  140. package/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -1
  141. package/dist/providers/cloudflare-ai-gateway.models.js +4 -2
  142. package/dist/providers/cloudflare-ai-gateway.models.js.map +1 -1
  143. package/dist/providers/cloudflare-stream.d.ts +6 -2
  144. package/dist/providers/cloudflare-stream.d.ts.map +1 -1
  145. package/dist/providers/cloudflare-stream.js +6 -0
  146. package/dist/providers/cloudflare-stream.js.map +1 -1
  147. package/dist/providers/cloudflare-workers-ai.d.ts.map +1 -1
  148. package/dist/providers/cloudflare-workers-ai.js +10 -3
  149. package/dist/providers/cloudflare-workers-ai.js.map +1 -1
  150. package/dist/providers/cloudflare-workers-ai.models.d.ts +4 -2
  151. package/dist/providers/cloudflare-workers-ai.models.d.ts.map +1 -1
  152. package/dist/providers/cloudflare-workers-ai.models.js +4 -2
  153. package/dist/providers/cloudflare-workers-ai.models.js.map +1 -1
  154. package/dist/providers/data/.manifest.json +1 -1
  155. package/dist/providers/data/amazon-bedrock.json +1 -1
  156. package/dist/providers/data/ant-ling.json +1 -1
  157. package/dist/providers/data/anthropic.json +1 -1
  158. package/dist/providers/data/azure-openai-responses.json +1 -1
  159. package/dist/providers/data/baseten.json +1 -1
  160. package/dist/providers/data/cerebras.json +1 -1
  161. package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  162. package/dist/providers/data/cloudflare-workers-ai.json +1 -1
  163. package/dist/providers/data/deepseek.json +1 -1
  164. package/dist/providers/data/fireworks.json +1 -1
  165. package/dist/providers/data/github-copilot.json +1 -1
  166. package/dist/providers/data/google-vertex.json +1 -1
  167. package/dist/providers/data/google.json +1 -1
  168. package/dist/providers/data/groq.json +1 -1
  169. package/dist/providers/data/huggingface.json +1 -1
  170. package/dist/providers/data/kimi-coding.json +1 -1
  171. package/dist/providers/data/meta.json +1 -1
  172. package/dist/providers/data/minimax-cn.json +1 -1
  173. package/dist/providers/data/minimax.json +1 -1
  174. package/dist/providers/data/mistral.json +1 -1
  175. package/dist/providers/data/moonshotai-cn.json +1 -1
  176. package/dist/providers/data/moonshotai.json +1 -1
  177. package/dist/providers/data/nvidia.json +1 -1
  178. package/dist/providers/data/openai-codex.json +1 -1
  179. package/dist/providers/data/openai.json +1 -1
  180. package/dist/providers/data/opencode-go.json +1 -1
  181. package/dist/providers/data/opencode.json +1 -1
  182. package/dist/providers/data/openrouter.json +1 -1
  183. package/dist/providers/data/qwen-token-plan-cn.json +1 -1
  184. package/dist/providers/data/qwen-token-plan-individual.json +1 -1
  185. package/dist/providers/data/qwen-token-plan.json +1 -1
  186. package/dist/providers/data/radius.json +1 -1
  187. package/dist/providers/data/together.json +1 -1
  188. package/dist/providers/data/typesafe.json +1 -0
  189. package/dist/providers/data/vercel-ai-gateway.json +1 -1
  190. package/dist/providers/data/xai.json +1 -1
  191. package/dist/providers/data/xiaomi-token-plan-ams.json +1 -1
  192. package/dist/providers/data/xiaomi-token-plan-cn.json +1 -1
  193. package/dist/providers/data/xiaomi-token-plan-sgp.json +1 -1
  194. package/dist/providers/data/xiaomi.json +1 -1
  195. package/dist/providers/data/zai-coding-cn.json +1 -1
  196. package/dist/providers/data/zai.json +1 -1
  197. package/dist/providers/deepseek.models.d.ts +4 -2
  198. package/dist/providers/deepseek.models.d.ts.map +1 -1
  199. package/dist/providers/deepseek.models.js +4 -2
  200. package/dist/providers/deepseek.models.js.map +1 -1
  201. package/dist/providers/fireworks.models.d.ts +4 -2
  202. package/dist/providers/fireworks.models.d.ts.map +1 -1
  203. package/dist/providers/fireworks.models.js +4 -2
  204. package/dist/providers/fireworks.models.js.map +1 -1
  205. package/dist/providers/github-copilot.models.d.ts +4 -2
  206. package/dist/providers/github-copilot.models.d.ts.map +1 -1
  207. package/dist/providers/github-copilot.models.js +4 -2
  208. package/dist/providers/github-copilot.models.js.map +1 -1
  209. package/dist/providers/google-vertex.models.d.ts +4 -2
  210. package/dist/providers/google-vertex.models.d.ts.map +1 -1
  211. package/dist/providers/google-vertex.models.js +4 -2
  212. package/dist/providers/google-vertex.models.js.map +1 -1
  213. package/dist/providers/google.models.d.ts +4 -2
  214. package/dist/providers/google.models.d.ts.map +1 -1
  215. package/dist/providers/google.models.js +4 -2
  216. package/dist/providers/google.models.js.map +1 -1
  217. package/dist/providers/groq.models.d.ts +4 -2
  218. package/dist/providers/groq.models.d.ts.map +1 -1
  219. package/dist/providers/groq.models.js +4 -2
  220. package/dist/providers/groq.models.js.map +1 -1
  221. package/dist/providers/huggingface.models.d.ts +4 -2
  222. package/dist/providers/huggingface.models.d.ts.map +1 -1
  223. package/dist/providers/huggingface.models.js +4 -2
  224. package/dist/providers/huggingface.models.js.map +1 -1
  225. package/dist/providers/images/register-builtins.d.ts +1 -1
  226. package/dist/providers/images/register-builtins.d.ts.map +1 -1
  227. package/dist/providers/images/register-builtins.js.map +1 -1
  228. package/dist/providers/kimi-coding.models.d.ts +4 -2
  229. package/dist/providers/kimi-coding.models.d.ts.map +1 -1
  230. package/dist/providers/kimi-coding.models.js +4 -2
  231. package/dist/providers/kimi-coding.models.js.map +1 -1
  232. package/dist/providers/meta.models.d.ts +4 -2
  233. package/dist/providers/meta.models.d.ts.map +1 -1
  234. package/dist/providers/meta.models.js +4 -2
  235. package/dist/providers/meta.models.js.map +1 -1
  236. package/dist/providers/minimax-cn.models.d.ts +4 -2
  237. package/dist/providers/minimax-cn.models.d.ts.map +1 -1
  238. package/dist/providers/minimax-cn.models.js +4 -2
  239. package/dist/providers/minimax-cn.models.js.map +1 -1
  240. package/dist/providers/minimax.models.d.ts +4 -2
  241. package/dist/providers/minimax.models.d.ts.map +1 -1
  242. package/dist/providers/minimax.models.js +4 -2
  243. package/dist/providers/minimax.models.js.map +1 -1
  244. package/dist/providers/mistral.models.d.ts +4 -2
  245. package/dist/providers/mistral.models.d.ts.map +1 -1
  246. package/dist/providers/mistral.models.js +4 -2
  247. package/dist/providers/mistral.models.js.map +1 -1
  248. package/dist/providers/moonshotai-cn.models.d.ts +4 -2
  249. package/dist/providers/moonshotai-cn.models.d.ts.map +1 -1
  250. package/dist/providers/moonshotai-cn.models.js +4 -2
  251. package/dist/providers/moonshotai-cn.models.js.map +1 -1
  252. package/dist/providers/moonshotai.models.d.ts +4 -2
  253. package/dist/providers/moonshotai.models.d.ts.map +1 -1
  254. package/dist/providers/moonshotai.models.js +4 -2
  255. package/dist/providers/moonshotai.models.js.map +1 -1
  256. package/dist/providers/nvidia.models.d.ts +4 -2
  257. package/dist/providers/nvidia.models.d.ts.map +1 -1
  258. package/dist/providers/nvidia.models.js +4 -2
  259. package/dist/providers/nvidia.models.js.map +1 -1
  260. package/dist/providers/openai-codex.models.d.ts +4 -2
  261. package/dist/providers/openai-codex.models.d.ts.map +1 -1
  262. package/dist/providers/openai-codex.models.js +4 -2
  263. package/dist/providers/openai-codex.models.js.map +1 -1
  264. package/dist/providers/openai.models.d.ts +4 -2
  265. package/dist/providers/openai.models.d.ts.map +1 -1
  266. package/dist/providers/openai.models.js +4 -2
  267. package/dist/providers/openai.models.js.map +1 -1
  268. package/dist/providers/opencode-go.models.d.ts +4 -2
  269. package/dist/providers/opencode-go.models.d.ts.map +1 -1
  270. package/dist/providers/opencode-go.models.js +4 -2
  271. package/dist/providers/opencode-go.models.js.map +1 -1
  272. package/dist/providers/opencode.models.d.ts +4 -2
  273. package/dist/providers/opencode.models.d.ts.map +1 -1
  274. package/dist/providers/opencode.models.js +4 -2
  275. package/dist/providers/opencode.models.js.map +1 -1
  276. package/dist/providers/openrouter.d.ts.map +1 -1
  277. package/dist/providers/openrouter.js +11 -2
  278. package/dist/providers/openrouter.js.map +1 -1
  279. package/dist/providers/openrouter.models.d.ts +4 -2
  280. package/dist/providers/openrouter.models.d.ts.map +1 -1
  281. package/dist/providers/openrouter.models.js +4 -2
  282. package/dist/providers/openrouter.models.js.map +1 -1
  283. package/dist/providers/qwen-token-plan-cn.models.d.ts +4 -2
  284. package/dist/providers/qwen-token-plan-cn.models.d.ts.map +1 -1
  285. package/dist/providers/qwen-token-plan-cn.models.js +4 -2
  286. package/dist/providers/qwen-token-plan-cn.models.js.map +1 -1
  287. package/dist/providers/qwen-token-plan-individual.models.d.ts +4 -2
  288. package/dist/providers/qwen-token-plan-individual.models.d.ts.map +1 -1
  289. package/dist/providers/qwen-token-plan-individual.models.js +4 -2
  290. package/dist/providers/qwen-token-plan-individual.models.js.map +1 -1
  291. package/dist/providers/qwen-token-plan.models.d.ts +4 -2
  292. package/dist/providers/qwen-token-plan.models.d.ts.map +1 -1
  293. package/dist/providers/qwen-token-plan.models.js +4 -2
  294. package/dist/providers/qwen-token-plan.models.js.map +1 -1
  295. package/dist/providers/radius.models.d.ts +4 -2
  296. package/dist/providers/radius.models.d.ts.map +1 -1
  297. package/dist/providers/radius.models.js +4 -2
  298. package/dist/providers/radius.models.js.map +1 -1
  299. package/dist/providers/together.models.d.ts +4 -2
  300. package/dist/providers/together.models.d.ts.map +1 -1
  301. package/dist/providers/together.models.js +4 -2
  302. package/dist/providers/together.models.js.map +1 -1
  303. package/dist/providers/typesafe.d.ts +3 -0
  304. package/dist/providers/typesafe.d.ts.map +1 -0
  305. package/dist/providers/typesafe.js +18 -0
  306. package/dist/providers/typesafe.js.map +1 -0
  307. package/dist/providers/typesafe.models.d.ts +5 -0
  308. package/dist/providers/typesafe.models.d.ts.map +1 -0
  309. package/dist/providers/typesafe.models.js +8 -0
  310. package/dist/providers/typesafe.models.js.map +1 -0
  311. package/dist/providers/vercel-ai-gateway.models.d.ts +4 -2
  312. package/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
  313. package/dist/providers/vercel-ai-gateway.models.js +4 -2
  314. package/dist/providers/vercel-ai-gateway.models.js.map +1 -1
  315. package/dist/providers/xai.models.d.ts +4 -2
  316. package/dist/providers/xai.models.d.ts.map +1 -1
  317. package/dist/providers/xai.models.js +4 -2
  318. package/dist/providers/xai.models.js.map +1 -1
  319. package/dist/providers/xiaomi-token-plan-ams.models.d.ts +4 -2
  320. package/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -1
  321. package/dist/providers/xiaomi-token-plan-ams.models.js +4 -2
  322. package/dist/providers/xiaomi-token-plan-ams.models.js.map +1 -1
  323. package/dist/providers/xiaomi-token-plan-cn.models.d.ts +4 -2
  324. package/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -1
  325. package/dist/providers/xiaomi-token-plan-cn.models.js +4 -2
  326. package/dist/providers/xiaomi-token-plan-cn.models.js.map +1 -1
  327. package/dist/providers/xiaomi-token-plan-sgp.models.d.ts +4 -2
  328. package/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -1
  329. package/dist/providers/xiaomi-token-plan-sgp.models.js +4 -2
  330. package/dist/providers/xiaomi-token-plan-sgp.models.js.map +1 -1
  331. package/dist/providers/xiaomi.models.d.ts +4 -2
  332. package/dist/providers/xiaomi.models.d.ts.map +1 -1
  333. package/dist/providers/xiaomi.models.js +4 -2
  334. package/dist/providers/xiaomi.models.js.map +1 -1
  335. package/dist/providers/zai-coding-cn.models.d.ts +4 -2
  336. package/dist/providers/zai-coding-cn.models.d.ts.map +1 -1
  337. package/dist/providers/zai-coding-cn.models.js +4 -2
  338. package/dist/providers/zai-coding-cn.models.js.map +1 -1
  339. package/dist/providers/zai.models.d.ts +4 -2
  340. package/dist/providers/zai.models.d.ts.map +1 -1
  341. package/dist/providers/zai.models.js +4 -2
  342. package/dist/providers/zai.models.js.map +1 -1
  343. package/dist/types.d.ts +109 -26
  344. package/dist/types.d.ts.map +1 -1
  345. package/dist/types.js.map +1 -1
  346. package/dist/utils/headers.d.ts +1 -1
  347. package/dist/utils/headers.d.ts.map +1 -1
  348. package/dist/utils/headers.js +10 -8
  349. package/dist/utils/headers.js.map +1 -1
  350. package/dist/utils/model-operations.d.ts +11 -0
  351. package/dist/utils/model-operations.d.ts.map +1 -0
  352. package/dist/utils/model-operations.js +47 -0
  353. package/dist/utils/model-operations.js.map +1 -0
  354. package/dist/utils/models-error.d.ts +8 -0
  355. package/dist/utils/models-error.d.ts.map +1 -0
  356. package/dist/utils/models-error.js +19 -0
  357. package/dist/utils/models-error.js.map +1 -0
  358. package/package.json +1 -2
  359. package/dist/image-models.generated.d.ts +0 -830
  360. package/dist/image-models.generated.d.ts.map +0 -1
  361. package/dist/image-models.generated.js +0 -832
  362. package/dist/image-models.generated.js.map +0 -1
  363. package/dist/images-models.d.ts +0 -95
  364. package/dist/images-models.d.ts.map +0 -1
  365. package/dist/images-models.js +0 -143
  366. package/dist/images-models.js.map +0 -1
  367. package/dist/providers/openrouter-images.d.ts +0 -3
  368. package/dist/providers/openrouter-images.d.ts.map +0 -1
  369. package/dist/providers/openrouter-images.js +0 -22
  370. package/dist/providers/openrouter-images.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,74 @@ This package is a Bastani fork of `@earendil-works/pi-ai`. Upstream history at t
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.20] - 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
+ - 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.
13
+
14
+ ### Added
15
+
16
+ - 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)).
17
+ - 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.
18
+ - 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.
19
+ - 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.
20
+ - Added Claude Opus 5.5, GPT-6 Sol, and GPT-6 Luna to the GitHub Copilot catalog.
21
+ - 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.
22
+ - 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.
23
+ - Added Claude Opus 5.5 to the built-in Anthropic model catalog with adaptive thinking, 1M context, and official pricing metadata.
24
+ - 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.
25
+ - Added Meta provider (Model API key and Muse subscription OAuth) with Muse Spark models.
26
+ - 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)).
27
+ - Added Grok 4.7 to the built-in xAI model catalog with long-context pricing metadata.
28
+ - Chronological system messages with named prompt patches and tool additions/removals, including native provider transitions where supported and replay checkpoints elsewhere.
29
+ - A static Radius catalog with authenticated dynamic refresh, refreshed image models, and prompt-cache lifetime metadata for direct Anthropic models.
30
+
31
+ ### Fixed
32
+
33
+ - 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.
34
+ - 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)).
35
+ - Rejected malformed TypeSafe classifier answers when the returned choice, score, confidence, or probability falls outside the submitted question's bounds.
36
+ - 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.
37
+ - 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.
38
+ - 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`.
39
+ - 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.
40
+ - 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)).
41
+ - 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)).
42
+ - 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.
43
+ - Documented Fireworks deferred tool loading against chronological system-message `toolsAdded`/`toolsRemoved` instead of the removed tool-result `addedToolNames` field.
44
+ - 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)).
45
+ - 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)).
46
+ - Kept Kimi Coding models available after the upstream catalog split into regional coding plans, preserving Atomic's existing kimi.com endpoint.
47
+ - Model catalog declarations preserve JSON import attributes for strict NodeNext consumers without requiring `skipLibCheck` ([#3105](https://github.com/bastani-inc/atomic/issues/3105)).
48
+ - Credential screening now recognizes `TYPESAFE_API_KEY` instead of `TYPESAFE_AI_API_KEY`, matching the renamed TypeSafe Jev environment variable.
49
+ - 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)).
50
+ - 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)).
51
+ - 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)).
52
+ - Fixed Amazon Bedrock one-hour cache writes being priced at the five-minute rate ([#9457](https://github.com/earendil-works/pi/issues/9457)).
53
+ - Fixed Baseten requests to send session-affinity headers from `sessionId` for automatic prompt-cache routing ([#9629](https://github.com/earendil-works/pi/issues/9629)).
54
+
55
+ ## [0.9.20-alpha.9] - 2026-09-24
56
+
57
+ ### Breaking Changes
58
+
59
+ - 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.
60
+
61
+ ### Added
62
+
63
+ - 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)).
64
+ - 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.
65
+ - 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.
66
+ - 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.
67
+
68
+ ### Fixed
69
+
70
+ - 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.
71
+ - 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)).
72
+ - Rejected malformed TypeSafe classifier answers when the returned choice, score, confidence, or probability falls outside the submitted question's bounds.
73
+ - 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.
74
+
7
75
  ## [0.9.20-alpha.7] - 2026-09-22
8
76
 
9
77
  ### Added
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 [`6671c604766b3670ed95f405aa7856835d0ca702`](https://github.com/earendil-works/pi/commit/6671c604766b3670ed95f405aa7856835d0ca702), 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,6 +42,7 @@ 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)
@@ -65,6 +67,8 @@ Unified LLM API with provider collections, automatic auth resolution, token and
65
67
  - **Ant Ling**
66
68
  - **Azure OpenAI (Responses)**
67
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)
68
72
  - **DeepSeek**
69
73
  - **NVIDIA NIM**
70
74
  - **Anthropic**
@@ -277,7 +281,7 @@ Reads are synchronous and return the last-known lists:
277
281
  const providers = models.getProviders(); // registered Provider objects
278
282
  const provider = models.getProvider('anthropic'); // one provider
279
283
 
280
- const all = models.getModels(); // every model across providers
284
+ const all = models.getModels(); // every chat model across providers
281
285
  const anthropicModels = models.getModels('anthropic');
282
286
  const model = models.getModel('anthropic', 'claude-sonnet-4-5');
283
287
 
@@ -290,7 +294,31 @@ for (const m of anthropicModels) {
290
294
  }
291
295
  ```
292
296
 
293
- 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:
294
322
 
295
323
  ```typescript
296
324
  import { hasApi } from '@bastani/pi-ai';
@@ -307,11 +335,26 @@ if (m && hasApi(m, 'anthropic-messages')) {
307
335
  For tooling that wants the generated built-in catalog with full literal typing (provider and model IDs auto-complete), independent of any collection:
308
336
 
309
337
  ```typescript
310
- 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';
311
348
 
312
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');
313
353
  const providers = getBuiltinProviders();
314
- 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[]
315
358
  ```
316
359
 
317
360
  ### Dynamic Providers
@@ -422,6 +465,8 @@ Built-in providers resolve these env vars (Node.js; in browsers pass `apiKey` ex
422
465
  | Ant Ling | `ANT_LING_API_KEY` |
423
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`. |
424
467
  | Anthropic | `ANTHROPIC_API_KEY` or `ANTHROPIC_OAUTH_TOKEN` |
468
+ | Radius | `RADIUS_API_KEY` |
469
+ | TypeSafe | `TYPESAFE_API_KEY` |
425
470
  | DeepSeek | `DEEPSEEK_API_KEY` |
426
471
  | NVIDIA NIM | `NVIDIA_API_KEY` |
427
472
  | Google | `GEMINI_API_KEY` |
@@ -725,20 +770,19 @@ for (const block of response.content) {
725
770
 
726
771
  ## Image Generation
727
772
 
728
- 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.
729
774
 
730
775
  ### Basic Image Generation
731
776
 
732
777
  ```typescript
733
- import { builtinImagesModels } from '@bastani/pi-ai/providers/all';
778
+ import { builtinModels } from '@bastani/pi-ai/providers/all';
734
779
 
735
- // Every built-in image-generation provider; accepts the same options as createModels()
736
- const imagesModels = builtinImagesModels();
780
+ const models = builtinModels();
737
781
 
738
- const model = imagesModels.getModel('openrouter', 'google/gemini-2.5-flash-image')!;
782
+ const model = models.getModelOfType('image', 'openrouter', 'google/gemini-2.5-flash-image')!;
739
783
 
740
784
  // Auth resolves through the provider (OPENROUTER_API_KEY here); explicit apiKey wins
741
- const result = await imagesModels.generateImages(model, {
785
+ const result = await models.generateImages(model, {
742
786
  input: [{ type: 'text', text: 'Generate a red circle on a plain white background.' }]
743
787
  });
744
788
 
@@ -752,7 +796,33 @@ for (const block of result.output) {
752
796
  }
753
797
  ```
754
798
 
755
- 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
+ ```
756
826
 
757
827
  The old global API (`getImageModel()` / `getImageModels()` / `getImageProviders()` / `generateImages()`) remains available on the [compat entrypoint](#migrating-from-the-old-global-api):
758
828
 
@@ -773,7 +843,7 @@ Some models also support image input:
773
843
  import { readFileSync } from 'fs';
774
844
 
775
845
  const imageBuffer = readFileSync('input.png');
776
- const result = await imagesModels.generateImages(model, {
846
+ const result = await models.generateImages(model, {
777
847
  input: [
778
848
  { type: 'text', text: 'Create a variation of this image with a blue background.' },
779
849
  { type: 'image', data: imageBuffer.toString('base64'), mimeType: 'image/png' }
@@ -784,14 +854,13 @@ const result = await imagesModels.generateImages(model, {
784
854
  Check capabilities on the model metadata:
785
855
 
786
856
  ```typescript
787
- console.log(model.input); // ['text', 'image']
788
- 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']
789
859
  ```
790
860
 
791
861
  ### Notes and Limitations
792
862
 
793
- - Image models live in `ImagesModels` collections, chat models in `Models` collections; the two are separate surfaces.
794
- - 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.
795
864
  - Image-generation models do not participate in tool calling.
796
865
  - Outputs are returned in `AssistantImages.output` and can include both base64-encoded `ImageContent` blocks and `TextContent` blocks.
797
866
  - Some models return only images, others return images plus text. Check `model.output`.
@@ -800,6 +869,63 @@ console.log(model.output); // ['image'] or ['image', 'text']
800
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.
801
870
  - At the moment, image generation is available through only one provider, OpenRouter.
802
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
+
803
929
  ## Thinking/Reasoning
804
930
 
805
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.
@@ -1008,11 +1134,30 @@ const response = await models.complete(model, context, {
1008
1134
 
1009
1135
  The callback is supported by `stream`, `complete`, `streamSimple`, and `completeSimple`.
1010
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
+
1011
1156
  ## Custom Providers
1012
1157
 
1013
1158
  ### createProvider()
1014
1159
 
1015
- `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:
1016
1161
 
1017
1162
  ```typescript
1018
1163
  import { createModels, createProvider, envApiKeyAuth, type Model } from '@bastani/pi-ai';
@@ -1094,7 +1239,7 @@ const tenantGateway = createProvider({
1094
1239
  });
1095
1240
  ```
1096
1241
 
1097
- 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.
1098
1243
 
1099
1244
  ```typescript
1100
1245
  const models = createModels({ credentials, modelsStore });
@@ -1116,7 +1261,7 @@ for (const [provider, error] of result.errors) console.error(provider, error);
1116
1261
 
1117
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.
1118
1263
 
1119
- `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.
1120
1265
 
1121
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).
1122
1267
 
@@ -1629,6 +1774,9 @@ Compat is a strict superset of the root entrypoint, so a file can switch its imp
1629
1774
  | `getEnvApiKey('openai')` | `await models.getAuth(model.provider)` |
1630
1775
  | `streamAnthropic(model, ctx, opts)` | `stream` from `@bastani/pi-ai/api/anthropic-messages`, or a provider in a collection |
1631
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.
1632
1780
 
1633
1781
  ## Development
1634
1782
 
@@ -1653,11 +1801,11 @@ Create a new API implementation file (for example `bedrock-converse-stream.ts`)
1653
1801
 
1654
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`.
1655
1803
 
1656
- #### 3. Model Generation (`scripts/generate-models.ts`, `scripts/generate-image-models.ts`)
1804
+ #### 3. Model Generation (`scripts/generate-models.ts`)
1657
1805
 
1658
1806
  - Add logic to fetch and parse models from the provider's source (e.g., models.dev API)
1659
- - 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
1660
- - 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
1661
1809
  - Handle provider-specific quirks (pricing format, capability flags, model ID transformations)
1662
1810
 
1663
1811
  #### 4. Provider Factory (`src/providers/<id>.ts`)