@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
package/src/utils.d.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { ResponseInput } from "openai/resources/responses/responses";
|
|
2
|
+
import type { CacheRetention, OpenAIResponsesHistoryPayload, ProviderPayload } from "./types";
|
|
3
|
+
export { isRecord } from "@vib-rato/utils";
|
|
4
|
+
export declare function normalizeSystemPrompts(systemPrompt: readonly string[] | string | undefined | null): string[];
|
|
5
|
+
export declare function sanitizeJsonStrings(value: unknown): unknown;
|
|
6
|
+
export declare function toNumber(value: unknown): number | undefined;
|
|
7
|
+
export declare function toPositiveNumber(value: unknown, fallback: number): number;
|
|
8
|
+
export declare function toBoolean(value: unknown): boolean | undefined;
|
|
9
|
+
export declare function normalizeToolCallId(id: string): string;
|
|
10
|
+
type ResponsesToolItemIdPrefix = "fc" | "ctc";
|
|
11
|
+
export declare function normalizeResponsesToolCallId(id: string, itemPrefix?: ResponsesToolItemIdPrefix): {
|
|
12
|
+
callId: string;
|
|
13
|
+
itemId: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Truncate an OpenAI Responses API item ID to 64 characters.
|
|
17
|
+
* IDs exceeding the limit are replaced with a hash-based ID using the given prefix.
|
|
18
|
+
*/
|
|
19
|
+
export declare function truncateResponseItemId(id: string, prefix: string): string;
|
|
20
|
+
export declare function sanitizeOpenAIResponsesHistoryItemsForReplay(items: Array<Record<string, unknown>>): ResponseInput;
|
|
21
|
+
/**
|
|
22
|
+
* Neutralize leaked OpenAI Harmony / control tokens (`<|channel|>`, `<|message|>`,
|
|
23
|
+
* `<|call|>`, `<|constrain|>`, `<|recipient|>`, `<|content|>`, ...) in replayed
|
|
24
|
+
* history text. A subagent whose tool-call channel degenerates can dump raw
|
|
25
|
+
* control-token scaffolding into its reply text; once that poisoned text lands in
|
|
26
|
+
* history the Codex / Responses endpoint rejects every subsequent request with
|
|
27
|
+
* `Request blocked (code=invalid_prompt)`, permanently wedging the session because
|
|
28
|
+
* the offending item is re-sent on each turn. Insert a zero-width space after `<`
|
|
29
|
+
* so the delimiter can no longer be tokenized as a reserved control token while the
|
|
30
|
+
* text stays human-readable.
|
|
31
|
+
*
|
|
32
|
+
* The pattern matches the two control-token shapes only, so ordinary text and pipe
|
|
33
|
+
* syntax is left untouched:
|
|
34
|
+
* - simple form `<|ident|>` — a leading run of identifier chars then `|>`; and
|
|
35
|
+
* - header form `<|role to=recipient|>` — a known Harmony role
|
|
36
|
+
* (`system`/`developer`/`user`/`assistant`/`tool`) followed by a single
|
|
37
|
+
* recipient assignment `to=<recipient>` whose value is an unbounded run of
|
|
38
|
+
* non-delimiter, non-whitespace chars (so long MCP/custom tool recipients like
|
|
39
|
+
* `to=functions.<long.name>` are covered).
|
|
40
|
+
* The header branch is deliberately scoped to the known role + `to=` recipient
|
|
41
|
+
* grammar rather than an arbitrary `key=value`, so request-boundary sanitization
|
|
42
|
+
* never rewrites non-control delimiter text such as `<|foo bar=baz|>`. A single-line
|
|
43
|
+
* body (no `\n`) and the required leading identifier char also leave compact
|
|
44
|
+
* pipe/operator syntax alone — e.g. F# `value <| f |> g` (space after `<|`),
|
|
45
|
+
* `sum<|a+b|>c` (punctuation body), and `<|foo bar|>` (no assignment) never match.
|
|
46
|
+
* The simple branch is a strict superset of the original identifier-only pattern:
|
|
47
|
+
* every marker the old regex caught still matches.
|
|
48
|
+
*/
|
|
49
|
+
export declare function neutralizeReservedControlTokens(text: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* Shape-tolerant classifier for the poisoned-history rejection that wedges
|
|
52
|
+
* gpt-5.6 sessions: `Request blocked (code=invalid_prompt)`. Accepts a raw
|
|
53
|
+
* provider error, an assistant message, or any object carrying a
|
|
54
|
+
* `providerCode` / `transportFailure` / `errorMessage` field, and returns true
|
|
55
|
+
* when the failure is the deterministic `invalid_prompt` content fault rather
|
|
56
|
+
* than a transient upstream error. This is the single shared contract the
|
|
57
|
+
* provider transports and the session-level circuit breaker key on so the
|
|
58
|
+
* classification is explicit (not inferred from a catch-all bucket) and
|
|
59
|
+
* uniformly testable across transports.
|
|
60
|
+
*/
|
|
61
|
+
export declare function isInvalidPromptError(input: unknown): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Shape-tolerant classifier for the DeepSeek-family reasoning-content replay
|
|
64
|
+
* rejection: "The `reasoning_content` in the thinking mode must be passed back
|
|
65
|
+
* to the API." DeepSeek V4 (and reasoning-capable siblings reached through any
|
|
66
|
+
* OpenAI-compatible proxy) 400 every follow-up turn once a prior assistant turn
|
|
67
|
+
* carried reasoning the proxy stripped to an empty `encrypted_content` /
|
|
68
|
+
* `reasoning_content`. Resending the identical history re-triggers it, so naive
|
|
69
|
+
* session auto-retry just burns the budget — it needs the same bounded
|
|
70
|
+
* repair-and-resend contract as the `invalid_prompt` poisoned-history breaker.
|
|
71
|
+
*
|
|
72
|
+
* Accepts a raw provider error, an assistant message, or any object carrying an
|
|
73
|
+
* `errorMessage` field (the agent-loop circuit breaker keys on this).
|
|
74
|
+
*/
|
|
75
|
+
export declare function isReasoningContentReplayError(input: unknown): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Remove Responses-API `reasoning` items whose `encrypted_content` is missing or
|
|
78
|
+
* empty from an outgoing history payload. DeepSeek rejects replay of reasoning
|
|
79
|
+
* whose encrypted blob a proxy stripped to `""`; dropping those items lets the
|
|
80
|
+
* model re-reason on the next turn instead of re-triggering a deterministic 400.
|
|
81
|
+
* Non-reasoning items (text, function_call, function_call_output, ...) are kept
|
|
82
|
+
* verbatim so tool-use pairing and message order are preserved. Returns whether
|
|
83
|
+
* any item was actually removed — the circuit breaker uses this to decide
|
|
84
|
+
* between a single repaired resend (removed) and immediate fail-fast (unchanged).
|
|
85
|
+
*/
|
|
86
|
+
export declare function stripUnusableReasoningItems(items: Array<Record<string, unknown>>): {
|
|
87
|
+
result: Array<Record<string, unknown>>;
|
|
88
|
+
removed: number;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Neutralize leaked reserved control tokens across every string in an outgoing
|
|
92
|
+
* Responses `input` array. This is the request-boundary complement to the
|
|
93
|
+
* replay-history sanitizer: leaked Harmony markers (`<|channel|>analysis`, ...)
|
|
94
|
+
* can enter the payload from assistant reasoning summaries, live-converted
|
|
95
|
+
* message/tool-output text, or user-authored content — not just replayed
|
|
96
|
+
* history — and every gpt-5.6 request that carries one is rejected with
|
|
97
|
+
* `Request blocked (code=invalid_prompt)`. Walking every string (rather than an
|
|
98
|
+
* item-type allowlist) guarantees no leak source is missed as item shapes
|
|
99
|
+
* evolve; the zero-width-space insertion is idempotent (`<\u200b|` no longer
|
|
100
|
+
* matches `<|`) and keeps the text human-readable.
|
|
101
|
+
*/
|
|
102
|
+
export declare function neutralizeResponsesInputControlTokens<T>(items: readonly T[]): T[];
|
|
103
|
+
export declare function createOpenAIResponsesHistoryPayload(provider: string, items: Array<Record<string, unknown>>, incremental?: boolean): OpenAIResponsesHistoryPayload;
|
|
104
|
+
export declare function getOpenAIResponsesHistoryPayload(providerPayload: ProviderPayload | undefined, currentProvider: string, fallbackProvider?: string): OpenAIResponsesHistoryPayload | undefined;
|
|
105
|
+
export declare function getOpenAIResponsesHistoryItems(providerPayload: ProviderPayload | undefined, currentProvider: string, fallbackProvider?: string): Array<Record<string, unknown>> | undefined;
|
|
106
|
+
/**
|
|
107
|
+
* Resolve cache retention preference.
|
|
108
|
+
*
|
|
109
|
+
* Resolution order: explicit request value → `VIB_CACHE_RETENTION` →
|
|
110
|
+
* legacy `PI_CACHE_RETENTION` → `fallback`. Both env vars act as explicit
|
|
111
|
+
* opt-in (`"long"`) or opt-out (any other value) so a provider-specific
|
|
112
|
+
* `fallback` only applies when nothing else is configured. `fallback`
|
|
113
|
+
* defaults to `"short"` to preserve the historical behaviour for callers
|
|
114
|
+
* that don't pass one.
|
|
115
|
+
*/
|
|
116
|
+
export declare function resolveCacheRetention(cacheRetention?: CacheRetention, fallback?: CacheRetention): CacheRetention;
|
|
117
|
+
export declare function isAnthropicOAuthToken(key: string): boolean;
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
import { $env } from "@vib-rato/utils";
|
|
2
|
+
import type { ResponseInput } from "openai/resources/responses/responses";
|
|
3
|
+
import type { CacheRetention, OpenAIResponsesHistoryPayload, ProviderPayload } from "./types";
|
|
4
|
+
|
|
5
|
+
type OpenAIResponsesReplayItem = ResponseInput[number];
|
|
6
|
+
|
|
7
|
+
export { isRecord } from "@vib-rato/utils";
|
|
8
|
+
export function normalizeSystemPrompts(systemPrompt: readonly string[] | string | undefined | null): string[] {
|
|
9
|
+
if (systemPrompt === undefined || systemPrompt === null) return [];
|
|
10
|
+
const prompts = Array.isArray(systemPrompt) ? systemPrompt : typeof systemPrompt === "string" ? [systemPrompt] : [];
|
|
11
|
+
return prompts.map(prompt => prompt.toWellFormed()).filter(prompt => prompt.length > 0);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function sanitizeJsonStrings(value: unknown): unknown {
|
|
15
|
+
return sanitizeJsonStringsInner(value, new WeakMap<object, unknown>());
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function sanitizeJsonStringsInner(value: unknown, seen: WeakMap<object, unknown>): unknown {
|
|
19
|
+
if (typeof value === "string") return value.toWellFormed();
|
|
20
|
+
if (!value || typeof value !== "object") return value;
|
|
21
|
+
|
|
22
|
+
const cached = seen.get(value);
|
|
23
|
+
if (cached !== undefined) return cached;
|
|
24
|
+
|
|
25
|
+
if (Array.isArray(value)) {
|
|
26
|
+
const sanitized: unknown[] = [];
|
|
27
|
+
seen.set(value, sanitized);
|
|
28
|
+
for (const item of value) {
|
|
29
|
+
sanitized.push(sanitizeJsonStringsInner(item, seen));
|
|
30
|
+
}
|
|
31
|
+
return sanitized;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const sanitized: Record<string, unknown> = {};
|
|
35
|
+
seen.set(value, sanitized);
|
|
36
|
+
for (const [key, nestedValue] of Object.entries(value)) {
|
|
37
|
+
sanitized[key.toWellFormed()] = sanitizeJsonStringsInner(nestedValue, seen);
|
|
38
|
+
}
|
|
39
|
+
return sanitized;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function toNumber(value: unknown): number | undefined {
|
|
43
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
44
|
+
if (typeof value === "string" && value.trim()) {
|
|
45
|
+
const parsed = Number(value);
|
|
46
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function toPositiveNumber(value: unknown, fallback: number): number {
|
|
52
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
53
|
+
return fallback;
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function toBoolean(value: unknown): boolean | undefined {
|
|
59
|
+
return typeof value === "boolean" ? value : undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function normalizeToolCallId(id: string): string {
|
|
63
|
+
const sanitized = id.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
64
|
+
return sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
type ResponsesToolItemIdPrefix = "fc" | "ctc";
|
|
68
|
+
|
|
69
|
+
export function normalizeResponsesToolCallId(
|
|
70
|
+
id: string,
|
|
71
|
+
itemPrefix: ResponsesToolItemIdPrefix = "fc",
|
|
72
|
+
): { callId: string; itemId: string } {
|
|
73
|
+
const [callId, itemId] = id.split("|");
|
|
74
|
+
if (callId && itemId) {
|
|
75
|
+
const normalizedCallId = truncateResponseItemId(callId, getIdPrefix(callId, "call"));
|
|
76
|
+
const normalizedItemId = normalizeResponsesItemId(itemId, itemPrefix);
|
|
77
|
+
return { callId: normalizedCallId, itemId: normalizedItemId };
|
|
78
|
+
}
|
|
79
|
+
const hash = Bun.hash(id).toString(36);
|
|
80
|
+
const normalizedCallId = id.startsWith("call_") ? truncateResponseItemId(id, "call") : `call_${hash}`;
|
|
81
|
+
return { callId: normalizedCallId, itemId: `${itemPrefix}_${hash}` };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function getIdPrefix(id: string, fallback: string): string {
|
|
85
|
+
const prefix = id.match(/^([a-zA-Z][a-zA-Z0-9]*)_/)?.[1];
|
|
86
|
+
return prefix || fallback;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function getExplicitIdPrefix(id: string): string | undefined {
|
|
90
|
+
return id.match(/^([a-zA-Z][a-zA-Z0-9]*)_/)?.[1];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function normalizeResponsesItemId(itemId: string, fallbackPrefix: ResponsesToolItemIdPrefix): string {
|
|
94
|
+
const prefix = getExplicitIdPrefix(itemId);
|
|
95
|
+
const isAllowedPrefix = prefix
|
|
96
|
+
? fallbackPrefix === "ctc"
|
|
97
|
+
? prefix === "ctc"
|
|
98
|
+
: prefix === "fc" || prefix === "fcr"
|
|
99
|
+
: false;
|
|
100
|
+
if (!prefix || !isAllowedPrefix) {
|
|
101
|
+
return `${fallbackPrefix}_${Bun.hash(itemId).toString(36)}`;
|
|
102
|
+
}
|
|
103
|
+
return truncateResponseItemId(itemId, prefix);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Truncate an OpenAI Responses API item ID to 64 characters.
|
|
108
|
+
* IDs exceeding the limit are replaced with a hash-based ID using the given prefix.
|
|
109
|
+
*/
|
|
110
|
+
export function truncateResponseItemId(id: string, prefix: string): string {
|
|
111
|
+
if (id.length <= 64) return id;
|
|
112
|
+
return `${prefix}_${Bun.hash(id).toString(36)}`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function sanitizeOpenAIResponsesHistoryItemsForReplay(items: Array<Record<string, unknown>>): ResponseInput {
|
|
116
|
+
const normalizedCallIds = new Map<string, string>();
|
|
117
|
+
return items.flatMap(item => {
|
|
118
|
+
const sanitized = sanitizeOpenAIResponsesHistoryItemForReplay(item, normalizedCallIds);
|
|
119
|
+
return sanitized ? [sanitized] : [];
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
const RESERVED_CONTROL_TOKEN_RE =
|
|
123
|
+
/<\|(?=(?:[A-Za-z0-9_]+|(?:system|developer|user|assistant|tool)[ \t]+to=[^\s<>|]+)\|>)/g;
|
|
124
|
+
/**
|
|
125
|
+
* Neutralize leaked OpenAI Harmony / control tokens (`<|channel|>`, `<|message|>`,
|
|
126
|
+
* `<|call|>`, `<|constrain|>`, `<|recipient|>`, `<|content|>`, ...) in replayed
|
|
127
|
+
* history text. A subagent whose tool-call channel degenerates can dump raw
|
|
128
|
+
* control-token scaffolding into its reply text; once that poisoned text lands in
|
|
129
|
+
* history the Codex / Responses endpoint rejects every subsequent request with
|
|
130
|
+
* `Request blocked (code=invalid_prompt)`, permanently wedging the session because
|
|
131
|
+
* the offending item is re-sent on each turn. Insert a zero-width space after `<`
|
|
132
|
+
* so the delimiter can no longer be tokenized as a reserved control token while the
|
|
133
|
+
* text stays human-readable.
|
|
134
|
+
*
|
|
135
|
+
* The pattern matches the two control-token shapes only, so ordinary text and pipe
|
|
136
|
+
* syntax is left untouched:
|
|
137
|
+
* - simple form `<|ident|>` — a leading run of identifier chars then `|>`; and
|
|
138
|
+
* - header form `<|role to=recipient|>` — a known Harmony role
|
|
139
|
+
* (`system`/`developer`/`user`/`assistant`/`tool`) followed by a single
|
|
140
|
+
* recipient assignment `to=<recipient>` whose value is an unbounded run of
|
|
141
|
+
* non-delimiter, non-whitespace chars (so long MCP/custom tool recipients like
|
|
142
|
+
* `to=functions.<long.name>` are covered).
|
|
143
|
+
* The header branch is deliberately scoped to the known role + `to=` recipient
|
|
144
|
+
* grammar rather than an arbitrary `key=value`, so request-boundary sanitization
|
|
145
|
+
* never rewrites non-control delimiter text such as `<|foo bar=baz|>`. A single-line
|
|
146
|
+
* body (no `\n`) and the required leading identifier char also leave compact
|
|
147
|
+
* pipe/operator syntax alone — e.g. F# `value <| f |> g` (space after `<|`),
|
|
148
|
+
* `sum<|a+b|>c` (punctuation body), and `<|foo bar|>` (no assignment) never match.
|
|
149
|
+
* The simple branch is a strict superset of the original identifier-only pattern:
|
|
150
|
+
* every marker the old regex caught still matches.
|
|
151
|
+
*/
|
|
152
|
+
export function neutralizeReservedControlTokens(text: string): string {
|
|
153
|
+
if (!text.includes("<|")) return text;
|
|
154
|
+
return text.replace(RESERVED_CONTROL_TOKEN_RE, "<\u200b|");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Shape-tolerant classifier for the poisoned-history rejection that wedges
|
|
159
|
+
* gpt-5.6 sessions: `Request blocked (code=invalid_prompt)`. Accepts a raw
|
|
160
|
+
* provider error, an assistant message, or any object carrying a
|
|
161
|
+
* `providerCode` / `transportFailure` / `errorMessage` field, and returns true
|
|
162
|
+
* when the failure is the deterministic `invalid_prompt` content fault rather
|
|
163
|
+
* than a transient upstream error. This is the single shared contract the
|
|
164
|
+
* provider transports and the session-level circuit breaker key on so the
|
|
165
|
+
* classification is explicit (not inferred from a catch-all bucket) and
|
|
166
|
+
* uniformly testable across transports.
|
|
167
|
+
*/
|
|
168
|
+
export function isInvalidPromptError(input: unknown): boolean {
|
|
169
|
+
if (!input) return false;
|
|
170
|
+
if (typeof input === "string") return INVALID_PROMPT_MESSAGE_RE.test(input);
|
|
171
|
+
if (typeof input !== "object") return false;
|
|
172
|
+
const value = input as {
|
|
173
|
+
providerCode?: unknown;
|
|
174
|
+
code?: unknown;
|
|
175
|
+
errorMessage?: unknown;
|
|
176
|
+
message?: unknown;
|
|
177
|
+
transportFailure?: { providerCode?: unknown; code?: unknown };
|
|
178
|
+
error?: { code?: unknown };
|
|
179
|
+
};
|
|
180
|
+
const code =
|
|
181
|
+
asLowerString(value.providerCode) ??
|
|
182
|
+
asLowerString(value.code) ??
|
|
183
|
+
asLowerString(value.transportFailure?.providerCode) ??
|
|
184
|
+
asLowerString(value.transportFailure?.code) ??
|
|
185
|
+
asLowerString(value.error?.code);
|
|
186
|
+
if (code === "invalid_prompt") return true;
|
|
187
|
+
const message =
|
|
188
|
+
typeof value.errorMessage === "string"
|
|
189
|
+
? value.errorMessage
|
|
190
|
+
: typeof value.message === "string"
|
|
191
|
+
? value.message
|
|
192
|
+
: undefined;
|
|
193
|
+
return message !== undefined && INVALID_PROMPT_MESSAGE_RE.test(message);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const INVALID_PROMPT_MESSAGE_RE = /code=invalid[_ -]prompt|request blocked[^\n]*invalid[_ -]prompt/i;
|
|
197
|
+
|
|
198
|
+
function asLowerString(value: unknown): string | undefined {
|
|
199
|
+
return typeof value === "string" ? value.toLowerCase() : undefined;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Shape-tolerant classifier for the DeepSeek-family reasoning-content replay
|
|
204
|
+
* rejection: "The `reasoning_content` in the thinking mode must be passed back
|
|
205
|
+
* to the API." DeepSeek V4 (and reasoning-capable siblings reached through any
|
|
206
|
+
* OpenAI-compatible proxy) 400 every follow-up turn once a prior assistant turn
|
|
207
|
+
* carried reasoning the proxy stripped to an empty `encrypted_content` /
|
|
208
|
+
* `reasoning_content`. Resending the identical history re-triggers it, so naive
|
|
209
|
+
* session auto-retry just burns the budget — it needs the same bounded
|
|
210
|
+
* repair-and-resend contract as the `invalid_prompt` poisoned-history breaker.
|
|
211
|
+
*
|
|
212
|
+
* Accepts a raw provider error, an assistant message, or any object carrying an
|
|
213
|
+
* `errorMessage` field (the agent-loop circuit breaker keys on this).
|
|
214
|
+
*/
|
|
215
|
+
export function isReasoningContentReplayError(input: unknown): boolean {
|
|
216
|
+
if (!input) return false;
|
|
217
|
+
const message =
|
|
218
|
+
typeof input === "string"
|
|
219
|
+
? input
|
|
220
|
+
: input && typeof input === "object"
|
|
221
|
+
? ((input as { errorMessage?: unknown; message?: unknown }).errorMessage ??
|
|
222
|
+
(input as { message?: unknown }).message)
|
|
223
|
+
: undefined;
|
|
224
|
+
return typeof message === "string" && REASONING_CONTENT_REPLAY_MESSAGE_RE.test(message);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const REASONING_CONTENT_REPLAY_MESSAGE_RE =
|
|
228
|
+
/reasoning_content[\s\S]*must be passed back to the API|reasoning content[\s\S]*must be passed back to the API/i;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Remove Responses-API `reasoning` items whose `encrypted_content` is missing or
|
|
232
|
+
* empty from an outgoing history payload. DeepSeek rejects replay of reasoning
|
|
233
|
+
* whose encrypted blob a proxy stripped to `""`; dropping those items lets the
|
|
234
|
+
* model re-reason on the next turn instead of re-triggering a deterministic 400.
|
|
235
|
+
* Non-reasoning items (text, function_call, function_call_output, ...) are kept
|
|
236
|
+
* verbatim so tool-use pairing and message order are preserved. Returns whether
|
|
237
|
+
* any item was actually removed — the circuit breaker uses this to decide
|
|
238
|
+
* between a single repaired resend (removed) and immediate fail-fast (unchanged).
|
|
239
|
+
*/
|
|
240
|
+
export function stripUnusableReasoningItems(items: Array<Record<string, unknown>>): {
|
|
241
|
+
result: Array<Record<string, unknown>>;
|
|
242
|
+
removed: number;
|
|
243
|
+
} {
|
|
244
|
+
let removed = 0;
|
|
245
|
+
const result: Array<Record<string, unknown>> = [];
|
|
246
|
+
for (const item of items) {
|
|
247
|
+
if (item?.type === "reasoning") {
|
|
248
|
+
const encrypted = item.encrypted_content;
|
|
249
|
+
if (encrypted === undefined || encrypted === null || encrypted === "") {
|
|
250
|
+
removed++;
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
result.push(item);
|
|
255
|
+
}
|
|
256
|
+
return { result, removed };
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Neutralize leaked reserved control tokens across every string in an outgoing
|
|
260
|
+
* Responses `input` array. This is the request-boundary complement to the
|
|
261
|
+
* replay-history sanitizer: leaked Harmony markers (`<|channel|>analysis`, ...)
|
|
262
|
+
* can enter the payload from assistant reasoning summaries, live-converted
|
|
263
|
+
* message/tool-output text, or user-authored content — not just replayed
|
|
264
|
+
* history — and every gpt-5.6 request that carries one is rejected with
|
|
265
|
+
* `Request blocked (code=invalid_prompt)`. Walking every string (rather than an
|
|
266
|
+
* item-type allowlist) guarantees no leak source is missed as item shapes
|
|
267
|
+
* evolve; the zero-width-space insertion is idempotent (`<\u200b|` no longer
|
|
268
|
+
* matches `<|`) and keeps the text human-readable.
|
|
269
|
+
*/
|
|
270
|
+
export function neutralizeResponsesInputControlTokens<T>(items: readonly T[]): T[] {
|
|
271
|
+
return items.map(item => deepNeutralizeReservedControlTokens(item) as T);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function deepNeutralizeReservedControlTokens(value: unknown): unknown {
|
|
275
|
+
if (typeof value === "string") return neutralizeReservedControlTokens(value);
|
|
276
|
+
if (Array.isArray(value)) return value.map(deepNeutralizeReservedControlTokens);
|
|
277
|
+
if (value && typeof value === "object") {
|
|
278
|
+
const out: Record<string, unknown> = {};
|
|
279
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
280
|
+
out[key] = deepNeutralizeReservedControlTokens(nested);
|
|
281
|
+
}
|
|
282
|
+
return out;
|
|
283
|
+
}
|
|
284
|
+
return value;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function stringifyResponsesStringParamForReplay(value: unknown): string {
|
|
288
|
+
if (typeof value === "string") return neutralizeReservedControlTokens(value.toWellFormed());
|
|
289
|
+
try {
|
|
290
|
+
const encoded = JSON.stringify(value);
|
|
291
|
+
if (typeof encoded === "string") return neutralizeReservedControlTokens(encoded.toWellFormed());
|
|
292
|
+
} catch {
|
|
293
|
+
// Fall through to String().
|
|
294
|
+
}
|
|
295
|
+
return neutralizeReservedControlTokens(String(value ?? "").toWellFormed());
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function normalizeResponsesMessageTextForReplay(value: unknown): string {
|
|
299
|
+
if (typeof value === "string") return neutralizeReservedControlTokens(value.toWellFormed());
|
|
300
|
+
if (value && typeof value === "object") {
|
|
301
|
+
const nestedText = (value as { text?: unknown }).text;
|
|
302
|
+
if (typeof nestedText === "string") return neutralizeReservedControlTokens(nestedText.toWellFormed());
|
|
303
|
+
}
|
|
304
|
+
return stringifyResponsesStringParamForReplay(value);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
type ResponsesImageDetail = "auto" | "low" | "high";
|
|
308
|
+
|
|
309
|
+
interface NormalizedResponsesImageUrl {
|
|
310
|
+
readonly imageUrl: string;
|
|
311
|
+
readonly detail?: ResponsesImageDetail;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function isResponsesImageDetail(value: unknown): value is ResponsesImageDetail {
|
|
315
|
+
return value === "auto" || value === "low" || value === "high";
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function normalizeResponsesImageUrlForReplay(value: unknown): NormalizedResponsesImageUrl {
|
|
319
|
+
if (typeof value === "string") return { imageUrl: value.toWellFormed() };
|
|
320
|
+
if (value && typeof value === "object" && "url" in value && typeof value.url === "string") {
|
|
321
|
+
const detail = "detail" in value && isResponsesImageDetail(value.detail) ? value.detail : undefined;
|
|
322
|
+
return {
|
|
323
|
+
imageUrl: value.url.toWellFormed(),
|
|
324
|
+
...(detail ? { detail } : {}),
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
return { imageUrl: stringifyResponsesStringParamForReplay(value) };
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* OpenAI Responses `input_image.image_url` must be a fetchable HTTP(S) URL or an
|
|
332
|
+
* image data URI. Session resident-blob materialization may leave a human-readable
|
|
333
|
+
* placeholder like `[Session resident imageUrl blob missing: sha256:…; …]` in this
|
|
334
|
+
* field; replaying that string as `image_url` makes Codex reject the entire turn
|
|
335
|
+
* with `invalid_value` (#2924).
|
|
336
|
+
*/
|
|
337
|
+
function isProviderSafeResponsesImageUrl(value: string): boolean {
|
|
338
|
+
const url = value.trim();
|
|
339
|
+
if (url.length === 0) return false;
|
|
340
|
+
if (url.startsWith("https://") || url.startsWith("http://")) return true;
|
|
341
|
+
// Accept only image data URIs — other data: schemes are not valid image inputs.
|
|
342
|
+
if (url.startsWith("data:image/")) return true;
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function hasNonEmptyResponsesFileId(part: Record<string, unknown>): boolean {
|
|
347
|
+
return typeof part.file_id === "string" && part.file_id.trim().length > 0;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function sanitizeResponsesMessageContentForReplay(content: unknown): unknown {
|
|
351
|
+
if (typeof content === "string") return neutralizeReservedControlTokens(content.toWellFormed());
|
|
352
|
+
if (!Array.isArray(content)) return content;
|
|
353
|
+
const sanitizedContent: unknown[] = [];
|
|
354
|
+
for (const part of content) {
|
|
355
|
+
if (!part || typeof part !== "object") {
|
|
356
|
+
sanitizedContent.push(part);
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
const sanitizedPart = { ...(part as Record<string, unknown>) };
|
|
360
|
+
if ("text" in sanitizedPart) {
|
|
361
|
+
sanitizedPart.text = normalizeResponsesMessageTextForReplay(sanitizedPart.text);
|
|
362
|
+
}
|
|
363
|
+
if ("image_url" in sanitizedPart) {
|
|
364
|
+
const normalizedImageUrl = normalizeResponsesImageUrlForReplay(sanitizedPart.image_url);
|
|
365
|
+
if (!isProviderSafeResponsesImageUrl(normalizedImageUrl.imageUrl)) {
|
|
366
|
+
// Keep the part when a provider file_id can stand alone; otherwise drop
|
|
367
|
+
// only this image part so neighboring text/history still replays.
|
|
368
|
+
if (!hasNonEmptyResponsesFileId(sanitizedPart)) continue;
|
|
369
|
+
delete sanitizedPart.image_url;
|
|
370
|
+
if (sanitizedPart.type === "image_url") sanitizedPart.type = "input_image";
|
|
371
|
+
if ("detail" in sanitizedPart && !isResponsesImageDetail(sanitizedPart.detail)) {
|
|
372
|
+
delete sanitizedPart.detail;
|
|
373
|
+
}
|
|
374
|
+
sanitizedContent.push(sanitizedPart);
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
sanitizedPart.image_url = normalizedImageUrl.imageUrl;
|
|
378
|
+
if (sanitizedPart.type === "image_url") {
|
|
379
|
+
sanitizedPart.type = "input_image";
|
|
380
|
+
}
|
|
381
|
+
if (normalizedImageUrl.detail) {
|
|
382
|
+
sanitizedPart.detail = normalizedImageUrl.detail;
|
|
383
|
+
} else if ("detail" in sanitizedPart && !isResponsesImageDetail(sanitizedPart.detail)) {
|
|
384
|
+
delete sanitizedPart.detail;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
sanitizedContent.push(sanitizedPart);
|
|
388
|
+
}
|
|
389
|
+
return sanitizedContent;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function sanitizeResponsesStringFieldsForReplay(item: Record<string, unknown>): void {
|
|
393
|
+
if (item.type === "message") {
|
|
394
|
+
item.content = sanitizeResponsesMessageContentForReplay(item.content);
|
|
395
|
+
}
|
|
396
|
+
if (item.type === "function_call" && "arguments" in item && typeof item.arguments !== "string") {
|
|
397
|
+
item.arguments = stringifyResponsesStringParamForReplay(item.arguments);
|
|
398
|
+
}
|
|
399
|
+
if (item.type === "custom_tool_call" && "input" in item && typeof item.input !== "string") {
|
|
400
|
+
item.input = stringifyResponsesStringParamForReplay(item.input);
|
|
401
|
+
}
|
|
402
|
+
if ((item.type === "function_call_output" || item.type === "custom_tool_call_output") && "output" in item) {
|
|
403
|
+
item.output =
|
|
404
|
+
typeof item.output === "string"
|
|
405
|
+
? neutralizeReservedControlTokens(item.output.toWellFormed())
|
|
406
|
+
: stringifyResponsesStringParamForReplay(item.output);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function sanitizeOpenAIResponsesHistoryItemForReplay(
|
|
411
|
+
item: Record<string, unknown>,
|
|
412
|
+
normalizedCallIds: Map<string, string>,
|
|
413
|
+
): OpenAIResponsesReplayItem | undefined {
|
|
414
|
+
if (item.type === "item_reference") return undefined;
|
|
415
|
+
|
|
416
|
+
// providerPayload stores raw output items; replay strips fields that are output-only.
|
|
417
|
+
const { id: _id, ...itemWithoutId } = item;
|
|
418
|
+
const sanitizedItem =
|
|
419
|
+
item.type === "computer_call"
|
|
420
|
+
? sanitizeComputerCallForResponsesInput(itemWithoutId)
|
|
421
|
+
: item.type === "image_generation_call"
|
|
422
|
+
? sanitizeImageGenerationCallForResponsesInput(itemWithoutId)
|
|
423
|
+
: itemWithoutId;
|
|
424
|
+
if (typeof item.call_id === "string") {
|
|
425
|
+
sanitizedItem.call_id = normalizeReplayedResponsesHistoryCallId(item.call_id, normalizedCallIds);
|
|
426
|
+
}
|
|
427
|
+
sanitizeResponsesStringFieldsForReplay(sanitizedItem);
|
|
428
|
+
|
|
429
|
+
return sanitizedItem as unknown as OpenAIResponsesReplayItem;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function sanitizeComputerCallForResponsesInput(item: Record<string, unknown>): Record<string, unknown> {
|
|
433
|
+
// The Responses stream includes the performed computer action on output items,
|
|
434
|
+
// but the create input accepts only the call identity/status fields on replay.
|
|
435
|
+
const { action: _action, actions: _actions, ...inputSafeItem } = item;
|
|
436
|
+
return inputSafeItem;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function sanitizeImageGenerationCallForResponsesInput(item: Record<string, unknown>): Record<string, unknown> {
|
|
440
|
+
// Image generation output items include request-time knobs that are not part of
|
|
441
|
+
// the Responses input replay schema. Replaying them verbatim makes OpenAI-compatible
|
|
442
|
+
// endpoints reject the next turn, e.g. `Unknown parameter: input[n].action`.
|
|
443
|
+
const {
|
|
444
|
+
action: _action,
|
|
445
|
+
background: _background,
|
|
446
|
+
output_format: _outputFormat,
|
|
447
|
+
quality: _quality,
|
|
448
|
+
revised_prompt: _revisedPrompt,
|
|
449
|
+
size: _size,
|
|
450
|
+
...inputSafeItem
|
|
451
|
+
} = item;
|
|
452
|
+
return inputSafeItem;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function normalizeReplayedResponsesHistoryCallId(value: string, normalizedValues: Map<string, string>): string {
|
|
456
|
+
const normalized = normalizedValues.get(value);
|
|
457
|
+
if (normalized) return normalized;
|
|
458
|
+
const next = truncateResponseItemId(value, getIdPrefix(value, "call"));
|
|
459
|
+
normalizedValues.set(value, next);
|
|
460
|
+
return next;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
export function createOpenAIResponsesHistoryPayload(
|
|
464
|
+
provider: string,
|
|
465
|
+
items: Array<Record<string, unknown>>,
|
|
466
|
+
incremental = true,
|
|
467
|
+
): OpenAIResponsesHistoryPayload {
|
|
468
|
+
return {
|
|
469
|
+
type: "openaiResponsesHistory",
|
|
470
|
+
provider,
|
|
471
|
+
...(incremental ? { dt: true } : {}),
|
|
472
|
+
items,
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export function getOpenAIResponsesHistoryPayload(
|
|
477
|
+
providerPayload: ProviderPayload | undefined,
|
|
478
|
+
currentProvider: string,
|
|
479
|
+
fallbackProvider?: string,
|
|
480
|
+
): OpenAIResponsesHistoryPayload | undefined {
|
|
481
|
+
if (providerPayload?.type !== "openaiResponsesHistory" || !Array.isArray(providerPayload.items)) {
|
|
482
|
+
return undefined;
|
|
483
|
+
}
|
|
484
|
+
const payloadProvider = providerPayload.provider ?? fallbackProvider;
|
|
485
|
+
if (!payloadProvider || payloadProvider !== currentProvider) {
|
|
486
|
+
return undefined;
|
|
487
|
+
}
|
|
488
|
+
return { ...providerPayload, provider: payloadProvider };
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
export function getOpenAIResponsesHistoryItems(
|
|
492
|
+
providerPayload: ProviderPayload | undefined,
|
|
493
|
+
currentProvider: string,
|
|
494
|
+
fallbackProvider?: string,
|
|
495
|
+
): Array<Record<string, unknown>> | undefined {
|
|
496
|
+
return getOpenAIResponsesHistoryPayload(providerPayload, currentProvider, fallbackProvider)?.items;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Resolve cache retention preference.
|
|
501
|
+
*
|
|
502
|
+
* Resolution order: explicit request value → `VIB_CACHE_RETENTION` →
|
|
503
|
+
* legacy `PI_CACHE_RETENTION` → `fallback`. Both env vars act as explicit
|
|
504
|
+
* opt-in (`"long"`) or opt-out (any other value) so a provider-specific
|
|
505
|
+
* `fallback` only applies when nothing else is configured. `fallback`
|
|
506
|
+
* defaults to `"short"` to preserve the historical behaviour for callers
|
|
507
|
+
* that don't pass one.
|
|
508
|
+
*/
|
|
509
|
+
export function resolveCacheRetention(
|
|
510
|
+
cacheRetention?: CacheRetention,
|
|
511
|
+
fallback: CacheRetention = "short",
|
|
512
|
+
): CacheRetention {
|
|
513
|
+
if (cacheRetention) return cacheRetention;
|
|
514
|
+
if ($env.VIB_CACHE_RETENTION === "long") return "long";
|
|
515
|
+
if ($env.VIB_CACHE_RETENTION !== undefined) return "short";
|
|
516
|
+
if ($env.PI_CACHE_RETENTION === "long") return "long";
|
|
517
|
+
if ($env.PI_CACHE_RETENTION !== undefined) return "short";
|
|
518
|
+
return fallback;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
export function isAnthropicOAuthToken(key: string): boolean {
|
|
522
|
+
return key.includes("sk-ant-oat");
|
|
523
|
+
}
|