HTTP API 与 WebSocket

先通过 HTTP 创建会话,再订阅事件并提交消息。响应码、回合终态与重连游标需要分别处理。

本页内容

连接与鉴权

基础地址采用 daemon 实际输出的地址。本机同源回环请求可不带 Token;远程或代理来源必须带认证。HTTP 使用 X-ACECode-Token 请求头,浏览器 WebSocket 使用 URL 的 token 参数。

先调用 GET /api/health 确认进程 GUID、版本、工作目录和能力。健康接口可以访问只证明该后台响应,不证明模型服务和外部工具均已可用。

HTTP 状态处理方向
400JSON、字段、参数或状态不满足要求。
401缺少 Token 或 Token 不匹配。
404会话、工作区、资源或路由不存在。
409工作区不可用、正在运行或其他状态冲突。
503对应后端能力或运行组件不可用。

错误正文通常包含 error,并可能提供 message。客户端同时保留状态码和可读错误,不将不同错误统一丢弃为一个连接失败提示。

创建会话与提交消息

顺序请求关键内容
1POST /api/workspaces{"cwd":"C:/repo"};返回工作区 hash。
2POST /api/workspaces/:hash/sessions可选 model 和 permission_mode;返回 session_id。
3订阅目标会话的 WebSocket取得 subscribe_ack 后监听事件。
4POST /api/sessions/:id/messages{"text":"说明项目入口"};返回 202 queued。
5GET /api/sessions/:id/messages按接口约定获取持久消息快照,配合实时事件显示。

model 使用已保存的预设名称。创建时 auto_start 默认关闭,只有提供 initial_user_message 并显式开启时才自动执行。下面的 Python 示例只创建一个默认权限会话,不发送模型请求。

Python · 先设置 ACECODE_PROJECT,远程连接还需设置地址与 Token
import json
import os
from urllib.request import Request, urlopen

base = os.environ.get("ACECODE_BASE_URL", "http://127.0.0.1:12399").rstrip("/")
token = os.environ.get("ACECODE_TOKEN", "")
project = os.environ["ACECODE_PROJECT"]  # 后台所在机器中的绝对路径

def post(path, value):
    headers = {"Content-Type": "application/json"}
    if token:
        headers["X-ACECode-Token"] = token
    request = Request(base + path,
                      data=json.dumps(value).encode("utf-8"),
                      headers=headers, method="POST")
    with urlopen(request, timeout=30) as response:
        return json.load(response)

workspace = post("/api/workspaces", {"cwd": project})
session = post("/api/workspaces/" + workspace["hash"] + "/sessions",
               {"permission_mode": "default"})
print(session["session_id"])

202 queued 只表示接受输入。可选 client_message_id 用于前端乐观消息与持久记录对齐,不提供服务端执行去重;网络超时后不要无条件重发同一个有副作用的请求。

订阅、重连与终态

当前前端使用 /ws/sessions/_multiplex?token=...。路由末尾不是自动绑定的会话 ID,连接打开后仍需发送订阅消息:

WebSocket 客户端消息 · sid 替换为实际 ID
{"type":"subscribe","payload":{"session_id":"sid","since":0}}

服务端事件包含 type、session_id、payload,通常还有每会话独立递增的 seq 和 timestamp_ms。文本、工具、用量、问题及回合状态都通过不同事件传输,不能只监听 token。

客户端保存已经处理的序号,重连后用 since 请求续传。订阅确认后补发的待处理权限与问题快照可能没有 seq,应按 request_id 去重,不推进序号游标。处理关闭事件后保留该轮已解决标记,防止迟到快照重新弹出旧请求。

普通回合用 turn_id 标识。busy_changed 的结束状态和后续 done 会带 outcome,只有 completed 表示成功;error 与 aborted 需要分别显示。重试产生的 transcript_replace 应按替换语义处理,避免保留失败尝试的临时输出。

回答问题与取消

独立消息示例 · 仅在用户作出相应决定时发送
{"type":"decision","payload":{"session_id":"sid","request_id":"request-id","choice":"allow"}}
{"type":"abort","payload":{"session_id":"sid"}}

权限选择字段是 choice,可为 allow、deny 或 allow_session。提问使用 question_answer,携带 request_id、cancelled 与 answers;每项回答使用 question_id、selected 和 custom_text。多会话连接必须带正确的 session_id。

收到 permission_closed 或 question_closed 时关闭对应交互。不要为了让集成看起来流畅而默默自动批准。完整路由、消息字段和 PTY 协议见仓库中的Daemon API 协议说明,接入时对照当前版本源码。

搜索全部帮助文档