move tool catalog to toolsrv: add /all file, tools_all ctl command

- Remove /tools from olliesrv root (toolsrv owns all tool state)
- Add /all file to toolsrv namespace (lists all available tools on disk)
- Add ListAllTools() to toolsrv client library
- Add tools_all ctl command to agent (reads from toolsrv/all)
- Update system prompt with tools_all usage
This commit is contained in:
Levi Neely 2026-08-13 21:58:08 +02:00
parent 16e54d1f03
commit fd4a3afa4f
4 changed files with 36 additions and 16 deletions

View File

@ -16,7 +16,6 @@ import (
"ollie/cmd/olliesrv/internal/backend"
"ollie/cmd/olliesrv/internal/session"
"ollie/paths"
"ollie/toolsrv"
"ollie/virtfs"
)
@ -95,20 +94,6 @@ func buildTreeSpec(cfg *Config) virtfs.FsNodeDecl {
return []byte(sb.String()), nil
}),
),
virtfs.FileNode("tools", 0444,
virtfs.Doc("Available tools. Format: name<spaces>description per line."),
virtfs.Read(func() ([]byte, error) {
tools := toolsrv.DiscoverTools()
if len(tools) == 0 {
return []byte("(no tools found)\n"), nil
}
var sb strings.Builder
for _, ti := range tools {
fmt.Fprintf(&sb, "%-24s %s\n", ti.Name, ti.Description)
}
return []byte(sb.String()), nil
}),
),
virtfs.FileNode("ctl", 0666,
virtfs.Doc("Server control. Write: 'invalidate', 'kill'"),
virtfs.Request(func(_ context.Context, data []byte) ([]byte, error) {
@ -619,6 +604,13 @@ func buildAgentChildren(a *agent.Agent, s *session.Session) []virtfs.FsNodeDecl
a.RefreshTools()
return []byte(args[0] + "\n"), nil
},
"tools_all": func(args []string) ([]byte, error) {
ts := a.ToolServer()
if ts == nil {
return nil, fmt.Errorf("no tool server")
}
return ts.ListAllTools()
},
"tool_unload": func(args []string) ([]byte, error) {
if len(args) == 0 {
return nil, fmt.Errorf("tool_unload requires a tool name")

View File

@ -32,6 +32,12 @@ Tools are loaded at startup. Additional tools can be loaded at runtime via ctl:
echo "tool_load file_read" | ollie-9p write session/$OLLIE_SESSION_ID/agent/$OLLIE_UNAME/ctl
```
To list all available tools (not just loaded ones):
```bash
echo "tools_all" | ollie-9p rdwr session/$OLLIE_SESSION_ID/agent/$OLLIE_UNAME/ctl
```
Once loaded, a tool is a first-class function — call it directly by name.
**Important**: Use native tool calls, not shell. For example:
@ -122,7 +128,7 @@ Your world model is a 9P filesystem. Your session ID is `${OLLIE_SESSION_ID}`. U
| `chat.raw` | read | Full conversation with block markers |
| `statewait` | read | Blocks until state changes; returns new value |
| `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 |
| `ctl` | rdwr | Control: stop, compact, clear, inject, agent, model, tools, tools_all, tool_load, tool_unload, cwd, name |
| `stats` | read | Usage, cost, context size |
| `tools` | r/w | Write: load tool by name. Read: list loaded tools. |
| `proc/` | dir | Detached background processes |

View File

@ -15,6 +15,7 @@ import (
"ollie/cmd/toolsrv/internal/bypass"
"ollie/cmd/toolsrv/internal/registry"
"ollie/toolsrv"
"ollie/virtfs"
)
@ -125,6 +126,17 @@ func Spec(srv *Server) virtfs.FsNodeDecl {
return []byte(srv.Fs.HandleToolsRequest(agentID)), nil
}),
),
virtfs.FileNode("all", 0444,
virtfs.Doc("All available tools on disk: name<tab>description per line"),
virtfs.Read(func() ([]byte, error) {
tools := toolsrv.DiscoverTools()
var sb strings.Builder
for _, ti := range tools {
fmt.Fprintf(&sb, "%s\t%s\n", ti.Name, ti.Description)
}
return []byte(sb.String()), nil
}),
),
virtfs.FileNode("info", 0444,
virtfs.Doc("Host info: platform, arch"),
virtfs.Read(func() ([]byte, error) {

View File

@ -245,6 +245,16 @@ func (c *Conn) LoadTool(name string) error {
return err
}
// ListAllTools reads the full catalog of available tools from toolsrv.
func (c *Conn) ListAllTools() ([]byte, error) {
fid, err := c.fsys.Open("all", plan9.OREAD)
if err != nil {
return nil, err
}
defer fid.Close()
return io.ReadAll(fid)
}
// UnloadTool unloads a tool by name.
func (c *Conn) UnloadTool(name string) error {
fid, err := c.fsys.Open("ctl", plan9.OWRITE)