Fix ModelSelectModal

This commit is contained in:
decolua
2026-04-05 21:25:00 +07:00
parent 67e0db77da
commit 57cfaccceb
4 changed files with 13 additions and 12 deletions

View File

@@ -396,9 +396,7 @@ export const PROVIDER_MODELS = {
{ id: "text-embedding-005", name: "Text Embedding 005", type: "embedding" },
{ id: "text-embedding-004", name: "Text Embedding 004 (Legacy)", type: "embedding" },
],
openrouter: [
// { id: "openrouter/free", name: "Free Models (Auto)" },
],
openrouter: [],
glm: [
{ id: "glm-5.1", name: "GLM 5.1" },
{ id: "glm-5", name: "GLM 5" },

View File

@@ -1,6 +1,6 @@
{
"name": "9router-app",
"version": "0.3.75",
"version": "0.3.78",
"description": "9Router web dashboard",
"private": true,
"scripts": {

View File

@@ -4,11 +4,12 @@ import { useState, useMemo, useEffect } from "react";
import PropTypes from "prop-types";
import Modal from "./Modal";
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 = [
...Object.keys(OAUTH_PROVIDERS),
...Object.keys(FREE_TIER_PROVIDERS),
...Object.keys(APIKEY_PROVIDERS),
];
@@ -57,7 +58,7 @@ export default function ModelSelectModal({
if (isOpen) fetchProviderNodes();
}, [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
const groupedModels = useMemo(() => {
@@ -142,16 +143,18 @@ export default function ModelSelectModal({
const hardcodedModels = getModelsByProviderId(providerId);
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)
.filter(([aliasName, fullModel]) =>
fullModel.startsWith(`${alias}/`) &&
aliasName === fullModel.replace(`${alias}/`, "") &&
(hasHardcoded ? aliasName === fullModel.replace(`${alias}/`, "") : true) &&
!hardcodedIds.has(fullModel.replace(`${alias}/`, ""))
)
.map(([, fullModel]) => {
.map(([aliasName, fullModel]) => {
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 = [

View File

@@ -13,7 +13,7 @@ export const FREE_PROVIDERS = {
// Free Tier Providers (has free access but may require account/API key)
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" } },
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" } },