proc: rename ListDetachedRaw→ListProcs, use proc/list rdwr (agent-filtered)

ListProcs now does rdwr to toolsrv proc/list with the agent ID.
Returns pre-formatted text. Ctl proc handler uses it directly.
Removed all ListDetachedRaw map-parsing logic.
This commit is contained in:
Levi Neely 2026-08-13 22:22:54 +02:00
parent 9246c44c0e
commit d64f6c1d76
2 changed files with 18 additions and 74 deletions

View File

@ -662,52 +662,18 @@ func buildAgentChildren(a *agent.Agent, s *session.Session) []virtfs.FsNodeDecl
if ts == nil { if ts == nil {
return nil, fmt.Errorf("no tool server") return nil, fmt.Errorf("no tool server")
} }
if len(args) == 0 { if len(args) == 0 || args[0] == "top" {
raw := ts.ListDetachedRaw() data, err := ts.ListProcs()
if len(raw) == 0 { if err != nil {
return nil, err
}
if len(data) == 0 {
return []byte("(no background processes)\n"), nil return []byte("(no background processes)\n"), nil
} }
var sb strings.Builder return data, nil
for _, r := range raw {
m, ok := r.(map[string]any)
if !ok {
continue
}
pid, _ := m["pid"].(int)
cmd, _ := m["command"].(string)
status := "running"
if exited, ok := m["exited"].(bool); ok && exited {
code, _ := m["exit_code"].(int)
status = fmt.Sprintf("exited (%d)", code)
}
fmt.Fprintf(&sb, "%d\t%s\tshell\t%s\n", pid, status, cmd)
}
return []byte(sb.String()), nil
} }
subcmd := args[0] subcmd := args[0]
switch subcmd { switch subcmd {
case "top":
raw := ts.ListDetachedRaw()
if len(raw) == 0 {
return []byte("(no background processes)\n"), nil
}
var sb strings.Builder
fmt.Fprintf(&sb, "%-8s %-10s %-16s %s\n", "PID", "STATUS", "TOOL", "CMD")
for _, r := range raw {
m, ok := r.(map[string]any)
if !ok {
continue
}
pid, _ := m["pid"].(int)
cmd, _ := m["command"].(string)
status := "running"
if exited, ok := m["exited"].(bool); ok && exited {
code, _ := m["exit_code"].(int)
status = fmt.Sprintf("exited (%d)", code)
}
fmt.Fprintf(&sb, "%-8d %-10s %-16s %s\n", pid, status, "shell", cmd)
}
return []byte(sb.String()), nil
case "term": case "term":
if len(args) < 2 { if len(args) < 2 {
return nil, fmt.Errorf("proc term requires pid") return nil, fmt.Errorf("proc term requires pid")
@ -757,18 +723,8 @@ func buildAgentChildren(a *agent.Agent, s *session.Session) []virtfs.FsNodeDecl
return nil, fmt.Errorf("process %d not found", pid) return nil, fmt.Errorf("process %d not found", pid)
} }
return []byte("ok\n"), nil return []byte("ok\n"), nil
case "raw":
raw := ts.ListDetachedRaw()
if len(raw) == 0 {
return []byte("(no procs in toolsrv)\n"), nil
}
var sb strings.Builder
for _, r := range raw {
fmt.Fprintf(&sb, "%v\n", r)
}
return []byte(sb.String()), nil
default: default:
return nil, fmt.Errorf("unknown proc subcommand: %s (use: top, term <pid>, kill <pid>, out <pid>, dismiss <pid>, raw)", subcmd) return nil, fmt.Errorf("unknown proc subcommand: %s (use: top, term <pid>, kill <pid>, out <pid>, dismiss <pid>)", subcmd)
} }
}, },
"systemprompt": func(_ []string) ([]byte, error) { "systemprompt": func(_ []string) ([]byte, error) {

View File

@ -379,32 +379,20 @@ func (c *Conn) Detach() bool {
return err == nil return err == nil
} }
// ListDetachedRaw returns raw info about detached processes. // ListProcs returns the proc listing for this agent (filtered by agent ID).
func (c *Conn) ListDetachedRaw() []any { func (c *Conn) ListProcs() ([]byte, error) {
fid, err := c.fsys.Open("proc", plan9.OREAD) fid, err := c.fsys.Open("proc/list", plan9.ORDWR)
if err != nil { if err != nil {
return nil return nil, err
} }
defer fid.Close() defer fid.Close()
if _, err := fid.Write([]byte(c.agentID)); err != nil {
var result []any return nil, err
// Read directory entries
for {
dirs, err := fid.Dirread()
if err != nil || len(dirs) == 0 {
break
} }
for _, d := range dirs { if _, err := fid.Seek(0, 0); err != nil {
if d.Name == "new" || d.Name == "new.bg" || d.Name == "list" { return nil, err
continue
} }
info := c.readProcInfo(d.Name) return io.ReadAll(fid)
if info != nil {
result = append(result, info)
}
}
}
return result
} }
// readProcInfo reads info about a single proc. // readProcInfo reads info about a single proc.