@aryee337/aery-ai 0.1.148 → 0.2.10
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 +2914 -0
- package/README.md +614 -813
- package/dist/types/api-registry.d.ts +30 -0
- package/dist/types/auth-broker/client.d.ts +66 -0
- package/dist/types/auth-broker/index.d.ts +5 -0
- package/dist/types/auth-broker/refresher.d.ts +25 -0
- package/dist/types/auth-broker/remote-store.d.ts +96 -0
- package/dist/types/auth-broker/server.d.ts +32 -0
- package/dist/types/auth-broker/types.d.ts +105 -0
- package/dist/types/auth-broker/wire-schemas.d.ts +412 -0
- package/dist/types/auth-gateway/http.d.ts +39 -0
- package/dist/types/auth-gateway/index.d.ts +3 -0
- package/dist/types/auth-gateway/server.d.ts +36 -0
- package/dist/types/auth-gateway/types.d.ts +117 -0
- package/dist/types/auth-storage.d.ts +739 -0
- package/dist/types/index.d.ts +49 -0
- package/dist/types/model-cache.d.ts +17 -0
- package/dist/types/model-manager.d.ts +64 -0
- package/dist/types/model-thinking.d.ts +100 -0
- package/dist/types/models.d.ts +12 -0
- package/dist/types/provider-details.d.ts +24 -0
- package/dist/types/provider-models/bundled-references.d.ts +4 -0
- package/dist/types/provider-models/descriptors.d.ts +50 -0
- package/dist/types/provider-models/google.d.ts +24 -0
- package/dist/types/provider-models/index.d.ts +5 -0
- package/dist/types/provider-models/ollama.d.ts +7 -0
- package/dist/types/provider-models/openai-compat.d.ts +296 -0
- package/dist/types/provider-models/special.d.ts +16 -0
- package/dist/types/providers/aery-native-client.d.ts +13 -0
- package/dist/types/providers/aery-native-server.d.ts +68 -0
- package/dist/types/providers/amazon-bedrock.d.ts +38 -0
- package/dist/types/providers/anthropic-client.d.ts +99 -0
- package/dist/types/providers/anthropic-messages-server-schema.d.ts +465 -0
- package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
- package/dist/types/providers/anthropic-wire.d.ts +262 -0
- package/dist/types/providers/anthropic.d.ts +206 -0
- package/dist/types/providers/aws-credentials.d.ts +43 -0
- package/dist/types/providers/aws-eventstream.d.ts +38 -0
- package/dist/types/providers/aws-sigv4.d.ts +55 -0
- package/dist/types/providers/azure-openai-responses.d.ts +15 -0
- package/dist/types/providers/cursor/gen/agent_pb.d.ts +13022 -0
- package/dist/types/providers/cursor.d.ts +43 -0
- package/dist/types/providers/error-message.d.ts +27 -0
- package/dist/types/providers/github-copilot-headers.d.ts +40 -0
- package/dist/types/providers/gitlab-duo.d.ts +27 -0
- package/dist/types/providers/google-auth.d.ts +24 -0
- package/dist/types/providers/google-gemini-cli.d.ts +81 -0
- package/dist/types/providers/google-gemini-headers.d.ts +18 -0
- package/dist/types/providers/google-shared.d.ts +171 -0
- package/dist/types/providers/google-types.d.ts +138 -0
- package/dist/types/providers/google-vertex.d.ts +7 -0
- package/dist/types/providers/google.d.ts +4 -0
- package/dist/types/providers/grammar.d.ts +1 -0
- package/dist/types/providers/kimi.d.ts +27 -0
- package/dist/types/providers/mock.d.ts +173 -0
- package/dist/types/providers/ollama.d.ts +6 -0
- package/dist/types/providers/openai-anthropic-shim.d.ts +31 -0
- package/dist/types/providers/openai-chat-server-schema.d.ts +817 -0
- package/dist/types/providers/openai-chat-server.d.ts +16 -0
- package/dist/types/providers/openai-codex/constants.d.ts +26 -0
- package/dist/types/providers/openai-codex/request-transformer.d.ts +49 -0
- package/dist/types/providers/openai-codex/response-handler.d.ts +17 -0
- package/dist/types/providers/openai-codex-responses.d.ts +67 -0
- package/dist/types/providers/openai-completions-compat.d.ts +25 -0
- package/dist/types/providers/openai-completions.d.ts +54 -0
- package/dist/types/providers/openai-responses-server-schema.d.ts +392 -0
- package/dist/types/providers/openai-responses-server.d.ts +17 -0
- package/dist/types/providers/openai-responses-shared.d.ts +100 -0
- package/dist/types/providers/openai-responses.d.ts +66 -0
- package/dist/types/providers/register-builtins.d.ts +31 -0
- package/dist/types/providers/synthetic.d.ts +26 -0
- package/dist/{providers → types/providers}/transform-messages.d.ts +6 -2
- package/dist/types/providers/vision-guard.d.ts +8 -0
- package/dist/types/providers/xai-responses.d.ts +23 -0
- package/dist/types/rate-limit-utils.d.ts +19 -0
- package/dist/types/stream.d.ts +28 -0
- package/dist/types/types.d.ts +801 -0
- package/dist/types/usage/claude.d.ts +4 -0
- package/dist/types/usage/gemini.d.ts +2 -0
- package/dist/types/usage/github-copilot.d.ts +7 -0
- package/dist/types/usage/google-antigravity.d.ts +2 -0
- package/dist/types/usage/kimi.d.ts +2 -0
- package/dist/types/usage/minimax-code.d.ts +2 -0
- package/dist/types/usage/openai-codex.d.ts +3 -0
- package/dist/types/usage/shared.d.ts +1 -0
- package/dist/types/usage/zai.d.ts +2 -0
- package/dist/types/usage.d.ts +260 -0
- package/dist/types/utils/abort.d.ts +19 -0
- package/dist/types/utils/abortable-iterator.d.ts +4 -0
- package/dist/types/utils/anthropic-auth.d.ts +35 -0
- package/dist/types/utils/discovery/antigravity.d.ts +61 -0
- package/dist/types/utils/discovery/codex.d.ts +38 -0
- package/dist/types/utils/discovery/cursor.d.ts +23 -0
- package/dist/types/utils/discovery/gemini.d.ts +25 -0
- package/dist/types/utils/discovery/index.d.ts +4 -0
- package/dist/types/utils/discovery/openai-compatible.d.ts +72 -0
- package/dist/types/utils/event-stream.d.ts +28 -0
- package/dist/types/utils/fireworks-model-id.d.ts +10 -0
- package/dist/types/utils/foundry.d.ts +1 -0
- package/dist/types/utils/http-inspector.d.ts +31 -0
- package/dist/types/utils/idle-iterator.d.ts +78 -0
- package/dist/types/utils/json-parse.d.ts +37 -0
- package/dist/types/utils/oauth/__tests__/xai-oauth.test.d.ts +1 -0
- package/dist/types/utils/oauth/alibaba-coding-plan.d.ts +18 -0
- package/dist/types/utils/oauth/anthropic.d.ts +22 -0
- package/dist/types/utils/oauth/api-key-login.d.ts +35 -0
- package/dist/types/utils/oauth/api-key-validation.d.ts +27 -0
- package/dist/types/utils/oauth/callback-server.d.ts +57 -0
- package/dist/types/utils/oauth/cerebras.d.ts +1 -0
- package/dist/types/utils/oauth/cloudflare-ai-gateway.d.ts +18 -0
- package/dist/types/utils/oauth/cursor.d.ts +15 -0
- package/dist/types/utils/oauth/deepseek.d.ts +10 -0
- package/dist/types/utils/oauth/firepass.d.ts +1 -0
- package/dist/types/utils/oauth/fireworks.d.ts +1 -0
- package/dist/types/utils/oauth/github-copilot.d.ts +38 -0
- package/dist/types/utils/oauth/gitlab-duo.d.ts +3 -0
- package/dist/types/utils/oauth/google-antigravity.d.ts +11 -0
- package/dist/types/utils/oauth/google-gemini-cli.d.ts +10 -0
- package/dist/types/utils/oauth/google-oauth-shared.d.ts +28 -0
- package/dist/types/utils/oauth/huggingface.d.ts +19 -0
- package/dist/types/utils/oauth/index.d.ts +38 -0
- package/dist/types/utils/oauth/kagi.d.ts +17 -0
- package/dist/types/utils/oauth/kilo.d.ts +5 -0
- package/dist/types/utils/oauth/kimi.d.ts +21 -0
- package/dist/types/utils/oauth/litellm.d.ts +18 -0
- package/dist/types/utils/oauth/lm-studio.d.ts +17 -0
- package/dist/types/utils/oauth/minimax-code.d.ts +28 -0
- package/dist/types/utils/oauth/moonshot.d.ts +1 -0
- package/dist/types/utils/oauth/nanogpt.d.ts +1 -0
- package/dist/types/utils/oauth/nvidia.d.ts +18 -0
- package/dist/types/utils/oauth/ollama-cloud.d.ts +2 -0
- package/dist/types/utils/oauth/ollama.d.ts +18 -0
- package/dist/types/utils/oauth/openai-codex.d.ts +21 -0
- package/dist/types/utils/oauth/opencode.d.ts +18 -0
- package/dist/types/utils/oauth/openrouter.d.ts +1 -0
- package/dist/types/utils/oauth/parallel.d.ts +17 -0
- package/dist/types/utils/oauth/perplexity.d.ts +9 -0
- package/dist/{utils → types/utils}/oauth/pkce.d.ts +0 -5
- package/dist/types/utils/oauth/qianfan.d.ts +17 -0
- package/dist/types/utils/oauth/qwen-portal.d.ts +19 -0
- package/dist/types/utils/oauth/synthetic.d.ts +1 -0
- package/dist/types/utils/oauth/tavily.d.ts +17 -0
- package/dist/types/utils/oauth/together.d.ts +1 -0
- package/dist/types/utils/oauth/types.d.ts +44 -0
- package/dist/types/utils/oauth/venice.d.ts +18 -0
- package/dist/types/utils/oauth/vercel-ai-gateway.d.ts +18 -0
- package/dist/types/utils/oauth/vllm.d.ts +16 -0
- package/dist/types/utils/oauth/wafer.d.ts +2 -0
- package/dist/types/utils/oauth/xai-oauth.d.ts +60 -0
- package/dist/types/utils/oauth/xiaomi.d.ts +19 -0
- package/dist/types/utils/oauth/zai.d.ts +18 -0
- package/dist/types/utils/oauth/zenmux.d.ts +1 -0
- package/dist/types/utils/oauth/zhipu.d.ts +18 -0
- package/dist/{utils → types/utils}/overflow.d.ts +9 -11
- package/dist/types/utils/parse-bind.d.ts +23 -0
- package/dist/types/utils/provider-response.d.ts +3 -0
- package/dist/types/utils/request-debug.d.ts +29 -0
- package/dist/types/utils/retry-after.d.ts +3 -0
- package/dist/types/utils/retry.d.ts +26 -0
- package/dist/types/utils/schema/adapt.d.ts +24 -0
- package/dist/types/utils/schema/compatibility.d.ts +30 -0
- package/dist/types/utils/schema/dereference.d.ts +11 -0
- package/dist/types/utils/schema/draft.d.ts +10 -0
- package/dist/types/utils/schema/equality.d.ts +4 -0
- package/dist/types/utils/schema/fields.d.ts +49 -0
- package/dist/types/utils/schema/index.d.ts +13 -0
- package/dist/types/utils/schema/json-schema-validator.d.ts +12 -0
- package/dist/types/utils/schema/meta-validator.d.ts +2 -0
- package/dist/types/utils/schema/normalize.d.ts +93 -0
- package/dist/types/utils/schema/spill.d.ts +8 -0
- package/dist/types/utils/schema/stamps.d.ts +25 -0
- package/dist/types/utils/schema/types.d.ts +4 -0
- package/dist/types/utils/schema/wire.d.ts +53 -0
- package/dist/types/utils/schema/zod-decontaminate.d.ts +31 -0
- package/dist/types/utils/sdk-stream-timeout.d.ts +33 -0
- package/dist/types/utils/sse-debug.d.ts +10 -0
- package/dist/types/utils/stream-markup-healing.d.ts +80 -0
- package/dist/types/utils/tool-choice.d.ts +50 -0
- package/dist/types/utils/validation.d.ts +17 -0
- package/dist/types/utils.d.ts +28 -0
- package/package.json +139 -105
- package/src/api-registry.ts +96 -0
- package/src/auth-broker/client.ts +358 -0
- package/src/auth-broker/index.ts +5 -0
- package/src/auth-broker/refresher.ts +117 -0
- package/src/auth-broker/remote-store.ts +623 -0
- package/src/auth-broker/server.ts +644 -0
- package/src/auth-broker/types.ts +127 -0
- package/src/auth-broker/wire-schemas.ts +200 -0
- package/src/auth-gateway/http.ts +194 -0
- package/src/auth-gateway/index.ts +3 -0
- package/src/auth-gateway/server.ts +818 -0
- package/src/auth-gateway/types.ts +143 -0
- package/src/auth-storage.ts +4422 -0
- package/src/index.ts +54 -0
- package/src/model-cache.ts +129 -0
- package/src/model-manager.ts +469 -0
- package/src/model-thinking.ts +782 -0
- package/src/models.json +83530 -0
- package/src/models.json.d.ts +9 -0
- package/src/models.ts +56 -0
- package/src/prompts/turn-aborted-guidance.md +4 -0
- package/src/provider-details.ts +90 -0
- package/src/provider-models/bundled-references.ts +38 -0
- package/src/provider-models/descriptors.ts +355 -0
- package/src/provider-models/google.ts +88 -0
- package/src/provider-models/index.ts +5 -0
- package/src/provider-models/ollama.ts +153 -0
- package/src/provider-models/openai-compat.ts +2817 -0
- package/src/provider-models/special.ts +67 -0
- package/src/providers/aery-native-client.ts +228 -0
- package/src/providers/aery-native-server.ts +212 -0
- package/src/providers/amazon-bedrock.ts +873 -0
- package/src/providers/anthropic-client.ts +318 -0
- package/src/providers/anthropic-messages-server-schema.ts +243 -0
- package/src/providers/anthropic-messages-server.ts +683 -0
- package/src/providers/anthropic-wire.ts +268 -0
- package/src/providers/anthropic.ts +3094 -0
- package/src/providers/aws-credentials.ts +501 -0
- package/src/providers/aws-eventstream.ts +185 -0
- package/src/providers/aws-sigv4.ts +218 -0
- package/src/providers/azure-openai-responses.ts +361 -0
- package/src/providers/cursor/gen/agent_pb.ts +15274 -0
- package/src/providers/cursor/proto/agent.proto +3526 -0
- package/src/providers/cursor/proto/buf.gen.yaml +6 -0
- package/src/providers/cursor/proto/buf.yaml +17 -0
- package/src/providers/cursor.ts +2621 -0
- package/src/providers/error-message.ts +21 -0
- package/src/providers/github-copilot-headers.ts +140 -0
- package/src/providers/gitlab-duo.ts +372 -0
- package/src/providers/google-auth.ts +252 -0
- package/src/providers/google-gemini-cli.ts +809 -0
- package/src/providers/google-gemini-headers.ts +41 -0
- package/src/providers/google-shared.ts +917 -0
- package/src/providers/google-types.ts +167 -0
- package/src/providers/google-vertex.ts +91 -0
- package/src/providers/google.ts +41 -0
- package/src/providers/grammar.ts +70 -0
- package/src/providers/kimi.ts +52 -0
- package/src/providers/mock.ts +496 -0
- package/src/providers/ollama.ts +644 -0
- package/src/providers/openai-anthropic-shim.ts +138 -0
- package/src/providers/openai-chat-server-schema.ts +252 -0
- package/src/providers/openai-chat-server.ts +647 -0
- package/src/providers/openai-codex/constants.ts +43 -0
- package/src/providers/openai-codex/request-transformer.ts +161 -0
- package/src/providers/openai-codex/response-handler.ts +81 -0
- package/src/providers/openai-codex-responses.ts +3018 -0
- package/src/providers/openai-completions-compat.ts +300 -0
- package/src/providers/openai-completions.ts +1979 -0
- package/src/providers/openai-responses-server-schema.ts +290 -0
- package/src/providers/openai-responses-server.ts +1183 -0
- package/src/providers/openai-responses-shared.ts +873 -0
- package/src/providers/openai-responses.ts +679 -0
- package/src/providers/register-builtins.ts +436 -0
- package/src/providers/synthetic.ts +50 -0
- package/src/providers/transform-messages.ts +382 -0
- package/src/providers/vision-guard.ts +31 -0
- package/src/providers/xai-responses.ts +82 -0
- package/src/rate-limit-utils.ts +84 -0
- package/src/stream.ts +1065 -0
- package/src/types.ts +944 -0
- package/src/usage/claude.ts +482 -0
- package/src/usage/gemini.ts +250 -0
- package/src/usage/github-copilot.ts +421 -0
- package/src/usage/google-antigravity.ts +201 -0
- package/src/usage/kimi.ts +271 -0
- package/src/usage/minimax-code.ts +31 -0
- package/src/usage/openai-codex.ts +503 -0
- package/src/usage/shared.ts +10 -0
- package/src/usage/zai.ts +247 -0
- package/src/usage.ts +185 -0
- package/src/utils/abort.ts +51 -0
- package/src/utils/abortable-iterator.ts +69 -0
- package/src/utils/anthropic-auth.ts +93 -0
- package/src/utils/discovery/antigravity.ts +261 -0
- package/src/utils/discovery/codex.ts +371 -0
- package/src/utils/discovery/cursor.ts +306 -0
- package/src/utils/discovery/gemini.ts +248 -0
- package/src/utils/discovery/index.ts +4 -0
- package/src/utils/discovery/openai-compatible.ts +224 -0
- package/src/utils/event-stream.ts +142 -0
- package/src/utils/fireworks-model-id.ts +30 -0
- package/src/utils/foundry.ts +8 -0
- package/src/utils/http-inspector.ts +176 -0
- package/src/utils/idle-iterator.ts +267 -0
- package/src/utils/json-parse.ts +182 -0
- package/src/utils/oauth/__tests__/xai-oauth.test.ts +107 -0
- package/src/utils/oauth/alibaba-coding-plan.ts +59 -0
- package/src/utils/oauth/anthropic.ts +273 -0
- package/src/utils/oauth/api-key-login.ts +87 -0
- package/src/utils/oauth/api-key-validation.ts +92 -0
- package/src/utils/oauth/callback-server.ts +276 -0
- package/src/utils/oauth/cerebras.ts +16 -0
- package/src/utils/oauth/cloudflare-ai-gateway.ts +48 -0
- package/src/utils/oauth/cursor.ts +157 -0
- package/src/utils/oauth/deepseek.ts +53 -0
- package/src/utils/oauth/firepass.ts +24 -0
- package/src/utils/oauth/fireworks.ts +15 -0
- package/src/utils/oauth/github-copilot.ts +362 -0
- package/src/utils/oauth/gitlab-duo.ts +123 -0
- package/src/utils/oauth/google-antigravity.ts +200 -0
- package/src/utils/oauth/google-gemini-cli.ts +256 -0
- package/src/utils/oauth/google-oauth-shared.ts +110 -0
- package/src/utils/oauth/huggingface.ts +62 -0
- package/src/utils/oauth/index.ts +484 -0
- package/src/utils/oauth/kagi.ts +47 -0
- package/src/utils/oauth/kilo.ts +87 -0
- package/src/utils/oauth/kimi.ts +254 -0
- package/src/utils/oauth/litellm.ts +47 -0
- package/src/utils/oauth/lm-studio.ts +38 -0
- package/src/utils/oauth/minimax-code.ts +78 -0
- package/src/utils/oauth/moonshot.ts +23 -0
- package/src/utils/oauth/nanogpt.ts +15 -0
- package/src/utils/oauth/nvidia.ts +70 -0
- package/src/utils/oauth/oauth.html +203 -0
- package/src/utils/oauth/ollama-cloud.ts +28 -0
- package/src/utils/oauth/ollama.ts +47 -0
- package/src/utils/oauth/openai-codex.ts +299 -0
- package/src/utils/oauth/opencode.ts +49 -0
- package/src/utils/oauth/openrouter.ts +20 -0
- package/src/utils/oauth/parallel.ts +46 -0
- package/src/utils/oauth/perplexity.ts +206 -0
- package/src/utils/oauth/pkce.ts +18 -0
- package/src/utils/oauth/qianfan.ts +58 -0
- package/src/utils/oauth/qwen-portal.ts +60 -0
- package/src/utils/oauth/synthetic.ts +15 -0
- package/src/utils/oauth/tavily.ts +46 -0
- package/src/utils/oauth/together.ts +16 -0
- package/src/utils/oauth/types.ts +99 -0
- package/src/utils/oauth/venice.ts +59 -0
- package/src/utils/oauth/vercel-ai-gateway.ts +47 -0
- package/src/utils/oauth/vllm.ts +40 -0
- package/src/utils/oauth/wafer.ts +50 -0
- package/src/utils/oauth/xai-oauth.ts +342 -0
- package/src/utils/oauth/xiaomi.ts +139 -0
- package/src/utils/oauth/zai.ts +60 -0
- package/src/utils/oauth/zenmux.ts +15 -0
- package/src/utils/oauth/zhipu.ts +60 -0
- package/src/utils/overflow.ts +137 -0
- package/src/utils/parse-bind.ts +54 -0
- package/src/utils/provider-response.ts +30 -0
- package/src/utils/request-debug.ts +336 -0
- package/src/utils/retry-after.ts +110 -0
- package/src/utils/retry.ts +54 -0
- package/src/utils/schema/CONSTRAINTS.md +164 -0
- package/src/utils/schema/adapt.ts +36 -0
- package/src/utils/schema/compatibility.ts +435 -0
- package/src/utils/schema/dereference.ts +98 -0
- package/src/utils/schema/draft.ts +341 -0
- package/src/utils/schema/equality.ts +97 -0
- package/src/utils/schema/fields.ts +191 -0
- package/src/utils/schema/index.ts +13 -0
- package/src/utils/schema/json-schema-validator.ts +577 -0
- package/src/utils/schema/meta-validator.ts +167 -0
- package/src/utils/schema/normalize.ts +1588 -0
- package/src/utils/schema/spill.ts +43 -0
- package/src/utils/schema/stamps.ts +97 -0
- package/src/utils/schema/types.ts +10 -0
- package/src/utils/schema/wire.ts +293 -0
- package/src/utils/schema/zod-decontaminate.ts +331 -0
- package/src/utils/sdk-stream-timeout.ts +43 -0
- package/src/utils/sse-debug.ts +289 -0
- package/src/utils/stream-markup-healing.ts +612 -0
- package/src/utils/tool-choice.ts +99 -0
- package/src/utils/validation.ts +1024 -0
- package/src/utils.ts +166 -0
- package/dist/api-registry.d.ts +0 -20
- package/dist/api-registry.d.ts.map +0 -1
- package/dist/api-registry.js +0 -44
- package/dist/api-registry.js.map +0 -1
- package/dist/bedrock-provider.d.ts +0 -5
- package/dist/bedrock-provider.d.ts.map +0 -1
- package/dist/bedrock-provider.js +0 -6
- package/dist/bedrock-provider.js.map +0 -1
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -130
- package/dist/cli.js.map +0 -1
- package/dist/env-api-keys.d.ts +0 -18
- package/dist/env-api-keys.d.ts.map +0 -1
- package/dist/env-api-keys.js +0 -178
- package/dist/env-api-keys.js.map +0 -1
- package/dist/image-models.d.ts +0 -10
- package/dist/image-models.d.ts.map +0 -1
- package/dist/image-models.generated.d.ts +0 -440
- package/dist/image-models.generated.d.ts.map +0 -1
- package/dist/image-models.generated.js +0 -442
- package/dist/image-models.generated.js.map +0 -1
- package/dist/image-models.js +0 -23
- package/dist/image-models.js.map +0 -1
- package/dist/images-api-registry.d.ts +0 -14
- package/dist/images-api-registry.d.ts.map +0 -1
- package/dist/images-api-registry.js +0 -22
- package/dist/images-api-registry.js.map +0 -1
- package/dist/images.d.ts +0 -4
- package/dist/images.d.ts.map +0 -1
- package/dist/images.js +0 -14
- package/dist/images.js.map +0 -1
- package/dist/index.d.ts +0 -32
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -20
- package/dist/index.js.map +0 -1
- package/dist/models.d.ts +0 -18
- package/dist/models.d.ts.map +0 -1
- package/dist/models.generated.d.ts +0 -17480
- package/dist/models.generated.d.ts.map +0 -1
- package/dist/models.generated.js +0 -16339
- package/dist/models.generated.js.map +0 -1
- package/dist/models.js +0 -71
- package/dist/models.js.map +0 -1
- package/dist/oauth.d.ts +0 -2
- package/dist/oauth.d.ts.map +0 -1
- package/dist/oauth.js +0 -2
- package/dist/oauth.js.map +0 -1
- package/dist/providers/aery-error-formatting.d.ts +0 -13
- package/dist/providers/aery-error-formatting.d.ts.map +0 -1
- package/dist/providers/aery-error-formatting.js +0 -112
- package/dist/providers/aery-error-formatting.js.map +0 -1
- package/dist/providers/amazon-bedrock.d.ts +0 -38
- package/dist/providers/amazon-bedrock.d.ts.map +0 -1
- package/dist/providers/amazon-bedrock.js +0 -763
- package/dist/providers/amazon-bedrock.js.map +0 -1
- package/dist/providers/anthropic.d.ts +0 -71
- package/dist/providers/anthropic.d.ts.map +0 -1
- package/dist/providers/anthropic.js +0 -949
- package/dist/providers/anthropic.js.map +0 -1
- package/dist/providers/azure-openai-responses.d.ts +0 -15
- package/dist/providers/azure-openai-responses.d.ts.map +0 -1
- package/dist/providers/azure-openai-responses.js +0 -225
- package/dist/providers/azure-openai-responses.js.map +0 -1
- package/dist/providers/cloudflare.d.ts +0 -13
- package/dist/providers/cloudflare.d.ts.map +0 -1
- package/dist/providers/cloudflare.js +0 -26
- package/dist/providers/cloudflare.js.map +0 -1
- package/dist/providers/faux.d.ts +0 -56
- package/dist/providers/faux.d.ts.map +0 -1
- package/dist/providers/faux.js +0 -368
- package/dist/providers/faux.js.map +0 -1
- package/dist/providers/github-copilot-headers.d.ts +0 -8
- package/dist/providers/github-copilot-headers.d.ts.map +0 -1
- package/dist/providers/github-copilot-headers.js +0 -29
- package/dist/providers/github-copilot-headers.js.map +0 -1
- package/dist/providers/google-gemini-cli.d.ts +0 -74
- package/dist/providers/google-gemini-cli.d.ts.map +0 -1
- package/dist/providers/google-gemini-cli.js +0 -779
- package/dist/providers/google-gemini-cli.js.map +0 -1
- package/dist/providers/google-shared.d.ts +0 -70
- package/dist/providers/google-shared.d.ts.map +0 -1
- package/dist/providers/google-shared.js +0 -329
- package/dist/providers/google-shared.js.map +0 -1
- package/dist/providers/google-vertex.d.ts +0 -15
- package/dist/providers/google-vertex.d.ts.map +0 -1
- package/dist/providers/google-vertex.js +0 -442
- package/dist/providers/google-vertex.js.map +0 -1
- package/dist/providers/google.d.ts +0 -13
- package/dist/providers/google.d.ts.map +0 -1
- package/dist/providers/google.js +0 -400
- package/dist/providers/google.js.map +0 -1
- package/dist/providers/images/openrouter.d.ts +0 -3
- package/dist/providers/images/openrouter.d.ts.map +0 -1
- package/dist/providers/images/openrouter.js +0 -129
- package/dist/providers/images/openrouter.js.map +0 -1
- package/dist/providers/images/register-builtins.d.ts +0 -4
- package/dist/providers/images/register-builtins.d.ts.map +0 -1
- package/dist/providers/images/register-builtins.js +0 -34
- package/dist/providers/images/register-builtins.js.map +0 -1
- package/dist/providers/mistral.d.ts +0 -25
- package/dist/providers/mistral.d.ts.map +0 -1
- package/dist/providers/mistral.js +0 -535
- package/dist/providers/mistral.js.map +0 -1
- package/dist/providers/openai-codex-responses.d.ts +0 -30
- package/dist/providers/openai-codex-responses.d.ts.map +0 -1
- package/dist/providers/openai-codex-responses.js +0 -1090
- package/dist/providers/openai-codex-responses.js.map +0 -1
- package/dist/providers/openai-completions.d.ts +0 -19
- package/dist/providers/openai-completions.d.ts.map +0 -1
- package/dist/providers/openai-completions.js +0 -950
- package/dist/providers/openai-completions.js.map +0 -1
- package/dist/providers/openai-prompt-cache.d.ts +0 -3
- package/dist/providers/openai-prompt-cache.d.ts.map +0 -1
- package/dist/providers/openai-prompt-cache.js +0 -10
- package/dist/providers/openai-prompt-cache.js.map +0 -1
- package/dist/providers/openai-responses-shared.d.ts +0 -18
- package/dist/providers/openai-responses-shared.d.ts.map +0 -1
- package/dist/providers/openai-responses-shared.js +0 -492
- package/dist/providers/openai-responses-shared.js.map +0 -1
- package/dist/providers/openai-responses.d.ts +0 -13
- package/dist/providers/openai-responses.d.ts.map +0 -1
- package/dist/providers/openai-responses.js +0 -237
- package/dist/providers/openai-responses.js.map +0 -1
- package/dist/providers/register-builtins.d.ts +0 -38
- package/dist/providers/register-builtins.d.ts.map +0 -1
- package/dist/providers/register-builtins.js +0 -278
- package/dist/providers/register-builtins.js.map +0 -1
- package/dist/providers/simple-options.d.ts +0 -8
- package/dist/providers/simple-options.d.ts.map +0 -1
- package/dist/providers/simple-options.js +0 -41
- package/dist/providers/simple-options.js.map +0 -1
- package/dist/providers/transform-messages.d.ts.map +0 -1
- package/dist/providers/transform-messages.js +0 -184
- package/dist/providers/transform-messages.js.map +0 -1
- package/dist/session-resources.d.ts +0 -4
- package/dist/session-resources.d.ts.map +0 -1
- package/dist/session-resources.js +0 -22
- package/dist/session-resources.js.map +0 -1
- package/dist/stream.d.ts +0 -8
- package/dist/stream.d.ts.map +0 -1
- package/dist/stream.js +0 -27
- package/dist/stream.js.map +0 -1
- package/dist/types.d.ts +0 -498
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/utils/diagnostics.d.ts +0 -19
- package/dist/utils/diagnostics.d.ts.map +0 -1
- package/dist/utils/diagnostics.js +0 -25
- package/dist/utils/diagnostics.js.map +0 -1
- package/dist/utils/event-stream.d.ts +0 -21
- package/dist/utils/event-stream.d.ts.map +0 -1
- package/dist/utils/event-stream.js +0 -81
- package/dist/utils/event-stream.js.map +0 -1
- package/dist/utils/hash.d.ts +0 -3
- package/dist/utils/hash.d.ts.map +0 -1
- package/dist/utils/hash.js +0 -14
- package/dist/utils/hash.js.map +0 -1
- package/dist/utils/headers.d.ts +0 -2
- package/dist/utils/headers.d.ts.map +0 -1
- package/dist/utils/headers.js +0 -8
- package/dist/utils/headers.js.map +0 -1
- package/dist/utils/json-parse.d.ts +0 -16
- package/dist/utils/json-parse.d.ts.map +0 -1
- package/dist/utils/json-parse.js +0 -113
- package/dist/utils/json-parse.js.map +0 -1
- package/dist/utils/node-http-proxy.d.ts +0 -10
- package/dist/utils/node-http-proxy.d.ts.map +0 -1
- package/dist/utils/node-http-proxy.js +0 -97
- package/dist/utils/node-http-proxy.js.map +0 -1
- package/dist/utils/oauth/anthropic.d.ts +0 -25
- package/dist/utils/oauth/anthropic.d.ts.map +0 -1
- package/dist/utils/oauth/anthropic.js +0 -335
- package/dist/utils/oauth/anthropic.js.map +0 -1
- package/dist/utils/oauth/device-code.d.ts +0 -19
- package/dist/utils/oauth/device-code.d.ts.map +0 -1
- package/dist/utils/oauth/device-code.js +0 -55
- package/dist/utils/oauth/device-code.js.map +0 -1
- package/dist/utils/oauth/github-copilot.d.ts +0 -30
- package/dist/utils/oauth/github-copilot.d.ts.map +0 -1
- package/dist/utils/oauth/github-copilot.js +0 -268
- package/dist/utils/oauth/github-copilot.js.map +0 -1
- package/dist/utils/oauth/google-antigravity.d.ts +0 -26
- package/dist/utils/oauth/google-antigravity.d.ts.map +0 -1
- package/dist/utils/oauth/google-antigravity.js +0 -377
- package/dist/utils/oauth/google-antigravity.js.map +0 -1
- package/dist/utils/oauth/google-gemini-cli.d.ts +0 -26
- package/dist/utils/oauth/google-gemini-cli.d.ts.map +0 -1
- package/dist/utils/oauth/google-gemini-cli.js +0 -482
- package/dist/utils/oauth/google-gemini-cli.js.map +0 -1
- package/dist/utils/oauth/index.d.ts +0 -63
- package/dist/utils/oauth/index.d.ts.map +0 -1
- package/dist/utils/oauth/index.js +0 -131
- package/dist/utils/oauth/index.js.map +0 -1
- package/dist/utils/oauth/oauth-page.d.ts +0 -3
- package/dist/utils/oauth/oauth-page.d.ts.map +0 -1
- package/dist/utils/oauth/oauth-page.js +0 -105
- package/dist/utils/oauth/oauth-page.js.map +0 -1
- package/dist/utils/oauth/openai-codex.d.ts +0 -34
- package/dist/utils/oauth/openai-codex.d.ts.map +0 -1
- package/dist/utils/oauth/openai-codex.js +0 -385
- package/dist/utils/oauth/openai-codex.js.map +0 -1
- package/dist/utils/oauth/pkce.d.ts.map +0 -1
- package/dist/utils/oauth/pkce.js +0 -31
- package/dist/utils/oauth/pkce.js.map +0 -1
- package/dist/utils/oauth/types.d.ts +0 -64
- package/dist/utils/oauth/types.d.ts.map +0 -1
- package/dist/utils/oauth/types.js +0 -2
- package/dist/utils/oauth/types.js.map +0 -1
- package/dist/utils/overflow.d.ts.map +0 -1
- package/dist/utils/overflow.js +0 -151
- package/dist/utils/overflow.js.map +0 -1
- package/dist/utils/sanitize-unicode.d.ts +0 -22
- package/dist/utils/sanitize-unicode.d.ts.map +0 -1
- package/dist/utils/sanitize-unicode.js +0 -26
- package/dist/utils/sanitize-unicode.js.map +0 -1
- package/dist/utils/typebox-helpers.d.ts +0 -17
- package/dist/utils/typebox-helpers.d.ts.map +0 -1
- package/dist/utils/typebox-helpers.js +0 -21
- package/dist/utils/typebox-helpers.js.map +0 -1
- package/dist/utils/validation.d.ts +0 -18
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/validation.js +0 -281
- package/dist/utils/validation.js.map +0 -1
|
@@ -0,0 +1,612 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streaming-safe filters for leaked chat-template tool-call and thinking markup.
|
|
3
|
+
*
|
|
4
|
+
* Hosted models sometimes leak raw template markup into visible `content` instead
|
|
5
|
+
* of returning structured events. One `StreamMarkupHealing` instance owns one stream
|
|
6
|
+
* and one grammar selected by options:
|
|
7
|
+
*
|
|
8
|
+
* - `kimi`: Kimi K2 `<|tool_calls_section_begin|>` sections.
|
|
9
|
+
* - `dsml`: DeepSeek `<|DSML|tool_calls>` envelopes.
|
|
10
|
+
* - `thinking`: plain `<think>` / `<thinking>` blocks used by MiniMax-style streams.
|
|
11
|
+
*
|
|
12
|
+
* The parser strips marker bytes, reconstructs embedded calls, emits thinking
|
|
13
|
+
* deltas for thinking blocks, and holds partial tags across chunk boundaries.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { parseJsonWithRepair } from "./json-parse";
|
|
17
|
+
|
|
18
|
+
const KIMI_SECTION_BEGIN = "<|tool_calls_section_begin|>";
|
|
19
|
+
const KIMI_SECTION_END = "<|tool_calls_section_end|>";
|
|
20
|
+
const KIMI_CALL_BEGIN = "<|tool_call_begin|>";
|
|
21
|
+
const KIMI_CALL_END = "<|tool_call_end|>";
|
|
22
|
+
const KIMI_ARG_BEGIN = "<|tool_call_argument_begin|>";
|
|
23
|
+
const KIMI_TOKENS = [KIMI_SECTION_BEGIN, KIMI_SECTION_END, KIMI_CALL_BEGIN, KIMI_CALL_END, KIMI_ARG_BEGIN] as const;
|
|
24
|
+
|
|
25
|
+
/** Maximum buffered Kimi partial-token length before giving up holdback. */
|
|
26
|
+
const MAX_KIMI_PARTIAL_HOLD = 64;
|
|
27
|
+
|
|
28
|
+
/** Both fullwidth (U+FF5C) and ASCII pipes are observed in DeepSeek DSML leaks. */
|
|
29
|
+
const DSML_PIPE = "[||]";
|
|
30
|
+
const DSML_TOOL_CALLS_OPEN_RE = new RegExp(`<${DSML_PIPE}DSML${DSML_PIPE}tool_calls>`, "y");
|
|
31
|
+
const DSML_TOOL_CALLS_CLOSE_RE = new RegExp(`</${DSML_PIPE}DSML${DSML_PIPE}tool_calls>`, "y");
|
|
32
|
+
const DSML_INVOKE_OPEN_RE = new RegExp(`<${DSML_PIPE}DSML${DSML_PIPE}invoke\\s+name="([^"]*)"\\s*>`, "y");
|
|
33
|
+
const DSML_INVOKE_CLOSE_RE = new RegExp(`</${DSML_PIPE}DSML${DSML_PIPE}invoke>`, "y");
|
|
34
|
+
const DSML_PARAMETER_OPEN_RE = new RegExp(
|
|
35
|
+
`<${DSML_PIPE}DSML${DSML_PIPE}parameter\\s+name="([^"]*)"(?:\\s+string="(true|false)")?\\s*>`,
|
|
36
|
+
"y",
|
|
37
|
+
);
|
|
38
|
+
const DSML_PARAMETER_CLOSE_RE = new RegExp(`</${DSML_PIPE}DSML${DSML_PIPE}parameter>`, "y");
|
|
39
|
+
|
|
40
|
+
const THINK_OPEN = "<think>";
|
|
41
|
+
const THINK_CLOSE = "</think>";
|
|
42
|
+
const THINKING_OPEN = "<thinking>";
|
|
43
|
+
const THINKING_CLOSE = "</thinking>";
|
|
44
|
+
|
|
45
|
+
const PLAIN_THINKING_TAGS = [
|
|
46
|
+
{ open: THINK_OPEN, close: THINK_CLOSE },
|
|
47
|
+
{ open: THINKING_OPEN, close: THINKING_CLOSE },
|
|
48
|
+
] as const;
|
|
49
|
+
|
|
50
|
+
/** Cap held-back XML tag bytes so a stray `<` in prose cannot grow unboundedly. */
|
|
51
|
+
const MAX_XML_PARTIAL_HOLD = 256;
|
|
52
|
+
|
|
53
|
+
/** Maximum parameter bytes to accumulate before abandoning a pathological XML call. */
|
|
54
|
+
const MAX_XML_PARAM_VALUE_LENGTH = 1_000_000;
|
|
55
|
+
|
|
56
|
+
export interface HealedToolCall {
|
|
57
|
+
readonly id: string;
|
|
58
|
+
readonly name: string;
|
|
59
|
+
readonly arguments: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type StreamMarkupHealingPattern = "kimi" | "dsml" | "thinking";
|
|
63
|
+
|
|
64
|
+
export interface StreamMarkupHealingOptions {
|
|
65
|
+
readonly pattern: StreamMarkupHealingPattern;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type StreamMarkupHealingEvent =
|
|
69
|
+
| { readonly type: "text"; readonly text: string }
|
|
70
|
+
| { readonly type: "thinking"; readonly thinking: string }
|
|
71
|
+
| { readonly type: "toolCall"; readonly call: HealedToolCall };
|
|
72
|
+
|
|
73
|
+
type XmlToolState =
|
|
74
|
+
| { readonly kind: "idle" }
|
|
75
|
+
| { readonly kind: "section" }
|
|
76
|
+
| { readonly kind: "invoke"; readonly name: string; readonly args: Record<string, unknown> }
|
|
77
|
+
| {
|
|
78
|
+
readonly kind: "parameter";
|
|
79
|
+
readonly invokeName: string;
|
|
80
|
+
readonly args: Record<string, unknown>;
|
|
81
|
+
readonly paramName: string;
|
|
82
|
+
readonly isString: boolean;
|
|
83
|
+
value: string;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
type ThinkingTag = { readonly open: string; readonly close: string };
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* State machine that consumes streamed visible text and emits cleaned text,
|
|
90
|
+
* thinking deltas, and reconstructed tool calls.
|
|
91
|
+
*
|
|
92
|
+
* Feed only one stream channel (usually `delta.content` / `message.content`).
|
|
93
|
+
* Mixing reasoning and visible text into the same instance can corrupt the
|
|
94
|
+
* held-back partial tag buffer.
|
|
95
|
+
*/
|
|
96
|
+
export class StreamMarkupHealing {
|
|
97
|
+
readonly #pattern: StreamMarkupHealingPattern;
|
|
98
|
+
#buffer = "";
|
|
99
|
+
#offset = 0;
|
|
100
|
+
|
|
101
|
+
#kimiInSection = false;
|
|
102
|
+
#kimiInCall = false;
|
|
103
|
+
#kimiInArgs = false;
|
|
104
|
+
#kimiPendingId = "";
|
|
105
|
+
#kimiPendingArgs = "";
|
|
106
|
+
|
|
107
|
+
#xmlState: XmlToolState = { kind: "idle" };
|
|
108
|
+
#thinkingCloseTag = "";
|
|
109
|
+
#sectionTerminated = false;
|
|
110
|
+
readonly #completed: HealedToolCall[] = [];
|
|
111
|
+
|
|
112
|
+
constructor(options: StreamMarkupHealingOptions) {
|
|
113
|
+
this.#pattern = options.pattern;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
get pattern(): StreamMarkupHealingPattern {
|
|
117
|
+
return this.#pattern;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Feed a chunk and return visible text only. Reconstructed tool calls are
|
|
122
|
+
* stored for {@link drainCompleted}; thinking blocks are intentionally not
|
|
123
|
+
* returned by this compatibility helper. Use {@link feedEvents} when the
|
|
124
|
+
* caller needs ordered text/thinking/tool-call events.
|
|
125
|
+
*/
|
|
126
|
+
feed(text: string): string {
|
|
127
|
+
let clean = "";
|
|
128
|
+
for (const event of this.feedEvents(text)) {
|
|
129
|
+
if (event.type === "text") {
|
|
130
|
+
clean += event.text;
|
|
131
|
+
} else if (event.type === "toolCall") {
|
|
132
|
+
this.#completed.push(event.call);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return clean;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Feed a chunk and return cleaned text/thinking/tool-call events in stream order. */
|
|
139
|
+
feedEvents(text: string): StreamMarkupHealingEvent[] {
|
|
140
|
+
if (text.length === 0) return [];
|
|
141
|
+
this.#compact();
|
|
142
|
+
this.#buffer += text;
|
|
143
|
+
switch (this.#pattern) {
|
|
144
|
+
case "kimi":
|
|
145
|
+
return this.#consumeKimiEvents();
|
|
146
|
+
case "dsml":
|
|
147
|
+
return this.#consumeDsmlEvents();
|
|
148
|
+
case "thinking":
|
|
149
|
+
return this.#consumePlainThinkingEvents();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Like {@link feed}, but discards completed calls. Used when the upstream
|
|
155
|
+
* chunk also carries structured `tool_calls`, keeping that structured payload
|
|
156
|
+
* as the single source of truth.
|
|
157
|
+
*/
|
|
158
|
+
consumeWithoutCalls(text: string): string {
|
|
159
|
+
let clean = "";
|
|
160
|
+
for (const event of this.feedEvents(text)) {
|
|
161
|
+
if (event.type === "text") clean += event.text;
|
|
162
|
+
}
|
|
163
|
+
return clean;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Drain accumulated tool calls from calls to {@link feed}. */
|
|
167
|
+
drainCompleted(): HealedToolCall[] {
|
|
168
|
+
if (this.#completed.length === 0) return [];
|
|
169
|
+
return this.#completed.splice(0, this.#completed.length);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Flush held-back stream-end fragments as ordered events. Partial tool-call
|
|
174
|
+
* sections/envelopes are dropped; unterminated thinking blocks are emitted as
|
|
175
|
+
* thinking, matching the previous MiniMax parser behavior.
|
|
176
|
+
*/
|
|
177
|
+
flushEvents(): StreamMarkupHealingEvent[] {
|
|
178
|
+
const tail = this.#remaining();
|
|
179
|
+
this.#buffer = "";
|
|
180
|
+
this.#offset = 0;
|
|
181
|
+
|
|
182
|
+
switch (this.#pattern) {
|
|
183
|
+
case "kimi": {
|
|
184
|
+
const inTemplate = this.#kimiInCall || this.#kimiInSection;
|
|
185
|
+
this.#resetKimi();
|
|
186
|
+
return inTemplate || tail.length === 0 ? [] : [{ type: "text", text: tail }];
|
|
187
|
+
}
|
|
188
|
+
case "dsml": {
|
|
189
|
+
const state = this.#xmlState;
|
|
190
|
+
this.#xmlState = { kind: "idle" };
|
|
191
|
+
return state.kind !== "idle" || tail.length === 0 ? [] : [{ type: "text", text: tail }];
|
|
192
|
+
}
|
|
193
|
+
case "thinking": {
|
|
194
|
+
const closeTag = this.#thinkingCloseTag;
|
|
195
|
+
this.#thinkingCloseTag = "";
|
|
196
|
+
if (tail.length === 0) return [];
|
|
197
|
+
return closeTag ? [{ type: "thinking", thinking: tail }] : [{ type: "text", text: tail }];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Flush held-back text only. Reconstructed calls are retained for {@link drainCompleted}. */
|
|
203
|
+
flushPending(): string {
|
|
204
|
+
let clean = "";
|
|
205
|
+
for (const event of this.flushEvents()) {
|
|
206
|
+
if (event.type === "text") {
|
|
207
|
+
clean += event.text;
|
|
208
|
+
} else if (event.type === "toolCall") {
|
|
209
|
+
this.#completed.push(event.call);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return clean;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** True once any configured tool-call section/envelope has fully closed. */
|
|
216
|
+
get sectionClosed(): boolean {
|
|
217
|
+
return this.#sectionTerminated;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
#remaining(): string {
|
|
221
|
+
return this.#offset === 0 ? this.#buffer : this.#buffer.slice(this.#offset);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
#compact(): void {
|
|
225
|
+
if (this.#offset === 0) return;
|
|
226
|
+
this.#buffer = this.#buffer.slice(this.#offset);
|
|
227
|
+
this.#offset = 0;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
#consumeKimiEvents(): StreamMarkupHealingEvent[] {
|
|
231
|
+
const events: StreamMarkupHealingEvent[] = [];
|
|
232
|
+
let clean = "";
|
|
233
|
+
const flushClean = (): void => {
|
|
234
|
+
if (clean.length === 0) return;
|
|
235
|
+
events.push({ type: "text", text: clean });
|
|
236
|
+
clean = "";
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
while (this.#offset < this.#buffer.length) {
|
|
240
|
+
if (this.#startsWithPartialToken(KIMI_TOKENS, MAX_KIMI_PARTIAL_HOLD)) break;
|
|
241
|
+
|
|
242
|
+
if (this.#matchesToken(KIMI_SECTION_BEGIN)) {
|
|
243
|
+
this.#kimiInSection = true;
|
|
244
|
+
this.#offset += KIMI_SECTION_BEGIN.length;
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (this.#matchesToken(KIMI_SECTION_END)) {
|
|
248
|
+
this.#kimiInSection = false;
|
|
249
|
+
this.#sectionTerminated = true;
|
|
250
|
+
this.#offset += KIMI_SECTION_END.length;
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (this.#matchesToken(KIMI_CALL_BEGIN)) {
|
|
254
|
+
if (!this.#kimiInSection) {
|
|
255
|
+
clean += KIMI_CALL_BEGIN;
|
|
256
|
+
this.#offset += KIMI_CALL_BEGIN.length;
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
this.#kimiInCall = true;
|
|
260
|
+
this.#kimiInArgs = false;
|
|
261
|
+
this.#kimiPendingId = "";
|
|
262
|
+
this.#kimiPendingArgs = "";
|
|
263
|
+
this.#offset += KIMI_CALL_BEGIN.length;
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
if (this.#matchesToken(KIMI_ARG_BEGIN)) {
|
|
267
|
+
if (!this.#kimiInSection) {
|
|
268
|
+
clean += KIMI_ARG_BEGIN;
|
|
269
|
+
this.#offset += KIMI_ARG_BEGIN.length;
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
this.#kimiInArgs = true;
|
|
273
|
+
this.#offset += KIMI_ARG_BEGIN.length;
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
if (this.#matchesToken(KIMI_CALL_END)) {
|
|
277
|
+
if (!this.#kimiInSection || !this.#kimiInCall) {
|
|
278
|
+
clean += KIMI_CALL_END;
|
|
279
|
+
this.#offset += KIMI_CALL_END.length;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
const call = this.#finalizeKimiCall();
|
|
283
|
+
flushClean();
|
|
284
|
+
events.push({ type: "toolCall", call });
|
|
285
|
+
this.#offset += KIMI_CALL_END.length;
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const ch = this.#buffer[this.#offset]!;
|
|
290
|
+
this.#offset += 1;
|
|
291
|
+
|
|
292
|
+
if (this.#kimiInCall) {
|
|
293
|
+
if (this.#kimiInArgs) {
|
|
294
|
+
this.#kimiPendingArgs += ch;
|
|
295
|
+
} else {
|
|
296
|
+
this.#kimiPendingId += ch;
|
|
297
|
+
}
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (!this.#kimiInSection) clean += ch;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
flushClean();
|
|
305
|
+
return events;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
#consumeDsmlEvents(): StreamMarkupHealingEvent[] {
|
|
309
|
+
return this.#consumeXmlToolEvents({
|
|
310
|
+
getState: () => this.#xmlState,
|
|
311
|
+
setState: state => {
|
|
312
|
+
this.#xmlState = state;
|
|
313
|
+
},
|
|
314
|
+
sectionOpen: DSML_TOOL_CALLS_OPEN_RE,
|
|
315
|
+
sectionClose: DSML_TOOL_CALLS_CLOSE_RE,
|
|
316
|
+
invokeOpen: DSML_INVOKE_OPEN_RE,
|
|
317
|
+
invokeClose: DSML_INVOKE_CLOSE_RE,
|
|
318
|
+
parameterOpen: DSML_PARAMETER_OPEN_RE,
|
|
319
|
+
parameterClose: DSML_PARAMETER_CLOSE_RE,
|
|
320
|
+
coerceStringByDefault: true,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
#consumePlainThinkingEvents(): StreamMarkupHealingEvent[] {
|
|
325
|
+
const events: StreamMarkupHealingEvent[] = [];
|
|
326
|
+
let clean = "";
|
|
327
|
+
let thinking = "";
|
|
328
|
+
const flushClean = (): void => {
|
|
329
|
+
if (clean.length === 0) return;
|
|
330
|
+
events.push({ type: "text", text: clean });
|
|
331
|
+
clean = "";
|
|
332
|
+
};
|
|
333
|
+
const flushThinking = (): void => {
|
|
334
|
+
if (thinking.length === 0) return;
|
|
335
|
+
events.push({ type: "thinking", thinking });
|
|
336
|
+
thinking = "";
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
while (this.#offset < this.#buffer.length) {
|
|
340
|
+
if (this.#thinkingCloseTag) {
|
|
341
|
+
if (this.#matchesToken(this.#thinkingCloseTag)) {
|
|
342
|
+
flushThinking();
|
|
343
|
+
this.#offset += this.#thinkingCloseTag.length;
|
|
344
|
+
this.#thinkingCloseTag = "";
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
if (this.#startsWithPartialToken([this.#thinkingCloseTag], MAX_XML_PARTIAL_HOLD)) break;
|
|
348
|
+
const ch = this.#buffer[this.#offset]!;
|
|
349
|
+
this.#offset += 1;
|
|
350
|
+
thinking += ch;
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const thinkingTag = this.#tryMatchThinkingOpen(PLAIN_THINKING_TAGS);
|
|
355
|
+
if (thinkingTag) {
|
|
356
|
+
flushClean();
|
|
357
|
+
this.#thinkingCloseTag = thinkingTag.close;
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
if (this.#startsWithPartialThinkingOpen(PLAIN_THINKING_TAGS)) break;
|
|
361
|
+
|
|
362
|
+
const ch = this.#buffer[this.#offset]!;
|
|
363
|
+
this.#offset += 1;
|
|
364
|
+
clean += ch;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
flushClean();
|
|
368
|
+
flushThinking();
|
|
369
|
+
return events;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
#consumeXmlToolEvents(config: {
|
|
373
|
+
readonly getState: () => XmlToolState;
|
|
374
|
+
readonly setState: (state: XmlToolState) => void;
|
|
375
|
+
readonly sectionOpen: RegExp;
|
|
376
|
+
readonly sectionClose: RegExp;
|
|
377
|
+
readonly invokeOpen: RegExp;
|
|
378
|
+
readonly invokeClose: RegExp;
|
|
379
|
+
readonly parameterOpen: RegExp;
|
|
380
|
+
readonly parameterClose: RegExp;
|
|
381
|
+
readonly coerceStringByDefault: boolean;
|
|
382
|
+
}): StreamMarkupHealingEvent[] {
|
|
383
|
+
const events: StreamMarkupHealingEvent[] = [];
|
|
384
|
+
let clean = "";
|
|
385
|
+
const flushClean = (): void => {
|
|
386
|
+
if (clean.length === 0) return;
|
|
387
|
+
events.push({ type: "text", text: clean });
|
|
388
|
+
clean = "";
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
while (this.#offset < this.#buffer.length) {
|
|
392
|
+
const state = config.getState();
|
|
393
|
+
|
|
394
|
+
if (state.kind === "idle") {
|
|
395
|
+
if (this.#tryMatch(config.sectionOpen)) {
|
|
396
|
+
config.setState({ kind: "section" });
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
} else if (state.kind === "section") {
|
|
400
|
+
if (this.#tryMatch(config.sectionClose)) {
|
|
401
|
+
config.setState({ kind: "idle" });
|
|
402
|
+
this.#sectionTerminated = true;
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
const invokeMatch = this.#tryMatchCapture(config.invokeOpen);
|
|
406
|
+
if (invokeMatch) {
|
|
407
|
+
config.setState({ kind: "invoke", name: invokeMatch[1] ?? "", args: {} });
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
} else if (state.kind === "invoke") {
|
|
411
|
+
if (this.#tryMatch(config.invokeClose)) {
|
|
412
|
+
const call = finalizeXmlToolCall(state.name, state.args);
|
|
413
|
+
flushClean();
|
|
414
|
+
events.push({ type: "toolCall", call });
|
|
415
|
+
config.setState({ kind: "section" });
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
const paramMatch = this.#tryMatchCapture(config.parameterOpen);
|
|
419
|
+
if (paramMatch) {
|
|
420
|
+
const stringAttr = paramMatch[2];
|
|
421
|
+
config.setState({
|
|
422
|
+
kind: "parameter",
|
|
423
|
+
invokeName: state.name,
|
|
424
|
+
args: state.args,
|
|
425
|
+
paramName: paramMatch[1] ?? "",
|
|
426
|
+
isString: config.coerceStringByDefault ? stringAttr !== "false" : false,
|
|
427
|
+
value: "",
|
|
428
|
+
});
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
} else if (this.#tryMatch(config.parameterClose)) {
|
|
432
|
+
state.args[state.paramName] = coerceXmlParamValue(state.value, state.isString);
|
|
433
|
+
config.setState({ kind: "invoke", name: state.invokeName, args: state.args });
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (this.#startsWithPartialXmlTag()) break;
|
|
438
|
+
|
|
439
|
+
const ch = this.#buffer[this.#offset]!;
|
|
440
|
+
this.#offset += 1;
|
|
441
|
+
if (state.kind === "idle") {
|
|
442
|
+
clean += ch;
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
if (state.kind === "parameter") {
|
|
446
|
+
if (state.value.length >= MAX_XML_PARAM_VALUE_LENGTH) {
|
|
447
|
+
config.setState({ kind: "idle" });
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
state.value += ch;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
flushClean();
|
|
455
|
+
return events;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
#tryMatch(pattern: RegExp): boolean {
|
|
459
|
+
pattern.lastIndex = this.#offset;
|
|
460
|
+
const match = pattern.exec(this.#buffer);
|
|
461
|
+
if (!match) return false;
|
|
462
|
+
this.#offset += match[0].length;
|
|
463
|
+
return true;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
#tryMatchCapture(pattern: RegExp): RegExpExecArray | undefined {
|
|
467
|
+
pattern.lastIndex = this.#offset;
|
|
468
|
+
const match = pattern.exec(this.#buffer);
|
|
469
|
+
if (!match) return undefined;
|
|
470
|
+
this.#offset += match[0].length;
|
|
471
|
+
return match;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
#tryMatchThinkingOpen(tags: readonly ThinkingTag[]): ThinkingTag | undefined {
|
|
475
|
+
for (const tag of tags) {
|
|
476
|
+
if (!this.#matchesToken(tag.open)) continue;
|
|
477
|
+
this.#offset += tag.open.length;
|
|
478
|
+
return tag;
|
|
479
|
+
}
|
|
480
|
+
return undefined;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
#matchesToken(token: string): boolean {
|
|
484
|
+
return this.#buffer.startsWith(token, this.#offset);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
#startsWithPartialThinkingOpen(tags: readonly ThinkingTag[]): boolean {
|
|
488
|
+
for (const tag of tags) {
|
|
489
|
+
if (this.#startsWithPartialToken([tag.open], MAX_XML_PARTIAL_HOLD)) return true;
|
|
490
|
+
}
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
#startsWithPartialToken(tokens: readonly string[], maxHold: number): boolean {
|
|
495
|
+
const remainingLength = this.#buffer.length - this.#offset;
|
|
496
|
+
if (remainingLength === 0 || remainingLength > maxHold) return false;
|
|
497
|
+
for (const token of tokens) {
|
|
498
|
+
if (token.length <= remainingLength) continue;
|
|
499
|
+
if (this.#bufferIsPrefixOf(token, remainingLength)) return true;
|
|
500
|
+
}
|
|
501
|
+
return false;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
#startsWithPartialXmlTag(): boolean {
|
|
505
|
+
if (this.#buffer[this.#offset] !== "<") return false;
|
|
506
|
+
const tailLength = this.#buffer.length - this.#offset;
|
|
507
|
+
if (tailLength > MAX_XML_PARTIAL_HOLD) return false;
|
|
508
|
+
for (let i = this.#offset + 1; i < this.#buffer.length; i++) {
|
|
509
|
+
if (this.#buffer[i] === ">") return false;
|
|
510
|
+
}
|
|
511
|
+
return true;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
#bufferIsPrefixOf(token: string, remainingLength: number): boolean {
|
|
515
|
+
for (let i = 0; i < remainingLength; i++) {
|
|
516
|
+
if (this.#buffer[this.#offset + i] !== token[i]) return false;
|
|
517
|
+
}
|
|
518
|
+
return true;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
#finalizeKimiCall(): HealedToolCall {
|
|
522
|
+
const rawId = this.#kimiPendingId.trim();
|
|
523
|
+
const rawArgs = this.#kimiPendingArgs.trim();
|
|
524
|
+
const name = normalizeKimiFunctionName(rawId);
|
|
525
|
+
|
|
526
|
+
let argsJson = rawArgs;
|
|
527
|
+
if (rawArgs.length > 0) {
|
|
528
|
+
try {
|
|
529
|
+
argsJson = JSON.stringify(parseJsonWithRepair<unknown>(rawArgs));
|
|
530
|
+
} catch {
|
|
531
|
+
// Leave raw; downstream parseStreamingJson absorbs the failure.
|
|
532
|
+
}
|
|
533
|
+
} else {
|
|
534
|
+
argsJson = "{}";
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
this.#kimiInCall = false;
|
|
538
|
+
this.#kimiInArgs = false;
|
|
539
|
+
this.#kimiPendingId = "";
|
|
540
|
+
this.#kimiPendingArgs = "";
|
|
541
|
+
return { id: generateHealedToolCallId(), name, arguments: argsJson };
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
#resetKimi(): void {
|
|
545
|
+
this.#kimiInSection = false;
|
|
546
|
+
this.#kimiInCall = false;
|
|
547
|
+
this.#kimiInArgs = false;
|
|
548
|
+
this.#kimiPendingId = "";
|
|
549
|
+
this.#kimiPendingArgs = "";
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function normalizeKimiFunctionName(rawId: string): string {
|
|
554
|
+
const stripped = rawId.startsWith("functions.") ? rawId.slice("functions.".length) : rawId;
|
|
555
|
+
const colon = stripped.indexOf(":");
|
|
556
|
+
return colon >= 0 ? stripped.slice(0, colon) : stripped;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
function finalizeXmlToolCall(name: string, args: Record<string, unknown>): HealedToolCall {
|
|
560
|
+
return {
|
|
561
|
+
id: generateHealedToolCallId(),
|
|
562
|
+
name: name.trim(),
|
|
563
|
+
arguments: JSON.stringify(args),
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
function coerceXmlParamValue(raw: string, isString: boolean): unknown {
|
|
568
|
+
if (isString) return raw;
|
|
569
|
+
const trimmed = raw.trim();
|
|
570
|
+
if (trimmed.length === 0) return raw;
|
|
571
|
+
try {
|
|
572
|
+
return parseJsonWithRepair<unknown>(trimmed);
|
|
573
|
+
} catch {
|
|
574
|
+
return raw;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function generateHealedToolCallId(): string {
|
|
579
|
+
return `call_${crypto.randomUUID().replace(/-/g, "").slice(0, 24)}`;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/** Cheap model/provider gate for Kimi-K2 chat-template token leaks. */
|
|
583
|
+
export function modelMayLeakKimiToolCalls(provider: string, modelId: string): boolean {
|
|
584
|
+
if (provider === "kimi-code" || provider === "moonshot") return true;
|
|
585
|
+
return /kimi[-/_.]?k2/i.test(modelId);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/** Cheap model/provider gate for DeepSeek DSML envelope leaks. */
|
|
589
|
+
export function modelMayLeakDsmlToolCalls(provider: string, modelId: string): boolean {
|
|
590
|
+
if (!/deepseek/i.test(modelId)) return false;
|
|
591
|
+
return (
|
|
592
|
+
provider === "ollama" ||
|
|
593
|
+
provider === "ollama-cloud" ||
|
|
594
|
+
provider === "nvidia" ||
|
|
595
|
+
provider === "deepseek" ||
|
|
596
|
+
provider === "fireworks" ||
|
|
597
|
+
provider === "nanogpt" ||
|
|
598
|
+
provider === "opencode-go" ||
|
|
599
|
+
provider === "openrouter"
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
export function getStreamMarkupHealingPattern(
|
|
604
|
+
provider: string,
|
|
605
|
+
modelId: string,
|
|
606
|
+
options?: { readonly parseThinkingTags?: boolean },
|
|
607
|
+
): StreamMarkupHealingPattern | undefined {
|
|
608
|
+
if (options?.parseThinkingTags) return "thinking";
|
|
609
|
+
if (modelMayLeakKimiToolCalls(provider, modelId)) return "kimi";
|
|
610
|
+
if (modelMayLeakDsmlToolCalls(provider, modelId)) return "dsml";
|
|
611
|
+
return undefined;
|
|
612
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for mapping unified ToolChoice to provider-specific formats.
|
|
3
|
+
*/
|
|
4
|
+
import type { ToolChoice } from "../types";
|
|
5
|
+
|
|
6
|
+
/** OpenAI Completions API tool choice format */
|
|
7
|
+
export type OpenAICompletionsToolChoice =
|
|
8
|
+
| "auto"
|
|
9
|
+
| "none"
|
|
10
|
+
| "required"
|
|
11
|
+
| { type: "function"; function: { name: string } }
|
|
12
|
+
| undefined;
|
|
13
|
+
|
|
14
|
+
/** OpenAI Responses API tool choice format (flat structure) */
|
|
15
|
+
export type OpenAIResponsesToolChoice =
|
|
16
|
+
| "auto"
|
|
17
|
+
| "none"
|
|
18
|
+
| "required"
|
|
19
|
+
| { type: "function"; name: string }
|
|
20
|
+
| { type: "custom"; name: string }
|
|
21
|
+
| undefined;
|
|
22
|
+
|
|
23
|
+
/** Anthropic-compatible tool choice format */
|
|
24
|
+
export type AnthropicToolChoice = "auto" | "none" | "any" | { type: "tool"; name: string } | undefined;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Extract function name from unified ToolChoice.
|
|
28
|
+
*/
|
|
29
|
+
function extractFunctionName(choice: ToolChoice): string | undefined {
|
|
30
|
+
if (typeof choice === "string") return undefined;
|
|
31
|
+
if (choice.type === "tool" && "name" in choice) return choice.name;
|
|
32
|
+
if (choice.type === "function") {
|
|
33
|
+
if ("function" in choice && choice.function && typeof choice.function === "object") {
|
|
34
|
+
return (choice.function as { name?: string }).name;
|
|
35
|
+
}
|
|
36
|
+
if ("name" in choice) return choice.name;
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Map unified ToolChoice to OpenAI Completions API format.
|
|
43
|
+
* - "any" → "required"
|
|
44
|
+
* - { type: "tool", name } → { type: "function", function: { name } }
|
|
45
|
+
*/
|
|
46
|
+
export function mapToOpenAICompletionsToolChoice(choice?: ToolChoice): OpenAICompletionsToolChoice {
|
|
47
|
+
if (!choice) return undefined;
|
|
48
|
+
if (typeof choice === "string") {
|
|
49
|
+
if (choice === "any") return "required";
|
|
50
|
+
if (choice === "auto" || choice === "none" || choice === "required") return choice;
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
const name = extractFunctionName(choice);
|
|
54
|
+
return name ? { type: "function", function: { name } } : undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Returns true when an OpenAI-completions `tool_choice` value forces a tool
|
|
59
|
+
* call (`"required"` or a function-name pin), as opposed to leaving it open
|
|
60
|
+
* (`"auto"`, `"none"`, or unset). Accepts `unknown` because the param shape
|
|
61
|
+
* pulled from the OpenAI SDK (`ChatCompletionToolChoiceOption`) widens with
|
|
62
|
+
* each release; this check only needs the open/forced bit.
|
|
63
|
+
*/
|
|
64
|
+
export function isForcedToolChoice(choice: unknown): boolean {
|
|
65
|
+
if (choice === undefined || choice === "auto" || choice === "none") return false;
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Map unified ToolChoice to OpenAI Responses API format.
|
|
71
|
+
* - "any" → "required"
|
|
72
|
+
* - { type: "tool", name } → { type: "function", name } (flat structure)
|
|
73
|
+
*/
|
|
74
|
+
export function mapToOpenAIResponsesToolChoice(choice?: ToolChoice): OpenAIResponsesToolChoice {
|
|
75
|
+
if (!choice) return undefined;
|
|
76
|
+
if (typeof choice === "string") {
|
|
77
|
+
if (choice === "any") return "required";
|
|
78
|
+
if (choice === "auto" || choice === "none" || choice === "required") return choice;
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
const name = extractFunctionName(choice);
|
|
82
|
+
return name ? { type: "function", name } : undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Map unified ToolChoice to Anthropic-compatible format.
|
|
87
|
+
* - "required" → "any"
|
|
88
|
+
* - { type: "function", ... } → { type: "tool", name }
|
|
89
|
+
*/
|
|
90
|
+
export function mapToAnthropicToolChoice(choice?: ToolChoice): AnthropicToolChoice {
|
|
91
|
+
if (!choice) return undefined;
|
|
92
|
+
if (typeof choice === "string") {
|
|
93
|
+
if (choice === "required") return "any";
|
|
94
|
+
if (choice === "auto" || choice === "none" || choice === "any") return choice;
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
const name = extractFunctionName(choice);
|
|
98
|
+
return name ? { type: "tool", name } : undefined;
|
|
99
|
+
}
|