chat

package
v0.0.82 Latest Latest
Warning

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

Go to latest
Published: Feb 18, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RenderEmptyHistory

func RenderEmptyHistory(theme *ui.Theme) string

RenderEmptyHistory renders the "no messages" placeholder.

func RenderScrollIndicator

func RenderScrollIndicator(offset int, theme *ui.Theme) string

RenderScrollIndicator renders the scroll position indicator.

Types

type BlockCache

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

BlockCache is an LRU cache for rendered MessageBlocks. It keeps memory bounded while avoiding re-rendering unchanged messages.

func NewBlockCache

func NewBlockCache(maxSize int) *BlockCache

NewBlockCache creates a new block cache with the given maximum size.

func (*BlockCache) Clear

func (c *BlockCache) Clear()

Clear removes all entries from the cache. Alias for InvalidateAll for semantic clarity.

func (*BlockCache) Get

func (c *BlockCache) Get(key string) *MessageBlock

Get retrieves a block from the cache, returning nil if not found. Accessing a block moves it to the front of the LRU list.

func (*BlockCache) InvalidateAll

func (c *BlockCache) InvalidateAll()

InvalidateAll clears the entire cache. Call this on terminal resize when all cached renders are invalid.

func (*BlockCache) Put

func (c *BlockCache) Put(key string, block *MessageBlock)

Put adds a block to the cache, evicting the least recently used block if the cache is at capacity.

func (*BlockCache) Remove

func (c *BlockCache) Remove(key string)

Remove removes a specific key from the cache.

func (*BlockCache) Size

func (c *BlockCache) Size() int

Size returns the current number of cached blocks.

type ChatRenderer

type ChatRenderer interface {
	// Render returns the full view content for the current state.
	// This is called by View() in the bubbletea model.
	Render(state RenderState) string

	// HandleEvent processes a render event and returns any commands
	// that should be executed (e.g., starting animations).
	HandleEvent(event RenderEvent) tea.Cmd

	// SetSize updates the terminal dimensions.
	// This invalidates caches as needed.
	SetSize(width, height int)

	// Flush returns content that should be printed to scrollback
	// and clears it from the active view (inline mode only).
	Flush() FlushResult

	// FlushAll flushes all remaining content to scrollback.
	// Called when streaming ends.
	FlushAll() FlushResult

	// InvalidateCache forces re-rendering of all cached content.
	// Call this on terminal resize.
	InvalidateCache()

	// SetMarkdownRenderer sets the function used to render markdown.
	SetMarkdownRenderer(renderer MarkdownRenderer)
}

ChatRenderer is the main interface for the chat rendering module. It provides a clean abstraction over the rendering logic, supporting both inline and alt-screen modes with virtualized rendering for large message histories.

type FlushResult

type FlushResult struct {
	// Content to print to scrollback (empty if nothing to flush)
	Content string
}

FlushResult contains the result of flushing content to scrollback

type InputState

type InputState struct {
	Height  int  // Height of input area in lines
	Focused bool // Whether input is focused
}

InputState tracks input area state for rendering

type MarkdownRenderer

type MarkdownRenderer func(content string, width int) string

MarkdownRenderer is a function that renders markdown content

type MessageBlock

type MessageBlock struct {
	// MessageID is the unique identifier for this message
	MessageID int64

	// Rendered is the complete rendered output for this message
	Rendered string

	// Height is the number of lines in the rendered output
	Height int

	// Width is the terminal width when this block was rendered
	// (used for cache invalidation on resize)
	Width int
}

MessageBlock represents a pre-rendered, cacheable message. Once rendered, blocks are immutable and can be reused across frames.

type MessageBlockRenderer

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

MessageBlockRenderer renders session messages to MessageBlocks.

func NewMessageBlockRenderer

func NewMessageBlockRenderer(width int, mdRenderer MarkdownRenderer) *MessageBlockRenderer

NewMessageBlockRenderer creates a new renderer for message blocks.

func NewMessageBlockRendererWithContext

func NewMessageBlockRendererWithContext(width int, mdRenderer MarkdownRenderer, messages []session.Message, index int) *MessageBlockRenderer

NewMessageBlockRendererWithContext creates a new renderer with message context for tool result lookup. This allows rendering diffs for edit_file tool calls by finding the corresponding tool result in subsequent messages.

func (*MessageBlockRenderer) Render

Render converts a session.Message to a MessageBlock.

type RenderEvent

type RenderEvent struct {
	Type RenderEventType

	// For RenderEventMessageAdded
	MessageID    int64
	MessageRole  string
	MessageIndex int

	// For RenderEventMessagesLoaded
	MessageCount int

	// For streaming text events
	Text string

	// For streaming tool events
	ToolCallID  string
	ToolName    string
	ToolInfo    string
	ToolSuccess bool

	// For streaming image/diff events
	ImagePath string
	DiffPath  string
	DiffOld   string
	DiffNew   string
	DiffLine  int

	// For ask user results
	AskUserSummary string

	// For resize events
	Width  int
	Height int

	// For scroll events
	ScrollOffset int

	// For error events
	Err error
}

RenderEvent represents an event that affects rendering. The renderer processes these events to update its internal state and produce the appropriate output.

func FromStreamEvent

func FromStreamEvent(ev ui.StreamEvent) RenderEvent

FromStreamEvent converts a ui.StreamEvent to a RenderEvent

func NewInvalidateCacheEvent

func NewInvalidateCacheEvent() RenderEvent

NewInvalidateCacheEvent creates an event to force cache invalidation

func NewMessageAddedEvent

func NewMessageAddedEvent(id int64, role string, index int) RenderEvent

NewMessageAddedEvent creates an event for when a message is added to history

func NewMessagesLoadedEvent

func NewMessagesLoadedEvent(count int) RenderEvent

NewMessagesLoadedEvent creates an event for when messages are loaded from storage

func NewResizeEvent

func NewResizeEvent(width, height int) RenderEvent

NewResizeEvent creates an event for terminal resize

func NewScrollEvent

func NewScrollEvent(offset int) RenderEvent

NewScrollEvent creates an event for scroll changes

func NewStreamAskUserResultEvent

func NewStreamAskUserResultEvent(summary string) RenderEvent

NewStreamAskUserResultEvent creates an event for ask_user results

func NewStreamDiffEvent

func NewStreamDiffEvent(path, old, new string, line int) RenderEvent

NewStreamDiffEvent creates an event for when a diff is generated

func NewStreamEndEvent

func NewStreamEndEvent() RenderEvent

NewStreamEndEvent creates an event for when streaming ends

func NewStreamErrorEvent

func NewStreamErrorEvent(err error) RenderEvent

NewStreamErrorEvent creates an event for streaming errors

func NewStreamImageEvent

func NewStreamImageEvent(path string) RenderEvent

NewStreamImageEvent creates an event for when an image is generated

func NewStreamStartEvent

func NewStreamStartEvent() RenderEvent

NewStreamStartEvent creates an event for when streaming begins

func NewStreamTextEvent

func NewStreamTextEvent(text string) RenderEvent

NewStreamTextEvent creates an event for streaming text content

func NewStreamToolEndEvent

func NewStreamToolEndEvent(callID, name, info string, success bool) RenderEvent

NewStreamToolEndEvent creates an event for when a tool finishes executing

func NewStreamToolStartEvent

func NewStreamToolStartEvent(callID, name, info string) RenderEvent

NewStreamToolStartEvent creates an event for when a tool starts executing

type RenderEventType

type RenderEventType int

RenderEventType identifies the type of render event

const (
	// Message events (historical)
	RenderEventMessageAdded RenderEventType = iota
	RenderEventMessagesLoaded
	RenderEventMessagesClear

	// Streaming events
	RenderEventStreamStart
	RenderEventStreamText
	RenderEventStreamToolStart
	RenderEventStreamToolEnd
	RenderEventStreamImage
	RenderEventStreamDiff
	RenderEventStreamAskUserResult
	RenderEventStreamEnd
	RenderEventStreamError

	// UI events
	RenderEventResize
	RenderEventScroll
	RenderEventInvalidateCache
)

type RenderMode

type RenderMode int

RenderMode determines how content is displayed

const (
	RenderModeInline    RenderMode = iota // Traditional inline mode with scrollback
	RenderModeAltScreen                   // Full-screen alternate screen mode
)

type RenderState

type RenderState struct {
	Messages  []session.Message
	Streaming *StreamingState // nil if not streaming
	Viewport  ViewportState
	Input     InputState
	Mode      RenderMode
	Width     int
	Height    int
	ShowStats bool
	Error     error // Display error if set
}

RenderState holds all state needed for rendering

type Renderer

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

Renderer implements ChatRenderer with virtualized rendering and caching for performance.

func NewRenderer

func NewRenderer(width, height int) *Renderer

NewRenderer creates a new chat renderer with the given dimensions.

func (*Renderer) ClearStreaming

func (r *Renderer) ClearStreaming()

ClearStreaming clears the streaming state without flushing. Call this when starting a new prompt.

func (*Renderer) Flush

func (r *Renderer) Flush() FlushResult

Flush returns content that should be printed to scrollback.

func (*Renderer) FlushAll

func (r *Renderer) FlushAll() FlushResult

FlushAll flushes all remaining content to scrollback.

func (*Renderer) GetStreamingContent

func (r *Renderer) GetStreamingContent() string

GetStreamingContent returns the completed streaming content for caching. Used in alt-screen mode to preserve diffs/images after streaming ends.

func (*Renderer) HandleEvent

func (r *Renderer) HandleEvent(event RenderEvent) tea.Cmd

HandleEvent processes a render event and returns any commands.

func (*Renderer) InvalidateCache

func (r *Renderer) InvalidateCache()

InvalidateCache forces re-rendering of all cached content.

func (*Renderer) Render

func (r *Renderer) Render(state RenderState) string

Render returns the full view content for the current state.

func (*Renderer) SetMarkdownRenderer

func (r *Renderer) SetMarkdownRenderer(renderer MarkdownRenderer)

SetMarkdownRenderer sets the function used to render markdown.

func (*Renderer) SetSize

func (r *Renderer) SetSize(width, height int)

SetSize updates the terminal dimensions and invalidates width-dependent caches.

type StreamingBlock

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

StreamingBlock handles rendering of the active streaming response. It manages segments (text, tools, images, diffs) and provides incremental flushing for inline mode.

func NewStreamingBlock

func NewStreamingBlock(width int, mdRenderer MarkdownRenderer) *StreamingBlock

NewStreamingBlock creates a new streaming block.

func (*StreamingBlock) AddAskUserResult

func (s *StreamingBlock) AddAskUserResult(summary string)

AddAskUserResult adds an ask_user result segment.

func (*StreamingBlock) AddDiff

func (s *StreamingBlock) AddDiff(path, old, new string, line int)

AddDiff adds a diff segment.

func (*StreamingBlock) AddImage

func (s *StreamingBlock) AddImage(path string)

AddImage adds an image segment.

func (*StreamingBlock) AddText

func (s *StreamingBlock) AddText(text string)

AddText adds streaming text content.

func (*StreamingBlock) Complete

func (s *StreamingBlock) Complete()

Complete marks the streaming as complete.

func (*StreamingBlock) EndTool

func (s *StreamingBlock) EndTool(callID string, success bool)

EndTool updates the status of a pending tool.

func (*StreamingBlock) Flush

func (s *StreamingBlock) Flush() FlushResult

Flush returns content to print to scrollback and marks it as flushed.

func (*StreamingBlock) FlushAll

func (s *StreamingBlock) FlushAll() FlushResult

FlushAll flushes all remaining content.

func (*StreamingBlock) GetCompletedContent

func (s *StreamingBlock) GetCompletedContent() string

GetCompletedContent returns the full rendered content for caching. Used to preserve images/diffs after streaming ends in alt-screen mode.

func (*StreamingBlock) GetTracker

func (s *StreamingBlock) GetTracker() *ui.ToolTracker

GetTracker returns the underlying ToolTracker. This is used for compatibility with existing code during migration.

func (*StreamingBlock) HandleWavePause

func (s *StreamingBlock) HandleWavePause() tea.Cmd

HandleWavePause handles wave animation pause end.

func (*StreamingBlock) HandleWaveTick

func (s *StreamingBlock) HandleWaveTick() tea.Cmd

HandleWaveTick handles wave animation tick.

func (*StreamingBlock) HasPendingTools

func (s *StreamingBlock) HasPendingTools() bool

HasPendingTools returns true if there are pending tools.

func (*StreamingBlock) Render

func (s *StreamingBlock) Render(wavePos int, pausedForUI bool, includeImages bool) string

Render renders the streaming block content. wavePos is the wave animation position (-1 = paused). pausedForUI is true when paused for external UI (hide indicator). includeImages controls whether to render images inline.

func (*StreamingBlock) Resize

func (s *StreamingBlock) Resize(width int)

Resize updates the width and invalidates cached renders.

func (*StreamingBlock) SetError

func (s *StreamingBlock) SetError(err error)

SetError sets an error on the streaming block.

func (*StreamingBlock) SetTracker

func (s *StreamingBlock) SetTracker(tracker *ui.ToolTracker)

SetTracker sets the underlying ToolTracker. This is used for compatibility with existing code during migration.

func (*StreamingBlock) StartTool

func (s *StreamingBlock) StartTool(callID, name, info string) bool

StartTool adds a new pending tool segment. Returns true if a new segment was added (for starting wave animation).

func (*StreamingBlock) StartWaveAnimation

func (s *StreamingBlock) StartWaveAnimation() tea.Cmd

StartWaveAnimation starts the wave animation for pending tools.

type StreamingState

type StreamingState struct {
	Phase       string   // Current phase ("Thinking", "Responding", etc.)
	WavePos     int      // Wave animation position (-1 = paused)
	SpinnerView string   // Pre-rendered spinner string
	RetryStatus string   // Retry status message if any
	PausedForUI bool     // True when paused for external UI
	ElapsedSecs float64  // Seconds since stream started
	Tokens      int      // Current token count
	ActiveTools []string // Names of currently executing tools
}

StreamingState represents the state of active streaming

type ViewportInfo

type ViewportInfo struct {
	StartMessage int  // First visible message index
	EndMessage   int  // Last visible message index (exclusive)
	TotalHeight  int  // Total height of all messages
	VisibleStart int  // First visible line (from top of all content)
	VisibleEnd   int  // Last visible line (from top of all content)
	AtTop        bool // True if showing the first message
	AtBottom     bool // True if showing the last message
}

ViewportInfo contains information about the current viewport state.

type ViewportState

type ViewportState struct {
	Height       int // Visible height in lines
	ScrollOffset int // Scroll offset from bottom (0 = bottom)
	AtBottom     bool
}

ViewportState tracks the viewport scroll position

type VirtualViewport

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

VirtualViewport handles virtualized rendering of message history. Instead of rendering all messages, it calculates which messages are visible in the viewport and only renders those.

func NewVirtualViewport

func NewVirtualViewport(width, height int) *VirtualViewport

NewVirtualViewport creates a new virtual viewport.

func (*VirtualViewport) CalculateTotalHeight

func (v *VirtualViewport) CalculateTotalHeight(heights []int) int

CalculateTotalHeight calculates the total height of all messages. This is used for scroll calculations.

func (*VirtualViewport) EstimateMessageHeight

func (v *VirtualViewport) EstimateMessageHeight(msg *session.Message) int

EstimateMessageHeight gives a rough estimate of how many lines a message will take. This is used for initial viewport calculations before actual rendering.

func (*VirtualViewport) GetViewportInfo

func (v *VirtualViewport) GetViewportInfo(messages []session.Message, heights []int, scrollOffset int) ViewportInfo

GetViewportInfo returns detailed information about the current viewport.

func (*VirtualViewport) GetVisibleRange

func (v *VirtualViewport) GetVisibleRange(messages []session.Message, scrollOffset int) (int, int)

GetVisibleRange returns the start and end indices (exclusive) of messages that should be rendered for the current viewport.

scrollOffset is the number of messages scrolled up from the bottom. Returns (start, end) where messages[start:end] should be rendered.

func (*VirtualViewport) GetVisibleRangeWithHeights

func (v *VirtualViewport) GetVisibleRangeWithHeights(messages []session.Message, heights []int, scrollOffset int) (int, int)

GetVisibleRangeWithHeights returns the visible range using actual rendered heights. This is more accurate but requires heights to be known.

Jump to

Keyboard shortcuts

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