From 9b08a3700595e9798369e154c29e40ba459e906a Mon Sep 17 00:00:00 2001 From: Luca Steeb Date: Wed, 22 Jul 2026 16:57:24 +0100 Subject: [PATCH] feat(llmgateway): add provider Adds LLM Gateway (https://llmgateway.io) as a provider, with a generator that builds the model list from its public models endpoint. Co-Authored-By: Claude Fable 5 --- .github/workflows/update.yml | 4 + Taskfile.yaml | 6 + cmd/llmgateway/main.go | 247 +++ internal/providers/configs/llmgateway.json | 2038 ++++++++++++++++++++ internal/providers/providers.go | 8 + pkg/catwalk/provider.go | 2 + 6 files changed, 2305 insertions(+) create mode 100644 cmd/llmgateway/main.go create mode 100644 internal/providers/configs/llmgateway.json diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml index 54d0aeeb..ced079da 100644 --- a/.github/workflows/update.yml +++ b/.github/workflows/update.yml @@ -58,6 +58,10 @@ jobs: run: go run ./cmd/ionet/main.go continue-on-error: true + - name: LLM Gateway + run: go run ./cmd/llmgateway/main.go + continue-on-error: true + - name: OpenCode Go run: go run ./cmd/opencode-go/main.go continue-on-error: true diff --git a/Taskfile.yaml b/Taskfile.yaml index ed8f6f13..a31767be 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -65,6 +65,7 @@ tasks: - task: gen:cortecs - task: gen:huggingface - task: gen:ionet + - task: gen:llmgateway - task: gen:nebius - task: gen:neuralwatt - task: gen:opencode-go @@ -115,6 +116,11 @@ tasks: cmds: - go run cmd/ionet/main.go + gen:llmgateway: + desc: Generate LLM Gateway provider configurations + cmds: + - go run cmd/llmgateway/main.go + gen:nebius: desc: Generate Nebius provider configurations cmds: diff --git a/cmd/llmgateway/main.go b/cmd/llmgateway/main.go new file mode 100644 index 00000000..3b394ad3 --- /dev/null +++ b/cmd/llmgateway/main.go @@ -0,0 +1,247 @@ +// Package main provides a command-line tool to fetch models from LLM Gateway +// and generate a configuration file for the provider. +package main + +import ( + "context" + "encoding/json" + "fmt" + "io" + "log" + "math" + "net/http" + "os" + "slices" + "strings" + "time" + + "charm.land/catwalk/pkg/catwalk" +) + +// LLMGatewayModel represents a model from the LLM Gateway models endpoint. +type LLMGatewayModel struct { + ID string `json:"id"` + Name string `json:"name"` + ContextLength int64 `json:"context_length"` + Pricing Pricing `json:"pricing"` + Architecture Architecture `json:"architecture"` + Providers []ModelProvider `json:"providers"` + Stability string `json:"stability"` + DeprecatedAt *string `json:"deprecated_at"` + DeactivatedAt *string `json:"deactivated_at"` +} + +// Architecture describes a model's input and output modalities. +type Architecture struct { + InputModalities []string `json:"input_modalities"` + OutputModalities []string `json:"output_modalities"` +} + +// ModelProvider is one upstream provider mapping for a model. +type ModelProvider struct { + ProviderID string `json:"providerId"` + Tools bool `json:"tools"` + Reasoning bool `json:"reasoning"` + ReasoningEfforts []string `json:"reasoning_efforts"` + Vision bool `json:"vision"` + Stability string `json:"stability"` +} + +// Pricing contains the per-token pricing for a model. +type Pricing struct { + Prompt string `json:"prompt"` + Completion string `json:"completion"` + InputCacheRead string `json:"input_cache_read"` +} + +// ModelsResponse is the response structure for the LLM Gateway models API. +type ModelsResponse struct { + Data []LLMGatewayModel `json:"data"` +} + +func fetchLLMGatewayModels() (*ModelsResponse, error) { + client := &http.Client{Timeout: 30 * time.Second} + req, _ := http.NewRequestWithContext( + context.Background(), + "GET", + "https://api.llmgateway.io/v1/models", + nil, + ) + req.Header.Set("User-Agent", "Crush-Client/1.0") + + resp, err := client.Do(req) + if err != nil { + return nil, err //nolint:wrapcheck + } + defer resp.Body.Close() //nolint:errcheck + if resp.StatusCode != 200 { + body, _ := io.ReadAll(resp.Body) + return nil, fmt.Errorf("status %d: %s", resp.StatusCode, body) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("unable to read response body: %w", err) + } + + _ = os.MkdirAll("tmp", 0o700) + _ = os.WriteFile("tmp/llmgateway-response.json", body, 0o600) + + var mr ModelsResponse + if err := json.Unmarshal(body, &mr); err != nil { + return nil, err //nolint:wrapcheck + } + return &mr, nil +} + +func hasModality(modalities []string, modality string) bool { + return slices.Contains(modalities, modality) +} + +// pastDate reports whether the given RFC 3339 timestamp is in the past. +// Deprecation and deactivation dates may be in the future, in which case the +// model is still usable and should be included. +func pastDate(ts *string) bool { + if ts == nil { + return false + } + t, err := time.Parse(time.RFC3339, *ts) + if err != nil { + return false + } + return t.Before(time.Now()) +} + +// parsePrice converts a per-token price string to cost per 1M tokens. +func parsePrice(perToken string) float64 { + var v float64 + if err := json.Unmarshal([]byte(perToken), &v); err != nil { + return 0 + } + return math.Round(v*1e6*1e5) / 1e5 +} + +// effortOrder is the canonical ordering of reasoning efforts. +var effortOrder = []string{"none", "minimal", "low", "medium", "high", "xhigh", "max"} + +// reasoningLevels merges the reasoning efforts of all stable provider +// mappings into a single canonically ordered list. +func reasoningLevels(providers []ModelProvider) []string { + seen := map[string]bool{} + for _, p := range providers { + if !p.Reasoning || p.Stability == "unstable" { + continue + } + for _, e := range p.ReasoningEfforts { + seen[e] = true + } + } + var levels []string + for _, e := range effortOrder { + if seen[e] { + levels = append(levels, e) + } + } + return levels +} + +func defaultReasoningEffort(levels []string) string { + if len(levels) == 0 { + return "" + } + if slices.Contains(levels, "medium") { + return "medium" + } + // Fall back to the middle of the supported range, skipping "none". + usable := slices.DeleteFunc(slices.Clone(levels), func(e string) bool { + return e == "none" + }) + if len(usable) == 0 { + return "" + } + return usable[len(usable)/2] +} + +func main() { + modelsResp, err := fetchLLMGatewayModels() + if err != nil { + log.Fatal("Error fetching LLM Gateway models:", err) + } + + llmgatewayProvider := catwalk.Provider{ + Name: "LLM Gateway", + ID: catwalk.InferenceProviderLLMGateway, + APIKey: "$LLMGATEWAY_API_KEY", + APIEndpoint: "https://api.llmgateway.io/v1", + Type: catwalk.TypeOpenAICompat, + DefaultLargeModelID: "claude-sonnet-5", + DefaultSmallModelID: "gpt-5-mini", + Models: []catwalk.Model{}, + } + + for _, model := range modelsResp.Data { + if model.ID == "custom" { + continue + } + if pastDate(model.DeprecatedAt) || pastDate(model.DeactivatedAt) { + continue + } + if model.Stability == "unstable" { + continue + } + if !hasModality(model.Architecture.InputModalities, "text") || + !hasModality(model.Architecture.OutputModalities, "text") { + continue + } + if model.ContextLength < 20000 { + continue + } + + // Only consider models with at least one stable tool-capable + // provider mapping. + supportsTools := slices.ContainsFunc(model.Providers, func(p ModelProvider) bool { + return p.Tools && p.Stability != "unstable" + }) + if !supportsTools { + continue + } + + canReason := slices.ContainsFunc(model.Providers, func(p ModelProvider) bool { + return p.Reasoning && p.Stability != "unstable" + }) + levels := reasoningLevels(model.Providers) + + m := catwalk.Model{ + ID: model.ID, + Name: model.Name, + CostPer1MIn: parsePrice(model.Pricing.Prompt), + CostPer1MOut: parsePrice(model.Pricing.Completion), + CostPer1MInCached: parsePrice(model.Pricing.InputCacheRead), + CostPer1MOutCached: 0, + ContextWindow: model.ContextLength, + DefaultMaxTokens: model.ContextLength / 10, + CanReason: canReason, + ReasoningLevels: levels, + DefaultReasoningEffort: defaultReasoningEffort(levels), + SupportsImages: hasModality(model.Architecture.InputModalities, "image"), + } + + llmgatewayProvider.Models = append(llmgatewayProvider.Models, m) + } + + slices.SortFunc(llmgatewayProvider.Models, func(a, b catwalk.Model) int { + return strings.Compare(a.Name, b.Name) + }) + + data, err := json.MarshalIndent(llmgatewayProvider, "", " ") + if err != nil { + log.Fatal("Error marshaling LLM Gateway provider:", err) + } + data = append(data, '\n') + + if err := os.WriteFile("internal/providers/configs/llmgateway.json", data, 0o600); err != nil { + log.Fatal("Error writing LLM Gateway provider config:", err) + } + + fmt.Printf("Generated llmgateway.json with %d models\n", len(llmgatewayProvider.Models)) +} diff --git a/internal/providers/configs/llmgateway.json b/internal/providers/configs/llmgateway.json new file mode 100644 index 00000000..b66d5310 --- /dev/null +++ b/internal/providers/configs/llmgateway.json @@ -0,0 +1,2038 @@ +{ + "name": "LLM Gateway", + "id": "llmgateway", + "api_key": "$LLMGATEWAY_API_KEY", + "api_endpoint": "https://api.llmgateway.io/v1", + "type": "openai-compat", + "default_large_model_id": "claude-sonnet-5", + "default_small_model_id": "gpt-5-mini", + "models": [ + { + "id": "claude-3-opus", + "name": "Claude 3 Opus", + "cost_per_1m_in": 15, + "cost_per_1m_out": 75, + "cost_per_1m_in_cached": 1.5, + "cost_per_1m_out_cached": 0, + "context_window": 200000, + "default_max_tokens": 20000, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "claude-fable-5", + "name": "Claude Fable 5", + "cost_per_1m_in": 10, + "cost_per_1m_out": 50, + "cost_per_1m_in_cached": 1, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "claude-haiku-4-5", + "name": "Claude Haiku 4.5", + "cost_per_1m_in": 1, + "cost_per_1m_out": 5, + "cost_per_1m_in_cached": 0.1, + "cost_per_1m_out_cached": 0, + "context_window": 200000, + "default_max_tokens": 20000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "claude-haiku-4-5-20251001", + "name": "Claude Haiku 4.5 (2025-10-01)", + "cost_per_1m_in": 1, + "cost_per_1m_out": 5, + "cost_per_1m_in_cached": 0.1, + "cost_per_1m_out_cached": 0, + "context_window": 200000, + "default_max_tokens": 20000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "claude-haiku-4-5-free", + "name": "Claude Haiku 4.5 (Free)", + "cost_per_1m_in": 0, + "cost_per_1m_out": 0, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 200000, + "default_max_tokens": 20000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "claude-opus-4-1-20250805", + "name": "Claude Opus 4.1", + "cost_per_1m_in": 15, + "cost_per_1m_out": 75, + "cost_per_1m_in_cached": 1.5, + "cost_per_1m_out_cached": 0, + "context_window": 200000, + "default_max_tokens": 20000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "claude-opus-4-5-20251101", + "name": "Claude Opus 4.5", + "cost_per_1m_in": 5, + "cost_per_1m_out": 25, + "cost_per_1m_in_cached": 0.5, + "cost_per_1m_out_cached": 0, + "context_window": 200000, + "default_max_tokens": 20000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "claude-opus-4-6", + "name": "Claude Opus 4.6", + "cost_per_1m_in": 5, + "cost_per_1m_out": 25, + "cost_per_1m_in_cached": 0.5, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "claude-opus-4-7", + "name": "Claude Opus 4.7", + "cost_per_1m_in": 5, + "cost_per_1m_out": 25, + "cost_per_1m_in_cached": 0.5, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "claude-opus-4-8", + "name": "Claude Opus 4.8", + "cost_per_1m_in": 5, + "cost_per_1m_out": 25, + "cost_per_1m_in_cached": 0.5, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "claude-sonnet-4-5", + "name": "Claude Sonnet 4.5", + "cost_per_1m_in": 3, + "cost_per_1m_out": 15, + "cost_per_1m_in_cached": 0.3, + "cost_per_1m_out_cached": 0, + "context_window": 200000, + "default_max_tokens": 20000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "claude-sonnet-4-5-20250929", + "name": "Claude Sonnet 4.5 (2025-09-29)", + "cost_per_1m_in": 3, + "cost_per_1m_out": 15, + "cost_per_1m_in_cached": 0.3, + "cost_per_1m_out_cached": 0, + "context_window": 200000, + "default_max_tokens": 20000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "claude-sonnet-4-6", + "name": "Claude Sonnet 4.6", + "cost_per_1m_in": 3, + "cost_per_1m_out": 15, + "cost_per_1m_in_cached": 0.3, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "claude-sonnet-5", + "name": "Claude Sonnet 5", + "cost_per_1m_in": 2, + "cost_per_1m_out": 10, + "cost_per_1m_in_cached": 0.2, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "deepseek-v3.2", + "name": "DeepSeek V3.2", + "cost_per_1m_in": 0.26, + "cost_per_1m_out": 0.38, + "cost_per_1m_in_cached": 0.13, + "cost_per_1m_out_cached": 0, + "context_window": 163840, + "default_max_tokens": 16384, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "deepseek-v4-flash", + "name": "DeepSeek V4 Flash", + "cost_per_1m_in": 0.14, + "cost_per_1m_out": 0.28, + "cost_per_1m_in_cached": 0.0028, + "cost_per_1m_out_cached": 0, + "context_window": 1050000, + "default_max_tokens": 105000, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": false + }, + { + "id": "deepseek-v4-pro", + "name": "DeepSeek V4 Pro", + "cost_per_1m_in": 0.435, + "cost_per_1m_out": 0.87, + "cost_per_1m_in_cached": 0.00363, + "cost_per_1m_out_cached": 0, + "context_window": 1050000, + "default_max_tokens": 105000, + "can_reason": true, + "reasoning_levels": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": false + }, + { + "id": "fugu-ultra", + "name": "Fugu Ultra", + "cost_per_1m_in": 5, + "cost_per_1m_out": 30, + "cost_per_1m_in_cached": 0.5, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "reasoning_levels": [ + "high", + "xhigh" + ], + "default_reasoning_effort": "xhigh", + "supports_attachments": true + }, + { + "id": "glm-4-32b-0414-128k", + "name": "GLM-4 32B (0414-128k)", + "cost_per_1m_in": 0.1, + "cost_per_1m_out": 0.1, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 128000, + "default_max_tokens": 12800, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "glm-4.5v", + "name": "GLM-4.5V", + "cost_per_1m_in": 0.6, + "cost_per_1m_out": 1.8, + "cost_per_1m_in_cached": 0.11, + "cost_per_1m_out_cached": 0, + "context_window": 128000, + "default_max_tokens": 12800, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "glm-4.6", + "name": "GLM-4.6", + "cost_per_1m_in": 0.55, + "cost_per_1m_out": 2.2, + "cost_per_1m_in_cached": 0.11, + "cost_per_1m_out_cached": 0, + "context_window": 204800, + "default_max_tokens": 20480, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "glm-4.6v", + "name": "GLM-4.6V", + "cost_per_1m_in": 0.3, + "cost_per_1m_out": 0.9, + "cost_per_1m_in_cached": 0.05, + "cost_per_1m_out_cached": 0, + "context_window": 131072, + "default_max_tokens": 13107, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "glm-4.6v-flashx", + "name": "GLM-4.6V FlashX", + "cost_per_1m_in": 0.04, + "cost_per_1m_out": 0.4, + "cost_per_1m_in_cached": 0.004, + "cost_per_1m_out_cached": 0, + "context_window": 128000, + "default_max_tokens": 12800, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "glm-4.7", + "name": "GLM-4.7", + "cost_per_1m_in": 0.38, + "cost_per_1m_out": 1.98, + "cost_per_1m_in_cached": 0.19, + "cost_per_1m_out_cached": 0, + "context_window": 204800, + "default_max_tokens": 20480, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "glm-5", + "name": "GLM-5", + "cost_per_1m_in": 0.72, + "cost_per_1m_out": 2.3, + "cost_per_1m_in_cached": 0.144, + "cost_per_1m_out_cached": 0, + "context_window": 203000, + "default_max_tokens": 20300, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "glm-5.1", + "name": "GLM-5.1", + "cost_per_1m_in": 0.931, + "cost_per_1m_out": 2.93, + "cost_per_1m_in_cached": 0.173, + "cost_per_1m_out_cached": 0, + "context_window": 204800, + "default_max_tokens": 20480, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "glm-5.2", + "name": "GLM-5.2", + "cost_per_1m_in": 1.26, + "cost_per_1m_out": 3.96, + "cost_per_1m_in_cached": 0.234, + "cost_per_1m_out_cached": 0, + "context_window": 1024000, + "default_max_tokens": 102400, + "can_reason": true, + "reasoning_levels": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": false + }, + { + "id": "gpt-oss-120b", + "name": "GPT OSS 120B", + "cost_per_1m_in": 0.05, + "cost_per_1m_out": 0.25, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 131072, + "default_max_tokens": 13107, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "gpt-oss-20b", + "name": "GPT OSS 20B", + "cost_per_1m_in": 0.04, + "cost_per_1m_out": 0.15, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 131072, + "default_max_tokens": 13107, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "gpt-4-turbo", + "name": "GPT-4 Turbo", + "cost_per_1m_in": 10, + "cost_per_1m_out": 30, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 128000, + "default_max_tokens": 12800, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "gpt-4.1", + "name": "GPT-4.1", + "cost_per_1m_in": 2, + "cost_per_1m_out": 8, + "cost_per_1m_in_cached": 0.5, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "gpt-4.1-mini", + "name": "GPT-4.1 Mini", + "cost_per_1m_in": 0.4, + "cost_per_1m_out": 1.6, + "cost_per_1m_in_cached": 0.1, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "gpt-4.1-nano", + "name": "GPT-4.1 Nano", + "cost_per_1m_in": 0.1, + "cost_per_1m_out": 0.4, + "cost_per_1m_in_cached": 0.025, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "gpt-4o", + "name": "GPT-4o", + "cost_per_1m_in": 2.5, + "cost_per_1m_out": 10, + "cost_per_1m_in_cached": 1.25, + "cost_per_1m_out_cached": 0, + "context_window": 128000, + "default_max_tokens": 12800, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "gpt-4o-mini", + "name": "GPT-4o Mini", + "cost_per_1m_in": 0.15, + "cost_per_1m_out": 0.6, + "cost_per_1m_in_cached": 0.075, + "cost_per_1m_out_cached": 0, + "context_window": 128000, + "default_max_tokens": 12800, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "gpt-5", + "name": "GPT-5", + "cost_per_1m_in": 1.25, + "cost_per_1m_out": 10, + "cost_per_1m_in_cached": 0.125, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5-mini", + "name": "GPT-5 Mini", + "cost_per_1m_in": 0.25, + "cost_per_1m_out": 2, + "cost_per_1m_in_cached": 0.025, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5-nano", + "name": "GPT-5 Nano", + "cost_per_1m_in": 0.05, + "cost_per_1m_out": 0.4, + "cost_per_1m_in_cached": 0.005, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": false + }, + { + "id": "gpt-5-pro", + "name": "GPT-5 Pro", + "cost_per_1m_in": 15, + "cost_per_1m_out": 120, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "reasoning_levels": [ + "high" + ], + "default_reasoning_effort": "high", + "supports_attachments": true + }, + { + "id": "gpt-5.1", + "name": "GPT-5.1", + "cost_per_1m_in": 1.25, + "cost_per_1m_out": 10, + "cost_per_1m_in_cached": 0.125, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "reasoning_levels": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.1-codex", + "name": "GPT-5.1 Codex", + "cost_per_1m_in": 1.25, + "cost_per_1m_out": 10, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "gpt-5.1-codex-mini", + "name": "GPT-5.1 Codex mini", + "cost_per_1m_in": 0.25, + "cost_per_1m_out": 2, + "cost_per_1m_in_cached": 0.025, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "gpt-5.2", + "name": "GPT-5.2", + "cost_per_1m_in": 1.75, + "cost_per_1m_out": 14, + "cost_per_1m_in_cached": 0.175, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "reasoning_levels": [ + "none", + "low", + "medium", + "high", + "xhigh" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.2-codex", + "name": "GPT-5.2 Codex", + "cost_per_1m_in": 1.75, + "cost_per_1m_out": 14, + "cost_per_1m_in_cached": 0.175, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.2-pro", + "name": "GPT-5.2 Pro", + "cost_per_1m_in": 21, + "cost_per_1m_out": 168, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "reasoning_levels": [ + "medium", + "high", + "xhigh" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.3-codex", + "name": "GPT-5.3 Codex", + "cost_per_1m_in": 1.75, + "cost_per_1m_out": 14, + "cost_per_1m_in_cached": 0.175, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.4", + "name": "GPT-5.4", + "cost_per_1m_in": 2.5, + "cost_per_1m_out": 15, + "cost_per_1m_in_cached": 0.25, + "cost_per_1m_out_cached": 0, + "context_window": 1050000, + "default_max_tokens": 105000, + "can_reason": true, + "reasoning_levels": [ + "none", + "low", + "medium", + "high", + "xhigh" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.4-mini", + "name": "GPT-5.4 Mini", + "cost_per_1m_in": 0.75, + "cost_per_1m_out": 4.5, + "cost_per_1m_in_cached": 0.075, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "reasoning_levels": [ + "none", + "low", + "medium", + "high", + "xhigh" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.4-nano", + "name": "GPT-5.4 Nano", + "cost_per_1m_in": 0.2, + "cost_per_1m_out": 1.25, + "cost_per_1m_in_cached": 0.02, + "cost_per_1m_out_cached": 0, + "context_window": 400000, + "default_max_tokens": 40000, + "can_reason": true, + "reasoning_levels": [ + "none", + "low", + "medium", + "high", + "xhigh" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.4-pro", + "name": "GPT-5.4 Pro", + "cost_per_1m_in": 30, + "cost_per_1m_out": 180, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 1050000, + "default_max_tokens": 105000, + "can_reason": true, + "reasoning_levels": [ + "medium", + "high", + "xhigh" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.5", + "name": "GPT-5.5", + "cost_per_1m_in": 5, + "cost_per_1m_out": 30, + "cost_per_1m_in_cached": 0.5, + "cost_per_1m_out_cached": 0, + "context_window": 1050000, + "default_max_tokens": 105000, + "can_reason": true, + "reasoning_levels": [ + "none", + "low", + "medium", + "high", + "xhigh" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.5-pro", + "name": "GPT-5.5 Pro", + "cost_per_1m_in": 30, + "cost_per_1m_out": 180, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 1050000, + "default_max_tokens": 105000, + "can_reason": true, + "reasoning_levels": [ + "medium", + "high", + "xhigh" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.6-luna", + "name": "GPT-5.6 Luna", + "cost_per_1m_in": 1, + "cost_per_1m_out": 6, + "cost_per_1m_in_cached": 0.1, + "cost_per_1m_out_cached": 0, + "context_window": 1050000, + "default_max_tokens": 105000, + "can_reason": true, + "reasoning_levels": [ + "none", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.6-sol", + "name": "GPT-5.6 Sol", + "cost_per_1m_in": 5, + "cost_per_1m_out": 30, + "cost_per_1m_in_cached": 0.5, + "cost_per_1m_out_cached": 0, + "context_window": 1050000, + "default_max_tokens": 105000, + "can_reason": true, + "reasoning_levels": [ + "none", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gpt-5.6-terra", + "name": "GPT-5.6 Terra", + "cost_per_1m_in": 2.5, + "cost_per_1m_out": 15, + "cost_per_1m_in_cached": 0.25, + "cost_per_1m_out_cached": 0, + "context_window": 1050000, + "default_max_tokens": 105000, + "can_reason": true, + "reasoning_levels": [ + "none", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gemini-2.5-flash", + "name": "Gemini 2.5 Flash", + "cost_per_1m_in": 0.3, + "cost_per_1m_out": 2.5, + "cost_per_1m_in_cached": 0.03, + "cost_per_1m_out_cached": 0, + "context_window": 1048576, + "default_max_tokens": 104857, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gemini-2.5-flash-lite", + "name": "Gemini 2.5 Flash Lite", + "cost_per_1m_in": 0.1, + "cost_per_1m_out": 0.4, + "cost_per_1m_in_cached": 0.01, + "cost_per_1m_out_cached": 0, + "context_window": 1048576, + "default_max_tokens": 104857, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "gemini-2.5-pro", + "name": "Gemini 2.5 Pro", + "cost_per_1m_in": 1.25, + "cost_per_1m_out": 10, + "cost_per_1m_in_cached": 0.125, + "cost_per_1m_out_cached": 0, + "context_window": 1048576, + "default_max_tokens": 104857, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "gemini-3-flash-preview", + "name": "Gemini 3 Flash (Preview)", + "cost_per_1m_in": 0.5, + "cost_per_1m_out": 3, + "cost_per_1m_in_cached": 0.05, + "cost_per_1m_out_cached": 0, + "context_window": 1048576, + "default_max_tokens": 104857, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gemini-3.1-flash-lite", + "name": "Gemini 3.1 Flash Lite", + "cost_per_1m_in": 0.25, + "cost_per_1m_out": 1.5, + "cost_per_1m_in_cached": 0.025, + "cost_per_1m_out_cached": 0, + "context_window": 1048576, + "default_max_tokens": 104857, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "gemini-3.1-pro-preview", + "name": "Gemini 3.1 Pro (Preview)", + "cost_per_1m_in": 2, + "cost_per_1m_out": 12, + "cost_per_1m_in_cached": 0.2, + "cost_per_1m_out_cached": 0, + "context_window": 1048576, + "default_max_tokens": 104857, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "gemini-3.5-flash", + "name": "Gemini 3.5 Flash", + "cost_per_1m_in": 1.5, + "cost_per_1m_out": 9, + "cost_per_1m_in_cached": 0.15, + "cost_per_1m_out_cached": 0, + "context_window": 1048576, + "default_max_tokens": 104857, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gemini-3.5-flash-lite", + "name": "Gemini 3.5 Flash Lite", + "cost_per_1m_in": 0.3, + "cost_per_1m_out": 2.5, + "cost_per_1m_in_cached": 0.03, + "cost_per_1m_out_cached": 0, + "context_window": 1048576, + "default_max_tokens": 104857, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gemini-3.6-flash", + "name": "Gemini 3.6 Flash", + "cost_per_1m_in": 1.5, + "cost_per_1m_out": 7.5, + "cost_per_1m_in_cached": 0.15, + "cost_per_1m_out_cached": 0, + "context_window": 1048576, + "default_max_tokens": 104857, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "gemini-pro-latest", + "name": "Gemini Pro Latest", + "cost_per_1m_in": 2, + "cost_per_1m_out": 12, + "cost_per_1m_in_cached": 0.2, + "cost_per_1m_out_cached": 0, + "context_window": 1048576, + "default_max_tokens": 104857, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "gemma-4-26b-a4b-it", + "name": "Gemma 4 26B A4B IT", + "cost_per_1m_in": 0.07, + "cost_per_1m_out": 0.34, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "gemma-4-31b-it", + "name": "Gemma 4 31B IT", + "cost_per_1m_in": 0.13, + "cost_per_1m_out": 0.38, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "grok-4", + "name": "Grok 4", + "cost_per_1m_in": 3, + "cost_per_1m_out": 15, + "cost_per_1m_in_cached": 0.75, + "cost_per_1m_out_cached": 0, + "context_window": 256000, + "default_max_tokens": 25600, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "grok-4-1-fast-non-reasoning", + "name": "Grok 4.1 Fast Non-Reasoning", + "cost_per_1m_in": 0.2, + "cost_per_1m_out": 0.5, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 2000000, + "default_max_tokens": 200000, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "grok-4-1-fast-reasoning", + "name": "Grok 4.1 Fast Reasoning", + "cost_per_1m_in": 0.2, + "cost_per_1m_out": 0.5, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 2000000, + "default_max_tokens": 200000, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "grok-4-20-beta-0309-non-reasoning", + "name": "Grok 4.20 Beta Non-Reasoning (0309)", + "cost_per_1m_in": 2, + "cost_per_1m_out": 6, + "cost_per_1m_in_cached": 0.2, + "cost_per_1m_out_cached": 0, + "context_window": 2000000, + "default_max_tokens": 200000, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "grok-4-20-beta-0309-reasoning", + "name": "Grok 4.20 Beta Reasoning (0309)", + "cost_per_1m_in": 2, + "cost_per_1m_out": 6, + "cost_per_1m_in_cached": 0.2, + "cost_per_1m_out_cached": 0, + "context_window": 2000000, + "default_max_tokens": 200000, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "grok-4-3", + "name": "Grok 4.3", + "cost_per_1m_in": 1.25, + "cost_per_1m_out": 2.5, + "cost_per_1m_in_cached": 0.3125, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "reasoning_levels": [ + "none", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "grok-4-5", + "name": "Grok 4.5", + "cost_per_1m_in": 2, + "cost_per_1m_out": 6, + "cost_per_1m_in_cached": 0.5, + "cost_per_1m_out_cached": 0, + "context_window": 500000, + "default_max_tokens": 50000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "grok-build-0-1", + "name": "Grok Build 0.1", + "cost_per_1m_in": 1, + "cost_per_1m_out": 2, + "cost_per_1m_in_cached": 0.2, + "cost_per_1m_out_cached": 0, + "context_window": 256000, + "default_max_tokens": 25600, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "kimi-k2", + "name": "Kimi K2", + "cost_per_1m_in": 0.57, + "cost_per_1m_out": 2.3, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 256000, + "default_max_tokens": 25600, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "kimi-k2-thinking", + "name": "Kimi K2 Thinking", + "cost_per_1m_in": 0.6, + "cost_per_1m_out": 2.5, + "cost_per_1m_in_cached": 0.06, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "kimi-k2.5", + "name": "Kimi K2.5", + "cost_per_1m_in": 0.405, + "cost_per_1m_out": 1.98, + "cost_per_1m_in_cached": 0.225, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "reasoning_levels": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "kimi-k2.6", + "name": "Kimi K2.6", + "cost_per_1m_in": 0.4, + "cost_per_1m_out": 2.2, + "cost_per_1m_in_cached": 0.08, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "reasoning_levels": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "kimi-k2.7-code", + "name": "Kimi K2.7 Code", + "cost_per_1m_in": 0.95, + "cost_per_1m_out": 4, + "cost_per_1m_in_cached": 0.19, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "kimi-k2.7-code-highspeed", + "name": "Kimi K2.7 Code Highspeed", + "cost_per_1m_in": 1.9, + "cost_per_1m_out": 8, + "cost_per_1m_in_cached": 0.38, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "kimi-k3", + "name": "Kimi K3", + "cost_per_1m_in": 3, + "cost_per_1m_out": 15, + "cost_per_1m_in_cached": 0.3, + "cost_per_1m_out_cached": 0, + "context_window": 1048576, + "default_max_tokens": 104857, + "can_reason": true, + "reasoning_levels": [ + "max" + ], + "default_reasoning_effort": "max", + "supports_attachments": true + }, + { + "id": "llama-3.3-70b-instruct", + "name": "Llama 3.3 70B Instruct", + "cost_per_1m_in": 0.13, + "cost_per_1m_out": 0.4, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 131072, + "default_max_tokens": 13107, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "mimo-v2.5", + "name": "MiMo V2.5", + "cost_per_1m_in": 0.14, + "cost_per_1m_out": 0.28, + "cost_per_1m_in_cached": 0.0028, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "reasoning_levels": [ + "none", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "mimo-v2.5-pro", + "name": "MiMo V2.5 Pro", + "cost_per_1m_in": 0.435, + "cost_per_1m_out": 0.87, + "cost_per_1m_in_cached": 0.0036, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "reasoning_levels": [ + "none", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": false + }, + { + "id": "minimax-m2", + "name": "MiniMax M2", + "cost_per_1m_in": 0.2, + "cost_per_1m_out": 1, + "cost_per_1m_in_cached": 0.03, + "cost_per_1m_out_cached": 0, + "context_window": 196608, + "default_max_tokens": 19660, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": false + }, + { + "id": "minimax-m2.1", + "name": "MiniMax M2.1", + "cost_per_1m_in": 0.27, + "cost_per_1m_out": 1.1, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 204800, + "default_max_tokens": 20480, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": false + }, + { + "id": "minimax-m2.1-lightning", + "name": "MiniMax M2.1 Lightning", + "cost_per_1m_in": 0.12, + "cost_per_1m_out": 0.48, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 196608, + "default_max_tokens": 19660, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": false + }, + { + "id": "minimax-m2.5", + "name": "MiniMax M2.5", + "cost_per_1m_in": 0.3, + "cost_per_1m_out": 1.2, + "cost_per_1m_in_cached": 0.03, + "cost_per_1m_out_cached": 0, + "context_window": 228700, + "default_max_tokens": 22870, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": false + }, + { + "id": "minimax-m2.5-highspeed", + "name": "MiniMax M2.5 Highspeed", + "cost_per_1m_in": 0.6, + "cost_per_1m_out": 2.4, + "cost_per_1m_in_cached": 0.03, + "cost_per_1m_out_cached": 0, + "context_window": 204800, + "default_max_tokens": 20480, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": false + }, + { + "id": "minimax-m2.7", + "name": "MiniMax M2.7", + "cost_per_1m_in": 0.3, + "cost_per_1m_out": 1.2, + "cost_per_1m_in_cached": 0.06, + "cost_per_1m_out_cached": 0, + "context_window": 204800, + "default_max_tokens": 20480, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": false + }, + { + "id": "minimax-m2.7-highspeed", + "name": "MiniMax M2.7 Highspeed", + "cost_per_1m_in": 0.6, + "cost_per_1m_out": 2.4, + "cost_per_1m_in_cached": 0.06, + "cost_per_1m_out_cached": 0, + "context_window": 204800, + "default_max_tokens": 20480, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": false + }, + { + "id": "minimax-m3", + "name": "MiniMax M3", + "cost_per_1m_in": 0.3, + "cost_per_1m_out": 1.2, + "cost_per_1m_in_cached": 0.06, + "cost_per_1m_out_cached": 0, + "context_window": 524288, + "default_max_tokens": 52428, + "can_reason": true, + "reasoning_levels": [ + "none", + "minimal", + "low", + "medium", + "high", + "xhigh", + "max" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "minimax-text-01", + "name": "MiniMax Text 01", + "cost_per_1m_in": 0.2, + "cost_per_1m_out": 1.1, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "muse-spark-1.1", + "name": "Muse Spark 1.1", + "cost_per_1m_in": 1.25, + "cost_per_1m_out": 4.25, + "cost_per_1m_in_cached": 0.15, + "cost_per_1m_out_cached": 0, + "context_window": 1048576, + "default_max_tokens": 104857, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high", + "xhigh" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "nemotron-3-ultra-550b", + "name": "Nemotron 3 Ultra 550B", + "cost_per_1m_in": 0.5, + "cost_per_1m_out": 2.5, + "cost_per_1m_in_cached": 0.15, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "qwen-coder-plus", + "name": "Qwen Coder Plus", + "cost_per_1m_in": 0.502, + "cost_per_1m_out": 1.004, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 131072, + "default_max_tokens": 13107, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen-flash", + "name": "Qwen Flash", + "cost_per_1m_in": 0.05, + "cost_per_1m_out": 0.4, + "cost_per_1m_in_cached": 0.01, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen-max", + "name": "Qwen Max", + "cost_per_1m_in": 1.6, + "cost_per_1m_out": 6.4, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 32768, + "default_max_tokens": 3276, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "qwen-max-latest", + "name": "Qwen Max Latest", + "cost_per_1m_in": 1.6, + "cost_per_1m_out": 6.4, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 32768, + "default_max_tokens": 3276, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "qwen-plus", + "name": "Qwen Plus", + "cost_per_1m_in": 0.4, + "cost_per_1m_out": 1.2, + "cost_per_1m_in_cached": 0.08, + "cost_per_1m_out_cached": 0, + "context_window": 131072, + "default_max_tokens": 13107, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen-plus-latest", + "name": "Qwen Plus Latest", + "cost_per_1m_in": 0.4, + "cost_per_1m_out": 1.2, + "cost_per_1m_in_cached": 0.08, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen3-235b-a22b-instruct-2507", + "name": "Qwen3 235B A22B Instruct 2507", + "cost_per_1m_in": 0.09, + "cost_per_1m_out": 0.58, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen3-235b-a22b-thinking-2507", + "name": "Qwen3 235B A22B Thinking 2507", + "cost_per_1m_in": 0.2, + "cost_per_1m_out": 0.6, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 262000, + "default_max_tokens": 26200, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen3-30b-a3b-instruct-2507", + "name": "Qwen3 30B A3B Instruct 2507", + "cost_per_1m_in": 0.1, + "cost_per_1m_out": 0.3, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 262000, + "default_max_tokens": 26200, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen3-32b", + "name": "Qwen3 32B", + "cost_per_1m_in": 0.1, + "cost_per_1m_out": 0.3, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 32768, + "default_max_tokens": 3276, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen3-coder-30b-a3b-instruct", + "name": "Qwen3 Coder 30B A3B Instruct", + "cost_per_1m_in": 0.07, + "cost_per_1m_out": 0.27, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 262000, + "default_max_tokens": 26200, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen3-coder-480b-a35b-instruct", + "name": "Qwen3 Coder 480B A35B Instruct", + "cost_per_1m_in": 0.3, + "cost_per_1m_out": 1.3, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen3-coder-flash", + "name": "Qwen3 Coder Flash", + "cost_per_1m_in": 0.3, + "cost_per_1m_out": 1.5, + "cost_per_1m_in_cached": 0.06, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen3-coder-next", + "name": "Qwen3 Coder Next", + "cost_per_1m_in": 0.108, + "cost_per_1m_out": 0.675, + "cost_per_1m_in_cached": 0.06, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen3-coder-plus", + "name": "Qwen3 Coder Plus", + "cost_per_1m_in": 6, + "cost_per_1m_out": 60, + "cost_per_1m_in_cached": 1.2, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen3-max", + "name": "Qwen3 Max", + "cost_per_1m_in": 0.845, + "cost_per_1m_out": 3.38, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "qwen3-next-80b-a3b-instruct", + "name": "Qwen3 Next 80B A3B Instruct", + "cost_per_1m_in": 0.15, + "cost_per_1m_out": 1.2, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 131072, + "default_max_tokens": 13107, + "can_reason": false, + "supports_attachments": false + }, + { + "id": "qwen3-next-80b-a3b-thinking", + "name": "Qwen3 Next 80B A3B Thinking", + "cost_per_1m_in": 0.15, + "cost_per_1m_out": 1.2, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 131072, + "default_max_tokens": 13107, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "qwen3-vl-235b-a22b-instruct", + "name": "Qwen3 VL 235B A22B Instruct", + "cost_per_1m_in": 0.3, + "cost_per_1m_out": 1.5, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 131072, + "default_max_tokens": 13107, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "qwen3-vl-30b-a3b-instruct", + "name": "Qwen3 VL 30B A3B Instruct", + "cost_per_1m_in": 0.2, + "cost_per_1m_out": 0.7, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 131072, + "default_max_tokens": 13107, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "qwen3-vl-flash", + "name": "Qwen3 VL Flash", + "cost_per_1m_in": 0.05, + "cost_per_1m_out": 0.4, + "cost_per_1m_in_cached": 0.01, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": false, + "supports_attachments": true + }, + { + "id": "qwen35-397b-a17b", + "name": "Qwen3.5 397B A17B", + "cost_per_1m_in": 0.6, + "cost_per_1m_out": 3.6, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "qwen3.6-35b-a3b", + "name": "Qwen3.6 35B A3B", + "cost_per_1m_in": 0.248, + "cost_per_1m_out": 1.485, + "cost_per_1m_in_cached": 0, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "qwen3.6-flash", + "name": "Qwen3.6 Flash", + "cost_per_1m_in": 0.15, + "cost_per_1m_out": 0.9, + "cost_per_1m_in_cached": 0.015, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "qwen3.6-max-preview", + "name": "Qwen3.6 Max Preview", + "cost_per_1m_in": 1.3, + "cost_per_1m_out": 7.8, + "cost_per_1m_in_cached": 0.13, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "qwen3.6-plus", + "name": "Qwen3.6 Plus", + "cost_per_1m_in": 0.5, + "cost_per_1m_out": 3, + "cost_per_1m_in_cached": 0.05, + "cost_per_1m_out_cached": 0, + "context_window": 262144, + "default_max_tokens": 26214, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "qwen3.7-max", + "name": "Qwen3.7 Max", + "cost_per_1m_in": 1.25, + "cost_per_1m_out": 3.75, + "cost_per_1m_in_cached": 0.125, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "supports_attachments": false + }, + { + "id": "qwen3.7-plus", + "name": "Qwen3.7 Plus", + "cost_per_1m_in": 0.4, + "cost_per_1m_out": 1.6, + "cost_per_1m_in_cached": 0.08, + "cost_per_1m_out_cached": 0, + "context_window": 1000000, + "default_max_tokens": 100000, + "can_reason": true, + "supports_attachments": true + }, + { + "id": "seed-1-6-250615", + "name": "Seed 1.6 (250615)", + "cost_per_1m_in": 0.25, + "cost_per_1m_out": 2, + "cost_per_1m_in_cached": 0.05, + "cost_per_1m_out_cached": 0, + "context_window": 256000, + "default_max_tokens": 25600, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "seed-1-6-250915", + "name": "Seed 1.6 (250915)", + "cost_per_1m_in": 0.25, + "cost_per_1m_out": 2, + "cost_per_1m_in_cached": 0.05, + "cost_per_1m_out_cached": 0, + "context_window": 256000, + "default_max_tokens": 25600, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "seed-1-6-flash-250715", + "name": "Seed 1.6 Flash (250715)", + "cost_per_1m_in": 0.07, + "cost_per_1m_out": 0.3, + "cost_per_1m_in_cached": 0.015, + "cost_per_1m_out_cached": 0, + "context_window": 256000, + "default_max_tokens": 25600, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "seed-1-8-251228", + "name": "Seed 1.8 (251228)", + "cost_per_1m_in": 0.25, + "cost_per_1m_out": 2, + "cost_per_1m_in_cached": 0.05, + "cost_per_1m_out_cached": 0, + "context_window": 256000, + "default_max_tokens": 25600, + "can_reason": true, + "reasoning_levels": [ + "minimal", + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + }, + { + "id": "o4-mini", + "name": "o4 Mini", + "cost_per_1m_in": 1.1, + "cost_per_1m_out": 4.4, + "cost_per_1m_in_cached": 0.275, + "cost_per_1m_out_cached": 0, + "context_window": 200000, + "default_max_tokens": 20000, + "can_reason": true, + "reasoning_levels": [ + "low", + "medium", + "high" + ], + "default_reasoning_effort": "medium", + "supports_attachments": true + } + ] +} diff --git a/internal/providers/providers.go b/internal/providers/providers.go index 6f11d669..8fb49deb 100644 --- a/internal/providers/providers.go +++ b/internal/providers/providers.go @@ -69,6 +69,9 @@ var ioNetConfig []byte //go:embed configs/kimi.json var kimiCodingConfig []byte +//go:embed configs/llmgateway.json +var llmGatewayConfig []byte + //go:embed configs/minimax.json var miniMaxConfig []byte @@ -160,6 +163,7 @@ var providerRegistry = []ProviderFunc{ groqProvider, huggingFaceProvider, ioNetProvider, + llmGatewayProvider, nebiusProvider, neuralwattProvider, openCodeGoProvider, @@ -272,6 +276,10 @@ func kimiCodingProvider() catwalk.Provider { return loadProviderFromConfig(kimiCodingConfig) } +func llmGatewayProvider() catwalk.Provider { + return loadProviderFromConfig(llmGatewayConfig) +} + func miniMaxProvider() catwalk.Provider { return loadProviderFromConfig(miniMaxConfig) } diff --git a/pkg/catwalk/provider.go b/pkg/catwalk/provider.go index f3a31375..0618929f 100644 --- a/pkg/catwalk/provider.go +++ b/pkg/catwalk/provider.go @@ -59,6 +59,7 @@ const ( InferenceProviderFireworks InferenceProvider = "fireworks" InferenceProviderBaseten InferenceProvider = "baseten" InferenceProviderMoonshot InferenceProvider = "moonshot" + InferenceProviderLLMGateway InferenceProvider = "llmgateway" ) // Provider represents an AI provider configuration. @@ -138,6 +139,7 @@ func KnownProviders() []InferenceProvider { InferenceProviderFireworks, InferenceProviderBaseten, InferenceProviderMoonshot, + InferenceProviderLLMGateway, } }