sessions

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: May 19, 2026 License: AGPL-3.0 Imports: 9 Imported by: 0

Documentation

Overview

Package sessions provides the shared types and logic for building a per-session summary from a chain of merkle nodes. It is consumed by both the API server (for /v1/sessions/summary) and the deck TUI (for rendering).

All functions in this package operate on *merkle.Node, not on any specific storage driver type. Callers are responsible for fetching and walking the ancestry chain; this package computes derived metadata over that chain.

Index

Constants

View Source
const (
	StatusCompleted = "completed"
	StatusFailed    = "failed"
	StatusAbandoned = "abandoned"
	StatusUnknown   = "unknown"
)

Status values returned by DetermineStatus.

Variables

This section is empty.

Functions

func BlocksHaveGitActivity

func BlocksHaveGitActivity(blocks []llm.ContentBlock) bool

BlocksHaveGitActivity reports whether the blocks contain a Bash tool call whose command invokes `git commit` or `git push`.

func BlocksHaveToolError

func BlocksHaveToolError(blocks []llm.ContentBlock) bool

BlocksHaveToolError reports whether any tool_result block is marked as an error.

func BuildLabel

func BuildLabel(nodes []*merkle.Node) string

BuildLabel derives a short human-readable label for the session from the most recent user-role prompts in the chain. Falls back to a truncated form of the leaf hash if no usable prompts are found.

func CopyModelCosts

func CopyModelCosts(costs map[string]ModelCost) map[string]ModelCost

CopyModelCosts returns a shallow copy of the map, or an empty map if nil.

func CostForTokens

func CostForTokens(pricing Pricing, inputTokens, outputTokens int64) (float64, float64, float64)

CostForTokens calculates cost using base input/output pricing. For cache-aware cost calculation, use CostForTokensWithCache.

func CostForTokensWithCache

func CostForTokensWithCache(pricing Pricing, inputTokens, outputTokens, cacheCreation, cacheRead int64) (float64, float64, float64)

CostForTokensWithCache calculates cost accounting for prompt caching. When cache token counts are available, base input tokens are:

baseInput = totalInput - cacheCreation - cacheRead

Each token type is priced at its respective rate.

func CountToolCalls

func CountToolCalls(blocks []llm.ContentBlock) int

CountToolCalls returns how many tool_use blocks are in the slice.

func DetermineStatus

func DetermineStatus(leaf *merkle.Node, hasToolError, hasGitActivity bool) string

DetermineStatus classifies a session based on its terminal (leaf) node and a pair of flags derived from scanning the full ancestry.

Precedence:

  1. Any tool_result error in the chain → StatusFailed
  2. Any git commit/push in the chain → StatusCompleted (strong done signal)
  3. Non-assistant leaf → StatusAbandoned
  4. Assistant leaf with a known-terminal stop_reason → StatusCompleted
  5. Assistant leaf with a known-failing stop_reason → StatusFailed
  6. Empty or otherwise unrecognised stop_reason → StatusUnknown

func DominantModel

func DominantModel(costs map[string]ModelCost) string

DominantModel returns the model with the highest total cost in the map, or the empty string if none.

func ExtractLabelText

func ExtractLabelText(blocks []llm.ContentBlock) string

ExtractLabelText concatenates human-visible text from content blocks for label-building purposes, stripping tagged meta sections like <system-reminder>...</system-reminder>.

func ExtractText

func ExtractText(blocks []llm.ContentBlock) string

ExtractText concatenates visible text across text, tool_output, and tool_use blocks, joined by newlines.

func ExtractToolCalls

func ExtractToolCalls(blocks []llm.ContentBlock) []string

ExtractToolCalls returns the names of all tool_use blocks.

func FirstModel

func FirstModel(nodes []*merkle.Node) string

FirstModel returns the normalized model of the first node in the chain that has a non-empty Model field, or the empty string.

func MergeModelCosts

func MergeModelCosts(target map[string]ModelCost, costs map[string]ModelCost)

MergeModelCosts adds the per-model values in costs into target in place. Does nothing if target is nil.

func NormalizeModel

func NormalizeModel(model string) string

NormalizeModel canonicalizes a model name: lowercased, trimmed, date suffixes stripped, and vendor-specific version markers rewritten so the result can be used as a key into PricingTable.

func StripTaggedSection

func StripTaggedSection(text, tag string) string

StripTaggedSection removes all occurrences of a given XML-like tagged section (e.g. <system-reminder>…</system-reminder>) from text.

func SumModelCosts

func SumModelCosts(costs map[string]ModelCost) (float64, float64, float64)

SumModelCosts totals input/output/total cost across all models in the map.

Types

type ModelCost

type ModelCost struct {
	Model        string  `json:"model"`
	InputTokens  int64   `json:"input_tokens"`
	OutputTokens int64   `json:"output_tokens"`
	InputCost    float64 `json:"input_cost"`
	OutputCost   float64 `json:"output_cost"`
	TotalCost    float64 `json:"total_cost"`
	SessionCount int     `json:"session_count"`
}

ModelCost is a per-model aggregate of cost and token usage within a session or a collection of sessions.

type NodeTokens

type NodeTokens struct {
	Input         int64
	Output        int64
	Total         int64
	CacheCreation int64
	CacheRead     int64
}

NodeTokens holds all token counts for a node, including cache breakdown.

func TokensForNode

func TokensForNode(n *merkle.Node) NodeTokens

TokensForNode extracts token counts from a merkle node's Usage metadata. Returns a zero-valued NodeTokens when Usage is nil.

type Pricing

type Pricing struct {
	Input      float64 `json:"input"`
	Output     float64 `json:"output"`
	CacheRead  float64 `json:"cache_read"`
	CacheWrite float64 `json:"cache_write"`
}

Pricing is the per-million-tokens price for a single model.

func PricingForModel

func PricingForModel(pricing PricingTable, model string) (Pricing, bool)

PricingForModel looks up pricing for a model name, trying the normalized form first and falling back to the raw string.

type PricingTable

type PricingTable map[string]Pricing

PricingTable maps model names (after normalization) to their Pricing.

func DefaultPricing

func DefaultPricing() PricingTable

DefaultPricing returns hardcoded pricing per million tokens for supported models.

Last verified: 2026-04-16 Sources:

Anthropic cache multipliers: CacheWrite = 1.25x input, CacheRead = 0.10x input. OpenAI cache: CacheWrite = 1x input (no surcharge), CacheRead = 0.50x input (except o3-mini).

To override at runtime, pass a JSON file path to LoadPricing.

func LoadPricing

func LoadPricing(path string) (PricingTable, error)

LoadPricing loads a pricing table, applying JSON overrides from path if set. An empty path returns DefaultPricing unchanged.

type SessionSummary

type SessionSummary struct {
	ID           string        `json:"id"`
	Label        string        `json:"label"`
	Model        string        `json:"model"`
	Project      string        `json:"project"`
	AgentName    string        `json:"agent_name,omitempty"`
	Status       string        `json:"status"`
	StartTime    time.Time     `json:"start_time"`
	EndTime      time.Time     `json:"end_time"`
	Duration     time.Duration `json:"duration_ns"`
	InputTokens  int64         `json:"input_tokens"`
	OutputTokens int64         `json:"output_tokens"`
	InputCost    float64       `json:"input_cost"`
	OutputCost   float64       `json:"output_cost"`
	TotalCost    float64       `json:"total_cost"`
	ToolCalls    int           `json:"tool_calls"`
	MessageCount int           `json:"message_count"`
	SessionCount int           `json:"session_count,omitempty"`

	// Truncated is true when this summary was built from a partial chain
	// because an ancestor's parent_hash could not be resolved in the
	// current store. MissingParent names the hash that would have
	// continued the walk if the referenced node existed. Both fields are
	// informational — they signal that higher ancestors may live outside
	// this store (trimmed history, foreign chain, offloaded data) rather
	// than an error.
	Truncated     bool   `json:"truncated,omitempty"`
	MissingParent string `json:"missing_parent,omitempty"`
}

SessionSummary is the aggregate view of a single session (a root-to-leaf chain). It is produced by BuildSummary and consumed by both the API's /v1/sessions/summary response and the deck TUI overview.

func BuildSummary

func BuildSummary(nodes []*merkle.Node, pricing PricingTable) (SessionSummary, map[string]ModelCost, string, error)

BuildSummary computes a SessionSummary from a chain of nodes in chronological order (root first, leaf last). It also returns the per-model cost breakdown used for rollups, and the derived status (duplicated on the returned summary for convenience).

Returns an error if the input chain is empty.

Jump to

Keyboard shortcuts

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