import { CHATGPT_MARK_PATH } from "../model-mark-paths"; import { modelDisplayName, modelLogoUrl, modelVendor, type ModelDisplayInput, type ModelVendor, } from "@opengeni/sdk/model-display"; import { SparklesIcon } from "lucide-react"; import { useState, type ReactNode, type SVGProps } from "react"; import { cn } from "../lib/cn"; import { ClaudeMark } from "./claude-mark"; import { GrokMark } from "./grok-mark"; /** ChatGPT / OpenAI mark (Simple Icons path), currentColor like the other marks. */ export function ChatGptMark(props: SVGProps) { return ( ); } const MARKED_VENDORS: ReadonlySet = new Set(["openai", "anthropic", "xai"]); /** True when `ModelMark` has a real maker logo for this model (not the neutral fallback). */ export function modelHasMark(model: ModelDisplayInput): boolean { const vendor = modelVendor(model); return modelLogoUrl(model) !== null || (vendor !== null && MARKED_VENDORS.has(vendor)); } /** * The catalog's maker logo, with bundled maker logos and a neutral fallback. * Makers without a configured or bundled logo get a neutral mark, so an org- and * a workspace-connected copy of one model always look the same. */ export function ModelMark(props: { model: ModelDisplayInput; className?: string | undefined; /** Shown when the maker has no bundled logo. Defaults to a neutral sparkle. */ fallback?: ReactNode; "aria-label"?: string | undefined; }) { const logoUrl = modelLogoUrl(props.model); const [failedUrl, setFailedUrl] = useState(null); const vendor = modelVendor(props.model); const className = cn("size-3.5 shrink-0", props.className); const label = props["aria-label"]; const a11y = label ? { role: "img" as const, "aria-label": label } : { "aria-hidden": true }; const mark = logoUrl && logoUrl !== failedUrl ? ( setFailedUrl(logoUrl)} /> ) : vendor === "openai" ? ( ) : vendor === "anthropic" ? ( ) : vendor === "xai" ? ( ) : props.fallback !== undefined ? ( props.fallback ) : ( ); if (mark === null) return null; return ( svg]:size-full", className)} data-model-vendor={vendor ?? "unknown"} {...a11y} > {mark} ); } /** * A model as people should see it outside model settings: the maker's mark and * the clean display name. Never a routing prefix, connection id or scope. */ export function ModelName(props: { model: ModelDisplayInput; /** Hide the maker mark for dense text-only contexts. */ mark?: boolean | undefined; className?: string | undefined; markClassName?: string | undefined; }) { const name = modelDisplayName(props.model); return ( {props.mark === false ? null : ( )} {name} ); }