docs: rewrite 9p.md to match current olliesrv and toolsrv namespaces

This commit is contained in:
Levi Neely 2026-08-12 18:16:55 +02:00
parent c2df612da5
commit 79a7cc68c7
1 changed files with 166 additions and 42 deletions

208
doc/9p.md
View File

@ -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: `backend<tab>model` per line |
| `agents` | r | Available agent profiles, one per line |
| `tools` | r | Available tools: `name<spaces>description` per line |
| `help` | r | Filesystem reference |
| `aliases` | r | ID-to-path table: `id<tab>path` 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 <text>` | 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 <name>` | Load a tool |
| `tool_unload <name>` | Unload a tool |
| `proc` | List background processes |
| `proc top` | Formatted process table |
| `proc term <pid>` | Terminate a process |
| `proc kill <pid>` | Force-kill a process |
| `proc out <pid>` | Read process output |
| `proc dismiss <pid>` | 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 <N>`, `dismiss` |
|------|------|-------------|
| `ctl` | w | Control: `load <agentID> <tool>`, `unload <agentID> <tool>` |
| `tools` | rdwr | Write agent ID, read tool list for that agent |
| `info` | r | Host info: `platform=<os>`, `arch=<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 `<system-proc-complete>` 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: `pid<tab>state<tab>tool` |
| `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=<agentID>
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 <N>`, `dismiss` |
When a background process exits, toolsrv pushes the complete output to the
agent's prompt as a `<system-proc-complete>` message:
```xml
<system-proc-complete id="1" cmd="echo test" exit="0">
output here
</system-proc-complete>
```
```
---
## 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.