# Runtime Layers

The runtime layers of Agenvoy: session storage, dashboard, pending routing, memory, scheduler, IPC and TUI, with the package that implements each.

| Layer | Package | Responsibility |
|---|---|---|
| Session | `internal/session` | history.json / summary / action.log / pending metadata / fsnotify observer; session config lives in the SQLite `session` table, and liveness is a ToriiDB online marker rather than a persisted `state` row |
| Dashboard | `page/` + `internal/runtime/routes` | Web UI embedded into the binary and served at `/`; `AGENVOY_PAGE_DIR` serves it from disk instead. On startup the daemon also installs a Chrome app launcher pointed at that URL — a bundle under `~/Applications` on macOS, a `.desktop` entry on Linux, a Windows shortcut under WSL — so the dashboard opens as its own window. It is written once and skipped thereafter; a missing Chrome only logs a warning. Since v1.0.1 it also runs offline: `/sw.js` precaches the embedded assets in a service worker and `/vendor/*` serves the third-party libraries from `~/.config/agenvoy/vendor/`, filled once at daemon startup by `internal/runtime/webapp.SyncAsset` and refreshed when the binary version changes |
| Pending | `internal/runtime/pending.go` | prefix-routed confirm/ask listener registry; per-front-end listener via `RegisterListener(prefix)` or `RegisterListenerMatch(prefix, match)`, claim via `PickNextMatch(prefix, accept)` |
| Memory | go-sqlkit (SQLite: `session`, `message_meta`, `messages` + FTS5, `action_history`, `file_history`, `usage`) + ToriiDB (`db_0` tool and provider-quota cache, `db_1` chat vectors, `db_2` error memory, `db_3` online markers) | full-text archive (trigram tokenizer), per-model usage (with the tool call ids of each reply since v1.0.26), file snapshots, semantic search, 90-day error memory. The `state` table was dropped in v0.35.3, when liveness moved to ToriiDB online markers; ToriiDB is reached over its own socket since v0.35.3 (now ToriiDB v0.7.0), so the `/v1/toriidb` HTTP gate is gone |
| Scheduler | `internal/runtime` scheduler + fsnotify watcher | cron / one-shot tasks bound to scheduler skills; hot-reload on `{tasks,crons}.json` change |
| IPC | `internal/runtime/ipc` | since v1.2.0, the daemon's Unix socket `~/.config/agenvoy/daemon.sock` (mode 0600, newline-delimited JSON). Client to daemon frames: `run`, `pending`, `cancel` (with `pause`), `steer`, `reply`, `mcp`; daemon to client: `event`, `ask`, `done`, `verify`, `workdir`, `mcp`. A run belongs to the connection that started it: closing that connection cancels the run and keeps its pending task. Confirmations and `ask_user` questions go only to the TUI window (window hash) that started the run; a restricted-path approval carries the password typed in the TUI, which the daemon checks with `sudo -S -v` |
| TUI | `internal/runtime/tui` | bubbletea inline-chat front-end; single-package by design. A client of the daemon over `internal/runtime/ipc`: it reconnects every 5 s and shows `Connecting` while offline, holding plain input, skills and `/pending` until connected, while local `/` commands still run. Removed in v1.2.0: running agents inside the TUI process was removed; use the daemon, which the TUI reaches over the socket |
