feat(*): 模型能力配置 - 支持模型级视频限制校验与协议管理

This commit is contained in:
ddCat committed 2026-08-06 15:34:45 +08:00
1 parent d023182b2f
commit b518489fdd
36 files changed
+1692 -401

No files matched your search

+10 -1
View File
@@ -3,6 +3,7 @@ import { Check, ChevronDown, Coins, Cpu } from "lucide-react";
import { Popover } from "antd";
import { canvasThemes, type CanvasTheme } from "@/lib/canvas-theme";
import { modelCapabilityConfigFor, videoDurationOptions } from "@/lib/model-capabilities";
import { cn } from "@/lib/utils";
import { modelDisplayName, modelOptionLabel, modelOptionName, resolveModelChannel, selectableModelsByCapability, type AiConfig, type ModelCapability } from "@/stores/use-config-store";
import { useThemeStore } from "@/stores/use-theme-store";
@@ -206,6 +207,8 @@ function emptyModelLabel(config: AiConfig, capability?: ModelCapability) {
function ModelLabel({ config, model, capability, theme, creationVariant, showPrice }: { config: AiConfig; model: string; capability?: ModelCapability; theme: (typeof canvasThemes)[keyof typeof canvasThemes]; creationVariant: boolean; showPrice: boolean }) {
const meta = modelMenuMeta(model, capability);
const videoProfile = capability === "video" ? modelCapabilityConfigFor(config, model).video : undefined;
const capabilitySummary = videoProfile ? `${formatDurationSummary(videoProfile)} · ${videoProfile.resolutions.map((item) => item.toUpperCase()).join("/")}` : meta.description;
return (
<span className="flex w-full min-w-0 items-center gap-1.5 overflow-hidden py-0">
<span className="grid size-6 shrink-0 place-items-center rounded-md" style={{ background: theme.toolbar.itemHover }}>
@@ -213,7 +216,7 @@ function ModelLabel({ config, model, capability, theme, creationVariant, showPri
</span>
<span className="min-w-0 flex-1 overflow-hidden">
<span className="block min-w-0 truncate text-[var(--fs-label)] font-medium leading-none">{modelDisplayName(config, model)}</span>
<span className="mt-1 block truncate text-[var(--fs-tiny)]" style={{ color: theme.node.muted }} title={meta.description}>{meta.description}</span>
<span className="mt-1 block truncate text-[var(--fs-tiny)]" style={{ color: theme.node.muted }} title={capabilitySummary}>{capabilitySummary}</span>
</span>
{showPrice ? <ModelPrice price={modelMenuPrice(config, model)} /> : null}
{!creationVariant && meta.time ? <span className="shrink-0 rounded-full px-1.5 py-0.5 text-[var(--fs-tiny)] tabular-nums" style={{ background: theme.toolbar.itemHover, color: theme.node.muted }}>{meta.time}</span> : null}
@@ -221,6 +224,12 @@ function ModelLabel({ config, model, capability, theme, creationVariant, showPri
);
}
function formatDurationSummary(profile: NonNullable<ReturnType<typeof modelCapabilityConfigFor>["video"]>) {
const values = videoDurationOptions(profile);
if (profile.duration.selection === "enum") return values.map((item) => `${item}s`).join("/");
return `${profile.duration.min || values[0]}-${profile.duration.max || values[values.length - 1]}s`;
}
function modelMenuPrice(config: AiConfig, model: string): { value: number; unit: "次" | "秒" } | null | undefined {
if (!model) return undefined;
const channel = resolveModelChannel(config, model);