diff --git a/src/app/(dashboard)/dashboard/providers/page.tsx b/src/app/(dashboard)/dashboard/providers/page.tsx index 9f2d5c32a7..fabe1b5193 100644 --- a/src/app/(dashboard)/dashboard/providers/page.tsx +++ b/src/app/(dashboard)/dashboard/providers/page.tsx @@ -134,14 +134,18 @@ export default function ProvidersPage() { const error = errorConns.length; const total = providerConnections.length; + // Check if all connections are manually disabled + const allDisabled = total > 0 && providerConnections.every((c) => c.isActive === false); + // Get latest error info const latestError = errorConns.sort( - (a: any, b: any) => (new Date(b.lastErrorAt || 0) as any) - (new Date(a.lastErrorAt || 0) as any) + (a: any, b: any) => + (new Date(b.lastErrorAt || 0) as any) - (new Date(a.lastErrorAt || 0) as any) )[0]; const errorCode = latestError ? getConnectionErrorTag(latestError) : null; const errorTime = latestError?.lastErrorAt ? getRelativeTime(latestError.lastErrorAt) : null; - return { connected, error, total, errorCode, errorTime }; + return { connected, error, total, errorCode, errorTime, allDisabled }; }; const handleBatchTest = async (mode, providerId = null) => { @@ -422,7 +426,7 @@ export default function ProvidersPage() { } function ProviderCard({ providerId, provider, stats, authType }) { - const { connected, error, errorCode, errorTime } = stats; + const { connected, error, errorCode, errorTime, allDisabled } = stats; const [imgError, setImgError] = useState(false); const dotColors = { @@ -437,7 +441,7 @@ function ProviderCard({ providerId, provider, stats, authType }) {
@@ -470,8 +474,19 @@ function ProviderCard({ providerId, provider, stats, authType }) { />
- {getStatusDisplay(connected, error, errorCode)} - {errorTime && • {errorTime}} + {allDisabled ? ( + + + pause_circle + Disabled + + + ) : ( + <> + {getStatusDisplay(connected, error, errorCode)} + {errorTime && • {errorTime}} + + )}
@@ -503,7 +518,7 @@ ProviderCard.propTypes = { // API Key providers - use image with textIcon fallback (same as OAuth providers) function ApiKeyProviderCard({ providerId, provider, stats, authType }) { - const { connected, error, errorCode, errorTime } = stats; + const { connected, error, errorCode, errorTime, allDisabled } = stats; const isCompatible = providerId.startsWith(OPENAI_COMPATIBLE_PREFIX); const isAnthropicCompatible = providerId.startsWith(ANTHROPIC_COMPATIBLE_PREFIX); const [imgError, setImgError] = useState(false); @@ -531,7 +546,7 @@ function ApiKeyProviderCard({ providerId, provider, stats, authType }) {
@@ -564,18 +579,29 @@ function ApiKeyProviderCard({ providerId, provider, stats, authType }) { />
- {getStatusDisplay(connected, error, errorCode)} - {isCompatible && ( + {allDisabled ? ( - {provider.apiType === "responses" ? "Responses" : "Chat"} + + pause_circle + Disabled + + ) : ( + <> + {getStatusDisplay(connected, error, errorCode)} + {isCompatible && ( + + {provider.apiType === "responses" ? "Responses" : "Chat"} + + )} + {isAnthropicCompatible && ( + + Messages + + )} + {errorTime && • {errorTime}} + )} - {isAnthropicCompatible && ( - - Messages - - )} - {errorTime && • {errorTime}}
diff --git a/src/app/api/models/route.ts b/src/app/api/models/route.ts index 6c77c81651..a90b890981 100644 --- a/src/app/api/models/route.ts +++ b/src/app/api/models/route.ts @@ -1,20 +1,37 @@ import { NextResponse } from "next/server"; -import { getModelAliases, setModelAlias } from "@/models"; +import { getModelAliases, setModelAlias, getProviderConnections } from "@/models"; import { AI_MODELS } from "@/shared/constants/config"; -// GET /api/models - Get models with aliases -export async function GET() { +// GET /api/models - Get models with aliases (only from active providers by default) +export async function GET(request: Request) { try { + const { searchParams } = new URL(request.url); + const showAll = searchParams.get("all") === "true"; + const modelAliases = await getModelAliases(); - const models = AI_MODELS.map((m) => { + // Get active provider connections to filter available models + let activeProviders: Set | null = null; + if (!showAll) { + try { + const connections = await getProviderConnections(); + const active = connections.filter((c: any) => c.isActive !== false); + activeProviders = new Set(active.map((c: any) => c.provider)); + } catch { + // If DB unavailable, show all models + } + } + + const models = AI_MODELS.map((m: any) => { const fullModel = `${m.provider}/${m.model}`; + const available = !activeProviders || activeProviders.has(m.provider); return { ...m, fullModel, alias: modelAliases[fullModel] || m.model, + available, }; - }); + }).filter((m: any) => showAll || m.available); return NextResponse.json({ models }); } catch (error) {