SPB Git

spb/zyquo-cloud Public MIT

Native macOS AI chat client for 12 cloud providers — your keys, every cloud model, one beautiful chat.

Swift 97.4% Shell 1.7% Makefile 1%
71.7 KB · 1,365 lines swift
Raw Blame History
1//2//  ModelCatalogData.swift3//  Zyquo Cloud4//5//  Author: Simon-Pierre Boucher6//  Mail: contact@spboucher.ai7//8//  Built-in model catalog, generated from docs/PROVIDERS.md and the per-provider9//  research files in docs/research/ on 2026-07-30. This file and docs/PROVIDERS.md10//  are a single source of truth and MUST stay in sync: when Phase 7 verification11//  (or any later research pass) changes a model, update both together.12//13//  Scope: chat-completions-capable chat models only. Embeddings, audio/TTS/ASR,14//  realtime, image/video generation, moderation, OCR, robotics, deep-research15//  agents, and Responses-API-only models are excluded by design.16//1718import Foundation1920enum ModelCatalogData {2122    // MARK: - Shared parameter-support presets2324    /// OpenAI reasoning models (o-series, gpt-5.x reasoning variants): reject25    /// temperature/top_p/penalties, require max_completion_tokens, accept reasoning_effort.26    private static let openAIReasoning = ParameterSupport(27        temperature: false, topP: false,28        usesMaxCompletionTokens: true, reasoningEffort: true29    )3031    // MARK: - OpenAI3233    static let openai: [AIModel] = [34        // Flagship GPT-5.6 trio35        AIModel(36            id: "gpt-5.6-sol", provider: .openai, displayName: "GPT-5.6 Sol",37            contextWindow: 1_050_000, maxOutputTokens: 128_000,38            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),39            pricing: ModelPricing(inputPerMTok: 5.00, outputPerMTok: 30.00),40            parameterSupport: openAIReasoning,41            isRecommended: true42        ),43        AIModel(44            id: "gpt-5.6-terra", provider: .openai, displayName: "GPT-5.6 Terra",45            contextWindow: 1_050_000, maxOutputTokens: 128_000,46            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),47            pricing: ModelPricing(inputPerMTok: 2.50, outputPerMTok: 15.00),48            parameterSupport: openAIReasoning,49            isRecommended: true50        ),51        AIModel(52            id: "gpt-5.6-luna", provider: .openai, displayName: "GPT-5.6 Luna",53            contextWindow: 1_050_000, maxOutputTokens: 128_000,54            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),55            pricing: ModelPricing(inputPerMTok: 1.00, outputPerMTok: 6.00),56            parameterSupport: openAIReasoning57        ),58        AIModel(59            id: "chat-latest", provider: .openai, displayName: "ChatGPT Latest",60            contextWindow: 128_000, maxOutputTokens: nil,61            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),62            pricing: ModelPricing(inputPerMTok: 5.00, outputPerMTok: 30.00),63            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, usesMaxCompletionTokens: true)64        ),65        // Current / recent GPT-5.x66        AIModel(67            id: "gpt-5.5", provider: .openai, displayName: "GPT-5.5",68            contextWindow: 400_000, maxOutputTokens: nil,69            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),70            pricing: ModelPricing(inputPerMTok: 5.00, outputPerMTok: 30.00),71            parameterSupport: openAIReasoning72        ),73        AIModel(74            id: "gpt-5.4", provider: .openai, displayName: "GPT-5.4",75            contextWindow: 400_000, maxOutputTokens: 128_000,76            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),77            pricing: ModelPricing(inputPerMTok: 2.50, outputPerMTok: 15.00),78            parameterSupport: openAIReasoning79        ),80        AIModel(81            id: "gpt-5.4-mini", provider: .openai, displayName: "GPT-5.4 mini",82            contextWindow: 400_000, maxOutputTokens: nil,83            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),84            pricing: ModelPricing(inputPerMTok: 0.75, outputPerMTok: 4.50),85            parameterSupport: openAIReasoning86        ),87        AIModel(88            id: "gpt-5.4-nano", provider: .openai, displayName: "GPT-5.4 nano",89            contextWindow: 400_000, maxOutputTokens: nil,90            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),91            pricing: ModelPricing(inputPerMTok: 0.20, outputPerMTok: 1.25),92            parameterSupport: openAIReasoning93        ),94        AIModel(95            id: "gpt-5.3-chat-latest", provider: .openai, displayName: "GPT-5.3 Chat Latest",96            contextWindow: 128_000, maxOutputTokens: nil,97            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),98            pricing: nil,99            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, usesMaxCompletionTokens: true)100        ),101        AIModel(102            id: "gpt-5.2", provider: .openai, displayName: "GPT-5.2",103            contextWindow: 400_000, maxOutputTokens: 128_000,104            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),105            pricing: ModelPricing(inputPerMTok: 1.75, outputPerMTok: 14.00),106            parameterSupport: openAIReasoning107        ),108        AIModel(109            id: "gpt-5.2-chat-latest", provider: .openai, displayName: "GPT-5.2 Chat Latest",110            contextWindow: 128_000, maxOutputTokens: 16_000,111            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),112            pricing: ModelPricing(inputPerMTok: 1.75, outputPerMTok: 14.00),113            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, usesMaxCompletionTokens: true)114        ),115        AIModel(116            id: "gpt-5.1", provider: .openai, displayName: "GPT-5.1",117            contextWindow: 400_000, maxOutputTokens: 128_000,118            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),119            pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 10.00),120            parameterSupport: openAIReasoning121        ),122        AIModel(123            id: "gpt-5", provider: .openai, displayName: "GPT-5",124            contextWindow: 400_000, maxOutputTokens: 128_000,125            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),126            pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 10.00),127            parameterSupport: openAIReasoning128        ),129        AIModel(130            id: "gpt-5-mini", provider: .openai, displayName: "GPT-5 mini",131            contextWindow: 400_000, maxOutputTokens: 128_000,132            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),133            pricing: ModelPricing(inputPerMTok: 0.25, outputPerMTok: 2.00),134            parameterSupport: openAIReasoning135        ),136        AIModel(137            id: "gpt-5-nano", provider: .openai, displayName: "GPT-5 nano",138            contextWindow: 400_000, maxOutputTokens: 128_000,139            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),140            pricing: ModelPricing(inputPerMTok: 0.05, outputPerMTok: 0.40),141            parameterSupport: openAIReasoning142        ),143        // o-series reasoning144        AIModel(145            id: "o3", provider: .openai, displayName: "OpenAI o3",146            contextWindow: 200_000, maxOutputTokens: 100_000,147            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),148            pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 8.00),149            parameterSupport: openAIReasoning150        ),151        AIModel(152            id: "o4-mini", provider: .openai, displayName: "OpenAI o4-mini",153            contextWindow: 200_000, maxOutputTokens: 100_000,154            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),155            pricing: ModelPricing(inputPerMTok: 1.10, outputPerMTok: 4.40),156            parameterSupport: openAIReasoning157        ),158        AIModel(159            id: "o3-mini", provider: .openai, displayName: "OpenAI o3-mini",160            contextWindow: 200_000, maxOutputTokens: 100_000,161            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),162            pricing: ModelPricing(inputPerMTok: 1.10, outputPerMTok: 4.40),163            parameterSupport: openAIReasoning,164            isLegacy: true165        ),166        AIModel(167            id: "o1", provider: .openai, displayName: "OpenAI o1",168            contextWindow: 200_000, maxOutputTokens: 100_000,169            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),170            pricing: ModelPricing(inputPerMTok: 15.00, outputPerMTok: 60.00),171            parameterSupport: openAIReasoning,172            isLegacy: true173        ),174        // Legacy GPT-4.x / 3.5175        AIModel(176            id: "gpt-4.1", provider: .openai, displayName: "GPT-4.1",177            contextWindow: 1_047_576, maxOutputTokens: 32_768,178            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),179            pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 8.00),180            parameterSupport: .openAIDefault,181            isLegacy: true182        ),183        AIModel(184            id: "gpt-4.1-mini", provider: .openai, displayName: "GPT-4.1 mini",185            contextWindow: 1_047_576, maxOutputTokens: 32_768,186            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),187            pricing: ModelPricing(inputPerMTok: 0.40, outputPerMTok: 1.60),188            parameterSupport: .openAIDefault,189            isLegacy: true190        ),191        AIModel(192            id: "gpt-4.1-nano", provider: .openai, displayName: "GPT-4.1 nano",193            contextWindow: 1_047_576, maxOutputTokens: 32_768,194            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),195            pricing: ModelPricing(inputPerMTok: 0.10, outputPerMTok: 0.40),196            parameterSupport: .openAIDefault,197            isLegacy: true198        ),199        AIModel(200            id: "gpt-4o", provider: .openai, displayName: "GPT-4o",201            contextWindow: 128_000, maxOutputTokens: 16_384,202            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),203            pricing: ModelPricing(inputPerMTok: 2.50, outputPerMTok: 10.00),204            parameterSupport: .openAIDefault,205            isLegacy: true206        ),207        AIModel(208            id: "gpt-4o-mini", provider: .openai, displayName: "GPT-4o mini",209            contextWindow: 128_000, maxOutputTokens: 16_384,210            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),211            pricing: ModelPricing(inputPerMTok: 0.15, outputPerMTok: 0.60),212            parameterSupport: .openAIDefault,213            isLegacy: true214        ),215        AIModel(216            id: "gpt-4-turbo", provider: .openai, displayName: "GPT-4 Turbo",217            contextWindow: 128_000, maxOutputTokens: 4_096,218            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),219            pricing: ModelPricing(inputPerMTok: 10.00, outputPerMTok: 30.00),220            parameterSupport: .openAIDefault,221            isLegacy: true222        ),223        AIModel(224            id: "gpt-4", provider: .openai, displayName: "GPT-4",225            contextWindow: 8_192, maxOutputTokens: 8_192,226            capabilities: ModelCapabilities(tools: true),227            pricing: ModelPricing(inputPerMTok: 30.00, outputPerMTok: 60.00),228            parameterSupport: .openAIDefault,229            isLegacy: true230        ),231        AIModel(232            id: "gpt-3.5-turbo", provider: .openai, displayName: "GPT-3.5 Turbo",233            contextWindow: 16_385, maxOutputTokens: 4_096,234            capabilities: ModelCapabilities(tools: true, jsonMode: true),235            pricing: ModelPricing(inputPerMTok: 0.50, outputPerMTok: 1.50),236            parameterSupport: .openAIDefault,237            isLegacy: true238        ),239    ]240241    // MARK: - Anthropic242243    static let anthropic: [AIModel] = [244        AIModel(245            id: "claude-opus-5", provider: .anthropic, displayName: "Claude Opus 5",246            contextWindow: 1_000_000, maxOutputTokens: 128_000,247            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),248            pricing: ModelPricing(inputPerMTok: 5.00, outputPerMTok: 25.00),249            parameterSupport: ParameterSupport(temperature: false, topP: false, thinkingToggle: true),250            isRecommended: true251        ),252        AIModel(253            id: "claude-sonnet-5", provider: .anthropic, displayName: "Claude Sonnet 5",254            contextWindow: 1_000_000, maxOutputTokens: 128_000,255            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),256            pricing: ModelPricing(inputPerMTok: 3.00, outputPerMTok: 15.00),257            parameterSupport: ParameterSupport(temperature: false, topP: false, thinkingToggle: true),258            isRecommended: true259        ),260        AIModel(261            id: "claude-fable-5", provider: .anthropic, displayName: "Claude Fable 5",262            contextWindow: 1_000_000, maxOutputTokens: 128_000,263            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),264            pricing: ModelPricing(inputPerMTok: 10.00, outputPerMTok: 50.00),265            // Thinking is always on and cannot be disabled — no toggle.266            parameterSupport: ParameterSupport(temperature: false, topP: false, thinkingToggle: false)267        ),268        AIModel(269            id: "claude-opus-4-8", provider: .anthropic, displayName: "Claude Opus 4.8",270            contextWindow: 1_000_000, maxOutputTokens: 128_000,271            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),272            pricing: ModelPricing(inputPerMTok: 5.00, outputPerMTok: 25.00),273            parameterSupport: ParameterSupport(temperature: false, topP: false, thinkingToggle: true)274        ),275        AIModel(276            id: "claude-opus-4-7", provider: .anthropic, displayName: "Claude Opus 4.7",277            contextWindow: 1_000_000, maxOutputTokens: 128_000,278            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),279            pricing: ModelPricing(inputPerMTok: 5.00, outputPerMTok: 25.00),280            parameterSupport: ParameterSupport(temperature: false, topP: false, thinkingToggle: true)281        ),282        AIModel(283            id: "claude-opus-4-6", provider: .anthropic, displayName: "Claude Opus 4.6",284            contextWindow: 1_000_000, maxOutputTokens: 128_000,285            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),286            pricing: ModelPricing(inputPerMTok: 5.00, outputPerMTok: 25.00),287            parameterSupport: ParameterSupport(temperature: true, topP: true, thinkingToggle: true)288        ),289        AIModel(290            id: "claude-sonnet-4-6", provider: .anthropic, displayName: "Claude Sonnet 4.6",291            contextWindow: 1_000_000, maxOutputTokens: 128_000,292            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),293            pricing: ModelPricing(inputPerMTok: 3.00, outputPerMTok: 15.00),294            parameterSupport: ParameterSupport(temperature: true, topP: true, thinkingToggle: true)295        ),296        AIModel(297            id: "claude-haiku-4-5-20251001", provider: .anthropic, displayName: "Claude Haiku 4.5",298            contextWindow: 200_000, maxOutputTokens: 64_000,299            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),300            pricing: ModelPricing(inputPerMTok: 1.00, outputPerMTok: 5.00),301            parameterSupport: ParameterSupport(temperature: true, topP: true, thinkingToggle: true)302        ),303        AIModel(304            id: "claude-opus-4-5-20251101", provider: .anthropic, displayName: "Claude Opus 4.5",305            contextWindow: 200_000, maxOutputTokens: 64_000,306            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),307            pricing: ModelPricing(inputPerMTok: 5.00, outputPerMTok: 25.00),308            parameterSupport: ParameterSupport(temperature: true, topP: true, thinkingToggle: true),309            isLegacy: true310        ),311        AIModel(312            id: "claude-sonnet-4-5-20250929", provider: .anthropic, displayName: "Claude Sonnet 4.5",313            contextWindow: 1_000_000, maxOutputTokens: 64_000,314            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),315            pricing: ModelPricing(inputPerMTok: 3.00, outputPerMTok: 15.00),316            parameterSupport: ParameterSupport(temperature: true, topP: true, thinkingToggle: true),317            isLegacy: true318        ),319        AIModel(320            id: "claude-opus-4-1-20250805", provider: .anthropic, displayName: "Claude Opus 4.1",321            contextWindow: 200_000, maxOutputTokens: 32_000,322            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),323            pricing: ModelPricing(inputPerMTok: 15.00, outputPerMTok: 75.00),324            parameterSupport: ParameterSupport(temperature: true, topP: true, thinkingToggle: true),325            isLegacy: true326        ),327    ]328329    // MARK: - xAI (Grok)330331    static let xai: [AIModel] = [332        AIModel(333            id: "grok-4.5", provider: .xai, displayName: "Grok 4.5",334            contextWindow: 500_000, maxOutputTokens: nil,335            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),336            pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 6.00),337            parameterSupport: ParameterSupport(reasoningEffort: true),338            isRecommended: true339        ),340        AIModel(341            id: "grok-4.3", provider: .xai, displayName: "Grok 4.3",342            contextWindow: 1_000_000, maxOutputTokens: nil,343            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),344            pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 2.50),345            parameterSupport: ParameterSupport(reasoningEffort: true)346        ),347        AIModel(348            id: "grok-4.20", provider: .xai, displayName: "Grok 4.20 Reasoning",349            contextWindow: 1_000_000, maxOutputTokens: nil,350            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),351            pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 2.50),352            parameterSupport: ParameterSupport()353        ),354        AIModel(355            id: "grok-4.20-non-reasoning", provider: .xai, displayName: "Grok 4.20 Non-Reasoning",356            contextWindow: 1_000_000, maxOutputTokens: nil,357            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),358            pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 2.50),359            parameterSupport: ParameterSupport()360        ),361        AIModel(362            id: "grok-code-fast-1", provider: .xai, displayName: "Grok Code Fast 1",363            contextWindow: 256_000, maxOutputTokens: nil,364            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),365            pricing: ModelPricing(inputPerMTok: 1.00, outputPerMTok: 2.00),366            parameterSupport: ParameterSupport(),367            isRecommended: true368        ),369    ]370371    // MARK: - Mistral372373    static let mistral: [AIModel] = [374        AIModel(375            id: "mistral-medium-latest", provider: .mistral, displayName: "Mistral Medium 3.5",376            contextWindow: 262_144, maxOutputTokens: nil,377            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),378            pricing: ModelPricing(inputPerMTok: 1.50, outputPerMTok: 7.50),379            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, reasoningEffort: true),380            isRecommended: true381        ),382        AIModel(383            id: "mistral-large-latest", provider: .mistral, displayName: "Mistral Large 3",384            contextWindow: 262_144, maxOutputTokens: nil,385            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),386            pricing: ModelPricing(inputPerMTok: 0.50, outputPerMTok: 1.50),387            parameterSupport: .openAIDefault,388            isRecommended: true389        ),390        AIModel(391            id: "mistral-small-latest", provider: .mistral, displayName: "Mistral Small 4",392            contextWindow: 262_144, maxOutputTokens: nil,393            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),394            pricing: ModelPricing(inputPerMTok: 0.15, outputPerMTok: 0.60),395            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, reasoningEffort: true),396            isRecommended: true397        ),398        AIModel(399            id: "codestral-latest", provider: .mistral, displayName: "Codestral",400            contextWindow: 256_000, maxOutputTokens: nil,401            capabilities: ModelCapabilities(tools: true, jsonMode: true),402            pricing: ModelPricing(inputPerMTok: 0.30, outputPerMTok: 0.90),403            parameterSupport: .openAIDefault404        ),405        AIModel(406            id: "ministral-14b-latest", provider: .mistral, displayName: "Ministral 3 14B",407            contextWindow: 262_144, maxOutputTokens: nil,408            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),409            pricing: ModelPricing(inputPerMTok: 0.20, outputPerMTok: 0.20),410            parameterSupport: .openAIDefault411        ),412        AIModel(413            id: "ministral-8b-latest", provider: .mistral, displayName: "Ministral 3 8B",414            contextWindow: 262_144, maxOutputTokens: nil,415            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),416            pricing: ModelPricing(inputPerMTok: 0.15, outputPerMTok: 0.15),417            parameterSupport: .openAIDefault418        ),419        AIModel(420            id: "ministral-3b-latest", provider: .mistral, displayName: "Ministral 3 3B",421            contextWindow: 131_072, maxOutputTokens: nil,422            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),423            pricing: ModelPricing(inputPerMTok: 0.10, outputPerMTok: 0.10),424            parameterSupport: .openAIDefault425        ),426        // Legacy / deprecated (still served; hidden by default)427        AIModel(428            id: "magistral-medium-latest", provider: .mistral, displayName: "Magistral Medium",429            contextWindow: 131_072, maxOutputTokens: nil,430            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),431            pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 5.00),432            parameterSupport: .openAIDefault,433            isLegacy: true434        ),435        AIModel(436            id: "devstral-latest", provider: .mistral, displayName: "Devstral 2",437            contextWindow: 262_144, maxOutputTokens: nil,438            capabilities: ModelCapabilities(tools: true, jsonMode: true),439            pricing: ModelPricing(inputPerMTok: 0.40, outputPerMTok: 2.00),440            parameterSupport: .openAIDefault,441            isLegacy: true442        ),443        AIModel(444            id: "open-mistral-nemo", provider: .mistral, displayName: "Mistral Nemo",445            contextWindow: 131_072, maxOutputTokens: nil,446            capabilities: ModelCapabilities(tools: true, jsonMode: true),447            pricing: ModelPricing(inputPerMTok: 0.15, outputPerMTok: 0.15),448            parameterSupport: .openAIDefault,449            isLegacy: true450        ),451    ]452453    // MARK: - Google Gemini454455    static let gemini: [AIModel] = [456        AIModel(457            id: "gemini-3.6-flash", provider: .gemini, displayName: "Gemini 3.6 Flash",458            contextWindow: 1_048_576, maxOutputTokens: 65_536,459            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),460            pricing: ModelPricing(inputPerMTok: 1.50, outputPerMTok: 7.50),461            parameterSupport: ParameterSupport(reasoningEffort: true),462            isRecommended: true463        ),464        AIModel(465            id: "gemini-3.5-flash", provider: .gemini, displayName: "Gemini 3.5 Flash",466            contextWindow: 1_048_576, maxOutputTokens: 65_536,467            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),468            pricing: ModelPricing(inputPerMTok: 1.50, outputPerMTok: 9.00),469            parameterSupport: ParameterSupport(reasoningEffort: true)470        ),471        AIModel(472            id: "gemini-3.5-flash-lite", provider: .gemini, displayName: "Gemini 3.5 Flash-Lite",473            contextWindow: 1_048_576, maxOutputTokens: 65_536,474            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),475            pricing: ModelPricing(inputPerMTok: 0.30, outputPerMTok: 2.50),476            parameterSupport: ParameterSupport(reasoningEffort: true),477            isRecommended: true478        ),479        AIModel(480            id: "gemini-3.1-pro-preview", provider: .gemini, displayName: "Gemini 3.1 Pro (Preview)",481            contextWindow: 1_048_576, maxOutputTokens: 65_536,482            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),483            pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 12.00),484            parameterSupport: ParameterSupport(reasoningEffort: true),485            isRecommended: true486        ),487        AIModel(488            id: "gemini-3.1-flash-lite", provider: .gemini, displayName: "Gemini 3.1 Flash-Lite",489            contextWindow: 1_048_576, maxOutputTokens: 65_536,490            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),491            pricing: ModelPricing(inputPerMTok: 0.25, outputPerMTok: 1.50),492            parameterSupport: ParameterSupport(reasoningEffort: true)493        ),494        AIModel(495            id: "gemini-2.5-pro", provider: .gemini, displayName: "Gemini 2.5 Pro",496            contextWindow: 1_048_576, maxOutputTokens: 65_536,497            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),498            pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 10.00),499            parameterSupport: ParameterSupport(reasoningEffort: true)500        ),501        AIModel(502            id: "gemini-2.5-flash", provider: .gemini, displayName: "Gemini 2.5 Flash",503            contextWindow: 1_048_576, maxOutputTokens: 65_536,504            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),505            pricing: ModelPricing(inputPerMTok: 0.30, outputPerMTok: 2.50),506            parameterSupport: ParameterSupport(reasoningEffort: true)507        ),508        AIModel(509            id: "gemini-2.5-flash-lite", provider: .gemini, displayName: "Gemini 2.5 Flash-Lite",510            contextWindow: 1_048_576, maxOutputTokens: 65_536,511            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),512            pricing: ModelPricing(inputPerMTok: 0.10, outputPerMTok: 0.40),513            parameterSupport: ParameterSupport(reasoningEffort: true)514        ),515        // Rolling aliases (auto-track the latest release; pricing varies with target)516        AIModel(517            id: "gemini-pro-latest", provider: .gemini, displayName: "Gemini Pro (Latest)",518            contextWindow: 1_048_576, maxOutputTokens: 65_536,519            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),520            pricing: nil,521            parameterSupport: ParameterSupport(reasoningEffort: true)522        ),523        AIModel(524            id: "gemini-flash-latest", provider: .gemini, displayName: "Gemini Flash (Latest)",525            contextWindow: 1_048_576, maxOutputTokens: 65_536,526            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),527            pricing: nil,528            parameterSupport: ParameterSupport(reasoningEffort: true)529        ),530        AIModel(531            id: "gemini-flash-lite-latest", provider: .gemini, displayName: "Gemini Flash-Lite (Latest)",532            contextWindow: 1_048_576, maxOutputTokens: 65_536,533            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),534            pricing: nil,535            parameterSupport: ParameterSupport(reasoningEffort: true)536        ),537        // Preview / secondary538        AIModel(539            id: "gemini-3-flash-preview", provider: .gemini, displayName: "Gemini 3 Flash (Preview)",540            contextWindow: 1_048_576, maxOutputTokens: 65_536,541            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),542            pricing: ModelPricing(inputPerMTok: 0.50, outputPerMTok: 3.00),543            parameterSupport: ParameterSupport(reasoningEffort: true)544        ),545        AIModel(546            id: "gemma-4-26b-a4b-it", provider: .gemini, displayName: "Gemma 4 26B",547            contextWindow: 262_144, maxOutputTokens: 32_768,548            capabilities: ModelCapabilities(jsonMode: true),549            pricing: nil,550            parameterSupport: ParameterSupport()551        ),552        AIModel(553            id: "gemma-4-31b-it", provider: .gemini, displayName: "Gemma 4 31B",554            contextWindow: 262_144, maxOutputTokens: 32_768,555            capabilities: ModelCapabilities(jsonMode: true),556            pricing: nil,557            parameterSupport: ParameterSupport()558        ),559    ]560561    // MARK: - Alibaba Qwen (DashScope)562563    static let qwen: [AIModel] = [564        // Flagship commercial565        AIModel(566            id: "qwen3.7-max", provider: .qwen, displayName: "Qwen3.7 Max",567            contextWindow: 1_000_000, maxOutputTokens: nil,568            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),569            pricing: ModelPricing(inputPerMTok: 2.50, outputPerMTok: 7.50),570            parameterSupport: ParameterSupport(thinkingToggle: true),571            isRecommended: true572        ),573        AIModel(574            id: "qwen3.7-plus", provider: .qwen, displayName: "Qwen3.7 Plus",575            contextWindow: 1_000_000, maxOutputTokens: 65_536,576            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),577            pricing: ModelPricing(inputPerMTok: 0.32, outputPerMTok: 1.28),578            parameterSupport: ParameterSupport(thinkingToggle: true),579            isRecommended: true580        ),581        AIModel(582            id: "qwen3.7-flash", provider: .qwen, displayName: "Qwen3.7 Flash",583            contextWindow: 1_000_000, maxOutputTokens: 65_536,584            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),585            pricing: ModelPricing(inputPerMTok: 0.03, outputPerMTok: 0.13),586            parameterSupport: ParameterSupport(thinkingToggle: true),587            isRecommended: true588        ),589        AIModel(590            id: "qwen3.6-plus", provider: .qwen, displayName: "Qwen3.6 Plus",591            contextWindow: 1_000_000, maxOutputTokens: nil,592            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),593            pricing: nil,594            parameterSupport: ParameterSupport(thinkingToggle: true)595        ),596        AIModel(597            id: "qwen3.6-flash", provider: .qwen, displayName: "Qwen3.6 Flash",598            contextWindow: 1_000_000, maxOutputTokens: nil,599            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),600            pricing: nil,601            parameterSupport: ParameterSupport(thinkingToggle: true)602        ),603        AIModel(604            id: "qwen3.5-plus", provider: .qwen, displayName: "Qwen3.5 Plus",605            contextWindow: 1_000_000, maxOutputTokens: nil,606            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),607            pricing: nil,608            parameterSupport: ParameterSupport(thinkingToggle: true)609        ),610        AIModel(611            id: "qwen3.5-flash", provider: .qwen, displayName: "Qwen3.5 Flash",612            contextWindow: 1_000_000, maxOutputTokens: nil,613            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),614            pricing: nil,615            parameterSupport: ParameterSupport(thinkingToggle: true)616        ),617        // Stable aliases (previous-gen commercial)618        AIModel(619            id: "qwen-max", provider: .qwen, displayName: "Qwen Max",620            contextWindow: 128_000, maxOutputTokens: nil,621            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),622            pricing: nil,623            parameterSupport: ParameterSupport(thinkingToggle: true)624        ),625        AIModel(626            id: "qwen-plus", provider: .qwen, displayName: "Qwen Plus",627            contextWindow: 1_000_000, maxOutputTokens: nil,628            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),629            pricing: nil,630            parameterSupport: ParameterSupport(thinkingToggle: true)631        ),632        AIModel(633            id: "qwen-turbo", provider: .qwen, displayName: "Qwen Turbo",634            contextWindow: 1_000_000, maxOutputTokens: nil,635            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),636            pricing: nil,637            parameterSupport: ParameterSupport(thinkingToggle: true),638            isLegacy: true639        ),640        AIModel(641            id: "qwen-flash", provider: .qwen, displayName: "Qwen Flash",642            contextWindow: 1_000_000, maxOutputTokens: nil,643            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),644            pricing: nil,645            parameterSupport: ParameterSupport(thinkingToggle: true)646        ),647        // Coder family648        AIModel(649            id: "qwen3-coder-plus", provider: .qwen, displayName: "Qwen3 Coder Plus",650            contextWindow: 1_000_000, maxOutputTokens: nil,651            capabilities: ModelCapabilities(tools: true, jsonMode: true),652            pricing: nil,653            parameterSupport: ParameterSupport()654        ),655        AIModel(656            id: "qwen3-coder-flash", provider: .qwen, displayName: "Qwen3 Coder Flash",657            contextWindow: 1_000_000, maxOutputTokens: nil,658            capabilities: ModelCapabilities(tools: true, jsonMode: true),659            pricing: nil,660            parameterSupport: ParameterSupport()661        ),662        AIModel(663            id: "qwen3-coder-next", provider: .qwen, displayName: "Qwen3 Coder Next",664            contextWindow: 262_144, maxOutputTokens: nil,665            capabilities: ModelCapabilities(tools: true, jsonMode: true),666            pricing: nil,667            parameterSupport: ParameterSupport()668        ),669        AIModel(670            id: "qwen3-coder-480b-a35b-instruct", provider: .qwen, displayName: "Qwen3 Coder 480B A35B",671            contextWindow: 262_144, maxOutputTokens: nil,672            capabilities: ModelCapabilities(tools: true, jsonMode: true),673            pricing: nil,674            parameterSupport: ParameterSupport()675        ),676        // Vision-language677        AIModel(678            id: "qwen3-vl-plus", provider: .qwen, displayName: "Qwen3 VL Plus",679            contextWindow: 1_000_000, maxOutputTokens: 65_536,680            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),681            pricing: nil,682            parameterSupport: ParameterSupport(thinkingToggle: true)683        ),684        AIModel(685            id: "qwen3-vl-flash", provider: .qwen, displayName: "Qwen3 VL Flash",686            contextWindow: 1_000_000, maxOutputTokens: 65_536,687            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),688            pricing: nil,689            parameterSupport: ParameterSupport(thinkingToggle: true)690        ),691        AIModel(692            id: "qwen3-vl-235b-a22b-instruct", provider: .qwen, displayName: "Qwen3 VL 235B Instruct",693            contextWindow: 131_072, maxOutputTokens: nil,694            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),695            pricing: nil,696            parameterSupport: ParameterSupport()697        ),698        AIModel(699            id: "qwen3-vl-235b-a22b-thinking", provider: .qwen, displayName: "Qwen3 VL 235B Thinking",700            contextWindow: 131_072, maxOutputTokens: nil,701            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),702            pricing: nil,703            parameterSupport: ParameterSupport()704        ),705        AIModel(706            id: "qvq-max", provider: .qwen, displayName: "QVQ Max",707            contextWindow: 131_072, maxOutputTokens: nil,708            capabilities: ModelCapabilities(vision: true, reasoning: true, jsonMode: true),709            pricing: nil,710            parameterSupport: ParameterSupport(requiresStreaming: true)711        ),712        // Reasoning-only713        AIModel(714            id: "qwq-plus", provider: .qwen, displayName: "QwQ Plus",715            contextWindow: 131_072, maxOutputTokens: nil,716            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),717            pricing: nil,718            parameterSupport: ParameterSupport(requiresStreaming: true)719        ),720        // Open-weights Qwen hosted on DashScope721        AIModel(722            id: "qwen3.5-397b-a17b", provider: .qwen, displayName: "Qwen3.5 397B A17B",723            contextWindow: 262_144, maxOutputTokens: nil,724            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),725            pricing: nil,726            parameterSupport: ParameterSupport(thinkingToggle: true)727        ),728        AIModel(729            id: "qwen3.5-122b-a10b", provider: .qwen, displayName: "Qwen3.5 122B A10B",730            contextWindow: 262_144, maxOutputTokens: nil,731            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),732            pricing: nil,733            parameterSupport: ParameterSupport(thinkingToggle: true)734        ),735        AIModel(736            id: "qwen3.5-35b-a3b", provider: .qwen, displayName: "Qwen3.5 35B A3B",737            contextWindow: 262_144, maxOutputTokens: nil,738            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),739            pricing: nil,740            parameterSupport: ParameterSupport(thinkingToggle: true)741        ),742        AIModel(743            id: "qwen3-235b-a22b-instruct-2507", provider: .qwen, displayName: "Qwen3 235B Instruct 2507",744            contextWindow: 262_144, maxOutputTokens: nil,745            capabilities: ModelCapabilities(tools: true, jsonMode: true),746            pricing: nil,747            parameterSupport: ParameterSupport()748        ),749        AIModel(750            id: "qwen3-235b-a22b-thinking-2507", provider: .qwen, displayName: "Qwen3 235B Thinking 2507",751            contextWindow: 262_144, maxOutputTokens: nil,752            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),753            pricing: nil,754            parameterSupport: ParameterSupport()755        ),756        AIModel(757            id: "qwen3-next-80b-a3b-instruct", provider: .qwen, displayName: "Qwen3 Next 80B Instruct",758            contextWindow: 262_144, maxOutputTokens: nil,759            capabilities: ModelCapabilities(tools: true, jsonMode: true),760            pricing: nil,761            parameterSupport: ParameterSupport()762        ),763        AIModel(764            id: "qwen3-next-80b-a3b-thinking", provider: .qwen, displayName: "Qwen3 Next 80B Thinking",765            contextWindow: 262_144, maxOutputTokens: nil,766            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),767            pricing: nil,768            parameterSupport: ParameterSupport()769        ),770        // Third-party models hosted on DashScope771        AIModel(772            id: "deepseek-v4-pro", provider: .qwen, displayName: "DeepSeek V4 Pro (DashScope)",773            contextWindow: 1_000_000, maxOutputTokens: nil,774            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),775            pricing: nil,776            parameterSupport: ParameterSupport(thinkingToggle: true)777        ),778        AIModel(779            id: "deepseek-v4-flash", provider: .qwen, displayName: "DeepSeek V4 Flash (DashScope)",780            contextWindow: 1_000_000, maxOutputTokens: nil,781            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),782            pricing: nil,783            parameterSupport: ParameterSupport(thinkingToggle: true)784        ),785        AIModel(786            id: "glm-5.2", provider: .qwen, displayName: "GLM 5.2 (DashScope)",787            contextWindow: 198_000, maxOutputTokens: nil,788            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),789            pricing: nil,790            parameterSupport: ParameterSupport(thinkingToggle: true)791        ),792        AIModel(793            id: "kimi-k2.7-code", provider: .qwen, displayName: "Kimi K2.7 Code (DashScope)",794            contextWindow: 262_144, maxOutputTokens: nil,795            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),796            pricing: nil,797            parameterSupport: ParameterSupport(thinkingToggle: true)798        ),799    ]800801    // MARK: - DeepSeek802803    static let deepseek: [AIModel] = [804        AIModel(805            id: "deepseek-v4-flash", provider: .deepseek, displayName: "DeepSeek V4 Flash",806            contextWindow: 1_000_000, maxOutputTokens: 384_000,807            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),808            pricing: ModelPricing(inputPerMTok: 0.14, outputPerMTok: 0.28),809            parameterSupport: ParameterSupport(reasoningEffort: true, thinkingToggle: true),810            isRecommended: true811        ),812        AIModel(813            id: "deepseek-v4-pro", provider: .deepseek, displayName: "DeepSeek V4 Pro",814            contextWindow: 1_000_000, maxOutputTokens: 384_000,815            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),816            pricing: ModelPricing(inputPerMTok: 0.435, outputPerMTok: 0.87),817            parameterSupport: ParameterSupport(reasoningEffort: true, thinkingToggle: true),818            isRecommended: true819        ),820    ]821822    // MARK: - Kimi (Moonshot AI)823824    static let kimi: [AIModel] = [825        AIModel(826            id: "kimi-k3", provider: .kimi, displayName: "Kimi K3",827            contextWindow: 1_048_576, maxOutputTokens: 131_072,828            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),829            pricing: ModelPricing(inputPerMTok: 3.00, outputPerMTok: 15.00),830            // Thinking always on with preserved thinking; depth via reasoning_effort.831            parameterSupport: ParameterSupport(temperature: false, topP: false, usesMaxCompletionTokens: true, reasoningEffort: true),832            isRecommended: true833        ),834        AIModel(835            id: "kimi-k2.7-code", provider: .kimi, displayName: "Kimi K2.7 Code",836            contextWindow: 262_144, maxOutputTokens: nil,837            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),838            pricing: ModelPricing(inputPerMTok: 0.95, outputPerMTok: 4.00),839            parameterSupport: ParameterSupport(temperature: false, topP: false, usesMaxCompletionTokens: true),840            isRecommended: true841        ),842        AIModel(843            id: "kimi-k2.7-code-highspeed", provider: .kimi, displayName: "Kimi K2.7 Code Highspeed",844            contextWindow: 262_144, maxOutputTokens: nil,845            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),846            pricing: ModelPricing(inputPerMTok: 1.90, outputPerMTok: 8.00),847            parameterSupport: ParameterSupport(temperature: false, topP: false, usesMaxCompletionTokens: true)848        ),849        AIModel(850            id: "kimi-k2.6", provider: .kimi, displayName: "Kimi K2.6",851            contextWindow: 262_144, maxOutputTokens: nil,852            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),853            pricing: ModelPricing(inputPerMTok: 0.95, outputPerMTok: 4.00),854            parameterSupport: ParameterSupport(temperature: false, topP: false, usesMaxCompletionTokens: true, thinkingToggle: true)855        ),856        AIModel(857            id: "kimi-k2.5", provider: .kimi, displayName: "Kimi K2.5",858            contextWindow: 262_144, maxOutputTokens: nil,859            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),860            pricing: ModelPricing(inputPerMTok: 0.60, outputPerMTok: 3.00),861            parameterSupport: ParameterSupport(temperature: false, topP: false, usesMaxCompletionTokens: true, thinkingToggle: true)862        ),863        // Legacy moonshot-v1 "classic" series (temperature capped at 1.0)864        AIModel(865            id: "moonshot-v1-8k", provider: .kimi, displayName: "Moonshot v1 8K",866            contextWindow: 8_192, maxOutputTokens: nil,867            capabilities: ModelCapabilities(tools: true, jsonMode: true),868            pricing: ModelPricing(inputPerMTok: 0.20, outputPerMTok: 2.00),869            parameterSupport: .openAIDefault,870            isLegacy: true871        ),872        AIModel(873            id: "moonshot-v1-32k", provider: .kimi, displayName: "Moonshot v1 32K",874            contextWindow: 32_768, maxOutputTokens: nil,875            capabilities: ModelCapabilities(tools: true, jsonMode: true),876            pricing: ModelPricing(inputPerMTok: 1.00, outputPerMTok: 3.00),877            parameterSupport: .openAIDefault,878            isLegacy: true879        ),880        AIModel(881            id: "moonshot-v1-128k", provider: .kimi, displayName: "Moonshot v1 128K",882            contextWindow: 131_072, maxOutputTokens: nil,883            capabilities: ModelCapabilities(tools: true, jsonMode: true),884            pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 5.00),885            parameterSupport: .openAIDefault,886            isLegacy: true887        ),888        AIModel(889            id: "moonshot-v1-auto", provider: .kimi, displayName: "Moonshot v1 Auto",890            contextWindow: 131_072, maxOutputTokens: nil,891            capabilities: ModelCapabilities(tools: true, jsonMode: true),892            pricing: nil,893            parameterSupport: .openAIDefault,894            isLegacy: true895        ),896        AIModel(897            id: "moonshot-v1-8k-vision-preview", provider: .kimi, displayName: "Moonshot v1 8K Vision",898            contextWindow: 8_192, maxOutputTokens: nil,899            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),900            pricing: ModelPricing(inputPerMTok: 0.20, outputPerMTok: 2.00),901            parameterSupport: .openAIDefault,902            isLegacy: true903        ),904        AIModel(905            id: "moonshot-v1-32k-vision-preview", provider: .kimi, displayName: "Moonshot v1 32K Vision",906            contextWindow: 32_768, maxOutputTokens: nil,907            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),908            pricing: ModelPricing(inputPerMTok: 1.00, outputPerMTok: 3.00),909            parameterSupport: .openAIDefault,910            isLegacy: true911        ),912        AIModel(913            id: "moonshot-v1-128k-vision-preview", provider: .kimi, displayName: "Moonshot v1 128K Vision",914            contextWindow: 131_072, maxOutputTokens: nil,915            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),916            pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 5.00),917            parameterSupport: .openAIDefault,918            isLegacy: true919        ),920    ]921922    // MARK: - Perplexity923924    static let perplexity: [AIModel] = [925        AIModel(926            id: "sonar", provider: .perplexity, displayName: "Sonar",927            contextWindow: 128_000, maxOutputTokens: 128_000,928            capabilities: ModelCapabilities(jsonMode: true, citations: true),929            pricing: ModelPricing(inputPerMTok: 1.00, outputPerMTok: 1.00),930            parameterSupport: ParameterSupport(),931            isRecommended: true932        ),933        AIModel(934            id: "sonar-pro", provider: .perplexity, displayName: "Sonar Pro",935            contextWindow: 200_000, maxOutputTokens: 8_000,936            capabilities: ModelCapabilities(jsonMode: true, citations: true),937            pricing: ModelPricing(inputPerMTok: 3.00, outputPerMTok: 15.00),938            parameterSupport: ParameterSupport(),939            isRecommended: true940        ),941        AIModel(942            id: "sonar-reasoning-pro", provider: .perplexity, displayName: "Sonar Reasoning Pro",943            contextWindow: 128_000, maxOutputTokens: nil,944            capabilities: ModelCapabilities(reasoning: true, jsonMode: true, citations: true),945            pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 8.00),946            parameterSupport: ParameterSupport(reasoningEffort: true)947        ),948        AIModel(949            id: "sonar-deep-research", provider: .perplexity, displayName: "Sonar Deep Research",950            contextWindow: 128_000, maxOutputTokens: nil,951            capabilities: ModelCapabilities(reasoning: true, jsonMode: true, citations: true),952            pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 8.00),953            parameterSupport: ParameterSupport(reasoningEffort: true)954        ),955    ]956957    // MARK: - Together AI958959    static let together: [AIModel] = [960        AIModel(961            id: "moonshotai/Kimi-K3", provider: .together, displayName: "Kimi K3",962            contextWindow: 1_000_000, maxOutputTokens: nil,963            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),964            pricing: ModelPricing(inputPerMTok: 3.00, outputPerMTok: 15.00),965            parameterSupport: .openAIDefault,966            isRecommended: true967        ),968        AIModel(969            id: "moonshotai/Kimi-K2.7-Code", provider: .together, displayName: "Kimi K2.7 Code",970            contextWindow: 262_144, maxOutputTokens: nil,971            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),972            pricing: ModelPricing(inputPerMTok: 0.95, outputPerMTok: 4.00),973            parameterSupport: .openAIDefault974        ),975        AIModel(976            id: "moonshotai/Kimi-K2.6", provider: .together, displayName: "Kimi K2.6",977            contextWindow: 262_144, maxOutputTokens: nil,978            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),979            pricing: ModelPricing(inputPerMTok: 1.20, outputPerMTok: 4.50),980            parameterSupport: .openAIDefault981        ),982        AIModel(983            id: "deepseek-ai/DeepSeek-V4-Pro", provider: .together, displayName: "DeepSeek V4 Pro",984            contextWindow: 512_000, maxOutputTokens: nil,985            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),986            pricing: ModelPricing(inputPerMTok: 1.74, outputPerMTok: 3.48),987            parameterSupport: .openAIDefault,988            isRecommended: true989        ),990        AIModel(991            id: "zai-org/GLM-5.2", provider: .together, displayName: "GLM 5.2",992            contextWindow: 512_000, maxOutputTokens: nil,993            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),994            pricing: ModelPricing(inputPerMTok: 1.40, outputPerMTok: 4.40),995            parameterSupport: .openAIDefault996        ),997        AIModel(998            id: "Qwen/Qwen3.7-Max", provider: .together, displayName: "Qwen3.7 Max",999            contextWindow: 1_000_000, maxOutputTokens: nil,1000            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1001            pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 3.75),1002            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, requiresStreaming: true)1003        ),1004        AIModel(1005            id: "Qwen/Qwen3.7-Plus", provider: .together, displayName: "Qwen3.7 Plus",1006            contextWindow: 1_000_000, maxOutputTokens: nil,1007            capabilities: ModelCapabilities(tools: true, jsonMode: true),1008            pricing: ModelPricing(inputPerMTok: 0.32, outputPerMTok: 1.28),1009            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, requiresStreaming: true)1010        ),1011        AIModel(1012            id: "Qwen/Qwen3.6-Plus", provider: .together, displayName: "Qwen3.6 Plus",1013            contextWindow: 1_000_000, maxOutputTokens: nil,1014            capabilities: ModelCapabilities(tools: true, jsonMode: true),1015            pricing: ModelPricing(inputPerMTok: 0.50, outputPerMTok: 3.00),1016            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, requiresStreaming: true)1017        ),1018        AIModel(1019            id: "Qwen/Qwen3.5-9B", provider: .together, displayName: "Qwen3.5 9B",1020            contextWindow: 262_144, maxOutputTokens: nil,1021            capabilities: ModelCapabilities(tools: true, jsonMode: true),1022            pricing: ModelPricing(inputPerMTok: 0.17, outputPerMTok: 0.25),1023            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, requiresStreaming: true)1024        ),1025        AIModel(1026            id: "meta-llama/Llama-3.3-70B-Instruct-Turbo", provider: .together, displayName: "Llama 3.3 70B Turbo",1027            contextWindow: 131_072, maxOutputTokens: nil,1028            capabilities: ModelCapabilities(tools: true, jsonMode: true),1029            pricing: ModelPricing(inputPerMTok: 1.04, outputPerMTok: 1.04),1030            parameterSupport: .openAIDefault1031        ),1032        AIModel(1033            id: "openai/gpt-oss-120b", provider: .together, displayName: "GPT-OSS 120B",1034            contextWindow: 131_072, maxOutputTokens: nil,1035            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1036            pricing: ModelPricing(inputPerMTok: 0.15, outputPerMTok: 0.60),1037            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, reasoningEffort: true),1038            isRecommended: true1039        ),1040        AIModel(1041            id: "openai/gpt-oss-20b", provider: .together, displayName: "GPT-OSS 20B",1042            contextWindow: 131_072, maxOutputTokens: nil,1043            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1044            pricing: ModelPricing(inputPerMTok: 0.05, outputPerMTok: 0.20),1045            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, reasoningEffort: true)1046        ),1047        AIModel(1048            id: "nvidia/nemotron-3-ultra-550b-a55b", provider: .together, displayName: "Nemotron 3 Ultra 550B",1049            contextWindow: 512_288, maxOutputTokens: nil,1050            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1051            pricing: ModelPricing(inputPerMTok: 0.60, outputPerMTok: 3.60),1052            parameterSupport: .openAIDefault1053        ),1054        AIModel(1055            id: "MiniMaxAI/MiniMax-M3", provider: .together, displayName: "MiniMax M3",1056            contextWindow: 524_288, maxOutputTokens: nil,1057            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1058            pricing: ModelPricing(inputPerMTok: 0.30, outputPerMTok: 1.20),1059            parameterSupport: .openAIDefault1060        ),1061        AIModel(1062            // vision disabled 2026-07-30: Together's endpoint accepts image1063            // input but streams an empty answer (verified live) — text only.1064            id: "google/gemma-4-31B-it", provider: .together, displayName: "Gemma 4 31B",1065            contextWindow: 262_144, maxOutputTokens: nil,1066            capabilities: ModelCapabilities(vision: false, tools: true, jsonMode: true),1067            pricing: ModelPricing(inputPerMTok: 0.39, outputPerMTok: 0.97),1068            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, requiresStreaming: true)1069        ),1070        AIModel(1071            id: "thinkingmachines/Inkling", provider: .together, displayName: "Inkling",1072            contextWindow: 524_288, maxOutputTokens: nil,1073            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1074            pricing: ModelPricing(inputPerMTok: 1.00, outputPerMTok: 4.05),1075            parameterSupport: .openAIDefault1076        ),1077    ]10781079    // MARK: - DeepInfra10801081    static let deepinfra: [AIModel] = [1082        // Proxied frontier models (Claude / Gemini under DeepInfra billing)1083        AIModel(1084            id: "anthropic/claude-fable-5", provider: .deepinfra, displayName: "Claude Fable 5",1085            contextWindow: 1_000_000, maxOutputTokens: nil,1086            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),1087            pricing: ModelPricing(inputPerMTok: 10.00, outputPerMTok: 50.00),1088            parameterSupport: ParameterSupport()1089        ),1090        AIModel(1091            id: "anthropic/claude-opus-5", provider: .deepinfra, displayName: "Claude Opus 5",1092            contextWindow: 1_000_000, maxOutputTokens: nil,1093            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),1094            pricing: ModelPricing(inputPerMTok: 5.00, outputPerMTok: 25.00),1095            parameterSupport: ParameterSupport()1096        ),1097        AIModel(1098            id: "anthropic/claude-sonnet-5", provider: .deepinfra, displayName: "Claude Sonnet 5",1099            contextWindow: 1_000_000, maxOutputTokens: nil,1100            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),1101            pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 10.00),1102            parameterSupport: ParameterSupport()1103        ),1104        AIModel(1105            id: "anthropic/claude-opus-4-8", provider: .deepinfra, displayName: "Claude Opus 4.8",1106            contextWindow: 1_000_000, maxOutputTokens: nil,1107            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),1108            pricing: ModelPricing(inputPerMTok: 5.00, outputPerMTok: 25.00),1109            parameterSupport: ParameterSupport()1110        ),1111        AIModel(1112            id: "anthropic/claude-haiku-4-5", provider: .deepinfra, displayName: "Claude Haiku 4.5",1113            contextWindow: 200_000, maxOutputTokens: nil,1114            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),1115            pricing: ModelPricing(inputPerMTok: 1.00, outputPerMTok: 5.00),1116            parameterSupport: ParameterSupport()1117        ),1118        AIModel(1119            id: "google/gemini-3.1-pro", provider: .deepinfra, displayName: "Gemini 3.1 Pro",1120            contextWindow: 1_000_000, maxOutputTokens: nil,1121            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),1122            pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 12.00),1123            parameterSupport: ParameterSupport()1124        ),1125        AIModel(1126            id: "google/gemini-3.5-flash", provider: .deepinfra, displayName: "Gemini 3.5 Flash",1127            contextWindow: 1_000_000, maxOutputTokens: nil,1128            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),1129            pricing: ModelPricing(inputPerMTok: 1.50, outputPerMTok: 9.00),1130            parameterSupport: ParameterSupport()1131        ),1132        AIModel(1133            id: "google/gemini-3.1-flash-lite", provider: .deepinfra, displayName: "Gemini 3.1 Flash-Lite",1134            contextWindow: 1_000_000, maxOutputTokens: nil,1135            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),1136            pricing: ModelPricing(inputPerMTok: 0.25, outputPerMTok: 1.50),1137            parameterSupport: ParameterSupport()1138        ),1139        AIModel(1140            id: "google/gemini-2.5-pro", provider: .deepinfra, displayName: "Gemini 2.5 Pro",1141            contextWindow: 1_000_000, maxOutputTokens: nil,1142            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),1143            pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 10.00),1144            parameterSupport: ParameterSupport()1145        ),1146        AIModel(1147            id: "google/gemini-2.5-flash", provider: .deepinfra, displayName: "Gemini 2.5 Flash",1148            contextWindow: 1_000_000, maxOutputTokens: nil,1149            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),1150            pricing: ModelPricing(inputPerMTok: 0.30, outputPerMTok: 2.50),1151            parameterSupport: ParameterSupport()1152        ),1153        // Open-weight chat models1154        AIModel(1155            id: "deepseek-ai/DeepSeek-V4-Pro", provider: .deepinfra, displayName: "DeepSeek V4 Pro",1156            contextWindow: 1_048_576, maxOutputTokens: nil,1157            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1158            pricing: ModelPricing(inputPerMTok: 1.30, outputPerMTok: 2.60),1159            parameterSupport: .openAIDefault,1160            isRecommended: true1161        ),1162        AIModel(1163            id: "deepseek-ai/DeepSeek-V4-Flash", provider: .deepinfra, displayName: "DeepSeek V4 Flash",1164            contextWindow: 1_048_576, maxOutputTokens: nil,1165            capabilities: ModelCapabilities(tools: true, jsonMode: true),1166            pricing: ModelPricing(inputPerMTok: 0.09, outputPerMTok: 0.18),1167            parameterSupport: .openAIDefault,1168            isRecommended: true1169        ),1170        AIModel(1171            id: "deepseek-ai/DeepSeek-V3.1", provider: .deepinfra, displayName: "DeepSeek V3.1",1172            contextWindow: 163_840, maxOutputTokens: nil,1173            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1174            pricing: ModelPricing(inputPerMTok: 0.25, outputPerMTok: 0.95),1175            parameterSupport: .openAIDefault1176        ),1177        AIModel(1178            id: "deepseek-ai/DeepSeek-R1-0528", provider: .deepinfra, displayName: "DeepSeek R1 0528",1179            contextWindow: 163_840, maxOutputTokens: nil,1180            capabilities: ModelCapabilities(reasoning: true),1181            pricing: ModelPricing(inputPerMTok: 0.50, outputPerMTok: 2.15),1182            parameterSupport: .openAIDefault1183        ),1184        AIModel(1185            id: "moonshotai/Kimi-K2.7-Code", provider: .deepinfra, displayName: "Kimi K2.7 Code",1186            contextWindow: 262_144, maxOutputTokens: nil,1187            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1188            pricing: ModelPricing(inputPerMTok: 0.74, outputPerMTok: 3.50),1189            parameterSupport: .openAIDefault1190        ),1191        AIModel(1192            id: "moonshotai/Kimi-K2.6", provider: .deepinfra, displayName: "Kimi K2.6",1193            contextWindow: 262_144, maxOutputTokens: nil,1194            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1195            pricing: ModelPricing(inputPerMTok: 0.75, outputPerMTok: 3.50),1196            parameterSupport: .openAIDefault1197        ),1198        AIModel(1199            id: "moonshotai/Kimi-K2.5", provider: .deepinfra, displayName: "Kimi K2.5",1200            contextWindow: 262_144, maxOutputTokens: nil,1201            capabilities: ModelCapabilities(tools: true, jsonMode: true),1202            pricing: ModelPricing(inputPerMTok: 0.45, outputPerMTok: 2.25),1203            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, requiresStreaming: true)1204        ),1205        AIModel(1206            id: "zai-org/GLM-5.2", provider: .deepinfra, displayName: "GLM 5.2",1207            contextWindow: 1_048_576, maxOutputTokens: nil,1208            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1209            pricing: ModelPricing(inputPerMTok: 0.75, outputPerMTok: 2.40),1210            parameterSupport: .openAIDefault,1211            isRecommended: true1212        ),1213        AIModel(1214            id: "zai-org/GLM-4.7", provider: .deepinfra, displayName: "GLM 4.7",1215            contextWindow: 202_752, maxOutputTokens: nil,1216            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1217            pricing: ModelPricing(inputPerMTok: 0.40, outputPerMTok: 1.75),1218            parameterSupport: .openAIDefault1219        ),1220        AIModel(1221            id: "Qwen/Qwen3.7-Max", provider: .deepinfra, displayName: "Qwen3.7 Max",1222            contextWindow: 256_000, maxOutputTokens: nil,1223            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1224            pricing: ModelPricing(inputPerMTok: 2.50, outputPerMTok: 7.50),1225            parameterSupport: .openAIDefault1226        ),1227        AIModel(1228            id: "Qwen/Qwen3.5-397B-A17B", provider: .deepinfra, displayName: "Qwen3.5 397B A17B",1229            contextWindow: 262_144, maxOutputTokens: nil,1230            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1231            pricing: ModelPricing(inputPerMTok: 0.45, outputPerMTok: 3.00),1232            parameterSupport: .openAIDefault1233        ),1234        AIModel(1235            id: "Qwen/Qwen3-235B-A22B-Instruct-2507", provider: .deepinfra, displayName: "Qwen3 235B Instruct 2507",1236            contextWindow: 262_144, maxOutputTokens: nil,1237            capabilities: ModelCapabilities(tools: true, jsonMode: true),1238            pricing: ModelPricing(inputPerMTok: 0.09, outputPerMTok: 0.55),1239            parameterSupport: .openAIDefault1240        ),1241        AIModel(1242            id: "Qwen/Qwen3-235B-A22B-Thinking-2507", provider: .deepinfra, displayName: "Qwen3 235B Thinking 2507",1243            contextWindow: 262_144, maxOutputTokens: nil,1244            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1245            pricing: ModelPricing(inputPerMTok: 0.23, outputPerMTok: 2.30),1246            parameterSupport: .openAIDefault1247        ),1248        AIModel(1249            id: "Qwen/Qwen3-Coder-480B-A35B-Instruct-Turbo", provider: .deepinfra, displayName: "Qwen3 Coder 480B Turbo",1250            contextWindow: 262_144, maxOutputTokens: nil,1251            capabilities: ModelCapabilities(tools: true, jsonMode: true),1252            pricing: ModelPricing(inputPerMTok: 0.30, outputPerMTok: 1.00),1253            parameterSupport: .openAIDefault1254        ),1255        AIModel(1256            id: "Qwen/Qwen3-VL-235B-A22B-Instruct", provider: .deepinfra, displayName: "Qwen3 VL 235B",1257            contextWindow: 262_144, maxOutputTokens: nil,1258            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),1259            pricing: ModelPricing(inputPerMTok: 0.20, outputPerMTok: 0.88),1260            parameterSupport: .openAIDefault1261        ),1262        AIModel(1263            id: "meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8", provider: .deepinfra, displayName: "Llama 4 Maverick",1264            contextWindow: 1_048_576, maxOutputTokens: nil,1265            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),1266            pricing: ModelPricing(inputPerMTok: 0.20, outputPerMTok: 0.80),1267            parameterSupport: .openAIDefault1268        ),1269        AIModel(1270            id: "meta-llama/Llama-4-Scout-17B-16E-Instruct", provider: .deepinfra, displayName: "Llama 4 Scout",1271            contextWindow: 327_680, maxOutputTokens: nil,1272            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),1273            pricing: ModelPricing(inputPerMTok: 0.10, outputPerMTok: 0.30),1274            parameterSupport: .openAIDefault1275        ),1276        AIModel(1277            id: "meta-llama/Llama-3.3-70B-Instruct-Turbo", provider: .deepinfra, displayName: "Llama 3.3 70B Turbo",1278            contextWindow: 131_072, maxOutputTokens: nil,1279            capabilities: ModelCapabilities(tools: true, jsonMode: true),1280            pricing: ModelPricing(inputPerMTok: 0.10, outputPerMTok: 0.32),1281            parameterSupport: .openAIDefault1282        ),1283        AIModel(1284            id: "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", provider: .deepinfra, displayName: "Llama 3.1 8B Turbo",1285            contextWindow: 131_072, maxOutputTokens: nil,1286            capabilities: ModelCapabilities(tools: true, jsonMode: true),1287            pricing: ModelPricing(inputPerMTok: 0.02, outputPerMTok: 0.04),1288            parameterSupport: .openAIDefault1289        ),1290        AIModel(1291            id: "openai/gpt-oss-120b", provider: .deepinfra, displayName: "GPT-OSS 120B",1292            contextWindow: 131_072, maxOutputTokens: nil,1293            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1294            pricing: ModelPricing(inputPerMTok: 0.037, outputPerMTok: 0.17),1295            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, reasoningEffort: true),1296            isRecommended: true1297        ),1298        AIModel(1299            id: "openai/gpt-oss-20b", provider: .deepinfra, displayName: "GPT-OSS 20B",1300            contextWindow: 131_072, maxOutputTokens: nil,1301            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1302            pricing: ModelPricing(inputPerMTok: 0.03, outputPerMTok: 0.14),1303            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, reasoningEffort: true)1304        ),1305        AIModel(1306            id: "MiniMaxAI/MiniMax-M3", provider: .deepinfra, displayName: "MiniMax M3",1307            contextWindow: 524_288, maxOutputTokens: nil,1308            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1309            pricing: ModelPricing(inputPerMTok: 0.30, outputPerMTok: 1.20),1310            parameterSupport: .openAIDefault1311        ),1312        AIModel(1313            id: "nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B", provider: .deepinfra, displayName: "Nemotron 3 Ultra 550B",1314            contextWindow: 262_144, maxOutputTokens: nil,1315            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1316            pricing: ModelPricing(inputPerMTok: 0.50, outputPerMTok: 2.20),1317            parameterSupport: .openAIDefault1318        ),1319        AIModel(1320            id: "mistralai/Mistral-Small-3.2-24B-Instruct-2506", provider: .deepinfra, displayName: "Mistral Small 3.2 24B",1321            contextWindow: 128_000, maxOutputTokens: nil,1322            capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true),1323            pricing: ModelPricing(inputPerMTok: 0.075, outputPerMTok: 0.20),1324            parameterSupport: .openAIDefault1325        ),1326        // google/gemma-4-31B-it removed 2026-07-30: endpoint hangs (60s+, zero1327        // bytes) on chat completions — see docs/PROVIDERS.md Phase 7 amendments.1328    ]13291330    // MARK: - Cerebras13311332    static let cerebras: [AIModel] = [1333        AIModel(1334            id: "gpt-oss-120b", provider: .cerebras, displayName: "GPT-OSS 120B",1335            contextWindow: 131_072, maxOutputTokens: 40_000,1336            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1337            pricing: ModelPricing(inputPerMTok: 0.35, outputPerMTok: 0.75),1338            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, usesMaxCompletionTokens: true, reasoningEffort: true),1339            isRecommended: true1340        ),1341        AIModel(1342            id: "gemma-4-31b", provider: .cerebras, displayName: "Gemma 4 31B",1343            contextWindow: 131_072, maxOutputTokens: 40_000,1344            capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true),1345            pricing: ModelPricing(inputPerMTok: 0.99, outputPerMTok: 1.49),1346            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, usesMaxCompletionTokens: true, reasoningEffort: true)1347        ),1348        AIModel(1349            id: "zai-glm-4.7", provider: .cerebras, displayName: "GLM 4.7",1350            contextWindow: 131_072, maxOutputTokens: 40_000,1351            capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true),1352            pricing: ModelPricing(inputPerMTok: 2.25, outputPerMTok: 2.75),1353            parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, usesMaxCompletionTokens: true, reasoningEffort: true),1354            // Scheduled for discontinuation on 2026-08-17.1355            isLegacy: true1356        ),1357    ]13581359    // MARK: - All providers13601361    static let all: [AIModel] =1362        openai + anthropic + xai + mistral + gemini + qwen +1363        deepseek + kimi + perplexity + together + deepinfra + cerebras1364}1365