// model-attribution: turn a raw model id into a short, friendly label for the // per-message model chip (e.g. "claude-sonnet-4-6" → "Sonnet 4.6", // "qwen3.6-35b-a3b-mxfp4" → "Qwen3.6 35B"). Strips provider prefixes and maps // the common families; falls back to the cleaned id so unknown models still // read. Returns null for empty/absent input so the caller can skip the chip. export function shortenModelName(model: string | null | undefined): string | null { if (!model) return null; let m = model.trim(); if (!m) return null; // opencode / provider-prefixed ids: "llama-swap/qwen…", "anthropic/claude…". const slash = m.lastIndexOf('/'); if (slash >= 0) m = m.slice(slash + 1); // claude-{opus,sonnet,haiku}-X-Y[-date] → "Opus X.Y". const claude = /^claude-(opus|sonnet|haiku)-(\d+)-(\d+)/i.exec(m); if (claude) { const tier = claude[1]!.charAt(0).toUpperCase() + claude[1]!.slice(1).toLowerCase(); return `${tier} ${claude[2]}.${claude[3]}`; } // qwen3.6-35b-a3b-… → "Qwen3.6 35B". const qwen = /^qwen([\d.]+)-(\d+)b/i.exec(m); if (qwen) return `Qwen${qwen[1]} ${qwen[2]}B`; // gpt-4o, gpt-5-… → "GPT-4o" / "GPT-5". const gpt = /^gpt-([\w.-]+)/i.exec(m); if (gpt) return `GPT-${gpt[1]}`; // Fallback: keep the id readable, cap the length for the chip. return m.length > 26 ? `${m.slice(0, 25)}…` : m; }