feat(canvas): 云端 Agent - 完成策略分层、节点能力注册与可解释审批改造
This commit is contained in:
@@ -258,17 +258,24 @@ for (const [id, name, vendor, baseUrl] of [
|
||||
|
||||
add({
|
||||
id: "openai-images", providerId: "openai-image", name: "OpenAI Images", vendor: "OpenAI", capability: "image",
|
||||
baseUrl: "https://api.openai.com", auth: bearer, params: imageParams,
|
||||
notes: "无参考图走 JSON generations;有参考图或蒙版走 multipart edits。quality 的 1k/2k/4k 映射为 OpenAI low/medium/high。",
|
||||
baseUrl: "https://api.openai.com", auth: bearer, params: imageParams, requiresPublicMediaUrls: true,
|
||||
notes: "无参考图走 JSON generations;有参考图或蒙版走 JSON edits,并按官方 images 数组传入多张 image_url。quality 的 1k/2k/4k 映射为 OpenAI low/medium/high。",
|
||||
create: {
|
||||
method: "POST",
|
||||
path: "/v1/images/generations",
|
||||
pathTemplate: conditional(gt(len(ref("request.images")), 0), "/v1/images/edits", "/v1/images/generations"),
|
||||
contentType: "application/json",
|
||||
contentTypeTemplate: conditional(gt(len(ref("request.images")), 0), "multipart/form-data", "application/json"),
|
||||
body: {
|
||||
model: ref("request.model"),
|
||||
prompt: ref("request.prompt"),
|
||||
images: omit(conditional(gt(len(ref("request.images")), 0), map(
|
||||
filter(sorted(ref("request.images")), "media", ne(ref("media.role"), "mask")),
|
||||
"media",
|
||||
{ image_url: ref("media.value") }
|
||||
))),
|
||||
mask: omit(conditional(gt(len(filter(ref("request.images"), "media", eq(ref("media.role"), "mask"))), 0), {
|
||||
image_url: first(map(filter(sorted(ref("request.images")), "media", eq(ref("media.role"), "mask")), "media", ref("media.value")))
|
||||
})),
|
||||
n: omit(conditional(gt(ref("request.imageCount"), 0), ref("request.imageCount"), 1)),
|
||||
size: omit(conditional({ $in: [lower(trim(ref("request.aspectRatio"))), ["", "auto"]] }, null, ref("request.aspectRatio"))),
|
||||
quality: omit({
|
||||
@@ -289,14 +296,10 @@ add({
|
||||
output_format: omit(coalesce(ref("request.providerOptions.openai-image.output_format"), "png")),
|
||||
output_compression: omit(ref("request.providerOptions.openai-image.output_compression")),
|
||||
moderation: omit(ref("request.providerOptions.openai-image.moderation")),
|
||||
response_format: omit(coalesce(ref("request.providerOptions.openai-image.response_format"), "b64_json")),
|
||||
response_format: omit(ref("request.providerOptions.openai-image.response_format")),
|
||||
style: omit(ref("request.providerOptions.openai-image.style")),
|
||||
user: omit(ref("request.providerOptions.openai-image.user"))
|
||||
},
|
||||
files: [
|
||||
{ name: "image", source: filter(ref("request.images"), "media", ne(ref("media.role"), "mask")), filename: "source.png" },
|
||||
{ name: "mask", source: filter(ref("request.images"), "media", eq(ref("media.role"), "mask")), filename: "mask.png" }
|
||||
]
|
||||
}
|
||||
},
|
||||
response: {
|
||||
status: "succeeded",
|
||||
|
||||
Binary file not shown.
@@ -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。
|
||||
|
||||
<!-- YINGCE_MANIFEST_CONTRACT_START -->
|
||||
## 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",
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user