archive

package
v0.2.16 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 24, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package archive persists agent transcript summaries for stopped/deleted instances so they can be reviewed after the container is gone.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Capture

func Capture(ctx context.Context, client *mcpclient.Client, inst *instance.Instance, archivesDir string) error

Capture fetches the full result from a running instance via its MCP endpoint and saves it as an archive entry. This is best-effort: the caller should log and continue on error.

func Exists

func Exists(archivesDir, uuid string) bool

Exists checks whether an archive for the given UUID already exists.

func Save

func Save(archivesDir string, entry *Entry) error

Save writes an archive entry as <uuid>.json in archivesDir.

Types

type ComplexityGroup

type ComplexityGroup struct {
	Level      string  `json:"level"`
	Runs       int     `json:"runs"`
	AvgCost    float64 `json:"avg_cost"`
	SuccessPct float64 `json:"success_pct"`
}

ComplexityGroup holds per-complexity-level stats for the summary breakdown.

type Entry

type Entry struct {
	// Instance metadata
	UUID        string    `json:"uuid"`
	Name        string    `json:"name"`
	Image       string    `json:"image"`
	Personality string    `json:"personality,omitempty"`
	Workspace   string    `json:"workspace"`
	Port        int       `json:"port"`
	StartedAt   time.Time `json:"started_at"`
	StoppedAt   time.Time `json:"stopped_at"`

	// Agent result — flat fields from the agent's full result response.
	ResultText    string            `json:"result_text,omitempty"`
	Messages      json.RawMessage   `json:"messages,omitempty"`
	MessageCount  int               `json:"message_count"`
	Status        string            `json:"status"`
	SessionID     string            `json:"session_id,omitempty"`
	TotalCostUSD  *float64          `json:"total_cost_usd,omitempty"`
	ToolCalls     map[string]int    `json:"tool_calls,omitempty"`
	ModelUsage    map[string]int    `json:"model_usage,omitempty"`
	TokenUsage    json.RawMessage   `json:"token_usage,omitempty"`
	SubagentCalls json.RawMessage   `json:"subagent_calls,omitempty"`
	PRURLs        []string          `json:"pr_urls,omitempty"`
	ErrorCount    int               `json:"error_count,omitempty"`
	ErrorMessage  string            `json:"error,omitempty"`
	Tags          map[string]string `json:"tags,omitempty"`
}

Entry is the archived snapshot of an instance run.

func EntryFromResult

func EntryFromResult(inst *instance.Instance, resultJSON string) (*Entry, error)

EntryFromResult builds an Entry from instance metadata and the raw JSON response from the agent's full result tool. Fields that don't appear in the JSON are left at their zero values.

func FilterEntries added in v0.0.43

func FilterEntries(entries []*Entry, f Filter) []*Entry

FilterEntries returns entries that match all non-zero filter criteria.

func Load

func Load(archivesDir, uuid string) (*Entry, error)

Load reads a single archive entry by UUID.

func LoadAll

func LoadAll(archivesDir string) ([]*Entry, error)

LoadAll reads all archive entries, sorted by StoppedAt descending (newest first).

func Tag

func Tag(archivesDir, uuid string, tags map[string]string) (*Entry, error)

Tag loads an archive entry by UUID, merges the provided tags (overwriting existing keys), saves the updated entry, and returns it.

func (*Entry) ToListSummary

func (e *Entry) ToListSummary() ListSummary

ToListSummary converts an Entry to a ListSummary for list responses.

type Filter added in v0.0.43

type Filter struct {
	Since   time.Time // only entries stopped after this time
	Name    string    // substring match on entry name
	Tagged  *bool     // nil = no filter, true = only tagged, false = only untagged
	Outcome string    // exact match on tags["outcome"]
}

Filter defines criteria for filtering archive entries. Zero-value fields are ignored (no filtering on that dimension).

type ListEntry

type ListEntry struct {
	Date       string  `json:"date"`
	Name       string  `json:"name"`
	Repo       string  `json:"repo"`
	Issue      string  `json:"issue"`
	Outcome    string  `json:"outcome"`
	Cost       float64 `json:"cost"`
	Messages   int     `json:"messages"`
	Duration   string  `json:"duration"`
	Complexity string  `json:"complexity"`
	// contains filtered or unexported fields
}

ListEntry holds the display fields for a single archive entry.

func ComputeList

func ComputeList(entries []*Entry, filters SummaryFilters, sortBy string, limit int) []ListEntry

ComputeList returns a flat list of entries with display fields, filtered and sorted.

type ListSummary

type ListSummary struct {
	UUID         string   `json:"uuid"`
	Name         string   `json:"name"`
	Status       string   `json:"status"`
	StoppedAt    string   `json:"stopped_at"`
	MessageCount int      `json:"message_count"`
	TotalCostUSD *float64 `json:"total_cost_usd,omitempty"`
}

ListSummary is the shared list-summary type used by both the CLI and MCP tool for archive list responses.

type SpendGroup

type SpendGroup struct {
	Group      string  `json:"group"`
	Runs       int     `json:"runs"`
	PctOfTotal float64 `json:"pct_of_total"`
	TotalCost  float64 `json:"total_cost"`
	AvgCost    float64 `json:"avg_cost"`
}

SpendGroup is a single row in a cost breakdown.

func ComputeSpend

func ComputeSpend(entries []*Entry, groupBy string, weeks int, filters ...SummaryFilters) []SpendGroup

ComputeSpend groups entries by the given dimension and returns cost breakdowns. groupBy is one of "week", "repo", or "complexity". weeks limits to the last N weeks.

type SummaryFilters

type SummaryFilters struct {
	Since      time.Time // zero means no lower bound
	Repo       string    // empty means all repos
	Outcome    string    // empty means all outcomes
	Complexity string    // empty means all complexities
}

SummaryFilters controls which entries are included in the summary.

type SummaryStats

type SummaryStats struct {
	TotalRuns      int     `json:"total_runs"`
	Success        int     `json:"success"`
	SuccessPct     float64 `json:"success_pct"`
	Partial        int     `json:"partial"`
	PartialPct     float64 `json:"partial_pct"`
	Failure        int     `json:"failure"`
	FailurePct     float64 `json:"failure_pct"`
	TotalCostUSD   float64 `json:"total_cost_usd"`
	AvgCostUSD     float64 `json:"avg_cost_usd"`
	AvgMessages    int     `json:"avg_messages"`
	MedianDuration string  `json:"median_duration"`

	// Enriched fields
	FirstAttempt        int               `json:"first_attempt"`
	FirstAttemptPct     float64           `json:"first_attempt_pct"`
	ScopeAdherence      int               `json:"scope_adherence"`
	ScopeAdherencePct   float64           `json:"scope_adherence_pct"`
	ScopeTotal          int               `json:"scope_total"`
	ReworkNone          int               `json:"rework_none"`
	ReworkMinor         int               `json:"rework_minor"`
	ReworkMajor         int               `json:"rework_major"`
	MinCost             float64           `json:"min_cost"`
	MaxCost             float64           `json:"max_cost"`
	MinMessages         int               `json:"min_messages"`
	MaxMessages         int               `json:"max_messages"`
	MinDuration         string            `json:"min_duration"`
	MaxDuration         string            `json:"max_duration"`
	ComplexityBreakdown []ComplexityGroup `json:"complexity_breakdown,omitempty"`
}

SummaryStats is the aggregated overview of archived runs.

func ComputeSummary

func ComputeSummary(entries []*Entry, filters SummaryFilters) *SummaryStats

ComputeSummary aggregates stats from the given entries after applying filters.

type TrendWeek

type TrendWeek struct {
	Week            string  `json:"week"`
	Runs            int     `json:"runs"`
	SuccessPct      float64 `json:"success_pct"`
	FirstAttemptPct float64 `json:"first_attempt_pct"`
	AvgCostUSD      float64 `json:"avg_cost_usd"`
	TotalCostUSD    float64 `json:"total_cost_usd"`
	AvgMessages     int     `json:"avg_messages"`
	AvgDuration     string  `json:"avg_duration"`
	AvgComplexity   float64 `json:"avg_complexity"`
}

TrendWeek is a single row in the week-over-week trends table.

func ComputeTrends

func ComputeTrends(entries []*Entry, weeks int, filters ...SummaryFilters) []TrendWeek

ComputeTrends returns week-over-week trend data for the last N weeks.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL