feat: наблюдение за живой opencode-сессией (/status N показывает что делает агент)
All checks were successful
CI / test (push) Successful in 54s
CI / build-and-package (amd64, linux) (push) Successful in 35s
CI / build-and-package (amd64, windows) (push) Successful in 43s

LiveRegistry собирает live-шаги из stdout процесса opencode по taskID
(через контекст, без изменения интерфейса Runner). /status N для running-задачи
прикладывает живое состояние: активный субагент, давность последнего шага,
последние text-шаги агента. Ничего не перезапускается и не убивается —
только наблюдение по запросу.
This commit is contained in:
Hermes
2026-08-17 08:05:15 +05:00
parent 2255917949
commit da775ac227
9 changed files with 329 additions and 26 deletions

View File

@@ -26,12 +26,12 @@ type Result struct {
// Runner — конфигурация запуска opencode-субагентов.
type Runner struct {
Bin string // путь к opencode (по умолчанию "opencode")
DBPath string // путь к opencode.db (idle-детекция активности)
Config string // путь к opencode.json (OPENCODE_CONFIG)
ConfigDir string // путь к каталогу с агентами (OPENCODE_CONFIG_DIR)
IdleTimeout time.Duration // нет новых сообщений в БД → зависание
HardTimeout time.Duration // общий лимит на запуск
Bin string // путь к opencode (по умолчанию "opencode")
DBPath string // путь к opencode.db (idle-детекция активности)
Config string // путь к opencode.json (OPENCODE_CONFIG)
ConfigDir string // путь к каталогу с агентами (OPENCODE_CONFIG_DIR)
IdleTimeout time.Duration // нет новых сообщений в БД → зависание
HardTimeout time.Duration // общий лимит на запуск
PollInterval time.Duration
// Заменяемые для тестов:
@@ -143,13 +143,25 @@ func (r *Runner) Run(ctx context.Context, prompt, cwd, agent, sessionID string)
var buf []string
var mu sync.Mutex
done := make(chan struct{})
// Живое наблюдение сессии (если задано через WithLive в контексте).
liveReg, liveTask := liveFromContext(ctx)
if liveReg != nil && liveTask != 0 {
liveReg.Start(liveTask, agent)
defer liveReg.Finish(liveTask)
}
go func() {
defer close(done)
sc := bufio.NewScanner(stdout)
for sc.Scan() {
line := sc.Text()
mu.Lock()
buf = append(buf, sc.Text())
buf = append(buf, line)
mu.Unlock()
if liveReg != nil {
if st := parseLiveStep(line); st != nil {
liveReg.Observe(liveTask, *st)
}
}
}
}()