diff --git a/app/(admin)/settings/admin-settings-client.tsx b/app/(admin)/settings/admin-settings-client.tsx index 58b8636e0..4f718a07c 100644 --- a/app/(admin)/settings/admin-settings-client.tsx +++ b/app/(admin)/settings/admin-settings-client.tsx @@ -151,6 +151,7 @@ type AiModel = { supportsVision: boolean; supportsImageGen: boolean; isEnabled: boolean; + isHidden: boolean; isDefault: boolean; sortOrder: number; isAgentModel?: boolean; @@ -998,6 +999,7 @@ export function AdminSettingsClient() { supportsVision: false, supportsImageGen: false, isEnabled: true, + isHidden: false, isDefault: false, isAgentModel: false, isMultimodal: false, @@ -1856,6 +1858,7 @@ export function AdminSettingsClient() { supportsVision: false, supportsImageGen: false, isEnabled: true, + isHidden: false, isDefault: false, isAgentModel: false, isMultimodal: false, @@ -5820,6 +5823,13 @@ export function AdminSettingsClient() { /> +
+ setModelForm({ ...modelForm, isHidden: checked })} + /> + +
默认} {model.isAgentModel && Agent} {model.isMultimodal && 多模态} + {model.isHidden && 前台隐藏}
ID: {model.modelId} | 提供商: {provider?.name ?? "未知"} @@ -6025,6 +6036,7 @@ export function AdminSettingsClient() { supportsVision: model.supportsVision, supportsImageGen: model.supportsImageGen, isEnabled: model.isEnabled, + isHidden: model.isHidden || false, isDefault: model.isDefault, isAgentModel: model.isAgentModel || false, isMultimodal: model.isMultimodal || false, diff --git a/app/(chat)/api/models/route.ts b/app/(chat)/api/models/route.ts index 89ce3a209..9fa69d63b 100644 --- a/app/(chat)/api/models/route.ts +++ b/app/(chat)/api/models/route.ts @@ -30,12 +30,12 @@ export async function GET() { } // 只获取主模型(不包括子模型),子模型由后端根据 videoParams.mode 自动选择 - const modelsWithProvider = await getEnabledAiModelsWithProvider(false); + const modelsWithProvider = await getEnabledAiModelsWithProvider(false, false); const agentModelWithProvider = await getAgentAiModelWithProvider(); const defaultModel = await getDefaultAiModel(); const visibleModelsWithProvider = sortModelsForDisplay( modelsWithProvider - .filter(({ model }) => !isAiModelAgentAuto(model)) + .filter(({ model }) => !isAiModelAgentAuto(model) && !model.isHidden) .map((item) => item.model) ); const visibleModelIdSet = new Set(visibleModelsWithProvider.map((m) => m.id)); diff --git a/app/(chat)/page.tsx b/app/(chat)/page.tsx index 85a2405a2..0c17ae458 100644 --- a/app/(chat)/page.tsx +++ b/app/(chat)/page.tsx @@ -79,13 +79,13 @@ async function NewChatPage() { // 尝试获取默认模型 const defaultModel = await getDefaultAiModel(); - if (defaultModel && !isAiModelAgentAuto(defaultModel)) { + if (defaultModel && !isAiModelAgentAuto(defaultModel) && !defaultModel.isHidden) { initialModelId = defaultModel.id; } else { // 如果没有设置默认模型,获取第一个启用的模型 - const enabledModels = await getEnabledAiModelsWithProvider(); + const enabledModels = await getEnabledAiModelsWithProvider(false, false); const visibleModels = enabledModels.filter( - ({ model }) => !isAiModelAgentAuto(model) + ({ model }) => !isAiModelAgentAuto(model) && !model.isHidden ); if (visibleModels.length > 0) { initialModelId = visibleModels[0].model.id; diff --git a/app/api/admin/ai-models/route.ts b/app/api/admin/ai-models/route.ts index cdd9d371c..6b91eb0ff 100644 --- a/app/api/admin/ai-models/route.ts +++ b/app/api/admin/ai-models/route.ts @@ -34,6 +34,7 @@ const createModelSchema = z.object({ supportsVision: z.boolean().optional(), supportsImageGen: z.boolean().optional(), isEnabled: z.boolean().optional(), + isHidden: z.boolean().optional(), isDefault: z.boolean().optional(), sortOrder: z.number().optional(), fallbackModelId1: z.string().max(128).optional(), @@ -53,6 +54,7 @@ const updateModelSchema = z.object({ supportsVision: z.boolean().optional(), supportsImageGen: z.boolean().optional(), isEnabled: z.boolean().optional(), + isHidden: z.boolean().optional(), isDefault: z.boolean().optional(), sortOrder: z.number().optional(), fallbackModelId1: z.string().max(128).optional(), diff --git a/components/canvas/CanvasChatPanel.tsx b/components/canvas/CanvasChatPanel.tsx index 63edb5a5d..81b2ed92e 100644 --- a/components/canvas/CanvasChatPanel.tsx +++ b/components/canvas/CanvasChatPanel.tsx @@ -808,7 +808,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF const [videoSlotUploading, setVideoSlotUploading] = useState(null); const [lastImageModelId, setLastImageModelId] = useState(null); const [lastVideoModelId, setLastVideoModelId] = useState(null); - const [deepThinkingEnabled, setDeepThinkingEnabled] = useState(true); + const [deepThinkingEnabled, setDeepThinkingEnabled] = useState(false); const imageParamsRef = useRef(imageParams); const videoParamsRef = useRef(videoParams); const deepThinkingEnabledRef = useRef(deepThinkingEnabled); diff --git a/components/image-params-bar.tsx b/components/image-params-bar.tsx index 12ad8199e..53dc5c40e 100644 --- a/components/image-params-bar.tsx +++ b/components/image-params-bar.tsx @@ -8,7 +8,7 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; -import { Check, Image, Ratio, Monitor, Images, SlidersHorizontal, Ban } from "lucide-react"; +import { Check, SlidersHorizontal } from "lucide-react"; import { cn } from "@/lib/utils"; import { Input } from "@/components/ui/input"; import { Switch } from "@/components/ui/switch"; @@ -183,10 +183,10 @@ export function ImageParamsBar({ @@ -212,10 +212,10 @@ export function ImageParamsBar({ @@ -238,10 +238,10 @@ export function ImageParamsBar({ diff --git a/lib/db/migrations/0039_add_ai_model_hidden.sql b/lib/db/migrations/0039_add_ai_model_hidden.sql new file mode 100644 index 000000000..67f8083bd --- /dev/null +++ b/lib/db/migrations/0039_add_ai_model_hidden.sql @@ -0,0 +1,2 @@ +ALTER TABLE "AiModel" +ADD COLUMN IF NOT EXISTS "isHidden" boolean NOT NULL DEFAULT false; diff --git a/lib/db/migrations/meta/_journal.json b/lib/db/migrations/meta/_journal.json index bdf5947f9..b3ca33da6 100644 --- a/lib/db/migrations/meta/_journal.json +++ b/lib/db/migrations/meta/_journal.json @@ -176,6 +176,13 @@ "when": 1771502400000, "tag": "0038_add_canvas_detail_archives", "breakpoints": true + }, + { + "idx": 25, + "version": "7", + "when": 1771588800000, + "tag": "0039_add_ai_model_hidden", + "breakpoints": true } ] } diff --git a/lib/db/queries.ts b/lib/db/queries.ts index 7ac882807..4dc3ca463 100644 --- a/lib/db/queries.ts +++ b/lib/db/queries.ts @@ -1352,6 +1352,7 @@ export async function createAiModel({ supportsVision, supportsImageGen, isEnabled, + isHidden, isDefault, sortOrder, fallbackModelId1, @@ -1368,6 +1369,7 @@ export async function createAiModel({ supportsVision?: boolean; supportsImageGen?: boolean; isEnabled?: boolean; + isHidden?: boolean; isDefault?: boolean; sortOrder?: number; fallbackModelId1?: string; @@ -1396,6 +1398,7 @@ export async function createAiModel({ supportsVision: supportsVision ?? false, supportsImageGen: supportsImageGen ?? false, isEnabled: isEnabled ?? true, + isHidden: isHidden ?? false, isDefault: isDefault ?? false, sortOrder: sortOrder ?? 0, fallbackModelId1: fallbackModelId1 || null, @@ -1429,6 +1432,7 @@ export async function updateAiModel({ supportsVision, supportsImageGen, isEnabled, + isHidden, isDefault, sortOrder, fallbackModelId1, @@ -1446,6 +1450,7 @@ export async function updateAiModel({ supportsVision?: boolean; supportsImageGen?: boolean; isEnabled?: boolean; + isHidden?: boolean; isDefault?: boolean; sortOrder?: number; fallbackModelId1?: string; @@ -1473,6 +1478,7 @@ export async function updateAiModel({ if (supportsImageGen !== undefined) updateData.supportsImageGen = supportsImageGen; if (isEnabled !== undefined) updateData.isEnabled = isEnabled; + if (isHidden !== undefined) updateData.isHidden = isHidden; if (isDefault !== undefined) updateData.isDefault = isDefault; if (sortOrder !== undefined) updateData.sortOrder = sortOrder; // 备用模型 ID(空字符串转为 null) @@ -1726,7 +1732,10 @@ export async function deleteStorageConfig({ id }: { id: string }) { } // 获取启用的 AI 模型及其提供商信息(用于前端展示) -export async function getEnabledAiModelsWithProvider(includeSubModels: boolean = false) { +export async function getEnabledAiModelsWithProvider( + includeSubModels: boolean = false, + includeHidden: boolean = true +) { try { const conditions = [ eq(aiModel.isEnabled, true), @@ -1737,6 +1746,9 @@ export async function getEnabledAiModelsWithProvider(includeSubModels: boolean = if (!includeSubModels) { conditions.push(eq(aiModel.isSubModel, false)); } + if (!includeHidden) { + conditions.push(eq(aiModel.isHidden, false)); + } const models = await db .select({ diff --git a/lib/db/schema.ts b/lib/db/schema.ts index 5a52d34f5..4d43a8208 100644 --- a/lib/db/schema.ts +++ b/lib/db/schema.ts @@ -284,6 +284,7 @@ export const aiModel = pgTable("AiModel", { supportsVision: boolean("supportsVision").notNull().default(false), // 是否支持图片输入 supportsImageGen: boolean("supportsImageGen").notNull().default(false), // 是否支持图片生成 isEnabled: boolean("isEnabled").notNull().default(true), // 是否启用 + isHidden: boolean("isHidden").notNull().default(false), // 是否在前端模型选择中隐藏 isDefault: boolean("isDefault").notNull().default(false), // 是否为默认模型 sortOrder: integer("sortOrder").notNull().default(0), // 排序顺序 capabilities: jsonb("capabilities"), // 🆕 模型能力配置(用于视频模型)