LiveRegistry собирает live-шаги из stdout процесса opencode по taskID (через контекст, без изменения интерфейса Runner). /status N для running-задачи прикладывает живое состояние: активный субагент, давность последнего шага, последние text-шаги агента. Ничего не перезапускается и не убивается — только наблюдение по запросу.
47 lines
1.2 KiB
Go
47 lines
1.2 KiB
Go
package app
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/kamelion/ratatoskr-go/internal/opencode"
|
|
)
|
|
|
|
// liveProbe адаптирует *opencode.LiveRegistry под интерфейс core.LiveProber.
|
|
// Формирует короткое человекочитаемое описание живой сессии задачи.
|
|
type liveProbe struct {
|
|
reg *opencode.LiveRegistry
|
|
}
|
|
|
|
func (p *liveProbe) Probe(taskID int64) (string, bool) {
|
|
if p == nil || p.reg == nil {
|
|
return "", false
|
|
}
|
|
snap, ok := p.reg.Snap(taskID)
|
|
if !ok {
|
|
return "", false
|
|
}
|
|
var b strings.Builder
|
|
b.WriteString(fmt.Sprintf("Агент **%s** активен", snap.Agent))
|
|
if idl := time.Since(snap.Last).Round(time.Second); idl > 0 {
|
|
b.WriteString(fmt.Sprintf(" (последний шаг %s назад)", idl))
|
|
}
|
|
// последние text-шаги — что агент делает прямо сейчас
|
|
n := 0
|
|
for i := len(snap.Steps) - 1; i >= 0 && n < 3; i-- {
|
|
st := snap.Steps[i]
|
|
if st.Type != "text" || strings.TrimSpace(st.Text) == "" {
|
|
continue
|
|
}
|
|
text := strings.TrimSpace(st.Text)
|
|
if len(text) > 140 {
|
|
text = text[:140] + "…"
|
|
}
|
|
text = strings.ReplaceAll(text, "\n", " ")
|
|
b.WriteString("\n▸ " + text)
|
|
n++
|
|
}
|
|
return b.String(), true
|
|
}
|