10 KiB
技術架構
AnyBot 是一個 Rust 程式(anybot),用 egui/eframe 畫介面。同一個執行檔有三種跑法:
| 跑法 | 指令 | 用途 |
|---|---|---|
| 視窗 | anybot |
桌面 App |
| 無視窗 | anybot --serve |
伺服器、一直開著的電腦、手腳:介面邏輯照跑,只是不畫畫面 |
| 設定 | anybot setup … |
終端機裡把這台接到帳號(src/setup.rs) |
另一個小程式 anybot-relay(relay/)是帳號伺服器。
程式分層
┌─────────────── 介面(src/app.rs、src/app/*)───────────────┐
│ 聊天、側邊欄、設定、電腦、檔案預覽、大腦同步(mirror_ui) │
│ 每個畫面一個 App 方法;狀態全部在 App.state(model::State) │
└───────┬───────────────────────────────┬────────────────────┘
│ 送出訊息 │ 手機/其他 AnyBot 的要求
┌───────▼──────────┐ ┌────────▼───────────────────┐
│ 回合(agent.rs) │ │ 遠端(remote.rs) │
│ 呼叫模型、跑工具、 │ │ 手機 API、裝置連結、大腦同步 │
│ 等你核准、整理摘要 │ │ 長連線(tunnel.rs、wire.rs) │
└───┬─────────┬────┘ └──────────────────────────────┘
│ │
┌───▼───┐ ┌───▼──────────────────────────────────────────────┐
│ 模型 │ │ 工具(tools.rs 為主) │
│ provi- │ │ 檔案與指令、Bot 的電腦(cloudbox.rs)、瀏覽器 │
│ ders.rs│ │ (botbrowser.rs、browser.rs、web.rs)、螢幕操作 │
└────────┘ │ (computer.rs、desktop.rs、axread.rs;Linux:x11.rs、 │
│ wl.rs、portal.rs、desk.rs)、Mac App(macapps.rs)、 │
│ 保險庫(vault*.rs)、MCP(mcp.rs)、記憶(memory.rs) │
└──────────────────────────────────────────────────────┘
| 檔案 | 做什麼 |
|---|---|
model.rs |
資料:State、Bot、Message、設定;讀寫 state.json |
agent.rs |
一個回合:組系統指示、送模型、收串流、跑工具、核准關卡、長對話摘要 |
providers.rs |
各家模型的 API(OpenAI 相容、Anthropic、OpenCode Go…)、串流、重試、看不到圖時的看圖小幫手 |
tools.rs |
檔案、指令、背景指令;指令在 macOS 沙盒裡跑(見「安全」) |
policy.rs |
哪些動作直接做、先問、拒絕 |
cloudbox.rs、box/ |
Bot 自己的電腦:一個 Docker 容器(有桌面、瀏覽器) |
computer.rs、desktop.rs、axread.rs |
看畫面、滑鼠鍵盤;讀 App 的按鈕清單(agent-desktop,只讀) |
vnc.rs、mobile/screen.html |
人看 Bot 的電腦、需要時接手:VNC 代理(經帳號伺服器或同一個網路),noVNC 網頁 |
botbrowser.rs、browser.rs、web.rs |
AnyBot 自己的瀏覽器(Chrome DevTools 協定)、讀你的瀏覽器、抓網頁 |
routines.rs、triggers.rs |
例行任務和觸發 |
channels.rs |
訊息管道(Slack、Discord、Telegram) |
remote.rs |
手機 API、帳號登入、裝置連結、大腦同步的請求端 |
tunnel.rs、wire.rs |
和帳號伺服器之間的長連線(WebSocket) |
app/mirror_ui.rs |
大腦和螢幕之間的同步 |
setup.rs |
anybot setup |
httpd.rs |
很小的 HTTP 伺服器(AnyBot 和帳號伺服器共用) |
mobile/index.html |
手機網頁(單一檔案,編進程式裡) |
資料存放
都在資料資料夾裡(macOS ~/Library/Application Support/AnyBot/、Linux ~/.local/share/AnyBot/、Windows %APPDATA%\AnyBot\;ANYBOT_DATA_DIR 可以改):
| 檔案 | 內容 |
|---|---|
state.json |
全部的 Bot、聊天、設定和金鑰 |
attachments/bot-<id>/ |
聊天附件 |
browser/ |
AnyBot 瀏覽器的設定檔(登入狀態) |
brain-copy.json |
螢幕電腦保留的大腦副本(離線時還能看) |
brain-files/ |
螢幕電腦從大腦下載的附件 |
image-notes.json |
看圖小幫手對每張圖的描述(不用重看) |
寫入時先寫暫存檔再改名,不會寫一半。
安全
- 核准關卡:工具動作照規則直接做、先問或拒絕(
policy.rs,FEATURES.md 第 16、19 節)。「直接操作模式」可以跳過詢問。 - 指令的沙盒(macOS):Bot 執行的指令在
sandbox-exec裡跑,讀不到也寫不到 AnyBot 的資料資料夾、.gnupg、鑰匙圈、.aws等;只有attachments/和.ssh可以讀(都不能寫,.ssh可讀讓 git 和 ssh 連得動)。只有沙盒管得到的才是祕密防線,核准層不再逐字掃路徑。環境變數裡的模型金鑰會先拿掉,PATH 會補齊 Homebrew 等位置(從 Finder 或 launchd 啟動也要找得到指令)。 - Bot 的電腦:放在容器裡,和你的電腦分開。標準(runc)容器和主機共用 Linux 核心,Chromium 在裡面關掉自己的沙盒,容器就是唯一那道牆。Docker 主機裝了 gVisor 時,設定 › 電腦 › 容器隔離可改「強隔離(gVisor)」:容器有自己的虛擬核心,Chromium 的沙盒重新開啟,牆變成兩道(虛擬核心+瀏覽器沙盒)。改完要按電腦的「更新」重建才生效。在 macOS 上沒有能裝 gVisor 的 Docker,用
deploy/mac/gvisor-vm.sh建一台自帶 Docker+gVisor 的 Lima 虛擬機,再把 Docker 主機指過去;那台虛擬機沒開時(例如 Mac 重開機後)AnyBot 會自己開。 - 保險庫:密碼、卡號、CVC 不會交給模型,由 AnyBot 直接填進網頁。
- 多台電腦:金鑰只留在大腦(下面說明);手腳只接受帳號裡的 AnyBot,用配對碼加入的只接受那一個大腦。
多台電腦怎麼運作
連線
每台 AnyBot(大腦、螢幕、手腳)都保持一條 WebSocket 連到帳號伺服器(/relay/host/ws),雙方每 15–20 秒互相確認,45–60 秒沒聲音就重連。帳號伺服器沒有 WebSocket 時(舊版),改用 HTTP 長輪詢(/relay/host/next)。
- 手機的要求:手機 → 帳號伺服器(HTTPS)→ 這條連線 → AnyBot → 回覆原路回去。
- AnyBot 找另一台 AnyBot(同步、手腳):從自己的連線送
call上去,伺服器轉給對方的連線,答案以ret回來。 - 連線斷掉時,等待中的請求立刻收到「斷線了」,不用等逾時;伺服器也立刻知道這台離線。
- 超過 1 KB、而且壓得小的內容用 deflate 壓縮(圖片、PDF 這類已壓縮的照原樣送)。
格式見 protocol.md。
大腦和螢幕的同步(app/mirror_ui.rs)
大腦回答「從版本 N 之後改了什麼」:
- 設定:State 去掉聊天、拿掉金鑰後算指紋,變了才送整份。
- 聊天:每則訊息有指紋,只送第一個不同的那則之後的部分。
- 討論串、誰在工作、等你核准的事。
螢幕的請求會等最多 20 秒,有變化就馬上回(長輪詢,跑在長連線上)。大腦上的改動通常 1 秒內出現在螢幕上。
螢幕上的改動變成小操作送回大腦:
- 單一值(
set、bot_set); - 清單和對照表逐項修改(
patch、bot_patch:新增或修改某幾項、刪掉某幾項、改順序),所以兩台同時改同一份清單的不同項目,兩邊都會保留; - 新增、刪除、排序 Bot(
bot_add、bot_del、bot_order)。
每個改動有編號,大腦回報收到第幾號;還沒確認的改動,會疊在大腦傳回來的新設定上,打字不會被蓋回去。所有改動和聊天動作由一個工作排隊依序送出。送失敗時,螢幕重新要一份完整資料。
聊天動作(傳訊息、停止、核准、重新產生、開新對話…)送 act,由大腦執行。附件先上傳到大腦。
金鑰只在大腦
送給螢幕的設定裡,模型金鑰、訊息管道的 Token、連接器的環境變數和標頭都換成「••••(已設定,在大腦上)」。螢幕改設定送回來時,大腦看到這個替代字,就保留原本的值(清單裡依 id 或名字對上)。螢幕要取得模型清單時,由大腦用自己的金鑰去抓。
手腳
大腦的 Bot 呼叫工具時可以指定 computer。如果是帳號裡的另一台,就透過長連線送 /api/device/run 給它,由它在自己身上執行(螢幕、檔案、指令、它的 AnyBot 瀏覽器),再把文字和截圖傳回來。那台要開「裝置連結」才接受;若設了只給某個大腦用(hands_for),帳號伺服器會附上是哪一台在問,不是那台就拒絕。指令在那台的工作資料夾(Bot 的 workdir)跑;連線經過帳號伺服器只有 35 秒,所以手腳上的指令超過 25 秒就移到背景,用同一台的 read_terminal 追蹤(computer 填那台)。
配對碼
已登入的手機或 AnyBot 向帳號伺服器要一組 6 位數字(10 分鐘、一次)。新電腦用這組數字換到自己的身分(主機 id 和金鑰),不經過密碼。配對碼記得它是給哪個大腦的,新電腦就只讓那個大腦使用。
看圖小幫手
模型拒收圖片時,AnyBot 記下這個模型看不到圖。之後送給它的請求裡,你傳的每張圖會先交給你帳號裡看得到圖的模型(依序試 xAI、Anthropic、OpenAI、Gemini、OpenRouter…,先用你設的預設模型),把描述(包括圖裡的文字)放進訊息。描述依圖片記住,同一張圖不會再看一次;失敗的模型 10 分鐘內跳過。