Documentation
¶
Overview ¶
Package timeline implements the Deterministic Context Pipeline (DCP) for assembling LLM context from canonical IM events. It provides Adaptation types, Projection (reduce), and Rendering (RC) layers.
Index ¶
- Constants
- func ComposeContextWithArtifactsBudgeted(rc RenderedContext, trs []TurnResponseEntry, artifacts []CompactionArtifact, ...) (*ComposeContextResult, ComposeAdmission)
- func ContentToPlainText(nodes []ContentNode) string
- func HasUncoveredExternalEvent(rc RenderedContext, position DiscussCursorPosition) bool
- func ProjectInterruptedReasoning(modelMsg turn.ModelMessage) turn.ModelMessage
- func RCToXML(rc RenderedContext) string
- type Attachment
- type CanonicalEvent
- type CanonicalUser
- type CompactionArtifact
- type CompactionSource
- type ComposeAdmission
- type ComposeBudget
- type ComposeContextResult
- type ContentNode
- type ContextMessage
- type ConversationMeta
- type DeleteEvent
- type DiscussCursorPosition
- type EditEvent
- type EventKind
- type EventStore
- func (s *EventStore) GetDiscussCursor(ctx context.Context, sessionID, scopeKey string) (DiscussCursorPosition, error)
- func (s *EventStore) HasEvents(ctx context.Context, sessionID string) (bool, error)
- func (s *EventStore) LoadEvents(ctx context.Context, sessionID string) ([]CanonicalEvent, error)
- func (s *EventStore) LoadEventsForReplay(ctx context.Context, botID, sessionID string) ([]CanonicalEvent, error)
- func (s *EventStore) PersistEvent(ctx context.Context, botID, sessionID string, event CanonicalEvent) (string, CanonicalEvent, error)
- func (s *EventStore) SetReplayArtifactProvider(provider ReplayArtifactProvider)
- func (s *EventStore) UpsertDiscussCursor(ctx context.Context, sessionID, scopeKey, routeID, source string, ...) error
- type ForwardInfo
- type ICMessage
- type ICNode
- type ICSystemEvent
- type ICUserState
- type ImageAttachmentRef
- type IntermediateContext
- type MessageEvent
- type Pipeline
- func (p *Pipeline) DropAll()
- func (p *Pipeline) DropSession(sessionID string)
- func (p *Pipeline) GetIC(sessionID string) (IntermediateContext, bool)
- func (p *Pipeline) GetRC(sessionID string) RenderedContext
- func (p *Pipeline) HasSession(sessionID string) bool
- func (p *Pipeline) PushEvent(sessionID string, event CanonicalEvent) RenderedContext
- func (p *Pipeline) ReplaySession(sessionID string, events []CanonicalEvent) RenderedContext
- func (p *Pipeline) SessionIDs() []string
- func (p *Pipeline) Stats() PipelineStats
- func (p *Pipeline) UpdateRenderParams(params RenderParams)
- type PipelineOptions
- type PipelineStats
- type RenderParams
- type RenderedContentPiece
- type RenderedContext
- type RenderedSegment
- type ReplayArtifactProvider
- type ServiceAction
- type ServiceEvent
- type TurnResponseEntry
Constants ¶
const MaxJSONSafeEventCursor int64 = 1<<53 - 1
MaxJSONSafeEventCursor bounds legitimate event cursors; the allocation sequence never exceeds it, so larger payload values are corrupt data.
const MaxTrustedEventCursor = MaxJSONSafeEventCursor / 2
MaxTrustedEventCursor bounds cursors read back from payloads or restores. Clock-seeded allocation stays three orders of magnitude below it, while accepting values near the sequence MAXVALUE would poison consumed watermarks or exhaust the global sequence.
Variables ¶
This section is empty.
Functions ¶
func ComposeContextWithArtifactsBudgeted ¶
func ComposeContextWithArtifactsBudgeted( rc RenderedContext, trs []TurnResponseEntry, artifacts []CompactionArtifact, budget ComposeBudget, ) (*ComposeContextResult, ComposeAdmission)
ComposeContextWithArtifactsBudgeted composes like ComposeContextWithArtifacts but makes the admission decision on entry metadata before materializing anything. Over budget it keeps every artifact summary plus the newest contiguous window that fits, dropping older raw entries deterministically. When even the protected set does not fit it returns a nil result with ProtectedOverflow set.
func ContentToPlainText ¶
func ContentToPlainText(nodes []ContentNode) string
ContentToPlainText extracts plain text from a ContentNode tree.
func HasUncoveredExternalEvent ¶
func HasUncoveredExternalEvent(rc RenderedContext, position DiscussCursorPosition) bool
HasUncoveredExternalEvent reports whether any non-self segment lies past the consumed position.
func ProjectInterruptedReasoning ¶
func ProjectInterruptedReasoning(modelMsg turn.ModelMessage) turn.ModelMessage
ProjectInterruptedReasoning exposes an unfinished reasoning part as text so every provider can continue it on the next turn. Other message fields and content parts remain unchanged.
func RCToXML ¶
func RCToXML(rc RenderedContext) string
RCToXML converts a RenderedContext to a single XML string for debugging.
Types ¶
type Attachment ¶
type Attachment struct {
Type string `json:"type"`
MimeType string `json:"mime_type,omitempty"`
FileName string `json:"file_name,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Duration int `json:"duration,omitempty"`
ThumbnailB64 string `json:"thumbnail_b64,omitempty"`
AltText string `json:"alt_text,omitempty"`
// FilePath is the workspace path where the attachment is stored.
FilePath string `json:"file_path,omitempty"`
// ContentHash is the media-store content hash for persisted attachments.
ContentHash string `json:"content_hash,omitempty"`
}
Attachment is a platform-agnostic media attachment.
type CanonicalEvent ¶
CanonicalEvent is the interface satisfied by all event types.
type CanonicalUser ¶
type CanonicalUser struct {
// ID is the channel_identity_id (Memoh UUID).
ID string `json:"id"`
DisplayName string `json:"display_name"`
Username string `json:"username,omitempty"`
IsBot bool `json:"is_bot,omitempty"`
}
CanonicalUser is a platform-agnostic sender identity.
type CompactionArtifact ¶
type CompactionArtifact struct {
ID string `json:"id"`
Summary string `json:"summary"`
AnchorStartMs int64 `json:"anchor_start_ms,omitempty"`
CoverageAsOfMs int64 `json:"coverage_as_of_ms,omitempty"`
Sources []CompactionSource `json:"sources,omitempty"`
}
CompactionArtifact is the timeline-facing projection of one active compaction artifact. Callers preserve frontier order; composition keeps each artifact separate so later restacks can supersede only the ranges they actually cover.
type CompactionSource ¶
type CompactionSource struct {
HistoryMessageID string `json:"history_message_id,omitempty"`
ExternalMessageID string `json:"external_message_id,omitempty"`
CreatedAtMs int64 `json:"created_at_ms,omitempty"`
}
CompactionSource identifies one durable history source covered by an active compaction artifact. ExternalMessageID projects that source onto the rendered stream; HistoryMessageID projects it onto persisted turn responses.
type ComposeAdmission ¶
type ComposeAdmission struct {
// EstimatedTokens is the pre-selection estimate of the full raw context.
EstimatedTokens int
// SelectedTokens is the estimate of what was actually materialized.
SelectedTokens int
// TotalEntries and DroppedEntries count merge entries, not messages.
TotalEntries int
DroppedEntries int
// ProtectedOverflow is set when the protected set alone (artifact
// summaries plus the newest entry) exceeds the budget; the caller must
// fail closed instead of materializing (CM-ADM-002).
ProtectedOverflow bool
}
ComposeAdmission reports the admission decision made for one composition.
type ComposeBudget ¶
type ComposeBudget struct {
// MaxTokens is the admission budget in shared-estimator tokens. Zero or
// negative disables budgeting (legacy behavior).
MaxTokens int
}
ComposeBudget bounds composition before materialization (CM-ADM-001).
type ComposeContextResult ¶
type ComposeContextResult struct {
Messages []ContextMessage
EstimatedTokens int
}
ComposeContextResult holds the output of ComposeContext.
func ComposeContext ¶
func ComposeContext(rc RenderedContext, trs []TurnResponseEntry) *ComposeContextResult
ComposeContext merges un-compacted RC and TR streams.
func ComposeContextWithArtifacts ¶
func ComposeContextWithArtifacts(rc RenderedContext, trs []TurnResponseEntry, artifacts []CompactionArtifact) *ComposeContextResult
ComposeContextWithArtifacts replaces covered RC/TR sources with each active artifact at the covered rendered slot when available, or its durable anchor.
type ContentNode ¶
type ContentNode struct {
Type string `json:"type"`
Text string `json:"text,omitempty"`
Language string `json:"language,omitempty"`
URL string `json:"url,omitempty"`
UserID string `json:"user_id,omitempty"`
Children []ContentNode `json:"children,omitempty"`
}
ContentNode represents a rich-text tree node, parsed from platform-specific encodings (e.g. Telegram entities, Discord markdown).
type ContextMessage ¶
type ContextMessage struct {
Role string `json:"role"`
Content string `json:"content"`
RawContent json.RawMessage `json:"raw_content,omitempty"`
CompactionArtifactID string `json:"compaction_artifact_id,omitempty"`
}
ContextMessage is a unified message for LLM context, produced by MergeContext.
func MergeContext ¶
func MergeContext(rc RenderedContext, trs []TurnResponseEntry) []ContextMessage
MergeContext interleaves RC segments and TR entries by timestamp. RC entries use receivedAtMs; TR entries use requestedAtMs. Tiebreaker: RC before TR on equal timestamp. Consecutive RC entries between TR entries are merged into one user message.
type ConversationMeta ¶
type ConversationMeta struct {
Channel string `json:"channel"`
ConversationName string `json:"conversation_name,omitempty"`
ConversationType string `json:"conversation_type"`
Target string `json:"target,omitempty"`
}
ConversationMeta carries session-level context embedded in every event, so each rendered message is self-contained.
type DeleteEvent ¶
type DeleteEvent struct {
SessionID string `json:"session_id"`
EventID string `json:"event_id,omitempty"`
EventCursor int64 `json:"event_cursor,omitempty"`
MessageIDs []string `json:"message_ids"`
ReceivedAtMs int64 `json:"received_at_ms"`
TimestampSec int64 `json:"timestamp_sec"`
UTCOffsetMin int `json:"utc_offset_min"`
}
DeleteEvent represents one or more deleted messages.
func (DeleteEvent) GetReceivedAtMs ¶
func (e DeleteEvent) GetReceivedAtMs() int64
func (DeleteEvent) GetSessionID ¶
func (e DeleteEvent) GetSessionID() string
func (DeleteEvent) Kind ¶
func (DeleteEvent) Kind() EventKind
type DiscussCursorPosition ¶
DiscussCursorPosition tracks consumed discuss progress in both the durable event-cursor domain and the legacy source-timestamp domain. Segments are compared inside their own domain, so cursor magnitudes never race the wall clock and cursor-less ingest degrades to source-time coverage.
func ConsumedDiscussCursor ¶
func ConsumedDiscussCursor(rc RenderedContext) DiscussCursorPosition
ConsumedDiscussCursor is the position a discuss turn consumes when it replies to the given rendered timeline.
func (DiscussCursorPosition) Covers ¶
func (p DiscussCursorPosition) Covers(seg RenderedSegment) bool
Covers reports whether the position already consumed the segment. Coverage must hold in every domain that carries information: cursor allocation order can invert against source order when concurrent workers stamp one thread, so a covered cursor alone never proves consumption, and a watermark seeded from persisted replies alone carries no cursor to compare against. Anything the watermark cannot prove consumed is treated as new.
func (DiscussCursorPosition) Merge ¶
func (p DiscussCursorPosition) Merge(other DiscussCursorPosition) DiscussCursorPosition
Merge returns the component-wise maximum of both positions.
type EditEvent ¶
type EditEvent struct {
SessionID string `json:"session_id"`
EventID string `json:"event_id,omitempty"`
EventCursor int64 `json:"event_cursor,omitempty"`
MessageID string `json:"message_id"`
Sender *CanonicalUser `json:"sender,omitempty"`
ReceivedAtMs int64 `json:"received_at_ms"`
TimestampSec int64 `json:"timestamp_sec"`
UTCOffsetMin int `json:"utc_offset_min"`
Content []ContentNode `json:"content"`
Attachments []Attachment `json:"attachments"`
}
EditEvent represents a message edit.
func (EditEvent) GetReceivedAtMs ¶
func (EditEvent) GetSessionID ¶
type EventStore ¶
type EventStore struct {
// contains filtered or unexported fields
}
EventStore persists and loads CanonicalEvents from the database.
func NewEventStore ¶
func NewEventStore(log *slog.Logger, queries dbstore.Queries) *EventStore
NewEventStore creates an EventStore.
func (*EventStore) GetDiscussCursor ¶
func (s *EventStore) GetDiscussCursor(ctx context.Context, sessionID, scopeKey string) (DiscussCursorPosition, error)
func (*EventStore) LoadEvents ¶
func (s *EventStore) LoadEvents(ctx context.Context, sessionID string) ([]CanonicalEvent, error)
LoadEvents is the compatibility surface for callers without a bot identity. It is still keyset/byte bounded, but cannot apply a compaction frontier.
func (*EventStore) LoadEventsForReplay ¶ added in v0.20.0
func (s *EventStore) LoadEventsForReplay(ctx context.Context, botID, sessionID string) ([]CanonicalEvent, error)
LoadEventsForReplay applies the active compaction frontier in SQL and loads the newest event tail within a hard byte budget.
func (*EventStore) PersistEvent ¶
func (s *EventStore) PersistEvent(ctx context.Context, botID, sessionID string, event CanonicalEvent) (string, CanonicalEvent, error)
PersistEvent writes a CanonicalEvent to the bot_session_events table with a freshly allocated monotonic event cursor stamped into its payload. Returns the UUID of the persisted event row (empty for ON CONFLICT duplicates) and the stamped event the caller must project instead of the input.
func (*EventStore) SetReplayArtifactProvider ¶ added in v0.20.0
func (s *EventStore) SetReplayArtifactProvider(provider ReplayArtifactProvider)
SetReplayArtifactProvider enables frontier-aware replay. It is setter- injected because the concrete provider belongs to agent compaction.
func (*EventStore) UpsertDiscussCursor ¶
func (s *EventStore) UpsertDiscussCursor(ctx context.Context, sessionID, scopeKey, routeID, source string, position DiscussCursorPosition) error
type ForwardInfo ¶
type ForwardInfo struct {
MessageID string `json:"message_id,omitempty"`
FromUserID string `json:"from_user_id,omitempty"`
FromConversationID string `json:"from_conversation_id,omitempty"`
Sender *CanonicalUser `json:"sender,omitempty"`
SenderName string `json:"sender_name,omitempty"`
Date int64 `json:"date,omitempty"`
}
ForwardInfo describes a forwarded message origin.
type ICMessage ¶
type ICMessage struct {
Type string `json:"type"` // always "message"
MessageID string `json:"message_id"`
Sender *CanonicalUser `json:"sender,omitempty"`
ReceivedAtMs int64 `json:"received_at_ms"`
LastEventCursor int64 `json:"last_event_cursor,omitempty"`
TimestampSec int64 `json:"timestamp_sec"`
UTCOffsetMin int `json:"utc_offset_min"`
Content []ContentNode `json:"content"`
ReplyToMessageID string `json:"reply_to_message_id,omitempty"`
ReplyToSender *CanonicalUser `json:"reply_to_sender,omitempty"`
ReplyToPreview string `json:"reply_to_preview,omitempty"`
ForwardInfo *ForwardInfo `json:"forward_info,omitempty"`
Attachments []Attachment `json:"attachments"`
EditedAtSec int64 `json:"edited_at_sec,omitempty"`
EditUTCOffsetMin int `json:"edit_utc_offset_min,omitempty"`
Deleted bool `json:"deleted,omitempty"`
IsSelfSent bool `json:"is_self_sent,omitempty"`
MentionsMe bool `json:"mentions_me,omitempty"`
RepliesToMe bool `json:"replies_to_me,omitempty"`
Conversation ConversationMeta `json:"conversation"`
}
ICMessage represents a message node in the IntermediateContext.
type ICNode ¶
type ICNode struct {
Message *ICMessage `json:"message,omitempty"`
SystemEvent *ICSystemEvent `json:"system_event,omitempty"`
}
ICNode is a union of ICMessage and ICSystemEvent.
func (ICNode) GetReceivedAtMs ¶
GetReceivedAtMs returns the node's receivedAtMs for ordering.
type ICSystemEvent ¶
type ICSystemEvent struct {
Type string `json:"type"` // always "system_event"
Kind string `json:"kind"`
ReceivedAtMs int64 `json:"received_at_ms"`
LastEventCursor int64 `json:"last_event_cursor,omitempty"`
TimestampSec int64 `json:"timestamp_sec"`
UTCOffsetMin int `json:"utc_offset_min"`
Actor *CanonicalUser `json:"actor,omitempty"`
// Kind-specific fields
UserID string `json:"user_id,omitempty"`
OldUser *CanonicalUser `json:"old_user,omitempty"`
NewUser *CanonicalUser `json:"new_user,omitempty"`
Members []CanonicalUser `json:"members,omitempty"`
Member *CanonicalUser `json:"member,omitempty"`
OldTitle string `json:"old_title,omitempty"`
NewTitle string `json:"new_title,omitempty"`
// For message_pinned
PinnedMessageID string `json:"pinned_message_id,omitempty"`
PinnedPreview string `json:"pinned_preview,omitempty"`
}
ICSystemEvent represents a group lifecycle event in the IC.
type ICUserState ¶
type ICUserState struct {
User CanonicalUser `json:"user"`
FirstSeenAtMs int64 `json:"first_seen_at_ms"`
LastSeenAtMs int64 `json:"last_seen_at_ms"`
MessageCount int `json:"message_count"`
}
ICUserState tracks per-user statistics.
type ImageAttachmentRef ¶
type ImageAttachmentRef struct {
ContentHash string `json:"content_hash"`
Mime string `json:"mime,omitempty"`
}
ImageAttachmentRef holds the content hash and MIME type of an image attachment that can be inlined as a vision input via the media store.
type IntermediateContext ¶
type IntermediateContext struct {
SessionID string `json:"session_id"`
Nodes []ICNode `json:"nodes"`
Users map[string]ICUserState `json:"users"`
ChatTitle string `json:"chat_title,omitempty"`
}
IntermediateContext is the per-session state produced by the Projection layer.
func NewEmptyIC ¶
func NewEmptyIC(sessionID string) IntermediateContext
NewEmptyIC creates a fresh IntermediateContext for a session.
func Reduce ¶
func Reduce(ic IntermediateContext, event CanonicalEvent) IntermediateContext
Reduce applies a CanonicalEvent to an IntermediateContext, returning the new IC. This is a pure function — it does not mutate the input IC.
type MessageEvent ¶
type MessageEvent struct {
SessionID string `json:"session_id"`
EventID string `json:"event_id,omitempty"`
EventCursor int64 `json:"event_cursor,omitempty"`
MessageID string `json:"message_id"`
Sender *CanonicalUser `json:"sender,omitempty"`
ReceivedAtMs int64 `json:"received_at_ms"`
TimestampSec int64 `json:"timestamp_sec"`
UTCOffsetMin int `json:"utc_offset_min"`
Content []ContentNode `json:"content"`
ReplyToMessageID string `json:"reply_to_message_id,omitempty"`
ReplyToSender string `json:"reply_to_sender,omitempty"`
ReplyToPreview string `json:"reply_to_preview,omitempty"`
ForwardInfo *ForwardInfo `json:"forward_info,omitempty"`
Attachments []Attachment `json:"attachments"`
IsSelfSent bool `json:"is_self_sent,omitempty"`
MentionsMe bool `json:"mentions_me,omitempty"`
RepliesToMe bool `json:"replies_to_me,omitempty"`
Conversation ConversationMeta `json:"conversation"`
}
MessageEvent represents a new message in a session.
func (MessageEvent) GetReceivedAtMs ¶
func (e MessageEvent) GetReceivedAtMs() int64
func (MessageEvent) GetSessionID ¶
func (e MessageEvent) GetSessionID() string
func (MessageEvent) Kind ¶
func (MessageEvent) Kind() EventKind
type Pipeline ¶
type Pipeline struct {
// contains filtered or unexported fields
}
Pipeline manages per-thread IC/RC state. It is goroutine-safe.
func NewPipeline ¶
func NewPipeline(params RenderParams) *Pipeline
NewPipeline creates a bounded Pipeline with production defaults.
func NewPipelineWithOptions ¶ added in v0.20.0
func NewPipelineWithOptions(params RenderParams, options PipelineOptions) *Pipeline
NewPipelineWithOptions creates a Pipeline with explicit cache controls.
func (*Pipeline) DropAll ¶ added in v0.20.0
func (p *Pipeline) DropAll()
DropAll removes every resident session. Bot-wide history reset uses this conservative invalidation because cache entries intentionally do not retain bot ownership metadata.
func (*Pipeline) DropSession ¶
DropSession removes a session's state from the pipeline.
func (*Pipeline) GetIC ¶
func (p *Pipeline) GetIC(sessionID string) (IntermediateContext, bool)
GetIC returns an ownership-safe copy of the current projection.
func (*Pipeline) GetRC ¶
func (p *Pipeline) GetRC(sessionID string) RenderedContext
GetRC returns an immutable rendered snapshot, or nil if not loaded.
func (*Pipeline) HasSession ¶ added in v0.20.0
HasSession reports whether a session is resident without cloning its IC.
func (*Pipeline) PushEvent ¶
func (p *Pipeline) PushEvent(sessionID string, event CanonicalEvent) RenderedContext
PushEvent applies one event and renders only dirty/new nodes. Existing rendered slices are detached before replacement so snapshots already queued to a discuss worker remain immutable.
func (*Pipeline) ReplaySession ¶
func (p *Pipeline) ReplaySession(sessionID string, events []CanonicalEvent) RenderedContext
ReplaySession rebuilds IC in place (no per-event full clone), renders once, and records replay volume for operational sizing.
func (*Pipeline) SessionIDs ¶
SessionIDs returns all loaded session IDs.
func (*Pipeline) Stats ¶ added in v0.20.0
func (p *Pipeline) Stats() PipelineStats
Stats returns replay/cache counters without exposing mutable state.
func (*Pipeline) UpdateRenderParams ¶
func (p *Pipeline) UpdateRenderParams(params RenderParams)
UpdateRenderParams replaces render params and re-renders resident sessions.
type PipelineOptions ¶ added in v0.20.0
type PipelineOptions struct {
MaxSessions int
MaxResidentByte int64
TTL time.Duration
Logger *slog.Logger
Now func() time.Time
}
PipelineOptions bounds the in-process projection cache. Zero values select safe defaults; negative limits disable that individual limit for tests.
type PipelineStats ¶ added in v0.20.0
type PipelineStats struct {
ResidentSessions int
ResidentBytes int64
ReplayEvents int64
ReplayBytes int64
Evictions int64
EvictedBytes int64
}
PipelineStats is a point-in-time snapshot of replay/cache counters.
type RenderParams ¶
RenderParams controls rendering behavior.
type RenderedContentPiece ¶
type RenderedContentPiece struct {
Type string `json:"type"` // "text" or "image"
Text string `json:"text,omitempty"`
URL string `json:"url,omitempty"`
}
RenderedContentPiece maps to LLM API content parts.
type RenderedContext ¶
type RenderedContext []RenderedSegment
RenderedContext is the output of the Rendering layer — a slice of segments.
func ActiveRenderedContext ¶
func ActiveRenderedContext(rc RenderedContext, artifacts []CompactionArtifact) RenderedContext
ActiveRenderedContext removes only segments covered by usable artifacts.
func Render ¶
func Render(ic IntermediateContext, params RenderParams) RenderedContext
Render converts an IntermediateContext into a RenderedContext.
type RenderedSegment ¶
type RenderedSegment struct {
MessageID string `json:"message_id,omitempty"`
ReceivedAtMs int64 `json:"received_at_ms"`
LastEventCursor int64 `json:"last_event_cursor,omitempty"`
EditedAtMs int64 `json:"edited_at_ms,omitempty"`
Content []RenderedContentPiece `json:"content"`
IsMyself bool `json:"is_myself,omitempty"`
IsSelfSent bool `json:"is_self_sent,omitempty"`
MentionsMe bool `json:"mentions_me,omitempty"`
RepliesToMe bool `json:"replies_to_me,omitempty"`
ImageRefs []ImageAttachmentRef `json:"image_refs,omitempty"`
}
RenderedSegment is a single segment of rendered context, one per IC node.
type ReplayArtifactProvider ¶ added in v0.20.0
type ReplayArtifactProvider interface {
ActiveCompactionArtifacts(ctx context.Context, botID, sessionID string) ([]CompactionArtifact, error)
}
ReplayArtifactProvider supplies the durable compaction frontier before a replay query loads event payloads.
type ServiceAction ¶
type ServiceAction string
ServiceAction classifies a group lifecycle event.
const ( ServiceMembersJoined ServiceAction = "members_joined" ServiceMemberLeft ServiceAction = "member_left" ServiceChatRenamed ServiceAction = "chat_renamed" ServiceChatPhotoChanged ServiceAction = "chat_photo_changed" ServiceChatPhotoDeleted ServiceAction = "chat_photo_deleted" ServiceMessagePinned ServiceAction = "message_pinned" )
type ServiceEvent ¶
type ServiceEvent struct {
SessionID string `json:"session_id"`
EventID string `json:"event_id,omitempty"`
EventCursor int64 `json:"event_cursor,omitempty"`
Action ServiceAction `json:"action"`
Actor *CanonicalUser `json:"actor,omitempty"`
ReceivedAtMs int64 `json:"received_at_ms"`
TimestampSec int64 `json:"timestamp_sec"`
UTCOffsetMin int `json:"utc_offset_min"`
// Action-specific fields
Members []CanonicalUser `json:"members,omitempty"`
Member *CanonicalUser `json:"member,omitempty"`
NewTitle string `json:"new_title,omitempty"`
OldTitle string `json:"old_title,omitempty"`
// For message_pinned
PinnedMessageID string `json:"pinned_message_id,omitempty"`
PinnedPreview string `json:"pinned_preview,omitempty"`
}
ServiceEvent represents a group lifecycle event (join, leave, rename, etc.).
func (ServiceEvent) GetReceivedAtMs ¶
func (e ServiceEvent) GetReceivedAtMs() int64
func (ServiceEvent) GetSessionID ¶
func (e ServiceEvent) GetSessionID() string
func (ServiceEvent) Kind ¶
func (ServiceEvent) Kind() EventKind
type TurnResponseEntry ¶
type TurnResponseEntry struct {
RequestedAtMs int64 `json:"requested_at_ms"`
Role string `json:"role"`
Content string `json:"content"`
RawContent json.RawMessage `json:"raw_content,omitempty"`
SourceMessageID string `json:"source_message_id,omitempty"`
}
TurnResponseEntry represents an assistant or tool message from bot_history_messages, used as the "TR" stream in context composition.
func DecodeTurnResponseEntries ¶
func DecodeTurnResponseEntries(msgs []messagepkg.Message) []TurnResponseEntry
DecodeTurnResponseEntries converts a chronological run of persisted bot messages into TR entries for pipeline context composition.
Decoding the run as a whole is what lets an interrupted checkpoint's reasoning be projected only while it is still the unfinished frontier; a single message cannot tell whether a completed answer already followed it.
func DecodeTurnResponseEntry ¶
func DecodeTurnResponseEntry(msg messagepkg.Message) (TurnResponseEntry, bool)
DecodeTurnResponseEntry converts a single persisted bot message into a TR entry. Reasoning is always dropped: an interrupted checkpoint's reasoning needs the surrounding history to know whether it is still live, so callers composing context use DecodeTurnResponseEntries instead.