# Computer 內 archive 套件 API 目前可透過 Tool Manager 的 archive 表單或已登入的 API 安裝預先放在 Computer workspace 的 tar/tar.gz。安裝器在 Computer 內讀取、驗證 SHA-256、解包並建立 binding;API 不下載或解包 task artifact。這是通用 stdio MCP 的 archive 入口,尚未包含遠端 URL 安裝、完整 V1 巢狀 manifest、安裝 hooks、帳戶 broker 或常駐 pool。 `POST /api/bots/{botId}/tools/install`: ```json { "artifactPath": "uploads/server.tar.gz", "manifest": { "id": "example.mcp.server", "version": "1.0.0", "sha256": "替換成 archive 的 64 位 SHA-256", "entrypoint": ["python3", "./server.py"], "share_immutable_package": true } } ``` `artifactPath` 使用 bot workspace 的相對路徑;Team 模式由伺服器映射至該 bot 的 workspace。Manifest 欄位必須符合此 profile;未支援的權限/hook 欄位會被拒絕,不能藉此宣告尚未實作的隔離保證。 套件可使用預裝 Python/Node interpreter 或 archive 內的可執行檔。Interpreter 不存在會拒絕安裝;本輪容器驗證使用 Python,不宣稱預設 image 已提供 Node。依賴需放在 archive 內,安裝器不執行 pip、npm 或任意系統 hook。 安裝成功回傳 `bindingId` 與 MCP schemas。模型透過 `computer_mcp`: ```json {"action":"list"} ``` ```json {"action":"discover","bindingId":"安裝回傳的 ID"} ``` ```json {"action":"call","bindingId":"安裝回傳的 ID","tool":"工具名稱","arguments":{}} ``` 每個 binding 有獨立 UID、私人 HOME/state;程式碼唯讀。`share_immutable_package=false` 時,程式碼也使用該 binding UID 才可讀的副本。每次呼叫重新驗證檔案、manifest 版本與綁定,啟動真正的 MCP SDK client,結束後清除該 UID 的子程序。state 保留,但目前沒有常駐 instance。 目前限制:archive 8 MiB、解包 32 MiB/512 members、32 個套件、64 個儲存中的 bindings;拒絕 symlink、hardlink、特殊檔與路徑逃逸。呼叫有 45 秒 deadline、256 MiB address space、32 個該 UID 程序與 256 個 descriptors 的限制。這不是完整網路/syscall sandbox;grants、broker、狀態磁碟 quota 與長期 GC 仍需補齊。 既有 revoke/remove API 會先關閉中央 admission,再要求 Runner 關閉 binding 並清理程序;無法確認 drain 時回報未完成,不宣稱未知外部效果已回滾。通用套件可在版本切換表單輸入已安裝的目標版本來升級或回滾。已撤銷套件可在安裝表單勾選重新授權,或在安裝 API body 增加 `"reauthorize": true`:確認舊 runtime 已停止後,建立新 binding/UID/私人狀態,舊 ID 永不恢復權限。仍需提供同一版本與 digest 的 archive;重試會沿用新的 installing intent。 驗證:設定 `DATABASE_URL` 指向拋棄式測試 PostgreSQL,再執行 `make test-runner-jobs`(SQLx 帳號須可建立測試資料庫)。此指令建立隔離容器,使用 Bookworm build stage 的 controld binary,執行 Runner、HTTP MCP、archive/stdio MCP、Rust Docker transport 與 API dispatcher→真實 Supervisor→Computer 的檔案回應遺失恢復測試;結束後清除測試容器與 Supervisor 程序。 Tool Manager 可重新探索 schemas,或輸入工具名稱與 JSON object 參數手動呼叫: - `POST /api/bots/{botId}/tools/{bindingId}/discover`:重新讀取工具 schemas。 - `POST /api/bots/{botId}/tools/{bindingId}/call`:body 為 `{"operationId":"UUID","tool":"工具名稱","arguments":{}}`。 手動呼叫沿用操作 journal。相同 ID/payload 回傳原結果;更改 payload 卻沿用 ID 會拒絕,未知效果不重做。UI 在目前瀏覽器分頁保存最近操作 ID 與請求雜湊(不保存參數),重新整理後重新輸入相同請求仍重用該 ID。變更請求、建立新操作或關閉分頁後重新開啟會使用新 ID;效果未知時需先查明狀態。 版本切換 API:`POST /api/bots/{botId}/tools/{bindingId}/switch`,body 為 `{"operationId":"UUID","version":"1.0.0"}`。目標必須是同一 Computer 已安裝的同名套件版本。切換保留來源 binding 的 UID 與私人 state;若該 bot 已有目標版本 binding,先等待其現有呼叫完成,再撤銷該目標 binding,避免兩個 active authorization 混用。 中央先 durable reserve transition、關閉參與 bindings 的新呼叫,再執行 root retire/switch/schema discovery;版本 pointer、ready 與 schemas 在同一 DB transaction 完成。忙碌或回應遺失時用同一 operation ID 重試,UI 重新載入可恢復 pending operation。完成後舊請求只重放 receipt,不重新切換。 撤銷任何參與 binding 會取消整筆 transition,並關閉所有參與 bindings;確認 runtime drain 後才結束 cancelling。跨 Computer generation 的 pending transition 會先讀取受保護的 root receipt,並重新驗證目前套件 bytes。只有「沒有 receipt 且仍在來源版本」或「有 receipt 且仍在目標版本」可更新中央 generation 並繼續。root binding/程式/紀錄遺失或版本已被其他操作取代時,保留 pending,需撤銷清理後重新建立。這仍不是 full V1 manifest/帳戶 schema grant registry/常駐 pool 的完成宣告。 新建 Computer 將 Runner registry、package cache、private executables 與 tool state 分別掛載到 `DATA_DIR/runtime/{homeKey}` 的 root-owned 子目錄,與 task home 分離。已有持久掛載的 Computer 可在 remove/recreate 後保留這些內容。舊 Computer 在替換/刪除前會停止並將 writable-layer runtime 封存到受保護 staging,驗證與持久發布全部完成後才移除來源;未完成時保留來源並可重試。資料目錄搬移、非空目的地或快照不符會拒絕覆寫。 舊 runtime 遷移使用 Rust tar loader,保留 numeric UID/GID、檔案權限、一般檔案、目錄及 symlink/hardlink;不執行套件內容或外部解包程式。每個來源目錄限制 8 GiB/100,000 archive entries,拒絕特殊檔、路徑逃逸、重複成員、未宣告父目錄與不受保護的 root。檔案與目錄 fsync 後才發布,發布中斷可恢復;SHA-256 快照涵蓋實際內容、路徑、owner/mode 與 symlink target。限制或驗證失敗會保留停止中的舊容器,不以成功回報掩蓋資料缺漏。