diff --git a/src/app/(dashboard)/dashboard/providers/components/ProviderCard.tsx b/src/app/(dashboard)/dashboard/providers/components/ProviderCard.tsx index ed6c405d32..86567d108a 100644 --- a/src/app/(dashboard)/dashboard/providers/components/ProviderCard.tsx +++ b/src/app/(dashboard)/dashboard/providers/components/ProviderCard.tsx @@ -149,20 +149,20 @@ export default function ProviderCard({
{staticIconPath ? ( {provider.name} ) : ( - + )}
diff --git a/src/app/(dashboard)/dashboard/providers/page.tsx b/src/app/(dashboard)/dashboard/providers/page.tsx index ab3a1c583b..fa2f5c30b0 100644 --- a/src/app/(dashboard)/dashboard/providers/page.tsx +++ b/src/app/(dashboard)/dashboard/providers/page.tsx @@ -532,6 +532,44 @@ export default function ProvidersPage() { searchQuery ); + const FREE_SECTION_IDS = new Set([ + "kiro", + "amazon-q", + "gemini-cli", + "qoder", + "pollinations", + "llm7", + "opencode", + "gemini", + "groq", + "cerebras", + "mistral", + "nvidia", + "openrouter", + "cloudflare-ai", + "together", + "siliconflow", + "deepseek", + "longcat", + "glhf", + "morph", + "bazaarlink", + "uncloseai", + "completions", + "freetheai", + "enally", + "puter", + "blackbox", + ]); + const freeSectionEntriesAll = [...oauthProviderEntriesAll, ...apiKeyProviderEntriesAll].filter( + (e) => FREE_SECTION_IDS.has(e.providerId) + ); + const freeSectionEntries = filterConfiguredProviderEntries( + freeSectionEntriesAll, + false, + searchQuery + ); + if (loading) { return (
@@ -568,6 +606,75 @@ export default function ProvidersPage() {
+ {/* API Key Compatible Providers — dynamic (OpenAI/Anthropic compatible) */} +
+
+

+ {t("compatibleProviders")}{" "} + + +

+
+ {(compatibleProviders.length > 0 || + anthropicCompatibleProviders.length > 0 || + ccCompatibleProviders.length > 0) && ( + + )} + {ccCompatibleProviderEnabled && ( + + )} + + +
+
+ {compatibleProviders.length === 0 && + anthropicCompatibleProviders.length === 0 && + ccCompatibleProviders.length === 0 ? ( +
+ + extension + +

{t("noCompatibleYet")}

+

{t("compatibleHint")}

+
+ ) : ( +
+ {compatibleProviderEntries.map( + ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => ( + handleToggleProvider(providerId, toggleAuthType, active)} + /> + ) + )} +
+ )} +
+ {/* Expiration Banner */} {expirations?.summary && (expirations.summary.expired > 0 || expirations.summary.expiringSoon > 0) && ( @@ -604,6 +711,34 @@ export default function ProvidersPage() {
)} + {/* Free Tier Providers */} + {freeSectionEntries.length > 0 && ( +
+
+

+ {t("freeTierProviders")} + + +

+

{t("freeTierProvidersDesc")}

+
+
+ {freeSectionEntries.map( + ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => ( + handleToggleProvider(providerId, toggleAuthType, active)} + /> + ) + )} +
+
+ )} + {/* OAuth Providers (including providers that expose free tiers via OAuth) */}
@@ -669,7 +804,7 @@ export default function ProvidersPage() {
-
+
{oauthProviderEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => ( {t("llmProviders")} -
+
{llmProviderEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => ( {t("aggregatorsGateways")} -
+
{aggregatorProviderEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => ( {t("enterpriseCloud")} -
+
{enterpriseProviderEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => ( {t("imageProviders")} -
+
{imageProviderEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => ( {t("videoProviders")} -
+
{videoProviderEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => ( {t("embeddingRerankProviders")} -
+
{embeddingRerankProviderEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => (
-
+
{webCookieProviderEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => (
-
+
{searchProviderEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => (
-
+
{audioProviderEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => (
-
+
{cloudAgentProviderEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => (
-
+
{localProviderEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => (
-
+
{upstreamProxyEntries.map( ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => ( )} - {/* API Key Compatible Providers — dynamic (OpenAI/Anthropic compatible) */} -
-
-

- {t("compatibleProviders")}{" "} - - -

-
- {(compatibleProviders.length > 0 || - anthropicCompatibleProviders.length > 0 || - ccCompatibleProviders.length > 0) && ( - - )} - {ccCompatibleProviderEnabled && ( - - )} - - -
-
- {compatibleProviders.length === 0 && - anthropicCompatibleProviders.length === 0 && - ccCompatibleProviders.length === 0 ? ( -
- - extension - -

{t("noCompatibleYet")}

-

{t("compatibleHint")}

-
- ) : ( -
- {compatibleProviderEntries.map( - ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => ( - handleToggleProvider(providerId, toggleAuthType, active)} - /> - ) - )} -
- )} -