first commit
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
// This file implements the telemetry holder that retains per-run telemetry
|
||||
// events (US-001, #291) and folds them into a cumulative accumulator for the
|
||||
// /status command to display. It was moved verbatim from cmd/pigo
|
||||
// (telemetry_state.go, US-013) into the shared cli layer so the status and repl
|
||||
// subpackages share one holder type.
|
||||
package cli
|
||||
|
||||
import (
|
||||
"github.com/smallnest/pigo/internal/agentcore"
|
||||
)
|
||||
|
||||
// TelemetryHolder holds the most recent run's telemetry event and a cumulative
|
||||
// accumulator that sums metrics across all runs in the session.
|
||||
type TelemetryHolder struct {
|
||||
// last is the telemetry event from the most recent completed run, or nil if
|
||||
// no run has completed yet.
|
||||
last *agentcore.TelemetryEvent
|
||||
// cumulative is the accumulator that sums metrics across all runs.
|
||||
cumulative cumulativeTelemetry
|
||||
}
|
||||
|
||||
// cumulativeTelemetry holds the accumulated metrics from all runs in the session.
|
||||
type cumulativeTelemetry struct {
|
||||
// turns is the total number of turns across all runs.
|
||||
turns int
|
||||
// toolDurationsMs maps tool name to aggregated count and total milliseconds
|
||||
// across all runs.
|
||||
toolDurationsMs map[string]agentcore.ToolTiming
|
||||
// truncationCount is the total number of truncations across all runs.
|
||||
truncationCount int
|
||||
// compactionCount is the total number of compactions across all runs.
|
||||
compactionCount int
|
||||
// contextTokens is the most recent observed context token count.
|
||||
contextTokens int
|
||||
// contextWindow is the most recent observed context window size.
|
||||
contextWindow int
|
||||
}
|
||||
|
||||
// NewTelemetryHolder creates a new, empty TelemetryHolder with no telemetry yet.
|
||||
func NewTelemetryHolder() *TelemetryHolder {
|
||||
return &TelemetryHolder{
|
||||
last: nil,
|
||||
cumulative: cumulativeTelemetry{
|
||||
toolDurationsMs: make(map[string]agentcore.ToolTiming),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Reset clears the holder to "no telemetry yet", as if the session had just
|
||||
// started. It is called when switching sessions (/fork, /clone, /import).
|
||||
func (h *TelemetryHolder) Reset() {
|
||||
h.last = nil
|
||||
h.cumulative = cumulativeTelemetry{
|
||||
toolDurationsMs: make(map[string]agentcore.ToolTiming),
|
||||
}
|
||||
}
|
||||
|
||||
// Fold incorporates a new TelemetryEvent into the holder: it becomes the new
|
||||
// "last run" event, and its metrics are added to the cumulative accumulator.
|
||||
func (h *TelemetryHolder) Fold(ev agentcore.TelemetryEvent) {
|
||||
// Store the new event as the last run.
|
||||
h.last = &ev
|
||||
|
||||
// Add its metrics to the cumulative accumulator.
|
||||
h.cumulative.turns += ev.Turns
|
||||
h.cumulative.truncationCount += ev.TruncationCount
|
||||
h.cumulative.compactionCount += ev.CompactionCount
|
||||
|
||||
// Update the latest context tokens and window (always use the most recent).
|
||||
h.cumulative.contextTokens = ev.ContextTokens
|
||||
h.cumulative.contextWindow = ev.ContextWindow
|
||||
|
||||
// Sum the per-tool timings.
|
||||
for name, timing := range ev.ToolDurationsMs {
|
||||
agg := h.cumulative.toolDurationsMs[name]
|
||||
agg.Count += timing.Count
|
||||
agg.TotalMs += timing.TotalMs
|
||||
h.cumulative.toolDurationsMs[name] = agg
|
||||
}
|
||||
}
|
||||
|
||||
// HasTelemetry returns true if at least one run has completed and telemetry is
|
||||
// available.
|
||||
func (h *TelemetryHolder) HasTelemetry() bool {
|
||||
return h.last != nil
|
||||
}
|
||||
|
||||
// Last returns the most recent TelemetryEvent, or nil if no run has completed.
|
||||
func (h *TelemetryHolder) Last() *agentcore.TelemetryEvent {
|
||||
return h.last
|
||||
}
|
||||
|
||||
// CumulativeTurns returns the total number of turns across all runs.
|
||||
func (h *TelemetryHolder) CumulativeTurns() int {
|
||||
return h.cumulative.turns
|
||||
}
|
||||
|
||||
// CumulativeTruncationCount returns the total number of truncations across all runs.
|
||||
func (h *TelemetryHolder) CumulativeTruncationCount() int {
|
||||
return h.cumulative.truncationCount
|
||||
}
|
||||
|
||||
// CumulativeCompactionCount returns the total number of compactions across all runs.
|
||||
func (h *TelemetryHolder) CumulativeCompactionCount() int {
|
||||
return h.cumulative.compactionCount
|
||||
}
|
||||
|
||||
// CumulativeToolDurations returns the aggregated tool timings across all runs.
|
||||
func (h *TelemetryHolder) CumulativeToolDurations() map[string]agentcore.ToolTiming {
|
||||
// Return a copy to prevent mutation of the internal state.
|
||||
result := make(map[string]agentcore.ToolTiming, len(h.cumulative.toolDurationsMs))
|
||||
for name, timing := range h.cumulative.toolDurationsMs {
|
||||
result[name] = timing
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// LatestContextTokens returns the most recent observed context token count.
|
||||
func (h *TelemetryHolder) LatestContextTokens() int {
|
||||
return h.cumulative.contextTokens
|
||||
}
|
||||
|
||||
// LatestContextWindow returns the most recent observed context window size.
|
||||
func (h *TelemetryHolder) LatestContextWindow() int {
|
||||
return h.cumulative.contextWindow
|
||||
}
|
||||
|
||||
// CumulativeContextUtilization returns the latest utilization ratio, or 0 if no
|
||||
// window is known.
|
||||
func (h *TelemetryHolder) CumulativeContextUtilization() float64 {
|
||||
if h.cumulative.contextWindow <= 0 {
|
||||
return 0
|
||||
}
|
||||
return float64(h.cumulative.contextTokens) / float64(h.cumulative.contextWindow)
|
||||
}
|
||||
Reference in New Issue
Block a user