feat(protocol): 可美 KM Seedream - 接入图片生成与编辑
This commit is contained in:
@@ -9,6 +9,13 @@ const protocols = [definition("disabled-text", "text", false), definition("text"
|
||||
const protocolsWithAudio = [...protocols, definition("audio", "audio")];
|
||||
|
||||
describe("channel model editor drafts", () => {
|
||||
test("Kemei Seedream selection initializes the image profile and preserves pricing", () => {
|
||||
const draft = initialChannelModelValues(null, protocols);
|
||||
draft.priceTiers[0].unitPrice = 19;
|
||||
const next = changeChannelModelCapability({ ...draft, capability: "image", protocol: "km-kemei-seedream", modelKey: "doubao-seedream-5-0-pro-260628" }, [definition("km-kemei-seedream", "image")]);
|
||||
expect(next.capabilityConfig?.image).toMatchObject({ references: { maxImages: 10, maskSupported: false }, maxOutputs: 1, size: { default: "2048x2048" } });
|
||||
expect(next.priceTiers[0].unitPrice).toBe(19);
|
||||
});
|
||||
test("new drafts select an enabled protocol and never share price state", () => {
|
||||
const first = initialChannelModelValues(null, protocols);
|
||||
first.priceTiers[0].unitPrice = 42;
|
||||
|
||||
@@ -11,6 +11,19 @@ import { resolveImageRequestSize, validateImageSize } from "../src/services/api/
|
||||
import { buildGeminiImageGenerationConfig } from "../src/lib/gemini-image";
|
||||
|
||||
describe("统一图片分辨率与宽高比", () => {
|
||||
test("Seedream 5.0 shows 1.5K and retains the exact official 2K wide size", () => {
|
||||
const profile = defaultImageCapabilityConfig("km-kemei-seedream", "doubao-seedream-5-0-pro-260628");
|
||||
const intermediate = renderToStaticMarkup(<ImageSizePicker profile={profile} size="1536x1536" onChange={() => {}} />);
|
||||
expect(intermediate).toMatch(/aria-pressed="true"[^>]*>1\.5K/);
|
||||
expect(intermediate).toContain("1536 × 1536 px");
|
||||
expect(intermediate).not.toMatch(/<button[^>]*>4K/);
|
||||
const wide = renderToStaticMarkup(<ImageSizePicker profile={profile} size="2816x1584" onChange={() => {}} />);
|
||||
expect(wide).toMatch(/aria-pressed="true"[^>]*>2K/);
|
||||
expect(wide).toContain("2816 × 1584 px");
|
||||
const reopened = normalizeModelCapabilityConfig({ version: 1, image: profile });
|
||||
expect(reopened.image?.size.presets?.filter((p) => p.tier === "1.5k")).toHaveLength(8);
|
||||
expect(resolveImageRequestSize(profile, "auto", "1536x1536")?.value).toBe("1536x1536");
|
||||
});
|
||||
test("管理员档位开关按已有比例启用,部分比例不显示为关闭", () => {
|
||||
for (const model of ["midjourney-1k", "midjourney-2k"]) {
|
||||
const profile = defaultImageCapabilityConfig("cangyuan-midjourney-v82", model);
|
||||
|
||||
@@ -3,7 +3,23 @@ import test from "node:test";
|
||||
|
||||
// Bun 直接执行 TypeScript 测试时需要保留扩展名;生产 tsconfig 不包含 test/。
|
||||
import { DEFAULT_VIDEO_PROMPT_MAX_CHARS, defaultModelCapabilityConfig, normalizeImageValue, normalizeVideoValue } from "../src/lib/model-capabilities.ts";
|
||||
import { imageTierAvailable } from "../src/lib/image-size-presets.ts";
|
||||
import { imageTierAvailable, imageResolutionTiers } from "../src/lib/image-size-presets.ts";
|
||||
|
||||
test("Kemei Seedream defaults retain official 1K/1.5K/2K sizes without a 4K preset", () => {
|
||||
for (const model of ["doubao-seedream-5-0-pro-260628", "doubao-seedream-5-0-flash-260915"]) {
|
||||
const image = defaultModelCapabilityConfig("km-kemei-seedream", model).image!;
|
||||
assert.equal(image.references.maxImages, 10);
|
||||
assert.equal(image.references.maskSupported, false);
|
||||
assert.equal(image.maxOutputs, 1);
|
||||
assert.equal(image.size.default, "2048x2048");
|
||||
assert.equal(image.quality.supported, false);
|
||||
assert.equal(image.size.presets!.length, 24);
|
||||
assert.deepEqual([...new Set(image.size.presets!.map((p) => p.tier))], ["1k", "1.5k", "2k"]);
|
||||
assert.equal(image.size.presets!.find((p) => p.size === "2816x1584")?.tier, "2k");
|
||||
assert.ok(imageResolutionTiers(image).includes("1.5k"));
|
||||
}
|
||||
assert.deepEqual(imageResolutionTiers(defaultModelCapabilityConfig("openai-image").image!), ["1k", "2k", "4k"]);
|
||||
});
|
||||
|
||||
test("text multimodal capability is not guessed from a model name", () => {
|
||||
for (const model of ["gpt-4o", "gemini-2.5-pro", "doubao-seed"]) {
|
||||
|
||||
Reference in New Issue
Block a user