diff --git a/doc/9p.md b/doc/9p.md index d731268..320a1c4 100644 --- a/doc/9p.md +++ b/doc/9p.md @@ -6,38 +6,39 @@ but the raw filesystem is the foundation. ### Mounting +The olliesrv namespace can be mounted as a real filesystem using 9pfuse or +Plan 9's mount(1): + ```sh -ollie-9p mount unix!/tmp/ns.$USER.$DISPLAY/ollie ~/mnt/ollie +9pfuse 'unix!/tmp/ns.$USER.$DISPLAY/ollie' ~/mnt/ollie cd ~/mnt/ollie ls session/ ``` -Or connect remotely: +Or use `ollie-9p` for direct file operations without mounting: ```sh -ollie-9p mount tcp!server:9564 ~/mnt/ollie +ollie-9p ls session/ +ollie-9p read session/myproj/agent/coding/chat ``` ### Raw session operations ```sh # Create a session -echo "name={sname}" > session/new +echo "name=myproj" | ollie-9p write session/new + +# Create an agent +echo "name=coding cwd=/home/user/project" | ollie-9p write session/myproj/agent/new # Submit a prompt -echo "fix the bug in main.go" > session/{sname}/agent/{aname}/prompt +echo "fix the bug in main.go" | ollie-9p write session/myproj/agent/coding/prompt # Stream the response -cat session/{sname}/agent/{aname}/chat +ollie-9p read session/myproj/agent/coding/chat -# Check state -cat session/{sname}/agent/{aname}/state - -# Block until state changes -cat session/{sname}/agent/{aname}/statewait - -# Read offset (byte position after user prompt) -cat session/{sname}/agent/{aname}/offset +# Check state (blocks until change) +ollie-9p read session/myproj/agent/coding/statewait ``` ### Network transparency @@ -47,7 +48,7 @@ session, tool, and config value is accessible as if local: ```sh # From another machine: -9p -a 'tcp!server:5640' read session/{sname}/agent/{aname}/state +9p -a 'tcp!server:5640' read session/myproj/agent/coding/statewait ``` No SSH tunneling, no port forwarding, no API gateway. @@ -67,10 +68,10 @@ for s in session/*/agent/*/statewait; do cat "$s" > /dev/null; done grep -r "TODO" session/*/agent/*/plan # Monitor costs -cat session/*/agent/*/cost +cat session/*/agent/*/stats # Strip block markup from chat output -cat session/{sname}/agent/{aname}/chat | grep -vE '^\[\[\[.*' +cat session/myproj/agent/coding/chat | grep -vE '^\[\[\[.*' ``` Pipe agents into `awk`. Filter with `grep`. Schedule with `cron`. Orchestrate @@ -87,48 +88,171 @@ with a 10-line shell script instead of a framework. - **Multiplexing** — multiple clients mount the same server simultaneously, each with an independent view through per-fid state +--- + +## olliesrv namespace + +### Root (`/`) + +| File | Mode | Description | +|------|------|-------------| +| `backends` | r | Available backend names, one per line | +| `models` | r | Available models: `backendmodel` per line | +| `agents` | r | Available agent profiles, one per line | +| `tools` | r | Available tools: `namedescription` per line | +| `help` | r | Filesystem reference | +| `aliases` | r | ID-to-path table: `idpath` per line | +| `ctl` | rdwr | Server control: `invalidate`, `kill` | +| `eventwait` | r (blocking) | Blocks until a server event, returns event data | +| `generate` | rdwr | One-shot LLM generation (write prompt, read response) | +| `session/` | dir | Session management | + ### `/generate` — one-shot LLM ```sh echo 'summarize this repo' | ollie-9p rdwr generate -cat main.go | ollie-9p rdwr generate echo '{"prompt":"explain recursion"}' | ollie-9p rdwr generate ``` -### Key files per agent +### Session (`session/`) | File | Mode | Description | -|---|---|---| -| `prompt` | write | Queue a new turn | +|------|------|-------------| +| `session/new` | rdwr | Create session: write `name=X [remote=Y]`, read name | +| `session/idx` | r | Session index | + +### Session instance (`session/{sname}/`) + +| File | Mode | Description | +|------|------|-------------| +| `env` | r | Session environment (OLLIE_SESSION_ID, OLLIE_* vars) | +| `paused` | r | `true` or `false` | +| `ctl` | rdwr | Session control: `kill`, `save`, `invalidate`, `pause`, `resume` | +| `name` | r/w | Mutable session name (write to rename) | +| `id` | r | Immutable session UUID | +| `agent/` | dir | Agents within this session | + +### Agent directory (`session/{sname}/agent/`) + +| File | Mode | Description | +|------|------|-------------| +| `new` | rdwr | Create agent: write `name=X cwd=Y`, read agent ID | +| `idx` | r | Agent index | + +### Agent instance (`session/{sname}/agent/{aname}/`) + +| File | Mode | Description | +|------|------|-------------| +| `prompt` | w | Queue a new turn (write prompt text) | | `fifo` | r/w | Prompt queue (write=enqueue, read=dequeue) | -| `statewait` | read (blocking) | Blocks until state changes | -| `chat` | read (streaming) | Filtered text (no markers/fences) | -| `chat.raw` | read (streaming) | Full markup with block markers | -| `log` | read | Last 64KB of conversation (non-blocking) | -| `plan` | r/w | Scratch space for agent planning | -| `cfg` | r/w | Agent config (key=value) | -| `ctl` | rdwr | Control commands (write cmd, read response) | -| `stats` | read | Token usage, cost, context size (key=value) | -| `name` | r/w | Mutable agent name | -| `id` | read | Immutable agent UUID | +| `chat` | r (streaming) | Filtered text output (markers stripped) | +| `chat.raw` | r (streaming) | Full output with block markers | +| `statewait` | r (blocking) | Blocks until state changes, returns new state | +| `log` | r | Last 64KB of conversation (non-blocking snapshot) | +| `plan` | r/w | Scratch space for agent planning (survives compaction) | +| `cfg` | r/w | Agent config (read: key=value dump; write: `key=value`) | +| `ctl` | rdwr | Agent control (write command, read response) | +| `stats` | r | Token usage, cost, context size (key=value) | +| `name` | r/w | Mutable agent display name | +| `id` | r | Immutable agent UUID | +| `proc/` | dir | Background processes owned by this agent | +| `proc/top` | r | Process table: PID, TOOL, CMD | -### Background processes (`proc/`) +### Agent ctl commands -Toolsrv manages background processes. The agent queries toolsrv for the proc list. +All ctl commands are request-response: write the command, read the result. + +| Command | Description | +|---------|-------------| +| `stop` | Interrupt running agent | +| `compact` | Compact context window | +| `clear` | Clear conversation history | +| `kill` | Remove the agent | +| `inject ` | Inject text into context (alias: `i`) | +| `agent [profile]` | Show or switch agent profile | +| `model [name]` | Show or switch model | +| `models` | List available models | +| `backend` | Show current backend (read-only) | +| `name [name]` | Show or set display name | +| `cwd [path]` | Show or change working directory | +| `tools` | List loaded tools | +| `tool_load ` | Load a tool | +| `tool_unload ` | Unload a tool | +| `proc` | List background processes | +| `proc top` | Formatted process table | +| `proc term ` | Terminate a process | +| `proc kill ` | Force-kill a process | +| `proc out ` | Read process output | +| `proc dismiss ` | Dismiss a completed process | +| `systemprompt` | Dump the resolved system prompt | +| `help` | List available commands | + +--- + +## toolsrv namespace + +toolsrv is a separate 9P server spawned by olliesrv (one per session). It +handles tool execution in a sandboxed environment. + +### Root (`/`) | File | Mode | Description | -|---|---|---| -| `proc/list` | read | All processes: `pid\tstate\ttool` | -| `proc/new` | rdwr | Execute tool (blocking) | -| `proc/new.bg` | rdwr | Execute tool (background, returns pid) | -| `proc/{pid}/out` | read | Process output buffer | -| `proc/{pid}/stat` | read | Process status (key=value) | -| `proc/{pid}/ctl` | write | Control: `term`, `kill`, `signal `, `dismiss` | +|------|------|-------------| +| `ctl` | w | Control: `load `, `unload ` | +| `tools` | rdwr | Write agent ID, read tool list for that agent | +| `info` | r | Host info: `platform=`, `arch=` | +| `bypass/` | dir | Sandbox bypass approval broker | +| `proc/` | dir | Process execution and management | -When a background process exits, toolsrv pushes the complete output to the agent's prompt as a `` message: +### Bypass broker (`bypass/`) + +| File | Mode | Description | +|------|------|-------------| +| `pending` | r (blocking) | Blocks until a bypass request arrives; returns JSON | +| `resolve` | w | Resolve request: write `{"id":"...","approved":true}` or `{"id":"...","error":"..."}` | + +### Processes (`proc/`) + +| File | Mode | Description | +|------|------|-------------| +| `list` | r | All processes: `pidstatetool` | +| `new` | rdwr | Execute tool (blocking): write key=value payload, read result | +| `new.bg` | rdwr | Execute tool in background: write same, read pid | + +Payload format for `new` / `new.bg` (key=value lines, `\n` escaped in values): + +``` +tool=shell +agent= +cmd=go test ./... +args={"cmd":"go test ./..."} +``` + +### Process instance (`proc/{pid}/`) + +| File | Mode | Description | +|------|------|-------------| +| `out` | r | Process output buffer | +| `wait` | r (blocking) | Blocks until process exits, returns exit code | +| `stat` | r | Process status: running/exited, runtime, tool | +| `ctl` | w | Control: `term`, `kill`, `signal `, `dismiss` | + +When a background process exits, toolsrv pushes the complete output to the +agent's prompt as a `` message: ```xml output here -``` \ No newline at end of file +``` + +--- + +## Authentication + +olliesrv does not require authentication — any client that can reach the Unix +socket (or TCP port) can connect. + +toolsrv uses Tauth for authentication. The first client to connect sets the +shared secret; subsequent clients must provide the same secret. olliesrv +generates and stores this secret when spawning toolsrv.