Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions components/dashboard/routing/provider-avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { cn } from "@/lib/utils"

import { providerLogoSrc } from "./provider-logos"
import { providerHue } from "./routing-utils"

/**
* O repo não versiona logos de provedor, então o avatar é a inicial sobre um
* hue derivado do id — estável entre sessões e suficiente para o olho encontrar
* o mesmo provedor em lanes diferentes.
* Logo oficial quando existe (public/providers/<id>.svg, ver provider-logos.ts);
* senão a inicial sobre um hue derivado do id — estável entre sessões e
* suficiente para o olho encontrar o mesmo provedor em lanes diferentes.
*/
export function ProviderAvatar({
className,
Expand All @@ -18,6 +19,24 @@ export function ProviderAvatar({
providerId: string
size?: number
}) {
const logoSrc = providerLogoSrc(providerId)

if (logoSrc) {
return (
<span
className={cn(
"flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-muted",
className,
)}
style={{ height: size, width: size }}
title={label}
>
{/* eslint-disable-next-line @next/next/no-img-element -- ícone estático pequeno, next/image não agrega nada aqui */}
<img alt="" className="h-[65%] w-[65%] object-contain" src={logoSrc} />
</span>
)
}

const hue = providerHue(providerId)

return (
Expand Down
13 changes: 13 additions & 0 deletions components/dashboard/routing/provider-logos.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { describe, expect, it } from "vitest"

import { providerLogoSrc } from "./provider-logos"

describe("providerLogoSrc", () => {
it("returns the static asset path for a provider with a logo", () => {
expect(providerLogoSrc("openai")).toBe("/providers/openai.svg")
})

it("returns undefined for a provider without a logo", () => {
expect(providerLogoSrc("puter")).toBeUndefined()
})
})
41 changes: 41 additions & 0 deletions components/dashboard/routing/provider-logos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Provedores com logo versionado em public/providers/<id>.svg (issue #249).
* Origem: @lobehub/icons-static-svg (MIT, devDependency usada só como fonte).
* Para adicionar um novo: ver scripts/add-provider-logo.mjs.
*/
const PROVIDERS_WITH_LOGO = new Set([
"bytepluscoding",
"cerebras",
"cloudflareworkersai",
"cohere",
"copilot",
"deepseek",
"fireworks",
"gateway",
"githubmodels",
"googleaistudio",
"groq",
"huggingface",
"mistral",
"moonshot",
"nvidianim",
"ollama",
"ollamacloud",
"opencodego",
"opencodezen",
"openai",
"openrouter",
"perplexity",
"pollinations",
"qwen",
"qwentoken",
"togetherai",
"zai",
"zaicoding",
])

export function providerLogoSrc(providerId: string): string | undefined {
return PROVIDERS_WITH_LOGO.has(providerId)
? `/providers/${providerId}.svg`
: undefined
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"zod": "^4.4.3"
},
"devDependencies": {
"@lobehub/icons-static-svg": "^1.94.0",
"@tailwindcss/postcss": "^4.3.3",
"@types/babel__standalone": "^7.1.9",
"@types/jsdom": "^30.0.0",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions public/providers/bytepluscoding.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/providers/cerebras.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/providers/cloudflareworkersai.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/providers/cohere.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/providers/copilot.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/providers/deepseek.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/providers/fireworks.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/providers/gateway.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/providers/githubmodels.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/providers/googleaistudio.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/providers/groq.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading