diff --git a/litellm/__init__.py b/litellm/__init__.py index 41a3789ab0dd..21765c937e50 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -672,6 +672,8 @@ def identify(event_details): v0_models: Set = set() morph_models: Set = set() lambda_ai_models: Set = set() +opencode_models: Set = set() +opencode_go_models: Set = set() inception_models: Set = set() hyperbolic_models: Set = set() black_forest_labs_models: Set = set() @@ -934,6 +936,10 @@ def _populate_provider_model_sets(model_cost_map: Dict) -> None: morph_models.add(key) elif value.get("litellm_provider") == "lambda_ai": lambda_ai_models.add(key) + elif value.get("litellm_provider") == "opencode": + opencode_models.add(key) + elif value.get("litellm_provider") == "opencode_go": + opencode_go_models.add(key) elif value.get("litellm_provider") == "inception": inception_models.add(key) elif value.get("litellm_provider") == "hyperbolic": @@ -1091,6 +1097,8 @@ def add_known_models(model_cost_map: Optional[Dict] = None): | v0_models | morph_models | lambda_ai_models + | opencode_models + | opencode_go_models | inception_models | black_forest_labs_models | recraft_models @@ -1200,6 +1208,8 @@ def _build_models_by_provider() -> dict: "v0": v0_models, "morph": morph_models, "lambda_ai": lambda_ai_models, + "opencode": opencode_models, + "opencode_go": opencode_go_models, "inception": inception_models, "hyperbolic": hyperbolic_models, "black_forest_labs": black_forest_labs_models, @@ -2064,6 +2074,18 @@ def set_global_gitlab_config(config: Dict[str, Any]) -> None: from .llms.lambda_ai.chat.transformation import ( LambdaAIChatConfig as LambdaAIChatConfig, ) + from .llms.opencode.chat.transformation import ( + OpenCodeGoChatConfig as OpenCodeGoChatConfig, + ) + from .llms.opencode.chat.transformation import ( + OpenCodeZenChatConfig as OpenCodeZenChatConfig, + ) + from .llms.opencode.responses.transformation import ( + OpenCodeGoResponsesAPIConfig as OpenCodeGoResponsesAPIConfig, + ) + from .llms.opencode.responses.transformation import ( + OpenCodeZenResponsesAPIConfig as OpenCodeZenResponsesAPIConfig, + ) from .llms.inception.chat.transformation import ( InceptionChatConfig as InceptionChatConfig, ) diff --git a/litellm/_lazy_imports_registry.py b/litellm/_lazy_imports_registry.py index e9199e1ec809..1970e394d099 100644 --- a/litellm/_lazy_imports_registry.py +++ b/litellm/_lazy_imports_registry.py @@ -320,6 +320,13 @@ "MorphChatConfig", "RAGFlowConfig", "LambdaAIChatConfig", + "OpenCodeZenChatConfig", + "OpenCodeGoChatConfig", + "OpenCodeZenMessagesChatConfig", + "OpenCodeGoMessagesChatConfig", + "OpenCodeZenGeminiChatConfig", + "OpenCodeZenResponsesAPIConfig", + "OpenCodeGoResponsesAPIConfig", "InceptionChatConfig", "HyperbolicChatConfig", "VercelAIGatewayConfig", @@ -1200,6 +1207,28 @@ "MorphChatConfig": (".llms.morph.chat.transformation", "MorphChatConfig"), "RAGFlowConfig": (".llms.ragflow.chat.transformation", "RAGFlowConfig"), "LambdaAIChatConfig": (".llms.lambda_ai.chat.transformation", "LambdaAIChatConfig"), + "OpenCodeZenChatConfig": (".llms.opencode.chat.transformation", "OpenCodeZenChatConfig"), + "OpenCodeGoChatConfig": (".llms.opencode.chat.transformation", "OpenCodeGoChatConfig"), + "OpenCodeZenMessagesChatConfig": ( + ".llms.opencode.chat.transformation", + "OpenCodeZenMessagesChatConfig", + ), + "OpenCodeGoMessagesChatConfig": ( + ".llms.opencode.chat.transformation", + "OpenCodeGoMessagesChatConfig", + ), + "OpenCodeZenGeminiChatConfig": ( + ".llms.opencode.chat.transformation", + "OpenCodeZenGeminiChatConfig", + ), + "OpenCodeZenResponsesAPIConfig": ( + ".llms.opencode.responses.transformation", + "OpenCodeZenResponsesAPIConfig", + ), + "OpenCodeGoResponsesAPIConfig": ( + ".llms.opencode.responses.transformation", + "OpenCodeGoResponsesAPIConfig", + ), "InceptionChatConfig": ( ".llms.inception.chat.transformation", "InceptionChatConfig", diff --git a/litellm/constants.py b/litellm/constants.py index ef9329b9dfce..3d6c316252c5 100644 --- a/litellm/constants.py +++ b/litellm/constants.py @@ -679,6 +679,8 @@ "oci", "morph", "lambda_ai", + "opencode", + "opencode_go", "inception", "vercel_ai_gateway", "wandb", @@ -865,6 +867,8 @@ "https://api.cognition.ai/v1", "https://api.scx.ai/v1", "https://gigachat.devices.sberbank.ru/api/v1", + "https://opencode.ai/zen/go/v1", + "https://opencode.ai/zen/v1", ] @@ -922,6 +926,8 @@ "helicone", "morph", "lambda_ai", + "opencode", + "opencode_go", "inception", "hyperbolic", "vercel_ai_gateway", diff --git a/litellm/litellm_core_utils/get_llm_provider_logic.py b/litellm/litellm_core_utils/get_llm_provider_logic.py index ce51fb199704..d5a3c39dea24 100644 --- a/litellm/litellm_core_utils/get_llm_provider_logic.py +++ b/litellm/litellm_core_utils/get_llm_provider_logic.py @@ -351,6 +351,12 @@ def get_llm_provider( elif endpoint == "https://api.lambda.ai/v1": custom_llm_provider = "lambda_ai" dynamic_api_key = get_secret_str("LAMBDA_API_KEY") + elif endpoint == "https://opencode.ai/zen/go/v1": + custom_llm_provider = "opencode_go" # rebind-ok: dispatch chain rebinds this param + dynamic_api_key = api_key or get_secret_str("OPENCODE_API_KEY") + elif endpoint == "https://opencode.ai/zen/v1": + custom_llm_provider = "opencode" # rebind-ok: dispatch chain rebinds this param + dynamic_api_key = api_key or get_secret_str("OPENCODE_API_KEY") elif endpoint == "https://api.inceptionlabs.ai/v1": custom_llm_provider = "inception" dynamic_api_key = get_secret_str("INCEPTION_API_KEY") @@ -829,6 +835,16 @@ def _get_openai_compatible_provider_info( api_base, dynamic_api_key, ) = litellm.LambdaAIChatConfig()._get_openai_compatible_provider_info(api_base, api_key) + elif custom_llm_provider == "opencode": + ( + api_base, # rebind-ok: resolution chain returns these params + dynamic_api_key, # rebind-ok: resolution chain returns these params + ) = litellm.OpenCodeZenChatConfig()._get_openai_compatible_provider_info(api_base, api_key) + elif custom_llm_provider == "opencode_go": + ( + api_base, # rebind-ok: resolution chain returns these params + dynamic_api_key, # rebind-ok: resolution chain returns these params + ) = litellm.OpenCodeGoChatConfig()._get_openai_compatible_provider_info(api_base, api_key) elif custom_llm_provider == "inception": ( api_base, diff --git a/litellm/llms/opencode/__init__.py b/litellm/llms/opencode/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/litellm/llms/opencode/chat/__init__.py b/litellm/llms/opencode/chat/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/litellm/llms/opencode/chat/transformation.py b/litellm/llms/opencode/chat/transformation.py new file mode 100644 index 000000000000..fb6da3ac21ef --- /dev/null +++ b/litellm/llms/opencode/chat/transformation.py @@ -0,0 +1,209 @@ +""" +Translate from OpenAI's `/v1/chat/completions` to OpenCode Zen's and OpenCode Go's. + +Both surfaces are OpenAI-compatible, so only the default base URL, the credential lookup and +the required `x-opencode-session` header differ from stock OpenAI. +""" + +from collections.abc import Mapping, Sequence +from itertools import chain +from typing import ClassVar, Final + +from litellm.llms.anthropic.chat.transformation import AnthropicConfig +from litellm.llms.gemini.chat.transformation import GoogleAIStudioGeminiConfig +from litellm.llms.openai_like.chat.transformation import OpenAILikeChatConfig +from litellm.secret_managers.main import get_secret_str +from litellm.types.llms.openai import AllMessageValues + +from ..common_utils import resolve_opencode_api_key, with_opencode_session_header + + +class OpenCodeChatConfig(OpenAILikeChatConfig): + _provider: ClassVar[str] + _default_api_base: ClassVar[str] + _api_base_env_var: ClassVar[str] + + @property + def custom_llm_provider(self) -> str | None: + return self._provider + + def _get_openai_compatible_provider_info( + self, api_base: str | None, api_key: str | None + ) -> tuple[str | None, str | None]: + resolved_api_base: Final = api_base or get_secret_str(self._api_base_env_var) or self._default_api_base + return resolved_api_base, resolve_opencode_api_key(api_key) + + def validate_environment( + self, + headers: Mapping[str, object], + model: str, + messages: Sequence[AllMessageValues], + optional_params: Mapping[str, object], + litellm_params: Mapping[str, object], + api_key: str | None = None, + api_base: str | None = None, + ) -> dict: # mutable-ok: return type is fixed by BaseConfig.validate_environment, whose callers mutate it + base_headers: Final[Mapping[str, object]] = super().validate_environment( + headers=dict(headers), # mutable-ok: BaseConfig.validate_environment only accepts mutable dicts + model=model, + messages=list(messages), # mutable-ok: BaseConfig.validate_environment only accepts a mutable list + optional_params=dict(optional_params), # mutable-ok: as above + litellm_params=dict(litellm_params), # mutable-ok: as above + api_key=api_key, + api_base=api_base, + ) + return with_opencode_session_header(base_headers, litellm_params) + + +class OpenCodeZenChatConfig(OpenCodeChatConfig): + _provider: ClassVar[str] = "opencode" + _default_api_base: ClassVar[str] = "https://opencode.ai/zen/v1" + _api_base_env_var: ClassVar[str] = "OPENCODE_API_BASE" + + +class OpenCodeGoChatConfig(OpenCodeChatConfig): + _provider: ClassVar[str] = "opencode_go" + _default_api_base: ClassVar[str] = "https://opencode.ai/zen/go/v1" + _api_base_env_var: ClassVar[str] = "OPENCODE_GO_API_BASE" + + +class OpenCodeMessagesChatConfig(AnthropicConfig): + """ + OpenCode serves part of its catalogue (Claude, Qwen, MiniMax) on an Anthropic-shaped + `/messages` endpoint that authenticates with `x-api-key` rather than a bearer token. + """ + + _provider: ClassVar[str] + _default_api_base: ClassVar[str] + _api_base_env_var: ClassVar[str] + + @property + def custom_llm_provider(self) -> str | None: + return self._provider + + def get_complete_url( + self, + api_base: str | None, + api_key: str | None, + model: str, + optional_params: Mapping[str, object], + litellm_params: Mapping[str, object], + stream: bool | None = None, + ) -> str: + resolved_api_base: Final = ( + api_base or get_secret_str(self._api_base_env_var) or self._default_api_base + ).rstrip("/") + if resolved_api_base.endswith("/messages"): + return resolved_api_base + return f"{resolved_api_base}/messages" + + def validate_environment( + self, + headers: Mapping[str, object], + model: str, + messages: Sequence[AllMessageValues], + optional_params: Mapping[str, object], + litellm_params: Mapping[str, object], + api_key: str | None = None, + api_base: str | None = None, + ) -> dict: # mutable-ok: return type is fixed by BaseConfig.validate_environment + base_headers: Final[Mapping[str, object]] = super().validate_environment( + headers=dict(headers), # mutable-ok: AnthropicConfig.validate_environment needs a mutable dict + model=model, + messages=list(messages), # mutable-ok: as above + optional_params=dict(optional_params), # mutable-ok: as above + litellm_params=dict(litellm_params), # mutable-ok: as above + api_key=resolve_opencode_api_key(api_key), + api_base=api_base, + ) + return with_opencode_session_header(base_headers, litellm_params) + + +class OpenCodeZenMessagesChatConfig(OpenCodeMessagesChatConfig): + _provider: ClassVar[str] = "opencode" + _default_api_base: ClassVar[str] = "https://opencode.ai/zen/v1" + _api_base_env_var: ClassVar[str] = "OPENCODE_API_BASE" + + +class OpenCodeGoMessagesChatConfig(OpenCodeMessagesChatConfig): + _provider: ClassVar[str] = "opencode_go" + _default_api_base: ClassVar[str] = "https://opencode.ai/zen/go/v1" + _api_base_env_var: ClassVar[str] = "OPENCODE_GO_API_BASE" + + +class OpenCodeZenGeminiChatConfig(GoogleAIStudioGeminiConfig): + """ + OpenCode Zen serves Google models on Gemini's own `models/:generateContent` shape, + hosted under the Zen base URL and authenticated with a bearer token. + """ + + _default_api_base: ClassVar[str] = "https://opencode.ai/zen/v1" + _api_base_env_var: ClassVar[str] = "OPENCODE_API_BASE" + + @property + def custom_llm_provider(self) -> str | None: + return "opencode" + + def get_complete_url( + self, + api_base: str | None, + api_key: str | None, + model: str, + optional_params: Mapping[str, object], + litellm_params: Mapping[str, object], + stream: bool | None = None, + ) -> str: + resolved_api_base: Final = ( + api_base or get_secret_str(self._api_base_env_var) or self._default_api_base + ).rstrip("/") + if stream: + return f"{resolved_api_base}/models/{model}:streamGenerateContent?alt=sse" + return f"{resolved_api_base}/models/{model}:generateContent" + + def transform_request( + self, + model: str, + messages: Sequence[AllMessageValues], + optional_params: Mapping[str, object], + litellm_params: Mapping[str, object], + headers: Mapping[str, object], + ) -> dict: # mutable-ok: return type is fixed by BaseConfig.transform_request + """ + VertexGeminiConfig.transform_request raises NotImplementedError because Vertex builds its + body in a bespoke handler, so reuse the shared Gemini body builder that handler calls. + """ + from litellm.llms.vertex_ai.gemini.transformation import _transform_request_body + + cached_content: Final = optional_params.get("cached_content") + return _transform_request_body( + messages=list(messages), # mutable-ok: the Gemini body builder takes a mutable list + model=model, + optional_params=dict(optional_params), # mutable-ok: as above + custom_llm_provider="gemini", + litellm_params=dict(litellm_params), # mutable-ok: as above + cached_content=cached_content if isinstance(cached_content, str) else None, + ) + + def validate_environment( + self, + headers: Mapping[str, object] | None, + model: str, + messages: Sequence[AllMessageValues], + optional_params: Mapping[str, object], + litellm_params: Mapping[str, object], + api_key: str | dict | None = None, # mutable-ok: signature is fixed by VertexGeminiConfig + api_base: str | None = None, + ) -> dict: # mutable-ok: return type is fixed by BaseConfig.validate_environment + """ + OpenCode authenticates this endpoint with Google's `x-goog-api-key`; a bearer token, + an `x-api-key` and a `?key=` query parameter all come back as `Missing API key`. + """ + resolved_key: Final = resolve_opencode_api_key(api_key if isinstance(api_key, str) else None) + base_headers: Final[Mapping[str, object]] = dict( + chain( + (("Content-Type", "application/json"),), + headers.items() if headers else (), + (("x-goog-api-key", resolved_key),), + ) + ) + return with_opencode_session_header(base_headers, litellm_params) diff --git a/litellm/llms/opencode/common_utils.py b/litellm/llms/opencode/common_utils.py new file mode 100644 index 000000000000..779edc4cbf19 --- /dev/null +++ b/litellm/llms/opencode/common_utils.py @@ -0,0 +1,66 @@ +""" +Shared helpers for OpenCode's managed inference APIs (Zen and Go). +""" + +from collections.abc import Iterable, Mapping, Sequence +from itertools import chain +from typing import Final + +from litellm.secret_managers.main import get_secret_str + +OPENCODE_SESSION_HEADER: Final = "x-opencode-session" +OPENCODE_API_KEY_ENV_VAR: Final = "OPENCODE_API_KEY" + + +def resolve_opencode_session_id(litellm_params: Mapping[str, object]) -> str | None: + """ + OpenCode requires a stable per-conversation id on every inference request so it can pin a + conversation to one upstream and keep that upstream's prompt cache warm. LiteLLM keeps no + conversation state of its own, so a caller-supplied session id is the only value that is + genuinely stable across turns; the per-request ids are a last resort that keeps the request + accepted even though it forfeits cache affinity. + """ + metadata: Final = litellm_params.get("metadata") + candidates: Final = ( + litellm_params.get("litellm_session_id"), + metadata.get("session_id") if isinstance(metadata, Mapping) else None, + litellm_params.get("litellm_trace_id"), + litellm_params.get("litellm_call_id"), + ) + return next((candidate for candidate in candidates if isinstance(candidate, str) and candidate), None) + + +def has_opencode_session_header(header_names: Iterable[str]) -> bool: + return any(name.lower() == OPENCODE_SESSION_HEADER for name in header_names) + + +def with_opencode_session_header( + headers: Mapping[str, object], litellm_params: Mapping[str, object] +) -> dict[str, object]: # mutable-ok: every caller hands this straight back to validate_environment, which returns dict + """Stamp the session header onto already-authenticated headers, leaving a caller's own value alone.""" + session_id: Final = None if has_opencode_session_header(headers) else resolve_opencode_session_id(litellm_params) + stamped: Final = () if session_id is None else ((OPENCODE_SESSION_HEADER, session_id),) + return dict(chain(headers.items(), stamped)) + + +def opencode_endpoint_for_model(provider: str, model: str) -> str: + """ + OpenCode splits its catalogue across three wire formats and the split is per model, not + per family: on Go, qwen and minimax are served by `/messages` while glm, kimi and deepseek + are served by `/chat/completions`. The cost map records each model's endpoint, so read it + from there and fall back to the OpenAI-compatible path for anything unlisted. + """ + import litellm + + entry: Final = litellm.model_cost.get(f"{provider}/{model}") or litellm.model_cost.get(model) + endpoints: Final = entry.get("supported_endpoints") if isinstance(entry, Mapping) else None + if isinstance(endpoints, Sequence) and not isinstance(endpoints, str) and endpoints: + first: Final = endpoints[0] + if isinstance(first, str): + return first + return "/v1/chat/completions" + + +def resolve_opencode_api_key(api_key: str | None) -> str | None: + """One OpenCode account key authenticates both Zen and Go, so both surfaces read one variable.""" + return api_key or get_secret_str(OPENCODE_API_KEY_ENV_VAR) diff --git a/litellm/llms/opencode/responses/__init__.py b/litellm/llms/opencode/responses/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/litellm/llms/opencode/responses/transformation.py b/litellm/llms/opencode/responses/transformation.py new file mode 100644 index 000000000000..c135ed4d6213 --- /dev/null +++ b/litellm/llms/opencode/responses/transformation.py @@ -0,0 +1,56 @@ +""" +OpenCode routes its OpenAI-family models to a `/responses` endpoint rather than +`/chat/completions`, which answers those models with a 500. + +The surface is OpenAI's own Responses API, so only the base URL, the credential lookup and +the required `x-opencode-session` header differ. +""" + +from collections.abc import Mapping +from typing import ClassVar, Final + +from litellm.llms.openai.responses.transformation import OpenAIResponsesAPIConfig +from litellm.secret_managers.main import get_secret_str +from litellm.types.router import GenericLiteLLMParams +from litellm.types.utils import LlmProviders + +from ..common_utils import resolve_opencode_api_key, with_opencode_session_header + + +class OpenCodeResponsesAPIConfig(OpenAIResponsesAPIConfig): + _provider: ClassVar[LlmProviders] + _default_api_base: ClassVar[str] + _api_base_env_var: ClassVar[str] + + @property + def custom_llm_provider(self) -> LlmProviders: + return self._provider + + def get_complete_url(self, api_base: str | None, litellm_params: Mapping[str, object]) -> str: + resolved_api_base: Final = ( + api_base or get_secret_str(self._api_base_env_var) or self._default_api_base + ).rstrip("/") + return f"{resolved_api_base}/responses" + + def validate_environment( + self, headers: Mapping[str, object], model: str, litellm_params: GenericLiteLLMParams | None + ) -> dict: # mutable-ok: signature is fixed by BaseResponsesAPIConfig.validate_environment + resolved_params: Final = litellm_params or GenericLiteLLMParams() + base_headers: Final[Mapping[str, object]] = { + "Content-Type": "application/json", + **headers, + "Authorization": f"Bearer {resolve_opencode_api_key(resolved_params.api_key)}", + } + return with_opencode_session_header(base_headers, resolved_params.model_dump()) + + +class OpenCodeZenResponsesAPIConfig(OpenCodeResponsesAPIConfig): + _provider: ClassVar[LlmProviders] = LlmProviders.OPENCODE + _default_api_base: ClassVar[str] = "https://opencode.ai/zen/v1" + _api_base_env_var: ClassVar[str] = "OPENCODE_API_BASE" + + +class OpenCodeGoResponsesAPIConfig(OpenCodeResponsesAPIConfig): + _provider: ClassVar[LlmProviders] = LlmProviders.OPENCODE_GO + _default_api_base: ClassVar[str] = "https://opencode.ai/zen/go/v1" + _api_base_env_var: ClassVar[str] = "OPENCODE_GO_API_BASE" diff --git a/litellm/main.py b/litellm/main.py index 0bca4a7350ef..6e56686b64a7 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -2076,6 +2076,56 @@ def _complete_groq(ctx: _CompletionDispatchContext) -> _CompletionDispatchResult ) +def _complete_opencode(ctx: _CompletionDispatchContext) -> _CompletionDispatchResult: + acompletion: Final = ctx.acompletion + api_base: Final = ctx.api_base + api_key: Final = ctx.api_key + client: Final = _dispatch_client_http(ctx) + custom_llm_provider: Final = ctx.custom_llm_provider + headers: Final = ctx.headers + litellm_params: Final = ctx.litellm_params + logging: Final = ctx.logging + messages: Final = ctx.messages + model: Final = ctx.model + model_response: Final = ctx.model_response + optional_params: Final = ctx.optional_params + provider_config: Final = ctx.provider_config + shared_session: Final = ctx.shared_session + stream: Final = ctx.stream + timeout: Final = ctx.timeout + + try: + response: Final = base_llm_http_handler.completion( + model=model, + messages=messages, + headers=headers, + model_response=model_response, + api_key=api_key, + api_base=api_base, + acompletion=acompletion, + logging_obj=logging, + optional_params=optional_params, + litellm_params=litellm_params, + shared_session=shared_session, + timeout=timeout, # pyright: ignore[reportArgumentType] # ctx.timeout allows str/None, as in sibling helpers + client=client, + custom_llm_provider=custom_llm_provider, + encoding=_get_encoding(), + stream=stream, + provider_config=provider_config, + ) + except Exception as e: + logging.post_call( + input=messages, + api_key=api_key, + original_response=str(e), + additional_args={"headers": headers}, + ) + raise e + + return response + + def _complete_bedrock_mantle( ctx: _CompletionDispatchContext, ) -> _CompletionDispatchResult: @@ -5671,6 +5721,8 @@ def completion( response = _complete_groq(_dispatch_ctx) elif custom_llm_provider == "bedrock_mantle": response = _complete_bedrock_mantle(_dispatch_ctx) + elif custom_llm_provider == "opencode" or custom_llm_provider == "opencode_go": + response = _complete_opencode(_dispatch_ctx) elif custom_llm_provider == "a2a": # A2A (Agent-to-Agent) Protocol # Resolve agent configuration from registry if model format is "a2a/" diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index d8a8f84b0323..1c154564b041 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -58456,5 +58456,2030 @@ "supported_endpoints": [ "/v1/audio/transcriptions" ] + }, + "opencode/big-pickle": { + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 200000, + "max_output_tokens": 32000, + "max_tokens": 32000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/claude-fable-5": { + "cache_creation_input_token_cost": 1.25e-05, + "cache_read_input_token_cost": 1e-06, + "input_cost_per_token": 1e-05, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 512, + "output_cost_per_token": 5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_sampling_params": false, + "thinking_always_on": true, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-fable-5-1": { + "cache_creation_input_token_cost": 1.25e-05, + "cache_read_input_token_cost": 2.5e-07, + "input_cost_per_token": 1e-05, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 512, + "output_cost_per_token": 5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_sampling_params": false, + "thinking_always_on": true, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-haiku-4-5": { + "cache_creation_input_token_cost": 1.25e-06, + "cache_read_input_token_cost": 1.0000000000000001e-07, + "input_cost_per_token": 1e-06, + "litellm_provider": "opencode", + "max_input_tokens": 200000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-opus-4-5": { + "cache_creation_input_token_cost": 6.25e-06, + "cache_read_input_token_cost": 5e-07, + "input_cost_per_token": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 200000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 2.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-opus-4-6": { + "cache_creation_input_token_cost": 6.25e-06, + "cache_read_input_token_cost": 5e-07, + "input_cost_per_token": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 2.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_legacy_thinking": true, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-opus-4-7": { + "cache_creation_input_token_cost": 6.25e-06, + "cache_read_input_token_cost": 5e-07, + "input_cost_per_token": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 2048, + "output_cost_per_token": 2.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_sampling_params": false, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-opus-4-8": { + "cache_creation_input_token_cost": 6.25e-06, + "cache_read_input_token_cost": 5e-07, + "input_cost_per_token": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 1024, + "output_cost_per_token": 2.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_sampling_params": false, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-opus-5": { + "cache_creation_input_token_cost": 6.25e-06, + "cache_read_input_token_cost": 5e-07, + "input_cost_per_token": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 512, + "output_cost_per_token": 2.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_sampling_params": false, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-sonnet-4": { + "cache_creation_input_token_cost": 3.75e-06, + "cache_creation_input_token_cost_above_200k_tokens": 7.5e-06, + "cache_read_input_token_cost": 3e-07, + "cache_read_input_token_cost_above_200k_tokens": 6e-07, + "input_cost_per_token": 3e-06, + "input_cost_per_token_above_200k_tokens": 6e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 1024, + "output_cost_per_token": 1.5e-05, + "output_cost_per_token_above_200k_tokens": 2.25e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-sonnet-4-5": { + "cache_creation_input_token_cost": 3.75e-06, + "cache_creation_input_token_cost_above_200k_tokens": 7.5e-06, + "cache_read_input_token_cost": 3e-07, + "cache_read_input_token_cost_above_200k_tokens": 6e-07, + "input_cost_per_token": 3e-06, + "input_cost_per_token_above_200k_tokens": 6e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 1024, + "output_cost_per_token": 1.5e-05, + "output_cost_per_token_above_200k_tokens": 2.25e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-sonnet-4-6": { + "cache_creation_input_token_cost": 3.75e-06, + "cache_read_input_token_cost": 3e-07, + "input_cost_per_token": 3e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 1024, + "output_cost_per_token": 1.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_legacy_thinking": true, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-sonnet-5": { + "cache_creation_input_token_cost": 2.5e-06, + "cache_read_input_token_cost": 2.0000000000000002e-07, + "input_cost_per_token": 2e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 1024, + "output_cost_per_token": 1e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_sampling_params": false, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/deepseek-v4-flash": { + "cache_read_input_token_cost": 2.8e-08, + "input_cost_per_token": 1.4e-07, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 2.8e-07, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/deepseek-v4-flash-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 200000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/deepseek-v4-pro": { + "cache_read_input_token_cost": 1.45e-07, + "input_cost_per_token": 1.74e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 3.84e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/gemini-3-flash": { + "cache_read_input_token_cost": 5.0000000000000004e-08, + "input_cost_per_token": 5e-07, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "output_cost_per_token": 3e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gemini-3.1-pro": { + "cache_read_input_token_cost": 2.0000000000000002e-07, + "cache_read_input_token_cost_above_200k_tokens": 4.0000000000000003e-07, + "input_cost_per_token": 2e-06, + "input_cost_per_token_above_200k_tokens": 4e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "output_cost_per_token": 1.2e-05, + "output_cost_per_token_above_200k_tokens": 1.8e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gemini-3.5-flash": { + "cache_read_input_token_cost": 1.5e-07, + "input_cost_per_token": 1.5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 9e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gemini-3.5-flash-lite": { + "cache_read_input_token_cost": 3e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "output_cost_per_token": 2.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gemini-3.6-flash": { + "cache_read_input_token_cost": 1.5e-07, + "input_cost_per_token": 1.5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 7.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gemini-3.7-flash": { + "cache_read_input_token_cost": 1.5e-07, + "input_cost_per_token": 1.5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 7.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gemini-3.8-flash": { + "cache_read_input_token_cost": 1.5e-07, + "input_cost_per_token": 1.5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 7.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/glm-5": { + "cache_read_input_token_cost": 2.0000000000000002e-07, + "input_cost_per_token": 1e-06, + "litellm_provider": "opencode", + "max_input_tokens": 204800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 3.2000000000000003e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/glm-5.1": { + "cache_read_input_token_cost": 2.6e-07, + "input_cost_per_token": 1.4e-06, + "litellm_provider": "opencode", + "max_input_tokens": 204800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4.4e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/glm-5.2": { + "cache_read_input_token_cost": 2.6e-07, + "input_cost_per_token": 1.4e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4.4e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/gpt-5": { + "cache_read_input_token_cost": 1.0699999999999999e-07, + "input_cost_per_token": 1.0700000000000001e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 8.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5-codex": { + "cache_read_input_token_cost": 1.0699999999999999e-07, + "input_cost_per_token": 1.0700000000000001e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 8.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5-nano": { + "cache_read_input_token_cost": 5e-09, + "input_cost_per_token": 5.0000000000000004e-08, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 4.0000000000000003e-07, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.1": { + "cache_read_input_token_cost": 1.0699999999999999e-07, + "input_cost_per_token": 1.0700000000000001e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 8.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.1-codex": { + "cache_read_input_token_cost": 1.0699999999999999e-07, + "input_cost_per_token": 1.0700000000000001e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 8.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.1-codex-max": { + "cache_read_input_token_cost": 1.25e-07, + "input_cost_per_token": 1.25e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.1-codex-mini": { + "cache_read_input_token_cost": 2.5000000000000002e-08, + "input_cost_per_token": 2.5e-07, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 2e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.2": { + "cache_read_input_token_cost": 1.75e-07, + "input_cost_per_token": 1.75e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.4e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.2-codex": { + "cache_read_input_token_cost": 1.75e-07, + "input_cost_per_token": 1.75e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.4e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.3-codex": { + "cache_read_input_token_cost": 1.75e-07, + "input_cost_per_token": 1.75e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.4e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.3-codex-spark": { + "cache_read_input_token_cost": 1.75e-07, + "input_cost_per_token": 1.75e-06, + "litellm_provider": "opencode", + "max_input_tokens": 128000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.4e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/gpt-5.4": { + "cache_read_input_token_cost": 2.5e-07, + "cache_read_input_token_cost_above_272k_tokens": 5e-07, + "input_cost_per_token": 2.5e-06, + "input_cost_per_token_above_272k_tokens": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.5e-05, + "output_cost_per_token_above_272k_tokens": 2.25e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.4-mini": { + "cache_read_input_token_cost": 7.5e-08, + "input_cost_per_token": 7.5e-07, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 4.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.4-nano": { + "cache_read_input_token_cost": 2e-08, + "input_cost_per_token": 2.0000000000000002e-07, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.25e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.4-pro": { + "cache_read_input_token_cost": 3e-05, + "input_cost_per_token": 3e-05, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 0.00018, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.5": { + "cache_read_input_token_cost": 5e-07, + "cache_read_input_token_cost_above_272k_tokens": 1e-06, + "input_cost_per_token": 5e-06, + "input_cost_per_token_above_272k_tokens": 1e-05, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 3e-05, + "output_cost_per_token_above_272k_tokens": 4.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.5-pro": { + "cache_read_input_token_cost": 3e-05, + "input_cost_per_token": 3e-05, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 0.00018, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.6-luna": { + "cache_creation_input_token_cost": 2.5e-07, + "cache_creation_input_token_cost_above_272k_tokens": 5e-07, + "cache_read_input_token_cost": 2e-08, + "cache_read_input_token_cost_above_272k_tokens": 4e-08, + "input_cost_per_token": 2.0000000000000002e-07, + "input_cost_per_token_above_272k_tokens": 4.0000000000000003e-07, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.2e-06, + "output_cost_per_token_above_272k_tokens": 1.8000000000000001e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.6-sol": { + "cache_creation_input_token_cost": 2.5e-06, + "cache_creation_input_token_cost_above_272k_tokens": 5e-06, + "cache_read_input_token_cost": 2.0000000000000002e-07, + "cache_read_input_token_cost_above_272k_tokens": 4.0000000000000003e-07, + "input_cost_per_token": 2e-06, + "input_cost_per_token_above_272k_tokens": 4e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1e-05, + "output_cost_per_token_above_272k_tokens": 1.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.6-terra": { + "cache_creation_input_token_cost": 3.125e-06, + "cache_creation_input_token_cost_above_272k_tokens": 6.25e-06, + "cache_read_input_token_cost": 2.5e-07, + "cache_read_input_token_cost_above_272k_tokens": 5e-07, + "input_cost_per_token": 2.5e-06, + "input_cost_per_token_above_272k_tokens": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.5e-05, + "output_cost_per_token_above_272k_tokens": 2.25e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/grok-4.5": { + "cache_read_input_token_cost": 3e-07, + "cache_read_input_token_cost_above_200k_tokens": 6e-07, + "input_cost_per_token": 2e-06, + "input_cost_per_token_above_200k_tokens": 4e-06, + "litellm_provider": "opencode", + "max_input_tokens": 500000, + "max_output_tokens": 500000, + "max_tokens": 500000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 6e-06, + "output_cost_per_token_above_200k_tokens": 1.2e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/grok-4.6": { + "cache_read_input_token_cost": 5e-07, + "cache_read_input_token_cost_above_200k_tokens": 1e-06, + "input_cost_per_token": 2e-06, + "input_cost_per_token_above_200k_tokens": 4e-06, + "litellm_provider": "opencode", + "max_input_tokens": 500000, + "max_output_tokens": 500000, + "max_tokens": 500000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 6e-06, + "output_cost_per_token_above_200k_tokens": 1.2e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/grok-build-0.1": { + "cache_read_input_token_cost": 2.0000000000000002e-07, + "input_cost_per_token": 1e-06, + "litellm_provider": "opencode", + "max_input_tokens": 256000, + "max_output_tokens": 256000, + "max_tokens": 256000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 2e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/kimi-k2.5": { + "cache_read_input_token_cost": 8e-08, + "input_cost_per_token": 6e-07, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 3e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/kimi-k2.6": { + "cache_read_input_token_cost": 1.6e-07, + "input_cost_per_token": 9.499999999999999e-07, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/kimi-k2.7-code": { + "cache_read_input_token_cost": 1.9e-07, + "input_cost_per_token": 9.499999999999999e-07, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/kimi-k3": { + "cache_read_input_token_cost": 3e-07, + "input_cost_per_token": 3e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/laguna-s-2.1-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 256000, + "max_output_tokens": 32000, + "max_tokens": 32000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/ling-3.0-flash-fin-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/mimo-v2.5-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 200000, + "max_output_tokens": 32000, + "max_tokens": 32000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/minimax-m2.5": { + "cache_read_input_token_cost": 6e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode", + "max_input_tokens": 204800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/minimax-m2.7": { + "cache_read_input_token_cost": 6e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode", + "max_input_tokens": 204800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/minimax-m3": { + "cache_read_input_token_cost": 6e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode", + "max_input_tokens": 512000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/muse-spark-1.2": { + "cache_read_input_token_cost": 1.5e-07, + "input_cost_per_token": 1.25e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 4.25e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/muse-spark-1.2-contributor-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/muse-spark-1.3-contributor-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/nemotron-3-ultra-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/nemotron-3.5-lightning-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/qwen3.5-plus": { + "cache_creation_input_token_cost": 2.5e-07, + "cache_read_input_token_cost": 2e-08, + "input_cost_per_token": 2.0000000000000002e-07, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/qwen3.6-plus": { + "cache_creation_input_token_cost": 6.25e-07, + "cache_read_input_token_cost": 5.0000000000000004e-08, + "input_cost_per_token": 5e-07, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 3e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/deepseek-v4-flash": { + "cache_read_input_token_cost": 7e-09, + "input_cost_per_token": 2.2e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 6.6e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode_go/deepseek-v4-flash-vision-exp": { + "cache_read_input_token_cost": 7e-09, + "input_cost_per_token": 2.2e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 6.6e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/deepseek-v4-pro": { + "cache_read_input_token_cost": 2.2e-08, + "input_cost_per_token": 6.6e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.98e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode_go/glm-5": { + "cache_read_input_token_cost": 2.0000000000000002e-07, + "input_cost_per_token": 1e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 202752, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 3.2000000000000003e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/glm-5.1": { + "cache_read_input_token_cost": 2.6e-07, + "input_cost_per_token": 1.4e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 202752, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4.4e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/glm-5.2": { + "cache_read_input_token_cost": 2.6e-07, + "input_cost_per_token": 1.4e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4.4e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode_go/glm-5.3": { + "cache_read_input_token_cost": 2.6e-07, + "input_cost_per_token": 1.4e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4.4e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode_go/glm-5.3-flash": { + "cache_read_input_token_cost": 1.5e-08, + "input_cost_per_token": 7.5e-08, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 2.5e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/gpt-5.6-luna": { + "cache_creation_input_token_cost": 2.5e-07, + "cache_creation_input_token_cost_above_272k_tokens": 5e-07, + "cache_read_input_token_cost": 2e-08, + "cache_read_input_token_cost_above_272k_tokens": 4e-08, + "input_cost_per_token": 2.0000000000000002e-07, + "input_cost_per_token_above_272k_tokens": 4.0000000000000003e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.2e-06, + "output_cost_per_token_above_272k_tokens": 1.8000000000000001e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/grok-4.5": { + "cache_read_input_token_cost": 3e-07, + "cache_read_input_token_cost_above_200k_tokens": 6e-07, + "input_cost_per_token": 2e-06, + "input_cost_per_token_above_200k_tokens": 4e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 500000, + "max_output_tokens": 500000, + "max_tokens": 500000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 6e-06, + "output_cost_per_token_above_200k_tokens": 1.2e-05, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/grok-4.6": { + "cache_read_input_token_cost": 5e-07, + "cache_read_input_token_cost_above_200k_tokens": 1e-06, + "input_cost_per_token": 2e-06, + "input_cost_per_token_above_200k_tokens": 4e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 500000, + "max_output_tokens": 500000, + "max_tokens": 500000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 6e-06, + "output_cost_per_token_above_200k_tokens": 1.2e-05, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/hy3": { + "cache_read_input_token_cost": 3.5e-08, + "input_cost_per_token": 1.4e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 256000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 5.8e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/hy4-preview": { + "cache_read_input_token_cost": 4.2000000000000006e-08, + "input_cost_per_token": 8.34e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1024000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 2.501e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/kimi-k2.5": { + "cache_read_input_token_cost": 1.0000000000000001e-07, + "input_cost_per_token": 6e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 3e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/kimi-k2.6": { + "cache_read_input_token_cost": 1.6e-07, + "input_cost_per_token": 9.499999999999999e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/kimi-k2.7-code": { + "cache_read_input_token_cost": 1.9e-07, + "input_cost_per_token": 9.499999999999999e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/kimi-k3": { + "cache_read_input_token_cost": 3e-07, + "input_cost_per_token": 3e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.5e-05, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/longcat-2.0": { + "cache_read_input_token_cost": 6e-09, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/mimo-v2-omni": { + "cache_read_input_token_cost": 8e-08, + "input_cost_per_token": 4.0000000000000003e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 262144, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 2e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/mimo-v2-pro": { + "cache_read_input_token_cost": 2.0000000000000002e-07, + "cache_read_input_token_cost_above_256k_tokens": 4.0000000000000003e-07, + "input_cost_per_token": 1e-06, + "input_cost_per_token_above_256k_tokens": 2e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1048576, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 3e-06, + "output_cost_per_token_above_256k_tokens": 6e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/mimo-v2.5": { + "cache_read_input_token_cost": 2.8e-09, + "input_cost_per_token": 1.4e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 2.8e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/mimo-v2.5-pro": { + "cache_read_input_token_cost": 3.625e-09, + "input_cost_per_token": 4.35e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1048576, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 8.7e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/minimax-m2.5": { + "cache_read_input_token_cost": 3e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 204800, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/minimax-m2.7": { + "cache_read_input_token_cost": 6e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 204800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/minimax-m3": { + "cache_read_input_token_cost": 6e-08, + "cache_read_input_token_cost_above_512k_tokens": 1.2e-07, + "input_cost_per_token": 3e-07, + "input_cost_per_token_above_512k_tokens": 6e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 1.2e-06, + "output_cost_per_token_above_512k_tokens": 2.4e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/muse-spark-1.2-contributor": { + "cache_read_input_token_cost": 2e-09, + "input_cost_per_token": 1.0000000000000001e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 2.0000000000000002e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/muse-spark-1.3-contributor": { + "cache_read_input_token_cost": 2e-09, + "input_cost_per_token": 1.0000000000000001e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 2.0000000000000002e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/qwen3.5-plus": { + "cache_creation_input_token_cost": 2.5e-07, + "cache_read_input_token_cost": 2e-08, + "input_cost_per_token": 2.0000000000000002e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/qwen3.6-plus": { + "cache_creation_input_token_cost": 6.25e-07, + "cache_creation_input_token_cost_above_256k_tokens": 2.5e-06, + "cache_read_input_token_cost": 5.0000000000000004e-08, + "cache_read_input_token_cost_above_256k_tokens": 2.0000000000000002e-07, + "input_cost_per_token": 5e-07, + "input_cost_per_token_above_256k_tokens": 2e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 3e-06, + "output_cost_per_token_above_256k_tokens": 6e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/qwen3.7-max": { + "cache_creation_input_token_cost": 3.125e-06, + "cache_read_input_token_cost": 5e-07, + "input_cost_per_token": 2.5e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 7.5e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/qwen3.7-plus": { + "cache_creation_input_token_cost": 5e-07, + "cache_creation_input_token_cost_above_256k_tokens": 1.5e-06, + "cache_read_input_token_cost": 4e-08, + "cache_read_input_token_cost_above_256k_tokens": 1.2e-07, + "input_cost_per_token": 4.0000000000000003e-07, + "input_cost_per_token_above_256k_tokens": 1.2e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 1.6000000000000001e-06, + "output_cost_per_token_above_256k_tokens": 4.8e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/qwen3.8-flash": { + "cache_creation_input_token_cost": 2.0000000000000002e-07, + "cache_read_input_token_cost": 1.6e-08, + "input_cost_per_token": 1.5e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 4.6999999999999995e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/qwen3.8-max": { + "cache_creation_input_token_cost": 2.5e-06, + "cache_read_input_token_cost": 2.5e-07, + "input_cost_per_token": 2e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 6e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true } } diff --git a/litellm/provider_endpoints_support_backup.json b/litellm/provider_endpoints_support_backup.json index 9d6b1e18f599..d83ffa94b734 100644 --- a/litellm/provider_endpoints_support_backup.json +++ b/litellm/provider_endpoints_support_backup.json @@ -1324,12 +1324,48 @@ "interactions": true } }, + "opencode": { + "display_name": "OpenCode Zen (`opencode`)", + "url": "https://docs.litellm.ai/docs/providers/opencode", + "endpoints": { + "chat_completions": true, + "messages": false, + "responses": true, + "embeddings": false, + "image_generations": false, + "audio_transcriptions": false, + "audio_speech": false, + "moderations": false, + "batches": false, + "rerank": false, + "a2a": false, + "interactions": false + } + }, + "opencode_go": { + "display_name": "OpenCode Go (`opencode_go`)", + "url": "https://docs.litellm.ai/docs/providers/opencode", + "endpoints": { + "chat_completions": true, + "messages": false, + "responses": true, + "embeddings": false, + "image_generations": false, + "audio_transcriptions": false, + "audio_speech": false, + "moderations": false, + "batches": false, + "rerank": false, + "a2a": false, + "interactions": false + } + }, "lemonade": { "display_name": "Lemonade (`lemonade`)", "url": "https://docs.litellm.ai/docs/providers/lemonade", "endpoints": { "chat_completions": true, - "messages": true, + "messages": false, "responses": true, "embeddings": false, "image_generations": false, @@ -1338,8 +1374,8 @@ "moderations": false, "batches": false, "rerank": false, - "a2a": true, - "interactions": true + "a2a": false, + "interactions": false } }, "libertai": { diff --git a/litellm/types/utils.py b/litellm/types/utils.py index 569fce4f7b8e..410f05f85f5d 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -3825,6 +3825,8 @@ class LlmProviders(str, Enum): V0 = "v0" MORPH = "morph" LAMBDA_AI = "lambda_ai" + OPENCODE = "opencode" + OPENCODE_GO = "opencode_go" INCEPTION = "inception" TEXT_COMPLETION_INCEPTION = "text-completion-inception" DEEPSEEK = "deepseek" diff --git a/litellm/utils.py b/litellm/utils.py index ba456fc353b1..682afcb847b0 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -8019,6 +8019,14 @@ def _build_provider_config_map() -> dict[LlmProviders, tuple[Callable, bool]]: LlmProviders.XAI: (lambda: litellm.XAIChatConfig(), False), LlmProviders.ZAI: (lambda: litellm.ZAIChatConfig(), False), LlmProviders.LAMBDA_AI: (lambda: litellm.LambdaAIChatConfig(), False), + LlmProviders.OPENCODE: ( + lambda model: ProviderConfigManager._get_opencode_config(model, LlmProviders.OPENCODE), + True, + ), + LlmProviders.OPENCODE_GO: ( + lambda model: ProviderConfigManager._get_opencode_config(model, LlmProviders.OPENCODE_GO), + True, + ), LlmProviders.INCEPTION: (lambda: litellm.InceptionChatConfig(), False), LlmProviders.LLAMA: (lambda: litellm.LlamaAPIConfig(), False), LlmProviders.TEXT_COMPLETION_OPENAI: ( @@ -8196,6 +8204,19 @@ def _get_bedrock_config(model: str) -> BaseConfig: return get_bedrock_chat_config(model=model) + @staticmethod + def _get_opencode_config(model: str, provider: LlmProviders) -> BaseConfig: + """Pick the wire format OpenCode serves this model on.""" + from litellm.llms.opencode.common_utils import opencode_endpoint_for_model + + is_go: Final = provider is LlmProviders.OPENCODE_GO + endpoint: Final = opencode_endpoint_for_model(provider.value, model) + if endpoint == "/v1/messages": + return litellm.OpenCodeGoMessagesChatConfig() if is_go else litellm.OpenCodeZenMessagesChatConfig() + if endpoint == "/v1/models:generateContent" and not is_go: + return litellm.OpenCodeZenGeminiChatConfig() + return litellm.OpenCodeGoChatConfig() if is_go else litellm.OpenCodeZenChatConfig() + @staticmethod def _get_cohere_config(model: str) -> BaseConfig: """Get Cohere config based on route.""" @@ -8646,6 +8667,10 @@ def _get_python_responses_api_config( return litellm.AzureOpenAIResponsesAPIConfig() elif litellm.LlmProviders.XAI == provider: return litellm.XAIResponsesAPIConfig() + elif litellm.LlmProviders.OPENCODE == provider: + return litellm.OpenCodeZenResponsesAPIConfig() + elif litellm.LlmProviders.OPENCODE_GO == provider: + return litellm.OpenCodeGoResponsesAPIConfig() elif litellm.LlmProviders.GITHUB_COPILOT == provider: from litellm.llms.github_copilot.responses.transformation import ( github_copilot_supports_responses_api, diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index d8a8f84b0323..1c154564b041 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -58456,5 +58456,2030 @@ "supported_endpoints": [ "/v1/audio/transcriptions" ] + }, + "opencode/big-pickle": { + "cache_creation_input_token_cost": 0.0, + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 200000, + "max_output_tokens": 32000, + "max_tokens": 32000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/claude-fable-5": { + "cache_creation_input_token_cost": 1.25e-05, + "cache_read_input_token_cost": 1e-06, + "input_cost_per_token": 1e-05, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 512, + "output_cost_per_token": 5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_sampling_params": false, + "thinking_always_on": true, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-fable-5-1": { + "cache_creation_input_token_cost": 1.25e-05, + "cache_read_input_token_cost": 2.5e-07, + "input_cost_per_token": 1e-05, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 512, + "output_cost_per_token": 5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_sampling_params": false, + "thinking_always_on": true, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-haiku-4-5": { + "cache_creation_input_token_cost": 1.25e-06, + "cache_read_input_token_cost": 1.0000000000000001e-07, + "input_cost_per_token": 1e-06, + "litellm_provider": "opencode", + "max_input_tokens": 200000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-opus-4-5": { + "cache_creation_input_token_cost": 6.25e-06, + "cache_read_input_token_cost": 5e-07, + "input_cost_per_token": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 200000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 2.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-opus-4-6": { + "cache_creation_input_token_cost": 6.25e-06, + "cache_read_input_token_cost": 5e-07, + "input_cost_per_token": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 2.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_legacy_thinking": true, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-opus-4-7": { + "cache_creation_input_token_cost": 6.25e-06, + "cache_read_input_token_cost": 5e-07, + "input_cost_per_token": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 2048, + "output_cost_per_token": 2.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_sampling_params": false, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-opus-4-8": { + "cache_creation_input_token_cost": 6.25e-06, + "cache_read_input_token_cost": 5e-07, + "input_cost_per_token": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 1024, + "output_cost_per_token": 2.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_sampling_params": false, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-opus-5": { + "cache_creation_input_token_cost": 6.25e-06, + "cache_read_input_token_cost": 5e-07, + "input_cost_per_token": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 512, + "output_cost_per_token": 2.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_sampling_params": false, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-sonnet-4": { + "cache_creation_input_token_cost": 3.75e-06, + "cache_creation_input_token_cost_above_200k_tokens": 7.5e-06, + "cache_read_input_token_cost": 3e-07, + "cache_read_input_token_cost_above_200k_tokens": 6e-07, + "input_cost_per_token": 3e-06, + "input_cost_per_token_above_200k_tokens": 6e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 1024, + "output_cost_per_token": 1.5e-05, + "output_cost_per_token_above_200k_tokens": 2.25e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-sonnet-4-5": { + "cache_creation_input_token_cost": 3.75e-06, + "cache_creation_input_token_cost_above_200k_tokens": 7.5e-06, + "cache_read_input_token_cost": 3e-07, + "cache_read_input_token_cost_above_200k_tokens": 6e-07, + "input_cost_per_token": 3e-06, + "input_cost_per_token_above_200k_tokens": 6e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 1024, + "output_cost_per_token": 1.5e-05, + "output_cost_per_token_above_200k_tokens": 2.25e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-sonnet-4-6": { + "cache_creation_input_token_cost": 3.75e-06, + "cache_read_input_token_cost": 3e-07, + "input_cost_per_token": 3e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 1024, + "output_cost_per_token": 1.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_legacy_thinking": true, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/claude-sonnet-5": { + "cache_creation_input_token_cost": 2.5e-06, + "cache_read_input_token_cost": 2.0000000000000002e-07, + "input_cost_per_token": 2e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "prompt_cache_min_tokens": 1024, + "output_cost_per_token": 1e-05, + "source": "https://opencode.ai/docs/zen", + "supports_adaptive_thinking": true, + "supports_sampling_params": false, + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/deepseek-v4-flash": { + "cache_read_input_token_cost": 2.8e-08, + "input_cost_per_token": 1.4e-07, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 2.8e-07, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/deepseek-v4-flash-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 200000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/deepseek-v4-pro": { + "cache_read_input_token_cost": 1.45e-07, + "input_cost_per_token": 1.74e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 3.84e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/gemini-3-flash": { + "cache_read_input_token_cost": 5.0000000000000004e-08, + "input_cost_per_token": 5e-07, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "output_cost_per_token": 3e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gemini-3.1-pro": { + "cache_read_input_token_cost": 2.0000000000000002e-07, + "cache_read_input_token_cost_above_200k_tokens": 4.0000000000000003e-07, + "input_cost_per_token": 2e-06, + "input_cost_per_token_above_200k_tokens": 4e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "output_cost_per_token": 1.2e-05, + "output_cost_per_token_above_200k_tokens": 1.8e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gemini-3.5-flash": { + "cache_read_input_token_cost": 1.5e-07, + "input_cost_per_token": 1.5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 9e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gemini-3.5-flash-lite": { + "cache_read_input_token_cost": 3e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "output_cost_per_token": 2.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gemini-3.6-flash": { + "cache_read_input_token_cost": 1.5e-07, + "input_cost_per_token": 1.5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 7.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gemini-3.7-flash": { + "cache_read_input_token_cost": 1.5e-07, + "input_cost_per_token": 1.5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 7.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gemini-3.8-flash": { + "cache_read_input_token_cost": 1.5e-07, + "input_cost_per_token": 1.5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/models:generateContent" + ], + "prompt_cache_min_tokens": 4096, + "output_cost_per_token": 7.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/glm-5": { + "cache_read_input_token_cost": 2.0000000000000002e-07, + "input_cost_per_token": 1e-06, + "litellm_provider": "opencode", + "max_input_tokens": 204800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 3.2000000000000003e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/glm-5.1": { + "cache_read_input_token_cost": 2.6e-07, + "input_cost_per_token": 1.4e-06, + "litellm_provider": "opencode", + "max_input_tokens": 204800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4.4e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/glm-5.2": { + "cache_read_input_token_cost": 2.6e-07, + "input_cost_per_token": 1.4e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4.4e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/gpt-5": { + "cache_read_input_token_cost": 1.0699999999999999e-07, + "input_cost_per_token": 1.0700000000000001e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 8.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5-codex": { + "cache_read_input_token_cost": 1.0699999999999999e-07, + "input_cost_per_token": 1.0700000000000001e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 8.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5-nano": { + "cache_read_input_token_cost": 5e-09, + "input_cost_per_token": 5.0000000000000004e-08, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 4.0000000000000003e-07, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.1": { + "cache_read_input_token_cost": 1.0699999999999999e-07, + "input_cost_per_token": 1.0700000000000001e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 8.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.1-codex": { + "cache_read_input_token_cost": 1.0699999999999999e-07, + "input_cost_per_token": 1.0700000000000001e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 8.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.1-codex-max": { + "cache_read_input_token_cost": 1.25e-07, + "input_cost_per_token": 1.25e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.1-codex-mini": { + "cache_read_input_token_cost": 2.5000000000000002e-08, + "input_cost_per_token": 2.5e-07, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 2e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.2": { + "cache_read_input_token_cost": 1.75e-07, + "input_cost_per_token": 1.75e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.4e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.2-codex": { + "cache_read_input_token_cost": 1.75e-07, + "input_cost_per_token": 1.75e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.4e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.3-codex": { + "cache_read_input_token_cost": 1.75e-07, + "input_cost_per_token": 1.75e-06, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.4e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.3-codex-spark": { + "cache_read_input_token_cost": 1.75e-07, + "input_cost_per_token": 1.75e-06, + "litellm_provider": "opencode", + "max_input_tokens": 128000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.4e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/gpt-5.4": { + "cache_read_input_token_cost": 2.5e-07, + "cache_read_input_token_cost_above_272k_tokens": 5e-07, + "input_cost_per_token": 2.5e-06, + "input_cost_per_token_above_272k_tokens": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.5e-05, + "output_cost_per_token_above_272k_tokens": 2.25e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.4-mini": { + "cache_read_input_token_cost": 7.5e-08, + "input_cost_per_token": 7.5e-07, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 4.5e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.4-nano": { + "cache_read_input_token_cost": 2e-08, + "input_cost_per_token": 2.0000000000000002e-07, + "litellm_provider": "opencode", + "max_input_tokens": 400000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.25e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.4-pro": { + "cache_read_input_token_cost": 3e-05, + "input_cost_per_token": 3e-05, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 0.00018, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.5": { + "cache_read_input_token_cost": 5e-07, + "cache_read_input_token_cost_above_272k_tokens": 1e-06, + "input_cost_per_token": 5e-06, + "input_cost_per_token_above_272k_tokens": 1e-05, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 3e-05, + "output_cost_per_token_above_272k_tokens": 4.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.5-pro": { + "cache_read_input_token_cost": 3e-05, + "input_cost_per_token": 3e-05, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 0.00018, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.6-luna": { + "cache_creation_input_token_cost": 2.5e-07, + "cache_creation_input_token_cost_above_272k_tokens": 5e-07, + "cache_read_input_token_cost": 2e-08, + "cache_read_input_token_cost_above_272k_tokens": 4e-08, + "input_cost_per_token": 2.0000000000000002e-07, + "input_cost_per_token_above_272k_tokens": 4.0000000000000003e-07, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.2e-06, + "output_cost_per_token_above_272k_tokens": 1.8000000000000001e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.6-sol": { + "cache_creation_input_token_cost": 2.5e-06, + "cache_creation_input_token_cost_above_272k_tokens": 5e-06, + "cache_read_input_token_cost": 2.0000000000000002e-07, + "cache_read_input_token_cost_above_272k_tokens": 4.0000000000000003e-07, + "input_cost_per_token": 2e-06, + "input_cost_per_token_above_272k_tokens": 4e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1e-05, + "output_cost_per_token_above_272k_tokens": 1.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/gpt-5.6-terra": { + "cache_creation_input_token_cost": 3.125e-06, + "cache_creation_input_token_cost_above_272k_tokens": 6.25e-06, + "cache_read_input_token_cost": 2.5e-07, + "cache_read_input_token_cost_above_272k_tokens": 5e-07, + "input_cost_per_token": 2.5e-06, + "input_cost_per_token_above_272k_tokens": 5e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.5e-05, + "output_cost_per_token_above_272k_tokens": 2.25e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/grok-4.5": { + "cache_read_input_token_cost": 3e-07, + "cache_read_input_token_cost_above_200k_tokens": 6e-07, + "input_cost_per_token": 2e-06, + "input_cost_per_token_above_200k_tokens": 4e-06, + "litellm_provider": "opencode", + "max_input_tokens": 500000, + "max_output_tokens": 500000, + "max_tokens": 500000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 6e-06, + "output_cost_per_token_above_200k_tokens": 1.2e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/grok-4.6": { + "cache_read_input_token_cost": 5e-07, + "cache_read_input_token_cost_above_200k_tokens": 1e-06, + "input_cost_per_token": 2e-06, + "input_cost_per_token_above_200k_tokens": 4e-06, + "litellm_provider": "opencode", + "max_input_tokens": 500000, + "max_output_tokens": 500000, + "max_tokens": 500000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 6e-06, + "output_cost_per_token_above_200k_tokens": 1.2e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/grok-build-0.1": { + "cache_read_input_token_cost": 2.0000000000000002e-07, + "input_cost_per_token": 1e-06, + "litellm_provider": "opencode", + "max_input_tokens": 256000, + "max_output_tokens": 256000, + "max_tokens": 256000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 2e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/kimi-k2.5": { + "cache_read_input_token_cost": 8e-08, + "input_cost_per_token": 6e-07, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 3e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/kimi-k2.6": { + "cache_read_input_token_cost": 1.6e-07, + "input_cost_per_token": 9.499999999999999e-07, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/kimi-k2.7-code": { + "cache_read_input_token_cost": 1.9e-07, + "input_cost_per_token": 9.499999999999999e-07, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/kimi-k3": { + "cache_read_input_token_cost": 3e-07, + "input_cost_per_token": 3e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.5e-05, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/laguna-s-2.1-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 256000, + "max_output_tokens": 32000, + "max_tokens": 32000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/ling-3.0-flash-fin-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/mimo-v2.5-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 200000, + "max_output_tokens": 32000, + "max_tokens": 32000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/minimax-m2.5": { + "cache_read_input_token_cost": 6e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode", + "max_input_tokens": 204800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/minimax-m2.7": { + "cache_read_input_token_cost": 6e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode", + "max_input_tokens": 204800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/minimax-m3": { + "cache_read_input_token_cost": 6e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode", + "max_input_tokens": 512000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/muse-spark-1.2": { + "cache_read_input_token_cost": 1.5e-07, + "input_cost_per_token": 1.25e-06, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 4.25e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/muse-spark-1.2-contributor-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/muse-spark-1.3-contributor-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/nemotron-3-ultra-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode/nemotron-3.5-lightning-free": { + "cache_read_input_token_cost": 0.0, + "input_cost_per_token": 0.0, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 0.0, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode/qwen3.5-plus": { + "cache_creation_input_token_cost": 2.5e-07, + "cache_read_input_token_cost": 2e-08, + "input_cost_per_token": 2.0000000000000002e-07, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode/qwen3.6-plus": { + "cache_creation_input_token_cost": 6.25e-07, + "cache_read_input_token_cost": 5.0000000000000004e-08, + "input_cost_per_token": 5e-07, + "litellm_provider": "opencode", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 3e-06, + "source": "https://opencode.ai/docs/zen", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/deepseek-v4-flash": { + "cache_read_input_token_cost": 7e-09, + "input_cost_per_token": 2.2e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 6.6e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode_go/deepseek-v4-flash-vision-exp": { + "cache_read_input_token_cost": 7e-09, + "input_cost_per_token": 2.2e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 6.6e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/deepseek-v4-pro": { + "cache_read_input_token_cost": 2.2e-08, + "input_cost_per_token": 6.6e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 384000, + "max_tokens": 384000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.98e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode_go/glm-5": { + "cache_read_input_token_cost": 2.0000000000000002e-07, + "input_cost_per_token": 1e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 202752, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 3.2000000000000003e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/glm-5.1": { + "cache_read_input_token_cost": 2.6e-07, + "input_cost_per_token": 1.4e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 202752, + "max_output_tokens": 32768, + "max_tokens": 32768, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4.4e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/glm-5.2": { + "cache_read_input_token_cost": 2.6e-07, + "input_cost_per_token": 1.4e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4.4e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode_go/glm-5.3": { + "cache_read_input_token_cost": 2.6e-07, + "input_cost_per_token": 1.4e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4.4e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true + }, + "opencode_go/glm-5.3-flash": { + "cache_read_input_token_cost": 1.5e-08, + "input_cost_per_token": 7.5e-08, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 2.5e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/gpt-5.6-luna": { + "cache_creation_input_token_cost": 2.5e-07, + "cache_creation_input_token_cost_above_272k_tokens": 5e-07, + "cache_read_input_token_cost": 2e-08, + "cache_read_input_token_cost_above_272k_tokens": 4e-08, + "input_cost_per_token": 2.0000000000000002e-07, + "input_cost_per_token_above_272k_tokens": 4.0000000000000003e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1050000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 1.2e-06, + "output_cost_per_token_above_272k_tokens": 1.8000000000000001e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/grok-4.5": { + "cache_read_input_token_cost": 3e-07, + "cache_read_input_token_cost_above_200k_tokens": 6e-07, + "input_cost_per_token": 2e-06, + "input_cost_per_token_above_200k_tokens": 4e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 500000, + "max_output_tokens": 500000, + "max_tokens": 500000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 6e-06, + "output_cost_per_token_above_200k_tokens": 1.2e-05, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/grok-4.6": { + "cache_read_input_token_cost": 5e-07, + "cache_read_input_token_cost_above_200k_tokens": 1e-06, + "input_cost_per_token": 2e-06, + "input_cost_per_token_above_200k_tokens": 4e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 500000, + "max_output_tokens": 500000, + "max_tokens": 500000, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 6e-06, + "output_cost_per_token_above_200k_tokens": 1.2e-05, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/hy3": { + "cache_read_input_token_cost": 3.5e-08, + "input_cost_per_token": 1.4e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 256000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 5.8e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/hy4-preview": { + "cache_read_input_token_cost": 4.2000000000000006e-08, + "input_cost_per_token": 8.34e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1024000, + "max_output_tokens": 64000, + "max_tokens": 64000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 2.501e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/kimi-k2.5": { + "cache_read_input_token_cost": 1.0000000000000001e-07, + "input_cost_per_token": 6e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 3e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/kimi-k2.6": { + "cache_read_input_token_cost": 1.6e-07, + "input_cost_per_token": 9.499999999999999e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/kimi-k2.7-code": { + "cache_read_input_token_cost": 1.9e-07, + "input_cost_per_token": 9.499999999999999e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 4e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/kimi-k3": { + "cache_read_input_token_cost": 3e-07, + "input_cost_per_token": 3e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.5e-05, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/longcat-2.0": { + "cache_read_input_token_cost": 6e-09, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/mimo-v2-omni": { + "cache_read_input_token_cost": 8e-08, + "input_cost_per_token": 4.0000000000000003e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 262144, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 2e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/mimo-v2-pro": { + "cache_read_input_token_cost": 2.0000000000000002e-07, + "cache_read_input_token_cost_above_256k_tokens": 4.0000000000000003e-07, + "input_cost_per_token": 1e-06, + "input_cost_per_token_above_256k_tokens": 2e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1048576, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 3e-06, + "output_cost_per_token_above_256k_tokens": 6e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/mimo-v2.5": { + "cache_read_input_token_cost": 2.8e-09, + "input_cost_per_token": 1.4e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 2.8e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/mimo-v2.5-pro": { + "cache_read_input_token_cost": 3.625e-09, + "input_cost_per_token": 4.35e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1048576, + "max_output_tokens": 128000, + "max_tokens": 128000, + "mode": "chat", + "supported_endpoints": [ + "/v1/chat/completions" + ], + "output_cost_per_token": 8.7e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/minimax-m2.5": { + "cache_read_input_token_cost": 3e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 204800, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/minimax-m2.7": { + "cache_read_input_token_cost": 6e-08, + "input_cost_per_token": 3e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 204800, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/minimax-m3": { + "cache_read_input_token_cost": 6e-08, + "cache_read_input_token_cost_above_512k_tokens": 1.2e-07, + "input_cost_per_token": 3e-07, + "input_cost_per_token_above_512k_tokens": 6e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 1.2e-06, + "output_cost_per_token_above_512k_tokens": 2.4e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/muse-spark-1.2-contributor": { + "cache_read_input_token_cost": 2e-09, + "input_cost_per_token": 1.0000000000000001e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 2.0000000000000002e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/muse-spark-1.3-contributor": { + "cache_read_input_token_cost": 2e-09, + "input_cost_per_token": 1.0000000000000001e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1048576, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "responses", + "supported_endpoints": [ + "/v1/responses" + ], + "output_cost_per_token": 2.0000000000000002e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/qwen3.5-plus": { + "cache_creation_input_token_cost": 2.5e-07, + "cache_read_input_token_cost": 2e-08, + "input_cost_per_token": 2.0000000000000002e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 262144, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 1.2e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/qwen3.6-plus": { + "cache_creation_input_token_cost": 6.25e-07, + "cache_creation_input_token_cost_above_256k_tokens": 2.5e-06, + "cache_read_input_token_cost": 5.0000000000000004e-08, + "cache_read_input_token_cost_above_256k_tokens": 2.0000000000000002e-07, + "input_cost_per_token": 5e-07, + "input_cost_per_token_above_256k_tokens": 2e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 3e-06, + "output_cost_per_token_above_256k_tokens": 6e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/qwen3.7-max": { + "cache_creation_input_token_cost": 3.125e-06, + "cache_read_input_token_cost": 5e-07, + "input_cost_per_token": 2.5e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 7.5e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, + "opencode_go/qwen3.7-plus": { + "cache_creation_input_token_cost": 5e-07, + "cache_creation_input_token_cost_above_256k_tokens": 1.5e-06, + "cache_read_input_token_cost": 4e-08, + "cache_read_input_token_cost_above_256k_tokens": 1.2e-07, + "input_cost_per_token": 4.0000000000000003e-07, + "input_cost_per_token_above_256k_tokens": 1.2e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 65536, + "max_tokens": 65536, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 1.6000000000000001e-06, + "output_cost_per_token_above_256k_tokens": 4.8e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/qwen3.8-flash": { + "cache_creation_input_token_cost": 2.0000000000000002e-07, + "cache_read_input_token_cost": 1.6e-08, + "input_cost_per_token": 1.5e-07, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 4.6999999999999995e-07, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true + }, + "opencode_go/qwen3.8-max": { + "cache_creation_input_token_cost": 2.5e-06, + "cache_read_input_token_cost": 2.5e-07, + "input_cost_per_token": 2e-06, + "litellm_provider": "opencode_go", + "max_input_tokens": 1000000, + "max_output_tokens": 131072, + "max_tokens": 131072, + "mode": "chat", + "supported_endpoints": [ + "/v1/messages" + ], + "output_cost_per_token": 6e-06, + "source": "https://opencode.ai/docs/go", + "supports_function_calling": true, + "supports_prompt_caching": true, + "supports_reasoning": true, + "supports_response_schema": true, + "supports_tool_choice": true, + "supports_vision": true } } diff --git a/model_prices_and_context_window.schema.json b/model_prices_and_context_window.schema.json index 9e370e5406ac..53651b66c3a4 100644 --- a/model_prices_and_context_window.schema.json +++ b/model_prices_and_context_window.schema.json @@ -94,6 +94,11 @@ "minimum": 0, "description": "Rate applied once the prompt exceeds the token threshold in the field name." }, + "cache_creation_input_token_cost_above_256k_tokens": { + "type": "number", + "minimum": 0, + "description": "Rate applied once the prompt exceeds the token threshold in the field name." + }, "cache_creation_input_token_cost_above_272k_tokens": { "type": "number", "minimum": 0, @@ -138,6 +143,11 @@ "minimum": 0, "description": "Priority service-tier rate for the same-named base field." }, + "cache_read_input_token_cost_above_256k_tokens": { + "type": "number", + "minimum": 0, + "description": "Rate applied once the prompt exceeds the token threshold in the field name." + }, "cache_read_input_token_cost_above_272k_tokens": { "type": "number", "minimum": 0, diff --git a/provider_endpoints_support.json b/provider_endpoints_support.json index ebc220b34965..bb1c2f6d8d07 100644 --- a/provider_endpoints_support.json +++ b/provider_endpoints_support.json @@ -1439,12 +1439,48 @@ "interactions": true } }, + "opencode": { + "display_name": "OpenCode Zen (`opencode`)", + "url": "https://docs.litellm.ai/docs/providers/opencode", + "endpoints": { + "chat_completions": true, + "messages": false, + "responses": true, + "embeddings": false, + "image_generations": false, + "audio_transcriptions": false, + "audio_speech": false, + "moderations": false, + "batches": false, + "rerank": false, + "a2a": false, + "interactions": false + } + }, + "opencode_go": { + "display_name": "OpenCode Go (`opencode_go`)", + "url": "https://docs.litellm.ai/docs/providers/opencode", + "endpoints": { + "chat_completions": true, + "messages": false, + "responses": true, + "embeddings": false, + "image_generations": false, + "audio_transcriptions": false, + "audio_speech": false, + "moderations": false, + "batches": false, + "rerank": false, + "a2a": false, + "interactions": false + } + }, "lemonade": { "display_name": "Lemonade (`lemonade`)", "url": "https://docs.litellm.ai/docs/providers/lemonade", "endpoints": { "chat_completions": true, - "messages": true, + "messages": false, "responses": true, "embeddings": false, "image_generations": false, @@ -1453,8 +1489,8 @@ "moderations": false, "batches": false, "rerank": false, - "a2a": true, - "interactions": true + "a2a": false, + "interactions": false } }, "libertai": { diff --git a/tests/test_litellm/llms/opencode/test_opencode_chat_transformation.py b/tests/test_litellm/llms/opencode/test_opencode_chat_transformation.py new file mode 100644 index 000000000000..1f15a68bf709 --- /dev/null +++ b/tests/test_litellm/llms/opencode/test_opencode_chat_transformation.py @@ -0,0 +1,744 @@ +""" +Unit tests for the OpenCode Zen and OpenCode Go providers. + +OpenCode rejects inference requests that arrive without an `x-opencode-session` header, so the +tests below pin both the value LiteLLM picks for it and the fact that it reaches the wire. +API docs: https://opencode.ai/docs/zen and https://opencode.ai/docs/go +""" + +import json +from collections.abc import Mapping +from typing import Final + +import httpx +import pytest + +import litellm +from litellm.llms.custom_httpx.http_handler import HTTPHandler +from litellm.llms.opencode.chat.transformation import ( + OpenCodeGoChatConfig, + OpenCodeGoMessagesChatConfig, + OpenCodeZenChatConfig, + OpenCodeZenGeminiChatConfig, + OpenCodeZenMessagesChatConfig, +) +from litellm.llms.opencode.responses.transformation import ( + OpenCodeGoResponsesAPIConfig, + OpenCodeZenResponsesAPIConfig, +) +from litellm.llms.opencode.common_utils import ( + OPENCODE_SESSION_HEADER, + opencode_endpoint_for_model, + resolve_opencode_api_key, + resolve_opencode_session_id, +) +from litellm.types.router import GenericLiteLLMParams +from litellm.types.utils import LlmProviders + +ZEN_API_BASE: Final = "https://opencode.ai/zen/v1" +GO_API_BASE: Final = "https://opencode.ai/zen/go/v1" + + +class RecordingHTTPHandler(HTTPHandler): + """Injected in place of the real client so the outbound request can be asserted on.""" + + def __init__(self, response_model: str): + super().__init__() + self.response_model = response_model + self.requests: tuple[Mapping[str, object], ...] = () + + def post(self, url, data=None, headers=None, **kwargs): + raw_body: Final = data.decode("utf-8") if isinstance(data, bytes) else data + self.requests = ( + *self.requests, + {"url": url, "headers": dict(headers or {}), "body": json.loads(raw_body or "{}")}, + ) + return httpx.Response( + status_code=200, + json={ + "id": "chatcmpl-test", + "object": "chat.completion", + "created": 1733529600, + "model": self.response_model, + "choices": [ + {"index": 0, "message": {"role": "assistant", "content": "ok"}, "finish_reason": "stop"} + ], + "usage": {"prompt_tokens": 1, "completion_tokens": 1, "total_tokens": 2}, + }, + request=httpx.Request("POST", url), + ) + + +def _headers_for(config, litellm_params, headers=None): + return config.validate_environment( + headers=dict(headers or {}), + model="kimi-k3", + messages=[{"role": "user", "content": "hi"}], + optional_params={}, + litellm_params=litellm_params, + api_key="fake-key", + ) + + +class TestSessionIdResolution: + @pytest.mark.parametrize( + "litellm_params, expected", + [ + pytest.param( + { + "litellm_session_id": "session-1", + "metadata": {"session_id": "meta-1"}, + "litellm_trace_id": "trace-1", + "litellm_call_id": "call-1", + }, + "session-1", + id="litellm_session_id-wins", + ), + pytest.param( + {"metadata": {"session_id": "meta-1"}, "litellm_trace_id": "trace-1", "litellm_call_id": "call-1"}, + "meta-1", + id="metadata-session-id-next", + ), + pytest.param( + {"litellm_trace_id": "trace-1", "litellm_call_id": "call-1"}, + "trace-1", + id="trace-id-next", + ), + pytest.param({"litellm_call_id": "call-1"}, "call-1", id="call-id-last"), + ], + ) + def test_precedence_order(self, litellm_params, expected): + assert resolve_opencode_session_id(litellm_params) == expected + + @pytest.mark.parametrize( + "litellm_params", + [ + pytest.param({}, id="nothing-available"), + pytest.param({"litellm_session_id": None, "litellm_call_id": None}, id="explicit-nones"), + pytest.param({"litellm_session_id": ""}, id="empty-string-is-not-an-id"), + pytest.param({"litellm_session_id": 42}, id="non-string-is-not-an-id"), + pytest.param({"metadata": "not-a-mapping"}, id="metadata-not-a-mapping"), + ], + ) + def test_returns_none_when_no_usable_id(self, litellm_params): + assert resolve_opencode_session_id(litellm_params) is None + + def test_empty_session_id_falls_through_to_next_candidate(self): + assert resolve_opencode_session_id({"litellm_session_id": "", "litellm_call_id": "call-1"}) == "call-1" + + +class TestSessionHeader: + @pytest.mark.parametrize("config", [OpenCodeZenChatConfig(), OpenCodeGoChatConfig()]) + def test_header_is_set_from_session_id(self, config): + headers = _headers_for(config, {"litellm_session_id": "session-1"}) + assert headers[OPENCODE_SESSION_HEADER] == "session-1" + + @pytest.mark.parametrize("config", [OpenCodeZenChatConfig(), OpenCodeGoChatConfig()]) + def test_header_absent_when_no_id_is_available(self, config): + assert OPENCODE_SESSION_HEADER not in _headers_for(config, {}) + + @pytest.mark.parametrize("supplied_name", ["x-opencode-session", "X-OpenCode-Session"]) + def test_caller_supplied_header_is_never_overwritten(self, supplied_name): + headers = _headers_for( + OpenCodeGoChatConfig(), + {"litellm_session_id": "session-1"}, + headers={supplied_name: "caller-owned"}, + ) + assert headers[supplied_name] == "caller-owned" + assert "session-1" not in headers.values() + + def test_auth_and_content_type_are_preserved(self): + headers = _headers_for(OpenCodeGoChatConfig(), {"litellm_session_id": "session-1"}) + assert headers["Authorization"] == "Bearer fake-key" + assert headers["Content-Type"] == "application/json" + + +class TestProviderRegistration: + def test_provider_enums_exist(self): + assert LlmProviders.OPENCODE == "opencode" + assert LlmProviders.OPENCODE_GO == "opencode_go" + + @pytest.mark.parametrize("provider", ["opencode", "opencode_go"]) + def test_provider_in_provider_list(self, provider): + assert provider in litellm.provider_list + + @pytest.mark.parametrize( + "model, expected_provider, expected_api_base", + [ + ("opencode/claude-opus-5", "opencode", ZEN_API_BASE), + ("opencode_go/kimi-k3", "opencode_go", GO_API_BASE), + ], + ) + def test_model_prefix_resolves_provider_and_default_api_base(self, model, expected_provider, expected_api_base): + _, provider, _, api_base = litellm.get_llm_provider(model=model) + assert provider == expected_provider + assert api_base == expected_api_base + + @pytest.mark.parametrize( + "api_base, expected_provider", + [ + (ZEN_API_BASE, "opencode"), + (GO_API_BASE, "opencode_go"), + ], + ) + def test_api_base_infers_provider(self, api_base, expected_provider): + _, provider, _, _ = litellm.get_llm_provider(model="kimi-k3", api_base=api_base) + assert provider == expected_provider + + @pytest.mark.parametrize( + "config", + [ + OpenCodeZenChatConfig(), + OpenCodeGoChatConfig(), + OpenCodeZenMessagesChatConfig(), + OpenCodeGoMessagesChatConfig(), + OpenCodeZenGeminiChatConfig(), + ], + ) + def test_one_account_key_authenticates_every_surface(self, monkeypatch, config): + """One OpenCode account key covers Zen and Go, so every config reads the same variable.""" + monkeypatch.setenv("OPENCODE_API_KEY", "account-key") + assert resolve_opencode_api_key(None) == "account-key" + _, resolved = OpenCodeZenChatConfig()._get_openai_compatible_provider_info(None, None) + assert resolved == "account-key" + + def test_api_key_is_none_when_unset(self, monkeypatch): + monkeypatch.delenv("OPENCODE_API_KEY", raising=False) + assert resolve_opencode_api_key(None) is None + + def test_explicit_api_key_wins_over_the_env_var(self, monkeypatch): + monkeypatch.setenv("OPENCODE_API_KEY", "account-key") + assert resolve_opencode_api_key("explicit-key") == "explicit-key" + + @pytest.mark.parametrize( + "config, expected_api_base", + [ + (OpenCodeZenChatConfig(), ZEN_API_BASE), + (OpenCodeGoChatConfig(), GO_API_BASE), + ], + ) + def test_default_api_base_needs_no_configuration(self, monkeypatch, config, expected_api_base): + monkeypatch.setenv("OPENCODE_API_KEY", "account-key") + api_base, _ = config._get_openai_compatible_provider_info(None, None) + assert api_base == expected_api_base + + @pytest.mark.parametrize("config", [OpenCodeZenChatConfig(), OpenCodeGoChatConfig()]) + def test_explicit_api_base_wins_over_default(self, config): + api_base, _ = config._get_openai_compatible_provider_info("https://proxy.internal/v1", "k") + assert api_base == "https://proxy.internal/v1" + + +class TestCompletionWiring: + @pytest.mark.parametrize( + "model, expected_url", + [ + ("opencode/kimi-k3", f"{ZEN_API_BASE}/chat/completions"), + ("opencode_go/kimi-k3", f"{GO_API_BASE}/chat/completions"), + ("opencode_go/glm-5.3-flash", f"{GO_API_BASE}/chat/completions"), + ], + ) + def test_session_header_reaches_the_wire(self, local_model_cost_map, model, expected_url): + client = RecordingHTTPHandler(response_model=model.split("/", 1)[1]) + response = litellm.completion( + model=model, + messages=[{"role": "user", "content": "hello"}], + api_key="fake-key", + litellm_session_id="session-42", + client=client, + ) + + assert response.choices[0].message.content == "ok" + assert len(client.requests) == 1 + assert client.requests[0]["url"] == expected_url + assert client.requests[0]["headers"][OPENCODE_SESSION_HEADER] == "session-42" + assert OPENCODE_SESSION_HEADER not in client.requests[0]["body"] + + def test_session_header_is_stable_across_turns_of_one_session(self, local_model_cost_map): + client = RecordingHTTPHandler(response_model="kimi-k3") + for turn in ("first", "second"): + litellm.completion( + model="opencode_go/kimi-k3", + messages=[{"role": "user", "content": turn}], + api_key="fake-key", + litellm_session_id="session-42", + client=client, + ) + + sent = [r["headers"][OPENCODE_SESSION_HEADER] for r in client.requests] + assert sent == ["session-42", "session-42"] + + def test_header_present_even_without_a_caller_supplied_session_id(self, local_model_cost_map): + client = RecordingHTTPHandler(response_model="kimi-k3") + litellm.completion( + model="opencode_go/kimi-k3", + messages=[{"role": "user", "content": "hello"}], + api_key="fake-key", + client=client, + ) + + assert client.requests[0]["headers"].get(OPENCODE_SESSION_HEADER) + + +class TestPricing: + @pytest.mark.parametrize( + "model, provider", + [ + ("opencode/claude-opus-5", "opencode"), + ("opencode_go/kimi-k3", "opencode_go"), + ], + ) + def test_models_are_registered_under_their_provider(self, local_model_cost_map, model, provider): + assert litellm.get_model_info(model)["litellm_provider"] == provider + + def test_go_pricing_matches_published_rates(self, local_model_cost_map): + info = litellm.get_model_info("opencode_go/kimi-k3") + assert info["input_cost_per_token"] == pytest.approx(3.0 / 1_000_000) + assert info["output_cost_per_token"] == pytest.approx(15.0 / 1_000_000) + assert info["cache_read_input_token_cost"] == pytest.approx(0.3 / 1_000_000) + assert info["max_input_tokens"] == 1_048_576 + + def test_zen_pricing_matches_published_rates(self, local_model_cost_map): + info = litellm.get_model_info("opencode/gpt-5.6-luna") + assert info["input_cost_per_token"] == pytest.approx(0.2 / 1_000_000) + assert info["output_cost_per_token"] == pytest.approx(1.2 / 1_000_000) + assert info["input_cost_per_token_above_272k_tokens"] == pytest.approx(0.4 / 1_000_000) + + def test_tiered_pricing_applies_above_the_context_threshold(self, local_model_cost_map): + from litellm.types.utils import Choices, Message, ModelResponse, Usage + + def cost_for(prompt_tokens): + response = ModelResponse( + id="x", + model="grok-4.6", + object="chat.completion", + created=0, + choices=[Choices(index=0, message=Message(role="assistant", content="hi"), finish_reason="stop")], + usage=Usage( + prompt_tokens=prompt_tokens, completion_tokens=1_000, total_tokens=prompt_tokens + 1_000 + ), + ) + return litellm.completion_cost(completion_response=response, model="opencode_go/grok-4.6") + + assert cost_for(100_000) == pytest.approx(100_000 * 2e-06 + 1_000 * 6e-06) + assert cost_for(300_000) == pytest.approx(300_000 * 4e-06 + 1_000 * 1.2e-05) + + +class TestEndpointRouting: + """ + OpenCode splits its catalogue across four wire formats, per model rather than per family, + and serving a model on the wrong one returns 500 or `not supported for format oa-compat`. + Every expectation below was verified against the live API with a real key, except the + Zen-only gemini and claude rows, which come from OpenCode's published endpoint table. + """ + + @pytest.mark.parametrize( + "model, expected_endpoint", + [ + pytest.param("opencode_go/glm-5.3-flash", "/v1/chat/completions", id="go-glm-chat"), + pytest.param("opencode_go/kimi-k3", "/v1/chat/completions", id="go-kimi-chat"), + pytest.param("opencode_go/deepseek-v4-pro", "/v1/chat/completions", id="go-deepseek-chat"), + pytest.param("opencode_go/gpt-5.6-luna", "/v1/responses", id="go-gpt-responses"), + pytest.param("opencode_go/grok-4.6", "/v1/responses", id="go-grok-responses"), + pytest.param("opencode_go/grok-4.5", "/v1/responses", id="go-grok45-responses-undocumented"), + pytest.param("opencode_go/muse-spark-1.3-contributor", "/v1/responses", id="go-muse-responses"), + pytest.param("opencode_go/minimax-m3", "/v1/messages", id="go-minimax-messages"), + pytest.param("opencode_go/minimax-m2.7", "/v1/messages", id="go-minimax27-messages"), + pytest.param("opencode_go/qwen3.7-max", "/v1/messages", id="go-qwen-messages"), + pytest.param("opencode_go/qwen3.5-plus", "/v1/messages", id="go-qwen35-messages-undocumented"), + pytest.param("opencode/claude-opus-5", "/v1/messages", id="zen-claude-messages"), + pytest.param("opencode/gemini-3.1-pro", "/v1/models:generateContent", id="zen-gemini-models"), + pytest.param("opencode/gpt-5.5", "/v1/responses", id="zen-gpt-responses"), + pytest.param("opencode/kimi-k3", "/v1/chat/completions", id="zen-kimi-chat"), + ], + ) + def test_cost_map_records_the_endpoint(self, local_model_cost_map, model, expected_endpoint): + assert litellm.model_cost[model]["supported_endpoints"] == [expected_endpoint] + + @pytest.mark.parametrize( + "model, expected_endpoint", + [ + ("opencode_go/minimax-m3", "/v1/messages"), + ("opencode_go/glm-5.3-flash", "/v1/chat/completions"), + ], + ) + def test_endpoint_lookup_reads_the_cost_map(self, local_model_cost_map, model, expected_endpoint): + provider, bare_model = model.split("/", 1) + assert opencode_endpoint_for_model(provider, bare_model) == expected_endpoint + + def test_unknown_model_falls_back_to_chat_completions(self, local_model_cost_map): + assert opencode_endpoint_for_model("opencode_go", "not-a-real-model") == "/v1/chat/completions" + + @pytest.mark.parametrize( + "provider, model, expected_config", + [ + (LlmProviders.OPENCODE_GO, "glm-5.3-flash", OpenCodeGoChatConfig), + (LlmProviders.OPENCODE_GO, "minimax-m3", OpenCodeGoMessagesChatConfig), + (LlmProviders.OPENCODE_GO, "qwen3.7-max", OpenCodeGoMessagesChatConfig), + (LlmProviders.OPENCODE, "claude-opus-5", OpenCodeZenMessagesChatConfig), + (LlmProviders.OPENCODE, "gemini-3.1-pro", OpenCodeZenGeminiChatConfig), + (LlmProviders.OPENCODE, "kimi-k3", OpenCodeZenChatConfig), + ], + ) + def test_provider_picks_the_matching_wire_format(self, local_model_cost_map, provider, model, expected_config): + from litellm.utils import ProviderConfigManager + + config = ProviderConfigManager.get_provider_chat_config(model=model, provider=provider) + assert type(config) is expected_config + + @pytest.mark.parametrize( + "model", ["opencode_go/gpt-5.6-luna", "opencode_go/grok-4.6", "opencode/gpt-5.5", "opencode/grok-4.6"] + ) + def test_responses_models_are_marked_for_the_bridge(self, local_model_cost_map, model): + assert litellm.get_model_info(model)["mode"] == "responses" + + @pytest.mark.parametrize("model", ["opencode_go/minimax-m3", "opencode/claude-opus-5", "opencode/gemini-3.1-pro"]) + def test_non_responses_models_stay_chat_mode(self, local_model_cost_map, model): + assert litellm.get_model_info(model)["mode"] == "chat" + + +class TestMessagesWireFormat: + @pytest.mark.parametrize( + "config, expected_url", + [ + (OpenCodeGoMessagesChatConfig(), f"{GO_API_BASE}/messages"), + (OpenCodeZenMessagesChatConfig(), f"{ZEN_API_BASE}/messages"), + ], + ) + def test_url_targets_the_messages_endpoint(self, config, expected_url): + url = config.get_complete_url( + api_base=None, api_key="k", model="minimax-m3", optional_params={}, litellm_params={} + ) + assert url == expected_url + + def test_auth_uses_x_api_key_not_bearer(self, monkeypatch): + """OpenCode's /messages rejects `Authorization: Bearer` with `Missing API key`.""" + monkeypatch.setenv("OPENCODE_API_KEY", "go-key") + headers = OpenCodeGoMessagesChatConfig().validate_environment( + headers={}, + model="minimax-m3", + messages=[{"role": "user", "content": "hi"}], + optional_params={}, + litellm_params={"litellm_session_id": "session-1"}, + ) + assert headers["x-api-key"] == "go-key" + assert "Authorization" not in headers + assert headers[OPENCODE_SESSION_HEADER] == "session-1" + + +class TestGeminiWireFormat: + def test_url_targets_generate_content(self): + url = OpenCodeZenGeminiChatConfig().get_complete_url( + api_base=None, api_key="k", model="gemini-3.1-pro", optional_params={}, litellm_params={} + ) + assert url == f"{ZEN_API_BASE}/models/gemini-3.1-pro:generateContent" + + def test_streaming_url_targets_stream_generate_content(self): + url = OpenCodeZenGeminiChatConfig().get_complete_url( + api_base=None, api_key="k", model="gemini-3.1-pro", optional_params={}, litellm_params={}, stream=True + ) + assert url == f"{ZEN_API_BASE}/models/gemini-3.1-pro:streamGenerateContent?alt=sse" + + def test_auth_and_session_header(self, monkeypatch): + monkeypatch.setenv("OPENCODE_API_KEY", "zen-key") + headers = OpenCodeZenGeminiChatConfig().validate_environment( + headers={}, + model="gemini-3.1-pro", + messages=[{"role": "user", "content": "hi"}], + optional_params={}, + litellm_params={"litellm_session_id": "session-1"}, + ) + assert headers["x-goog-api-key"] == "zen-key" + assert "Authorization" not in headers + assert headers[OPENCODE_SESSION_HEADER] == "session-1" + + +class RecordingGeminiHTTPHandler(HTTPHandler): + """Gemini answers in Google's own shape, so the canned reply differs from the OpenAI one.""" + + def __init__(self): + super().__init__() + self.requests: tuple[Mapping[str, object], ...] = () + + def post(self, url, data=None, headers=None, **kwargs): + raw_body: Final = data.decode("utf-8") if isinstance(data, bytes) else data + self.requests = ( + *self.requests, + {"url": url, "headers": dict(headers or {}), "body": json.loads(raw_body or "{}")}, + ) + return httpx.Response( + status_code=200, + json={ + "candidates": [ + {"content": {"parts": [{"text": "OK"}], "role": "model"}, "finishReason": "STOP", "index": 0} + ], + "usageMetadata": {"promptTokenCount": 5, "candidatesTokenCount": 1, "totalTokenCount": 6}, + "modelVersion": "gemini-3.5-flash-lite", + }, + request=httpx.Request("POST", url), + ) + + +class TestGeminiRequestBody: + def test_transform_request_builds_a_gemini_body(self): + """VertexGeminiConfig.transform_request raises NotImplementedError; the override must not.""" + body = OpenCodeZenGeminiChatConfig().transform_request( + model="gemini-3.5-flash-lite", + messages=[{"role": "system", "content": "Be terse."}, {"role": "user", "content": "hi"}], + optional_params={}, + litellm_params={}, + headers={}, + ) + assert body["contents"] == [{"role": "user", "parts": [{"text": "hi"}]}] + assert body["system_instruction"] == {"parts": [{"text": "Be terse."}]} + + def test_completion_reaches_generate_content_with_the_session_header(self, local_model_cost_map): + client = RecordingGeminiHTTPHandler() + response = litellm.completion( + model="opencode/gemini-3.5-flash-lite", + messages=[{"role": "user", "content": "hi"}], + api_key="fake-key", + litellm_session_id="session-77", + client=client, + ) + + assert response.choices[0].message.content == "OK" + assert len(client.requests) == 1 + sent = client.requests[0] + assert sent["url"] == f"{ZEN_API_BASE}/models/gemini-3.5-flash-lite:generateContent" + assert sent["headers"][OPENCODE_SESSION_HEADER] == "session-77" + assert sent["headers"]["x-goog-api-key"] == "fake-key" + assert sent["body"]["contents"] == [{"role": "user", "parts": [{"text": "hi"}]}] + + +class TestTieredPricingPropagation: + """The 256k tier fields are not named in ModelInfoBase's constructor; a generic pass copies them.""" + + @pytest.mark.parametrize( + "model, field", + [ + ("opencode_go/qwen3.7-plus", "input_cost_per_token_above_256k_tokens"), + ("opencode_go/qwen3.7-plus", "output_cost_per_token_above_256k_tokens"), + ("opencode_go/qwen3.7-plus", "cache_read_input_token_cost_above_256k_tokens"), + ("opencode_go/qwen3.6-plus", "cache_creation_input_token_cost_above_256k_tokens"), + ], + ) + def test_256k_tier_fields_survive_model_info(self, local_model_cost_map, model, field): + raw = litellm.model_cost[model][field] + assert litellm.get_model_info(model)[field] == raw + + def test_256k_tier_is_actually_billed(self, local_model_cost_map): + from litellm.types.utils import Choices, Message, ModelResponse, Usage + + model = "opencode_go/qwen3.7-plus" + raw = litellm.model_cost[model] + + def cost_for(prompt_tokens): + response = ModelResponse( + id="x", model="qwen3.7-plus", object="chat.completion", created=0, + choices=[Choices(index=0, message=Message(role="assistant", content="hi"), finish_reason="stop")], + usage=Usage(prompt_tokens=prompt_tokens, completion_tokens=1_000, + total_tokens=prompt_tokens + 1_000), + ) + return litellm.completion_cost(completion_response=response, model=model) + + below = 100_000 * raw["input_cost_per_token"] + 1_000 * raw["output_cost_per_token"] + above = 300_000 * raw["input_cost_per_token_above_256k_tokens"] + ( + 1_000 * raw["output_cost_per_token_above_256k_tokens"] + ) + assert cost_for(100_000) == pytest.approx(below) + assert cost_for(300_000) == pytest.approx(above) + assert cost_for(300_000) > cost_for(100_000) * 2 + + +class FailingHTTPHandler(HTTPHandler): + """Drives the dispatch helper's error path, which logs the failure before re-raising.""" + + def post(self, url, data=None, headers=None, **kwargs): + raise httpx.ConnectError("connection refused") + + +class TestDispatchErrorPath: + @pytest.mark.parametrize("model", ["opencode_go/kimi-k3", "opencode/claude-opus-5"]) + def test_upstream_failure_surfaces_to_the_caller(self, local_model_cost_map, model): + with pytest.raises(litellm.InternalServerError, match="connection refused"): + litellm.completion( + model=model, + messages=[{"role": "user", "content": "hi"}], + api_key="fake-key", + litellm_session_id="session-err", + client=FailingHTTPHandler(), + ) + + +class TestResponsesWireFormat: + """OpenCode serves its OpenAI-native models on /responses; /chat/completions answers them 500.""" + + @pytest.mark.parametrize( + "config, expected_provider, expected_url", + [ + (OpenCodeZenResponsesAPIConfig(), LlmProviders.OPENCODE, f"{ZEN_API_BASE}/responses"), + (OpenCodeGoResponsesAPIConfig(), LlmProviders.OPENCODE_GO, f"{GO_API_BASE}/responses"), + ], + ) + def test_provider_and_default_url(self, config, expected_provider, expected_url): + assert config.custom_llm_provider == expected_provider + assert config.get_complete_url(api_base=None, litellm_params={}) == expected_url + + @pytest.mark.parametrize( + "config", [OpenCodeZenResponsesAPIConfig(), OpenCodeGoResponsesAPIConfig()] + ) + def test_explicit_api_base_wins_and_trailing_slash_is_trimmed(self, config): + assert config.get_complete_url(api_base="https://proxy.internal/v1/", litellm_params={}) == ( + "https://proxy.internal/v1/responses" + ) + + def test_auth_uses_bearer_and_stamps_the_session_header(self, monkeypatch): + monkeypatch.setenv("OPENCODE_API_KEY", "account-key") + headers = OpenCodeGoResponsesAPIConfig().validate_environment( + headers={}, + model="gpt-5.6-luna", + litellm_params=GenericLiteLLMParams(litellm_session_id="session-9"), + ) + assert headers["Authorization"] == "Bearer account-key" + assert headers["Content-Type"] == "application/json" + assert headers[OPENCODE_SESSION_HEADER] == "session-9" + + def test_request_api_key_wins_over_the_env_var(self, monkeypatch): + monkeypatch.setenv("OPENCODE_API_KEY", "account-key") + headers = OpenCodeZenResponsesAPIConfig().validate_environment( + headers={}, + model="gpt-5.5", + litellm_params=GenericLiteLLMParams(api_key="request-key"), + ) + assert headers["Authorization"] == "Bearer request-key" + + def test_caller_supplied_session_header_is_not_overwritten(self, monkeypatch): + monkeypatch.setenv("OPENCODE_API_KEY", "account-key") + headers = OpenCodeZenResponsesAPIConfig().validate_environment( + headers={"X-OpenCode-Session": "caller-owned"}, + model="gpt-5.5", + litellm_params=GenericLiteLLMParams(litellm_session_id="session-9"), + ) + assert headers["X-OpenCode-Session"] == "caller-owned" + assert "session-9" not in headers.values() + + def test_missing_litellm_params_still_produces_headers(self, monkeypatch): + monkeypatch.setenv("OPENCODE_API_KEY", "account-key") + headers = OpenCodeGoResponsesAPIConfig().validate_environment( + headers={}, model="gpt-5.6-luna", litellm_params=None + ) + assert headers["Authorization"] == "Bearer account-key" + + @pytest.mark.parametrize( + "provider, expected_config", + [ + (LlmProviders.OPENCODE, OpenCodeZenResponsesAPIConfig), + (LlmProviders.OPENCODE_GO, OpenCodeGoResponsesAPIConfig), + ], + ) + def test_provider_manager_returns_the_responses_config(self, provider, expected_config): + from litellm.utils import ProviderConfigManager + + config = ProviderConfigManager.get_provider_responses_api_config(provider=provider, model="gpt-5.6-luna") + assert type(config) is expected_config + + +class TestChatConfigProviderNames: + @pytest.mark.parametrize( + "config, expected", + [ + (OpenCodeZenChatConfig(), "opencode"), + (OpenCodeGoChatConfig(), "opencode_go"), + (OpenCodeZenMessagesChatConfig(), "opencode"), + (OpenCodeGoMessagesChatConfig(), "opencode_go"), + (OpenCodeZenGeminiChatConfig(), "opencode"), + ], + ) + def test_custom_llm_provider(self, config, expected): + assert config.custom_llm_provider == expected + + def test_messages_config_honours_an_explicit_api_base(self): + url = OpenCodeGoMessagesChatConfig().get_complete_url( + api_base="https://proxy.internal/v1/messages", + api_key="k", + model="minimax-m3", + optional_params={}, + litellm_params={}, + ) + assert url == "https://proxy.internal/v1/messages" + + +class RecordingAnthropicHTTPHandler(HTTPHandler): + """OpenCode's /messages answers in Anthropic's shape, so the canned reply differs again.""" + + def __init__(self, response_model: str): + super().__init__() + self.response_model = response_model + self.requests: tuple[Mapping[str, object], ...] = () + + def post(self, url, data=None, headers=None, **kwargs): + raw_body: Final = data.decode("utf-8") if isinstance(data, bytes) else data + self.requests = ( + *self.requests, + {"url": url, "headers": dict(headers or {}), "body": json.loads(raw_body or "{}")}, + ) + return httpx.Response( + status_code=200, + json={ + "id": "msg_test", + "type": "message", + "role": "assistant", + "model": self.response_model, + "content": [{"type": "text", "text": "ok"}], + "stop_reason": "end_turn", + "usage": {"input_tokens": 5, "output_tokens": 1}, + }, + request=httpx.Request("POST", url), + ) + + +class TestMessagesCompletionWiring: + """Claude and the qwen/minimax families are served on /messages, not /chat/completions.""" + + @pytest.mark.parametrize( + "model, expected_url", + [ + ("opencode/claude-opus-5", f"{ZEN_API_BASE}/messages"), + ("opencode/claude-haiku-4-5", f"{ZEN_API_BASE}/messages"), + ("opencode_go/minimax-m3", f"{GO_API_BASE}/messages"), + ("opencode_go/qwen3.7-max", f"{GO_API_BASE}/messages"), + ], + ) + def test_session_header_reaches_the_wire(self, local_model_cost_map, model, expected_url): + client = RecordingAnthropicHTTPHandler(response_model=model.split("/", 1)[1]) + response = litellm.completion( + model=model, + messages=[{"role": "user", "content": "hello"}], + api_key="fake-key", + litellm_session_id="session-42", + client=client, + ) + + assert response.choices[0].message.content == "ok" + assert len(client.requests) == 1 + sent = client.requests[0] + assert sent["url"] == expected_url + assert sent["headers"][OPENCODE_SESSION_HEADER] == "session-42" + assert sent["headers"]["x-api-key"] == "fake-key" + assert "Authorization" not in sent["headers"] + + def test_body_is_anthropic_shaped_not_openai_shaped(self, local_model_cost_map): + """A regression here means the model is being sent to /chat/completions, which answers 500.""" + client = RecordingAnthropicHTTPHandler(response_model="claude-opus-5") + litellm.completion( + model="opencode/claude-opus-5", + messages=[{"role": "system", "content": "Be terse."}, {"role": "user", "content": "hello"}], + api_key="fake-key", + max_tokens=16, + client=client, + ) + + body = client.requests[0]["body"] + assert body["messages"] == [{"role": "user", "content": [{"type": "text", "text": "hello"}]}] + assert body["system"] == [{"type": "text", "text": "Be terse."}] + assert body["max_tokens"] == 16 diff --git a/tests/test_litellm/test_utils.py b/tests/test_litellm/test_utils.py index 200cfd021970..4cda36dc4989 100644 --- a/tests/test_litellm/test_utils.py +++ b/tests/test_litellm/test_utils.py @@ -865,6 +865,7 @@ def test_aaamodel_prices_and_context_window_json_is_valid(): "cache_creation_input_token_cost": {"type": "number"}, "cache_creation_input_token_cost_above_1hr": {"type": "number"}, "cache_creation_input_token_cost_above_200k_tokens": {"type": "number"}, + "cache_creation_input_token_cost_above_256k_tokens": {"type": "number"}, "cache_creation_input_token_cost_above_272k_tokens": {"type": "number"}, "cache_creation_input_token_cost_above_272k_tokens_flex": { "type": "number" @@ -876,6 +877,7 @@ def test_aaamodel_prices_and_context_window_json_is_valid(): "cache_creation_input_token_cost_priority": {"type": "number"}, "cache_read_input_token_cost": {"type": "number"}, "cache_read_input_token_cost_above_200k_tokens": {"type": "number"}, + "cache_read_input_token_cost_above_256k_tokens": {"type": "number"}, "cache_read_input_token_cost_above_272k_tokens": {"type": "number"}, "cache_read_input_token_cost_above_272k_tokens_flex": { "type": "number" @@ -1070,6 +1072,7 @@ def test_aaamodel_prices_and_context_window_json_is_valid(): "/v1/audio/transcriptions", "/v1/audio/speech", "/v1/ocr", + "/v1/models:generateContent", "/vertex_ai/live", "/v1beta/interactions", ],