# Execution Engine

所有進入點（TUI、`/v1/send`、`/v1/chat/completions`、Telegram、Discord、scheduler）走同一套啟動流程：`exec.Prepare` 從輸入比對 skill，接著 `exec.Start` 解析呼叫端指名的 skill、發出 skill 與模型選擇事件、透過 `ResolveAgent` 挑選模型與 fallback，再交給 `exec.Execute()`。`exec.Run` 已移除，改用 `exec.Prepare` + `exec.Start`。自 v1.1.0 起 reasoning 為 per-session 設定：設為 `auto`（或未設定）時，`ResolveAgent` 內的 selector 會依工作類型一併決定 reasoning 等級，全域的 `auto_reasoning` 開關已移除。自動路由永不選用 `pass` tier 模型 —— 即使訊息直接點名也一樣 —— 且這類模型不列入 fallback 清單；只有綁定該模型的 session，或呼叫端以明確的 `model` 指定時才會使用它。

`exec.Execute()` 執行主迴圈，最多 **256 次迭代**（`limits.max_tool_iterations`；v1.1.2 前為 128）。每次迭代：

1. 組裝 messages：`SystemPrompts` + `OldHistories`（排除 guardrail 拒絕）+ 摘要訊息（若有）+ `UserInput` + `ToolHistories` —— 依此順序 append，執行中途不改寫，讓 prompt cache 的前綴保持穩定
2. 對所選 provider 呼叫 `Agent.Send()`
3. 從 response 解析 `tool_calls`
4. 透過 `toolCall.go` 分派 tool call（three-pass concurrency，見下）
5. 將結果 append 至 `ToolHistories`；工具回傳的圖片接在該輪結果之後，以一則 `user` 訊息 append（v1.1.1 起 —— 先前是注入 `UserInput`，會改寫已快取的前綴）
6. 當無 `tool_calls` 剩餘或撞到迭代上限時停止

每次 `Send` 會在 SQLite `usage` 表寫入一列（模型、input / output / cache-write / cache-hit tokens、耗時）；自 v1.0.26 起該列另記錄此回應要求的 tool call ID。自 v1.1.0 起完成事件不再附帶 provider 剩餘額度，改由 `GET /v1/providers/quota` 依需求提供。

**無 inter-round delay** — rate-limit 保護來自 provider round-trip 延遲、per-model cooldown 以及各 tool 的 timeout。

## Three-pass tool concurrency

`toolCall.go` 將每一輪的 tool call 拆成三個序列 pass；只有 Pass 2 會 fan out：

| Pass | 模式 | 工作 |
|---|---|---|
| 1 — pre-flight | 序列 | 重複呼叫去重（`tool\|args` hash）、confirm gate、JSON-schema 驗證（自 v1.0.27 所有工具改帶完整 schema 後，stub-tool 短路已不再觸發） |
| 2 — execute | 對標記 `IsConcurrent` 的 tool 並行，同時最多 5 個（`MAX_CONCURRENT_TOOLS`，v1.0.20），其餘排隊；其餘 tool 序列 | `tools.Execute` |
| 3 — commit | 序列 | 落地 `sessionData.Tools` 與 `ToolHistories`、更新去重表、寫入結果 cache、發出 `EventToolResult` |

標記為 concurrent 的內建 tool（18 個）：`read_files`、`find_files`、`find_tools`、`file_history`、`chat_history`、`error_history`、`fetch_page`、`search_web`、`http_request`、`download_file`、`test_tool`、`calculate`、`subagents`、`list_chatbot`、`send_to_chatbot`、`reasoning_guide`、`html_template`、`write_todo`（v1.0.26 起；`find_note` 已於 v1.0.23 隨工具移除而退出此集合）。`generate_audio` 與 `generate_image` 不帶此旗標。`api_*` / `script_*` / `ext_*` tool 僅在自身定義宣告時才並行。`edit_file`、`run_command`、互動類 tool 以及 MCP tool 一律序列執行 —— v1.0.23 新增的並行 `run_command_readonly` 工具已於 v1.0.25 移除。

去重是「每次執行」而非「每個 session」：重複的 `tool|args` 組合直接回傳先前結果而不再執行，且 `edit_file` 會使涵蓋其寫入路徑的 `read_files` 項目失效。另有一層 30 分鐘的結果 cache 存於 ToriiDB（`db_0`），僅涵蓋 `fetch_page`、`search_web` 與 `http_request` 的 `GET` 呼叫。

## 跨 turn workdir 重置

Workdir 由每次請求提供，而非從歷史沿用：TUI 傳入自身的工作目錄、`/v1/send` 解析 `work_dir` 欄位、subagent 沿用或自行解析。`GetSession` 每次執行都以該目錄重建 system prompt，因此先前 turn 的 `cd` **不會**保留。

- **System prompt** — `Work directory: {{.WorkPath}}` 行，加上明確規則：`{{.WorkPath}}` 為本輪權威基準、忽略歷史中過期的提及，且每次 `run_command` 都已從該目錄開始

逐則訊息的 metadata header（包在每則 user message 外的時間戳與工作目錄）及其 TUI 剝除函式 `stripUserMetaHeader` 已移除；system prompt 的 `{{.WorkPath}}` 行是唯一的 workdir 錨點。

***

> [!NOTE]
> 本文件由 Claude 讀取完整原始碼後自動生成。
