Files
OmniRoute/src/shared/components/lobeProviderIcons.ts
hppsc1215 b3d3dd5954 feat(providers): Complete GHE Copilot OAuth provider implementation (#7546)
* docs: add design spec for GHE Copilot provider

* feat(mitm): add GHE Copilot target descriptor

* feat(executors): add GheCopilotExecutor for GHE Copilot

* feat(executors): register GheCopilotExecutor in factory

* feat(providers): add ghe-copilot provider with gheUrl validation

* feat(providers): add ghe-copilot to OAUTH_PROVIDERS and enforce HTTPS gheUrl validation

* test(ghe-copilot): add unit tests for GheCopilotExecutor and GHE_COPILOT_TARGET

* feat: complete GHE Copilot provider implementation

* feat: register ghe-copilot provider in registry

Add GHE Copilot registry entry (executor: "ghe-copilot") so the
provider is resolvable by the API routes and gets the same model
catalog as github Copilot.

* feat: wire ghe-copilot into OAuth flow with per-connection gheUrl

- Add gheCopilot OAuth provider (device-code flow targeting GHE host)
- Register in OAuth PROVIDERS map
- Thread gheUrl from query param → device-code request → poll →
  postExchange → providerSpecificData so the GHE host is used end-to-end
- Restore corrupted src/lib/oauth/providers/github.ts from HEAD

* feat: add ghe-copilot device-code UI with gheUrl input

- Route ghe-copilot through the device-code OAuth branch (was falling
  through to browser OAuth → "Browser OAuth unavailable" error)
- Add a gheUrl collection step so the enterprise host is supplied before
  the device-code request, and thread it into /device-code + /poll

* fix: thread gheUrl through GHE Copilot pollToken + postExchange

pollToken read gheUrl from config (GITHUB_CONFIG, which has none) and
threw "gheUrl is required" on every poll — the connection hung forever
after device authorization. Now reads gheUrl from extraData (passed by
the route), and postExchange carries it forward into mapTokens so it is
persisted in providerSpecificData for the executor.

* fix: GHE Copilot chat routing + account test

- Capture endpoints.proxy from the GHE token response and store it as
  copilotProxyUrl; route chat/responses traffic to that enterprise host
  instead of the static gheUrl/chat/completions path (was 406/404).
- Always route GHE Copilot to /chat/completions (GHE proxy 404s on
  /responses); the Responses API is served via the chat transformer.
- Strip the ghe-copilot/ prefix from the upstream model id.
- Remove openai-responses targetFormat from GHE models so chatCore does
  not run the Responses transformer (which dropped `messages`).
- Add ghe-copilot to OAUTH_TEST_CONFIG (account test was "unsupported").
- Register executor in eslint suppressions.

* fix: drop stream:false for GHE Copilot

The GHE Copilot proxy rejects `stream: false` ("stream": false is not
supported). Only forward the flag when actually streaming; omit it
otherwise.

* fix: force stream:true upstream for GHE Copilot (streaming-only proxy)

The GHE Copilot proxy rejects `stream: false`. forceStream:true in the
registry makes chatCore pass upstreamStream=true, but GithubExecutor
.transformRequest ignores the stream arg (void stream) and keeps the
client's stream:false. Override transformRequest in GheCopilotExecutor to
force stream:true so the proxy accepts the request; chatCore drains the
SSE back to JSON for non-stream clients.

* fix: GHE Copilot live model discovery from copilotProxyUrl/models

- Add fetchGheCopilotModels/parseGheCopilotModels using enterprise proxy URL
  and { models: [{ name }] } response shape (no static allowlist)
- Wire ghe-copilot into models-import route; use plain fetch (safeOutboundFetch
  header guard strips the copilot bearer token -> 403)
- Import now returns real enterprise models (copilot-nes-oct, etc.) and chat
  resolves them correctly

* fix: GHE Copilot uses endpoints.api host for chat + model discovery

The GHE token endpoint returns two hosts:
  - endpoints.api   (copilotApiUrl)   -> chat/completions + real chat model
    catalog, shape { data: [{ id }] }
  - endpoints.proxy (copilotProxyUrl) -> NES/autocomplete/instant-apply only,
    shape { models: [{ name }] }

We were routing chat AND model discovery to endpoints.proxy, so import only
returned completion models (copilot-nes-*, instant-apply) and never the real
chat models (claude-*, gpt-*, gemini-*).

- Executor: capture endpoints.api as copilotApiUrl; buildUrl prefers it
- OAuth postExchange/mapTokens: persist copilotApiUrl from endpoints.api
- Model discovery: fetch from copilotApiUrl/models, parse { data:[{id}] }
  (and proxy { models:[{name}] }) shapes, no allowlist
- All traffic stays on the configured GHE host (deutschebahn.ghe.com),
  never api.githubcopilot.com

Verified: import returns 28 real chat models; chat with gpt-4o streams OK.

* feat(providers): finalize GHE Copilot implementation and add changelog fragment

* fix(providers): resolve ghe-copilot no-explicit-any + complexity ratchet

- Replace the 6 explicit `any` types in GheCopilotExecutor
  (transformRequest, refreshCredentials) with proper ProviderCredentials /
  unknown / ExecutorLog types, and drop the config/quality/eslint-suppressions.json
  allowlist entry added for them — policy requires new violations be fixed,
  not frozen.
- Extract refreshViaGitHubToken() and buildRefreshedProviderSpecificData()
  helpers out of refreshCredentials() to bring its cyclomatic complexity
  (21) back under the repo's ratchet threshold (15); behavior unchanged.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* fix(oauth): unblock #7546 file-size gate for GHE Copilot OAuth provider

Extracts the GHE enterprise-URL config step from OAuthModal.tsx into a
new leaf component (src/shared/components/oauthModal/GheConfigStep.tsx)
to shrink the frozen file's own growth, and rebaselines the two
remaining irreducible wiring bumps (device-code route.ts 960->963,
OAuthModal.tsx 1030->1056) with justification comments, mirroring the
existing #7399/#6636 precedent on this same file.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* chore(ghe-copilot): drop planning spec from docs/ and revert out-of-scope eslint bump

Planning artifacts live outside the repo tree; package.json/lock restored to the
release state (the eslint patch bump was unrelated drift from the fork's history).

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* fix(oauth): validate gheUrl (HTTPS-only) at both raw entry points of the device-code flow

Applies the PR's existing providerSpecificData HTTPS rule to the OAuth route's
searchParams and device-flow extraData entry points, rejecting malformed or
non-HTTPS enterprise URLs with 400 before any upstream fetch. Private-IP hosts
stay allowed by design — on-prem GHE Server is the primary use case.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* chore(quality): extend oauth route file-size note for the gheUrl validation guards (963->970)

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: Alexander Helm <alexander.helm@deutschebahn.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouzapw@users.noreply.github.com>
Co-authored-by: hppsc1215 <hppsc1215@users.noreply.github.com>
2026-07-19 21:22:37 -03:00

493 lines
24 KiB
TypeScript

import type { CSSProperties, ElementType } from "react";
import Ai21MonoIcon from "@lobehub/icons/es/Ai21/components/Mono";
import AlibabaColorIcon from "@lobehub/icons/es/Alibaba/components/Color";
import AlibabaMonoIcon from "@lobehub/icons/es/Alibaba/components/Mono";
import AnthropicMonoIcon from "@lobehub/icons/es/Anthropic/components/Mono";
import AntigravityColorIcon from "@lobehub/icons/es/Antigravity/components/Color";
import AntigravityMonoIcon from "@lobehub/icons/es/Antigravity/components/Mono";
import ArceeColorIcon from "@lobehub/icons/es/Arcee/components/Color";
import ArceeMonoIcon from "@lobehub/icons/es/Arcee/components/Mono";
import AssemblyAIColorIcon from "@lobehub/icons/es/AssemblyAI/components/Color";
import AssemblyAIMonoIcon from "@lobehub/icons/es/AssemblyAI/components/Mono";
import AutomaticColorIcon from "@lobehub/icons/es/Automatic/components/Color";
import AutomaticMonoIcon from "@lobehub/icons/es/Automatic/components/Mono";
import AwsColorIcon from "@lobehub/icons/es/Aws/components/Color";
import AwsMonoIcon from "@lobehub/icons/es/Aws/components/Mono";
import AzureColorIcon from "@lobehub/icons/es/Azure/components/Color";
import AzureMonoIcon from "@lobehub/icons/es/Azure/components/Mono";
import AzureAIColorIcon from "@lobehub/icons/es/AzureAI/components/Color";
import AzureAIMonoIcon from "@lobehub/icons/es/AzureAI/components/Mono";
import BaichuanColorIcon from "@lobehub/icons/es/Baichuan/components/Color";
import BaichuanMonoIcon from "@lobehub/icons/es/Baichuan/components/Mono";
import BaiduColorIcon from "@lobehub/icons/es/Baidu/components/Color";
import BaiduMonoIcon from "@lobehub/icons/es/Baidu/components/Mono";
import BailianColorIcon from "@lobehub/icons/es/Bailian/components/Color";
import BailianMonoIcon from "@lobehub/icons/es/Bailian/components/Mono";
import BasetenMonoIcon from "@lobehub/icons/es/Baseten/components/Mono";
import BedrockColorIcon from "@lobehub/icons/es/Bedrock/components/Color";
import BedrockMonoIcon from "@lobehub/icons/es/Bedrock/components/Mono";
import BflMonoIcon from "@lobehub/icons/es/Bfl/components/Mono";
import CerebrasColorIcon from "@lobehub/icons/es/Cerebras/components/Color";
import CerebrasMonoIcon from "@lobehub/icons/es/Cerebras/components/Mono";
import ClaudeColorIcon from "@lobehub/icons/es/Claude/components/Color";
import ClaudeMonoIcon from "@lobehub/icons/es/Claude/components/Mono";
import ClaudeCodeColorIcon from "@lobehub/icons/es/ClaudeCode/components/Color";
import ClaudeCodeMonoIcon from "@lobehub/icons/es/ClaudeCode/components/Mono";
import ClineMonoIcon from "@lobehub/icons/es/Cline/components/Mono";
import CloudflareColorIcon from "@lobehub/icons/es/Cloudflare/components/Color";
import CloudflareMonoIcon from "@lobehub/icons/es/Cloudflare/components/Mono";
import CodexColorIcon from "@lobehub/icons/es/Codex/components/Color";
import CodexMonoIcon from "@lobehub/icons/es/Codex/components/Mono";
import CohereColorIcon from "@lobehub/icons/es/Cohere/components/Color";
import CohereMonoIcon from "@lobehub/icons/es/Cohere/components/Mono";
import ComfyUIColorIcon from "@lobehub/icons/es/ComfyUI/components/Color";
import ComfyUIMonoIcon from "@lobehub/icons/es/ComfyUI/components/Mono";
import CopilotColorIcon from "@lobehub/icons/es/Copilot/components/Color";
import CopilotMonoIcon from "@lobehub/icons/es/Copilot/components/Mono";
import CursorMonoIcon from "@lobehub/icons/es/Cursor/components/Mono";
import DbrxColorIcon from "@lobehub/icons/es/Dbrx/components/Color";
import CozeMonoIcon from "@lobehub/icons/es/Coze/components/Mono";
import DbrxMonoIcon from "@lobehub/icons/es/Dbrx/components/Mono";
import DeepInfraColorIcon from "@lobehub/icons/es/DeepInfra/components/Color";
import DeepInfraMonoIcon from "@lobehub/icons/es/DeepInfra/components/Mono";
import DeepSeekColorIcon from "@lobehub/icons/es/DeepSeek/components/Color";
import DeepSeekMonoIcon from "@lobehub/icons/es/DeepSeek/components/Mono";
import DevinColorIcon from "@lobehub/icons/es/Devin/components/Color";
import DifyColorIcon from "@lobehub/icons/es/Dify/components/Color";
import DifyMonoIcon from "@lobehub/icons/es/Dify/components/Mono";
import DoubaoColorIcon from "@lobehub/icons/es/Doubao/components/Color";
import DoubaoMonoIcon from "@lobehub/icons/es/Doubao/components/Mono";
import ElevenLabsMonoIcon from "@lobehub/icons/es/ElevenLabs/components/Mono";
import ExaColorIcon from "@lobehub/icons/es/Exa/components/Color";
import ExaMonoIcon from "@lobehub/icons/es/Exa/components/Mono";
import FalColorIcon from "@lobehub/icons/es/Fal/components/Color";
import FalMonoIcon from "@lobehub/icons/es/Fal/components/Mono";
import FeatherlessColorIcon from "@lobehub/icons/es/Featherless/components/Color";
import FeatherlessMonoIcon from "@lobehub/icons/es/Featherless/components/Mono";
import FireworksColorIcon from "@lobehub/icons/es/Fireworks/components/Color";
import FireworksMonoIcon from "@lobehub/icons/es/Fireworks/components/Mono";
import FriendliMonoIcon from "@lobehub/icons/es/Friendli/components/Mono";
import GeminiColorIcon from "@lobehub/icons/es/Gemini/components/Color";
import GeminiMonoIcon from "@lobehub/icons/es/Gemini/components/Mono";
import GithubMonoIcon from "@lobehub/icons/es/Github/components/Mono";
import GithubCopilotMonoIcon from "@lobehub/icons/es/GithubCopilot/components/Mono";
import GoogleColorIcon from "@lobehub/icons/es/Google/components/Color";
import GoogleMonoIcon from "@lobehub/icons/es/Google/components/Mono";
import GrokMonoIcon from "@lobehub/icons/es/Grok/components/Mono";
import GroqMonoIcon from "@lobehub/icons/es/Groq/components/Mono";
import HuggingFaceColorIcon from "@lobehub/icons/es/HuggingFace/components/Color";
import HuggingFaceMonoIcon from "@lobehub/icons/es/HuggingFace/components/Mono";
import HyperbolicColorIcon from "@lobehub/icons/es/Hyperbolic/components/Color";
import HyperbolicMonoIcon from "@lobehub/icons/es/Hyperbolic/components/Mono";
import IBMMonoIcon from "@lobehub/icons/es/IBM/components/Mono";
import InferenceMonoIcon from "@lobehub/icons/es/Inference/components/Mono";
import JinaMonoIcon from "@lobehub/icons/es/Jina/components/Mono";
import KiloCodeMonoIcon from "@lobehub/icons/es/KiloCode/components/Mono";
import KimiColorIcon from "@lobehub/icons/es/Kimi/components/Color";
import KimiMonoIcon from "@lobehub/icons/es/Kimi/components/Mono";
import LambdaMonoIcon from "@lobehub/icons/es/Lambda/components/Mono";
import LiquidMonoIcon from "@lobehub/icons/es/Liquid/components/Mono";
import LmStudioMonoIcon from "@lobehub/icons/es/LmStudio/components/Mono";
import LongCatColorIcon from "@lobehub/icons/es/LongCat/components/Color";
import LongCatMonoIcon from "@lobehub/icons/es/LongCat/components/Mono";
import MetaColorIcon from "@lobehub/icons/es/Meta/components/Color";
import MetaMonoIcon from "@lobehub/icons/es/Meta/components/Mono";
import MetaAIColorIcon from "@lobehub/icons/es/MetaAI/components/Color";
import MetaAIMonoIcon from "@lobehub/icons/es/MetaAI/components/Mono";
import MinimaxColorIcon from "@lobehub/icons/es/Minimax/components/Color";
import MinimaxMonoIcon from "@lobehub/icons/es/Minimax/components/Mono";
import MistralColorIcon from "@lobehub/icons/es/Mistral/components/Color";
import MistralMonoIcon from "@lobehub/icons/es/Mistral/components/Mono";
import MoonshotMonoIcon from "@lobehub/icons/es/Moonshot/components/Mono";
import MorphColorIcon from "@lobehub/icons/es/Morph/components/Color";
import MorphMonoIcon from "@lobehub/icons/es/Morph/components/Mono";
import NanoBananaColorIcon from "@lobehub/icons/es/NanoBanana/components/Color";
import NanoBananaMonoIcon from "@lobehub/icons/es/NanoBanana/components/Mono";
import NebiusMonoIcon from "@lobehub/icons/es/Nebius/components/Mono";
import NousResearchMonoIcon from "@lobehub/icons/es/NousResearch/components/Mono";
import NovitaColorIcon from "@lobehub/icons/es/Novita/components/Color";
import NovitaMonoIcon from "@lobehub/icons/es/Novita/components/Mono";
import NvidiaColorIcon from "@lobehub/icons/es/Nvidia/components/Color";
import NvidiaMonoIcon from "@lobehub/icons/es/Nvidia/components/Mono";
import OllamaMonoIcon from "@lobehub/icons/es/Ollama/components/Mono";
import OpenAIMonoIcon from "@lobehub/icons/es/OpenAI/components/Mono";
import OpenClawColorIcon from "@lobehub/icons/es/OpenClaw/components/Color";
import OpenClawMonoIcon from "@lobehub/icons/es/OpenClaw/components/Mono";
import OpenCodeMonoIcon from "@lobehub/icons/es/OpenCode/components/Mono";
import OpenRouterMonoIcon from "@lobehub/icons/es/OpenRouter/components/Mono";
import PerplexityColorIcon from "@lobehub/icons/es/Perplexity/components/Color";
import PerplexityMonoIcon from "@lobehub/icons/es/Perplexity/components/Mono";
import PoeColorIcon from "@lobehub/icons/es/Poe/components/Color";
import PoeMonoIcon from "@lobehub/icons/es/Poe/components/Mono";
import PollinationsMonoIcon from "@lobehub/icons/es/Pollinations/components/Mono";
import QoderColorIcon from "@lobehub/icons/es/Qoder/components/Color";
import QoderMonoIcon from "@lobehub/icons/es/Qoder/components/Mono";
import QwenColorIcon from "@lobehub/icons/es/Qwen/components/Color";
import QwenMonoIcon from "@lobehub/icons/es/Qwen/components/Mono";
import RecraftMonoIcon from "@lobehub/icons/es/Recraft/components/Mono";
import ReplicateMonoIcon from "@lobehub/icons/es/Replicate/components/Mono";
import RooCodeMonoIcon from "@lobehub/icons/es/RooCode/components/Mono";
import RunwayMonoIcon from "@lobehub/icons/es/Runway/components/Mono";
import SambaNovaColorIcon from "@lobehub/icons/es/SambaNova/components/Color";
import SambaNovaMonoIcon from "@lobehub/icons/es/SambaNova/components/Mono";
import SearchApiMonoIcon from "@lobehub/icons/es/SearchApi/components/Mono";
import SiliconCloudColorIcon from "@lobehub/icons/es/SiliconCloud/components/Color";
import SiliconCloudMonoIcon from "@lobehub/icons/es/SiliconCloud/components/Mono";
import SnowflakeColorIcon from "@lobehub/icons/es/Snowflake/components/Color";
import SnowflakeMonoIcon from "@lobehub/icons/es/Snowflake/components/Mono";
import SenseNovaColorIcon from "@lobehub/icons/es/SenseNova/components/Color";
import SenseNovaMonoIcon from "@lobehub/icons/es/SenseNova/components/Mono";
import StabilityColorIcon from "@lobehub/icons/es/Stability/components/Color";
import StabilityMonoIcon from "@lobehub/icons/es/Stability/components/Mono";
// Stepfun has no Color component in the installed @lobehub/icons version; use Mono as fallback
import StepfunMonoIcon from "@lobehub/icons/es/Stepfun/components/Mono";
import SunoMonoIcon from "@lobehub/icons/es/Suno/components/Mono";
import TavilyColorIcon from "@lobehub/icons/es/Tavily/components/Color";
import TavilyMonoIcon from "@lobehub/icons/es/Tavily/components/Mono";
import TogetherColorIcon from "@lobehub/icons/es/Together/components/Color";
import TencentColorIcon from "@lobehub/icons/es/Tencent/components/Color";
import TencentMonoIcon from "@lobehub/icons/es/Tencent/components/Mono";
import TogetherMonoIcon from "@lobehub/icons/es/Together/components/Mono";
import TopazLabsMonoIcon from "@lobehub/icons/es/TopazLabs/components/Mono";
import TraeColorIcon from "@lobehub/icons/es/Trae/components/Color";
import TraeMonoIcon from "@lobehub/icons/es/Trae/components/Mono";
import UdioColorIcon from "@lobehub/icons/es/Udio/components/Color";
import UdioMonoIcon from "@lobehub/icons/es/Udio/components/Mono";
import UpstageColorIcon from "@lobehub/icons/es/Upstage/components/Color";
import UpstageMonoIcon from "@lobehub/icons/es/Upstage/components/Mono";
import YiColorIcon from "@lobehub/icons/es/Yi/components/Color";
import YiMonoIcon from "@lobehub/icons/es/Yi/components/Mono";
import V0MonoIcon from "@lobehub/icons/es/V0/components/Mono";
import VeniceColorIcon from "@lobehub/icons/es/Venice/components/Color";
import VeniceMonoIcon from "@lobehub/icons/es/Venice/components/Mono";
import VercelMonoIcon from "@lobehub/icons/es/Vercel/components/Mono";
import VertexAIColorIcon from "@lobehub/icons/es/VertexAI/components/Color";
import VertexAIMonoIcon from "@lobehub/icons/es/VertexAI/components/Mono";
import VllmColorIcon from "@lobehub/icons/es/Vllm/components/Color";
import VllmMonoIcon from "@lobehub/icons/es/Vllm/components/Mono";
import VolcengineColorIcon from "@lobehub/icons/es/Volcengine/components/Color";
import VolcengineMonoIcon from "@lobehub/icons/es/Volcengine/components/Mono";
import VoyageColorIcon from "@lobehub/icons/es/Voyage/components/Color";
import VoyageMonoIcon from "@lobehub/icons/es/Voyage/components/Mono";
import WindsurfMonoIcon from "@lobehub/icons/es/Windsurf/components/Mono";
import WorkersAIColorIcon from "@lobehub/icons/es/WorkersAI/components/Color";
import WorkersAIMonoIcon from "@lobehub/icons/es/WorkersAI/components/Mono";
import XAIMonoIcon from "@lobehub/icons/es/XAI/components/Mono";
import XiaomiMiMoMonoIcon from "@lobehub/icons/es/XiaomiMiMo/components/Mono";
import XinferenceColorIcon from "@lobehub/icons/es/Xinference/components/Color";
import XinferenceMonoIcon from "@lobehub/icons/es/Xinference/components/Mono";
import ZAIMonoIcon from "@lobehub/icons/es/ZAI/components/Mono";
import ZhipuColorIcon from "@lobehub/icons/es/Zhipu/components/Color";
import ZhipuMonoIcon from "@lobehub/icons/es/Zhipu/components/Mono";
type LobeIconComponent = ElementType<{
"aria-label"?: string;
className?: string;
size?: number | string;
style?: CSSProperties;
}>;
type LobeIconEntry = {
color?: LobeIconComponent;
mono: LobeIconComponent;
};
const LOBE_ICON_COMPONENTS = {
Ai21: { mono: Ai21MonoIcon },
Alibaba: { mono: AlibabaMonoIcon, color: AlibabaColorIcon },
Anthropic: { mono: AnthropicMonoIcon },
Antigravity: { mono: AntigravityMonoIcon, color: AntigravityColorIcon },
Arcee: { mono: ArceeMonoIcon, color: ArceeColorIcon },
AssemblyAI: { mono: AssemblyAIMonoIcon, color: AssemblyAIColorIcon },
Automatic: { mono: AutomaticMonoIcon, color: AutomaticColorIcon },
Aws: { mono: AwsMonoIcon, color: AwsColorIcon },
Azure: { mono: AzureMonoIcon, color: AzureColorIcon },
AzureAI: { mono: AzureAIMonoIcon, color: AzureAIColorIcon },
Baichuan: { mono: BaichuanMonoIcon, color: BaichuanColorIcon },
Baidu: { mono: BaiduMonoIcon, color: BaiduColorIcon },
Bailian: { mono: BailianMonoIcon, color: BailianColorIcon },
Baseten: { mono: BasetenMonoIcon },
Bedrock: { mono: BedrockMonoIcon, color: BedrockColorIcon },
Bfl: { mono: BflMonoIcon },
Cerebras: { mono: CerebrasMonoIcon, color: CerebrasColorIcon },
Claude: { mono: ClaudeMonoIcon, color: ClaudeColorIcon },
ClaudeCode: { mono: ClaudeCodeMonoIcon, color: ClaudeCodeColorIcon },
Cline: { mono: ClineMonoIcon },
Cloudflare: { mono: CloudflareMonoIcon, color: CloudflareColorIcon },
Codex: { mono: CodexMonoIcon, color: CodexColorIcon },
Cohere: { mono: CohereMonoIcon, color: CohereColorIcon },
ComfyUI: { mono: ComfyUIMonoIcon, color: ComfyUIColorIcon },
Copilot: { mono: CopilotMonoIcon, color: CopilotColorIcon },
Coze: { mono: CozeMonoIcon },
Cursor: { mono: CursorMonoIcon },
Dbrx: { mono: DbrxMonoIcon, color: DbrxColorIcon },
DeepInfra: { mono: DeepInfraMonoIcon, color: DeepInfraColorIcon },
DeepSeek: { mono: DeepSeekMonoIcon, color: DeepSeekColorIcon },
Devin: { mono: DevinColorIcon, color: DevinColorIcon },
Dify: { mono: DifyMonoIcon, color: DifyColorIcon },
Doubao: { mono: DoubaoMonoIcon, color: DoubaoColorIcon },
ElevenLabs: { mono: ElevenLabsMonoIcon },
Exa: { mono: ExaMonoIcon, color: ExaColorIcon },
Fal: { mono: FalMonoIcon, color: FalColorIcon },
Featherless: { mono: FeatherlessMonoIcon, color: FeatherlessColorIcon },
Fireworks: { mono: FireworksMonoIcon, color: FireworksColorIcon },
Friendli: { mono: FriendliMonoIcon },
Gemini: { mono: GeminiMonoIcon, color: GeminiColorIcon },
Github: { mono: GithubMonoIcon },
GithubCopilot: { mono: GithubCopilotMonoIcon },
Google: { mono: GoogleMonoIcon, color: GoogleColorIcon },
Grok: { mono: GrokMonoIcon },
Groq: { mono: GroqMonoIcon },
HuggingFace: { mono: HuggingFaceMonoIcon, color: HuggingFaceColorIcon },
Hyperbolic: { mono: HyperbolicMonoIcon, color: HyperbolicColorIcon },
IBM: { mono: IBMMonoIcon },
Inference: { mono: InferenceMonoIcon },
Jina: { mono: JinaMonoIcon },
KiloCode: { mono: KiloCodeMonoIcon },
Kimi: { mono: KimiMonoIcon, color: KimiColorIcon },
Lambda: { mono: LambdaMonoIcon },
Liquid: { mono: LiquidMonoIcon },
LmStudio: { mono: LmStudioMonoIcon },
LongCat: { mono: LongCatMonoIcon, color: LongCatColorIcon },
Meta: { mono: MetaMonoIcon, color: MetaColorIcon },
MetaAI: { mono: MetaAIMonoIcon, color: MetaAIColorIcon },
Minimax: { mono: MinimaxMonoIcon, color: MinimaxColorIcon },
Mistral: { mono: MistralMonoIcon, color: MistralColorIcon },
Moonshot: { mono: MoonshotMonoIcon },
Morph: { mono: MorphMonoIcon, color: MorphColorIcon },
NanoBanana: { mono: NanoBananaMonoIcon, color: NanoBananaColorIcon },
Nebius: { mono: NebiusMonoIcon },
NousResearch: { mono: NousResearchMonoIcon },
Novita: { mono: NovitaMonoIcon, color: NovitaColorIcon },
Nvidia: { mono: NvidiaMonoIcon, color: NvidiaColorIcon },
Ollama: { mono: OllamaMonoIcon },
OpenAI: { mono: OpenAIMonoIcon },
OpenClaw: { mono: OpenClawMonoIcon, color: OpenClawColorIcon },
OpenCode: { mono: OpenCodeMonoIcon },
OpenRouter: { mono: OpenRouterMonoIcon },
Perplexity: { mono: PerplexityMonoIcon, color: PerplexityColorIcon },
Poe: { mono: PoeMonoIcon, color: PoeColorIcon },
Pollinations: { mono: PollinationsMonoIcon },
Qoder: { mono: QoderMonoIcon, color: QoderColorIcon },
Qwen: { mono: QwenMonoIcon, color: QwenColorIcon },
Recraft: { mono: RecraftMonoIcon },
Replicate: { mono: ReplicateMonoIcon },
RooCode: { mono: RooCodeMonoIcon },
Runway: { mono: RunwayMonoIcon },
SambaNova: { mono: SambaNovaMonoIcon, color: SambaNovaColorIcon },
SearchApi: { mono: SearchApiMonoIcon },
SiliconCloud: { mono: SiliconCloudMonoIcon, color: SiliconCloudColorIcon },
SenseNova: { mono: SenseNovaMonoIcon, color: SenseNovaColorIcon },
Snowflake: { mono: SnowflakeMonoIcon, color: SnowflakeColorIcon },
Stability: { mono: StabilityMonoIcon, color: StabilityColorIcon },
Stepfun: { mono: StepfunMonoIcon, color: StepfunMonoIcon },
Suno: { mono: SunoMonoIcon },
Tavily: { mono: TavilyMonoIcon, color: TavilyColorIcon },
Tencent: { mono: TencentMonoIcon, color: TencentColorIcon },
Together: { mono: TogetherMonoIcon, color: TogetherColorIcon },
TopazLabs: { mono: TopazLabsMonoIcon },
Trae: { mono: TraeMonoIcon, color: TraeColorIcon },
Udio: { mono: UdioMonoIcon, color: UdioColorIcon },
Upstage: { mono: UpstageMonoIcon, color: UpstageColorIcon },
V0: { mono: V0MonoIcon },
Venice: { mono: VeniceMonoIcon, color: VeniceColorIcon },
Vercel: { mono: VercelMonoIcon },
VertexAI: { mono: VertexAIMonoIcon, color: VertexAIColorIcon },
Vllm: { mono: VllmMonoIcon, color: VllmColorIcon },
Volcengine: { mono: VolcengineMonoIcon, color: VolcengineColorIcon },
Voyage: { mono: VoyageMonoIcon, color: VoyageColorIcon },
Windsurf: { mono: WindsurfMonoIcon },
WorkersAI: { mono: WorkersAIMonoIcon, color: WorkersAIColorIcon },
XAI: { mono: XAIMonoIcon },
XiaomiMiMo: { mono: XiaomiMiMoMonoIcon },
Xinference: { mono: XinferenceMonoIcon, color: XinferenceColorIcon },
Yi: { mono: YiMonoIcon, color: YiColorIcon },
ZAI: { mono: ZAIMonoIcon },
Zhipu: { mono: ZhipuMonoIcon, color: ZhipuColorIcon },
} satisfies Record<string, LobeIconEntry>;
const LOBE_PROVIDER_ALIASES = {
ai21: "Ai21",
alibaba: "Alibaba",
"alibaba-cn": "Alibaba",
"amazon-q": "Aws",
anthropic: "Anthropic",
antigravity: "Antigravity",
agy: "Antigravity", // Antigravity CLI — same brand icon as the antigravity provider
assemblyai: "AssemblyAI",
"aws-polly": "Aws",
azure: "Azure",
"azure-ai": "AzureAI",
"azure-openai": "AzureAI",
bai: "Baichuan",
baidu: "Baidu",
"bailian-coding-plan": "Bailian",
baseten: "Baseten",
bedrock: "Bedrock",
bfl: "Bfl",
"black-forest-labs": "Bfl",
cerebras: "Cerebras",
"chatgpt-web": "OpenAI",
claude: "ClaudeCode",
"claude-web": "Claude",
cline: "Cline",
clinepass: "Cline",
cloudflare: "Cloudflare",
"cloudflare-ai": "WorkersAI",
codestral: "Mistral",
codex: "Codex",
"codex-cloud": "Codex",
cohere: "Cohere",
comfyui: "ComfyUI",
copilot: "GithubCopilot",
"copilot-m365-web": "Copilot",
"copilot-web": "Copilot",
coze: "Coze",
cursor: "Cursor",
"cursor-cloud": "Cursor",
databricks: "Dbrx",
deepinfra: "DeepInfra",
deepseek: "DeepSeek",
"deepseek-web": "DeepSeek",
devin: "Devin",
"devin-cli": "Devin",
doubao: "Doubao",
"doubao-web": "Doubao",
elevenlabs: "ElevenLabs",
exa: "Exa",
"exa-search": "Exa",
fal: "Fal",
"fal-ai": "Fal",
featherless: "Featherless",
"featherless-ai": "Featherless",
fireworks: "Fireworks",
"fireworks-ai": "Fireworks",
friendli: "Friendli",
friendliai: "Friendli",
gemini: "Gemini",
"gemini-web": "Gemini",
"gemini-business": "Gemini",
github: "GithubCopilot",
"github-models": "Github",
"github-copilot": "GithubCopilot",
"ghe-copilot": "GithubCopilot",
glm: "Zhipu",
"glm-cn": "Zhipu",
glmt: "Zhipu",
"google-pse-search": "Google",
grok: "Grok",
"grok-web": "Grok",
"grok-cli": "Grok",
groq: "Groq",
huggingchat: "HuggingFace",
"hugging-face": "HuggingFace",
huggingface: "HuggingFace",
hyperbolic: "Hyperbolic",
ibm: "IBM",
"inference-net": "Inference",
jina: "Jina",
"jina-ai": "Jina",
kilocode: "KiloCode",
kimi: "Kimi",
"kimi-web": "Kimi",
"kimi-coding": "Kimi",
"kimi-coding-apikey": "Kimi",
lambda: "Lambda",
"lambda-ai": "Lambda",
liquid: "Liquid",
"lm-studio": "LmStudio",
lmstudio: "LmStudio",
longcat: "LongCat",
"meta-llama": "Meta",
minimax: "Minimax",
"minimax-cn": "Minimax",
mimocode: "XiaomiMiMo",
mistral: "Mistral",
mistralai: "Mistral",
moonshot: "Moonshot",
morph: "Morph",
"muse-spark-web": "MetaAI",
nanobanana: "NanoBanana",
nebius: "Nebius",
"nous-research": "NousResearch",
nousresearch: "NousResearch",
novita: "Novita",
nvidia: "Nvidia",
ollama: "Ollama",
"ollama-cloud": "Ollama",
"ollama-search": "Ollama",
openai: "OpenAI",
openclaw: "OpenClaw",
opencode: "OpenCode",
"opencode-go": "OpenCode",
"opencode-zen": "OpenCode",
"open-router": "OpenRouter",
openrouter: "OpenRouter",
perplexity: "Perplexity",
"perplexity-search": "Perplexity",
"perplexity-web": "Perplexity",
poe: "Poe",
pollinations: "Pollinations",
qoder: "Qoder",
qwen: "Qwen",
"qwen-web": "Qwen",
recraft: "Recraft",
replicate: "Replicate",
roo: "RooCode",
runwayml: "Runway",
sambanova: "SambaNova",
sdwebui: "Automatic",
searchapi: "SearchApi",
"searchapi-search": "SearchApi",
siliconflow: "SiliconCloud",
snowflake: "Snowflake",
stepfun: "Stepfun",
stability: "Stability",
"stability-ai": "Stability",
suno: "Suno",
tavily: "Tavily",
"tavily-search": "Tavily",
tencent: "Tencent",
"codebuddy-cn": "Tencent",
together: "Together",
topaz: "TopazLabs",
trae: "Trae",
triton: "Nvidia",
udio: "Udio",
upstage: "Upstage",
v0: "V0",
"v0-vercel": "V0",
venice: "Venice",
"vercel-ai-gateway": "Vercel",
vertex: "VertexAI",
"vertex-partner": "VertexAI",
vertexai: "VertexAI",
vllm: "Vllm",
volcengine: "Volcengine",
voyage: "Voyage",
"voyage-ai": "Voyage",
watsonx: "IBM",
windsurf: "Windsurf",
"workers-ai": "WorkersAI",
workersai: "WorkersAI",
xai: "XAI",
"xiaomi-mimo": "XiaomiMiMo",
xiaomimimo: "XiaomiMiMo",
xinference: "Xinference",
zai: "ZAI",
yi: "Yi",
zhipu: "Zhipu",
} satisfies Record<string, keyof typeof LOBE_ICON_COMPONENTS>;
export function getLobeProviderIcon(
providerId: string,
type: "mono" | "color" = "color"
): LobeIconComponent | null {
const iconKey = LOBE_PROVIDER_ALIASES[providerId.toLowerCase()];
if (!iconKey) return null;
const entry = LOBE_ICON_COMPONENTS[iconKey];
return type === "color" && entry.color ? entry.color : entry.mono;
}