import { Cpu } from "lucide-react"; function LlamaCppIcon({ size, color, label = "llama.cpp" }: { size: number; color: string; label?: string }) { return ; } export interface ProviderIconProps { provider: string; size?: "sm" | "md" | "lg"; } const sizeMap = { sm: 16, md: 20, lg: 24, }; // Anthropic "A" logo from SimpleIcons function AnthropicIcon({ size, color, label = "Anthropic" }: { size: number; color: string; label?: string }) { return ( ); } // OpenAI flower logo from Iconify/SimpleIcons function OpenAIIcon({ size, color, label = "OpenAI" }: { size: number; color: string; label?: string }) { return ( ); } // Google Gemini sparkle logo from SimpleIcons function GeminiIcon({ size, color, label = "Google Gemini" }: { size: number; color: string; label?: string }) { return ( ); } // Ollama llama head logo from SimpleIcons function OllamaIcon({ size, color, label = "Ollama" }: { size: number; color: string; label?: string }) { return ( ); } // MiniMax logo from SimpleIcons — stylized "M" grid mark function MiniMaxIcon({ size, color, label = "MiniMax" }: { size: number; color: string; label?: string }) { return ( ); } // Z.ai / Zhipu AI logo — stylized "Z" mark from brand identity function ZaiIcon({ size, color, label = "Z.ai" }: { size: number; color: string; label?: string }) { return ( ); } // Kimi / Moonshot AI logo — crescent moon mark from official Moonshot AI brand identity // Source: https://raw.githubusercontent.com/gilbarbara/logos/master/logos/moonshot-ai.svg // The moon crescent shape is derived from the official Moonshot AI logo // For a 24x24 icon, we use a simplified crescent moon path function KimiIcon({ size, color, label = "Kimi" }: { size: number; color: string; label?: string }) { return ( {/* Crescent moon from official Moonshot AI logo mark */} ); } function BedrockIcon({ size, color, label = "Amazon Bedrock" }: { size: number; color: string; label?: string }) { return ( ); } function XaiIcon({ size, color, label = "xAI" }: { size: number; color: string; label?: string }) { return ( ); } function OpencodeIcon({ size, color, label = "Opencode" }: { size: number; color: string; label?: string }) { return ( ); } function DeepSeekIcon({ size, color, label = "DeepSeek" }: { size: number; color: string; label?: string }) { return ( ); } function CloudflareIcon({ size, color, label = "Cloudflare" }: { size: number; color: string; label?: string }) { return ( ); } // Qwen / Tongyi Qianwen monogram — stylized "Q" with the tail piercing // the ring, a recognizable simplification of the official mark. function QwenIcon({ size, color, label = "Qwen" }: { size: number; color: string; label?: string }) { return ( ); } // LM Studio — rounded square frame with a stylized "LM" wordmark inside, // reminiscent of the desktop app's icon. function LMStudioIcon({ size, color, label = "LM Studio" }: { size: number; color: string; label?: string }) { return ( LM ); } // Hugging Face — the iconic smiling-face emoji used as their official // brand mark. Eyes and mouth are stamped using the surrounding contrast // token so the face remains legible on any theme background. function HuggingFaceIcon({ size, color, label = "Hugging Face" }: { size: number; color: string; label?: string }) { return ( {/* Hands flanking the face — the "hugging" part of the emoji. */} ); } // Mistral — geometric "M" simplified from the official tricolor mark. function MistralIcon({ size, color, label = "Mistral AI" }: { size: number; color: string; label?: string }) { return ( {/* Five vertical bars descending into staggered baselines, the essence of the Mistral wordmark's M. */} ); } // Azure — Microsoft Azure "A" sail mark. function AzureIcon({ size, color, label = "Azure" }: { size: number; color: string; label?: string }) { return ( ); } // Cerebras — concentric arcs forming a stylized "C", echoing the // official wafer-scale brand mark. function CerebrasIcon({ size, color, label = "Cerebras" }: { size: number; color: string; label?: string }) { return ( ); } // Groq — stylized lightning-bolt pulse, evoking their fast-inference // brand identity. function GroqIcon({ size, color, label = "Groq" }: { size: number; color: string; label?: string }) { return ( ); } // Vercel — the iconic equilateral triangle wordmark. function VercelIcon({ size, color, label = "Vercel" }: { size: number; color: string; label?: string }) { return ( ); } // Fireworks AI — burst of dots radiating from a central nucleus, a // monochrome simplification of their identity mark. function FireworksIcon({ size, color, label = "Fireworks AI" }: { size: number; color: string; label?: string }) { return ( {/* 8 outer dots arranged on a circle */} {/* 4 connecting rays from the nucleus to the cardinal dots */} ); } // OpenRouter ring mark — simplified geometric version of the OpenRouter brand symbol. function OpenRouterIcon({ size, color, label = "OpenRouter" }: { size: number; color: string; label?: string }) { return ( ); } // GitHub logo (Octocat mark) from SimpleIcons. function GitHubIcon({ size, color, label = "GitHub" }: { size: number; color: string; label?: string }) { return ( ); } // Hermes — caduceus (winged staff) mark, single-color so it adapts to theme. function HermesIcon({ size, color, label = "Hermes" }: { size: number; color: string; label?: string }) { return ( ); } // OpenClaw — pixel-art lobster (verbatim 16×16 source SVG, recolor disabled // so the iconic palette survives). function OpenClawIcon({ size, label = "OpenClaw" }: { size: number; color: string; label?: string }) { return ( ); } // Paperclip — official paperclip outline, theme-color aware. function PaperclipIcon({ size, color, label = "Paperclip" }: { size: number; color: string; label?: string }) { return ( ); } // Anthropic "A" mark composited with a small terminal "> _" badge in the // bottom-right, visually signalling "Anthropic, but via the local CLI". function ClaudeCliIcon({ size, color, label = "Anthropic — via Claude CLI" }: { size: number; color: string; label?: string }) { return ( {/* Anthropic "A" mark, slightly shrunk + shifted to leave room for the badge */} {/* Terminal badge — filled square with "> _" glyph */} ); } function DroidCliIcon({ size, color, label = "Factory AI — via Droid CLI" }: { size: number; color: string; label?: string }) { return ( ); } function CursorCliIcon({ size, color, label = "Cursor — via Cursor CLI" }: { size: number; color: string; label?: string }) { return ( ); } const providerConfig: Record< string, { component: typeof AnthropicIcon; color: string; label?: string } > = { // Branded provider colors are tokenized in app/styles.css for theme-system consistency. anthropic: { component: AnthropicIcon, color: "var(--provider-anthropic)" }, "claude-cli": { component: ClaudeCliIcon, color: "var(--provider-anthropic)", label: "Anthropic — via Claude CLI" }, "pi-claude-cli": { component: ClaudeCliIcon, color: "var(--provider-anthropic)", label: "Anthropic — via Claude CLI" }, "droid-cli": { component: DroidCliIcon, color: "var(--provider-openai)", label: "Factory AI — via Droid CLI" }, "cursor-cli": { component: CursorCliIcon, color: "var(--provider-cursor-cli)", label: "Cursor — via Cursor CLI" }, "llama-cpp": { component: LlamaCppIcon, color: "var(--provider-ollama)", label: "llama.cpp" }, "llama-server": { component: LlamaCppIcon, color: "var(--provider-ollama)", label: "llama.cpp" }, openai: { component: OpenAIIcon, color: "var(--provider-openai)" }, "openai-codex": { component: OpenAIIcon, color: "var(--provider-openai)", label: "OpenAI Codex" }, // OpenAI alias google: { component: GeminiIcon, color: "var(--provider-gemini)" }, gemini: { component: GeminiIcon, color: "var(--provider-gemini)" }, // Gemini alias family // Deprecated upstream in pi-coding-agent 0.71+, retained for legacy usage/auth history rendering. "google-antigravity": { component: GeminiIcon, color: "var(--provider-gemini)", label: "Google Gemini" }, antigravity: { component: GeminiIcon, color: "var(--provider-gemini)", label: "Google Gemini" }, "google-vertex": { component: GeminiIcon, color: "var(--provider-gemini)", label: "Google Vertex AI" }, vertex: { component: GeminiIcon, color: "var(--provider-gemini)", label: "Google Vertex AI" }, "google-cloud-code": { component: GeminiIcon, color: "var(--provider-gemini)", label: "Google Cloud Code" }, "cloud-code": { component: GeminiIcon, color: "var(--provider-gemini)", label: "Google Cloud Code" }, // Deprecated upstream in pi-coding-agent 0.71+, retained for legacy usage/auth history rendering. "google-gemini-cli": { component: GeminiIcon, color: "var(--provider-gemini)", label: "Google Gemini CLI" }, "google-generative-ai": { component: GeminiIcon, color: "var(--provider-gemini)", label: "Google Generative AI" }, // Monochrome marks use theme-aware text color for dark/light safety. ollama: { component: OllamaIcon, color: "var(--text)" }, github: { component: GitHubIcon, color: "var(--text)" }, "github-copilot": { component: GitHubIcon, color: "var(--text)", label: "GitHub Copilot" }, // OpenRouter appears in onboarding auth cards and should not fall back to CPU. openrouter: { component: OpenRouterIcon, color: "var(--provider-openrouter)" }, minimax: { component: MiniMaxIcon, color: "var(--provider-minimax)" }, "minimax-cn": { component: MiniMaxIcon, color: "var(--provider-minimax)", label: "MiniMax (CN)" }, zai: { component: ZaiIcon, color: "var(--provider-zai)" }, kimi: { component: KimiIcon, color: "var(--provider-kimi)" }, moonshot: { component: KimiIcon, color: "var(--provider-kimi)" }, // Moonshot alias "kimi-coding": { component: KimiIcon, color: "var(--provider-kimi)", label: "Kimi" }, // Kimi alias bedrock: { component: BedrockIcon, color: "var(--provider-bedrock)" }, "amazon-bedrock": { component: BedrockIcon, color: "var(--provider-bedrock)", label: "Amazon Bedrock" }, xai: { component: XaiIcon, color: "var(--text)" }, grok: { component: XaiIcon, color: "var(--text)", label: "xAI" }, opencode: { component: OpencodeIcon, color: "var(--provider-opencode)" }, "opencode-go": { component: OpencodeIcon, color: "var(--provider-opencode)", label: "Opencode (Go)" }, deepseek: { component: DeepSeekIcon, color: "var(--provider-deepseek)", label: "DeepSeek" }, "deepseek-ai": { component: DeepSeekIcon, color: "var(--provider-deepseek)", label: "DeepSeek" }, "deep-seek": { component: DeepSeekIcon, color: "var(--provider-deepseek)", label: "DeepSeek" }, cloudflare: { component: CloudflareIcon, color: "var(--provider-cloudflare)", label: "Cloudflare" }, cloudflared: { component: CloudflareIcon, color: "var(--provider-cloudflare)", label: "Cloudflare" }, qwen: { component: QwenIcon, color: "var(--provider-qwen)" }, "qwen-ai": { component: QwenIcon, color: "var(--provider-qwen)", label: "Qwen" }, "qwen-coder": { component: QwenIcon, color: "var(--provider-qwen)", label: "Qwen Coder" }, alibaba: { component: QwenIcon, color: "var(--provider-qwen)", label: "Qwen" }, tongyi: { component: QwenIcon, color: "var(--provider-qwen)", label: "Qwen" }, lmstudio: { component: LMStudioIcon, color: "var(--provider-lmstudio)", label: "LM Studio" }, "lm-studio": { component: LMStudioIcon, color: "var(--provider-lmstudio)", label: "LM Studio" }, huggingface: { component: HuggingFaceIcon, color: "var(--provider-huggingface)", label: "Hugging Face" }, "hugging-face": { component: HuggingFaceIcon, color: "var(--provider-huggingface)", label: "Hugging Face" }, hf: { component: HuggingFaceIcon, color: "var(--provider-huggingface)", label: "Hugging Face" }, mistral: { component: MistralIcon, color: "var(--provider-mistral)", label: "Mistral AI" }, "mistral-ai": { component: MistralIcon, color: "var(--provider-mistral)", label: "Mistral AI" }, azure: { component: AzureIcon, color: "var(--provider-azure)" }, "azure-openai": { component: AzureIcon, color: "var(--provider-azure)", label: "Azure OpenAI" }, "azure-openai-responses": { component: AzureIcon, color: "var(--provider-azure)", label: "Azure OpenAI" }, fireworks: { component: FireworksIcon, color: "var(--provider-fireworks)", label: "Fireworks AI" }, "fireworks-ai": { component: FireworksIcon, color: "var(--provider-fireworks)", label: "Fireworks AI" }, fireworksai: { component: FireworksIcon, color: "var(--provider-fireworks)", label: "Fireworks AI" }, cerebras: { component: CerebrasIcon, color: "var(--provider-cerebras)" }, groq: { component: GroqIcon, color: "var(--provider-groq)" }, vercel: { component: VercelIcon, color: "var(--provider-vercel)" }, "vercel-ai-gateway": { component: VercelIcon, color: "var(--provider-vercel)", label: "Vercel AI Gateway" }, // Runtime-plugin marks (Hermes / OpenClaw / Paperclip). hermes: { component: HermesIcon, color: "var(--provider-hermes)", label: "Hermes" }, "hermes-agent": { component: HermesIcon, color: "var(--provider-hermes)", label: "Hermes" }, hermesagent: { component: HermesIcon, color: "var(--provider-hermes)", label: "Hermes" }, openclaw: { component: OpenClawIcon, color: "var(--provider-openclaw)", label: "OpenClaw" }, "open-claw": { component: OpenClawIcon, color: "var(--provider-openclaw)", label: "OpenClaw" }, paperclip: { component: PaperclipIcon, color: "var(--provider-paperclip)", label: "Paperclip" }, paperclipai: { component: PaperclipIcon, color: "var(--provider-paperclip)", label: "Paperclip" }, "paperclip-ai": { component: PaperclipIcon, color: "var(--provider-paperclip)", label: "Paperclip" }, }; export function ProviderIcon({ provider, size = "sm" }: ProviderIconProps) { const normalizedProvider = provider.toLowerCase(); const config = providerConfig[normalizedProvider]; const IconComponent = config?.component; const color = config?.color ?? "var(--text-muted)"; const label = config?.label; const iconSize = sizeMap[size]; return ( {IconComponent ? ( ) : ( )} ); }