mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-13 21:33:32 +08:00
155 lines
4.9 KiB
Python
155 lines
4.9 KiB
Python
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
from enum import Enum
|
|
|
|
|
|
class Color(str, Enum):
|
|
RESET = "\033[0m"
|
|
BOLD = "\033[1m"
|
|
GREEN = "\033[92m"
|
|
YELLOW = "\033[93m"
|
|
BLUE = "\033[94m"
|
|
CYAN = "\033[96m"
|
|
|
|
|
|
def print_banner() -> None:
|
|
banner = f"""{Color.CYAN}
|
|
╔═══════════════════════════════════════════╗
|
|
║ LLM Provider Selector ║
|
|
║ Provider-agnostic AI interactions ║
|
|
╚═══════════════════════════════════════════╝{Color.RESET}"""
|
|
print(banner)
|
|
|
|
|
|
def print_providers(providers: list[tuple[str, str]]) -> None:
|
|
print(f"\n{Color.BOLD}Available Providers:{Color.RESET}\n")
|
|
for i, (name, desc) in enumerate(providers, 1):
|
|
print(f" {Color.GREEN}{i}{Color.RESET}. {Color.BOLD}{name}{Color.RESET} - {desc}")
|
|
|
|
|
|
def select_provider(providers: list[tuple[str, str]]) -> str | None:
|
|
if not providers:
|
|
print("No providers available.")
|
|
return None
|
|
|
|
print_providers(providers)
|
|
|
|
while True:
|
|
try:
|
|
choice = input(f"\n{Color.YELLOW}Select provider (1-{len(providers)}): {Color.RESET}").strip()
|
|
if not choice:
|
|
return None
|
|
idx = int(choice) - 1
|
|
if 0 <= idx < len(providers):
|
|
return providers[idx][0]
|
|
print(f"{Color.YELLOW}Invalid selection. Try again.{Color.RESET}")
|
|
except ValueError:
|
|
print(f"{Color.YELLOW}Please enter a number.{Color.RESET}")
|
|
|
|
|
|
def select_model(models: list[tuple[str, str]]) -> str | None:
|
|
if not models:
|
|
print("No models available.")
|
|
return None
|
|
|
|
print(f"\n{Color.BOLD}Available Models:{Color.RESET}\n")
|
|
for i, (name, desc) in enumerate(models, 1):
|
|
print(f" {Color.GREEN}{i}{Color.RESET}. {Color.BOLD}{name}{Color.RESET} - {desc}")
|
|
|
|
while True:
|
|
try:
|
|
choice = input(f"\n{Color.YELLOW}Select model (1-{len(models)}): {Color.RESET}").strip()
|
|
if not choice:
|
|
return None
|
|
idx = int(choice) - 1
|
|
if 0 <= idx < len(models):
|
|
return models[idx][0]
|
|
print(f"{Color.YELLOW}Invalid selection. Try again.{Color.RESET}")
|
|
except ValueError:
|
|
print(f"{Color.YELLOW}Please enter a number.{Color.RESET}")
|
|
|
|
|
|
def save_config(provider: str, model: str, persist: bool = False) -> None:
|
|
config = f"LLM_PROVIDER={provider}\nLLM_MODEL={model}\n"
|
|
env_file = ".llm.env"
|
|
|
|
with open(env_file, "w") as f:
|
|
f.write(config)
|
|
|
|
print(f"\n{Color.GREEN}✓{Color.RESET} Config saved to {Color.CYAN}{env_file}{Color.RESET}")
|
|
|
|
if persist:
|
|
os.environ["LLM_PROVIDER"] = provider
|
|
os.environ["LLM_MODEL"] = model
|
|
print(f"{Color.GREEN}✓{Color.RESET} Config loaded to current session")
|
|
|
|
|
|
def interactive_select(
|
|
providers: list[tuple[str, str]] | None = None,
|
|
models_per_provider: dict[str, list[tuple[str, str]]] | None = None,
|
|
persist: bool = False,
|
|
) -> tuple[str, str] | None:
|
|
print_banner()
|
|
|
|
if providers is None:
|
|
providers = [
|
|
("claude", "Anthropic Claude ( Sonnet, Opus, Haiku)"),
|
|
("openai", "OpenAI GPT (4o, 4o-mini, 3.5-turbo)"),
|
|
("ollama", "Local Ollama models"),
|
|
]
|
|
|
|
if models_per_provider is None:
|
|
models_per_provider = {
|
|
"claude": [
|
|
("claude-opus-4-5", "Claude Opus 4.5 - Most capable"),
|
|
("claude-sonnet-4-7", "Claude Sonnet 4.7 - Balanced"),
|
|
("claude-haiku-4-7", "Claude Haiku 4.7 - Fast"),
|
|
],
|
|
"openai": [
|
|
("gpt-4o", "GPT-4o - Most capable"),
|
|
("gpt-4o-mini", "GPT-4o-mini - Fast & affordable"),
|
|
("gpt-4-turbo", "GPT-4 Turbo - Legacy powerful"),
|
|
("gpt-3.5-turbo", "GPT-3.5 - Legacy fast"),
|
|
],
|
|
"ollama": [
|
|
("llama3.2", "Llama 3.2 - General purpose"),
|
|
("mistral", "Mistral - Fast & efficient"),
|
|
("codellama", "CodeLlama - Code specialized"),
|
|
],
|
|
}
|
|
|
|
provider = select_provider(providers)
|
|
if not provider:
|
|
return None
|
|
|
|
models = models_per_provider.get(provider, [])
|
|
model = select_model(models)
|
|
if not model:
|
|
return None
|
|
|
|
print(f"\n{Color.GREEN}Selected: {Color.BOLD}{provider}{Color.RESET} / {Color.BOLD}{model}{Color.RESET}")
|
|
|
|
save_config(provider, model, persist)
|
|
|
|
return (provider, model)
|
|
|
|
|
|
def main() -> None:
|
|
result = interactive_select(persist=True)
|
|
|
|
if result:
|
|
print(f"\n{Color.GREEN}Ready to use!{Color.RESET}")
|
|
print(f" export LLM_PROVIDER={result[0]}")
|
|
print(f" export LLM_MODEL={result[1]}")
|
|
else:
|
|
print("\nSelection cancelled.")
|
|
sys.exit(0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|