mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-03 22:02:08 +03:00
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.
This commit is contained in:
committed by
GitHub
parent
86af4765f5
commit
152d77cf4b
1
changelog.d/fixes/6936-providercard-audio-badge.md
Normal file
1
changelog.d/fixes/6936-providercard-audio-badge.md
Normal file
@@ -0,0 +1 @@
|
||||
- fix(dashboard): label audio/embeddings/image compatible providers by kind instead of "Chat" on ProviderCard (#6936)
|
||||
@@ -42,6 +42,15 @@ const KIND_LABEL: Record<string, string> = {
|
||||
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<string, string> = {
|
||||
"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 && (
|
||||
<Badge variant="default" size="sm">
|
||||
{provider.apiType === "responses" ? t("responses") : t("chat")}
|
||||
{provider.apiType === "responses"
|
||||
? t("responses")
|
||||
: (KIND_LABEL[COMPATIBLE_API_TYPE_KIND[provider.apiType ?? ""] ?? ""] ??
|
||||
t("chat"))}
|
||||
</Badge>
|
||||
)}
|
||||
{isCcCompatible && (
|
||||
|
||||
@@ -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(
|
||||
<ProviderCard
|
||||
providerId="openai-compatible-speaches-stt"
|
||||
provider={{
|
||||
id: "openai-compatible-speaches-stt",
|
||||
name: "Speaches-stt",
|
||||
apiType: "audio-transcriptions",
|
||||
serviceKinds: [],
|
||||
}}
|
||||
stats={{ total: 1, connected: 1, error: 0, warning: 0 }}
|
||||
authType="apikey"
|
||||
onToggle={() => {}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
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(
|
||||
<ProviderCard
|
||||
providerId="openai-compatible-speaches-tts"
|
||||
provider={{
|
||||
id: "openai-compatible-speaches-tts",
|
||||
name: "Speaches-tts",
|
||||
apiType: "audio-speech",
|
||||
serviceKinds: [],
|
||||
}}
|
||||
stats={{ total: 1, connected: 1, error: 0, warning: 0 }}
|
||||
authType="apikey"
|
||||
onToggle={() => {}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
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(
|
||||
<ProviderCard
|
||||
providerId="openai-compatible-plain"
|
||||
provider={{
|
||||
id: "openai-compatible-plain",
|
||||
name: "Plain-chat",
|
||||
apiType: "chat",
|
||||
serviceKinds: [],
|
||||
}}
|
||||
stats={{ total: 1, connected: 1, error: 0, warning: 0 }}
|
||||
authType="apikey"
|
||||
onToggle={() => {}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
const text = (container.textContent || "").toLowerCase();
|
||||
expect(text).toContain("chat");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user