# Models

## Error

```json
{
  "type": "object",
  "properties": {
    "error": {
      "type": "string"
    }
  },
  "required": [
    "error"
  ]
}
```

## FingerprintEnvelope

```json
{
  "type": "object",
  "properties": {
    "fingerprint": {
      "$ref": "#/components/schemas/Fingerprint"
    }
  },
  "required": [
    "fingerprint"
  ]
}
```

## Fingerprint

```json
{
  "type": "object",
  "description": "原生 FingerprintConfig。记录的子对象为最常见的；\n该对象是开放的，创建端点会原样保存，\n因此此处的任何字段都会原封不动地传递。\n",
  "additionalProperties": true,
  "properties": {
    "name": {
      "type": "string"
    },
    "notes": {
      "type": "string"
    },
    "seed": {
      "type": "integer",
      "description": "0 = 仅覆盖模式（典型情况）。"
    },
    "navigator": {
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "user_agent": {
          "type": "string"
        },
        "platform": {
          "type": "string",
          "example": "Win32"
        },
        "hardware_concurrency": {
          "type": "integer",
          "example": 12
        },
        "device_memory": {
          "type": "integer",
          "enum": [
            8,
            16,
            32
          ],
          "example": 16
        },
        "language": {
          "type": "string"
        },
        "do_not_track": {
          "type": "boolean"
        }
      }
    },
    "screen": {
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "width": {
          "type": "integer"
        },
        "height": {
          "type": "integer"
        },
        "avail_width": {
          "type": "integer"
        },
        "avail_height": {
          "type": "integer"
        },
        "color_depth": {
          "type": "integer",
          "example": 24
        },
        "device_pixel_ratio": {
          "type": "number",
          "example": 2
        },
        "color_gamut": {
          "type": "string",
          "enum": [
            "",
            "srgb",
            "p3",
            "rec2020"
          ]
        },
        "refresh_rate": {
          "type": "integer",
          "minimum": 24,
          "maximum": 480,
          "example": 60,
          "description": "所声明的显示刷新频率。缺席意味着 60。请参阅创建/编辑请求上的刷新率字段。"
        }
      }
    },
    "client_hints": {
      "type": "object",
      "description": "Sec-CH-UA 系列（在 browser.vision 中称为 `hints`）。",
      "additionalProperties": true,
      "properties": {
        "platform": {
          "type": "string"
        },
        "platform_version": {
          "type": "string"
        },
        "architecture": {
          "type": "string",
          "example": "x86"
        },
        "bitness": {
          "type": "string",
          "example": "64"
        },
        "mobile": {
          "type": "boolean"
        }
      }
    },
    "webgl": {
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "unmasked_vendor": {
          "type": "string"
        },
        "unmasked_renderer": {
          "type": "string"
        }
      }
    },
    "webgpu": {
      "type": "object",
      "additionalProperties": true
    },
    "webrtc": {
      "type": "string",
      "description": "WebRTC 处理模式。",
      "enum": [
        "auto",
        "tcp_only",
        "block"
      ]
    },
    "noise": {
      "$ref": "#/components/schemas/NoisePrefs"
    },
    "network": {
      "type": "object",
      "properties": {
        "blocked_ports": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "局域网端口扫描防护（ports_protection）。"
        }
      }
    },
    "timezone": {
      "type": "string",
      "description": "IANA 名称或 \"auto\"; 将在启动时通过绑定代理解析。"
    }
  }
}
```

## NoisePrefs

```json
{
  "type": "object",
  "description": "各向量的反指纹噪音配置。每个块：`{enabled, seed}`\n（+ 特定参数）。`enabled:false` = 直接透传。\n",
  "properties": {
    "canvas": {
      "$ref": "#/components/schemas/NoiseBlock"
    },
    "webgl": {
      "allOf": [
        {
          "$ref": "#/components/schemas/NoiseBlock"
        }
      ],
      "properties": {
        "intensity": {
          "type": "number"
        }
      }
    },
    "audio": {
      "allOf": [
        {
          "$ref": "#/components/schemas/NoiseBlock"
        }
      ],
      "properties": {
        "intensity": {
          "type": "number"
        }
      }
    },
    "client_rects": {
      "allOf": [
        {
          "$ref": "#/components/schemas/NoiseBlock"
        }
      ],
      "properties": {
        "max_offset": {
          "type": "number"
        }
      }
    },
    "sensors": {
      "$ref": "#/components/schemas/NoiseBlock"
    },
    "fonts": {
      "allOf": [
        {
          "$ref": "#/components/schemas/NoiseBlock"
        }
      ],
      "description": "`enabled:true` 为每个配置文件隐藏少量确定性的\n非关键字体子集（其余真实主机字体直接透传）。\n"
    }
  }
}
```

## NoiseBlock

```json
{
  "type": "object",
  "properties": {
    "enabled": {
      "type": "boolean"
    },
    "seed": {
      "type": "integer",
      "description": "每个配置文件的熵值；0 = 自动计算。"
    }
  }
}
```

## CreateProfileRequest

```json
{
  "type": "object",
  "required": [
    "fingerprint"
  ],
  "properties": {
    "name": {
      "type": "string"
    },
    "notes": {
      "type": "string"
    },
    "proxy_id": {
      "type": "string",
      "description": "绑定存储中的代理（按 id）。"
    },
    "proxy": {
      "type": "string",
      "description": "以字符串方式绑定代理（`host:port:user:pass` 或\n`scheme://user:pass@host:port`）。对于**永久**配置文件，代理\n会被添加到存储（按端点去重）并完成全量测试（UDP + 地理位置），\n然后按 id 绑定; 显示在代理列表中，QUIC/WebRTC 结果被缓存。\n对于**临时**配置文件，代理以内联方式附加（不保存）。\n若已指定 `proxy_id` 则忽略。\n",
      "example": "socks5://user:pass@1.2.3.4:1080"
    },
    "folder": {
      "type": "string",
      "description": "文件夹标签（对于 /folders/{folder}/profiles 被忽略; 路径优先）。"
    },
    "color": {
      "type": "string",
      "description": "配置文件窗口图标和地址栏名称标签的强调色。省略时，图标颜色根据名称生成，标签保留浏览器工具栏的颜色。",
      "example": "#2FCB80"
    },
    "extensions": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "扩展库 ID (`GET /extensions`)，在启动时加载。库不保存的 id 是 400，而不是在没有它的情况下静默启动的配置文件。"
    },
    "refresh_rate": {
      "type": "integer",
      "minimum": 24,
      "maximum": 480,
      "example": 60,
      "description": "声称的显示刷新率，写入`screen.refresh_rate`。没有 Web API 报告它；页面通过计时 requestAnimationFrame 来衡量它，这就是为什么将其排除在外并不是中立的；缺席意味着 60，这是大多数机器报告的值，而不是主机自己的屏幕所做的任何内容。帧只能减慢，因此有效速率是主机面板在此或低于此的最接近的整个划分。"
    },
    "fingerprint": {
      "allOf": [
        {
          "$ref": "#/components/schemas/Fingerprint"
        }
      ],
      "description": "原样保存。从 /fingerprint/new 获取后按需编辑。"
    }
  }
}
```

## EditProfileRequest

```json
{
  "type": "object",
  "description": "所有字段均为可选; 仅更新传入的字段。",
  "properties": {
    "name": {
      "type": "string"
    },
    "notes": {
      "type": "string"
    },
    "folder": {
      "type": "string",
      "description": "\"\"将配置文件移出文件夹（移至\"全部\"）。"
    },
    "proxy_id": {
      "type": "string",
      "description": "\"\"解绑代理。"
    },
    "proxy": {
      "type": "string",
      "description": "代理字符串; 保存（去重）+ 全量测试，然后绑定。"
    },
    "color": {
      "type": "string",
      "description": "`#rrggbb`； “”回到源自名称的颜色。"
    },
    "extensions": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "替换整个列表； `[]` 不加载任何内容。"
    },
    "refresh_rate": {
      "type": "integer",
      "minimum": 24,
      "maximum": 480,
      "example": 60,
      "description": "声明的显示刷新率，在 `fingerprint` 之后应用并写入 `screen.refresh_rate`。没有 Web API 报告它；页面通过计时 requestAnimationFrame 来衡量它，这就是为什么将其排除在外并不是中立的；缺席意味着 60，这是大多数机器报告的值，而不是主机自己的屏幕所做的任何内容。帧只能减慢，因此有效速率是主机面板在此或低于此的最接近的整个划分。"
    },
    "fingerprint": {
      "allOf": [
        {
          "$ref": "#/components/schemas/Fingerprint"
        }
      ],
      "description": "若提供，则原样**替换**已保存的指纹。"
    }
  }
}
```

## TempProfileRequest

```json
{
  "type": "object",
  "properties": {
    "fingerprint_id": {
      "type": "string",
      "description": "配置文件所基于的库条目；未提供时，在 `platform` 下随机选取。"
    },
    "platform": {
      "type": "string",
      "enum": [
        "Windows",
        "macOS",
        "Linux"
      ],
      "description": "若未指定 `fingerprint_id` 则用于随机选取指纹；两者均未提供时使用主机 OS。"
    },
    "proxy": {
      "type": "string",
      "description": "内联代理字符串（不保存到存储中）。"
    },
    "name": {
      "type": "string"
    },
    "folder": {
      "type": "string"
    },
    "refresh_rate": {
      "type": "integer",
      "minimum": 24,
      "maximum": 480,
      "example": 60,
      "description": "声称的显示刷新率，写入`screen.refresh_rate`。没有 Web API 报告它；页面通过计时 requestAnimationFrame 来衡量它，这就是为什么将其排除在外并不是中立的；缺席意味着 60，这是大多数机器报告的值，而不是主机自己的屏幕所做的任何内容。帧只能减慢，因此有效速率是主机面板在此或低于此的最接近的整个划分。"
    },
    "noise": {
      "type": "object",
      "description": "按向量设置指纹噪声。请求中省略的向量保留默认值（关闭）。\n\n同一个请求可以组合两种格式：\n\n  * 简写：`{\"canvas\": true, \"webgl\": true}`。这样启用 `webgl` 或 `client_rects` 时，也会使用界面中的默认强度；\n  * 完整对象：`{\"canvas\": {\"enabled\": true, \"seed\": 42}}`，格式与 `GET /profiles/{id}` 返回的对象相同。\n\n字段会与现有向量设置合并，而不是替换整个向量。例如 `{\"webgl\": {\"intensity\": 0.001}}` 不会修改 `enabled`。`seed` 为 0 或未提供时，系统会根据配置文件 ID 生成稳定值，避免两个临时配置文件使用相同的指纹。",
      "additionalProperties": {
        "oneOf": [
          {
            "type": "boolean"
          },
          {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "seed": {
                "type": "integer",
                "format": "int64"
              },
              "intensity": {
                "type": "number",
                "description": "仅限 `webgl`。"
              },
              "max_offset": {
                "type": "number",
                "description": "仅限 `client_rects`。"
              }
            }
          }
        ]
      },
      "properties": {
        "canvas": {},
        "webgl": {},
        "audio": {},
        "client_rects": {},
        "sensors": {},
        "fonts": {}
      },
      "example": {
        "canvas": true,
        "webgl": {
          "enabled": true,
          "intensity": 0.0005
        },
        "fonts": true
      }
    }
  }
}
```

## Extension

```json
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "将其传递到配置文件的 `extensions` 中。"
    },
    "name": {
      "type": "string"
    },
    "version": {
      "type": "string"
    },
    "description": {
      "type": "string"
    },
    "size_bytes": {
      "type": "integer",
      "format": "int64"
    },
    "added_at": {
      "type": "string",
      "description": "`@<unix_secs>`。"
    },
    "icon": {
      "type": "string",
      "nullable": true,
      "description": "清单声明的最大图标，作为 `data:` URL。列表端点和不提供任何内容的扩展上为 Null。"
    }
  }
}
```

## AddExtensionRequest

```json
{
  "type": "object",
  "description": "恰好是 `url` 或 `path` 之一。",
  "properties": {
    "url": {
      "type": "string",
      "description": "Chrome 网上应用店页面、裸露的 32 个字符的扩展 ID 或指向 `.crx` / `.zip` 的直接链接。",
      "example": "https://chromewebstore.google.com/detail/rabby-wallet/acmacodkjbdgmoleebolmdjonilkdbch"
    },
    "path": {
      "type": "string",
      "description": "启动器计算机上的本地 `.crx`、`.zip` 或解压文件夹。"
    }
  }
}
```

## Bookmark

```json
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "title": {
      "type": "string"
    },
    "url": {
      "type": "string"
    },
    "folder": {
      "type": "string",
      "description": "启动器文件夹；空意味着每个配置文件。"
    }
  }
}
```

## BookmarkRequest

```json
{
  "type": "object",
  "required": [
    "url"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "显示该书签的更新；缺席创造一个。"
    },
    "url": {
      "type": "string",
      "description": "裸主机就可以了；添加了 `https://`。",
      "example": "facebook.com/ads/manager"
    },
    "title": {
      "type": "string",
      "description": "空白使用地址本身。"
    },
    "folder": {
      "type": "string",
      "description": "空（或不存在）意味着每个配置文件。"
    }
  }
}
```

## TrashEntry

```json
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string"
    },
    "folder": {
      "type": "string"
    },
    "deleted_at": {
      "type": "integer",
      "format": "int64",
      "description": "Unix 秒。"
    },
    "expires_at": {
      "type": "integer",
      "format": "int64",
      "description": "Unix 秒；启动扫描会删除所有过去的内容。"
    },
    "size_bytes": {
      "type": "integer",
      "format": "int64",
      "description": "存档，保存帐户而不是缓存。"
    }
  }
}
```

## ProfileMeta

```json
{
  "type": "object",
  "description": "启动器中配置文件的元数据（创建时返回）。",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string"
    },
    "notes": {
      "type": "string"
    },
    "proxy_id": {
      "type": "string",
      "nullable": true
    },
    "last_launched_at": {
      "type": "string",
      "nullable": true,
      "description": "ISO-8601 或 null。"
    },
    "created_at": {
      "type": "string",
      "nullable": true
    },
    "pinned": {
      "type": "boolean"
    },
    "folder": {
      "type": "string"
    },
    "color": {
      "type": "string",
      "nullable": true,
      "description": "图标强调色，格式为 `#rrggbb`；`null` 表示根据名称自动生成颜色，这是浏览器在未选择颜色时的默认行为。"
    },
    "extensions": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "启动时加载的扩展库 ID。"
    }
  }
}
```

## ProfileListItem

```json
{
  "allOf": [
    {
      "$ref": "#/components/schemas/ProfileMeta"
    },
    {
      "type": "object",
      "properties": {
        "running": {
          "type": "boolean"
        },
        "pid": {
          "type": "integer",
          "format": "int64",
          "nullable": true
        },
        "cdp": {
          "nullable": true,
          "allOf": [
            {
              "$ref": "#/components/schemas/CdpInfo"
            }
          ]
        }
      }
    }
  ]
}
```

## StoredProfile

```json
{
  "type": "object",
  "description": "磁盘上的完整配置文件：`_meta` 包装层加上展开的\nFingerprintConfig（所有 `Fingerprint` 字段位于顶层）。\n`running`/`cdp` 仅在配置文件运行时存在。\n",
  "additionalProperties": true,
  "properties": {
    "_meta": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid"
        },
        "proxy_id": {
          "type": "string",
          "nullable": true
        },
        "inline_proxy": {
          "nullable": true,
          "allOf": [
            {
              "$ref": "#/components/schemas/ProxyEntry"
            }
          ]
        },
        "last_launched_at": {
          "type": "string",
          "nullable": true
        },
        "created_at": {
          "type": "string",
          "nullable": true
        },
        "pinned": {
          "type": "boolean"
        },
        "folder": {
          "type": "string"
        },
        "temporary": {
          "type": "boolean"
        },
        "rev": {
          "type": "integer",
          "description": "每次写入都会递增。桌面编辑器会回传打开配置文件时的版本号；如果配置文件已通过此 API 修改，桌面保存会被拒绝，以免覆盖修改。API 修改不会被拒绝，而是读取并一次性写回配置文件。"
        }
      }
    },
    "running": {
      "type": "boolean"
    },
    "cdp": {
      "nullable": true,
      "allOf": [
        {
          "$ref": "#/components/schemas/CdpInfo"
        }
      ]
    }
  }
}
```

## CdpInfo

```json
{
  "type": "object",
  "description": "正在运行的配置文件的 CDP 端点。",
  "properties": {
    "port": {
      "type": "integer",
      "description": "Chrome 选择的 remote-debugging 端口。"
    },
    "http_url": {
      "type": "string",
      "example": "http://127.0.0.1:53217",
      "description": "REST 基础地址（/json、/json/version）。"
    },
    "web_socket_debugger_url": {
      "type": "string",
      "example": "ws://127.0.0.1:53217/devtools/browser/ab12-...",
      "description": "Puppeteer/Playwright `connect` 使用的浏览器级 WS 端点。"
    }
  }
}
```

## RunningProfile

```json
{
  "type": "object",
  "properties": {
    "profile_id": {
      "type": "string"
    },
    "pid": {
      "type": "integer",
      "format": "int64"
    },
    "cdp": {
      "nullable": true,
      "allOf": [
        {
          "$ref": "#/components/schemas/CdpInfo"
        }
      ]
    }
  }
}
```

## LibraryEntry

```json
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "label": {
      "type": "string"
    },
    "platform": {
      "type": "string",
      "enum": [
        "Windows",
        "macOS",
        "Linux"
      ]
    },
    "chrome": {
      "type": "string",
      "description": "Chrome 版本字符串。"
    },
    "gpu": {
      "type": "string"
    },
    "builtin": {
      "type": "boolean",
      "description": "包含在随附的起始集中。"
    }
  }
}
```

## AddProxyRequest

```json
{
  "type": "object",
  "description": "代理字符串或显式字段（字符串优先）。",
  "properties": {
    "proxy": {
      "type": "string",
      "description": "`scheme://user:pass@host:port` 或 `host:port:user:pass`。"
    },
    "kind": {
      "type": "string",
      "enum": [
        "socks5",
        "http",
        "https"
      ]
    },
    "host": {
      "type": "string"
    },
    "port": {
      "type": "integer"
    },
    "username": {
      "type": "string"
    },
    "password": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "country": {
      "type": "string"
    },
    "notes": {
      "type": "string"
    }
  }
}
```

## ProxySummary

```json
{
  "type": "object",
  "description": "不含凭据的已保存代理信息。",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "kind": {
      "type": "string",
      "enum": [
        "socks5",
        "http",
        "https"
      ]
    },
    "host": {
      "type": "string"
    },
    "port": {
      "type": "integer"
    },
    "country": {
      "type": "string",
      "description": "信息标签（例如\"US\"）。"
    }
  }
}
```

## Cookie

```json
{
  "type": "object",
  "description": "工具友好格式的 cookie（兼容 EditThisCookie / Puppeteer 格式; \n导入时接受 `httpOnly`/`sameSite` 作为别名）。\n",
  "required": [
    "domain",
    "name",
    "value"
  ],
  "properties": {
    "domain": {
      "type": "string",
      "description": "Cookie 主机（Chromium `host_key`），例如\".example.com\"。"
    },
    "name": {
      "type": "string"
    },
    "value": {
      "type": "string"
    },
    "path": {
      "type": "string",
      "default": "/"
    },
    "expires": {
      "type": "number",
      "nullable": true,
      "description": "Unix 秒数；null/缺失 = 会话 cookie。"
    },
    "secure": {
      "type": "boolean",
      "default": false
    },
    "http_only": {
      "type": "boolean",
      "default": false
    },
    "same_site": {
      "type": "string",
      "enum": [
        "Strict",
        "Lax",
        "None",
        "unspecified"
      ],
      "description": "导入时不区分大小写。"
    }
  }
}
```

## ProxyEntry

```json
{
  "type": "object",
  "description": "完整的代理条目（嵌入在 `_meta.inline_proxy` 中）。",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "kind": {
      "type": "string",
      "enum": [
        "socks5",
        "http",
        "https"
      ]
    },
    "host": {
      "type": "string"
    },
    "port": {
      "type": "integer"
    },
    "username": {
      "type": "string"
    },
    "password": {
      "type": "string"
    },
    "country": {
      "type": "string"
    },
    "notes": {
      "type": "string"
    }
  }
}
```

## AutomationBranch

```json
{
  "description": "步骤执行后的分支目标。简单情况使用字符串，需要传值时使用对象。",
  "oneOf": [
    {
      "type": "string",
      "enum": [
        "next",
        "stop",
        "endpass"
      ],
      "description": "`next`；下面的步骤。 `stop`；结束此配置文件的整个运行。 `endpass`；结束本次传递；下一个从顶部开始。"
    },
    {
      "type": "object",
      "properties": {
        "goto": {
          "type": "string",
          "description": "要跳转到的块 id；不再存在的行为与下一个一样。"
        }
      }
    },
    {
      "type": "object",
      "properties": {
        "retry": {
          "type": "integer",
          "description": "再次尝试同样的步骤，多次，然后进行下一步。"
        }
      }
    }
  ]
}
```

## AutomationBlock

```json
{
  "type": "object",
  "description": "一步。 `kind` 和 `params` 已开放；模块可以添加此构建从未听说过的类型。",
  "properties": {
    "id": {
      "type": "string"
    },
    "kind": {
      "type": "string",
      "description": "内置调色板类型（`goto`、`click`、`type`、`profile.create`、`var.set` 等）或 `module:<module id>:<block>`。\n\n**在移动配置文件中**，普通步骤会转换为触摸操作：`click` 执行点按，`rightClick` 执行长按，`scroll` 和 `swipe` 使用触摸手势。移动设备没有指针，因此不支持 `hover`。以下步骤仅适用于移动配置文件，在桌面配置文件中会被拒绝：\n\n| 类型 | 参数 | 操作 |\n| --- | --- | --- |\n| `touch.tap` | `selector` 或 `x`+`y`、`tapCount`（1-3）、`timeout` | 点按目标。 |\n| `touch.longPress` | `selector` 或 `x`+`y`、`timeout` | 按住不放。 |\n| `touch.swipe` | `selector` 或 `x`+`y`、`dx`、`dy`、`timeout` | 滑动。 |\n| `touch.drag` | `selector`、`to`、`holdMs`、`timeout` | 拖动元素。 |\n| `touch.pinch` | `scale`、`selector` 或 `x`+`y` | 双指缩放。值大于 1 时缩小。 |\n| `screen.rotate` | `angle`（0/90/180/270）、`turnMs`、`into` | 旋转设备。`into` 保存新的 `screen.orientation.type`。 |",
      "example": "click"
    },
    "label": {
      "type": "string"
    },
    "params": {
      "type": "object",
      "additionalProperties": true,
      "description": "步骤自己的字段，如调色板定义的那样。"
    },
    "enabled": {
      "type": "boolean",
      "default": true
    },
    "x": {
      "type": "number",
      "description": "画布位置。仅用于布局，执行顺序由分支决定。"
    },
    "y": {
      "type": "number"
    },
    "on_done": {
      "$ref": "#/components/schemas/AutomationBranch"
    },
    "on_fail": {
      "allOf": [
        {
          "$ref": "#/components/schemas/AutomationBranch"
        }
      ],
      "description": "默认为 `stop`；单击后什么也没找到，这就是运行输入错误页面的原因。"
    },
    "secrets": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "导出时参数名称被清空。"
    }
  }
}
```

## AutomationRunSettings

```json
{
  "type": "object",
  "properties": {
    "threads": {
      "type": "integer",
      "default": 1,
      "description": "浏览器同时运行；限制为 1-64。"
    },
    "loops": {
      "type": "integer",
      "default": 1,
      "description": "越过街区。 0 表示运行直到 `hours` 启动。"
    },
    "hours": {
      "type": "number",
      "description": "仅当 `loops` 为 0 时才有意义。"
    },
    "start": {
      "type": "string",
      "description": "块 ID 开始；空的意思是第一个。"
    },
    "profiles": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "保留在配置文件成为块之前保存的项目；设置时各一根线。"
    }
  }
}
```

## AutomationProject

```json
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string"
    },
    "notes": {
      "type": "string"
    },
    "blocks": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/AutomationBlock"
      }
    },
    "run": {
      "$ref": "#/components/schemas/AutomationRunSettings"
    },
    "created_at": {
      "type": "integer",
      "description": "Unix 秒。"
    },
    "updated_at": {
      "type": "integer",
      "description": "Unix 秒。"
    }
  }
}
```

## AutomationBundle

```json
{
  "type": "object",
  "description": "一个项目正在转移到另一台机器上。",
  "properties": {
    "format": {
      "type": "integer",
      "example": 1,
      "description": "导入拒绝它不知道的号码。"
    },
    "exported_at": {
      "type": "integer",
      "description": "Unix 秒。"
    },
    "project": {
      "$ref": "#/components/schemas/AutomationProject"
    },
    "modules": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "模块 ID 需要的步骤。"
    },
    "module_files": {
      "type": "array",
      "description": "这些模块的文件位于捆绑包内，以便导入的项目可以在其所在的位置运行。导出时磁盘中丢失的模块在此处被忽略，但仍以 `modules` 命名。导入时，已安装在同一 ID 下的模块将保持原样，而不是被覆盖。",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "wasm": {
            "type": "string",
            "description": ".wasm 经过 gzip 压缩，然后进行 Base64 处理。"
          }
        }
      }
    },
    "needs": {
      "type": "array",
      "description": "导出的内容被清空，因此导入可以准确地要求该内容。",
      "items": {
        "type": "object",
        "properties": {
          "block_id": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "params": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    }
  }
}
```

## AutomationWorker

```json
{
  "type": "object",
  "description": "运行一个浏览器。",
  "properties": {
    "profile_id": {
      "type": "string"
    },
    "profile_name": {
      "type": "string"
    },
    "pass": {
      "type": "integer",
      "description": "1 为基础； 0 在第一遍开始之前。"
    },
    "step": {
      "type": "integer"
    },
    "steps_total": {
      "type": "integer"
    },
    "status": {
      "type": "string",
      "enum": [
        "queued",
        "starting",
        "running",
        "done",
        "failed",
        "stopped"
      ]
    },
    "note": {
      "type": "string"
    }
  }
}
```

## AutomationRun

```json
{
  "type": "object",
  "properties": {
    "project_id": {
      "type": "string",
      "format": "uuid"
    },
    "project_name": {
      "type": "string"
    },
    "started_at": {
      "type": "integer",
      "description": "Unix 秒。"
    },
    "running": {
      "type": "boolean"
    },
    "workers": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/AutomationWorker"
      }
    },
    "log": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "机队窗口显示的尾部；整个日志位于磁盘上的 `automation-runs/` 下。"
    }
  }
}
```

## AutomationModule

```json
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "文件茎；还有其每个块类型所携带的前缀。"
    },
    "name": {
      "type": "string"
    },
    "path": {
      "type": "string"
    },
    "blocks": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": true
      },
      "description": "块描述符，形状与内置调色板相同。"
    },
    "error": {
      "type": "string",
      "description": "模块加载成功时为空，否则为错误原因。"
    }
  }
}
```
