Files
tai/taicpp/docs/agent.md
T
2026-10-25 05:03:08 +01:00

49 lines
4.4 KiB
Markdown

# agent: Agent core, Tools, goal verifier, RAG stats, scheduler
Literal port of tai.py 1.44.2 (lines 9016-9335, 17071-20640, 40391-40460). Namespace `detz::agent`, sources in `src/agent`.
## Layout
| File | tai.py origin |
|---|---|
| `data.cpp` (generated) | `TOOL_SCHEMAS`, `TOOL_TAGS`, `CORE_TOOLS`, `LAZY_NAME_STOP`, prompt texts. Regenerate: `python3 -I src/agent/gen/gen_data.py > src/agent/data.cpp` |
| `data_html.cpp` (generated) | `html.entities.html5` for `html.unescape` |
| `agent.cpp/.h` | `Agent`, `select_tools`, `tool_catalog`, `compact_messages`, `resume_turn`, `update_models_command`, `default_runner`, mentions |
| `tools_*.cpp`, `tools.h` | `Tools` (61 handlers, `dispatch`, secrets, audit, box helpers) |
| `goal.cpp` | `Denied`, `AgentsFull`, `Approval`, `GoalFailure`, `GoalVerdict`, `GoalVerifier` |
| `rag.cpp` | `RetrievalEval`, `RagStats` |
| `registry.cpp` | `spawn_agent`, `poll_agent`, `list_agents`, `clear_agents`, `running_agents` |
| `scheduler.cpp` | `note_schedule_result`, `watch_schedule`, `schedule_running`, `scheduler_tick`, `run_scheduler_loop`/`start_scheduler` (class `Scheduler`) |
| `text.cpp` | `truncate`-family helpers, tags, `chunk_lines`, `spill_*`, tmux/history helpers, `html.unescape`, schedule helpers |
| `tui_control.cpp` | `grr_control_path`, `grr_control_call` (client only) |
| `zipfile.cpp` | `zipfile.extractall` (stored + deflate) for `install_skill` |
| `ports.h` | the narrow interfaces to everything this module does not own |
## Ports (declared here, implemented elsewhere)
`StorePort` (mirrors Python `Store` method names), `RuntimePort` (worker store), `ShellPort` (run_live, LiveStream, LaneBoard, box), `UiPort` (Spinner, Glow, markdown, diff; optional, plain fallbacks exist), `McpPort`, `SkillsPort`, `PlexerPort`, `TuiControlPort` (optional, built-in client otherwise), `OpsPort` (install, release, sysinfo, speech), `SchedulerDbPort`. Unwired required ports raise `PortNotWired`, shown to the model as `error: port not wired: X`. Plexer unwired means "no session", exactly like no tmux.
## Behaviour notes
- All string lengths and slices are code points (`detz::py`, `src/llm/py.h`).
- Integers beyond int64 clamp in `int()` conversions (Python is unbounded); JSON keeps big ints verbatim.
- `html.unescape`, `str.lower/upper` (including final sigma) use tables generated from Python.
## Verification (what was actually run)
- `tests/agent_diff.py`: 7601 cases per seed (seeds 1-4 run, 0 mismatches). Includes the full `json.dumps(TOOL_SCHEMAS)` byte comparison, `select_tools` on 24 prompts plus fuzz, `tool_catalog`, all prompt texts, goal verdicts, CLI output parsers, history cleanup, tag helpers, html/url helpers, schedule helpers, candidate ordering of `ChatClient`.
- `tests/agent_e2e.py`: 43 scripted conversations through the real Agent loop in both programs (messages, HTTP request bodies, store events, audit rows identical). Covers file tools, shell, secrets, schedules, bots/mentions, compaction, retries, 400 tool fallback, ask_user, approval deny, verify loop, remember, web_fetch/search, fork/poll, streaming quirks, deadline.
- `tests/agent_sched.py`: `scheduler_tick` against a real sqlite vault.
- Build for these tests: compile `src/llm/*.cpp src/agent/*.cpp tests/agent_*.cpp` with `-lcurl -lpthread` (see wiring doc).
## Not verified / gaps (honest list)
- Tools needing FTS or other modules were only checked on argument validation paths: `search`, `record_search`, `graph_*`, `tags`, `recall`, `audit` search, `export_terminal_log`.
- Port-backed tools (MCP, skills install/create, plexer, install, release, sysinfo, speak, listen, sandbox `box_*` paths, LaneBoard) are ported but no test drives a real implementation: the ports are fakes or unwired.
- `RagStats`/`RetrievalEval` compile and follow the Python line by line but have no differential test (needs a real vault).
- Interactive tty paths (`ask_approval` console branch with `Denied` guidance, `shell_ask` getpass) are unexercised.
- urllib error strings are approximated from libcurl codes (`<urlopen error [Errno 111] Connection refused>` etc.).
- Muse session map/locking and CLI runners (`muse_run`, grok, claude, codex, gemini, opencode) are ported; only their output parsers are differentially tested, the process runners were not run against the real CLIs.
- `zipfile`: bzip2/lzma members unsupported.
- `str.lower` final-sigma uses derived property sets; `repr` printable test is approximated for exotic code points.