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 {
return nil, fmt.Errorf("no tool server")
}
if len(args) == 0 {
raw := ts.ListDetachedRaw()
if len(raw) == 0 {
if len(args) == 0 || args[0] == "top" {
data, err := ts.ListProcs()
if err != nil {
return nil, err
}
if len(data) == 0 {
return []byte("(no background processes)\n"), nil
}
var sb strings.Builder
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
return data, nil
}
subcmd := args[0]
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":
if len(args) < 2 {
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 []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:
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) {

View File

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