AnyBot/docs/protocol.md

8.4 KiB
Raw Blame History

介面與長連線格式

給要改帳號伺服器或寫其他用戶端的人。所有回覆都是 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};開了兩步驗證時回 {need_2fa: true, challenge}(5 分鐘內有效)。IP+帳號 8 次/5 分锁定
POST /relay/2fa/verify 兩步驗證的第二步。登入時:{challenge, code} → {token}(TOTP 六位碼,或一次性恢復碼 → 多附 used_recovery: true);設定時(帶 session):{code} 啟用新-secret
POST /relay/2fa/enroll (帶 session)開始設定 → {secret, uri, recovery_codes}(恢復碼只顯示這一次;2FA 要到 verify 成功才生效)
POST /relay/2fa/disable (帶 session){code} 關掉兩步驗證
POST /relay/sessions/logout (帶 session)一頁登出:踢掉這帳號的所有裝置(含自己)
POST /relay/logout 登出這個 session
GET /relay/me 帳號、two_factor、可用的 AnyBot(含 online、uses、hands)、登入過的裝置、有沒有備份

密碼雜湊為 argon2id(memory-hard);舊 PBKDF2 雜湊仍可登入,下次改密碼時自動升級。

主機

方法 路徑 說明
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 或名字、或鍵重複時,送整個值。