FN-7801: infer xAI icon for Grok model IDs in ProviderIcon

Fix ProviderIcon so Grok model-shaped provider strings (e.g. grok-4.5, grok-cli/grok-4-fast) render the xAI brand icon instead of falling back to the generic Cpu icon.

- ProviderIcon now falls back to inferProviderIconKey(provider) when an exact providerConfig lookup misses, before defaulting to the Cpu icon
- Added a changeset (patch) documenting the fix for dashboard provider icon surfaces
- Added regression tests covering exact xAI/Grok keys, inferred Grok model-id strings, non-Grok inferred providers (e.g. gpt-5.5), and confirming unknown/empty providers still fall back to Cpu without the xAI icon

Files changed:
 .changeset/fn-7801-grok-xai-logo.md                |  7 ++++++
 packages/dashboard/app/components/ProviderIcon.tsx | 11 ++++++++-
 .../app/components/__tests__/ProviderIcon.test.tsx | 27 ++++++++++++++++++++++
 3 files changed, 44 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7801

Fusion-Task-Lineage: e81f15f6-d295-4f6d-b21f-7cf58854457f

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-10 17:07:06 -07:00
parent ea1e4fe062
commit 915c1e0152
3 changed files with 44 additions and 1 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Show the xAI logo for Grok model IDs across dashboard provider surfaces.
category: fix
dev: ProviderIcon now falls back through inferProviderIconKey before the generic CPU icon.

View File

@@ -1,5 +1,7 @@
import { Cpu } from "lucide-react";
import { inferProviderIconKey } from "../utils/providerIconKey";
function LlamaCppIcon({ size, color, label = "llama.cpp" }: { size: number; color: string; label?: string }) {
return <Cpu size={size} color={color} aria-label={label} data-testid="llama-cpp-icon" />;
}
@@ -829,7 +831,14 @@ const providerConfig: Record<
export function ProviderIcon({ provider, size = "sm" }: ProviderIconProps) {
const normalizedProvider = provider.toLowerCase();
const config = providerConfig[normalizedProvider];
const directConfig = providerConfig[normalizedProvider];
/*
FNXC:ProviderIcons 2026-07-10-00:00:
FN-7801: dashboard surfaces can pass model-id-shaped provider strings such as grok-4.5 or grok-cli/grok-4-fast, which strict providerConfig lookups miss.
Fall through to the shared inferProviderIconKey normalizer before the Cpu default so Grok/xAI and other provider families keep their brand icons, while exact keys and genuinely unknown providers retain existing behavior.
*/
const inferredConfig = directConfig ? undefined : providerConfig[inferProviderIconKey(provider)];
const config = directConfig ?? inferredConfig;
const IconComponent = config?.component;
const color = config?.color ?? "var(--text-muted)";
const label = config?.label;

View File

@@ -122,6 +122,7 @@ describe("ProviderIcon", () => {
it("renders Cpu icon as fallback for unknown providers", () => {
render(<ProviderIcon provider="unknown" />);
expect(screen.queryByTestId("xai-icon")).not.toBeInTheDocument();
// Cpu icon from lucide-react renders as an svg without our custom data-testid
const icon = screen.getByText((_, element) => {
return element?.tagName.toLowerCase() === "svg" &&
@@ -132,6 +133,7 @@ describe("ProviderIcon", () => {
it("renders Cpu icon as fallback for empty provider", () => {
render(<ProviderIcon provider="" />);
expect(screen.queryByTestId("xai-icon")).not.toBeInTheDocument();
const icon = screen.getByText((_, element) => {
return element?.tagName.toLowerCase() === "svg" &&
element?.parentElement?.getAttribute("data-provider") === "";
@@ -418,6 +420,31 @@ describe("ProviderIcon", () => {
});
// xAI provider tests
it.each(["xai", "grok", "grok-cli"])("renders xAI brand icon for exact %s provider key", (provider) => {
render(<ProviderIcon provider={provider} />);
expect(screen.getByTestId("xai-icon")).toBeInTheDocument();
});
it.each([
["grok-4.5", "grok-4.5"],
["grok-4-fast", "grok-4-fast"],
["grok-cli/grok-4-fast", "grok-cli/grok-4-fast"],
["xai-grok-4", "xai-grok-4"],
["Grok-4.5", "grok-4.5"],
])("renders xAI brand icon for inferred Grok model/provider string %s", (provider, expectedDataProvider) => {
render(<ProviderIcon provider={provider} />);
const icon = screen.getByTestId("xai-icon").parentElement;
expect(icon).toHaveStyle({ color: "var(--text)" });
expect(icon).toHaveAttribute("data-provider", expectedDataProvider);
});
it("infers non-Grok provider icons from model-shaped ids", () => {
render(<ProviderIcon provider="gpt-5.5" />);
const icon = screen.getByTestId("openai-icon").parentElement;
expect(icon).toHaveStyle({ color: "var(--provider-openai)" });
expect(icon).toHaveAttribute("data-provider", "gpt-5.5");
});
it("renders xAI brand icon for xai provider", () => {
render(<ProviderIcon provider="xai" />);
expect(screen.getByTestId("xai-icon")).toBeInTheDocument();