mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
Fix ModelSelectModal
This commit is contained in:
@@ -396,9 +396,7 @@ export const PROVIDER_MODELS = {
|
|||||||
{ id: "text-embedding-005", name: "Text Embedding 005", type: "embedding" },
|
{ id: "text-embedding-005", name: "Text Embedding 005", type: "embedding" },
|
||||||
{ id: "text-embedding-004", name: "Text Embedding 004 (Legacy)", type: "embedding" },
|
{ id: "text-embedding-004", name: "Text Embedding 004 (Legacy)", type: "embedding" },
|
||||||
],
|
],
|
||||||
openrouter: [
|
openrouter: [],
|
||||||
// { id: "openrouter/free", name: "Free Models (Auto)" },
|
|
||||||
],
|
|
||||||
glm: [
|
glm: [
|
||||||
{ id: "glm-5.1", name: "GLM 5.1" },
|
{ id: "glm-5.1", name: "GLM 5.1" },
|
||||||
{ id: "glm-5", name: "GLM 5" },
|
{ id: "glm-5", name: "GLM 5" },
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "9router-app",
|
"name": "9router-app",
|
||||||
"version": "0.3.75",
|
"version": "0.3.78",
|
||||||
"description": "9Router web dashboard",
|
"description": "9Router web dashboard",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ import { useState, useMemo, useEffect } from "react";
|
|||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import Modal from "./Modal";
|
import Modal from "./Modal";
|
||||||
import { getModelsByProviderId, PROVIDER_ID_TO_ALIAS } from "@/shared/constants/models";
|
import { getModelsByProviderId, PROVIDER_ID_TO_ALIAS } from "@/shared/constants/models";
|
||||||
import { OAUTH_PROVIDERS, APIKEY_PROVIDERS, isOpenAICompatibleProvider, isAnthropicCompatibleProvider } from "@/shared/constants/providers";
|
import { OAUTH_PROVIDERS, APIKEY_PROVIDERS, FREE_TIER_PROVIDERS, isOpenAICompatibleProvider, isAnthropicCompatibleProvider } from "@/shared/constants/providers";
|
||||||
|
|
||||||
// Provider order: OAuth first, then API Key (matches dashboard/providers)
|
// Provider order: OAuth first, then Free Tier, then API Key (matches dashboard/providers)
|
||||||
const PROVIDER_ORDER = [
|
const PROVIDER_ORDER = [
|
||||||
...Object.keys(OAUTH_PROVIDERS),
|
...Object.keys(OAUTH_PROVIDERS),
|
||||||
|
...Object.keys(FREE_TIER_PROVIDERS),
|
||||||
...Object.keys(APIKEY_PROVIDERS),
|
...Object.keys(APIKEY_PROVIDERS),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ export default function ModelSelectModal({
|
|||||||
if (isOpen) fetchProviderNodes();
|
if (isOpen) fetchProviderNodes();
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
const allProviders = useMemo(() => ({ ...OAUTH_PROVIDERS, ...APIKEY_PROVIDERS }), []);
|
const allProviders = useMemo(() => ({ ...OAUTH_PROVIDERS, ...FREE_TIER_PROVIDERS, ...APIKEY_PROVIDERS }), []);
|
||||||
|
|
||||||
// Group models by provider with priority order
|
// Group models by provider with priority order
|
||||||
const groupedModels = useMemo(() => {
|
const groupedModels = useMemo(() => {
|
||||||
@@ -142,16 +143,18 @@ export default function ModelSelectModal({
|
|||||||
const hardcodedModels = getModelsByProviderId(providerId);
|
const hardcodedModels = getModelsByProviderId(providerId);
|
||||||
const hardcodedIds = new Set(hardcodedModels.map((m) => m.id));
|
const hardcodedIds = new Set(hardcodedModels.map((m) => m.id));
|
||||||
|
|
||||||
// Custom models user added via "Add Model" button (alias === modelId pattern)
|
// Custom models: if no hardcoded models (e.g. openrouter), show all aliases for this provider
|
||||||
|
// Otherwise only show aliases where aliasName === modelId ("Add Model" button pattern)
|
||||||
|
const hasHardcoded = hardcodedModels.length > 0;
|
||||||
const customModels = Object.entries(modelAliases)
|
const customModels = Object.entries(modelAliases)
|
||||||
.filter(([aliasName, fullModel]) =>
|
.filter(([aliasName, fullModel]) =>
|
||||||
fullModel.startsWith(`${alias}/`) &&
|
fullModel.startsWith(`${alias}/`) &&
|
||||||
aliasName === fullModel.replace(`${alias}/`, "") &&
|
(hasHardcoded ? aliasName === fullModel.replace(`${alias}/`, "") : true) &&
|
||||||
!hardcodedIds.has(fullModel.replace(`${alias}/`, ""))
|
!hardcodedIds.has(fullModel.replace(`${alias}/`, ""))
|
||||||
)
|
)
|
||||||
.map(([, fullModel]) => {
|
.map(([aliasName, fullModel]) => {
|
||||||
const modelId = fullModel.replace(`${alias}/`, "");
|
const modelId = fullModel.replace(`${alias}/`, "");
|
||||||
return { id: modelId, name: modelId, value: fullModel, isCustom: true };
|
return { id: modelId, name: aliasName, value: fullModel, isCustom: true };
|
||||||
});
|
});
|
||||||
|
|
||||||
const allModels = [
|
const allModels = [
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const FREE_PROVIDERS = {
|
|||||||
|
|
||||||
// Free Tier Providers (has free access but may require account/API key)
|
// Free Tier Providers (has free access but may require account/API key)
|
||||||
export const FREE_TIER_PROVIDERS = {
|
export const FREE_TIER_PROVIDERS = {
|
||||||
openrouter: { id: "openrouter", alias: "openrouter", name: "OpenRouter", icon: "router", color: "#F97316", textIcon: "OR", passthroughModels: true, website: "https://openrouter.ai", notice: { text: "Free tier: 27+ free models, no credit card needed, 200 req/day. After $10 credit: 1,000 req/day.", apiKeyUrl: "https://openrouter.ai/settings/keys" }, modelsFetcher: { url: "https://openrouter.ai/api/v1/models", type: "openrouter-free" } },
|
openrouter: { id: "openrouter", alias: "openrouter", name: "OpenRouter", icon: "router", color: "#F97316", textIcon: "OR", website: "https://openrouter.ai", notice: { text: "Free tier: 27+ free models, no credit card needed, 200 req/day. After $10 credit: 1,000 req/day.", apiKeyUrl: "https://openrouter.ai/settings/keys" }, modelsFetcher: { url: "https://openrouter.ai/api/v1/models", type: "openrouter-free" } },
|
||||||
nvidia: { id: "nvidia", alias: "nvidia", name: "NVIDIA NIM", icon: "developer_board", color: "#76B900", textIcon: "NV", website: "https://developer.nvidia.com/nim", notice: { text: "Free access for NVIDIA Developer Program members (prototyping & testing).", apiKeyUrl: "https://build.nvidia.com/settings/api-keys" } },
|
nvidia: { id: "nvidia", alias: "nvidia", name: "NVIDIA NIM", icon: "developer_board", color: "#76B900", textIcon: "NV", website: "https://developer.nvidia.com/nim", notice: { text: "Free access for NVIDIA Developer Program members (prototyping & testing).", apiKeyUrl: "https://build.nvidia.com/settings/api-keys" } },
|
||||||
ollama: { id: "ollama", alias: "ollama", name: "Ollama Cloud", icon: "cloud", color: "#ffffffff", textIcon: "OL", website: "https://ollama.com", notice: { text: "Free tier: light usage, 1 cloud model at a time (limits reset every 5h & 7d). Pro $20/mo · Max $100/mo.", apiKeyUrl: "https://ollama.com/settings/keys" } },
|
ollama: { id: "ollama", alias: "ollama", name: "Ollama Cloud", icon: "cloud", color: "#ffffffff", textIcon: "OL", website: "https://ollama.com", notice: { text: "Free tier: light usage, 1 cloud model at a time (limits reset every 5h & 7d). Pro $20/mo · Max $100/mo.", apiKeyUrl: "https://ollama.com/settings/keys" } },
|
||||||
vertex: { id: "vertex", alias: "vx", name: "Vertex AI", icon: "cloud", color: "#4285F4", textIcon: "VX", website: "https://cloud.google.com/vertex-ai", notice: { text: "New Google Cloud accounts get $300 free credits. Requires GCP project + Service Account with Vertex AI API enabled.", apiKeyUrl: "https://console.cloud.google.com/iam-admin/serviceaccounts" } },
|
vertex: { id: "vertex", alias: "vx", name: "Vertex AI", icon: "cloud", color: "#4285F4", textIcon: "VX", website: "https://cloud.google.com/vertex-ai", notice: { text: "New Google Cloud accounts get $300 free credits. Requires GCP project + Service Account with Vertex AI API enabled.", apiKeyUrl: "https://console.cloud.google.com/iam-admin/serviceaccounts" } },
|
||||||
|
|||||||
Reference in New Issue
Block a user