diff --git a/plugin-packages/a6api.yingce-plugin b/plugin-packages/a6api.yingce-plugin index cd70adef5..1414493ce 100644 Binary files a/plugin-packages/a6api.yingce-plugin and b/plugin-packages/a6api.yingce-plugin differ diff --git a/plugin-packages/antigravity-proxy.yingce-plugin b/plugin-packages/antigravity-proxy.yingce-plugin index f5ad9ab1f..d7ed5de73 100644 Binary files a/plugin-packages/antigravity-proxy.yingce-plugin and b/plugin-packages/antigravity-proxy.yingce-plugin differ diff --git a/plugin-packages/metaso-h3.yingce-plugin b/plugin-packages/metaso-h3.yingce-plugin index 6b4ece702..f2aea8239 100644 Binary files a/plugin-packages/metaso-h3.yingce-plugin and b/plugin-packages/metaso-h3.yingce-plugin differ diff --git a/plugin-packages/openai-images.yingce-plugin b/plugin-packages/openai-images.yingce-plugin index 0305559ca..385a9f4b5 100644 Binary files a/plugin-packages/openai-images.yingce-plugin and b/plugin-packages/openai-images.yingce-plugin differ diff --git a/plugin-packages/openai-images/docs/interface.md b/plugin-packages/openai-images/docs/interface.md index 0d01706b8..2cce8744a 100644 --- a/plugin-packages/openai-images/docs/interface.md +++ b/plugin-packages/openai-images/docs/interface.md @@ -40,6 +40,8 @@ | `create.contentType` | `"application/json"` | | `create.body.model` | `{"$ref":"request.model"}` | | `create.body.prompt` | `{"$ref":"request.prompt"}` | +| `create.body.images` | `{"$omitEmpty":{"$if":{"condition":{"$gt":[{"$len":{"$ref":"request.images"}},0]},"then":{"$map":{"from":{"$filter":{"from":{"$sortByOrder":{"$ref":"request.images"}},"as":"media","where":{"$ne":[{"$ref":"media.role"},"mask"]}}},"as":"media","in":{"image_url":{"$ref":"media.value"}}}},"else":null}}}` | +| `create.body.mask` | `{"$omitEmpty":{"$if":{"condition":{"$gt":[{"$len":{"$filter":{"from":{"$ref":"request.images"},"as":"media","where":{"$eq":[{"$ref":"media.role"},"mask"]}}}},0]},"then":{"image_url":{"$first":{"$map":{"from":{"$filter":{"from":{"$sortByOrder":{"$ref":"request.images"}},"as":"media","where":{"$eq":[{"$ref":"media.role"},"mask"]}}},"as":"media","in":{"$ref":"media.value"}}}}},"else":null}}}` | | `create.body.n` | `{"$omitEmpty":{"$if":{"condition":{"$gt":[{"$ref":"request.imageCount"},0]},"then":{"$ref":"request.imageCount"},"else":1}}}` | | `create.body.size` | `{"$omitEmpty":{"$if":{"condition":{"$in":[{"$lower":{"$trim":{"$ref":"request.aspectRatio"}}},["","auto"]]},"then":null,"else":{"$ref":"request.aspectRatio"}}}}` | | `create.body.quality` | `{"$omitEmpty":{"$switch":{"cases":[{"when":{"$in":[{"$lower":{"$trim":{"$ref":"request.quality"}}},["1k"]]},"then":"low"},{"when":{"$in":[{"$lower":{"$trim":{"$ref":"request.quality"}}},["2k"]]},"then":"medium"},{"when":{"$in":[{"$lower":{"$trim":{"$ref":"request.quality"}}},["4k"]]},"then":"high"},{"when":{"$in":[{"$lower":{"$trim":{"$ref":"request.quality"}}},["","auto"]]},"then":null}],"default":{"$ref":"request.quality"}}}}` | @@ -47,15 +49,9 @@ | `create.body.output_format` | `{"$omitEmpty":{"$coalesce":[{"$ref":"request.providerOptions.openai-image.output_format"},"png"]}}` | | `create.body.output_compression` | `{"$omitEmpty":{"$ref":"request.providerOptions.openai-image.output_compression"}}` | | `create.body.moderation` | `{"$omitEmpty":{"$ref":"request.providerOptions.openai-image.moderation"}}` | -| `create.body.response_format` | `{"$omitEmpty":{"$coalesce":[{"$ref":"request.providerOptions.openai-image.response_format"},"b64_json"]}}` | +| `create.body.response_format` | `{"$omitEmpty":{"$ref":"request.providerOptions.openai-image.response_format"}}` | | `create.body.style` | `{"$omitEmpty":{"$ref":"request.providerOptions.openai-image.style"}}` | | `create.body.user` | `{"$omitEmpty":{"$ref":"request.providerOptions.openai-image.user"}}` | -| `create.files[0].name` | `"image"` | -| `create.files[0].source` | `{"$filter":{"from":{"$ref":"request.images"},"as":"media","where":{"$ne":[{"$ref":"media.role"},"mask"]}}}` | -| `create.files[0].filename` | `"source.png"` | -| `create.files[1].name` | `"mask"` | -| `create.files[1].source` | `{"$filter":{"from":{"$ref":"request.images"},"as":"media","where":{"$eq":[{"$ref":"media.role"},"mask"]}}}` | -| `create.files[1].filename` | `"mask.png"` | ## Provider 扩展键 @@ -85,7 +81,7 @@ ## 兼容边界 -无参考图走 JSON generations;有参考图或蒙版走 multipart edits。quality 的 1k/2k/4k 映射为 OpenAI low/medium/high。 +无参考图走 JSON generations;有参考图或蒙版走 JSON edits,并按官方 images 数组传入多张 image_url。quality 的 1k/2k/4k 映射为 OpenAI low/medium/high。 ## Manifest 完整接口定义 @@ -131,7 +127,7 @@ "agent" ], "baseUrl": "https://api.openai.com", - "requiresPublicMediaUrls": false, + "requiresPublicMediaUrls": true, "auth": { "type": "bearer", "field": "apiKey" @@ -214,22 +210,6 @@ } }, "contentType": "application/json", - "contentTypeTemplate": { - "$if": { - "condition": { - "$gt": [ - { - "$len": { - "$ref": "request.images" - } - }, - 0 - ] - }, - "then": "multipart/form-data", - "else": "application/json" - } - }, "body": { "model": { "$ref": "request.model" @@ -237,6 +217,111 @@ "prompt": { "$ref": "request.prompt" }, + "images": { + "$omitEmpty": { + "$if": { + "condition": { + "$gt": [ + { + "$len": { + "$ref": "request.images" + } + }, + 0 + ] + }, + "then": { + "$map": { + "from": { + "$filter": { + "from": { + "$sortByOrder": { + "$ref": "request.images" + } + }, + "as": "media", + "where": { + "$ne": [ + { + "$ref": "media.role" + }, + "mask" + ] + } + } + }, + "as": "media", + "in": { + "image_url": { + "$ref": "media.value" + } + } + } + }, + "else": null + } + } + }, + "mask": { + "$omitEmpty": { + "$if": { + "condition": { + "$gt": [ + { + "$len": { + "$filter": { + "from": { + "$ref": "request.images" + }, + "as": "media", + "where": { + "$eq": [ + { + "$ref": "media.role" + }, + "mask" + ] + } + } + } + }, + 0 + ] + }, + "then": { + "image_url": { + "$first": { + "$map": { + "from": { + "$filter": { + "from": { + "$sortByOrder": { + "$ref": "request.images" + } + }, + "as": "media", + "where": { + "$eq": [ + { + "$ref": "media.role" + }, + "mask" + ] + } + } + }, + "as": "media", + "in": { + "$ref": "media.value" + } + } + } + } + }, + "else": null + } + } + }, "n": { "$omitEmpty": { "$if": { @@ -405,12 +490,7 @@ }, "response_format": { "$omitEmpty": { - "$coalesce": [ - { - "$ref": "request.providerOptions.openai-image.response_format" - }, - "b64_json" - ] + "$ref": "request.providerOptions.openai-image.response_format" } }, "style": { @@ -423,49 +503,7 @@ "$ref": "request.providerOptions.openai-image.user" } } - }, - "files": [ - { - "name": "image", - "source": { - "$filter": { - "from": { - "$ref": "request.images" - }, - "as": "media", - "where": { - "$ne": [ - { - "$ref": "media.role" - }, - "mask" - ] - } - } - }, - "filename": "source.png" - }, - { - "name": "mask", - "source": { - "$filter": { - "from": { - "$ref": "request.images" - }, - "as": "media", - "where": { - "$eq": [ - { - "$ref": "media.role" - }, - "mask" - ] - } - } - }, - "filename": "mask.png" - } - ] + } }, "response": { "status": "succeeded", diff --git a/plugin-packages/openai-images/manifest.json b/plugin-packages/openai-images/manifest.json index 289314634..16d42fe95 100644 --- a/plugin-packages/openai-images/manifest.json +++ b/plugin-packages/openai-images/manifest.json @@ -5,7 +5,7 @@ "version": "2.0.0", "author": "OpenAI / 影策", "description": "OpenAI Images 独立请求协议插件。", - "documentation": "# OpenAI Images\n\n该目录是独立官方协议插件源码。后端从生成的 `openai-images.yingce-plugin` 包加载,不依赖系统内置 `host:` 适配器。\n\n完整接口见 [docs/interface.md](docs/interface.md)。\n\n---\n\n# OpenAI Images 接口字段\n\n## 协议身份\n\n- 插件 ID:`openai-images`。\n- Provider ID:`openai-image`。\n- 能力:`image`。\n- 默认 Base URL:`https://api.openai.com`。\n- 鉴权驱动:`bearer`。\n- 创建:`POST /v1/images/generations`。\n- 生命周期:同步响应。\n\n## 配置字段\n\n| 字段 | 类型 | 必填 | 含义 |\n| --- | --- | --- | --- |\n| `apiKey` | secret | 是 | API Key |\n\n## 统一字段映射\n\n| 统一字段 | 类型 | 必填 | 上游映射 | 说明 |\n| --- | --- | --- | --- | --- |\n| `model` | string | 是 | `model` | 图片模型 ID。 |\n| `prompt` | string | 是 | `prompt` | 图片提示词。 |\n| `images` | media[] | 否 | `provider image/reference fields` | 参考图或编辑源图,role 由业务层确定。 |\n| `imageCount` | integer | 否 | `n/sample_count` | 输出数量。 |\n| `aspectRatio` | string | 否 | `size/aspect_ratio` | 比例或尺寸,语义按协议说明。 |\n| `resolution` | string | 否 | `resolution/imageSize` | 分辨率档位。 |\n| `quality` | string | 否 | `quality` | 质量档位。 |\n| `providerOptions` | object | 否 | `provider-specific fields` | 插件命名空间内的厂商扩展字段。 |\n\n## 上游请求模板逐字段清单\n\n下表由插件请求模板生成,覆盖 body、query、headers 和 multipart 文件声明中的每个字段。\n\n| 上游位置 | 值或转换表达式 |\n| --- | --- |\n| `create.method` | `\"POST\"` |\n| `create.path` | `\"/v1/images/generations\"` |\n| `create.contentType` | `\"application/json\"` |\n| `create.body.model` | `{\"$ref\":\"request.model\"}` |\n| `create.body.prompt` | `{\"$ref\":\"request.prompt\"}` |\n| `create.body.n` | `{\"$omitEmpty\":{\"$if\":{\"condition\":{\"$gt\":[{\"$ref\":\"request.imageCount\"},0]},\"then\":{\"$ref\":\"request.imageCount\"},\"else\":1}}}` |\n| `create.body.size` | `{\"$omitEmpty\":{\"$if\":{\"condition\":{\"$in\":[{\"$lower\":{\"$trim\":{\"$ref\":\"request.aspectRatio\"}}},[\"\",\"auto\"]]},\"then\":null,\"else\":{\"$ref\":\"request.aspectRatio\"}}}}` |\n| `create.body.quality` | `{\"$omitEmpty\":{\"$switch\":{\"cases\":[{\"when\":{\"$in\":[{\"$lower\":{\"$trim\":{\"$ref\":\"request.quality\"}}},[\"1k\"]]},\"then\":\"low\"},{\"when\":{\"$in\":[{\"$lower\":{\"$trim\":{\"$ref\":\"request.quality\"}}},[\"2k\"]]},\"then\":\"medium\"},{\"when\":{\"$in\":[{\"$lower\":{\"$trim\":{\"$ref\":\"request.quality\"}}},[\"4k\"]]},\"then\":\"high\"},{\"when\":{\"$in\":[{\"$lower\":{\"$trim\":{\"$ref\":\"request.quality\"}}},[\"\",\"auto\"]]},\"then\":null}],\"default\":{\"$ref\":\"request.quality\"}}}}` |\n| `create.body.background` | `{\"$omitEmpty\":{\"$coalesce\":[{\"$ref\":\"request.providerOptions.openai-image.background\"},{\"$if\":{\"condition\":{\"$eq\":[{\"$ref\":\"request.extra.transparentBackground\"},\"true\"]},\"then\":\"transparent\",\"else\":null}}]}}` |\n| `create.body.output_format` | `{\"$omitEmpty\":{\"$coalesce\":[{\"$ref\":\"request.providerOptions.openai-image.output_format\"},\"png\"]}}` |\n| `create.body.output_compression` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.openai-image.output_compression\"}}` |\n| `create.body.moderation` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.openai-image.moderation\"}}` |\n| `create.body.response_format` | `{\"$omitEmpty\":{\"$coalesce\":[{\"$ref\":\"request.providerOptions.openai-image.response_format\"},\"b64_json\"]}}` |\n| `create.body.style` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.openai-image.style\"}}` |\n| `create.body.user` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.openai-image.user\"}}` |\n| `create.files[0].name` | `\"image\"` |\n| `create.files[0].source` | `{\"$filter\":{\"from\":{\"$ref\":\"request.images\"},\"as\":\"media\",\"where\":{\"$ne\":[{\"$ref\":\"media.role\"},\"mask\"]}}}` |\n| `create.files[0].filename` | `\"source.png\"` |\n| `create.files[1].name` | `\"mask\"` |\n| `create.files[1].source` | `{\"$filter\":{\"from\":{\"$ref\":\"request.images\"},\"as\":\"media\",\"where\":{\"$eq\":[{\"$ref\":\"media.role\"},\"mask\"]}}}` |\n| `create.files[1].filename` | `\"mask.png\"` |\n\n## Provider 扩展键\n\n- `providerOptions.openai-image.background`\n- `providerOptions.openai-image.moderation`\n- `providerOptions.openai-image.output_compression`\n- `providerOptions.openai-image.output_format`\n- `providerOptions.openai-image.response_format`\n- `providerOptions.openai-image.style`\n- `providerOptions.openai-image.user`\n\n动态模型或工作流允许使用文档声明的完整 `parameters/input/extra_body` 对象;该对象是协议本身的开放 schema,不会被宿主裁剪。\n\n## 响应映射逐字段清单\n\n| 映射位置 | 上游路径或转换表达式 |\n| --- | --- |\n| `response.status` | `\"succeeded\"` |\n| `response.images` | `{\"$map\":{\"from\":{\"$ref\":\"response.data\"},\"as\":\"item\",\"in\":{\"url\":{\"$omitEmpty\":{\"$ref\":\"item.url\"}},\"dataUrl\":{\"$if\":{\"condition\":{\"$ref\":\"item.b64_json\"},\"then\":{\"$concat\":[\"data:image/png;base64,\",{\"$ref\":\"item.b64_json\"}]},\"else\":null}}}}}` |\n| `response.usage` | `{\"$ref\":\"response.usage\"}` |\n| `response.errorPaths[0]` | `\"error.code\"` |\n| `response.messagePaths[0]` | `\"error.message\"` |\n\n## 响应与错误\n\n插件把上游 task/status/text/media/usage 映射为统一结果。临时媒体 URL 标记为 ephemeral,由宿主立即下载持久化。HTTP 错误、业务 code 和 error object 保持失败语义,不包装成成功。\n\n## 兼容边界\n\n无参考图走 JSON generations;有参考图或蒙版走 multipart edits。quality 的 1k/2k/4k 映射为 OpenAI low/medium/high。\n\n\n## Manifest 完整接口定义\n\n以下 JSON 与插件包内实际 `manifest.json` 逐字段一致,覆盖插件身份、权限、配置、鉴权、参数、校验、创建、Agent、查询、取消、结果下载、响应和 Agent 响应映射。`documentation` 字段的值就是当前完整文档;为避免文档在自身内部无限递归,JSON 中仅用等义占位文本表示正文。\n\n```json\n{\n \"apiVersion\": \"yingce.plugin/v2\",\n \"id\": \"openai-images\",\n \"name\": \"OpenAI Images\",\n \"version\": \"2.0.0\",\n \"author\": \"OpenAI / 影策\",\n \"description\": \"OpenAI Images 独立请求协议插件。\",\n \"documentation\": \"<当前插件的完整 documentation,由 README.md 与 docs/interface.md 拼接而成;为避免 JSON 递归,此处不重复展开正文。>\",\n \"permissions\": [\n \"generation.run\",\n \"media.read\"\n ],\n \"configuration\": {\n \"fields\": [\n {\n \"name\": \"apiKey\",\n \"type\": \"secret\",\n \"label\": \"API Key\",\n \"required\": true\n }\n ]\n },\n \"contributes\": {\n \"providers\": [\n {\n \"id\": \"openai-image\",\n \"label\": \"OpenAI Images\",\n \"capabilities\": [\n \"image\"\n ],\n \"scopes\": [\n \"admin.system-channel\",\n \"user.custom-channel\",\n \"canvas\",\n \"creation\",\n \"agent\"\n ],\n \"baseUrl\": \"https://api.openai.com\",\n \"requiresPublicMediaUrls\": false,\n \"auth\": {\n \"type\": \"bearer\",\n \"field\": \"apiKey\"\n },\n \"parameters\": [\n {\n \"name\": \"model\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"model\",\n \"description\": \"图片模型 ID。\"\n },\n {\n \"name\": \"prompt\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"prompt\",\n \"description\": \"图片提示词。\"\n },\n {\n \"name\": \"images\",\n \"type\": \"media[]\",\n \"required\": false,\n \"mapping\": \"provider image/reference fields\",\n \"description\": \"参考图或编辑源图,role 由业务层确定。\"\n },\n {\n \"name\": \"imageCount\",\n \"type\": \"integer\",\n \"required\": false,\n \"mapping\": \"n/sample_count\",\n \"description\": \"输出数量。\"\n },\n {\n \"name\": \"aspectRatio\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"size/aspect_ratio\",\n \"description\": \"比例或尺寸,语义按协议说明。\"\n },\n {\n \"name\": \"resolution\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"resolution/imageSize\",\n \"description\": \"分辨率档位。\"\n },\n {\n \"name\": \"quality\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"quality\",\n \"description\": \"质量档位。\"\n },\n {\n \"name\": \"providerOptions\",\n \"type\": \"object\",\n \"required\": false,\n \"mapping\": \"provider-specific fields\",\n \"description\": \"插件命名空间内的厂商扩展字段。\"\n }\n ],\n \"create\": {\n \"method\": \"POST\",\n \"path\": \"/v1/images/generations\",\n \"pathTemplate\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\n \"$ref\": \"request.images\"\n }\n },\n 0\n ]\n },\n \"then\": \"/v1/images/edits\",\n \"else\": \"/v1/images/generations\"\n }\n },\n \"contentType\": \"application/json\",\n \"contentTypeTemplate\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\n \"$ref\": \"request.images\"\n }\n },\n 0\n ]\n },\n \"then\": \"multipart/form-data\",\n \"else\": \"application/json\"\n }\n },\n \"body\": {\n \"model\": {\n \"$ref\": \"request.model\"\n },\n \"prompt\": {\n \"$ref\": \"request.prompt\"\n },\n \"n\": {\n \"$omitEmpty\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$ref\": \"request.imageCount\"\n },\n 0\n ]\n },\n \"then\": {\n \"$ref\": \"request.imageCount\"\n },\n \"else\": 1\n }\n }\n },\n \"size\": {\n \"$omitEmpty\": {\n \"$if\": {\n \"condition\": {\n \"$in\": [\n {\n \"$lower\": {\n \"$trim\": {\n \"$ref\": \"request.aspectRatio\"\n }\n }\n },\n [\n \"\",\n \"auto\"\n ]\n ]\n },\n \"then\": null,\n \"else\": {\n \"$ref\": \"request.aspectRatio\"\n }\n }\n }\n },\n \"quality\": {\n \"$omitEmpty\": {\n \"$switch\": {\n \"cases\": [\n {\n \"when\": {\n \"$in\": [\n {\n \"$lower\": {\n \"$trim\": {\n \"$ref\": \"request.quality\"\n }\n }\n },\n [\n \"1k\"\n ]\n ]\n },\n \"then\": \"low\"\n },\n {\n \"when\": {\n \"$in\": [\n {\n \"$lower\": {\n \"$trim\": {\n \"$ref\": \"request.quality\"\n }\n }\n },\n [\n \"2k\"\n ]\n ]\n },\n \"then\": \"medium\"\n },\n {\n \"when\": {\n \"$in\": [\n {\n \"$lower\": {\n \"$trim\": {\n \"$ref\": \"request.quality\"\n }\n }\n },\n [\n \"4k\"\n ]\n ]\n },\n \"then\": \"high\"\n },\n {\n \"when\": {\n \"$in\": [\n {\n \"$lower\": {\n \"$trim\": {\n \"$ref\": \"request.quality\"\n }\n }\n },\n [\n \"\",\n \"auto\"\n ]\n ]\n },\n \"then\": null\n }\n ],\n \"default\": {\n \"$ref\": \"request.quality\"\n }\n }\n }\n },\n \"background\": {\n \"$omitEmpty\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.openai-image.background\"\n },\n {\n \"$if\": {\n \"condition\": {\n \"$eq\": [\n {\n \"$ref\": \"request.extra.transparentBackground\"\n },\n \"true\"\n ]\n },\n \"then\": \"transparent\",\n \"else\": null\n }\n }\n ]\n }\n },\n \"output_format\": {\n \"$omitEmpty\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.openai-image.output_format\"\n },\n \"png\"\n ]\n }\n },\n \"output_compression\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.openai-image.output_compression\"\n }\n },\n \"moderation\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.openai-image.moderation\"\n }\n },\n \"response_format\": {\n \"$omitEmpty\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.openai-image.response_format\"\n },\n \"b64_json\"\n ]\n }\n },\n \"style\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.openai-image.style\"\n }\n },\n \"user\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.openai-image.user\"\n }\n }\n },\n \"files\": [\n {\n \"name\": \"image\",\n \"source\": {\n \"$filter\": {\n \"from\": {\n \"$ref\": \"request.images\"\n },\n \"as\": \"media\",\n \"where\": {\n \"$ne\": [\n {\n \"$ref\": \"media.role\"\n },\n \"mask\"\n ]\n }\n }\n },\n \"filename\": \"source.png\"\n },\n {\n \"name\": \"mask\",\n \"source\": {\n \"$filter\": {\n \"from\": {\n \"$ref\": \"request.images\"\n },\n \"as\": \"media\",\n \"where\": {\n \"$eq\": [\n {\n \"$ref\": \"media.role\"\n },\n \"mask\"\n ]\n }\n }\n },\n \"filename\": \"mask.png\"\n }\n ]\n },\n \"response\": {\n \"status\": \"succeeded\",\n \"images\": {\n \"$map\": {\n \"from\": {\n \"$ref\": \"response.data\"\n },\n \"as\": \"item\",\n \"in\": {\n \"url\": {\n \"$omitEmpty\": {\n \"$ref\": \"item.url\"\n }\n },\n \"dataUrl\": {\n \"$if\": {\n \"condition\": {\n \"$ref\": \"item.b64_json\"\n },\n \"then\": {\n \"$concat\": [\n \"data:image/png;base64,\",\n {\n \"$ref\": \"item.b64_json\"\n }\n ]\n },\n \"else\": null\n }\n }\n }\n }\n },\n \"usage\": {\n \"$ref\": \"response.usage\"\n },\n \"errorPaths\": [\n \"error.code\"\n ],\n \"messagePaths\": [\n \"error.message\"\n ]\n }\n }\n ]\n }\n}\n```\n\n", + "documentation": "# OpenAI Images\n\n该目录是独立官方协议插件源码。后端从生成的 `openai-images.yingce-plugin` 包加载,不依赖系统内置 `host:` 适配器。\n\n完整接口见 [docs/interface.md](docs/interface.md)。\n\n---\n\n# OpenAI Images 接口字段\n\n## 协议身份\n\n- 插件 ID:`openai-images`。\n- Provider ID:`openai-image`。\n- 能力:`image`。\n- 默认 Base URL:`https://api.openai.com`。\n- 鉴权驱动:`bearer`。\n- 创建:`POST /v1/images/generations`。\n- 生命周期:同步响应。\n\n## 配置字段\n\n| 字段 | 类型 | 必填 | 含义 |\n| --- | --- | --- | --- |\n| `apiKey` | secret | 是 | API Key |\n\n## 统一字段映射\n\n| 统一字段 | 类型 | 必填 | 上游映射 | 说明 |\n| --- | --- | --- | --- | --- |\n| `model` | string | 是 | `model` | 图片模型 ID。 |\n| `prompt` | string | 是 | `prompt` | 图片提示词。 |\n| `images` | media[] | 否 | `provider image/reference fields` | 参考图或编辑源图,role 由业务层确定。 |\n| `imageCount` | integer | 否 | `n/sample_count` | 输出数量。 |\n| `aspectRatio` | string | 否 | `size/aspect_ratio` | 比例或尺寸,语义按协议说明。 |\n| `resolution` | string | 否 | `resolution/imageSize` | 分辨率档位。 |\n| `quality` | string | 否 | `quality` | 质量档位。 |\n| `providerOptions` | object | 否 | `provider-specific fields` | 插件命名空间内的厂商扩展字段。 |\n\n## 上游请求模板逐字段清单\n\n下表由插件请求模板生成,覆盖 body、query、headers 和 multipart 文件声明中的每个字段。\n\n| 上游位置 | 值或转换表达式 |\n| --- | --- |\n| `create.method` | `\"POST\"` |\n| `create.path` | `\"/v1/images/generations\"` |\n| `create.contentType` | `\"application/json\"` |\n| `create.body.model` | `{\"$ref\":\"request.model\"}` |\n| `create.body.prompt` | `{\"$ref\":\"request.prompt\"}` |\n| `create.body.images` | `{\"$omitEmpty\":{\"$if\":{\"condition\":{\"$gt\":[{\"$len\":{\"$ref\":\"request.images\"}},0]},\"then\":{\"$map\":{\"from\":{\"$filter\":{\"from\":{\"$sortByOrder\":{\"$ref\":\"request.images\"}},\"as\":\"media\",\"where\":{\"$ne\":[{\"$ref\":\"media.role\"},\"mask\"]}}},\"as\":\"media\",\"in\":{\"image_url\":{\"$ref\":\"media.value\"}}}},\"else\":null}}}` |\n| `create.body.mask` | `{\"$omitEmpty\":{\"$if\":{\"condition\":{\"$gt\":[{\"$len\":{\"$filter\":{\"from\":{\"$ref\":\"request.images\"},\"as\":\"media\",\"where\":{\"$eq\":[{\"$ref\":\"media.role\"},\"mask\"]}}}},0]},\"then\":{\"image_url\":{\"$first\":{\"$map\":{\"from\":{\"$filter\":{\"from\":{\"$sortByOrder\":{\"$ref\":\"request.images\"}},\"as\":\"media\",\"where\":{\"$eq\":[{\"$ref\":\"media.role\"},\"mask\"]}}},\"as\":\"media\",\"in\":{\"$ref\":\"media.value\"}}}}},\"else\":null}}}` |\n| `create.body.n` | `{\"$omitEmpty\":{\"$if\":{\"condition\":{\"$gt\":[{\"$ref\":\"request.imageCount\"},0]},\"then\":{\"$ref\":\"request.imageCount\"},\"else\":1}}}` |\n| `create.body.size` | `{\"$omitEmpty\":{\"$if\":{\"condition\":{\"$in\":[{\"$lower\":{\"$trim\":{\"$ref\":\"request.aspectRatio\"}}},[\"\",\"auto\"]]},\"then\":null,\"else\":{\"$ref\":\"request.aspectRatio\"}}}}` |\n| `create.body.quality` | `{\"$omitEmpty\":{\"$switch\":{\"cases\":[{\"when\":{\"$in\":[{\"$lower\":{\"$trim\":{\"$ref\":\"request.quality\"}}},[\"1k\"]]},\"then\":\"low\"},{\"when\":{\"$in\":[{\"$lower\":{\"$trim\":{\"$ref\":\"request.quality\"}}},[\"2k\"]]},\"then\":\"medium\"},{\"when\":{\"$in\":[{\"$lower\":{\"$trim\":{\"$ref\":\"request.quality\"}}},[\"4k\"]]},\"then\":\"high\"},{\"when\":{\"$in\":[{\"$lower\":{\"$trim\":{\"$ref\":\"request.quality\"}}},[\"\",\"auto\"]]},\"then\":null}],\"default\":{\"$ref\":\"request.quality\"}}}}` |\n| `create.body.background` | `{\"$omitEmpty\":{\"$coalesce\":[{\"$ref\":\"request.providerOptions.openai-image.background\"},{\"$if\":{\"condition\":{\"$eq\":[{\"$ref\":\"request.extra.transparentBackground\"},\"true\"]},\"then\":\"transparent\",\"else\":null}}]}}` |\n| `create.body.output_format` | `{\"$omitEmpty\":{\"$coalesce\":[{\"$ref\":\"request.providerOptions.openai-image.output_format\"},\"png\"]}}` |\n| `create.body.output_compression` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.openai-image.output_compression\"}}` |\n| `create.body.moderation` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.openai-image.moderation\"}}` |\n| `create.body.response_format` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.openai-image.response_format\"}}` |\n| `create.body.style` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.openai-image.style\"}}` |\n| `create.body.user` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.openai-image.user\"}}` |\n\n## Provider 扩展键\n\n- `providerOptions.openai-image.background`\n- `providerOptions.openai-image.moderation`\n- `providerOptions.openai-image.output_compression`\n- `providerOptions.openai-image.output_format`\n- `providerOptions.openai-image.response_format`\n- `providerOptions.openai-image.style`\n- `providerOptions.openai-image.user`\n\n动态模型或工作流允许使用文档声明的完整 `parameters/input/extra_body` 对象;该对象是协议本身的开放 schema,不会被宿主裁剪。\n\n## 响应映射逐字段清单\n\n| 映射位置 | 上游路径或转换表达式 |\n| --- | --- |\n| `response.status` | `\"succeeded\"` |\n| `response.images` | `{\"$map\":{\"from\":{\"$ref\":\"response.data\"},\"as\":\"item\",\"in\":{\"url\":{\"$omitEmpty\":{\"$ref\":\"item.url\"}},\"dataUrl\":{\"$if\":{\"condition\":{\"$ref\":\"item.b64_json\"},\"then\":{\"$concat\":[\"data:image/png;base64,\",{\"$ref\":\"item.b64_json\"}]},\"else\":null}}}}}` |\n| `response.usage` | `{\"$ref\":\"response.usage\"}` |\n| `response.errorPaths[0]` | `\"error.code\"` |\n| `response.messagePaths[0]` | `\"error.message\"` |\n\n## 响应与错误\n\n插件把上游 task/status/text/media/usage 映射为统一结果。临时媒体 URL 标记为 ephemeral,由宿主立即下载持久化。HTTP 错误、业务 code 和 error object 保持失败语义,不包装成成功。\n\n## 兼容边界\n\n无参考图走 JSON generations;有参考图或蒙版走 JSON edits,并按官方 images 数组传入多张 image_url。quality 的 1k/2k/4k 映射为 OpenAI low/medium/high。\n\n\n## Manifest 完整接口定义\n\n以下 JSON 与插件包内实际 `manifest.json` 逐字段一致,覆盖插件身份、权限、配置、鉴权、参数、校验、创建、Agent、查询、取消、结果下载、响应和 Agent 响应映射。`documentation` 字段的值就是当前完整文档;为避免文档在自身内部无限递归,JSON 中仅用等义占位文本表示正文。\n\n```json\n{\n \"apiVersion\": \"yingce.plugin/v2\",\n \"id\": \"openai-images\",\n \"name\": \"OpenAI Images\",\n \"version\": \"2.0.0\",\n \"author\": \"OpenAI / 影策\",\n \"description\": \"OpenAI Images 独立请求协议插件。\",\n \"documentation\": \"<当前插件的完整 documentation,由 README.md 与 docs/interface.md 拼接而成;为避免 JSON 递归,此处不重复展开正文。>\",\n \"permissions\": [\n \"generation.run\",\n \"media.read\"\n ],\n \"configuration\": {\n \"fields\": [\n {\n \"name\": \"apiKey\",\n \"type\": \"secret\",\n \"label\": \"API Key\",\n \"required\": true\n }\n ]\n },\n \"contributes\": {\n \"providers\": [\n {\n \"id\": \"openai-image\",\n \"label\": \"OpenAI Images\",\n \"capabilities\": [\n \"image\"\n ],\n \"scopes\": [\n \"admin.system-channel\",\n \"user.custom-channel\",\n \"canvas\",\n \"creation\",\n \"agent\"\n ],\n \"baseUrl\": \"https://api.openai.com\",\n \"requiresPublicMediaUrls\": true,\n \"auth\": {\n \"type\": \"bearer\",\n \"field\": \"apiKey\"\n },\n \"parameters\": [\n {\n \"name\": \"model\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"model\",\n \"description\": \"图片模型 ID。\"\n },\n {\n \"name\": \"prompt\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"prompt\",\n \"description\": \"图片提示词。\"\n },\n {\n \"name\": \"images\",\n \"type\": \"media[]\",\n \"required\": false,\n \"mapping\": \"provider image/reference fields\",\n \"description\": \"参考图或编辑源图,role 由业务层确定。\"\n },\n {\n \"name\": \"imageCount\",\n \"type\": \"integer\",\n \"required\": false,\n \"mapping\": \"n/sample_count\",\n \"description\": \"输出数量。\"\n },\n {\n \"name\": \"aspectRatio\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"size/aspect_ratio\",\n \"description\": \"比例或尺寸,语义按协议说明。\"\n },\n {\n \"name\": \"resolution\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"resolution/imageSize\",\n \"description\": \"分辨率档位。\"\n },\n {\n \"name\": \"quality\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"quality\",\n \"description\": \"质量档位。\"\n },\n {\n \"name\": \"providerOptions\",\n \"type\": \"object\",\n \"required\": false,\n \"mapping\": \"provider-specific fields\",\n \"description\": \"插件命名空间内的厂商扩展字段。\"\n }\n ],\n \"create\": {\n \"method\": \"POST\",\n \"path\": \"/v1/images/generations\",\n \"pathTemplate\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\n \"$ref\": \"request.images\"\n }\n },\n 0\n ]\n },\n \"then\": \"/v1/images/edits\",\n \"else\": \"/v1/images/generations\"\n }\n },\n \"contentType\": \"application/json\",\n \"body\": {\n \"model\": {\n \"$ref\": \"request.model\"\n },\n \"prompt\": {\n \"$ref\": \"request.prompt\"\n },\n \"images\": {\n \"$omitEmpty\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\n \"$ref\": \"request.images\"\n }\n },\n 0\n ]\n },\n \"then\": {\n \"$map\": {\n \"from\": {\n \"$filter\": {\n \"from\": {\n \"$sortByOrder\": {\n \"$ref\": \"request.images\"\n }\n },\n \"as\": \"media\",\n \"where\": {\n \"$ne\": [\n {\n \"$ref\": \"media.role\"\n },\n \"mask\"\n ]\n }\n }\n },\n \"as\": \"media\",\n \"in\": {\n \"image_url\": {\n \"$ref\": \"media.value\"\n }\n }\n }\n },\n \"else\": null\n }\n }\n },\n \"mask\": {\n \"$omitEmpty\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\n \"$filter\": {\n \"from\": {\n \"$ref\": \"request.images\"\n },\n \"as\": \"media\",\n \"where\": {\n \"$eq\": [\n {\n \"$ref\": \"media.role\"\n },\n \"mask\"\n ]\n }\n }\n }\n },\n 0\n ]\n },\n \"then\": {\n \"image_url\": {\n \"$first\": {\n \"$map\": {\n \"from\": {\n \"$filter\": {\n \"from\": {\n \"$sortByOrder\": {\n \"$ref\": \"request.images\"\n }\n },\n \"as\": \"media\",\n \"where\": {\n \"$eq\": [\n {\n \"$ref\": \"media.role\"\n },\n \"mask\"\n ]\n }\n }\n },\n \"as\": \"media\",\n \"in\": {\n \"$ref\": \"media.value\"\n }\n }\n }\n }\n },\n \"else\": null\n }\n }\n },\n \"n\": {\n \"$omitEmpty\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$ref\": \"request.imageCount\"\n },\n 0\n ]\n },\n \"then\": {\n \"$ref\": \"request.imageCount\"\n },\n \"else\": 1\n }\n }\n },\n \"size\": {\n \"$omitEmpty\": {\n \"$if\": {\n \"condition\": {\n \"$in\": [\n {\n \"$lower\": {\n \"$trim\": {\n \"$ref\": \"request.aspectRatio\"\n }\n }\n },\n [\n \"\",\n \"auto\"\n ]\n ]\n },\n \"then\": null,\n \"else\": {\n \"$ref\": \"request.aspectRatio\"\n }\n }\n }\n },\n \"quality\": {\n \"$omitEmpty\": {\n \"$switch\": {\n \"cases\": [\n {\n \"when\": {\n \"$in\": [\n {\n \"$lower\": {\n \"$trim\": {\n \"$ref\": \"request.quality\"\n }\n }\n },\n [\n \"1k\"\n ]\n ]\n },\n \"then\": \"low\"\n },\n {\n \"when\": {\n \"$in\": [\n {\n \"$lower\": {\n \"$trim\": {\n \"$ref\": \"request.quality\"\n }\n }\n },\n [\n \"2k\"\n ]\n ]\n },\n \"then\": \"medium\"\n },\n {\n \"when\": {\n \"$in\": [\n {\n \"$lower\": {\n \"$trim\": {\n \"$ref\": \"request.quality\"\n }\n }\n },\n [\n \"4k\"\n ]\n ]\n },\n \"then\": \"high\"\n },\n {\n \"when\": {\n \"$in\": [\n {\n \"$lower\": {\n \"$trim\": {\n \"$ref\": \"request.quality\"\n }\n }\n },\n [\n \"\",\n \"auto\"\n ]\n ]\n },\n \"then\": null\n }\n ],\n \"default\": {\n \"$ref\": \"request.quality\"\n }\n }\n }\n },\n \"background\": {\n \"$omitEmpty\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.openai-image.background\"\n },\n {\n \"$if\": {\n \"condition\": {\n \"$eq\": [\n {\n \"$ref\": \"request.extra.transparentBackground\"\n },\n \"true\"\n ]\n },\n \"then\": \"transparent\",\n \"else\": null\n }\n }\n ]\n }\n },\n \"output_format\": {\n \"$omitEmpty\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.openai-image.output_format\"\n },\n \"png\"\n ]\n }\n },\n \"output_compression\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.openai-image.output_compression\"\n }\n },\n \"moderation\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.openai-image.moderation\"\n }\n },\n \"response_format\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.openai-image.response_format\"\n }\n },\n \"style\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.openai-image.style\"\n }\n },\n \"user\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.openai-image.user\"\n }\n }\n }\n },\n \"response\": {\n \"status\": \"succeeded\",\n \"images\": {\n \"$map\": {\n \"from\": {\n \"$ref\": \"response.data\"\n },\n \"as\": \"item\",\n \"in\": {\n \"url\": {\n \"$omitEmpty\": {\n \"$ref\": \"item.url\"\n }\n },\n \"dataUrl\": {\n \"$if\": {\n \"condition\": {\n \"$ref\": \"item.b64_json\"\n },\n \"then\": {\n \"$concat\": [\n \"data:image/png;base64,\",\n {\n \"$ref\": \"item.b64_json\"\n }\n ]\n },\n \"else\": null\n }\n }\n }\n }\n },\n \"usage\": {\n \"$ref\": \"response.usage\"\n },\n \"errorPaths\": [\n \"error.code\"\n ],\n \"messagePaths\": [\n \"error.message\"\n ]\n }\n }\n ]\n }\n}\n```\n\n", "permissions": [ "generation.run", "media.read" @@ -36,7 +36,7 @@ "agent" ], "baseUrl": "https://api.openai.com", - "requiresPublicMediaUrls": false, + "requiresPublicMediaUrls": true, "auth": { "type": "bearer", "field": "apiKey" @@ -119,22 +119,6 @@ } }, "contentType": "application/json", - "contentTypeTemplate": { - "$if": { - "condition": { - "$gt": [ - { - "$len": { - "$ref": "request.images" - } - }, - 0 - ] - }, - "then": "multipart/form-data", - "else": "application/json" - } - }, "body": { "model": { "$ref": "request.model" @@ -142,6 +126,111 @@ "prompt": { "$ref": "request.prompt" }, + "images": { + "$omitEmpty": { + "$if": { + "condition": { + "$gt": [ + { + "$len": { + "$ref": "request.images" + } + }, + 0 + ] + }, + "then": { + "$map": { + "from": { + "$filter": { + "from": { + "$sortByOrder": { + "$ref": "request.images" + } + }, + "as": "media", + "where": { + "$ne": [ + { + "$ref": "media.role" + }, + "mask" + ] + } + } + }, + "as": "media", + "in": { + "image_url": { + "$ref": "media.value" + } + } + } + }, + "else": null + } + } + }, + "mask": { + "$omitEmpty": { + "$if": { + "condition": { + "$gt": [ + { + "$len": { + "$filter": { + "from": { + "$ref": "request.images" + }, + "as": "media", + "where": { + "$eq": [ + { + "$ref": "media.role" + }, + "mask" + ] + } + } + } + }, + 0 + ] + }, + "then": { + "image_url": { + "$first": { + "$map": { + "from": { + "$filter": { + "from": { + "$sortByOrder": { + "$ref": "request.images" + } + }, + "as": "media", + "where": { + "$eq": [ + { + "$ref": "media.role" + }, + "mask" + ] + } + } + }, + "as": "media", + "in": { + "$ref": "media.value" + } + } + } + } + }, + "else": null + } + } + }, "n": { "$omitEmpty": { "$if": { @@ -310,12 +399,7 @@ }, "response_format": { "$omitEmpty": { - "$coalesce": [ - { - "$ref": "request.providerOptions.openai-image.response_format" - }, - "b64_json" - ] + "$ref": "request.providerOptions.openai-image.response_format" } }, "style": { @@ -328,49 +412,7 @@ "$ref": "request.providerOptions.openai-image.user" } } - }, - "files": [ - { - "name": "image", - "source": { - "$filter": { - "from": { - "$ref": "request.images" - }, - "as": "media", - "where": { - "$ne": [ - { - "$ref": "media.role" - }, - "mask" - ] - } - } - }, - "filename": "source.png" - }, - { - "name": "mask", - "source": { - "$filter": { - "from": { - "$ref": "request.images" - }, - "as": "media", - "where": { - "$eq": [ - { - "$ref": "media.role" - }, - "mask" - ] - } - } - }, - "filename": "mask.png" - } - ] + } }, "response": { "status": "succeeded", diff --git a/plugin-packages/src-a6api/README.md b/plugin-packages/src-a6api/README.md index 7bb76ee60..afeacbe92 100644 --- a/plugin-packages/src-a6api/README.md +++ b/plugin-packages/src-a6api/README.md @@ -17,4 +17,4 @@ A6api 模型网关协议插件。统一入口 `https://api.a6api.com`,OpenAI - 模型名以 A6api 模型市场当前列表为准。 - 图像编辑(带参考图)走 `/images/edits` multipart 请求。 -- 错误体为 OpenAI 风格,携带 `request_id`。 \ No newline at end of file +- 错误体为 OpenAI 风格,携带 `request_id`。 diff --git a/plugin-packages/src-a6api/docs/interface.md b/plugin-packages/src-a6api/docs/interface.md index 48bade060..d50b716d3 100644 --- a/plugin-packages/src-a6api/docs/interface.md +++ b/plugin-packages/src-a6api/docs/interface.md @@ -26,4 +26,497 @@ POST `https://api.a6api.com/images/edits`(multipart,带参考图时使用) ## 模型列表 -GET `https://api.a6api.com/models` \ No newline at end of file +GET `https://api.a6api.com/models` + + +## Manifest 完整接口定义 + +以下 JSON 与插件包内实际 `manifest.json` 逐字段一致,覆盖插件身份、权限、配置、鉴权、参数、校验、创建、Agent、查询、取消、结果下载、响应和 Agent 响应映射。`documentation` 字段的值就是当前完整文档;为避免文档在自身内部无限递归,JSON 中仅用等义占位文本表示正文。 + +```json +{ + "apiVersion": "yingce.plugin/v2", + "id": "a6api", + "name": "A6api", + "version": "1.0.0", + "author": "A6api", + "description": "A6api 模型网关协议插件:OpenAI 兼容对话与图像生成。", + "permissions": [ + "generation.run", + "media.read" + ], + "configuration": { + "fields": [ + { + "name": "apiKey", + "type": "secret", + "label": "API Key", + "required": true + } + ] + }, + "contributes": { + "providers": [ + { + "id": "a6api-chat", + "label": "A6api Chat", + "capabilities": [ + "text" + ], + "scopes": [ + "admin.system-channel", + "user.custom-channel", + "canvas", + "creation", + "agent" + ], + "baseUrl": "https://api.a6api.com", + "auth": { + "type": "bearer", + "field": "apiKey" + }, + "parameters": [ + { + "name": "model", + "type": "string", + "required": true, + "mapping": "model", + "description": "A6api 模型市场中的模型 ID。" + }, + { + "name": "messages", + "type": "message[]", + "required": true, + "mapping": "provider message container", + "description": "包含历史消息和当前用户输入。" + }, + { + "name": "instructions", + "type": "string", + "required": false, + "mapping": "system/instructions", + "description": "系统指令。" + }, + { + "name": "temperature", + "type": "number", + "required": false, + "mapping": "temperature", + "description": "采样温度。" + }, + { + "name": "top_p", + "type": "number", + "required": false, + "mapping": "top_p", + "description": "核采样参数。" + }, + { + "name": "max_tokens", + "type": "integer", + "required": false, + "mapping": "max_tokens/max_output_tokens", + "description": "最大输出 token。" + }, + { + "name": "tools", + "type": "array", + "required": false, + "mapping": "tools/toolConfig", + "description": "工具定义。" + }, + { + "name": "tool_choice", + "type": "object|string", + "required": false, + "mapping": "tool_choice", + "description": "工具选择策略。" + }, + { + "name": "response_format", + "type": "object", + "required": false, + "mapping": "response_format/text", + "description": "结构化输出配置。" + }, + { + "name": "stream", + "type": "boolean", + "required": false, + "mapping": "stream", + "description": "流式开关;后台任务当前以最终响应归一。" + }, + { + "name": "providerOptions", + "type": "object", + "required": false, + "mapping": "provider-specific fields", + "description": "插件命名空间内的厂商扩展字段。" + } + ], + "create": { + "method": "POST", + "path": "/chat/completions", + "contentType": "application/json", + "body": { + "model": { + "$ref": "request.model" + }, + "messages": { + "$ref": "request.messages" + }, + "temperature": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.temperature" + } + }, + "top_p": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.top_p" + } + }, + "max_tokens": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.extra.max_tokens" + }, + { + "$ref": "request.providerOptions.a6api-chat.max_tokens" + } + ] + } + }, + "tools": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.tools" + } + }, + "tool_choice": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.tool_choice" + } + }, + "response_format": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.response_format" + } + }, + "stream": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.stream" + } + }, + "stop": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.stop" + } + }, + "seed": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.seed" + } + }, + "frequency_penalty": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.frequency_penalty" + } + }, + "presence_penalty": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.presence_penalty" + } + }, + "user": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.user" + } + } + } + }, + "response": { + "status": "succeeded", + "textPaths": [ + "choices.0.message.content", + "choices.0.text" + ], + "reasoningPaths": [ + "choices.0.message.reasoning_content" + ], + "usage": { + "$ref": "response.usage" + }, + "errorPaths": [ + "error.code" + ], + "messagePaths": [ + "error.message" + ] + } + }, + { + "id": "a6api-image", + "label": "A6api Image", + "capabilities": [ + "image" + ], + "scopes": [ + "admin.system-channel", + "user.custom-channel", + "canvas", + "creation", + "agent" + ], + "baseUrl": "https://api.a6api.com", + "auth": { + "type": "bearer", + "field": "apiKey" + }, + "parameters": [ + { + "name": "model", + "type": "string", + "required": true, + "mapping": "model", + "description": "A6api 模型市场中的图像模型 ID。" + }, + { + "name": "prompt", + "type": "string", + "required": true, + "mapping": "prompt", + "description": "图片提示词。" + }, + { + "name": "images", + "type": "media[]", + "required": false, + "mapping": "provider image/reference fields", + "description": "参考图或编辑源图,role 由业务层确定。" + }, + { + "name": "imageCount", + "type": "integer", + "required": false, + "mapping": "n/sample_count", + "description": "输出数量。" + }, + { + "name": "aspectRatio", + "type": "string", + "required": false, + "mapping": "size/aspect_ratio", + "description": "比例或尺寸,语义按协议说明。" + }, + { + "name": "resolution", + "type": "string", + "required": false, + "mapping": "resolution/imageSize", + "description": "分辨率档位。" + }, + { + "name": "quality", + "type": "string", + "required": false, + "mapping": "quality", + "description": "质量档位。" + }, + { + "name": "providerOptions", + "type": "object", + "required": false, + "mapping": "provider-specific fields", + "description": "插件命名空间内的厂商扩展字段。" + } + ], + "create": { + "method": "POST", + "path": "/images/generations", + "pathTemplate": { + "$if": { + "condition": { + "$gt": [ + { + "$len": { + "$ref": "request.images" + } + }, + 0 + ] + }, + "then": "/images/edits", + "else": "/images/generations" + } + }, + "contentType": "application/json", + "contentTypeTemplate": { + "$if": { + "condition": { + "$gt": [ + { + "$len": { + "$ref": "request.images" + } + }, + 0 + ] + }, + "then": "multipart/form-data", + "else": "application/json" + } + }, + "body": { + "model": { + "$ref": "request.model" + }, + "prompt": { + "$ref": "request.prompt" + }, + "n": { + "$omitEmpty": { + "$if": { + "condition": { + "$gt": [ + { + "$ref": "request.imageCount" + }, + 0 + ] + }, + "then": { + "$ref": "request.imageCount" + }, + "else": 1 + } + } + }, + "size": { + "$omitEmpty": { + "$ref": "request.aspectRatio" + } + }, + "quality": { + "$omitEmpty": { + "$ref": "request.quality" + } + }, + "output_format": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.providerOptions.a6api-image.output_format" + }, + "png" + ] + } + }, + "response_format": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.providerOptions.a6api-image.response_format" + }, + "b64_json" + ] + } + }, + "user": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-image.user" + } + } + }, + "files": [ + { + "name": "image", + "source": { + "$filter": { + "from": { + "$ref": "request.images" + }, + "as": "media", + "where": { + "$ne": [ + { + "$ref": "media.role" + }, + "mask" + ] + } + } + }, + "filename": "source.png" + }, + { + "name": "mask", + "source": { + "$filter": { + "from": { + "$ref": "request.images" + }, + "as": "media", + "where": { + "$eq": [ + { + "$ref": "media.role" + }, + "mask" + ] + } + } + }, + "filename": "mask.png" + } + ] + }, + "response": { + "status": "succeeded", + "images": { + "$map": { + "from": { + "$ref": "response.data" + }, + "as": "item", + "in": { + "url": { + "$omitEmpty": { + "$ref": "item.url" + } + }, + "dataUrl": { + "$if": { + "condition": { + "$ref": "item.b64_json" + }, + "then": { + "$concat": [ + "data:image/png;base64,", + { + "$ref": "item.b64_json" + } + ] + }, + "else": null + } + } + } + } + }, + "usage": { + "$ref": "response.usage" + }, + "errorPaths": [ + "error.code" + ], + "messagePaths": [ + "error.message" + ] + } + } + ] + }, + "documentation": "<当前插件的完整 documentation,由 README.md 与 docs/interface.md 拼接而成;为避免 JSON 递归,此处不重复展开正文。>" +} +``` + diff --git a/plugin-packages/src-a6api/manifest.json b/plugin-packages/src-a6api/manifest.json index 8bb12ca02..2278f2780 100644 --- a/plugin-packages/src-a6api/manifest.json +++ b/plugin-packages/src-a6api/manifest.json @@ -5,10 +5,18 @@ "version": "1.0.0", "author": "A6api", "description": "A6api 模型网关协议插件:OpenAI 兼容对话与图像生成。", - "permissions": ["generation.run", "media.read"], + "permissions": [ + "generation.run", + "media.read" + ], "configuration": { "fields": [ - { "name": "apiKey", "type": "secret", "label": "API Key", "required": true } + { + "name": "apiKey", + "type": "secret", + "label": "API Key", + "required": true + } ] }, "contributes": { @@ -16,76 +24,291 @@ { "id": "a6api-chat", "label": "A6api Chat", - "capabilities": ["text"], - "scopes": ["admin.system-channel", "user.custom-channel", "canvas", "creation", "agent"], + "capabilities": [ + "text" + ], + "scopes": [ + "admin.system-channel", + "user.custom-channel", + "canvas", + "creation", + "agent" + ], "baseUrl": "https://api.a6api.com", - "auth": { "type": "bearer", "field": "apiKey" }, + "auth": { + "type": "bearer", + "field": "apiKey" + }, "parameters": [ - { "name": "model", "type": "string", "required": true, "mapping": "model", "description": "A6api 模型市场中的模型 ID。" }, - { "name": "messages", "type": "message[]", "required": true, "mapping": "provider message container", "description": "包含历史消息和当前用户输入。" }, - { "name": "instructions", "type": "string", "required": false, "mapping": "system/instructions", "description": "系统指令。" }, - { "name": "temperature", "type": "number", "required": false, "mapping": "temperature", "description": "采样温度。" }, - { "name": "top_p", "type": "number", "required": false, "mapping": "top_p", "description": "核采样参数。" }, - { "name": "max_tokens", "type": "integer", "required": false, "mapping": "max_tokens/max_output_tokens", "description": "最大输出 token。" }, - { "name": "tools", "type": "array", "required": false, "mapping": "tools/toolConfig", "description": "工具定义。" }, - { "name": "tool_choice", "type": "object|string", "required": false, "mapping": "tool_choice", "description": "工具选择策略。" }, - { "name": "response_format", "type": "object", "required": false, "mapping": "response_format/text", "description": "结构化输出配置。" }, - { "name": "stream", "type": "boolean", "required": false, "mapping": "stream", "description": "流式开关;后台任务当前以最终响应归一。" }, - { "name": "providerOptions", "type": "object", "required": false, "mapping": "provider-specific fields", "description": "插件命名空间内的厂商扩展字段。" } + { + "name": "model", + "type": "string", + "required": true, + "mapping": "model", + "description": "A6api 模型市场中的模型 ID。" + }, + { + "name": "messages", + "type": "message[]", + "required": true, + "mapping": "provider message container", + "description": "包含历史消息和当前用户输入。" + }, + { + "name": "instructions", + "type": "string", + "required": false, + "mapping": "system/instructions", + "description": "系统指令。" + }, + { + "name": "temperature", + "type": "number", + "required": false, + "mapping": "temperature", + "description": "采样温度。" + }, + { + "name": "top_p", + "type": "number", + "required": false, + "mapping": "top_p", + "description": "核采样参数。" + }, + { + "name": "max_tokens", + "type": "integer", + "required": false, + "mapping": "max_tokens/max_output_tokens", + "description": "最大输出 token。" + }, + { + "name": "tools", + "type": "array", + "required": false, + "mapping": "tools/toolConfig", + "description": "工具定义。" + }, + { + "name": "tool_choice", + "type": "object|string", + "required": false, + "mapping": "tool_choice", + "description": "工具选择策略。" + }, + { + "name": "response_format", + "type": "object", + "required": false, + "mapping": "response_format/text", + "description": "结构化输出配置。" + }, + { + "name": "stream", + "type": "boolean", + "required": false, + "mapping": "stream", + "description": "流式开关;后台任务当前以最终响应归一。" + }, + { + "name": "providerOptions", + "type": "object", + "required": false, + "mapping": "provider-specific fields", + "description": "插件命名空间内的厂商扩展字段。" + } ], "create": { "method": "POST", "path": "/chat/completions", "contentType": "application/json", "body": { - "model": { "$ref": "request.model" }, - "messages": { "$ref": "request.messages" }, - "temperature": { "$omitEmpty": { "$ref": "request.providerOptions.a6api-chat.temperature" } }, - "top_p": { "$omitEmpty": { "$ref": "request.providerOptions.a6api-chat.top_p" } }, - "max_tokens": { "$omitEmpty": { "$coalesce": [ { "$ref": "request.extra.max_tokens" }, { "$ref": "request.providerOptions.a6api-chat.max_tokens" } ] } }, - "tools": { "$omitEmpty": { "$ref": "request.providerOptions.a6api-chat.tools" } }, - "tool_choice": { "$omitEmpty": { "$ref": "request.providerOptions.a6api-chat.tool_choice" } }, - "response_format": { "$omitEmpty": { "$ref": "request.providerOptions.a6api-chat.response_format" } }, - "stream": { "$omitEmpty": { "$ref": "request.providerOptions.a6api-chat.stream" } }, - "stop": { "$omitEmpty": { "$ref": "request.providerOptions.a6api-chat.stop" } }, - "seed": { "$omitEmpty": { "$ref": "request.providerOptions.a6api-chat.seed" } }, - "frequency_penalty": { "$omitEmpty": { "$ref": "request.providerOptions.a6api-chat.frequency_penalty" } }, - "presence_penalty": { "$omitEmpty": { "$ref": "request.providerOptions.a6api-chat.presence_penalty" } }, - "user": { "$omitEmpty": { "$ref": "request.providerOptions.a6api-chat.user" } } + "model": { + "$ref": "request.model" + }, + "messages": { + "$ref": "request.messages" + }, + "temperature": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.temperature" + } + }, + "top_p": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.top_p" + } + }, + "max_tokens": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.extra.max_tokens" + }, + { + "$ref": "request.providerOptions.a6api-chat.max_tokens" + } + ] + } + }, + "tools": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.tools" + } + }, + "tool_choice": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.tool_choice" + } + }, + "response_format": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.response_format" + } + }, + "stream": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.stream" + } + }, + "stop": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.stop" + } + }, + "seed": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.seed" + } + }, + "frequency_penalty": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.frequency_penalty" + } + }, + "presence_penalty": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.presence_penalty" + } + }, + "user": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-chat.user" + } + } } }, "response": { "status": "succeeded", - "textPaths": ["choices.0.message.content", "choices.0.text"], - "reasoningPaths": ["choices.0.message.reasoning_content"], - "usage": { "$ref": "response.usage" }, - "errorPaths": ["error.code"], - "messagePaths": ["error.message"] + "textPaths": [ + "choices.0.message.content", + "choices.0.text" + ], + "reasoningPaths": [ + "choices.0.message.reasoning_content" + ], + "usage": { + "$ref": "response.usage" + }, + "errorPaths": [ + "error.code" + ], + "messagePaths": [ + "error.message" + ] } }, { "id": "a6api-image", "label": "A6api Image", - "capabilities": ["image"], - "scopes": ["admin.system-channel", "user.custom-channel", "canvas", "creation", "agent"], + "capabilities": [ + "image" + ], + "scopes": [ + "admin.system-channel", + "user.custom-channel", + "canvas", + "creation", + "agent" + ], "baseUrl": "https://api.a6api.com", - "auth": { "type": "bearer", "field": "apiKey" }, + "auth": { + "type": "bearer", + "field": "apiKey" + }, "parameters": [ - { "name": "model", "type": "string", "required": true, "mapping": "model", "description": "A6api 模型市场中的图像模型 ID。" }, - { "name": "prompt", "type": "string", "required": true, "mapping": "prompt", "description": "图片提示词。" }, - { "name": "images", "type": "media[]", "required": false, "mapping": "provider image/reference fields", "description": "参考图或编辑源图,role 由业务层确定。" }, - { "name": "imageCount", "type": "integer", "required": false, "mapping": "n/sample_count", "description": "输出数量。" }, - { "name": "aspectRatio", "type": "string", "required": false, "mapping": "size/aspect_ratio", "description": "比例或尺寸,语义按协议说明。" }, - { "name": "resolution", "type": "string", "required": false, "mapping": "resolution/imageSize", "description": "分辨率档位。" }, - { "name": "quality", "type": "string", "required": false, "mapping": "quality", "description": "质量档位。" }, - { "name": "providerOptions", "type": "object", "required": false, "mapping": "provider-specific fields", "description": "插件命名空间内的厂商扩展字段。" } + { + "name": "model", + "type": "string", + "required": true, + "mapping": "model", + "description": "A6api 模型市场中的图像模型 ID。" + }, + { + "name": "prompt", + "type": "string", + "required": true, + "mapping": "prompt", + "description": "图片提示词。" + }, + { + "name": "images", + "type": "media[]", + "required": false, + "mapping": "provider image/reference fields", + "description": "参考图或编辑源图,role 由业务层确定。" + }, + { + "name": "imageCount", + "type": "integer", + "required": false, + "mapping": "n/sample_count", + "description": "输出数量。" + }, + { + "name": "aspectRatio", + "type": "string", + "required": false, + "mapping": "size/aspect_ratio", + "description": "比例或尺寸,语义按协议说明。" + }, + { + "name": "resolution", + "type": "string", + "required": false, + "mapping": "resolution/imageSize", + "description": "分辨率档位。" + }, + { + "name": "quality", + "type": "string", + "required": false, + "mapping": "quality", + "description": "质量档位。" + }, + { + "name": "providerOptions", + "type": "object", + "required": false, + "mapping": "provider-specific fields", + "description": "插件命名空间内的厂商扩展字段。" + } ], "create": { "method": "POST", "path": "/images/generations", "pathTemplate": { "$if": { - "condition": { "$gt": [ { "$len": { "$ref": "request.images" } }, 0 ] }, + "condition": { + "$gt": [ + { + "$len": { + "$ref": "request.images" + } + }, + 0 + ] + }, "then": "/images/edits", "else": "/images/generations" } @@ -93,30 +316,120 @@ "contentType": "application/json", "contentTypeTemplate": { "$if": { - "condition": { "$gt": [ { "$len": { "$ref": "request.images" } }, 0 ] }, + "condition": { + "$gt": [ + { + "$len": { + "$ref": "request.images" + } + }, + 0 + ] + }, "then": "multipart/form-data", "else": "application/json" } }, "body": { - "model": { "$ref": "request.model" }, - "prompt": { "$ref": "request.prompt" }, - "n": { "$omitEmpty": { "$if": { "condition": { "$gt": [ { "$ref": "request.imageCount" }, 0 ] }, "then": { "$ref": "request.imageCount" }, "else": 1 } } }, - "size": { "$omitEmpty": { "$ref": "request.aspectRatio" } }, - "quality": { "$omitEmpty": { "$ref": "request.quality" } }, - "output_format": { "$omitEmpty": { "$coalesce": [ { "$ref": "request.providerOptions.a6api-image.output_format" }, "png" ] } }, - "response_format": { "$omitEmpty": { "$coalesce": [ { "$ref": "request.providerOptions.a6api-image.response_format" }, "b64_json" ] } }, - "user": { "$omitEmpty": { "$ref": "request.providerOptions.a6api-image.user" } } + "model": { + "$ref": "request.model" + }, + "prompt": { + "$ref": "request.prompt" + }, + "n": { + "$omitEmpty": { + "$if": { + "condition": { + "$gt": [ + { + "$ref": "request.imageCount" + }, + 0 + ] + }, + "then": { + "$ref": "request.imageCount" + }, + "else": 1 + } + } + }, + "size": { + "$omitEmpty": { + "$ref": "request.aspectRatio" + } + }, + "quality": { + "$omitEmpty": { + "$ref": "request.quality" + } + }, + "output_format": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.providerOptions.a6api-image.output_format" + }, + "png" + ] + } + }, + "response_format": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.providerOptions.a6api-image.response_format" + }, + "b64_json" + ] + } + }, + "user": { + "$omitEmpty": { + "$ref": "request.providerOptions.a6api-image.user" + } + } }, "files": [ { "name": "image", - "source": { "$filter": { "from": { "$ref": "request.images" }, "as": "media", "where": { "$ne": [ { "$ref": "media.role" }, "mask" ] } } }, + "source": { + "$filter": { + "from": { + "$ref": "request.images" + }, + "as": "media", + "where": { + "$ne": [ + { + "$ref": "media.role" + }, + "mask" + ] + } + } + }, "filename": "source.png" }, { "name": "mask", - "source": { "$filter": { "from": { "$ref": "request.images" }, "as": "media", "where": { "$eq": [ { "$ref": "media.role" }, "mask" ] } } }, + "source": { + "$filter": { + "from": { + "$ref": "request.images" + }, + "as": "media", + "where": { + "$eq": [ + { + "$ref": "media.role" + }, + "mask" + ] + } + } + }, "filename": "mask.png" } ] @@ -125,19 +438,47 @@ "status": "succeeded", "images": { "$map": { - "from": { "$ref": "response.data" }, + "from": { + "$ref": "response.data" + }, "as": "item", "in": { - "url": { "$omitEmpty": { "$ref": "item.url" } }, - "dataUrl": { "$if": { "condition": { "$ref": "item.b64_json" }, "then": { "$concat": [ "data:image/png;base64,", { "$ref": "item.b64_json" } ] }, "else": null } } + "url": { + "$omitEmpty": { + "$ref": "item.url" + } + }, + "dataUrl": { + "$if": { + "condition": { + "$ref": "item.b64_json" + }, + "then": { + "$concat": [ + "data:image/png;base64,", + { + "$ref": "item.b64_json" + } + ] + }, + "else": null + } + } } } }, - "usage": { "$ref": "response.usage" }, - "errorPaths": ["error.code"], - "messagePaths": ["error.message"] + "usage": { + "$ref": "response.usage" + }, + "errorPaths": [ + "error.code" + ], + "messagePaths": [ + "error.message" + ] } } ] - } -} \ No newline at end of file + }, + "documentation": "# A6api\n\nA6api 模型网关协议插件。统一入口 `https://api.a6api.com`,OpenAI 兼容(`Authorization: Bearer `)。\n\n## Providers\n\n| Provider | 能力 | 端点 |\n|---|---|---|\n| a6api-chat | text | POST /chat/completions |\n| a6api-image | image | POST /images/generations、POST /images/edits |\n\n## 配置\n\n在渠道中填写 API Key(A6api 控制台创建,形如 `sk-xxxxxxxx`),baseUrl 使用 `https://api.a6api.com`。\n\n## 说明\n\n- 模型名以 A6api 模型市场当前列表为准。\n- 图像编辑(带参考图)走 `/images/edits` multipart 请求。\n- 错误体为 OpenAI 风格,携带 `request_id`。\n\n---\n\n# A6api 接口说明\n\n## 鉴权\n\n`Authorization: Bearer sk-xxxxxxxxxxxxxxxxxxxxxxxx`\n\n## 文本对话\n\nPOST `https://api.a6api.com/chat/completions`\n\n请求体 OpenAI Chat Completions 格式:`model`、`messages`、`temperature`、`max_tokens`、`tools`、`tool_choice`、`response_format`、`stream` 等。\n\n响应 `choices[0].message.content` 为正文,`choices[0].message.reasoning_content` 为推理内容,`usage` 为用量。\n\n## 图像生成\n\nPOST `https://api.a6api.com/images/generations`\n\n请求体:`model`、`prompt`、`n`、`size`、`quality`、`response_format`。\n\n响应 `data[].url` 或 `data[].b64_json`。\n\n## 图像编辑\n\nPOST `https://api.a6api.com/images/edits`(multipart,带参考图时使用)\n\n## 模型列表\n\nGET `https://api.a6api.com/models`\n\n\n## Manifest 完整接口定义\n\n以下 JSON 与插件包内实际 `manifest.json` 逐字段一致,覆盖插件身份、权限、配置、鉴权、参数、校验、创建、Agent、查询、取消、结果下载、响应和 Agent 响应映射。`documentation` 字段的值就是当前完整文档;为避免文档在自身内部无限递归,JSON 中仅用等义占位文本表示正文。\n\n```json\n{\n \"apiVersion\": \"yingce.plugin/v2\",\n \"id\": \"a6api\",\n \"name\": \"A6api\",\n \"version\": \"1.0.0\",\n \"author\": \"A6api\",\n \"description\": \"A6api 模型网关协议插件:OpenAI 兼容对话与图像生成。\",\n \"permissions\": [\n \"generation.run\",\n \"media.read\"\n ],\n \"configuration\": {\n \"fields\": [\n {\n \"name\": \"apiKey\",\n \"type\": \"secret\",\n \"label\": \"API Key\",\n \"required\": true\n }\n ]\n },\n \"contributes\": {\n \"providers\": [\n {\n \"id\": \"a6api-chat\",\n \"label\": \"A6api Chat\",\n \"capabilities\": [\n \"text\"\n ],\n \"scopes\": [\n \"admin.system-channel\",\n \"user.custom-channel\",\n \"canvas\",\n \"creation\",\n \"agent\"\n ],\n \"baseUrl\": \"https://api.a6api.com\",\n \"auth\": {\n \"type\": \"bearer\",\n \"field\": \"apiKey\"\n },\n \"parameters\": [\n {\n \"name\": \"model\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"model\",\n \"description\": \"A6api 模型市场中的模型 ID。\"\n },\n {\n \"name\": \"messages\",\n \"type\": \"message[]\",\n \"required\": true,\n \"mapping\": \"provider message container\",\n \"description\": \"包含历史消息和当前用户输入。\"\n },\n {\n \"name\": \"instructions\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"system/instructions\",\n \"description\": \"系统指令。\"\n },\n {\n \"name\": \"temperature\",\n \"type\": \"number\",\n \"required\": false,\n \"mapping\": \"temperature\",\n \"description\": \"采样温度。\"\n },\n {\n \"name\": \"top_p\",\n \"type\": \"number\",\n \"required\": false,\n \"mapping\": \"top_p\",\n \"description\": \"核采样参数。\"\n },\n {\n \"name\": \"max_tokens\",\n \"type\": \"integer\",\n \"required\": false,\n \"mapping\": \"max_tokens/max_output_tokens\",\n \"description\": \"最大输出 token。\"\n },\n {\n \"name\": \"tools\",\n \"type\": \"array\",\n \"required\": false,\n \"mapping\": \"tools/toolConfig\",\n \"description\": \"工具定义。\"\n },\n {\n \"name\": \"tool_choice\",\n \"type\": \"object|string\",\n \"required\": false,\n \"mapping\": \"tool_choice\",\n \"description\": \"工具选择策略。\"\n },\n {\n \"name\": \"response_format\",\n \"type\": \"object\",\n \"required\": false,\n \"mapping\": \"response_format/text\",\n \"description\": \"结构化输出配置。\"\n },\n {\n \"name\": \"stream\",\n \"type\": \"boolean\",\n \"required\": false,\n \"mapping\": \"stream\",\n \"description\": \"流式开关;后台任务当前以最终响应归一。\"\n },\n {\n \"name\": \"providerOptions\",\n \"type\": \"object\",\n \"required\": false,\n \"mapping\": \"provider-specific fields\",\n \"description\": \"插件命名空间内的厂商扩展字段。\"\n }\n ],\n \"create\": {\n \"method\": \"POST\",\n \"path\": \"/chat/completions\",\n \"contentType\": \"application/json\",\n \"body\": {\n \"model\": {\n \"$ref\": \"request.model\"\n },\n \"messages\": {\n \"$ref\": \"request.messages\"\n },\n \"temperature\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.a6api-chat.temperature\"\n }\n },\n \"top_p\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.a6api-chat.top_p\"\n }\n },\n \"max_tokens\": {\n \"$omitEmpty\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.extra.max_tokens\"\n },\n {\n \"$ref\": \"request.providerOptions.a6api-chat.max_tokens\"\n }\n ]\n }\n },\n \"tools\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.a6api-chat.tools\"\n }\n },\n \"tool_choice\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.a6api-chat.tool_choice\"\n }\n },\n \"response_format\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.a6api-chat.response_format\"\n }\n },\n \"stream\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.a6api-chat.stream\"\n }\n },\n \"stop\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.a6api-chat.stop\"\n }\n },\n \"seed\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.a6api-chat.seed\"\n }\n },\n \"frequency_penalty\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.a6api-chat.frequency_penalty\"\n }\n },\n \"presence_penalty\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.a6api-chat.presence_penalty\"\n }\n },\n \"user\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.a6api-chat.user\"\n }\n }\n }\n },\n \"response\": {\n \"status\": \"succeeded\",\n \"textPaths\": [\n \"choices.0.message.content\",\n \"choices.0.text\"\n ],\n \"reasoningPaths\": [\n \"choices.0.message.reasoning_content\"\n ],\n \"usage\": {\n \"$ref\": \"response.usage\"\n },\n \"errorPaths\": [\n \"error.code\"\n ],\n \"messagePaths\": [\n \"error.message\"\n ]\n }\n },\n {\n \"id\": \"a6api-image\",\n \"label\": \"A6api Image\",\n \"capabilities\": [\n \"image\"\n ],\n \"scopes\": [\n \"admin.system-channel\",\n \"user.custom-channel\",\n \"canvas\",\n \"creation\",\n \"agent\"\n ],\n \"baseUrl\": \"https://api.a6api.com\",\n \"auth\": {\n \"type\": \"bearer\",\n \"field\": \"apiKey\"\n },\n \"parameters\": [\n {\n \"name\": \"model\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"model\",\n \"description\": \"A6api 模型市场中的图像模型 ID。\"\n },\n {\n \"name\": \"prompt\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"prompt\",\n \"description\": \"图片提示词。\"\n },\n {\n \"name\": \"images\",\n \"type\": \"media[]\",\n \"required\": false,\n \"mapping\": \"provider image/reference fields\",\n \"description\": \"参考图或编辑源图,role 由业务层确定。\"\n },\n {\n \"name\": \"imageCount\",\n \"type\": \"integer\",\n \"required\": false,\n \"mapping\": \"n/sample_count\",\n \"description\": \"输出数量。\"\n },\n {\n \"name\": \"aspectRatio\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"size/aspect_ratio\",\n \"description\": \"比例或尺寸,语义按协议说明。\"\n },\n {\n \"name\": \"resolution\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"resolution/imageSize\",\n \"description\": \"分辨率档位。\"\n },\n {\n \"name\": \"quality\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"quality\",\n \"description\": \"质量档位。\"\n },\n {\n \"name\": \"providerOptions\",\n \"type\": \"object\",\n \"required\": false,\n \"mapping\": \"provider-specific fields\",\n \"description\": \"插件命名空间内的厂商扩展字段。\"\n }\n ],\n \"create\": {\n \"method\": \"POST\",\n \"path\": \"/images/generations\",\n \"pathTemplate\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\n \"$ref\": \"request.images\"\n }\n },\n 0\n ]\n },\n \"then\": \"/images/edits\",\n \"else\": \"/images/generations\"\n }\n },\n \"contentType\": \"application/json\",\n \"contentTypeTemplate\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\n \"$ref\": \"request.images\"\n }\n },\n 0\n ]\n },\n \"then\": \"multipart/form-data\",\n \"else\": \"application/json\"\n }\n },\n \"body\": {\n \"model\": {\n \"$ref\": \"request.model\"\n },\n \"prompt\": {\n \"$ref\": \"request.prompt\"\n },\n \"n\": {\n \"$omitEmpty\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$ref\": \"request.imageCount\"\n },\n 0\n ]\n },\n \"then\": {\n \"$ref\": \"request.imageCount\"\n },\n \"else\": 1\n }\n }\n },\n \"size\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.aspectRatio\"\n }\n },\n \"quality\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.quality\"\n }\n },\n \"output_format\": {\n \"$omitEmpty\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.a6api-image.output_format\"\n },\n \"png\"\n ]\n }\n },\n \"response_format\": {\n \"$omitEmpty\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.a6api-image.response_format\"\n },\n \"b64_json\"\n ]\n }\n },\n \"user\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.a6api-image.user\"\n }\n }\n },\n \"files\": [\n {\n \"name\": \"image\",\n \"source\": {\n \"$filter\": {\n \"from\": {\n \"$ref\": \"request.images\"\n },\n \"as\": \"media\",\n \"where\": {\n \"$ne\": [\n {\n \"$ref\": \"media.role\"\n },\n \"mask\"\n ]\n }\n }\n },\n \"filename\": \"source.png\"\n },\n {\n \"name\": \"mask\",\n \"source\": {\n \"$filter\": {\n \"from\": {\n \"$ref\": \"request.images\"\n },\n \"as\": \"media\",\n \"where\": {\n \"$eq\": [\n {\n \"$ref\": \"media.role\"\n },\n \"mask\"\n ]\n }\n }\n },\n \"filename\": \"mask.png\"\n }\n ]\n },\n \"response\": {\n \"status\": \"succeeded\",\n \"images\": {\n \"$map\": {\n \"from\": {\n \"$ref\": \"response.data\"\n },\n \"as\": \"item\",\n \"in\": {\n \"url\": {\n \"$omitEmpty\": {\n \"$ref\": \"item.url\"\n }\n },\n \"dataUrl\": {\n \"$if\": {\n \"condition\": {\n \"$ref\": \"item.b64_json\"\n },\n \"then\": {\n \"$concat\": [\n \"data:image/png;base64,\",\n {\n \"$ref\": \"item.b64_json\"\n }\n ]\n },\n \"else\": null\n }\n }\n }\n }\n },\n \"usage\": {\n \"$ref\": \"response.usage\"\n },\n \"errorPaths\": [\n \"error.code\"\n ],\n \"messagePaths\": [\n \"error.message\"\n ]\n }\n }\n ]\n },\n \"documentation\": \"<当前插件的完整 documentation,由 README.md 与 docs/interface.md 拼接而成;为避免 JSON 递归,此处不重复展开正文。>\"\n}\n```\n\n" +} diff --git a/plugin-packages/src-antigravity-proxy/docs/interface.md b/plugin-packages/src-antigravity-proxy/docs/interface.md index 5a19a4f61..66f7d83c9 100644 --- a/plugin-packages/src-antigravity-proxy/docs/interface.md +++ b/plugin-packages/src-antigravity-proxy/docs/interface.md @@ -68,3 +68,236 @@ ## 兼容边界 该包只代表 Antigravity 中转渠道的 OpenAI Chat Completions 线协议;其他端点或网关包装必须使用独立插件。 + + +## Manifest 完整接口定义 + +以下 JSON 与插件包内实际 `manifest.json` 逐字段一致,覆盖插件身份、权限、配置、鉴权、参数、校验、创建、Agent、查询、取消、结果下载、响应和 Agent 响应映射。`documentation` 字段的值就是当前完整文档;为避免文档在自身内部无限递归,JSON 中仅用等义占位文本表示正文。 + +```json +{ + "apiVersion": "yingce.plugin/v2", + "id": "antigravity-proxy", + "name": "Antigravity Proxy", + "version": "1.0.0", + "author": "Yingce", + "description": "Antigravity 中转渠道插件:OpenAI 兼容对话(gemini-3.8-flash-high / gemini-pro-agent)。", + "permissions": [ + "generation.run", + "media.read" + ], + "configuration": { + "fields": [ + { + "name": "apiKey", + "type": "secret", + "label": "API Key", + "required": true + } + ] + }, + "contributes": { + "providers": [ + { + "id": "antigravity-chat", + "label": "Antigravity Chat", + "capabilities": [ + "text" + ], + "scopes": [ + "admin.system-channel", + "user.custom-channel", + "canvas", + "creation", + "agent" + ], + "baseUrl": "http://103.242.14.110:8317", + "auth": { + "type": "bearer", + "field": "apiKey" + }, + "parameters": [ + { + "name": "model", + "type": "string", + "required": true, + "mapping": "model", + "description": "模型 ID(gemini-3.8-flash-high / gemini-pro-agent)。" + }, + { + "name": "messages", + "type": "message[]", + "required": true, + "mapping": "provider message container", + "description": "包含历史消息和当前用户输入。" + }, + { + "name": "instructions", + "type": "string", + "required": false, + "mapping": "system/instructions", + "description": "系统指令。" + }, + { + "name": "temperature", + "type": "number", + "required": false, + "mapping": "temperature", + "description": "采样温度。" + }, + { + "name": "top_p", + "type": "number", + "required": false, + "mapping": "top_p", + "description": "核采样参数。" + }, + { + "name": "max_tokens", + "type": "integer", + "required": false, + "mapping": "max_tokens/max_output_tokens", + "description": "最大输出 token。" + }, + { + "name": "tools", + "type": "array", + "required": false, + "mapping": "tools/toolConfig", + "description": "工具定义。" + }, + { + "name": "tool_choice", + "type": "object|string", + "required": false, + "mapping": "tool_choice", + "description": "工具选择策略。" + }, + { + "name": "response_format", + "type": "object", + "required": false, + "mapping": "response_format/text", + "description": "结构化输出配置。" + }, + { + "name": "stream", + "type": "boolean", + "required": false, + "mapping": "stream", + "description": "流式开关;后台任务当前以最终响应归一。" + }, + { + "name": "providerOptions", + "type": "object", + "required": false, + "mapping": "provider-specific fields", + "description": "插件命名空间内的厂商扩展字段。" + } + ], + "create": { + "method": "POST", + "path": "/chat/completions", + "contentType": "application/json", + "body": { + "model": { + "$ref": "request.model" + }, + "messages": { + "$ref": "request.messages" + }, + "temperature": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.temperature" + } + }, + "top_p": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.top_p" + } + }, + "max_tokens": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.extra.max_tokens" + }, + { + "$ref": "request.providerOptions.antigravity-chat.max_tokens" + } + ] + } + }, + "tools": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.tools" + } + }, + "tool_choice": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.tool_choice" + } + }, + "response_format": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.response_format" + } + }, + "stream": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.stream" + } + }, + "stop": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.stop" + } + }, + "seed": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.seed" + } + }, + "frequency_penalty": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.frequency_penalty" + } + }, + "presence_penalty": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.presence_penalty" + } + }, + "user": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.user" + } + } + } + }, + "response": { + "status": "succeeded", + "textPaths": [ + "choices.0.message.content", + "choices.0.text" + ], + "reasoningPaths": [ + "choices.0.message.reasoning_content" + ], + "usage": { + "$ref": "response.usage" + }, + "errorPaths": [ + "error.code" + ], + "messagePaths": [ + "error.message" + ] + } + } + ] + }, + "documentation": "<当前插件的完整 documentation,由 README.md 与 docs/interface.md 拼接而成;为避免 JSON 递归,此处不重复展开正文。>" +} +``` + diff --git a/plugin-packages/src-antigravity-proxy/manifest.json b/plugin-packages/src-antigravity-proxy/manifest.json index 290fd46b2..e914d6856 100644 --- a/plugin-packages/src-antigravity-proxy/manifest.json +++ b/plugin-packages/src-antigravity-proxy/manifest.json @@ -5,10 +5,18 @@ "version": "1.0.0", "author": "Yingce", "description": "Antigravity 中转渠道插件:OpenAI 兼容对话(gemini-3.8-flash-high / gemini-pro-agent)。", - "permissions": ["generation.run", "media.read"], + "permissions": [ + "generation.run", + "media.read" + ], "configuration": { "fields": [ - { "name": "apiKey", "type": "secret", "label": "API Key", "required": true } + { + "name": "apiKey", + "type": "secret", + "label": "API Key", + "required": true + } ] }, "contributes": { @@ -16,53 +24,201 @@ { "id": "antigravity-chat", "label": "Antigravity Chat", - "capabilities": ["text"], - "scopes": ["admin.system-channel", "user.custom-channel", "canvas", "creation", "agent"], + "capabilities": [ + "text" + ], + "scopes": [ + "admin.system-channel", + "user.custom-channel", + "canvas", + "creation", + "agent" + ], "baseUrl": "http://103.242.14.110:8317", - "auth": { "type": "bearer", "field": "apiKey" }, + "auth": { + "type": "bearer", + "field": "apiKey" + }, "parameters": [ - { "name": "model", "type": "string", "required": true, "mapping": "model", "description": "模型 ID(gemini-3.8-flash-high / gemini-pro-agent)。" }, - { "name": "messages", "type": "message[]", "required": true, "mapping": "provider message container", "description": "包含历史消息和当前用户输入。" }, - { "name": "instructions", "type": "string", "required": false, "mapping": "system/instructions", "description": "系统指令。" }, - { "name": "temperature", "type": "number", "required": false, "mapping": "temperature", "description": "采样温度。" }, - { "name": "top_p", "type": "number", "required": false, "mapping": "top_p", "description": "核采样参数。" }, - { "name": "max_tokens", "type": "integer", "required": false, "mapping": "max_tokens/max_output_tokens", "description": "最大输出 token。" }, - { "name": "tools", "type": "array", "required": false, "mapping": "tools/toolConfig", "description": "工具定义。" }, - { "name": "tool_choice", "type": "object|string", "required": false, "mapping": "tool_choice", "description": "工具选择策略。" }, - { "name": "response_format", "type": "object", "required": false, "mapping": "response_format/text", "description": "结构化输出配置。" }, - { "name": "stream", "type": "boolean", "required": false, "mapping": "stream", "description": "流式开关;后台任务当前以最终响应归一。" }, - { "name": "providerOptions", "type": "object", "required": false, "mapping": "provider-specific fields", "description": "插件命名空间内的厂商扩展字段。" } + { + "name": "model", + "type": "string", + "required": true, + "mapping": "model", + "description": "模型 ID(gemini-3.8-flash-high / gemini-pro-agent)。" + }, + { + "name": "messages", + "type": "message[]", + "required": true, + "mapping": "provider message container", + "description": "包含历史消息和当前用户输入。" + }, + { + "name": "instructions", + "type": "string", + "required": false, + "mapping": "system/instructions", + "description": "系统指令。" + }, + { + "name": "temperature", + "type": "number", + "required": false, + "mapping": "temperature", + "description": "采样温度。" + }, + { + "name": "top_p", + "type": "number", + "required": false, + "mapping": "top_p", + "description": "核采样参数。" + }, + { + "name": "max_tokens", + "type": "integer", + "required": false, + "mapping": "max_tokens/max_output_tokens", + "description": "最大输出 token。" + }, + { + "name": "tools", + "type": "array", + "required": false, + "mapping": "tools/toolConfig", + "description": "工具定义。" + }, + { + "name": "tool_choice", + "type": "object|string", + "required": false, + "mapping": "tool_choice", + "description": "工具选择策略。" + }, + { + "name": "response_format", + "type": "object", + "required": false, + "mapping": "response_format/text", + "description": "结构化输出配置。" + }, + { + "name": "stream", + "type": "boolean", + "required": false, + "mapping": "stream", + "description": "流式开关;后台任务当前以最终响应归一。" + }, + { + "name": "providerOptions", + "type": "object", + "required": false, + "mapping": "provider-specific fields", + "description": "插件命名空间内的厂商扩展字段。" + } ], "create": { "method": "POST", "path": "/chat/completions", "contentType": "application/json", "body": { - "model": { "$ref": "request.model" }, - "messages": { "$ref": "request.messages" }, - "temperature": { "$omitEmpty": { "$ref": "request.providerOptions.antigravity-chat.temperature" } }, - "top_p": { "$omitEmpty": { "$ref": "request.providerOptions.antigravity-chat.top_p" } }, - "max_tokens": { "$omitEmpty": { "$coalesce": [ { "$ref": "request.extra.max_tokens" }, { "$ref": "request.providerOptions.antigravity-chat.max_tokens" } ] } }, - "tools": { "$omitEmpty": { "$ref": "request.providerOptions.antigravity-chat.tools" } }, - "tool_choice": { "$omitEmpty": { "$ref": "request.providerOptions.antigravity-chat.tool_choice" } }, - "response_format": { "$omitEmpty": { "$ref": "request.providerOptions.antigravity-chat.response_format" } }, - "stream": { "$omitEmpty": { "$ref": "request.providerOptions.antigravity-chat.stream" } }, - "stop": { "$omitEmpty": { "$ref": "request.providerOptions.antigravity-chat.stop" } }, - "seed": { "$omitEmpty": { "$ref": "request.providerOptions.antigravity-chat.seed" } }, - "frequency_penalty": { "$omitEmpty": { "$ref": "request.providerOptions.antigravity-chat.frequency_penalty" } }, - "presence_penalty": { "$omitEmpty": { "$ref": "request.providerOptions.antigravity-chat.presence_penalty" } }, - "user": { "$omitEmpty": { "$ref": "request.providerOptions.antigravity-chat.user" } } + "model": { + "$ref": "request.model" + }, + "messages": { + "$ref": "request.messages" + }, + "temperature": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.temperature" + } + }, + "top_p": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.top_p" + } + }, + "max_tokens": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.extra.max_tokens" + }, + { + "$ref": "request.providerOptions.antigravity-chat.max_tokens" + } + ] + } + }, + "tools": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.tools" + } + }, + "tool_choice": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.tool_choice" + } + }, + "response_format": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.response_format" + } + }, + "stream": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.stream" + } + }, + "stop": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.stop" + } + }, + "seed": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.seed" + } + }, + "frequency_penalty": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.frequency_penalty" + } + }, + "presence_penalty": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.presence_penalty" + } + }, + "user": { + "$omitEmpty": { + "$ref": "request.providerOptions.antigravity-chat.user" + } + } } }, "response": { "status": "succeeded", - "textPaths": ["choices.0.message.content", "choices.0.text"], - "reasoningPaths": ["choices.0.message.reasoning_content"], - "usage": { "$ref": "response.usage" }, - "errorPaths": ["error.code"], - "messagePaths": ["error.message"] + "textPaths": [ + "choices.0.message.content", + "choices.0.text" + ], + "reasoningPaths": [ + "choices.0.message.reasoning_content" + ], + "usage": { + "$ref": "response.usage" + }, + "errorPaths": [ + "error.code" + ], + "messagePaths": [ + "error.message" + ] } } ] - } + }, + "documentation": "# Antigravity Proxy\n\nAntigravity 中转渠道插件:OpenAI Chat Completions 兼容对话协议。\n\n## 协议身份\n\n- 插件 ID:`antigravity-proxy`\n- Provider ID:`antigravity-chat`\n- 能力:`text`\n- 默认 Base URL:`http://103.242.14.110:8317`\n- 鉴权驱动:`bearer`\n- 创建:`POST /chat/completions`\n- 生命周期:同步响应\n\n## 配置字段\n\n| 字段 | 类型 | 必填 | 含义 |\n| --- | --- | --- | --- |\n| `apiKey` | secret | 是 | 中转渠道 API Key |\n\n## 模型\n\n- `gemini-3.8-flash-high`\n- `gemini-pro-agent`\n\n## 统一字段映射\n\n| 统一字段 | 类型 | 必填 | 上游映射 |\n| --- | --- | --- | --- |\n| `model` | string | 是 | `model` |\n| `messages` | message[] | 是 | `messages` |\n| `instructions` | string | 否 | `system/instructions` |\n| `temperature` | number | 否 | `temperature` |\n| `top_p` | number | 否 | `top_p` |\n| `max_tokens` | integer | 否 | `max_tokens` |\n| `tools` | array | 否 | `tools` |\n| `tool_choice` | object\\|string | 否 | `tool_choice` |\n| `response_format` | object | 否 | `response_format` |\n| `stream` | boolean | 否 | `stream` |\n\n完整接口见 [docs/interface.md](docs/interface.md)。\n\n---\n\n# Antigravity Proxy 接口字段\n\n## 协议身份\n\n- 插件 ID:`antigravity-proxy`\n- Provider ID:`antigravity-chat`\n- 能力:`text`\n- 默认 Base URL:`http://103.242.14.110:8317`\n- 鉴权驱动:`bearer`\n- 创建:`POST /chat/completions`\n- 生命周期:同步响应\n\n## 配置字段\n\n| 字段 | 类型 | 必填 | 含义 |\n| --- | --- | --- | --- |\n| `apiKey` | secret | 是 | 中转渠道 API Key |\n\n## 统一字段映射\n\n| 统一字段 | 类型 | 必填 | 上游映射 | 说明 |\n| --- | --- | --- | --- | --- |\n| `model` | string | 是 | `model` | 上游模型 ID。 |\n| `messages` | message[] | 是 | `messages` | 包含历史消息和当前用户输入。 |\n| `instructions` | string | 否 | `system/instructions` | 系统指令。 |\n| `temperature` | number | 否 | `temperature` | 采样温度。 |\n| `top_p` | number | 否 | `top_p` | 核采样参数。 |\n| `max_tokens` | integer | 否 | `max_tokens/max_output_tokens` | 最大输出 token。 |\n| `tools` | array | 否 | `tools/toolConfig` | 工具定义。 |\n| `tool_choice` | object\\|string | 否 | `tool_choice` | 工具选择策略。 |\n| `response_format` | object | 否 | `response_format/text` | 结构化输出配置。 |\n| `stream` | boolean | 否 | `stream` | 流式开关。 |\n\n## 上游请求模板\n\n| 上游位置 | 值或转换表达式 |\n| --- | --- |\n| `create.method` | `\"POST\"` |\n| `create.path` | `\"/chat/completions\"` |\n| `create.contentType` | `\"application/json\"` |\n| `create.body.model` | `{\"$ref\":\"request.model\"}` |\n| `create.body.messages` | `{\"$ref\":\"request.messages\"}` |\n| `create.body.temperature` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.antigravity-chat.temperature\"}}` |\n| `create.body.top_p` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.antigravity-chat.top_p\"}}` |\n| `create.body.max_tokens` | `{\"$omitEmpty\":{\"$coalesce\":[{\"$ref\":\"request.extra.max_tokens\"},{\"$ref\":\"request.providerOptions.antigravity-chat.max_tokens\"}]}}` |\n| `create.body.tools` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.antigravity-chat.tools\"}}` |\n| `create.body.tool_choice` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.antigravity-chat.tool_choice\"}}` |\n| `create.body.response_format` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.antigravity-chat.response_format\"}}` |\n| `create.body.stream` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.antigravity-chat.stream\"}}` |\n| `create.body.stop` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.antigravity-chat.stop\"}}` |\n| `create.body.seed` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.antigravity-chat.seed\"}}` |\n| `create.body.frequency_penalty` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.antigravity-chat.frequency_penalty\"}}` |\n| `create.body.presence_penalty` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.antigravity-chat.presence_penalty\"}}` |\n| `create.body.user` | `{\"$omitEmpty\":{\"$ref\":\"request.providerOptions.antigravity-chat.user\"}}` |\n\n## 响应映射\n\n| 映射位置 | 上游路径或转换表达式 |\n| --- | --- |\n| `response.status` | `\"succeeded\"` |\n| `response.textPaths[0]` | `\"choices.0.message.content\"` |\n| `response.textPaths[1]` | `\"choices.0.text\"` |\n| `response.reasoningPaths[0]` | `\"choices.0.message.reasoning_content\"` |\n| `response.usage` | `{\"$ref\":\"response.usage\"}` |\n| `response.errorPaths[0]` | `\"error.code\"` |\n| `response.messagePaths[0]` | `\"error.message\"` |\n\n## 兼容边界\n\n该包只代表 Antigravity 中转渠道的 OpenAI Chat Completions 线协议;其他端点或网关包装必须使用独立插件。\n\n\n## Manifest 完整接口定义\n\n以下 JSON 与插件包内实际 `manifest.json` 逐字段一致,覆盖插件身份、权限、配置、鉴权、参数、校验、创建、Agent、查询、取消、结果下载、响应和 Agent 响应映射。`documentation` 字段的值就是当前完整文档;为避免文档在自身内部无限递归,JSON 中仅用等义占位文本表示正文。\n\n```json\n{\n \"apiVersion\": \"yingce.plugin/v2\",\n \"id\": \"antigravity-proxy\",\n \"name\": \"Antigravity Proxy\",\n \"version\": \"1.0.0\",\n \"author\": \"Yingce\",\n \"description\": \"Antigravity 中转渠道插件:OpenAI 兼容对话(gemini-3.8-flash-high / gemini-pro-agent)。\",\n \"permissions\": [\n \"generation.run\",\n \"media.read\"\n ],\n \"configuration\": {\n \"fields\": [\n {\n \"name\": \"apiKey\",\n \"type\": \"secret\",\n \"label\": \"API Key\",\n \"required\": true\n }\n ]\n },\n \"contributes\": {\n \"providers\": [\n {\n \"id\": \"antigravity-chat\",\n \"label\": \"Antigravity Chat\",\n \"capabilities\": [\n \"text\"\n ],\n \"scopes\": [\n \"admin.system-channel\",\n \"user.custom-channel\",\n \"canvas\",\n \"creation\",\n \"agent\"\n ],\n \"baseUrl\": \"http://103.242.14.110:8317\",\n \"auth\": {\n \"type\": \"bearer\",\n \"field\": \"apiKey\"\n },\n \"parameters\": [\n {\n \"name\": \"model\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"model\",\n \"description\": \"模型 ID(gemini-3.8-flash-high / gemini-pro-agent)。\"\n },\n {\n \"name\": \"messages\",\n \"type\": \"message[]\",\n \"required\": true,\n \"mapping\": \"provider message container\",\n \"description\": \"包含历史消息和当前用户输入。\"\n },\n {\n \"name\": \"instructions\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"system/instructions\",\n \"description\": \"系统指令。\"\n },\n {\n \"name\": \"temperature\",\n \"type\": \"number\",\n \"required\": false,\n \"mapping\": \"temperature\",\n \"description\": \"采样温度。\"\n },\n {\n \"name\": \"top_p\",\n \"type\": \"number\",\n \"required\": false,\n \"mapping\": \"top_p\",\n \"description\": \"核采样参数。\"\n },\n {\n \"name\": \"max_tokens\",\n \"type\": \"integer\",\n \"required\": false,\n \"mapping\": \"max_tokens/max_output_tokens\",\n \"description\": \"最大输出 token。\"\n },\n {\n \"name\": \"tools\",\n \"type\": \"array\",\n \"required\": false,\n \"mapping\": \"tools/toolConfig\",\n \"description\": \"工具定义。\"\n },\n {\n \"name\": \"tool_choice\",\n \"type\": \"object|string\",\n \"required\": false,\n \"mapping\": \"tool_choice\",\n \"description\": \"工具选择策略。\"\n },\n {\n \"name\": \"response_format\",\n \"type\": \"object\",\n \"required\": false,\n \"mapping\": \"response_format/text\",\n \"description\": \"结构化输出配置。\"\n },\n {\n \"name\": \"stream\",\n \"type\": \"boolean\",\n \"required\": false,\n \"mapping\": \"stream\",\n \"description\": \"流式开关;后台任务当前以最终响应归一。\"\n },\n {\n \"name\": \"providerOptions\",\n \"type\": \"object\",\n \"required\": false,\n \"mapping\": \"provider-specific fields\",\n \"description\": \"插件命名空间内的厂商扩展字段。\"\n }\n ],\n \"create\": {\n \"method\": \"POST\",\n \"path\": \"/chat/completions\",\n \"contentType\": \"application/json\",\n \"body\": {\n \"model\": {\n \"$ref\": \"request.model\"\n },\n \"messages\": {\n \"$ref\": \"request.messages\"\n },\n \"temperature\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.antigravity-chat.temperature\"\n }\n },\n \"top_p\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.antigravity-chat.top_p\"\n }\n },\n \"max_tokens\": {\n \"$omitEmpty\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.extra.max_tokens\"\n },\n {\n \"$ref\": \"request.providerOptions.antigravity-chat.max_tokens\"\n }\n ]\n }\n },\n \"tools\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.antigravity-chat.tools\"\n }\n },\n \"tool_choice\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.antigravity-chat.tool_choice\"\n }\n },\n \"response_format\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.antigravity-chat.response_format\"\n }\n },\n \"stream\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.antigravity-chat.stream\"\n }\n },\n \"stop\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.antigravity-chat.stop\"\n }\n },\n \"seed\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.antigravity-chat.seed\"\n }\n },\n \"frequency_penalty\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.antigravity-chat.frequency_penalty\"\n }\n },\n \"presence_penalty\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.antigravity-chat.presence_penalty\"\n }\n },\n \"user\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.antigravity-chat.user\"\n }\n }\n }\n },\n \"response\": {\n \"status\": \"succeeded\",\n \"textPaths\": [\n \"choices.0.message.content\",\n \"choices.0.text\"\n ],\n \"reasoningPaths\": [\n \"choices.0.message.reasoning_content\"\n ],\n \"usage\": {\n \"$ref\": \"response.usage\"\n },\n \"errorPaths\": [\n \"error.code\"\n ],\n \"messagePaths\": [\n \"error.message\"\n ]\n }\n }\n ]\n },\n \"documentation\": \"<当前插件的完整 documentation,由 README.md 与 docs/interface.md 拼接而成;为避免 JSON 递归,此处不重复展开正文。>\"\n}\n```\n\n" } diff --git a/plugin-packages/src-metaso-h3/docs/interface.md b/plugin-packages/src-metaso-h3/docs/interface.md index 85cdb615a..57f64e02c 100644 --- a/plugin-packages/src-metaso-h3/docs/interface.md +++ b/plugin-packages/src-metaso-h3/docs/interface.md @@ -59,3 +59,379 @@ status 取值:queued / running / succeeded / failed / cancelled。 ## 错误 创建与查询均返回 OpenAI 风格错误体,含 `error.type` / `error.message` / `request_id`;余额不足为 402,速率限制为 429。 + + +## Manifest 完整接口定义 + +以下 JSON 与插件包内实际 `manifest.json` 逐字段一致,覆盖插件身份、权限、配置、鉴权、参数、校验、创建、Agent、查询、取消、结果下载、响应和 Agent 响应映射。`documentation` 字段的值就是当前完整文档;为避免文档在自身内部无限递归,JSON 中仅用等义占位文本表示正文。 + +```json +{ + "apiVersion": "yingce.plugin/v2", + "id": "metaso-h3", + "name": "METASO MiniMax H3", + "version": "1.0.0", + "author": "METASO", + "description": "秘塔 METASO MiniMax H3 文生视频/图生视频协议插件(异步任务)。", + "permissions": [ + "generation.run", + "media.read" + ], + "configuration": { + "fields": [ + { + "name": "apiKey", + "type": "secret", + "label": "API Key", + "required": true + } + ] + }, + "contributes": { + "providers": [ + { + "id": "metaso-h3", + "label": "METASO MiniMax H3", + "capabilities": [ + "video" + ], + "scopes": [ + "admin.system-channel", + "user.custom-channel", + "canvas", + "creation", + "agent" + ], + "baseUrl": "https://metaso.cn", + "auth": { + "type": "bearer", + "field": "apiKey" + }, + "requiresPublicMediaUrls": true, + "parameters": [ + { + "name": "model", + "type": "string", + "required": true, + "mapping": "model", + "description": "视频模型 ID(MiniMax-H3 / MiniMax-H3-Max)。" + }, + { + "name": "prompt", + "type": "string", + "required": true, + "mapping": "prompt/content/input", + "description": "视频提示词。" + }, + { + "name": "images", + "type": "media[]", + "required": false, + "mapping": "first/last/reference image", + "description": "显式 role 图片输入(首帧/尾帧/参考图)。" + }, + { + "name": "videos", + "type": "media[]", + "required": false, + "mapping": "reference video", + "description": "参考视频。" + }, + { + "name": "audios", + "type": "media[]", + "required": false, + "mapping": "reference audio/voice", + "description": "参考音频或音色。" + }, + { + "name": "duration", + "type": "integer", + "required": false, + "mapping": "duration/seconds", + "description": "时长秒数(4-15)。" + }, + { + "name": "aspectRatio", + "type": "string", + "required": false, + "mapping": "ratio/aspect_ratio/size", + "description": "画幅比例(16:9 等)。" + }, + { + "name": "resolution", + "type": "string", + "required": false, + "mapping": "resolution", + "description": "分辨率档位(768P / 2K)。" + }, + { + "name": "watermark", + "type": "boolean", + "required": false, + "mapping": "watermark", + "description": "AIGC 水印开关。" + }, + { + "name": "providerOptions", + "type": "object", + "required": false, + "mapping": "provider-specific fields", + "description": "插件命名空间内的厂商扩展字段。" + } + ], + "create": { + "method": "POST", + "path": "/api/minimax/v2/video_generation", + "contentType": "application/json", + "body": { + "model": { + "$coalesce": [ + { + "$ref": "request.model" + }, + "MiniMax-H3" + ] + }, + "content": { + "$concatArrays": [ + { + "$if": { + "condition": { + "$gt": [ + { + "$len": { + "$ref": "request.prompt" + } + }, + 0 + ] + }, + "then": [ + { + "type": "text", + "text": { + "$ref": "request.prompt" + } + } + ], + "else": [] + } + }, + { + "$map": { + "from": { + "$ref": "request.images" + }, + "as": "media", + "in": { + "type": "image_url", + "image_url": { + "url": { + "$coalesce": [ + { + "$ref": "media.url" + }, + { + "$ref": "media.dataUrl" + } + ] + } + }, + "role": { + "$omitEmpty": { + "$ref": "media.role" + } + } + } + } + }, + { + "$map": { + "from": { + "$ref": "request.videos" + }, + "as": "media", + "in": { + "type": "video_url", + "video_url": { + "url": { + "$coalesce": [ + { + "$ref": "media.url" + }, + { + "$ref": "media.dataUrl" + } + ] + } + }, + "role": { + "$omitEmpty": { + "$ref": "media.role" + } + } + } + } + }, + { + "$map": { + "from": { + "$ref": "request.audios" + }, + "as": "media", + "in": { + "type": "audio_url", + "audio_url": { + "url": { + "$coalesce": [ + { + "$ref": "media.url" + }, + { + "$ref": "media.dataUrl" + } + ] + } + }, + "role": { + "$omitEmpty": { + "$ref": "media.role" + } + } + } + } + } + ] + }, + "resolution": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.resolution" + }, + { + "$ref": "request.providerOptions.metaso-h3.resolution" + }, + "768P" + ] + } + }, + "duration": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.duration" + }, + { + "$ref": "request.providerOptions.metaso-h3.duration" + }, + 5 + ] + } + }, + "ratio": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.aspectRatio" + }, + { + "$ref": "request.providerOptions.metaso-h3.ratio" + }, + "16:9" + ] + } + }, + "aigc_watermark": { + "$omitEmpty": { + "$ref": "request.providerOptions.metaso-h3.aigc_watermark" + } + } + } + }, + "poll": { + "method": "GET", + "path": "/api/minimax/v2/query/video_generation/{{taskId}}" + }, + "response": { + "taskId": { + "$coalesce": [ + { + "$ref": "response.task_id" + }, + { + "$ref": "response.taskId" + }, + { + "$ref": "response.data.task_id" + } + ] + }, + "status": { + "$coalesce": [ + { + "$ref": "response.task.status" + }, + { + "$ref": "response.status" + }, + { + "$ref": "response.data.status" + }, + "pending" + ] + }, + "message": { + "$coalesce": [ + { + "$ref": "response.task.error.message" + }, + { + "$ref": "response.task.fail_reason" + }, + { + "$ref": "response.error.message" + }, + { + "$ref": "response.message" + } + ] + }, + "videos": { + "$coalesce": [ + { + "$ref": "response.task.content.url" + }, + { + "$ref": "response.task.content.video_url" + }, + { + "$ref": "response.content.url" + }, + { + "$ref": "response.data.url" + } + ] + }, + "usage": { + "$ref": "response.task.usage" + }, + "errorPaths": [ + "task.error.type", + "error.type", + "error.code" + ], + "resultEphemeral": true, + "messagePaths": [ + "task.error.message", + "error.message" + ] + } + } + ] + }, + "documentation": "<当前插件的完整 documentation,由 README.md 与 docs/interface.md 拼接而成;为避免 JSON 递归,此处不重复展开正文。>" +} +``` + diff --git a/plugin-packages/src-metaso-h3/manifest.json b/plugin-packages/src-metaso-h3/manifest.json index 1a051962a..0e70020df 100644 --- a/plugin-packages/src-metaso-h3/manifest.json +++ b/plugin-packages/src-metaso-h3/manifest.json @@ -5,10 +5,18 @@ "version": "1.0.0", "author": "METASO", "description": "秘塔 METASO MiniMax H3 文生视频/图生视频协议插件(异步任务)。", - "permissions": ["generation.run", "media.read"], + "permissions": [ + "generation.run", + "media.read" + ], "configuration": { "fields": [ - { "name": "apiKey", "type": "secret", "label": "API Key", "required": true } + { + "name": "apiKey", + "type": "secret", + "label": "API Key", + "required": true + } ] }, "contributes": { @@ -16,41 +24,262 @@ { "id": "metaso-h3", "label": "METASO MiniMax H3", - "capabilities": ["video"], - "scopes": ["admin.system-channel", "user.custom-channel", "canvas", "creation", "agent"], + "capabilities": [ + "video" + ], + "scopes": [ + "admin.system-channel", + "user.custom-channel", + "canvas", + "creation", + "agent" + ], "baseUrl": "https://metaso.cn", - "auth": { "type": "bearer", "field": "apiKey" }, + "auth": { + "type": "bearer", + "field": "apiKey" + }, "requiresPublicMediaUrls": true, "parameters": [ - { "name": "model", "type": "string", "required": true, "mapping": "model", "description": "视频模型 ID(MiniMax-H3 / MiniMax-H3-Max)。" }, - { "name": "prompt", "type": "string", "required": true, "mapping": "prompt/content/input", "description": "视频提示词。" }, - { "name": "images", "type": "media[]", "required": false, "mapping": "first/last/reference image", "description": "显式 role 图片输入(首帧/尾帧/参考图)。" }, - { "name": "videos", "type": "media[]", "required": false, "mapping": "reference video", "description": "参考视频。" }, - { "name": "audios", "type": "media[]", "required": false, "mapping": "reference audio/voice", "description": "参考音频或音色。" }, - { "name": "duration", "type": "integer", "required": false, "mapping": "duration/seconds", "description": "时长秒数(4-15)。" }, - { "name": "aspectRatio", "type": "string", "required": false, "mapping": "ratio/aspect_ratio/size", "description": "画幅比例(16:9 等)。" }, - { "name": "resolution", "type": "string", "required": false, "mapping": "resolution", "description": "分辨率档位(768P / 2K)。" }, - { "name": "watermark", "type": "boolean", "required": false, "mapping": "watermark", "description": "AIGC 水印开关。" }, - { "name": "providerOptions", "type": "object", "required": false, "mapping": "provider-specific fields", "description": "插件命名空间内的厂商扩展字段。" } + { + "name": "model", + "type": "string", + "required": true, + "mapping": "model", + "description": "视频模型 ID(MiniMax-H3 / MiniMax-H3-Max)。" + }, + { + "name": "prompt", + "type": "string", + "required": true, + "mapping": "prompt/content/input", + "description": "视频提示词。" + }, + { + "name": "images", + "type": "media[]", + "required": false, + "mapping": "first/last/reference image", + "description": "显式 role 图片输入(首帧/尾帧/参考图)。" + }, + { + "name": "videos", + "type": "media[]", + "required": false, + "mapping": "reference video", + "description": "参考视频。" + }, + { + "name": "audios", + "type": "media[]", + "required": false, + "mapping": "reference audio/voice", + "description": "参考音频或音色。" + }, + { + "name": "duration", + "type": "integer", + "required": false, + "mapping": "duration/seconds", + "description": "时长秒数(4-15)。" + }, + { + "name": "aspectRatio", + "type": "string", + "required": false, + "mapping": "ratio/aspect_ratio/size", + "description": "画幅比例(16:9 等)。" + }, + { + "name": "resolution", + "type": "string", + "required": false, + "mapping": "resolution", + "description": "分辨率档位(768P / 2K)。" + }, + { + "name": "watermark", + "type": "boolean", + "required": false, + "mapping": "watermark", + "description": "AIGC 水印开关。" + }, + { + "name": "providerOptions", + "type": "object", + "required": false, + "mapping": "provider-specific fields", + "description": "插件命名空间内的厂商扩展字段。" + } ], "create": { "method": "POST", "path": "/api/minimax/v2/video_generation", "contentType": "application/json", "body": { - "model": { "$coalesce": [ { "$ref": "request.model" }, "MiniMax-H3" ] }, - "content": { - "$concatArrays": [ - { "$if": { "condition": { "$gt": [ { "$len": { "$ref": "request.prompt" } }, 0 ] }, "then": [ { "type": "text", "text": { "$ref": "request.prompt" } } ], "else": [] } }, - { "$map": { "from": { "$ref": "request.images" }, "as": "media", "in": { "type": "image_url", "image_url": { "url": { "$coalesce": [ { "$ref": "media.url" }, { "$ref": "media.dataUrl" } ] } }, "role": { "$omitEmpty": { "$ref": "media.role" } } } } }, - { "$map": { "from": { "$ref": "request.videos" }, "as": "media", "in": { "type": "video_url", "video_url": { "url": { "$coalesce": [ { "$ref": "media.url" }, { "$ref": "media.dataUrl" } ] } }, "role": { "$omitEmpty": { "$ref": "media.role" } } } } }, - { "$map": { "from": { "$ref": "request.audios" }, "as": "media", "in": { "type": "audio_url", "audio_url": { "url": { "$coalesce": [ { "$ref": "media.url" }, { "$ref": "media.dataUrl" } ] } }, "role": { "$omitEmpty": { "$ref": "media.role" } } } } } + "model": { + "$coalesce": [ + { + "$ref": "request.model" + }, + "MiniMax-H3" ] }, - "resolution": { "$omitEmpty": { "$coalesce": [ { "$ref": "request.resolution" }, { "$ref": "request.providerOptions.metaso-h3.resolution" }, "768P" ] } }, - "duration": { "$omitEmpty": { "$coalesce": [ { "$ref": "request.duration" }, { "$ref": "request.providerOptions.metaso-h3.duration" }, 5 ] } }, - "ratio": { "$omitEmpty": { "$coalesce": [ { "$ref": "request.aspectRatio" }, { "$ref": "request.providerOptions.metaso-h3.ratio" }, "16:9" ] } }, - "aigc_watermark": { "$omitEmpty": { "$ref": "request.providerOptions.metaso-h3.aigc_watermark" } } + "content": { + "$concatArrays": [ + { + "$if": { + "condition": { + "$gt": [ + { + "$len": { + "$ref": "request.prompt" + } + }, + 0 + ] + }, + "then": [ + { + "type": "text", + "text": { + "$ref": "request.prompt" + } + } + ], + "else": [] + } + }, + { + "$map": { + "from": { + "$ref": "request.images" + }, + "as": "media", + "in": { + "type": "image_url", + "image_url": { + "url": { + "$coalesce": [ + { + "$ref": "media.url" + }, + { + "$ref": "media.dataUrl" + } + ] + } + }, + "role": { + "$omitEmpty": { + "$ref": "media.role" + } + } + } + } + }, + { + "$map": { + "from": { + "$ref": "request.videos" + }, + "as": "media", + "in": { + "type": "video_url", + "video_url": { + "url": { + "$coalesce": [ + { + "$ref": "media.url" + }, + { + "$ref": "media.dataUrl" + } + ] + } + }, + "role": { + "$omitEmpty": { + "$ref": "media.role" + } + } + } + } + }, + { + "$map": { + "from": { + "$ref": "request.audios" + }, + "as": "media", + "in": { + "type": "audio_url", + "audio_url": { + "url": { + "$coalesce": [ + { + "$ref": "media.url" + }, + { + "$ref": "media.dataUrl" + } + ] + } + }, + "role": { + "$omitEmpty": { + "$ref": "media.role" + } + } + } + } + } + ] + }, + "resolution": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.resolution" + }, + { + "$ref": "request.providerOptions.metaso-h3.resolution" + }, + "768P" + ] + } + }, + "duration": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.duration" + }, + { + "$ref": "request.providerOptions.metaso-h3.duration" + }, + 5 + ] + } + }, + "ratio": { + "$omitEmpty": { + "$coalesce": [ + { + "$ref": "request.aspectRatio" + }, + { + "$ref": "request.providerOptions.metaso-h3.ratio" + }, + "16:9" + ] + } + }, + "aigc_watermark": { + "$omitEmpty": { + "$ref": "request.providerOptions.metaso-h3.aigc_watermark" + } + } } }, "poll": { @@ -60,41 +289,79 @@ "response": { "taskId": { "$coalesce": [ - { "$ref": "response.task_id" }, - { "$ref": "response.taskId" }, - { "$ref": "response.data.task_id" } + { + "$ref": "response.task_id" + }, + { + "$ref": "response.taskId" + }, + { + "$ref": "response.data.task_id" + } ] }, "status": { "$coalesce": [ - { "$ref": "response.task.status" }, - { "$ref": "response.status" }, - { "$ref": "response.data.status" }, + { + "$ref": "response.task.status" + }, + { + "$ref": "response.status" + }, + { + "$ref": "response.data.status" + }, "pending" ] }, "message": { "$coalesce": [ - { "$ref": "response.task.error.message" }, - { "$ref": "response.task.fail_reason" }, - { "$ref": "response.error.message" }, - { "$ref": "response.message" } + { + "$ref": "response.task.error.message" + }, + { + "$ref": "response.task.fail_reason" + }, + { + "$ref": "response.error.message" + }, + { + "$ref": "response.message" + } ] }, "videos": { "$coalesce": [ - { "$ref": "response.task.content.url" }, - { "$ref": "response.task.content.video_url" }, - { "$ref": "response.content.url" }, - { "$ref": "response.data.url" } + { + "$ref": "response.task.content.url" + }, + { + "$ref": "response.task.content.video_url" + }, + { + "$ref": "response.content.url" + }, + { + "$ref": "response.data.url" + } ] }, - "usage": { "$ref": "response.task.usage" }, - "errorPaths": ["task.error.type", "error.type", "error.code"], + "usage": { + "$ref": "response.task.usage" + }, + "errorPaths": [ + "task.error.type", + "error.type", + "error.code" + ], "resultEphemeral": true, - "messagePaths": ["task.error.message", "error.message"] + "messagePaths": [ + "task.error.message", + "error.message" + ] } } ] - } + }, + "documentation": "# METASO MiniMax H3\n\n秘塔 METASO MiniMax H3 文生视频 / 图生视频协议插件(异步任务模式)。\n\n## Provider\n\n| Provider | 能力 | 端点 |\n|---|---|---|\n| metaso-h3 | video | POST /api/minimax/v2/video_generation(创建)
GET /api/minimax/v2/query/video_generation/{taskId}(轮询) |\n\n## 配置\n\n在渠道中填写 API Key(METASO 控制台创建,形如 `mk-xxxxxxxx`),baseUrl 使用 `https://metaso.cn`。\n\n## 说明\n\n- 模型:`MiniMax-H3`(支持 768P / 2K,4-15 秒,文生图/图生视频/多模态参考),`MiniMax-H3-Max`(480P / 768P,5-15 秒)。\n- 文生视频:仅文本提示词,ratio 必填(21:9 / 16:9 / 4:3 / 1:1 / 3:4 / 9:16)。\n- 图生视频:图片 role 为 first_frame / last_frame(首尾帧)。\n- 多模态参考:图片 reference_image / 视频 reference_video / 音频 reference_audio。\n- 异步任务:创建后返回 task_id,轮询查询接口直到 status=succeeded,成片 URL 在 task.content.url。\n- 鉴权:`Authorization: Bearer mk-xxx`。\n\n---\n\n# METASO MiniMax H3 接口说明\n\n## 鉴权\n\n`Authorization: Bearer mk-xxxxxxxxxxxxxxxxxxxxxxxx`\n\n## 创建视频生成任务\n\nPOST `https://metaso.cn/api/minimax/v2/video_generation`\n\n请求体:\n\n```json\n{\n \"model\": \"MiniMax-H3\",\n \"content\": [\n { \"type\": \"text\", \"text\": \"视频描述\" },\n { \"type\": \"image_url\", \"image_url\": { \"url\": \"https://...\" }, \"role\": \"first_frame\" },\n { \"type\": \"video_url\", \"video_url\": { \"url\": \"https://...\" }, \"role\": \"reference_video\" },\n { \"type\": \"audio_url\", \"audio_url\": { \"url\": \"https://...\" }, \"role\": \"reference_audio\" }\n ],\n \"resolution\": \"768P\",\n \"duration\": 5,\n \"ratio\": \"16:9\"\n}\n```\n\n- content 必须包含一个非空 text 项。\n- 首尾帧(first_frame/last_frame)与多模态参考(reference_*)互斥。\n- 图片 ≤ 9 张、视频 ≤ 3 段、音频 ≤ 3 段;请求体总大小 ≤ 64 MB。\n\n响应:\n\n```json\n{ \"task_id\": \"424010985738629\" }\n```\n\n## 查询任务\n\nGET `https://metaso.cn/api/minimax/v2/query/video_generation/{task_id}`\n\n响应:\n\n```json\n{\n \"task\": {\n \"id\": \"424010985738629\",\n \"status\": \"succeeded\",\n \"content\": { \"url\": \"https://.../output.mp4\" },\n \"resolution\": \"2K\",\n \"duration\": 5,\n \"usage\": { \"total_seconds\": 5, \"output_seconds\": 5 }\n }\n}\n```\n\nstatus 取值:queued / running / succeeded / failed / cancelled。\n\n## 错误\n\n创建与查询均返回 OpenAI 风格错误体,含 `error.type` / `error.message` / `request_id`;余额不足为 402,速率限制为 429。\n\n\n## Manifest 完整接口定义\n\n以下 JSON 与插件包内实际 `manifest.json` 逐字段一致,覆盖插件身份、权限、配置、鉴权、参数、校验、创建、Agent、查询、取消、结果下载、响应和 Agent 响应映射。`documentation` 字段的值就是当前完整文档;为避免文档在自身内部无限递归,JSON 中仅用等义占位文本表示正文。\n\n```json\n{\n \"apiVersion\": \"yingce.plugin/v2\",\n \"id\": \"metaso-h3\",\n \"name\": \"METASO MiniMax H3\",\n \"version\": \"1.0.0\",\n \"author\": \"METASO\",\n \"description\": \"秘塔 METASO MiniMax H3 文生视频/图生视频协议插件(异步任务)。\",\n \"permissions\": [\n \"generation.run\",\n \"media.read\"\n ],\n \"configuration\": {\n \"fields\": [\n {\n \"name\": \"apiKey\",\n \"type\": \"secret\",\n \"label\": \"API Key\",\n \"required\": true\n }\n ]\n },\n \"contributes\": {\n \"providers\": [\n {\n \"id\": \"metaso-h3\",\n \"label\": \"METASO MiniMax H3\",\n \"capabilities\": [\n \"video\"\n ],\n \"scopes\": [\n \"admin.system-channel\",\n \"user.custom-channel\",\n \"canvas\",\n \"creation\",\n \"agent\"\n ],\n \"baseUrl\": \"https://metaso.cn\",\n \"auth\": {\n \"type\": \"bearer\",\n \"field\": \"apiKey\"\n },\n \"requiresPublicMediaUrls\": true,\n \"parameters\": [\n {\n \"name\": \"model\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"model\",\n \"description\": \"视频模型 ID(MiniMax-H3 / MiniMax-H3-Max)。\"\n },\n {\n \"name\": \"prompt\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"prompt/content/input\",\n \"description\": \"视频提示词。\"\n },\n {\n \"name\": \"images\",\n \"type\": \"media[]\",\n \"required\": false,\n \"mapping\": \"first/last/reference image\",\n \"description\": \"显式 role 图片输入(首帧/尾帧/参考图)。\"\n },\n {\n \"name\": \"videos\",\n \"type\": \"media[]\",\n \"required\": false,\n \"mapping\": \"reference video\",\n \"description\": \"参考视频。\"\n },\n {\n \"name\": \"audios\",\n \"type\": \"media[]\",\n \"required\": false,\n \"mapping\": \"reference audio/voice\",\n \"description\": \"参考音频或音色。\"\n },\n {\n \"name\": \"duration\",\n \"type\": \"integer\",\n \"required\": false,\n \"mapping\": \"duration/seconds\",\n \"description\": \"时长秒数(4-15)。\"\n },\n {\n \"name\": \"aspectRatio\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"ratio/aspect_ratio/size\",\n \"description\": \"画幅比例(16:9 等)。\"\n },\n {\n \"name\": \"resolution\",\n \"type\": \"string\",\n \"required\": false,\n \"mapping\": \"resolution\",\n \"description\": \"分辨率档位(768P / 2K)。\"\n },\n {\n \"name\": \"watermark\",\n \"type\": \"boolean\",\n \"required\": false,\n \"mapping\": \"watermark\",\n \"description\": \"AIGC 水印开关。\"\n },\n {\n \"name\": \"providerOptions\",\n \"type\": \"object\",\n \"required\": false,\n \"mapping\": \"provider-specific fields\",\n \"description\": \"插件命名空间内的厂商扩展字段。\"\n }\n ],\n \"create\": {\n \"method\": \"POST\",\n \"path\": \"/api/minimax/v2/video_generation\",\n \"contentType\": \"application/json\",\n \"body\": {\n \"model\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.model\"\n },\n \"MiniMax-H3\"\n ]\n },\n \"content\": {\n \"$concatArrays\": [\n {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\n \"$ref\": \"request.prompt\"\n }\n },\n 0\n ]\n },\n \"then\": [\n {\n \"type\": \"text\",\n \"text\": {\n \"$ref\": \"request.prompt\"\n }\n }\n ],\n \"else\": []\n }\n },\n {\n \"$map\": {\n \"from\": {\n \"$ref\": \"request.images\"\n },\n \"as\": \"media\",\n \"in\": {\n \"type\": \"image_url\",\n \"image_url\": {\n \"url\": {\n \"$coalesce\": [\n {\n \"$ref\": \"media.url\"\n },\n {\n \"$ref\": \"media.dataUrl\"\n }\n ]\n }\n },\n \"role\": {\n \"$omitEmpty\": {\n \"$ref\": \"media.role\"\n }\n }\n }\n }\n },\n {\n \"$map\": {\n \"from\": {\n \"$ref\": \"request.videos\"\n },\n \"as\": \"media\",\n \"in\": {\n \"type\": \"video_url\",\n \"video_url\": {\n \"url\": {\n \"$coalesce\": [\n {\n \"$ref\": \"media.url\"\n },\n {\n \"$ref\": \"media.dataUrl\"\n }\n ]\n }\n },\n \"role\": {\n \"$omitEmpty\": {\n \"$ref\": \"media.role\"\n }\n }\n }\n }\n },\n {\n \"$map\": {\n \"from\": {\n \"$ref\": \"request.audios\"\n },\n \"as\": \"media\",\n \"in\": {\n \"type\": \"audio_url\",\n \"audio_url\": {\n \"url\": {\n \"$coalesce\": [\n {\n \"$ref\": \"media.url\"\n },\n {\n \"$ref\": \"media.dataUrl\"\n }\n ]\n }\n },\n \"role\": {\n \"$omitEmpty\": {\n \"$ref\": \"media.role\"\n }\n }\n }\n }\n }\n ]\n },\n \"resolution\": {\n \"$omitEmpty\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.resolution\"\n },\n {\n \"$ref\": \"request.providerOptions.metaso-h3.resolution\"\n },\n \"768P\"\n ]\n }\n },\n \"duration\": {\n \"$omitEmpty\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.duration\"\n },\n {\n \"$ref\": \"request.providerOptions.metaso-h3.duration\"\n },\n 5\n ]\n }\n },\n \"ratio\": {\n \"$omitEmpty\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.aspectRatio\"\n },\n {\n \"$ref\": \"request.providerOptions.metaso-h3.ratio\"\n },\n \"16:9\"\n ]\n }\n },\n \"aigc_watermark\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.metaso-h3.aigc_watermark\"\n }\n }\n }\n },\n \"poll\": {\n \"method\": \"GET\",\n \"path\": \"/api/minimax/v2/query/video_generation/{{taskId}}\"\n },\n \"response\": {\n \"taskId\": {\n \"$coalesce\": [\n {\n \"$ref\": \"response.task_id\"\n },\n {\n \"$ref\": \"response.taskId\"\n },\n {\n \"$ref\": \"response.data.task_id\"\n }\n ]\n },\n \"status\": {\n \"$coalesce\": [\n {\n \"$ref\": \"response.task.status\"\n },\n {\n \"$ref\": \"response.status\"\n },\n {\n \"$ref\": \"response.data.status\"\n },\n \"pending\"\n ]\n },\n \"message\": {\n \"$coalesce\": [\n {\n \"$ref\": \"response.task.error.message\"\n },\n {\n \"$ref\": \"response.task.fail_reason\"\n },\n {\n \"$ref\": \"response.error.message\"\n },\n {\n \"$ref\": \"response.message\"\n }\n ]\n },\n \"videos\": {\n \"$coalesce\": [\n {\n \"$ref\": \"response.task.content.url\"\n },\n {\n \"$ref\": \"response.task.content.video_url\"\n },\n {\n \"$ref\": \"response.content.url\"\n },\n {\n \"$ref\": \"response.data.url\"\n }\n ]\n },\n \"usage\": {\n \"$ref\": \"response.task.usage\"\n },\n \"errorPaths\": [\n \"task.error.type\",\n \"error.type\",\n \"error.code\"\n ],\n \"resultEphemeral\": true,\n \"messagePaths\": [\n \"task.error.message\",\n \"error.message\"\n ]\n }\n }\n ]\n },\n \"documentation\": \"<当前插件的完整 documentation,由 README.md 与 docs/interface.md 拼接而成;为避免 JSON 递归,此处不重复展开正文。>\"\n}\n```\n\n" }