import logging
import re
from datetime import date
from functools import cache

import litellm

from bulkllm.rate_limiter import RateLimiter
from bulkllm.schema import LLMConfig

logger = logging.getLogger(__name__)

default_max_tokens = None

default_temperature = 1

DEFAULT_SYSTEM_PROMPT = ""
default_models = []

# Mapping of model families to the family that supersedes them.  Families
# appearing as keys here are considered obsolete and excluded from the
# "current" model group.
FAMILY_SUCCESSORS: dict[str, str] = {
    "gemini/gemini-1.5-flash": "gemini/gemini-2.0-flash",
    "gemini/gemini-1.5-pro": "gemini/gemini-2.0-pro",
    "gemini/gemini-2.0-flash-lite": "gemini/gemini-2.5-flash-lite",
    "gemini/gemini-2.0-flash": "gemini/gemini-2.5-flash",
    "gemini/gemini-2.5-flash-preview": "gemini/gemini-2.5-flash",
    "anthropic/claude-3-haiku": "anthropic/claude-3.5-haiku",
    "anthropic/claude-3-sonnet": "anthropic/claude-3.5-sonnet",
    "anthropic/claude-3.5-sonnet": "anthropic/claude-3.7-sonnet",
    "anthropic/claude-3.7-sonnet": "anthropic/claude-sonnet",
    "anthropic/claude-3-opus": "anthropic/claude-opus",
    "meta-llama/llama-3.3-70b-instruct": "meta-llama/llama-4",
    "xai/grok": "xai/grok-2",
    "xai/grok-2": "xai/grok-3",
    "xai/grok-3": "xai/grok-4",
    "openai/gpt-4": "openai/gpt-4o",
    "openai/gpt-4-turbo": "openai/gpt-4o",
    # "openai/gpt-4o": "openai/gpt-4.1",
    "openai/gpt-3.5-turbo": "openai/gpt-4o",
    "openai/gpt-4.5": "openai/gpt-4.1",
    "openai/o1": "openai/o3",
    "openai/o1-mini": "openai/o3-mini",
    "openai/o1-pro": "openai/o3-pro",
    "openai/o3-mini": "openai/o4-mini",
}


openai_configs = [
    LLMConfig(
        slug="openai-o4-mini-low-20250416",
        display_name="o4-mini (Low) 20250416",
        company_name="OpenAI",
        litellm_model_name="openai/o4-mini-2025-04-16",
        llm_family="openai/o4-mini",
        temperature=1,
        max_completion_tokens=8000 - 1,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        reasoning_effort="low",
        release_date=date(2025, 4, 16),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="openai-o4-mini-medium-20250416",
        display_name="o4-mini (Medium) 20250416",
        company_name="OpenAI",
        litellm_model_name="openai/o4-mini-2025-04-16",
        llm_family="openai/o4-mini",
        temperature=1,
        max_completion_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        reasoning_effort="medium",
        release_date=date(2025, 4, 16),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="openai-o4-mini-20250416-high",
        display_name="o4-mini (High) 20250416",
        company_name="OpenAI",
        litellm_model_name="openai/o4-mini-2025-04-16",
        llm_family="openai/o4-mini",
        temperature=1,
        max_completion_tokens=8000 - 2,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        reasoning_effort="high",
        release_date=date(2025, 4, 16),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="openai-o3-mini-low-20250131",
        display_name="o3-mini (Low) 20250131",
        company_name="OpenAI",
        litellm_model_name="openai/o3-mini-2025-01-31",
        llm_family="openai/o3-mini",
        temperature=1,
        max_tokens=8000 - 1,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        reasoning_effort="low",
        release_date=date(2025, 1, 31),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="openai-o3-mini-medium-20250131",
        display_name="o3-mini (Medium) 20250131",
        company_name="OpenAI",
        litellm_model_name="openai/o3-mini-2025-01-31",
        llm_family="openai/o3-mini",
        temperature=1,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        reasoning_effort="medium",
        release_date=date(2025, 1, 31),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="openai-o3-mini-high-20250131",
        display_name="o3-mini (High) 20250131",
        company_name="OpenAI",
        litellm_model_name="openai/o3-mini-2025-01-31",
        llm_family="openai/o3-mini",
        temperature=1,
        max_tokens=8000 - 2,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        reasoning_effort="high",
        release_date=date(2025, 1, 31),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="openai-gpt-4.1-20250414",
        display_name="GPT-4.1 20250414",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4.1-2025-04-14",
        llm_family="openai/gpt-4.1",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 4, 14),
    ),
    LLMConfig(
        slug="openai-gpt-4.1-mini-20250414",
        display_name="GPT-4.1 Mini 20250414",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4.1-mini-2025-04-14",
        llm_family="openai/gpt-4.1-mini",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 4, 14),
    ),
    LLMConfig(
        slug="openai-gpt-4.1-nano-20250414",
        display_name="GPT-4.1 Nano 20250414",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4.1-nano-2025-04-14",
        llm_family="openai/gpt-4.1-nano",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 4, 14),
    ),
    LLMConfig(
        slug="openai-gpt-4o-20240513",
        display_name="GPT-4o 20240513",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4o-2024-05-13",
        llm_family="openai/gpt-4o",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 5, 13),
    ),
    LLMConfig(
        slug="openai-gpt-4o-20240806",
        display_name="GPT-4o 20240806",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4o-2024-08-06",
        llm_family="openai/gpt-4o",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 8, 6),
    ),
    LLMConfig(
        slug="openai-gpt-4o-20241120",
        display_name="GPT-4o 20241120",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4o-2024-11-20",
        llm_family="openai/gpt-4o",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 11, 20),
    ),
    LLMConfig(
        slug="openai-gpt-4o-mini-20240718",
        display_name="GPT-4o mini 20240718",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4o-mini-2024-07-18",
        llm_family="openai/gpt-4o-mini",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 7, 18),
    ),
    LLMConfig(
        slug="openai-gpt-3.5-turbo-20230125",
        display_name="GPT-3.5 Turbo 20230125",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-3.5-turbo-0125",
        llm_family="openai/gpt-3.5-turbo",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2023, 1, 25),
    ),
    LLMConfig(
        slug="openai-gpt-3.5-turbo-20231106",
        display_name="GPT-3.5 Turbo 20231106",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-3.5-turbo-1106",
        llm_family="openai/gpt-3.5-turbo",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2023, 11, 6),
    ),
    # LLMConfig(
    #     slug="openai-babbage-002",
    #     display_name="Babbage 002",
    #     company_name="OpenAI",
    #     litellm_model_name="openai/babbage-002",
    #     llm_family="openai/babbage",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=None,
    # ),
    LLMConfig(
        slug="openai-chatgpt-4o-latest",
        display_name="ChatGPT-4o Latest",
        company_name="OpenAI",
        litellm_model_name="openai/chatgpt-4o-latest",
        llm_family="openai/chatgpt-4o-latest",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 5, 13),
    ),
    LLMConfig(
        slug="openai-codex-mini-latest",
        display_name="codex-mini-latest",
        company_name="OpenAI",
        litellm_model_name="openai/codex-mini-latest",
        llm_family="openai/codex-mini-latest",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 5, 16),
    ),
    # LLMConfig(
    #     slug="openai-davinci-002",
    #     display_name="Davinci 002",
    #     company_name="OpenAI",
    #     litellm_model_name="openai/davinci-002",
    #     llm_family="openai/davinci",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2022, 3, 15),
    # ),
    # LLMConfig(
    #     slug="openai-gpt-3.5-0301",
    #     display_name="Gpt 3.5 0301",
    #     company_name="OpenAI",
    #     litellm_model_name="openai/gpt-3.5-0301",
    #     llm_family="openai/gpt-3.5",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2023, 3, 1),
    # ),
    # LLMConfig(
    #     slug="openai-gpt-3.5-turbo-0613",
    #     display_name="Gpt 3.5 Turbo 0613",
    #     company_name="OpenAI",
    #     litellm_model_name="openai/gpt-3.5-turbo-0613",
    #     llm_family="openai/gpt-3.5-turbo",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2023, 6, 13),
    # ),
    LLMConfig(
        slug="openai-gpt-3.5-turbo-16k-20230613",
        display_name="GPT-3.5 Turbo 16K 0613",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-3.5-turbo-16k-0613",
        llm_family="openai/gpt-3.5-turbo-16k",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2023, 6, 13),
        is_deprecated=date(2024, 9, 13),
    ),
    # LLMConfig(
    #     slug="openai-gpt-3.5-turbo-instruct",
    #     display_name="Gpt 3.5 Turbo Instruct",
    #     company_name="OpenAI",
    #     litellm_model_name="openai/gpt-3.5-turbo-instruct",
    #     llm_family="openai/gpt-3.5-turbo-instruct",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=None,
    # ),
    LLMConfig(
        slug="openai-gpt-4-20240125",
        display_name="GPT-4 20240125",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4-0125-preview",
        llm_family="openai/gpt-4",
        temperature=default_temperature,
        max_tokens=4096,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 1, 25),
    ),
    LLMConfig(
        slug="openai-gpt-4-20230314",
        display_name="GPT-4 20230314",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4-0314",
        llm_family="openai/gpt-4",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2023, 3, 14),
        is_deprecated=date(2024, 6, 13),
    ),
    LLMConfig(
        slug="openai-gpt-4-20230613",
        display_name="GPT-4 20230613",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4-0613",
        llm_family="openai/gpt-4",
        temperature=default_temperature,
        max_tokens=4096,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2023, 6, 13),
    ),
    LLMConfig(
        slug="openai-gpt-4-20231106",
        display_name="GPT-4 20231106",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4-1106-preview",
        llm_family="openai/gpt-4",
        temperature=default_temperature,
        max_tokens=4096,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2023, 11, 6),
    ),
    # LLMConfig(
    #     slug="openai-gpt-4-1106-vision-preview",
    #     display_name="GPT-4 Vision 20231106",
    #     company_name="OpenAI",
    #     litellm_model_name="openai/gpt-4-1106-vision-preview",
    #     llm_family="openai/gpt-4-vision",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2023, 11, 6),
    # ),
    LLMConfig(
        slug="openai-gpt-4-turbo-20240409",
        display_name="GPT-4 Turbo 20240409",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4-turbo-2024-04-09",
        llm_family="openai/gpt-4-turbo",
        temperature=default_temperature,
        max_tokens=4096,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 4, 9),
    ),
    LLMConfig(
        slug="openai-gpt-4.5-20250227",
        display_name="GPT-4.5 20250227",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-4.5-preview-2025-02-27",
        llm_family="openai/gpt-4.5",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 2, 27),
        is_deprecated=date(2025, 7, 16),
    ),
    # LLMConfig(
    #     slug="openai-gpt-4o-mini-search-preview-2025-03-11",
    #     display_name="GPT-4o mini Search 20250311",
    #     company_name="OpenAI",
    #     litellm_model_name="openai/gpt-4o-mini-search-preview-2025-03-11",
    #     llm_family="openai/gpt-4o-mini-search",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 3, 11),
    # ),
    # LLMConfig(
    #     slug="openai-gpt-4o-search-preview-2025-03-11",
    #     display_name="GPT-4o Search 20250311",
    #     company_name="OpenAI",
    #     litellm_model_name="openai/gpt-4o-search-preview-2025-03-11",
    #     llm_family="openai/gpt-4o-search",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 3, 11),
    # ),
    LLMConfig(
        slug="openai-o1-20241217",
        display_name="o1 20241217",
        company_name="OpenAI",
        litellm_model_name="openai/o1-2024-12-17",
        llm_family="openai/o1",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 12, 17),
    ),
    LLMConfig(
        slug="openai-o1-mini-20240912",
        display_name="o1-mini 20240912",
        company_name="OpenAI",
        litellm_model_name="openai/o1-mini-2024-09-12",
        llm_family="openai/o1-mini",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 9, 12),
    ),
    LLMConfig(
        slug="openai-o1-20240912",
        display_name="o1 20240912",
        company_name="OpenAI",
        litellm_model_name="openai/o1-preview-2024-09-12",
        llm_family="openai/o1",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 9, 12),
    ),
    LLMConfig(
        slug="openai-o1-pro-20250319",
        display_name="o1-pro 20250319",
        company_name="OpenAI",
        litellm_model_name="openai/o1-pro-2025-03-19",
        llm_family="openai/o1-pro",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 3, 19),
    ),
    LLMConfig(
        slug="openai-o3-20250416",
        display_name="o3 20250416",
        company_name="OpenAI",
        litellm_model_name="openai/o3-2025-04-16",
        llm_family="openai/o3",
        temperature=1,
        max_completion_tokens=8000 - 2,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        reasoning_effort="high",
        release_date=date(2025, 4, 16),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="openai-o3-pro-20250610",
        display_name="o3-pro 20250610",
        company_name="OpenAI",
        litellm_model_name="openai/o3-pro-2025-06-10",
        llm_family="openai/o3-pro",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        reasoning_effort="high",
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 6, 10),
        timeout=600,
    ),
    # GPT-5 family
    LLMConfig(
        slug="openai-gpt-5-20250807",
        display_name="GPT-5 20250807",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-5-2025-08-07",
        llm_family="openai/gpt-5",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 8, 7),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="openai-gpt-5-mini-20250807",
        display_name="GPT-5 Mini 20250807",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-5-mini-2025-08-07",
        llm_family="openai/gpt-5-mini",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 8, 7),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="openai-gpt-5-nano-20250807",
        display_name="GPT-5 Nano 20250807",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-5-nano-2025-08-07",
        llm_family="openai/gpt-5-nano",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 8, 7),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="openai-gpt-5-chat-latest",
        display_name="GPT-5 Chat Latest",
        company_name="OpenAI",
        litellm_model_name="openai/gpt-5-chat-latest",
        llm_family="openai/gpt-5-chat-latest",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 8, 7),
        is_reasoning=True,
    ),
]
default_models.extend(openai_configs)

openrouter_configs = [
    LLMConfig(
        slug="openrouter-deepseek-r1",
        display_name="DeepSeek R1 20250120",
        company_name="DeepSeek",
        litellm_model_name="openrouter/deepseek/deepseek-r1",
        llm_family="deepseek/deepseek-r1",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        is_reasoning=True,
        release_date=date(2025, 1, 20),
    ),
    LLMConfig(
        slug="openrouter-deepseek-r1-20250528",
        display_name="DeepSeek R1 20250528",
        company_name="DeepSeek",
        litellm_model_name="openrouter/deepseek/deepseek-r1-0528",
        llm_family="deepseek/deepseek-r1",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        is_reasoning=True,
        release_date=date(2025, 5, 28),
    ),
    LLMConfig(
        slug="openrouter-deepseek-chat-v3-20250324",
        display_name="DeepSeek V3 20250324",
        company_name="DeepSeek",
        litellm_model_name="openrouter/deepseek/deepseek-chat-v3-0324",
        llm_family="deepseek/deepseek-chat",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 3, 24),
    ),
    LLMConfig(
        slug="openrouter-deepseek-chat",
        display_name="DeepSeek V3 20241226",
        company_name="DeepSeek",
        litellm_model_name="openrouter/deepseek/deepseek-chat",
        llm_family="deepseek/deepseek-chat",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 12, 26),
    ),
    LLMConfig(
        slug="openrouter-amazon-nova-lite-v1",
        display_name="Nova Lite V1",
        company_name="Amazon",
        litellm_model_name="openrouter/amazon/nova-lite-v1",
        llm_family="amazon/nova-lite",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 12, 3),
    ),
    LLMConfig(
        slug="openrouter-amazon-nova-micro-v1",
        display_name="Nova Micro V1",
        company_name="Amazon",
        litellm_model_name="openrouter/amazon/nova-micro-v1",
        llm_family="amazon/nova-micro",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 12, 3),
    ),
    LLMConfig(
        slug="openrouter-amazon-nova-pro-v1",
        display_name="Nova Pro V1",
        company_name="Amazon",
        litellm_model_name="openrouter/amazon/nova-pro-v1",
        llm_family="amazon/nova-pro",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 12, 3),
    ),
    LLMConfig(
        slug="amazon-nova-premier-v1",
        display_name="Nova Premier V1",
        company_name="Amazon",
        litellm_model_name="bedrock/us.amazon.nova-premier-v1:0",
        llm_family="amazon/nova-premier",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 4, 30),
    ),
    LLMConfig(
        slug="openrouter-qwen-qwq-32b",
        display_name="Qwen QwQ-32B",
        company_name="Alibaba",
        litellm_model_name="openrouter/qwen/qwq-32b",
        llm_family="qwen/qwq-32b",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        is_reasoning=True,
        release_date=date(2025, 3, 6),
    ),
    LLMConfig(
        slug="openrouter-qwen-max-20250128",
        display_name="Qwen 2.5 Max 20250128",
        company_name="Alibaba",
        litellm_model_name="openrouter/qwen/qwen-max",
        llm_family="qwen/qwen-max",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 1, 28),
    ),
    LLMConfig(
        slug="openrouter-qwen3-235b-a22b-20250428",
        display_name="Qwen 3 235B A22B-20250428",
        company_name="Alibaba",
        litellm_model_name="openrouter/qwen/qwen3-235b-a22b",
        llm_family="qwen/qwen3-235b-a22b",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 4, 28),
    ),
    LLMConfig(
        slug="openrouter-qwen3-235b-a22b-20250721",
        display_name="Qwen 3 235B A22B-20250721",
        company_name="Alibaba",
        litellm_model_name="openrouter/qwen/qwen3-235b-a22b-07-25",
        llm_family="qwen/qwen3-235b-a22b",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 7, 21),
    ),
    LLMConfig(
        slug="openrouter-llama-3.3-70b-instruct",
        display_name="Llama 3.3 70b Instruct",
        company_name="Meta",
        litellm_model_name="openrouter/meta-llama/llama-3.3-70b-instruct",
        llm_family="meta-llama/llama-3.3-70b-instruct",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 12, 6),
    ),
    LLMConfig(
        slug="openrouter-mistralai-mistral-large-2411",
        display_name="Mistral Large 20241118",
        company_name="MistralAI",
        litellm_model_name="openrouter/mistralai/mistral-large-2411",
        llm_family="mistralai/mistral-large",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 11, 18),
    ),
    LLMConfig(
        slug="openrouter-mistralai-mistral-small-3.1-24b-instruct",
        display_name="Mistral Small 3.1 24b Instruct 20250317",
        company_name="MistralAI",
        litellm_model_name="openrouter/mistralai/mistral-small-3.1-24b-instruct",
        llm_family="mistralai/mistral-small-3.1-24b-instruct",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 3, 17),
    ),
    # LLMConfig(
    #     slug="mistral-small-20250620",
    #     display_name="Mistral Small 20250620",
    #     company_name="MistralAI",
    #     litellm_model_name="mistral/mistral-small-latest",
    #     llm_family="mistral/mistral-small",
    #     temperature=default_temperature,
    #     max_tokens=default_max_tokens,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 6, 20),
    # ),
    LLMConfig(
        slug="openrouter-google-gemma-3-27b-it",
        display_name="Gemma 3 27b IT",
        company_name="Google",
        litellm_model_name="openrouter/google/gemma-3-27b-it",
        llm_family="google/gemma-3-27b-it",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 3, 12),
    ),
    LLMConfig(
        slug="openrouter-meta-llama-4-maverick",
        display_name="Llama 4 Maverick",
        company_name="Meta",
        litellm_model_name="openrouter/meta-llama/llama-4-maverick",
        llm_family="meta-llama/llama-4",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 4, 5),
    ),
    LLMConfig(
        slug="openrouter-meta-llama-4-scout",
        display_name="Llama 4 Scout",
        company_name="Meta",
        litellm_model_name="openrouter/meta-llama/llama-4-scout",
        llm_family="meta-llama/llama-4",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 4, 5),
    ),
    # moonshotai/kimi-k2
    LLMConfig(
        slug="openrouter-moonshotai-kimi-k2",
        display_name="Kimi K2",
        company_name="MoonshotAI",
        litellm_model_name="openrouter/moonshotai/kimi-k2",
        llm_family="moonshotai/kimi-k2",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 7, 11),
    ),
    LLMConfig(
        slug="openrouter-openai-gpt-oss-20b",
        display_name="gpt-oss 20B",
        company_name="OpenAI",
        litellm_model_name="openrouter/openai/gpt-oss-20b",
        llm_family="openai/gpt-oss-20b",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 8, 5),
    ),
    LLMConfig(
        slug="openrouter-openai-gpt-oss-120b",
        display_name="gpt-oss 120B",
        company_name="OpenAI",
        litellm_model_name="openrouter/openai/gpt-oss-120b",
        llm_family="openai/gpt-oss-120b",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 8, 5),
    ),
]
default_models.extend(openrouter_configs)

anthropic_configs = [
    LLMConfig(
        slug="anthropic-claude-3.7-sonnet-20250219",
        display_name="Claude 3.7 Sonnet 20250219",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-3-7-sonnet-20250219",
        llm_family="anthropic/claude-3.7-sonnet",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 2, 19),
    ),
    LLMConfig(
        slug="anthropic-claude-3.7-sonnet-20250219-thinking",
        display_name="Claude 3.7 Sonnet Thinking 20250219",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-3-7-sonnet-20250219",
        llm_family="anthropic/claude-3.7-sonnet",
        temperature=default_temperature,
        max_tokens=8000 + 1,
        thinking_config={"type": "enabled", "budget_tokens": 4096},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 2, 19),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="anthropic-claude-3.5-sonnet-20241022",
        display_name="Claude 3.5 Sonnet 20241022",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-3-5-sonnet-20241022",
        llm_family="anthropic/claude-3.5-sonnet",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 10, 22),
    ),
    LLMConfig(
        slug="anthropic-claude-3.5-sonnet-20240620",
        display_name="Claude 3.5 Sonnet 20240620",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-3-5-sonnet-20240620",
        llm_family="anthropic/claude-3.5-sonnet",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 6, 20),
    ),
    LLMConfig(
        slug="anthropic-claude-3-5-haiku-20241022",
        display_name="Claude 3.5 Haiku 20241022",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-3-5-haiku-20241022",
        llm_family="anthropic/claude-3.5-haiku",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 10, 22),
    ),
    # LLMConfig(
    #     slug="anthropic-claude-2.0",
    #     display_name="Claude 2.0",
    #     company_name="Anthropic",
    #     litellm_model_name="anthropic/claude-2.0",
    #     llm_family="anthropic/claude-2.0",
    #     temperature=default_temperature,
    #     max_tokens=4096,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2023, 7, 11),
    # ),
    # LLMConfig(
    #     slug="anthropic-claude-2.1",
    #     display_name="Claude 2.1",
    #     company_name="Anthropic",
    #     litellm_model_name="anthropic/claude-2.1",
    #     llm_family="anthropic/claude-2.1",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2023, 11, 21),
    # ),
    LLMConfig(
        slug="anthropic-claude-3-haiku-20240307",
        display_name="Claude Haiku 3",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-3-haiku-20240307",
        llm_family="anthropic/claude-3-haiku",
        temperature=default_temperature,
        max_tokens=4096,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 3, 7),
    ),
    LLMConfig(
        slug="anthropic-claude-3-opus-20240229",
        display_name="Claude Opus 3",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-3-opus-20240229",
        llm_family="anthropic/claude-3-opus",
        temperature=default_temperature,
        max_tokens=4096,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 2, 29),
    ),
    LLMConfig(
        slug="anthropic-claude-3-sonnet-20240229",
        display_name="Claude Sonnet 3",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-3-sonnet-20240229",
        llm_family="anthropic/claude-3-sonnet",
        temperature=default_temperature,
        max_tokens=4096,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 2, 29),
    ),
    LLMConfig(
        slug="anthropic-claude-opus-4-20250514",
        display_name="Claude Opus 4 20250514",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-opus-4-20250514",
        llm_family="anthropic/claude-4-opus",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 5, 14),
    ),
    LLMConfig(
        slug="anthropic-claude-opus-4-thinking-20250514",
        display_name="Claude Opus 4 Thinking 20250514",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-opus-4-20250514",
        llm_family="anthropic/claude-4-opus",
        temperature=default_temperature,
        max_tokens=8000 + 1,  # litellm caching issue
        thinking_config={"type": "enabled", "budget_tokens": 4096},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 5, 14),
    ),
    LLMConfig(
        slug="anthropic-claude-sonnet-4-20250514",
        display_name="Claude Sonnet 4 20250514",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-sonnet-4-20250514",
        llm_family="anthropic/claude-4-sonnet",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 5, 14),
    ),
    #        thinking_config={"type": "enabled", "budget_tokens": 4096},
    LLMConfig(
        slug="anthropic-claude-sonnet-4-thinking-20250514",
        display_name="Claude Sonnet 4 Thinking 20250514",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-sonnet-4-20250514",
        llm_family="anthropic/claude-4-sonnet",
        temperature=default_temperature,
        max_tokens=8000 + 1,  # litellm caching issue
        thinking_config={"type": "enabled", "budget_tokens": 4096},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 5, 14),
    ),
    LLMConfig(
        slug="anthropic-claude-opus-4-1-20250805",
        display_name="Claude Opus 4.1 20250805",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-opus-4-1-20250805",
        llm_family="anthropic/claude-4-opus",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={"type": "disabled"},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 8, 5),
    ),
    LLMConfig(
        slug="anthropic-claude-opus-4-1-thinking-20250805",
        display_name="Claude Opus 4.1 Thinking 20250805",
        company_name="Anthropic",
        litellm_model_name="anthropic/claude-opus-4-1-20250805",
        llm_family="anthropic/claude-4-opus",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={"type": "enabled", "budget_tokens": 4096},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 8, 5),
        is_reasoning=True,
    ),
]
default_models.extend(anthropic_configs)

gemini_configs = [
    LLMConfig(
        slug="gemini-1.5-flash-002",
        display_name="Gemini 1.5 Flash 002",
        company_name="Google",
        litellm_model_name="gemini/gemini-1.5-flash-002",
        llm_family="gemini/gemini-1.5-flash",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 9, 24),
    ),
    LLMConfig(
        slug="gemini-1.5-pro-002",
        display_name="Gemini 1.5 Pro 002",
        company_name="Google",
        litellm_model_name="gemini/gemini-1.5-pro-002",
        llm_family="gemini/gemini-1.5-pro",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 9, 24),
    ),
    LLMConfig(
        slug="gemini-2.0-flash",
        display_name="Gemini 2.0 Flash",
        company_name="Google",
        litellm_model_name="gemini/gemini-2.0-flash-001",
        llm_family="gemini/gemini-2.0-flash",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 2, 25),
    ),
    # LLMConfig(
    #     slug="gemini-1.0-pro-vision-latest",
    #     display_name="Gemini 1.0 Pro Vision",
    #     company_name="Google",
    #     litellm_model_name="gemini/gemini-1.0-pro-vision-latest",
    #     llm_family="gemini/gemini-1.0-pro-vision-latest",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2024, 2, 15),
    #     is_deprecated=True,
    # ),
    LLMConfig(
        slug="gemini-2.0-flash-lite-20250205",
        display_name="Gemini 2.0 Flash Lite 20250205",
        company_name="Google",
        litellm_model_name="gemini/gemini-2.0-flash-lite-preview-02-05",
        llm_family="gemini/gemini-2.0-flash-lite",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 2, 5),
    ),
    LLMConfig(
        slug="gemini-2.0-flash-lite-20250225",
        display_name="Gemini 2.0 Flash Lite 20250225",
        company_name="Google",
        litellm_model_name="gemini/gemini-2.0-flash-lite-001",
        llm_family="gemini/gemini-2.0-flash-lite",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 2, 25),
    ),
    LLMConfig(
        slug="gemini-2.5-flash-lite-20250617",
        display_name="Gemini 2.5 Flash Lite 20250617",
        company_name="Google",
        litellm_model_name="gemini/gemini-2.5-flash-lite-preview-06-17",
        llm_family="gemini/gemini-2.5-flash-lite",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 6, 17),
    ),
    LLMConfig(
        slug="gemini-2.5-flash-lite-thinking-20250617",
        display_name="Gemini 2.5 Flash Lite Thinking 20250617",
        company_name="Google",
        litellm_model_name="gemini/gemini-2.5-flash-lite-preview-06-17",
        llm_family="gemini/gemini-2.5-flash-lite",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={"type": "enabled", "budget_tokens": 4096},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 6, 17),
    ),
    LLMConfig(
        slug="gemini-2.5-flash-20250417",
        display_name="Gemini 2.5 Flash 20250417",
        company_name="Google",
        litellm_model_name="gemini/gemini-2.5-flash-preview-04-17",
        llm_family="gemini/gemini-2.5-flash",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 4, 17),
    ),
    LLMConfig(
        slug="gemini-2.5-flash-20250617",
        display_name="Gemini 2.5 Flash 20250617",
        company_name="Google",
        litellm_model_name="gemini/gemini-2.5-flash",
        llm_family="gemini/gemini-2.5-flash",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={"type": "disabled", "budget_tokens": 0},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 6, 17),
        is_reasoning=False,
    ),
    LLMConfig(
        slug="gemini-2.5-flash-thinking-20250617",
        display_name="Gemini 2.5 Flash Thinking 20250617",
        company_name="Google",
        litellm_model_name="gemini/gemini-2.5-flash",
        llm_family="gemini/gemini-2.5-flash",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={"type": "enabled", "budget_tokens": 8192},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 6, 17),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="gemini-2.5-pro-20250325",
        display_name="Gemini 2.5 Pro 20250325",
        company_name="Google",
        litellm_model_name="gemini/gemini-2.5-pro-preview-03-25",
        llm_family="gemini/gemini-2.5-pro",
        temperature=default_temperature,
        max_tokens=default_max_tokens,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 3, 25),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="gemini-2.5-pro-20250506",
        display_name="Gemini 2.5 Pro 20250506",
        company_name="Google",
        litellm_model_name="gemini/gemini-2.5-pro-preview-05-06",
        llm_family="gemini/gemini-2.5-pro",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 5, 6),
        is_reasoning=True,
    ),
    LLMConfig(
        slug="gemini-2.5-pro-20250605",
        display_name="Gemini 2.5 Pro 20250605",
        company_name="Google",
        litellm_model_name="gemini/gemini-2.5-pro-preview-06-05",
        llm_family="gemini/gemini-2.5-pro",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 6, 5),
        is_reasoning=True,
    ),
    # LLMConfig(
    #     slug="gemini-2.5-pro-20250617",
    #     display_name="Gemini 2.5 Pro 20250617",
    #     company_name="Google",
    #     litellm_model_name="gemini/gemini-2.5-pro",
    #     llm_family="gemini/gemini-2.5-pro",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 6, 17),
    #     is_reasoning=True,
    # ),
    LLMConfig(
        slug="openrouter-gemini-2.5-pro-20250617",
        display_name="Gemini 2.5 Pro 20250617",
        company_name="Google",
        litellm_model_name="openrouter/google/gemini-2.5-pro",
        llm_family="gemini/gemini-2.5-pro",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 6, 17),
        is_reasoning=True,
        timeout=500,
    ),
]
default_models.extend(gemini_configs)

xai_configs = [
    LLMConfig(
        slug="xai-grok-2-20241212",
        display_name="Grok 2 20241212",
        company_name="xAI",
        litellm_model_name="xai/grok-2-1212",
        llm_family="xai/grok-2",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2024, 12, 12),
    ),
    # LLMConfig(
    #     slug="xai-grok-3-20250409",
    #     display_name="Grok 3 Beta",
    #     company_name="xai",
    #     litellm_model_name="xai/grok-3-beta",
    #     llm_family="xai/grok-3",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 4, 9),
    # ),
    # LLMConfig(
    #     slug="xai-grok-3-mini-low-20250409",
    #     display_name="Grok 3 Mini Beta (low)",
    #     company_name="xai",
    #     litellm_model_name="xai/grok-3-mini-beta",
    #     llm_family="xai/grok-3-mini",
    #     temperature=default_temperature,
    #     max_tokens=32000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 4, 9),
    #     reasoning_effort="low",
    #     is_reasoning=True,
    # ),
    # LLMConfig(
    #     slug="xai-grok-3-mini-high-20250409",
    #     display_name="Grok 3 Mini Beta (high)",
    #     company_name="xai",
    #     litellm_model_name="xai/grok-3-mini-beta",
    #     llm_family="xai/grok-3-mini",
    #     temperature=default_temperature,
    #     max_tokens=32000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 4, 9),
    #     reasoning_effort="high",
    #     is_reasoning=True,
    # ),
    LLMConfig(
        slug="xai-grok-3",
        display_name="Grok 3",
        company_name="xAI",
        litellm_model_name="xai/grok-3",
        llm_family="xai/grok-3",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 2, 17),
    ),
    LLMConfig(
        slug="xai-grok-3-mini",
        display_name="Grok 3 Mini 20250217",
        company_name="xAI",
        litellm_model_name="xai/grok-3-mini",
        llm_family="xai/grok-3-mini",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 2, 17),
    ),
    LLMConfig(
        slug="xai-grok-3-mini-thinking",
        display_name="Grok 3 Mini Thinking 20250217",
        company_name="xAI",
        litellm_model_name="xai/grok-3-mini",
        llm_family="xai/grok-3-mini",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 2, 17),
        reasoning_effort="high",
        is_reasoning=True,
    ),
    LLMConfig(
        slug="xai-grok-4",
        display_name="Grok 4",
        company_name="xAI",
        litellm_model_name="xai/grok-4-0709",
        llm_family="xai/grok-4",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 7, 9),
    ),
    LLMConfig(
        slug="openrouter-xai-grok-4",
        display_name="Grok 4",
        company_name="xAI",
        litellm_model_name="openrouter/x-ai/grok-4-07-09",
        llm_family="xai/grok-4",
        temperature=default_temperature,
        max_tokens=8000,
        thinking_config={},
        system_prompt=DEFAULT_SYSTEM_PROMPT,
        release_date=date(2025, 7, 9),
        timeout=600,
    ),
]
default_models.extend(xai_configs)

mistral_configs = [
    # LLMConfig(
    #     slug="mistral-codestral-2405",
    #     display_name="Codestral 2405",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/codestral-2405",
    #     llm_family="mistral/codestral",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2024, 5, 29),
    # ),
    # LLMConfig(
    #     slug="mistral-codestral-2501",
    #     display_name="Codestral 2501",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/codestral-2501",
    #     llm_family="mistral/codestral",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 1, 13),
    # ),
    # LLMConfig(
    #     slug="mistral-devstral-small-2505",
    #     display_name="Devstral Small 2505",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/devstral-small-2505",
    #     llm_family="mistral/devstral-small",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 5, 21),
    # ),
    # LLMConfig(
    #     slug="mistral-magistral-medium-2506",
    #     display_name="Magistral Medium 2506",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/magistral-medium-2506",
    #     llm_family="mistral/magistral-medium",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 6, 10),
    # ),
    # LLMConfig(
    #     slug="mistral-magistral-small-2506",
    #     display_name="Magistral Small 2506",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/magistral-small-2506",
    #     llm_family="mistral/magistral-small",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 6, 10),
    # ),
    # LLMConfig(
    #     slug="mistral-ministral-3b-2410",
    #     display_name="Ministral 3B 2410",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/ministral-3b-2410",
    #     llm_family="mistral/ministral-3b",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2024, 10, 9),
    # ),
    # LLMConfig(
    #     slug="mistral-ministral-8b-2410",
    #     display_name="Ministral 8B 2410",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/ministral-8b-2410",
    #     llm_family="mistral/ministral-8b",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2024, 10, 9),
    # ),
    # LLMConfig(
    #     slug="mistral-mistral-large-2402",
    #     display_name="Mistral Large 2402",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/mistral-large-2402",
    #     llm_family="mistral/mistral-large",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=None,
    # ),
    # LLMConfig(
    #     slug="mistral-mistral-large-2407",
    #     display_name="Mistral Large 2407",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/mistral-large-2407",
    #     llm_family="mistral/mistral-large",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2024, 7, 24),
    # ),
    # LLMConfig(
    #     slug="mistral-mistral-large-2411",
    #     display_name="Mistral Large 2411",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/mistral-large-2411",
    #     llm_family="mistral/mistral-large",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2024, 11, 18),
    # ),
    # LLMConfig(
    #     slug="mistral-mistral-medium-2312",
    #     display_name="Mistral Medium 2312",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/mistral-medium-2312",
    #     llm_family="mistral/mistral-medium",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=None,
    # ),
    # LLMConfig(
    #     slug="mistral-mistral-medium-2505",
    #     display_name="Mistral Medium 2505",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/mistral-medium-2505",
    #     llm_family="mistral/mistral-medium",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 5, 7),
    # ),
    # LLMConfig(
    #     slug="mistral-mistral-saba-2502",
    #     display_name="Mistral Saba 2502",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/mistral-saba-2502",
    #     llm_family="mistral/mistral-saba",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 2, 17),
    # ),
    # LLMConfig(
    #     slug="mistral-mistral-small-2402",
    #     display_name="Mistral Small 2402",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/mistral-small-2402",
    #     llm_family="mistral/mistral-small",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=None,
    # ),
    # LLMConfig(
    #     slug="mistral-mistral-small-2409",
    #     display_name="Mistral Small 2409",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/mistral-small-2409",
    #     llm_family="mistral/mistral-small",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 1, 13),
    # ),
    # LLMConfig(
    #     slug="mistral-mistral-small-2501",
    #     display_name="Mistral Small 2501",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/mistral-small-2501",
    #     llm_family="mistral/mistral-small",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=None,
    # ),
    # LLMConfig(
    #     slug="mistral-mistral-small-2503",
    #     display_name="Mistral Small 2503",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/mistral-small-2503",
    #     llm_family="mistral/mistral-small",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=None,
    # ),
    # LLMConfig(
    #     slug="mistral-open-mistral-7b",
    #     display_name="Open Mistral 7B",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/open-mistral-7b",
    #     llm_family="mistral/open-mistral-7b",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=None,
    # ),
    # LLMConfig(
    #     slug="mistral-open-mistral-nemo",
    #     display_name="Open Mistral Nemo",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/open-mistral-nemo",
    #     llm_family="mistral/open-mistral-nemo",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2024, 7, 18),
    # ),
    # LLMConfig(
    #     slug="mistral-open-mixtral-8x22b",
    #     display_name="Open Mixtral 8X22B",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/open-mixtral-8x22b",
    #     llm_family="mistral/open-mixtral-8x22b",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2024, 4, 17),
    # ),
    # LLMConfig(
    #     slug="mistral-open-mixtral-8x7b",
    #     display_name="Open Mixtral 8X7B",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/open-mixtral-8x7b",
    #     llm_family="mistral/open-mixtral-8x7b",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=None,
    # ),
    # LLMConfig(
    #     slug="mistral-pixtral-12b-2409",
    #     display_name="Pixtral 12B 2409",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/pixtral-12b-2409",
    #     llm_family="mistral/pixtral-12b",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2025, 1, 13),
    # ),
    # LLMConfig(
    #     slug="mistral-pixtral-large-2411",
    #     display_name="Pixtral Large 2411",
    #     company_name="Mistral",
    #     litellm_model_name="mistral/pixtral-large-2411",
    #     llm_family="mistral/pixtral-large",
    #     temperature=default_temperature,
    #     max_tokens=8000,
    #     thinking_config={},
    #     system_prompt=DEFAULT_SYSTEM_PROMPT,
    #     release_date=date(2024, 11, 18),
    # ),
]
default_models.extend(mistral_configs)


def create_model_configs(system_prompt: str | None = "You are a helpful AI assistant."):
    """Return deep copies of default models with a custom system prompt."""
    new_configs = []
    for llm_config in default_models:
        new_config = llm_config.model_copy()
        new_config.system_prompt = system_prompt
        if new_config.is_deprecated:
            continue
        new_configs.append(new_config)
    return new_configs


@cache
def model_info():
    """Gather info for each model config."""
    from bulkllm.model_registration.main import register_models
    from bulkllm.rate_limiter import RateLimiter

    register_models()

    # Initialize rate limiter to fetch rate limits
    rate_limiter = RateLimiter()
    prompt_tokens = 1_700_000  # Fixed input tokens for all models

    # Company → colour and logo mappings used for charts / table
    company_colors = {
        "openai": "rgba(116, 170, 156, 1)",
        "anthropic": "rgb(204, 120, 92)",
        "google": "yellow",
        "gemini": "yellow",
        "vertex": "yellow",
        "deepseek": "rgba(83, 106, 245, 1)",
        "xai": "purple",
        "meta": "rgba(49, 111, 246, 1)",
        "llama": "rgba(49, 111, 246, 1)",
        "amazon": "rgba(255, 153, 0, 1)",
    }

    # Function to create a simpleicons logo URL for a company slug.
    def get_company_icon(c_slug: str) -> str:
        """Return an SVG logo URL from simpleicons CDN (falls back to generic icon)."""
        base = "https://cdn.simpleicons.org/"
        # Some company names differ from slug we want in URL
        simpleicons_overrides = {
            "openai": "openai",
            "anthropic": "anthropic",
            "google": "google",
            "gemini": "google",  # gemini not in simpleicons, use google icon
            "vertex": "googlecloud",
            "meta": "meta",
            "llama": "meta",
            "amazon": "amazon",
            "deepseek": "openrouter",  # fallback generic
            "xai": "x",
        }
        icon_slug = simpleicons_overrides.get(c_slug, c_slug)
        return f"{base}{icon_slug}/FFFFFF"

    # Default color for unknown companies
    default_color = "gray"

    model_entries: list[dict] = []

    for llm in default_models:
        completion_tokens = 4_800_000 if llm.is_reasoning else 1_800_000

        prompt_cost: float | None = None
        completion_cost: float | None = None
        total_cost: float | None = None

        try:
            prompt_cost, completion_cost = litellm.cost_per_token(
                model=llm.litellm_model_name,
                prompt_tokens=prompt_tokens,
                completion_tokens=completion_tokens,
            )
            total_cost = prompt_cost + completion_cost
        except Exception as e:  # noqa
            logger.warning("Could not calculate cost for model %s: %s", llm.litellm_model_name, e)

        # Retrieve rate limit values from RateLimiter
        model_rl = rate_limiter.get_rate_limit_for_model(llm.litellm_model_name)
        tpm = model_rl.tpm
        itpm = model_rl.itpm
        otpm = model_rl.otpm
        rpm = model_rl.rpm

        # Determine colour & icon
        company = llm.company_name.lower()
        color = company_colors.get(company, default_color)
        company_icon = get_company_icon(company)

        # Remove trailing release-date numbers from display name (6+ digit sequences)
        sanitized_name = re.sub(r"(?:\s*\(?\d{4,}\)?)+$", "", llm.display_name).strip()

        model_entries.append(
            {
                "name": sanitized_name,
                "model_id": llm.litellm_model_name,
                "company": llm.company_name,
                "company_icon": company_icon,
                "release_date": llm.release_date.isoformat() if llm.release_date else None,
                "is_reasoning": llm.is_reasoning,
                "input_tokens": prompt_tokens,
                "output_tokens": completion_tokens,
                "tpm": tpm,
                "itpm": itpm,
                "otpm": otpm,
                "rpm": rpm,
                "prompt_cost": prompt_cost,
                "completion_cost": completion_cost,
                "total_cost": total_cost,
                "color": color,
            }
        )

    # Sort by total cost (descending where available)
    model_entries.sort(key=lambda x: x["total_cost"] if x["total_cost"] is not None else -1, reverse=True)
    return model_entries


@cache
def cheap_model_configs():
    """Return LLMConfig objects whose estimated total cost is less than $1."""
    entries = model_info()
    cheap_ids = {entry["model_id"] for entry in entries if entry["total_cost"] is not None and entry["total_cost"] < 2}
    if not cheap_ids:
        return []
    configs = create_model_configs()
    configs = [config for config in configs if not config.is_deprecated]
    return [config for config in configs if config.litellm_model_name in cheap_ids]


@cache
def current_model_configs() -> list[LLMConfig]:
    """Return all configs in each family that share the latest release date and have no successor."""
    configs = create_model_configs()
    succeeded = set(FAMILY_SUCCESSORS.keys())

    # First, find the latest release date for each family
    latest_dates: dict[str, date | None] = {}
    for cfg in configs:
        if cfg.llm_family in succeeded:
            continue
        existing_date = latest_dates.get(cfg.llm_family)
        if existing_date is None or (cfg.release_date and existing_date and cfg.release_date > existing_date):
            latest_dates[cfg.llm_family] = cfg.release_date
        elif existing_date is None and cfg.release_date:
            latest_dates[cfg.llm_family] = cfg.release_date

    # Then, collect all models that have the latest release date for their family
    current_configs = []
    for cfg in configs:
        if cfg.llm_family in succeeded:
            continue
        if cfg.release_date == latest_dates.get(cfg.llm_family):
            current_configs.append(cfg)

    return current_configs


def for_benchmarking() -> list[LLMConfig]:
    """Return all configs that are not deprecated and have a rate limit."""
    configs = current_model_configs()
    excluded_for_daily_limit = {
        # "gemini/gemini-2.5-pro-preview-06-05",
    }
    excluded_for_openrouter = {"xai/grok-4-0709"}
    excluded_configs = {"openai/codex-mini-latest", "openai/chatgpt-4o-latest", "openai/o3-pro-2025-06-10"}
    configs = [config for config in configs if config.litellm_model_name not in excluded_for_daily_limit]
    configs = [config for config in configs if config.litellm_model_name not in excluded_configs]
    configs = [config for config in configs if config.litellm_model_name not in excluded_for_openrouter]
    return configs


def has_rate_limit(cfg: LLMConfig) -> bool:
    """Return True if the model has a configured rate limit."""
    limiter = RateLimiter()
    return limiter.get_rate_limit_for_model(cfg.litellm_model_name) is not limiter.default_rate_limit


def model_resolver(model_slugs: list[str]) -> list[LLMConfig]:
    """Expand slugs or groups into concrete model configurations."""
    if not model_slugs:
        return cheap_model_configs()

    configs = create_model_configs()

    model_lookup = {config.slug: [config] for config in configs}
    model_group_lookup = {
        "cheap": cheap_model_configs,
        "default": cheap_model_configs,
        "all": configs,
        "benchmarking": for_benchmarking,
        "reasoning": [config for config in configs if config.is_reasoning],
        "current": current_model_configs,
        "missing-rate-limits": [config for config in configs if not has_rate_limit(config)],
        "cheap-current": lambda: [
            cfg for cfg in cheap_model_configs() if cfg.slug in {c.slug for c in current_model_configs()}
        ],
    }
    found_configs = []
    for slug in model_slugs:
        if slug in model_lookup:
            found_configs.extend(model_lookup[slug])
        elif slug in model_group_lookup:
            val = model_group_lookup[slug]
            if callable(val):
                val = val()
            found_configs.extend(val)
        elif slug.startswith("company:"):
            # Handle company-based filtering
            company_name = slug[8:]  # Remove "company:" prefix
            company_configs = [config for config in configs if config.company_name.lower() == company_name.lower()]
            if not company_configs:
                msg = f"No models found for company: {company_name}"
                raise ValueError(msg)
            found_configs.extend(company_configs)
        else:
            msg = f"Unknown model config: {slug}"
            raise ValueError(msg)
    # deduplicate configs
    cfgs = list({cfg.slug: cfg for cfg in found_configs}.values())

    return cfgs
