Files
Popiai-skill/image-creation/multi-shot/SKILL.md
T

160 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: multi-shot
summary-en: Re-render image from new camera angle
summary-cn: 拖动 3D 球体,给一张图换新视角
display-name-zh: 多角度
trigger-words: [多角度, 换视角, 换镜头, multi shot, change angle, new camera angle]
description: |
把已有的一张图片用全新的相机视角重新生成。用户拖动 3D 球体控件设定旋转/倾斜/缩放后,nano banana 模型按该视角重渲染原图。GUI 仅负责参数收集,结果由主站对话流呈现。
allowed-tools: hub_open_remote_tool_gui, hub_submit_dag
tags: [Image, 3D, Multi-View]
tags-cn: [图片, 3D, 多视角]
version: 1.0.0
exported-by: MiniMax-hub
---
# Multi Shot
拖动 3D 球体调整摄像机角度,给图片换一个新视角
## 参数
| ID | 类型 | 必填 | 取值约束 | 说明 |
|----|------|------|---------|------|
| image_url | file(image/*) | 是 | — | 原图引用,由主站从对话流注入;GUI 不上传也不做格式校验。可以是 CDN URLhttp/https)、blob:、data: 或本地路径,统一原样透传给后端。 |
| view_prompt | string | 是 | — | 视角描述 prompt(英文自然语言)。由 GUI 在用户点击「立即使用」时根据 rotation/tilt/zoom 三参数自动拼装,外部 inject 会被覆盖。 |
## 全局禁令
- ❌ **禁止**调用 `save_file_to_session` 工具 — 本工具产生的所有资产 gateway 已自动保存到 workspace 并通过 `recordAsset` 注册到画布,任何手动保存(`save_file_to_session` / `curl` / `wget` / `download_videos` 等)都会让同一资产入两次库。完成后只需用 markdown 媒体语法引用 `local_path` / 脚本 `outputs` 返回的路径即可。
## 执行流程
### STEP 1: 打开 GUI 收集参数
调用 `hub_open_remote_tool_gui`,入参:
```ts
{
tool_name: "multi-shot",
entry: "scripts/index.js",
initial_params?: { /* 可选,用户在对话里已经给出的具体参数,key 对齐"参数"表里的 id */ },
}
```
**预填规则**:如果用户在对话中已经明确给出某个参数的具体值(例如"用 kissing 这个 pose"、"prompt 写'夕阳下奔跑'"),把它们打包进 `initial_params` 一并传入,GUI 挂载后会自动预填,用户无需再次输入。没明确给值的参数不要瞎猜,留给 GUI 表单收集即可。
**附件预填(本工具的 file 参数:`image_url`)**:
用户消息可能以系统自动注入的 `[User attached files: <path1>, <path2>, ...]` 开头 —— 这是文件路径,不是用户手打的文字。出现这种情况时**必须**按下表把附件路径塞进 `initial_params`,即使用户文字里没说"用这张图":
| 参数 id | accept | 取值规则 |
|---------|--------|----------|
| `image_url` | `image/*` | 附件列表中第一个匹配该 MIME 的路径 |
补充约束:
- 把匹配到的本地路径**直接**塞进 `initial_params[<id>]`(GUI 会识别本地路径并自动上传到 CDN,agent 不要自己调 `hub_upload_to_cdn` / `upload_to_cdn`)
- 没匹配到的 file 字段:不传(留给 GUI 表单让用户上传)
- 同一字段有多张匹配:只取第一个,其余交给 GUI
示例:
- 用户消息: `[User attached files: /Users/me/face.webp]\n\n/multi-shot`
- 应调用: `open_remote_tool_gui({ tool_name: "multi-shot", entry: "scripts/index.js", initial_params: { image_url: "/Users/me/face.webp" } })`
`initial_params` 仅用于 `open_remote_tool_gui` 调用时的预填。GUI 打开后由用户操作,不要尝试再用其他方式去操控 GUI。
### STEP 2: 接收用户提交
GUI 提交后,系统会注入一条 user message,形如:
```
User submitted GUI form for tool "multi-shot". Form data:
{ "params": { ... }, "files": [{ "param_id": "...", "url": "...", "name": "...", "type": "..." }] }
```
`files[].url``param_id` 匹配到对应字段(`params[<param_id>] = files[i].url`),组装出完整的 DAG inputs。**无需再次上传文件**(GUI 已通过 `sdk.uploadFile` 上传到 CDN)。
#### 收到 form data 后直接进入 STEP 3,严格禁令
- ❌ **禁止**重新调用 `hub_open_remote_tool_gui`(无论是否改 `initial_params`)—— 用户已经在 GUI 里确认过参数,你不是产品经理,不要替用户改主意。同一 turn 内重开 GUI 会让新 link 覆盖旧 pending、UI 永远停在 "Thinking..."、用户被迫重填,直接死循环
- ❌ **禁止**在对话流输出"本次方案 / 这版思路 / 我再帮你调整一版 / 我重新设计一下"之类的二次提案 —— 参数已经 lock,不要"反悔"
如果你判断 GUI 提交的参数确实不合理,只有两个合法选项:(a) STEP 3 照常 submit,让 DAG 后端报错,你再用错误信息向用户解释;(b) 完全终止本次任务并向用户说明原因。**绝对不是悄悄重开 GUI**。
### STEP 3: 调用 hub_submit_dag
用上一步组装好的 inputs 调用工具:
| 字段 | 值 |
|------|----|
| dag_id | "508694798475620358" |
| inputs | `{ "image_url": "<cdn_url>", "view_prompt": "<视角描述 prompt(英文自然语言)。由 GUI 在用户点击「立即使用」时根据 rotation/tilt/zoom 三参数自动拼装,外部 inject 会被覆盖。>" }` |
| asset_keys | `[]`(始终传空数组) |
**inputs 格式约束**:
- 所有 value **必须是字符串字面量**(包括数字、布尔)
- 上方"参数"表中所有参数都必须传递,可选参数无值时传空字符串 `""` 占位
- file 类型参数填 CDN URL(`https://...` 开头)
**出参**:`{ run_id: string, estimated_seconds: number }`
### STEP 4: 提交后立即结束当前 turn
`submit_dag` 返回后,**当前 turn 必须立即结束**。Gateway 在后台代理轮询(15s 间隔,30 分钟超时),完成时会自动注入新 user message 唤醒。
#### 严格禁令
-**禁止**重新调用 `hub_open_remote_tool_gui` —— submit_dag 已发出,任务在跑;再开 GUI = 同一任务排队两次 + 旧 link 被新 link 覆盖 + UI 永远卡在 "Thinking..." + 用户被迫重填,死循环。**这是同一 turn 内最常见、危害最大的违规**,任何"我再帮你调整一版"的冲动都意味着你已经踩进死循环
- ❌ **禁止**在对话流输出"本次方案 / 这版思路 / 我再设计一版"之类二次提案文本 —— 参数已交给 DAG,你不是产品经理,不要替用户改主意
- ❌ **禁止**用 `question` / `ask` 工具"通知用户等待"或"询问是否继续" — UI 已自带 loading 反馈,question 会卡住对话流,DAG 完成消息排队进不来
- ❌ **禁止**主动调用 `hub_query_dag_result` — gateway 会回调,主动查会浪费 turn 还可能 race condition
- ❌ **禁止**重复 `submit_dag` — 会在后端创建多个任务,消耗用户配额
- ❌ **禁止**输出"任务进行中,请稍候"之类的中间态文本 — 会让 UI 误以为在等用户回复
-**禁止** sleep / 自旋 / 任何形式的等待 — 事件驱动,等待靠系统注入
### STEP 5: 处理完成消息
注入的 user message 形如:
```
Async task completed:
{
"task_id": "<run_id>",
"status": "succeeded" | "failed" | "timeout",
"outputs": { ... },
"asset_outputs": [
{ "key": "image", "status": "finished", "url": "https://cdn...", "local_path": "..." }
],
"error_message": null
}
```
#### `status: "succeeded"`
用 markdown 媒体语法插入资产,从 `asset_outputs` 中遍历 `status == "finished"` 的条目:
- 图片:`![描述](<asset_outputs[i].local_path>)`
- 视频:`![描述](<asset_outputs[i].local_path>)` 或链接 `[查看视频](<local_path>)`
- 其他文件:`[<描述>](<local_path>)`
**关键约束**:
-**必须用 `local_path`**(gateway 已自动下载到 workspace 并通过 `recordAsset` 注册到画布)
-**不要用 `url`**(CDN URL 仅作 fallback,直接用会让画布丢失资产引用)
- ❌ **禁止**调用 `save_file_to_session` / `curl` / `wget` / `download_videos` 等下载工具 — gateway 已下载,重复会让同一资产入两次库
- ⚠️ 纯文本(如「已生成」「已保存」)不会渲染媒体,**必须用 markdown 语法**
#### `status: "failed"`
向用户报告 `error_message`,建议调整输入后重试。**不要**自动 retry。
#### `status: "timeout"`
任务已被 gateway abort(30 分钟未完成),向用户报告超时并建议稍后重试。
## 排查参考
- `submit_dag` 调用本身报错(返回非 ok):检查 inputs 是否完整,所有 key 都必须传(可选项传 `""`)
- 完成消息一直没来:用户应能看到 UI 端 loading;若超过 30 分钟仍无完成消息,gateway 可能已 abort,等下一次用户主动操作