db

package
v0.23.1 Latest Latest
Warning

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

Go to latest
Published: Apr 19, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Overview

internal/db/session_stats.go

Index

Constants

View Source
const (

	// DefaultMessageLimit is the default number of messages returned.
	DefaultMessageLimit = 100
	// MaxMessageLimit is the maximum number of messages returned.
	MaxMessageLimit = 1000
)
View Source
const (
	DefaultSearchLimit = 50
	MaxSearchLimit     = 500
)
View Source
const (
	// DefaultSessionLimit is the default number of sessions returned.
	DefaultSessionLimit = 200
	// MaxSessionLimit is the maximum number of sessions returned.
	MaxSessionLimit = 500
)
View Source
const MaxHeatmapDays = 366

MaxHeatmapDays is the maximum number of day entries the heatmap will return. Ranges exceeding this are clamped to the most recent MaxHeatmapDays from the end date.

Variables

View Source
var ErrInvalidCursor = errors.New("invalid cursor")

ErrInvalidCursor is returned when a cursor cannot be decoded or verified.

View Source
var ErrReadOnly = errReadOnly{}

ErrReadOnly is returned by write methods on read-only store implementations (e.g. the PostgreSQL reader).

View Source
var ErrSessionExcluded = errors.New("session excluded")

ErrSessionExcluded is returned by UpsertSession when the session was permanently deleted by the user. Callers should skip any follow-up writes (messages, tool_calls) for this session.

View Source
var SystemMsgPrefixes = []string{
	"This session is being continued",
	"[Request interrupted",
	"<task-notification>",
	"<command-message>",
	"<command-name>",
	"<local-command-",
	"Stop hook feedback:",
}

SystemMsgPrefixes lists content prefixes that identify system-injected user messages. These are excluded from search results even when the is_system column has not been backfilled (e.g. Claude sessions parsed before schema version 2). Keep in sync with the frontend list in frontend/src/lib/utils/messages.ts.

Functions

func CurrentDataVersion added in v0.23.0

func CurrentDataVersion() int

CurrentDataVersion returns the current parser data version.

func IsAutomatedSession added in v0.18.0

func IsAutomatedSession(firstMessage string) bool

IsAutomatedSession returns true if the first message matches a known automated review/fix prompt pattern.

func SnapInterval added in v0.17.0

func SnapInterval(durationSec int64) int64

SnapInterval picks a bucket interval targeting ~30 buckets. For very long sessions the interval scales beyond the fixed step list so the total bucket count never exceeds maxBuckets.

func SystemPrefixSQL added in v0.16.0

func SystemPrefixSQL(contentCol, roleCol string) string

SystemPrefixSQL returns a SQL clause that excludes user messages matching any system prefix. The column alias for content must be passed (e.g. "m.content" or "m2.content"). Uses case-sensitive substr comparison, which behaves identically on SQLite and PostgreSQL (unlike LIKE, which is case-insensitive on SQLite).

Types

type ActivityEntry

type ActivityEntry struct {
	Date              string         `json:"date"`
	Sessions          int            `json:"sessions"`
	Messages          int            `json:"messages"`
	UserMessages      int            `json:"user_messages"`
	AssistantMessages int            `json:"assistant_messages"`
	ToolCalls         int            `json:"tool_calls"`
	ThinkingMessages  int            `json:"thinking_messages"`
	ByAgent           map[string]int `json:"by_agent"`
}

ActivityEntry is one time bucket in the activity timeline.

type ActivityResponse

type ActivityResponse struct {
	Granularity string          `json:"granularity"`
	Series      []ActivityEntry `json:"series"`
}

ActivityResponse wraps the activity series.

type AgentBreakdown added in v0.21.0

type AgentBreakdown struct {
	Agent               string  `json:"agent"`
	InputTokens         int     `json:"inputTokens"`
	OutputTokens        int     `json:"outputTokens"`
	CacheCreationTokens int     `json:"cacheCreationTokens"`
	CacheReadTokens     int     `json:"cacheReadTokens"`
	Cost                float64 `json:"cost"`
}

AgentBreakdown is the per-agent slice of a day's usage.

type AgentInfo added in v0.9.0

type AgentInfo struct {
	Name         string `json:"name"`
	SessionCount int    `json:"session_count"`
}

AgentInfo holds an agent name and its session count.

type AgentSummary

type AgentSummary struct {
	Sessions int `json:"sessions"`
	Messages int `json:"messages"`
}

AgentSummary holds per-agent counts for the summary.

type AnalyticsFilter

type AnalyticsFilter struct {
	From             string // ISO date YYYY-MM-DD, inclusive
	To               string // ISO date YYYY-MM-DD, inclusive
	Machine          string // optional machine filter
	Project          string // optional project filter
	Agent            string // optional agent filter
	Timezone         string // IANA timezone for day bucketing
	DayOfWeek        *int   // nil = all, 0=Mon, 6=Sun (ISO)
	Hour             *int   // nil = all, 0-23
	MinUserMessages  int    // user_message_count >= N
	ExcludeOneShot   bool   // exclude sessions with user_message_count <= 1
	ExcludeAutomated bool   // exclude automated (roborev) sessions
	ActiveSince      string // ISO timestamp cutoff
}

AnalyticsFilter is the shared filter for all analytics queries.

func (AnalyticsFilter) HasTimeFilter

func (f AnalyticsFilter) HasTimeFilter() bool

HasTimeFilter returns true when hour-of-day or day-of-week filtering is active.

type AnalyticsSummary

type AnalyticsSummary struct {
	TotalSessions          int                      `json:"total_sessions"`
	TotalMessages          int                      `json:"total_messages"`
	TotalOutputTokens      int                      `json:"total_output_tokens"`
	TokenReportingSessions int                      `json:"token_reporting_sessions"`
	ActiveProjects         int                      `json:"active_projects"`
	ActiveDays             int                      `json:"active_days"`
	AvgMessages            float64                  `json:"avg_messages"`
	MedianMessages         int                      `json:"median_messages"`
	P90Messages            int                      `json:"p90_messages"`
	MostActive             string                   `json:"most_active_project"`
	Concentration          float64                  `json:"concentration"`
	Agents                 map[string]*AgentSummary `json:"agents"`
}

AnalyticsSummary is the response for the summary endpoint.

type CacheHitRatioDistribution added in v0.23.0

type CacheHitRatioDistribution struct {
	Overall float64                `json:"overall"`
	Buckets []DistributionBucketV1 `json:"buckets"`
}

type DB

type DB struct {
	// contains filtered or unexported fields
}

DB manages a write connection and a read-only pool. The reader and writer fields use atomic.Pointer so that concurrent HTTP handler goroutines can safely read while Reopen/CloseConnections swap the underlying *sql.DB.

func Open

func Open(path string) (*DB, error)

Open creates or opens a SQLite database at the given path. It configures WAL mode, mmap, and returns a DB with separate writer and reader connections.

If an existing database has an outdated schema (missing columns), it is deleted and recreated from scratch. If the schema is current but the data version is stale, the database is preserved and file mtimes are reset to trigger a re-sync on the next cycle.

func (*DB) BackfillSignals added in v0.23.0

func (db *DB) BackfillSignals(
	ctx context.Context,
	computeFn func(ctx context.Context, sessionID string) error,
) error

BackfillSignals runs a one-time computation of session signals for all sessions. Guarded by a stats marker so it only runs once. computeFn returns nil on success or an error to signal that the per-session recompute could not be completed (e.g. the DB connection went away during a concurrent resync swap). The completion marker is only set when every session was processed successfully -- partial runs leave the marker unset so the next startup retries.

func (*DB) BulkStarSessions added in v0.11.0

func (db *DB) BulkStarSessions(sessionIDs []string) error

BulkStarSessions stars multiple sessions in a single transaction. Used for migrating localStorage stars to the database.

func (*DB) Close

func (db *DB) Close() error

Close closes both writer and reader connections, plus any retired pools left over from previous Reopen calls.

func (*DB) CloseConnections added in v0.8.0

func (db *DB) CloseConnections() error

CloseConnections closes both connections without reopening, releasing file locks so the database file can be renamed. Also drains any retired pools from previous Reopen calls. Callers must call Reopen afterwards to restore service.

func (*DB) CopyExcludedSessionsFrom added in v0.11.0

func (d *DB) CopyExcludedSessionsFrom(
	sourcePath string,
) error

CopyExcludedSessionsFrom copies the excluded_sessions table from the source DB so permanently deleted sessions survive full DB rebuilds. The source must not have active connections.

func (*DB) CopyInsightsFrom added in v0.8.0

func (db *DB) CopyInsightsFrom(sourcePath string) error

CopyInsightsFrom copies all insights from the database at sourcePath into this database using ATTACH/DETACH.

func (*DB) CopyOrphanedDataFrom added in v0.10.0

func (d *DB) CopyOrphanedDataFrom(
	sourcePath string,
) (int, error)

CopyOrphanedDataFrom copies sessions (and their messages and tool_calls) that exist in the source database but not in this database. This preserves archived sessions whose source files no longer exist on disk.

Orphaned sessions are identified by ID-diff: any session present in the source but absent from the target after a full file sync. This correctly captures sessions whose source files were deleted, moved, or otherwise lost — exactly the set that would be dropped by a naive DB swap.

The source database must not have active connections (call CloseConnections on its DB handle first). Uses ATTACH DATABASE on a pinned connection for atomicity.

func (*DB) CopySessionMetadataFrom added in v0.11.0

func (d *DB) CopySessionMetadataFrom(
	sourcePath string,
) error

CopySessionMetadataFrom merges user-managed data from the source DB into sessions that were re-synced into this DB. This preserves display_name, deleted_at, starred_sessions, and pinned_messages across full DB rebuilds.

func (*DB) DecodeCursor

func (db *DB) DecodeCursor(s string) (SessionCursor, error)

DecodeCursor parses a base64-encoded cursor string.

func (*DB) DeleteInsight added in v0.4.0

func (db *DB) DeleteInsight(id int64) error

DeleteInsight removes an insight by ID.

func (*DB) DeleteSession

func (db *DB) DeleteSession(id string) error

DeleteSession removes a session and its messages (cascading). The session ID is recorded in excluded_sessions so the sync engine does not re-import it from disk. Both operations run in a single transaction. The exclusion is only written when a session row was actually deleted, preventing ghost entries for non-existent IDs.

func (*DB) DeleteSessionIfTrashed added in v0.11.0

func (db *DB) DeleteSessionIfTrashed(id string) (int64, error)

DeleteSessionIfTrashed atomically deletes a session only if it is currently in the trash (deleted_at IS NOT NULL). Returns the number of rows affected. This avoids a TOCTOU race between checking deleted_at and performing the delete.

func (*DB) DeleteSessions

func (db *DB) DeleteSessions(ids []string) (int, error)

DeleteSessions removes multiple sessions by ID in a single transaction. Batches operations in groups of 500 to stay under SQLite variable limits. Deleted IDs are recorded in excluded_sessions so the sync engine does not re-import them. Returns count of deleted rows.

func (*DB) DeleteSkippedFile added in v0.5.0

func (db *DB) DeleteSkippedFile(path string) error

DeleteSkippedFile removes a single skip cache entry.

func (*DB) DropFTS added in v0.8.0

func (db *DB) DropFTS() error

DropFTS drops the FTS table and its triggers. This makes bulk message delete+reinsert fast by avoiding per-row FTS index updates. Call RebuildFTS after to restore search.

func (*DB) EmptyTrash added in v0.11.0

func (db *DB) EmptyTrash() (int, error)

EmptyTrash permanently deletes all soft-deleted sessions. Session IDs are recorded in excluded_sessions so the sync engine does not re-import them. Both operations run in a single transaction to prevent ghost exclusions when the delete fails. Returns the count of deleted rows.

func (*DB) EncodeCursor

func (db *DB) EncodeCursor(endedAt, id string, total ...int) string

EncodeCursor returns a base64-encoded cursor string.

func (*DB) FileBackedSessionCount added in v0.8.0

func (db *DB) FileBackedSessionCount(
	ctx context.Context,
) (int, error)

FileBackedSessionCount returns the number of root sessions synced from files (excludes non-file-backed agents like OpenCode and Claude.ai). Used by ResyncAll to decide whether empty file discovery should abort the swap.

func (*DB) FindPruneCandidates

func (db *DB) FindPruneCandidates(
	f PruneFilter,
) ([]Session, error)

FindPruneCandidates returns sessions matching all filter criteria. Returns full Session rows including file metadata.

func (*DB) FindSessionIDsByPartial added in v0.23.0

func (db *DB) FindSessionIDsByPartial(
	ctx context.Context, partial string, limit int,
) ([]string, error)

FindSessionIDsByPartial returns up to limit session IDs that contain the given substring. Used by CLI lookups so users can reference sessions by a short prefix shown in list output. Excludes soft-deleted sessions.

func (*DB) FindSessionIDsByRawSuffix added in v0.23.0

func (db *DB) FindSessionIDsByRawSuffix(
	ctx context.Context, raw string, limit int,
) ([]string, error)

FindSessionIDsByRawSuffix returns up to limit session IDs whose stored id is either the exact raw input or the raw input preceded by an agent prefix (e.g. "codex:<uuid>"). The suffix comparison uses SUBSTR rather than LIKE so that SQL wildcard characters ('_' and '%') present in session IDs (which permit underscores) are compared literally instead of matching any character. Results are sorted by most recently active first. Excludes soft-deleted sessions.

func (*DB) GetAgents added in v0.9.0

func (db *DB) GetAgents(
	ctx context.Context,
	excludeOneShot, excludeAutomated bool,
) ([]AgentInfo, error)

GetAgents returns distinct agent names with session counts.

func (*DB) GetAllMessages

func (db *DB) GetAllMessages(
	ctx context.Context, sessionID string,
) ([]Message, error)

GetAllMessages returns all messages for a session ordered by ordinal.

func (*DB) GetAnalyticsActivity

func (db *DB) GetAnalyticsActivity(
	ctx context.Context, f AnalyticsFilter,
	granularity string,
) (ActivityResponse, error)

GetAnalyticsActivity returns session/message counts grouped by time bucket.

func (*DB) GetAnalyticsHeatmap

func (db *DB) GetAnalyticsHeatmap(
	ctx context.Context, f AnalyticsFilter,
	metric string,
) (HeatmapResponse, error)

GetAnalyticsHeatmap returns daily counts with intensity levels.

func (*DB) GetAnalyticsHourOfWeek

func (db *DB) GetAnalyticsHourOfWeek(
	ctx context.Context, f AnalyticsFilter,
) (HourOfWeekResponse, error)

GetAnalyticsHourOfWeek returns message counts bucketed by day-of-week and hour-of-day in the user's timezone.

func (*DB) GetAnalyticsProjects

func (db *DB) GetAnalyticsProjects(
	ctx context.Context, f AnalyticsFilter,
) (ProjectsAnalyticsResponse, error)

GetAnalyticsProjects returns per-project analytics.

func (*DB) GetAnalyticsSessionShape

func (db *DB) GetAnalyticsSessionShape(
	ctx context.Context, f AnalyticsFilter,
) (SessionShapeResponse, error)

GetAnalyticsSessionShape returns distribution histograms for session length, duration, and autonomy ratio.

func (*DB) GetAnalyticsSignals added in v0.23.0

func (db *DB) GetAnalyticsSignals(
	ctx context.Context, f AnalyticsFilter,
) (SignalsAnalyticsResponse, error)

GetAnalyticsSignals returns aggregated session signal data.

func (*DB) GetAnalyticsSummary

func (db *DB) GetAnalyticsSummary(
	ctx context.Context, f AnalyticsFilter,
) (AnalyticsSummary, error)

GetAnalyticsSummary returns aggregate statistics.

func (*DB) GetAnalyticsTools

func (db *DB) GetAnalyticsTools(
	ctx context.Context, f AnalyticsFilter,
) (ToolsAnalyticsResponse, error)

GetAnalyticsTools returns tool usage analytics aggregated from the tool_calls table.

func (*DB) GetAnalyticsTopSessions

func (db *DB) GetAnalyticsTopSessions(
	ctx context.Context, f AnalyticsFilter, metric string,
) (TopSessionsResponse, error)

GetAnalyticsTopSessions returns the top 10 sessions by the given metric ("messages", "duration", or "output_tokens") within the filter.

func (*DB) GetAnalyticsVelocity

func (db *DB) GetAnalyticsVelocity(
	ctx context.Context, f AnalyticsFilter,
) (VelocityResponse, error)

GetAnalyticsVelocity computes turn cycle, first response, and throughput metrics with breakdowns by agent and complexity.

func (*DB) GetChildSessions added in v0.7.0

func (db *DB) GetChildSessions(
	ctx context.Context, parentID string,
) ([]Session, error)

GetChildSessions returns sessions whose parent_session_id matches the given parentID, ordered by started_at ascending.

func (*DB) GetDailyUsage added in v0.20.0

func (db *DB) GetDailyUsage(
	ctx context.Context, f UsageFilter,
) (DailyUsageResult, error)

GetDailyUsage returns token usage and cost aggregated by day. It scans messages with non-empty token_usage JSON blobs, parses them in Go (faster than SQLite's json_extract per row), joins against an in-memory pricing map, and buckets by local date.

func (*DB) GetDataVersionByPath added in v0.23.0

func (db *DB) GetDataVersionByPath(path string) int

GetDataVersionByPath returns the minimum data_version for sessions matching a file_path. Returns 0 when no session exists for the path.

func (*DB) GetFileInfoByPath added in v0.4.1

func (db *DB) GetFileInfoByPath(
	path string,
) (size int64, mtime int64, ok bool)

GetFileInfoByPath returns file_size and file_mtime for a session identified by file_path. Used for codex/gemini files where the session ID requires parsing.

func (*DB) GetInsight added in v0.4.0

func (db *DB) GetInsight(
	ctx context.Context, id int64,
) (*Insight, error)

GetInsight returns a single insight by ID. Returns nil, nil if not found.

func (*DB) GetMachines

func (db *DB) GetMachines(
	ctx context.Context,
	excludeOneShot, excludeAutomated bool,
) ([]string, error)

GetMachines returns distinct machine names.

func (*DB) GetMessageByOrdinal

func (db *DB) GetMessageByOrdinal(
	sessionID string, ordinal int,
) (*Message, error)

GetMessageByOrdinal returns a single message by session ID and ordinal.

func (*DB) GetMessages

func (db *DB) GetMessages(
	ctx context.Context,
	sessionID string, from, limit int, asc bool,
) ([]Message, error)

GetMessages returns paginated messages for a session. from: starting ordinal (inclusive) limit: max messages to return asc: true for ascending ordinal order, false for descending

func (*DB) GetModelPricing added in v0.20.0

func (db *DB) GetModelPricing(
	model string,
) (*ModelPricing, error)

GetModelPricing returns pricing for an exact model match. Returns nil, nil if not found.

func (*DB) GetPinnedMessageIDs added in v0.11.0

func (db *DB) GetPinnedMessageIDs(
	ctx context.Context, sessionID string,
) (map[int64]bool, error)

GetPinnedMessageIDs returns message IDs that are pinned for a session.

func (*DB) GetPricingMeta added in v0.22.2

func (db *DB) GetPricingMeta(key string) (string, error)

GetPricingMeta reads a metadata value stored as a sentinel row in model_pricing. Returns "" if not found.

func (*DB) GetProjects

func (db *DB) GetProjects(
	ctx context.Context,
	excludeOneShot, excludeAutomated bool,
) ([]ProjectInfo, error)

GetProjects returns project names with session counts.

func (*DB) GetSession

func (db *DB) GetSession(
	ctx context.Context, id string,
) (*Session, error)

GetSession returns a single session by ID, excluding soft-deleted (trashed) sessions.

func (*DB) GetSessionActivity added in v0.17.0

func (d *DB) GetSessionActivity(
	ctx context.Context, sessionID string,
) (*SessionActivityResponse, error)

GetSessionActivity returns time-bucketed message counts for a session. Only visible messages are counted (system and prefix-detected injected messages excluded).

func (*DB) GetSessionDataVersion added in v0.23.0

func (db *DB) GetSessionDataVersion(id string) int

GetSessionDataVersion returns the data_version for a session. Returns 0 when the session does not exist.

func (*DB) GetSessionFileInfo

func (db *DB) GetSessionFileInfo(
	id string,
) (size int64, mtime int64, ok bool)

GetSessionFileInfo returns file_size and file_mtime for a session. Used for fast skip checks during sync.

func (*DB) GetSessionFilePath added in v0.14.0

func (db *DB) GetSessionFilePath(id string) string

GetSessionFilePath returns the stored file_path for a session, or empty string if not found or NULL.

func (*DB) GetSessionForIncremental added in v0.13.0

func (db *DB) GetSessionForIncremental(
	path string,
) (*IncrementalInfo, bool)

GetSessionForIncremental returns session state needed for incremental parsing, looked up by file_path. Returns false when the path is unknown or maps to multiple sessions (e.g. Claude DAG forks), since incremental parsing cannot update multiple sessions from a single append.

func (*DB) GetSessionFull

func (db *DB) GetSessionFull(
	ctx context.Context, id string,
) (*Session, error)

GetSessionFull returns a single session by ID with all file metadata.

func (*DB) GetSessionMessageCount added in v0.13.0

func (db *DB) GetSessionMessageCount(
	id string,
) (count int, ok bool)

GetSessionMessageCount returns the message_count for a session. Returns (0, false) when the session does not exist.

func (*DB) GetSessionStats added in v0.23.0

func (db *DB) GetSessionStats(
	ctx context.Context, f StatsFilter,
) (*SessionStats, error)

GetSessionStats computes the v1 session-stats JSON response. Sections are populated in order so each step can reuse the per-session rows (and derived sessionIDs) loaded once by loadSessionsInWindow.

func (*DB) GetSessionVersion added in v0.13.0

func (db *DB) GetSessionVersion(
	id string,
) (count int, fileMtime int64, ok bool)

GetSessionVersion returns the message count and file mtime for change detection in SSE watchers.

func (*DB) GetStats

func (db *DB) GetStats(
	ctx context.Context,
	excludeOneShot, excludeAutomated bool,
) (Stats, error)

GetStats returns database statistics, counting only root sessions with messages (matching the session list filter).

func (*DB) GetSyncState added in v0.16.0

func (db *DB) GetSyncState(key string) (string, error)

GetSyncState reads a value from the pg_sync_state table.

func (*DB) GetTopSessionsByCost added in v0.21.0

func (db *DB) GetTopSessionsByCost(
	ctx context.Context, f UsageFilter, limit int,
) ([]TopSessionEntry, error)

GetTopSessionsByCost returns sessions ranked by total cost over the filter range. Default limit 20, max 100.

func (*DB) GetUsageSessionCounts added in v0.21.0

func (db *DB) GetUsageSessionCounts(
	ctx context.Context, f UsageFilter,
) (UsageSessionCounts, error)

GetUsageSessionCounts returns distinct session counts grouped by project and agent. Sessions spanning multiple days count once. Soft-deleted sessions are excluded via usageMessageEligibility.

Like GetDailyUsage and GetTopSessionsByCost, this query pads the UTC bounds by +/-14h and applies a post-query localDate filter so timezone-boundary messages are counted correctly.

func (*DB) HasFTS

func (db *DB) HasFTS() bool

HasFTS checks if Full Text Search is available.

func (*DB) InsertInsight added in v0.4.0

func (db *DB) InsertInsight(s Insight) (int64, error)

InsertInsight inserts an insight and returns its ID.

func (*DB) InsertMessages

func (db *DB) InsertMessages(msgs []Message) error

InsertMessages batch-inserts messages for a session.

func (*DB) IsSessionExcluded added in v0.11.0

func (db *DB) IsSessionExcluded(id string) bool

IsSessionExcluded returns true if the session ID was permanently deleted by the user.

func (*DB) LinkSubagentSessions added in v0.14.0

func (db *DB) LinkSubagentSessions() error

LinkSubagentSessions sets parent_session_id and relationship_type on sessions that are referenced by tool_calls.subagent_session_id. Updates sessions that either have no parent yet or have a non-subagent relationship (e.g. a Zencoder session classified as "continuation" from header parentId that is actually a spawned subagent).

func (*DB) ListInsights added in v0.4.0

func (db *DB) ListInsights(
	ctx context.Context, f InsightFilter,
) ([]Insight, error)

ListInsights returns insights matching the filter, ordered by created_at DESC, capped at 500 rows.

func (*DB) ListModelPricing added in v0.23.0

func (db *DB) ListModelPricing(
	ctx context.Context,
) ([]ModelPricing, error)

ListModelPricing returns every pricing row, including sentinel metadata rows (for example `_fallback_version`).

func (*DB) ListPinnedMessages added in v0.11.0

func (db *DB) ListPinnedMessages(
	ctx context.Context, sessionID string, project string,
) ([]PinnedMessage, error)

ListPinnedMessages returns all pins, optionally filtered by session or project. Pass empty sessionID for all pins across all sessions. When listing all pins, message content and role are included. project is only applied when sessionID is empty.

func (*DB) ListSessions

func (db *DB) ListSessions(
	ctx context.Context, f SessionFilter,
) (SessionPage, error)

ListSessions returns a cursor-paginated list of sessions.

func (*DB) ListSessionsModifiedBetween added in v0.16.0

func (db *DB) ListSessionsModifiedBetween(
	ctx context.Context, since, until string,
	projects, excludeProjects []string,
) ([]Session, error)

ListSessionsModifiedBetween returns all sessions created or modified after since and at or before until.

Uses file_mtime (nanoseconds since epoch from the source file) as the primary modification signal so that active sessions with new messages are detected even when ended_at has not changed. Falls back to session timestamps for rows without file_mtime.

Precision note: file_mtime is compared as nanosecond integers, while text timestamps are normalized to millisecond precision (strftime '%f' -> 3 decimal places). Sub-millisecond differences in text timestamp fields are therefore truncated.

func (*DB) ListStarredSessionIDs added in v0.11.0

func (db *DB) ListStarredSessionIDs(
	ctx context.Context,
) ([]string, error)

ListStarredSessionIDs returns all starred session IDs.

func (*DB) ListTrashedSessions added in v0.11.0

func (db *DB) ListTrashedSessions(
	ctx context.Context,
) ([]Session, error)

ListTrashedSessions returns sessions that have been soft-deleted.

func (*DB) LoadRemoteSkippedFiles added in v0.23.0

func (db *DB) LoadRemoteSkippedFiles(
	host string,
) (map[string]int64, error)

LoadRemoteSkippedFiles returns persisted skip cache entries for the given remote host as a map from path to file_mtime.

func (*DB) LoadSkippedFiles added in v0.5.0

func (db *DB) LoadSkippedFiles() (map[string]int64, error)

LoadSkippedFiles returns all persisted skip cache entries as a map from file_path to file_mtime.

func (*DB) MarkSignalsBackfillDone added in v0.23.0

func (db *DB) MarkSignalsBackfillDone() error

MarkSignalsBackfillDone records that legacy signal backfill is no longer needed for this database. Set after a fresh resync, where every session is rewritten through the inline signal path, so the post-resync BackfillSignals call is a no-op.

func (*DB) MaxOrdinal added in v0.5.0

func (db *DB) MaxOrdinal(sessionID string) int

MaxOrdinal returns the highest ordinal for a session, or -1 if the session has no messages.

func (*DB) MessageContentFingerprint added in v0.16.0

func (db *DB) MessageContentFingerprint(sessionID string) (sum, max, min int64, err error)

MessageContentFingerprint returns a lightweight fingerprint of all messages for a session, computed as the sum, max, and min of content_length values.

func (*DB) MessageCount

func (db *DB) MessageCount(sessionID string) (int, error)

MessageCount returns the number of messages for a session.

func (*DB) MessageTokenFingerprint added in v0.18.0

func (db *DB) MessageTokenFingerprint(sessionID string) (string, error)

MessageTokenFingerprint returns an exact ordered fingerprint of stored token metadata for a session's messages. Used by PG push fast-paths to detect token metadata changes without rewriting unchanged sessions. Includes the source-tracking columns so metadata-only changes invalidate the fast path.

func (*DB) NeedsResync added in v0.10.0

func (db *DB) NeedsResync() bool

NeedsResync reports whether the database was opened with a stale data version, indicating the caller should trigger a full resync (build fresh DB, copy orphaned data, swap) rather than an incremental sync.

func (*DB) Path added in v0.8.0

func (db *DB) Path() string

Path returns the file path of the database.

func (*DB) PendingSignalSessions added in v0.23.0

func (db *DB) PendingSignalSessions(
	ctx context.Context, cutoff string,
) ([]string, error)

PendingSignalSessions returns session IDs whose signals_pending_since is non-NULL and older than cutoff.

func (*DB) PinMessage added in v0.11.0

func (db *DB) PinMessage(
	sessionID string, messageID int64, note *string,
) (int64, error)

PinMessage creates a pin for a message. If the message is already pinned, the note is updated. The message must belong to the specified session (enforced via INSERT ... SELECT).

func (*DB) PurgeExcludedSessions added in v0.11.0

func (db *DB) PurgeExcludedSessions() error

PurgeExcludedSessions removes any session rows whose IDs appear in excluded_sessions. Used after a resync to clean up sessions that were synced before their exclusion was recorded.

func (*DB) ReadOnly added in v0.16.0

func (db *DB) ReadOnly() bool

ReadOnly returns false for the local SQLite store.

func (*DB) Reader

func (db *DB) Reader() *sql.DB

Reader returns the read-only connection pool.

func (*DB) RebuildFTS added in v0.8.0

func (db *DB) RebuildFTS() error

RebuildFTS recreates the FTS table, triggers, and repopulates the index from the messages table.

func (*DB) RenameSession added in v0.11.0

func (db *DB) RenameSession(id string, displayName *string) error

RenameSession sets or clears the display_name for a session. Pass nil to clear a custom name (reverts to first_message).

func (*DB) Reopen added in v0.8.0

func (db *DB) Reopen() error

Reopen closes and reopens both connections to the same path. Used after an atomic file swap to pick up the new database contents. Preserves cursorSecret.

func (*DB) ReplaceRemoteSkippedFiles added in v0.23.0

func (db *DB) ReplaceRemoteSkippedFiles(
	host string, entries map[string]int64,
) error

ReplaceRemoteSkippedFiles replaces all skip cache entries for the given host in a single transaction. Entries for other hosts are not affected.

func (*DB) ReplaceSessionMessages

func (db *DB) ReplaceSessionMessages(
	sessionID string, msgs []Message,
) error

ReplaceSessionMessages deletes existing and inserts new messages in a single transaction. Any existing pins are preserved by re-attaching them to the new message rows that share the same ordinal (pins for ordinals that no longer exist are dropped).

func (*DB) ReplaceSkippedFiles added in v0.5.0

func (db *DB) ReplaceSkippedFiles(
	entries map[string]int64,
) error

ReplaceSkippedFiles replaces all skip cache entries in a single transaction. This is called after each sync cycle to persist the in-memory skip cache.

func (*DB) ResetAllMtimes added in v0.6.0

func (db *DB) ResetAllMtimes() error

ResetAllMtimes zeroes file_mtime for every session, forcing the next sync to re-process all files regardless of whether their size+mtime matches what was previously stored.

func (*DB) RestoreSession added in v0.11.0

func (db *DB) RestoreSession(id string) (int64, error)

RestoreSession clears deleted_at, making the session visible again. Returns the number of rows affected (0 if session doesn't exist or is not in trash).

func (*DB) Search

func (db *DB) Search(
	ctx context.Context, f SearchFilter,
) (SearchPage, error)

Search performs FTS5 full-text search across messages, grouped by session, plus a LIKE-based search on session display names and first messages.

Results come from two branches joined with UNION ALL:

  1. FTS branch — message content matches. ROW_NUMBER() picks the single best-ranked message per session (rank ASC, ordinal ASC, rowid ASC). The outer JOIN messages_fts includes a MATCH clause to prevent segment duplicates. Ordinal is the matched message's ordinal (≥ 0).

  2. Name branch — display_name / first_message LIKE matches that are NOT already covered by the FTS branch. Ordinal is -1 (no specific message to navigate to).

func (*DB) SearchSession added in v0.14.0

func (db *DB) SearchSession(
	ctx context.Context, sessionID, query string,
) ([]int, error)

SearchSession performs a case-insensitive substring search within a single session's messages, returning matching ordinals in document order. This is used by the in-session find bar (analogous to browser Cmd+F). Both message content and tool-call result_content are searched so that matches inside tool output blocks are reachable. Only fields that the frontend renders and highlights are included to avoid phantom matches.

func (*DB) SetCursorSecret

func (db *DB) SetCursorSecret(secret []byte)

SetCursorSecret updates the secret key used for cursor signing.

func (*DB) SetPricingMeta added in v0.22.2

func (db *DB) SetPricingMeta(key, value string) error

SetPricingMeta stores a metadata value as a sentinel row in model_pricing with zero pricing fields.

func (*DB) SetSessionDataVersion added in v0.23.0

func (db *DB) SetSessionDataVersion(id string, version int) error

SetSessionDataVersion stamps the parser data_version on a session row. Call this only after the associated message rewrite has succeeded -- skipping it on failure ensures the next sync re-parses the file instead of treating it as already current. Bumps local_modified_at so the change propagates through the next pg push.

func (*DB) SetSyncState added in v0.16.0

func (db *DB) SetSyncState(key, value string) error

SetSyncState writes a value to the pg_sync_state table.

func (*DB) SoftDeleteSession added in v0.11.0

func (db *DB) SoftDeleteSession(id string) error

SoftDeleteSession marks a session as deleted by setting deleted_at.

func (*DB) StarSession added in v0.11.0

func (db *DB) StarSession(sessionID string) (bool, error)

StarSession marks a session as starred. Uses INSERT...SELECT with an EXISTS check so the operation is atomic and avoids FK errors if the session is concurrently deleted. Returns false if the session does not exist (idempotent for already-starred).

func (*DB) SystemMessageFingerprint added in v0.16.0

func (db *DB) SystemMessageFingerprint(sessionID string) (string, error)

SystemMessageFingerprint returns the ordered, comma-separated list of ordinals for system messages in a session (e.g. "0,2,5"). This is an exact fingerprint of the system-message ordinal set: any reclassification of which messages are system — even when counts, sums, or sums-of-squares remain equal — produces a different string. Used by the PG push fast-path.

func (*DB) ToolCallContentFingerprint added in v0.16.0

func (db *DB) ToolCallContentFingerprint(sessionID string) (int64, error)

ToolCallContentFingerprint returns the sum of result_content_length values for a session's tool calls, used as a lightweight content change detector.

func (*DB) ToolCallCount added in v0.16.0

func (db *DB) ToolCallCount(sessionID string) (int, error)

ToolCallCount returns the number of tool_calls rows for a session.

func (*DB) UnpinMessage added in v0.11.0

func (db *DB) UnpinMessage(sessionID string, messageID int64) error

UnpinMessage removes a pin.

func (*DB) UnstarSession added in v0.11.0

func (db *DB) UnstarSession(sessionID string) error

UnstarSession removes a session's star.

func (*DB) Update

func (db *DB) Update(fn func(tx *sql.Tx) error) error

Update executes fn within a write lock and transaction. The transaction is committed if fn returns nil, rolled back otherwise.

func (*DB) UpdateSessionIncremental added in v0.13.0

func (db *DB) UpdateSessionIncremental(
	id string,
	endedAt *string,
	msgCount, userMsgCount int,
	fileSize, fileMtime int64,
	totalOutputTokens, peakContextTokens int,
	hasTotalOutputTokens, hasPeakContextTokens bool,
) error

UpdateSessionIncremental updates only the fields that change during an incremental append: ended_at, message_count, user_message_count, file_size, file_mtime, and token aggregates. All values are absolute (not deltas) so the update is idempotent on retry.

func (*DB) UpdateSessionSignals added in v0.23.0

func (db *DB) UpdateSessionSignals(
	sessionID string, u SessionSignalUpdate,
) error

UpdateSessionSignals persists computed signal values on the sessions table. Bumps local_modified_at so the session is re-selected by the next pg push -- a recomputed signal column is a change to the row from PG's perspective, even when the inline write path didn't touch anything else (e.g. a one-time BackfillSignals run after a schema migration).

func (*DB) UpsertModelPricing added in v0.20.0

func (db *DB) UpsertModelPricing(
	prices []ModelPricing,
) error

UpsertModelPricing inserts or replaces pricing rows in a single transaction.

func (*DB) UpsertSession

func (db *DB) UpsertSession(s Session) error

UpsertSession inserts or updates a session. Sessions that were permanently deleted (in excluded_sessions) are silently skipped.

func (*DB) Vacuum added in v0.23.0

func (db *DB) Vacuum() error

Vacuum runs VACUUM on the database to reclaim space.

type DailyUsageEntry added in v0.20.0

type DailyUsageEntry struct {
	Date                string             `json:"date"`
	InputTokens         int                `json:"inputTokens"`
	OutputTokens        int                `json:"outputTokens"`
	CacheCreationTokens int                `json:"cacheCreationTokens"`
	CacheReadTokens     int                `json:"cacheReadTokens"`
	TotalCost           float64            `json:"totalCost"`
	ModelsUsed          []string           `json:"modelsUsed"`
	ModelBreakdowns     []ModelBreakdown   `json:"modelBreakdowns,omitempty"`
	ProjectBreakdowns   []ProjectBreakdown `json:"projectBreakdowns,omitempty"`
	AgentBreakdowns     []AgentBreakdown   `json:"agentBreakdowns,omitempty"`
}

DailyUsageEntry holds token counts and cost for one day.

type DailyUsageResult added in v0.20.0

type DailyUsageResult struct {
	Daily  []DailyUsageEntry `json:"daily"`
	Totals UsageTotals       `json:"totals"`
}

DailyUsageResult wraps the daily entries and totals.

type DistributionBucket

type DistributionBucket struct {
	Label string `json:"label"`
	Count int    `json:"count"`
}

DistributionBucket is a labeled count for histogram display.

type DistributionBucketV1 added in v0.23.0

type DistributionBucketV1 struct {
	// Edge is [lo, hi]; hi may be JSON null for the unbounded top bucket.
	Edge  [2]*float64 `json:"edge"`
	Count int         `json:"count"`
}

type HeatmapEntry

type HeatmapEntry struct {
	Date  string `json:"date"`
	Value int    `json:"value"`
	Level int    `json:"level"`
}

HeatmapEntry is one day in the heatmap calendar.

type HeatmapLevels

type HeatmapLevels struct {
	L1 int `json:"l1"`
	L2 int `json:"l2"`
	L3 int `json:"l3"`
	L4 int `json:"l4"`
}

HeatmapLevels defines the quartile thresholds for levels 1-4.

type HeatmapResponse

type HeatmapResponse struct {
	Metric      string         `json:"metric"`
	Entries     []HeatmapEntry `json:"entries"`
	Levels      HeatmapLevels  `json:"levels"`
	EntriesFrom string         `json:"entries_from"`
}

HeatmapResponse wraps the heatmap data.

type HourOfWeekCell

type HourOfWeekCell struct {
	DayOfWeek int `json:"day_of_week"` // 0=Mon, 6=Sun
	Hour      int `json:"hour"`        // 0-23
	Messages  int `json:"messages"`
}

HourOfWeekCell is one cell in the 7x24 hour-of-week grid.

type HourOfWeekResponse

type HourOfWeekResponse struct {
	Cells []HourOfWeekCell `json:"cells"`
}

HourOfWeekResponse wraps the hour-of-week heatmap data.

type IncrementalInfo added in v0.13.0

type IncrementalInfo struct {
	ID                   string
	FileSize             int64
	FileMtime            int64
	FileInode            int64
	FileDevice           int64
	MsgCount             int
	UserMsgCount         int
	TotalOutputTokens    int
	PeakContextTokens    int
	HasTotalOutputTokens bool
	HasPeakContextTokens bool
}

IncrementalInfo holds the data needed for incremental re-parsing of an append-only session file.

type Insight added in v0.4.0

type Insight struct {
	ID        int64   `json:"id"`
	Type      string  `json:"type"`
	DateFrom  string  `json:"date_from"`
	DateTo    string  `json:"date_to"`
	Project   *string `json:"project"`
	Agent     string  `json:"agent"`
	Model     *string `json:"model"`
	Prompt    *string `json:"prompt"`
	Content   string  `json:"content"`
	CreatedAt string  `json:"created_at"`
}

Insight represents a row in the insights table.

type InsightFilter added in v0.4.0

type InsightFilter struct {
	Type       string // "daily_activity" or "agent_analysis"
	Project    string // "" = no filter
	GlobalOnly bool   // true = project IS NULL only
}

InsightFilter specifies how to query insights.

type Message

type Message struct {
	ID        int64  `json:"id"`
	SessionID string `json:"session_id"`
	Ordinal   int    `json:"ordinal"`
	Role      string `json:"role"`
	Content   string `json:"content"`
	// ThinkingText holds the concatenated text of all thinking
	// blocks for this message; "" if none.
	ThinkingText      string          `json:"thinking_text"`
	Timestamp         string          `json:"timestamp"`
	HasThinking       bool            `json:"has_thinking"`
	HasToolUse        bool            `json:"has_tool_use"`
	ContentLength     int             `json:"content_length"`
	Model             string          `json:"model"`
	TokenUsage        json.RawMessage `json:"token_usage,omitempty"`
	ContextTokens     int             `json:"context_tokens"`
	OutputTokens      int             `json:"output_tokens"`
	HasContextTokens  bool            `json:"has_context_tokens"`
	HasOutputTokens   bool            `json:"has_output_tokens"`
	ClaudeMessageID   string          `json:"claude_message_id,omitempty"`
	ClaudeRequestID   string          `json:"claude_request_id,omitempty"`
	ToolCalls         []ToolCall      `json:"tool_calls,omitempty"`
	ToolResults       []ToolResult    `json:"-"`         // transient, for pairing
	IsSystem          bool            `json:"is_system"` // persisted, filters search/analytics
	SourceType        string          `json:"source_type,omitempty"`
	SourceSubtype     string          `json:"source_subtype,omitempty"`
	SourceUUID        string          `json:"source_uuid,omitempty"`
	SourceParentUUID  string          `json:"source_parent_uuid,omitempty"`
	IsSidechain       bool            `json:"is_sidechain,omitempty"`
	IsCompactBoundary bool            `json:"is_compact_boundary,omitempty"`
}

Message represents a row in the messages table.

func (Message) TokenPresence added in v0.18.0

func (m Message) TokenPresence() (bool, bool)

TokenPresence reports whether context/output token fields were present in stored message metadata. It preserves explicit flags, falls back to non-zero numeric values for legacy rows, and inspects raw token_usage payload keys to preserve zero-valued coverage.

type ModelBreakdown added in v0.20.0

type ModelBreakdown struct {
	ModelName           string  `json:"modelName"`
	InputTokens         int     `json:"inputTokens"`
	OutputTokens        int     `json:"outputTokens"`
	CacheCreationTokens int     `json:"cacheCreationTokens"`
	CacheReadTokens     int     `json:"cacheReadTokens"`
	Cost                float64 `json:"cost"`
}

ModelBreakdown holds per-model token and cost breakdown.

type ModelPricing added in v0.20.0

type ModelPricing struct {
	ModelPattern         string  `json:"model_pattern"`
	InputPerMTok         float64 `json:"input_per_mtok"`
	OutputPerMTok        float64 `json:"output_per_mtok"`
	CacheCreationPerMTok float64 `json:"cache_creation_per_mtok"`
	CacheReadPerMTok     float64 `json:"cache_read_per_mtok"`
	UpdatedAt            string  `json:"updated_at"`
}

ModelPricing holds per-model token pricing (per million tokens).

type PeakContextDistribution added in v0.23.0

type PeakContextDistribution struct {
	ScopeAll   ScopedDistribution `json:"scope_all"`
	ScopeHuman ScopedDistribution `json:"scope_human"`
	NullCount  int                `json:"null_count"`
	ClaudeOnly bool               `json:"claude_only"`
}

type Percentiles

type Percentiles struct {
	P50 float64 `json:"p50"`
	P90 float64 `json:"p90"`
}

Percentiles holds p50 and p90 values.

type PinnedMessage added in v0.11.0

type PinnedMessage struct {
	ID        int64   `json:"id"`
	SessionID string  `json:"session_id"`
	MessageID int64   `json:"message_id"`
	Ordinal   int     `json:"ordinal"`
	Note      *string `json:"note,omitempty"`
	Content   *string `json:"content,omitempty"`
	Role      *string `json:"role,omitempty"`
	CreatedAt string  `json:"created_at"`

	// Session metadata — populated only for the "all pins" query.
	SessionProject      *string `json:"session_project,omitempty"`
	SessionAgent        *string `json:"session_agent,omitempty"`
	SessionDisplayName  *string `json:"session_display_name,omitempty"`
	SessionFirstMessage *string `json:"session_first_message,omitempty"`
}

PinnedMessage represents a row in the pinned_messages table.

type ProjectAnalytics

type ProjectAnalytics struct {
	Name           string         `json:"name"`
	Sessions       int            `json:"sessions"`
	Messages       int            `json:"messages"`
	FirstSession   string         `json:"first_session"`
	LastSession    string         `json:"last_session"`
	AvgMessages    float64        `json:"avg_messages"`
	MedianMessages int            `json:"median_messages"`
	Agents         map[string]int `json:"agents"`
	DailyTrend     float64        `json:"daily_trend"`
}

ProjectAnalytics holds analytics for a single project.

type ProjectBreakdown added in v0.21.0

type ProjectBreakdown struct {
	Project             string  `json:"project"`
	InputTokens         int     `json:"inputTokens"`
	OutputTokens        int     `json:"outputTokens"`
	CacheCreationTokens int     `json:"cacheCreationTokens"`
	CacheReadTokens     int     `json:"cacheReadTokens"`
	Cost                float64 `json:"cost"`
}

ProjectBreakdown is the per-project slice of a day's usage.

type ProjectInfo

type ProjectInfo struct {
	Name         string `json:"name"`
	SessionCount int    `json:"session_count"`
}

ProjectInfo holds a project name and its session count.

type ProjectsAnalyticsResponse

type ProjectsAnalyticsResponse struct {
	Projects []ProjectAnalytics `json:"projects"`
}

ProjectsAnalyticsResponse wraps the projects list.

type PruneFilter

type PruneFilter struct {
	Project      string // substring match (LIKE '%x%')
	MaxMessages  *int   // user messages <= N (nil = no filter)
	Before       string // ended_at < date (YYYY-MM-DD)
	FirstMessage string // first_message LIKE 'prefix%'
}

PruneFilter defines criteria for finding sessions to prune. Filters combine with AND. At least one must be set.

func (PruneFilter) HasFilters

func (f PruneFilter) HasFilters() bool

HasFilters reports whether at least one filter is set.

type ScopedDistribution added in v0.23.0

type ScopedDistribution struct {
	Buckets []DistributionBucketV1 `json:"buckets"`
	Mean    float64                `json:"mean"`
}

type ScopedDistributionPair added in v0.23.0

type ScopedDistributionPair struct {
	ScopeAll   ScopedDistribution `json:"scope_all"`
	ScopeHuman ScopedDistribution `json:"scope_human"`
}

type SearchFilter

type SearchFilter struct {
	Query   string
	Project string
	Sort    string // "relevance" (default) or "recency"
	Cursor  int    // offset for pagination
	Limit   int
}

SearchFilter specifies search parameters.

type SearchPage

type SearchPage struct {
	Results    []SearchResult `json:"results"`
	NextCursor int            `json:"next_cursor,omitempty"`
}

SearchPage holds paginated search results.

type SearchResult

type SearchResult struct {
	SessionID      string  `json:"session_id"`
	Project        string  `json:"project"`
	Agent          string  `json:"agent"`
	Name           string  `json:"name"`
	Ordinal        int     `json:"ordinal"`
	SessionEndedAt string  `json:"session_ended_at"`
	Snippet        string  `json:"snippet"`
	Rank           float64 `json:"rank"`
}

SearchResult holds a session-level match with the best-ranked snippet.

type Session

type Session struct {
	ID                   string  `json:"id"`
	Project              string  `json:"project"`
	Machine              string  `json:"machine"`
	Agent                string  `json:"agent"`
	FirstMessage         *string `json:"first_message"`
	DisplayName          *string `json:"display_name,omitempty"`
	StartedAt            *string `json:"started_at"`
	EndedAt              *string `json:"ended_at"`
	MessageCount         int     `json:"message_count"`
	UserMessageCount     int     `json:"user_message_count"`
	ParentSessionID      *string `json:"parent_session_id,omitempty"`
	RelationshipType     string  `json:"relationship_type,omitempty"`
	TotalOutputTokens    int     `json:"total_output_tokens"`
	PeakContextTokens    int     `json:"peak_context_tokens"`
	HasTotalOutputTokens bool    `json:"has_total_output_tokens"`
	HasPeakContextTokens bool    `json:"has_peak_context_tokens"`
	IsAutomated          bool    `json:"is_automated"`

	// Session signals (computed from messages/tool_calls).
	ToolFailureSignalCount int      `json:"tool_failure_signal_count"`
	ToolRetryCount         int      `json:"tool_retry_count"`
	EditChurnCount         int      `json:"edit_churn_count"`
	ConsecutiveFailureMax  int      `json:"consecutive_failure_max"`
	Outcome                string   `json:"outcome"`
	OutcomeConfidence      string   `json:"outcome_confidence"`
	EndedWithRole          string   `json:"ended_with_role"`
	FinalFailureStreak     int      `json:"final_failure_streak"`
	SignalsPendingSince    *string  `json:"signals_pending_since,omitempty"`
	CompactionCount        int      `json:"compaction_count"`
	MidTaskCompactionCount int      `json:"mid_task_compaction_count"`
	ContextPressureMax     *float64 `json:"context_pressure_max,omitempty"`
	HealthScore            *int     `json:"health_score,omitempty"`
	HealthGrade            *string  `json:"health_grade,omitempty"`
	HasToolCalls           bool     `json:"-"`
	HasContextData         bool     `json:"-"`
	DataVersion            int      `json:"-"`
	Cwd                    string   `json:"cwd,omitempty"`
	GitBranch              string   `json:"git_branch,omitempty"`
	SourceSessionID        string   `json:"source_session_id,omitempty"`
	SourceVersion          string   `json:"source_version,omitempty"`
	ParserMalformedLines   int      `json:"parser_malformed_lines,omitempty"`
	IsTruncated            bool     `json:"is_truncated,omitempty"`

	DeletedAt       *string `json:"deleted_at,omitempty"`
	FilePath        *string `json:"file_path,omitempty"`
	FileSize        *int64  `json:"file_size,omitempty"`
	FileMtime       *int64  `json:"file_mtime,omitempty"`
	FileInode       *int64  `json:"file_inode,omitempty"`
	FileDevice      *int64  `json:"file_device,omitempty"`
	FileHash        *string `json:"file_hash,omitempty"`
	LocalModifiedAt *string `json:"local_modified_at,omitempty"`
	CreatedAt       string  `json:"created_at"`
}

Session represents a row in the sessions table.

type SessionActivityBucket added in v0.17.0

type SessionActivityBucket struct {
	StartTime      string `json:"start_time"`
	EndTime        string `json:"end_time"`
	UserCount      int    `json:"user_count"`
	AssistantCount int    `json:"assistant_count"`
	FirstOrdinal   *int   `json:"first_ordinal"` // nil for empty buckets
}

SessionActivityBucket holds message counts for one time interval.

type SessionActivityResponse added in v0.17.0

type SessionActivityResponse struct {
	Buckets         []SessionActivityBucket `json:"buckets"`
	IntervalSeconds int64                   `json:"interval_seconds"`
	TotalMessages   int                     `json:"total_messages"`
}

SessionActivityResponse is the response for the activity endpoint.

type SessionCoverageCandidate added in v0.18.0

type SessionCoverageCandidate struct {
	ID                string
	TotalOutputTokens int
	PeakContextTokens int
	HasTotal          bool
	HasPeak           bool
}

SessionCoverageCandidate holds the current state of a session's token coverage flags, used as input to ComputeSessionCoverageUpdates.

type SessionCoverageUpdate added in v0.18.0

type SessionCoverageUpdate struct {
	ID       string
	HasTotal bool
	HasPeak  bool
}

SessionCoverageUpdate holds the computed coverage flags for a session that needs updating.

func ComputeSessionCoverageUpdates added in v0.18.0

func ComputeSessionCoverageUpdates(
	candidates []SessionCoverageCandidate,
	msgCoverage map[string][2]bool,
) []SessionCoverageUpdate

ComputeSessionCoverageUpdates computes which sessions need their coverage flags updated based on their current state and message-level coverage. msgCoverage maps session ID to [hasContext, hasOutput]. Returns only sessions whose flags would change.

type SessionCursor

type SessionCursor struct {
	EndedAt string `json:"e"`
	ID      string `json:"i"`
	Total   int    `json:"t,omitempty"`
}

SessionCursor is the opaque pagination token.

type SessionFilter

type SessionFilter struct {
	Project          string
	ExcludeProject   string // exclude sessions with this project name
	Machine          string
	Agent            string
	Date             string   // exact date YYYY-MM-DD
	DateFrom         string   // range start (inclusive)
	DateTo           string   // range end (inclusive)
	ActiveSince      string   // ISO-8601 timestamp; filters on most recent activity
	MinMessages      int      // message_count >= N (0 = no filter)
	MaxMessages      int      // message_count <= N (0 = no filter)
	MinUserMessages  int      // user_message_count >= N (0 = no filter)
	ExcludeOneShot   bool     // exclude sessions with user_message_count <= 1
	ExcludeAutomated bool     // exclude sessions where is_automated = 1
	IncludeChildren  bool     // include subagent sessions (for sidebar grouping)
	Outcome          []string // filter by outcome values
	HealthGrade      []string // filter by health grade values
	MinToolFailures  *int     // minimum tool_failure_signal_count
	Cursor           string   // opaque cursor from previous page
	Limit            int
}

SessionFilter specifies how to query sessions.

type SessionPage

type SessionPage struct {
	Sessions   []Session `json:"sessions"`
	NextCursor string    `json:"next_cursor,omitempty"`
	Total      int       `json:"total"`
}

SessionPage is a page of session results.

type SessionShapeResponse

type SessionShapeResponse struct {
	Count                int                  `json:"count"`
	LengthDistribution   []DistributionBucket `json:"length_distribution"`
	DurationDistribution []DistributionBucket `json:"duration_distribution"`
	AutonomyDistribution []DistributionBucket `json:"autonomy_distribution"`
}

SessionShapeResponse holds distribution histograms for session characteristics.

type SessionSignalUpdate added in v0.23.0

type SessionSignalUpdate struct {
	ToolFailureSignalCount int
	ToolRetryCount         int
	EditChurnCount         int
	ConsecutiveFailureMax  int
	Outcome                string
	OutcomeConfidence      string
	EndedWithRole          string
	FinalFailureStreak     int
	SignalsPendingSince    *string
	CompactionCount        int
	MidTaskCompactionCount int
	ContextPressureMax     *float64
	HealthScore            *int
	HealthGrade            *string
	HasToolCalls           bool
	HasContextData         bool
}

SessionSignalUpdate holds computed signal values to persist on the sessions table.

type SessionStats added in v0.23.0

type SessionStats struct {
	SchemaVersion  int                  `json:"schema_version"`
	Window         StatsWindow          `json:"window"`
	Filters        StatsFilters         `json:"filters"`
	Totals         StatsTotals          `json:"totals"`
	Distributions  StatsDistributions   `json:"distributions"`
	Archetypes     StatsArchetypes      `json:"archetypes"`
	Velocity       StatsVelocity        `json:"velocity"`
	ToolMix        StatsToolMix         `json:"tool_mix"`
	ModelMix       StatsModelMix        `json:"model_mix"`
	Adoption       *StatsAdoption       `json:"adoption,omitempty"`
	AgentPortfolio StatsAgentPortfolio  `json:"agent_portfolio"`
	CacheEconomics *StatsCacheEconomics `json:"cache_economics,omitempty"`
	Temporal       StatsTemporal        `json:"temporal"`
	OutcomeStats   *StatsOutcomeStats   `json:"outcome_stats,omitempty"`
	Outcomes       *StatsOutcomes       `json:"outcomes,omitempty"`
	GeneratedAt    string               `json:"generated_at"`
}

SessionStats is the top-level v1 output of GetSessionStats. schema_version is locked at 1 for this CLI release; changes to bucket boundaries or field semantics require a version bump.

type SignalRow added in v0.23.0

type SignalRow struct {
	ID                     string
	Agent                  string
	Project                string
	Date                   string
	HealthScore            *int
	HealthGrade            *string
	Outcome                string
	OutcomeConfidence      string
	ToolFailureSignalCount int
	ToolRetryCount         int
	EditChurnCount         int
	CompactionCount        int
	MidTaskCompactionCount int
	ContextPressureMax     *float64
}

SignalRow holds per-session signal data from the query. Exported so the PostgreSQL store can build the same rows from its own SELECT and feed them into AggregateSignals without duplicating the aggregation logic.

type SignalsAgentRow added in v0.23.0

type SignalsAgentRow struct {
	Agent             string   `json:"agent"`
	SessionCount      int      `json:"session_count"`
	AvgHealthScore    *float64 `json:"avg_health_score"`
	CompletedRate     float64  `json:"completed_rate"`
	AvgFailureSignals float64  `json:"avg_failure_signals"`
}

SignalsAgentRow holds signal data grouped by agent.

type SignalsAnalyticsResponse added in v0.23.0

type SignalsAnalyticsResponse struct {
	ScoredSessions                int                  `json:"scored_sessions"`
	UnscoredSessions              int                  `json:"unscored_sessions"`
	GradeDistribution             map[string]int       `json:"grade_distribution"`
	AvgHealthScore                *float64             `json:"avg_health_score"`
	OutcomeDistribution           map[string]int       `json:"outcome_distribution"`
	OutcomeConfidenceDistribution map[string]int       `json:"outcome_confidence_distribution"`
	ToolHealth                    SignalsToolHealth    `json:"tool_health"`
	ContextHealth                 SignalsContextHealth `json:"context_health"`
	Trend                         []SignalsTrendBucket `json:"trend"`
	ByAgent                       []SignalsAgentRow    `json:"by_agent"`
	ByProject                     []SignalsProjectRow  `json:"by_project"`
}

SignalsAnalyticsResponse holds aggregated session signal data.

func AggregateSignals added in v0.23.0

func AggregateSignals(
	all []SignalRow,
) SignalsAnalyticsResponse

AggregateSignals builds the response from collected rows. Exported so the PostgreSQL store can reuse the same aggregation logic instead of re-implementing it.

type SignalsContextHealth added in v0.23.0

type SignalsContextHealth struct {
	AvgCompactionCount        float64  `json:"avg_compaction_count"`
	SessionsWithCompaction    int      `json:"sessions_with_compaction"`
	MidTaskCompactionCount    int      `json:"mid_task_compaction_count"`
	SessionsWithMidTaskCompac int      `json:"sessions_with_mid_task_compaction"`
	SessionsWithContextData   int      `json:"sessions_with_context_data"`
	AvgContextPressure        *float64 `json:"avg_context_pressure"`
	HighPressureSessions      int      `json:"high_pressure_sessions"`
}

SignalsContextHealth holds aggregate context pressure metrics.

type SignalsProjectRow added in v0.23.0

type SignalsProjectRow struct {
	Project           string   `json:"project"`
	SessionCount      int      `json:"session_count"`
	AvgHealthScore    *float64 `json:"avg_health_score"`
	CompletedRate     float64  `json:"completed_rate"`
	AvgFailureSignals float64  `json:"avg_failure_signals"`
}

SignalsProjectRow holds signal data grouped by project.

type SignalsToolHealth added in v0.23.0

type SignalsToolHealth struct {
	TotalFailureSignals  int     `json:"total_failure_signals"`
	TotalRetries         int     `json:"total_retries"`
	TotalEditChurn       int     `json:"total_edit_churn"`
	SessionsWithFailures int     `json:"sessions_with_failures"`
	FailureRate          float64 `json:"failure_rate"`
}

SignalsToolHealth holds aggregate tool failure metrics.

type SignalsTrendBucket added in v0.23.0

type SignalsTrendBucket struct {
	Date              string   `json:"date"`
	SessionCount      int      `json:"session_count"`
	AvgHealthScore    *float64 `json:"avg_health_score"`
	Completed         int      `json:"completed"`
	Errored           int      `json:"errored"`
	Abandoned         int      `json:"abandoned"`
	AvgFailureSignals float64  `json:"avg_failure_signals"`
}

SignalsTrendBucket holds signal data for one date bucket.

type Stats

type Stats struct {
	SessionCount    int     `json:"session_count"`
	MessageCount    int     `json:"message_count"`
	ProjectCount    int     `json:"project_count"`
	MachineCount    int     `json:"machine_count"`
	EarliestSession *string `json:"earliest_session"`
}

Stats holds database-wide statistics.

type StatsAdoption added in v0.23.0

type StatsAdoption struct {
	ClaudeOnly          bool    `json:"claude_only"`
	PlanModeRate        float64 `json:"plan_mode_rate"`
	SubagentsPerSession float64 `json:"subagents_per_session"`
	DistinctSkills      int     `json:"distinct_skills"`
}

type StatsAgentPortfolio added in v0.23.0

type StatsAgentPortfolio struct {
	BySessions map[string]int   `json:"by_sessions"`
	ByTokens   map[string]int64 `json:"by_tokens"`
	ByMessages map[string]int   `json:"by_messages"`
	Primary    string           `json:"primary"`
}

type StatsArchetypes added in v0.23.0

type StatsArchetypes struct {
	Automation   int    `json:"automation"`
	Quick        int    `json:"quick"`
	Standard     int    `json:"standard"`
	Deep         int    `json:"deep"`
	Marathon     int    `json:"marathon"`
	Primary      string `json:"primary"`
	PrimaryHuman string `json:"primary_human"`
}

type StatsCacheEconomics added in v0.23.0

type StatsCacheEconomics struct {
	ClaudeOnly             bool                      `json:"claude_only"`
	CacheHitRatio          CacheHitRatioDistribution `json:"cache_hit_ratio"`
	DollarsSavedVsUncached float64                   `json:"dollars_saved_vs_uncached"`
	DollarsSpent           float64                   `json:"dollars_spent"`
}

type StatsDistributions added in v0.23.0

type StatsDistributions struct {
	DurationMinutes   ScopedDistributionPair  `json:"duration_minutes"`
	UserMessages      ScopedDistributionPair  `json:"user_messages"`
	PeakContextTokens PeakContextDistribution `json:"peak_context_tokens"`
	ToolsPerTurn      ScopedDistributionPair  `json:"tools_per_turn"`
}

type StatsFilter added in v0.23.0

type StatsFilter struct {
	Since           string
	Until           string
	Agent           string
	IncludeProjects []string
	ExcludeProjects []string
	Timezone        string
	GHToken         string
}

StatsFilter mirrors the service-layer StatsFilter but lives in db because db functions take typed filters without cross-package deps.

type StatsFilters added in v0.23.0

type StatsFilters struct {
	Agent            string   `json:"agent"`
	ProjectsIncluded []string `json:"projects_included,omitempty"`
	ProjectsExcluded []string `json:"projects_excluded"`
	Timezone         string   `json:"timezone"`
}

type StatsModelMix added in v0.23.0

type StatsModelMix struct {
	ByTokens map[string]int64 `json:"by_tokens"`
}

type StatsOutcomeStats added in v0.23.0

type StatsOutcomeStats struct {
	ReposActive  int  `json:"repos_active"`
	Commits      int  `json:"commits"`
	LOCAdded     int  `json:"loc_added"`
	LOCRemoved   int  `json:"loc_removed"`
	FilesChanged int  `json:"files_changed"`
	PRsOpened    *int `json:"prs_opened,omitempty"` // nil when gh not configured
	PRsMerged    *int `json:"prs_merged,omitempty"`
}

type StatsOutcomes added in v0.23.0

type StatsOutcomes struct {
	ClaudeOnly            bool           `json:"claude_only"`
	Success               int            `json:"success"`
	Failure               int            `json:"failure"`
	Unknown               int            `json:"unknown"`
	GradeDistribution     map[string]int `json:"grade_distribution"`
	ToolRetryRate         float64        `json:"tool_retry_rate"`
	CompactionsPerSession float64        `json:"compactions_per_session"`
	AvgEditChurn          float64        `json:"avg_edit_churn"`
}

type StatsPercentiles added in v0.23.0

type StatsPercentiles struct {
	P50  float64 `json:"p50"`
	P90  float64 `json:"p90"`
	Mean float64 `json:"mean"`
}

type StatsTemporal added in v0.23.0

type StatsTemporal struct {
	HourlyUTC        []TemporalHourlyUTCEntry `json:"hourly_utc"`
	ReporterTimezone string                   `json:"reporter_timezone"`
}

type StatsToolMix added in v0.23.0

type StatsToolMix struct {
	ByCategory map[string]int `json:"by_category"`
	TotalCalls int            `json:"total_calls"`
}

type StatsTotals added in v0.23.0

type StatsTotals struct {
	SessionsAll        int `json:"sessions_all"`
	SessionsHuman      int `json:"sessions_human"`
	SessionsAutomation int `json:"sessions_automation"`
	MessagesTotal      int `json:"messages_total"`
	UserMessagesTotal  int `json:"user_messages_total"`
}

type StatsVelocity added in v0.23.0

type StatsVelocity struct {
	TurnCycleSeconds      StatsPercentiles `json:"turn_cycle_seconds"`
	FirstResponseSeconds  StatsPercentiles `json:"first_response_seconds"`
	MessagesPerActiveHour float64          `json:"messages_per_active_hour"`
}

type StatsWindow added in v0.23.0

type StatsWindow struct {
	Since string `json:"since"`
	Until string `json:"until"`
	Days  int    `json:"days"`
}

type Store added in v0.16.0

type Store interface {
	// Cursor pagination.
	SetCursorSecret(secret []byte)
	EncodeCursor(endedAt, id string, total ...int) string
	DecodeCursor(s string) (SessionCursor, error)

	// Sessions.
	ListSessions(ctx context.Context, f SessionFilter) (SessionPage, error)
	GetSession(ctx context.Context, id string) (*Session, error)
	GetSessionFull(ctx context.Context, id string) (*Session, error)
	GetChildSessions(ctx context.Context, parentID string) ([]Session, error)

	// Messages.
	GetMessages(ctx context.Context, sessionID string, from, limit int, asc bool) ([]Message, error)
	GetAllMessages(ctx context.Context, sessionID string) ([]Message, error)
	GetSessionActivity(ctx context.Context, sessionID string) (*SessionActivityResponse, error)

	// Search.
	HasFTS() bool
	Search(ctx context.Context, f SearchFilter) (SearchPage, error)
	SearchSession(ctx context.Context, sessionID, query string) ([]int, error)

	// SSE change detection.
	GetSessionVersion(id string) (count int, fileMtime int64, ok bool)

	// Metadata.
	GetStats(ctx context.Context, excludeOneShot, excludeAutomated bool) (Stats, error)
	GetProjects(ctx context.Context, excludeOneShot, excludeAutomated bool) ([]ProjectInfo, error)
	GetAgents(ctx context.Context, excludeOneShot, excludeAutomated bool) ([]AgentInfo, error)
	GetMachines(ctx context.Context, excludeOneShot, excludeAutomated bool) ([]string, error)

	// Analytics.
	GetAnalyticsSummary(ctx context.Context, f AnalyticsFilter) (AnalyticsSummary, error)
	GetAnalyticsActivity(ctx context.Context, f AnalyticsFilter, granularity string) (ActivityResponse, error)
	GetAnalyticsHeatmap(ctx context.Context, f AnalyticsFilter, metric string) (HeatmapResponse, error)
	GetAnalyticsProjects(ctx context.Context, f AnalyticsFilter) (ProjectsAnalyticsResponse, error)
	GetAnalyticsHourOfWeek(ctx context.Context, f AnalyticsFilter) (HourOfWeekResponse, error)
	GetAnalyticsSessionShape(ctx context.Context, f AnalyticsFilter) (SessionShapeResponse, error)
	GetAnalyticsTools(ctx context.Context, f AnalyticsFilter) (ToolsAnalyticsResponse, error)
	GetAnalyticsVelocity(ctx context.Context, f AnalyticsFilter) (VelocityResponse, error)
	GetAnalyticsTopSessions(ctx context.Context, f AnalyticsFilter, metric string) (TopSessionsResponse, error)
	GetAnalyticsSignals(ctx context.Context, f AnalyticsFilter) (SignalsAnalyticsResponse, error)

	// Usage (token cost).
	GetDailyUsage(ctx context.Context, f UsageFilter) (DailyUsageResult, error)
	GetTopSessionsByCost(ctx context.Context, f UsageFilter, limit int) ([]TopSessionEntry, error)
	GetUsageSessionCounts(ctx context.Context, f UsageFilter) (UsageSessionCounts, error)

	// Stars (local-only; PG returns ErrReadOnly).
	StarSession(sessionID string) (bool, error)
	UnstarSession(sessionID string) error
	ListStarredSessionIDs(ctx context.Context) ([]string, error)
	BulkStarSessions(sessionIDs []string) error

	// Pins (local-only; PG returns ErrReadOnly).
	PinMessage(sessionID string, messageID int64, note *string) (int64, error)
	UnpinMessage(sessionID string, messageID int64) error
	ListPinnedMessages(ctx context.Context, sessionID string, project string) ([]PinnedMessage, error)

	// Insights (local-only; PG returns ErrReadOnly).
	ListInsights(ctx context.Context, f InsightFilter) ([]Insight, error)
	GetInsight(ctx context.Context, id int64) (*Insight, error)
	InsertInsight(s Insight) (int64, error)
	DeleteInsight(id int64) error

	// Session management (local-only; PG returns ErrReadOnly).
	RenameSession(id string, displayName *string) error
	SoftDeleteSession(id string) error
	RestoreSession(id string) (int64, error)
	DeleteSessionIfTrashed(id string) (int64, error)
	ListTrashedSessions(ctx context.Context) ([]Session, error)
	EmptyTrash() (int, error)

	// Upload (local-only; PG returns ErrReadOnly).
	UpsertSession(s Session) error
	ReplaceSessionMessages(sessionID string, msgs []Message) error

	// ReadOnly returns true for remote/PG-backed stores.
	ReadOnly() bool
}

Store is the interface the HTTP server uses for all data access. The concrete *DB (SQLite) satisfies it implicitly. The pgdb package provides a read-only PostgreSQL implementation.

type TemporalHourlyUTCEntry added in v0.23.0

type TemporalHourlyUTCEntry struct {
	TS           string `json:"ts"` // RFC3339 at UTC hour boundary
	Sessions     int    `json:"sessions"`
	UserMessages int    `json:"user_messages"`
}

type ToolAgentBreakdown

type ToolAgentBreakdown struct {
	Agent      string              `json:"agent"`
	Total      int                 `json:"total"`
	Categories []ToolCategoryCount `json:"categories"`
}

ToolAgentBreakdown holds tool usage breakdown for one agent.

type ToolCall

type ToolCall struct {
	MessageID           int64             `json:"-"`
	SessionID           string            `json:"-"`
	ToolName            string            `json:"tool_name"`
	Category            string            `json:"category"`
	ToolUseID           string            `json:"tool_use_id,omitempty"`
	InputJSON           string            `json:"input_json,omitempty"`
	SkillName           string            `json:"skill_name,omitempty"`
	ResultContentLength int               `json:"result_content_length,omitempty"`
	ResultContent       string            `json:"result_content,omitempty"`
	SubagentSessionID   string            `json:"subagent_session_id,omitempty"`
	ResultEvents        []ToolResultEvent `json:"result_events,omitempty"`
}

ToolCall represents a single tool invocation stored in the tool_calls table.

type ToolCategoryCount

type ToolCategoryCount struct {
	Category string  `json:"category"`
	Count    int     `json:"count"`
	Pct      float64 `json:"pct"`
}

ToolCategoryCount holds a count and percentage for one tool category.

type ToolResult added in v0.4.0

type ToolResult struct {
	ToolUseID     string
	ContentLength int
	ContentRaw    string // raw JSON of the content field; decode lazily
}

ToolResult holds a tool_result content block for pairing.

type ToolResultEvent added in v0.17.0

type ToolResultEvent struct {
	ToolUseID         string `json:"tool_use_id,omitempty"`
	AgentID           string `json:"agent_id,omitempty"`
	SubagentSessionID string `json:"subagent_session_id,omitempty"`
	Source            string `json:"source"`
	Status            string `json:"status"`
	Content           string `json:"content"`
	ContentLength     int    `json:"content_length"`
	Timestamp         string `json:"timestamp,omitempty"`
	EventIndex        int    `json:"event_index"`
}

ToolResultEvent represents a canonical chronological result update.

type ToolTrendEntry

type ToolTrendEntry struct {
	Date  string         `json:"date"`
	ByCat map[string]int `json:"by_category"`
}

ToolTrendEntry holds tool call counts for one time bucket.

type ToolsAnalyticsResponse

type ToolsAnalyticsResponse struct {
	TotalCalls int                  `json:"total_calls"`
	ByCategory []ToolCategoryCount  `json:"by_category"`
	ByAgent    []ToolAgentBreakdown `json:"by_agent"`
	Trend      []ToolTrendEntry     `json:"trend"`
}

ToolsAnalyticsResponse wraps tool usage analytics.

type TopSession

type TopSession struct {
	ID           string  `json:"id"`
	Project      string  `json:"project"`
	FirstMessage *string `json:"first_message"`
	MessageCount int     `json:"message_count"`
	OutputTokens int     `json:"output_tokens"`
	DurationMin  float64 `json:"duration_min"`
}

TopSession holds summary info for a ranked session.

type TopSessionEntry added in v0.21.0

type TopSessionEntry struct {
	SessionID   string  `json:"sessionId"`
	DisplayName string  `json:"displayName"`
	Agent       string  `json:"agent"`
	Project     string  `json:"project"`
	StartedAt   string  `json:"startedAt"`
	TotalTokens int     `json:"totalTokens"`
	Cost        float64 `json:"cost"`
}

TopSessionEntry is one row in the "top sessions by cost" result.

type TopSessionsResponse

type TopSessionsResponse struct {
	Metric   string       `json:"metric"`
	Sessions []TopSession `json:"sessions"`
}

TopSessionsResponse wraps the top sessions list.

type UsageFilter added in v0.20.0

type UsageFilter struct {
	From           string // YYYY-MM-DD, inclusive
	To             string // YYYY-MM-DD, inclusive
	Agent          string // "" for all; supports comma-separated
	Project        string // "" for all; supports comma-separated
	Model          string // "" for all; supports comma-separated
	ExcludeProject string // comma-separated projects to exclude
	ExcludeAgent   string // comma-separated agents to exclude
	ExcludeModel   string // comma-separated models to exclude
	Timezone       string // IANA timezone, "" for UTC
	Breakdowns     bool   // populate Project/AgentBreakdowns per day
}

UsageFilter controls the date range, agent, and timezone for daily usage aggregation queries.

type UsageSessionCounts added in v0.21.0

type UsageSessionCounts struct {
	Total     int            `json:"total"`
	ByProject map[string]int `json:"byProject"`
	ByAgent   map[string]int `json:"byAgent"`
}

UsageSessionCounts holds distinct session counts grouped by project and agent over a filter range.

type UsageTotals added in v0.20.0

type UsageTotals struct {
	InputTokens         int     `json:"inputTokens"`
	OutputTokens        int     `json:"outputTokens"`
	CacheCreationTokens int     `json:"cacheCreationTokens"`
	CacheReadTokens     int     `json:"cacheReadTokens"`
	TotalCost           float64 `json:"totalCost"`
	// CacheSavings is the net dollar delta vs an uncached run:
	// cache reads save (input_rate - cache_read_rate) per token,
	// cache creations cost (input_rate - cache_creation_rate)
	// per token (usually negative because creation is billed
	// above the input rate). Computed from per-model rates so
	// mixed-model workloads get the right number, not a fixed
	// Sonnet proxy.
	CacheSavings float64 `json:"cacheSavings"`
}

UsageTotals holds aggregate token and cost totals.

type VelocityBreakdown

type VelocityBreakdown struct {
	Label    string           `json:"label"`
	Sessions int              `json:"sessions"`
	Overview VelocityOverview `json:"overview"`
}

VelocityBreakdown is velocity metrics for a subgroup.

type VelocityOverview

type VelocityOverview struct {
	TurnCycleSec          Percentiles `json:"turn_cycle_sec"`
	FirstResponseSec      Percentiles `json:"first_response_sec"`
	MsgsPerActiveMin      float64     `json:"msgs_per_active_min"`
	CharsPerActiveMin     float64     `json:"chars_per_active_min"`
	ToolCallsPerActiveMin float64     `json:"tool_calls_per_active_min"`
}

VelocityOverview holds aggregate velocity metrics.

type VelocityResponse

type VelocityResponse struct {
	Overall      VelocityOverview    `json:"overall"`
	ByAgent      []VelocityBreakdown `json:"by_agent"`
	ByComplexity []VelocityBreakdown `json:"by_complexity"`
}

VelocityResponse wraps overall and grouped velocity metrics.

Directories

Path Synopsis
Package git discovers local repositories and aggregates git-derived metrics for session analytics.
Package git discovers local repositories and aggregates git-derived metrics for session analytics.

Jump to

Keyboard shortcuts

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