compaction

package
v0.20.0 Latest Latest
Warning

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

Go to latest
Published: Sep 15, 2026 License: AGPL-3.0 Imports: 31 Imported by: 0

Documentation

Index

Constants

View Source
const (
	StatusOK   = "ok"   // messages were compacted into a summary
	StatusNoop = "noop" // nothing to compact (already compact, cooled down, or in flight)
)

Compaction result statuses reported by RunCompactionSync.

View Source
const ArtifactVersion = 1

Variables

View Source
var (

	// ErrSummaryWindowTooSmall marks a summarizer whose declared window cannot
	// hold the fixed prompt plus the output reserve; running it would overflow
	// on every attempt, so it fails closed before claiming any source rows.
	// Exported so manual surfaces can map it to a stable capability error.
	ErrSummaryWindowTooSmall = errors.New("compaction: summarizer window too small for the compaction prompt")
)

Functions

func ShouldCompact

func ShouldCompact(inputTokens, threshold int) bool

ShouldCompact returns true if inputTokens exceeds the threshold.

func TimelineArtifacts

func TimelineArtifacts(artifacts []Artifact) []timeline.CompactionArtifact

TimelineArtifacts projects active artifacts onto the timeline contract. Artifacts without a trustworthy summary or coverage must not swallow their original sources, and legacy artifacts without any coverage cannot replace anything — injecting them would duplicate the history they summarize — so both are omitted entirely.

Types

type Artifact

type Artifact struct {
	ID                string
	BotID             string
	SessionID         string
	Status            string
	Summary           string
	Version           int
	Coverage          []CoveredSource
	AnchorStartMs     int64
	AnchorEndMs       int64
	Level             int
	ParentIDs         []string
	SupersededBy      string
	SupersededAt      time.Time
	StartedAt         time.Time
	CoverageMalformed bool
}

func (Artifact) CoversRecord

func (a Artifact) CoversRecord(record historyfrag.HistoryRecord) bool

func (Artifact) HistoryRecord

func (a Artifact) HistoryRecord(scope contextfrag.Scope) historyfrag.HistoryRecord

type ArtifactCatalog

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

func NewArtifactCatalog

func NewArtifactCatalog() *ArtifactCatalog

func (*ArtifactCatalog) Add

func (*ArtifactCatalog) Resolve

func (c *ArtifactCatalog) Resolve(owner ArtifactOwner, lineageID string) (Artifact, bool)

func (*ArtifactCatalog) ResolveCoverageIdentity

func (c *ArtifactCatalog) ResolveCoverageIdentity(owner ArtifactOwner, ref contextfrag.ContextRef) (Artifact, bool)

func (*ArtifactCatalog) ResolveCoveredRef

func (c *ArtifactCatalog) ResolveCoveredRef(owner ArtifactOwner, ref contextfrag.ContextRef) (Artifact, bool)

type ArtifactFrontier

type ArtifactFrontier struct {
	Artifacts []Artifact
	Issues    []LineageIssue
	// contains filtered or unexported fields
}

func MergeArtifactFrontiers

func MergeArtifactFrontiers(frontiers ...ArtifactFrontier) ArtifactFrontier

func NewArtifactAliasFrontier

func NewArtifactAliasFrontier(lineageID string, artifact Artifact) ArtifactFrontier

func (ArtifactFrontier) Resolve

func (f ArtifactFrontier) Resolve(lineageID string) (Artifact, bool)

func (ArtifactFrontier) ResolveCoverageIdentity

func (f ArtifactFrontier) ResolveCoverageIdentity(ref contextfrag.ContextRef) (Artifact, bool)

func (ArtifactFrontier) ResolveCoveredRef

func (f ArtifactFrontier) ResolveCoveredRef(ref contextfrag.ContextRef) (Artifact, bool)

type ArtifactOwner

type ArtifactOwner struct {
	BotID          string
	SessionID      string
	SessionIDKnown bool
}

type ArtifactProjection

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

func NewArtifactProjection

func NewArtifactProjection(queries artifactProjectionQueries) ArtifactProjection

func (ArtifactProjection) LoadActiveByID

func (p ArtifactProjection) LoadActiveByID(ctx context.Context, id string, owner ArtifactOwner) (Artifact, error)

func (ArtifactProjection) LoadActiveSession

func (p ArtifactProjection) LoadActiveSession(ctx context.Context, owner ArtifactOwner) (ArtifactFrontier, error)

type CompactPolicy

type CompactPolicy string
const (
	CompactPolicyPreserveRecent      CompactPolicy = "preserve_recent"
	CompactPolicyPreserveToolClosure CompactPolicy = "preserve_tool_closure"
	CompactPolicyMustKeep            CompactPolicy = "must_keep"
)

type CompactionCandidate

type CompactionCandidate struct {
	ID           pgtype.UUID
	RawContent   []byte
	RawUsage     []byte
	Record       historyfrag.HistoryRecord
	Policies     []CompactPolicy
	IsToolResult bool
}

CompactionCandidate is the typed view of one uncompacted history row used during candidate selection. RawContent and RawUsage retain the raw row payload so token estimation stays byte-identical to the legacy path; Record carries the typed classifier output used for policies, tool-aware boundaries, and summarizer rendering.

func (CompactionCandidate) HasPolicy

func (c CompactionCandidate) HasPolicy(policy CompactPolicy) bool

type CoveredSource

type CoveredSource struct {
	Ref                    contextfrag.ContextRef `json:"ref"`
	ExternalMessageID      string                 `json:"external_message_id,omitempty"`
	SourceReplyToMessageID string                 `json:"source_reply_to_message_id,omitempty"`
	CreatedAtMs            int64                  `json:"created_at_ms,omitempty"`
}

func DecodeArtifactCoverage

func DecodeArtifactCoverage(raw []byte) ([]CoveredSource, error)

type LineageError

type LineageError struct {
	Issue LineageIssue
}

func (*LineageError) Error

func (e *LineageError) Error() string

type LineageIssue

type LineageIssue struct {
	Kind       LineageIssueKind
	ArtifactID string
	RelatedID  string
}

func (LineageIssue) Error

func (i LineageIssue) Error() string

type LineageIssueKind

type LineageIssueKind string
const (
	LineageIssueCycle                  LineageIssueKind = "cycle"
	LineageIssueMissingSuccessor       LineageIssueKind = "missing_successor"
	LineageIssueInactiveSuccessor      LineageIssueKind = "inactive_successor"
	LineageIssueInconsistentMarker     LineageIssueKind = "inconsistent_supersession_marker"
	LineageIssueParentMismatch         LineageIssueKind = "parent_mismatch"
	LineageIssueScopeMismatch          LineageIssueKind = "scope_mismatch"
	LineageIssueMissingDerivedCoverage LineageIssueKind = "missing_derived_coverage"
	LineageIssueCoverageMismatch       LineageIssueKind = "coverage_mismatch"
	LineageIssueCoverageOverlap        LineageIssueKind = "coverage_overlap"
	LineageIssueAliasConflict          LineageIssueKind = "alias_conflict"
	LineageIssueMalformedCoverage      LineageIssueKind = "malformed_coverage"
)

type ListLogsResponse

type ListLogsResponse struct {
	Items      []Log `json:"items"`
	TotalCount int64 `json:"total_count"`

} // @name compaction.ListLogsResponse

ListLogsResponse is the API response for listing compaction logs.

type Log

type Log struct {
	ID           string     `json:"id"`
	BotID        string     `json:"bot_id"`
	SessionID    string     `json:"session_id,omitempty"`
	Status       string     `json:"status"`
	Summary      string     `json:"summary"`
	MessageCount int        `json:"message_count"`
	ErrorMessage string     `json:"error_message"`
	Usage        any        `json:"usage,omitempty"`
	ModelID      string     `json:"model_id,omitempty"`
	StartedAt    time.Time  `json:"started_at"`
	CompletedAt  *time.Time `json:"completed_at,omitempty"`

} // @name compaction.Log

Log represents a compaction log entry.

type Result

type Result struct {
	Status       string
	Summary      string
	MessageCount int
}

Result is the scoped outcome of a synchronous compaction. Callers use it to respond with this session's own result instead of reading unscoped bot-wide logs. A failed attempt returns an error, not a Result.

type Service

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

Service manages context compaction for bot conversations.

func NewService

func NewService(log *slog.Logger, queries dbstore.Queries) *Service

NewService creates a new compaction Service.

func (*Service) ActiveSessions added in v0.20.0

func (s *Service) ActiveSessions(botID string) []string

ActiveSessions is a process-local activity snapshot, not an admission gate.

func (*Service) DeleteLogs

func (s *Service) DeleteLogs(ctx context.Context, botID string) error

DeleteLogs deletes all compaction logs for a bot.

func (*Service) ListLogs

func (s *Service) ListLogs(ctx context.Context, botID string, limit, offset int) ([]Log, int64, error)

ListLogs returns paginated compaction logs for a bot.

func (*Service) RunCompaction

func (s *Service) RunCompaction(ctx context.Context, cfg TriggerConfig) error

RunCompaction runs one automatic attempt without waiting for an existing owner. The caller owns the goroutine lifetime so surrounding coordination remains active until selection and persistence finish.

func (*Service) RunCompactionSync

func (s *Service) RunCompactionSync(ctx context.Context, cfg TriggerConfig) (Result, error)

RunCompactionSync runs compaction synchronously and reports this session's scoped Result, so callers act on their own outcome (a noop keeps their current context) instead of reading an unscoped bot-wide log that may belong to another session. When another run for the session is already in flight, the sync path waits for the owner and reuses its outcome — the summary is seconds away, and waiting removes a duplicate LLM call over the same span; a canceled wait degrades to a noop.

func (*Service) SetEventPublisher added in v0.20.0

func (s *Service) SetEventPublisher(p messageevent.Publisher)

SetEventPublisher wires lightweight activity notifications at startup.

func (*Service) SetHookService

func (s *Service) SetHookService(h *hooks.Service)

type TimelineArtifactSource

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

TimelineArtifactSource loads the active artifact frontier of a session as timeline projections for context composition.

func NewTimelineArtifactSource

func NewTimelineArtifactSource(queries artifactProjectionQueries) TimelineArtifactSource

func (TimelineArtifactSource) ActiveCompactionArtifacts

func (s TimelineArtifactSource) ActiveCompactionArtifacts(ctx context.Context, botID, sessionID string) ([]timeline.CompactionArtifact, error)

type TriggerConfig

type TriggerConfig struct {
	BotID                 string
	SessionID             string
	ModelID               string // runtime model slug sent to the provider
	ModelRecordID         string // models.id row UUID recorded as artifact/log provenance
	ClientType            string
	APIKey                string //nolint:gosec // runtime credential, not a hardcoded secret
	CodexAccountID        string
	BaseURL               string
	ChatCompletionsCompat string
	HTTPClient            *http.Client
	Ratio                 int
	TotalInputTokens      int
	MaxCompactTokens      int // if > 0, cap compaction input to this many tokens (e.g. 85% of the summarizer window)
	TargetTokens          int // if > 0, compaction goal: reduce context to this many tokens (used by sync compaction)
	// SummaryWindowTokens is the summarizer model's full context window when
	// declared; it bounds the summary output reserve. Zero means unknown and
	// keeps the engine's conservative defaults.
	SummaryWindowTokens int
	// ContextWindowTokens is the chat model's context window. It is separate
	// from SummaryWindowTokens, which belongs to the summarizer model.
	ContextWindowTokens int
	PromptCacheTTL      string
	AllowFrontierFusion bool

	// Manual marks a user-initiated compaction (slash command, HTTP endpoint).
	// Such a request bypasses the per-session failure cooldown so a user who
	// just fixed their credentials/model isn't told "done" while nothing runs.
	// Automatic per-request paths leave this false to keep the cooldown backstop.
	Manual bool

	// HardPressure marks an automatic trigger fired at or above the blocking
	// share of the context window. Such retries re-attempt on an exponential
	// backoff instead of waiting out the full failure cooldown, because every
	// turn until a summary lands degrades or fails.
	HardPressure bool
}

TriggerConfig holds the parameters needed to trigger a compaction.

func NewTriggerConfig

func NewTriggerConfig(model TriggerModel) TriggerConfig

NewTriggerConfig derives both window budgets from a resolved summarizer: candidate selection is capped at 85% of the window so the prompt keeps headroom for the system prompt and provider framing on top of the summary output reserve.

type TriggerModel

type TriggerModel struct {
	Slug                  string // runtime model slug sent to the provider
	RecordID              string // models.id row UUID recorded as artifact/log provenance
	ClientType            string
	APIKey                string //nolint:gosec // runtime credential, not a hardcoded secret
	CodexAccountID        string
	BaseURL               string
	ChatCompletionsCompat string
	PromptCacheTTL        string
	WindowTokens          int // summarizer model's declared context window
}

TriggerModel is the resolved summarizer identity handed to the engine: selection policy and credential resolution belong to the orchestration surfaces, the engine only receives this completed contract.

Jump to

Keyboard shortcuts

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