@linxiraos/pi-ai 1.0.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 +5066 -0
- package/README.md +1195 -0
- package/dist/types/api-registry.d.ts +30 -0
- package/dist/types/auth/sqlite-credential-store.d.ts +117 -0
- package/dist/types/auth-broker/client.d.ts +93 -0
- package/dist/types/auth-broker/discover.d.ts +39 -0
- package/dist/types/auth-broker/index.d.ts +7 -0
- package/dist/types/auth-broker/refresher.d.ts +25 -0
- package/dist/types/auth-broker/remote-store.d.ts +136 -0
- package/dist/types/auth-broker/server.d.ts +48 -0
- package/dist/types/auth-broker/snapshot-cache.d.ts +17 -0
- package/dist/types/auth-broker/types.d.ts +152 -0
- package/dist/types/auth-broker/wire-schema-resource.d.ts +53 -0
- package/dist/types/auth-broker/wire-schemas.d.ts +5 -0
- package/dist/types/auth-gateway/http.d.ts +56 -0
- package/dist/types/auth-gateway/index.d.ts +3 -0
- package/dist/types/auth-gateway/server.d.ts +36 -0
- package/dist/types/auth-gateway/types.d.ts +127 -0
- package/dist/types/auth-retry.d.ts +150 -0
- package/dist/types/auth-storage.d.ts +1258 -0
- package/dist/types/dialect/anthropic.d.ts +15 -0
- package/dist/types/dialect/catalog.d.ts +3 -0
- package/dist/types/dialect/coercion.d.ts +23 -0
- package/dist/types/dialect/deepseek.d.ts +14 -0
- package/dist/types/dialect/demotion.d.ts +30 -0
- package/dist/types/dialect/examples.d.ts +18 -0
- package/dist/types/dialect/factory.d.ts +3 -0
- package/dist/types/dialect/fenced-thinking.d.ts +53 -0
- package/dist/types/dialect/gemini.d.ts +17 -0
- package/dist/types/dialect/gemma.d.ts +15 -0
- package/dist/types/dialect/glm.d.ts +9 -0
- package/dist/types/dialect/harmony.d.ts +8 -0
- package/dist/types/dialect/hermes.d.ts +9 -0
- package/dist/types/dialect/history.d.ts +3 -0
- package/dist/types/dialect/index.d.ts +11 -0
- package/dist/types/dialect/inventory.d.ts +9 -0
- package/dist/types/dialect/kimi.d.ts +14 -0
- package/dist/types/dialect/minimax.d.ts +3 -0
- package/dist/types/dialect/owned-stream.d.ts +4 -0
- package/dist/types/dialect/qwen3.d.ts +9 -0
- package/dist/types/dialect/rendering.d.ts +54 -0
- package/dist/types/dialect/thinking.d.ts +6 -0
- package/dist/types/dialect/types.d.ts +68 -0
- package/dist/types/dialect/xml.d.ts +9 -0
- package/dist/types/error/abort.d.ts +14 -0
- package/dist/types/error/auth-classify.d.ts +20 -0
- package/dist/types/error/auth.d.ts +27 -0
- package/dist/types/error/aws.d.ts +27 -0
- package/dist/types/error/classes.d.ts +106 -0
- package/dist/types/error/finalize.d.ts +39 -0
- package/dist/types/error/flags.d.ts +94 -0
- package/dist/types/error/format.d.ts +20 -0
- package/dist/types/error/gateway.d.ts +20 -0
- package/dist/types/error/index.d.ts +14 -0
- package/dist/types/error/oauth.d.ts +43 -0
- package/dist/types/error/provider.d.ts +42 -0
- package/dist/types/error/rate-limit.d.ts +80 -0
- package/dist/types/error/retryable.d.ts +27 -0
- package/dist/types/error/validation.d.ts +32 -0
- package/dist/types/index.d.ts +51 -0
- package/dist/types/provider-details.d.ts +24 -0
- package/dist/types/providers/amazon-bedrock.d.ts +39 -0
- package/dist/types/providers/anthropic-client.d.ts +106 -0
- package/dist/types/providers/anthropic-messages-server-schema.d.ts +937 -0
- package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
- package/dist/types/providers/anthropic-wire.d.ts +345 -0
- package/dist/types/providers/anthropic.d.ts +261 -0
- package/dist/types/providers/aws-credentials.d.ts +48 -0
- package/dist/types/providers/aws-eventstream.d.ts +39 -0
- package/dist/types/providers/aws-sigv4.d.ts +55 -0
- package/dist/types/providers/azure-openai-responses.d.ts +16 -0
- package/dist/types/providers/bedrock-mantle.d.ts +13 -0
- package/dist/types/providers/claude-code-fingerprint.d.ts +19 -0
- package/dist/types/providers/cowork-fetch.d.ts +3 -0
- package/dist/types/providers/cursor/exec-modern.d.ts +98 -0
- package/dist/types/providers/cursor-pi-args.d.ts +105 -0
- package/dist/types/providers/cursor.d.ts +221 -0
- package/dist/types/providers/devin.d.ts +12 -0
- package/dist/types/providers/error-message.d.ts +25 -0
- package/dist/types/providers/github-copilot-headers.d.ts +40 -0
- package/dist/types/providers/gitlab-duo-workflow.d.ts +254 -0
- package/dist/types/providers/gitlab-duo.d.ts +27 -0
- package/dist/types/providers/google-auth.d.ts +24 -0
- package/dist/types/providers/google-gemini-cli.d.ts +120 -0
- package/dist/types/providers/google-shared.d.ts +203 -0
- package/dist/types/providers/google-types.d.ts +155 -0
- package/dist/types/providers/google-vertex.d.ts +7 -0
- package/dist/types/providers/google.d.ts +4 -0
- package/dist/types/providers/grammar.d.ts +1 -0
- package/dist/types/providers/kimi.d.ts +27 -0
- package/dist/types/providers/mock.d.ts +179 -0
- package/dist/types/providers/ollama.d.ts +8 -0
- package/dist/types/providers/openai-anthropic-shim.d.ts +35 -0
- package/dist/types/providers/openai-chat-server-schema.d.ts +1311 -0
- package/dist/types/providers/openai-chat-server.d.ts +16 -0
- package/dist/types/providers/openai-chat-wire.d.ts +669 -0
- package/dist/types/providers/openai-codex/request-transformer.d.ts +109 -0
- package/dist/types/providers/openai-codex/response-handler.d.ts +26 -0
- package/dist/types/providers/openai-codex-responses.d.ts +238 -0
- package/dist/types/providers/openai-completions.d.ts +48 -0
- package/dist/types/providers/openai-reasoning-fallback.d.ts +25 -0
- package/dist/types/providers/openai-responses-server-schema.d.ts +1314 -0
- package/dist/types/providers/openai-responses-server.d.ts +17 -0
- package/dist/types/providers/openai-responses-wire.d.ts +6099 -0
- package/dist/types/providers/openai-responses.d.ts +131 -0
- package/dist/types/providers/openai-shared.d.ts +624 -0
- package/dist/types/providers/pi-native-client.d.ts +13 -0
- package/dist/types/providers/pi-native-server.d.ts +69 -0
- package/dist/types/providers/register-builtins.d.ts +37 -0
- package/dist/types/providers/synthetic.d.ts +26 -0
- package/dist/types/providers/transform-messages.d.ts +32 -0
- package/dist/types/providers/vision-guard.d.ts +20 -0
- package/dist/types/registry/aiand.d.ts +7 -0
- package/dist/types/registry/aimlapi.d.ts +4 -0
- package/dist/types/registry/alibaba-coding-plan.d.ts +8 -0
- package/dist/types/registry/alibaba-token-plan.d.ts +18 -0
- package/dist/types/registry/amazon-bedrock.d.ts +5 -0
- package/dist/types/registry/anthropic.d.ts +10 -0
- package/dist/types/registry/api-key-login.d.ts +42 -0
- package/dist/types/registry/api-key-validation.d.ts +43 -0
- package/dist/types/registry/aws.d.ts +13 -0
- package/dist/types/registry/azure.d.ts +4 -0
- package/dist/types/registry/baseten.d.ts +7 -0
- package/dist/types/registry/bedrock-mantle.d.ts +22 -0
- package/dist/types/registry/cerebras.d.ts +7 -0
- package/dist/types/registry/cloudflare-ai-gateway.d.ts +13 -0
- package/dist/types/registry/coreweave.d.ts +7 -0
- package/dist/types/registry/cursor.d.ts +7 -0
- package/dist/types/registry/deepseek.d.ts +8 -0
- package/dist/types/registry/derived.d.ts +5 -0
- package/dist/types/registry/devin.d.ts +8 -0
- package/dist/types/registry/exa.d.ts +8 -0
- package/dist/types/registry/firepass.d.ts +16 -0
- package/dist/types/registry/fireworks.d.ts +7 -0
- package/dist/types/registry/github-copilot.d.ts +7 -0
- package/dist/types/registry/gitlab-duo-workflow.d.ts +10 -0
- package/dist/types/registry/gitlab-duo.d.ts +9 -0
- package/dist/types/registry/gmi-cloud.d.ts +7 -0
- package/dist/types/registry/google-antigravity.d.ts +9 -0
- package/dist/types/registry/google-gemini-cli.d.ts +9 -0
- package/dist/types/registry/google-vertex.d.ts +5 -0
- package/dist/types/registry/google.d.ts +4 -0
- package/dist/types/registry/groq.d.ts +4 -0
- package/dist/types/registry/huggingface.d.ts +7 -0
- package/dist/types/registry/index.d.ts +4 -0
- package/dist/types/registry/kagi.d.ts +14 -0
- package/dist/types/registry/kilo.d.ts +7 -0
- package/dist/types/registry/kimi-code.d.ts +7 -0
- package/dist/types/registry/litellm.d.ts +13 -0
- package/dist/types/registry/llama-cpp.d.ts +8 -0
- package/dist/types/registry/lm-studio.d.ts +8 -0
- package/dist/types/registry/meta.d.ts +7 -0
- package/dist/types/registry/minimax-code-cn.d.ts +6 -0
- package/dist/types/registry/minimax-code.d.ts +6 -0
- package/dist/types/registry/minimax.d.ts +4 -0
- package/dist/types/registry/mistral.d.ts +4 -0
- package/dist/types/registry/moonshot.d.ts +7 -0
- package/dist/types/registry/nanogpt.d.ts +7 -0
- package/dist/types/registry/novita.d.ts +6 -0
- package/dist/types/registry/nvidia.d.ts +7 -0
- package/dist/types/registry/oauth/anthropic-constants.d.ts +12 -0
- package/dist/types/registry/oauth/anthropic.d.ts +24 -0
- package/dist/types/registry/oauth/callback-server.d.ts +74 -0
- package/dist/types/registry/oauth/cursor.d.ts +16 -0
- package/dist/types/registry/oauth/device-code.d.ts +25 -0
- package/dist/types/registry/oauth/devin.d.ts +5 -0
- package/dist/types/registry/oauth/github-copilot.d.ts +30 -0
- package/dist/types/registry/oauth/gitlab-duo-workflow.d.ts +6 -0
- package/dist/types/registry/oauth/gitlab-duo.d.ts +3 -0
- package/dist/types/registry/oauth/google-antigravity.d.ts +11 -0
- package/dist/types/registry/oauth/google-gemini-cli.d.ts +22 -0
- package/dist/types/registry/oauth/google-oauth-shared.d.ts +56 -0
- package/dist/types/registry/oauth/index.d.ts +45 -0
- package/dist/types/registry/oauth/kimi.d.ts +21 -0
- package/dist/types/registry/oauth/minimax-code.d.ts +27 -0
- package/dist/types/registry/oauth/openai-codex.d.ts +33 -0
- package/dist/types/registry/oauth/opencode.d.ts +18 -0
- package/dist/types/registry/oauth/perplexity.d.ts +9 -0
- package/dist/types/registry/oauth/pkce.d.ts +8 -0
- package/dist/types/registry/oauth/types.d.ts +87 -0
- package/dist/types/registry/oauth/wafer.d.ts +1 -0
- package/dist/types/registry/oauth/xai-oauth.d.ts +46 -0
- package/dist/types/registry/oauth/xiaomi.d.ts +25 -0
- package/dist/types/registry/oauth/zai.d.ts +25 -0
- package/dist/types/registry/ollama-cloud.d.ts +7 -0
- package/dist/types/registry/ollama.d.ts +12 -0
- package/dist/types/registry/openai-codex-device.d.ts +8 -0
- package/dist/types/registry/openai-codex.d.ts +9 -0
- package/dist/types/registry/openai.d.ts +4 -0
- package/dist/types/registry/opencode-go.d.ts +6 -0
- package/dist/types/registry/opencode-zen.d.ts +6 -0
- package/dist/types/registry/openrouter.d.ts +13 -0
- package/dist/types/registry/parallel.d.ts +14 -0
- package/dist/types/registry/perplexity.d.ts +7 -0
- package/dist/types/registry/qianfan.d.ts +7 -0
- package/dist/types/registry/qwen-portal.d.ts +7 -0
- package/dist/types/registry/registry.d.ts +367 -0
- package/dist/types/registry/sakana.d.ts +7 -0
- package/dist/types/registry/siliconflow-cn.d.ts +7 -0
- package/dist/types/registry/siliconflow.d.ts +7 -0
- package/dist/types/registry/synthetic.d.ts +6 -0
- package/dist/types/registry/tavily.d.ts +14 -0
- package/dist/types/registry/together.d.ts +6 -0
- package/dist/types/registry/types.d.ts +75 -0
- package/dist/types/registry/umans.d.ts +7 -0
- package/dist/types/registry/venice.d.ts +13 -0
- package/dist/types/registry/vercel-ai-gateway.d.ts +7 -0
- package/dist/types/registry/vllm.d.ts +7 -0
- package/dist/types/registry/wafer-serverless.d.ts +6 -0
- package/dist/types/registry/xai-oauth.d.ts +7 -0
- package/dist/types/registry/xai.d.ts +7 -0
- package/dist/types/registry/xiaomi-token-plan-ams.d.ts +6 -0
- package/dist/types/registry/xiaomi-token-plan-cn.d.ts +6 -0
- package/dist/types/registry/xiaomi-token-plan-sgp.d.ts +6 -0
- package/dist/types/registry/xiaomi.d.ts +6 -0
- package/dist/types/registry/zai.d.ts +15 -0
- package/dist/types/registry/zenmux.d.ts +7 -0
- package/dist/types/registry/zhipu-coding-plan.d.ts +7 -0
- package/dist/types/stream.d.ts +46 -0
- package/dist/types/types.d.ts +1064 -0
- package/dist/types/usage/alibaba-token-plan.d.ts +3 -0
- package/dist/types/usage/claude.d.ts +4 -0
- package/dist/types/usage/cursor.d.ts +4 -0
- package/dist/types/usage/gemini.d.ts +2 -0
- package/dist/types/usage/github-copilot.d.ts +7 -0
- package/dist/types/usage/google-antigravity.d.ts +15 -0
- package/dist/types/usage/kimi.d.ts +2 -0
- package/dist/types/usage/minimax-code.d.ts +3 -0
- package/dist/types/usage/ollama.d.ts +5 -0
- package/dist/types/usage/openai-codex-base-url.d.ts +18 -0
- package/dist/types/usage/openai-codex-reset.d.ts +88 -0
- package/dist/types/usage/openai-codex.d.ts +10 -0
- package/dist/types/usage/opencode-go.d.ts +2 -0
- package/dist/types/usage/shared.d.ts +1 -0
- package/dist/types/usage/synthetic.d.ts +2 -0
- package/dist/types/usage/umans.d.ts +2 -0
- package/dist/types/usage/xai-oauth.d.ts +12 -0
- package/dist/types/usage/zai.d.ts +3 -0
- package/dist/types/usage.d.ts +527 -0
- package/dist/types/utils/abort.d.ts +25 -0
- package/dist/types/utils/anthropic-auth.d.ts +35 -0
- package/dist/types/utils/aws-profile.d.ts +17 -0
- package/dist/types/utils/block-symbols.d.ts +62 -0
- package/dist/types/utils/deterministic-id.d.ts +16 -0
- package/dist/types/utils/empty-completion-retry.d.ts +21 -0
- package/dist/types/utils/event-stream.d.ts +39 -0
- package/dist/types/utils/foundry.d.ts +1 -0
- package/dist/types/utils/google-validation.d.ts +2 -0
- package/dist/types/utils/harmony-leak.d.ts +135 -0
- package/dist/types/utils/http-inspector.d.ts +49 -0
- package/dist/types/utils/idle-iterator.d.ts +149 -0
- package/dist/types/utils/leaked-thinking-stream.d.ts +33 -0
- package/dist/types/utils/openai-http.d.ts +48 -0
- package/dist/types/utils/openrouter-headers.d.ts +1 -0
- package/dist/types/utils/parse-bind.d.ts +23 -0
- package/dist/types/utils/provider-response.d.ts +3 -0
- package/dist/types/utils/proxy.d.ts +39 -0
- package/dist/types/utils/request-debug.d.ts +29 -0
- package/dist/types/utils/retry-after.d.ts +4 -0
- package/dist/types/utils/retry.d.ts +14 -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 +54 -0
- package/dist/types/utils/schema/index.d.ts +14 -0
- package/dist/types/utils/schema/json-schema-validator.d.ts +20 -0
- package/dist/types/utils/schema/meta-validator.d.ts +2 -0
- package/dist/types/utils/schema/normalize.d.ts +153 -0
- package/dist/types/utils/schema/spill.d.ts +8 -0
- package/dist/types/utils/schema/stamps.d.ts +17 -0
- package/dist/types/utils/schema/strict-tool-validation.d.ts +16 -0
- package/dist/types/utils/schema/types.d.ts +4 -0
- package/dist/types/utils/schema/typescript.d.ts +24 -0
- package/dist/types/utils/schema/wire.d.ts +52 -0
- package/dist/types/utils/sdk-stream-timeout.d.ts +33 -0
- package/dist/types/utils/sse-debug.d.ts +5 -0
- package/dist/types/utils/stream-markup-healing.d.ts +87 -0
- package/dist/types/utils/thinking-loop.d.ts +102 -0
- package/dist/types/utils/tool-call-loop-guard.d.ts +26 -0
- package/dist/types/utils/tool-choice.d.ts +52 -0
- package/dist/types/utils/validation.d.ts +28 -0
- package/dist/types/utils.d.ts +57 -0
- package/package.json +138 -0
- package/src/api-registry.ts +109 -0
- package/src/auth/sqlite-credential-store.ts +2066 -0
- package/src/auth-broker/client.ts +471 -0
- package/src/auth-broker/discover.ts +310 -0
- package/src/auth-broker/index.ts +7 -0
- package/src/auth-broker/refresher.ts +117 -0
- package/src/auth-broker/remote-store.ts +1332 -0
- package/src/auth-broker/server.ts +898 -0
- package/src/auth-broker/snapshot-cache.ts +200 -0
- package/src/auth-broker/types.ts +193 -0
- package/src/auth-broker/wire-schema-resource.ts +487 -0
- package/src/auth-broker/wire-schemas.ts +43 -0
- package/src/auth-gateway/http.ts +227 -0
- package/src/auth-gateway/index.ts +3 -0
- package/src/auth-gateway/server.ts +836 -0
- package/src/auth-gateway/types.ts +153 -0
- package/src/auth-retry.ts +401 -0
- package/src/auth-storage.ts +6540 -0
- package/src/dialect/anthropic.md +31 -0
- package/src/dialect/anthropic.ts +608 -0
- package/src/dialect/catalog.ts +29 -0
- package/src/dialect/coercion.ts +136 -0
- package/src/dialect/deepseek.md +24 -0
- package/src/dialect/deepseek.ts +609 -0
- package/src/dialect/demotion.ts +40 -0
- package/src/dialect/examples.ts +71 -0
- package/src/dialect/factory.ts +34 -0
- package/src/dialect/fenced-thinking.ts +184 -0
- package/src/dialect/gemini.md +44 -0
- package/src/dialect/gemini.ts +583 -0
- package/src/dialect/gemma.md +33 -0
- package/src/dialect/gemma.ts +387 -0
- package/src/dialect/glm.md +32 -0
- package/src/dialect/glm.ts +579 -0
- package/src/dialect/harmony.md +31 -0
- package/src/dialect/harmony.ts +345 -0
- package/src/dialect/hermes.md +25 -0
- package/src/dialect/hermes.ts +206 -0
- package/src/dialect/history.ts +81 -0
- package/src/dialect/index.ts +15 -0
- package/src/dialect/inventory.ts +30 -0
- package/src/dialect/kimi.md +24 -0
- package/src/dialect/kimi.ts +340 -0
- package/src/dialect/minimax.md +31 -0
- package/src/dialect/minimax.ts +95 -0
- package/src/dialect/owned-stream.ts +481 -0
- package/src/dialect/prompt-template.md +12 -0
- package/src/dialect/qwen3.md +28 -0
- package/src/dialect/qwen3.ts +240 -0
- package/src/dialect/rendering.ts +304 -0
- package/src/dialect/thinking.ts +292 -0
- package/src/dialect/types.ts +56 -0
- package/src/dialect/xml.md +22 -0
- package/src/dialect/xml.ts +90 -0
- package/src/error/abort.ts +18 -0
- package/src/error/auth-classify.ts +47 -0
- package/src/error/auth.ts +48 -0
- package/src/error/aws.ts +35 -0
- package/src/error/classes.ts +281 -0
- package/src/error/finalize.ts +69 -0
- package/src/error/flags.ts +602 -0
- package/src/error/format.ts +45 -0
- package/src/error/gateway.ts +96 -0
- package/src/error/index.ts +14 -0
- package/src/error/oauth.ts +58 -0
- package/src/error/provider.ts +63 -0
- package/src/error/rate-limit.ts +303 -0
- package/src/error/retryable.ts +70 -0
- package/src/error/validation.ts +44 -0
- package/src/index.ts +51 -0
- package/src/provider-details.ts +90 -0
- package/src/providers/amazon-bedrock.ts +1064 -0
- package/src/providers/anthropic-client.ts +317 -0
- package/src/providers/anthropic-messages-server-schema.ts +252 -0
- package/src/providers/anthropic-messages-server.ts +818 -0
- package/src/providers/anthropic-wire.ts +359 -0
- package/src/providers/anthropic.ts +4539 -0
- package/src/providers/aws-credentials.ts +772 -0
- package/src/providers/aws-eventstream.ts +181 -0
- package/src/providers/aws-sigv4.ts +218 -0
- package/src/providers/azure-openai-responses.ts +438 -0
- package/src/providers/bedrock-mantle.ts +110 -0
- package/src/providers/claude-code-fingerprint.ts +20 -0
- package/src/providers/cowork-fetch.ts +201 -0
- package/src/providers/cursor/exec-modern.ts +496 -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.ts +165 -0
- package/src/providers/cursor.ts +4689 -0
- package/src/providers/devin/proto/buf/validate/validate.proto +468 -0
- package/src/providers/devin/proto/buf.gen.yaml +33 -0
- package/src/providers/devin/proto/buf.yaml +17 -0
- package/src/providers/devin/proto/cel/expr/checked.proto +103 -0
- package/src/providers/devin/proto/cel/expr/eval.proto +38 -0
- package/src/providers/devin/proto/cel/expr/explain.proto +15 -0
- package/src/providers/devin/proto/cel/expr/syntax.proto +113 -0
- package/src/providers/devin/proto/cel/expr/value.proto +41 -0
- package/src/providers/devin/proto/connectext/grpc/status/v1/status.proto +11 -0
- package/src/providers/devin/proto/errorspb/errors.proto +56 -0
- package/src/providers/devin/proto/errorspb/hintdetail.proto +7 -0
- package/src/providers/devin/proto/errorspb/markers.proto +10 -0
- package/src/providers/devin/proto/errorspb/tags.proto +12 -0
- package/src/providers/devin/proto/errorspb/testing.proto +6 -0
- package/src/providers/devin/proto/exa/analytics_pb/analytics.proto +188 -0
- package/src/providers/devin/proto/exa/api_server_pb/api_server.proto +2461 -0
- package/src/providers/devin/proto/exa/auth_pb/auth.proto +19 -0
- package/src/providers/devin/proto/exa/auto_cascade_common_pb/auto_cascade_common.proto +79 -0
- package/src/providers/devin/proto/exa/browser_preview_pb/browser_preview.proto +32 -0
- package/src/providers/devin/proto/exa/bug_checker_pb/bug_checker.proto +22 -0
- package/src/providers/devin/proto/exa/cascade_plugins_pb/cascade_plugins.proto +262 -0
- package/src/providers/devin/proto/exa/chat_client_server_pb/chat_client_server.proto +57 -0
- package/src/providers/devin/proto/exa/chat_pb/chat.proto +449 -0
- package/src/providers/devin/proto/exa/code_edit/code_edit_pb/code_edit.proto +186 -0
- package/src/providers/devin/proto/exa/codeium_common_pb/codeium_common.proto +4157 -0
- package/src/providers/devin/proto/exa/context_module_pb/context_module.proto +175 -0
- package/src/providers/devin/proto/exa/cortex_pb/cortex.proto +3268 -0
- package/src/providers/devin/proto/exa/dev_pb/dev.proto +26 -0
- package/src/providers/devin/proto/exa/diff_action_pb/diff_action.proto +75 -0
- package/src/providers/devin/proto/exa/eval/pr_eval/datasets_pb/datasets.proto +103 -0
- package/src/providers/devin/proto/exa/eval_pb/eval.proto +1315 -0
- package/src/providers/devin/proto/exa/extension_server_pb/extension_server.proto +556 -0
- package/src/providers/devin/proto/exa/file_system_provider_pb/file_system_provider.proto +75 -0
- package/src/providers/devin/proto/exa/index_pb/index.proto +461 -0
- package/src/providers/devin/proto/exa/knowledge_base_pb/knowledge_base.proto +144 -0
- package/src/providers/devin/proto/exa/language_server_pb/language_server.proto +2385 -0
- package/src/providers/devin/proto/exa/model_management_pb/model_management.proto +186 -0
- package/src/providers/devin/proto/exa/opensearch_clients_pb/opensearch_clients.proto +503 -0
- package/src/providers/devin/proto/exa/product_analytics_pb/product_analytics.proto +37 -0
- package/src/providers/devin/proto/exa/prompt_pb/prompt.proto +92 -0
- package/src/providers/devin/proto/exa/reactive_component_pb/reactive_component.proto +96 -0
- package/src/providers/devin/proto/exa/seat_management_pb/seat_management.proto +2680 -0
- package/src/providers/devin/proto/exa/tokenizer_pb/tokenizer.proto +37 -0
- package/src/providers/devin/proto/exa/trainer_pb/config.proto +647 -0
- package/src/providers/devin/proto/exa/tree_sitter/language_data_pb/language_data.proto +14 -0
- package/src/providers/devin/proto/exa/trust_pb/trust.proto +157 -0
- package/src/providers/devin/proto/exa/user_analytics_pb/user_analytics.proto +519 -0
- package/src/providers/devin/proto/google.golang.org/appengine/internal/base/api_base.proto +28 -0
- package/src/providers/devin/proto/google.golang.org/appengine/internal/datastore/datastore_v3.proto +484 -0
- package/src/providers/devin/proto/google.golang.org/appengine/internal/log/log_service.proto +136 -0
- package/src/providers/devin/proto/google.golang.org/appengine/internal/remote_api/remote_api.proto +42 -0
- package/src/providers/devin/proto/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto +61 -0
- package/src/providers/devin/proto/grpc/binlog/v1/binarylog.proto +84 -0
- package/src/providers/devin/proto/io/prometheus/client/metrics.proto +98 -0
- package/src/providers/devin.ts +679 -0
- package/src/providers/error-message.ts +23 -0
- package/src/providers/github-copilot-headers.ts +141 -0
- package/src/providers/gitlab-duo-workflow-chatml-note.md +1 -0
- package/src/providers/gitlab-duo-workflow.ts +3135 -0
- package/src/providers/gitlab-duo.ts +399 -0
- package/src/providers/google-auth.ts +330 -0
- package/src/providers/google-gemini-cli.ts +1370 -0
- package/src/providers/google-shared.ts +1122 -0
- package/src/providers/google-types.ts +180 -0
- package/src/providers/google-vertex.ts +135 -0
- package/src/providers/google.ts +47 -0
- package/src/providers/grammar.ts +70 -0
- package/src/providers/kimi.ts +51 -0
- package/src/providers/mock.ts +514 -0
- package/src/providers/ollama.ts +776 -0
- package/src/providers/openai-anthropic-shim.ts +166 -0
- package/src/providers/openai-chat-server-schema.ts +243 -0
- package/src/providers/openai-chat-server.ts +752 -0
- package/src/providers/openai-chat-wire.ts +859 -0
- package/src/providers/openai-codex/request-transformer.ts +491 -0
- package/src/providers/openai-codex/response-handler.ts +102 -0
- package/src/providers/openai-codex-responses.ts +4716 -0
- package/src/providers/openai-completions.ts +2389 -0
- package/src/providers/openai-reasoning-fallback.ts +269 -0
- package/src/providers/openai-responses-server-schema.ts +397 -0
- package/src/providers/openai-responses-server.ts +1466 -0
- package/src/providers/openai-responses-wire.ts +6416 -0
- package/src/providers/openai-responses.ts +1393 -0
- package/src/providers/openai-shared.ts +3500 -0
- package/src/providers/pi-native-client.ts +275 -0
- package/src/providers/pi-native-server.ts +245 -0
- package/src/providers/register-builtins.ts +503 -0
- package/src/providers/synthetic.ts +50 -0
- package/src/providers/transform-messages.ts +1083 -0
- package/src/providers/vision-guard.ts +54 -0
- package/src/registry/aiand.ts +22 -0
- package/src/registry/aimlapi.ts +6 -0
- package/src/registry/alibaba-coding-plan.ts +104 -0
- package/src/registry/alibaba-token-plan.ts +125 -0
- package/src/registry/amazon-bedrock.ts +22 -0
- package/src/registry/anthropic.ts +26 -0
- package/src/registry/api-key-login.ts +115 -0
- package/src/registry/api-key-validation.ts +145 -0
- package/src/registry/aws.ts +57 -0
- package/src/registry/azure.ts +6 -0
- package/src/registry/baseten.ts +22 -0
- package/src/registry/bedrock-mantle.ts +34 -0
- package/src/registry/cerebras.ts +23 -0
- package/src/registry/cloudflare-ai-gateway.ts +45 -0
- package/src/registry/coreweave.ts +40 -0
- package/src/registry/cursor.ts +20 -0
- package/src/registry/deepseek.ts +46 -0
- package/src/registry/derived.ts +9 -0
- package/src/registry/devin.ts +15 -0
- package/src/registry/exa.ts +19 -0
- package/src/registry/firepass.ts +32 -0
- package/src/registry/fireworks.ts +28 -0
- package/src/registry/github-copilot.ts +22 -0
- package/src/registry/gitlab-duo-workflow.ts +20 -0
- package/src/registry/gitlab-duo.ts +19 -0
- package/src/registry/gmi-cloud.ts +22 -0
- package/src/registry/google-antigravity.ts +22 -0
- package/src/registry/google-gemini-cli.ts +22 -0
- package/src/registry/google-vertex.ts +38 -0
- package/src/registry/google.ts +6 -0
- package/src/registry/groq.ts +6 -0
- package/src/registry/huggingface.ts +29 -0
- package/src/registry/index.ts +4 -0
- package/src/registry/kagi.ts +46 -0
- package/src/registry/kilo.ts +114 -0
- package/src/registry/kimi-code.ts +17 -0
- package/src/registry/litellm.ts +45 -0
- package/src/registry/llama-cpp.ts +35 -0
- package/src/registry/lm-studio.ts +31 -0
- package/src/registry/meta.ts +22 -0
- package/src/registry/minimax-code-cn.ts +12 -0
- package/src/registry/minimax-code.ts +12 -0
- package/src/registry/minimax.ts +6 -0
- package/src/registry/mistral.ts +6 -0
- package/src/registry/moonshot.ts +28 -0
- package/src/registry/nanogpt.ts +22 -0
- package/src/registry/novita.ts +25 -0
- package/src/registry/nvidia.ts +61 -0
- package/src/registry/oauth/anthropic-constants.ts +12 -0
- package/src/registry/oauth/anthropic.ts +346 -0
- package/src/registry/oauth/callback-server.ts +438 -0
- package/src/registry/oauth/cursor.ts +187 -0
- package/src/registry/oauth/device-code.ts +92 -0
- package/src/registry/oauth/devin.ts +124 -0
- package/src/registry/oauth/github-copilot.ts +369 -0
- package/src/registry/oauth/gitlab-duo-workflow.ts +146 -0
- package/src/registry/oauth/gitlab-duo.ts +222 -0
- package/src/registry/oauth/google-antigravity.ts +225 -0
- package/src/registry/oauth/google-gemini-cli.ts +297 -0
- package/src/registry/oauth/google-oauth-shared.ts +211 -0
- package/src/registry/oauth/index.ts +187 -0
- package/src/registry/oauth/kimi.ts +297 -0
- package/src/registry/oauth/minimax-code.ts +53 -0
- package/src/registry/oauth/oauth.html +317 -0
- package/src/registry/oauth/openai-codex.ts +384 -0
- package/src/registry/oauth/opencode.ts +50 -0
- package/src/registry/oauth/perplexity.ts +228 -0
- package/src/registry/oauth/pkce.ts +18 -0
- package/src/registry/oauth/types.ts +96 -0
- package/src/registry/oauth/wafer.ts +24 -0
- package/src/registry/oauth/xai-oauth.ts +559 -0
- package/src/registry/oauth/xiaomi.ts +211 -0
- package/src/registry/oauth/zai.ts +285 -0
- package/src/registry/ollama-cloud.ts +36 -0
- package/src/registry/ollama.ts +43 -0
- package/src/registry/openai-codex-device.ts +18 -0
- package/src/registry/openai-codex.ts +19 -0
- package/src/registry/openai.ts +6 -0
- package/src/registry/opencode-go.ts +12 -0
- package/src/registry/opencode-zen.ts +12 -0
- package/src/registry/openrouter.ts +28 -0
- package/src/registry/parallel.ts +45 -0
- package/src/registry/perplexity.ts +13 -0
- package/src/registry/qianfan.ts +27 -0
- package/src/registry/qwen-portal.ts +50 -0
- package/src/registry/registry.ts +182 -0
- package/src/registry/sakana.ts +22 -0
- package/src/registry/siliconflow-cn.ts +22 -0
- package/src/registry/siliconflow.ts +22 -0
- package/src/registry/synthetic.ts +21 -0
- package/src/registry/tavily.ts +45 -0
- package/src/registry/together.ts +22 -0
- package/src/registry/types.ts +86 -0
- package/src/registry/umans.ts +23 -0
- package/src/registry/venice.ts +33 -0
- package/src/registry/vercel-ai-gateway.ts +38 -0
- package/src/registry/vllm.ts +34 -0
- package/src/registry/wafer-serverless.ts +12 -0
- package/src/registry/xai-oauth.ts +17 -0
- package/src/registry/xai.ts +22 -0
- package/src/registry/xiaomi-token-plan-ams.ts +12 -0
- package/src/registry/xiaomi-token-plan-cn.ts +12 -0
- package/src/registry/xiaomi-token-plan-sgp.ts +12 -0
- package/src/registry/xiaomi.ts +12 -0
- package/src/registry/zai.ts +41 -0
- package/src/registry/zenmux.ts +22 -0
- package/src/registry/zhipu-coding-plan.ts +27 -0
- package/src/stream.ts +1944 -0
- package/src/types.ts +1243 -0
- package/src/usage/alibaba-token-plan.ts +230 -0
- package/src/usage/claude.ts +830 -0
- package/src/usage/cursor.ts +335 -0
- package/src/usage/gemini.ts +258 -0
- package/src/usage/github-copilot.ts +424 -0
- package/src/usage/google-antigravity.ts +497 -0
- package/src/usage/kimi.ts +277 -0
- package/src/usage/minimax-code.ts +291 -0
- package/src/usage/ollama.ts +41 -0
- package/src/usage/openai-codex-base-url.ts +35 -0
- package/src/usage/openai-codex-reset.ts +205 -0
- package/src/usage/openai-codex.ts +627 -0
- package/src/usage/opencode-go.ts +89 -0
- package/src/usage/shared.ts +10 -0
- package/src/usage/synthetic.ts +180 -0
- package/src/usage/umans.ts +192 -0
- package/src/usage/xai-oauth.ts +414 -0
- package/src/usage/zai.ts +370 -0
- package/src/usage.ts +411 -0
- package/src/utils/abort.ts +67 -0
- package/src/utils/anthropic-auth.ts +93 -0
- package/src/utils/aws-profile.ts +88 -0
- package/src/utils/block-symbols.ts +78 -0
- package/src/utils/deterministic-id.ts +20 -0
- package/src/utils/empty-completion-retry.ts +161 -0
- package/src/utils/event-stream.ts +202 -0
- package/src/utils/foundry.ts +8 -0
- package/src/utils/google-validation.ts +25 -0
- package/src/utils/harmony-leak.ts +500 -0
- package/src/utils/http-inspector.ts +196 -0
- package/src/utils/idle-iterator.ts +531 -0
- package/src/utils/leaked-thinking-stream.ts +483 -0
- package/src/utils/openai-http.ts +119 -0
- package/src/utils/openrouter-headers.ts +12 -0
- package/src/utils/parse-bind.ts +56 -0
- package/src/utils/provider-response.ts +30 -0
- package/src/utils/proxy.ts +314 -0
- package/src/utils/request-debug.ts +351 -0
- package/src/utils/retry-after.ts +121 -0
- package/src/utils/retry.ts +77 -0
- package/src/utils/schema/CONSTRAINTS.md +168 -0
- package/src/utils/schema/adapt.ts +36 -0
- package/src/utils/schema/compatibility.ts +435 -0
- package/src/utils/schema/dereference.ts +98 -0
- package/src/utils/schema/draft.ts +341 -0
- package/src/utils/schema/equality.ts +97 -0
- package/src/utils/schema/fields.ts +210 -0
- package/src/utils/schema/index.ts +14 -0
- package/src/utils/schema/json-schema-validator.ts +595 -0
- package/src/utils/schema/meta-validator.ts +167 -0
- package/src/utils/schema/normalize.ts +2314 -0
- package/src/utils/schema/spill.ts +43 -0
- package/src/utils/schema/stamps.ts +109 -0
- package/src/utils/schema/strict-tool-validation.ts +117 -0
- package/src/utils/schema/types.ts +10 -0
- package/src/utils/schema/typescript.ts +212 -0
- package/src/utils/schema/wire.ts +662 -0
- package/src/utils/sdk-stream-timeout.ts +43 -0
- package/src/utils/sse-debug.ts +18 -0
- package/src/utils/stream-markup-healing.ts +247 -0
- package/src/utils/thinking-loop.ts +552 -0
- package/src/utils/tool-call-loop-guard.ts +107 -0
- package/src/utils/tool-choice.ts +101 -0
- package/src/utils/validation.ts +1932 -0
- package/src/utils.ts +492 -0
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
import { isUnexpectedSocketCloseMessage } from "@linxiraos/pi-utils";
|
|
2
|
+
import type { Api, AssistantMessage } from "../types";
|
|
3
|
+
import { AwsCredentialsError } from "./aws";
|
|
4
|
+
import {
|
|
5
|
+
AnthropicConnectionError,
|
|
6
|
+
AnthropicConnectionTimeoutError,
|
|
7
|
+
ProviderHttpError,
|
|
8
|
+
STREAM_ENVELOPE_ERROR_PREFIX,
|
|
9
|
+
} from "./classes";
|
|
10
|
+
import {
|
|
11
|
+
isAccountScopedCapText,
|
|
12
|
+
isOpaqueStatusBody,
|
|
13
|
+
isUsageLimitStatus,
|
|
14
|
+
matchesUsageLimitText,
|
|
15
|
+
parseRateLimitReason,
|
|
16
|
+
} from "./rate-limit";
|
|
17
|
+
|
|
18
|
+
export const Flag = {
|
|
19
|
+
Class: 0x1000,
|
|
20
|
+
ThinkingLoop: 0x0001_0000,
|
|
21
|
+
Transient: 0x0002_0000,
|
|
22
|
+
Timeout: 0x0004_0000,
|
|
23
|
+
UsageLimit: 0x0008_0000,
|
|
24
|
+
StaleResponsesItem: 0x0010_0000,
|
|
25
|
+
MalformedFunctionCall: 0x0020_0000,
|
|
26
|
+
ProviderFinishError: 0x0040_0000,
|
|
27
|
+
ContentBlocked: 0x0000_8000,
|
|
28
|
+
ContextOverflow: 0x0080_0000,
|
|
29
|
+
AuthFailed: 0x0100_0000,
|
|
30
|
+
SilentAbort: 0x0200_0000,
|
|
31
|
+
UserInterrupt: 0x0400_0000,
|
|
32
|
+
Abort: 0x0800_0000,
|
|
33
|
+
/** Strict-tool rejection (400): grammar too large, schema too complex, or structured outputs unsupported by the model/endpoint. */
|
|
34
|
+
Grammar: 0x1000_0000,
|
|
35
|
+
/** Anthropic model/account does not support fast mode / the `speed` parameter. */
|
|
36
|
+
FastModeUnsupported: 0x2000_0000,
|
|
37
|
+
/** OAuth refresh failed definitively — the stored grant is dead, re-login required. */
|
|
38
|
+
OAuthExpiry: 0x4000_0000,
|
|
39
|
+
} as const;
|
|
40
|
+
|
|
41
|
+
export type Flag = (typeof Flag)[keyof typeof Flag];
|
|
42
|
+
|
|
43
|
+
const KIND_MASK =
|
|
44
|
+
Flag.ThinkingLoop |
|
|
45
|
+
Flag.Transient |
|
|
46
|
+
Flag.Timeout |
|
|
47
|
+
Flag.UsageLimit |
|
|
48
|
+
Flag.StaleResponsesItem |
|
|
49
|
+
Flag.MalformedFunctionCall |
|
|
50
|
+
Flag.ProviderFinishError |
|
|
51
|
+
Flag.ContentBlocked |
|
|
52
|
+
Flag.ContextOverflow |
|
|
53
|
+
Flag.AuthFailed |
|
|
54
|
+
Flag.SilentAbort |
|
|
55
|
+
Flag.UserInterrupt |
|
|
56
|
+
Flag.Abort |
|
|
57
|
+
Flag.Grammar |
|
|
58
|
+
Flag.FastModeUnsupported |
|
|
59
|
+
Flag.OAuthExpiry;
|
|
60
|
+
|
|
61
|
+
const RETRIABLE_KINDS =
|
|
62
|
+
Flag.Transient | Flag.UsageLimit | Flag.ThinkingLoop | Flag.StaleResponsesItem | Flag.ProviderFinishError;
|
|
63
|
+
|
|
64
|
+
const OVERFLOW_PATTERNS = [
|
|
65
|
+
/prompt is too long/i, // Anthropic
|
|
66
|
+
/input is too long for requested model/i, // Amazon Bedrock
|
|
67
|
+
/exceeds the context window/i, // OpenAI (Completions & Responses API)
|
|
68
|
+
/input token count.*exceeds the maximum/i, // Google (Gemini)
|
|
69
|
+
/maximum prompt length is \d+/i, // xAI (Grok)
|
|
70
|
+
/reduce the length of the messages/i, // Groq
|
|
71
|
+
/maximum context length is \d+ tokens/i, // OpenRouter (all backends)
|
|
72
|
+
/exceeds the limit of \d+/i, // GitHub Copilot
|
|
73
|
+
/exceeds the available context size/i, // llama.cpp server
|
|
74
|
+
/requested tokens?.*exceed.*context (window|length|size)/i, // llama.cpp / OpenAI-compatible local servers
|
|
75
|
+
/context (window|length|size).*(exceeded|overflow|too small)/i, // Generic local server variants
|
|
76
|
+
/(prompt|input).*(too long|too large).*(context|n_ctx)/i, // llama.cpp phrasing variants
|
|
77
|
+
/requested tokens?.*(exceeds?|greater than).*(n_ctx|context)/i, // llama.cpp n_ctx variants
|
|
78
|
+
/greater than the context length/i, // LM Studio
|
|
79
|
+
/context window exceeds limit/i, // MiniMax
|
|
80
|
+
/exceeded model token limit/i, // Kimi For Coding
|
|
81
|
+
/context[_ ]length[_ ]exceeded/i, // Generic fallback
|
|
82
|
+
/too many tokens/i, // Generic fallback
|
|
83
|
+
/token limit exceeded/i, // Generic fallback
|
|
84
|
+
/request_too_large/i, // Anthropic 413 (request body too large)
|
|
85
|
+
/request exceeds the maximum size/i, // Anthropic 413 variant
|
|
86
|
+
/payload too large/i, // Generic HTTP 413 variant
|
|
87
|
+
/entity too large/i, // Generic HTTP 413 variant
|
|
88
|
+
/\b413\b.*\b(request|payload|entity)\b.*\btoo large\b/i, // "413 Request Entity Too Large" variants
|
|
89
|
+
/model_context_window_exceeded/i, // z.ai non-standard finish_reason surfaced as error text
|
|
90
|
+
/prompt filled the context window/i, // Ollama OpenAI-compatible empty length completion
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
const OVERFLOW_NO_BODY_PATTERN = /\b4(00|13)\s*(status code)?\s*\(no body\)/i;
|
|
94
|
+
const TIMEOUT_PATTERN = /\b(?:operation\s+)?timed?\s*out\b|\btimeout\b|\bstream stall\b/i;
|
|
95
|
+
const TRANSIENT_ENVELOPE_PATTERN = /anthropic stream envelope error:/i;
|
|
96
|
+
const TRANSIENT_ENVELOPE_BEFORE_START_PATTERN = /before message_start/i;
|
|
97
|
+
export const STREAM_READ_ERROR_PATTERN = /stream[_ -]?read[_ -]?error/i;
|
|
98
|
+
export const TRANSIENT_TRANSPORT_PATTERN =
|
|
99
|
+
/\b(?:no[_ -]?capacity|(?:high|peak)[ _-]?demand|(?:at|over|insufficient)[ _-]?capacity|capacity[ _-]?(?:exceeded|exhausted)|peak[ _-]?load)\b|overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|retry your request|network.?error|connection.?error|connection.?refused|unable.?to.?connect\.\s*is the computer able to access the url\?|other side closed|fetch failed|upstream.?connect|upstream.?request.?failed|reset before headers|socket hang up|timed? out|timeout|terminated|retry delay|stream stall|no error details in response|HTTP2(?:StreamReset|RefusedStream|EnhanceYourCalm)|malformed.?function.?call/i;
|
|
100
|
+
const AUTH_FAILURE_PATTERN =
|
|
101
|
+
/\b(?:401|403|unauthorized|forbidden|authentication|auth[_ ]?unavailable|no auth available|(?:invalid|no)[_ ]?api[_ ]?key)\b/i;
|
|
102
|
+
const MALFORMED_FUNCTION_CALL_PATTERN = /\bmalformed.?function.?call\b/i;
|
|
103
|
+
const PROVIDER_FINISH_ERROR_PATTERN = /\bProvider (?:returned error finish_reason|finish_reason:\s*error)\b/i;
|
|
104
|
+
const CONTENT_FILTER_PATTERN = /\b(?:incomplete:\s*)?content_filter\b/i;
|
|
105
|
+
const STALE_RESPONSE_ITEM_PATTERNS = [/\bItem with id ['"][^'"]+['"] not found\.?/i, /previous[ _]?response/i] as const;
|
|
106
|
+
const STALE_RESPONSE_ITEM_DETAIL_PATTERN = /not[ _]?found|invalid|expired|stale|zero[ _-]?data[ _-]?retention/i;
|
|
107
|
+
/**
|
|
108
|
+
* Local llama.cpp / Ollama deterministic tool-call argument JSON parse failure.
|
|
109
|
+
* The model emitted invalid JSON in a tool call and the server returned HTTP 500
|
|
110
|
+
* with this exact text — replaying the same prompt yields the same malformed
|
|
111
|
+
* output, so callers strip {@link Flag.Transient} when this matches.
|
|
112
|
+
*/
|
|
113
|
+
export const LLAMA_CPP_TOOL_CALL_PARSE_PATTERN =
|
|
114
|
+
/failed to parse tool call arguments as json|\[json\.exception\.parse_error\.101\]/i;
|
|
115
|
+
|
|
116
|
+
// Copilot fleet skew: HTTP 400 `model_not_supported` can reject a model that
|
|
117
|
+
// `/models` advertised on the same host when the request lands on a stale
|
|
118
|
+
// replica. `model_not_available_for_integrator` is deliberately excluded:
|
|
119
|
+
// GitHub also uses it for stable per-integrator entitlement denials and includes
|
|
120
|
+
// that integrator's actionable `Available models` list in the response.
|
|
121
|
+
const COPILOT_TRANSIENT_MODEL_CODES: Record<string, true> = {
|
|
122
|
+
model_not_supported: true,
|
|
123
|
+
};
|
|
124
|
+
const COPILOT_TRANSIENT_MODEL_PATTERN = /model_not_supported/i;
|
|
125
|
+
// Anthropic strict-tool grammar too large / schema too complex (400 invalid_request_error).
|
|
126
|
+
// Feature-gated deployments (Azure Foundry, Baseten, …) reject `strict: true`
|
|
127
|
+
// tools outright when the hosted model lacks structured outputs, e.g.
|
|
128
|
+
// "structured_outputs not supported" — without an invalid_request_error wrapper.
|
|
129
|
+
const GRAMMAR_TOO_LARGE_PATTERN = /compiled grammar/i;
|
|
130
|
+
const GRAMMAR_TOO_LARGE_DETAIL_PATTERN = /too large/i;
|
|
131
|
+
const SCHEMA_TOO_COMPLEX_PATTERN = /schema/i;
|
|
132
|
+
const SCHEMA_TOO_COMPLEX_DETAIL_PATTERN = /too complex/i;
|
|
133
|
+
const SCHEMA_COMPILE_PATTERN = /compil/i;
|
|
134
|
+
const INVALID_REQUEST_PATTERN = /invalid_request_error/i;
|
|
135
|
+
const STRUCTURED_OUTPUTS_PATTERN = /structured[_ -]?outputs?/i;
|
|
136
|
+
const FEATURE_NOT_SUPPORTED_PATTERN = /not (?:supported|available|enabled)|unsupported|does(?: not|n'?t) support/i;
|
|
137
|
+
const ANTHROPIC_STRICT_FIELD_PATTERN = /\btools\.\d+\.custom\.strict\b/i;
|
|
138
|
+
const EXTRA_INPUTS_NOT_PERMITTED_PATTERN = /extra inputs? (?:are|is) not permitted/i;
|
|
139
|
+
// Anthropic fast-mode unsupported: 400 rejecting `speed`, or 429 rate_limit_error
|
|
140
|
+
// because the account lacks the extra-usage entitlement fast mode requires.
|
|
141
|
+
const FAST_MODE_SPEED_PARAM_PATTERN = /\bspeed\b/i;
|
|
142
|
+
const FAST_MODE_NOT_SUPPORTED_PATTERN = /not support/i;
|
|
143
|
+
const FAST_MODE_RATE_LIMIT_PATTERN = /rate_limit_error/i;
|
|
144
|
+
const FAST_MODE_ENTITLEMENT_PATTERN = /fast mode/i;
|
|
145
|
+
// Definitive OAuth refresh failure — the stored grant/client is dead.
|
|
146
|
+
const OAUTH_DEFINITIVE_FAILURE_PATTERN =
|
|
147
|
+
/invalid_grant|invalid_token|unauthorized_client|\brevoked\b|refresh[\s_]?token.*expired/i;
|
|
148
|
+
const OAUTH_TRANSIENT_FAILURE_PATTERN =
|
|
149
|
+
/timeout|network|fetch failed|ECONN(?:REFUSED|RESET)|ETIMEDOUT|EAI_AGAIN|socket hang up|\b(?:408|425|429|5\d{2})\b|rate.?limit|too many requests|temporar|unavailable|forbidden|permission_denied|cloudflare|captcha/i;
|
|
150
|
+
const OAUTH_HTTP_AUTH_PATTERN = /\b401\b/;
|
|
151
|
+
|
|
152
|
+
function matchesStrictToolsRejection(message: string, errorStatus: number | undefined): boolean {
|
|
153
|
+
if (errorStatus !== 400) return false;
|
|
154
|
+
if (ANTHROPIC_STRICT_FIELD_PATTERN.test(message) && EXTRA_INPUTS_NOT_PERMITTED_PATTERN.test(message)) {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
if (STRUCTURED_OUTPUTS_PATTERN.test(message) && FEATURE_NOT_SUPPORTED_PATTERN.test(message)) return true;
|
|
158
|
+
if (!INVALID_REQUEST_PATTERN.test(message)) return false;
|
|
159
|
+
const grammarTooLarge = GRAMMAR_TOO_LARGE_PATTERN.test(message) && GRAMMAR_TOO_LARGE_DETAIL_PATTERN.test(message);
|
|
160
|
+
const schemaTooComplex =
|
|
161
|
+
SCHEMA_TOO_COMPLEX_PATTERN.test(message) &&
|
|
162
|
+
SCHEMA_TOO_COMPLEX_DETAIL_PATTERN.test(message) &&
|
|
163
|
+
SCHEMA_COMPILE_PATTERN.test(message);
|
|
164
|
+
return grammarTooLarge || schemaTooComplex;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function matchesFastModeUnsupported(message: string, errorStatus: number | undefined): boolean {
|
|
168
|
+
if (errorStatus !== 400 && errorStatus !== 429) return false;
|
|
169
|
+
if (
|
|
170
|
+
errorStatus === 400 &&
|
|
171
|
+
INVALID_REQUEST_PATTERN.test(message) &&
|
|
172
|
+
FAST_MODE_SPEED_PARAM_PATTERN.test(message) &&
|
|
173
|
+
FAST_MODE_NOT_SUPPORTED_PATTERN.test(message)
|
|
174
|
+
) {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
return (
|
|
178
|
+
errorStatus === 429 && FAST_MODE_RATE_LIMIT_PATTERN.test(message) && FAST_MODE_ENTITLEMENT_PATTERN.test(message)
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Whether an OAuth refresh error message means the grant is definitively dead. */
|
|
183
|
+
export function isOAuthExpiry(errorMessage: string): boolean {
|
|
184
|
+
if (OAUTH_DEFINITIVE_FAILURE_PATTERN.test(errorMessage)) return true;
|
|
185
|
+
return OAUTH_HTTP_AUTH_PATTERN.test(errorMessage) && !OAUTH_TRANSIENT_FAILURE_PATTERN.test(errorMessage);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const ERROR_KIND_LABELS: readonly [Flag, string][] = [
|
|
189
|
+
[Flag.ThinkingLoop, "thinking-loop"],
|
|
190
|
+
[Flag.Transient, "transient"],
|
|
191
|
+
[Flag.Timeout, "timeout"],
|
|
192
|
+
[Flag.UsageLimit, "usage-limit"],
|
|
193
|
+
[Flag.StaleResponsesItem, "stale-responses-item"],
|
|
194
|
+
[Flag.MalformedFunctionCall, "malformed-function-call"],
|
|
195
|
+
[Flag.ProviderFinishError, "provider-finish-error"],
|
|
196
|
+
[Flag.ContentBlocked, "content-blocked"],
|
|
197
|
+
[Flag.ContextOverflow, "context-overflow"],
|
|
198
|
+
[Flag.AuthFailed, "auth-failed"],
|
|
199
|
+
[Flag.SilentAbort, "silent-abort"],
|
|
200
|
+
[Flag.UserInterrupt, "user-interrupt"],
|
|
201
|
+
[Flag.Abort, "abort"],
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
const STATUS_MESSAGE_PATTERNS = [
|
|
205
|
+
/\bstatus(?:_code)?[:=]\s*(\d{3})\b/i,
|
|
206
|
+
/\bstatus\s+(\d{3})\b/i,
|
|
207
|
+
/\bHTTP\s+(\d{3})\b/i,
|
|
208
|
+
/\b(?:error|failed)\s*[:=]?\s*(\d{3})\b/i,
|
|
209
|
+
/(?:^|\s)(\d{3})\s+(?:[A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)/,
|
|
210
|
+
] as const;
|
|
211
|
+
|
|
212
|
+
export function create(...flags: number[]): number {
|
|
213
|
+
let bits = 0;
|
|
214
|
+
for (const f of flags) bits |= f;
|
|
215
|
+
return bits | Flag.Class;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function is(id: number | undefined, flag: Flag): boolean {
|
|
219
|
+
return ((id ?? 0) & flag) !== 0;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function retriable(id: number | undefined, opts?: { replayUnsafe?: boolean }): boolean {
|
|
223
|
+
if (is(id, Flag.ContentBlocked)) return false;
|
|
224
|
+
if (opts?.replayUnsafe) return false;
|
|
225
|
+
if (is(id, Flag.MalformedFunctionCall)) return true;
|
|
226
|
+
return ((id ?? 0) & RETRIABLE_KINDS) !== 0;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function isClassified(id: number | undefined): boolean {
|
|
230
|
+
return ((id ?? 0) & Flag.Class) !== 0;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function statusFromId(id: number | undefined): number | undefined {
|
|
234
|
+
return id && !isClassified(id) ? id : undefined;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function status(error: unknown): number | undefined {
|
|
238
|
+
return statusInternal(error, 0);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function statusInternal(error: unknown, depth: number): number | undefined {
|
|
242
|
+
if (depth > 2 || error === undefined || error === null) return undefined;
|
|
243
|
+
if (typeof error === "object") {
|
|
244
|
+
const errObj = error as Record<string, unknown>;
|
|
245
|
+
|
|
246
|
+
if (typeof errObj.status === "number" && errObj.status >= 100 && errObj.status <= 599) {
|
|
247
|
+
return errObj.status;
|
|
248
|
+
}
|
|
249
|
+
if (typeof errObj.statusCode === "number" && errObj.statusCode >= 100 && errObj.statusCode <= 599) {
|
|
250
|
+
return errObj.statusCode;
|
|
251
|
+
}
|
|
252
|
+
if (typeof errObj.response === "object" && errObj.response !== null) {
|
|
253
|
+
const resp = errObj.response as Record<string, unknown>;
|
|
254
|
+
if (typeof resp.status === "number" && resp.status >= 100 && resp.status <= 599) {
|
|
255
|
+
return resp.status;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if ("cause" in errObj) {
|
|
260
|
+
const nested = statusInternal(errObj.cause, depth + 1);
|
|
261
|
+
if (nested !== undefined) return nested;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (error instanceof Error || (typeof error === "object" && error !== null && "message" in error)) {
|
|
266
|
+
const message = (error as { message: string }).message;
|
|
267
|
+
if (typeof message === "string") {
|
|
268
|
+
for (const pattern of STATUS_MESSAGE_PATTERNS) {
|
|
269
|
+
const match = pattern.exec(message);
|
|
270
|
+
if (match) {
|
|
271
|
+
const code = parseInt(match[1], 10);
|
|
272
|
+
if (code >= 100 && code <= 599) return code;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function isStreamReadErrorText(text: string): boolean {
|
|
281
|
+
return STREAM_READ_ERROR_PATTERN.test(text);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** Persisted-text form of {@link isStreamEnvelopeError}: recognizes the
|
|
285
|
+
* prefix-tagged envelope diagnostic on an aborted turn's `errorMessage` /
|
|
286
|
+
* `stopDetails.explanation` so loop-level salvage can classify it after the
|
|
287
|
+
* original `Error` instance is gone. */
|
|
288
|
+
export function isStreamEnvelopeErrorText(text: string): boolean {
|
|
289
|
+
return text.includes(STREAM_ENVELOPE_ERROR_PREFIX);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function isTransientErrorText(text: string): boolean {
|
|
293
|
+
return (
|
|
294
|
+
isUnexpectedSocketCloseMessage(text) ||
|
|
295
|
+
isStreamReadErrorText(text) ||
|
|
296
|
+
(TRANSIENT_ENVELOPE_PATTERN.test(text) && TRANSIENT_ENVELOPE_BEFORE_START_PATTERN.test(text)) ||
|
|
297
|
+
TRANSIENT_TRANSPORT_PATTERN.test(text)
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function isTimeoutText(text: string): boolean {
|
|
302
|
+
return TIMEOUT_PATTERN.test(text);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function isAuthFailureText(text: string): boolean {
|
|
306
|
+
return AUTH_FAILURE_PATTERN.test(text);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function isStaleResponsesText(text: string): boolean {
|
|
310
|
+
return (
|
|
311
|
+
STALE_RESPONSE_ITEM_PATTERNS[0].test(text) ||
|
|
312
|
+
(STALE_RESPONSE_ITEM_PATTERNS[1].test(text) && STALE_RESPONSE_ITEM_DETAIL_PATTERN.test(text))
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function isMalformedFunctionCallText(text: string): boolean {
|
|
317
|
+
return MALFORMED_FUNCTION_CALL_PATTERN.test(text);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function isProviderFinishErrorText(text: string): boolean {
|
|
321
|
+
return PROVIDER_FINISH_ERROR_PATTERN.test(text);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function isContentBlockedText(text: string): boolean {
|
|
325
|
+
return CONTENT_FILTER_PATTERN.test(text);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function matchesOverflowText(text: string): boolean {
|
|
329
|
+
return OVERFLOW_PATTERNS.some(p => p.test(text)) || OVERFLOW_NO_BODY_PATTERN.test(text);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function classifyText(errorMessage: string | undefined, errorStatus: number | undefined, api?: Api): number {
|
|
333
|
+
let kinds = 0;
|
|
334
|
+
if (errorMessage) {
|
|
335
|
+
if (matchesOverflowText(errorMessage)) kinds |= Flag.ContextOverflow;
|
|
336
|
+
if (isMalformedFunctionCallText(errorMessage)) kinds |= Flag.MalformedFunctionCall;
|
|
337
|
+
if (isProviderFinishErrorText(errorMessage)) kinds |= Flag.ProviderFinishError;
|
|
338
|
+
if (isContentBlockedText(errorMessage)) kinds |= Flag.ContentBlocked;
|
|
339
|
+
if (isAuthFailureText(errorMessage)) kinds |= Flag.AuthFailed;
|
|
340
|
+
|
|
341
|
+
const statusClean = errorStatus ? errorStatus : (status({ message: errorMessage }) ?? undefined);
|
|
342
|
+
const cleanMessage = errorMessage;
|
|
343
|
+
const isOpaque = isOpaqueStatusBody(cleanMessage);
|
|
344
|
+
|
|
345
|
+
const isLimitStatus = isUsageLimitStatus(statusClean);
|
|
346
|
+
const reason = parseRateLimitReason(cleanMessage);
|
|
347
|
+
// Concurrency caps (e.g. Vertex "Online prediction concurrent requests
|
|
348
|
+
// quota exceeded") are shed-and-backoff, not credential-rotatable —
|
|
349
|
+
// exclude them even when the quota-worded phrasing matches the generic
|
|
350
|
+
// usage-limit text matcher, whose `quota.?exceeded` arm would otherwise
|
|
351
|
+
// set Flag.UsageLimit and burn a healthy sibling credential. HTTP 402 is
|
|
352
|
+
// excluded from this gate: it is categorically an account-billing cap, so
|
|
353
|
+
// a 402 whose body merely mentions concurrency still classifies as a
|
|
354
|
+
// usage limit, mirroring isUsageLimitOutcome.
|
|
355
|
+
const isBillingCapStatus = statusClean === 402;
|
|
356
|
+
const concurrencyExcluded = reason === "CONCURRENT_LIMIT" && !isBillingCapStatus;
|
|
357
|
+
if (
|
|
358
|
+
!concurrencyExcluded &&
|
|
359
|
+
(matchesUsageLimitText(cleanMessage) ||
|
|
360
|
+
((statusClean === 403 || statusClean === undefined) && isAccountScopedCapText(cleanMessage)) ||
|
|
361
|
+
(isLimitStatus &&
|
|
362
|
+
(isOpaque || reason === "QUOTA_EXHAUSTED" || (isBillingCapStatus && reason === "CONCURRENT_LIMIT"))))
|
|
363
|
+
) {
|
|
364
|
+
kinds |= Flag.UsageLimit;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (isTimeoutText(errorMessage)) kinds |= Flag.Transient | Flag.Timeout;
|
|
368
|
+
else if (isTransientErrorText(errorMessage)) kinds |= Flag.Transient;
|
|
369
|
+
// A concurrency cap (e.g. Vertex "Online prediction concurrent requests
|
|
370
|
+
// quota exceeded") is transient — shed-and-backoff. The bare wording need
|
|
371
|
+
// not match TRANSIENT_TRANSPORT_PATTERN, so flag it explicitly to keep
|
|
372
|
+
// AIError.retriable from treating the temporary cap as terminal.
|
|
373
|
+
if (reason === "CONCURRENT_LIMIT") kinds |= Flag.Transient;
|
|
374
|
+
if ((api === "openai-responses" || api === "openai-codex-responses") && isStaleResponsesText(errorMessage)) {
|
|
375
|
+
kinds |= Flag.StaleResponsesItem;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Copilot's `model_not_supported` fleet-skew rejection is transient.
|
|
379
|
+
if (statusClean === 400 && COPILOT_TRANSIENT_MODEL_PATTERN.test(cleanMessage)) kinds |= Flag.Transient;
|
|
380
|
+
if (matchesStrictToolsRejection(cleanMessage, statusClean)) kinds |= Flag.Grammar;
|
|
381
|
+
if (matchesFastModeUnsupported(cleanMessage, statusClean)) kinds |= Flag.FastModeUnsupported;
|
|
382
|
+
}
|
|
383
|
+
if (kinds !== 0) return create(kinds);
|
|
384
|
+
const fallbackStatus = errorStatus ?? (errorMessage ? status({ message: errorMessage }) : undefined);
|
|
385
|
+
if (fallbackStatus === 401 || fallbackStatus === 403) return create(Flag.AuthFailed);
|
|
386
|
+
return fallbackStatus ?? 0;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export function classify(error: unknown, api?: Api): number {
|
|
390
|
+
let kinds = 0;
|
|
391
|
+
const seen = new Set<object>();
|
|
392
|
+
let link: unknown = error;
|
|
393
|
+
while (link !== undefined && link !== null) {
|
|
394
|
+
if (typeof link === "object") {
|
|
395
|
+
if (seen.has(link)) break;
|
|
396
|
+
seen.add(link);
|
|
397
|
+
|
|
398
|
+
if ("errorId" in link && typeof (link as { errorId: unknown }).errorId === "number") {
|
|
399
|
+
kinds |= (link as { errorId: number }).errorId & KIND_MASK;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (link instanceof AwsCredentialsError) {
|
|
404
|
+
kinds |= Flag.AuthFailed;
|
|
405
|
+
} else if (link instanceof AnthropicConnectionTimeoutError) {
|
|
406
|
+
kinds |= Flag.Timeout | Flag.Transient;
|
|
407
|
+
} else if (link instanceof AnthropicConnectionError) {
|
|
408
|
+
kinds |= Flag.Transient;
|
|
409
|
+
} else if (
|
|
410
|
+
typeof link === "object" &&
|
|
411
|
+
"name" in link &&
|
|
412
|
+
(link as { name: string }).name === "CodexWebSocketTransportError"
|
|
413
|
+
) {
|
|
414
|
+
kinds |= Flag.Transient;
|
|
415
|
+
} else if (
|
|
416
|
+
link instanceof Error &&
|
|
417
|
+
link.name === "CodexProviderStreamError" &&
|
|
418
|
+
"retryable" in link &&
|
|
419
|
+
(link as { retryable: unknown }).retryable === true
|
|
420
|
+
) {
|
|
421
|
+
kinds |= Flag.Transient;
|
|
422
|
+
} else if (link instanceof ProviderHttpError) {
|
|
423
|
+
let linkKinds = 0;
|
|
424
|
+
const { status: codeStatus, code } = link;
|
|
425
|
+
if (code === "usage_limit_reached" || code === "insufficient_quota") {
|
|
426
|
+
linkKinds |= Flag.UsageLimit;
|
|
427
|
+
}
|
|
428
|
+
if (code === "overloaded_error" || code === "rate_limit_error") {
|
|
429
|
+
linkKinds |= Flag.Transient;
|
|
430
|
+
}
|
|
431
|
+
if (
|
|
432
|
+
(codeStatus === 401 || codeStatus === 403) &&
|
|
433
|
+
!(codeStatus === 403 && parseRateLimitReason(link.message) === "CONCURRENT_LIMIT")
|
|
434
|
+
) {
|
|
435
|
+
linkKinds |= Flag.AuthFailed;
|
|
436
|
+
} else if (codeStatus === 429) {
|
|
437
|
+
if ((linkKinds & Flag.UsageLimit) === 0) {
|
|
438
|
+
linkKinds |= Flag.Transient;
|
|
439
|
+
}
|
|
440
|
+
} else if (codeStatus >= 500) {
|
|
441
|
+
linkKinds |= Flag.Transient;
|
|
442
|
+
}
|
|
443
|
+
kinds |= linkKinds;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
let linkMessage: string | undefined;
|
|
447
|
+
if (link instanceof Error) {
|
|
448
|
+
linkMessage = link.message;
|
|
449
|
+
} else if (typeof link === "string") {
|
|
450
|
+
linkMessage = link;
|
|
451
|
+
} else if (
|
|
452
|
+
typeof link === "object" &&
|
|
453
|
+
"message" in link &&
|
|
454
|
+
typeof (link as { message: unknown }).message === "string"
|
|
455
|
+
) {
|
|
456
|
+
linkMessage = (link as { message: string }).message;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const textId = classifyText(linkMessage, status(link), api);
|
|
460
|
+
kinds |= textId & KIND_MASK;
|
|
461
|
+
|
|
462
|
+
link = typeof link === "object" && "cause" in link ? (link as { cause: unknown }).cause : undefined;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return kinds !== 0 ? create(kinds) : (status(error) ?? 0);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Whether an error (or message string) classifies as an account usage/quota
|
|
470
|
+
* limit — the persistent, credential-rotation-worthy kind. This is the public
|
|
471
|
+
* accessor for {@link Flag.UsageLimit}; prefer it over re-running message
|
|
472
|
+
* regexes at call sites.
|
|
473
|
+
*/
|
|
474
|
+
export function isUsageLimit(error: unknown, api?: Api): boolean {
|
|
475
|
+
return is(classify(error, api), Flag.UsageLimit);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Strict-tool rejection: grammar too large, schema too complex, or structured
|
|
480
|
+
* outputs unsupported by the model/endpoint.
|
|
481
|
+
* Accessor for {@link Flag.Grammar}.
|
|
482
|
+
*/
|
|
483
|
+
export function isGrammarError(error: unknown): boolean {
|
|
484
|
+
return is(classify(error), Flag.Grammar);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Anthropic model/account does not support fast mode / the `speed` parameter.
|
|
489
|
+
* Accessor for {@link Flag.FastModeUnsupported}.
|
|
490
|
+
*/
|
|
491
|
+
export function isFastModeUnsupported(error: unknown): boolean {
|
|
492
|
+
return is(classify(error), Flag.FastModeUnsupported);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Depth-bounded search for a provider error `code`. SDK error objects keep the
|
|
497
|
+
* parsed response body on `.error`, and Copilot's body is itself
|
|
498
|
+
* `{ error: { code } }`, so the code sits up to two envelopes below the thrown
|
|
499
|
+
* error depending on which SDK produced it.
|
|
500
|
+
*/
|
|
501
|
+
function providerErrorCode(error: object): string | undefined {
|
|
502
|
+
let node: object = error;
|
|
503
|
+
for (let depth = 0; depth < 3; depth++) {
|
|
504
|
+
if ("code" in node && typeof node.code === "string") return node.code;
|
|
505
|
+
if (!("error" in node)) return undefined;
|
|
506
|
+
const nested: unknown = node.error;
|
|
507
|
+
if (!nested || typeof nested !== "object") return undefined;
|
|
508
|
+
node = nested;
|
|
509
|
+
}
|
|
510
|
+
return undefined;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* GitHub Copilot 400 `model_not_supported` response for a model advertised by
|
|
515
|
+
* `/models` — transient fleet skew, not a malformed request. Reads the
|
|
516
|
+
* structural `code` through the SDK/body envelopes, then falls back to the
|
|
517
|
+
* stringified body both SDK families put in `message`.
|
|
518
|
+
*/
|
|
519
|
+
export function isCopilotTransientModelError(error: unknown): boolean {
|
|
520
|
+
if (!error || typeof error !== "object" || status(error) !== 400) return false;
|
|
521
|
+
const code = providerErrorCode(error);
|
|
522
|
+
// `Object.hasOwn`, not a bare index: `code` is provider-controlled, and a
|
|
523
|
+
// prototype key (`__proto__`, `toString`, …) would otherwise read truthy.
|
|
524
|
+
if (code !== undefined && Object.hasOwn(COPILOT_TRANSIENT_MODEL_CODES, code)) return true;
|
|
525
|
+
const message: unknown = "message" in error ? error.message : undefined;
|
|
526
|
+
return typeof message === "string" && COPILOT_TRANSIENT_MODEL_PATTERN.test(message);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export function classifyMessage(message: {
|
|
530
|
+
api?: Api;
|
|
531
|
+
errorId?: number;
|
|
532
|
+
errorMessage?: string;
|
|
533
|
+
errorStatus?: number;
|
|
534
|
+
}): number {
|
|
535
|
+
const existingId = message.errorId;
|
|
536
|
+
const currentStatus = message.errorStatus ?? statusFromId(existingId);
|
|
537
|
+
const textId = classifyText(message.errorMessage, currentStatus, message.api);
|
|
538
|
+
|
|
539
|
+
let kinds = ((existingId ?? 0) | textId) & KIND_MASK;
|
|
540
|
+
if (message.errorMessage && LLAMA_CPP_TOOL_CALL_PARSE_PATTERN.test(message.errorMessage)) {
|
|
541
|
+
// Deterministic local-model tool-call JSON parse failure: HTTP 500 is misleading
|
|
542
|
+
// because the same prompt reproduces the same malformed output, so the agent-level
|
|
543
|
+
// auto-retry would loop. Strip Transient so the recovery message surfaces immediately.
|
|
544
|
+
kinds &= ~Flag.Transient;
|
|
545
|
+
}
|
|
546
|
+
const id = kinds !== 0 ? create(kinds) : (statusFromId(textId) ?? statusFromId(existingId) ?? currentStatus ?? 0);
|
|
547
|
+
|
|
548
|
+
message.errorId = id;
|
|
549
|
+
return id;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
export function attach<E extends object>(error: E, id: number): E {
|
|
553
|
+
Object.defineProperty(error, "errorId", { value: id, enumerable: false, configurable: true });
|
|
554
|
+
return error;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
export function isContextOverflow(message: AssistantMessage, contextWindow?: number): boolean {
|
|
558
|
+
if (is(message.errorId, Flag.ContextOverflow)) return true;
|
|
559
|
+
if (contextWindow) {
|
|
560
|
+
const inputTokens = message.usage.input + message.usage.cacheRead + message.usage.cacheWrite;
|
|
561
|
+
if (inputTokens > contextWindow) return true;
|
|
562
|
+
}
|
|
563
|
+
return message.stopReason === "error" && !!message.errorMessage && matchesOverflowText(message.errorMessage);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
export function stringify(id: number | undefined): string {
|
|
567
|
+
if (!id) return "none";
|
|
568
|
+
if (!isClassified(id)) return `status:${id}`;
|
|
569
|
+
const labels = ERROR_KIND_LABELS.filter(([kind]) => is(id, kind)).map(([, label]) => label);
|
|
570
|
+
return labels.length > 0 ? labels.join("|") : `classified:0x${id.toString(16)}`;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const STREAM_PARSE_TRUNCATION_PATTERN =
|
|
574
|
+
/unterminated string|unexpected end of json input|unexpected end of data|unexpected eof|end of file|eof while parsing|truncated/i;
|
|
575
|
+
const STREAM_PARSE_DIAGNOSTIC_PATTERN =
|
|
576
|
+
/(?:json parse error:\s*(?:unterminated string|unexpected end of json input|unexpected end of data|unexpected eof|end of file|eof while parsing|truncated)|json\.parse:\s*(?:unterminated string|unexpected end of data)|unexpected end of json input|unexpected eof|eof while parsing)/i;
|
|
577
|
+
const STREAM_EVENT_ORDER_PATTERN = /stream event order|before message_start/i;
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Transient stream corruption where the response was truncated mid-JSON.
|
|
581
|
+
*
|
|
582
|
+
* Strings (persisted `stopDetails.explanation`/`errorMessage` diagnostics) are matched with the
|
|
583
|
+
* stricter {@link STREAM_PARSE_DIAGNOSTIC_PATTERN} — bare "truncated"/"end of file" text is too
|
|
584
|
+
* low-signal to trust once detached from a live transport `Error`, which keeps the broad pattern.
|
|
585
|
+
*/
|
|
586
|
+
export function isTransientStreamParseError(error: unknown): boolean {
|
|
587
|
+
if (typeof error === "string") return STREAM_PARSE_DIAGNOSTIC_PATTERN.test(error);
|
|
588
|
+
return error instanceof Error && STREAM_PARSE_TRUNCATION_PATTERN.test(error.message);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/** Any malformed stream-envelope error (prefix-tagged or out-of-order events). */
|
|
592
|
+
export function isStreamEnvelopeError(error: unknown): boolean {
|
|
593
|
+
return (
|
|
594
|
+
error instanceof Error &&
|
|
595
|
+
(error.message.includes(STREAM_ENVELOPE_ERROR_PREFIX) || STREAM_EVENT_ORDER_PATTERN.test(error.message))
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/** Stream-envelope errors safe to retry against the provider (event ordering only). */
|
|
600
|
+
export function isRetryableStreamEnvelopeError(error: unknown): boolean {
|
|
601
|
+
return error instanceof Error && STREAM_EVENT_ORDER_PATTERN.test(error.message);
|
|
602
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type CapturedHttpErrorResponse,
|
|
3
|
+
finalizeErrorMessage,
|
|
4
|
+
type RawHttpRequestDump,
|
|
5
|
+
rewriteCopilotError,
|
|
6
|
+
} from "../utils/http-inspector";
|
|
7
|
+
import { formatErrorMessageWithRetryAfter } from "../utils/retry-after";
|
|
8
|
+
import { LLAMA_CPP_TOOL_CALL_PARSE_PATTERN } from "./flags";
|
|
9
|
+
|
|
10
|
+
function rewriteOllamaToolCallJsonError(message: string): string {
|
|
11
|
+
if (!LLAMA_CPP_TOOL_CALL_PARSE_PATTERN.test(message)) return message;
|
|
12
|
+
return `Local Ollama model emitted malformed tool-call JSON and llama.cpp rejected it (HTTP 500). This is usually a deterministic model-output failure after context degradation, not a transient server outage; reload the model or reduce context, then retry.\n${message}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Inputs that steer {@link formatMessage}'s formatter selection. */
|
|
16
|
+
export interface FormatMessageOptions {
|
|
17
|
+
/** When present, the raw request is dumped into the message for 400-class failures. */
|
|
18
|
+
rawRequestDump?: RawHttpRequestDump;
|
|
19
|
+
/** Captured non-2xx response body, appended to the message when available. */
|
|
20
|
+
capturedErrorResponse?: CapturedHttpErrorResponse;
|
|
21
|
+
/** Provider id; gates provider-specific user-facing rewrites. */
|
|
22
|
+
provider?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Format a provider error into a user-facing message, unifying the three
|
|
27
|
+
* formatters: lightweight retry-after extraction, the raw-dump finalizer, and
|
|
28
|
+
* the copilot rewrite.
|
|
29
|
+
*
|
|
30
|
+
* Selection is driven by inputs, not a mode flag: a `rawRequestDump` routes
|
|
31
|
+
* through {@link finalizeErrorMessage} (retry-after + raw dump + captured body),
|
|
32
|
+
* otherwise the lightweight {@link formatErrorMessageWithRetryAfter} is used.
|
|
33
|
+
*/
|
|
34
|
+
export async function formatMessage(error: unknown, opts: FormatMessageOptions = {}): Promise<string> {
|
|
35
|
+
let message = opts.rawRequestDump
|
|
36
|
+
? await finalizeErrorMessage(error, opts.rawRequestDump, opts.capturedErrorResponse)
|
|
37
|
+
: formatErrorMessageWithRetryAfter(error);
|
|
38
|
+
if (opts.provider === "github-copilot") {
|
|
39
|
+
message = rewriteCopilotError(message, error, opts.provider);
|
|
40
|
+
}
|
|
41
|
+
if (opts.provider === "ollama") {
|
|
42
|
+
message = rewriteOllamaToolCallJsonError(message);
|
|
43
|
+
}
|
|
44
|
+
return message;
|
|
45
|
+
}
|