feat(*): 模型能力配置 - 支持模型级视频限制校验与协议管理
This commit is contained in:
1 parent
d023182b2f
commit
b518489fdd
36 files changed
+1692
-401
No files matched your search
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user