From 8f9f326229779396f95c6e0789eb2a7c8509095c Mon Sep 17 00:00:00 2001 From: ddCat <2695092045@qq.com> Date: Fri, 28 Aug 2026 14:13:03 +0800 Subject: [PATCH] =?UTF-8?q?fix(platform):=20AutoDL=20=E6=8F=92=E4=BB=B6=20?= =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=E8=A7=86=E9=A2=91=E5=88=86=E8=BE=A8?= =?UTF-8?q?=E7=8E=87=E5=90=8E=E7=BC=80=E4=B8=A2=E5=A4=B1=E5=B9=B6=E5=8D=87?= =?UTF-8?q?=E7=BA=A7=E6=8F=92=E4=BB=B6=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../protocol/autodl_plugin_artifact_test.go | 4 ++-- backend/internal/protocol/builtin_test.go | 17 +++++++++++++++++ .../internal/protocol/docs/autodl-comfyui.md | 2 +- backend/internal/protocol/manifest.go | 15 +++++++++++++++ plugin-packages/autodl-comfyui.yingce-plugin | Bin 2076 -> 2154 bytes plugin-packages/autodl-comfyui/manifest.json | 6 +++--- .../pages/plugins/plugin-development-guide.md | 2 +- 7 files changed, 39 insertions(+), 7 deletions(-) diff --git a/backend/internal/protocol/autodl_plugin_artifact_test.go b/backend/internal/protocol/autodl_plugin_artifact_test.go index 12c057991..ecff94c6e 100644 --- a/backend/internal/protocol/autodl_plugin_artifact_test.go +++ b/backend/internal/protocol/autodl_plugin_artifact_test.go @@ -25,7 +25,7 @@ func TestAutoDLPluginArtifact(t *testing.T) { t.Fatalf("loaded adapters = %d", len(adapters)) } adapter := adapters[0] - if adapter.Metadata().ID != "autodl-comfyui" || adapter.Metadata().Execution != "declarative" { + if adapter.Metadata().ID != "autodl-comfyui" || adapter.Metadata().Version != "1.0.1" || adapter.Metadata().Execution != "declarative" { t.Fatalf("metadata = %#v", adapter.Metadata()) } if !adapter.Metadata().RequiresPublicMediaURLs { @@ -33,7 +33,7 @@ func TestAutoDLPluginArtifact(t *testing.T) { } create, err := adapter.BuildCreate(context.Background(), RequestContext{BaseURL: "https://autodl.art", Request: GenerationRequest{ - Model: "minimax_h3_lightx2v_no_pic", Prompt: "a cinematic test", Duration: 3, Resolution: "768P", Images: []MediaReference{{URL: "https://cdn.example/reference.png"}}, + Model: "minimax_h3_lightx2v_no_pic", Prompt: "a cinematic test", Duration: 3, Resolution: "768", Images: []MediaReference{{URL: "https://cdn.example/reference.png"}}, }}) if err != nil { t.Fatal(err) diff --git a/backend/internal/protocol/builtin_test.go b/backend/internal/protocol/builtin_test.go index 8056838d7..10426f1da 100644 --- a/backend/internal/protocol/builtin_test.go +++ b/backend/internal/protocol/builtin_test.go @@ -365,6 +365,23 @@ func TestDeclarativeManifestSupportsMediaPathsTransformsAndErrors(t *testing.T) } } +func TestDeclarativeManifestNormalizesVideoResolutionWithoutBreakingWorkflowValues(t *testing.T) { + tests := map[string]string{ + "768": "768p", + "768p": "768p", + "768P": "768p", + " 768P ": "768p", + "768p竖": "768p竖", + "768P横": "768p横", + "2K": "2k", + } + for input, expected := range tests { + if actual := applyManifestTransform(input, "video-resolution"); actual != expected { + t.Errorf("video resolution transform %q = %#v, want %q", input, actual, expected) + } + } +} + func TestDeclarativeManifestRequiresDocumentation(t *testing.T) { manifest := Manifest{ APIVersion: "v1", diff --git a/backend/internal/protocol/docs/autodl-comfyui.md b/backend/internal/protocol/docs/autodl-comfyui.md index d401d709e..275293e9e 100644 --- a/backend/internal/protocol/docs/autodl-comfyui.md +++ b/backend/internal/protocol/docs/autodl-comfyui.md @@ -10,7 +10,7 @@ AutoDL 的模型选择对应 ComfyUI 工作流 ID。不同工作流可以声明 ## 参数 -请求体为 JSON。常用字段包括 `prompt`、`duration` 和 `resolution`;实际工作流可以扩展自己的参数 schema。状态返回值位于 `data.status`,任务 ID 位于 `data.task_id`,成功结果位于 `data.results`。结果数组中的地址是短期 URL,成功后必须立即由宿主下载到影策资源存储,不能把临时地址直接写入画布长期数据。 +请求体为 JSON。常用字段包括 `prompt`、`duration` 和 `resolution`;实际工作流可以扩展自己的参数 schema。插件使用 `video-resolution` 字段变换:历史状态中的纯数字 `768` 会发送为 `768p`,已经带后缀的 `768p` 以及工作流值 `768p竖`、`768p横` 保持其语义。状态返回值位于 `data.status`,任务 ID 位于 `data.task_id`,成功结果位于 `data.results`。结果数组中的地址是短期 URL,成功后必须立即由宿主下载到影策资源存储,不能把临时地址直接写入画布长期数据。 ## 鉴权 diff --git a/backend/internal/protocol/manifest.go b/backend/internal/protocol/manifest.go index f5403eb09..e20def879 100644 --- a/backend/internal/protocol/manifest.go +++ b/backend/internal/protocol/manifest.go @@ -554,11 +554,26 @@ func applyManifestTransform(value any, transform string) any { return strings.ToLower(text) case "upper", "uppercase": return strings.ToUpper(text) + case "video-resolution", "video_resolution", "videoresolution": + return normalizeManifestVideoResolution(text) default: return value } } +func normalizeManifestVideoResolution(value string) string { + normalized := strings.ToLower(strings.TrimSpace(value)) + if normalized == "" { + return "" + } + for _, char := range normalized { + if char < '0' || char > '9' { + return normalized + } + } + return normalized + "p" +} + func pathValue(payload map[string]any, path string) any { var value any = payload for _, part := range strings.Split(strings.Trim(path, "."), ".") { diff --git a/plugin-packages/autodl-comfyui.yingce-plugin b/plugin-packages/autodl-comfyui.yingce-plugin index bbcf657bce65ba013919dde260eca9adff58a0d8..87d348c8781a475608813a690e8c6824825c8089 100644 GIT binary patch delta 2131 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 A2E`LSOe?yVi5<(-3E_Y~sDU#5o!g)<&ei=NGFh z0GY?zcddmfupcZB_4Zx9+}+!23xTduM5LpLOAHJyJi9??|J&7bh3IooczeHpazKo% zE`hsw{4j-!OQ4DfiXdBNOp8KC9j+S3Ppn6efs0whSV&V)`OGb&G|z=1yv_$$J8L)l z194S^vdEWkdKsAQ7F^%MPZIS!v2SxF&l1W$!DM^TZBAEmdqi{L0J@c_s;BL6l@wBL z4h#XTQMg|zm!WLIUQ)LA_Sjy3sJy;w78eL)V#iJk&aIfsZ(%f;TQCk*Z#KgM!qUpph-5!CJTpAOJ>@gjjzC)VM?m0UARQ zfrN>VbO4~AvWI19NQm0a2m;0!>5zcLNL?Uj!zr$|H^GiC(5Nk(V)Rjeg<>=mR*~+; zi2NWDUCWksiJL%0-^B$Lk!7u`apb}@ZB)Fq3vJ4|5;tX5cqbOtusM@!YS9sxNF#g0@v7xigc z_hsCrS>aVEZM`w?EGL=M)>`6@@T=`3i4p2KT9GrWfE) zspM0xYH#w;*OS^d_VY!MbQEn0e51L35{XXHq!-5W61!J}sTJzIx17HTeaD8ONv)-$=(8>?C2X=`-6|9l^d z!8R4g$D3Lih8?_rA#T_K0necoY1)F{YE53(S3pz1?ZUjoY8h#Iz^7E}OU0q|s}fh_ zUDS2xkKj~m`MIt@HyZ_M@LYp4z@O!`2g~X9EN47e&a`Ja>%nriJ(& zZ_jeUgXKbdmWv)N7u&ORda!g-7SHZz7{;?}9HENGO`s(Y6K#O>)2Qmdt zs+RU-T-QNc^O7JXPtH*LHR<-Szrj=u9`SLlod`zZF9E5ltojHbXS6?O3~3rf-L$oT1G48mm!fn3je0r#mpn-R4wuDW?R*&F#dyoTPBHeMb($CeVgHS%6=DCu z$D4y78sPo!3EI&^JYD>d<0XQIc-qiS^U<~S&o{TPYsJ^x^J`!7K07gf;&)I>0RkQa t6aWAK2mr2P8eK?@xLTkG008C{000dD000000004#J_sfT%Lf1e006lg?%4nU diff --git a/plugin-packages/autodl-comfyui/manifest.json b/plugin-packages/autodl-comfyui/manifest.json index b3a7dc36a..89ec4c079 100644 --- a/plugin-packages/autodl-comfyui/manifest.json +++ b/plugin-packages/autodl-comfyui/manifest.json @@ -2,10 +2,10 @@ "apiVersion": "yingce.plugin/v1", "id": "autodl-comfyui", "name": "AutoDL ComfyUI 视频", - "version": "1.0.0", + "version": "1.0.1", "author": "影策社区", "description": "通过 AutoDL.Art ComfyUI 工作流 API 接入异步视频生成。", - "documentation": "# AutoDL ComfyUI 视频\n\n## 接口\n\n创建任务:`POST /api/v1/comfyui/comfyui_workflow/{workflow_id}`。清单把渠道中的模型字段作为 `workflow_id`,因此每个 ComfyUI 工作流都可以通过工作流贡献加入,不需要修改宿主代码。\n\n查询任务:`GET /api/v1/comfyui/comfyui_workflow/result/{task_id}`。\n\n## 工作流\n\n示例 `minimax_h3_lightx2v_no_pic` 作为 MiniMax H3 文生视频入口,默认时长为 5 秒、分辨率为 `768p竖`。支持 `480p竖`、`768p竖`、`480p横`、`768p横`。上传后可以在渠道中直接选择该工作流;新增工作流只需扩展本清单。\n\n## 请求与鉴权\n\n创建请求为 JSON,发送 `prompt`、`duration`、`resolution`,并按存在的参考图片发送 `ref_image_0` 至 `ref_image_8`。分辨率字段由插件在发送前统一转换为小写。参考图片由宿主转换为短期签名公网 URL。AutoDL Token 在渠道密钥字段中配置,宿主以后端出站请求发送 `Authorization: Bearer `;清单不包含密钥。\n\n## 状态与结果\n\n`QUEUED` 和 `RUNNING` 映射为统一任务的排队与处理中,`SUCCESS` 和 `completed` 映射为成功,`FAILED` 映射为失败。错误响应的 `code` 和 `msg` 会保留为任务错误。成功结果从 `data.results[].url` 读取为视频地址。AutoDL 地址是短期地址,清单标记为临时结果,宿主会在完成时下载并保存到影策资源存储。\n\n官方文档:[AutoDL ComfyUI API](https://autodl.art/docs/comfyui_api/)。", + "documentation": "# AutoDL ComfyUI 视频\n\n## 接口\n\n创建任务:`POST /api/v1/comfyui/comfyui_workflow/{workflow_id}`。清单把渠道中的模型字段作为 `workflow_id`,因此每个 ComfyUI 工作流都可以通过工作流贡献加入,不需要修改宿主代码。\n\n查询任务:`GET /api/v1/comfyui/comfyui_workflow/result/{task_id}`。\n\n## 工作流\n\n示例 `minimax_h3_lightx2v_no_pic` 作为 MiniMax H3 文生视频入口,默认时长为 5 秒、分辨率为 `768p竖`。支持 `480p竖`、`768p竖`、`480p横`、`768p横`。上传后可以在渠道中直接选择该工作流;新增工作流只需扩展本清单。\n\n## 请求与鉴权\n\n创建请求为 JSON,发送 `prompt`、`duration`、`resolution`,并按存在的参考图片发送 `ref_image_0` 至 `ref_image_8`。分辨率字段由插件在发送前统一 trim 并转换为小写;纯数字值会自动补上 `p`,因此 `768` 与 `768p` 都会发送为 `768p`,`768p竖`、`768p横` 等工作流值保持不变。参考图片由宿主转换为短期签名公网 URL。AutoDL Token 在渠道密钥字段中配置,宿主以后端出站请求发送 `Authorization: Bearer `;清单不包含密钥。\n\n## 状态与结果\n\n`QUEUED` 和 `RUNNING` 映射为统一任务的排队与处理中,`SUCCESS` 和 `completed` 映射为成功,`FAILED` 映射为失败。错误响应的 `code` 和 `msg` 会保留为任务错误。成功结果从 `data.results[].url` 读取为视频地址。AutoDL 地址是短期地址,清单标记为临时结果,宿主会在完成时下载并保存到影策资源存储。\n\n官方文档:[AutoDL ComfyUI API](https://autodl.art/docs/comfyui_api/)。", "permissions": [ "generation.run", "media.read" @@ -70,7 +70,7 @@ "fields": { "prompt": "request.prompt", "duration": "request.duration", - "resolution": "request.resolution|lower", + "resolution": "request.resolution|video-resolution", "ref_image_0": "request.images.0.url", "ref_image_1": "request.images.1.url", "ref_image_2": "request.images.2.url", diff --git a/web/src/pages/plugins/plugin-development-guide.md b/web/src/pages/plugins/plugin-development-guide.md index dd68745f1..699d9c290 100644 --- a/web/src/pages/plugins/plugin-development-guide.md +++ b/web/src/pages/plugins/plugin-development-guide.md @@ -65,7 +65,7 @@ my-plugin.yingce-plugin ## 4. Provider 与工作流 -请求字段右侧只能引用影策统一请求,例如 `request.prompt`、`request.model`、`request.duration`、`request.extra`。声明式字段也支持安全的对象/数组路径(例如 `request.images.0.url`)和字符串变换(`|trim`、`|lower`、`|upper`),不执行插件代码。字段解析为空时会省略该字段,适合映射可选参考素材。Provider 如果把 `requiresPublicMediaUrls` 设为 `true`,宿主会在请求前把用户资源转换为短期签名公网 URL。响应映射支持对象路径和数组下标,并可用 `errorPaths` 声明上游错误码路径。同步 provider 只需要 `create` 和 `response`;异步 provider 再声明 `poll`。 +请求字段右侧只能引用影策统一请求,例如 `request.prompt`、`request.model`、`request.duration`、`request.extra`。声明式字段也支持安全的对象/数组路径(例如 `request.images.0.url`)和字符串变换(`|trim`、`|lower`、`|upper`、`|video-resolution`),不执行插件代码。`video-resolution` 会 trim 并转为小写,仅在输入是纯数字时补上 `p`,因此同时兼容历史状态中的 `768`、标准值 `768p` 和工作流值 `768p竖`。字段解析为空时会省略该字段,适合映射可选参考素材。Provider 如果把 `requiresPublicMediaUrls` 设为 `true`,宿主会在请求前把用户资源转换为短期签名公网 URL。响应映射支持对象路径和数组下标,并可用 `errorPaths` 声明上游错误码路径。同步 provider 只需要 `create` 和 `response`;异步 provider 再声明 `poll`。 结果 URL 如果是短期地址,必须设置 `resultEphemeral: true`。宿主会在任务完成后立即下载并保存资源,画布和任务记录只保存影策资源引用。