@vib-rato/ai 0.16.0
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 +3354 -0
- package/README.md +1194 -0
- package/dist/types/adapter-internals/provider-safety-stop.d.ts +45 -0
- package/dist/types/api-registry.d.ts +30 -0
- package/dist/types/auth-broker/client.d.ts +80 -0
- package/dist/types/auth-broker/index.d.ts +5 -0
- package/dist/types/auth-broker/redact.d.ts +7 -0
- package/dist/types/auth-broker/refresher.d.ts +25 -0
- package/dist/types/auth-broker/remote-store.d.ts +153 -0
- package/dist/types/auth-broker/server.d.ts +32 -0
- package/dist/types/auth-broker/types.d.ts +132 -0
- package/dist/types/auth-broker/wire-schemas.d.ts +555 -0
- package/dist/types/auth-gateway/http.d.ts +40 -0
- package/dist/types/auth-gateway/index.d.ts +3 -0
- package/dist/types/auth-gateway/server.d.ts +70 -0
- package/dist/types/auth-gateway/types.d.ts +129 -0
- package/dist/types/auth-storage.d.ts +1074 -0
- package/dist/types/cli.d.ts +2 -0
- package/dist/types/codex-tools.d.ts +4 -0
- package/dist/types/context-cap-policy.d.ts +68 -0
- package/dist/types/core.d.ts +35 -0
- package/dist/types/index.d.ts +55 -0
- package/dist/types/model-cache.d.ts +24 -0
- package/dist/types/model-manager.d.ts +77 -0
- package/dist/types/model-pricing.d.ts +3 -0
- package/dist/types/model-retirements.d.ts +6 -0
- package/dist/types/model-thinking.d.ts +100 -0
- package/dist/types/models.d.ts +21 -0
- package/dist/types/openai-completions-compat.d.ts +34 -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 +48 -0
- package/dist/types/provider-models/google.d.ts +20 -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 +293 -0
- package/dist/types/provider-models/special.d.ts +29 -0
- package/dist/types/providers/amazon-bedrock.d.ts +60 -0
- package/dist/types/providers/anthropic-messages-server-schema.d.ts +450 -0
- package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
- package/dist/types/providers/anthropic.d.ts +280 -0
- package/dist/types/providers/aws-credential-config.d.ts +19 -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 +22 -0
- package/dist/types/providers/composer-discipline.d.ts +32 -0
- package/dist/types/providers/cursor/client-version.d.ts +10 -0
- package/dist/types/providers/cursor/exec-modern.d.ts +98 -0
- package/dist/types/providers/cursor/gen/agent_pb.d.ts +16769 -0
- package/dist/types/providers/cursor-pi-args.d.ts +119 -0
- package/dist/types/providers/cursor.d.ts +72 -0
- package/dist/types/providers/dashscope-token-plan-headers.d.ts +57 -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 +26 -0
- package/dist/types/providers/google-gemini-cli.d.ts +75 -0
- package/dist/types/providers/google-gemini-headers.d.ts +43 -0
- package/dist/types/providers/google-shared.d.ts +183 -0
- package/dist/types/providers/google-types.d.ts +138 -0
- package/dist/types/providers/google-vertex.d.ts +11 -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/kiro-api-key.d.ts +50 -0
- package/dist/types/providers/kiro-codewhisperer.d.ts +11 -0
- package/dist/types/providers/mock.d.ts +189 -0
- package/dist/types/providers/ollama.d.ts +41 -0
- package/dist/types/providers/openai-anthropic-shim.d.ts +31 -0
- package/dist/types/providers/openai-bounded-rate-limits.d.ts +3 -0
- package/dist/types/providers/openai-chat-server-schema.d.ts +1733 -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 +50 -0
- package/dist/types/providers/openai-codex/response-handler.d.ts +18 -0
- package/dist/types/providers/openai-codex-responses.d.ts +71 -0
- package/dist/types/providers/openai-completions-compat.d.ts +6 -0
- package/dist/types/providers/openai-completions.d.ts +35 -0
- package/dist/types/providers/openai-opencodex-responses.d.ts +10 -0
- package/dist/types/providers/openai-request-transform.d.ts +4 -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 +106 -0
- package/dist/types/providers/openai-responses.d.ts +37 -0
- package/dist/types/providers/pi-native-client.d.ts +29 -0
- package/dist/types/providers/pi-native-server.d.ts +60 -0
- package/dist/types/providers/register-builtins.d.ts +59 -0
- package/dist/types/providers/synthetic.d.ts +26 -0
- package/dist/types/providers/transform-messages.d.ts +33 -0
- package/dist/types/providers/vision-guard.d.ts +8 -0
- package/dist/types/rate-limit-utils.d.ts +19 -0
- package/dist/types/stream.d.ts +45 -0
- package/dist/types/types.d.ts +1073 -0
- package/dist/types/usage/claude.d.ts +3 -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/grok-cli.d.ts +17 -0
- package/dist/types/usage/kimi.d.ts +4 -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 +264 -0
- package/dist/types/utils/abort.d.ts +19 -0
- package/dist/types/utils/anthropic-auth.d.ts +39 -0
- package/dist/types/utils/block-symbols.d.ts +6 -0
- package/dist/types/utils/discovery/antigravity.d.ts +67 -0
- package/dist/types/utils/discovery/codex.d.ts +38 -0
- package/dist/types/utils/discovery/cursor.d.ts +49 -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 +81 -0
- package/dist/types/utils/event-stream.d.ts +41 -0
- package/dist/types/utils/fallback-transport.d.ts +110 -0
- package/dist/types/utils/fireworks-model-id.d.ts +10 -0
- package/dist/types/utils/foundry.d.ts +11 -0
- package/dist/types/utils/h2-fetch.d.ts +22 -0
- package/dist/types/utils/http-inspector.d.ts +59 -0
- package/dist/types/utils/idle-iterator.d.ts +122 -0
- package/dist/types/utils/json-parse.d.ts +98 -0
- package/dist/types/utils/oauth/alibaba-token-plan.d.ts +19 -0
- package/dist/types/utils/oauth/anthropic.d.ts +41 -0
- package/dist/types/utils/oauth/api-key-login.d.ts +38 -0
- package/dist/types/utils/oauth/api-key-validation.d.ts +39 -0
- package/dist/types/utils/oauth/bizrouter.d.ts +1 -0
- package/dist/types/utils/oauth/callback-server.d.ts +80 -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/commandcode.d.ts +1 -0
- package/dist/types/utils/oauth/cursor.d.ts +15 -0
- package/dist/types/utils/oauth/deepinfra.d.ts +1 -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/fugu.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/glm-zcode.d.ts +71 -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 +39 -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 +17 -0
- package/dist/types/utils/oauth/kiro.d.ts +71 -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/mara.d.ts +1 -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/opengateway.d.ts +1 -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 +4 -0
- package/dist/types/utils/oauth/pkce.d.ts +8 -0
- 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/sglang.d.ts +16 -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 +56 -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/xai.d.ts +30 -0
- package/dist/types/utils/oauth/xiaomi.d.ts +25 -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/overflow.d.ts +14 -0
- package/dist/types/utils/parse-bind.d.ts +26 -0
- package/dist/types/utils/provider-response.d.ts +6 -0
- package/dist/types/utils/provider-safety-stop.d.ts +8 -0
- package/dist/types/utils/proxy.d.ts +7 -0
- package/dist/types/utils/retry-after.d.ts +3 -0
- package/dist/types/utils/retry-budget.d.ts +1 -0
- package/dist/types/utils/retry.d.ts +29 -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 +14 -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/root-combinator.d.ts +12 -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 +54 -0
- package/dist/types/utils/schema/zod-decontaminate.d.ts +31 -0
- package/dist/types/utils/sse-debug.d.ts +10 -0
- package/dist/types/utils/tool-call-healing.d.ts +80 -0
- package/dist/types/utils/tool-choice-capability.d.ts +57 -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 +117 -0
- package/package.json +152 -0
- package/src/adapter-internals/provider-safety-stop.d.ts +45 -0
- package/src/adapter-internals/provider-safety-stop.ts +156 -0
- package/src/api-registry.d.ts +30 -0
- package/src/api-registry.ts +96 -0
- package/src/auth-broker/client.ts +444 -0
- package/src/auth-broker/index.ts +5 -0
- package/src/auth-broker/redact.ts +39 -0
- package/src/auth-broker/refresher.ts +130 -0
- package/src/auth-broker/remote-store.ts +1576 -0
- package/src/auth-broker/server.ts +764 -0
- package/src/auth-broker/types.ts +164 -0
- package/src/auth-broker/wire-schemas.ts +261 -0
- package/src/auth-gateway/http.ts +198 -0
- package/src/auth-gateway/index.ts +3 -0
- package/src/auth-gateway/server.ts +1315 -0
- package/src/auth-gateway/types.ts +160 -0
- package/src/auth-storage.ts +7312 -0
- package/src/cli.ts +269 -0
- package/src/codex-tools.d.ts +4 -0
- package/src/codex-tools.ts +24 -0
- package/src/context-cap-policy.d.ts +68 -0
- package/src/context-cap-policy.ts +123 -0
- package/src/core.ts +44 -0
- package/src/index.ts +61 -0
- package/src/model-cache.ts +236 -0
- package/src/model-manager.ts +744 -0
- package/src/model-pricing.d.ts +3 -0
- package/src/model-pricing.ts +68 -0
- package/src/model-retirements.d.ts +6 -0
- package/src/model-retirements.ts +19 -0
- package/src/model-thinking.d.ts +100 -0
- package/src/model-thinking.ts +1054 -0
- package/src/models.d.ts +21 -0
- package/src/models.json +94672 -0
- package/src/models.json.d.ts +9 -0
- package/src/models.ts +126 -0
- package/src/openai-completions-compat.d.ts +34 -0
- package/src/openai-completions-compat.ts +383 -0
- package/src/prompts/composer-bash-policy-recovery.md +1 -0
- package/src/prompts/cursor-composer-bash-policy-recovery.md +1 -0
- package/src/prompts/cursor-composer-edit-discipline.md +7 -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 +392 -0
- package/src/provider-models/google.ts +92 -0
- package/src/provider-models/index.ts +5 -0
- package/src/provider-models/ollama.ts +159 -0
- package/src/provider-models/openai-compat.ts +2920 -0
- package/src/provider-models/special.ts +185 -0
- package/src/providers/amazon-bedrock.d.ts +60 -0
- package/src/providers/amazon-bedrock.ts +939 -0
- package/src/providers/anthropic-messages-server-schema.ts +229 -0
- package/src/providers/anthropic-messages-server.ts +839 -0
- package/src/providers/anthropic.d.ts +280 -0
- package/src/providers/anthropic.ts +4421 -0
- package/src/providers/aws-credential-config.d.ts +19 -0
- package/src/providers/aws-credential-config.ts +179 -0
- package/src/providers/aws-credentials.d.ts +43 -0
- package/src/providers/aws-credentials.ts +457 -0
- package/src/providers/aws-eventstream.d.ts +38 -0
- package/src/providers/aws-eventstream.ts +185 -0
- package/src/providers/aws-sigv4.d.ts +55 -0
- package/src/providers/aws-sigv4.ts +218 -0
- package/src/providers/azure-openai-responses.d.ts +22 -0
- package/src/providers/azure-openai-responses.ts +447 -0
- package/src/providers/composer-discipline.d.ts +32 -0
- package/src/providers/composer-discipline.ts +95 -0
- package/src/providers/cursor/client-version.d.ts +10 -0
- package/src/providers/cursor/client-version.ts +10 -0
- package/src/providers/cursor/exec-modern.d.ts +98 -0
- package/src/providers/cursor/exec-modern.ts +497 -0
- package/src/providers/cursor/gen/agent_pb.d.ts +16769 -0
- package/src/providers/cursor/gen/agent_pb.ts +19780 -0
- package/src/providers/cursor/proto/agent.proto +4533 -0
- package/src/providers/cursor/proto/buf.gen.yaml +6 -0
- package/src/providers/cursor/proto/buf.yaml +17 -0
- package/src/providers/cursor-pi-args.d.ts +119 -0
- package/src/providers/cursor-pi-args.ts +187 -0
- package/src/providers/cursor.d.ts +72 -0
- package/src/providers/cursor.ts +3396 -0
- package/src/providers/dashscope-token-plan-headers.d.ts +57 -0
- package/src/providers/dashscope-token-plan-headers.ts +84 -0
- package/src/providers/error-message.d.ts +27 -0
- package/src/providers/error-message.ts +21 -0
- package/src/providers/github-copilot-headers.d.ts +40 -0
- package/src/providers/github-copilot-headers.ts +140 -0
- package/src/providers/gitlab-duo.d.ts +27 -0
- package/src/providers/gitlab-duo.ts +393 -0
- package/src/providers/google-auth.d.ts +26 -0
- package/src/providers/google-auth.ts +262 -0
- package/src/providers/google-gemini-cli.d.ts +75 -0
- package/src/providers/google-gemini-cli.ts +969 -0
- package/src/providers/google-gemini-headers.d.ts +43 -0
- package/src/providers/google-gemini-headers.ts +100 -0
- package/src/providers/google-shared.d.ts +183 -0
- package/src/providers/google-shared.ts +1105 -0
- package/src/providers/google-types.d.ts +138 -0
- package/src/providers/google-types.ts +167 -0
- package/src/providers/google-vertex.d.ts +11 -0
- package/src/providers/google-vertex.ts +124 -0
- package/src/providers/google.d.ts +4 -0
- package/src/providers/google.ts +41 -0
- package/src/providers/grammar.d.ts +1 -0
- package/src/providers/grammar.ts +70 -0
- package/src/providers/kimi.d.ts +27 -0
- package/src/providers/kimi.ts +52 -0
- package/src/providers/kiro-api-key.d.ts +50 -0
- package/src/providers/kiro-api-key.ts +786 -0
- package/src/providers/kiro-codewhisperer.d.ts +11 -0
- package/src/providers/kiro-codewhisperer.ts +600 -0
- package/src/providers/mock.ts +526 -0
- package/src/providers/ollama.d.ts +41 -0
- package/src/providers/ollama.ts +645 -0
- package/src/providers/openai-anthropic-shim.d.ts +31 -0
- package/src/providers/openai-anthropic-shim.ts +156 -0
- package/src/providers/openai-bounded-rate-limits.d.ts +3 -0
- package/src/providers/openai-bounded-rate-limits.ts +57 -0
- package/src/providers/openai-chat-server-schema.ts +254 -0
- package/src/providers/openai-chat-server.ts +724 -0
- package/src/providers/openai-codex/constants.d.ts +26 -0
- package/src/providers/openai-codex/constants.ts +43 -0
- package/src/providers/openai-codex/request-transformer.d.ts +50 -0
- package/src/providers/openai-codex/request-transformer.ts +219 -0
- package/src/providers/openai-codex/response-handler.d.ts +18 -0
- package/src/providers/openai-codex/response-handler.ts +111 -0
- package/src/providers/openai-codex-responses.d.ts +71 -0
- package/src/providers/openai-codex-responses.ts +3288 -0
- package/src/providers/openai-completions-compat.d.ts +6 -0
- package/src/providers/openai-completions-compat.ts +6 -0
- package/src/providers/openai-completions.d.ts +35 -0
- package/src/providers/openai-completions.ts +2294 -0
- package/src/providers/openai-opencodex-responses.ts +174 -0
- package/src/providers/openai-request-transform.d.ts +4 -0
- package/src/providers/openai-request-transform.ts +136 -0
- package/src/providers/openai-responses-server-schema.ts +290 -0
- package/src/providers/openai-responses-server.ts +1268 -0
- package/src/providers/openai-responses-shared.d.ts +106 -0
- package/src/providers/openai-responses-shared.ts +1253 -0
- package/src/providers/openai-responses.d.ts +37 -0
- package/src/providers/openai-responses.ts +989 -0
- package/src/providers/pi-native-client.d.ts +29 -0
- package/src/providers/pi-native-client.ts +243 -0
- package/src/providers/pi-native-server.ts +488 -0
- package/src/providers/register-builtins.d.ts +59 -0
- package/src/providers/register-builtins.ts +544 -0
- package/src/providers/synthetic.d.ts +26 -0
- package/src/providers/synthetic.ts +50 -0
- package/src/providers/transform-messages.d.ts +33 -0
- package/src/providers/transform-messages.ts +408 -0
- package/src/providers/vision-guard.d.ts +8 -0
- package/src/providers/vision-guard.ts +31 -0
- package/src/rate-limit-utils.d.ts +19 -0
- package/src/rate-limit-utils.ts +102 -0
- package/src/stream.d.ts +45 -0
- package/src/stream.ts +1306 -0
- package/src/types.d.ts +1073 -0
- package/src/types.ts +1305 -0
- package/src/usage/claude.ts +449 -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/grok-cli.ts +259 -0
- package/src/usage/kimi.ts +285 -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 +190 -0
- package/src/utils/abort.d.ts +19 -0
- package/src/utils/abort.ts +51 -0
- package/src/utils/anthropic-auth.ts +95 -0
- package/src/utils/block-symbols.d.ts +6 -0
- package/src/utils/block-symbols.ts +11 -0
- package/src/utils/discovery/antigravity.ts +275 -0
- package/src/utils/discovery/codex.ts +362 -0
- package/src/utils/discovery/cursor.ts +388 -0
- package/src/utils/discovery/gemini.ts +248 -0
- package/src/utils/discovery/index.ts +4 -0
- package/src/utils/discovery/openai-compatible.ts +379 -0
- package/src/utils/event-stream.d.ts +41 -0
- package/src/utils/event-stream.ts +269 -0
- package/src/utils/fallback-transport.d.ts +110 -0
- package/src/utils/fallback-transport.ts +411 -0
- package/src/utils/fireworks-model-id.d.ts +10 -0
- package/src/utils/fireworks-model-id.ts +30 -0
- package/src/utils/foundry.d.ts +11 -0
- package/src/utils/foundry.ts +18 -0
- package/src/utils/h2-fetch.ts +60 -0
- package/src/utils/http-inspector.d.ts +59 -0
- package/src/utils/http-inspector.ts +380 -0
- package/src/utils/idle-iterator.d.ts +122 -0
- package/src/utils/idle-iterator.ts +410 -0
- package/src/utils/json-parse.d.ts +98 -0
- package/src/utils/json-parse.ts +607 -0
- package/src/utils/oauth/alibaba-token-plan.ts +60 -0
- package/src/utils/oauth/anthropic.ts +233 -0
- package/src/utils/oauth/api-key-login.ts +98 -0
- package/src/utils/oauth/api-key-validation.ts +344 -0
- package/src/utils/oauth/bizrouter.ts +15 -0
- package/src/utils/oauth/callback-server.d.ts +80 -0
- package/src/utils/oauth/callback-server.ts +359 -0
- package/src/utils/oauth/cerebras.ts +16 -0
- package/src/utils/oauth/cloudflare-ai-gateway.ts +48 -0
- package/src/utils/oauth/commandcode.ts +17 -0
- package/src/utils/oauth/cursor.ts +157 -0
- package/src/utils/oauth/deepinfra.ts +15 -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/fugu.ts +15 -0
- package/src/utils/oauth/github-copilot.d.ts +38 -0
- package/src/utils/oauth/github-copilot.ts +362 -0
- package/src/utils/oauth/gitlab-duo.ts +123 -0
- package/src/utils/oauth/glm-zcode.d.ts +71 -0
- package/src/utils/oauth/glm-zcode.ts +433 -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 +558 -0
- package/src/utils/oauth/kagi.ts +47 -0
- package/src/utils/oauth/kilo.ts +87 -0
- package/src/utils/oauth/kimi.d.ts +17 -0
- package/src/utils/oauth/kimi.ts +275 -0
- package/src/utils/oauth/kiro.ts +448 -0
- package/src/utils/oauth/litellm.ts +47 -0
- package/src/utils/oauth/lm-studio.ts +38 -0
- package/src/utils/oauth/mara.ts +16 -0
- package/src/utils/oauth/minimax-code.ts +78 -0
- package/src/utils/oauth/moonshot.ts +16 -0
- package/src/utils/oauth/nanogpt.ts +15 -0
- package/src/utils/oauth/nvidia.ts +70 -0
- package/src/utils/oauth/oauth.html +199 -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/opengateway.ts +15 -0
- package/src/utils/oauth/openrouter.ts +16 -0
- package/src/utils/oauth/parallel.ts +46 -0
- package/src/utils/oauth/perplexity.ts +225 -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/sglang.ts +42 -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.d.ts +56 -0
- package/src/utils/oauth/types.ts +122 -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 +42 -0
- package/src/utils/oauth/xai.ts +246 -0
- package/src/utils/oauth/xiaomi.ts +199 -0
- package/src/utils/oauth/zai.ts +60 -0
- package/src/utils/oauth/zenmux.ts +15 -0
- package/src/utils/overflow.ts +275 -0
- package/src/utils/parse-bind.ts +81 -0
- package/src/utils/provider-response.d.ts +6 -0
- package/src/utils/provider-response.ts +30 -0
- package/src/utils/provider-safety-stop.ts +8 -0
- package/src/utils/proxy.d.ts +7 -0
- package/src/utils/proxy.ts +652 -0
- package/src/utils/retry-after.d.ts +3 -0
- package/src/utils/retry-after.ts +110 -0
- package/src/utils/retry-budget.d.ts +1 -0
- package/src/utils/retry-budget.ts +4 -0
- package/src/utils/retry.d.ts +29 -0
- package/src/utils/retry.ts +67 -0
- package/src/utils/schema/CONSTRAINTS.md +164 -0
- package/src/utils/schema/adapt.d.ts +24 -0
- package/src/utils/schema/adapt.ts +36 -0
- package/src/utils/schema/compatibility.d.ts +30 -0
- package/src/utils/schema/compatibility.ts +435 -0
- package/src/utils/schema/dereference.d.ts +11 -0
- package/src/utils/schema/dereference.ts +98 -0
- package/src/utils/schema/draft.d.ts +10 -0
- package/src/utils/schema/draft.ts +341 -0
- package/src/utils/schema/equality.d.ts +4 -0
- package/src/utils/schema/equality.ts +97 -0
- package/src/utils/schema/fields.d.ts +49 -0
- package/src/utils/schema/fields.ts +190 -0
- package/src/utils/schema/index.d.ts +14 -0
- package/src/utils/schema/index.ts +14 -0
- package/src/utils/schema/json-schema-validator.d.ts +12 -0
- package/src/utils/schema/json-schema-validator.ts +577 -0
- package/src/utils/schema/meta-validator.d.ts +2 -0
- package/src/utils/schema/meta-validator.ts +167 -0
- package/src/utils/schema/normalize.d.ts +93 -0
- package/src/utils/schema/normalize.ts +1588 -0
- package/src/utils/schema/root-combinator.d.ts +12 -0
- package/src/utils/schema/root-combinator.ts +143 -0
- package/src/utils/schema/spill.d.ts +8 -0
- package/src/utils/schema/spill.ts +43 -0
- package/src/utils/schema/stamps.d.ts +25 -0
- package/src/utils/schema/stamps.ts +97 -0
- package/src/utils/schema/types.d.ts +4 -0
- package/src/utils/schema/types.ts +11 -0
- package/src/utils/schema/wire.d.ts +54 -0
- package/src/utils/schema/wire.ts +213 -0
- package/src/utils/schema/zod-decontaminate.d.ts +31 -0
- package/src/utils/schema/zod-decontaminate.ts +331 -0
- package/src/utils/sse-debug.d.ts +10 -0
- package/src/utils/sse-debug.ts +289 -0
- package/src/utils/tool-call-healing.d.ts +80 -0
- package/src/utils/tool-call-healing.ts +298 -0
- package/src/utils/tool-choice-capability.d.ts +57 -0
- package/src/utils/tool-choice-capability.ts +633 -0
- package/src/utils/tool-choice.d.ts +50 -0
- package/src/utils/tool-choice.ts +99 -0
- package/src/utils/validation.ts +1080 -0
- package/src/utils.d.ts +117 -0
- package/src/utils.ts +523 -0
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
import { Database } from "bun:sqlite";
|
|
2
|
+
import * as crypto from "node:crypto";
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { getToolChoiceCapabilityCachePath } from "@vib-rato/utils/dirs";
|
|
6
|
+
import { extractHttpStatusFromError } from "@vib-rato/utils/fetch-retry";
|
|
7
|
+
import * as logger from "@vib-rato/utils/logger";
|
|
8
|
+
import type { Api, Model, ToolChoice, ToolChoiceCompat, ToolChoiceSupport, ToolChoiceSupportSource } from "../types";
|
|
9
|
+
|
|
10
|
+
const supportRank: Record<ToolChoiceSupport, number> = {
|
|
11
|
+
none: 0,
|
|
12
|
+
auto: 1,
|
|
13
|
+
required: 2,
|
|
14
|
+
named: 3,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const registry = new Map<string, ToolChoiceSupport>();
|
|
18
|
+
const loggedRegistryKeys = new Set<string>();
|
|
19
|
+
const registryExpiresAt = new Map<string, number>();
|
|
20
|
+
const CACHE_SCHEMA_VERSION = 1;
|
|
21
|
+
const CACHE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
22
|
+
const EMPTY_CACHE_TTL_MS = 5 * 60 * 1000;
|
|
23
|
+
const CACHE_MAX_ENTRIES = 256;
|
|
24
|
+
const REGISTRY_MAX_ENTRIES = 256;
|
|
25
|
+
const CACHE_MUTATION_LOCK_STALE_MS = 5_000;
|
|
26
|
+
|
|
27
|
+
type NativeExactUnlinkBindings = Pick<typeof import("@vib-rato/natives"), "exactUnlink">;
|
|
28
|
+
|
|
29
|
+
let nativeExactUnlinkBindings: NativeExactUnlinkBindings | undefined;
|
|
30
|
+
|
|
31
|
+
let cachePathOverride: string | undefined;
|
|
32
|
+
let nowForTests: (() => number) | undefined;
|
|
33
|
+
let beforeExpiredDeleteForTests: (() => void) | undefined;
|
|
34
|
+
let beforeMalformedDeleteForTests: (() => void) | undefined;
|
|
35
|
+
let onCacheOpenForTests: (() => void) | undefined;
|
|
36
|
+
let simulateCacheOperationErrorForTests: (() => Error | undefined) | undefined;
|
|
37
|
+
let beforeCorruptRetireForTests: (() => void) | undefined;
|
|
38
|
+
let beforeLockExactUnlinkForTests: ((lockPath: string) => void) | undefined;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Claude Mythos accepts tools but rejects forced tool use (Anthropic 400:
|
|
42
|
+
* "tool_choice forces tool use is not compatible with this model"). Catalog
|
|
43
|
+
* generation and dynamic discovery use this to default `toolChoiceSupport`.
|
|
44
|
+
*/
|
|
45
|
+
export function isClaudeForcedToolChoiceIncapableModelId(modelId: string): boolean {
|
|
46
|
+
return /(?:^|[/.])claude-mythos(?:-|$)/i.test(modelId);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Derives the effective static tool-choice support from compatibility flags. */
|
|
50
|
+
export function deriveToolChoiceSupport(compat: ToolChoiceCompat | undefined): {
|
|
51
|
+
support: ToolChoiceSupport;
|
|
52
|
+
source: "static" | "derived";
|
|
53
|
+
} {
|
|
54
|
+
if (compat?.toolChoiceSupport) {
|
|
55
|
+
return { support: compat.toolChoiceSupport, source: "static" };
|
|
56
|
+
}
|
|
57
|
+
if (compat?.supportsToolChoice === false) {
|
|
58
|
+
return { support: "none", source: "derived" };
|
|
59
|
+
}
|
|
60
|
+
if (compat?.supportsForcedToolChoice === false) {
|
|
61
|
+
return { support: "auto", source: "derived" };
|
|
62
|
+
}
|
|
63
|
+
return { support: "named", source: "derived" };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Returns the registry key used for runtime tool-choice capability overrides. */
|
|
67
|
+
export function toolChoiceRegistryKey(model: Model<Api>): string {
|
|
68
|
+
return [model.api, model.provider, model.baseUrl, model.wireModelId ?? model.id].join("|");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Returns the current runtime tool-choice capability override for a model. */
|
|
72
|
+
export function getToolChoiceCapabilityOverride(model: Model<Api>): ToolChoiceSupport | undefined {
|
|
73
|
+
const key = toolChoiceRegistryKey(model);
|
|
74
|
+
hydrateToolChoiceCapability(key);
|
|
75
|
+
return registry.get(key);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Clears runtime tool-choice capability overrides for tests. */
|
|
79
|
+
export function clearToolChoiceIncapabilityRegistryForTests(): void {
|
|
80
|
+
registry.clear();
|
|
81
|
+
loggedRegistryKeys.clear();
|
|
82
|
+
registryExpiresAt.clear();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Overrides durable-cache dependencies for isolated tests. */
|
|
86
|
+
export function configureToolChoiceCapabilityCacheForTests(options?: {
|
|
87
|
+
path?: string;
|
|
88
|
+
now?: () => number;
|
|
89
|
+
beforeExpiredDelete?: () => void;
|
|
90
|
+
beforeMalformedDelete?: () => void;
|
|
91
|
+
onCacheOpen?: () => void;
|
|
92
|
+
simulateOperationError?: () => Error | undefined;
|
|
93
|
+
beforeCorruptRetire?: () => void;
|
|
94
|
+
beforeLockExactUnlink?: (lockPath: string) => void;
|
|
95
|
+
}): void {
|
|
96
|
+
cachePathOverride = options?.path;
|
|
97
|
+
nowForTests = options?.now;
|
|
98
|
+
beforeExpiredDeleteForTests = options?.beforeExpiredDelete;
|
|
99
|
+
beforeMalformedDeleteForTests = options?.beforeMalformedDelete;
|
|
100
|
+
onCacheOpenForTests = options?.onCacheOpen;
|
|
101
|
+
simulateCacheOperationErrorForTests = options?.simulateOperationError;
|
|
102
|
+
beforeCorruptRetireForTests = options?.beforeCorruptRetire;
|
|
103
|
+
beforeLockExactUnlinkForTests = options?.beforeLockExactUnlink;
|
|
104
|
+
clearToolChoiceIncapabilityRegistryForTests();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Records a discovered maximum supported tool-choice level for a model. */
|
|
108
|
+
export function markToolChoiceIncapability(model: Model<Api>, maxSupport: ToolChoiceSupport, reason?: string): void {
|
|
109
|
+
const key = toolChoiceRegistryKey(model);
|
|
110
|
+
const releaseMutationLock = acquireCapabilityCacheMutationLock();
|
|
111
|
+
try {
|
|
112
|
+
hydrateToolChoiceCapability(key);
|
|
113
|
+
const existing = registry.get(key);
|
|
114
|
+
const next = existing && supportRank[existing] < supportRank[maxSupport] ? existing : maxSupport;
|
|
115
|
+
registry.set(key, next);
|
|
116
|
+
const persisted = persistToolChoiceCapability(key, next);
|
|
117
|
+
if (persisted) registry.set(key, persisted.support);
|
|
118
|
+
registryExpiresAt.set(key, (persisted?.observedAt ?? currentTime()) + CACHE_TTL_MS);
|
|
119
|
+
} finally {
|
|
120
|
+
releaseMutationLock?.();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!loggedRegistryKeys.has(key)) {
|
|
124
|
+
loggedRegistryKeys.add(key);
|
|
125
|
+
logger.debug("Discovered tool_choice incapability", {
|
|
126
|
+
api: model.api,
|
|
127
|
+
provider: model.provider,
|
|
128
|
+
baseUrlHost: safeHostname(model.baseUrl),
|
|
129
|
+
model: model.wireModelId ?? model.id,
|
|
130
|
+
maxSupport,
|
|
131
|
+
reason,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function acquireCapabilityCacheMutationLock(): (() => void) | undefined {
|
|
137
|
+
if (process.env.NODE_ENV === "test" && cachePathOverride === undefined) return;
|
|
138
|
+
const cachePath = cachePathOverride ?? getToolChoiceCapabilityCachePath();
|
|
139
|
+
const lockPath = `${cachePath}.mutation.lock`;
|
|
140
|
+
const sleeper = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
|
141
|
+
const owner = `${process.pid}:${crypto.randomUUID()}`;
|
|
142
|
+
while (true) {
|
|
143
|
+
try {
|
|
144
|
+
fs.mkdirSync(path.dirname(cachePath), { recursive: true, mode: 0o700 });
|
|
145
|
+
const descriptor = fs.openSync(lockPath, "wx", 0o600);
|
|
146
|
+
fs.writeFileSync(descriptor, owner);
|
|
147
|
+
fs.closeSync(descriptor);
|
|
148
|
+
return () => {
|
|
149
|
+
try {
|
|
150
|
+
exactUnlinkCapabilityLock(lockPath, owner);
|
|
151
|
+
} catch {
|
|
152
|
+
// A crashed owner was already reaped.
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
} catch (error) {
|
|
156
|
+
if (!(error && typeof error === "object" && (error as { code?: unknown }).code === "EEXIST")) return;
|
|
157
|
+
try {
|
|
158
|
+
const lockOwner = fs.readFileSync(lockPath, "utf8");
|
|
159
|
+
const ownerPid = Number(lockOwner.split(":", 1)[0]);
|
|
160
|
+
const ownerIsAlive = Number.isSafeInteger(ownerPid) && ownerPid > 0 && isProcessAlive(ownerPid);
|
|
161
|
+
const staleOwner =
|
|
162
|
+
!ownerIsAlive && Date.now() - fs.statSync(lockPath).mtimeMs > CACHE_MUTATION_LOCK_STALE_MS;
|
|
163
|
+
if (staleOwner && !exactUnlinkCapabilityLock(lockPath, lockOwner)) {
|
|
164
|
+
Atomics.wait(sleeper, 0, 0, 10);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
} catch {
|
|
168
|
+
// The lock changed while this waiter was being inspected.
|
|
169
|
+
}
|
|
170
|
+
Atomics.wait(sleeper, 0, 0, 10);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function exactUnlinkCapabilityLock(lockPath: string, expectedOwner: string): boolean {
|
|
176
|
+
// Open the lock first and read bytes + identity from the SAME descriptor: the
|
|
177
|
+
// pinned inode cannot be recycled or substituted while the handle is open, so
|
|
178
|
+
// a replacement owner that lands at the pathname after the read can never be
|
|
179
|
+
// mistaken for the record whose bytes authorized this removal.
|
|
180
|
+
const descriptor = fs.openSync(lockPath, "r");
|
|
181
|
+
let bytes: Buffer;
|
|
182
|
+
let stat: import("node:fs").BigIntStats;
|
|
183
|
+
try {
|
|
184
|
+
bytes = fs.readFileSync(descriptor);
|
|
185
|
+
if (bytes.toString("utf8") !== expectedOwner) return false;
|
|
186
|
+
stat = fs.fstatSync(descriptor, { bigint: true });
|
|
187
|
+
beforeLockExactUnlinkForTests?.(lockPath);
|
|
188
|
+
if (!stat.isFile()) return false;
|
|
189
|
+
} finally {
|
|
190
|
+
fs.closeSync(descriptor);
|
|
191
|
+
}
|
|
192
|
+
const parent = fs.statSync(path.dirname(lockPath), { bigint: true });
|
|
193
|
+
if (!parent.isDirectory()) return false;
|
|
194
|
+
if (!nativeExactUnlinkBindings)
|
|
195
|
+
nativeExactUnlinkBindings = require("@vib-rato/natives") as NativeExactUnlinkBindings;
|
|
196
|
+
const bindings = nativeExactUnlinkBindings;
|
|
197
|
+
const result = bindings.exactUnlink(lockPath, {
|
|
198
|
+
dev: stat.dev,
|
|
199
|
+
ino: stat.ino,
|
|
200
|
+
nlink: stat.nlink,
|
|
201
|
+
parentDev: parent.dev,
|
|
202
|
+
parentIno: parent.ino,
|
|
203
|
+
size: stat.size,
|
|
204
|
+
mtimeNs: stat.mtimeNs,
|
|
205
|
+
sha256: crypto.createHash("sha256").update(bytes).digest("hex"),
|
|
206
|
+
quarantineName: `.tool-choice-capability-lock-${crypto.randomUUID()}`,
|
|
207
|
+
});
|
|
208
|
+
return (
|
|
209
|
+
result.ok ||
|
|
210
|
+
(result.code === "cleanup_pending" &&
|
|
211
|
+
result.payloadDurable === true &&
|
|
212
|
+
result.detachedPath !== undefined &&
|
|
213
|
+
result.retainedSuccessorPath === undefined &&
|
|
214
|
+
result.retainedUnknownPath === undefined)
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function isProcessAlive(pid: number): boolean {
|
|
219
|
+
try {
|
|
220
|
+
process.kill(pid, 0);
|
|
221
|
+
return true;
|
|
222
|
+
} catch (error) {
|
|
223
|
+
// EPERM means the process exists but may not be signalable; only ESRCH
|
|
224
|
+
// proves the pid is gone. Any other outcome is treated as alive so an
|
|
225
|
+
// uncertain owner is never reaped as stale.
|
|
226
|
+
return (error as { code?: string }).code !== "ESRCH";
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Resolves a requested tool_choice against static and runtime capability limits.
|
|
232
|
+
* `compat` overrides `model.compat` for transports that layer URL/provider
|
|
233
|
+
* detection on top of explicit model overrides (e.g. resolveOpenAICompat).
|
|
234
|
+
*/
|
|
235
|
+
export function resolveToolChoice(
|
|
236
|
+
model: Model<Api>,
|
|
237
|
+
requested: ToolChoice | undefined,
|
|
238
|
+
compat?: ToolChoiceCompat,
|
|
239
|
+
): ResolveToolChoiceResult {
|
|
240
|
+
const derived = deriveToolChoiceSupport(compat ?? model.compat);
|
|
241
|
+
const registryKey = toolChoiceRegistryKey(model);
|
|
242
|
+
hydrateToolChoiceCapability(registryKey);
|
|
243
|
+
const runtime = registry.get(registryKey);
|
|
244
|
+
const support = runtime && supportRank[runtime] < supportRank[derived.support] ? runtime : derived.support;
|
|
245
|
+
const supportSource: ToolChoiceSupportSource = support === derived.support ? derived.source : "runtime";
|
|
246
|
+
const requestedInfo = requestedToolChoiceLevel(requested);
|
|
247
|
+
const clampLevel = requestedInfo.requestedLevel === "none" ? "auto" : requestedInfo.requestedLevel;
|
|
248
|
+
|
|
249
|
+
if (requested === undefined) {
|
|
250
|
+
return {
|
|
251
|
+
requestedChoice: requested,
|
|
252
|
+
requestedLevel: requestedInfo.requestedLevel,
|
|
253
|
+
resolvedChoice: undefined,
|
|
254
|
+
resolvedLevel: "auto",
|
|
255
|
+
support,
|
|
256
|
+
supportSource,
|
|
257
|
+
degraded: false,
|
|
258
|
+
registryKey,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (support === "none") {
|
|
263
|
+
return {
|
|
264
|
+
requestedChoice: requested,
|
|
265
|
+
requestedLevel: requestedInfo.requestedLevel,
|
|
266
|
+
resolvedChoice: undefined,
|
|
267
|
+
resolvedLevel: "none",
|
|
268
|
+
support,
|
|
269
|
+
supportSource,
|
|
270
|
+
degraded: requestedInfo.requestedLevel !== "none",
|
|
271
|
+
reason: "tool_choice is not supported by this model",
|
|
272
|
+
registryKey,
|
|
273
|
+
targetToolName: requestedInfo.targetToolName,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (supportRank[support] >= supportRank[clampLevel]) {
|
|
278
|
+
return {
|
|
279
|
+
requestedChoice: requested,
|
|
280
|
+
requestedLevel: requestedInfo.requestedLevel,
|
|
281
|
+
resolvedChoice: requested,
|
|
282
|
+
resolvedLevel: requestedInfo.requestedLevel,
|
|
283
|
+
support,
|
|
284
|
+
supportSource,
|
|
285
|
+
degraded: false,
|
|
286
|
+
registryKey,
|
|
287
|
+
targetToolName: requestedInfo.targetToolName,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (requestedInfo.requestedLevel === "named" && support === "required") {
|
|
292
|
+
return {
|
|
293
|
+
requestedChoice: requested,
|
|
294
|
+
requestedLevel: "named",
|
|
295
|
+
resolvedChoice: "required",
|
|
296
|
+
resolvedLevel: "required",
|
|
297
|
+
support,
|
|
298
|
+
supportSource,
|
|
299
|
+
degraded: true,
|
|
300
|
+
reason: "named tool_choice degraded to required",
|
|
301
|
+
registryKey,
|
|
302
|
+
targetToolName: requestedInfo.targetToolName,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return {
|
|
307
|
+
requestedChoice: requested,
|
|
308
|
+
requestedLevel: requestedInfo.requestedLevel,
|
|
309
|
+
resolvedChoice: undefined,
|
|
310
|
+
resolvedLevel: support === "auto" ? "auto" : "none",
|
|
311
|
+
support,
|
|
312
|
+
supportSource,
|
|
313
|
+
degraded: true,
|
|
314
|
+
reason: "forced tool_choice is not supported by this model",
|
|
315
|
+
registryKey,
|
|
316
|
+
targetToolName: requestedInfo.targetToolName,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/** Detects provider errors indicating forced tool_choice is unsupported. */
|
|
321
|
+
export function isForcedToolChoiceUnsupportedError(error: unknown, sentForcedToolChoice: boolean): boolean {
|
|
322
|
+
const status = extractHttpStatusFromError(error);
|
|
323
|
+
if (!sentForcedToolChoice || status !== 400) {
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
const message = errorMessage(error);
|
|
327
|
+
return (
|
|
328
|
+
// `by <something>` continuations ("not supported by billing") describe a
|
|
329
|
+
// different subject than the model's tool_choice capability — reject them
|
|
330
|
+
// unless the continuation names the model itself.
|
|
331
|
+
/tool[_\s-]?choices?\b.*?(not\s+compatible|incompatible|not\s+supported)(?!\s+by\s+(?!(?:this|the)\s+model\b|model\b))/is.test(
|
|
332
|
+
message,
|
|
333
|
+
) ||
|
|
334
|
+
/forces?\s+tool\s+use.*?(not\s+compatible|incompatible|not\s+supported)/is.test(message) ||
|
|
335
|
+
/does\s+not\s+support\s+forced\s+tool[_\s-]?choices?/is.test(message) ||
|
|
336
|
+
/tool[_\s-]?choices?\s+['"`][^'"`\r\n]+['"`]\s+not\s+found\s+in\s+['"`]tools['"`]\s+parameter\b/is.test(message)
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Detects Codex's statusless SSE rejection for a named function tool choice.
|
|
341
|
+
* This is intentionally separate from the shared HTTP-400 classifier.
|
|
342
|
+
*/
|
|
343
|
+
export function isCodexStatuslessNamedToolChoiceNotFoundError(
|
|
344
|
+
error: unknown,
|
|
345
|
+
forcedToolName: string | undefined,
|
|
346
|
+
sentToolNames: readonly string[],
|
|
347
|
+
): boolean {
|
|
348
|
+
if (
|
|
349
|
+
extractHttpStatusFromError(error) !== undefined ||
|
|
350
|
+
extractProviderErrorCode(error) !== "invalid_request_error" ||
|
|
351
|
+
!forcedToolName
|
|
352
|
+
) {
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
const match =
|
|
356
|
+
/^Tool choice '([^']+)' not found in 'tools' parameter\.$/.exec(errorMessage(error)) ??
|
|
357
|
+
/^Codex error event: Tool choice '([^']+)' not found in 'tools' parameter\. \(code=invalid_request_error\)$/.exec(
|
|
358
|
+
errorMessage(error),
|
|
359
|
+
);
|
|
360
|
+
return match?.[1] === forcedToolName && sentToolNames.includes(forcedToolName);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
function extractProviderErrorCode(error: unknown): string | undefined {
|
|
364
|
+
if (!error || typeof error !== "object") return undefined;
|
|
365
|
+
const code = (error as { code?: unknown }).code;
|
|
366
|
+
return typeof code === "string" ? code : undefined;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export type { ToolChoiceCompat, ToolChoiceSupport, ToolChoiceSupportSource } from "../types";
|
|
370
|
+
|
|
371
|
+
export interface ResolveToolChoiceResult {
|
|
372
|
+
requestedChoice: ToolChoice | undefined;
|
|
373
|
+
requestedLevel: ToolChoiceSupport;
|
|
374
|
+
resolvedChoice: ToolChoice | undefined;
|
|
375
|
+
resolvedLevel: ToolChoiceSupport;
|
|
376
|
+
support: ToolChoiceSupport;
|
|
377
|
+
supportSource: ToolChoiceSupportSource;
|
|
378
|
+
degraded: boolean;
|
|
379
|
+
reason?: string;
|
|
380
|
+
registryKey: string;
|
|
381
|
+
targetToolName?: string;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function requestedToolChoiceLevel(requested: ToolChoice | undefined): {
|
|
385
|
+
requestedLevel: ToolChoiceSupport;
|
|
386
|
+
targetToolName?: string;
|
|
387
|
+
} {
|
|
388
|
+
if (requested === undefined || requested === "auto") return { requestedLevel: "auto" };
|
|
389
|
+
if (requested === "none") return { requestedLevel: "none" };
|
|
390
|
+
if (requested === "any" || requested === "required") return { requestedLevel: "required" };
|
|
391
|
+
if ("name" in requested) return { requestedLevel: "named", targetToolName: requested.name };
|
|
392
|
+
return { requestedLevel: "named", targetToolName: requested.function.name };
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function errorMessage(error: unknown): string {
|
|
396
|
+
if (error instanceof Error) return error.message;
|
|
397
|
+
if (typeof error === "string") return error;
|
|
398
|
+
return String(error);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function safeHostname(baseUrl: string): string | undefined {
|
|
402
|
+
try {
|
|
403
|
+
return new URL(baseUrl).hostname;
|
|
404
|
+
} catch {
|
|
405
|
+
return undefined;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
function hydrateToolChoiceCapability(registryKey: string): void {
|
|
410
|
+
const now = currentTime();
|
|
411
|
+
const expiresAt = registryExpiresAt.get(registryKey);
|
|
412
|
+
if (expiresAt !== undefined && now < expiresAt) return;
|
|
413
|
+
registry.delete(registryKey);
|
|
414
|
+
registryExpiresAt.delete(registryKey);
|
|
415
|
+
const hydrated = withCapabilityCache(database => {
|
|
416
|
+
const digest = capabilityKeyDigest(registryKey);
|
|
417
|
+
const row = database
|
|
418
|
+
.query("SELECT max_support, support_rank, observed_at FROM tool_choice_capabilities WHERE key_digest = ?")
|
|
419
|
+
.get(digest) as { max_support?: unknown; support_rank?: unknown; observed_at?: unknown } | null;
|
|
420
|
+
if (!row) return false;
|
|
421
|
+
if (
|
|
422
|
+
!isToolChoiceSupport(row.max_support) ||
|
|
423
|
+
row.support_rank !== supportRank[row.max_support] ||
|
|
424
|
+
!isValidObservedAt(row.observed_at, now)
|
|
425
|
+
) {
|
|
426
|
+
beforeMalformedDeleteForTests?.();
|
|
427
|
+
database.run(
|
|
428
|
+
"DELETE FROM tool_choice_capabilities WHERE key_digest = ? AND max_support = ? AND support_rank = ? AND observed_at = ?",
|
|
429
|
+
[
|
|
430
|
+
digest,
|
|
431
|
+
typeof row.max_support === "string" ? row.max_support : String(row.max_support),
|
|
432
|
+
typeof row.support_rank === "number" ? row.support_rank : -1,
|
|
433
|
+
typeof row.observed_at === "number" ? row.observed_at : -1,
|
|
434
|
+
],
|
|
435
|
+
);
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
if (now - row.observed_at >= CACHE_TTL_MS) {
|
|
439
|
+
beforeExpiredDeleteForTests?.();
|
|
440
|
+
database.run("DELETE FROM tool_choice_capabilities WHERE key_digest = ? AND observed_at = ?", [
|
|
441
|
+
digest,
|
|
442
|
+
row.observed_at,
|
|
443
|
+
]);
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
registry.set(registryKey, row.max_support);
|
|
447
|
+
registryExpiresAt.set(registryKey, row.observed_at + CACHE_TTL_MS);
|
|
448
|
+
return true;
|
|
449
|
+
});
|
|
450
|
+
if (hydrated === false && !registryExpiresAt.has(registryKey)) {
|
|
451
|
+
registryExpiresAt.set(registryKey, now + EMPTY_CACHE_TTL_MS);
|
|
452
|
+
}
|
|
453
|
+
pruneRegistry(now);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function persistToolChoiceCapability(
|
|
457
|
+
registryKey: string,
|
|
458
|
+
maxSupport: ToolChoiceSupport,
|
|
459
|
+
): { support: ToolChoiceSupport; observedAt: number } | undefined {
|
|
460
|
+
return withCapabilityCache(database => {
|
|
461
|
+
const write = database.transaction(() => {
|
|
462
|
+
const digest = capabilityKeyDigest(registryKey);
|
|
463
|
+
const observedAt = currentTime();
|
|
464
|
+
database.run(
|
|
465
|
+
"INSERT INTO tool_choice_capabilities (key_digest, max_support, support_rank, observed_at) VALUES (?, ?, ?, ?) ON CONFLICT(key_digest) DO UPDATE SET max_support = excluded.max_support, support_rank = excluded.support_rank, observed_at = excluded.observed_at WHERE excluded.support_rank <= tool_choice_capabilities.support_rank",
|
|
466
|
+
[digest, maxSupport, supportRank[maxSupport], observedAt],
|
|
467
|
+
);
|
|
468
|
+
database.run(
|
|
469
|
+
"DELETE FROM tool_choice_capabilities WHERE key_digest NOT IN (SELECT key_digest FROM tool_choice_capabilities ORDER BY observed_at DESC, key_digest DESC LIMIT ?)",
|
|
470
|
+
[CACHE_MAX_ENTRIES],
|
|
471
|
+
);
|
|
472
|
+
const row = database
|
|
473
|
+
.query("SELECT max_support, observed_at FROM tool_choice_capabilities WHERE key_digest = ?")
|
|
474
|
+
.get(digest) as { max_support?: unknown; observed_at?: unknown } | null;
|
|
475
|
+
return row && isToolChoiceSupport(row.max_support) && typeof row.observed_at === "number"
|
|
476
|
+
? { support: row.max_support, observedAt: row.observed_at }
|
|
477
|
+
: undefined;
|
|
478
|
+
});
|
|
479
|
+
return write();
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function withCapabilityCache<T>(operation: (database: Database) => T): T | undefined {
|
|
484
|
+
if (process.env.NODE_ENV === "test" && cachePathOverride === undefined) return;
|
|
485
|
+
const cachePath = cachePathOverride ?? getToolChoiceCapabilityCachePath();
|
|
486
|
+
let openedFileSize: number | undefined;
|
|
487
|
+
try {
|
|
488
|
+
fs.mkdirSync(path.dirname(cachePath), { recursive: true, mode: 0o700 });
|
|
489
|
+
try {
|
|
490
|
+
openedFileSize = fs.statSync(cachePath).size;
|
|
491
|
+
} catch {
|
|
492
|
+
// File does not exist yet (first run); nothing to identity-check on retirement.
|
|
493
|
+
}
|
|
494
|
+
const database = openCapabilityCache(cachePath);
|
|
495
|
+
try {
|
|
496
|
+
try {
|
|
497
|
+
fs.chmodSync(cachePath, 0o600);
|
|
498
|
+
} catch {
|
|
499
|
+
// Cache access remains fail-open on filesystems without POSIX modes.
|
|
500
|
+
}
|
|
501
|
+
const simulatedError = simulateCacheOperationErrorForTests?.();
|
|
502
|
+
if (simulatedError) throw simulatedError;
|
|
503
|
+
return operation(database);
|
|
504
|
+
} finally {
|
|
505
|
+
database.close();
|
|
506
|
+
}
|
|
507
|
+
} catch (error) {
|
|
508
|
+
logger.debug("Tool-choice capability cache unavailable", {
|
|
509
|
+
cachePath: path.basename(cachePath),
|
|
510
|
+
error: error instanceof Error ? error.message : String(error),
|
|
511
|
+
});
|
|
512
|
+
if (isCorruptCapabilityCacheError(error)) {
|
|
513
|
+
beforeCorruptRetireForTests?.();
|
|
514
|
+
retireCorruptCapabilityCache(cachePath, openedFileSize);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function openCapabilityCache(cachePath: string): Database {
|
|
520
|
+
onCacheOpenForTests?.();
|
|
521
|
+
const database = new Database(cachePath, { create: true, strict: true });
|
|
522
|
+
try {
|
|
523
|
+
database.run("PRAGMA busy_timeout = 3000");
|
|
524
|
+
database.run("PRAGMA journal_mode = WAL");
|
|
525
|
+
database.run("PRAGMA synchronous = FULL");
|
|
526
|
+
const initialize = database.transaction(() => {
|
|
527
|
+
const version = database.query("PRAGMA user_version").get() as { user_version?: number } | null;
|
|
528
|
+
const schemaVersion = version?.user_version ?? 0;
|
|
529
|
+
if (schemaVersion === 0) {
|
|
530
|
+
database.run(`
|
|
531
|
+
CREATE TABLE IF NOT EXISTS tool_choice_capabilities (
|
|
532
|
+
key_digest TEXT PRIMARY KEY NOT NULL,
|
|
533
|
+
max_support TEXT NOT NULL,
|
|
534
|
+
support_rank INTEGER NOT NULL,
|
|
535
|
+
observed_at INTEGER NOT NULL
|
|
536
|
+
) STRICT
|
|
537
|
+
`);
|
|
538
|
+
assertCapabilityCacheSchema(database);
|
|
539
|
+
database.run(`PRAGMA user_version = ${CACHE_SCHEMA_VERSION}`);
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
if (schemaVersion !== CACHE_SCHEMA_VERSION) {
|
|
543
|
+
throw new CapabilityCacheCorruptionError("unsupported cache schema version");
|
|
544
|
+
}
|
|
545
|
+
assertCapabilityCacheSchema(database);
|
|
546
|
+
});
|
|
547
|
+
initialize();
|
|
548
|
+
return database;
|
|
549
|
+
} catch (error) {
|
|
550
|
+
database.close();
|
|
551
|
+
throw error;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function assertCapabilityCacheSchema(database: Database): void {
|
|
556
|
+
const columns = database.query("PRAGMA table_info(tool_choice_capabilities)").all() as Array<{
|
|
557
|
+
name?: unknown;
|
|
558
|
+
type?: unknown;
|
|
559
|
+
notnull?: unknown;
|
|
560
|
+
pk?: unknown;
|
|
561
|
+
}>;
|
|
562
|
+
const actual = columns.map(column => [column.name, column.type, column.notnull, column.pk]);
|
|
563
|
+
const expected = [
|
|
564
|
+
["key_digest", "TEXT", 1, 1],
|
|
565
|
+
["max_support", "TEXT", 1, 0],
|
|
566
|
+
["support_rank", "INTEGER", 1, 0],
|
|
567
|
+
["observed_at", "INTEGER", 1, 0],
|
|
568
|
+
];
|
|
569
|
+
if (JSON.stringify(actual) !== JSON.stringify(expected)) {
|
|
570
|
+
throw new CapabilityCacheCorruptionError("invalid cache schema");
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
class CapabilityCacheCorruptionError extends Error {}
|
|
575
|
+
|
|
576
|
+
function isCorruptCapabilityCacheError(error: unknown): boolean {
|
|
577
|
+
if (error instanceof CapabilityCacheCorruptionError) return true;
|
|
578
|
+
if (!error || typeof error !== "object") return false;
|
|
579
|
+
const code = (error as { code?: unknown }).code;
|
|
580
|
+
return code === "SQLITE_CORRUPT" || code === "SQLITE_NOTADB";
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* Removes a confirmed-corrupt cache file and its WAL/SHM siblings. The file
|
|
585
|
+
* size captured before the corrupt open (`openedFileSize`) is checked before
|
|
586
|
+
* unlinking so a concurrently recreated valid replacement database with a
|
|
587
|
+
* different file size is never deleted.
|
|
588
|
+
*/
|
|
589
|
+
function retireCorruptCapabilityCache(cachePath: string, openedFileSize?: number): void {
|
|
590
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
591
|
+
const target = `${cachePath}${suffix}`;
|
|
592
|
+
try {
|
|
593
|
+
if (openedFileSize !== undefined && suffix === "") {
|
|
594
|
+
const stat = fs.statSync(target);
|
|
595
|
+
if (stat.size !== openedFileSize) continue;
|
|
596
|
+
}
|
|
597
|
+
fs.rmSync(target, { force: true });
|
|
598
|
+
} catch {
|
|
599
|
+
// A best-effort cache reset must never break provider fallback behavior.
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
function capabilityKeyDigest(registryKey: string): string {
|
|
605
|
+
return crypto.createHash("sha256").update(registryKey).digest("hex");
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
function isToolChoiceSupport(value: unknown): value is ToolChoiceSupport {
|
|
609
|
+
return value === "none" || value === "auto" || value === "required" || value === "named";
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
function isValidObservedAt(value: unknown, now: number): value is number {
|
|
613
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && value <= now;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
function currentTime(): number {
|
|
617
|
+
return nowForTests?.() ?? Date.now();
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
function pruneRegistry(now: number): void {
|
|
621
|
+
for (const [key, expiresAt] of registryExpiresAt) {
|
|
622
|
+
if (expiresAt <= now) {
|
|
623
|
+
registryExpiresAt.delete(key);
|
|
624
|
+
registry.delete(key);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
while (registryExpiresAt.size > REGISTRY_MAX_ENTRIES) {
|
|
628
|
+
const oldestKey = registryExpiresAt.keys().next().value;
|
|
629
|
+
if (typeof oldestKey !== "string") break;
|
|
630
|
+
registryExpiresAt.delete(oldestKey);
|
|
631
|
+
registry.delete(oldestKey);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for mapping unified ToolChoice to provider-specific formats.
|
|
3
|
+
*/
|
|
4
|
+
import type { ToolChoice } from "../types";
|
|
5
|
+
/** OpenAI Completions API tool choice format */
|
|
6
|
+
export type OpenAICompletionsToolChoice = "auto" | "none" | "required" | {
|
|
7
|
+
type: "function";
|
|
8
|
+
function: {
|
|
9
|
+
name: string;
|
|
10
|
+
};
|
|
11
|
+
} | undefined;
|
|
12
|
+
/** OpenAI Responses API tool choice format (flat structure) */
|
|
13
|
+
export type OpenAIResponsesToolChoice = "auto" | "none" | "required" | {
|
|
14
|
+
type: "function";
|
|
15
|
+
name: string;
|
|
16
|
+
} | {
|
|
17
|
+
type: "custom";
|
|
18
|
+
name: string;
|
|
19
|
+
} | undefined;
|
|
20
|
+
/** Anthropic-compatible tool choice format */
|
|
21
|
+
export type AnthropicToolChoice = "auto" | "none" | "any" | {
|
|
22
|
+
type: "tool";
|
|
23
|
+
name: string;
|
|
24
|
+
} | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Map unified ToolChoice to OpenAI Completions API format.
|
|
27
|
+
* - "any" → "required"
|
|
28
|
+
* - { type: "tool", name } → { type: "function", function: { name } }
|
|
29
|
+
*/
|
|
30
|
+
export declare function mapToOpenAICompletionsToolChoice(choice?: ToolChoice): OpenAICompletionsToolChoice;
|
|
31
|
+
/**
|
|
32
|
+
* Returns true when an OpenAI-completions `tool_choice` value forces a tool
|
|
33
|
+
* call (`"required"` or a function-name pin), as opposed to leaving it open
|
|
34
|
+
* (`"auto"`, `"none"`, or unset). Accepts `unknown` because the param shape
|
|
35
|
+
* pulled from the OpenAI SDK (`ChatCompletionToolChoiceOption`) widens with
|
|
36
|
+
* each release; this check only needs the open/forced bit.
|
|
37
|
+
*/
|
|
38
|
+
export declare function isForcedToolChoice(choice: unknown): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Map unified ToolChoice to OpenAI Responses API format.
|
|
41
|
+
* - "any" → "required"
|
|
42
|
+
* - { type: "tool", name } → { type: "function", name } (flat structure)
|
|
43
|
+
*/
|
|
44
|
+
export declare function mapToOpenAIResponsesToolChoice(choice?: ToolChoice): OpenAIResponsesToolChoice;
|
|
45
|
+
/**
|
|
46
|
+
* Map unified ToolChoice to Anthropic-compatible format.
|
|
47
|
+
* - "required" → "any"
|
|
48
|
+
* - { type: "function", ... } → { type: "tool", name }
|
|
49
|
+
*/
|
|
50
|
+
export declare function mapToAnthropicToolChoice(choice?: ToolChoice): AnthropicToolChoice;
|