> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nekohub.fengying.xin/llms.txt
> Use this file to discover all available pages before exploring further.

# 工作流接口

> 创建和管理 workflow profile，并对已有资产手动触发 workflow 执行。

所有 workflow profile 管理接口都需要鉴权，并受 `settings.*` 权限控制。

***

## List workflow profiles

```http theme={null}
GET /api/v1/system/workflows
```

需要权限：`settings.read`

返回所有 workflow profile。当前列表会按 `isAutoRun` 优先、再按名称排序。

### 响应字段

* `id`
* `name`
* `description`
* `isAutoRun`
* `graphJson`
* `createdAtUtc`
* `updatedAtUtc`

***

## Get workflow profile

```http theme={null}
GET /api/v1/system/workflows/{id}
```

需要权限：`settings.read`

如果 workflow 不存在，返回 `404`，错误码为 `workflow_profile_not_found`。

***

## Create workflow profile

```http theme={null}
POST /api/v1/system/workflows
```

需要权限：`settings.update`

### Request body

```json theme={null}
{
  "name": "image-post-process",
  "description": "Generate thumbnail and caption after upload.",
  "isAutoRun": true,
  "graphJson": "{\"nodes\":[{\"id\":\"node-1\",\"data\":{\"skillId\":\"thumbnail\"}}],\"edges\":[],\"viewport\":{\"x\":0,\"y\":0,\"zoom\":1}}"
}
```

### 校验规则

* `name` 必填，最长 `100` 字符
* `description` 可为空，最长 `1000` 字符
* `graphJson` 必填，且必须是合法 JSON 对象
* workflow 名称必须唯一，否则返回 `workflow_profile_name_conflict`
* 如果创建时 `isAutoRun=true`，后端会自动清除其他 workflow 的自动运行标记

***

## Update workflow profile

```http theme={null}
PUT /api/v1/system/workflows/{id}
```

需要权限：`settings.update`

请求体字段与创建时相同，但这是**整体更新**，不是 PATCH 语义。

### 说明

* 你需要重新提交完整的 `name`、`description`、`isAutoRun`、`graphJson`
* 如果 `isAutoRun=true`，后端同样会自动取消其他 workflow 的自动运行状态

***

## Delete workflow profile

```http theme={null}
DELETE /api/v1/system/workflows/{id}
```

需要权限：`settings.update`

成功时返回 `204 No Content`。

***

## Set workflow as auto-run

```http theme={null}
PATCH /api/v1/system/workflows/{id}/autorun
```

需要权限：`settings.update`

把指定 workflow 设为自动运行 workflow。

当前约束：

* 同一时刻只能有一个 `isAutoRun=true` 的 workflow
* 后端会自动清除其他 workflow 的自动运行标记

***

## Run workflow on an asset

```http theme={null}
POST /api/v1/assets/{id}/workflows/{workflowId}/run
```

需要权限：`assets.update`

这个接口不是 workflow profile 管理接口，但它是 workflow 的实际执行入口。

### 行为

* 后端会先读取 asset 和 workflow profile
* 解析 `graphJson` 中的技能节点
* 在入队前检查这些 skill 是否适用于当前 asset
* 校验通过后，将 workflow 对应 skill 序列放入异步处理队列

### 响应

成功时返回 `202 Accepted`：

```json theme={null}
{
  "data": {
    "assetId": "01956f8d-88e4-7c6a-a8f1-5f235293db7a",
    "workflowId": "01957000-0000-7000-0000-000000000001",
    "skillIds": [
      "thumbnail",
      "ai-caption"
    ]
  }
}
```

### 常见错误

* `workflow_profile_not_found`
* `workflow_profile_has_no_skills`
* `workflow_profile_contains_unsupported_skills`

## graphJson 结构说明

后端当前要求 `graphJson` 是一个 JSON 对象。解析时：

* 优先读取 `nodes[].data.skillId`
* 如果没有 `data.skillId`，再回退到旧结构里的 `nodes[].type`
* 如果 `data.parameters` 存在，则作为该节点的参数
* 如果是旧图结构，后端也会尝试把 `data` 中除 `skillId` 以外的字段视为参数

最小示例：

```json theme={null}
{
  "nodes": [
    {
      "id": "node-1",
      "data": {
        "skillId": "thumbnail"
      }
    },
    {
      "id": "node-2",
      "data": {
        "skillId": "watermark",
        "parameters": {
          "Text": "NekoHub",
          "Opacity": 0.5,
          "FontSize": 36,
          "Position": "BottomRight"
        }
      }
    }
  ],
  "edges": [],
  "viewport": {
    "x": 0,
    "y": 0,
    "zoom": 1
  }
}
```

<Note>
  当前执行模型仍按节点保存顺序线性执行，`edges` 和 `viewport` 主要用于前端编辑器展示与回填。
</Note>
