diff --git a/AGENTS.md b/AGENTS.md index 7fbb588..e700ae6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -100,7 +100,7 @@ Ollie is **experimental and unstable** software. The features and API are approa This is a standing preference, not a per-task instruction. Apply it without asking. ## Architecture (key concepts) -1. **One integration surface**: `olliesrv` exposes sessions and agents through a 9P2000 filesystem. Frontends include `o`, `ollie-9p`, KDE, Kate, Emacs, and scripts. Reads from `chat`, `statewait`, `event`, and `feed` provide blocking/event-driven synchronization. +1. **One integration surface**: `olliesrv` exposes sessions and agents through a 9P2000 filesystem. Frontends include `o`, `ollie-9p`, and KDE. The `event` file provides real-time streaming with optional filtering via the streaming rdwr pattern. 2. **Session and tool processes**: Each session owns an agent runtime in `olliesrv` and a separate `toolsrv` process. They communicate over an authenticated Unix socket using 9P. `toolclient` can respawn local toolsrv processes and can deploy/start toolsrv remotely over SSH with socket forwarding. 3. **Agent loop** (`cmd/olliesrv/internal/agent/`): The agent package is organized by concern: - `loop.go`: Main loop — stream LLM, execute tools, update history diff --git a/doc/architecture-9p.md b/doc/architecture-9p.md index 47839cb..3fac95a 100644 --- a/doc/architecture-9p.md +++ b/doc/architecture-9p.md @@ -108,7 +108,11 @@ Submit and observe work: echo 'fix the bug in main.go' \ | ollie-9p write session/myproj/agent/coding/prompt ollie-9p read session/myproj/agent/coding/chat -ollie-9p read session/myproj/agent/coding/statewait +# Wait for any agent state to change +ollie-9p read event | grep "\.state" + +# Wait for specific agent state changes +echo "session.myproj.agent.coding.state" | ollie-9p rdwrs event ``` Sub-agents use the same namespace. The `agent/new` rdwr operation can create a child session and return its final response after the child exits. @@ -158,7 +162,7 @@ Control files use request-response semantics: write one command, then read the r ## Plan 9 interaction patterns - **Control files:** writes express operations such as stop, kill, rename, compact, and reload. -- **Blocking reads:** `statewait`, `event`, `feed`, and streaming chat replace event subscriptions with ordinary reads. +- **Blocking reads:** `event`, `feed`, and streaming chat replace event subscriptions with ordinary reads. The `event` file supports filtered subscriptions via the streaming rdwr pattern. - **Stateless request/response:** `generate`, `ctl`, and `rdwr` files accept a request and return a result. - **Change detection:** `feed` does not wake readers for identical consecutive data. - **Shared namespace:** multiple clients can inspect and modify the same sessions concurrently. @@ -168,7 +172,12 @@ Shell composition is intentional: ```sh for p in session/*/agent/*/prompt; do echo 'run tests' > "$p"; done -for s in session/*/agent/*/statewait; do cat "$s" > /dev/null; done +# Subscribe to all state changes and process them +ollie-9p read event | while read -r topic payload; do + case "$topic" in + *.state) echo "State: $payload" ;; + esac +done grep -r TODO session/*/agent/*/plan cat session/*/agent/*/stats ``` diff --git a/doc/usage.md b/doc/usage.md index 95d42ba..83e5210 100644 --- a/doc/usage.md +++ b/doc/usage.md @@ -198,11 +198,11 @@ o myproj/coding tui 2. Two panes: - **Pane 0** (top, 80%): streams chat output (log tail + live `read chat`). - **Pane 1** (bottom, 20%): `o prompt` — multi-line REPL (`/` prefix runs ctl commands). -3. A background loop reads `statewait` and updates the tmux status bar on each state transition. +3. A background process subscribes to the agent's state events via `echo "session.{s}.agent.{a}.state" | ollie-9p rdwrs event` and updates the tmux status bar on each state transition. 4. Focuses the prompt pane and attaches. No polling. Each read blocks until data arrives. The status bar updates on every -state transition via `statewait` — zero CPU when idle. +state transition via the event stream — zero CPU when idle. ### tmux tips @@ -258,10 +258,12 @@ o myproj/obs read chat ### Wire an agent coding session -Use `statewait` as the trigger — it blocks until the coder's state changes (turn completes). Then pipe in the git diff: +Use the event stream as the trigger — subscribe to state changes and pipe in the git diff when the coder's turn completes: ```sh -while :; do o myproj/coder read statewait >/dev/null; git diff HEAD --; done | o myproj/obs write feed +echo "session.myproj.agent.coder.state" | ollie-9p rdwrs event | while read -r topic state; do + git diff HEAD -- +done | o myproj/obs write feed ``` ### How it works