fix(dashboard): cut duplicate API/icon spam, lazy-load provider assets
Share one /api/models fetch via useModelCaps cache, mount ModelSelectModal only when open, stop double fetchModelAliases on CLI tool cards, and resolve provider icons through a session 404 cache with missing PNGs + loading=lazy. Also include Claude Exa MCP toggle (claude-settings + ClaudeToolCard) that was already in the working tree. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
68566f53dc
commit
ccb0842d0a
50 files changed
+612
-392
No files matched your search
@@ -116,26 +116,22 @@ export default function ModelsCard({ providerId, kindFilter, providerAliasOverri
|
||||
const [testingModelId, setTestingModelId] = useState(null);
|
||||
const [testError, setTestError] = useState("");
|
||||
const [showAddCustomModel, setShowAddCustomModel] = useState(false);
|
||||
const [connections, setConnections] = useState([]);
|
||||
|
||||
const providerAlias = providerAliasOverride || getProviderAlias(providerId);
|
||||
const effectiveType = kindFilter || "llm";
|
||||
|
||||
const fetchData = useCallback(async () => {
|
||||
try {
|
||||
const [aliasRes, connRes, customRes] = await Promise.all([
|
||||
const [aliasRes, customRes] = await Promise.all([
|
||||
fetch("/api/models/alias"),
|
||||
fetch("/api/providers", { cache: "no-store" }),
|
||||
fetch("/api/models/custom", { cache: "no-store" }),
|
||||
]);
|
||||
const aliasData = await aliasRes.json();
|
||||
const connData = await connRes.json();
|
||||
const customData = await customRes.json();
|
||||
if (aliasRes.ok) setModelAliases(aliasData.aliases || {});
|
||||
if (connRes.ok) setConnections((connData.connections || []).filter((c) => c.provider === providerId));
|
||||
if (customRes.ok) setCustomModels(customData.models || []);
|
||||
} catch (e) { console.log("ModelsCard fetch error:", e); }
|
||||
}, [providerId]);
|
||||
}, []);
|
||||
|
||||
useEffect(() => { fetchData(); }, [fetchData]);
|
||||
|
||||
@@ -242,7 +238,7 @@ export default function ModelsCard({ providerId, kindFilter, providerAliasOverri
|
||||
onSetAlias={(alias) => handleSetAlias(model.id, alias)}
|
||||
onDeleteAlias={() => handleDeleteAlias(existingAlias)}
|
||||
testStatus={modelTestResults[model.id]}
|
||||
onTest={connections.length > 0 ? () => handleTestModel(model.id) : undefined}
|
||||
onTest={() => handleTestModel(model.id)}
|
||||
isTesting={testingModelId === model.id}
|
||||
isFree={model.isFree}
|
||||
/>
|
||||
@@ -259,7 +255,7 @@ export default function ModelsCard({ providerId, kindFilter, providerAliasOverri
|
||||
onSetAlias={() => {}}
|
||||
onDeleteAlias={() => handleDeleteCustomModel(model.id)}
|
||||
testStatus={modelTestResults[model.id]}
|
||||
onTest={connections.length > 0 ? () => handleTestModel(model.id) : undefined}
|
||||
onTest={() => handleTestModel(model.id)}
|
||||
isTesting={testingModelId === model.id}
|
||||
isCustom
|
||||
/>
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
Toggle,
|
||||
} from "@/shared/components";
|
||||
import ProviderIcon from "@/shared/components/ProviderIcon";
|
||||
import { getProviderIconSrc } from "@/shared/utils/providerIcon";
|
||||
import { OAUTH_PROVIDERS, APIKEY_PROVIDERS } from "@/shared/constants/config";
|
||||
import {
|
||||
FREE_PROVIDERS,
|
||||
@@ -756,12 +757,12 @@ function ApiKeyProviderCard({
|
||||
};
|
||||
|
||||
const getIconPath = () => {
|
||||
if (isCompatible)
|
||||
if (isCompatible && provider.apiType)
|
||||
return provider.apiType === "responses"
|
||||
? "/providers/oai-r.png"
|
||||
: "/providers/oai-cc.png";
|
||||
if (isAnthropicCompatible) return "/providers/anthropic-m.png";
|
||||
return `/providers/${provider.id}.png`;
|
||||
return getProviderIconSrc(provider.id);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
Reference in new issue
Block a user