diff --git a/CHANGELOG.md b/CHANGELOG.md index 129d5370c..9cfa0db89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added privacy-scoped setup wizard funnel and Docker startup-failure telemetry with deployment identity handoff, Node.js 20.20.0 support, and cross-platform end-to-end test coverage. [#1653](https://github.com/sourcebot-dev/sourcebot/pull/1653) +- [EE] Added per-model retry and fallback configuration for Ask inference requests, with detailed provider error reporting surfaced through Ask, the MCP `ask_codebase` tool, and the blocking chat API. [#1657](https://github.com/sourcebot-dev/sourcebot/pull/1657) ### Fixed - Prevented browser performance instrumentation from breaking code views when `performance.measure()` returns no value. [#1665](https://github.com/sourcebot-dev/sourcebot/pull/1665) diff --git a/docs/docs/configuration/language-model-providers.mdx b/docs/docs/configuration/language-model-providers.mdx index 032e38e8c..54a41d4b4 100644 --- a/docs/docs/configuration/language-model-providers.mdx +++ b/docs/docs/configuration/language-model-providers.mdx @@ -390,6 +390,57 @@ You can pass custom headers to the language model provider by using the `headers ``` +# Retry and fallbacks + +If an inference request fails with a transient error (a network error, or a `408`, `429`, or `5xx` response), Sourcebot retries the request with exponential backoff. You can tune this behavior per model with the `retry` field. If a model keeps failing, Sourcebot tries the models you list in `fallbackModels` in order. Fallbacks apply to programmatic Ask requests (the MCP `ask_codebase` tool and the blocking chat API). Interactive chat streams retry but stay on the selected model. + +```json wrap icon="code" Example config with retry and fallbacks +{ + "$schema": "https://raw.githubusercontent.com/sourcebot-dev/sourcebot/main/schemas/v3/index.json", + "models": [ + { + "provider": "openai", + "model": "YOUR_MODEL_HERE", + "displayName": "OPTIONAL_DISPLAY_NAME", + "token": { + "env": "OPENAI_API_KEY" + }, + // Retry failed requests up to 5 times, waiting 1s before the first retry. + "retry": { + "maxRetries": 5, + "initialBackoffMs": 1000, + "maxBackoffMs": 10000 + }, + // Fall back to these models (in order) when this model keeps failing. + // Each entry must reference another model in this `models` array. + "fallbackModels": [ + { + "provider": "anthropic", + "model": "YOUR_FALLBACK_MODEL_HERE" + } + ] + }, + { + "provider": "anthropic", + "model": "YOUR_FALLBACK_MODEL_HERE", + "token": { + "env": "ANTHROPIC_API_KEY" + } + } + ] +} +``` + +When every model fails, the API returns the details for each model tried (model, error message, and status code) so you can debug the underlying issue. A truncated provider response snippet is kept in the server logs for debugging. Full response bodies are never sent to clients. + +| Field | Description | +| ----- | ----------- | +| `retry.maxRetries` | Maximum retries after the initial request, per model. Only transient failures are retried. Set to `0` to disable retries. Defaults to `3`, max `10`. | +| `retry.initialBackoffMs` | Delay before the first retry. Doubles after each attempt. Defaults to `500`. | +| `retry.maxBackoffMs` | Maximum delay between retries. Defaults to `8000`. | +| `fallbackModels` | Ordered list of fallback models (max `5`). Each entry needs a `provider` and `model`, plus an optional `displayName` to disambiguate models that share a provider and model id. | + + # Schema reference diff --git a/docs/snippets/schemas/v3/index.schema.mdx b/docs/snippets/schemas/v3/index.schema.mdx index 60f08e149..3d820fe66 100644 --- a/docs/snippets/schemas/v3/index.schema.mdx +++ b/docs/snippets/schemas/v3/index.schema.mdx @@ -1875,6 +1875,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2013,6 +2083,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2148,6 +2288,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2255,6 +2465,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2376,6 +2656,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2499,6 +2849,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2638,6 +3058,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2745,6 +3235,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2878,6 +3438,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3042,6 +3672,76 @@ "temperature": { "type": "number", "description": "Optional temperature setting to use with the model." + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3150,12 +3850,82 @@ } }, "additionalProperties": false - } - }, - "required": [ - "provider", - "model" - ], + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 + } + }, + "required": [ + "provider", + "model" + ], "additionalProperties": false }, "XaiLanguageModel": { @@ -3261,6 +4031,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3441,6 +4281,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3579,6 +4489,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3714,6 +4694,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3821,6 +4871,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3942,6 +5062,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4065,6 +5255,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4204,6 +5464,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4311,6 +5641,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4444,6 +5844,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4608,6 +6078,76 @@ "temperature": { "type": "number", "description": "Optional temperature setting to use with the model." + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4716,6 +6256,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4827,6 +6437,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ diff --git a/docs/snippets/schemas/v3/languageModel.schema.mdx b/docs/snippets/schemas/v3/languageModel.schema.mdx index 90aee08af..61d5a63fa 100644 --- a/docs/snippets/schemas/v3/languageModel.schema.mdx +++ b/docs/snippets/schemas/v3/languageModel.schema.mdx @@ -174,6 +174,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -312,6 +382,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -447,6 +587,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -554,6 +764,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -675,6 +955,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -798,6 +1148,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -937,6 +1357,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1044,6 +1534,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1177,6 +1737,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1341,6 +1971,76 @@ "temperature": { "type": "number", "description": "Optional temperature setting to use with the model." + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1449,6 +2149,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1560,6 +2330,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1740,6 +2580,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1878,6 +2788,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2013,6 +2993,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2120,6 +3170,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2241,6 +3361,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2364,6 +3554,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2503,6 +3763,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2610,6 +3940,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2743,6 +4143,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2907,6 +4377,76 @@ "temperature": { "type": "number", "description": "Optional temperature setting to use with the model." + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3015,6 +4555,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3126,6 +4736,76 @@ } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ diff --git a/docs/snippets/schemas/v3/shared.schema.mdx b/docs/snippets/schemas/v3/shared.schema.mdx index 270d85b4b..5f0deb89b 100644 --- a/docs/snippets/schemas/v3/shared.schema.mdx +++ b/docs/snippets/schemas/v3/shared.schema.mdx @@ -162,6 +162,71 @@ } }, "additionalProperties": false + }, + "LanguageModelRetry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "LanguageModelFallbackReference": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false } } } diff --git a/packages/schemas/src/v3/index.schema.ts b/packages/schemas/src/v3/index.schema.ts index 0d7a76d92..9079a5284 100644 --- a/packages/schemas/src/v3/index.schema.ts +++ b/packages/schemas/src/v3/index.schema.ts @@ -1874,6 +1874,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2012,6 +2082,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2147,6 +2287,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2254,6 +2464,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2375,6 +2655,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2498,6 +2848,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2637,6 +3057,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2744,6 +3234,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2877,6 +3437,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3041,6 +3671,76 @@ const schema = { "temperature": { "type": "number", "description": "Optional temperature setting to use with the model." + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3149,12 +3849,82 @@ const schema = { } }, "additionalProperties": false - } - }, - "required": [ - "provider", - "model" - ], + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 + } + }, + "required": [ + "provider", + "model" + ], "additionalProperties": false }, "XaiLanguageModel": { @@ -3260,6 +4030,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3440,6 +4280,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3578,6 +4488,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3713,6 +4693,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3820,6 +4870,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3941,6 +5061,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4064,6 +5254,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4203,6 +5463,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4310,6 +5640,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4443,6 +5843,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4607,6 +6077,76 @@ const schema = { "temperature": { "type": "number", "description": "Optional temperature setting to use with the model." + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4715,6 +6255,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -4826,6 +6436,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ diff --git a/packages/schemas/src/v3/index.type.ts b/packages/schemas/src/v3/index.type.ts index 13027d9ff..d15974bb0 100644 --- a/packages/schemas/src/v3/index.type.ts +++ b/packages/schemas/src/v3/index.type.ts @@ -770,6 +770,13 @@ export interface AmazonBedrockLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } /** * Optional headers to use with the model. @@ -796,6 +803,52 @@ export interface LanguageModelHeaders { } ); } +/** + * Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms). + */ +export interface LanguageModelRetry { + /** + * Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3. + */ + maxRetries?: number; + /** + * Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500. + */ + initialBackoffMs?: number; + /** + * Maximum delay in milliseconds between retries. Defaults to 8000. + */ + maxBackoffMs?: number; +} +/** + * Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. + */ +export interface LanguageModelFallbackReference { + /** + * The provider of the fallback language model. Must match the provider of another entry in `models`. + */ + provider: + | "amazon-bedrock" + | "anthropic" + | "azure" + | "deepseek" + | "google-generative-ai" + | "google-vertex-anthropic" + | "google-vertex" + | "mistral" + | "openai" + | "openai-compatible" + | "openrouter" + | "xai"; + /** + * The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider. + */ + model: string; + /** + * Optional display name. When set, the fallback matches the configured model with the same provider, model and display name. + */ + displayName?: string; +} export interface AnthropicLanguageModel { /** * Anthropic Configuration @@ -850,6 +903,13 @@ export interface AnthropicLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface AzureLanguageModel { /** @@ -905,6 +965,13 @@ export interface AzureLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface DeepSeekLanguageModel { /** @@ -944,6 +1011,13 @@ export interface DeepSeekLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface GoogleGenerativeAILanguageModel { /** @@ -991,6 +1065,13 @@ export interface GoogleGenerativeAILanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface GoogleVertexAnthropicLanguageModel { /** @@ -1038,6 +1119,13 @@ export interface GoogleVertexAnthropicLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface GoogleVertexLanguageModel { /** @@ -1093,6 +1181,13 @@ export interface GoogleVertexLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface MistralLanguageModel { /** @@ -1132,6 +1227,13 @@ export interface MistralLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface OpenAILanguageModel { /** @@ -1179,6 +1281,13 @@ export interface OpenAILanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface OpenAICompatibleLanguageModel { /** @@ -1223,6 +1332,13 @@ export interface OpenAICompatibleLanguageModel { * Optional temperature setting to use with the model. */ temperature?: number; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } /** * Optional query parameters to include in the request url. @@ -1287,6 +1403,13 @@ export interface OpenRouterLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface XaiLanguageModel { /** @@ -1326,6 +1449,13 @@ export interface XaiLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface GitHubAppConfig { /** diff --git a/packages/schemas/src/v3/languageModel.schema.ts b/packages/schemas/src/v3/languageModel.schema.ts index ab418ce79..1245a5ab1 100644 --- a/packages/schemas/src/v3/languageModel.schema.ts +++ b/packages/schemas/src/v3/languageModel.schema.ts @@ -173,6 +173,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -311,6 +381,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -446,6 +586,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -553,6 +763,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -674,6 +954,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -797,6 +1147,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -936,6 +1356,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1043,6 +1533,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1176,6 +1736,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1340,6 +1970,76 @@ const schema = { "temperature": { "type": "number", "description": "Optional temperature setting to use with the model." + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1448,6 +2148,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1559,6 +2329,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1739,6 +2579,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -1877,6 +2787,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2012,6 +2992,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2119,6 +3169,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2240,6 +3360,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2363,6 +3553,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2502,6 +3762,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2609,6 +3939,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2742,6 +4142,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -2906,6 +4376,76 @@ const schema = { "temperature": { "type": "number", "description": "Optional temperature setting to use with the model." + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3014,6 +4554,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ @@ -3125,6 +4735,76 @@ const schema = { } }, "additionalProperties": false + }, + "retry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false + }, + "maxItems": 5 } }, "required": [ diff --git a/packages/schemas/src/v3/languageModel.type.ts b/packages/schemas/src/v3/languageModel.type.ts index 5c3b25668..a8a3b5c69 100644 --- a/packages/schemas/src/v3/languageModel.type.ts +++ b/packages/schemas/src/v3/languageModel.type.ts @@ -88,6 +88,13 @@ export interface AmazonBedrockLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } /** * Optional headers to use with the model. @@ -114,6 +121,52 @@ export interface LanguageModelHeaders { } ); } +/** + * Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms). + */ +export interface LanguageModelRetry { + /** + * Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3. + */ + maxRetries?: number; + /** + * Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500. + */ + initialBackoffMs?: number; + /** + * Maximum delay in milliseconds between retries. Defaults to 8000. + */ + maxBackoffMs?: number; +} +/** + * Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. + */ +export interface LanguageModelFallbackReference { + /** + * The provider of the fallback language model. Must match the provider of another entry in `models`. + */ + provider: + | "amazon-bedrock" + | "anthropic" + | "azure" + | "deepseek" + | "google-generative-ai" + | "google-vertex-anthropic" + | "google-vertex" + | "mistral" + | "openai" + | "openai-compatible" + | "openrouter" + | "xai"; + /** + * The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider. + */ + model: string; + /** + * Optional display name. When set, the fallback matches the configured model with the same provider, model and display name. + */ + displayName?: string; +} export interface AnthropicLanguageModel { /** * Anthropic Configuration @@ -168,6 +221,13 @@ export interface AnthropicLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface AzureLanguageModel { /** @@ -223,6 +283,13 @@ export interface AzureLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface DeepSeekLanguageModel { /** @@ -262,6 +329,13 @@ export interface DeepSeekLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface GoogleGenerativeAILanguageModel { /** @@ -309,6 +383,13 @@ export interface GoogleGenerativeAILanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface GoogleVertexAnthropicLanguageModel { /** @@ -356,6 +437,13 @@ export interface GoogleVertexAnthropicLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface GoogleVertexLanguageModel { /** @@ -411,6 +499,13 @@ export interface GoogleVertexLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface MistralLanguageModel { /** @@ -450,6 +545,13 @@ export interface MistralLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface OpenAILanguageModel { /** @@ -497,6 +599,13 @@ export interface OpenAILanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface OpenAICompatibleLanguageModel { /** @@ -541,6 +650,13 @@ export interface OpenAICompatibleLanguageModel { * Optional temperature setting to use with the model. */ temperature?: number; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } /** * Optional query parameters to include in the request url. @@ -605,6 +721,13 @@ export interface OpenRouterLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } export interface XaiLanguageModel { /** @@ -644,4 +767,11 @@ export interface XaiLanguageModel { */ temperature?: number; headers?: LanguageModelHeaders; + retry?: LanguageModelRetry; + /** + * Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order. + * + * @maxItems 5 + */ + fallbackModels?: LanguageModelFallbackReference[]; } diff --git a/packages/schemas/src/v3/shared.schema.ts b/packages/schemas/src/v3/shared.schema.ts index 91a34529b..eb1b46435 100644 --- a/packages/schemas/src/v3/shared.schema.ts +++ b/packages/schemas/src/v3/shared.schema.ts @@ -161,6 +161,71 @@ const schema = { } }, "additionalProperties": false + }, + "LanguageModelRetry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "LanguageModelFallbackReference": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false } } } as const; diff --git a/packages/schemas/src/v3/shared.type.ts b/packages/schemas/src/v3/shared.type.ts index 043d1c80c..3e5e40b02 100644 --- a/packages/schemas/src/v3/shared.type.ts +++ b/packages/schemas/src/v3/shared.type.ts @@ -63,3 +63,55 @@ export interface LanguageModelQueryParams { */ [k: string]: string | Token; } +/** + * Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms). + * + * This interface was referenced by `Shared`'s JSON-Schema + * via the `definition` "LanguageModelRetry". + */ +export interface LanguageModelRetry { + /** + * Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3. + */ + maxRetries?: number; + /** + * Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500. + */ + initialBackoffMs?: number; + /** + * Maximum delay in milliseconds between retries. Defaults to 8000. + */ + maxBackoffMs?: number; +} +/** + * Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. + * + * This interface was referenced by `Shared`'s JSON-Schema + * via the `definition` "LanguageModelFallbackReference". + */ +export interface LanguageModelFallbackReference { + /** + * The provider of the fallback language model. Must match the provider of another entry in `models`. + */ + provider: + | "amazon-bedrock" + | "anthropic" + | "azure" + | "deepseek" + | "google-generative-ai" + | "google-vertex-anthropic" + | "google-vertex" + | "mistral" + | "openai" + | "openai-compatible" + | "openrouter" + | "xai"; + /** + * The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider. + */ + model: string; + /** + * Optional display name. When set, the fallback matches the configured model with the same provider, model and display name. + */ + displayName?: string; +} diff --git a/packages/web/src/app/api/(server)/ee/chat/route.ts b/packages/web/src/app/api/(server)/ee/chat/route.ts index c8a34aa8f..b938209c6 100644 --- a/packages/web/src/app/api/(server)/ee/chat/route.ts +++ b/packages/web/src/app/api/(server)/ee/chat/route.ts @@ -9,6 +9,7 @@ import { isMediaTypeAccepted, mediaTypeToModality } from "@/features/chat/attach import { resolveModelCapabilities } from "@/features/chat/modelCapabilities.server"; import { checkAskEntitlement, commitMessageAttachments, getConfiguredLanguageModels, isOwnerOfChat, updateChatMessages } from "@/features/chat/utils.server"; import { getAISDKLanguageModelAndOptions } from "@/features/chat/llm.server"; +import { formatInferenceError, resolveInferenceRetryConfig } from "@/features/chat/inferenceRetry.server"; import { resolveContextWindow } from "@/features/chat/modelContextWindow.server"; import { materializeCommandMessageTexts } from "@/ee/features/chat/skills/commandResolution"; import { getAskSkillAvailabilityAnalytics, getAskSkillTurnCompletedAnalytics } from "@/ee/features/chat/skills/skillAnalytics.server"; @@ -235,6 +236,11 @@ export const POST = apiHandler(async (req: NextRequest) => { promptCacheStrategy, modelProviderOptions: providerOptions, modelTemperature: temperature, + // Surface the per-model retry policy to the SDK. Model + // fallback is intentionally not attempted here: an + // interactive stream cannot switch models mid-response + // (fallbacks apply to the blocking ask/MCP path instead). + modelMaxRetries: resolveInferenceRetryConfig(languageModelConfig).maxRetries, userId: user?.id, orgId: org.id, acceptedModalities, @@ -267,19 +273,15 @@ export const POST = apiHandler(async (req: NextRequest) => { logger.error(error); Sentry.captureException(error); + // Report the failure with the model and provider status + // code instead of a generic failure so it is debuggable + // from the client. The provider response body stays in + // the server logs. if (error == null) { - return 'unknown error'; + return `[${languageModelConfig.provider}/${languageModelConfig.model}] unknown error`; } - if (typeof error === 'string') { - return error; - } - - if (error instanceof Error) { - return error.message; - } - - return JSON.stringify(error); + return formatInferenceError(error, languageModelConfig); } }); diff --git a/packages/web/src/ee/features/chat/agent.ts b/packages/web/src/ee/features/chat/agent.ts index e69f368cf..ab85b5ccc 100644 --- a/packages/web/src/ee/features/chat/agent.ts +++ b/packages/web/src/ee/features/chat/agent.ts @@ -1,4 +1,5 @@ import { BlobAttachment, InputModality, SBChatMessage, SBChatMessageMetadata, StepTokenUsageEntry, ToolTokenUsageEntry } from "@/features/chat/types"; +import { DEFAULT_INFERENCE_MAX_RETRIES } from "@/features/chat/inferenceRetry.server"; import { isMediaTypeAccepted, mediaTypeToModality } from "@/features/chat/attachments/modality"; import { getStorageBackend } from "@sourcebot/shared"; import { estimateModelToolOutputTokens } from "@/ee/features/chat/tokenEstimation"; @@ -228,6 +229,10 @@ interface CreateMessageStreamResponseProps { onError: (error: unknown) => string; modelProviderOptions?: Record>; modelTemperature?: number; + // Passed through to the AI SDK as `maxRetries`. Blocking callers that run + // their own retry/fallback loop (see `executeWithInferenceFallback`) pass + // 0 to avoid compounding retries with the SDK's built-in ones. + modelMaxRetries?: number; metadata?: Partial; userId?: string; orgId?: number; @@ -251,6 +256,7 @@ export const createMessageStream = async ({ promptCacheStrategy, modelProviderOptions, modelTemperature, + modelMaxRetries, onFinish, onError, userId, @@ -372,6 +378,7 @@ export const createMessageStream = async ({ promptCacheStrategy, providerOptions: modelProviderOptions, temperature: modelTemperature, + maxRetries: modelMaxRetries, inputMessages: messageHistory, inputSources: sources, selectedRepos, @@ -530,6 +537,9 @@ interface AgentOptions { promptCacheStrategy: PromptCacheStrategy; providerOptions?: ProviderOptions; temperature?: number; + // When undefined, the shared default (`DEFAULT_INFERENCE_MAX_RETRIES`) + // applies. Blocking callers pass 0 since they retry outside the SDK. + maxRetries?: number; selectedRepos: string[]; disabledMcpServerIds?: string[]; inputMessages: ModelMessage[]; @@ -557,6 +567,7 @@ const createAgentStream = async ({ promptCacheStrategy, providerOptions, temperature, + maxRetries, inputMessages, inputSources, selectedRepos, @@ -779,6 +790,7 @@ const createAgentStream = async ({ const stream = streamText({ model, providerOptions, + maxRetries: maxRetries ?? DEFAULT_INFERENCE_MAX_RETRIES, messages: inputMessages, system: systemMessages, tools: allTools, @@ -883,7 +895,7 @@ const createAgentStream = async ({ isEnabled: env.SOURCEBOT_TELEMETRY_PII_COLLECTION_ENABLED === 'true', }, onError: (error) => { - logger.error(error); + logger.error(`Inference error (model ${typeof model === 'string' ? model : model.modelId}):`, error); }, }); diff --git a/packages/web/src/ee/features/chat/llm.server.ts b/packages/web/src/ee/features/chat/llm.server.ts index 2880fded9..b9193f339 100644 --- a/packages/web/src/ee/features/chat/llm.server.ts +++ b/packages/web/src/ee/features/chat/llm.server.ts @@ -3,8 +3,9 @@ import 'server-only'; import { LanguageModel } from '@sourcebot/schemas/v3/languageModel.type'; import { generateText } from "ai"; import { getAISDKLanguageModelAndOptions } from "@/features/chat/llm.server"; +import { DEFAULT_INFERENCE_MAX_RETRIES } from "@/features/chat/inferenceRetry.server"; -export const generateChatNameFromMessage = async ({ message, languageModelConfig }: { message: string, languageModelConfig: LanguageModel }) => { +export const generateChatNameFromMessage = async ({ message, languageModelConfig, maxRetries = DEFAULT_INFERENCE_MAX_RETRIES }: { message: string, languageModelConfig: LanguageModel, maxRetries?: number }) => { const { model } = await getAISDKLanguageModelAndOptions(languageModelConfig); const prompt = `Convert this question into a short topic title (max 50 characters). @@ -26,6 +27,7 @@ User question: ${message}`; const result = await generateText({ model, prompt, + maxRetries, }); return result.text; diff --git a/packages/web/src/ee/features/mcp/askCodebase.ts b/packages/web/src/ee/features/mcp/askCodebase.ts index 35337d29f..ecb029b4a 100644 --- a/packages/web/src/ee/features/mcp/askCodebase.ts +++ b/packages/web/src/ee/features/mcp/askCodebase.ts @@ -6,6 +6,7 @@ import { resolveContextWindow } from "@/features/chat/modelContextWindow.server" import { LanguageModelInfo, SBChatMessage, SearchScope } from "@/features/chat/types"; import { convertLLMOutputToPortableMarkdown, getAnswerPartFromAssistantMessage, getLanguageModelKey } from "@/features/chat/utils"; import { resolveModelCapabilities } from "@/features/chat/modelCapabilities.server"; +import { describeLanguageModel, executeWithInferenceFallback, formatInferenceError, formatInferenceErrorForLog } from "@/features/chat/inferenceRetry.server"; import { ErrorCode } from "@/lib/errorCodes"; import { ServiceError, ServiceErrorException } from "@/lib/serviceError"; import { withOptionalAuth } from "@/middleware/withAuth"; @@ -84,17 +85,6 @@ export const askCodebase = (params: AskCodebaseParams): Promise r.value), - prisma, - model, - modelName, - contextWindow, - promptCacheStrategy, - modelProviderOptions: providerOptions, - modelTemperature: temperature, - onFinish: async ({ messages }) => { - finalMessages = messages; - }, - onError: (error) => { - if (error instanceof ServiceErrorException) { - throw error; - } - const message = error instanceof Error ? error.message : String(error); - throw new ServiceErrorException({ - statusCode: StatusCodes.INTERNAL_SERVER_ERROR, - errorCode: ErrorCode.UNEXPECTED_ERROR, - message, - }); - }, - }); + // Inference runs through the shared retry/fallback executor: the + // primary model is retried on transient failures, then the models + // listed in its `fallbackModels` config are tried in order. Only + // inference failures fall back; deterministic request errors (bad + // repo names, entitlement errors, ...) are rethrown immediately. + // Chat-name generation runs concurrently and is best-effort: a + // single attempt with no retries, so naming never delays the + // answer. A naming failure falls back to the query and must not + // fail the whole answer. + const [agentOutcome, chatNameOutcome] = await Promise.allSettled([ + executeWithInferenceFallback({ + primaryModel: languageModelConfig, + allModels: configuredModels, + run: async (candidate) => { + const { model, providerOptions, temperature } = await getAISDKLanguageModelAndOptions(candidate); + const modelName = candidate.displayName ?? candidate.model; + const contextWindow = await resolveContextWindow(candidate); + const { inputModalities, supportedDocumentTypes } = await resolveModelCapabilities(candidate); + + // No-op for non-Anthropic providers / when caching is disabled. + const promptCacheStrategy = getPromptCacheStrategy( + candidate.provider, + env.SOURCEBOT_CHAT_PROMPT_CACHING_ENABLED === 'true', + ); - const [, name] = await Promise.all([ - blockStreamUntilFinish(stream), + // The UI-message stream reports failures through `onError`, + // which by contract returns a message string. Capture the + // raw error and rethrow it after draining so the + // retry/fallback loop can classify it (mapping it here + // would discard the provider status code and retryability). + let streamError: unknown; + let attemptMessages: SBChatMessage[] = []; + + const stream = await createMessageStream({ + chatId: chat.id, + messages: [userMessage], + metadata: { + selectedSearchScopes: selectedRepos, + }, + selectedRepos: selectedRepos.map(r => r.value), + prisma, + model, + modelName, + contextWindow, + promptCacheStrategy, + modelProviderOptions: providerOptions, + modelTemperature: temperature, + // Retries are handled by the loop around `run` + // (uniform backoff + fallback); disable the SDK's + // built-in retries to avoid compounding them. + modelMaxRetries: 0, + onFinish: async ({ messages }) => { + attemptMessages = messages; + }, + onError: (error) => { + streamError = error; + return formatInferenceError(error, candidate); + }, + }); + + await blockStreamUntilFinish(stream); + if (streamError !== undefined) { + throw streamError; + } + + return { messages: attemptMessages, inputModalities, supportedDocumentTypes }; + }, + }), generateChatNameFromMessage({ message: query, languageModelConfig, - }) + // No retries: naming is best-effort and must not hold up + // the answer behind a retry/backoff budget. + maxRetries: 0, + }), ]); + if (agentOutcome.status === 'rejected') { + throw agentOutcome.reason; + } + + const { modelConfig: servedModelConfig, result: agentResult } = agentOutcome.value; + const finalMessages = agentResult.messages; + + let name: string; + if (chatNameOutcome.status === 'fulfilled' && chatNameOutcome.value) { + name = chatNameOutcome.value; + } else { + logger.warn(`Failed to generate a chat name for chat ${chat.id}. Using the query as the name. Details: ${chatNameOutcome.status === 'rejected' ? formatInferenceErrorForLog(chatNameOutcome.reason, languageModelConfig) : 'empty response'}`); + name = query.substring(0, 50); + } + await updateChatMessages({ chatId: chat.id, messages: finalMessages, prisma }); await prisma.chat.update({ @@ -238,18 +280,22 @@ export const askCodebase = (params: AskCodebaseParams): Promise { + class FakeAPICallError extends Error { + static isInstance(error: unknown): boolean { + return error instanceof FakeAPICallError; + } + + statusCode?: number; + responseBody?: unknown; + url?: string; + isRetryable?: boolean; + + constructor(opts: { message: string; statusCode?: number; responseBody?: unknown; url?: string; isRetryable?: boolean }) { + super(opts.message); + this.name = 'AI_APICallError'; + this.statusCode = opts.statusCode; + this.responseBody = opts.responseBody; + this.url = opts.url; + this.isRetryable = opts.isRetryable; + } + } + + return { + FakeAPICallError, + logger: { + error: vi.fn(), + warn: vi.fn(), + debug: vi.fn(), + info: vi.fn(), + }, + }; +}); + +vi.mock('server-only', () => ({})); +vi.mock('ai', () => ({ + APICallError: mocks.FakeAPICallError, +})); +vi.mock('@/features/chat/logger', () => ({ + logger: mocks.logger, +})); +vi.mock('@/features/chat/utils', () => ({ + getLanguageModelKey: (model: { provider: string; model: string; displayName?: string }) => + `${model.provider}-${model.model}-${model.displayName}`, +})); + +import { + computeRetryDelayMs, + describeLanguageModel, + executeWithInferenceFallback, + formatInferenceError, + formatInferenceErrorForLog, + isRetryableInferenceError, + resolveFallbackChain, + resolveInferenceRetryConfig, + toInferenceServiceError, + withInferenceRetries, +} from './inferenceRetry.server'; +import { ErrorCode } from '@/lib/errorCodes'; +import { ServiceErrorException } from '@/lib/serviceError'; +import { LanguageModel } from '@sourcebot/schemas/v3/languageModel.type'; +import { StatusCodes } from 'http-status-codes'; + +const openaiModel = (overrides: Partial = {}): LanguageModel => ({ + provider: 'openai', + model: 'gpt-4o', + ...overrides, +} as LanguageModel); + +const anthropicModel = (overrides: Partial = {}): LanguageModel => ({ + provider: 'anthropic', + model: 'claude-sonnet-4-5', + ...overrides, +} as LanguageModel); + +const apiError = (opts: { message: string; statusCode?: number; responseBody?: unknown; isRetryable?: boolean }) => + new mocks.FakeAPICallError({ url: 'https://api.provider.test/v1/chat', ...opts }); + +beforeEach(() => { + mocks.logger.warn.mockReset(); + mocks.logger.error.mockReset(); +}); + +describe('resolveInferenceRetryConfig', () => { + test('applies defaults when no retry policy is configured', () => { + expect(resolveInferenceRetryConfig(openaiModel())).toEqual({ + maxRetries: 3, + initialBackoffMs: 500, + maxBackoffMs: 8000, + }); + }); + + test('honors a per-model retry policy', () => { + expect(resolveInferenceRetryConfig(openaiModel({ + retry: { maxRetries: 1, initialBackoffMs: 100, maxBackoffMs: 1000 }, + }))).toEqual({ + maxRetries: 1, + initialBackoffMs: 100, + maxBackoffMs: 1000, + }); + }); + + test('clamps out-of-range values', () => { + expect(resolveInferenceRetryConfig(openaiModel({ + retry: { maxRetries: 99, initialBackoffMs: -5, maxBackoffMs: 999999999 }, + }))).toEqual({ + maxRetries: 10, + initialBackoffMs: 0, + maxBackoffMs: 120000, + }); + }); +}); + +describe('computeRetryDelayMs', () => { + test('backs off exponentially up to the cap', () => { + const config = { maxRetries: 5, initialBackoffMs: 500, maxBackoffMs: 1200 }; + expect(computeRetryDelayMs(config, 0)).toBe(500); + expect(computeRetryDelayMs(config, 1)).toBe(1000); + expect(computeRetryDelayMs(config, 2)).toBe(1200); + }); +}); + +describe('isRetryableInferenceError', () => { + test('retries rate limits and server errors', () => { + expect(isRetryableInferenceError(apiError({ message: 'slow down', statusCode: 429 }))).toBe(true); + expect(isRetryableInferenceError(apiError({ message: 'boom', statusCode: 500 }))).toBe(true); + expect(isRetryableInferenceError(apiError({ message: 'timeout', statusCode: 408 }))).toBe(true); + }); + + test('does not retry deterministic client errors', () => { + expect(isRetryableInferenceError(apiError({ message: 'bad request', statusCode: 400 }))).toBe(false); + expect(isRetryableInferenceError(apiError({ message: 'unauthorized', statusCode: 401 }))).toBe(false); + expect(isRetryableInferenceError(apiError({ message: 'not found', statusCode: 404 }))).toBe(false); + }); + + test('honors the SDK retryability flag', () => { + expect(isRetryableInferenceError(apiError({ message: 'ok', statusCode: 200, isRetryable: true }))).toBe(true); + }); + + test('retries network-level transport failures', () => { + expect(isRetryableInferenceError(new TypeError('fetch failed'))).toBe(true); + const reset = new TypeError('terminated'); + (reset as unknown as Record)['cause'] = { code: 'ECONNRESET' }; + expect(isRetryableInferenceError(reset)).toBe(true); + }); + + test('does not retry unknown errors or Sourcebot service errors', () => { + expect(isRetryableInferenceError(new Error('boom'))).toBe(false); + expect(isRetryableInferenceError(new ServiceErrorException({ + statusCode: StatusCodes.BAD_REQUEST, + errorCode: ErrorCode.INVALID_REQUEST_BODY, + message: 'bad repo', + }))).toBe(false); + }); +}); + +describe('formatInferenceError', () => { + test('includes the model, message, and status code', () => { + const formatted = formatInferenceError( + apiError({ message: 'Resource exhausted', statusCode: 429, responseBody: '{"error":{"code":429}}' }), + { provider: 'openai', model: 'gpt-4o' }, + ); + expect(formatted).toBe('[openai/gpt-4o] Resource exhausted (status 429)'); + }); + + test('omits the provider response body from client-facing messages', () => { + const formatted = formatInferenceError( + apiError({ message: 'bad', statusCode: 500, responseBody: '{"error":{"secret":"provider-secret"}}' }), + { provider: 'openai', model: 'gpt-4o' }, + ); + expect(formatted).not.toContain('provider response'); + expect(formatted).not.toContain('provider-secret'); + }); + + test('never leaks request bodies', () => { + const error = apiError({ message: 'bad', statusCode: 500 }); + (error as unknown as Record)['requestBodyValues'] = { secret: 'super-secret-prompt' }; + const formatted = formatInferenceError(error, { provider: 'openai', model: 'gpt-4o' }); + expect(formatted).not.toContain('super-secret-prompt'); + }); +}); + +describe('formatInferenceErrorForLog', () => { + test('includes a truncated provider response for server logs', () => { + const formatted = formatInferenceErrorForLog( + apiError({ message: 'bad', statusCode: 500, responseBody: `{"data":"${'x'.repeat(1000)}"}` }), + { provider: 'openai', model: 'gpt-4o' }, + ); + expect(formatted).toContain('[openai/gpt-4o] bad (status 500) | provider response: '); + expect(formatted.length).toBeLessThan(900); + expect(formatted).toContain('…'); + }); + + test('never leaks request bodies', () => { + const error = apiError({ message: 'bad', statusCode: 500 }); + (error as unknown as Record)['requestBodyValues'] = { secret: 'super-secret-prompt' }; + const formatted = formatInferenceErrorForLog(error, { provider: 'openai', model: 'gpt-4o' }); + expect(formatted).not.toContain('super-secret-prompt'); + }); +}); + +describe('toInferenceServiceError', () => { + test('passes the provider status code through without the response body', () => { + const serviceError = toInferenceServiceError( + apiError({ message: 'slow down', statusCode: 429, responseBody: '{"error":{"secret":"provider-secret"}}' }), + { provider: 'openai', model: 'gpt-4o' }, + ); + expect(serviceError.statusCode).toBe(429); + expect(serviceError.errorCode).toBe(ErrorCode.INFERENCE_ERROR); + expect(serviceError.message).toContain('[openai/gpt-4o]'); + expect(serviceError.message).toContain('slow down'); + expect(serviceError.message).not.toContain('provider response'); + expect(serviceError.message).not.toContain('provider-secret'); + }); + + test('falls back to 500 without a provider status code', () => { + const serviceError = toInferenceServiceError(new Error('boom'), { provider: 'openai', model: 'gpt-4o' }); + expect(serviceError.statusCode).toBe(StatusCodes.INTERNAL_SERVER_ERROR); + expect(serviceError.errorCode).toBe(ErrorCode.INFERENCE_ERROR); + }); + + test('passes non-inference service errors through untouched', () => { + const original = { + statusCode: StatusCodes.BAD_REQUEST, + errorCode: ErrorCode.INVALID_REQUEST_BODY, + message: 'bad repo', + }; + expect(toInferenceServiceError( + new ServiceErrorException(original), + { provider: 'openai', model: 'gpt-4o' }, + )).toBe(original); + }); +}); + +describe('resolveFallbackChain', () => { + test('returns just the primary model when no fallbacks are configured', () => { + const primary = openaiModel(); + expect(resolveFallbackChain(primary, [primary])).toEqual([primary]); + }); + + test('resolves configured fallbacks in order', () => { + const primary = openaiModel({ + fallbackModels: [ + { provider: 'anthropic', model: 'claude-sonnet-4-5' }, + { provider: 'openai', model: 'gpt-4o-mini' }, + ], + }); + const fallbackA = anthropicModel(); + const fallbackB = openaiModel({ model: 'gpt-4o-mini' }); + expect(resolveFallbackChain(primary, [primary, fallbackA, fallbackB])).toEqual([primary, fallbackA, fallbackB]); + }); + + test('skips unconfigured fallbacks, self-references, and duplicates', () => { + const primary = openaiModel({ + fallbackModels: [ + { provider: 'openai', model: 'gpt-4o' }, + { provider: 'anthropic', model: 'missing-model' }, + { provider: 'anthropic', model: 'claude-sonnet-4-5' }, + { provider: 'anthropic', model: 'claude-sonnet-4-5' }, + ], + }); + const fallback = anthropicModel(); + expect(resolveFallbackChain(primary, [primary, fallback])).toEqual([primary, fallback]); + expect(mocks.logger.warn).toHaveBeenCalled(); + }); + + test('matches on displayName when the reference sets one', () => { + const primary = openaiModel({ + fallbackModels: [{ provider: 'anthropic', model: 'claude', displayName: 'Work Claude' }], + }); + const other = anthropicModel({ model: 'claude', displayName: 'Personal Claude' }); + const match = anthropicModel({ model: 'claude', displayName: 'Work Claude' }); + expect(resolveFallbackChain(primary, [primary, other, match])).toEqual([primary, match]); + }); + + test('tries a same-id backup instead of silently reusing the primary', () => { + const primary = openaiModel({ + displayName: 'Primary key', + fallbackModels: [{ provider: 'openai', model: 'gpt-4o' }], + }); + const backup = openaiModel({ displayName: 'Backup key' }); + // The backup shares the primary's provider and model id; the + // reference must resolve to it rather than no-op on the primary. + expect(resolveFallbackChain(primary, [primary, backup])).toEqual([primary, backup]); + }); + + test('warns when a reference resolves only to models already in the chain', () => { + const primary = openaiModel({ + fallbackModels: [{ provider: 'openai', model: 'gpt-4o' }], + }); + expect(resolveFallbackChain(primary, [primary])).toEqual([primary]); + expect(mocks.logger.warn).toHaveBeenCalledWith( + expect.stringContaining('resolves only to models already in the chain'), + ); + }); +}); + +describe('withInferenceRetries', () => { + const fastConfig = { maxRetries: 2, initialBackoffMs: 1, maxBackoffMs: 1 }; + + test('returns immediately on success', async () => { + const fn = vi.fn().mockResolvedValue('ok'); + await expect(withInferenceRetries(fn, fastConfig, { provider: 'openai', model: 'gpt-4o' })).resolves.toBe('ok'); + expect(fn).toHaveBeenCalledTimes(1); + }); + + test('retries transient failures and then succeeds', async () => { + const fn = vi.fn() + .mockRejectedValueOnce(apiError({ message: 'busy', statusCode: 429 })) + .mockResolvedValueOnce('ok'); + await expect(withInferenceRetries(fn, fastConfig, { provider: 'openai', model: 'gpt-4o' })).resolves.toBe('ok'); + expect(fn).toHaveBeenCalledTimes(2); + }); + + test('does not retry deterministic failures', async () => { + const fn = vi.fn().mockRejectedValue(apiError({ message: 'bad key', statusCode: 401 })); + await expect(withInferenceRetries(fn, fastConfig, { provider: 'openai', model: 'gpt-4o' })).rejects.toThrow('bad key'); + expect(fn).toHaveBeenCalledTimes(1); + }); + + test('gives up after maxRetries', async () => { + const fn = vi.fn().mockRejectedValue(apiError({ message: 'down', statusCode: 503 })); + await expect(withInferenceRetries(fn, fastConfig, { provider: 'openai', model: 'gpt-4o' })).rejects.toThrow('down'); + expect(fn).toHaveBeenCalledTimes(3); + }); +}); + +describe('executeWithInferenceFallback', () => { + test('serves from the primary model when it succeeds', async () => { + const primary = openaiModel(); + const run = vi.fn().mockResolvedValue('answer'); + const outcome = await executeWithInferenceFallback({ + primaryModel: primary, + allModels: [primary], + run, + }); + expect(outcome.result).toBe('answer'); + expect(outcome.modelConfig).toBe(primary); + expect(run).toHaveBeenCalledTimes(1); + }); + + test('falls back to the next model after retries are exhausted', async () => { + const primary = openaiModel({ + retry: { maxRetries: 1, initialBackoffMs: 1, maxBackoffMs: 1 }, + fallbackModels: [{ provider: 'anthropic', model: 'claude-sonnet-4-5' }], + }); + const fallback = anthropicModel(); + const run = vi.fn() + .mockRejectedValueOnce(apiError({ message: 'primary down', statusCode: 503 })) + .mockRejectedValueOnce(apiError({ message: 'primary still down', statusCode: 503 })) + .mockResolvedValueOnce('fallback answer'); + + const outcome = await executeWithInferenceFallback({ + primaryModel: primary, + allModels: [primary, fallback], + run, + }); + + expect(outcome.result).toBe('fallback answer'); + expect(outcome.modelConfig).toBe(fallback); + // 1 initial attempt + 1 retry on the primary, then the fallback. + expect(run).toHaveBeenCalledTimes(3); + }); + + test('aggregates every attempt when all models fail', async () => { + const primary = openaiModel({ + retry: { maxRetries: 0 }, + fallbackModels: [{ provider: 'anthropic', model: 'claude-sonnet-4-5' }], + }); + const fallback = anthropicModel({ retry: { maxRetries: 0 } }); + const run = vi.fn() + .mockRejectedValueOnce(apiError({ message: 'primary down', statusCode: 503 })) + .mockRejectedValueOnce(apiError({ message: 'fallback limited', statusCode: 429 })); + + const failure = await executeWithInferenceFallback({ + primaryModel: primary, + allModels: [primary, fallback], + run, + }).catch((error: unknown) => error); + + expect(failure).toBeInstanceOf(ServiceErrorException); + const serviceError = (failure as ServiceErrorException).serviceError; + expect(serviceError.errorCode).toBe(ErrorCode.INFERENCE_ERROR); + expect(serviceError.statusCode).toBe(429); + expect(serviceError.message).toContain('[openai/gpt-4o]'); + expect(serviceError.message).toContain('[anthropic/claude-sonnet-4-5]'); + expect(serviceError.message).toContain('primary down'); + expect(serviceError.message).toContain('fallback limited'); + }); + + test('fails fast on deterministic provider errors without falling back', async () => { + const primary = openaiModel({ + retry: { maxRetries: 3, initialBackoffMs: 1, maxBackoffMs: 1 }, + fallbackModels: [{ provider: 'anthropic', model: 'claude-sonnet-4-5' }], + }); + const fallback = anthropicModel(); + const run = vi.fn().mockRejectedValue(apiError({ message: 'bad key', statusCode: 401 })); + + const failure = await executeWithInferenceFallback({ + primaryModel: primary, + allModels: [primary, fallback], + run, + }).catch((error: unknown) => error); + + expect(run).toHaveBeenCalledTimes(1); + expect(failure).toBeInstanceOf(ServiceErrorException); + const serviceError = (failure as ServiceErrorException).serviceError; + expect(serviceError.errorCode).toBe(ErrorCode.INFERENCE_ERROR); + expect(serviceError.statusCode).toBe(401); + expect(serviceError.message).toContain('[openai/gpt-4o]'); + expect(serviceError.message).toContain('bad key'); + expect(serviceError.message).not.toContain('All 2 models failed'); + }); + + test('fails fast on internal errors without misreporting fallback exhaustion', async () => { + const primary = openaiModel({ + fallbackModels: [{ provider: 'anthropic', model: 'claude-sonnet-4-5' }], + }); + const fallback = anthropicModel(); + const run = vi.fn().mockRejectedValue(new Error('entitlement backstop')); + + const failure = await executeWithInferenceFallback({ + primaryModel: primary, + allModels: [primary, fallback], + run, + }).catch((error: unknown) => error); + + expect(run).toHaveBeenCalledTimes(1); + expect(failure).toBeInstanceOf(ServiceErrorException); + expect((failure as ServiceErrorException).serviceError.statusCode).toBe(StatusCodes.INTERNAL_SERVER_ERROR); + expect((failure as ServiceErrorException).serviceError.message).not.toContain('fallback'); + }); + + test('rethrows deterministic request errors without falling back', async () => { + const primary = openaiModel({ + fallbackModels: [{ provider: 'anthropic', model: 'claude-sonnet-4-5' }], + }); + const fallback = anthropicModel(); + const requestError = new ServiceErrorException({ + statusCode: StatusCodes.BAD_REQUEST, + errorCode: ErrorCode.INVALID_REQUEST_BODY, + message: "Repository 'x' not found.", + }); + const run = vi.fn().mockRejectedValue(requestError); + + await expect(executeWithInferenceFallback({ + primaryModel: primary, + allModels: [primary, fallback], + run, + })).rejects.toBe(requestError); + expect(run).toHaveBeenCalledTimes(1); + }); +}); + +describe('describeLanguageModel', () => { + test('labels a model as provider/model', () => { + expect(describeLanguageModel({ provider: 'openai', model: 'gpt-4o' })).toBe('openai/gpt-4o'); + }); +}); diff --git a/packages/web/src/features/chat/inferenceRetry.server.ts b/packages/web/src/features/chat/inferenceRetry.server.ts new file mode 100644 index 000000000..69f1b9a04 --- /dev/null +++ b/packages/web/src/features/chat/inferenceRetry.server.ts @@ -0,0 +1,464 @@ +import 'server-only'; + +import { logger } from "@/features/chat/logger"; +import { getLanguageModelKey } from "@/features/chat/utils"; +import { ErrorCode } from "@/lib/errorCodes"; +import { ServiceError, ServiceErrorException } from "@/lib/serviceError"; +import { LanguageModel } from "@sourcebot/schemas/v3/languageModel.type"; +import { APICallError } from "ai"; +import { StatusCodes } from "http-status-codes"; + +// @note: This module is the single place where inference (LLM provider) +// failures are interpreted, retried, and escalated. Both the interactive Ask +// chat path and the programmatic `askCodebase` path (MCP `ask_codebase` tool +// and `/api/chat/blocking`) share it so error reporting and resilience behave +// identically everywhere. +// +// Two layers of defense exist: +// 1. Retries (same model): transient failures (network errors, 408/429/5xx) +// are retried with exponential backoff, configured per model via the +// `retry` field in `config.json`. +// 2. Fallbacks (other models): when a model keeps failing, the ordered +// `fallbackModels` list on that model is tried in order. Fallbacks are +// only attempted on the blocking path (`askCodebase`), since an +// interactive stream cannot switch models mid-response. + +export const DEFAULT_INFERENCE_MAX_RETRIES = 3; +export const DEFAULT_INFERENCE_INITIAL_BACKOFF_MS = 500; +export const DEFAULT_INFERENCE_MAX_BACKOFF_MS = 8000; +const MAX_INFERENCE_MAX_RETRIES = 10; +const MAX_INFERENCE_BACKOFF_MS = 120000; +export const MAX_INFERENCE_FALLBACK_MODELS = 5; +// Provider error payloads can be large; keep only a prefix for observability. +const MAX_RESPONSE_BODY_SNIPPET_CHARS = 500; + +export type InferenceRetryConfig = { + maxRetries: number; + initialBackoffMs: number; + maxBackoffMs: number; +}; + +const clampInt = (value: unknown, fallback: number, min: number, max: number): number => { + if (typeof value !== 'number' || !Number.isFinite(value)) { + return fallback; + } + + const rounded = Math.floor(value); + if (rounded < min) { + return min; + } + + if (rounded > max) { + return max; + } + + return rounded; +}; + +/** + * Resolves the effective retry policy for a model, falling back to the + * defaults when the model configures no (or a partial) `retry` policy. + */ +export const resolveInferenceRetryConfig = (model: LanguageModel): InferenceRetryConfig => { + const retry = model.retry ?? {}; + return { + maxRetries: clampInt(retry.maxRetries, DEFAULT_INFERENCE_MAX_RETRIES, 0, MAX_INFERENCE_MAX_RETRIES), + initialBackoffMs: clampInt(retry.initialBackoffMs, DEFAULT_INFERENCE_INITIAL_BACKOFF_MS, 0, MAX_INFERENCE_BACKOFF_MS), + maxBackoffMs: clampInt(retry.maxBackoffMs, DEFAULT_INFERENCE_MAX_BACKOFF_MS, 0, MAX_INFERENCE_BACKOFF_MS), + }; +}; + +export const computeRetryDelayMs = (config: InferenceRetryConfig, failedAttemptIndex: number): number => { + return Math.min( + config.initialBackoffMs * Math.pow(2, failedAttemptIndex), + config.maxBackoffMs, + ); +}; + +/** + * Short human-readable model label used in logs and error messages. + */ +export const describeLanguageModel = (model: Pick): string => { + return `${model.provider}/${model.model}`; +}; + +type ApiErrorDetails = { + statusCode?: number; + responseBody?: unknown; + url?: string; + isRetryable?: boolean; +}; + +/** + * Best-effort extraction of the provider-facing fields from an inference + * error. Prefers the AI SDK's `APICallError` shape but duck-types the same + * fields so errors from wrapped providers are still surfaced. + */ +export const extractApiErrorDetails = (error: unknown): ApiErrorDetails => { + if (error === null || typeof error !== 'object') { + return {}; + } + + if (APICallError.isInstance(error)) { + return { + statusCode: typeof error.statusCode === 'number' ? error.statusCode : undefined, + responseBody: error.responseBody, + url: typeof error.url === 'string' ? error.url : undefined, + isRetryable: error.isRetryable, + }; + } + + const record = error as Record; + const details: ApiErrorDetails = {}; + if (typeof record['statusCode'] === 'number') { + details.statusCode = record['statusCode']; + } else if (typeof record['status'] === 'number') { + details.statusCode = record['status']; + } + + if (typeof record['responseBody'] === 'string' || (typeof record['responseBody'] === 'object' && record['responseBody'] !== null)) { + details.responseBody = record['responseBody']; + } + + if (typeof record['url'] === 'string') { + details.url = record['url']; + } + + if (typeof record['isRetryable'] === 'boolean') { + details.isRetryable = record['isRetryable']; + } + + return details; +}; + +const NETWORK_ERROR_CODES = new Set([ + 'ECONNRESET', + 'ECONNREFUSED', + 'ETIMEDOUT', + 'EAI_AGAIN', + 'ENOTFOUND', + 'EPIPE', + 'UND_ERR_CONNECT_TIMEOUT', + 'UND_ERR_SOCKET', +]); + +const NETWORK_ERROR_MESSAGE_HINTS = [ + 'fetch failed', + 'network error', + 'terminated', + 'socket hang up', +]; + +/** + * Walks the `cause` chain looking for a network-level failure. The AI SDK + * does not always mark body-read network errors retryable, so this covers + * transient transport failures explicitly. + */ +const hasNetworkErrorCause = (error: unknown): boolean => { + let current: unknown = error; + // Bound the walk: cause chains are short, but never trust their shape. + for (let depth = 0; depth < 5; depth++) { + if (current === null || (typeof current !== 'object' && typeof current !== 'string')) { + return false; + } + + if (typeof current === 'string') { + const text = current; + return NETWORK_ERROR_MESSAGE_HINTS.some((hint) => text.toLowerCase().includes(hint)); + } + + const record = current as Record; + const code = record['code']; + if (typeof code === 'string' && NETWORK_ERROR_CODES.has(code)) { + return true; + } + + const message = record['message']; + if (typeof message === 'string') { + const text = message; + if (NETWORK_ERROR_MESSAGE_HINTS.some((hint) => text.toLowerCase().includes(hint))) { + return true; + } + } + + if (!('cause' in record)) { + return false; + } + + current = record['cause']; + } + + return false; +}; + +/** + * Whether an inference failure is worth retrying: explicit SDK retryability, + * retry-safe status codes (408/429/5xx), or a network-level transport error. + * Deterministic client errors (other 4xx, bad config, unknown models) are + * surfaced immediately. + */ +export const isRetryableInferenceError = (error: unknown): boolean => { + if (error instanceof ServiceErrorException) { + return false; + } + + const details = extractApiErrorDetails(error); + if (details.isRetryable === true) { + return true; + } + + if (details.statusCode !== undefined) { + return details.statusCode === 408 || details.statusCode === 429 || details.statusCode >= 500; + } + + return hasNetworkErrorCause(error); +}; + +const collapseWhitespace = (value: string): string => { + return value.replace(/\s+/g, ' ').trim(); +}; + +const responseBodySnippet = (responseBody: unknown): string | undefined => { + if (responseBody === undefined) { + return undefined; + } + + const text = typeof responseBody === 'string' ? responseBody : JSON.stringify(responseBody); + const collapsed = collapseWhitespace(text); + if (collapsed.length === 0) { + return undefined; + } + + return collapsed.length > MAX_RESPONSE_BODY_SNIPPET_CHARS + ? `${collapsed.substring(0, MAX_RESPONSE_BODY_SNIPPET_CHARS)}…` + : collapsed; +}; + +/** + * Client-safe, single-line description of an inference failure. Includes the + * model, the provider's message, and its status code. Never includes the + * provider response body: it is untrusted third-party content that can echo + * request data, and these messages reach client-facing surfaces (interactive + * chat error chunks, the blocking chat API, and MCP tool responses), including + * for anonymous requests. Never includes request bodies either (they may + * contain prompt content). Use `formatInferenceErrorForLog` for server logs. + */ +export const formatInferenceError = (error: unknown, model: Pick): string => { + const label = describeLanguageModel(model); + const message = error instanceof Error ? error.message : String(error); + const details = extractApiErrorDetails(error); + + let formatted = `[${label}] ${collapseWhitespace(message) || 'Unknown inference error'}`; + if (details.statusCode !== undefined) { + formatted += ` (status ${details.statusCode})`; + } + + return formatted; +}; + +/** + * Log-only description of an inference failure. Same as + * `formatInferenceError` plus a truncated provider response body for + * debugging. Must only be written to server logs, never returned to clients. + */ +export const formatInferenceErrorForLog = (error: unknown, model: Pick): string => { + const formatted = formatInferenceError(error, model); + const snippet = responseBodySnippet(extractApiErrorDetails(error).responseBody); + if (snippet) { + return `${formatted} | provider response: ${snippet}`; + } + + return formatted; +}; + +const isValidHttpStatusCode = (statusCode: number): boolean => { + return Number.isInteger(statusCode) && statusCode >= 400 && statusCode <= 599; +}; + +/** + * Maps any inference failure to a `ServiceError` that preserves the + * provider's status code and details. `ServiceErrorException`s that do not + * describe inference failures (e.g. bad request params) pass through + * untouched so deterministic request errors never look like provider errors. + */ +export const toInferenceServiceError = (error: unknown, model: Pick): ServiceError => { + if (error instanceof ServiceErrorException) { + return error.serviceError; + } + + const { statusCode } = extractApiErrorDetails(error); + return { + statusCode: statusCode !== undefined && isValidHttpStatusCode(statusCode) + ? statusCode + : StatusCodes.INTERNAL_SERVER_ERROR, + errorCode: ErrorCode.INFERENCE_ERROR, + message: formatInferenceError(error, model), + }; +}; + +const sleep = (ms: number): Promise => { + return new Promise((resolve) => setTimeout(resolve, ms)); +}; + +/** + * Runs `fn` with exponential-backoff retries for transient inference + * failures. Non-retryable failures (and `ServiceErrorException`s, which + * describe Sourcebot-side request errors) are rethrown immediately. + */ +export const withInferenceRetries = async ( + fn: () => Promise, + config: InferenceRetryConfig, + model: Pick, +): Promise => { + const label = describeLanguageModel(model); + let attempt = 0; + for (;;) { + try { + return await fn(); + } catch (error) { + if (error instanceof ServiceErrorException || attempt >= config.maxRetries || !isRetryableInferenceError(error)) { + throw error; + } + + const delayMs = computeRetryDelayMs(config, attempt); + logger.warn(`Inference request with model ${label} failed (attempt ${attempt + 1}/${config.maxRetries + 1}). Retrying in ${delayMs}ms. Details: ${formatInferenceErrorForLog(error, model)}`); + await sleep(delayMs); + attempt += 1; + } + } +}; + +/** + * Resolves the ordered candidate chain for a request: the requested model + * first, then its configured `fallbackModels` in order. References to models + * that are not configured are skipped with a warning. A reference matches the + * first configured model with the same provider and model (and display name, + * when set) that is not already in the chain, so a same-id backup entry is + * tried instead of silently reusing the primary; references that resolve only + * to models already in the chain are skipped with a warning. + */ +export const resolveFallbackChain = (primaryModel: LanguageModel, allModels: LanguageModel[]): LanguageModel[] => { + const chain: LanguageModel[] = [primaryModel]; + const seen = new Set([getLanguageModelKey(primaryModel)]); + + for (const ref of primaryModel.fallbackModels ?? []) { + if (chain.length > MAX_INFERENCE_FALLBACK_MODELS) { + break; + } + + const matches = allModels.filter((candidate) => + candidate.provider === ref.provider && + candidate.model === ref.model && + (ref.displayName === undefined || candidate.displayName === ref.displayName) + ); + + if (matches.length === 0) { + logger.warn(`Fallback model ${describeLanguageModel(ref)} for ${describeLanguageModel(primaryModel)} is not configured. Skipping.`); + continue; + } + + const match = matches.find((candidate) => !seen.has(getLanguageModelKey(candidate))); + if (!match) { + logger.warn(`Fallback model ${describeLanguageModel(ref)} for ${describeLanguageModel(primaryModel)} resolves only to models already in the chain. Skipping.`); + continue; + } + + seen.add(getLanguageModelKey(match)); + chain.push(match); + } + + return chain; +}; + +export type InferenceFallbackOutcome = { + result: T; + /** The model that actually served the request (a fallback when the primary failed). */ + modelConfig: LanguageModel; + primaryModelConfig: LanguageModel; +}; + +const buildFallbackExhaustedError = ( + candidates: LanguageModel[], + attemptErrors: { model: LanguageModel; error: unknown }[], +): ServiceError => { + const attempts = attemptErrors + .map(({ model, error }) => formatInferenceError( + error instanceof ServiceErrorException ? error.serviceError.message : error, + model, + )) + .join('; '); + + const lastError = attemptErrors[attemptErrors.length - 1]?.error; + const lastServiceError = lastError instanceof ServiceErrorException + ? lastError.serviceError + : toInferenceServiceError(lastError, candidates[candidates.length - 1]); + + return { + statusCode: lastServiceError.statusCode, + errorCode: ErrorCode.INFERENCE_ERROR, + message: candidates.length === 1 + ? `Inference failed after retries. ${attempts}` + : `All ${candidates.length} models failed (primary ${describeLanguageModel(candidates[0])} + ${candidates.length - 1} fallback(s)). Attempts: ${attempts}`, + }; +}; + +/** + * Runs `run` against the primary model (with retries), falling back through + * the primary model's configured `fallbackModels` when inference fails + * transiently. Only retryable inference failures advance to the next model; + * deterministic failures (e.g. 401/403 provider responses) and non-inference + * `ServiceErrorException`s (bad request params, entitlement errors, ...) are + * surfaced immediately without burning fallback attempts. + */ +export const executeWithInferenceFallback = async ({ + primaryModel, + allModels, + run, +}: { + primaryModel: LanguageModel; + allModels: LanguageModel[]; + run: (model: LanguageModel, retryConfig: InferenceRetryConfig) => Promise; +}): Promise> => { + const candidates = resolveFallbackChain(primaryModel, allModels); + const attemptErrors: { model: LanguageModel; error: unknown }[] = []; + + for (let index = 0; index < candidates.length; index++) { + const candidate = candidates[index]; + const label = describeLanguageModel(candidate); + if (index > 0) { + logger.warn(`Falling back to model ${label} after inference failures with ${describeLanguageModel(candidates[index - 1])}.`); + } + + try { + const result = await withInferenceRetries( + () => run(candidate, resolveInferenceRetryConfig(candidate)), + resolveInferenceRetryConfig(candidate), + candidate, + ); + return { result, modelConfig: candidate, primaryModelConfig: primaryModel }; + } catch (error) { + if (error instanceof ServiceErrorException && error.serviceError.errorCode !== ErrorCode.INFERENCE_ERROR) { + throw error; + } + + // Fall back only on transient inference failures. Deterministic + // failures (e.g. 401/403) and internal errors surface immediately + // so they are neither retried pointlessly nor misreported as + // exhausted inference retries. + const isFallbackEligible = error instanceof ServiceErrorException || isRetryableInferenceError(error); + if (!isFallbackEligible) { + throw new ServiceErrorException(toInferenceServiceError(error, candidate)); + } + + attemptErrors.push({ model: candidate, error }); + if (index === candidates.length - 1) { + throw new ServiceErrorException(buildFallbackExhaustedError(candidates, attemptErrors)); + } + + logger.warn(`Inference with model ${label} failed. Trying the next fallback model. Details: ${formatInferenceErrorForLog(error, candidate)}`); + } + } + + // Unreachable: the loop above always returns or throws. + throw new Error('executeWithInferenceFallback: exhausted candidates without a result'); +}; diff --git a/packages/web/src/features/searchAssist/actions.ts b/packages/web/src/features/searchAssist/actions.ts index cf02e6087..102d9eaaa 100644 --- a/packages/web/src/features/searchAssist/actions.ts +++ b/packages/web/src/features/searchAssist/actions.ts @@ -3,8 +3,9 @@ import { sew } from "@/middleware/sew"; import { getConfiguredLanguageModels } from "../chat/utils.server"; import { getAISDKLanguageModelAndOptions } from "@/features/chat/llm.server"; +import { resolveInferenceRetryConfig, toInferenceServiceError, withInferenceRetries } from "@/features/chat/inferenceRetry.server"; import { ErrorCode } from "@/lib/errorCodes"; -import { ServiceError } from "@/lib/serviceError"; +import { ServiceError, ServiceErrorException } from "@/lib/serviceError"; import { withOptionalAuth } from "@/middleware/withAuth"; import { SEARCH_SYNTAX_DESCRIPTION } from "@sourcebot/query-language"; import { generateObject } from "ai"; @@ -38,16 +39,31 @@ export const translateSearchQuery = async ({ prompt }: { prompt: string }) => se } const { model } = await getAISDKLanguageModelAndOptions(models[0]); + const retryConfig = resolveInferenceRetryConfig(models[0]); - const { object } = await generateObject({ - model, - system: SYSTEM_PROMPT, - prompt, - schema: z.object({ - query: z.string().describe("The Sourcebot search query."), - }), - }); + try { + const { object } = await withInferenceRetries( + () => generateObject({ + model, + system: SYSTEM_PROMPT, + prompt, + schema: z.object({ + query: z.string().describe("The Sourcebot search query."), + }), + // Retries are handled by the wrapper so the per-model + // backoff policy applies; disable the SDK's built-in + // retries to avoid compounding them. + maxRetries: 0, + }), + retryConfig, + models[0], + ); - return { query: object.query }; + return { query: object.query }; + } catch (error) { + // Surface the provider's details instead of the generic + // `sew` fallback so translation failures are debuggable. + throw new ServiceErrorException(toInferenceServiceError(error, models[0])); + } }) ); diff --git a/packages/web/src/lib/errorCodes.ts b/packages/web/src/lib/errorCodes.ts index 766842b9f..1d07864ec 100644 --- a/packages/web/src/lib/errorCodes.ts +++ b/packages/web/src/lib/errorCodes.ts @@ -52,4 +52,5 @@ export enum ErrorCode { MEMBERSHIP_MANAGED_BY_IDP = 'MEMBERSHIP_MANAGED_BY_IDP', AGENT_SKILL_ALREADY_EXISTS = 'AGENT_SKILL_ALREADY_EXISTS', AGENT_SKILL_NOT_FOUND = 'AGENT_SKILL_NOT_FOUND', + INFERENCE_ERROR = 'INFERENCE_ERROR', } diff --git a/schemas/v3/languageModel.json b/schemas/v3/languageModel.json index 3f1d13d52..00b572595 100644 --- a/schemas/v3/languageModel.json +++ b/schemas/v3/languageModel.json @@ -50,6 +50,17 @@ }, "headers": { "$ref": "./shared.json#/definitions/LanguageModelHeaders" + }, + "retry": { + "$ref": "./shared.json#/definitions/LanguageModelRetry" + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "$ref": "./shared.json#/definitions/LanguageModelFallbackReference" + }, + "maxItems": 5 } }, "required": [ @@ -93,6 +104,17 @@ }, "headers": { "$ref": "./shared.json#/definitions/LanguageModelHeaders" + }, + "retry": { + "$ref": "./shared.json#/definitions/LanguageModelRetry" + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "$ref": "./shared.json#/definitions/LanguageModelFallbackReference" + }, + "maxItems": 5 } }, "required": [ @@ -160,6 +182,17 @@ }, "headers": { "$ref": "./shared.json#/definitions/LanguageModelHeaders" + }, + "retry": { + "$ref": "./shared.json#/definitions/LanguageModelRetry" + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "$ref": "./shared.json#/definitions/LanguageModelFallbackReference" + }, + "maxItems": 5 } }, "required": [ @@ -199,6 +232,17 @@ }, "headers": { "$ref": "./shared.json#/definitions/LanguageModelHeaders" + }, + "retry": { + "$ref": "./shared.json#/definitions/LanguageModelRetry" + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "$ref": "./shared.json#/definitions/LanguageModelFallbackReference" + }, + "maxItems": 5 } }, "required": [ @@ -252,6 +296,17 @@ }, "headers": { "$ref": "./shared.json#/definitions/LanguageModelHeaders" + }, + "retry": { + "$ref": "./shared.json#/definitions/LanguageModelRetry" + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "$ref": "./shared.json#/definitions/LanguageModelFallbackReference" + }, + "maxItems": 5 } }, "required": [ @@ -307,6 +362,17 @@ }, "headers": { "$ref": "./shared.json#/definitions/LanguageModelHeaders" + }, + "retry": { + "$ref": "./shared.json#/definitions/LanguageModelRetry" + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "$ref": "./shared.json#/definitions/LanguageModelFallbackReference" + }, + "maxItems": 5 } }, "required": [ @@ -378,6 +444,17 @@ }, "headers": { "$ref": "./shared.json#/definitions/LanguageModelHeaders" + }, + "retry": { + "$ref": "./shared.json#/definitions/LanguageModelRetry" + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "$ref": "./shared.json#/definitions/LanguageModelFallbackReference" + }, + "maxItems": 5 } }, "required": [ @@ -417,6 +494,17 @@ }, "headers": { "$ref": "./shared.json#/definitions/LanguageModelHeaders" + }, + "retry": { + "$ref": "./shared.json#/definitions/LanguageModelRetry" + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "$ref": "./shared.json#/definitions/LanguageModelFallbackReference" + }, + "maxItems": 5 } }, "required": [ @@ -482,6 +570,17 @@ }, "headers": { "$ref": "./shared.json#/definitions/LanguageModelHeaders" + }, + "retry": { + "$ref": "./shared.json#/definitions/LanguageModelRetry" + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "$ref": "./shared.json#/definitions/LanguageModelFallbackReference" + }, + "maxItems": 5 } }, "required": [ @@ -537,6 +636,17 @@ "temperature": { "type": "number", "description": "Optional temperature setting to use with the model." + }, + "retry": { + "$ref": "./shared.json#/definitions/LanguageModelRetry" + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "$ref": "./shared.json#/definitions/LanguageModelFallbackReference" + }, + "maxItems": 5 } }, "required": [ @@ -577,6 +687,17 @@ }, "headers": { "$ref": "./shared.json#/definitions/LanguageModelHeaders" + }, + "retry": { + "$ref": "./shared.json#/definitions/LanguageModelRetry" + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "$ref": "./shared.json#/definitions/LanguageModelFallbackReference" + }, + "maxItems": 5 } }, "required": [ @@ -620,6 +741,17 @@ }, "headers": { "$ref": "./shared.json#/definitions/LanguageModelHeaders" + }, + "retry": { + "$ref": "./shared.json#/definitions/LanguageModelRetry" + }, + "fallbackModels": { + "type": "array", + "description": "Optional ordered list of fallback models to try when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries. Each entry must reference another model in the `models` array. Fallbacks are attempted in order.", + "items": { + "$ref": "./shared.json#/definitions/LanguageModelFallbackReference" + }, + "maxItems": 5 } }, "required": [ diff --git a/schemas/v3/shared.json b/schemas/v3/shared.json index c45c834f0..d729079f4 100644 --- a/schemas/v3/shared.json +++ b/schemas/v3/shared.json @@ -106,6 +106,71 @@ } }, "additionalProperties": false + }, + "LanguageModelRetry": { + "type": "object", + "description": "Optional retry policy for inference requests made with this model. When unset, defaults apply (3 retries with exponential backoff starting at 500ms).", + "properties": { + "maxRetries": { + "type": "integer", + "description": "Maximum number of retry attempts for a failed inference request. Only transient failures (network errors, 408/429/5xx responses) are retried. Set to 0 to disable retries. Defaults to 3.", + "minimum": 0, + "maximum": 10, + "default": 3 + }, + "initialBackoffMs": { + "type": "integer", + "description": "Delay in milliseconds before the first retry. Doubles after each attempt, up to maxBackoffMs. Defaults to 500.", + "minimum": 0, + "maximum": 120000, + "default": 500 + }, + "maxBackoffMs": { + "type": "integer", + "description": "Maximum delay in milliseconds between retries. Defaults to 8000.", + "minimum": 0, + "maximum": 120000, + "default": 8000 + } + }, + "additionalProperties": false + }, + "LanguageModelFallbackReference": { + "type": "object", + "description": "Reference to another configured language model to use as a fallback when blocking Ask requests (the MCP ask_codebase tool and the blocking chat API) with this model keep failing after retries.", + "properties": { + "provider": { + "type": "string", + "description": "The provider of the fallback language model. Must match the provider of another entry in `models`.", + "enum": [ + "amazon-bedrock", + "anthropic", + "azure", + "deepseek", + "google-generative-ai", + "google-vertex-anthropic", + "google-vertex", + "mistral", + "openai", + "openai-compatible", + "openrouter", + "xai" + ] + }, + "model": { + "type": "string", + "description": "The name of the fallback language model. Must match the `model` of another entry in `models` with the same provider." + }, + "displayName": { + "type": "string", + "description": "Optional display name. When set, the fallback matches the configured model with the same provider, model and display name." + } + }, + "required": [ + "provider", + "model" + ], + "additionalProperties": false } } } \ No newline at end of file