7.6 KiB
7.6 KiB
介面與長連線格式
給要改帳號伺服器或寫其他用戶端的人。所有回覆都是 JSON;錯誤是 {"error": "白話的說明"} 加上對應的 HTTP 狀態碼。
身分
| 誰 | 怎麼證明 | 從哪來 |
|---|---|---|
| 人(手機) | Authorization: Bearer <session> |
POST /relay/login |
| 一台 AnyBot(主機) | Authorization: Bearer <host token> |
POST /relay/hosts(登入後)或 POST /relay/pair/claim(配對碼) |
伺服器只存密碼和金鑰的雜湊值。
帳號伺服器(relay)
帳號
| 方法 | 路徑 | 說明 |
|---|---|---|
| POST | /relay/signup |
{user, password, invite}。第一個帳號不用邀請碼,之後要 ANYBOT_RELAY_INVITE |
| POST | /relay/login |
{user, password, device} → {token}。錯 8 次停 5 分鐘 |
| POST | /relay/logout |
登出這個 session |
| GET | /relay/me |
帳號、可用的 AnyBot(含 online、uses、hands)、登入過的裝置、有沒有備份 |
主機
| 方法 | 路徑 | 說明 |
|---|---|---|
| POST | /relay/hosts |
(人){name} → {id, token}。同名的主機會換新金鑰 |
| POST | /relay/hosts/<id>/remove |
(人)移除主機 |
| GET | /relay/host/ws |
(主機)長連線,見下面 |
| GET | /relay/host/next |
(主機)舊式長輪詢:有要求就回 job,25 秒沒有回 204 |
| POST | /relay/host/reply/<job id> |
(主機)回答舊式 job |
| GET | /relay/host/peers |
(主機)帳號裡的其他主機 |
| GET/POST | /relay/host/members |
(主機)團隊成員和角色(admin、member) |
| POST | /relay/host/notify |
(主機)推播通知到帳號的手機 |
| POST | /relay/host/sites/<name> |
(主機)發布 Bot 做的網頁,公開在 /s/<name>/ |
| PUT/GET | /relay/backup |
加密備份(伺服器打不開) |
配對碼
| 方法 | 路徑 | 說明 |
|---|---|---|
| POST | /relay/pair |
(人或主機){for: 大腦的主機 id} → {code, expires_in: 600} |
| POST | /relay/pair/claim |
(不用登入){code, name} → {id, token, user, for, for_name}。只能用一次;同一個位址錯 8 次停 5 分鐘 |
轉送
| 路徑 | 誰 | 轉成 |
|---|---|---|
/h/<host>/api/... |
手機 | 那台 AnyBot 的 /api/...,角色是 owner/admin/member |
/relay/hosts/<host>/api/sync[/...] |
同帳號的主機 | 大腦的 /api/sync...,角色 mirror |
/relay/hosts/<host>/api/device/run |
同帳號的主機 | 手腳的 /api/device/run,角色 device |
轉送時伺服器附上 user、role 和 from(問的那台主機 id)。對方不在線時立刻回 503「目前離線」;收到了但 35 秒內沒回答,回 504。
看 Bot 的電腦(VNC,一條串流,不是一問一答):
| 路徑 | 誰 | 說明 |
|---|---|---|
GET /screen、GET /novnc.js |
任何人 | 看畫面的網頁和 noVNC 1.6.0(MPL-2.0) |
POST /relay/screen-ticket {host} |
同帳號的主機(host token) | → {ticket}:10 分鐘內有效,讓這台的 App 開瀏覽器看那台的電腦 |
WebSocket /relay/vnc/<host>?t= 或 ?ticket= |
擁有者、管理員 | 二進位訊息是 VNC;文字訊息是要打進去的字。伺服器把它接到那台 AnyBot 的長連線(下面的 v*) |
AnyBot 提供的介面(remote::handle)
只有經過帳號伺服器(或同一個網路、用手機密碼登入)才到得了。
| 方法 | 路徑 | 角色 | 說明 |
|---|---|---|---|
| GET | /api/state?since= |
手機 | Bot 清單、誰在工作、等核准的事(有變化才回,最多等 20 秒) |
| GET | /api/bots/<id>?since= |
手機 | 一個 Bot 的訊息 |
| POST | /api/bots/<id>/<動作> |
手機 | send、stop、answer、read、new、upload… |
| GET/POST | /api/screen/mac |
手機 | 看這台 Mac 的畫面、點擊打字(開了「從手機操作」才可以) |
| GET | /screen、/novnc.js |
任何人 | 看 Bot 的電腦的網頁(noVNC);本身沒有資料 |
| WebSocket | /api/vnc?t= |
手機(同一個網路) | VNC,直接到這台的 Bot 的電腦(見 vnc.rs) |
| GET | /api/sync/screen |
mirror | Bot 的電腦的小縮圖(JPEG,寬 320) |
| POST | /api/sync/screen |
mirror | {kind: "hold", on}(接管時 Bot 等你)、{kind: "wake"} |
| POST | /api/device/run |
device | {tool, args, who} → {text, ok, image}:在這台跑一個工具 |
| GET | /api/sync?since=&client= |
mirror | 大腦的變化(見 architecture.md) |
| POST | /api/sync/edit |
mirror | {ops, client, seq} → {ok, applied} |
| POST | /api/sync/act |
mirror | {bot, action, …}:send、stop、answer、read、new、regenerate、reply、restore |
| POST | /api/sync/upload/<bot>?name= |
mirror | 原始檔案內容 → {path} |
| GET | /api/sync/file?path= |
mirror | 大腦上的附件(只限 attachments/ 裡的檔案) |
| POST | /api/sync/models |
mirror | {provider} → {models}:用大腦的金鑰取得模型清單 |
長連線的格式(src/wire.rs)
WebSocket 的二進位訊息,每則是:
[4 位元組,表頭長度,big-endian] [表頭 JSON] [內容的原始位元組]
內容不做 base64。z: true 表示內容用 deflate 壓過;z_ok: true 表示問的人看得懂壓過的回答。
| t | 方向 | 表頭欄位 | 意思 |
|---|---|---|---|
hello |
AnyBot → 伺服器 | brain、hands |
這台在看哪個大腦、是不是手腳(手機和設定畫面用) |
job |
伺服器 → AnyBot | id, method, path, query, user, role, from, z, z_ok |
給這台的要求 |
reply |
AnyBot → 伺服器 | id, status, ctype, headers, z |
回答 job |
call |
AnyBot → 伺服器 | id, to, method, path, query, z |
要問帳號裡的另一台(只能是 /api/sync… 或 /api/device/run) |
ret |
伺服器 → AnyBot | id, status, ctype, z, headers |
call 的回答 |
vopen |
伺服器 → AnyBot | sid |
有人要看這台的 Bot 的電腦:接上它的 VNC(AnyBot 先回 VNC 的開頭) |
vdata |
雙向 | sid |
VNC 的位元組(內容) |
vtext |
伺服器 → AnyBot | sid |
看的人打的字(UTF-8),貼進 Bot 的電腦 |
vclose |
雙向 | sid(AnyBot 送的有 why) |
結束這條 |
兩邊的迴圈有東西在跑時每 2 毫秒、安靜時每 40 毫秒看一次有沒有要讀的(wire::Pace),之後立刻送出排隊的訊息。心跳用 WebSocket 的 ping/pong。連線斷掉時,伺服器把還在等的 job 都回 503「斷線了」,AnyBot 把還在等的 call 都回「和帳號伺服器的連線斷了」。
同步的改動(/api/sync/edit 的 ops)
| op | 欄位 | 說明 |
|---|---|---|
set |
key, value |
換掉一個設定(next_* 計數只會變大) |
patch |
key, patch |
清單或對照表逐項修改 |
merge |
key, value |
搬移時補上大腦沒有的(providers、skills、mcp_servers) |
bot_add |
bot |
新增 Bot(id 撞到會換) |
bot_del |
id |
刪除(主要 Bot 不能刪) |
bot_set |
id, key, value |
改 Bot 的一個欄位 |
bot_patch |
id, key, patch |
逐項修改 Bot 的清單欄位(例行任務保留大腦記錄的執行時間) |
bot_read |
id |
標為已讀 |
bot_order |
ids |
Bot 的順序 |
patch 的格式:
{"value": …} 換掉整個值
{"map": {"put": {"鍵": 值}, "del": ["鍵"]}} 對照表
{"list": {"put": [項目], "del": [鍵], "order": [鍵]}} 清單;鍵是項目的 id,沒有就用 name,純值就是值本身
清單裡的項目沒有 id 或名字、或鍵重複時,送整個值。