Documentation
¶
Index ¶
- Constants
- Variables
- func ShouldCompact(inputTokens, threshold int) bool
- func TimelineArtifacts(artifacts []Artifact) []timeline.CompactionArtifact
- type Artifact
- type ArtifactCatalog
- func (c *ArtifactCatalog) Add(owner ArtifactOwner, frontier ArtifactFrontier) ArtifactFrontier
- func (c *ArtifactCatalog) Resolve(owner ArtifactOwner, lineageID string) (Artifact, bool)
- func (c *ArtifactCatalog) ResolveCoverageIdentity(owner ArtifactOwner, ref contextfrag.ContextRef) (Artifact, bool)
- func (c *ArtifactCatalog) ResolveCoveredRef(owner ArtifactOwner, ref contextfrag.ContextRef) (Artifact, bool)
- type ArtifactFrontier
- type ArtifactOwner
- type ArtifactProjection
- type CompactPolicy
- type CompactionCandidate
- type CoveredSource
- type LineageError
- type LineageIssue
- type LineageIssueKind
- type ListLogsResponse
- type Log
- type Result
- type Service
- func (s *Service) ActiveSessions(botID string) []string
- func (s *Service) DeleteLogs(ctx context.Context, botID string) error
- func (s *Service) ListLogs(ctx context.Context, botID string, limit, offset int) ([]Log, int64, error)
- func (s *Service) RunCompaction(ctx context.Context, cfg TriggerConfig) error
- func (s *Service) RunCompactionSync(ctx context.Context, cfg TriggerConfig) (Result, error)
- func (s *Service) SetEventPublisher(p messageevent.Publisher)
- func (s *Service) SetHookService(h *hooks.Service)
- type TimelineArtifactSource
- type TriggerConfig
- type TriggerModel
Constants ¶
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.
const ArtifactVersion = 1
Variables ¶
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 ¶
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 (c *ArtifactCatalog) Add(owner ArtifactOwner, frontier ArtifactFrontier) ArtifactFrontier
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 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 ¶
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 ¶
NewService creates a new compaction Service.
func (*Service) ActiveSessions ¶ added in v0.20.0
ActiveSessions is a process-local activity snapshot, not an admission gate.
func (*Service) DeleteLogs ¶
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 ¶
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 ¶
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.