package supervisor import "sync" // ringBuffer keeps the last n lines of output. // // Engine logs are the only diagnosis available when a shard fails to load, but // they are also unbounded — a model loading for ten minutes can produce // megabytes. Keeping a bounded tail makes `ctl logs` useful without letting a // chatty engine consume the agent's memory. type ringBuffer struct { mu sync.Mutex lines []string next int full bool } func newRingBuffer(n int) *ringBuffer { if n <= 0 { n = 256 } return &ringBuffer{lines: make([]string, n)} } func (r *ringBuffer) add(line string) { r.mu.Lock() defer r.mu.Unlock() r.lines[r.next] = line r.next = (r.next + 1) % len(r.lines) if r.next == 0 { r.full = true } } // tail returns up to n most recent lines, oldest first. func (r *ringBuffer) tail(n int) []string { r.mu.Lock() defer r.mu.Unlock() size := r.next if r.full { size = len(r.lines) } if n <= 0 || n > size { n = size } out := make([]string, 0, n) for i := size - n; i < size; i++ { idx := i if r.full { idx = (r.next + i) % len(r.lines) } out = append(out, r.lines[idx]) } return out }