{
  "description": "RunComfy 任务执行工具：接收 workflow_api.json 和输入文件，在已启动的 ComfyUI 服务器上运行并下载结果",
  "task_spec": "## 目标\n创建一个 HTTP API 工具并注册到 Router，用于在已启动的 RunComfy 机器上执行 ComfyUI 工作流。\n\n## 核心功能\n在已就绪的 RunComfy 机器上提交 ComfyUI 工作流。上传指定的输入文件（到 input 目录及相应子目录），提交 prompt，通过 WebSocket 监听状态，并在完成后下载结果图片。\n\n## 环境变量\n- RUNCOMFY_USER_ID：RunComfy 用户 ID\n- API_TOKEN：RunComfy API Token\n\n## HTTP API 接口（必须实现）\n实现 `POST /run` 接口：\n\n### 输入 JSON Schema\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"server_id\": {\"type\": \"string\", \"description\": \"运行目标机器 ID\"},\n    \"workflow_api\": {\"type\": \"object\", \"description\": \"解析好的 workflow_api.json 字典\"},\n    \"input_files\": {\n      \"type\": \"array\",\n      \"description\": \"输入文件列表\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"filename\": {\"type\": \"string\"},\n          \"type\": {\"type\": \"string\", \"enum\": [\"images\", \"loras\", \"checkpoints\"], \"description\": \"文件类型，对应 subfolder\"},\n          \"base64_data\": {\"type\": \"string\", \"description\": \"文件的 Base64 编码数据\"}\n        }\n      }\n    }\n  },\n  \"required\": [\"server_id\", \"workflow_api\"]\n}\n```\n\n### 输出 JSON Schema\n```json\n{\n  \"type\": \"object\",\n  \"properties\": {\n    \"prompt_id\": {\"type\": \"string\", \"description\": \"提交的 prompt ID\"},\n    \"images\": {\"type\": \"array\", \"items\": {\"type\": \"string\"}, \"description\": \"结果图片的 Base64 数据列表\"},\n    \"status\": {\"type\": \"string\", \"description\": \"Success 或错误信息\"},\n    \"server_id\": {\"type\": \"string\", \"description\": \"透传回显\"}\n  }\n}\n```\n\n## 核心逻辑\n1. 通过 `GET /users/{USER_ID}/servers/{server_id}` 验证机器状态（需为 Ready），并获取 `main_service_url`\n2. 如果有文件，调用 `POST {main_service_url}/upload/image`。支持 `type=input`，通过 `subfolder` 区分 `loras`, `checkpoints`\n3. 调用 `POST {main_service_url}/prompt` 提交 `{\"prompt\": workflow_api, \"client_id\": client_id}`\n4. 连接 `wss://{main_service_url_host}/ws?clientId={client_id}` 监听进度\n5. 当收到 `type=executing` 且 `data.node === null` 时表示完成\n6. 调用 `GET {main_service_url}/history/{prompt_id}` 获取输出文件名，再从 `/view?filename=x&subfolder=y&type=z` 下载图片并转 Base64 返回\n7. 无论是成功还是报错，**绝不自动关闭机器**（留给 runcomfy_stop_env 处理）\n\n## 实现要求\n1. 使用 uv 创建项目，项目名：runcomfy_run_only\n2. 使用 FastAPI 实现 HTTP 接口\n3. 从环境变量读取 RUNCOMFY_USER_ID 和 API_TOKEN\n4. 实现 POST /run 接口\n5. 添加依赖：httpx, websocket-client\n6. 编写测试脚本验证功能\n7. **必须调用 register_tool 注册到 Router**，tool_id 为 \"runcomfy_run_only\"",
  "reference_files": [
    "tests/run_comfy/run_workflow.py"
  ]
}