Documentation
¶
Index ¶
- Constants
- func CostForTokens(pricing Pricing, inputTokens, outputTokens int64) (float64, float64, float64)
- func CostForTokensWithCache(pricing Pricing, inputTokens, outputTokens, cacheCreation, cacheRead int64) (float64, float64, float64)
- func HasLLMCredentials(cfg LLMCallerConfig) bool
- func SeedDemo(ctx context.Context, path string, overwrite bool) (int, int, error)
- func SortSessions(sessions []SessionSummary, sortKey, sortDir string)
- func StripTaggedSection(text, tag string) string
- type AnalyticsOverview
- type Bucket
- type DayActivity
- type EntFacetStore
- type FacetAnalytics
- type FacetExtractor
- type FacetStore
- type FacetSummary
- type FacetWorker
- type Filters
- type FrictionItem
- type LLMCallFunc
- type LLMCallerConfig
- type ModelCost
- type ModelPerformance
- type Overview
- type PeriodComparison
- type Pricing
- type PricingTable
- type Querier
- type Query
- func (q *Query) AnalyticsOverview(ctx context.Context, filters Filters) (*AnalyticsOverview, error)
- func (q *Query) EntClient() *ent.Client
- func (q *Query) Overview(ctx context.Context, filters Filters) (*Overview, error)
- func (q *Query) SessionAnalytics(ctx context.Context, sessionID string) (*SessionAnalytics, error)
- func (q *Query) SessionDetail(ctx context.Context, sessionID string) (*SessionDetail, error)
- type SessionAnalytics
- type SessionDetail
- type SessionFacet
- type SessionMessage
- type SessionMessageGroup
- type SessionSummary
- type ToolMetric
Constants ¶
const ( StatusCompleted = "completed" StatusFailed = "failed" StatusAbandoned = "abandoned" StatusUnknown = "unknown" )
const DemoSQLitePath = "tapes.demo.sqlite"
Variables ¶
This section is empty.
Functions ¶
func CostForTokens ¶
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 calculated as: baseInput = totalInput - cacheCreation - cacheRead Each token type is priced at its respective rate.
func HasLLMCredentials ¶
func HasLLMCredentials(cfg LLMCallerConfig) bool
HasLLMCredentials checks whether an API key can be resolved from the config without creating a caller. Used for auto-enabling insights.
func SortSessions ¶
func SortSessions(sessions []SessionSummary, sortKey, sortDir string)
SortSessions sorts session summaries in place by the given key and direction.
func StripTaggedSection ¶
StripTaggedSection removes all occurrences of a given XML-like tagged section (e.g. <system-reminder>…</system-reminder>) from text.
Types ¶
type AnalyticsOverview ¶
type AnalyticsOverview struct {
TotalSessions int `json:"total_sessions"`
AvgSessionCost float64 `json:"avg_session_cost"`
AvgDurationNs int64 `json:"avg_duration_ns"`
TopTools []ToolMetric `json:"top_tools"`
ActivityByDay []DayActivity `json:"activity_by_day"`
DurationBuckets []Bucket `json:"duration_buckets"`
CostBuckets []Bucket `json:"cost_buckets"`
ModelPerformance []ModelPerformance `json:"model_performance"`
ProviderBreakdown map[string]int `json:"provider_breakdown"`
}
AnalyticsOverview holds cross-session analytics.
type DayActivity ¶
type EntFacetStore ¶
type EntFacetStore struct {
// contains filtered or unexported fields
}
EntFacetStore implements FacetStore using ent.
func NewEntFacetStore ¶
func NewEntFacetStore(client *ent.Client) *EntFacetStore
NewEntFacetStore creates a new EntFacetStore.
func (*EntFacetStore) GetFacet ¶
func (s *EntFacetStore) GetFacet(ctx context.Context, sessionID string) (*SessionFacet, error)
func (*EntFacetStore) ListFacets ¶
func (s *EntFacetStore) ListFacets(ctx context.Context) ([]*SessionFacet, error)
func (*EntFacetStore) SaveFacet ¶
func (s *EntFacetStore) SaveFacet(ctx context.Context, f *SessionFacet) error
type FacetAnalytics ¶
type FacetAnalytics struct {
GoalDistribution map[string]int `json:"goal_distribution"`
OutcomeDistribution map[string]int `json:"outcome_distribution"`
SessionTypes map[string]int `json:"session_types"`
TopFriction []FrictionItem `json:"top_friction"`
RecentSummaries []FacetSummary `json:"recent_summaries"`
}
FacetAnalytics holds aggregated facet data across sessions.
type FacetExtractor ¶
type FacetExtractor struct {
// contains filtered or unexported fields
}
FacetExtractor extracts qualitative facets from session transcripts.
func NewFacetExtractor ¶
func NewFacetExtractor(query Querier, llmCall LLMCallFunc, store FacetStore, log *slog.Logger) *FacetExtractor
NewFacetExtractor creates a new FacetExtractor.
func (*FacetExtractor) AggregateFacets ¶
func (f *FacetExtractor) AggregateFacets(ctx context.Context) (*FacetAnalytics, error)
AggregateFacets computes aggregated analytics from all stored facets.
func (*FacetExtractor) Extract ¶
func (f *FacetExtractor) Extract(ctx context.Context, sessionID string) (*SessionFacet, error)
Extract runs facet extraction for a single session. It retries up to 2 times on JSON parse failures with a stricter prompt.
type FacetStore ¶
type FacetStore interface {
SaveFacet(ctx context.Context, facet *SessionFacet) error
GetFacet(ctx context.Context, sessionID string) (*SessionFacet, error)
ListFacets(ctx context.Context) ([]*SessionFacet, error)
}
FacetStore is the interface for persisting and retrieving facets.
type FacetSummary ¶
type FacetSummary struct {
SessionID string `json:"session_id"`
UnderlyingGoal string `json:"underlying_goal"`
BriefSummary string `json:"brief_summary"`
GoalCategory string `json:"goal_category"`
Outcome string `json:"outcome"`
}
FacetSummary is a brief summary for display.
type FacetWorker ¶
type FacetWorker struct {
// contains filtered or unexported fields
}
FacetWorker processes sessions in the background to extract facets.
func NewFacetWorker ¶
func NewFacetWorker(extractor *FacetExtractor, store FacetStore, query Querier, log *slog.Logger) *FacetWorker
NewFacetWorker creates a new FacetWorker.
func (*FacetWorker) Progress ¶
func (w *FacetWorker) Progress() (done, total int)
Progress returns the number of sessions processed and total to process.
func (*FacetWorker) Run ¶
func (w *FacetWorker) Run(ctx context.Context)
Run starts background facet extraction. It queries all sessions, skips those with existing facets, and processes the rest with bounded concurrency. It blocks until all sessions are processed or the context is cancelled.
type FrictionItem ¶
FrictionItem represents a friction type with its count.
type LLMCallFunc ¶
LLMCallFunc is the signature for an LLM inference call.
func NewLLMCaller ¶
func NewLLMCaller(cfg LLMCallerConfig) (LLMCallFunc, error)
NewLLMCaller creates a LLMCallFunc based on the provided configuration. Resolution order for API key:
- Explicit APIKey in config
- credentials.Manager (from tapes auth)
- Environment variables (OPENAI_API_KEY / ANTHROPIC_API_KEY)
- Fall back to Ollama at localhost:11434
type LLMCallerConfig ¶
type LLMCallerConfig struct {
Provider string // "openai", "anthropic", or "ollama"
Model string // e.g. "gpt-4o-mini", "claude-haiku-4-5-20251001"
APIKey string // explicit API key (highest priority)
BaseURL string // override base URL
CredMgr *credentials.Manager // credentials from tapes auth
Logger *slog.Logger // optional logger; defaults to noop
}
LLMCallerConfig holds configuration for creating an LLM caller.
type ModelPerformance ¶
type ModelPerformance struct {
Model string `json:"model"`
Provider string `json:"provider"`
Sessions int `json:"sessions"`
AvgCost float64 `json:"avg_cost"`
AvgDurationNs int64 `json:"avg_duration_ns"`
AvgTokens int64 `json:"avg_tokens"`
TotalCost float64 `json:"total_cost"`
SuccessRate float64 `json:"success_rate"`
CompletedCount int `json:"completed_count"`
}
type Overview ¶
type Overview struct {
Sessions []SessionSummary `json:"sessions"`
TotalCost float64 `json:"total_cost"`
TotalTokens int64 `json:"total_tokens"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
TotalDuration time.Duration `json:"total_duration_ns"`
TotalToolCalls int `json:"total_tool_calls"`
SuccessRate float64 `json:"success_rate"`
Completed int `json:"completed"`
Failed int `json:"failed"`
Abandoned int `json:"abandoned"`
CostByModel map[string]ModelCost `json:"cost_by_model"`
PreviousPeriod *PeriodComparison `json:"previous_period,omitempty"`
}
type PeriodComparison ¶
type Pricing ¶
type Pricing struct {
Input float64 `json:"input"`
Output float64 `json:"output"`
CacheRead float64 `json:"cache_read"`
CacheWrite float64 `json:"cache_write"`
}
func PricingForModel ¶
func PricingForModel(pricing PricingTable, model string) (Pricing, bool)
type PricingTable ¶
func DefaultPricing ¶
func DefaultPricing() PricingTable
DefaultPricing returns hardcoded pricing per million tokens for supported models.
Last verified: 2026-02-15 Sources:
- Anthropic: https://platform.claude.com/docs/en/about-claude/pricing
- OpenAI: https://platform.openai.com/docs/pricing
- DeepSeek: https://api-docs.deepseek.com/quick_start/pricing
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, use --pricing with a JSON file. See LoadPricing.
func LoadPricing ¶
func LoadPricing(path string) (PricingTable, error)
type Querier ¶
type Querier interface {
Overview(ctx context.Context, filters Filters) (*Overview, error)
SessionDetail(ctx context.Context, sessionID string) (*SessionDetail, error)
AnalyticsOverview(ctx context.Context, filters Filters) (*AnalyticsOverview, error)
SessionAnalytics(ctx context.Context, sessionID string) (*SessionAnalytics, error)
}
Querier is an interface for querying session data. This allows for mock implementations in testing and sandboxes.
type Query ¶
type Query struct {
// contains filtered or unexported fields
}
func (*Query) AnalyticsOverview ¶
func (*Query) EntClient ¶
EntClient returns the underlying ent client for use by subsystems like the facet store.
func (*Query) SessionAnalytics ¶
func (*Query) SessionDetail ¶
type SessionAnalytics ¶
type SessionAnalytics struct {
SessionID string `json:"session_id"`
UserMessageCount int `json:"user_message_count"`
AssistantMsgCount int `json:"assistant_message_count"`
AvgResponseTimeNs int64 `json:"avg_response_time_ns"`
LongestPauseNs int64 `json:"longest_pause_ns"`
UniqueTools int `json:"unique_tools"`
ToolErrorCount int `json:"tool_error_count"`
TokensPerMinute float64 `json:"tokens_per_minute"`
AvgPromptLength int `json:"avg_prompt_length"`
AvgResponseLength int `json:"avg_response_length"`
FirstPrompt string `json:"first_prompt"`
}
SessionAnalytics holds per-session computed analytics.
type SessionDetail ¶
type SessionDetail struct {
Summary SessionSummary `json:"summary"`
Messages []SessionMessage `json:"messages"`
GroupedMessages []SessionMessageGroup `json:"grouped_messages,omitempty"`
ToolFrequency map[string]int `json:"tool_frequency"`
SubSessions []SessionSummary `json:"sub_sessions,omitempty"`
}
type SessionFacet ¶
type SessionFacet struct {
SessionID string `json:"session_id"`
UnderlyingGoal string `json:"underlying_goal"`
GoalCategory string `json:"goal_category"`
Outcome string `json:"outcome"`
SessionType string `json:"session_type"`
FrictionTypes []string `json:"friction_types"`
BriefSummary string `json:"brief_summary"`
ExtractedAt time.Time `json:"extracted_at"`
}
SessionFacet holds LLM-extracted qualitative data about a session.
type SessionMessage ¶
type SessionMessage struct {
Hash string `json:"hash"`
Role string `json:"role"`
Model string `json:"model"`
Timestamp time.Time `json:"timestamp"`
Delta time.Duration `json:"delta_ns"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
TotalTokens int64 `json:"total_tokens"`
InputCost float64 `json:"input_cost"`
OutputCost float64 `json:"output_cost"`
TotalCost float64 `json:"total_cost"`
ToolCalls []string `json:"tool_calls"`
Text string `json:"text"`
}
type SessionMessageGroup ¶
type SessionMessageGroup struct {
Role string `json:"role"`
StartTime time.Time `json:"start_time"`
EndTime time.Time `json:"end_time"`
Delta time.Duration `json:"delta_ns"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
TotalTokens int64 `json:"total_tokens"`
InputCost float64 `json:"input_cost"`
OutputCost float64 `json:"output_cost"`
TotalCost float64 `json:"total_cost"`
ToolCalls []string `json:"tool_calls"`
Text string `json:"text"`
Count int `json:"count"`
StartIndex int `json:"start_index"`
EndIndex int `json:"end_index"`
}
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"`
}