文件 v0.28.1

架構

Agenvoy 整體如何組合的高階視角。各模組圖表、序列流程與 tool-dispatch 狀態機請跳至各主題專頁。

概覽

graph TB
    subgraph Entry["Entry · cmd/app"]
        App["agen model · session · mcp · stop · update<br/>make app · TUI + Discord + Telegram + REST<br/>make cli / run · single-shot"]
    end

    subgraph Engine["Engine · internal/agents/exec"]
        Run["exec.Run<br/>:bot → MatchExternal → MatchSkillCall"]
        Execute["exec.Execute · ≤128 iterations<br/>3-pass parallel tool calls"]
        Sub["ExecWithSubagent<br/>in-process · ctx inheritance"]
    end

    subgraph Pending["Pending · internal/runtime"]
        Reg["Prefix-routed listener registry<br/>per-entry buffered=1 reply ch<br/>TUI/CLI listen '' · Telegram listens 'tg-'"]
    end

    subgraph Providers["LLM Providers · 9"]
        P["Claude · OpenAI · Codex · Gemini<br/>Copilot · Nvidia · Compat"]
    end

    subgraph Tools["Tool Subsystem"]
        T["File · Web · Git · API · Script<br/>run_skill · invoke_subagent<br/>ask_user · scheduler · memory"]
        MCP["MCP Adapter<br/>stdio · HTTP/SSE"]
        Ext["External CLI<br/>codex · claude · copilot · gemini"]
    end

    subgraph Security["Security · go-pkg/sandbox"]
        S["bwrap (Linux) / sandbox-exec (macOS)<br/>filesystem.Policy · DeniedMap"]
    end

    subgraph Session["Session · internal/session"]
        SL["bot.md · status.json · action.log<br/>observer · fsnotify watch"]
    end

    subgraph Memory["Memory · ToriiDB"]
        M["DBSessionHist · DBSessionSummary<br/>error_memory · 90d TTL<br/>OpenAI text-embedding-3-small"]
    end

    subgraph Kura["KuraDB · daemon-managed child"]
        K["/usr/local/bin/kura<br/>endpoint @ ~/.config/kuradb/endpoint<br/>3-strike health check · 5s backoff<br/>list_rag · search_rag"]
    end

    App --> Run
    Run --> Execute
    Execute -->|invoke_subagent| Sub
    Sub --> Execute
    Execute -->|Send| Providers
    Execute -->|tool calls| Tools
    Tools --> MCP
    Tools --> Ext
    Tools --> Security
    Tools -.->|list_rag · search_rag<br/>per-turn excluded if endpoint absent| Kura
    Execute <-->|confirm/ask| Pending
    Sub <-->|subagent ask_user| Pending
    Execute <--> Memory
    Execute <--> Session
    App -.->|spawn + healthcheck| Kura

分層

套件 職責
Entry cmd/app argv dispatch(model / session / mcp / cli / run / stop / update);初始化 env、sandbox、filesystem policy、MCP manager
Runtime singleton internal/runtime server-mode UID lock;啟動時對先前 server 送 SIGTERM
Engine internal/agents/exec iteration loop;tool dispatch;provider routing
Subagent internal/agents/subagent in-process 子 agent(無 HTTP)
External agents internal/agents/external one-shot subprocess wrapper(codex / claude / copilot / gemini)
Providers internal/agents/provider/<name> 統一的 Agent.Send() 介面
Tools internal/tools + adapters built-in / API / script / MCP tool 定義
Sandbox go-pkg/sandbox OS-native 隔離,單一入口 Wrap()
Filesystem go-pkg/filesystem(+ reader/)+ internal/filesystem policy-aware 寫入;ToriiDB pathing
Session internal/session bot.md / status.json / action.log / fsnotify observer
Pending internal/runtime/pending.go prefix-routed 的 confirm/ask listener registry;per-runtime listener 透過 RegisterListener(prefix),透過 PickNextFor(prefix) 認領
Memory ToriiDB(DBSessionHist / DBSessionSummary / error_memory)+ go-sqlkit(SQLite FTS5 archive) semantic search + 90 天 TTL + 全文持久化 archive
Scheduler internal/runtime/scheduler.go(+ runtime.SchedulerWatcher fsnotify) 綁定 scheduler skill 的 cron / one-shot 任務;{tasks,crons}.json 變更時 hot-reload
KuraDB internal/runtime/kuradb/kuradb.go / run.go)+ internal/runtime/kuradb/tool/ RAG provider 子進程;daemon-managed spawn + 3-strike health check;endpoint 缺失時 per-turn 動態排除 tool
TUI internal/runtime/tui bubbletea inline-chat 前端;設計上為單一 package

橫切原則

TUI 設計取捨

引 pardn chiu:「bubbletea 的設計不是要拆成互相 reference 的獨立模組——拆了會讓 lifecycle 一團亂。我現在沒餘力處理它。」 此模組刻意保持不切分。

TUI 住在單一 package(internal/runtime/tui),拆成子 package。internal/runtime/tui/ 底下每個檔案都遵循此原則。

為何選 bubbletea(而非 tview / tcell)

先前的 TUI 用 rivo/tview,被替換的原因:

代價是 bubbletea 為 The Elm Architecture 的 Go port——其 tea.Model 介面設計上即為 monolithic。

為何單一 package

tea.Model 要求 Update(tea.Msg) (tea.Model, tea.Cmd) 為 model type 上的 method。Method 必須與 type 住在同一 package。這強制:

真正 Go 風格的 TUI 會建 per-domain widget package(各自持有 state struct、render method 與 event handler),bubbletea 僅作為 event loop。該重構為 600-800 LOC 的重寫,切成 4 個 phase。對目前約 1.1k LOC、由單一開發者維護的 TUI,收益不足以正當化成本。

何時重新檢視

任一條件成立時,切換為 per-domain widget package:


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

EN