Replace quiescence detection with process tree inspection
Detect idle state by checking if kiro-cli-chat has tool children rather than relying purely on output quiescence. Fixes premature idle detection during long-running processes like remote builds.
This commit is contained in:
parent
4253c52f15
commit
fe56df8930
|
|
@ -109,6 +109,44 @@ func getPanePID(target string) (int, error) {
|
|||
return pid, err
|
||||
}
|
||||
|
||||
// hasToolChildren checks if kiro-cli-chat has any child processes (tool executions)
|
||||
func hasToolChildren(panePID int) bool {
|
||||
// Find kiro-cli-chat PID in the process tree: pane -> bash -> kiro-cli -> kiro-cli-chat
|
||||
chatPID := findKiroChatPID(panePID)
|
||||
if chatPID == 0 {
|
||||
return false
|
||||
}
|
||||
// Check if kiro-cli-chat has any children
|
||||
cmd := exec.Command("pgrep", "-P", fmt.Sprintf("%d", chatPID))
|
||||
return cmd.Run() == nil
|
||||
}
|
||||
|
||||
// findKiroChatPID traverses the process tree to find kiro-cli-chat
|
||||
func findKiroChatPID(panePID int) int {
|
||||
// pane (kiro-cli-term) -> bash -> kiro-cli -> kiro-cli-chat
|
||||
bashPID := findChildByName(panePID, "bash")
|
||||
if bashPID == 0 {
|
||||
return 0
|
||||
}
|
||||
kiroPID := findChildByName(bashPID, "kiro-cli")
|
||||
if kiroPID == 0 {
|
||||
return 0
|
||||
}
|
||||
return findChildByName(kiroPID, "kiro-cli-chat")
|
||||
}
|
||||
|
||||
// findChildByName finds a child process with the given name
|
||||
func findChildByName(parentPID int, name string) int {
|
||||
cmd := exec.Command("pgrep", "-P", fmt.Sprintf("%d", parentPID), "-x", name)
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
var pid int
|
||||
fmt.Sscanf(strings.TrimSpace(string(out)), "%d", &pid)
|
||||
return pid
|
||||
}
|
||||
|
||||
// makeNonBlocking sets a file descriptor to non-blocking mode
|
||||
func makeNonBlocking(fd int) error {
|
||||
return syscall.SetNonblock(fd, true)
|
||||
|
|
|
|||
|
|
@ -336,7 +336,10 @@ func (s *Session) Send(ctx context.Context, prompt string) (string, error) {
|
|||
|
||||
func (s *Session) waitForComplete(ctx context.Context, prompt string) error {
|
||||
const minContent = 50
|
||||
const quiescence = 400 * time.Millisecond
|
||||
const quiescence = 300 * time.Millisecond
|
||||
const pollInterval = 100 * time.Millisecond
|
||||
|
||||
var quiesceStart time.Time
|
||||
|
||||
for {
|
||||
select {
|
||||
|
|
@ -349,10 +352,29 @@ func (s *Session) waitForComplete(ctx context.Context, prompt string) error {
|
|||
return fmt.Errorf("session closed")
|
||||
}
|
||||
s.output.Write(data)
|
||||
quiesceStart = time.Time{} // Reset quiescence on new data
|
||||
|
||||
case <-time.After(quiescence):
|
||||
if s.output.Len() > minContent {
|
||||
debug.Log("[session %s] quiescence detected, %d bytes", s.id, s.output.Len())
|
||||
case <-time.After(pollInterval):
|
||||
// Check if we have minimum content
|
||||
if s.output.Len() < minContent {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check process tree: if kiro-cli-chat has tool children, still running
|
||||
if hasToolChildren(s.pid) {
|
||||
quiesceStart = time.Time{} // Reset quiescence
|
||||
continue
|
||||
}
|
||||
|
||||
// No tool children - start or continue quiescence timer
|
||||
if quiesceStart.IsZero() {
|
||||
quiesceStart = time.Now()
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if quiescence period has passed
|
||||
if time.Since(quiesceStart) >= quiescence {
|
||||
debug.Log("[session %s] idle detected (no tool children, %d bytes)", s.id, s.output.Len())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Reference in New Issue