LazyBoy2/docs/TOOL-PORTABILITY-AUDIT.md

123 lines
24 KiB
Markdown
Raw Normal View History

2026-09-14 09:08:35 +00:00
# 工具可攜性盤點
日期2026-09-14。範圍目前工作區 LazyBoy2 原始碼非尚未實作的理想架構。本次僅新增盤點文件未改動程式、金鑰、provider 或 Docker 設定。
已核對 **51 個核心工具 + 8 個團隊新增名稱,共 59 個不同工具名稱**。各角色看到的子集不同send_message 同名用途也依角色不同;這不是所有工具在每個 turn 同時出現的保證。MCP 服務內部動態工具不包含在此數量。
## 主要結論
1. 直接與主模型供應商耦合的是 web_search、web_fetchspawn_subagentdelegate_taskspawn_agent 會繼承或使用共享模型設定。
2. 其餘工具的底層大多不綁模型供應商,但模型必須能透過目前的 Chat Completions串流 tool_calls 介面正確呼叫它們。這個共同前提不滿足,所有 agent 工作都可能停住。
3. 模型 adapter 目前沒有任意 provider capability discovery、ResponsesMessages 自動適配,也沒有每個子 agent 的獨立 provider 選擇。換環境變數不會改變已運行 daemon 捕捉的 Config需重啟相應程序。
4. 換電腦最容易丟失的是 Docker volume、網站登入、本地 CLIMCP 授權、絕對路徑、team/session資料以及無法直接遷移的活動程序。
5. Docker 並未包含全部狀態主程式、模型MCP編排、SQLite、對話與大型結果快取仍可能在本地。
## 實際檢查到的環境
- 正式容器grokboy-box映像 grokboy-box:local。
- 已掛載 grokboy-box-workspace → /workspace、grokboy-box-home → /home/box。
- 全域預設 ~/.grokboy/mcp.json 與此工作區 .grokboy/mcp.json 均不存在:有 MCP 管理工具,不代表目前已配置任何 MCP 連線。
- 本次檢查程序未帶入 GROKBOY_WEB_*GROKBOY_BASE_URLGROKBOY_API_KEYXAI_API_KEY 等已檢查變數。不能據此推定你另一個 terminal/daemon 也沒有設定;本次未讀取其他程序的憑證,亦未發送付費模型或第三方服務測試請求。
## 完整工具清單
「底層不綁 provider」均受上述模型協議相容前提限制。
| 工具 | 執行位置 | 換 provider | 換電腦/程序 | 所需準備或限制 |
|---|---|---|---|---|
| `add_mcp_server` | 本地主機 MCP 設定檔 | 不綁模型 provider | 依賴可寫入的 MCP 設定路徑;添加成功不等於相應服務可用 | 搬設定並檢查來源workspace 設定與全域設定需一起盤點 |
| `answer_task` | team daemonSQLiteUnix socket | 查詢/控制不直接依賴provider任務繼續與記憶整理仍需模型 | 不搬 DB 就沒有原 agent、task、記憶active 任務不能只靠同名ID繼續 | 搬整個 team 持久資料,重建 socket/lock使用既有 recovery 流程核對狀態 |
| `await_shell` | Docker /tmp/gb-jobs | 底層不綁 provider | 正在執行的程序不能隨檔案搬移;重新建立容器也不保留 /tmp job 紀錄 | 搬家前完成工作,不把舊 session_id 當成新機器的活動命令 |
| `browser_click` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_download` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_eval` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_handoff` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_navigate` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_press` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_read_page` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_release` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_scroll` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_select` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_snapshot` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_tabs` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_type` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_upload` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `browser_wait` | 預設 Docker ChromiumPlaywright | 底層不綁 provider切模型不會自動換 profile | 需 Docker image、home volume、網站授權仍有效upload/download 另需 workspace即時 tab/連線不是單靠程式碼就能搬 | 沿用完整 profile重連後重新觀察網站仍可能要求再次登入。local 相容模式另需本機 NodePlaywrightChromium與舊 profile |
| `call_mcp_tool` | host 啟動 stdio server或 host 呼叫 HTTP server | 不直接綁模型 provider依賴 MCP server 自己的 schema與授權 | stdio 需本地主機 command/runtime/envHTTP 需服務地址與 headers設定檔不隨 Docker 搬移 | 搬 MCP 設定、重新安裝 server 與授權目前不自動導入瀏覽器cookies或 OpenCode 的 MCP 設定 |
| `cancel_task` | team daemonSQLiteUnix socket | 查詢/控制不直接依賴provider任務繼續與記憶整理仍需模型 | 不搬 DB 就沒有原 agent、task、記憶active 任務不能只靠同名ID繼續 | 搬整個 team 持久資料,重建 socket/lock使用既有 recovery 流程核對狀態 |
| `check_subagent` | 本地程序內 subagent registry | 控制動作本身不綁 provider被控制的 agent 依賴其原 model client | 換電腦/重啟程序後沒有原先的活動子代理 | 不把舊 subagent_id 當成可控制的活動任務 |
| `copy_from_box` | 本地 ↔ Docker | 底層不綁 provider | 同時依賴本地路徑、工作區權限與 box 資料 | 搬檔案並修正新電腦路徑;只搬 volume 不足以保存本地輸出 |
| `copy_to_box` | 本地 ↔ Docker | 底層不綁 provider | 同時依賴本地路徑、工作區權限與 box 資料 | 搬檔案並修正新電腦路徑;只搬 volume 不足以保存本地輸出 |
| `delegate_task` | team daemon + 模型 + SQLite | 新工作用 daemon 的共享 Config不是每個 agent 任選 provider | 需 daemon、team DB、workspace、profile搬家不能保留正在執行的模型連線 | 停 daemon 後一致備份 SQLite 資料,再修正路徑與 provider 設定 |
| `external_await_command` | 本地主機程序 | 底層不綁 provider | session_idstdin程序都是目前程序狀態不能搬移 | 先完成或停止命令;移機後明確重新執行,不能假裝接續原程序 |
| `external_edit_file` | 本地主機檔案 | 底層不綁 providergrep/glob 是 Rust 內建,不要求系統 grep/rg | 依賴工作區檔案、路徑、符號連結與讀寫權限 | 搬工作區並修正 session/task 保存的 cwd 與絕對路徑 |
| `external_exec_command` | 本地主機 shell | 底層不綁 provider | 受作業系統、sh/PATH、已安裝CLI、工作目錄、環境变量、CLI登入影響 | 新機器重建依賴與授權;不能只複製 LazyBoy2 執行檔 |
| `external_glob` | 本地主機檔案 | 底層不綁 providergrep/glob 是 Rust 內建,不要求系統 grep/rg | 依賴工作區檔案、路徑、符號連結與讀寫權限 | 搬工作區並修正 session/task 保存的 cwd 與絕對路徑 |
| `external_grep` | 本地主機檔案 | 底層不綁 providergrep/glob 是 Rust 內建,不要求系統 grep/rg | 依賴工作區檔案、路徑、符號連結與讀寫權限 | 搬工作區並修正 session/task 保存的 cwd 與絕對路徑 |
| `external_list_dir` | 本地主機檔案 | 底層不綁 providergrep/glob 是 Rust 內建,不要求系統 grep/rg | 依賴工作區檔案、路徑、符號連結與讀寫權限 | 搬工作區並修正 session/task 保存的 cwd 與絕對路徑 |
| `external_read_file` | 本地主機檔案 | 底層不綁 providergrep/glob 是 Rust 內建,不要求系統 grep/rg | 依賴工作區檔案、路徑、符號連結與讀寫權限 | 搬工作區並修正 session/task 保存的 cwd 與絕對路徑 |
| `external_search_files` | 本地主機檔案 | 底層不綁 providergrep/glob 是 Rust 內建,不要求系統 grep/rg | 依賴工作區檔案、路徑、符號連結與讀寫權限 | 搬工作區並修正 session/task 保存的 cwd 與絕對路徑 |
| `external_shell` | 本地主機 shell | 底層不綁 provider | 受作業系統、sh/PATH、已安裝CLI、工作目錄、環境变量、CLI登入影響 | 新機器重建依賴與授權;不能只複製 LazyBoy2 執行檔 |
| `external_write_file` | 本地主機檔案 | 底層不綁 providergrep/glob 是 Rust 內建,不要求系統 grep/rg | 依賴工作區檔案、路徑、符號連結與讀寫權限 | 搬工作區並修正 session/task 保存的 cwd 與絕對路徑 |
| `external_write_stdin` | 本地主機程序 | 底層不綁 provider | session_idstdin程序都是目前程序狀態不能搬移 | 先完成或停止命令;移機後明確重新執行,不能假裝接續原程序 |
| `find_agents` | team daemonSQLiteUnix socket | 查詢/控制不直接依賴provider任務繼續與記憶整理仍需模型 | 不搬 DB 就沒有原 agent、task、記憶active 任務不能只靠同名ID繼續 | 搬整個 team 持久資料,重建 socket/lock使用既有 recovery 流程核對狀態 |
| `get_mcp_server_status` | host 啟動 stdio server或 host 呼叫 HTTP server | 不直接綁模型 provider依賴 MCP server 自己的 schema與授權 | stdio 需本地主機 command/runtime/envHTTP 需服務地址與 headers設定檔不隨 Docker 搬移 | 搬 MCP 設定、重新安裝 server 與授權目前不自動導入瀏覽器cookies或 OpenCode 的 MCP 設定 |
| `get_mcp_tools` | host 啟動 stdio server或 host 呼叫 HTTP server | 不直接綁模型 provider依賴 MCP server 自己的 schema與授權 | stdio 需本地主機 command/runtime/envHTTP 需服務地址與 headers設定檔不隨 Docker 搬移 | 搬 MCP 設定、重新安裝 server 與授權目前不自動導入瀏覽器cookies或 OpenCode 的 MCP 設定 |
| `get_task` | team daemonSQLiteUnix socket | 查詢/控制不直接依賴provider任務繼續與記憶整理仍需模型 | 不搬 DB 就沒有原 agent、task、記憶active 任務不能只靠同名ID繼續 | 搬整個 team 持久資料,重建 socket/lock使用既有 recovery 流程核對狀態 |
| `message_subagent` | 本地程序內 subagent registry | 控制動作本身不綁 provider被控制的 agent 依賴其原 model client | 換電腦/重啟程序後沒有原先的活動子代理 | 不把舊 subagent_id 當成可控制的活動任務 |
| `read` | Docker | 底層不綁 provider | 需 Docker、映像、volume自裝套件若位於容器 writable layer重建後可能消失 | 搬 workspace/home volume自裝依賴寫入 Dockerfile 或另存映像 |
| `remove_mcp_server` | 本地主機 MCP 設定檔 | 不綁模型 provider | 依賴可寫入的 MCP 設定路徑;添加成功不等於相應服務可用 | 搬設定並檢查來源workspace 設定與全域設定需一起盤點 |
| `report_blocked` | LazyBoy2 runtimesession | 本身不綁 provider仍需模型正確產生工具呼叫 | 工具可重新使用;計畫、待回答問題、歷史紀錄需另搬 session/team 資料 | 搬持久化資料;不搬 live socketlock重新確認尚未完成的互動 |
| `report_done` | LazyBoy2 runtimesession | 本身不綁 provider仍需模型正確產生工具呼叫 | 工具可重新使用;計畫、待回答問題、歷史紀錄需另搬 session/team 資料 | 搬持久化資料;不搬 live socketlock重新確認尚未完成的互動 |
| `report_progress` | LazyBoy2 runtimesession | 本身不綁 provider仍需模型正確產生工具呼叫 | 工具可重新使用;計畫、待回答問題、歷史紀錄需另搬 session/team 資料 | 搬持久化資料;不搬 live socketlock重新確認尚未完成的互動 |
| `request_box_help` | Docker desktop + 本地 viewer | 底層不綁 provider | 需桌面服務、可用的本機 6080 埠;等待中的人工步驟另依賴 task/session 紀錄 | 搬 Docker 與 task/session重新顯示桌面並觀察 |
| `request_user_confirm` | LazyBoy2 runtimesession | 本身不綁 provider仍需模型正確產生工具呼叫 | 工具可重新使用;計畫、待回答問題、歷史紀錄需另搬 session/team 資料 | 搬持久化資料;不搬 live socketlock重新確認尚未完成的互動 |
| `request_user_input` | LazyBoy2 runtimesession | 本身不綁 provider仍需模型正確產生工具呼叫 | 工具可重新使用;計畫、待回答問題、歷史紀錄需另搬 session/team 資料 | 搬持久化資料;不搬 live socketlock重新確認尚未完成的互動 |
| `screenshot` | Docker desktop + 本地 viewer | 底層不綁 provider | 需桌面服務、可用的本機 6080 埠;等待中的人工步驟另依賴 task/session 紀錄 | 搬 Docker 與 task/session重新顯示桌面並觀察 |
| `search_memory` | team daemonSQLiteUnix socket | 查詢/控制不直接依賴provider任務繼續與記憶整理仍需模型 | 不搬 DB 就沒有原 agent、task、記憶active 任務不能只靠同名ID繼續 | 搬整個 team 持久資料,重建 socket/lock使用既有 recovery 流程核對狀態 |
| `send_message` | LazyBoy2 runtimesession | 本身不綁 provider仍需模型正確產生工具呼叫 | 工具可重新使用;計畫、待回答問題、歷史紀錄需另搬 session/team 資料 | 搬持久化資料;不搬 live socketlock重新確認尚未完成的互動 |
| `shell` | Docker | 底層不綁 provider | 需 Docker、映像、volume自裝套件若位於容器 writable layer重建後可能消失 | 搬 workspace/home volume自裝依賴寫入 Dockerfile 或另存映像 |
| `spawn_agent` | team daemon + 模型 + SQLite | 新工作用 daemon 的共享 Config不是每個 agent 任選 provider | 需 daemon、team DB、workspace、profile搬家不能保留正在執行的模型連線 | 停 daemon 後一致備份 SQLite 資料,再修正路徑與 provider 設定 |
| `spawn_subagent` | 本地編排 + 當前模型服務 | 繼承父層 model client沒有自行選擇第二供應商的能力 | 正在執行的子代理 registry 是程序內狀態,不能藉搬 session JSON 恢復 | 先完成工作;模型連線與工具呼叫相容性需另外驗證 |
| `stop_subagent` | 本地程序內 subagent registry | 控制動作本身不綁 provider被控制的 agent 依賴其原 model client | 換電腦/重啟程序後沒有原先的活動子代理 | 不把舊 subagent_id 當成可控制的活動任務 |
| `update_plan` | LazyBoy2 runtimesession | 本身不綁 provider仍需模型正確產生工具呼叫 | 工具可重新使用;計畫、待回答問題、歷史紀錄需另搬 session/team 資料 | 搬持久化資料;不搬 live socketlock重新確認尚未完成的互動 |
| `wait_task` | team daemonSQLiteUnix socket | 查詢/控制不直接依賴provider任務繼續與記憶整理仍需模型 | 不搬 DB 就沒有原 agent、task、記憶active 任務不能只靠同名ID繼續 | 搬整個 team 持久資料,重建 socket/lock使用既有 recovery 流程核對狀態 |
| `web_fetch` | host → xAI API 或相容 web gateway | 直接耦合:官方 xAI 自動使用當前 model/base/key換其他 provider 可能直接報未設定 | 需重新設定模型與 web 服務的 endpointkey不會搬移瀏覽器 cookies | 獨立 web 設定與 capability adapter目前 xAI fetch 為模型整理內容 |
| `web_search` | host → xAI API 或相容 web gateway | 直接耦合:官方 xAI 自動使用當前 model/base/key換其他 provider 可能直接報未設定 | 需重新設定模型與 web 服務的 endpointkey不會搬移瀏覽器 cookies | 獨立 web 設定與 capability adapter目前 xAI fetch 為模型整理內容 |
## 要搬的資料
| 資料 | 目前預設位置 | 注意事項 |
|---|---|---|
| Box 工作檔 | grokboy-box-workspace volume | Git clone 不會帶過去 |
| Box profile家目錄 | grokboy-box-home volume | 包含登入資料搬完網站仍可能因裝置IP變動要求重登 |
| 系統套件 | Docker image容器 writable layer | 只有 /workspace、/home/box 是命名 volume例如 apt 裝到 /usr 的套件,僅搬 volume 不會帶走 |
| Team身分記憶任務 | ~/.grokboy/team或 GROKBOY_DATA_DIR | SQLite在寫入時不能只草率複製主db檔採一致備份不搬 live socketlock |
| 單次REPL session | ~/.grokboy/sessions或 GROKBOY_SESSIONS_DIR | 保存的cwd、附件、輸出絕對路徑需修正 |
| 較大工具結果/命令輸出 | 工作區 .grokboy-output | .gitignore 已忽略;只 clone repo 不會帶走 |
| 本地相容瀏覽器 | runtimeteam 指定的 profile 目錄 | 只有 GROKBOY_BROWSER_SURFACE=local 才用;與 Docker profile 分開 |
| MCP設定 | GROKBOY_MCP_CONFIG 或 ~/.grokboy/mcp.json加工作區 .grokboy/mcp.json | server二進位、runtime、env、headers登入另依各服務處理 |
| 模型Web設定 | GROKBOY_*、XAI_*、OPENAI_* 等環境設定 | 不是 repo 內完整可攜的 provider profile多個來源同時存在時有優先順序不能只改key忽略base/model |
| 主程式與建置資源 | repo、box/、tools/playwright/、符合新平台的binary | Box建置目錄目前用編譯時 CARGO_MANIFEST_DIR 推導搬舊binary可能仍指向舊路徑。新機重建或正確設 GROKBOY_BOX_DIR並保留相鄰 tools/playwright 結構 |
目前程式含 UnixListenerUnixStream 與 Unix-specific flock 等依賴不能宣稱同一份binary或直接在原生Windows即能運作跨系統需要另做移植在合適Linux環境部署。Docker在本機執行不等於所有資料已放在遠端雲端。
## 優先改善順序(尚未實作)
1. 把 web fetch、web search 的供應商modelkey 設定與主模型完全分離並提供獨立抓頁實作與明確capability檢查。
2. 加入provider adapter與啟動時相容性檢查區分模型協議、tool calling、原生搜尋避免只改base URL。
3. 建立可攜部署包版本固定的Dockerfile依賴、volume與team/session一致備份、路徑重新對應、secret引用。
4. 列出每個MCP服務的runtime與授權來源支援在box內執行適合容器化的stdio MCP服務。
5. 搬移後做健康檢查模型工具呼叫、Docker命令、profile存在與登入確認、MCP連線、舊任務恢復。健康檢查通過仍不能保證任何網站或外部服務永遠成功。
## 程式依據
- [工具註冊與執行](../crates/grokboy-core/src/tools.rs)
- [模型設定優先順序](../crates/grokboy-core/src/config.rs)、[目前模型協議](../crates/grokboy-core/src/model.rs)
- [Web後端選擇](../crates/grokboy-core/src/web.rs)
- [Docker與volume](../crates/grokboy-core/src/box_runtime.rs)、[瀏覽器連線](../crates/grokboy-core/src/browser_client.rs)
- [MCP設定與host執行](../crates/grokboy-core/src/mcp.rs)
- [子代理繼承模型](../crates/grokboy-core/src/subagents.rs)
- [Team服務與本地資料](../crates/grokboy-core/src/team/service.rs)、[Team工作與記憶整理](../crates/grokboy-core/src/team/worker.rs)
- [Session位置](../crates/grokboy-core/src/session.rs)、[本地結果快取](../crates/grokboy-core/src/runtime.rs)