package ui import ( "strings" "github.com/kamelion/ratatoskr-go/internal/events" "github.com/kamelion/ratatoskr-go/internal/model" "github.com/kamelion/ratatoskr-go/internal/storage" ) // StatePanel — панель «Состояние» (спец 12.13): агенты и трейсы выбранной // задачи. Снимок (SetText) + live-строки (Append), буфер ограничен. type StatePanel interface { // SetText заменяет содержимое снимком трасс. SetText(text string) // Append добавляет live-строку (буфер ограничен). Append(text string) } // NilStatePanel — no-op реализация StatePanel для headless-режима и тестов. type NilStatePanel struct{} // NewNilStatePanel создаёт NilStatePanel. func NewNilStatePanel() *NilStatePanel { return &NilStatePanel{} } func (NilStatePanel) SetText(string) {} func (NilStatePanel) Append(string) {} // StateText — снимок трасс задачи (pure-функция, спец 12.13). func StateText(traces []storage.Trace) string { var b strings.Builder for _, tr := range traces { b.WriteString(strings.ToUpper(tr.Agent) + ": " + string(tr.Status)) if tr.SessionID != "" { b.WriteString(" (session " + tr.SessionID + ")") } b.WriteString("\n") } if b.Len() == 0 { b.WriteString("Нет активных агентов.") } return b.String() } // TraceLine — строка добавленного/обновлённого трейса субагента. func TraceLine(agent string, status model.TraceStatus) string { return strings.ToUpper(agent) + ": " + string(status) } // ActivityLine — строка смены этапа агента. func ActivityLine(agent, stage string) string { return strings.ToUpper(agent) + " → " + stage } // TaskStatusText — строка изменения статуса задачи (бейдж + ID). func TaskStatusText(e events.TaskStatusChanged) string { return StatusBadge(e.To) + " #" + Itoa(e.ID) + ": " + string(e.From) + " → " + string(e.To) } // StatusBadge — эмодзи-бейдж статуса задачи. func StatusBadge(s model.Status) string { switch s { case model.StatusSuccess: return "✅" case model.StatusFailed, model.StatusAborted: return "❌" case model.StatusRunning, model.StatusCollecting: return "⏳" case model.StatusReady, model.StatusApproved: return "🟡" case model.StatusCancelled: return "🚫" default: return "•" } } // Itoa — int64 в строку без зависимостей. func Itoa(v int64) string { if v == 0 { return "0" } neg := v < 0 if neg { v = -v } var b [24]byte i := len(b) for v > 0 { i-- b[i] = byte('0' + v%10) v /= 10 } if neg { i-- b[i] = '-' } return string(b[i:]) }