fs: add /help ctl command — returns command reference

This commit is contained in:
Ollie Agent 2026-08-09 03:16:15 +02:00
parent 05e9c45495
commit 25924d0909
10 changed files with 42 additions and 89 deletions

View File

@ -53,11 +53,9 @@ Everything lives under `$XDG_CONFIG_HOME/ollie/` (default: `~/.config/ollie/`)
| Capability | How |
|---|---|
| **CLI** | `o` — unified namespace CLI: `read`, `write`, `ls`, `ctl`, `prompt`, `tui`, `env`, `generate`, `complete`, `route` |
| **CLI** | `o` — unified namespace CLI: `read`, `write`, `ls`, `ctl`, `prompt`, `tui`, `env`, `generate` |
| **Terminal TUI** | `o tui` — tmux layout, no widgets |
| **One-shot LLM** | `o generate "explain monads"` or `echo "prompt" \| o generate` |
| **Code completion** | `o complete '{"file":"main.go","prefix":"func "}'` or `echo '{"file":"..."}' \| o complete` |
| **Task routing** | `o route "implement login"` or `echo "task" \| o route` → `backend=X model=Y` |
| **Run an agent** | Create a session + agent via 9P — then connect with any frontend ([ellie](doc/ellie.md), KDE (GUI/KRunner/Kate), `o tui`) |
| **Remote execution** | Set `remote=user@host` in session config |
| **Agents** | Write a JSON config in `data/agents/` with agent prompt in `data/prompts/` |
@ -98,7 +96,7 @@ graph TB
TUI["o tui<br>(tmux + o read/ctl)"]
KDE[KDE GUI<br>ollie-9p native client]
KATE[Kate plugin]
EMACS[Emacs<br>ellie.el]
EMACS[Emacs<br>ellie.el · ollie-9p]
ACME[Plan 9 acme]
SCRIPTS[Shell scripts<br>o read · o ctl · o write]
end
@ -109,9 +107,8 @@ graph TB
subgraph "olliesrv"
P9[9P Filesystem<br>session/ namespace]
SM[Session Manager]
SESS[session.Session<br>tool server conn · persistence]
AG[agent.Agent<br>loop · compaction<br>prompt assembly]
ROUTE[Router<br>complete · generate · route]
TOOLS[toolsrv.Server<br>dynamic dispatch · sandbox]
end
@ -124,22 +121,19 @@ graph TB
end
subgraph Execution
LOCAL[Tool Scripts<br>loaded via ctl<br>· shell, reasoning_think<br>· file_*, lsp_*, memory_*<br>· gui_*, subagent_*]
REMOTE[ollie-remote<br>via SSH · no embedded tools]
EXEC[Tool Scripts<br>loaded via ctl<br>· shell, reasoning_think<br>· file_*, lsp_*, memory_*<br>· gui_*, subagent_*]
end
TUI & SCRIPTS & EMACS & ACME --> O
TUI & SCRIPTS & ACME --> O
O --> P9
KDE & KATE --> P9
P9 --> SM
SM --> AG
AG --> ROUTE
AG --> TOOLS
KDE & KATE & EMACS --> P9
P9 --> SESS
SESS --> AG
SESS -->|shared RPC conn| TOOLS
AG -->|streaming| OLL & OAI & ANT & COP & KIRO
TOOLS --> LOCAL
TOOLS -->|SSH| REMOTE
TOOLS --> EXEC
```
`olliesrv` exposes the agent runtime over a single surface: a 9P2000 filesystem.

View File

@ -614,15 +614,15 @@ Attaches to the last session if it still exists; otherwise creates a new one."
(defun ellie--complete-send (prefix suffix)
"Send a completion request with PREFIX and SUFFIX text.
Returns the raw response from the server."
(let ((payload (format "%s\n__COMPLETE_SEPARATOR__\n%s" prefix suffix)))
Returns the raw response from the server via /generate."
(let ((payload (format "Complete the code between the markers. Return ONLY the completion, no explanation.\n\n```\n%s<CURSOR>%s\n```" prefix suffix)))
(with-temp-buffer
(insert payload)
(let ((rc (call-process-region (point-min) (point-max)
"ollie-9p" t t nil "rdwr" "complete")))
"ollie-9p" t t nil "rdwr" "generate")))
(if (zerop rc)
(buffer-string)
(error "ollie-9p complete failed (exit %d)" rc))))))
(error "ollie-9p generate failed (exit %d)" rc))))))
(defun ellie-complete-at-point (&optional prefix suffix)
"Request a completion for the region around point.

View File

@ -27,7 +27,7 @@ set -euo pipefail
# ── Path classification ─────────────────────────────────────────
# Root-level entries (no context needed)
ROOT_ENTRIES="session bypass agents backends models help ctl eventwait complete generate route aliases tools"
ROOT_ENTRIES="session bypass agents backends models help ctl eventwait generate aliases tools"
# Session-level files (exist directly under session/{name}/)
SESSION_FILES="env paused connected ctl name id bypass"
@ -235,40 +235,6 @@ cmd_generate() {
printf '%s' "$prompt" | ollie-9p rdwr generate
}
cmd_complete() {
# Code completion via /complete (no session/agent needed)
# Usage: o complete '{"file":"...","prefix":"...","suffix":"..."}'
# echo '{"file":"..."}' | o complete
local json=""
if [[ $# -gt 0 ]]; then
json="$*"
else
json=$(cat)
fi
[[ -z "$json" ]] && { echo "usage: o complete <json>" >&2; exit 1; }
printf '%s' "$json" | ollie-9p rdwr complete
}
cmd_route() {
# Task routing via /route (no session/agent needed)
# Usage: o route "task description"
# echo "task" | o route
local task=""
if [[ $# -gt 0 ]]; then
task="$*"
else
task=$(cat)
fi
[[ -z "$task" ]] && { echo "usage: o route <task>" >&2; exit 1; }
printf '%s' "$task" | ollie-9p rdwr route
}
cmd_ctl() {
if [[ $# -lt 1 ]]; then
echo "usage: o ctl <command> [args...]" >&2
@ -518,10 +484,8 @@ Commands:
ls [path] List namespace entries
generate <prompt> One-shot generation (no session needed)
complete <json> Code completion (no session needed)
route <task> Route task to best model (no session needed)
ctl <cmd> [s] [a] Send control command (session or agent level)
ctl <cmd> [args] Send control command (rdwr: gets response)
prompt Interactive multi-line prompt REPL
log [-n N] Show last N lines of agent log (default 1000)
@ -562,8 +526,6 @@ case "$subcmd" in
write) cmd_write "$@" ;;
ls) cmd_ls "$@" ;;
generate) cmd_generate "$@" ;;
complete) cmd_complete "$@" ;;
route) cmd_route "$@" ;;
ctl) cmd_ctl "$@" ;;
prompt) cmd_prompt "$@" ;;
log) cmd_log "$@" ;;

View File

@ -64,7 +64,7 @@ for s in session/*/agent/*/prompt; do echo "run tests" > "$s"; done
for s in session/*/agent/*/statewait; do cat "$s" > /dev/null; done
# Grep all agent plans
grep -r "TODO" session/*/plan
grep -r "TODO" session/*/agent/*/plan
# Monitor costs
cat session/*/agent/*/cost
@ -78,7 +78,7 @@ with a 10-line shell script instead of a framework.
### Plan 9 patterns
- **`/net/dns` pattern** — `/complete`, `/generate`, `/route` are stateless
- **`/net/dns` pattern** — `/generate` and `ctl` are stateless
per-fid: write a request, read back the result
- **`ctl` files** — control operations (stop, kill, rename, compact) are writes
to a control file, not method calls
@ -95,21 +95,6 @@ cat main.go | ollie-9p rdwr generate
echo '{"prompt":"explain recursion"}' | ollie-9p rdwr generate
```
### `/complete` — code completion
Fill-in-the-middle:
```sh
echo '{"file":"main.go","prefix":"func ","suffix":""}' | ollie-9p rdwr complete
```
### `/route` — task routing
```sh
echo 'implement login page' | ollie-9p rdwr route
# backend=anthropic model=claude-sonnet-4-20250514
```
### Key files per agent
| File | Mode | Description |

View File

@ -205,7 +205,6 @@ Agent configs declare prompts as a JSON array of shell commands. Each command is
├── {name}/
│ ├── env session environment variables
│ ├── ctl session control (rdwr: kill, save, invalidate, pause, resume)
│ ├── plan session-scoped markdown checklist
│ ├── id immutable session UUID
│ ├── name mutable session name (write to rename)
│ ├── bypass per-session bypass policy

View File

@ -15,12 +15,12 @@ to its `name` file moves the entire directory subtree.
|------|---------|
| `/session/new` | Create an empty session (write `name=...`, read back name) |
| `/session/{name}/agent/new` | Create an agent within a session (write `cwd=... backend=...`) |
| `/session/{name}/plan` | Session-scoped markdown checklist |
| `/session/{name}/env` | Session environment variables |
| `/session/{name}/id` | Immutable session UUID |
| `/session/{name}/name` | Mutable session name (write to rename) |
| `/session/{name}/agent/{aname}/prompt` | Submit a prompt |
| `/session/{name}/agent/{aname}/chat` | Streaming chat log (blocking read) |
| `/session/{name}/agent/{aname}/chat` | Streaming chat (filtered text) |
| `/session/{name}/agent/{aname}/plan` | Agent-scoped markdown checklist |
| `/session/{name}/agent/{aname}/cfg` | Agent config KV: backend, model, agent, cwd, params |
| `/session/{name}/agent/{aname}/statewait` | **Blocking read** — returns when state changes |
| `/session/{name}/agent/{aname}/ctl` | Control commands: `stop`, `kill`, `compact`, `rn <name>` |
@ -32,16 +32,14 @@ Global request-response files provide stateless operations without sessions:
| File | Purpose |
|------|---------|
| `/generate` | Write prompt, read response (one-shot generation) |
| `/complete` | Write JSON `{file, prefix, suffix}`, read code completion |
| `/route` | Write task description, read `backend=X model=Y` recommendation |
Global namespaces are shared across all sessions:
| Path | Purpose |
|------|---------|
| `/session/idx` | Session index (id, state, cwd, backend, model) |
| `/session/{name}/plan` | Shared session-scoped checklist |
| `/session/{name}/agent/{aname}/chat` | Full chat history (searchable) |
| `/session/{name}/agent/{aname}/plan` | Agent checklist |
| `/session/{name}/agent/{aname}/chat` | Streaming filtered text |
## Spawning Agents
@ -84,7 +82,7 @@ flowchart TB
```
A root agent reasons about a task and delegates subtasks to workers. Workers
report back via their chat history; the conductor reads `/session/{name}/agent/{aname}/chat` after
report back via their log; the conductor reads `/session/{name}/agent/{aname}/log` after
`statewait` unblocks.
```sh

View File

@ -71,8 +71,6 @@ o read chat # stream chat output
| `o ls [path]` | List namespace entries |
| `o ctl <cmd> [args]` | Send control command (rdwr: gets response) |
| `o generate <prompt>` | One-shot generation (no session needed) |
| `o complete <json>` | Code completion |
| `o route <task>` | Route task to best model |
| `o tui` | Launch tmux TUI |
| `o env [session] [agent]` | Print export statements for context |

View File

@ -774,6 +774,23 @@ var agentCtlHandlers = map[string]rdwrHandler{
"systemprompt": func(ctx HandlerCtx, _ []string) ([]byte, error) {
return []byte(ctx.Agent.SystemPrompt() + "\n"), nil
},
"help": func(_ HandlerCtx, _ []string) ([]byte, error) {
return []byte(`stop — interrupt running agent
compact — compact context
clear — clear history
inject <text> — inject prompt mid-turn (overwrites pending)
agent [name] — show/switch agent profile
model [name] — show/switch model
models — list available models
tools — list loaded tools
tool_load <n> — load a tool
cwd [path] — show/change working directory
name [name] — show/rename agent
backend — show backend
systemprompt — show rendered system prompt
help — this message
`), nil
},
}
func readAgentStats(ctx HandlerCtx) ([]byte, error) {

2
kde

@ -1 +1 @@
Subproject commit ec3419aa4e710eb63d449be612995a4e4b6f46ca
Subproject commit c6da56310992d19049a60910955ab2b915a9e5aa

View File

@ -165,7 +165,7 @@ echo '{"file":"main.go","prefix":"func "}' | ollie-9p rdwr complete
| File | Mode | Purpose |
|---|---|---|
| `plan` | r/w | Session-scoped markdown checklist; survives compaction |
| `plan` | r/w | Agent-scoped markdown checklist; survives compaction |
| `env` | read | Session environment variables |
| `agent/` | dir | Agents within this session |