fix: improve kiro-cli state detection and add Refresh method

- IsBusy now checks /proc/PID/stat for process state (R/D = busy)
  when no child processes exist, fixing false idle detection
- Add Refresh() to Session interface to re-detect state on demand
This commit is contained in:
Levi Neely 2026-02-13 15:03:27 +01:00
parent 1656ff6a6b
commit e28d39aab6
3 changed files with 44 additions and 1 deletions

View File

@ -31,6 +31,9 @@ type Session interface {
// State returns current state ("starting", "idle", "running", "error: ...", "exited")
State() string
// Refresh retries startup if in error state, or refreshes state detection
Refresh(ctx context.Context) error
// Send sends a prompt and returns the response
// Blocks until response is complete
Send(ctx context.Context, prompt string) (string, error)

View File

@ -475,3 +475,23 @@ func (s *Session) Close() error {
s.state = "exited"
return nil
}
// Refresh re-detects state based on process activity
func (s *Session) Refresh(ctx context.Context) error {
s.mu.Lock()
defer s.mu.Unlock()
if s.state == "exited" {
return nil
}
// Check if process is busy
busy := s.stateInspector != nil && s.stateInspector.IsBusy(s.pid)
if busy {
s.state = "running"
} else {
s.state = "idle"
}
debug.Log("[session %s] refresh: state=%s", s.id, s.state)
return nil
}

View File

@ -46,7 +46,27 @@ func (i *kiroStateInspector) IsBusy(panePID int) bool {
}
// Check if kiro-cli-chat has any children (tool executions)
cmd := exec.Command("pgrep", "-P", fmt.Sprintf("%d", chatPID))
return cmd.Run() == nil
if cmd.Run() == nil {
return true // has children = busy
}
// No children - check if process is actively running (not sleeping waiting for input)
return isProcessActive(chatPID)
}
// isProcessActive checks if a process is doing work (not blocked waiting for input)
func isProcessActive(pid int) bool {
data, err := os.ReadFile(fmt.Sprintf("/proc/%d/stat", pid))
if err != nil {
return false
}
fields := strings.Fields(string(data))
if len(fields) < 3 {
return false
}
state := fields[2]
// R = running, D = disk sleep (I/O), both indicate active work
// S = interruptible sleep (waiting for input) = idle
return state == "R" || state == "D"
}
// kiroCommands implements command handling for kiro-cli