From 152d77cf4be941e779afbe3d8c1ec3257446c151 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Date: Sun, 12 Jul 2026 10:23:47 -0300 Subject: [PATCH] fix(dashboard): label audio/embeddings/image compatible providers by kind on ProviderCard (#6936) (#6961) ProviderCard's compatibility badge used a binary apiType ternary (responses vs everything-else -> "Chat"), so audio-transcriptions, audio-speech, images-generations and embeddings compatible providers (e.g. a locally-hosted speaches TTS/STT server) were mislabeled as "Chat". Reuse the existing KIND_LABEL map (stt/tts/image/embedding) instead of adding new i18n keys. --- .../fixes/6936-providercard-audio-badge.md | 1 + .../providers/components/ProviderCard.tsx | 14 ++- .../__tests__/providerCardAudioBadge.test.tsx | 94 +++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 changelog.d/fixes/6936-providercard-audio-badge.md create mode 100644 src/app/(dashboard)/dashboard/providers/components/__tests__/providerCardAudioBadge.test.tsx diff --git a/changelog.d/fixes/6936-providercard-audio-badge.md b/changelog.d/fixes/6936-providercard-audio-badge.md new file mode 100644 index 0000000000..6b70fb4434 --- /dev/null +++ b/changelog.d/fixes/6936-providercard-audio-badge.md @@ -0,0 +1 @@ +- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936) diff --git a/src/app/(dashboard)/dashboard/providers/components/ProviderCard.tsx b/src/app/(dashboard)/dashboard/providers/components/ProviderCard.tsx index 23a990abf5..d290f07be0 100644 --- a/src/app/(dashboard)/dashboard/providers/components/ProviderCard.tsx +++ b/src/app/(dashboard)/dashboard/providers/components/ProviderCard.tsx @@ -42,6 +42,15 @@ const KIND_LABEL: Record = { music: "Music", }; +/** Maps a compatible-provider `apiType` to its `KIND_LABEL` key (#6936: non-chat + * apiTypes — audio/embeddings/image — were falling through to the "Chat" badge). */ +const COMPATIBLE_API_TYPE_KIND: Record = { + "audio-transcriptions": "stt", + "audio-speech": "tts", + "images-generations": "image", + embeddings: "embedding", +}; + interface ProviderCardProps { providerId: string; provider: { @@ -319,7 +328,10 @@ export default function ProviderCard({ ))} {isCompatible && ( - {provider.apiType === "responses" ? t("responses") : t("chat")} + {provider.apiType === "responses" + ? t("responses") + : (KIND_LABEL[COMPATIBLE_API_TYPE_KIND[provider.apiType ?? ""] ?? ""] ?? + t("chat"))} )} {isCcCompatible && ( diff --git a/src/app/(dashboard)/dashboard/providers/components/__tests__/providerCardAudioBadge.test.tsx b/src/app/(dashboard)/dashboard/providers/components/__tests__/providerCardAudioBadge.test.tsx new file mode 100644 index 0000000000..71850594aa --- /dev/null +++ b/src/app/(dashboard)/dashboard/providers/components/__tests__/providerCardAudioBadge.test.tsx @@ -0,0 +1,94 @@ +import React from "react"; +import { createRoot } from "react-dom/client"; +import { act } from "react"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import ProviderCard from "../ProviderCard"; + +vi.mock("next-intl", () => ({ useTranslations: () => (k: string) => k })); +vi.mock("@/shared/components/ProviderTestSlideOver", () => ({ default: () => null })); +vi.mock("@/shared/components/ProviderIcon", () => ({ default: () => null })); + +describe("ProviderCard — #6936 audio-transcriptions provider badge", () => { + let container: HTMLDivElement | null = null; + + afterEach(() => { + if (container) { + document.body.removeChild(container); + container = null; + } + }); + + it("does NOT label an audio-transcriptions compatible node as Chat", () => { + container = document.createElement("div"); + document.body.appendChild(container); + const root = createRoot(container); + act(() => { + root.render( + {}} + /> + ); + }); + const text = (container.textContent || "").toLowerCase(); + expect(text).not.toContain("chat"); + expect(text).toContain("stt"); + }); + + it("labels an audio-speech compatible node as TTS", () => { + container = document.createElement("div"); + document.body.appendChild(container); + const root = createRoot(container); + act(() => { + root.render( + {}} + /> + ); + }); + const text = (container.textContent || "").toLowerCase(); + expect(text).not.toContain("chat"); + expect(text).toContain("tts"); + }); + + it("still labels a plain chat compatible node as Chat", () => { + container = document.createElement("div"); + document.body.appendChild(container); + const root = createRoot(container); + act(() => { + root.render( + {}} + /> + ); + }); + const text = (container.textContent || "").toLowerCase(); + expect(text).toContain("chat"); + }); +});