@bastani/pi-ai 0.9.14
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 +9 -0
- package/LICENSE +22 -0
- package/NOTICE.md +16 -0
- package/README.md +1672 -0
- package/dist/api/anthropic-messages.d.ts +71 -0
- package/dist/api/anthropic-messages.d.ts.map +1 -0
- package/dist/api/anthropic-messages.js +1060 -0
- package/dist/api/anthropic-messages.js.map +1 -0
- package/dist/api/anthropic-messages.lazy.d.ts +3 -0
- package/dist/api/anthropic-messages.lazy.d.ts.map +1 -0
- package/dist/api/anthropic-messages.lazy.js +3 -0
- package/dist/api/anthropic-messages.lazy.js.map +1 -0
- package/dist/api/azure-openai-responses.d.ts +15 -0
- package/dist/api/azure-openai-responses.d.ts.map +1 -0
- package/dist/api/azure-openai-responses.js +242 -0
- package/dist/api/azure-openai-responses.js.map +1 -0
- package/dist/api/azure-openai-responses.lazy.d.ts +3 -0
- package/dist/api/azure-openai-responses.lazy.d.ts.map +1 -0
- package/dist/api/azure-openai-responses.lazy.js +3 -0
- package/dist/api/azure-openai-responses.lazy.js.map +1 -0
- package/dist/api/bedrock-converse-stream.d.ts +38 -0
- package/dist/api/bedrock-converse-stream.d.ts.map +1 -0
- package/dist/api/bedrock-converse-stream.js +967 -0
- package/dist/api/bedrock-converse-stream.js.map +1 -0
- package/dist/api/bedrock-converse-stream.lazy.d.ts +9 -0
- package/dist/api/bedrock-converse-stream.lazy.d.ts.map +1 -0
- package/dist/api/bedrock-converse-stream.lazy.js +30 -0
- package/dist/api/bedrock-converse-stream.lazy.js.map +1 -0
- package/dist/api/cloudflare-gateway-binding.d.ts +69 -0
- package/dist/api/cloudflare-gateway-binding.d.ts.map +1 -0
- package/dist/api/cloudflare-gateway-binding.js +159 -0
- package/dist/api/cloudflare-gateway-binding.js.map +1 -0
- package/dist/api/cloudflare.d.ts +9 -0
- package/dist/api/cloudflare.d.ts.map +1 -0
- package/dist/api/cloudflare.js +9 -0
- package/dist/api/cloudflare.js.map +1 -0
- package/dist/api/constrained-sampling.d.ts +20 -0
- package/dist/api/constrained-sampling.d.ts.map +1 -0
- package/dist/api/constrained-sampling.js +222 -0
- package/dist/api/constrained-sampling.js.map +1 -0
- package/dist/api/github-copilot-headers.d.ts +8 -0
- package/dist/api/github-copilot-headers.d.ts.map +1 -0
- package/dist/api/github-copilot-headers.js +29 -0
- package/dist/api/github-copilot-headers.js.map +1 -0
- package/dist/api/google-generative-ai.d.ts +13 -0
- package/dist/api/google-generative-ai.d.ts.map +1 -0
- package/dist/api/google-generative-ai.js +417 -0
- package/dist/api/google-generative-ai.js.map +1 -0
- package/dist/api/google-generative-ai.lazy.d.ts +3 -0
- package/dist/api/google-generative-ai.lazy.d.ts.map +1 -0
- package/dist/api/google-generative-ai.lazy.js +3 -0
- package/dist/api/google-generative-ai.lazy.js.map +1 -0
- package/dist/api/google-shared.d.ts +81 -0
- package/dist/api/google-shared.d.ts.map +1 -0
- package/dist/api/google-shared.js +384 -0
- package/dist/api/google-shared.js.map +1 -0
- package/dist/api/google-vertex.d.ts +15 -0
- package/dist/api/google-vertex.d.ts.map +1 -0
- package/dist/api/google-vertex.js +466 -0
- package/dist/api/google-vertex.js.map +1 -0
- package/dist/api/google-vertex.lazy.d.ts +3 -0
- package/dist/api/google-vertex.lazy.d.ts.map +1 -0
- package/dist/api/google-vertex.lazy.js +3 -0
- package/dist/api/google-vertex.lazy.js.map +1 -0
- package/dist/api/lazy.d.ts +19 -0
- package/dist/api/lazy.d.ts.map +1 -0
- package/dist/api/lazy.js +70 -0
- package/dist/api/lazy.js.map +1 -0
- package/dist/api/mistral-conversations.d.ts +25 -0
- package/dist/api/mistral-conversations.d.ts.map +1 -0
- package/dist/api/mistral-conversations.js +736 -0
- package/dist/api/mistral-conversations.js.map +1 -0
- package/dist/api/mistral-conversations.lazy.d.ts +3 -0
- package/dist/api/mistral-conversations.lazy.d.ts.map +1 -0
- package/dist/api/mistral-conversations.lazy.js +3 -0
- package/dist/api/mistral-conversations.lazy.js.map +1 -0
- package/dist/api/openai-codex-responses.d.ts +31 -0
- package/dist/api/openai-codex-responses.d.ts.map +1 -0
- package/dist/api/openai-codex-responses.js +1294 -0
- package/dist/api/openai-codex-responses.js.map +1 -0
- package/dist/api/openai-codex-responses.lazy.d.ts +3 -0
- package/dist/api/openai-codex-responses.lazy.d.ts.map +1 -0
- package/dist/api/openai-codex-responses.lazy.js +3 -0
- package/dist/api/openai-codex-responses.lazy.js.map +1 -0
- package/dist/api/openai-completions.d.ts +22 -0
- package/dist/api/openai-completions.d.ts.map +1 -0
- package/dist/api/openai-completions.js +1279 -0
- package/dist/api/openai-completions.js.map +1 -0
- package/dist/api/openai-completions.lazy.d.ts +3 -0
- package/dist/api/openai-completions.lazy.d.ts.map +1 -0
- package/dist/api/openai-completions.lazy.js +3 -0
- package/dist/api/openai-completions.lazy.js.map +1 -0
- package/dist/api/openai-prompt-cache.d.ts +3 -0
- package/dist/api/openai-prompt-cache.d.ts.map +1 -0
- package/dist/api/openai-prompt-cache.js +10 -0
- package/dist/api/openai-prompt-cache.js.map +1 -0
- package/dist/api/openai-responses-shared.d.ts +26 -0
- package/dist/api/openai-responses-shared.d.ts.map +1 -0
- package/dist/api/openai-responses-shared.js +686 -0
- package/dist/api/openai-responses-shared.js.map +1 -0
- package/dist/api/openai-responses.d.ts +14 -0
- package/dist/api/openai-responses.d.ts.map +1 -0
- package/dist/api/openai-responses.js +283 -0
- package/dist/api/openai-responses.js.map +1 -0
- package/dist/api/openai-responses.lazy.d.ts +3 -0
- package/dist/api/openai-responses.lazy.d.ts.map +1 -0
- package/dist/api/openai-responses.lazy.js +3 -0
- package/dist/api/openai-responses.lazy.js.map +1 -0
- package/dist/api/openrouter-images.d.ts +3 -0
- package/dist/api/openrouter-images.d.ts.map +1 -0
- package/dist/api/openrouter-images.js +132 -0
- package/dist/api/openrouter-images.js.map +1 -0
- package/dist/api/openrouter-images.lazy.d.ts +3 -0
- package/dist/api/openrouter-images.lazy.d.ts.map +1 -0
- package/dist/api/openrouter-images.lazy.js +4 -0
- package/dist/api/openrouter-images.lazy.js.map +1 -0
- package/dist/api/pi-messages.d.ts +97 -0
- package/dist/api/pi-messages.d.ts.map +1 -0
- package/dist/api/pi-messages.js +307 -0
- package/dist/api/pi-messages.js.map +1 -0
- package/dist/api/pi-messages.lazy.d.ts +3 -0
- package/dist/api/pi-messages.lazy.d.ts.map +1 -0
- package/dist/api/pi-messages.lazy.js +3 -0
- package/dist/api/pi-messages.lazy.js.map +1 -0
- package/dist/api/simple-options.d.ts +11 -0
- package/dist/api/simple-options.d.ts.map +1 -0
- package/dist/api/simple-options.js +59 -0
- package/dist/api/simple-options.js.map +1 -0
- package/dist/api/transform-messages.d.ts +8 -0
- package/dist/api/transform-messages.d.ts.map +1 -0
- package/dist/api/transform-messages.js +187 -0
- package/dist/api/transform-messages.js.map +1 -0
- package/dist/auth/context.d.ts +7 -0
- package/dist/auth/context.d.ts.map +1 -0
- package/dist/auth/context.js +42 -0
- package/dist/auth/context.js.map +1 -0
- package/dist/auth/credential-store.d.ts +17 -0
- package/dist/auth/credential-store.d.ts.map +1 -0
- package/dist/auth/credential-store.js +51 -0
- package/dist/auth/credential-store.js.map +1 -0
- package/dist/auth/helpers.d.ts +22 -0
- package/dist/auth/helpers.d.ts.map +1 -0
- package/dist/auth/helpers.js +53 -0
- package/dist/auth/helpers.js.map +1 -0
- package/dist/auth/oauth/anthropic.d.ts +9 -0
- package/dist/auth/oauth/anthropic.d.ts.map +1 -0
- package/dist/auth/oauth/anthropic.js +308 -0
- package/dist/auth/oauth/anthropic.js.map +1 -0
- package/dist/auth/oauth/device-code.d.ts +23 -0
- package/dist/auth/oauth/device-code.d.ts.map +1 -0
- package/dist/auth/oauth/device-code.js +69 -0
- package/dist/auth/oauth/device-code.js.map +1 -0
- package/dist/auth/oauth/github-copilot.d.ts +6 -0
- package/dist/auth/oauth/github-copilot.d.ts.map +1 -0
- package/dist/auth/oauth/github-copilot.js +328 -0
- package/dist/auth/oauth/github-copilot.js.map +1 -0
- package/dist/auth/oauth/kimi-coding.d.ts +10 -0
- package/dist/auth/oauth/kimi-coding.d.ts.map +1 -0
- package/dist/auth/oauth/kimi-coding.js +261 -0
- package/dist/auth/oauth/kimi-coding.js.map +1 -0
- package/dist/auth/oauth/load.d.ts +27 -0
- package/dist/auth/oauth/load.d.ts.map +1 -0
- package/dist/auth/oauth/load.js +59 -0
- package/dist/auth/oauth/load.js.map +1 -0
- package/dist/auth/oauth/oauth-page.d.ts +3 -0
- package/dist/auth/oauth/oauth-page.d.ts.map +1 -0
- package/dist/auth/oauth/oauth-page.js +105 -0
- package/dist/auth/oauth/oauth-page.js.map +1 -0
- package/dist/auth/oauth/openai-codex.d.ts +9 -0
- package/dist/auth/oauth/openai-codex.d.ts.map +1 -0
- package/dist/auth/oauth/openai-codex.js +450 -0
- package/dist/auth/oauth/openai-codex.js.map +1 -0
- package/dist/auth/oauth/openrouter.d.ts +15 -0
- package/dist/auth/oauth/openrouter.d.ts.map +1 -0
- package/dist/auth/oauth/openrouter.js +277 -0
- package/dist/auth/oauth/openrouter.js.map +1 -0
- package/dist/auth/oauth/pkce.d.ts +13 -0
- package/dist/auth/oauth/pkce.d.ts.map +1 -0
- package/dist/auth/oauth/pkce.js +31 -0
- package/dist/auth/oauth/pkce.js.map +1 -0
- package/dist/auth/oauth/radius.d.ts +17 -0
- package/dist/auth/oauth/radius.d.ts.map +1 -0
- package/dist/auth/oauth/radius.js +321 -0
- package/dist/auth/oauth/radius.js.map +1 -0
- package/dist/auth/oauth/xai.d.ts +6 -0
- package/dist/auth/oauth/xai.d.ts.map +1 -0
- package/dist/auth/oauth/xai.js +190 -0
- package/dist/auth/oauth/xai.js.map +1 -0
- package/dist/auth/resolve.d.ts +27 -0
- package/dist/auth/resolve.d.ts.map +1 -0
- package/dist/auth/resolve.js +132 -0
- package/dist/auth/resolve.js.map +1 -0
- package/dist/auth/types.d.ts +231 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +2 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/bedrock-provider.d.ts +5 -0
- package/dist/bedrock-provider.d.ts.map +1 -0
- package/dist/bedrock-provider.js +6 -0
- package/dist/bedrock-provider.js.map +1 -0
- package/dist/bun-oauth.d.ts +3 -0
- package/dist/bun-oauth.d.ts.map +1 -0
- package/dist/bun-oauth.js +21 -0
- package/dist/bun-oauth.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +113 -0
- package/dist/cli.js.map +1 -0
- package/dist/compat/extension-oauth-types.d.ts +39 -0
- package/dist/compat/extension-oauth-types.d.ts.map +1 -0
- package/dist/compat/extension-oauth-types.js +2 -0
- package/dist/compat/extension-oauth-types.js.map +1 -0
- package/dist/compat.d.ts +67 -0
- package/dist/compat.d.ts.map +1 -0
- package/dist/compat.js +199 -0
- package/dist/compat.js.map +1 -0
- package/dist/env-api-keys.d.ts +21 -0
- package/dist/env-api-keys.d.ts.map +1 -0
- package/dist/env-api-keys.js +156 -0
- package/dist/env-api-keys.js.map +1 -0
- package/dist/image-models.d.ts +10 -0
- package/dist/image-models.d.ts.map +1 -0
- package/dist/image-models.generated.d.ts +680 -0
- package/dist/image-models.generated.d.ts.map +1 -0
- package/dist/image-models.generated.js +682 -0
- package/dist/image-models.generated.js.map +1 -0
- package/dist/image-models.js +23 -0
- package/dist/image-models.js.map +1 -0
- package/dist/images-api-registry.d.ts +14 -0
- package/dist/images-api-registry.d.ts.map +1 -0
- package/dist/images-api-registry.js +22 -0
- package/dist/images-api-registry.js.map +1 -0
- package/dist/images-models.d.ts +95 -0
- package/dist/images-models.d.ts.map +1 -0
- package/dist/images-models.js +143 -0
- package/dist/images-models.js.map +1 -0
- package/dist/images.d.ts +4 -0
- package/dist/images.d.ts.map +1 -0
- package/dist/images.js +14 -0
- package/dist/images.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/legacy-api-aliases.d.ts +42 -0
- package/dist/legacy-api-aliases.d.ts.map +1 -0
- package/dist/legacy-api-aliases.js +49 -0
- package/dist/legacy-api-aliases.js.map +1 -0
- package/dist/model-catalog.d.ts +17 -0
- package/dist/model-catalog.d.ts.map +1 -0
- package/dist/model-catalog.js +4 -0
- package/dist/model-catalog.js.map +1 -0
- package/dist/models-store.d.ts +29 -0
- package/dist/models-store.d.ts.map +1 -0
- package/dist/models-store.js +17 -0
- package/dist/models-store.js.map +1 -0
- package/dist/models.d.ts +200 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.generated.d.ts +81 -0
- package/dist/models.generated.d.ts.map +1 -0
- package/dist/models.generated.js +83 -0
- package/dist/models.generated.js.map +1 -0
- package/dist/models.js +588 -0
- package/dist/models.js.map +1 -0
- package/dist/oauth.d.ts +3 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +2 -0
- package/dist/oauth.js.map +1 -0
- package/dist/providers/all.d.ts +28 -0
- package/dist/providers/all.d.ts.map +1 -0
- package/dist/providers/all.js +131 -0
- package/dist/providers/all.js.map +1 -0
- package/dist/providers/amazon-bedrock.d.ts +3 -0
- package/dist/providers/amazon-bedrock.d.ts.map +1 -0
- package/dist/providers/amazon-bedrock.js +93 -0
- package/dist/providers/amazon-bedrock.js.map +1 -0
- package/dist/providers/amazon-bedrock.models.d.ts +4 -0
- package/dist/providers/amazon-bedrock.models.d.ts.map +1 -0
- package/dist/providers/amazon-bedrock.models.js +6 -0
- package/dist/providers/amazon-bedrock.models.js.map +1 -0
- package/dist/providers/ant-ling.d.ts +3 -0
- package/dist/providers/ant-ling.d.ts.map +1 -0
- package/dist/providers/ant-ling.js +15 -0
- package/dist/providers/ant-ling.js.map +1 -0
- package/dist/providers/ant-ling.models.d.ts +4 -0
- package/dist/providers/ant-ling.models.d.ts.map +1 -0
- package/dist/providers/ant-ling.models.js +6 -0
- package/dist/providers/ant-ling.models.js.map +1 -0
- package/dist/providers/anthropic.d.ts +3 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +56 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/anthropic.models.d.ts +4 -0
- package/dist/providers/anthropic.models.d.ts.map +1 -0
- package/dist/providers/anthropic.models.js +6 -0
- package/dist/providers/anthropic.models.js.map +1 -0
- package/dist/providers/azure-openai-responses.d.ts +3 -0
- package/dist/providers/azure-openai-responses.d.ts.map +1 -0
- package/dist/providers/azure-openai-responses.js +14 -0
- package/dist/providers/azure-openai-responses.js.map +1 -0
- package/dist/providers/azure-openai-responses.models.d.ts +4 -0
- package/dist/providers/azure-openai-responses.models.d.ts.map +1 -0
- package/dist/providers/azure-openai-responses.models.js +6 -0
- package/dist/providers/azure-openai-responses.models.js.map +1 -0
- package/dist/providers/baseten.d.ts +3 -0
- package/dist/providers/baseten.d.ts.map +1 -0
- package/dist/providers/baseten.js +15 -0
- package/dist/providers/baseten.js.map +1 -0
- package/dist/providers/baseten.models.d.ts +4 -0
- package/dist/providers/baseten.models.d.ts.map +1 -0
- package/dist/providers/baseten.models.js +6 -0
- package/dist/providers/baseten.models.js.map +1 -0
- package/dist/providers/cerebras.d.ts +3 -0
- package/dist/providers/cerebras.d.ts.map +1 -0
- package/dist/providers/cerebras.js +15 -0
- package/dist/providers/cerebras.js.map +1 -0
- package/dist/providers/cerebras.models.d.ts +4 -0
- package/dist/providers/cerebras.models.d.ts.map +1 -0
- package/dist/providers/cerebras.models.js +6 -0
- package/dist/providers/cerebras.models.js.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.d.ts +3 -0
- package/dist/providers/cloudflare-ai-gateway.d.ts.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.js +21 -0
- package/dist/providers/cloudflare-ai-gateway.js.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.models.d.ts +4 -0
- package/dist/providers/cloudflare-ai-gateway.models.d.ts.map +1 -0
- package/dist/providers/cloudflare-ai-gateway.models.js +6 -0
- package/dist/providers/cloudflare-ai-gateway.models.js.map +1 -0
- package/dist/providers/cloudflare-auth.d.ts +4 -0
- package/dist/providers/cloudflare-auth.d.ts.map +1 -0
- package/dist/providers/cloudflare-auth.js +86 -0
- package/dist/providers/cloudflare-auth.js.map +1 -0
- package/dist/providers/cloudflare-stream.d.ts +8 -0
- package/dist/providers/cloudflare-stream.d.ts.map +1 -0
- package/dist/providers/cloudflare-stream.js +21 -0
- package/dist/providers/cloudflare-stream.js.map +1 -0
- package/dist/providers/cloudflare-workers-ai.d.ts +3 -0
- package/dist/providers/cloudflare-workers-ai.d.ts.map +1 -0
- package/dist/providers/cloudflare-workers-ai.js +15 -0
- package/dist/providers/cloudflare-workers-ai.js.map +1 -0
- package/dist/providers/cloudflare-workers-ai.models.d.ts +4 -0
- package/dist/providers/cloudflare-workers-ai.models.d.ts.map +1 -0
- package/dist/providers/cloudflare-workers-ai.models.js +6 -0
- package/dist/providers/cloudflare-workers-ai.models.js.map +1 -0
- package/dist/providers/data/.manifest.json +1 -0
- package/dist/providers/data/amazon-bedrock.json +1 -0
- package/dist/providers/data/ant-ling.json +1 -0
- package/dist/providers/data/anthropic.json +1 -0
- package/dist/providers/data/azure-openai-responses.json +1 -0
- package/dist/providers/data/baseten.json +1 -0
- package/dist/providers/data/cerebras.json +1 -0
- package/dist/providers/data/cloudflare-ai-gateway.json +1 -0
- package/dist/providers/data/cloudflare-workers-ai.json +1 -0
- package/dist/providers/data/deepseek.json +1 -0
- package/dist/providers/data/fireworks.json +1 -0
- package/dist/providers/data/github-copilot.json +1 -0
- package/dist/providers/data/google-vertex.json +1 -0
- package/dist/providers/data/google.json +1 -0
- package/dist/providers/data/groq.json +1 -0
- package/dist/providers/data/huggingface.json +1 -0
- package/dist/providers/data/kimi-coding.json +1 -0
- package/dist/providers/data/minimax-cn.json +1 -0
- package/dist/providers/data/minimax.json +1 -0
- package/dist/providers/data/mistral.json +1 -0
- package/dist/providers/data/moonshotai-cn.json +1 -0
- package/dist/providers/data/moonshotai.json +1 -0
- package/dist/providers/data/nvidia.json +1 -0
- package/dist/providers/data/openai-codex.json +1 -0
- package/dist/providers/data/openai.json +1 -0
- package/dist/providers/data/opencode-go.json +1 -0
- package/dist/providers/data/opencode.json +1 -0
- package/dist/providers/data/openrouter.json +1 -0
- package/dist/providers/data/qwen-token-plan-cn.json +1 -0
- package/dist/providers/data/qwen-token-plan-individual.json +1 -0
- package/dist/providers/data/qwen-token-plan.json +1 -0
- package/dist/providers/data/together.json +1 -0
- package/dist/providers/data/vercel-ai-gateway.json +1 -0
- package/dist/providers/data/xai.json +1 -0
- package/dist/providers/data/xiaomi-token-plan-ams.json +1 -0
- package/dist/providers/data/xiaomi-token-plan-cn.json +1 -0
- package/dist/providers/data/xiaomi-token-plan-sgp.json +1 -0
- package/dist/providers/data/xiaomi.json +1 -0
- package/dist/providers/data/zai-coding-cn.json +1 -0
- package/dist/providers/data/zai.json +1 -0
- package/dist/providers/deepseek.d.ts +3 -0
- package/dist/providers/deepseek.d.ts.map +1 -0
- package/dist/providers/deepseek.js +15 -0
- package/dist/providers/deepseek.js.map +1 -0
- package/dist/providers/deepseek.models.d.ts +4 -0
- package/dist/providers/deepseek.models.d.ts.map +1 -0
- package/dist/providers/deepseek.models.js +6 -0
- package/dist/providers/deepseek.models.js.map +1 -0
- package/dist/providers/faux.d.ts +102 -0
- package/dist/providers/faux.d.ts.map +1 -0
- package/dist/providers/faux.js +488 -0
- package/dist/providers/faux.js.map +1 -0
- package/dist/providers/fireworks.d.ts +3 -0
- package/dist/providers/fireworks.d.ts.map +1 -0
- package/dist/providers/fireworks.js +19 -0
- package/dist/providers/fireworks.js.map +1 -0
- package/dist/providers/fireworks.models.d.ts +4 -0
- package/dist/providers/fireworks.models.d.ts.map +1 -0
- package/dist/providers/fireworks.models.js +6 -0
- package/dist/providers/fireworks.models.js.map +1 -0
- package/dist/providers/github-copilot.d.ts +3 -0
- package/dist/providers/github-copilot.d.ts.map +1 -0
- package/dist/providers/github-copilot.js +35 -0
- package/dist/providers/github-copilot.js.map +1 -0
- package/dist/providers/github-copilot.models.d.ts +4 -0
- package/dist/providers/github-copilot.models.d.ts.map +1 -0
- package/dist/providers/github-copilot.models.js +6 -0
- package/dist/providers/github-copilot.models.js.map +1 -0
- package/dist/providers/google-vertex.d.ts +3 -0
- package/dist/providers/google-vertex.d.ts.map +1 -0
- package/dist/providers/google-vertex.js +94 -0
- package/dist/providers/google-vertex.js.map +1 -0
- package/dist/providers/google-vertex.models.d.ts +4 -0
- package/dist/providers/google-vertex.models.d.ts.map +1 -0
- package/dist/providers/google-vertex.models.js +6 -0
- package/dist/providers/google-vertex.models.js.map +1 -0
- package/dist/providers/google.d.ts +3 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +15 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/google.models.d.ts +4 -0
- package/dist/providers/google.models.d.ts.map +1 -0
- package/dist/providers/google.models.js +6 -0
- package/dist/providers/google.models.js.map +1 -0
- package/dist/providers/groq.d.ts +3 -0
- package/dist/providers/groq.d.ts.map +1 -0
- package/dist/providers/groq.js +15 -0
- package/dist/providers/groq.js.map +1 -0
- package/dist/providers/groq.models.d.ts +4 -0
- package/dist/providers/groq.models.d.ts.map +1 -0
- package/dist/providers/groq.models.js +6 -0
- package/dist/providers/groq.models.js.map +1 -0
- package/dist/providers/huggingface.d.ts +3 -0
- package/dist/providers/huggingface.d.ts.map +1 -0
- package/dist/providers/huggingface.js +15 -0
- package/dist/providers/huggingface.js.map +1 -0
- package/dist/providers/huggingface.models.d.ts +4 -0
- package/dist/providers/huggingface.models.d.ts.map +1 -0
- package/dist/providers/huggingface.models.js +6 -0
- package/dist/providers/huggingface.models.js.map +1 -0
- package/dist/providers/images/register-builtins.d.ts +4 -0
- package/dist/providers/images/register-builtins.d.ts.map +1 -0
- package/dist/providers/images/register-builtins.js +34 -0
- package/dist/providers/images/register-builtins.js.map +1 -0
- package/dist/providers/kimi-coding.d.ts +3 -0
- package/dist/providers/kimi-coding.d.ts.map +1 -0
- package/dist/providers/kimi-coding.js +24 -0
- package/dist/providers/kimi-coding.js.map +1 -0
- package/dist/providers/kimi-coding.models.d.ts +4 -0
- package/dist/providers/kimi-coding.models.d.ts.map +1 -0
- package/dist/providers/kimi-coding.models.js +6 -0
- package/dist/providers/kimi-coding.models.js.map +1 -0
- package/dist/providers/minimax-cn.d.ts +3 -0
- package/dist/providers/minimax-cn.d.ts.map +1 -0
- package/dist/providers/minimax-cn.js +15 -0
- package/dist/providers/minimax-cn.js.map +1 -0
- package/dist/providers/minimax-cn.models.d.ts +4 -0
- package/dist/providers/minimax-cn.models.d.ts.map +1 -0
- package/dist/providers/minimax-cn.models.js +6 -0
- package/dist/providers/minimax-cn.models.js.map +1 -0
- package/dist/providers/minimax.d.ts +3 -0
- package/dist/providers/minimax.d.ts.map +1 -0
- package/dist/providers/minimax.js +15 -0
- package/dist/providers/minimax.js.map +1 -0
- package/dist/providers/minimax.models.d.ts +4 -0
- package/dist/providers/minimax.models.d.ts.map +1 -0
- package/dist/providers/minimax.models.js +6 -0
- package/dist/providers/minimax.models.js.map +1 -0
- package/dist/providers/mistral.d.ts +3 -0
- package/dist/providers/mistral.d.ts.map +1 -0
- package/dist/providers/mistral.js +15 -0
- package/dist/providers/mistral.js.map +1 -0
- package/dist/providers/mistral.models.d.ts +4 -0
- package/dist/providers/mistral.models.d.ts.map +1 -0
- package/dist/providers/mistral.models.js +6 -0
- package/dist/providers/mistral.models.js.map +1 -0
- package/dist/providers/moonshotai-cn.d.ts +3 -0
- package/dist/providers/moonshotai-cn.d.ts.map +1 -0
- package/dist/providers/moonshotai-cn.js +15 -0
- package/dist/providers/moonshotai-cn.js.map +1 -0
- package/dist/providers/moonshotai-cn.models.d.ts +4 -0
- package/dist/providers/moonshotai-cn.models.d.ts.map +1 -0
- package/dist/providers/moonshotai-cn.models.js +6 -0
- package/dist/providers/moonshotai-cn.models.js.map +1 -0
- package/dist/providers/moonshotai.d.ts +3 -0
- package/dist/providers/moonshotai.d.ts.map +1 -0
- package/dist/providers/moonshotai.js +15 -0
- package/dist/providers/moonshotai.js.map +1 -0
- package/dist/providers/moonshotai.models.d.ts +4 -0
- package/dist/providers/moonshotai.models.d.ts.map +1 -0
- package/dist/providers/moonshotai.models.js +6 -0
- package/dist/providers/moonshotai.models.js.map +1 -0
- package/dist/providers/nvidia.d.ts +3 -0
- package/dist/providers/nvidia.d.ts.map +1 -0
- package/dist/providers/nvidia.js +15 -0
- package/dist/providers/nvidia.js.map +1 -0
- package/dist/providers/nvidia.models.d.ts +4 -0
- package/dist/providers/nvidia.models.d.ts.map +1 -0
- package/dist/providers/nvidia.models.js +6 -0
- package/dist/providers/nvidia.models.js.map +1 -0
- package/dist/providers/openai-codex.d.ts +3 -0
- package/dist/providers/openai-codex.d.ts.map +1 -0
- package/dist/providers/openai-codex.js +22 -0
- package/dist/providers/openai-codex.js.map +1 -0
- package/dist/providers/openai-codex.models.d.ts +4 -0
- package/dist/providers/openai-codex.models.d.ts.map +1 -0
- package/dist/providers/openai-codex.models.js +6 -0
- package/dist/providers/openai-codex.models.js.map +1 -0
- package/dist/providers/openai.d.ts +3 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +15 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/openai.models.d.ts +4 -0
- package/dist/providers/openai.models.d.ts.map +1 -0
- package/dist/providers/openai.models.js +6 -0
- package/dist/providers/openai.models.js.map +1 -0
- package/dist/providers/opencode-go.d.ts +3 -0
- package/dist/providers/opencode-go.d.ts.map +1 -0
- package/dist/providers/opencode-go.js +20 -0
- package/dist/providers/opencode-go.js.map +1 -0
- package/dist/providers/opencode-go.models.d.ts +4 -0
- package/dist/providers/opencode-go.models.d.ts.map +1 -0
- package/dist/providers/opencode-go.models.js +6 -0
- package/dist/providers/opencode-go.models.js.map +1 -0
- package/dist/providers/opencode.d.ts +3 -0
- package/dist/providers/opencode.d.ts.map +1 -0
- package/dist/providers/opencode.js +22 -0
- package/dist/providers/opencode.js.map +1 -0
- package/dist/providers/opencode.models.d.ts +4 -0
- package/dist/providers/opencode.models.d.ts.map +1 -0
- package/dist/providers/opencode.models.js +6 -0
- package/dist/providers/opencode.models.js.map +1 -0
- package/dist/providers/openrouter-images.d.ts +3 -0
- package/dist/providers/openrouter-images.d.ts.map +1 -0
- package/dist/providers/openrouter-images.js +22 -0
- package/dist/providers/openrouter-images.js.map +1 -0
- package/dist/providers/openrouter.d.ts +3 -0
- package/dist/providers/openrouter.d.ts.map +1 -0
- package/dist/providers/openrouter.js +23 -0
- package/dist/providers/openrouter.js.map +1 -0
- package/dist/providers/openrouter.models.d.ts +4 -0
- package/dist/providers/openrouter.models.d.ts.map +1 -0
- package/dist/providers/openrouter.models.js +6 -0
- package/dist/providers/openrouter.models.js.map +1 -0
- package/dist/providers/qwen-token-plan-cn.d.ts +3 -0
- package/dist/providers/qwen-token-plan-cn.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan-cn.js +15 -0
- package/dist/providers/qwen-token-plan-cn.js.map +1 -0
- package/dist/providers/qwen-token-plan-cn.models.d.ts +4 -0
- package/dist/providers/qwen-token-plan-cn.models.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan-cn.models.js +6 -0
- package/dist/providers/qwen-token-plan-cn.models.js.map +1 -0
- package/dist/providers/qwen-token-plan-individual.d.ts +3 -0
- package/dist/providers/qwen-token-plan-individual.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan-individual.js +15 -0
- package/dist/providers/qwen-token-plan-individual.js.map +1 -0
- package/dist/providers/qwen-token-plan-individual.models.d.ts +4 -0
- package/dist/providers/qwen-token-plan-individual.models.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan-individual.models.js +6 -0
- package/dist/providers/qwen-token-plan-individual.models.js.map +1 -0
- package/dist/providers/qwen-token-plan.d.ts +3 -0
- package/dist/providers/qwen-token-plan.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan.js +15 -0
- package/dist/providers/qwen-token-plan.js.map +1 -0
- package/dist/providers/qwen-token-plan.models.d.ts +4 -0
- package/dist/providers/qwen-token-plan.models.d.ts.map +1 -0
- package/dist/providers/qwen-token-plan.models.js +6 -0
- package/dist/providers/qwen-token-plan.models.js.map +1 -0
- package/dist/providers/radius-config.d.ts +26 -0
- package/dist/providers/radius-config.d.ts.map +1 -0
- package/dist/providers/radius-config.js +63 -0
- package/dist/providers/radius-config.js.map +1 -0
- package/dist/providers/radius.d.ts +9 -0
- package/dist/providers/radius.d.ts.map +1 -0
- package/dist/providers/radius.js +64 -0
- package/dist/providers/radius.js.map +1 -0
- package/dist/providers/together.d.ts +3 -0
- package/dist/providers/together.d.ts.map +1 -0
- package/dist/providers/together.js +15 -0
- package/dist/providers/together.js.map +1 -0
- package/dist/providers/together.models.d.ts +4 -0
- package/dist/providers/together.models.d.ts.map +1 -0
- package/dist/providers/together.models.js +6 -0
- package/dist/providers/together.models.js.map +1 -0
- package/dist/providers/vercel-ai-gateway.d.ts +3 -0
- package/dist/providers/vercel-ai-gateway.d.ts.map +1 -0
- package/dist/providers/vercel-ai-gateway.js +15 -0
- package/dist/providers/vercel-ai-gateway.js.map +1 -0
- package/dist/providers/vercel-ai-gateway.models.d.ts +4 -0
- package/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -0
- package/dist/providers/vercel-ai-gateway.models.js +6 -0
- package/dist/providers/vercel-ai-gateway.models.js.map +1 -0
- package/dist/providers/xai.d.ts +3 -0
- package/dist/providers/xai.d.ts.map +1 -0
- package/dist/providers/xai.js +28 -0
- package/dist/providers/xai.js.map +1 -0
- package/dist/providers/xai.models.d.ts +4 -0
- package/dist/providers/xai.models.d.ts.map +1 -0
- package/dist/providers/xai.models.js +6 -0
- package/dist/providers/xai.models.js.map +1 -0
- package/dist/providers/xiaomi-token-plan-ams.d.ts +3 -0
- package/dist/providers/xiaomi-token-plan-ams.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-ams.js +15 -0
- package/dist/providers/xiaomi-token-plan-ams.js.map +1 -0
- package/dist/providers/xiaomi-token-plan-ams.models.d.ts +4 -0
- package/dist/providers/xiaomi-token-plan-ams.models.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-ams.models.js +6 -0
- package/dist/providers/xiaomi-token-plan-ams.models.js.map +1 -0
- package/dist/providers/xiaomi-token-plan-cn.d.ts +3 -0
- package/dist/providers/xiaomi-token-plan-cn.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-cn.js +15 -0
- package/dist/providers/xiaomi-token-plan-cn.js.map +1 -0
- package/dist/providers/xiaomi-token-plan-cn.models.d.ts +4 -0
- package/dist/providers/xiaomi-token-plan-cn.models.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-cn.models.js +6 -0
- package/dist/providers/xiaomi-token-plan-cn.models.js.map +1 -0
- package/dist/providers/xiaomi-token-plan-sgp.d.ts +3 -0
- package/dist/providers/xiaomi-token-plan-sgp.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-sgp.js +15 -0
- package/dist/providers/xiaomi-token-plan-sgp.js.map +1 -0
- package/dist/providers/xiaomi-token-plan-sgp.models.d.ts +4 -0
- package/dist/providers/xiaomi-token-plan-sgp.models.d.ts.map +1 -0
- package/dist/providers/xiaomi-token-plan-sgp.models.js +6 -0
- package/dist/providers/xiaomi-token-plan-sgp.models.js.map +1 -0
- package/dist/providers/xiaomi.d.ts +3 -0
- package/dist/providers/xiaomi.d.ts.map +1 -0
- package/dist/providers/xiaomi.js +15 -0
- package/dist/providers/xiaomi.js.map +1 -0
- package/dist/providers/xiaomi.models.d.ts +4 -0
- package/dist/providers/xiaomi.models.d.ts.map +1 -0
- package/dist/providers/xiaomi.models.js +6 -0
- package/dist/providers/xiaomi.models.js.map +1 -0
- package/dist/providers/zai-coding-cn.d.ts +3 -0
- package/dist/providers/zai-coding-cn.d.ts.map +1 -0
- package/dist/providers/zai-coding-cn.js +15 -0
- package/dist/providers/zai-coding-cn.js.map +1 -0
- package/dist/providers/zai-coding-cn.models.d.ts +4 -0
- package/dist/providers/zai-coding-cn.models.d.ts.map +1 -0
- package/dist/providers/zai-coding-cn.models.js +6 -0
- package/dist/providers/zai-coding-cn.models.js.map +1 -0
- package/dist/providers/zai.d.ts +3 -0
- package/dist/providers/zai.d.ts.map +1 -0
- package/dist/providers/zai.js +15 -0
- package/dist/providers/zai.js.map +1 -0
- package/dist/providers/zai.models.d.ts +4 -0
- package/dist/providers/zai.models.d.ts.map +1 -0
- package/dist/providers/zai.models.js +6 -0
- package/dist/providers/zai.models.js.map +1 -0
- package/dist/session-resources.d.ts +4 -0
- package/dist/session-resources.d.ts.map +1 -0
- package/dist/session-resources.js +22 -0
- package/dist/session-resources.js.map +1 -0
- package/dist/types.d.ts +697 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/abort-signals.d.ts +6 -0
- package/dist/utils/abort-signals.d.ts.map +1 -0
- package/dist/utils/abort-signals.js +34 -0
- package/dist/utils/abort-signals.js.map +1 -0
- package/dist/utils/abort.d.ts +8 -0
- package/dist/utils/abort.d.ts.map +1 -0
- package/dist/utils/abort.js +49 -0
- package/dist/utils/abort.js.map +1 -0
- package/dist/utils/deferred-tools.d.ts +9 -0
- package/dist/utils/deferred-tools.d.ts.map +1 -0
- package/dist/utils/deferred-tools.js +36 -0
- package/dist/utils/deferred-tools.js.map +1 -0
- package/dist/utils/diagnostics.d.ts +19 -0
- package/dist/utils/diagnostics.d.ts.map +1 -0
- package/dist/utils/diagnostics.js +25 -0
- package/dist/utils/diagnostics.js.map +1 -0
- package/dist/utils/error-body.d.ts +25 -0
- package/dist/utils/error-body.d.ts.map +1 -0
- package/dist/utils/error-body.js +133 -0
- package/dist/utils/error-body.js.map +1 -0
- package/dist/utils/estimate.d.ts +17 -0
- package/dist/utils/estimate.d.ts.map +1 -0
- package/dist/utils/estimate.js +116 -0
- package/dist/utils/estimate.js.map +1 -0
- package/dist/utils/event-stream.d.ts +21 -0
- package/dist/utils/event-stream.d.ts.map +1 -0
- package/dist/utils/event-stream.js +81 -0
- package/dist/utils/event-stream.js.map +1 -0
- package/dist/utils/hash.d.ts +3 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +14 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/headers.d.ts +4 -0
- package/dist/utils/headers.d.ts.map +1 -0
- package/dist/utils/headers.js +18 -0
- package/dist/utils/headers.js.map +1 -0
- package/dist/utils/json-parse.d.ts +16 -0
- package/dist/utils/json-parse.d.ts.map +1 -0
- package/dist/utils/json-parse.js +113 -0
- package/dist/utils/json-parse.js.map +1 -0
- package/dist/utils/node-http-proxy.d.ts +4 -0
- package/dist/utils/node-http-proxy.d.ts.map +1 -0
- package/dist/utils/node-http-proxy.js +92 -0
- package/dist/utils/node-http-proxy.js.map +1 -0
- package/dist/utils/overflow.d.ts +68 -0
- package/dist/utils/overflow.d.ts.map +1 -0
- package/dist/utils/overflow.js +172 -0
- package/dist/utils/overflow.js.map +1 -0
- package/dist/utils/pi-user-agent.d.ts +2 -0
- package/dist/utils/pi-user-agent.d.ts.map +1 -0
- package/dist/utils/pi-user-agent.js +12 -0
- package/dist/utils/pi-user-agent.js.map +1 -0
- package/dist/utils/provider-env.d.ts +7 -0
- package/dist/utils/provider-env.d.ts.map +1 -0
- package/dist/utils/provider-env.js +44 -0
- package/dist/utils/provider-env.js.map +1 -0
- package/dist/utils/provider-retry.d.ts +16 -0
- package/dist/utils/provider-retry.d.ts.map +1 -0
- package/dist/utils/provider-retry.js +94 -0
- package/dist/utils/provider-retry.js.map +1 -0
- package/dist/utils/retry.d.ts +53 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +174 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/sanitize-unicode.d.ts +22 -0
- package/dist/utils/sanitize-unicode.d.ts.map +1 -0
- package/dist/utils/sanitize-unicode.js +26 -0
- package/dist/utils/sanitize-unicode.js.map +1 -0
- package/dist/utils/text.d.ts +6 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +10 -0
- package/dist/utils/text.js.map +1 -0
- package/dist/utils/typebox-helpers.d.ts +17 -0
- package/dist/utils/typebox-helpers.d.ts.map +1 -0
- package/dist/utils/typebox-helpers.js +21 -0
- package/dist/utils/typebox-helpers.js.map +1 -0
- package/dist/utils/uuid.d.ts +3 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/utils/uuid.js +46 -0
- package/dist/utils/uuid.js.map +1 -0
- package/dist/utils/validation.d.ts +18 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +309 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +122 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// Shared normalization for provider HTTP error objects.
|
|
2
|
+
//
|
|
3
|
+
// Endpoints behind a proxy / gateway may return a non-2xx response whose body
|
|
4
|
+
// the provider SDK cannot fold into `error.message`. The SDK error object still
|
|
5
|
+
// carries the HTTP status and the raw/parsed body, but under SDK-specific field
|
|
6
|
+
// names. Provider catch blocks that read only `error.message` therefore drop
|
|
7
|
+
// the body and surface opaque messages like `"403 status code (no body)"` or
|
|
8
|
+
// collapse to `"Unknown: UnknownError"`.
|
|
9
|
+
//
|
|
10
|
+
// `normalizeProviderError` probes the known SDK field shapes (Mistral,
|
|
11
|
+
// `openai`, `@google/genai`, AWS Bedrock) and returns a struct each provider
|
|
12
|
+
// composes into its display string. The `messageCarriesBody` flag captures the
|
|
13
|
+
// Anthropic / `@google/genai` happy path where the SDK already folded the body
|
|
14
|
+
// into the message, so providers can preserve it without double-printing.
|
|
15
|
+
export const MAX_PROVIDER_ERROR_BODY_CHARS = 4000;
|
|
16
|
+
export function normalizeProviderError(error) {
|
|
17
|
+
if (!(error instanceof Error)) {
|
|
18
|
+
return { message: safeJsonStringify(error), messageCarriesBody: false };
|
|
19
|
+
}
|
|
20
|
+
const sdkError = error;
|
|
21
|
+
const status = extractStatus(sdkError);
|
|
22
|
+
const body = extractBody(sdkError);
|
|
23
|
+
const messageCarriesBody = body === undefined || error.message.includes(body);
|
|
24
|
+
return {
|
|
25
|
+
status,
|
|
26
|
+
body,
|
|
27
|
+
message: error.message,
|
|
28
|
+
messageCarriesBody,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Probe the HTTP status, first numeric hit wins, in SDK-field order:
|
|
33
|
+
* `statusCode` (Mistral) → `status` (`openai`, `@google/genai`) →
|
|
34
|
+
* `$metadata.httpStatusCode` (Bedrock) → `$response.statusCode` (Bedrock).
|
|
35
|
+
*/
|
|
36
|
+
function extractStatus(error) {
|
|
37
|
+
if (typeof error.statusCode === "number")
|
|
38
|
+
return error.statusCode;
|
|
39
|
+
if (typeof error.status === "number")
|
|
40
|
+
return error.status;
|
|
41
|
+
if (typeof error.$metadata?.httpStatusCode === "number")
|
|
42
|
+
return error.$metadata.httpStatusCode;
|
|
43
|
+
if (typeof error.$response?.statusCode === "number")
|
|
44
|
+
return error.$response.statusCode;
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Probe the raw body reason, first usable hit wins, in SDK-field order:
|
|
49
|
+
* `body` string (Mistral) → `error` parsed JSON body object (`openai` SDK's
|
|
50
|
+
* `this.error`) → `$response.body` (Bedrock). Empty objects and unread response
|
|
51
|
+
* streams are treated as no body so they do not surface as `"{}"` or serialized
|
|
52
|
+
* stream internals. The chosen body is truncated to the cap.
|
|
53
|
+
*/
|
|
54
|
+
function extractBody(error) {
|
|
55
|
+
const bodyText = pickBodyText(error);
|
|
56
|
+
if (bodyText === undefined)
|
|
57
|
+
return undefined;
|
|
58
|
+
const trimmed = bodyText.trim();
|
|
59
|
+
if (trimmed.length === 0)
|
|
60
|
+
return undefined;
|
|
61
|
+
return truncateErrorText(trimmed, MAX_PROVIDER_ERROR_BODY_CHARS);
|
|
62
|
+
}
|
|
63
|
+
function pickBodyText(error) {
|
|
64
|
+
if (typeof error.body === "string")
|
|
65
|
+
return error.body;
|
|
66
|
+
if (isPlainNonEmptyObject(error.error))
|
|
67
|
+
return safeJsonStringify(error.error);
|
|
68
|
+
const responseBody = error.$response?.body;
|
|
69
|
+
if (typeof responseBody === "string")
|
|
70
|
+
return responseBody;
|
|
71
|
+
if (isReadableStreamLike(responseBody))
|
|
72
|
+
return undefined;
|
|
73
|
+
if (isPlainNonEmptyObject(responseBody))
|
|
74
|
+
return safeJsonStringify(responseBody);
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
function isReadableStreamLike(value) {
|
|
78
|
+
return typeof value === "object" && value !== null && "pipe" in value && typeof value.pipe === "function";
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Only a PLAIN object counts as an HTTP body. SDK error fields can hold class
|
|
82
|
+
* instances instead of parsed bodies — AWS SDK v3's `$response.body` is an
|
|
83
|
+
* HTTP stream/response wrapper object, and stringifying one produced garbage
|
|
84
|
+
* like `{"_events":...}` as the "body", which then REPLACED `error.message`
|
|
85
|
+
* in the composed display string. `error.message` is where the SDK puts the
|
|
86
|
+
* real deserialized exception text ("Input is too long...", schema validation
|
|
87
|
+
* details, ...), so the one useful string was discarded for noise. A class
|
|
88
|
+
* instance yields no body, `messageCarriesBody` stays true, and the real
|
|
89
|
+
* message survives. Complements the `pipe` sniffing above: web
|
|
90
|
+
* ReadableStreams (pipeTo/pipeThrough, no `pipe`) and non-stream SDK wrapper
|
|
91
|
+
* classes fail the prototype check, while parsed JSON bodies (plain objects
|
|
92
|
+
* by construction) still pass.
|
|
93
|
+
*/
|
|
94
|
+
function isPlainNonEmptyObject(value) {
|
|
95
|
+
if (typeof value !== "object" || value === null)
|
|
96
|
+
return false;
|
|
97
|
+
const proto = Object.getPrototypeOf(value);
|
|
98
|
+
if (proto !== Object.prototype && proto !== null)
|
|
99
|
+
return false;
|
|
100
|
+
return Object.keys(value).length > 0;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Compose a display string from a normalized error. When the message already
|
|
104
|
+
* carries the body (Anthropic / `@google/genai` happy path) or no body/status
|
|
105
|
+
* was extracted, the message is returned unchanged. Otherwise the status and
|
|
106
|
+
* body are surfaced, with an optional provider prefix.
|
|
107
|
+
*
|
|
108
|
+
* - no prefix: `"<status>: <body>"`
|
|
109
|
+
* - prefix: `"<prefix> (<status>): <body>"`
|
|
110
|
+
*/
|
|
111
|
+
export function formatProviderError(norm, prefix) {
|
|
112
|
+
if (norm.messageCarriesBody || norm.status === undefined || norm.body === undefined) {
|
|
113
|
+
return prefix !== undefined && norm.status !== undefined
|
|
114
|
+
? `${prefix} (${norm.status}): ${norm.message}`
|
|
115
|
+
: norm.message;
|
|
116
|
+
}
|
|
117
|
+
return prefix !== undefined ? `${prefix} (${norm.status}): ${norm.body}` : `${norm.status}: ${norm.body}`;
|
|
118
|
+
}
|
|
119
|
+
export function truncateErrorText(text, maxChars) {
|
|
120
|
+
if (text.length <= maxChars)
|
|
121
|
+
return text;
|
|
122
|
+
return `${text.slice(0, maxChars)}... [truncated ${text.length - maxChars} chars]`;
|
|
123
|
+
}
|
|
124
|
+
export function safeJsonStringify(value) {
|
|
125
|
+
try {
|
|
126
|
+
const serialized = JSON.stringify(value);
|
|
127
|
+
return serialized === undefined ? String(value) : serialized;
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return String(value);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=error-body.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-body.js","sourceRoot":"","sources":["../../src/utils/error-body.ts"],"names":[],"mappings":"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","sourcesContent":["// Shared normalization for provider HTTP error objects.\n//\n// Endpoints behind a proxy / gateway may return a non-2xx response whose body\n// the provider SDK cannot fold into `error.message`. The SDK error object still\n// carries the HTTP status and the raw/parsed body, but under SDK-specific field\n// names. Provider catch blocks that read only `error.message` therefore drop\n// the body and surface opaque messages like `\"403 status code (no body)\"` or\n// collapse to `\"Unknown: UnknownError\"`.\n//\n// `normalizeProviderError` probes the known SDK field shapes (Mistral,\n// `openai`, `@google/genai`, AWS Bedrock) and returns a struct each provider\n// composes into its display string. The `messageCarriesBody` flag captures the\n// Anthropic / `@google/genai` happy path where the SDK already folded the body\n// into the message, so providers can preserve it without double-printing.\n\nexport const MAX_PROVIDER_ERROR_BODY_CHARS = 4000;\n\nexport interface NormalizedProviderError {\n\t/** HTTP status code, when one could be extracted from the SDK error object. */\n\tstatus?: number;\n\t/** Raw HTTP body reason, already trimmed and truncated to the cap. */\n\tbody?: string;\n\t/** `error.message`, or `safeJsonStringify(error)` for a non-`Error` throw. */\n\tmessage: string;\n\t/** True when `message` already contains the body (no separate body to add). */\n\tmessageCarriesBody: boolean;\n}\n\ntype SdkErrorShape = Error & {\n\tstatusCode?: unknown;\n\tstatus?: unknown;\n\tbody?: unknown;\n\terror?: unknown;\n\t$metadata?: { httpStatusCode?: unknown };\n\t$response?: { statusCode?: unknown; body?: unknown };\n};\n\nexport function normalizeProviderError(error: unknown): NormalizedProviderError {\n\tif (!(error instanceof Error)) {\n\t\treturn { message: safeJsonStringify(error), messageCarriesBody: false };\n\t}\n\n\tconst sdkError = error as SdkErrorShape;\n\tconst status = extractStatus(sdkError);\n\tconst body = extractBody(sdkError);\n\tconst messageCarriesBody = body === undefined || error.message.includes(body);\n\n\treturn {\n\t\tstatus,\n\t\tbody,\n\t\tmessage: error.message,\n\t\tmessageCarriesBody,\n\t} satisfies NormalizedProviderError;\n}\n\n/**\n * Probe the HTTP status, first numeric hit wins, in SDK-field order:\n * `statusCode` (Mistral) → `status` (`openai`, `@google/genai`) →\n * `$metadata.httpStatusCode` (Bedrock) → `$response.statusCode` (Bedrock).\n */\nfunction extractStatus(error: SdkErrorShape): number | undefined {\n\tif (typeof error.statusCode === \"number\") return error.statusCode;\n\tif (typeof error.status === \"number\") return error.status;\n\tif (typeof error.$metadata?.httpStatusCode === \"number\") return error.$metadata.httpStatusCode;\n\tif (typeof error.$response?.statusCode === \"number\") return error.$response.statusCode;\n\treturn undefined;\n}\n\n/**\n * Probe the raw body reason, first usable hit wins, in SDK-field order:\n * `body` string (Mistral) → `error` parsed JSON body object (`openai` SDK's\n * `this.error`) → `$response.body` (Bedrock). Empty objects and unread response\n * streams are treated as no body so they do not surface as `\"{}\"` or serialized\n * stream internals. The chosen body is truncated to the cap.\n */\nfunction extractBody(error: SdkErrorShape): string | undefined {\n\tconst bodyText = pickBodyText(error);\n\tif (bodyText === undefined) return undefined;\n\tconst trimmed = bodyText.trim();\n\tif (trimmed.length === 0) return undefined;\n\treturn truncateErrorText(trimmed, MAX_PROVIDER_ERROR_BODY_CHARS);\n}\n\nfunction pickBodyText(error: SdkErrorShape): string | undefined {\n\tif (typeof error.body === \"string\") return error.body;\n\tif (isPlainNonEmptyObject(error.error)) return safeJsonStringify(error.error);\n\tconst responseBody = error.$response?.body;\n\tif (typeof responseBody === \"string\") return responseBody;\n\tif (isReadableStreamLike(responseBody)) return undefined;\n\tif (isPlainNonEmptyObject(responseBody)) return safeJsonStringify(responseBody);\n\treturn undefined;\n}\n\nfunction isReadableStreamLike(value: unknown): boolean {\n\treturn typeof value === \"object\" && value !== null && \"pipe\" in value && typeof value.pipe === \"function\";\n}\n\n/**\n * Only a PLAIN object counts as an HTTP body. SDK error fields can hold class\n * instances instead of parsed bodies — AWS SDK v3's `$response.body` is an\n * HTTP stream/response wrapper object, and stringifying one produced garbage\n * like `{\"_events\":...}` as the \"body\", which then REPLACED `error.message`\n * in the composed display string. `error.message` is where the SDK puts the\n * real deserialized exception text (\"Input is too long...\", schema validation\n * details, ...), so the one useful string was discarded for noise. A class\n * instance yields no body, `messageCarriesBody` stays true, and the real\n * message survives. Complements the `pipe` sniffing above: web\n * ReadableStreams (pipeTo/pipeThrough, no `pipe`) and non-stream SDK wrapper\n * classes fail the prototype check, while parsed JSON bodies (plain objects\n * by construction) still pass.\n */\nfunction isPlainNonEmptyObject(value: unknown): boolean {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst proto = Object.getPrototypeOf(value);\n\tif (proto !== Object.prototype && proto !== null) return false;\n\treturn Object.keys(value).length > 0;\n}\n\n/**\n * Compose a display string from a normalized error. When the message already\n * carries the body (Anthropic / `@google/genai` happy path) or no body/status\n * was extracted, the message is returned unchanged. Otherwise the status and\n * body are surfaced, with an optional provider prefix.\n *\n * - no prefix: `\"<status>: <body>\"`\n * - prefix: `\"<prefix> (<status>): <body>\"`\n */\nexport function formatProviderError(norm: NormalizedProviderError, prefix?: string): string {\n\tif (norm.messageCarriesBody || norm.status === undefined || norm.body === undefined) {\n\t\treturn prefix !== undefined && norm.status !== undefined\n\t\t\t? `${prefix} (${norm.status}): ${norm.message}`\n\t\t\t: norm.message;\n\t}\n\treturn prefix !== undefined ? `${prefix} (${norm.status}): ${norm.body}` : `${norm.status}: ${norm.body}`;\n}\n\nexport function truncateErrorText(text: string, maxChars: number): string {\n\tif (text.length <= maxChars) return text;\n\treturn `${text.slice(0, maxChars)}... [truncated ${text.length - maxChars} chars]`;\n}\n\nexport function safeJsonStringify(value: unknown): string {\n\ttry {\n\t\tconst serialized = JSON.stringify(value);\n\t\treturn serialized === undefined ? String(value) : serialized;\n\t} catch {\n\t\treturn String(value);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Context, ImageContent, Message, TextContent, Usage } from "../types.ts";
|
|
2
|
+
export interface ContextUsageEstimate {
|
|
3
|
+
/** Estimated total context tokens. */
|
|
4
|
+
tokens: number;
|
|
5
|
+
/** Tokens reported by the most recent applicable assistant usage block. */
|
|
6
|
+
usageTokens: number;
|
|
7
|
+
/** Estimated tokens after the most recent applicable assistant usage block. */
|
|
8
|
+
trailingTokens: number;
|
|
9
|
+
/** Index of the applicable message that provided usage, or null when none exists. */
|
|
10
|
+
lastUsageIndex: number | null;
|
|
11
|
+
}
|
|
12
|
+
export declare function calculateContextTokens(usage: Usage): number;
|
|
13
|
+
export declare function estimateTextTokens(text: string): number;
|
|
14
|
+
export declare function estimateTextAndImageContentTokens(content: string | Array<TextContent | ImageContent>): number;
|
|
15
|
+
export declare function estimateMessageTokens(message: Message): number;
|
|
16
|
+
export declare function estimateContextTokens(context: Context | readonly Message[]): ContextUsageEstimate;
|
|
17
|
+
//# sourceMappingURL=estimate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estimate.d.ts","sourceRoot":"","sources":["../../src/utils/estimate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAQ,KAAK,EAAE,MAAM,aAAa,CAAC;AAE9G,MAAM,WAAW,oBAAoB;IACpC,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,cAAc,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAKD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAE3D;AAkBD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,WAAW,GAAG,YAAY,CAAC,GAAG,MAAM,CAE7G;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAgB9D;AAqDD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,OAAO,EAAE,GAAG,oBAAoB,CA6BjG","sourcesContent":["import type { AssistantMessage, Context, ImageContent, Message, TextContent, Tool, Usage } from \"../types.ts\";\n\nexport interface ContextUsageEstimate {\n\t/** Estimated total context tokens. */\n\ttokens: number;\n\t/** Tokens reported by the most recent applicable assistant usage block. */\n\tusageTokens: number;\n\t/** Estimated tokens after the most recent applicable assistant usage block. */\n\ttrailingTokens: number;\n\t/** Index of the applicable message that provided usage, or null when none exists. */\n\tlastUsageIndex: number | null;\n}\n\nconst CHARS_PER_TOKEN = 4;\nconst ESTIMATED_IMAGE_CHARS = 4800;\n\nexport function calculateContextTokens(usage: Usage): number {\n\treturn usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;\n}\n\nfunction safeJsonStringify(value: unknown): string {\n\ttry {\n\t\treturn JSON.stringify(value) ?? \"undefined\";\n\t} catch {\n\t\treturn \"[unserializable]\";\n\t}\n}\n\nfunction estimateTextAndImageContentChars(content: string | Array<TextContent | ImageContent>): number {\n\tif (typeof content === \"string\") return content.length;\n\n\tlet chars = 0;\n\tfor (const block of content) chars += block.type === \"text\" ? block.text.length : ESTIMATED_IMAGE_CHARS;\n\treturn chars;\n}\n\nexport function estimateTextTokens(text: string): number {\n\treturn Math.ceil(text.length / CHARS_PER_TOKEN);\n}\n\nexport function estimateTextAndImageContentTokens(content: string | Array<TextContent | ImageContent>): number {\n\treturn Math.ceil(estimateTextAndImageContentChars(content) / CHARS_PER_TOKEN);\n}\n\nexport function estimateMessageTokens(message: Message): number {\n\tlet chars = 0;\n\n\tif (message.role === \"user\") return estimateTextAndImageContentTokens(message.content);\n\tif (message.role === \"toolResult\") return estimateTextAndImageContentTokens(message.content);\n\n\tfor (const block of message.content) {\n\t\tif (block.type === \"text\") {\n\t\t\tchars += block.text.length;\n\t\t} else if (block.type === \"thinking\") {\n\t\t\tchars += block.thinking.length;\n\t\t} else {\n\t\t\tchars += block.name.length + safeJsonStringify(block.arguments).length;\n\t\t}\n\t}\n\treturn Math.ceil(chars / CHARS_PER_TOKEN);\n}\n\nfunction getLastAssistantUsageInfo(messages: readonly Message[]): { usage: Usage; index: number } | undefined {\n\tlet latestPrefixTimestamp = Number.NEGATIVE_INFINITY;\n\tlet usageInfo: { usage: Usage; index: number } | undefined;\n\n\tfor (let i = 0; i < messages.length; i++) {\n\t\tconst message = messages[i];\n\t\tif (message.role === \"assistant\") {\n\t\t\tconst assistant = message as AssistantMessage;\n\t\t\t// A newer prefix message was inserted after this response (for example, a\n\t\t\t// compaction summary), so its usage cannot describe the current prefix.\n\t\t\tconst usageAppliesToPrefix = assistant.timestamp >= latestPrefixTimestamp;\n\t\t\tif (\n\t\t\t\tusageAppliesToPrefix &&\n\t\t\t\tassistant.stopReason !== \"aborted\" &&\n\t\t\t\tassistant.stopReason !== \"error\" &&\n\t\t\t\tcalculateContextTokens(assistant.usage) > 0\n\t\t\t) {\n\t\t\t\tusageInfo = { usage: assistant.usage, index: i };\n\t\t\t}\n\t\t}\n\t\tlatestPrefixTimestamp = Math.max(latestPrefixTimestamp, message.timestamp);\n\t}\n\n\treturn usageInfo;\n}\n\nfunction estimateMessages(messages: readonly Message[]): ContextUsageEstimate {\n\tconst usageInfo = getLastAssistantUsageInfo(messages);\n\tif (usageInfo) {\n\t\tconst usageTokens = calculateContextTokens(usageInfo.usage);\n\t\tlet trailingTokens = 0;\n\t\tfor (let i = usageInfo.index + 1; i < messages.length; i++) {\n\t\t\ttrailingTokens += estimateMessageTokens(messages[i]);\n\t\t}\n\t\treturn { tokens: usageTokens + trailingTokens, usageTokens, trailingTokens, lastUsageIndex: usageInfo.index };\n\t}\n\n\tlet tokens = 0;\n\tfor (const message of messages) tokens += estimateMessageTokens(message);\n\treturn { tokens, usageTokens: 0, trailingTokens: tokens, lastUsageIndex: null };\n}\n\nfunction estimateToolsTokens(tools: readonly Tool[] | undefined): number {\n\tif (!tools || tools.length === 0) return 0;\n\treturn estimateTextTokens(safeJsonStringify(tools));\n}\n\nfunction isMessageArray(value: Context | readonly Message[]): value is readonly Message[] {\n\treturn Array.isArray(value);\n}\n\nexport function estimateContextTokens(context: Context | readonly Message[]): ContextUsageEstimate {\n\tif (isMessageArray(context)) return estimateMessages(context);\n\n\tconst estimate = estimateMessages(context.messages);\n\tif (estimate.lastUsageIndex !== null) {\n\t\tconst addedNames = new Set(\n\t\t\tcontext.messages\n\t\t\t\t.slice(estimate.lastUsageIndex + 1)\n\t\t\t\t.filter((message) => message.role === \"toolResult\")\n\t\t\t\t.flatMap((message) => message.addedToolNames ?? []),\n\t\t);\n\t\tconst addedToolTokens = estimateToolsTokens(context.tools?.filter((tool) => addedNames.has(tool.name)));\n\t\treturn {\n\t\t\ttokens: estimate.tokens + addedToolTokens,\n\t\t\tusageTokens: estimate.usageTokens,\n\t\t\ttrailingTokens: estimate.trailingTokens + addedToolTokens,\n\t\t\tlastUsageIndex: estimate.lastUsageIndex,\n\t\t};\n\t}\n\n\tconst prefixTokens =\n\t\t(context.systemPrompt ? estimateTextTokens(context.systemPrompt) : 0) + estimateToolsTokens(context.tools);\n\n\treturn {\n\t\ttokens: estimate.tokens + prefixTokens,\n\t\tusageTokens: estimate.usageTokens,\n\t\ttrailingTokens: estimate.trailingTokens + prefixTokens,\n\t\tlastUsageIndex: estimate.lastUsageIndex,\n\t};\n}\n"]}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const CHARS_PER_TOKEN = 4;
|
|
2
|
+
const ESTIMATED_IMAGE_CHARS = 4800;
|
|
3
|
+
export function calculateContextTokens(usage) {
|
|
4
|
+
return usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
5
|
+
}
|
|
6
|
+
function safeJsonStringify(value) {
|
|
7
|
+
try {
|
|
8
|
+
return JSON.stringify(value) ?? "undefined";
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return "[unserializable]";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function estimateTextAndImageContentChars(content) {
|
|
15
|
+
if (typeof content === "string")
|
|
16
|
+
return content.length;
|
|
17
|
+
let chars = 0;
|
|
18
|
+
for (const block of content)
|
|
19
|
+
chars += block.type === "text" ? block.text.length : ESTIMATED_IMAGE_CHARS;
|
|
20
|
+
return chars;
|
|
21
|
+
}
|
|
22
|
+
export function estimateTextTokens(text) {
|
|
23
|
+
return Math.ceil(text.length / CHARS_PER_TOKEN);
|
|
24
|
+
}
|
|
25
|
+
export function estimateTextAndImageContentTokens(content) {
|
|
26
|
+
return Math.ceil(estimateTextAndImageContentChars(content) / CHARS_PER_TOKEN);
|
|
27
|
+
}
|
|
28
|
+
export function estimateMessageTokens(message) {
|
|
29
|
+
let chars = 0;
|
|
30
|
+
if (message.role === "user")
|
|
31
|
+
return estimateTextAndImageContentTokens(message.content);
|
|
32
|
+
if (message.role === "toolResult")
|
|
33
|
+
return estimateTextAndImageContentTokens(message.content);
|
|
34
|
+
for (const block of message.content) {
|
|
35
|
+
if (block.type === "text") {
|
|
36
|
+
chars += block.text.length;
|
|
37
|
+
}
|
|
38
|
+
else if (block.type === "thinking") {
|
|
39
|
+
chars += block.thinking.length;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
chars += block.name.length + safeJsonStringify(block.arguments).length;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return Math.ceil(chars / CHARS_PER_TOKEN);
|
|
46
|
+
}
|
|
47
|
+
function getLastAssistantUsageInfo(messages) {
|
|
48
|
+
let latestPrefixTimestamp = Number.NEGATIVE_INFINITY;
|
|
49
|
+
let usageInfo;
|
|
50
|
+
for (let i = 0; i < messages.length; i++) {
|
|
51
|
+
const message = messages[i];
|
|
52
|
+
if (message.role === "assistant") {
|
|
53
|
+
const assistant = message;
|
|
54
|
+
// A newer prefix message was inserted after this response (for example, a
|
|
55
|
+
// compaction summary), so its usage cannot describe the current prefix.
|
|
56
|
+
const usageAppliesToPrefix = assistant.timestamp >= latestPrefixTimestamp;
|
|
57
|
+
if (usageAppliesToPrefix &&
|
|
58
|
+
assistant.stopReason !== "aborted" &&
|
|
59
|
+
assistant.stopReason !== "error" &&
|
|
60
|
+
calculateContextTokens(assistant.usage) > 0) {
|
|
61
|
+
usageInfo = { usage: assistant.usage, index: i };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
latestPrefixTimestamp = Math.max(latestPrefixTimestamp, message.timestamp);
|
|
65
|
+
}
|
|
66
|
+
return usageInfo;
|
|
67
|
+
}
|
|
68
|
+
function estimateMessages(messages) {
|
|
69
|
+
const usageInfo = getLastAssistantUsageInfo(messages);
|
|
70
|
+
if (usageInfo) {
|
|
71
|
+
const usageTokens = calculateContextTokens(usageInfo.usage);
|
|
72
|
+
let trailingTokens = 0;
|
|
73
|
+
for (let i = usageInfo.index + 1; i < messages.length; i++) {
|
|
74
|
+
trailingTokens += estimateMessageTokens(messages[i]);
|
|
75
|
+
}
|
|
76
|
+
return { tokens: usageTokens + trailingTokens, usageTokens, trailingTokens, lastUsageIndex: usageInfo.index };
|
|
77
|
+
}
|
|
78
|
+
let tokens = 0;
|
|
79
|
+
for (const message of messages)
|
|
80
|
+
tokens += estimateMessageTokens(message);
|
|
81
|
+
return { tokens, usageTokens: 0, trailingTokens: tokens, lastUsageIndex: null };
|
|
82
|
+
}
|
|
83
|
+
function estimateToolsTokens(tools) {
|
|
84
|
+
if (!tools || tools.length === 0)
|
|
85
|
+
return 0;
|
|
86
|
+
return estimateTextTokens(safeJsonStringify(tools));
|
|
87
|
+
}
|
|
88
|
+
function isMessageArray(value) {
|
|
89
|
+
return Array.isArray(value);
|
|
90
|
+
}
|
|
91
|
+
export function estimateContextTokens(context) {
|
|
92
|
+
if (isMessageArray(context))
|
|
93
|
+
return estimateMessages(context);
|
|
94
|
+
const estimate = estimateMessages(context.messages);
|
|
95
|
+
if (estimate.lastUsageIndex !== null) {
|
|
96
|
+
const addedNames = new Set(context.messages
|
|
97
|
+
.slice(estimate.lastUsageIndex + 1)
|
|
98
|
+
.filter((message) => message.role === "toolResult")
|
|
99
|
+
.flatMap((message) => message.addedToolNames ?? []));
|
|
100
|
+
const addedToolTokens = estimateToolsTokens(context.tools?.filter((tool) => addedNames.has(tool.name)));
|
|
101
|
+
return {
|
|
102
|
+
tokens: estimate.tokens + addedToolTokens,
|
|
103
|
+
usageTokens: estimate.usageTokens,
|
|
104
|
+
trailingTokens: estimate.trailingTokens + addedToolTokens,
|
|
105
|
+
lastUsageIndex: estimate.lastUsageIndex,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const prefixTokens = (context.systemPrompt ? estimateTextTokens(context.systemPrompt) : 0) + estimateToolsTokens(context.tools);
|
|
109
|
+
return {
|
|
110
|
+
tokens: estimate.tokens + prefixTokens,
|
|
111
|
+
usageTokens: estimate.usageTokens,
|
|
112
|
+
trailingTokens: estimate.trailingTokens + prefixTokens,
|
|
113
|
+
lastUsageIndex: estimate.lastUsageIndex,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=estimate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"estimate.js","sourceRoot":"","sources":["../../src/utils/estimate.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage, Context, ImageContent, Message, TextContent, Tool, Usage } from \"../types.ts\";\n\nexport interface ContextUsageEstimate {\n\t/** Estimated total context tokens. */\n\ttokens: number;\n\t/** Tokens reported by the most recent applicable assistant usage block. */\n\tusageTokens: number;\n\t/** Estimated tokens after the most recent applicable assistant usage block. */\n\ttrailingTokens: number;\n\t/** Index of the applicable message that provided usage, or null when none exists. */\n\tlastUsageIndex: number | null;\n}\n\nconst CHARS_PER_TOKEN = 4;\nconst ESTIMATED_IMAGE_CHARS = 4800;\n\nexport function calculateContextTokens(usage: Usage): number {\n\treturn usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;\n}\n\nfunction safeJsonStringify(value: unknown): string {\n\ttry {\n\t\treturn JSON.stringify(value) ?? \"undefined\";\n\t} catch {\n\t\treturn \"[unserializable]\";\n\t}\n}\n\nfunction estimateTextAndImageContentChars(content: string | Array<TextContent | ImageContent>): number {\n\tif (typeof content === \"string\") return content.length;\n\n\tlet chars = 0;\n\tfor (const block of content) chars += block.type === \"text\" ? block.text.length : ESTIMATED_IMAGE_CHARS;\n\treturn chars;\n}\n\nexport function estimateTextTokens(text: string): number {\n\treturn Math.ceil(text.length / CHARS_PER_TOKEN);\n}\n\nexport function estimateTextAndImageContentTokens(content: string | Array<TextContent | ImageContent>): number {\n\treturn Math.ceil(estimateTextAndImageContentChars(content) / CHARS_PER_TOKEN);\n}\n\nexport function estimateMessageTokens(message: Message): number {\n\tlet chars = 0;\n\n\tif (message.role === \"user\") return estimateTextAndImageContentTokens(message.content);\n\tif (message.role === \"toolResult\") return estimateTextAndImageContentTokens(message.content);\n\n\tfor (const block of message.content) {\n\t\tif (block.type === \"text\") {\n\t\t\tchars += block.text.length;\n\t\t} else if (block.type === \"thinking\") {\n\t\t\tchars += block.thinking.length;\n\t\t} else {\n\t\t\tchars += block.name.length + safeJsonStringify(block.arguments).length;\n\t\t}\n\t}\n\treturn Math.ceil(chars / CHARS_PER_TOKEN);\n}\n\nfunction getLastAssistantUsageInfo(messages: readonly Message[]): { usage: Usage; index: number } | undefined {\n\tlet latestPrefixTimestamp = Number.NEGATIVE_INFINITY;\n\tlet usageInfo: { usage: Usage; index: number } | undefined;\n\n\tfor (let i = 0; i < messages.length; i++) {\n\t\tconst message = messages[i];\n\t\tif (message.role === \"assistant\") {\n\t\t\tconst assistant = message as AssistantMessage;\n\t\t\t// A newer prefix message was inserted after this response (for example, a\n\t\t\t// compaction summary), so its usage cannot describe the current prefix.\n\t\t\tconst usageAppliesToPrefix = assistant.timestamp >= latestPrefixTimestamp;\n\t\t\tif (\n\t\t\t\tusageAppliesToPrefix &&\n\t\t\t\tassistant.stopReason !== \"aborted\" &&\n\t\t\t\tassistant.stopReason !== \"error\" &&\n\t\t\t\tcalculateContextTokens(assistant.usage) > 0\n\t\t\t) {\n\t\t\t\tusageInfo = { usage: assistant.usage, index: i };\n\t\t\t}\n\t\t}\n\t\tlatestPrefixTimestamp = Math.max(latestPrefixTimestamp, message.timestamp);\n\t}\n\n\treturn usageInfo;\n}\n\nfunction estimateMessages(messages: readonly Message[]): ContextUsageEstimate {\n\tconst usageInfo = getLastAssistantUsageInfo(messages);\n\tif (usageInfo) {\n\t\tconst usageTokens = calculateContextTokens(usageInfo.usage);\n\t\tlet trailingTokens = 0;\n\t\tfor (let i = usageInfo.index + 1; i < messages.length; i++) {\n\t\t\ttrailingTokens += estimateMessageTokens(messages[i]);\n\t\t}\n\t\treturn { tokens: usageTokens + trailingTokens, usageTokens, trailingTokens, lastUsageIndex: usageInfo.index };\n\t}\n\n\tlet tokens = 0;\n\tfor (const message of messages) tokens += estimateMessageTokens(message);\n\treturn { tokens, usageTokens: 0, trailingTokens: tokens, lastUsageIndex: null };\n}\n\nfunction estimateToolsTokens(tools: readonly Tool[] | undefined): number {\n\tif (!tools || tools.length === 0) return 0;\n\treturn estimateTextTokens(safeJsonStringify(tools));\n}\n\nfunction isMessageArray(value: Context | readonly Message[]): value is readonly Message[] {\n\treturn Array.isArray(value);\n}\n\nexport function estimateContextTokens(context: Context | readonly Message[]): ContextUsageEstimate {\n\tif (isMessageArray(context)) return estimateMessages(context);\n\n\tconst estimate = estimateMessages(context.messages);\n\tif (estimate.lastUsageIndex !== null) {\n\t\tconst addedNames = new Set(\n\t\t\tcontext.messages\n\t\t\t\t.slice(estimate.lastUsageIndex + 1)\n\t\t\t\t.filter((message) => message.role === \"toolResult\")\n\t\t\t\t.flatMap((message) => message.addedToolNames ?? []),\n\t\t);\n\t\tconst addedToolTokens = estimateToolsTokens(context.tools?.filter((tool) => addedNames.has(tool.name)));\n\t\treturn {\n\t\t\ttokens: estimate.tokens + addedToolTokens,\n\t\t\tusageTokens: estimate.usageTokens,\n\t\t\ttrailingTokens: estimate.trailingTokens + addedToolTokens,\n\t\t\tlastUsageIndex: estimate.lastUsageIndex,\n\t\t};\n\t}\n\n\tconst prefixTokens =\n\t\t(context.systemPrompt ? estimateTextTokens(context.systemPrompt) : 0) + estimateToolsTokens(context.tools);\n\n\treturn {\n\t\ttokens: estimate.tokens + prefixTokens,\n\t\tusageTokens: estimate.usageTokens,\n\t\ttrailingTokens: estimate.trailingTokens + prefixTokens,\n\t\tlastUsageIndex: estimate.lastUsageIndex,\n\t};\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AssistantMessage, AssistantMessageEvent } from "../types.ts";
|
|
2
|
+
export declare class EventStream<T, R = T> implements AsyncIterable<T> {
|
|
3
|
+
private queue;
|
|
4
|
+
private waiting;
|
|
5
|
+
private done;
|
|
6
|
+
private finalResultPromise;
|
|
7
|
+
private resolveFinalResult;
|
|
8
|
+
private isComplete;
|
|
9
|
+
private extractResult;
|
|
10
|
+
constructor(isComplete: (event: T) => boolean, extractResult: (event: T) => R);
|
|
11
|
+
push(event: T): void;
|
|
12
|
+
end(result?: R): void;
|
|
13
|
+
[Symbol.asyncIterator](): AsyncIterator<T>;
|
|
14
|
+
result(): Promise<R>;
|
|
15
|
+
}
|
|
16
|
+
export declare class AssistantMessageEventStream extends EventStream<AssistantMessageEvent, AssistantMessage> {
|
|
17
|
+
constructor();
|
|
18
|
+
}
|
|
19
|
+
/** Factory function for AssistantMessageEventStream (for use in extensions) */
|
|
20
|
+
export declare function createAssistantMessageEventStream(): AssistantMessageEventStream;
|
|
21
|
+
//# sourceMappingURL=event-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-stream.d.ts","sourceRoot":"","sources":["../../src/utils/event-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAG3E,qBAAa,WAAW,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAE,YAAW,aAAa,CAAC,CAAC,CAAC;IAC7D,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,OAAO,CAA8C;IAC7D,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,aAAa,CAAkB;IAEvC,YAAY,UAAU,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,EAAE,aAAa,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAM5E;IAED,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAenB;IAED,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAUpB;IAEM,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,CAYhD;IAED,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,CAEnB;CACD;AAED,qBAAa,2BAA4B,SAAQ,WAAW,CAAC,qBAAqB,EAAE,gBAAgB,CAAC;IACpG,cAYC;CACD;AAED,+EAA+E;AAC/E,wBAAgB,iCAAiC,IAAI,2BAA2B,CAE/E","sourcesContent":["import type { AssistantMessage, AssistantMessageEvent } from \"../types.ts\";\n\n// Generic event stream class for async iteration\nexport class EventStream<T, R = T> implements AsyncIterable<T> {\n\tprivate queue: T[] = [];\n\tprivate waiting: ((value: IteratorResult<T>) => void)[] = [];\n\tprivate done = false;\n\tprivate finalResultPromise: Promise<R>;\n\tprivate resolveFinalResult!: (result: R) => void;\n\tprivate isComplete: (event: T) => boolean;\n\tprivate extractResult: (event: T) => R;\n\n\tconstructor(isComplete: (event: T) => boolean, extractResult: (event: T) => R) {\n\t\tthis.isComplete = isComplete;\n\t\tthis.extractResult = extractResult;\n\t\tthis.finalResultPromise = new Promise((resolve) => {\n\t\t\tthis.resolveFinalResult = resolve;\n\t\t});\n\t}\n\n\tpush(event: T): void {\n\t\tif (this.done) return;\n\n\t\tif (this.isComplete(event)) {\n\t\t\tthis.done = true;\n\t\t\tthis.resolveFinalResult(this.extractResult(event));\n\t\t}\n\n\t\t// Deliver to waiting consumer or queue it\n\t\tconst waiter = this.waiting.shift();\n\t\tif (waiter) {\n\t\t\twaiter({ value: event, done: false });\n\t\t} else {\n\t\t\tthis.queue.push(event);\n\t\t}\n\t}\n\n\tend(result?: R): void {\n\t\tthis.done = true;\n\t\tif (result !== undefined) {\n\t\t\tthis.resolveFinalResult(result);\n\t\t}\n\t\t// Notify all waiting consumers that we're done\n\t\twhile (this.waiting.length > 0) {\n\t\t\tconst waiter = this.waiting.shift()!;\n\t\t\twaiter({ value: undefined as any, done: true });\n\t\t}\n\t}\n\n\tasync *[Symbol.asyncIterator](): AsyncIterator<T> {\n\t\twhile (true) {\n\t\t\tif (this.queue.length > 0) {\n\t\t\t\tyield this.queue.shift()!;\n\t\t\t} else if (this.done) {\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tconst result = await new Promise<IteratorResult<T>>((resolve) => this.waiting.push(resolve));\n\t\t\t\tif (result.done) return;\n\t\t\t\tyield result.value;\n\t\t\t}\n\t\t}\n\t}\n\n\tresult(): Promise<R> {\n\t\treturn this.finalResultPromise;\n\t}\n}\n\nexport class AssistantMessageEventStream extends EventStream<AssistantMessageEvent, AssistantMessage> {\n\tconstructor() {\n\t\tsuper(\n\t\t\t(event) => event.type === \"done\" || event.type === \"error\",\n\t\t\t(event) => {\n\t\t\t\tif (event.type === \"done\") {\n\t\t\t\t\treturn event.message;\n\t\t\t\t} else if (event.type === \"error\") {\n\t\t\t\t\treturn event.error;\n\t\t\t\t}\n\t\t\t\tthrow new Error(\"Unexpected event type for final result\");\n\t\t\t},\n\t\t);\n\t}\n}\n\n/** Factory function for AssistantMessageEventStream (for use in extensions) */\nexport function createAssistantMessageEventStream(): AssistantMessageEventStream {\n\treturn new AssistantMessageEventStream();\n}\n"]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Generic event stream class for async iteration
|
|
2
|
+
export class EventStream {
|
|
3
|
+
queue = [];
|
|
4
|
+
waiting = [];
|
|
5
|
+
done = false;
|
|
6
|
+
finalResultPromise;
|
|
7
|
+
resolveFinalResult;
|
|
8
|
+
isComplete;
|
|
9
|
+
extractResult;
|
|
10
|
+
constructor(isComplete, extractResult) {
|
|
11
|
+
this.isComplete = isComplete;
|
|
12
|
+
this.extractResult = extractResult;
|
|
13
|
+
this.finalResultPromise = new Promise((resolve) => {
|
|
14
|
+
this.resolveFinalResult = resolve;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
push(event) {
|
|
18
|
+
if (this.done)
|
|
19
|
+
return;
|
|
20
|
+
if (this.isComplete(event)) {
|
|
21
|
+
this.done = true;
|
|
22
|
+
this.resolveFinalResult(this.extractResult(event));
|
|
23
|
+
}
|
|
24
|
+
// Deliver to waiting consumer or queue it
|
|
25
|
+
const waiter = this.waiting.shift();
|
|
26
|
+
if (waiter) {
|
|
27
|
+
waiter({ value: event, done: false });
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
this.queue.push(event);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
end(result) {
|
|
34
|
+
this.done = true;
|
|
35
|
+
if (result !== undefined) {
|
|
36
|
+
this.resolveFinalResult(result);
|
|
37
|
+
}
|
|
38
|
+
// Notify all waiting consumers that we're done
|
|
39
|
+
while (this.waiting.length > 0) {
|
|
40
|
+
const waiter = this.waiting.shift();
|
|
41
|
+
waiter({ value: undefined, done: true });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async *[Symbol.asyncIterator]() {
|
|
45
|
+
while (true) {
|
|
46
|
+
if (this.queue.length > 0) {
|
|
47
|
+
yield this.queue.shift();
|
|
48
|
+
}
|
|
49
|
+
else if (this.done) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const result = await new Promise((resolve) => this.waiting.push(resolve));
|
|
54
|
+
if (result.done)
|
|
55
|
+
return;
|
|
56
|
+
yield result.value;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
result() {
|
|
61
|
+
return this.finalResultPromise;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export class AssistantMessageEventStream extends EventStream {
|
|
65
|
+
constructor() {
|
|
66
|
+
super((event) => event.type === "done" || event.type === "error", (event) => {
|
|
67
|
+
if (event.type === "done") {
|
|
68
|
+
return event.message;
|
|
69
|
+
}
|
|
70
|
+
else if (event.type === "error") {
|
|
71
|
+
return event.error;
|
|
72
|
+
}
|
|
73
|
+
throw new Error("Unexpected event type for final result");
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** Factory function for AssistantMessageEventStream (for use in extensions) */
|
|
78
|
+
export function createAssistantMessageEventStream() {
|
|
79
|
+
return new AssistantMessageEventStream();
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=event-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-stream.js","sourceRoot":"","sources":["../../src/utils/event-stream.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AssistantMessage, AssistantMessageEvent } from \"../types.ts\";\n\n// Generic event stream class for async iteration\nexport class EventStream<T, R = T> implements AsyncIterable<T> {\n\tprivate queue: T[] = [];\n\tprivate waiting: ((value: IteratorResult<T>) => void)[] = [];\n\tprivate done = false;\n\tprivate finalResultPromise: Promise<R>;\n\tprivate resolveFinalResult!: (result: R) => void;\n\tprivate isComplete: (event: T) => boolean;\n\tprivate extractResult: (event: T) => R;\n\n\tconstructor(isComplete: (event: T) => boolean, extractResult: (event: T) => R) {\n\t\tthis.isComplete = isComplete;\n\t\tthis.extractResult = extractResult;\n\t\tthis.finalResultPromise = new Promise((resolve) => {\n\t\t\tthis.resolveFinalResult = resolve;\n\t\t});\n\t}\n\n\tpush(event: T): void {\n\t\tif (this.done) return;\n\n\t\tif (this.isComplete(event)) {\n\t\t\tthis.done = true;\n\t\t\tthis.resolveFinalResult(this.extractResult(event));\n\t\t}\n\n\t\t// Deliver to waiting consumer or queue it\n\t\tconst waiter = this.waiting.shift();\n\t\tif (waiter) {\n\t\t\twaiter({ value: event, done: false });\n\t\t} else {\n\t\t\tthis.queue.push(event);\n\t\t}\n\t}\n\n\tend(result?: R): void {\n\t\tthis.done = true;\n\t\tif (result !== undefined) {\n\t\t\tthis.resolveFinalResult(result);\n\t\t}\n\t\t// Notify all waiting consumers that we're done\n\t\twhile (this.waiting.length > 0) {\n\t\t\tconst waiter = this.waiting.shift()!;\n\t\t\twaiter({ value: undefined as any, done: true });\n\t\t}\n\t}\n\n\tasync *[Symbol.asyncIterator](): AsyncIterator<T> {\n\t\twhile (true) {\n\t\t\tif (this.queue.length > 0) {\n\t\t\t\tyield this.queue.shift()!;\n\t\t\t} else if (this.done) {\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tconst result = await new Promise<IteratorResult<T>>((resolve) => this.waiting.push(resolve));\n\t\t\t\tif (result.done) return;\n\t\t\t\tyield result.value;\n\t\t\t}\n\t\t}\n\t}\n\n\tresult(): Promise<R> {\n\t\treturn this.finalResultPromise;\n\t}\n}\n\nexport class AssistantMessageEventStream extends EventStream<AssistantMessageEvent, AssistantMessage> {\n\tconstructor() {\n\t\tsuper(\n\t\t\t(event) => event.type === \"done\" || event.type === \"error\",\n\t\t\t(event) => {\n\t\t\t\tif (event.type === \"done\") {\n\t\t\t\t\treturn event.message;\n\t\t\t\t} else if (event.type === \"error\") {\n\t\t\t\t\treturn event.error;\n\t\t\t\t}\n\t\t\t\tthrow new Error(\"Unexpected event type for final result\");\n\t\t\t},\n\t\t);\n\t}\n}\n\n/** Factory function for AssistantMessageEventStream (for use in extensions) */\nexport function createAssistantMessageEventStream(): AssistantMessageEventStream {\n\treturn new AssistantMessageEventStream();\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAW7C","sourcesContent":["/** Fast deterministic hash to shorten long strings */\nexport function shortHash(str: string): string {\n\tlet h1 = 0xdeadbeef;\n\tlet h2 = 0x41c6ce57;\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst ch = str.charCodeAt(i);\n\t\th1 = Math.imul(h1 ^ ch, 2654435761);\n\t\th2 = Math.imul(h2 ^ ch, 1597334677);\n\t}\n\th1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n\th2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n\treturn (h2 >>> 0).toString(36) + (h1 >>> 0).toString(36);\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Fast deterministic hash to shorten long strings */
|
|
2
|
+
export function shortHash(str) {
|
|
3
|
+
let h1 = 0xdeadbeef;
|
|
4
|
+
let h2 = 0x41c6ce57;
|
|
5
|
+
for (let i = 0; i < str.length; i++) {
|
|
6
|
+
const ch = str.charCodeAt(i);
|
|
7
|
+
h1 = Math.imul(h1 ^ ch, 2654435761);
|
|
8
|
+
h2 = Math.imul(h2 ^ ch, 1597334677);
|
|
9
|
+
}
|
|
10
|
+
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
|
11
|
+
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
|
|
12
|
+
return (h2 >>> 0).toString(36) + (h1 >>> 0).toString(36);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/utils/hash.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,MAAM,UAAU,SAAS,CAAC,GAAW,EAAU;IAC9C,IAAI,EAAE,GAAG,UAAU,CAAC;IACpB,IAAI,EAAE,GAAG,UAAU,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC7B,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;QACpC,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;IACrC,CAAC;IACD,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IACvF,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IACvF,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAAA,CACzD","sourcesContent":["/** Fast deterministic hash to shorten long strings */\nexport function shortHash(str: string): string {\n\tlet h1 = 0xdeadbeef;\n\tlet h2 = 0x41c6ce57;\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst ch = str.charCodeAt(i);\n\t\th1 = Math.imul(h1 ^ ch, 2654435761);\n\t\th2 = Math.imul(h2 ^ ch, 1597334677);\n\t}\n\th1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n\th2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n\treturn (h2 >>> 0).toString(36) + (h1 >>> 0).toString(36);\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ProviderHeaders } from "../types.ts";
|
|
2
|
+
export declare function headersToRecord(headers: Headers): Record<string, string>;
|
|
3
|
+
export declare function providerHeadersToRecord(headers: ProviderHeaders | undefined): Record<string, string> | undefined;
|
|
4
|
+
//# sourceMappingURL=headers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/utils/headers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMxE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAOhH","sourcesContent":["import type { ProviderHeaders } from \"../types.ts\";\n\nexport function headersToRecord(headers: Headers): Record<string, string> {\n\tconst result: Record<string, string> = {};\n\tfor (const [key, value] of headers.entries()) {\n\t\tresult[key] = value;\n\t}\n\treturn result;\n}\n\nexport function providerHeadersToRecord(headers: ProviderHeaders | undefined): Record<string, string> | undefined {\n\tif (!headers) return undefined;\n\tconst result: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value !== null) result[key] = value;\n\t}\n\treturn Object.keys(result).length > 0 ? result : undefined;\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function headersToRecord(headers) {
|
|
2
|
+
const result = {};
|
|
3
|
+
for (const [key, value] of headers.entries()) {
|
|
4
|
+
result[key] = value;
|
|
5
|
+
}
|
|
6
|
+
return result;
|
|
7
|
+
}
|
|
8
|
+
export function providerHeadersToRecord(headers) {
|
|
9
|
+
if (!headers)
|
|
10
|
+
return undefined;
|
|
11
|
+
const result = {};
|
|
12
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
13
|
+
if (value !== null)
|
|
14
|
+
result[key] = value;
|
|
15
|
+
}
|
|
16
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=headers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../src/utils/headers.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,OAAgB,EAA0B;IACzE,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;QAC9C,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC;AAAA,CACd;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAoC,EAAsC;IACjH,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,IAAI,KAAK,KAAK,IAAI;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACzC,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAAA,CAC3D","sourcesContent":["import type { ProviderHeaders } from \"../types.ts\";\n\nexport function headersToRecord(headers: Headers): Record<string, string> {\n\tconst result: Record<string, string> = {};\n\tfor (const [key, value] of headers.entries()) {\n\t\tresult[key] = value;\n\t}\n\treturn result;\n}\n\nexport function providerHeadersToRecord(headers: ProviderHeaders | undefined): Record<string, string> | undefined {\n\tif (!headers) return undefined;\n\tconst result: Record<string, string> = {};\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value !== null) result[key] = value;\n\t}\n\treturn Object.keys(result).length > 0 ? result : undefined;\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repairs malformed JSON string literals by:
|
|
3
|
+
* - escaping raw control characters inside strings
|
|
4
|
+
* - doubling backslashes before invalid escape characters
|
|
5
|
+
*/
|
|
6
|
+
export declare function repairJson(json: string): string;
|
|
7
|
+
export declare function parseJsonWithRepair<T>(json: string): T;
|
|
8
|
+
/**
|
|
9
|
+
* Attempts to parse potentially incomplete JSON during streaming.
|
|
10
|
+
* Always returns a valid object, even if the JSON is incomplete.
|
|
11
|
+
*
|
|
12
|
+
* @param partialJson The partial JSON string from streaming
|
|
13
|
+
* @returns Parsed object or empty object if parsing fails
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseStreamingJson<T = Record<string, unknown>>(partialJson: string | undefined): T;
|
|
16
|
+
//# sourceMappingURL=json-parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-parse.d.ts","sourceRoot":"","sources":["../../src/utils/json-parse.ts"],"names":[],"mappings":"AA0BA;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmD/C;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAUtD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,CAAC,CAoBlG","sourcesContent":["import { parse as partialParse } from \"partial-json\";\n\nconst VALID_JSON_ESCAPES = new Set(['\"', \"\\\\\", \"/\", \"b\", \"f\", \"n\", \"r\", \"t\", \"u\"]);\n\nfunction isControlCharacter(char: string): boolean {\n\tconst codePoint = char.codePointAt(0);\n\treturn codePoint !== undefined && codePoint >= 0x00 && codePoint <= 0x1f;\n}\n\nfunction escapeControlCharacter(char: string): string {\n\tswitch (char) {\n\t\tcase \"\\b\":\n\t\t\treturn \"\\\\b\";\n\t\tcase \"\\f\":\n\t\t\treturn \"\\\\f\";\n\t\tcase \"\\n\":\n\t\t\treturn \"\\\\n\";\n\t\tcase \"\\r\":\n\t\t\treturn \"\\\\r\";\n\t\tcase \"\\t\":\n\t\t\treturn \"\\\\t\";\n\t\tdefault:\n\t\t\treturn `\\\\u${char.codePointAt(0)?.toString(16).padStart(4, \"0\") ?? \"0000\"}`;\n\t}\n}\n\n/**\n * Repairs malformed JSON string literals by:\n * - escaping raw control characters inside strings\n * - doubling backslashes before invalid escape characters\n */\nexport function repairJson(json: string): string {\n\tlet repaired = \"\";\n\tlet inString = false;\n\n\tfor (let index = 0; index < json.length; index++) {\n\t\tconst char = json[index];\n\n\t\tif (!inString) {\n\t\t\trepaired += char;\n\t\t\tif (char === '\"') {\n\t\t\t\tinString = true;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === '\"') {\n\t\t\trepaired += char;\n\t\t\tinString = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"\\\\\") {\n\t\t\tconst nextChar = json[index + 1];\n\t\t\tif (nextChar === undefined) {\n\t\t\t\trepaired += \"\\\\\\\\\";\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (nextChar === \"u\") {\n\t\t\t\tconst unicodeDigits = json.slice(index + 2, index + 6);\n\t\t\t\tif (/^[0-9a-fA-F]{4}$/.test(unicodeDigits)) {\n\t\t\t\t\trepaired += `\\\\u${unicodeDigits}`;\n\t\t\t\t\tindex += 5;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (VALID_JSON_ESCAPES.has(nextChar)) {\n\t\t\t\trepaired += `\\\\${nextChar}`;\n\t\t\t\tindex += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\trepaired += \"\\\\\\\\\";\n\t\t\tcontinue;\n\t\t}\n\n\t\trepaired += isControlCharacter(char) ? escapeControlCharacter(char) : char;\n\t}\n\n\treturn repaired;\n}\n\nexport function parseJsonWithRepair<T>(json: string): T {\n\ttry {\n\t\treturn JSON.parse(json) as T;\n\t} catch (error) {\n\t\tconst repairedJson = repairJson(json);\n\t\tif (repairedJson !== json) {\n\t\t\treturn JSON.parse(repairedJson) as T;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * Attempts to parse potentially incomplete JSON during streaming.\n * Always returns a valid object, even if the JSON is incomplete.\n *\n * @param partialJson The partial JSON string from streaming\n * @returns Parsed object or empty object if parsing fails\n */\nexport function parseStreamingJson<T = Record<string, unknown>>(partialJson: string | undefined): T {\n\tif (!partialJson || partialJson.trim() === \"\") {\n\t\treturn {} as T;\n\t}\n\n\ttry {\n\t\treturn parseJsonWithRepair<T>(partialJson);\n\t} catch {\n\t\ttry {\n\t\t\tconst result = partialParse(partialJson);\n\t\t\treturn (result ?? {}) as T;\n\t\t} catch {\n\t\t\ttry {\n\t\t\t\tconst result = partialParse(repairJson(partialJson));\n\t\t\t\treturn (result ?? {}) as T;\n\t\t\t} catch {\n\t\t\t\treturn {} as T;\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|