# 接口配置指引

画布不绑定任何一家 API。你把中转站的地址、请求格式填进去，它就能调。
配置存在浏览器 localStorage 里，关掉浏览器也不会丢。

---

## 一、三步跑起来

### 1. 启动本地代理

```
双击运行 proxy.py
```

或命令行 `python proxy.py`。看到下面这行就说明好了：

```
代理已启动: http://127.0.0.1:8787
```

**这个窗口要一直开着。** 关掉它画布就连不上接口了。
画布左上角有指示灯：绿点=已连接，红点=未启动。

> 为什么需要它：浏览器不允许网页直接请求别的域名（CORS）。
> 代理是你自己电脑上的小程序，帮你把请求转发出去，顺便补上跨域头。

### 2. 打开画布，配置接口

双击 `index.html` → 点工具栏 **⚙ 接口设置**

填两样东西：

| 字段 | 填什么 |
|---|---|
| 代理地址 | `http://127.0.0.1:8787`（一般不用改） |
| API Key | 你中转站的密钥 |

然后在左边模型列表里选一个改，或者点 **+ 新增模型**。

### 3. 执行

连好节点 → 点 **▶ 执行** → 节点会依次亮起绿框，预览节点直接出图/出视频。

---

## 二、模型配置每个字段怎么填

### 基础部分

| 字段 | 说明 | 例子 |
|---|---|---|
| 名称 | 随便起，显示在节点下拉里 | `即梦-文生图` |
| 类型 | 生图 / 生视频 / 文本。决定它出现在哪类节点上 | `生图` |
| 方法 | 一般是 POST | `POST` |
| 地址 | 中转站的完整接口 URL | `https://xxx.com/v1/images/generations` |
| 请求头 | JSON，放鉴权 | 见下方示例 |
| 请求体 | JSON 模板，用 `${变量}` 占位 | 见下方示例 |
| 结果路径 | 从返回的 JSON 里取结果，点号路径 | `data[0].url` |

### 异步部分（生视频几乎都是异步）

勾选 **异步** 后会出现这些：

| 字段 | 说明 | 例子 |
|---|---|---|
| 任务ID路径 | 提交后从返回里取任务号 | `data.id` |
| 查询地址 | 轮询用的 URL，用 `${task_id}` 占位 | `https://xxx.com/v1/videos/${task_id}` |
| 状态路径 | 从轮询返回里取状态 | `data.status` |
| 完成值 | 状态等于这个值就算成功 | `succeeded` |
| 查询结果路径 | 成功后从轮询返回里取结果 | `data.output.video_url` |
| 轮询间隔 | 每隔几秒查一次 | `8` |
| 最大轮询 | 最多查几次就放弃 | `60` |

> 异步流程是：提交拿任务号 → 每隔 N 秒查一次 → 状态等于「完成值」→ 取结果。
> 常见的完成值：`succeeded` / `success` / `completed` / `done` / `2`，照着你的接口文档填。

---

## 三、请求体里能用的变量

变量名 = 节点的**输入端口名** 或 **控件名**。填 `${名字}` 就行。

| 变量 | 从哪来 |
|---|---|
| `${提示词}` | 上游文本，或提示词输入节点 |
| `${参考图}` | 图生图节点的参考图端口 |
| `${首帧}` | 图生视频节点的首帧端口 |
| `${尺寸}` `${数量}` | 文生图/图生图节点的控件 |
| `${时长}` `${比例}` | 生视频节点的控件 |
| `${强度}` | 图生图节点的控件 |
| `${KEY}` | 设置面板里填的 API Key |

**注意：**
- 文本类型要加引号 → `"prompt": "${提示词}"`
- 数字类型不加引号 → `"n": ${数量}`
- 加错了会提示「请求体不是合法 JSON」，照着改就行

### 结果路径怎么写

点号 + 下标：

```
{"data":[{"url":"http://..."}]}          →  data[0].url
{"choices":[{"message":{"content":"x"}}]} →  choices[0].message.content
{"result":{"image_url":"http://..."}}     →  result.image_url
```

---

## 四、三种常见格式的填写示例

### A. OpenAI 兼容（很多中转站都支持）

```
地址     https://你的域名/v1/images/generations
请求头   {"Content-Type":"application/json","Authorization":"Bearer ${KEY}"}
请求体   {"model":"dall-e-3","prompt":"${提示词}","size":"${尺寸}","n":${数量}}
结果路径 data[0].url
```

### B. 异步生视频（可灵 / 即梦 / 海螺这类）

```
地址         https://你的域名/v1/videos/generations
请求头       {"Content-Type":"application/json","Authorization":"Bearer ${KEY}"}
请求体       {"model":"kling-v1","prompt":"${提示词}","duration":${时长}}
异步         ✓
任务ID路径   data.id
查询地址     https://你的域名/v1/videos/${task_id}
状态路径     data.status
完成值       succeeded
查询结果路径 data.output.video_url
轮询间隔     8
```

### C. 让 AI 帮你改写提示词

```
地址     https://你的域名/v1/chat/completions
请求头   {"Content-Type":"application/json","Authorization":"Bearer ${KEY}"}
请求体   {"model":"gpt-4o-mini","messages":[{"role":"user","content":"${提示词}"}]}
结果路径 choices[0].message.content
```

---

## 五、报错了怎么看

节点变**红框**就是失败了，把鼠标停在节点上，底部状态栏会显示原因。
也可以在节点上右键 → **查看错误**。

| 提示 | 原因 |
|---|---|
| 连不上本地代理 | proxy.py 没运行，或端口被占 |
| 未选择模型 | 设置里没有对应类型的模型 |
| 请求体不是合法 JSON | 变量引号加错了，文本要引号、数字不要 |
| 没取到结果，检查「结果字段路径」 | 路径写错，错误信息里会打印接口实际返回的内容 |
| 没取到任务ID | 异步配置的任务ID路径不对 |
| 任务失败，状态=xxx | 接口返回了失败状态，看打印的内容 |
| 轮询超时 | 视频生成太慢，把「最大轮询」调大 |

---

## 六、拿不准格式怎么办

1. 先用 Postman / curl 调通一次你的接口，把返回的 JSON 复制出来
2. 照着返回的层级写「结果路径」
3. 把接口文档发我，我直接帮你把模型配置写好

---

## 附：本地测试用的模拟中转站

`mock_api.py` 是我写来测试用的假接口，模拟了同步生图、异步生视频、文本改写三种形态。
跑 `python mock_api.py` 后把模型地址指向 `http://127.0.0.1:8899/...` 就能在不花一分钱的情况下
把整条链路跑通，验证画布没问题再换成真实接口。

---

## 七、内置模型库（47 个）与「官方直连 / 中转兜底」说明

画布默认内置 47 个主流模型（生图 16 / 生视频 15 / 文本 11 / Agnes 4 / 中转站 3），**主流的已经直接填了各品牌官方 OpenAI 兼容基址**；
少数没有统一 OpenAI 兼容接口的厂商，地址仍是中转站占位 `https://你的中转站域名/v1/`，由你的中转站去代理。

> 为什么不全改官方？因为 Flux / SD / Imagen / Midjourney / 可灵 / 即梦视频 / Runway 等厂商的生图、生视频接口
> **不是标准 OpenAI 兼容路径**（有的把 model 写在 URL 里、有的返回结构完全不同），直接填官方地址反而调不通，所以这部分留作中转站兜底。
> 等你要接哪家，到「接口设置」里把它的「地址 / 任务ID路径 / 状态路径 / 完成值 / 查询结果路径」改成该厂的官方返回值即可。

### 已改为官方直连的模型（23 个）
| 模型 | 官方基址（地址前缀） |
|---|---|
| OpenAI GPT-Image-1 / 1.5、DALL·E 3（生图） | `https://api.openai.com/v1/` |
| OpenAI Sora（生视频） | `https://api.openai.com/v1/` |
| OpenAI GPT-4o / 4o-mini（文本） | `https://api.openai.com/v1/` |
| DeepSeek Chat / V3（文本） | `https://api.deepseek.com/v1/` |
| 通义千问 Qwen-Max / Plus（文本） | `https://dashscope.aliyuncs.com/compatible-mode/v1/` |
| 智谱 GLM-4 Plus / Flash（文本） | `https://open.bigmodel.cn/api/paas/v4/` |
| 智谱 CogView-3（生图） | `https://open.bigmodel.cn/api/paas/v4/` |
| **智谱 CogVideoX-Flash（生视频·免费·支持图生视频）** | `https://open.bigmodel.cn/api/paas/v4/` |
| 豆包 Doubao-Pro（文本） | `https://ark.cn-beijing.volces.com/api/v3/` |
| 即梦 Seedream 3.0（生图） | `https://ark.cn-beijing.volces.com/api/v3/` |
| Kimi Moonshot（文本） | `https://api.moonshot.cn/v1/` |
| 文心一言 ERNIE 4.0（文本） | `https://qianfan.baidubce.com/v2/` |
| 腾讯混元 Image（生图） | `https://api.hunyuan.cloud.tencent.com/v1/` |
| Agnes Image / Video V2.0 / Video 2.5 Flash ×2（见第八节） | `https://apihub.agnes-ai.com/v1/` |

### 仍走中转站兜底的模型（24 个）
生图：Flux 2 Pro/Dev、Flux Schnell、SD 3.5、SDXL、Ideogram 3.0、Recraft v3、Google Imagen 4、通义万相 wanx2.1、Midjourney
生视频：可灵 Kling 2.6 / 2.5 Turbo / 2.1 Master、即梦 Seedance 2.0、通义万相 Wan 2.6、MiniMax 海螺 Hailuo 2、Runway Gen-4、Luma Dream Machine、Pika、Vidu、PixVerse V6
（外加 3 个「中转站 · 任意」填空项）

> **免费图生视频首选：智谱 CogVideoX-Flash**。智谱开放平台对 `cogvideox-flash` 模型**免费开放**（手机号注册即送大量 Token，OpenAI 兼容接口）。画布已内置为官方直连：`地址=https://open.bigmodel.cn/api/paas/v4/videos/generations`，图生视频把图片接到「首帧」输入端口（自动映射到智谱 `image_url` 参数），纯文生视频时该字段自动省略。轮询配置沿用智谱标准（`任务ID=id`、`状态=task_status`、`完成值=SUCCESS`、`结果=video_result[0].url`）。免费版有水印、时长较短（默认 5 秒、质量模式 speed），商用需留意平台条款。

### 各厂官方兼容基址速查
| 厂商 | 兼容模式基址（地址前缀） | 备注 |
|---|---|---|
| OpenAI | `https://api.openai.com/v1/` | 原生 OpenAI 格式 |
| DeepSeek | `https://api.deepseek.com/v1/` | — |
| 阿里 · 通义（万相/千问） | `https://dashscope.aliyuncs.com/compatible-mode/v1/` | DashScope 兼容模式 |
| 智谱 AI（GLM/CogView） | `https://open.bigmodel.cn/api/paas/v4/` | 注意是 `/v4` |
| 字节 · 即梦/Seedream（火山方舟） | `https://ark.cn-beijing.volces.com/api/v3/` | 路径是 `/api/v3` |
| 腾讯 · 混元 | `https://api.hunyuan.cloud.tencent.com/v1/` | — |
| Kimi · Moonshot | `https://api.moonshot.cn/v1/` | — |
| 文心一言 · ERNIE | `https://qianfan.baidubce.com/v2/` | 千帆兼容模式 |
| 可灵 Kling / 其它无兼容接口的厂 | 建议走中转站 | 原生接口把 model 写在 URL 路径里、格式特殊，中转站更省事 |

**生视频轮询格式差异提醒**：不同厂轮询返回结构不同，若用官方直连，请按文档改这几项：
- 通用中转/OpenAI 风格：`任务ID=data.id`、`状态=data.status`、`完成值=succeeded`、`结果=data.output.video_url`
- 智谱 CogVideoX 风格（内置已配好）：`任务ID=id`、`状态=task_status`、`完成值=SUCCESS`、`结果=video_result[0].url`
- 其它厂（如 `success`/`completed`/`done`、结果在 `results[0].url` 等）照着文档改「状态路径 / 完成值 / 查询结果路径」即可。



---

## 八、Agnes AI 与「范围」分组

### 范围（官方API / 中转站）是什么

设置面板里的每个模型现在都有一个 **范围** 字段，把模型库分成两组，方便你在下拉里一眼区分：

- **官方API**：OpenAI、智谱、通义、混元、DeepSeek、Kimi、文心、豆包等**已填品牌官方兼容基址**的模型（以及 Agnes，见下）。
  这些地址已经直连官方（请求仍经本地 `proxy.py` 转发以绕过浏览器 CORS）。需要换 key / 换域就改「地址」前缀即可（见第七节）。
- **中转站**：没有统一 OpenAI 兼容接口的厂商（Flux、SD、Imagen、Midjourney、可灵、即梦视频、Runway 等），以及 3 个「中转站 · 任意」填空项。
  它们的「地址」是中转站占位 `https://你的中转站域名/v1/`，由你的中转站去代理官方。
- **中转站**：通用的「任意模型」填空项（生图 / 生视频 / 文本各一个），走你自己的中转站，
  **请求体里的 `"model"` 改成你想用的任意模型名**即可，适合你中转站里那些没列进官方库的模型。

节点上的「模型」下拉也会按范围用分隔线分组显示。

### Agnes AI（已内置，官方直连）

Agnes AI 完全兼容 OpenAI 协议，基址 `https://apihub.agnes-ai.com/v1`，已内置 4 个模型（生图 ×1、生视频 ×3）：

- **Agnes · Image 2.1**（生图，同步）：`/v1/images/generations`，结果 `data[0].url`
- **Agnes · Video V2.0**（生视频，异步）：
  - 提交：`POST /v1/videos`，请求体 `model=agnes-video-v2.0` + `prompt` + `num_frames`(默认121≈5秒) + `frame_rate`(24) + `width/height`
  - **图生视频**：把「图生视频」节点的 `首帧` 端口接到一张图（来自生图节点，需是**公网可访问**的 URL，Agnes 会去抓取），请求体已自动带上 `image` 字段（`"image": "${首帧}"`）；没接图时该字段会自动省略，退化成纯文生视频。
  - 任务ID：`video_id`（提交响应里同时返回 `id` / `task_id` / `video_id`，**官方要求轮询优先用 `video_id`**）
  - 轮询：`GET /agnesapi?video_id=${video_id}`（**注意：在 /v1 之外，不是 `/v1/videos/{id}`**），状态字段 `status`，**完成值 `completed`**
  - 结果：视频直链。已配成「先取 `url`，取不到再退回 `metadata.url`」双兜底（不同版本 API 返回位置不一致）。**注意：官方字段 `remixed_from_video_id` 恒为 `null`**，真正的视频地址在 `url` / `metadata.url`，所以画布里「查询结果路径」配成 `url`、「结果路径」配成 `metadata.url` 互相兜底。

- **Agnes · Video 2.5 Flash**（生视频，异步，**推荐**，免费且质量更高）：
  - 与 V2.0 **参数体系完全不同，不能直接在 V2.0 上改 model 名**，必须用这个专用模型：
  - 提交：`POST /v1/videos`，请求体固定 `model=agnes-video-2.5-flash` + **必填 `mode`（text / keyframe / reference）** + `prompt` + `seconds`（**字符串** `"5"`，范围 `"4"`–`"12"`） + `size`（**固定 `"720P"`**，其它值直接 HTTP 400） + `aspect_ratio`（默认 `16:9`）。
  - 任务ID：`video_id`
  - 轮询：`GET /agnesapi?video_id=${video_id}&model_name=agnes-video-2.5-flash`（**2.5 Flash 推荐带 `model_name`，否则 keyframe / reference 模式查不到任务**）
  - 结果：视频直链，取「查询结果路径」`url`（实测地址在顶层 `url`，`metadata.url` 不一定有）。
- **Agnes · Video 2.5 Flash 图生**（生视频，异步）：同上，但 `mode=keyframe` 并自动带 `first_frame`（接「图生视频」节点的 `首帧`）。必须接图，未接图会因缺首帧被官方拒绝。

> 注意：Agnes 生视频的「完成值」是 `completed`（不是 `succeeded`），已在内置配置里写死。
> 轮询地址采用 Agnes **官方**接口 `/agnesapi?video_id=`（见 wiki.agnes-ai.com 与 agnes-ai.com 官方文档），之前博客里常见的 `/v1/videos/{task_id}` 已弃用。
> 官方特别提醒：**轮询地址不含 `/v1`**，拼成 `https://apihub.agnes-ai.com/v1/agnesapi?...` 是错的。
> 如果你的账号返回结构不同，到「接口设置」里把 `状态路径 / 完成值 / 查询结果路径` 改成你实际返回的字段即可。
> 报错如果以前显示成 `[object Object]`，那是因为官方把错误信息放在了 `error` **对象**里；现已修复为显示真实错误文案（例如图片 URL 不可访问、key 无效等），按提示排查即可。
> 如果你是用中转站代理 Agnes，把这两个模型「地址」前缀也改回你的中转站域名即可（范围保持官方API 也行）。
> **图生视频（keyframe）必须从上游客流接一张图到「首帧」输入**，且图片需是**公网可访问**的 URL（本地路径/内网图 Agnes 抓不到）。没接图会直接 `HTTP 400：keyframe mode requires first_frame`——这不是 key 问题，把图接上即可。
> **免费队列拥堵时会「轮询超时」**：Agnes 免费额度排队慢，高峰期一个任务要 2 分钟以上才出片，且轮询频繁会被官方 `429` 限流。实测 2026-09-03 一次文生视频共轮询 **28 次（约 2 分 20 秒）** 才 `completed`，最终正常拿到 mp4 直链——所以「等 2~4 分钟」是正常排队，不是卡死。已做三处加固：轮询间隔调慢（5 秒，少触发限流）、最大轮询调高（150 次 ≈ 12 分钟上限，足够覆盖拥堵）、被 429/5xx 时**指数退避**自动重试。遇到超时请稍等或换非高峰再试，并非配置错误。
> **图生视频现在会提前拦截**：如果「图生视频 / 图生图」节点没接图就运行，会直接提示「请先把图片连到『首帧 / 参考图』输入端口」，不再浪费额度被官方 400 拒绝。

## 九、每模型独立密钥（不再共用一个 Key）

之前所有模型共用「接口设置」里的**一个**全局 API Key（`${KEY}` 统一取它）。现在支持**每个模型单独配自己的 Key**：

- **两个配置入口**：
  1. 「接口设置 ⚙ → 模型列表」里每个模型多了一个 **密钥** 框（密码框），填的就是这个模型专属的 Key。
  2. 在画布上**选中一个节点**，右侧属性面板的「操作」上方会出现 **本模型密钥** 输入框，就地填写、立刻生效并自动保存。
- **优先级**：运行时先看模型自己的「密钥」框有没有填 → 有就用它；没填（留空）才回退到「接口设置」底部的**全局 API Key**。
- **好处**：OpenAI 的图用一个 key、智谱的文用一个 key、Agnes 用一个 key，互不干扰；没单独填的就统一走全局 key，不用每个都填。
- **注意**：节点属性面板里填的密钥会直接写回该模型配置并持久化（存到本地 `comfyui-canvas` 的配置里），下次打开还在。

## 十、生成的视频/图片「看不了」「存不下来」——本地媒体转发

**现象**：任务明明 SUCCESS 了，预览区却黑屏或一直转圈；点「保存结果」也没反应。

**根因（三个叠加）**：

1. **结果链接是带签名的临时地址**。各平台返回的图片/视频 URL 形如
   `https://…ufileos.com/xxx_watermark.mp4?UCloudPublicKey=…&Signature=…&Expires=1788593553`
   其中 `Expires` 是**有效期**，智谱实测只有 **24 小时**。过期后直连会返回
   `{"RetCode":-148643,"ErrMsg":"no authorization found"}`（HTTP 401），视频自然播不了。
2. **浏览器直连 CDN 常被 CORS / 401 / 403 拦掉**，`<video src="跨域URL">` 直接黑屏。
3. **跨域 `<a download>` 会被浏览器忽略**，`download` 属性只对同源链接生效——
   跨域时浏览器不下载、直接跳转，表现就是「点了保存没反应」。

**解决办法：一律走本地代理转发（`/media?url=…`）**

`proxy.py` 新增媒体端点，服务端代抓远程文件再**同源**吐给浏览器：

```
GET http://127.0.0.1:8787/media?url=<URL编码后的结果链接>         # 播放（支持 Range，可拖进度条）
GET http://127.0.0.1:8787/media?url=<…>&dl=1                     # 下载（带 Content-Disposition 附件头）
```

- 带**浏览器 UA** 抓取，规避 CDN 对 `Python-urllib` 的 403；
- **透传 Range 请求**（返回 206），视频能正常拖动进度条；
- 返回 `Accept-Ranges: bytes` + 正确的 `Content-Type`（如 `video/mp4`）；
- `dl=1` 时追加 `Content-Disposition: attachment; filename=…; filename*=UTF-8''…`（中文名兼容）。

前端已自动接入，无需手动配置：

| 位置 | 行为 |
|---|---|
| 预览区（图片/视频） | 渲染时把远程 URL 自动包成 `/media?url=…`，**同源播放、能拖进度条** |
| 预览区右上角「⤓ 保存」 | 一键把当前结果存到本地下载文件夹 |
| 预览区左下角灰字提示 | 「链接 24 小时后失效」，提醒及时下载 |
| 「保存结果」节点 | 先经代理抓成 **Blob** 再触发下载，真正落盘（不再被跨域吞掉） |
| 加载失败时 | 预览区直接提示「链接可能已过期，请重新生成」 |

`mediaUrl()` 的规则：`data:` / `blob:` / 相对地址 / 空值**原样返回**；只有 `http(s)://` 远程地址才包代理；没配代理地址时直连。

> **建议**：视频生成成功后**立刻点「⤓ 保存」**，别等到第二天——链接 24 小时后就打不开了。

## 十一、从端口拉线到空白处：点了候选没反应（已修）

**现象**：从节点的输出端口往空白处拖一条线，会弹出候选节点面板，但**鼠标移上去再点，节点没被创建**。

**根因**：候选项的 `mouseenter` 事件里调用了 `renderSearchList()`，它会 `innerHTML=''` **重建整个列表**。
鼠标一悬停，原 DOM 元素就被摘除；接着按下、抬起落在新元素上，浏览器因「mousedown 与 mouseup 的 target 不同」
**不派发 `click` 事件** —— 于是看起来就是「点了没反应」。

**修复**：

- 悬停改为 `pointerenter` → 只调 `setSearchIdx(i)` **切换高亮 class，绝不重建 DOM**；
- 选中改用 `pointerdown` 立即响应（比 click 更跟手，也不受 DOM 变动影响）；
- 键盘 ↑↓ 同样走 `setSearchIdx`，不再重建。

现在从端口拖到空白 → 弹面板 → 点一项，会**立刻在松手位置建出新节点并自动连好线**。

---

## 十二、落地页 `home.html` 与画布的双向互通（深链）

目录里有两个入口，互相都能跳：

| 文件 | 角色 | 怎么进 |
| --- | --- | --- |
| `home.html` | 落地页（能力介绍 / 模型矩阵 / 三步开跑 / FAQ） | 双击打开，或点画布工具栏的「← 首页」 |
| `index.html` | 画布本体 | 落地页任一「打开画布」按钮，或一键直达芯片 |

### 画布 → 首页

工具栏最左侧新增 `汤少画布工作流 ←首页` 链接（复用了早先写好但一直没用上的 `.brand` 样式），
点一下即回 `home.html`。**没有改 `index.html` 的文件名**，老书签照常可用。

### 首页 → 画布：三种深链

进画布时带 hash，画布初始化会按 hash 铺设内容（优先级高于默认的示例工作流）：

| 链接 | 效果 |
| --- | --- |
| `index.html#demo` | 载入示例工作流（5 节点全链路）。**不带 hash 时也是它**，行为与改动前完全一致 |
| `index.html#blank` | 空白画布，双击空白处自己加节点 |
| `index.html#t=文生图` | 直接把该类型节点建好、选中并自动居中 |

`#t=` 后面是**节点类型名**，中文要走 URL 编码（HTML 里写成百分号形式，地址栏里直接打中文也行）：

```
文生图      index.html#t=%E6%96%87%E7%94%9F%E5%9B%BE
图生图      index.html#t=%E5%9B%BE%E7%94%9F%E5%9B%BE
文生视频    index.html#t=%E6%96%87%E7%94%9F%E8%A7%86%E9%A2%91
图生视频    index.html#t=%E5%9B%BE%E7%94%9F%E8%A7%86%E9%A2%91
提示词输入  index.html#t=%E6%8F%90%E7%A4%BA%E8%AF%8D%E8%BE%93%E5%85%A5
保存结果    index.html#t=%E4%BF%9D%E5%AD%98%E7%BB%93%E6%9E%9C
```

可用类型就是节点库里的九个：`提示词输入 / AI改写提示词 / 文生图 / 图生图 / 文生视频 /
图生视频 / 图片预览 / 视频预览 / 保存结果`。
**拼错不会白屏**：认识就直达，不认识会 toast 报错并回退到示例工作流。

落地页「能力」区下方那排「带着节点直接进画布 →」芯片就是这些链接，页脚也留了
`画布 / 空白画布 / 图生视频` 三个快捷入口。

### 首页上的代理状态

落地页顶部导航会**每 10 秒**轮询一次画布用的同一个 `http://127.0.0.1:8787/health`：

- 在线 → 徽章转绿「代理已连接」；
- 离线 → 徽章转红「代理未启动」，Hero 区下方浮出提示条，提醒先跑 `python proxy.py`。

能通是因为 `proxy.py` 的所有响应都带 `Access-Control-Allow-Origin: *`，`file://` 页面也能读到。
**代理没起时画布照常能打开、能连线，但执行节点会失败**（浏览器直连会被 CORS 拦）。
