* feat(image): 图片参数 - 统一插件声明配置与生成合同 * docs(image): 图片参数 - 说明声明合同与验证边界 * fix(plugins): 图片声明 - 保留内联素材支持并同步制品文档 * fix(image): 参数合同 - 对齐审批意图和尺寸预检调用方 * fix(image): 调用链 - 保留公开意图并接通独立分辨率 * fix(image): 图片参数 - 补齐分辨率接线与目录价格投影
1364 lines
92 KiB
JSON
1364 lines
92 KiB
JSON
{
|
||
"apiVersion": "yingce.plugin/v2",
|
||
"id": "cangyuan-midjourney",
|
||
"name": "沧元 Midjourney",
|
||
"version": "1.1.0",
|
||
"author": "沧元算力 / 影绘",
|
||
"description": "独立适配 V7 与默认 V8.2 的 1K/2K 线路,按供应商合同创建、查询并提取全部图片。",
|
||
"enabled": true,
|
||
"installable": true,
|
||
"permissions": [
|
||
"generation.run",
|
||
"media.read"
|
||
],
|
||
"configuration": {
|
||
"fields": [
|
||
{
|
||
"name": "apiKey",
|
||
"type": "secret",
|
||
"label": "API Key",
|
||
"required": true
|
||
}
|
||
]
|
||
},
|
||
"contributes": {
|
||
"providers": [
|
||
{
|
||
"id": "cangyuan-midjourney-v7",
|
||
"label": "沧元 Midjourney V7",
|
||
"capabilities": [
|
||
"image"
|
||
],
|
||
"scopes": [
|
||
"admin.system-channel",
|
||
"user.custom-channel",
|
||
"canvas",
|
||
"creation",
|
||
"agent"
|
||
],
|
||
"baseUrl": "https://ai.cangyuansuanli.cn/v1",
|
||
"requiresPublicMediaUrls": true,
|
||
"auth": {
|
||
"type": "bearer",
|
||
"field": "apiKey"
|
||
},
|
||
"imageParameters": [
|
||
{
|
||
"name": "size",
|
||
"label": "画幅 / 尺寸",
|
||
"type": "string",
|
||
"binding": "aspectRatio"
|
||
},
|
||
{
|
||
"name": "count",
|
||
"label": "生成数量",
|
||
"type": "integer",
|
||
"binding": "imageCount",
|
||
"min": 1,
|
||
"max": 1,
|
||
"step": 1,
|
||
"default": 1
|
||
}
|
||
],
|
||
"parameters": [
|
||
{
|
||
"name": "model",
|
||
"type": "string",
|
||
"required": true,
|
||
"mapping": "model",
|
||
"description": "供应商公开模型名;两条线路分别校验。"
|
||
},
|
||
{
|
||
"name": "prompt",
|
||
"type": "string",
|
||
"required": true,
|
||
"mapping": "prompt",
|
||
"description": "原提示词;1K/2K 默认 V8.2,可写官网 --v / --niji 参数;V7 不支持这些版本参数。"
|
||
},
|
||
{
|
||
"name": "images",
|
||
"type": "media[]",
|
||
"mapping": "images[] / mask",
|
||
"description": "按宿主显式 role 转换为 HTTPS URL 字符串数组;mask 单独映射。"
|
||
},
|
||
{
|
||
"name": "imageCount",
|
||
"type": "integer",
|
||
"mapping": "n=1",
|
||
"description": "一次提交只能为 1,结果 data 可能含多张,全部保存。"
|
||
},
|
||
{
|
||
"name": "aspectRatio",
|
||
"type": "string",
|
||
"mapping": "size",
|
||
"description": "比例或 V7 宽x高;空值和 auto 不发送,沿用供应商默认值。"
|
||
},
|
||
{
|
||
"name": "providerOptions",
|
||
"type": "object",
|
||
"mapping": "cangyuan-midjourney-v82.speed/reference",
|
||
"description": "1K/2K 插件命名空间可指定 speed=relax/fast、reference=image/style/edit/moodboard/editor。V7 没有速度或版本扩展字段。"
|
||
}
|
||
],
|
||
"validations": [
|
||
{
|
||
"assert": {
|
||
"$in": [
|
||
{
|
||
"$ref": "request.model"
|
||
},
|
||
[
|
||
"midjourney-v7"
|
||
]
|
||
]
|
||
},
|
||
"message": "模型名与 Midjourney 线路不匹配。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$lte": [
|
||
{
|
||
"$ref": "request.imageCount"
|
||
},
|
||
1
|
||
]
|
||
},
|
||
"message": "Midjourney 一次提交 n 只能为 1;返回多张图片会全部保存。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$trim": {
|
||
"$ref": "request.prompt"
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"message": "Midjourney 提示词不能为空。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$eq": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$first": {
|
||
"$split": [
|
||
{
|
||
"$ref": "media.value"
|
||
},
|
||
":"
|
||
]
|
||
}
|
||
},
|
||
"https"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"message": "Midjourney 参考图和蒙版必须是 HTTPS URL,不能发送本地文件或 data URI。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$lte": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
5
|
||
]
|
||
},
|
||
"message": "Midjourney V7 参考图最多 5 张。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$eq": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$eq": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"message": "Midjourney V7 线路不支持蒙版。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$lte": [
|
||
{
|
||
"$len": {
|
||
"$ref": "request.prompt"
|
||
}
|
||
},
|
||
4000
|
||
]
|
||
},
|
||
"message": "Midjourney V7 提示词最多 4000 字符。"
|
||
}
|
||
],
|
||
"create": {
|
||
"method": "POST",
|
||
"path": "/v1/images/generations",
|
||
"contentType": "application/json",
|
||
"body": {
|
||
"model": {
|
||
"$ref": "request.model"
|
||
},
|
||
"prompt": {
|
||
"$ref": "request.prompt"
|
||
},
|
||
"n": 1,
|
||
"size": {
|
||
"$if": {
|
||
"condition": {
|
||
"$in": [
|
||
{
|
||
"$lower": {
|
||
"$trim": {
|
||
"$ref": "request.aspectRatio"
|
||
}
|
||
}
|
||
},
|
||
[
|
||
"",
|
||
"auto"
|
||
]
|
||
]
|
||
},
|
||
"then": null,
|
||
"else": {
|
||
"$ref": "request.aspectRatio"
|
||
}
|
||
}
|
||
},
|
||
"images": {
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": {
|
||
"$map": {
|
||
"from": {
|
||
"$sortByOrder": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"as": "media",
|
||
"in": {
|
||
"$ref": "media.value"
|
||
}
|
||
}
|
||
},
|
||
"else": null
|
||
}
|
||
},
|
||
"response_format": "url",
|
||
"async": false
|
||
},
|
||
"pathTemplate": {
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": "/v1/images/edits",
|
||
"else": "/v1/images/generations"
|
||
}
|
||
}
|
||
},
|
||
"poll": {
|
||
"method": "GET",
|
||
"path": "/v1/images/generations/{{taskId}}",
|
||
"pathTemplate": {
|
||
"$concat": [
|
||
{
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": "/v1/images/edits",
|
||
"else": "/v1/images/generations"
|
||
}
|
||
},
|
||
"/",
|
||
{
|
||
"$ref": "taskId"
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"response": {
|
||
"taskIdPaths": [
|
||
"id",
|
||
"task_id"
|
||
],
|
||
"statusPaths": [
|
||
"status"
|
||
],
|
||
"errorPaths": [
|
||
"error.code"
|
||
],
|
||
"messagePaths": [
|
||
"error.message",
|
||
"message"
|
||
],
|
||
"images": {
|
||
"$map": {
|
||
"from": {
|
||
"$ref": "response.data"
|
||
},
|
||
"as": "item",
|
||
"in": {
|
||
"url": {
|
||
"$ref": "item.url"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"usage": {
|
||
"$ref": "response.usage"
|
||
}
|
||
}
|
||
},
|
||
{
|
||
"id": "cangyuan-midjourney-v82",
|
||
"label": "沧元 Midjourney 1K/2K · V8.2",
|
||
"capabilities": [
|
||
"image"
|
||
],
|
||
"scopes": [
|
||
"admin.system-channel",
|
||
"user.custom-channel",
|
||
"canvas",
|
||
"creation",
|
||
"agent"
|
||
],
|
||
"baseUrl": "https://ai.cangyuansuanli.cn/v1",
|
||
"requiresPublicMediaUrls": true,
|
||
"auth": {
|
||
"type": "bearer",
|
||
"field": "apiKey"
|
||
},
|
||
"imageParameters": [
|
||
{
|
||
"name": "size",
|
||
"label": "画幅比例",
|
||
"type": "string",
|
||
"binding": "aspectRatio"
|
||
},
|
||
{
|
||
"name": "count",
|
||
"label": "生成数量",
|
||
"type": "integer",
|
||
"binding": "imageCount",
|
||
"min": 1,
|
||
"max": 1,
|
||
"step": 1,
|
||
"default": 1
|
||
},
|
||
{
|
||
"name": "speed",
|
||
"label": "生成速度",
|
||
"type": "string",
|
||
"binding": "providerOptions.cangyuan-midjourney-v82.speed",
|
||
"values": [
|
||
"relax",
|
||
"fast"
|
||
],
|
||
"pricing": true
|
||
},
|
||
{
|
||
"name": "reference",
|
||
"label": "参考方式",
|
||
"type": "string",
|
||
"binding": "providerOptions.cangyuan-midjourney-v82.reference",
|
||
"values": [
|
||
"image",
|
||
"style",
|
||
"edit",
|
||
"moodboard",
|
||
"editor"
|
||
]
|
||
}
|
||
],
|
||
"parameters": [
|
||
{
|
||
"name": "model",
|
||
"type": "string",
|
||
"required": true,
|
||
"mapping": "model",
|
||
"description": "供应商公开模型名;两条线路分别校验。"
|
||
},
|
||
{
|
||
"name": "prompt",
|
||
"type": "string",
|
||
"required": true,
|
||
"mapping": "prompt",
|
||
"description": "原提示词;1K/2K 默认 V8.2,可写官网 --v / --niji 参数;V7 不支持这些版本参数。"
|
||
},
|
||
{
|
||
"name": "images",
|
||
"type": "media[]",
|
||
"mapping": "images[] / mask",
|
||
"description": "按宿主显式 role 转换为 HTTPS URL 字符串数组;mask 单独映射。"
|
||
},
|
||
{
|
||
"name": "imageCount",
|
||
"type": "integer",
|
||
"mapping": "n=1",
|
||
"description": "一次提交只能为 1,结果 data 可能含多张,全部保存。"
|
||
},
|
||
{
|
||
"name": "aspectRatio",
|
||
"type": "string",
|
||
"mapping": "size",
|
||
"description": "比例或 V7 宽x高;空值和 auto 不发送,沿用供应商默认值。"
|
||
},
|
||
{
|
||
"name": "providerOptions",
|
||
"type": "object",
|
||
"mapping": "cangyuan-midjourney-v82.speed/reference",
|
||
"description": "1K/2K 插件命名空间可指定 speed=relax/fast、reference=image/style/edit/moodboard/editor。V7 没有速度或版本扩展字段。"
|
||
}
|
||
],
|
||
"validations": [
|
||
{
|
||
"assert": {
|
||
"$in": [
|
||
{
|
||
"$ref": "request.model"
|
||
},
|
||
[
|
||
"midjourney-1k",
|
||
"midjourney-2k"
|
||
]
|
||
]
|
||
},
|
||
"message": "模型名与 Midjourney 线路不匹配。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$lte": [
|
||
{
|
||
"$ref": "request.imageCount"
|
||
},
|
||
1
|
||
]
|
||
},
|
||
"message": "Midjourney 一次提交 n 只能为 1;返回多张图片会全部保存。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$trim": {
|
||
"$ref": "request.prompt"
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"message": "Midjourney 提示词不能为空。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$eq": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$first": {
|
||
"$split": [
|
||
{
|
||
"$ref": "media.value"
|
||
},
|
||
":"
|
||
]
|
||
}
|
||
},
|
||
"https"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"message": "Midjourney 参考图和蒙版必须是 HTTPS URL,不能发送本地文件或 data URI。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$in": [
|
||
{
|
||
"$coalesce": [
|
||
{
|
||
"$ref": "request.providerOptions.cangyuan-midjourney-v82.speed"
|
||
},
|
||
"relax"
|
||
]
|
||
},
|
||
[
|
||
"relax",
|
||
"fast"
|
||
]
|
||
]
|
||
},
|
||
"message": "Midjourney speed 只支持 relax 或 fast。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$in": [
|
||
{
|
||
"$coalesce": [
|
||
{
|
||
"$ref": "request.providerOptions.cangyuan-midjourney-v82.reference"
|
||
},
|
||
{
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$eq": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"edit_source"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": "editor",
|
||
"else": "image"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
[
|
||
"image",
|
||
"style",
|
||
"edit",
|
||
"moodboard",
|
||
"editor"
|
||
]
|
||
]
|
||
},
|
||
"message": "Midjourney reference 类型无效。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$or": [
|
||
{
|
||
"$not": {
|
||
"$eq": [
|
||
{
|
||
"$coalesce": [
|
||
{
|
||
"$ref": "request.providerOptions.cangyuan-midjourney-v82.reference"
|
||
},
|
||
{
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$eq": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"edit_source"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": "editor",
|
||
"else": "image"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"editor"
|
||
]
|
||
}
|
||
},
|
||
{
|
||
"$eq": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
1
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"message": "Midjourney editor 只能有一张源图。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$or": [
|
||
{
|
||
"$ne": [
|
||
{
|
||
"$coalesce": [
|
||
{
|
||
"$ref": "request.providerOptions.cangyuan-midjourney-v82.reference"
|
||
},
|
||
{
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$eq": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"edit_source"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": "editor",
|
||
"else": "image"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"edit"
|
||
]
|
||
},
|
||
{
|
||
"$lte": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
4
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"message": "Midjourney edit 参考图最多 4 张。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$lte": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$eq": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
1
|
||
]
|
||
},
|
||
"message": "Midjourney 蒙版只能有一张。"
|
||
},
|
||
{
|
||
"assert": {
|
||
"$or": [
|
||
{
|
||
"$eq": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$eq": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
{
|
||
"$and": [
|
||
{
|
||
"$eq": [
|
||
{
|
||
"$coalesce": [
|
||
{
|
||
"$ref": "request.providerOptions.cangyuan-midjourney-v82.reference"
|
||
},
|
||
{
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$eq": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"edit_source"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": "editor",
|
||
"else": "image"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"editor"
|
||
]
|
||
},
|
||
{
|
||
"$eq": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
1
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"message": "蒙版只能用于 editor,且必须有一张源图。"
|
||
}
|
||
],
|
||
"create": {
|
||
"method": "POST",
|
||
"path": "/v1/images/generations",
|
||
"contentType": "application/json",
|
||
"body": {
|
||
"model": {
|
||
"$ref": "request.model"
|
||
},
|
||
"prompt": {
|
||
"$ref": "request.prompt"
|
||
},
|
||
"n": 1,
|
||
"size": {
|
||
"$if": {
|
||
"condition": {
|
||
"$in": [
|
||
{
|
||
"$lower": {
|
||
"$trim": {
|
||
"$ref": "request.aspectRatio"
|
||
}
|
||
}
|
||
},
|
||
[
|
||
"",
|
||
"auto"
|
||
]
|
||
]
|
||
},
|
||
"then": null,
|
||
"else": {
|
||
"$ref": "request.aspectRatio"
|
||
}
|
||
}
|
||
},
|
||
"images": {
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": {
|
||
"$map": {
|
||
"from": {
|
||
"$sortByOrder": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"as": "media",
|
||
"in": {
|
||
"$ref": "media.value"
|
||
}
|
||
}
|
||
},
|
||
"else": null
|
||
}
|
||
},
|
||
"response_format": "url",
|
||
"async": false,
|
||
"speed": {
|
||
"$omitEmpty": {
|
||
"$ref": "request.providerOptions.cangyuan-midjourney-v82.speed"
|
||
}
|
||
},
|
||
"reference": {
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": {
|
||
"$coalesce": [
|
||
{
|
||
"$ref": "request.providerOptions.cangyuan-midjourney-v82.reference"
|
||
},
|
||
{
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$eq": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"edit_source"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": "editor",
|
||
"else": "image"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"else": null
|
||
}
|
||
},
|
||
"mask": {
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$eq": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": {
|
||
"$first": {
|
||
"$map": {
|
||
"from": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$eq": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
},
|
||
"as": "media",
|
||
"in": {
|
||
"$ref": "media.value"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"else": null
|
||
}
|
||
}
|
||
},
|
||
"pathTemplate": {
|
||
"$if": {
|
||
"condition": {
|
||
"$and": [
|
||
{
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
{
|
||
"$eq": [
|
||
{
|
||
"$coalesce": [
|
||
{
|
||
"$ref": "request.providerOptions.cangyuan-midjourney-v82.reference"
|
||
},
|
||
{
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$eq": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"edit_source"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": "editor",
|
||
"else": "image"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"editor"
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"then": "/v1/images/edits",
|
||
"else": "/v1/images/generations"
|
||
}
|
||
}
|
||
},
|
||
"poll": {
|
||
"method": "GET",
|
||
"path": "/v1/images/generations/{{taskId}}",
|
||
"pathTemplate": {
|
||
"$concat": [
|
||
{
|
||
"$if": {
|
||
"condition": {
|
||
"$and": [
|
||
{
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$ne": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"mask"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
{
|
||
"$eq": [
|
||
{
|
||
"$coalesce": [
|
||
{
|
||
"$ref": "request.providerOptions.cangyuan-midjourney-v82.reference"
|
||
},
|
||
{
|
||
"$if": {
|
||
"condition": {
|
||
"$gt": [
|
||
{
|
||
"$len": {
|
||
"$filter": {
|
||
"from": {
|
||
"$ref": "request.images"
|
||
},
|
||
"as": "media",
|
||
"where": {
|
||
"$eq": [
|
||
{
|
||
"$ref": "media.role"
|
||
},
|
||
"edit_source"
|
||
]
|
||
}
|
||
}
|
||
}
|
||
},
|
||
0
|
||
]
|
||
},
|
||
"then": "editor",
|
||
"else": "image"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"editor"
|
||
]
|
||
}
|
||
]
|
||
},
|
||
"then": "/v1/images/edits",
|
||
"else": "/v1/images/generations"
|
||
}
|
||
},
|
||
"/",
|
||
{
|
||
"$ref": "taskId"
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"response": {
|
||
"taskIdPaths": [
|
||
"id",
|
||
"task_id"
|
||
],
|
||
"statusPaths": [
|
||
"status"
|
||
],
|
||
"errorPaths": [
|
||
"error.code"
|
||
],
|
||
"messagePaths": [
|
||
"error.message",
|
||
"message"
|
||
],
|
||
"images": {
|
||
"$map": {
|
||
"from": {
|
||
"$ref": "response.data"
|
||
},
|
||
"as": "item",
|
||
"in": {
|
||
"url": {
|
||
"$ref": "item.url"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"usage": {
|
||
"$ref": "response.usage"
|
||
}
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"documentation": "# 沧元 Midjourney\n\n独立声明式协议插件(`yingce.plugin/v2`),同时提供 `cangyuan-midjourney-v7` 和 `cangyuan-midjourney-v82`。使用宿主的渠道鉴权、出站安全检查、下载和资源持久化,不执行额外服务代码。\n\nV7 使用 `midjourney-v7`,无分辨率和速度档。1K/2K 使用 `midjourney-1k` / `midjourney-2k`,供应商默认版本为 V8.2,提示词可显式写 `--v 8.2`;不存在独立的 `midjourney-v8.2` 模型名。\n\n两条线路不能互换。1K/2K 返回官网 CDN 原链,服务器下载可能遇到 HTTP 403;本插件不会伪报保存成功或自动换模型。V7 返回供应商可直接下载的结果地址。`n=1` 表示一次请求,返回的所有图片均交给宿主保存。\n\n完整接口见 [docs/interface.md](docs/interface.md)。\n\n---\n\n# 沧元 Midjourney 接口字段\n\n## 来源与协议身份\n\n- V7:https://ai.cangyuansuanli.cn/docs/models/midjourney-v7\n- V8.2 / 1K / 2K:https://ai.cangyuansuanli.cn/docs/models/midjourney-1k\n- 模型清单以渠道 `GET /v1/models` 为准:`midjourney-v7`、`midjourney-1k`、`midjourney-2k`。\n- 插件 ID `cangyuan-midjourney`;Provider ID `cangyuan-midjourney-v7`、`cangyuan-midjourney-v82`。\n- 配置 `apiKey`(secret、必填),由宿主渠道配置提供;鉴权 `Authorization: Bearer <TOKEN>`。\n- 创建 `POST /v1/images/generations`;源图编辑 `POST /v1/images/edits`。\n- 查询 `GET /v1/images/generations/{task_id}`;编辑查询 `GET /v1/images/edits/{task_id}`。\n- 默认同步等待(`async=false`);保留任务 ID、查询路径以及 pending/completed/failed 的响应解析。\n- 不声明取消或单独结果下载端点,供应商未提供相应合同。\n\n## 统一参数与上游请求\n\n| 参数 | 映射与约束 |\n| --- | --- |\n| `model` | 两条线路分别校验公开模型名,不自动换模型。 |\n| `prompt` | 原样传递;V7 最多 4000 字符。1K/2K 可在提示词写 `--v 8.2`,省略版本时由供应商默认 V8.2。 |\n| `images` | 依据宿主 role 排序,映射为 HTTPS URL 字符串数组;不能发 data URI 或本地文件。V7 最多 5 张,拒绝蒙版。 |\n| `imageCount` | 只能为 1 或未设置,上游固定 `n=1`;返回多张不截断。 |\n| `aspectRatio` | 传 `size`;空值或 auto 不发送。V7 支持 1:1 / 16:9 / 9:16 / 4:3 / 3:4 / 3:2 / 2:3 / 5:4 / 4:5 / 21:9 及对应宽x高;默认 16:9。1K/2K 支持 1:2 / 6:11 / 9:16 / 2:3 / 3:4 / 4:5 / 5:6 / 1:1 及其反向比例。 |\n| `providerOptions` | 仅 1K/2K 使用 `cangyuan-midjourney-v82.speed`(relax / fast)和 `reference`(image / style / edit / moodboard / editor)。不把速度映射为 quality。 |\n\n`reference=editor` 或宿主显式 `edit_source` 默认走 edits,必须只有一张源图;`reference=edit` 走 generations,最多四张图。mask role 单独映射为 `mask` HTTPS URL,仅 editor 可用。style/moodboard 等含义由调用方显式指定,插件不猜测风格用途。speed 不指定时不发送,沿用供应商默认或 prompt 中的 --fast/--relax;两者同时指定时须一致。\n\nV7 不支持 --v、--niji、--fast、--hd,且不发送 speed、quality、resolution、background、output_format、mask。1K/2K 不发送 quality、resolution、aspect_ratio、background、output_format,不支持 b64_json;不要写 --turbo,1K 不写 --hd。\n\n两条线路均固定 `response_format=url`、`async=false`。请求完整字段、校验表达式与动态端点见下方 Manifest,未列出的字段不透传。\n\n## 响应、保存和错误\n\n- 创建或查询任务 ID:`id` / `task_id`;查询保留当前 task ID。\n- 状态读取 `status`,queued/pending 为等待,processing/running 为进行中,completed/succeeded 为完成,failed 为失败。\n- 同步 `data[].url` 无 status 时,宿主依据真实图片引用判定完成;遍历全部 data 元素。\n- 错误读取 `error.code` 和 `error.message` / `message`;空结果仍失败,不伪造媒体。\n- 用量读取 `usage`,不在插件自行计算积分。\n- 所有 URL 通过现有宿主 SSRF、跨域凭证隔离、大小/MIME 校验和资源保存。跨源图片不携带供应商 API Key。\n- 1K/2K 官方 CDN HTTP 403 与协议字段映射是两件事;新增插件不能保证消除 CDN 拦截。失败保留原任务恢复机制,不提交新的收费生成。\n\n## 动态图片参数\n\n`contributes.providers[].imageParameters` 是渠道模型、前台模型与生成界面共用的参数合同。`name` 为稳定身份,`type`、`values`、`min/max/step`、`default` 描述输入;`models` 限定适用上游模型,`enabled` 为初始启用状态。只有 `pricing: true` 的启用字段允许作为价格条件;其他参数仍参与生成。渠道可收窄范围,绑定与计价资格由插件拥有。`binding` 映射到统一请求或插件自己的 `providerOptions` 命名空间。\n\n<!-- YINGCE_MANIFEST_CONTRACT_START -->\n## Manifest 完整接口定义\n\n以下 JSON 与插件包内实际 `manifest.json` 逐字段一致,覆盖插件身份、权限、配置、鉴权、参数、校验、创建、Agent、查询、取消、结果下载、响应和 Agent 响应映射。`documentation` 字段的值就是当前完整文档;为避免文档在自身内部无限递归,JSON 中仅用等义占位文本表示正文。\n\n```json\n{\n \"apiVersion\": \"yingce.plugin/v2\",\n \"id\": \"cangyuan-midjourney\",\n \"name\": \"沧元 Midjourney\",\n \"version\": \"1.1.0\",\n \"author\": \"沧元算力 / 影绘\",\n \"description\": \"独立适配 V7 与默认 V8.2 的 1K/2K 线路,按供应商合同创建、查询并提取全部图片。\",\n \"enabled\": true,\n \"installable\": true,\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\": \"cangyuan-midjourney-v7\",\n \"label\": \"沧元 Midjourney V7\",\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://ai.cangyuansuanli.cn/v1\",\n \"requiresPublicMediaUrls\": true,\n \"auth\": {\n \"type\": \"bearer\",\n \"field\": \"apiKey\"\n },\n \"imageParameters\": [\n {\n \"name\": \"size\",\n \"label\": \"画幅 / 尺寸\",\n \"type\": \"string\",\n \"binding\": \"aspectRatio\"\n },\n {\n \"name\": \"count\",\n \"label\": \"生成数量\",\n \"type\": \"integer\",\n \"binding\": \"imageCount\",\n \"min\": 1,\n \"max\": 1,\n \"step\": 1,\n \"default\": 1\n }\n ],\n \"parameters\": [\n {\n \"name\": \"model\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"model\",\n \"description\": \"供应商公开模型名;两条线路分别校验。\"\n },\n {\n \"name\": \"prompt\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"prompt\",\n \"description\": \"原提示词;1K/2K 默认 V8.2,可写官网 --v / --niji 参数;V7 不支持这些版本参数。\"\n },\n {\n \"name\": \"images\",\n \"type\": \"media[]\",\n \"mapping\": \"images[] / mask\",\n \"description\": \"按宿主显式 role 转换为 HTTPS URL 字符串数组;mask 单独映射。\"\n },\n {\n \"name\": \"imageCount\",\n \"type\": \"integer\",\n \"mapping\": \"n=1\",\n \"description\": \"一次提交只能为 1,结果 data 可能含多张,全部保存。\"\n },\n {\n \"name\": \"aspectRatio\",\n \"type\": \"string\",\n \"mapping\": \"size\",\n \"description\": \"比例或 V7 宽x高;空值和 auto 不发送,沿用供应商默认值。\"\n },\n {\n \"name\": \"providerOptions\",\n \"type\": \"object\",\n \"mapping\": \"cangyuan-midjourney-v82.speed/reference\",\n \"description\": \"1K/2K 插件命名空间可指定 speed=relax/fast、reference=image/style/edit/moodboard/editor。V7 没有速度或版本扩展字段。\"\n }\n ],\n \"validations\": [\n {\n \"assert\": {\n \"$in\": [\n {\n \"$ref\": \"request.model\"\n },\n [\n \"midjourney-v7\"\n ]\n ]\n },\n \"message\": \"模型名与 Midjourney 线路不匹配。\"\n },\n {\n \"assert\": {\n \"$lte\": [\n {\n \"$ref\": \"request.imageCount\"\n },\n 1\n ]\n },\n \"message\": \"Midjourney 一次提交 n 只能为 1;返回多张图片会全部保存。\"\n },\n {\n \"assert\": {\n \"$gt\": [\n {\n \"$len\": {\n \"$trim\": {\n \"$ref\": \"request.prompt\"\n }\n }\n },\n 0\n ]\n },\n \"message\": \"Midjourney 提示词不能为空。\"\n },\n {\n \"assert\": {\n \"$eq\": [\n {\n \"$len\": {\n \"$filter\": {\n \"from\": {\n \"$ref\": \"request.images\"\n },\n \"as\": \"media\",\n \"where\": {\n \"$ne\": [\n {\n \"$first\": {\n \"$split\": [\n {\n \"$ref\": \"media.value\"\n },\n \":\"\n ]\n }\n },\n \"https\"\n ]\n }\n }\n }\n },\n 0\n ]\n },\n \"message\": \"Midjourney 参考图和蒙版必须是 HTTPS URL,不能发送本地文件或 data URI。\"\n },\n {\n \"assert\": {\n \"$lte\": [\n {\n \"$len\": {\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 },\n 5\n ]\n },\n \"message\": \"Midjourney V7 参考图最多 5 张。\"\n },\n {\n \"assert\": {\n \"$eq\": [\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 \"message\": \"Midjourney V7 线路不支持蒙版。\"\n },\n {\n \"assert\": {\n \"$lte\": [\n {\n \"$len\": {\n \"$ref\": \"request.prompt\"\n }\n },\n 4000\n ]\n },\n \"message\": \"Midjourney V7 提示词最多 4000 字符。\"\n }\n ],\n \"create\": {\n \"method\": \"POST\",\n \"path\": \"/v1/images/generations\",\n \"contentType\": \"application/json\",\n \"body\": {\n \"model\": {\n \"$ref\": \"request.model\"\n },\n \"prompt\": {\n \"$ref\": \"request.prompt\"\n },\n \"n\": 1,\n \"size\": {\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 \"images\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\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 },\n 0\n ]\n },\n \"then\": {\n \"$map\": {\n \"from\": {\n \"$sortByOrder\": {\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 },\n \"as\": \"media\",\n \"in\": {\n \"$ref\": \"media.value\"\n }\n }\n },\n \"else\": null\n }\n },\n \"response_format\": \"url\",\n \"async\": false\n },\n \"pathTemplate\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\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 },\n 0\n ]\n },\n \"then\": \"/v1/images/edits\",\n \"else\": \"/v1/images/generations\"\n }\n }\n },\n \"poll\": {\n \"method\": \"GET\",\n \"path\": \"/v1/images/generations/{{taskId}}\",\n \"pathTemplate\": {\n \"$concat\": [\n {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\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 },\n 0\n ]\n },\n \"then\": \"/v1/images/edits\",\n \"else\": \"/v1/images/generations\"\n }\n },\n \"/\",\n {\n \"$ref\": \"taskId\"\n }\n ]\n }\n },\n \"response\": {\n \"taskIdPaths\": [\n \"id\",\n \"task_id\"\n ],\n \"statusPaths\": [\n \"status\"\n ],\n \"errorPaths\": [\n \"error.code\"\n ],\n \"messagePaths\": [\n \"error.message\",\n \"message\"\n ],\n \"images\": {\n \"$map\": {\n \"from\": {\n \"$ref\": \"response.data\"\n },\n \"as\": \"item\",\n \"in\": {\n \"url\": {\n \"$ref\": \"item.url\"\n }\n }\n }\n },\n \"usage\": {\n \"$ref\": \"response.usage\"\n }\n }\n },\n {\n \"id\": \"cangyuan-midjourney-v82\",\n \"label\": \"沧元 Midjourney 1K/2K · V8.2\",\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://ai.cangyuansuanli.cn/v1\",\n \"requiresPublicMediaUrls\": true,\n \"auth\": {\n \"type\": \"bearer\",\n \"field\": \"apiKey\"\n },\n \"imageParameters\": [\n {\n \"name\": \"size\",\n \"label\": \"画幅比例\",\n \"type\": \"string\",\n \"binding\": \"aspectRatio\"\n },\n {\n \"name\": \"count\",\n \"label\": \"生成数量\",\n \"type\": \"integer\",\n \"binding\": \"imageCount\",\n \"min\": 1,\n \"max\": 1,\n \"step\": 1,\n \"default\": 1\n },\n {\n \"name\": \"speed\",\n \"label\": \"生成速度\",\n \"type\": \"string\",\n \"binding\": \"providerOptions.cangyuan-midjourney-v82.speed\",\n \"values\": [\n \"relax\",\n \"fast\"\n ],\n \"pricing\": true\n },\n {\n \"name\": \"reference\",\n \"label\": \"参考方式\",\n \"type\": \"string\",\n \"binding\": \"providerOptions.cangyuan-midjourney-v82.reference\",\n \"values\": [\n \"image\",\n \"style\",\n \"edit\",\n \"moodboard\",\n \"editor\"\n ]\n }\n ],\n \"parameters\": [\n {\n \"name\": \"model\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"model\",\n \"description\": \"供应商公开模型名;两条线路分别校验。\"\n },\n {\n \"name\": \"prompt\",\n \"type\": \"string\",\n \"required\": true,\n \"mapping\": \"prompt\",\n \"description\": \"原提示词;1K/2K 默认 V8.2,可写官网 --v / --niji 参数;V7 不支持这些版本参数。\"\n },\n {\n \"name\": \"images\",\n \"type\": \"media[]\",\n \"mapping\": \"images[] / mask\",\n \"description\": \"按宿主显式 role 转换为 HTTPS URL 字符串数组;mask 单独映射。\"\n },\n {\n \"name\": \"imageCount\",\n \"type\": \"integer\",\n \"mapping\": \"n=1\",\n \"description\": \"一次提交只能为 1,结果 data 可能含多张,全部保存。\"\n },\n {\n \"name\": \"aspectRatio\",\n \"type\": \"string\",\n \"mapping\": \"size\",\n \"description\": \"比例或 V7 宽x高;空值和 auto 不发送,沿用供应商默认值。\"\n },\n {\n \"name\": \"providerOptions\",\n \"type\": \"object\",\n \"mapping\": \"cangyuan-midjourney-v82.speed/reference\",\n \"description\": \"1K/2K 插件命名空间可指定 speed=relax/fast、reference=image/style/edit/moodboard/editor。V7 没有速度或版本扩展字段。\"\n }\n ],\n \"validations\": [\n {\n \"assert\": {\n \"$in\": [\n {\n \"$ref\": \"request.model\"\n },\n [\n \"midjourney-1k\",\n \"midjourney-2k\"\n ]\n ]\n },\n \"message\": \"模型名与 Midjourney 线路不匹配。\"\n },\n {\n \"assert\": {\n \"$lte\": [\n {\n \"$ref\": \"request.imageCount\"\n },\n 1\n ]\n },\n \"message\": \"Midjourney 一次提交 n 只能为 1;返回多张图片会全部保存。\"\n },\n {\n \"assert\": {\n \"$gt\": [\n {\n \"$len\": {\n \"$trim\": {\n \"$ref\": \"request.prompt\"\n }\n }\n },\n 0\n ]\n },\n \"message\": \"Midjourney 提示词不能为空。\"\n },\n {\n \"assert\": {\n \"$eq\": [\n {\n \"$len\": {\n \"$filter\": {\n \"from\": {\n \"$ref\": \"request.images\"\n },\n \"as\": \"media\",\n \"where\": {\n \"$ne\": [\n {\n \"$first\": {\n \"$split\": [\n {\n \"$ref\": \"media.value\"\n },\n \":\"\n ]\n }\n },\n \"https\"\n ]\n }\n }\n }\n },\n 0\n ]\n },\n \"message\": \"Midjourney 参考图和蒙版必须是 HTTPS URL,不能发送本地文件或 data URI。\"\n },\n {\n \"assert\": {\n \"$in\": [\n {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.cangyuan-midjourney-v82.speed\"\n },\n \"relax\"\n ]\n },\n [\n \"relax\",\n \"fast\"\n ]\n ]\n },\n \"message\": \"Midjourney speed 只支持 relax 或 fast。\"\n },\n {\n \"assert\": {\n \"$in\": [\n {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.cangyuan-midjourney-v82.reference\"\n },\n {\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 \"edit_source\"\n ]\n }\n }\n }\n },\n 0\n ]\n },\n \"then\": \"editor\",\n \"else\": \"image\"\n }\n }\n ]\n },\n [\n \"image\",\n \"style\",\n \"edit\",\n \"moodboard\",\n \"editor\"\n ]\n ]\n },\n \"message\": \"Midjourney reference 类型无效。\"\n },\n {\n \"assert\": {\n \"$or\": [\n {\n \"$not\": {\n \"$eq\": [\n {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.cangyuan-midjourney-v82.reference\"\n },\n {\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 \"edit_source\"\n ]\n }\n }\n }\n },\n 0\n ]\n },\n \"then\": \"editor\",\n \"else\": \"image\"\n }\n }\n ]\n },\n \"editor\"\n ]\n }\n },\n {\n \"$eq\": [\n {\n \"$len\": {\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 },\n 1\n ]\n }\n ]\n },\n \"message\": \"Midjourney editor 只能有一张源图。\"\n },\n {\n \"assert\": {\n \"$or\": [\n {\n \"$ne\": [\n {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.cangyuan-midjourney-v82.reference\"\n },\n {\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 \"edit_source\"\n ]\n }\n }\n }\n },\n 0\n ]\n },\n \"then\": \"editor\",\n \"else\": \"image\"\n }\n }\n ]\n },\n \"edit\"\n ]\n },\n {\n \"$lte\": [\n {\n \"$len\": {\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 },\n 4\n ]\n }\n ]\n },\n \"message\": \"Midjourney edit 参考图最多 4 张。\"\n },\n {\n \"assert\": {\n \"$lte\": [\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 1\n ]\n },\n \"message\": \"Midjourney 蒙版只能有一张。\"\n },\n {\n \"assert\": {\n \"$or\": [\n {\n \"$eq\": [\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 {\n \"$and\": [\n {\n \"$eq\": [\n {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.cangyuan-midjourney-v82.reference\"\n },\n {\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 \"edit_source\"\n ]\n }\n }\n }\n },\n 0\n ]\n },\n \"then\": \"editor\",\n \"else\": \"image\"\n }\n }\n ]\n },\n \"editor\"\n ]\n },\n {\n \"$eq\": [\n {\n \"$len\": {\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 },\n 1\n ]\n }\n ]\n }\n ]\n },\n \"message\": \"蒙版只能用于 editor,且必须有一张源图。\"\n }\n ],\n \"create\": {\n \"method\": \"POST\",\n \"path\": \"/v1/images/generations\",\n \"contentType\": \"application/json\",\n \"body\": {\n \"model\": {\n \"$ref\": \"request.model\"\n },\n \"prompt\": {\n \"$ref\": \"request.prompt\"\n },\n \"n\": 1,\n \"size\": {\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 \"images\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\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 },\n 0\n ]\n },\n \"then\": {\n \"$map\": {\n \"from\": {\n \"$sortByOrder\": {\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 },\n \"as\": \"media\",\n \"in\": {\n \"$ref\": \"media.value\"\n }\n }\n },\n \"else\": null\n }\n },\n \"response_format\": \"url\",\n \"async\": false,\n \"speed\": {\n \"$omitEmpty\": {\n \"$ref\": \"request.providerOptions.cangyuan-midjourney-v82.speed\"\n }\n },\n \"reference\": {\n \"$if\": {\n \"condition\": {\n \"$gt\": [\n {\n \"$len\": {\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 },\n 0\n ]\n },\n \"then\": {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.cangyuan-midjourney-v82.reference\"\n },\n {\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 \"edit_source\"\n ]\n }\n }\n }\n },\n 0\n ]\n },\n \"then\": \"editor\",\n \"else\": \"image\"\n }\n }\n ]\n },\n \"else\": null\n }\n },\n \"mask\": {\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 \"$first\": {\n \"$map\": {\n \"from\": {\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 \"as\": \"media\",\n \"in\": {\n \"$ref\": \"media.value\"\n }\n }\n }\n },\n \"else\": null\n }\n }\n },\n \"pathTemplate\": {\n \"$if\": {\n \"condition\": {\n \"$and\": [\n {\n \"$gt\": [\n {\n \"$len\": {\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 },\n 0\n ]\n },\n {\n \"$eq\": [\n {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.cangyuan-midjourney-v82.reference\"\n },\n {\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 \"edit_source\"\n ]\n }\n }\n }\n },\n 0\n ]\n },\n \"then\": \"editor\",\n \"else\": \"image\"\n }\n }\n ]\n },\n \"editor\"\n ]\n }\n ]\n },\n \"then\": \"/v1/images/edits\",\n \"else\": \"/v1/images/generations\"\n }\n }\n },\n \"poll\": {\n \"method\": \"GET\",\n \"path\": \"/v1/images/generations/{{taskId}}\",\n \"pathTemplate\": {\n \"$concat\": [\n {\n \"$if\": {\n \"condition\": {\n \"$and\": [\n {\n \"$gt\": [\n {\n \"$len\": {\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 },\n 0\n ]\n },\n {\n \"$eq\": [\n {\n \"$coalesce\": [\n {\n \"$ref\": \"request.providerOptions.cangyuan-midjourney-v82.reference\"\n },\n {\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 \"edit_source\"\n ]\n }\n }\n }\n },\n 0\n ]\n },\n \"then\": \"editor\",\n \"else\": \"image\"\n }\n }\n ]\n },\n \"editor\"\n ]\n }\n ]\n },\n \"then\": \"/v1/images/edits\",\n \"else\": \"/v1/images/generations\"\n }\n },\n \"/\",\n {\n \"$ref\": \"taskId\"\n }\n ]\n }\n },\n \"response\": {\n \"taskIdPaths\": [\n \"id\",\n \"task_id\"\n ],\n \"statusPaths\": [\n \"status\"\n ],\n \"errorPaths\": [\n \"error.code\"\n ],\n \"messagePaths\": [\n \"error.message\",\n \"message\"\n ],\n \"images\": {\n \"$map\": {\n \"from\": {\n \"$ref\": \"response.data\"\n },\n \"as\": \"item\",\n \"in\": {\n \"url\": {\n \"$ref\": \"item.url\"\n }\n }\n }\n },\n \"usage\": {\n \"$ref\": \"response.usage\"\n }\n }\n }\n ]\n },\n \"documentation\": \"<当前插件的完整 documentation,由 README.md 与 docs/interface.md 拼接而成;为避免 JSON 递归,此处不重复展开正文。>\"\n}\n```\n<!-- YINGCE_MANIFEST_CONTRACT_END -->\n"
|
||
}
|