From 4ae71968fa2fba039c6f1fc72304b6bc8757c814 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Sat, 29 Nov 2025 16:08:05 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20feat:=20display=20mux=20gateway?= =?UTF-8?q?=20models=20with=20provider=20icon=20and=20suffix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add mux.svg icon (black/white M logo matching other provider styles) - Parse mux-gateway:provider/model format to extract inner provider - Show dual icons: mux icon + inner provider icon (e.g., Anthropic) - Append "(mux gateway)" suffix to display name - Model name formatting uses existing formatModelDisplayName() Example: mux-gateway:anthropic/claude-opus-4-5 displays as: [mux] [anthropic] Opus 4.5 (mux gateway) --- src/browser/assets/icons/mux.svg | 1 + .../components/Messages/ModelDisplay.tsx | 84 ++++++++++++++----- 2 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 src/browser/assets/icons/mux.svg diff --git a/src/browser/assets/icons/mux.svg b/src/browser/assets/icons/mux.svg new file mode 100644 index 000000000..bad35b38d --- /dev/null +++ b/src/browser/assets/icons/mux.svg @@ -0,0 +1 @@ + diff --git a/src/browser/components/Messages/ModelDisplay.tsx b/src/browser/components/Messages/ModelDisplay.tsx index d19412ab4..50f99f548 100644 --- a/src/browser/components/Messages/ModelDisplay.tsx +++ b/src/browser/components/Messages/ModelDisplay.tsx @@ -2,6 +2,7 @@ import React from "react"; import AnthropicIcon from "@/browser/assets/icons/anthropic.svg?react"; import OpenAIIcon from "@/browser/assets/icons/openai.svg?react"; import AWSIcon from "@/browser/assets/icons/aws.svg?react"; +import MuxIcon from "@/browser/assets/icons/mux.svg?react"; import { TooltipWrapper, Tooltip } from "@/browser/components/Tooltip"; import { formatModelDisplayName } from "@/common/utils/ai/modelDisplay"; @@ -11,46 +12,83 @@ interface ModelDisplayProps { showTooltip?: boolean; } +/** + * Parse a model string into provider and model name. + * Handles mux-gateway format: "mux-gateway:inner-provider/model-name" + * Returns: { provider, modelName, isMuxGateway, innerProvider } + */ +function parseModelString(modelString: string): { + provider: string; + modelName: string; + isMuxGateway: boolean; + innerProvider: string; +} { + const [provider, rest] = modelString.includes(":") + ? modelString.split(":", 2) + : ["", modelString]; + + // Handle mux-gateway format: mux-gateway:anthropic/claude-sonnet-4-5 + if (provider === "mux-gateway" && rest.includes("/")) { + const [innerProvider, modelName] = rest.split("/", 2); + return { provider, modelName, isMuxGateway: true, innerProvider }; + } + + return { provider, modelName: rest, isMuxGateway: false, innerProvider: "" }; +} + +/** Get icon component for a provider name */ +function getProviderIcon(provider: string): React.ReactNode { + switch (provider) { + case "anthropic": + return ; + case "openai": + return ; + case "bedrock": + return ; + case "mux-gateway": + return ; + default: + return null; + } +} + /** * Display a model name with its provider icon. * Supports format "provider:model-name" (e.g., "anthropic:claude-sonnet-4-5") + * Also supports mux-gateway: "mux-gateway:anthropic/claude-sonnet-4-5" + * -> Shows mux icon + inner provider icon + model name + "(mux gateway)" * * Uses standard inline layout for natural text alignment. * Icon is 1em (matches font size) with vertical-align: middle. */ export const ModelDisplay: React.FC = ({ modelString, showTooltip = true }) => { - const [provider, modelName] = modelString.includes(":") - ? modelString.split(":", 2) - : ["", modelString]; + const { provider, modelName, isMuxGateway, innerProvider } = parseModelString(modelString); - // Map provider names to their icons - const getProviderIcon = () => { - switch (provider) { - case "anthropic": - return ; - case "openai": - return ; - case "bedrock": - return ; - default: - return null; - } - }; - - const providerIcon = getProviderIcon(); + // For mux-gateway, show the inner provider's icon (the model's actual provider) + const providerIcon = isMuxGateway ? getProviderIcon(innerProvider) : getProviderIcon(provider); + const muxIcon = isMuxGateway ? getProviderIcon("mux-gateway") : null; const displayName = formatModelDisplayName(modelName); + const suffix = isMuxGateway ? " (mux gateway)" : ""; + + const iconClass = + "mr-[0.3em] inline-block h-[1.1em] w-[1.1em] align-[-0.19em] [&_svg]:block [&_svg]:h-full [&_svg]:w-full [&_svg_.st0]:fill-current [&_svg_circle]:!fill-current [&_svg_path]:!fill-current [&_svg_rect]:!fill-current"; const content = ( + {muxIcon && ( + + {muxIcon} + + )} {providerIcon && ( - + {providerIcon} )} - {displayName} + + {displayName} + {suffix} + );