From 86fbc90b436006a494ec4764d8cfcea33556e552 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Tue, 6 Oct 2026 12:44:02 +0200 Subject: [PATCH] server: remove statewait file, use event stream instead The event stream with filtering replaces statewait: - echo filter | rdwrs event Removed: - statewait file from agent namespace - All non-historical references in docs and code The state file remains for simple polling reads. --- README.md | 5 +++-- cmd/olliesrv/internal/agent/state.go | 2 +- cmd/olliesrv/internal/fs/doc.go | 5 +++-- cmd/olliesrv/internal/fs/spec.go | 7 ------- cmd/olliesrv/internal/prompts/system_prompt.md | 2 +- doc/architecture-9p.md | 2 +- doc/architecture-ide.md | 5 +++-- doc/architecture.md | 4 ++-- kde/gui/lib9pclient.h | 2 +- kde/gui/lib9pstreamer.cpp | 2 +- kde/gui/ollie9pclient.cpp | 2 +- 11 files changed, 17 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index cc284eb..5422437 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,8 @@ session/ ├── cfg configuration ├── ctl control commands ├── state current state - ├── statewait block until state changes + ├── state current state (idle, calling, thinking, paused) + ├── status human-readable status ├── prompt submit a prompt ├── peer/ write to peer/{name} to message a peer agent ├── chat conversation history @@ -106,7 +107,7 @@ Persistent memory is provided by [OptMem](https://github.com/VictorTaelin/OptMem ## Frontends -Shell scripts, Acme, KDE components, and other clients create sessions, write prompts, and read files such as `chat`, `statewait`, `context`, and `feed`. They do not embed provider, tool, or agent-loop logic. +Shell scripts, KDE components, and other clients create sessions, write prompts, and read files such as `chat`, `state`, and `feed`. They subscribe to state changes via the `event` stream. They do not embed provider, tool, or agent-loop logic. See [`doc/architecture-ide.md`](doc/architecture-ide.md) for integrating Ollie with an editor or IDE. diff --git a/cmd/olliesrv/internal/agent/state.go b/cmd/olliesrv/internal/agent/state.go index eed94f4..6967782 100644 --- a/cmd/olliesrv/internal/agent/state.go +++ b/cmd/olliesrv/internal/agent/state.go @@ -2,7 +2,7 @@ // // The agent state tracks execution progress: idle, running, completed, error. // WaitChange blocks until a field changes, enabling 9P clients to observe -// state transitions via statewait. +// state transitions via the event stream. package agent diff --git a/cmd/olliesrv/internal/fs/doc.go b/cmd/olliesrv/internal/fs/doc.go index 2479e0d..c319828 100644 --- a/cmd/olliesrv/internal/fs/doc.go +++ b/cmd/olliesrv/internal/fs/doc.go @@ -27,13 +27,14 @@ // // prompt - submit prompt (write) // chat - conversation history (streaming read) -// statewait - block until state changes +// state - current agent state +// status - human-readable status // plan - agent's plan (survives compaction) // ctl - agent control commands // // # Blocking Reads // -// Files like statewait and event block until their condition is met. +// Files like event block until their condition is met. // This is the primary coordination mechanism — clients read these files // in a loop to react to state changes. // diff --git a/cmd/olliesrv/internal/fs/spec.go b/cmd/olliesrv/internal/fs/spec.go index 1651bdb..32bde9b 100644 --- a/cmd/olliesrv/internal/fs/spec.go +++ b/cmd/olliesrv/internal/fs/spec.go @@ -883,13 +883,6 @@ func buildAgentChildren(a *agent.Agent, s *session.Session) []virtfs.FsNodeDecl return []byte(a.State() + "\n"), nil }), ), - virtfs.FileNode("statewait", 0444, - virtfs.Doc("Blocks until state changes; returns new value"), - virtfs.BlockOnce(func() ([]byte, string, error) { - st := a.State() - return []byte(st + "\n"), st, nil - }, a.SignalCh), - ), virtfs.FileNode("status", 0444, virtfs.Doc("Human-readable status: current activity and elapsed time"), virtfs.Read(func() ([]byte, error) { diff --git a/cmd/olliesrv/internal/prompts/system_prompt.md b/cmd/olliesrv/internal/prompts/system_prompt.md index 9f19006..6795eff 100644 --- a/cmd/olliesrv/internal/prompts/system_prompt.md +++ b/cmd/olliesrv/internal/prompts/system_prompt.md @@ -191,7 +191,7 @@ Use `client_9p` for all 9P operations. Your session ID is `${OLLIE_SESSION_ID}`. | `fifo` | r/w | Prompt queue. Write: enqueue. Read: dequeue. | | `chat` | read | Conversation (filtered text, streamable) | | `chat.raw` | read | Full conversation with block markers | -| `statewait` | read | Blocks until state changes; returns new value | +| `state` | r/w | Current state; subscribe via event stream | | `cfg` | r/w | Agent config (key=value: backend, model, cwd, temperature, etc.) | | `ctl` | rdwr | Control: stop, compact, clear, inject, agent, model, tools, tool_load, tool_unload, cwd, name, peeradd, peerdel, peers, proc | | `peer/` | dir | Peer agent links. Write to `peer/{name}` to send a message to that peer. | diff --git a/doc/architecture-9p.md b/doc/architecture-9p.md index 3fac95a..887ded1 100644 --- a/doc/architecture-9p.md +++ b/doc/architecture-9p.md @@ -90,7 +90,7 @@ echo "name=coding cwd=$PWD" | ollie-9p write session/myproj/agent/new | `agent/{aname}/feed` | r/w | Change-detecting input stream. | | `agent/{aname}/chat` | r | Filtered streaming chat output. | | `agent/{aname}/chat.raw` | r | Full streaming output with markers. | -| `agent/{aname}/statewait` | r | Blocking state-change read. | +| `agent/{aname}/state` | r | Current agent state (idle, calling, thinking, paused). | | `agent/{aname}/log` | r | Conversation snapshot. | | `agent/{aname}/plan` | r/w | Persistent planning scratch space. | | `agent/{aname}/cfg` | r/w | Agent configuration. | diff --git a/doc/architecture-ide.md b/doc/architecture-ide.md index d9b87ae..33bebed 100644 --- a/doc/architecture-ide.md +++ b/doc/architecture-ide.md @@ -9,7 +9,8 @@ editor or IDE ├─ file, selection, cursor, project, or diff └─ 9P client → agent/.../prompt ├─ chat / chat.raw - ├─ statewait + ├─ state + ├─ status └─ ctl ``` @@ -49,7 +50,7 @@ The editor does not need to display agent output or reload files itself. Use the | Operation | 9P integration | |---|---| | Explain file or selection | Write a read-only prompt; read `chat`. | -| Fix, refactor, document, or add tests | Write a mutating prompt; read `statewait`; reload the buffer. | +| Fix, refactor, document, or add tests | Write a mutating prompt; subscribe to state events; reload the buffer on completion. | | Review a diff | Send the diff as fenced `diff` context. | | Inline completion | Send a bounded prefix/suffix request to root `generate`. | | Agent control | Write a command to `ctl`. | diff --git a/doc/architecture.md b/doc/architecture.md index 52b4af9..21d32ce 100644 --- a/doc/architecture.md +++ b/doc/architecture.md @@ -22,7 +22,7 @@ flowchart TB The daemon constructs an `fs.Tree`. The tree is the session collection; there is no separate manager abstraction. Session operations are package functions over the tree. A session owns its agents, context, cancellation, and lifecycle. An agent owns history and runs the model/tool loop. -The daemon exposes the 9P namespace directly. Reads and writes are the protocol: writing `session/new` creates a session, writing an agent's `prompt` submits work, reading `chat` observes history, and reading `statewait` blocks until a state transition. +The daemon exposes the 9P namespace directly. Reads and writes are the protocol: writing `session/new` creates a session, writing an agent's `prompt` submits work, reading `chat` observes history, and subscribing to the `event` stream monitors state transitions. ### Agent loop @@ -43,7 +43,7 @@ Ollie deliberately does not build the following into the agent runtime: - **Native MCP client support.** Use executable or metadata-only tools. An external bridge can invoke an MCP client when required. - **Embedded tool frameworks.** Tools live outside the agent loop; toolsrv owns discovery, loading, execution, sandboxing, and process state. See [`architecture-tools.md`](architecture-tools.md) and [`architecture-toolsrv.md`](architecture-toolsrv.md). - **Plan-and-execute workflow engines.** Ollie does not own planners, task graphs, schedulers, retries, compensation, or durable workflow state. A system such as [Beads](https://github.com/steveyegge/beads) can expose those capabilities through a tool. -- **External coordination protocols.** Ollie does not expose a workflow engine, actor framework, master coordinator, or public message bus. It does have an internal session event bus for observers. Inter-agent communication uses peer links (`peer/` directory) for topology-controlled messaging within a session. External coordination uses sessions, agents, `prompt`, `chat`, `statewait`, `feed`, and `ctl`. +- **External coordination protocols.** Ollie does not expose a workflow engine, actor framework, master coordinator, or public message bus. It does have an internal session event bus for observers. Inter-agent communication uses peer links (`peer/` directory) for topology-controlled messaging within a session. External coordination uses sessions, agents, `prompt`, `chat`, `event`, `feed`, and `ctl`. - **Separate frontend control planes.** UIs, editor integrations, shell clients, and automation are 9P clients. They do not maintain a parallel session store or frontend-specific API. See [`architecture-9p.md`](architecture-9p.md). - **Distributed agent state.** Remote execution moves toolsrv and tool execution, not the agent loop, prompts, history, or model calls. See [`architecture-remote.md`](architecture-remote.md). - **A competing memory store.** [OptMem](https://github.com/VictorTaelin/OptMem) owns persistent memory; Ollie exposes it through tools. diff --git a/kde/gui/lib9pclient.h b/kde/gui/lib9pclient.h index 9a4a7f8..8d7525f 100644 --- a/kde/gui/lib9pclient.h +++ b/kde/gui/lib9pclient.h @@ -45,7 +45,7 @@ public: bool mkdir(const QString &path); bool rename(const QString &oldPath, const QString &newName); - // Streaming API - for continuous reads (chat, statewait, etc.) + // Streaming API - for continuous reads (chat, event, etc.) int open(const QString &path); // Returns fid handle, -1 on error int readFid(int fid, char *buf, int bufLen); // Returns bytes read, 0 on EOF, -1 on error void closeFid(int fid); diff --git a/kde/gui/lib9pstreamer.cpp b/kde/gui/lib9pstreamer.cpp index c8da6d4..74f1216 100644 --- a/kde/gui/lib9pstreamer.cpp +++ b/kde/gui/lib9pstreamer.cpp @@ -70,7 +70,7 @@ void Lib9pStreamer::Worker::run() return; } if (n == 0) { - // EOF — normal for statewait/event after returning data + // EOF — normal for event stream after returning data emit finished(true, QString()); return; } diff --git a/kde/gui/ollie9pclient.cpp b/kde/gui/ollie9pclient.cpp index 6e7e6b1..8df7619 100644 --- a/kde/gui/ollie9pclient.cpp +++ b/kde/gui/ollie9pclient.cpp @@ -64,7 +64,7 @@ void Ollie9pClient::setActiveSessionId(const QString &id) qDebug() << "setActiveSessionId" << id << "prev session" << m_activeSessionId << "prev agent" << m_agentId; // Session selection must be side-effect free for per-agent streams. // Even re-selecting the same session should clear agent selection and stop - // statewait/chat so the UI can stay in a pure "session selected" state. + // chat so the UI can stay in a pure "session selected" state. stopStreams(); m_activeSessionId = id; m_agentId.clear();