Documentation Index
Fetch the complete documentation index at: https://docs.cyberun.cloud/llms.txt
Use this file to discover all available pages before exploring further.
GET /api/v1/r/tasks/{taskId}/events 打开一个 Server-Sent Events
流,每次状态变化或进度更新都会推送一个事件。连接保持开启直到任务
进入终态(completed、failed、cancelled),然后关闭。
请优先使用它,而非轮询 GET /r/tasks/{taskId} —— 延迟更低、请求更少。
建立连接
使用 Bearer 令牌(JWT、sk- 或 dk-):
curl -N \
-H "Authorization: Bearer sk-..." \
https://core.cyberun.cloud/api/v1/r/tasks/{taskId}/events
浏览器内建的 EventSource 不支持自定义请求头,意味着它无法
携带 Authorization 头。服务端运行时(Node fetch、Python
requests、httpx)、React Native、以及 eventsource 这类库都
可以正常使用。在浏览器中请通过你自己的后端中转。
事件类型
| 事件 | 含义 |
|---|
status | 任务状态变化(例如 pending → waiting → queued → running)。 |
progress | 执行进度,包含 progress、step_current、step_total、当前节点。 |
completed | 任务完成。包含输出对象。 |
failed | 任务失败。包含错误字符串。 |
cancelled | 任务在进入终态前被取消。 |
error | 服务端读取任务状态时出错。流可能仍然继续。 |
status
event: status
data: {"task_id":"...","status":"running","timestamp":"2026-02-01T14:30:05Z"}
progress
event: progress
data: {
"task_id":"...",
"progress":0.35,
"current_node":"3",
"step_current":7,
"step_total":20,
"timestamp":"2026-02-01T14:30:10Z"
}
Nerfstudio 任务额外携带 stage(download、process_data、train、
export、upload)以及人类可读的 message 字段。
| 字段 | 类型 | 含义 |
|---|
progress | number | 0.0–1.0 的整体进度。 |
step_current | integer | 已完成的步数(运行时报告时)。 |
step_total | integer | 本次运行的总步数。 |
current_node | string | 运行时的当前节点标识(ComfyUI 工作流为节点 ID)。 |
stage | string | 仅 Nerfstudio。粗粒度阶段名称。 |
message | string | 仅 Nerfstudio。自由格式状态文本。 |
终态事件
event: completed
data: {"task_id":"...","status":"completed","completed_at":"...","output":{...}}
event: failed
data: {"task_id":"...","status":"failed","error":"ComfyUI execution error: ..."}
event: cancelled
data: {"task_id":"...","status":"cancelled"}
这三种事件之后服务器会关闭连接。
error
event: error
data: {"message":"failed to fetch task status"}
服务端读取任务状态的瞬时问题。视为可恢复 —— 任务本身可能仍在运行。
如果流也关闭,请改为轮询(见下方)。
完整事件流示例
一个典型的 ComfyUI 任务从头到尾:
event: status
data: {"task_id":"...","status":"waiting","timestamp":"..."}
event: status
data: {"task_id":"...","status":"queued","timestamp":"..."}
event: status
data: {"task_id":"...","status":"running","timestamp":"..."}
event: progress
data: {"task_id":"...","progress":0.15,"step_current":3,"step_total":20,"current_node":"3"}
event: progress
data: {"task_id":"...","progress":0.5,"step_current":10,"step_total":20,"current_node":"3"}
event: progress
data: {"task_id":"...","progress":1.0,"step_current":20,"step_total":20,"current_node":"3"}
event: completed
data: {"task_id":"...","status":"completed","output":{...}}
轮询兜底
如果网络无法承载 SSE,或你不想长连接,可改为轮询
GET /r/tasks/{taskId} 直到 task_status 为
completed、failed、cancelled 之一。轮询间隔 3 秒是个合理默认值。
curl -s \
-H "Authorization: Bearer sk-..." \
https://core.cyberun.cloud/api/v1/r/tasks/{taskId}
当任务为 completed 时,通过 GET /r/tasks/{taskId}/result
获取产物链接。
消费事件流
import json, requests
API_KEY = "sk-..."
BASE = "https://core.cyberun.cloud/api/v1/r"
with requests.get(
f"{BASE}/tasks/{task_id}/events",
headers={"Authorization": f"Bearer {API_KEY}"},
stream=True,
) as stream:
event_type = None
for line in stream.iter_lines(decode_unicode=True):
if not line:
continue
if line.startswith("event:"):
event_type = line[6:].strip()
elif line.startswith("data:"):
data = json.loads(line[5:].strip())
if event_type == "progress":
pct = int(data["progress"] * 100)
print(f"{pct}% ({data['step_current']}/{data['step_total']})")
elif event_type in ("completed", "failed", "cancelled"):
print(event_type, data)
break