diff --git a/bun.lock b/bun.lock index 37c07ca..4cac622 100644 --- a/bun.lock +++ b/bun.lock @@ -20,7 +20,7 @@ }, "packages/plugins/xiaoyunque-generation": { "name": "@microvoid/convax-plugin-xiaoyunque-generation", - "version": "0.3.2", + "version": "0.3.3", "dependencies": { "@microvoid/convax-xiaoyunque-mcp": "workspace:*" } @@ -83,7 +83,7 @@ }, "packages/tools/xiaoyunque-mcp": { "name": "@microvoid/convax-xiaoyunque-mcp", - "version": "0.3.0", + "version": "0.3.1", "devDependencies": { "@types/bun": "1.3.14", "typescript": "5.9.3" diff --git a/packages/plugins/xiaoyunque-generation/convax-package.json b/packages/plugins/xiaoyunque-generation/convax-package.json index 24e1745..09a3c5b 100644 --- a/packages/plugins/xiaoyunque-generation/convax-package.json +++ b/packages/plugins/xiaoyunque-generation/convax-package.json @@ -4,7 +4,7 @@ "id": "xiaoyunque-generation", "name": "小云雀生成", "description": "通过宿主管理的小云雀网页授权展示服务状态,并使用小云雀第一方网页能力生成图片和视频。", - "version": "0.3.2", + "version": "0.3.3", "license": "MIT", "compatibility": { "pluginSchema": "convax.plugin/3", @@ -13,7 +13,7 @@ "companions": [ { "command": "convax-xiaoyunque-mcp", - "version": "0.3.0", + "version": "0.3.1", "source": "packages/tools/xiaoyunque-mcp", "targets": [ { diff --git a/packages/plugins/xiaoyunque-generation/package.json b/packages/plugins/xiaoyunque-generation/package.json index 09675a1..a80f4ac 100644 --- a/packages/plugins/xiaoyunque-generation/package.json +++ b/packages/plugins/xiaoyunque-generation/package.json @@ -1,6 +1,6 @@ { "name": "@microvoid/convax-plugin-xiaoyunque-generation", - "version": "0.3.2", + "version": "0.3.3", "private": true, "type": "module", "dependencies": { diff --git a/packages/plugins/xiaoyunque-generation/package/manifest.json b/packages/plugins/xiaoyunque-generation/package/manifest.json index e8a4f7f..8a3a12e 100644 --- a/packages/plugins/xiaoyunque-generation/package/manifest.json +++ b/packages/plugins/xiaoyunque-generation/package/manifest.json @@ -3,35 +3,18 @@ "id": "xiaoyunque-generation", "name": "小云雀生成", "description": "通过宿主管理的小云雀网页授权展示服务状态,并使用小云雀第一方网页能力生成图片和视频。", - "version": "0.3.2", + "version": "0.3.3", "contributes": { "generation": { "models": [ - { "tool": "image.seedream_5.0_pro", "name": "Seedream 5.0 Pro" }, { "tool": "image.seedream_5.0", "name": "Seedream 5.0" }, - { "tool": "image.seedream_4.3", "name": "Seedream 4.3" }, - { "tool": "image.seedream_4.5", "name": "Seedream 4.5" }, - { "tool": "image.seedream_4.1", "name": "Seedream 4.1" }, - { "tool": "image.seedream_4", "name": "Seedream 4" }, - { "tool": "image.nano_banana_pro_1", "name": "Nano Banana Pro 1" }, - { "tool": "image.gpt_image_2", "name": "GPT Image 2" }, + { "tool": "image.seedream_5.0_pro", "name": "Seedream 5.0 Pro" }, { "tool": "video.seedance_2.0_mini_lite", "name": "Seedance 2.0 Mini Lite" }, - { "tool": "video.seedance_2.0_mini", "name": "Seedance 2.0 Mini" }, - { "tool": "video.seedance2.0_fast_vision", "name": "Seedance 2.0 Fast Vision" }, - { "tool": "video.seedance2.0_vision", "name": "Seedance 2.0 Vision" }, - { "tool": "video.seedance2.0_fast_direct", "name": "Seedance 2.0 Fast" }, { "tool": "video.seedance2.0_direct", "name": "Seedance 2.0" }, - { "tool": "video.seedance1.5_direct", "name": "Seedance 1.5" }, - { "tool": "video.seedance_1.0_fast", "name": "Seedance 1.0 Fast" } + { "tool": "video.seedance2.0_vision", "name": "Seedance 2.0 Vision" }, + { "tool": "video.seedance_2.0_mini", "name": "Seedance 2.0 Mini" } ], "tools": [ - { - "id": "image.seedream_5.0_pro", - "title": "小云雀 · Seedream 5.0 Pro", - "description": "使用小云雀 Seedream 5.0 Pro,根据提示词和可选参考图生成图片。", - "output": "image", - "acceptedInputs": ["reference_image"] - }, { "id": "image.seedream_5.0", "title": "小云雀 · Seedream 5.0", @@ -40,44 +23,9 @@ "acceptedInputs": ["reference_image"] }, { - "id": "image.seedream_4.3", - "title": "小云雀 · Seedream 4.3", - "description": "使用小云雀 Seedream 4.3,根据提示词和可选参考图生成图片。", - "output": "image", - "acceptedInputs": ["reference_image"] - }, - { - "id": "image.seedream_4.5", - "title": "小云雀 · Seedream 4.5", - "description": "使用小云雀 Seedream 4.5,根据提示词和可选参考图生成图片。", - "output": "image", - "acceptedInputs": ["reference_image"] - }, - { - "id": "image.seedream_4.1", - "title": "小云雀 · Seedream 4.1", - "description": "使用小云雀 Seedream 4.1,根据提示词和可选参考图生成图片。", - "output": "image", - "acceptedInputs": ["reference_image"] - }, - { - "id": "image.seedream_4", - "title": "小云雀 · Seedream 4", - "description": "使用小云雀 Seedream 4,根据提示词和可选参考图生成图片。", - "output": "image", - "acceptedInputs": ["reference_image"] - }, - { - "id": "image.nano_banana_pro_1", - "title": "小云雀 · Nano Banana Pro 1", - "description": "使用小云雀 Nano Banana Pro 1,根据提示词和可选参考图生成图片。", - "output": "image", - "acceptedInputs": ["reference_image"] - }, - { - "id": "image.gpt_image_2", - "title": "小云雀 · GPT Image 2", - "description": "使用小云雀 GPT Image 2,根据提示词和可选参考图生成图片。", + "id": "image.seedream_5.0_pro", + "title": "小云雀 · Seedream 5.0 Pro", + "description": "使用小云雀 Seedream 5.0 Pro,根据提示词和可选参考图生成图片。", "output": "image", "acceptedInputs": ["reference_image"] }, @@ -89,16 +37,9 @@ "acceptedInputs": ["reference_image", "reference_video", "first_frame", "last_frame", "audio"] }, { - "id": "video.seedance_2.0_mini", - "title": "小云雀 · Seedance 2.0 Mini", - "description": "使用小云雀 Seedance 2.0 Mini,根据提示词和可选多模态参考生成视频。", - "output": "video", - "acceptedInputs": ["reference_image", "reference_video", "first_frame", "last_frame", "audio"] - }, - { - "id": "video.seedance2.0_fast_vision", - "title": "小云雀 · Seedance 2.0 Fast Vision", - "description": "使用小云雀 Seedance 2.0 Fast Vision,根据提示词和可选多模态参考生成视频。", + "id": "video.seedance2.0_direct", + "title": "小云雀 · Seedance 2.0", + "description": "使用小云雀 Seedance 2.0,根据提示词和可选多模态参考生成视频。", "output": "video", "acceptedInputs": ["reference_image", "reference_video", "first_frame", "last_frame", "audio"] }, @@ -110,32 +51,11 @@ "acceptedInputs": ["reference_image", "reference_video", "first_frame", "last_frame", "audio"] }, { - "id": "video.seedance2.0_fast_direct", - "title": "小云雀 · Seedance 2.0 Fast", - "description": "使用小云雀 Seedance 2.0 Fast,根据提示词和可选多模态参考生成视频。", - "output": "video", - "acceptedInputs": ["reference_image", "reference_video", "first_frame", "last_frame", "audio"] - }, - { - "id": "video.seedance2.0_direct", - "title": "小云雀 · Seedance 2.0", - "description": "使用小云雀 Seedance 2.0,根据提示词和可选多模态参考生成视频。", - "output": "video", - "acceptedInputs": ["reference_image", "reference_video", "first_frame", "last_frame", "audio"] - }, - { - "id": "video.seedance1.5_direct", - "title": "小云雀 · Seedance 1.5", - "description": "使用小云雀 Seedance 1.5,根据提示词和可选多模态参考生成视频。", + "id": "video.seedance_2.0_mini", + "title": "小云雀 · Seedance 2.0 Mini", + "description": "使用小云雀 Seedance 2.0 Mini,根据提示词和可选多模态参考生成视频。", "output": "video", "acceptedInputs": ["reference_image", "reference_video", "first_frame", "last_frame", "audio"] - }, - { - "id": "video.seedance_1.0_fast", - "title": "小云雀 · Seedance 1.0 Fast", - "description": "使用小云雀 Seedance 1.0 Fast,根据提示词和可选单张参考图生成视频。", - "output": "video", - "acceptedInputs": ["reference_image"] } ] }, diff --git a/packages/tools/xiaoyunque-mcp/AGENTS.md b/packages/tools/xiaoyunque-mcp/AGENTS.md index 532a7d3..b887270 100644 --- a/packages/tools/xiaoyunque-mcp/AGENTS.md +++ b/packages/tools/xiaoyunque-mcp/AGENTS.md @@ -42,12 +42,11 @@ the Plugin ZIP and must never be imported by Convax packages. contracts: images submit through `agent/submit_run` and poll `agent/get_thread`; video submits the current Canvas direct video-part tool through `agent/submit_run` and polls the same `agent/get_thread` entry-list surface. - Never fall back to the legacy dedicated video-result endpoint. Use an exact model-specific - parameter shape: both Seedance 2.0 Mini variants omit - `resolution`, every Canvas video request omits imitation-video input, and Seedance 1.0 Fast - accepts at most one reference image while omitting video/audio/frame inputs. - Keep the exposed video model catalog synchronized with the first-party - `web_model_config` response rather than marketing pages. Generation envelopes + Never fall back to the legacy dedicated video-result endpoint. Keep the public + catalog limited to the product-governed allowlist in `src/models.ts`; use + first-party `web_model_config` evidence for its raw identifiers rather than + marketing pages. Both Seedance 2.0 Mini variants omit `resolution`, and every + Canvas video request omits imitation-video input. Generation envelopes require an explicit integer `ret: 0` or canonical string `ret: "0"`; task ids must match the client-created ids, and only canonical run states 0 through 9 are accepted. diff --git a/packages/tools/xiaoyunque-mcp/README.md b/packages/tools/xiaoyunque-mcp/README.md index 6e2b0d8..93d8834 100644 --- a/packages/tools/xiaoyunque-mcp/README.md +++ b/packages/tools/xiaoyunque-mcp/README.md @@ -61,15 +61,12 @@ Cookie 从不进入 stdout、日志或 service status。`0600` 只能隔离其 ## 能力 -- 图像:模型目录以当前小云雀第一方 Web 客户端为发现入口,并仅暴露已被 raw - `image_generation` 提交链路接受的 Seedream 5.0/4.x、Nano Banana Pro 1 与 - GPT Image 2,支持 prompt 与参考图。`web_model_config` v5 中出现但被真实 - `get_thread` 以 `unsupported image_model_name` 拒绝的条目不会进入工具目录。 -- 视频:模型目录与请求能力来自当前小云雀第一方 Web 同源配置,包括 Seedance - 1.0 Fast、1.5 与 2.0 系列;使用当前 Canvas 的 direct video-part submit, - 并与生图共享 `get_thread` entry-list 轮询链路。 - Seedance 1.0 Fast 只接受单张参考图,其余当前模型支持参考图、参考视频、音频、 - 首帧与首尾帧。请求体按模型能力裁剪,不向 Mini 系列发送网页端省略的分辨率字段。 +- 图像:只暴露 Seedream 5.0 与 Seedream 5.0 Pro,默认使用 Seedream 5.0;两者 + 均支持 prompt 与参考图。 +- 视频:只暴露 Seedance 2.0、Seedance 2.0 Mini Lite(非 VIP 通道)以及 + Seedance 2.0 Vision、Seedance 2.0 Mini(VIP 通道),默认使用 Seedance 2.0 + Mini Lite。四个模型均支持参考图、参考视频、音频、首帧与首尾帧;请求体不向 Mini + 系列发送网页端省略的分辨率字段。 - 服务:`service.status` 使用同一 Cookie session 读取固定的账号、积分和最近最多 20 条已结算消费记录;缺失或失败的数据返回 `unavailable`,不会猜测。 diff --git a/packages/tools/xiaoyunque-mcp/package.json b/packages/tools/xiaoyunque-mcp/package.json index 943035a..1b24493 100644 --- a/packages/tools/xiaoyunque-mcp/package.json +++ b/packages/tools/xiaoyunque-mcp/package.json @@ -1,6 +1,6 @@ { "name": "@microvoid/convax-xiaoyunque-mcp", - "version": "0.3.0", + "version": "0.3.1", "private": true, "type": "module", "bin": { diff --git a/packages/tools/xiaoyunque-mcp/scripts/live-image-smoke.ts b/packages/tools/xiaoyunque-mcp/scripts/live-image-smoke.ts index c000b4a..2a75550 100644 --- a/packages/tools/xiaoyunque-mcp/scripts/live-image-smoke.ts +++ b/packages/tools/xiaoyunque-mcp/scripts/live-image-smoke.ts @@ -55,7 +55,7 @@ function notify(method: string, params: unknown) { try { const initialized = await request("initialize", { capabilities: {}, - clientInfo: { name: "convax-xiaoyunque-live-smoke", version: "0.3.0" }, + clientInfo: { name: "convax-xiaoyunque-live-smoke", version: "0.3.1" }, protocolVersion: "2025-03-26", }) if ((initialized.result as Record | undefined)?.protocolVersion !== "2025-03-26") { @@ -64,12 +64,12 @@ try { notify("notifications/initialized", {}) const listed = await request("tools/list", {}) const names = ((listed.result as { tools?: Array<{ name?: string }> } | undefined)?.tools ?? []).map((tool) => tool.name) - if (!names.includes("image.seedream_4.5")) { - throw new Error("Sidecar did not expose the verified Seedream 4.5 generation tool") + if (!names.includes("image.seedream_5.0")) { + throw new Error("Sidecar did not expose the default Seedream 5.0 generation tool") } process.stderr.write("将使用 Convax 服务页授权的小云雀网页会话执行一次计费生图。\n") const generated = await request("tools/call", { - name: "image.seedream_4.5", + name: "image.seedream_5.0", arguments: { schema: "convax.generation-call/1", operation_id: `live-image-${crypto.randomUUID()}`, diff --git a/packages/tools/xiaoyunque-mcp/scripts/live-video-smoke.ts b/packages/tools/xiaoyunque-mcp/scripts/live-video-smoke.ts index 4ff44cb..edf0985 100644 --- a/packages/tools/xiaoyunque-mcp/scripts/live-video-smoke.ts +++ b/packages/tools/xiaoyunque-mcp/scripts/live-video-smoke.ts @@ -117,7 +117,7 @@ try { progress("mcp.initialize") const initialized = await request("initialize", { capabilities: {}, - clientInfo: { name: "convax-xiaoyunque-live-video-smoke", version: "0.3.0" }, + clientInfo: { name: "convax-xiaoyunque-live-video-smoke", version: "0.3.1" }, protocolVersion: "2025-03-26", }) if ((initialized.result as Record | undefined)?.protocolVersion !== "2025-03-26") { @@ -130,7 +130,7 @@ try { const names = ((listed.result as { tools?: Array<{ name?: string }> } | undefined)?.tools ?? []) .map((tool) => tool.name) if (!names.includes(toolName)) { - throw new Error("Sidecar did not expose the verified Seedance 2.0 Mini Lite generation tool") + throw new Error("Sidecar did not expose the default Seedance 2.0 Mini Lite generation tool") } process.stderr.write(`${formatSafeGenerationOperation(operationId)}\n`) diff --git a/packages/tools/xiaoyunque-mcp/src/mcp-server.ts b/packages/tools/xiaoyunque-mcp/src/mcp-server.ts index c097bf3..a9ef087 100644 --- a/packages/tools/xiaoyunque-mcp/src/mcp-server.ts +++ b/packages/tools/xiaoyunque-mcp/src/mcp-server.ts @@ -296,7 +296,7 @@ export class McpServer { this.#sendResult(request.id, { capabilities: { tools: {} }, protocolVersion, - serverInfo: { name: "convax-xiaoyunque-mcp", version: "0.3.0" }, + serverInfo: { name: "convax-xiaoyunque-mcp", version: "0.3.1" }, }) return } diff --git a/packages/tools/xiaoyunque-mcp/src/models.ts b/packages/tools/xiaoyunque-mcp/src/models.ts index d2b6f8d..fc6b031 100644 --- a/packages/tools/xiaoyunque-mcp/src/models.ts +++ b/packages/tools/xiaoyunque-mcp/src/models.ts @@ -7,6 +7,8 @@ export interface XiaoYunqueGenerationTool { output: GenerationOutput } +// These unions also cover legacy persisted operations and direct API contract +// tests. Only entries in imageTools/videoTools are exposed through MCP tools/list. export type XiaoYunqueImageModel = | "seedream_5.0_pro" | "seedream_5.0" @@ -30,30 +32,17 @@ export type XiaoYunqueVideoModel = export type XiaoYunqueModel = XiaoYunqueImageModel | XiaoYunqueVideoModel const imageTools = [ - ["seedream_5.0_pro", "image.seedream_5.0_pro", "Seedream 5.0 Pro"], ["seedream_5.0", "image.seedream_5.0", "Seedream 5.0"], - ["seedream_4.3", "image.seedream_4.3", "Seedream 4.3"], - // The live web_model_config v5 catalog can include entries that the raw - // image_generation submit contract does not accept. On 2026-07-20 an - // accepted Nova 2 run terminated through get_thread with the exact reason - // `unsupported image_model_name: nova2`; keep it out of the executable tool - // catalog until that raw submit surface publishes a verified identifier. - ["seedream_4.5", "image.seedream_4.5", "Seedream 4.5"], - ["seedream_4.1", "image.seedream_4.1", "Seedream 4.1"], - ["seedream_4", "image.seedream_4", "Seedream 4"], - ["nano_banana_pro_1", "image.nano_banana_pro_1", "Nano Banana Pro 1"], - ["gpt_image_2", "image.gpt_image_2", "GPT Image 2"], + ["seedream_5.0_pro", "image.seedream_5.0_pro", "Seedream 5.0 Pro"], ] as const satisfies readonly (readonly [XiaoYunqueImageModel, string, string])[] const videoTools = [ + // The first entry is Convax's default video model. It uses the non-VIP channel. ["Seedance_2.0_mini_lite", "video.seedance_2.0_mini_lite", "Seedance 2.0 Mini Lite"], - ["Seedance_2.0_mini", "video.seedance_2.0_mini", "Seedance 2.0 Mini"], - ["seedance2.0_fast_vision", "video.seedance2.0_fast_vision", "Seedance 2.0 Fast Vision"], - ["seedance2.0_vision", "video.seedance2.0_vision", "Seedance 2.0 Vision"], - ["seedance2.0_fast_direct", "video.seedance2.0_fast_direct", "Seedance 2.0 Fast"], ["seedance2.0_direct", "video.seedance2.0_direct", "Seedance 2.0"], - ["seedance1.5_direct", "video.seedance1.5_direct", "Seedance 1.5"], - ["Seedance_1.0_fast", "video.seedance_1.0_fast", "Seedance 1.0 Fast"], + // VIP channel. + ["seedance2.0_vision", "video.seedance2.0_vision", "Seedance 2.0 Vision"], + ["Seedance_2.0_mini", "video.seedance_2.0_mini", "Seedance 2.0 Mini"], ] as const satisfies readonly (readonly [XiaoYunqueVideoModel, string, string])[] export const generationTools = [ diff --git a/packages/tools/xiaoyunque-mcp/test/generator.test.ts b/packages/tools/xiaoyunque-mcp/test/generator.test.ts index 170a410..2792193 100644 --- a/packages/tools/xiaoyunque-mcp/test/generator.test.ts +++ b/packages/tools/xiaoyunque-mcp/test/generator.test.ts @@ -15,7 +15,7 @@ import { XiaoYunqueApi, XiaoYunqueRequestRejectedError } from "../src/xiaoyunque const png = Uint8Array.from([137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 0]) const mp4 = Uint8Array.from([0, 0, 0, 24, 102, 116, 121, 112, 105, 115, 111, 109, 0, 0, 0, 0]) -const imageModel = "seedream_4.5" as const +const imageModel = "seedream_5.0" as const const videoModel = "Seedance_2.0_mini_lite" as const const visionVideoModel = "seedance2.0_vision" as const const directories: string[] = [] @@ -233,7 +233,7 @@ describe("XiaoYunque generation engine", () => { args: {}, image_count: 1, image_resolution: "2K", - model: "seedream_4.5", + model: "seedream_5.0", pippit_asset_ids: [], prompt: imageCall.prompt, ratio: "1:1", diff --git a/packages/tools/xiaoyunque-mcp/test/mcp-process.test.ts b/packages/tools/xiaoyunque-mcp/test/mcp-process.test.ts index 3d8846e..d0ac733 100644 --- a/packages/tools/xiaoyunque-mcp/test/mcp-process.test.ts +++ b/packages/tools/xiaoyunque-mcp/test/mcp-process.test.ts @@ -164,7 +164,7 @@ describe("MCP process", () => { protocolVersion: "2025-03-26", }) const generated = await withTimeout(harness.request("tools/call", { - name: "image.seedream_4.5", + name: "image.seedream_5.0", arguments: { schema: "convax.generation-call/1", operation_id: "missing-authorization-operation", @@ -253,7 +253,7 @@ describe("MCP process", () => { }) expect(initialized).toMatchObject({ result: { - serverInfo: { name: "convax-xiaoyunque-mcp", version: "0.3.0" }, + serverInfo: { name: "convax-xiaoyunque-mcp", version: "0.3.1" }, }, }) const authorization = await harness.request("tools/call", { name: "service.authorize", arguments: {} }) @@ -524,22 +524,12 @@ describe("MCP process", () => { const listed = await harness.request("tools/list", {}) expect((listed.result as { tools: Array<{ name: string }> }).tools.map((tool) => tool.name)) .toEqual([ - "image.seedream_5.0_pro", "image.seedream_5.0", - "image.seedream_4.3", - "image.seedream_4.5", - "image.seedream_4.1", - "image.seedream_4", - "image.nano_banana_pro_1", - "image.gpt_image_2", + "image.seedream_5.0_pro", "video.seedance_2.0_mini_lite", - "video.seedance_2.0_mini", - "video.seedance2.0_fast_vision", - "video.seedance2.0_vision", - "video.seedance2.0_fast_direct", "video.seedance2.0_direct", - "video.seedance1.5_direct", - "video.seedance_1.0_fast", + "video.seedance2.0_vision", + "video.seedance_2.0_mini", "service.status", "service.authorize", "service.reauthorize", @@ -548,7 +538,7 @@ describe("MCP process", () => { "service.sign_out", ]) const generated = await harness.request("tools/call", { - name: "image.seedream_4.5", + name: "image.seedream_5.0", arguments: { schema: "convax.generation-call/1", operation_id: "black-box-operation", @@ -761,7 +751,7 @@ describe("MCP process", () => { protocolVersion: "2025-03-26", }) void harness.request("tools/call", { - name: "image.seedream_4.5", + name: "image.seedream_5.0", arguments: { schema: "convax.generation-call/1", operation_id: "stdin-eof-operation", @@ -858,7 +848,7 @@ describe("MCP process", () => { protocolVersion: "2025-03-26", }) void harness.request("tools/call", { - name: "image.seedream_4.5", + name: "image.seedream_5.0", arguments: { schema: "convax.generation-call/1", operation_id: "sigterm-operation", diff --git a/packages/tools/xiaoyunque-mcp/test/mcp-server-lifecycle.test.ts b/packages/tools/xiaoyunque-mcp/test/mcp-server-lifecycle.test.ts index c62b5ef..b7ec651 100644 --- a/packages/tools/xiaoyunque-mcp/test/mcp-server-lifecycle.test.ts +++ b/packages/tools/xiaoyunque-mcp/test/mcp-server-lifecycle.test.ts @@ -27,7 +27,7 @@ function generationRequest(operationId: string) { references: [], schema: "convax.generation-call/1", }, - name: "image.seedream_4.5", + name: "image.seedream_5.0", }, })}\n` } diff --git a/packages/tools/xiaoyunque-mcp/test/model-catalog.test.ts b/packages/tools/xiaoyunque-mcp/test/model-catalog.test.ts index f2a9471..18dacd8 100644 --- a/packages/tools/xiaoyunque-mcp/test/model-catalog.test.ts +++ b/packages/tools/xiaoyunque-mcp/test/model-catalog.test.ts @@ -5,37 +5,23 @@ import { generationMcpTools, serviceMcpTools } from "../src/mcp-server.ts" import { generationTools } from "../src/models.ts" const expectedCatalog = [ - { model: "seedream_5.0_pro", name: "image.seedream_5.0_pro", output: "image" }, { model: "seedream_5.0", name: "image.seedream_5.0", output: "image" }, - { model: "seedream_4.3", name: "image.seedream_4.3", output: "image" }, - { model: "seedream_4.5", name: "image.seedream_4.5", output: "image" }, - { model: "seedream_4.1", name: "image.seedream_4.1", output: "image" }, - { model: "seedream_4", name: "image.seedream_4", output: "image" }, - { model: "nano_banana_pro_1", name: "image.nano_banana_pro_1", output: "image" }, - { model: "gpt_image_2", name: "image.gpt_image_2", output: "image" }, + { model: "seedream_5.0_pro", name: "image.seedream_5.0_pro", output: "image" }, { model: "Seedance_2.0_mini_lite", name: "video.seedance_2.0_mini_lite", output: "video" }, - { model: "Seedance_2.0_mini", name: "video.seedance_2.0_mini", output: "video" }, - { model: "seedance2.0_fast_vision", name: "video.seedance2.0_fast_vision", output: "video" }, - { model: "seedance2.0_vision", name: "video.seedance2.0_vision", output: "video" }, - { model: "seedance2.0_fast_direct", name: "video.seedance2.0_fast_direct", output: "video" }, { model: "seedance2.0_direct", name: "video.seedance2.0_direct", output: "video" }, - { model: "seedance1.5_direct", name: "video.seedance1.5_direct", output: "video" }, - { model: "Seedance_1.0_fast", name: "video.seedance_1.0_fast", output: "video" }, + { model: "seedance2.0_vision", name: "video.seedance2.0_vision", output: "video" }, + { model: "Seedance_2.0_mini", name: "video.seedance_2.0_mini", output: "video" }, ] as const -describe("XiaoYunque first-party Web model catalog", () => { - test("uses the model values exposed by the current first-party Web client", () => { +describe("XiaoYunque governed model catalog", () => { + test("exposes only the approved image and video models", () => { expect(generationTools.map(({ model, name, output }) => ({ model, name, output }))) .toEqual([...expectedCatalog]) }) - test("excludes web_model_config v5 entries rejected by the raw image submit surface", () => { - // Live regression evidence: get_thread ended an accepted raw-image Nova 2 - // run with the exact terminal reason `unsupported image_model_name: nova2`. - // A discovery catalog entry is not sufficient evidence that submit_run can - // execute it, so this id must remain absent until a valid raw id is verified. - expect(generationTools.map(({ model }) => model)).not.toContain("nova2") - expect(generationTools.map(({ name }) => name)).not.toContain("image.nova2") + test("puts the requested defaults first for each output", () => { + expect(generationTools.filter((tool) => tool.output === "image")[0]?.model).toBe("seedream_5.0") + expect(generationTools.filter((tool) => tool.output === "video")[0]?.model).toBe("Seedance_2.0_mini_lite") }) test("keeps Plugin manifest tool ids identical to MCP tools/list names", async () => { @@ -61,27 +47,24 @@ describe("XiaoYunque first-party Web model catalog", () => { expect(manifestIds).toEqual(expectedCatalog.map((tool) => tool.name)) expect(manifest.contributes.generation.models.map((model) => model.tool)).toEqual(manifestIds) expect(manifest.contributes.generation.models.map((model) => model.name)).toEqual([ - "Seedream 5.0 Pro", "Seedream 5.0", - "Seedream 4.3", - "Seedream 4.5", - "Seedream 4.1", - "Seedream 4", - "Nano Banana Pro 1", - "GPT Image 2", + "Seedream 5.0 Pro", "Seedance 2.0 Mini Lite", - "Seedance 2.0 Mini", - "Seedance 2.0 Fast Vision", - "Seedance 2.0 Vision", - "Seedance 2.0 Fast", "Seedance 2.0", - "Seedance 1.5", - "Seedance 1.0 Fast", + "Seedance 2.0 Vision", + "Seedance 2.0 Mini", ]) const mcpNames: string[] = generationMcpTools.map((tool) => tool.name) expect(mcpNames).toEqual(manifestIds) - expect(manifest.contributes.generation.tools.find((tool) => tool.id === "video.seedance_1.0_fast")?.acceptedInputs) - .toEqual(["reference_image"]) + for (const tool of manifest.contributes.generation.tools.filter((item) => item.id.startsWith("video."))) { + expect(tool.acceptedInputs).toEqual([ + "reference_image", + "reference_video", + "first_frame", + "last_frame", + "audio", + ]) + } }) test("declares service tools separately from generation models", async () => { diff --git a/packages/tools/xiaoyunque-mcp/test/operation-store.test.ts b/packages/tools/xiaoyunque-mcp/test/operation-store.test.ts index b6b554c..6fb1391 100644 --- a/packages/tools/xiaoyunque-mcp/test/operation-store.test.ts +++ b/packages/tools/xiaoyunque-mcp/test/operation-store.test.ts @@ -6,7 +6,7 @@ import type { GenerationCall } from "../src/contracts.ts" import { fingerprintGenerationCall, OperationStore } from "../src/operation-store.ts" const png = Uint8Array.from([137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 0]) -const imageModel = "seedream_4.5" as const +const imageModel = "seedream_5.0" as const const directories: string[] = [] afterEach(async () => { diff --git a/registry/config.json b/registry/config.json index acac10c..f433fc1 100644 --- a/registry/config.json +++ b/registry/config.json @@ -1,4 +1,4 @@ { - "sequence": 21, + "sequence": 22, "yanked": [] } diff --git a/tooling/registry.test.js b/tooling/registry.test.js index 63477bc..dc724c3 100644 --- a/tooling/registry.test.js +++ b/tooling/registry.test.js @@ -67,33 +67,25 @@ describe("source packages", () => { expect(xiaoyunque.manifest.contributes.generation.models.map((model) => model.tool)).toEqual( generationTools.map((tool) => tool.id), ) - expect(xiaoyunque.manifest.contributes.generation.models[0].name).toBe("Seedream 5.0 Pro") + expect(xiaoyunque.manifest.contributes.generation.models[0].name).toBe("Seedream 5.0") + expect(xiaoyunque.manifest.contributes.generation.models.find((model) => model.tool.startsWith("video."))?.name) + .toBe("Seedance 2.0 Mini Lite") expect(generationTools.map((tool) => tool.id)).toEqual([ - "image.seedream_5.0_pro", "image.seedream_5.0", - "image.seedream_4.3", - "image.seedream_4.5", - "image.seedream_4.1", - "image.seedream_4", - "image.nano_banana_pro_1", - "image.gpt_image_2", + "image.seedream_5.0_pro", "video.seedance_2.0_mini_lite", - "video.seedance_2.0_mini", - "video.seedance2.0_fast_vision", - "video.seedance2.0_vision", - "video.seedance2.0_fast_direct", "video.seedance2.0_direct", - "video.seedance1.5_direct", - "video.seedance_1.0_fast", + "video.seedance2.0_vision", + "video.seedance_2.0_mini", ]) for (const tool of generationTools) { - expect(tool.acceptedInputs).toEqual(tool.output === "image" || tool.id === "video.seedance_1.0_fast" + expect(tool.acceptedInputs).toEqual(tool.output === "image" ? ["reference_image"] : ["reference_image", "reference_video", "first_frame", "last_frame", "audio"]) } expect(xiaoyunque.metadata.companions).toEqual([{ command: "convax-xiaoyunque-mcp", - version: "0.3.0", + version: "0.3.1", source: "packages/tools/xiaoyunque-mcp", targets: [{ platform: "darwin", @@ -178,9 +170,9 @@ describe("source packages", () => { expect(readStoredZip(hello.zip).map((entry) => entry.relativePath)).toContain("manifest.json") expect(readStoredZip(xiaoyunque.zip).map((entry) => entry.relativePath)).toEqual(["LICENSE", "manifest.json"]) expect(xiaoyunque.companionAssets.map((asset) => asset.assetName)).toEqual([ - "convax-companion-convax-xiaoyunque-mcp-0.3.0-darwin-arm64", + "convax-companion-convax-xiaoyunque-mcp-0.3.1-darwin-arm64", ]) - expect(xiaoyunque.tag).toBe("plugin-xiaoyunque-generation-v0.3.2") + expect(xiaoyunque.tag).toBe("plugin-xiaoyunque-generation-v0.3.3") expect(await fs.readFile(xiaoyunque.companionAssets[0].path)).toEqual(xiaoyunque.companionAssets[0].data) expect(readStoredZip(skill.zip).map((entry) => entry.relativePath)).toContain("SKILL.md") expect(readStoredZip(ffmpeg.zip).map((entry) => entry.relativePath)).toEqual([ @@ -316,7 +308,7 @@ describe("source packages", () => { expect(helloEntry.artifact.url).toContain("/plugin-hello-convax-v0.2.0/") expect(xiaoyunqueEntry.manifest.schema).toBe("convax.plugin/3") expect(xiaoyunqueEntry.companions[0].targets[0].artifact.url).toContain( - "/convax-companion-convax-xiaoyunque-mcp-0.3.0-darwin-arm64", + "/convax-companion-convax-xiaoyunque-mcp-0.3.1-darwin-arm64", ) expect(firstSkill).not.toHaveProperty("manifest") expect(ffmpegSkillEntry.ownerPluginId).toBe("ffmpeg-tools")