feat: enhance agent management with support for multiple instances and update UI accordingly

This commit is contained in:
2026-03-04 23:41:26 +00:00
parent bcbbd974e3
commit 1e5103eb70
7 changed files with 48 additions and 48 deletions
+20 -12
View File
@@ -29,8 +29,9 @@ type AgentInfo struct {
// AgentStatus combines agent metadata with runtime state.
type AgentStatus struct {
AgentInfo
Running bool
PID int
Running bool
PID int
Instances int
}
// ProcessStats holds resource usage for a running process.
@@ -82,9 +83,17 @@ func (m *Manager) Scan() ([]AgentInfo, error) {
// Status returns the runtime status for a single agent.
func (m *Manager) Status(info AgentInfo) AgentStatus {
pid := m.resolveRunningPID(info.ID)
running := pid > 0
return AgentStatus{AgentInfo: info, Running: running, PID: pid}
pids := m.findProcessPIDs(info.ID)
primary := 0
if len(pids) > 0 {
primary = pids[0]
}
return AgentStatus{
AgentInfo: info,
Running: len(pids) > 0,
PID: primary,
Instances: len(pids),
}
}
// StatusAll returns status for every discovered agent.
@@ -101,13 +110,8 @@ func (m *Manager) StatusAll() ([]AgentStatus, error) {
}
// Start launches an agent process in the background.
// Multiple instances of the same agent are allowed.
func (m *Manager) Start(info AgentInfo) error {
// Check for orphan instances
if existing := m.findProcessPIDs(info.ID); len(existing) > 0 {
return fmt.Errorf("agent %q already has %d running instance(s) (PIDs: %v) — stop them first",
info.ID, len(existing), existing)
}
if err := os.MkdirAll(m.runDir, 0o755); err != nil {
return fmt.Errorf("create run dir: %w", err)
}
@@ -233,7 +237,11 @@ func (m *Manager) Stats(id string) (ProcessStats, error) {
if pid == 0 {
return ProcessStats{}, fmt.Errorf("agent %q is not running", id)
}
return m.statsForPID(pid, id), nil
}
// statsForPID gathers resource usage for a specific PID.
func (m *Manager) statsForPID(pid int, id string) ProcessStats {
s := ProcessStats{PID: pid}
// Uptime from /proc/<pid>/stat
@@ -278,7 +286,7 @@ func (m *Manager) Stats(id string) (ProcessStats, error) {
s.LogBytes = info.Size()
}
return s, nil
return s
}
// LogTail returns the last N lines of an agent's log.