mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 20:00:47 +00:00
Enhance configuration and model capabilities
This commit is contained in:
@@ -48,7 +48,7 @@ export default function ProviderDetailPage() {
|
||||
const [headerImgError, setHeaderImgError] = useState(false);
|
||||
const [modelTestResults, setModelTestResults] = useState({});
|
||||
const [modelsTestError, setModelsTestError] = useState("");
|
||||
const [testingModelId, setTestingModelId] = useState(null);
|
||||
const [testingModelIds, setTestingModelIds] = useState(() => new Set());
|
||||
const [showAddCustomModel, setShowAddCustomModel] = useState(false);
|
||||
const [selectedConnectionIds, setSelectedConnectionIds] = useState([]);
|
||||
const [bulkProxyPoolId, setBulkProxyPoolId] = useState("__none__");
|
||||
@@ -876,8 +876,8 @@ export default function ProviderDetailPage() {
|
||||
);
|
||||
|
||||
const handleTestModel = async (modelId) => {
|
||||
if (testingModelId) return;
|
||||
setTestingModelId(modelId);
|
||||
if (testingModelIds.has(modelId)) return;
|
||||
setTestingModelIds((prev) => new Set(prev).add(modelId));
|
||||
try {
|
||||
const res = await fetch("/api/models/test", {
|
||||
method: "POST",
|
||||
@@ -891,7 +891,7 @@ export default function ProviderDetailPage() {
|
||||
setModelTestResults((prev) => ({ ...prev, [modelId]: "error" }));
|
||||
setModelsTestError("Network error");
|
||||
} finally {
|
||||
setTestingModelId(null);
|
||||
setTestingModelIds((prev) => { const n = new Set(prev); n.delete(modelId); return n; });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -952,7 +952,7 @@ export default function ProviderDetailPage() {
|
||||
onDeleteAlias={() => handleDeleteAlias(model.alias)}
|
||||
testStatus={modelTestResults[model.id]}
|
||||
onTest={connections.length > 0 || isFreeNoAuth ? () => handleTestModel(model.id) : undefined}
|
||||
isTesting={testingModelId === model.id}
|
||||
isTesting={testingModelIds.has(model.id)}
|
||||
isCustom
|
||||
isFree={false}
|
||||
caps={getCaps(`${providerId}/${model.id}`)}
|
||||
@@ -977,7 +977,7 @@ export default function ProviderDetailPage() {
|
||||
onDeleteAlias={() => handleDeleteAlias(existingAlias)}
|
||||
testStatus={modelTestResults[model.id]}
|
||||
onTest={connections.length > 0 || isFreeNoAuth ? () => handleTestModel(model.id) : undefined}
|
||||
isTesting={testingModelId === model.id}
|
||||
isTesting={testingModelIds.has(model.id)}
|
||||
isFree={model.isFree}
|
||||
onDisable={() => handleDisableModel(model.id)}
|
||||
caps={getCaps(`${providerId}/${model.id}`)}
|
||||
|
||||
@@ -281,15 +281,18 @@ export default function ProvidersPage() {
|
||||
Object.entries(OAUTH_PROVIDERS).filter(([, info]) => !info.hidden && matchSearch(info.name)),
|
||||
"oauth",
|
||||
);
|
||||
const freeEntries = Object.entries(FREE_PROVIDERS).filter(
|
||||
([, info]) => !info.hidden && matchSearch(info.name),
|
||||
);
|
||||
const freeEntries = Object.entries(FREE_PROVIDERS)
|
||||
.filter(([, info]) => !info.hidden && matchSearch(info.name))
|
||||
.sort(([, a], [, b]) => (b.noAuth ? 1 : 0) - (a.noAuth ? 1 : 0));
|
||||
const freeTierEntries = sortByPriority(
|
||||
Object.entries(FREE_TIER_PROVIDERS).filter(
|
||||
([, info]) => !info.hidden && matchSearch(info.name),
|
||||
([, info]) =>
|
||||
!info.hidden &&
|
||||
matchSearch(info.name) &&
|
||||
(info.serviceKinds ?? ["llm"]).includes("llm"),
|
||||
),
|
||||
"freeTier",
|
||||
);
|
||||
).sort(([, a], [, b]) => (b.noAuth ? 1 : 0) - (a.noAuth ? 1 : 0));
|
||||
// API Key: connected providers first, then alphabetical by name
|
||||
const apikeyEntries = Object.entries(APIKEY_PROVIDERS)
|
||||
.filter(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { getCapabilitiesForModel } from "open-sse/providers/capabilities.js";
|
||||
|
||||
// Fetch model capabilities once and expose a lookup by fullModel ("provider/model") or bare model id.
|
||||
export function useModelCaps() {
|
||||
@@ -32,7 +33,11 @@ export function useModelCaps() {
|
||||
if (!key) return null;
|
||||
if (byFull[key]) return byFull[key];
|
||||
const bare = key.includes("/") ? key.slice(key.indexOf("/") + 1) : key;
|
||||
return byId[bare] || null;
|
||||
if (byId[bare]) return byId[bare];
|
||||
// Fallback: compute caps for dynamic models (passthrough/custom/suggested) not in static list
|
||||
const provider = key.includes("/") ? key.slice(0, key.indexOf("/")) : null;
|
||||
const c = getCapabilitiesForModel(provider, bare);
|
||||
return { vision: c.vision, search: c.search, reasoning: c.reasoning };
|
||||
};
|
||||
|
||||
return { getCaps };
|
||||
|
||||
Reference in New Issue
Block a user