timeline

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: 21 Imported by: 0

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

View Source
const MaxJSONSafeEventCursor int64 = 1<<53 - 1

MaxJSONSafeEventCursor bounds legitimate event cursors; the allocation sequence never exceeds it, so larger payload values are corrupt data.

View Source
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

type CanonicalEvent interface {
	Kind() EventKind
	GetSessionID() string
	GetReceivedAtMs() int64
}

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

type DiscussCursorPosition struct {
	EventCursor  int64
	SourceCursor int64
}

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

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

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 (e EditEvent) GetReceivedAtMs() int64

func (EditEvent) GetSessionID

func (e EditEvent) GetSessionID() string

func (EditEvent) Kind

func (EditEvent) Kind() EventKind

type EventKind

type EventKind string

EventKind classifies a canonical event.

const (
	EventMessage EventKind = "message"
	EventEdit    EventKind = "edit"
	EventDelete  EventKind = "delete"
	EventService EventKind = "service"
)

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) HasEvents

func (s *EventStore) HasEvents(ctx context.Context, sessionID string) (bool, error)

HasEvents checks whether a session has any events persisted.

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

func (n ICNode) GetReceivedAtMs() int64

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

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

func (p *Pipeline) DropSession(sessionID string)

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

func (p *Pipeline) HasSession(sessionID string) bool

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

func (p *Pipeline) SessionIDs() []string

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

type RenderParams struct {
	BotUserID    string
	ContactNames map[string]string
}

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

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.

Jump to

Keyboard shortcuts

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