@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.
- package/CHANGELOG.md +68 -0
- package/README.md +172 -24
- package/dist/api/anthropic-messages.d.ts.map +1 -1
- package/dist/api/anthropic-messages.js +9 -3
- package/dist/api/anthropic-messages.js.map +1 -1
- package/dist/api/azure-openai-responses.d.ts.map +1 -1
- package/dist/api/azure-openai-responses.js +4 -1
- package/dist/api/azure-openai-responses.js.map +1 -1
- package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
- package/dist/api/bedrock-converse-stream.js +5 -3
- package/dist/api/bedrock-converse-stream.js.map +1 -1
- package/dist/api/cloudflare-workers-ai-system-one.d.ts +4 -0
- package/dist/api/cloudflare-workers-ai-system-one.d.ts.map +1 -0
- package/dist/api/cloudflare-workers-ai-system-one.js +43 -0
- package/dist/api/cloudflare-workers-ai-system-one.js.map +1 -0
- package/dist/api/cloudflare-workers-ai-system-one.lazy.d.ts +3 -0
- package/dist/api/cloudflare-workers-ai-system-one.lazy.d.ts.map +1 -0
- package/dist/api/cloudflare-workers-ai-system-one.lazy.js +4 -0
- package/dist/api/cloudflare-workers-ai-system-one.lazy.js.map +1 -0
- package/dist/api/cloudflare.d.ts +2 -0
- package/dist/api/cloudflare.d.ts.map +1 -1
- package/dist/api/cloudflare.js +2 -0
- package/dist/api/cloudflare.js.map +1 -1
- package/dist/api/constrained-sampling.d.ts +8 -3
- package/dist/api/constrained-sampling.d.ts.map +1 -1
- package/dist/api/constrained-sampling.js +29 -11
- package/dist/api/constrained-sampling.js.map +1 -1
- package/dist/api/google-generative-ai.d.ts.map +1 -1
- package/dist/api/google-generative-ai.js +1 -0
- package/dist/api/google-generative-ai.js.map +1 -1
- package/dist/api/google-vertex.d.ts.map +1 -1
- package/dist/api/google-vertex.js +1 -0
- package/dist/api/google-vertex.js.map +1 -1
- package/dist/api/mistral-conversations.d.ts.map +1 -1
- package/dist/api/mistral-conversations.js +3 -2
- package/dist/api/mistral-conversations.js.map +1 -1
- package/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/dist/api/openai-codex-responses.js +20 -4
- package/dist/api/openai-codex-responses.js.map +1 -1
- package/dist/api/openai-completions.d.ts.map +1 -1
- package/dist/api/openai-completions.js +1 -0
- package/dist/api/openai-completions.js.map +1 -1
- package/dist/api/openai-responses-shared.d.ts +2 -1
- package/dist/api/openai-responses-shared.d.ts.map +1 -1
- package/dist/api/openai-responses-shared.js +1 -0
- package/dist/api/openai-responses-shared.js.map +1 -1
- package/dist/api/openai-responses.d.ts.map +1 -1
- package/dist/api/openai-responses.js +1 -0
- package/dist/api/openai-responses.js.map +1 -1
- package/dist/api/openrouter-images.d.ts +2 -1
- package/dist/api/openrouter-images.d.ts.map +1 -1
- package/dist/api/openrouter-images.js +1 -0
- package/dist/api/openrouter-images.js.map +1 -1
- package/dist/api/openrouter-images.lazy.d.ts.map +1 -1
- package/dist/api/openrouter-images.lazy.js.map +1 -1
- package/dist/api/pi-messages.d.ts.map +1 -1
- package/dist/api/pi-messages.js +1 -0
- package/dist/api/pi-messages.js.map +1 -1
- package/dist/api/simple-options.d.ts.map +1 -1
- package/dist/api/simple-options.js +1 -0
- package/dist/api/simple-options.js.map +1 -1
- package/dist/api/system-one-shared.d.ts +23 -0
- package/dist/api/system-one-shared.d.ts.map +1 -0
- package/dist/api/system-one-shared.js +170 -0
- package/dist/api/system-one-shared.js.map +1 -0
- package/dist/api/typesafe-system-one.d.ts +4 -0
- package/dist/api/typesafe-system-one.d.ts.map +1 -0
- package/dist/api/typesafe-system-one.js +19 -0
- package/dist/api/typesafe-system-one.js.map +1 -0
- package/dist/api/typesafe-system-one.lazy.d.ts +3 -0
- package/dist/api/typesafe-system-one.lazy.d.ts.map +1 -0
- package/dist/api/typesafe-system-one.lazy.js +4 -0
- package/dist/api/typesafe-system-one.lazy.js.map +1 -0
- package/dist/auth/resolve.d.ts +2 -8
- package/dist/auth/resolve.d.ts.map +1 -1
- package/dist/auth/resolve.js +3 -19
- package/dist/auth/resolve.js.map +1 -1
- package/dist/env-api-keys.d.ts.map +1 -1
- package/dist/env-api-keys.js +1 -0
- package/dist/env-api-keys.js.map +1 -1
- package/dist/image-models.d.ts +19 -8
- package/dist/image-models.d.ts.map +1 -1
- package/dist/image-models.js +14 -13
- package/dist/image-models.js.map +1 -1
- package/dist/images-api-registry.d.ts +7 -7
- package/dist/images-api-registry.d.ts.map +1 -1
- package/dist/images-api-registry.js.map +1 -1
- package/dist/images.d.ts +7 -2
- package/dist/images.d.ts.map +1 -1
- package/dist/images.js +5 -0
- package/dist/images.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/model-catalog.d.ts +25 -9
- package/dist/model-catalog.d.ts.map +1 -1
- package/dist/model-catalog.js +14 -2
- package/dist/model-catalog.js.map +1 -1
- package/dist/models-store.d.ts +3 -2
- package/dist/models-store.d.ts.map +1 -1
- package/dist/models-store.js.map +1 -1
- package/dist/models.d.ts +95 -28
- package/dist/models.d.ts.map +1 -1
- package/dist/models.generated.d.ts +131 -41
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.generated.js +131 -41
- package/dist/models.generated.js.map +1 -1
- package/dist/models.js +155 -28
- package/dist/models.js.map +1 -1
- package/dist/providers/all.d.ts +19 -13
- package/dist/providers/all.d.ts.map +1 -1
- package/dist/providers/all.js +25 -21
- package/dist/providers/all.js.map +1 -1
- package/dist/providers/amazon-bedrock.models.d.ts +4 -2
- package/dist/providers/amazon-bedrock.models.d.ts.map +1 -1
- package/dist/providers/amazon-bedrock.models.js +4 -2
- package/dist/providers/amazon-bedrock.models.js.map +1 -1
- package/dist/providers/ant-ling.models.d.ts +4 -2
- package/dist/providers/ant-ling.models.d.ts.map +1 -1
- package/dist/providers/ant-ling.models.js +4 -2
- package/dist/providers/ant-ling.models.js.map +1 -1
- package/dist/providers/anthropic.models.d.ts +4 -2
- package/dist/providers/anthropic.models.d.ts.map +1 -1
- package/dist/providers/anthropic.models.js +4 -2
- package/dist/providers/anthropic.models.js.map +1 -1
- package/dist/providers/azure-openai-responses.models.d.ts +4 -2
- package/dist/providers/azure-openai-responses.models.d.ts.map +1 -1
- package/dist/providers/azure-openai-responses.models.js +4 -2
- package/dist/providers/azure-openai-responses.models.js.map +1 -1
- package/dist/providers/baseten.models.d.ts +4 -2
- package/dist/providers/baseten.models.d.ts.map +1 -1
- package/dist/providers/baseten.models.js +4 -2
- package/dist/providers/baseten.models.js.map +1 -1
- package/dist/providers/cerebras.models.d.ts +4 -2
- package/dist/providers/cerebras.models.d.ts.map +1 -1
- package/dist/providers/cerebras.models.js +4 -2
- package/dist/providers/cerebras.models.js.map +1 -1
- package/dist/providers/cloudflare-ai-gateway.models.d.ts +4 -2
- package/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -1
- package/dist/providers/cloudflare-ai-gateway.models.js +4 -2
- package/dist/providers/cloudflare-ai-gateway.models.js.map +1 -1
- package/dist/providers/cloudflare-stream.d.ts +6 -2
- package/dist/providers/cloudflare-stream.d.ts.map +1 -1
- package/dist/providers/cloudflare-stream.js +6 -0
- package/dist/providers/cloudflare-stream.js.map +1 -1
- package/dist/providers/cloudflare-workers-ai.d.ts.map +1 -1
- package/dist/providers/cloudflare-workers-ai.js +10 -3
- package/dist/providers/cloudflare-workers-ai.js.map +1 -1
- package/dist/providers/cloudflare-workers-ai.models.d.ts +4 -2
- package/dist/providers/cloudflare-workers-ai.models.d.ts.map +1 -1
- package/dist/providers/cloudflare-workers-ai.models.js +4 -2
- package/dist/providers/cloudflare-workers-ai.models.js.map +1 -1
- package/dist/providers/data/.manifest.json +1 -1
- package/dist/providers/data/amazon-bedrock.json +1 -1
- package/dist/providers/data/ant-ling.json +1 -1
- package/dist/providers/data/anthropic.json +1 -1
- package/dist/providers/data/azure-openai-responses.json +1 -1
- package/dist/providers/data/baseten.json +1 -1
- package/dist/providers/data/cerebras.json +1 -1
- package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/dist/providers/data/deepseek.json +1 -1
- package/dist/providers/data/fireworks.json +1 -1
- package/dist/providers/data/github-copilot.json +1 -1
- package/dist/providers/data/google-vertex.json +1 -1
- package/dist/providers/data/google.json +1 -1
- package/dist/providers/data/groq.json +1 -1
- package/dist/providers/data/huggingface.json +1 -1
- package/dist/providers/data/kimi-coding.json +1 -1
- package/dist/providers/data/meta.json +1 -1
- package/dist/providers/data/minimax-cn.json +1 -1
- package/dist/providers/data/minimax.json +1 -1
- package/dist/providers/data/mistral.json +1 -1
- package/dist/providers/data/moonshotai-cn.json +1 -1
- package/dist/providers/data/moonshotai.json +1 -1
- package/dist/providers/data/nvidia.json +1 -1
- package/dist/providers/data/openai-codex.json +1 -1
- package/dist/providers/data/openai.json +1 -1
- package/dist/providers/data/opencode-go.json +1 -1
- package/dist/providers/data/opencode.json +1 -1
- package/dist/providers/data/openrouter.json +1 -1
- package/dist/providers/data/qwen-token-plan-cn.json +1 -1
- package/dist/providers/data/qwen-token-plan-individual.json +1 -1
- package/dist/providers/data/qwen-token-plan.json +1 -1
- package/dist/providers/data/radius.json +1 -1
- package/dist/providers/data/together.json +1 -1
- package/dist/providers/data/typesafe.json +1 -0
- package/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/dist/providers/data/xai.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-ams.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-cn.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-sgp.json +1 -1
- package/dist/providers/data/xiaomi.json +1 -1
- package/dist/providers/data/zai-coding-cn.json +1 -1
- package/dist/providers/data/zai.json +1 -1
- package/dist/providers/deepseek.models.d.ts +4 -2
- package/dist/providers/deepseek.models.d.ts.map +1 -1
- package/dist/providers/deepseek.models.js +4 -2
- package/dist/providers/deepseek.models.js.map +1 -1
- package/dist/providers/fireworks.models.d.ts +4 -2
- package/dist/providers/fireworks.models.d.ts.map +1 -1
- package/dist/providers/fireworks.models.js +4 -2
- package/dist/providers/fireworks.models.js.map +1 -1
- package/dist/providers/github-copilot.models.d.ts +4 -2
- package/dist/providers/github-copilot.models.d.ts.map +1 -1
- package/dist/providers/github-copilot.models.js +4 -2
- package/dist/providers/github-copilot.models.js.map +1 -1
- package/dist/providers/google-vertex.models.d.ts +4 -2
- package/dist/providers/google-vertex.models.d.ts.map +1 -1
- package/dist/providers/google-vertex.models.js +4 -2
- package/dist/providers/google-vertex.models.js.map +1 -1
- package/dist/providers/google.models.d.ts +4 -2
- package/dist/providers/google.models.d.ts.map +1 -1
- package/dist/providers/google.models.js +4 -2
- package/dist/providers/google.models.js.map +1 -1
- package/dist/providers/groq.models.d.ts +4 -2
- package/dist/providers/groq.models.d.ts.map +1 -1
- package/dist/providers/groq.models.js +4 -2
- package/dist/providers/groq.models.js.map +1 -1
- package/dist/providers/huggingface.models.d.ts +4 -2
- package/dist/providers/huggingface.models.d.ts.map +1 -1
- package/dist/providers/huggingface.models.js +4 -2
- package/dist/providers/huggingface.models.js.map +1 -1
- package/dist/providers/images/register-builtins.d.ts +1 -1
- package/dist/providers/images/register-builtins.d.ts.map +1 -1
- package/dist/providers/images/register-builtins.js.map +1 -1
- package/dist/providers/kimi-coding.models.d.ts +4 -2
- package/dist/providers/kimi-coding.models.d.ts.map +1 -1
- package/dist/providers/kimi-coding.models.js +4 -2
- package/dist/providers/kimi-coding.models.js.map +1 -1
- package/dist/providers/meta.models.d.ts +4 -2
- package/dist/providers/meta.models.d.ts.map +1 -1
- package/dist/providers/meta.models.js +4 -2
- package/dist/providers/meta.models.js.map +1 -1
- package/dist/providers/minimax-cn.models.d.ts +4 -2
- package/dist/providers/minimax-cn.models.d.ts.map +1 -1
- package/dist/providers/minimax-cn.models.js +4 -2
- package/dist/providers/minimax-cn.models.js.map +1 -1
- package/dist/providers/minimax.models.d.ts +4 -2
- package/dist/providers/minimax.models.d.ts.map +1 -1
- package/dist/providers/minimax.models.js +4 -2
- package/dist/providers/minimax.models.js.map +1 -1
- package/dist/providers/mistral.models.d.ts +4 -2
- package/dist/providers/mistral.models.d.ts.map +1 -1
- package/dist/providers/mistral.models.js +4 -2
- package/dist/providers/mistral.models.js.map +1 -1
- package/dist/providers/moonshotai-cn.models.d.ts +4 -2
- package/dist/providers/moonshotai-cn.models.d.ts.map +1 -1
- package/dist/providers/moonshotai-cn.models.js +4 -2
- package/dist/providers/moonshotai-cn.models.js.map +1 -1
- package/dist/providers/moonshotai.models.d.ts +4 -2
- package/dist/providers/moonshotai.models.d.ts.map +1 -1
- package/dist/providers/moonshotai.models.js +4 -2
- package/dist/providers/moonshotai.models.js.map +1 -1
- package/dist/providers/nvidia.models.d.ts +4 -2
- package/dist/providers/nvidia.models.d.ts.map +1 -1
- package/dist/providers/nvidia.models.js +4 -2
- package/dist/providers/nvidia.models.js.map +1 -1
- package/dist/providers/openai-codex.models.d.ts +4 -2
- package/dist/providers/openai-codex.models.d.ts.map +1 -1
- package/dist/providers/openai-codex.models.js +4 -2
- package/dist/providers/openai-codex.models.js.map +1 -1
- package/dist/providers/openai.models.d.ts +4 -2
- package/dist/providers/openai.models.d.ts.map +1 -1
- package/dist/providers/openai.models.js +4 -2
- package/dist/providers/openai.models.js.map +1 -1
- package/dist/providers/opencode-go.models.d.ts +4 -2
- package/dist/providers/opencode-go.models.d.ts.map +1 -1
- package/dist/providers/opencode-go.models.js +4 -2
- package/dist/providers/opencode-go.models.js.map +1 -1
- package/dist/providers/opencode.models.d.ts +4 -2
- package/dist/providers/opencode.models.d.ts.map +1 -1
- package/dist/providers/opencode.models.js +4 -2
- package/dist/providers/opencode.models.js.map +1 -1
- package/dist/providers/openrouter.d.ts.map +1 -1
- package/dist/providers/openrouter.js +11 -2
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/openrouter.models.d.ts +4 -2
- package/dist/providers/openrouter.models.d.ts.map +1 -1
- package/dist/providers/openrouter.models.js +4 -2
- package/dist/providers/openrouter.models.js.map +1 -1
- package/dist/providers/qwen-token-plan-cn.models.d.ts +4 -2
- package/dist/providers/qwen-token-plan-cn.models.d.ts.map +1 -1
- package/dist/providers/qwen-token-plan-cn.models.js +4 -2
- package/dist/providers/qwen-token-plan-cn.models.js.map +1 -1
- package/dist/providers/qwen-token-plan-individual.models.d.ts +4 -2
- package/dist/providers/qwen-token-plan-individual.models.d.ts.map +1 -1
- package/dist/providers/qwen-token-plan-individual.models.js +4 -2
- package/dist/providers/qwen-token-plan-individual.models.js.map +1 -1
- package/dist/providers/qwen-token-plan.models.d.ts +4 -2
- package/dist/providers/qwen-token-plan.models.d.ts.map +1 -1
- package/dist/providers/qwen-token-plan.models.js +4 -2
- package/dist/providers/qwen-token-plan.models.js.map +1 -1
- package/dist/providers/radius.models.d.ts +4 -2
- package/dist/providers/radius.models.d.ts.map +1 -1
- package/dist/providers/radius.models.js +4 -2
- package/dist/providers/radius.models.js.map +1 -1
- package/dist/providers/together.models.d.ts +4 -2
- package/dist/providers/together.models.d.ts.map +1 -1
- package/dist/providers/together.models.js +4 -2
- package/dist/providers/together.models.js.map +1 -1
- package/dist/providers/typesafe.d.ts +3 -0
- package/dist/providers/typesafe.d.ts.map +1 -0
- package/dist/providers/typesafe.js +18 -0
- package/dist/providers/typesafe.js.map +1 -0
- package/dist/providers/typesafe.models.d.ts +5 -0
- package/dist/providers/typesafe.models.d.ts.map +1 -0
- package/dist/providers/typesafe.models.js +8 -0
- package/dist/providers/typesafe.models.js.map +1 -0
- package/dist/providers/vercel-ai-gateway.models.d.ts +4 -2
- package/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
- package/dist/providers/vercel-ai-gateway.models.js +4 -2
- package/dist/providers/vercel-ai-gateway.models.js.map +1 -1
- package/dist/providers/xai.models.d.ts +4 -2
- package/dist/providers/xai.models.d.ts.map +1 -1
- package/dist/providers/xai.models.js +4 -2
- package/dist/providers/xai.models.js.map +1 -1
- package/dist/providers/xiaomi-token-plan-ams.models.d.ts +4 -2
- package/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -1
- package/dist/providers/xiaomi-token-plan-ams.models.js +4 -2
- package/dist/providers/xiaomi-token-plan-ams.models.js.map +1 -1
- package/dist/providers/xiaomi-token-plan-cn.models.d.ts +4 -2
- package/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -1
- package/dist/providers/xiaomi-token-plan-cn.models.js +4 -2
- package/dist/providers/xiaomi-token-plan-cn.models.js.map +1 -1
- package/dist/providers/xiaomi-token-plan-sgp.models.d.ts +4 -2
- package/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -1
- package/dist/providers/xiaomi-token-plan-sgp.models.js +4 -2
- package/dist/providers/xiaomi-token-plan-sgp.models.js.map +1 -1
- package/dist/providers/xiaomi.models.d.ts +4 -2
- package/dist/providers/xiaomi.models.d.ts.map +1 -1
- package/dist/providers/xiaomi.models.js +4 -2
- package/dist/providers/xiaomi.models.js.map +1 -1
- package/dist/providers/zai-coding-cn.models.d.ts +4 -2
- package/dist/providers/zai-coding-cn.models.d.ts.map +1 -1
- package/dist/providers/zai-coding-cn.models.js +4 -2
- package/dist/providers/zai-coding-cn.models.js.map +1 -1
- package/dist/providers/zai.models.d.ts +4 -2
- package/dist/providers/zai.models.d.ts.map +1 -1
- package/dist/providers/zai.models.js +4 -2
- package/dist/providers/zai.models.js.map +1 -1
- package/dist/types.d.ts +109 -26
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/headers.d.ts +1 -1
- package/dist/utils/headers.d.ts.map +1 -1
- package/dist/utils/headers.js +10 -8
- package/dist/utils/headers.js.map +1 -1
- package/dist/utils/model-operations.d.ts +11 -0
- package/dist/utils/model-operations.d.ts.map +1 -0
- package/dist/utils/model-operations.js +47 -0
- package/dist/utils/model-operations.js.map +1 -0
- package/dist/utils/models-error.d.ts +8 -0
- package/dist/utils/models-error.d.ts.map +1 -0
- package/dist/utils/models-error.js +19 -0
- package/dist/utils/models-error.js.map +1 -0
- package/package.json +1 -2
- package/dist/image-models.generated.d.ts +0 -830
- package/dist/image-models.generated.d.ts.map +0 -1
- package/dist/image-models.generated.js +0 -832
- package/dist/image-models.generated.js.map +0 -1
- package/dist/images-models.d.ts +0 -95
- package/dist/images-models.d.ts.map +0 -1
- package/dist/images-models.js +0 -143
- package/dist/images-models.js.map +0 -1
- package/dist/providers/openrouter-images.d.ts +0 -3
- package/dist/providers/openrouter-images.d.ts.map +0 -1
- package/dist/providers/openrouter-images.js +0 -22
- 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
|
|
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**:
|
|
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
|
-
|
|
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 {
|
|
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
|
|
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
|
|
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 {
|
|
778
|
+
import { builtinModels } from '@bastani/pi-ai/providers/all';
|
|
734
779
|
|
|
735
|
-
|
|
736
|
-
const imagesModels = builtinImagesModels();
|
|
780
|
+
const models = builtinModels();
|
|
737
781
|
|
|
738
|
-
const model =
|
|
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
|
|
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
|
-
|
|
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
|
|
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);
|
|
788
|
-
console.log(model.output);
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1660
|
-
-
|
|
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`)
|