fs: remove proc/ proxy, add tool_unload to agent ctl

- Remove session/{sname}/agent/{aname}/proc/ tree (redundant proxy to toolsrv)
- Add tool_unload command to agent ctl file
This commit is contained in:
Levi Neely 2026-08-12 08:25:22 +02:00
parent 47b460b2da
commit 3ee4f16653
1 changed files with 15 additions and 102 deletions

View File

@ -9,9 +9,7 @@ import (
"fmt"
"os"
"os/user"
"strconv"
"strings"
"syscall"
"ollie/cmd/olliesrv/internal/agent"
"ollie/cmd/olliesrv/internal/backend"
@ -698,6 +696,20 @@ func buildAgentChildren(a *agent.Agent, s *session.Session) []virtfs.FsNodeDecl
a.RefreshTools()
return []byte(args[0] + "\n"), nil
},
"tool_unload": func(args []string) ([]byte, error) {
if len(args) == 0 {
return nil, fmt.Errorf("tool_unload requires a tool name")
}
ts := a.ToolServer()
if ts == nil {
return nil, fmt.Errorf("no tool server")
}
if err := ts.UnloadTool(args[0]); err != nil {
return nil, err
}
a.RefreshTools()
return []byte(args[0] + "\n"), nil
},
"backend": func(args []string) ([]byte, error) {
if len(args) == 0 {
if be := a.Backend(); be != nil {
@ -729,7 +741,7 @@ func buildAgentChildren(a *agent.Agent, s *session.Session) []virtfs.FsNodeDecl
return []byte(a.SystemPrompt() + "\n"), nil
},
"help": func(_ []string) ([]byte, error) {
return []byte("stop compact clear inject agent model models tools tool_load cwd name backend systemprompt help\n"), nil
return []byte("stop compact clear inject agent model models tools tool_load tool_unload cwd name backend systemprompt help\n"), nil
},
}, data)
}),
@ -754,104 +766,5 @@ func buildAgentChildren(a *agent.Agent, s *session.Session) []virtfs.FsNodeDecl
virtfs.FileNode("id", 0444,
virtfs.Read(func() ([]byte, error) { return []byte(a.ID() + "\n"), nil }),
),
virtfs.DirNode("proc",
virtfs.Each("{pid}", func() ([]virtfs.FsNodeDecl, error) {
conn := s.DialToolServer()
if conn == nil {
return nil, nil
}
defer conn.Close()
raw := conn.ListDetachedRaw()
var out []virtfs.FsNodeDecl
for _, r := range raw {
m, ok := r.(map[string]any)
if !ok {
continue
}
id, ok := m["pid"].(int)
if !ok {
continue
}
pid := id
out = append(out, virtfs.FsNodeDecl{
Name: strconv.Itoa(pid),
Children: []virtfs.FsNodeDecl{
virtfs.FileNode("out", 0444,
virtfs.Read(func() ([]byte, error) {
c := s.DialToolServer()
if c == nil {
return nil, fmt.Errorf("no tool server")
}
defer c.Close()
output, err := c.GetDetachedOutput(pid)
if err != nil {
return nil, err
}
return []byte(output), nil
}),
),
virtfs.FileNode("ctl", 0222,
virtfs.Write(func(data []byte) error {
c := s.DialToolServer()
if c == nil {
return fmt.Errorf("no tool server")
}
defer c.Close()
cmd := strings.TrimSpace(string(data))
switch {
case cmd == "term":
return c.SignalDetached(pid, syscall.SIGTERM)
case cmd == "kill":
return c.SignalDetached(pid, syscall.SIGKILL)
case cmd == "dismiss":
if !c.DismissDetached(pid) {
return fmt.Errorf("process %d not found", pid)
}
return nil
case strings.HasPrefix(cmd, "signal "):
parts := strings.Fields(cmd)
if len(parts) < 2 {
return fmt.Errorf("signal requires signal number")
}
sig, err := strconv.Atoi(parts[1])
if err != nil {
return fmt.Errorf("invalid signal: %s", parts[1])
}
return c.SignalDetached(pid, syscall.Signal(sig))
default:
return fmt.Errorf("unknown command: %s (valid: term, kill, signal <n>, dismiss)", cmd)
}
}),
),
virtfs.FileNode("status", 0444,
virtfs.Read(func() ([]byte, error) {
c := s.DialToolServer()
if c == nil {
return nil, fmt.Errorf("no tool server")
}
defer c.Close()
for _, r := range c.ListDetachedRaw() {
if m, ok := r.(map[string]any); ok {
if id, ok := m["pid"].(int); ok && id == pid {
if exited, ok := m["exited"].(bool); ok && exited {
exitCode := 0
if code, ok := m["exit_code"].(int); ok {
exitCode = code
}
return []byte(fmt.Sprintf("exited %d\n", exitCode)), nil
}
return []byte("running\n"), nil
}
}
}
return nil, fmt.Errorf("process %d not found", pid)
}),
),
},
})
}
return out, nil
}),
),
}
}