refactor(*): 平台架构 - 拆分后端领域模块并同步插件协议与模型能力

This commit is contained in:
ddCat
2026-09-11 14:02:49 +08:00
parent 916043fb5a
commit 6e5cbc8b05
644 changed files with 62731 additions and 2320 deletions

View File

@@ -4,13 +4,74 @@ import { ImageSizePicker } from "../src/components/image-size-picker";
import { applyImageSizeSelection } from "../src/components/image-settings-panel";
import { ImageSizePresetsEditor } from "../src/components/image-size-presets-editor";
import { ModelCapabilityEditor } from "../src/components/model-capability-editor";
import { defaultImageCapabilityConfig, normalizeModelCapabilityConfig } from "../src/lib/model-capabilities";
import { IMAGE_RATIOS, IMAGE_RESOLUTIONS, imagePresetForRatio, imagePresetValue, imageQualityForTier, imageSizeConfigWithPresets, imageSizePresets, imageTierAvailable } from "../src/lib/image-size-presets";
import { defaultImageCapabilityConfig, normalizeImageValue, normalizeModelCapabilityConfig } from "../src/lib/model-capabilities";
import { IMAGE_RATIOS, IMAGE_RESOLUTIONS, imagePresetForRatio, imagePresetValue, imageQualityForSelection, imageQualityForTier, imageSizeConfigWithPresets, imageSizePresets, imageTierAvailable } from "../src/lib/image-size-presets";
import { buildImageResolutionOptions } from "../src/lib/image-resolution-tiers";
import { resolveImageRequestSize, validateImageSize } from "../src/services/api/image-validation";
import { buildGeminiImageGenerationConfig } from "../src/lib/gemini-image";
describe("统一图片分辨率与宽高比", () => {
test("默认 Gemini 质量枚举不能把未启用的 1K 显示出来", () => {
const profile = defaultImageCapabilityConfig("gemini-image", "nano-banana-pro-4k");
profile.size = imageSizeConfigWithPresets(profile, IMAGE_RATIOS.map((ratio) => imagePresetForRatio("4k", ratio)));
expect(profile.quality.supported).toBe(true);
expect(imageTierAvailable(profile, "4k")).toBe(true);
expect(imageTierAvailable(profile, "1k")).toBe(false);
const picker = renderToStaticMarkup(<ImageSizePicker profile={profile} size="16:9" quality="high" onChange={() => {}} />);
expect(picker).toMatch(/aria-pressed="true"[^>]*>4K/);
expect(picker).not.toMatch(/<button[^>]*>1K/);
});
test("无质量参数的固定 4K 模型保留管理员档位,重开及自定义比例不回退 1K", () => {
const profile = defaultImageCapabilityConfig("gemini-image", "nano-banana-pro-4k");
profile.quality = { supported: false, values: [], default: "auto" };
profile.size = imageSizeConfigWithPresets(profile, IMAGE_RATIOS.map((ratio) => imagePresetForRatio("4k", ratio)));
expect(imageTierAvailable(profile, "4k")).toBe(true);
expect(imageTierAvailable(profile, "1k")).toBe(false);
expect(imageQualityForTier(profile, "4k")).toBeUndefined();
const picker = renderToStaticMarkup(<ImageSizePicker profile={profile} size="16:9" onChange={() => {}} />);
expect(picker).toMatch(/aria-pressed="true"[^>]*>4K/);
expect(picker).not.toMatch(/<button[^>]*>[12]K/);
expect(picker).toContain("3840 × 2160 px");
expect(normalizeImageValue(profile, { size: "16:9", quality: "auto" }).quality).toBe("4k");
expect(resolveImageRequestSize(profile, undefined, "16:9")).toEqual({ parameter: "aspect_ratio", value: "16:9" });
profile.size.allowCustom = true;
const custom = renderToStaticMarkup(<ImageSizePicker profile={profile} size="17:11" onChange={() => {}} />);
expect(custom).toMatch(/aria-pressed="true"[^>]*>4K/);
expect(custom).toContain("17:11 ·");
});
test("无质量参数时管理员启用的 1K 和 4K 都对用户开放,未启用的 2K 仍隐藏", () => {
const profile = defaultImageCapabilityConfig("gemini-image", "test");
profile.quality = { supported: false, values: [], default: "auto" };
profile.size = imageSizeConfigWithPresets(profile, [...IMAGE_RATIOS.flatMap((ratio) => [imagePresetForRatio("1k", ratio), imagePresetForRatio("4k", ratio)])]);
expect(imageTierAvailable(profile, "1k")).toBe(true);
expect(imageTierAvailable(profile, "4k")).toBe(true);
expect(imageTierAvailable(profile, "2k")).toBe(false);
expect(imageQualityForSelection(profile, "4k")).toBe("4k");
expect(normalizeImageValue(profile, { size: "16:9", quality: "4k" }).quality).toBe("4k");
expect(buildGeminiImageGenerationConfig("16:9", "4k").imageConfig).toEqual({ aspectRatio: "16:9", imageSize: "4K" });
const picker = renderToStaticMarkup(<ImageSizePicker profile={profile} size="16:9" onChange={() => {}} />);
expect(picker).toMatch(/<button[^>]*>1K/);
expect(picker).toMatch(/<button[^>]*>4K/);
expect(picker).not.toMatch(/<button[^>]*>2K/);
expect(picker).not.toContain("当前协议未配置独立分辨率");
const selected = renderToStaticMarkup(<ImageSizePicker profile={profile} size="16:9" quality="4k" onChange={() => {}} />);
expect(selected).toMatch(/aria-pressed="true"[^>]*>4K/);
expect(selected).not.toMatch(/aria-pressed="true"[^>]*>1K/);
expect(selected).toContain("3840 × 2160 px");
const editor = renderToStaticMarkup(<ImageSizePresetsEditor profile={profile} onChange={() => {}} />);
expect(editor).not.toContain("需先配置此档位对应的质量值,用户端才会开放。");
});
test("真实图片质量字段不被分辨率预设推断覆盖", () => {
const profile = defaultImageCapabilityConfig("gemini-image", "test");
profile.quality = { supported: true, values: ["auto", "low", "medium", "high"], default: "auto" };
profile.size = imageSizeConfigWithPresets(profile, [imagePresetForRatio("2k", "16:9"), imagePresetForRatio("4k", "16:9")]);
expect(normalizeImageValue(profile, { size: "16:9", quality: "auto" }).quality).toBe("auto");
expect(normalizeImageValue(profile, { size: "16:9", quality: "high" }).quality).toBe("high");
});
test("比例协议切换 4K 时同时提交尺寸和真实质量档位", () => {
const changes: Array<[string, string]> = [];
applyImageSizeSelection((key, value) => changes.push([key, value]), "16:9", "high");

View File

@@ -0,0 +1,61 @@
import { describe, expect, test } from "bun:test";
import { renderToStaticMarkup } from "react-dom/server";
import { ImageSizePicker } from "../src/components/image-size-picker";
import { IMAGE_RATIOS, imagePresetForRatio, imageSizeConfigWithPresets, imageTierAvailable } from "../src/lib/image-size-presets";
import { defaultImageCapabilityConfig } from "../src/lib/model-capabilities";
import { projectLogicalCapability } from "../src/lib/user-session";
import { capabilitySpecFromChannelModel, mergeCapabilitySpecs } from "../src/pages/admin/logical-models/model-routing-capabilities";
import type { ChannelModel } from "../src/services/api/wallet";
function channelModelWithPresets(): ChannelModel {
const profile = defaultImageCapabilityConfig("gemini-image", "test");
profile.quality = { supported: false, values: [], default: "auto" };
profile.size = imageSizeConfigWithPresets(profile, IMAGE_RATIOS.flatMap((ratio) => [imagePresetForRatio("1k", ratio), imagePresetForRatio("4k", ratio)]));
return {
id: "cm-1",
channelId: "ch-1",
modelKey: "nano-banana",
displayName: "Nano Banana",
capability: "image",
protocol: "gemini-image",
capabilityConfig: { version: 1, image: profile },
} as ChannelModel;
}
describe("前台模型同步系统模型尺寸档位", () => {
test("供应线路规格保留 aspect_ratio 与 1K/4K 预设", () => {
const spec = capabilitySpecFromChannelModel(channelModelWithPresets());
expect(spec?.imageSize?.parameter).toBe("aspect_ratio");
expect(spec?.imageSize?.presets?.some((preset) => preset.tier === "1k")).toBe(true);
expect(spec?.imageSize?.presets?.some((preset) => preset.tier === "4k")).toBe(true);
expect(spec?.imageSize?.presets?.some((preset) => preset.tier === "2k")).toBe(false);
});
test("前台投影不再把多档压成只有 1K", () => {
const spec = capabilitySpecFromChannelModel(channelModelWithPresets())!;
const projected = projectLogicalCapability(spec, { size: "16:9" }).image!;
expect(projected.size.parameter).toBe("aspect_ratio");
expect(imageTierAvailable(projected, "1k")).toBe(true);
expect(imageTierAvailable(projected, "4k")).toBe(true);
expect(imageTierAvailable(projected, "2k")).toBe(false);
const picker = renderToStaticMarkup(<ImageSizePicker profile={projected} size="16:9" quality="4k" onChange={() => {}} />);
expect(picker).toMatch(/<button[^>]*>1K/);
expect(picker).toMatch(/<button[^>]*>4K/);
expect(picker).not.toMatch(/<button[^>]*>2K/);
expect(picker).toMatch(/aria-pressed="true"[^>]*>4K/);
});
test("合并供应线路时并集 1K/4K 预设", () => {
const oneK = defaultImageCapabilityConfig("gemini-image", "a");
oneK.size = imageSizeConfigWithPresets(oneK, [imagePresetForRatio("1k", "16:9")]);
const fourK = defaultImageCapabilityConfig("gemini-image", "b");
fourK.quality = { supported: false, values: [], default: "auto" };
fourK.size = imageSizeConfigWithPresets(fourK, [imagePresetForRatio("4k", "16:9")]);
const merged = mergeCapabilitySpecs("image", [
capabilitySpecFromChannelModel({ capability: "image", capabilityConfig: { version: 1, image: oneK } } as ChannelModel)!,
capabilitySpecFromChannelModel({ capability: "image", capabilityConfig: { version: 1, image: fourK } } as ChannelModel)!,
]);
expect(merged.imageSize?.parameter).toBe("aspect_ratio");
expect(merged.imageSize?.presets?.map((preset) => preset.tier).sort()).toEqual(["1k", "4k"]);
});
});