ui

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

Documentation

Index

Constants

View Source
const (
	// SectionBreakTrailingNewlines is the minimum trailing newline run that
	// separates adjacent output sections.
	SectionBreakTrailingNewlines = 1
	// FinalSpacerTrailingNewlines is the minimum trailing newline run to keep
	// one spacer line before the next prompt after completion.
	FinalSpacerTrailingNewlines = 2
)
View Source
const (
	SmoothFrameInterval    = 16 * time.Millisecond // 60fps
	SmoothBufferCapacity   = 500                   // characters
	SmoothMinWordsPerFrame = 1
	SmoothMaxWordsPerFrame = 5
	SmoothMaxWordLength    = 12 // Chunk words longer than this
)

Smooth buffer constants for 60fps adaptive rendering

View Source
const (
	EnabledIcon  = "●"
	DisabledIcon = "○"
	SuccessIcon  = "✓"
	FailIcon     = "✗"
)

Status indicators

View Source
const DefaultStreamBufferSize = 100

DefaultStreamBufferSize is the default buffer size for the event channel. Large enough to handle bursts while still providing backpressure.

View Source
const SomethingElse = "__something_else__"

Variables

View Source
var PresetThemeNames = []string{
	"gruvbox",
	"dracula",
	"nord",
	"solarized",
	"monokai",
	"classic",
}

PresetThemeNames defines the display order of themes

View Source
var PresetThemes = map[string]ThemePreset{
	"classic": {
		Name:        "classic",
		Description: "Classic green terminal style",
		Config: ThemeConfig{
			Primary:   "10",
			Secondary: "4",
			Success:   "10",
			Error:     "9",
			Warning:   "11",
			Muted:     "245",
			Text:      "15",
			Spinner:   "205",
		},
	},
	"dracula": {
		Name:        "dracula",
		Description: "Popular dark theme with purple accents",
		Config: ThemeConfig{
			Primary:   "#bd93f9",
			Secondary: "#8be9fd",
			Success:   "#50fa7b",
			Error:     "#ff5555",
			Warning:   "#f1fa8c",
			Muted:     "#6272a4",
			Text:      "#f8f8f2",
			Spinner:   "#ff79c6",
		},
	},
	"nord": {
		Name:        "nord",
		Description: "Arctic, north-bluish color palette",
		Config: ThemeConfig{
			Primary:   "#88c0d0",
			Secondary: "#81a1c1",
			Success:   "#a3be8c",
			Error:     "#bf616a",
			Warning:   "#ebcb8b",
			Muted:     "#4c566a",
			Text:      "#eceff4",
			Spinner:   "#b48ead",
		},
	},
	"solarized": {
		Name:        "solarized",
		Description: "Precision colors for machines and people",
		Config: ThemeConfig{
			Primary:   "#268bd2",
			Secondary: "#2aa198",
			Success:   "#859900",
			Error:     "#dc322f",
			Warning:   "#b58900",
			Muted:     "#586e75",
			Text:      "#839496",
			Spinner:   "#d33682",
		},
	},
	"monokai": {
		Name:        "monokai",
		Description: "Vibrant colors inspired by Sublime Text",
		Config: ThemeConfig{
			Primary:   "#a6e22e",
			Secondary: "#66d9ef",
			Success:   "#a6e22e",
			Error:     "#f92672",
			Warning:   "#e6db74",
			Muted:     "#75715e",
			Text:      "#f8f8f2",
			Spinner:   "#ae81ff",
		},
	},
	"gruvbox": {
		Name:        "gruvbox",
		Description: "Retro groove color scheme (default)",
		Config: ThemeConfig{
			Primary:   "#b8bb26",
			Secondary: "#83a598",
			Success:   "#b8bb26",
			Error:     "#fb4934",
			Warning:   "#fabd2f",
			Muted:     "#928374",
			Text:      "#ebdbb2",
			Spinner:   "#d3869b",
		},
	},
}

PresetThemes contains all predefined themes

Functions

func ANSILen added in v0.0.6

func ANSILen(s string) int

ANSILen returns the display width of a string, ignoring ANSI codes

func BuildSubagentPreview added in v0.0.42

func BuildSubagentPreview(p *SubagentProgress, maxLines int) []string

BuildSubagentPreview builds preview lines for a subagent in chronological order. Shows completed tools first (oldest first), then active tools (most recent). maxLines is the total number of lines to show.

func CalcDiffWidth added in v0.0.5

func CalcDiffWidth(oldContent, newContent string) int

CalcDiffWidth calculates the required padding width for a diff The result is capped to the terminal-aware max content width

func ClearRenderedImages added in v0.0.39

func ClearRenderedImages()

ClearRenderedImages clears the cache of rendered images. Call this when starting a new session.

func ComposeFlushFirstCommands added in v0.0.62

func ComposeFlushFirstCommands(flushCmds []tea.Cmd, asyncCmds []tea.Cmd) tea.Cmd

ComposeFlushFirstCommands builds a command pipeline where flush commands run first in-order, and all non-flush commands run afterward.

This prevents output-printing commands from racing with follow-up commands when the caller needs deterministic boundary rendering.

func CountLines added in v0.0.35

func CountLines(content string) int

CountLines counts the number of newlines in content

func CountTrailingNewlines added in v0.0.69

func CountTrailingNewlines(s string) int

CountTrailingNewlines returns how many '\n' characters appear at the end of s.

func ErrorCircle added in v0.0.26

func ErrorCircle() string

ErrorCircle returns the error status indicator

func FindSafeBoundary added in v0.0.46

func FindSafeBoundary(text string) int

FindSafeBoundary finds the last byte position where markdown context is complete. Returns -1 if no safe boundary exists.

A safe boundary is a position after which we can split the text without breaking markdown rendering. Safe positions are: - After complete paragraphs (\n\n) - After closed code blocks (balanced ``` markers) - When not inside incomplete inline markers (**, `, etc.)

func FindSafeBoundaryIncremental added in v0.0.46

func FindSafeBoundaryIncremental(text string, lastSafePos int) int

FindSafeBoundaryIncremental finds a safe boundary only scanning from lastSafePos. This is O(delta) instead of O(n) for streaming scenarios. Returns -1 if no new safe boundary exists beyond lastSafePos.

func FormatTokenCount added in v0.0.61

func FormatTokenCount(n int) string

FormatTokenCount formats a token count in compact form: 1, 999, 1.5k, 12.3k, 1.1M

func GetPendingToolTextLen added in v0.0.26

func GetPendingToolTextLen(segments []Segment) int

GetPendingToolTextLen returns the text length of the first pending tool (for wave animation)

func GetRefinement

func GetRefinement() (string, error)

GetRefinement prompts the user for additional guidance

func GlamourStyle added in v0.0.31

func GlamourStyle() ansi.StyleConfig

GlamourStyle returns a glamour StyleConfig based on the current theme

func GlamourStyleFromTheme added in v0.0.31

func GlamourStyleFromTheme(theme *Theme) ansi.StyleConfig

GlamourStyleFromTheme creates a glamour StyleConfig from the given theme

func HandleSubagentProgress added in v0.0.42

func HandleSubagentProgress(tracker *ToolTracker, subagentTracker *SubagentTracker, callID string, event tools.SubagentEvent)

HandleSubagentProgress processes subagent events and updates both the subagent tracker and the corresponding spawn_agent segment's stats. This is shared logic used by both the ask command (streaming mode) and the chat TUI.

tracker: the ToolTracker containing segments subagentTracker: the SubagentTracker for subagent progress callID: the tool call ID of the spawn_agent invocation event: the subagent event to process

func HasDiff added in v0.0.10

func HasDiff(oldContent, newContent string) bool

HasDiff returns true if old and new content are different

func HasPendingTool added in v0.0.26

func HasPendingTool(segments []Segment) bool

HasPendingTool returns true if any segment has a pending tool

func InitTheme

func InitTheme(cfg ThemeConfig)

InitTheme initializes the theme from config

func MatchPresetTheme added in v0.0.31

func MatchPresetTheme(cfg ThemeConfig) string

MatchPresetTheme finds a preset that matches the given config, or returns empty string

func NewlinePadding added in v0.0.69

func NewlinePadding(currentTrailing, targetTrailing int) string

NewlinePadding returns the minimal newline padding needed to reach at least targetTrailing trailing newlines.

func NewlinesNeededForTrailing added in v0.0.69

func NewlinesNeededForTrailing(currentTrailing, targetTrailing int) int

NewlinesNeededForTrailing returns the number of '\n' characters required to reach at least targetTrailing newlines.

func NormalizeNewlines added in v0.0.55

func NormalizeNewlines(s string) string

NormalizeNewlines reduces 3+ consecutive newlines to 2 (one blank line max). This fixes inconsistent spacing between headers caused by glamour's hardcoded extra newline before headings combined with our BlockSuffix settings.

func ParseBoolDefault added in v0.0.74

func ParseBoolDefault(raw string, defaultValue bool) bool

ParseBoolDefault parses a boolean-like environment value with a fallback default. True values: 1, true, yes, on, y False values: 0, false, no, off, n Empty/unknown values return defaultValue.

func PendingCircle added in v0.0.26

func PendingCircle() string

PendingCircle returns the pending status indicator

func PrintCompactDiff added in v0.0.5

func PrintCompactDiff(filePath, oldContent, newContent string, padWidth int)

PrintCompactDiff prints a compact diff with 2 lines of context and line numbers padWidth specifies the total line width for consistent backgrounds across diffs

func PrintUnifiedDiff added in v0.0.10

func PrintUnifiedDiff(filePath, oldContent, newContent string)

PrintUnifiedDiff prints a clean unified diff between old and new content If multiFile is true, shows the filename header (for multi-file diffs)

func PrintUnifiedDiffMulti added in v0.0.10

func PrintUnifiedDiffMulti(filePath, oldContent, newContent string)

PrintUnifiedDiffMulti prints a diff with filename header (for multi-file edits)

func PromptApplyEdit added in v0.0.5

func PromptApplyEdit() bool

PromptApplyEdit asks the user whether to apply an edit Returns true if user wants to apply (Enter or y), false to skip (n)

func RenderDiffSegment added in v0.0.46

func RenderDiffSegment(filePath, oldContent, newContent string, width int, startLine int) string

RenderDiffSegment renders a unified diff as a string for inline display. Returns empty string if no changes or on error. The width parameter is used for wrapping long lines. The startLine parameter is the 1-indexed line number where the edit starts (0 = use diff header).

func RenderImagesAndDiffs added in v0.0.50

func RenderImagesAndDiffs(segments []*Segment, width int) string

RenderImagesAndDiffs renders only image and diff segments from a list. This is used for alt screen mode to preserve images/diffs after streaming ends, since text content is already stored in message history.

func RenderInlineImage added in v0.0.39

func RenderInlineImage(path string) string

RenderInlineImage renders an image as terminal escape sequences for inline display. The rendered output is cached, so subsequent calls return the cached result. Returns empty string on error or if terminal doesn't support images. The cache is limited to maxImageCacheSize entries; oldest entries are evicted when full. The cache is invalidated when the file's modification time changes.

func RenderMarkdown added in v0.0.34

func RenderMarkdown(content string, width int) string

RenderMarkdown renders markdown content using glamour with standard styling. This is the main function for rendering markdown in streaming contexts. On error, returns the original content unchanged.

func RenderMarkdownWithError added in v0.0.34

func RenderMarkdownWithError(content string, width int) (string, error)

RenderMarkdownWithError renders markdown content and returns any errors. Use this variant when error handling is needed.

func RenderSegments added in v0.0.26

func RenderSegments(segments []*Segment, width int, wavePos int, renderMarkdown func(string, int) string, includeImages bool) string

RenderSegments renders a list of segments with proper spacing.

func RenderSegmentsWithLeading added in v0.0.55

func RenderSegmentsWithLeading(leading *Segment, segments []*Segment, width int, wavePos int, renderMarkdown func(string, int) string, includeImages bool) string

RenderSegmentsWithLeading renders a list of segments, optionally using a leading segment for initial spacing.

func RenderSubagentProgress added in v0.0.42

func RenderSubagentProgress(p *SubagentProgress, expanded bool) string

RenderSubagentProgress renders progress for a single subagent. This is used when displaying inline beneath a spawn_agent tool indicator.

func RenderToolCallFromPart added in v0.0.49

func RenderToolCallFromPart(tc *llm.ToolCall, width int) string

RenderToolCallFromPart renders a historical tool call from an llm.ToolCall. Uses success styling since historical calls have completed. width is the terminal width used to truncate long lines (0 = no truncation).

func RenderToolSegment added in v0.0.26

func RenderToolSegment(seg *Segment, wavePos int, width int) string

RenderToolSegment renders a tool segment with its status indicator. For pending tools, wavePos controls the wave animation (-1 = paused/all dim). Tool name is rendered normally, params are rendered in slightly muted gray. For spawn_agent tools with progress, stats are shown instead of wave animation. width is the terminal width used to truncate long lines (0 = no truncation).

func RenderWaveText added in v0.0.26

func RenderWaveText(text string, wavePos int) string

RenderWaveText renders text with a wave animation effect using bold highlighting. wavePos is the position of the bright "peak" traveling through the text. If wavePos < 0, we're in the pause phase - show all dim.

func RunSetupWizard

func RunSetupWizard() (*config.Config, error)

RunSetupWizard runs the first-time setup wizard and returns the config

func RunWithSpinner

func RunWithSpinner(ctx context.Context, debug bool, run func(context.Context) (any, error)) (any, error)

RunWithSpinner shows a spinner while executing the provided function.

func RunWithSpinnerProgress added in v0.0.11

func RunWithSpinnerProgress(ctx context.Context, debug bool, progress <-chan ProgressUpdate, run func(context.Context) (any, error)) (any, error)

RunWithSpinnerProgress shows a spinner with progress updates while executing the provided function. The progress channel can receive updates with token counts, status messages, and milestones.

func RunWithSpinnerProgressAndHooks added in v0.0.26

func RunWithSpinnerProgressAndHooks(ctx context.Context, debug bool, progress <-chan ProgressUpdate, run func(context.Context) (any, error), setupHooks ApprovalHookSetup) (any, error)

RunWithSpinnerProgressAndHooks is like RunWithSpinnerProgress but also sets up approval hooks. The setupHooks function is called with pause/resume functions that should be used to set up tools.SetApprovalHooks() so the spinner pauses during tool approval prompts.

func ScrollbackPrintlnCommands added in v0.0.69

func ScrollbackPrintlnCommands(content string, includeFinalSpacer bool) []tea.Cmd

ScrollbackPrintlnCommands returns tea.Println command(s) for content and an optional final spacer line. It preserves content while avoiding synthetic double-newline inflation from unconditional blank-line commands.

func SegmentSeparator added in v0.0.55

func SegmentSeparator(prevType, currType SegmentType) string

SegmentSeparator returns the vertical spacing (newlines) required between two segments.

func SelectCommand

func SelectCommand(suggestions []llm.CommandSuggestion, shell string, engine *llm.Engine, allowNonTTY bool) (selected string, refinement string, err error)

SelectCommand presents the user with a list of command suggestions and returns the selected one. Returns the selected command or SomethingElse if user wants to refine their request. When SomethingElse is returned, the second return value contains the user's refinement text. If engine is non-nil and user presses 'i', shows help for the highlighted command. allowNonTTY permits a non-interactive fallback when no TTY is available.

func SetTheme

func SetTheme(t *Theme)

SetTheme sets the current active theme

func ShowCommand

func ShowCommand(cmd string)

ShowCommand displays the command that will be executed (to stderr, keeping stdout clean)

func ShowCommandHelp

func ShowCommandHelp(command, shell string, engine *llm.Engine) error

ShowCommandHelp renders scrollable help for a command

func ShowEditInfo added in v0.0.10

func ShowEditInfo(aboutText string)

ShowEditInfo displays the about/info text in a fullscreen pager

func ShowEditSkipped added in v0.0.5

func ShowEditSkipped(filePath string, reason string)

ShowEditSkipped shows that an edit was skipped

func ShowError

func ShowError(msg string)

ShowError displays an error message

func SmoothTick added in v0.0.39

func SmoothTick() tea.Cmd

SmoothTick returns a tea.Cmd that sends a SmoothTickMsg after the frame interval

func SplitLines added in v0.0.35

func SplitLines(content string) []string

SplitLines splits content by newlines. Unlike strings.Split, this does NOT include an empty trailing element for content ending in newline. Example: "hello\nworld\n" → ["hello", "world"] (not ["hello", "world", ""])

func StripANSI added in v0.0.6

func StripANSI(s string) string

StripANSI removes all ANSI escape codes from a string

func SuccessCircle added in v0.0.26

func SuccessCircle() string

SuccessCircle returns the success status indicator

func Truncate

func Truncate(s string, maxLen int) string

Truncate shortens a string to maxLen with ellipsis

func UpdateSegmentFromSubagentProgress added in v0.0.42

func UpdateSegmentFromSubagentProgress(tracker *ToolTracker, callID string, p *SubagentProgress)

UpdateSegmentFromSubagentProgress updates the spawn_agent segment stats from subagent progress. This syncs the subagent's stats (tool calls, tokens, provider/model) to the segment for display.

func WorkingCircle added in v0.0.29

func WorkingCircle() string

WorkingCircle returns the working status indicator

Types

type ApprovalHookSetup added in v0.0.26

type ApprovalHookSetup func(pause, resume func())

ApprovalHookSetup is called with functions to pause/resume the spinner. It should set up approval hooks that call these functions.

type DiffData added in v0.0.55

type DiffData = llm.DiffData

DiffData is an alias for llm.DiffData for backward compatibility.

func ParseDiffMarkers added in v0.0.55

func ParseDiffMarkers(output string) []DiffData

ParseDiffMarkers extracts diff data from tool output that contain __DIFF__: markers. Used for backward compatibility when rendering old sessions that have markers in Display/Content. Format: __DIFF__:<base64-encoded JSON>

type EditApprovalResult added in v0.0.10

type EditApprovalResult int

EditApprovalResult represents the result of batch approval prompt

const (
	EditApprovalYes  EditApprovalResult = iota // Apply all changes
	EditApprovalNo                             // Skip all changes
	EditApprovalInfo                           // Show info/about text
)

func PromptBatchApproval added in v0.0.10

func PromptBatchApproval(hasInfo bool, reprompt bool) EditApprovalResult

PromptBatchApproval asks user to approve all changes with option to see info Returns EditApprovalYes, EditApprovalNo, or EditApprovalInfo If reprompt is true, clears the line before showing prompt (used after returning from info)

type FlushStreamingTextResult added in v0.0.52

type FlushStreamingTextResult struct {
	// ToPrint is the rendered content to print to scrollback (empty if nothing to flush)
	ToPrint string
}

FlushStreamingTextResult contains the result of a streaming text flush.

type FlushToScrollbackResult added in v0.0.34

type FlushToScrollbackResult struct {
	// ToPrint is the content to print to scrollback (empty if nothing to flush)
	ToPrint string
	// NewPrintedLines is kept for API compatibility but no longer used for tracking
	NewPrintedLines int
}

FlushToScrollbackResult contains the result of a scrollback flush operation.

type Highlighter added in v0.0.6

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

Highlighter handles syntax highlighting for diff display

func NewHighlighter added in v0.0.6

func NewHighlighter(filePath string) *Highlighter

NewHighlighter creates a highlighter for the given file path. Returns nil if the language is not recognized. Results are cached since lexers.Match is expensive (iterates all ~500 lexers).

func (*Highlighter) HighlightLine added in v0.0.6

func (h *Highlighter) HighlightLine(line string) string

HighlightLine applies syntax highlighting to a line without a background color.

func (*Highlighter) HighlightLineWithBg added in v0.0.6

func (h *Highlighter) HighlightLineWithBg(line string, bg [3]int) string

HighlightLineWithBg applies syntax highlighting to a line with a specific background color. bg is an RGB array [r, g, b] for true color background.

type PlanStreamAdapter added in v0.0.52

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

PlanStreamAdapter bridges an llm.Stream to a channel of StreamEvents, with inline edit marker parsing for the plan mode. It converts text stream events into inline edit events when markers are detected.

func NewPlanStreamAdapter added in v0.0.52

func NewPlanStreamAdapter(bufSize int) *PlanStreamAdapter

NewPlanStreamAdapter creates a new PlanStreamAdapter with the specified buffer size. If bufSize <= 0, DefaultStreamBufferSize is used.

func (*PlanStreamAdapter) EmitErrorAndClose added in v0.0.52

func (a *PlanStreamAdapter) EmitErrorAndClose(err error)

EmitErrorAndClose sends an error event and closes the channel. Use this when stream creation fails before ProcessStream can be called.

func (*PlanStreamAdapter) Events added in v0.0.52

func (a *PlanStreamAdapter) Events() <-chan StreamEvent

Events returns the channel to read events from.

func (*PlanStreamAdapter) ProcessStream added in v0.0.52

func (a *PlanStreamAdapter) ProcessStream(ctx context.Context, stream llm.Stream)

ProcessStream reads events from the llm.Stream and sends them to the events channel. Text events are parsed for inline edit markers (INSERT/DELETE) and converted to StreamEventInlineInsert/StreamEventInlineDelete events. This method blocks until the stream is exhausted or an error occurs. The events channel is closed when this method returns.

Call this in a goroutine:

go adapter.ProcessStream(ctx, stream)

func (*PlanStreamAdapter) Stats added in v0.0.52

func (a *PlanStreamAdapter) Stats() *SessionStats

Stats returns the session stats being tracked.

type ProgressUpdate added in v0.0.11

type ProgressUpdate struct {
	// OutputTokens is the number of tokens generated so far.
	OutputTokens int

	// Status is the current status text (e.g., "editing main.go").
	Status string

	// Milestone is a completed milestone to print above the spinner
	// (e.g., "✓ Found edit for main.go").
	Milestone string

	// Phase is the current phase of the operation (e.g., "Thinking", "Responding").
	// Used to show state transitions in the spinner.
	Phase string
}

ProgressUpdate represents a progress update during long-running operations.

type Segment added in v0.0.26

type Segment struct {
	Type         SegmentType
	Text         string     // For text segments: markdown content (finalized on completion)
	Rendered     string     // For text segments: cached rendered markdown
	ToolCallID   string     // For tool segments: unique ID for this invocation
	ToolName     string     // For tool segments
	ToolInfo     string     // For tool segments: additional context
	ToolStatus   ToolStatus // For tool segments
	Complete     bool       // For text segments: whether streaming is complete
	ImagePath    string     // For image segments: path to image file
	DiffPath     string     // For diff segments: file path
	DiffOld      string     // For diff segments: old content
	DiffNew      string     // For diff segments: new content
	DiffLine     int        // For diff segments: 1-indexed starting line (0 = unknown)
	DiffRendered string     // For diff segments: cached rendered output
	DiffWidth    int        // For diff segments: width when rendered (for cache invalidation)
	Flushed      bool       // True if this segment has been printed to scrollback

	// Streaming text accumulation (O(1) append instead of O(n) string concat)
	TextBuilder *strings.Builder // Used during streaming; nil when Complete

	// Text snapshot cache - updated on append to avoid repeated String() calls
	TextSnapshot    string // Cached result of TextBuilder.String()
	TextSnapshotLen int    // Length when snapshot was taken (0 = invalid)

	// Streaming markdown renderer - renders complete blocks as they arrive
	StreamRenderer *TextSegmentRenderer // Active streaming renderer; nil when Complete

	// Incremental rendering cache (streaming optimization)
	SafePos            int    // Byte position of last safe markdown boundary
	SafeRendered       string // Cached render of text[:SafePos]
	FlushedPos         int    // Byte position up to which content has been flushed to scrollback
	FlushedRenderedPos int    // Number of rendered bytes already flushed to scrollback

	// Stitched rendering state (for correct inter-chunk spacing)
	LastFlushedRaw         string // Raw markdown of last flushed chunk (for stitched rendering)
	LastFlushedRenderedLen int    // Byte length of rendered LastFlushedRaw

	// Subagent stats (for spawn_agent tools only)
	SubagentToolCalls   int            // Number of tool calls made by subagent
	SubagentTotalTokens int            // Total tokens used by subagent
	SubagentHasProgress bool           // True if we have progress from this subagent
	SubagentProvider    string         // Provider name if different from parent
	SubagentModel       string         // Model name if different from parent
	SubagentPreview     []string       // Preview lines (active tools + last few text lines)
	SubagentStartTime   time.Time      // Start time for elapsed time display
	SubagentEndTime     time.Time      // When subagent completed (zero if still running)
	SubagentDiffs       []SubagentDiff // Diffs from subagent's edit_file calls
}

Segment represents a discrete unit in the response stream (text or tool)

func FindSegmentByCallID added in v0.0.42

func FindSegmentByCallID(tracker *ToolTracker, callID string) *Segment

FindSegmentByCallID finds a segment by its tool call ID. Returns nil if not found.

func UpdateToolStatus added in v0.0.26

func UpdateToolStatus(segments []Segment, callID string, success bool) []Segment

UpdateToolStatus updates the status of a pending tool matching the given call ID. Matching by unique ID ensures we update the correct tool when multiple calls to the same tool may be in progress.

func (*Segment) GetText added in v0.0.46

func (s *Segment) GetText() string

GetText returns the current text content of a segment. During streaming, it uses the cached TextSnapshot; after completion, it reads from Text. The snapshot is updated by AddTextSegment when content changes, avoiding repeated O(n) String() allocations on every render tick.

type SegmentType added in v0.0.26

type SegmentType int

SegmentType identifies the type of stream segment

const (
	SegmentText SegmentType = iota
	SegmentTool
	SegmentAskUserResult // For ask_user answers (plain text, styled at render time)
	SegmentImage         // For inline image display
	SegmentDiff          // For inline diff display from edit tool
)

type SessionStats added in v0.0.19

type SessionStats struct {
	StartTime         time.Time
	InputTokens       int
	OutputTokens      int
	CachedInputTokens int // Tokens read from cache
	CacheWriteTokens  int // Tokens written to cache
	ToolCallCount     int
	LLMCallCount      int // Number of LLM API calls made

	// Time tracking
	LLMTime  time.Duration
	ToolTime time.Duration
	// contains filtered or unexported fields
}

SessionStats tracks statistics for a session.

func NewSessionStats added in v0.0.19

func NewSessionStats() *SessionStats

NewSessionStats creates a new SessionStats with StartTime set to now.

func (*SessionStats) AddUsage added in v0.0.19

func (s *SessionStats) AddUsage(input, output, cached, cacheWrite int)

AddUsage adds token usage to the stats and increments the LLM call count.

func (*SessionStats) Finalize added in v0.0.19

func (s *SessionStats) Finalize()

Finalize records any remaining time.

func (SessionStats) Render added in v0.0.19

func (s SessionStats) Render() string

Render returns the stats as a compact single-line string.

func (*SessionStats) SeedTotals added in v0.0.73

func (s *SessionStats) SeedTotals(input, output, cached, toolCalls, llmCalls int)

SeedTotals initializes cumulative counters from persisted session metrics. Timing remains scoped to the current process run.

func (*SessionStats) ToolEnd added in v0.0.19

func (s *SessionStats) ToolEnd()

ToolEnd marks the end of tool execution (back to LLM).

func (*SessionStats) ToolStart added in v0.0.19

func (s *SessionStats) ToolStart()

ToolStart marks the start of a tool execution.

type SmoothBuffer added in v0.0.39

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

SmoothBuffer provides smooth 60fps text streaming with adaptive speed. Text is buffered and released word-by-word at a pace that adapts to the incoming content rate.

func NewSmoothBuffer added in v0.0.39

func NewSmoothBuffer() *SmoothBuffer

NewSmoothBuffer creates a new SmoothBuffer

func (*SmoothBuffer) FlushAll added in v0.0.39

func (b *SmoothBuffer) FlushAll() string

FlushAll returns all remaining content (for immediate display on tool start or cancel)

func (*SmoothBuffer) IsDrained added in v0.0.39

func (b *SmoothBuffer) IsDrained() bool

IsDrained returns true if the stream is done and buffer is empty

func (*SmoothBuffer) IsEmpty added in v0.0.39

func (b *SmoothBuffer) IsEmpty() bool

IsEmpty returns true if the buffer is empty

func (*SmoothBuffer) Len added in v0.0.39

func (b *SmoothBuffer) Len() int

Len returns the current buffer size in bytes

func (*SmoothBuffer) MarkDone added in v0.0.39

func (b *SmoothBuffer) MarkDone()

MarkDone signals that the input stream has ended

func (*SmoothBuffer) NextWords added in v0.0.39

func (b *SmoothBuffer) NextWords() string

NextWords returns the next N words based on buffer fill level. Long words are chunked into pieces. Whitespace is preserved.

func (*SmoothBuffer) Reset added in v0.0.39

func (b *SmoothBuffer) Reset()

Reset clears the buffer and resets the done flag

func (*SmoothBuffer) Write added in v0.0.39

func (b *SmoothBuffer) Write(text string)

Write adds incoming text to the buffer

type SmoothTickMsg added in v0.0.39

type SmoothTickMsg struct{}

SmoothTickMsg is sent to trigger the next frame of smooth text rendering

type StreamAdapter added in v0.0.34

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

StreamAdapter bridges an llm.Stream to a channel of StreamEvents. It handles event conversion and provides proper buffering with blocking sends to ensure no events are dropped.

func NewStreamAdapter added in v0.0.34

func NewStreamAdapter(bufSize int) *StreamAdapter

NewStreamAdapter creates a new StreamAdapter with the specified buffer size. If bufSize <= 0, DefaultStreamBufferSize is used.

func (*StreamAdapter) EmitErrorAndClose added in v0.0.34

func (a *StreamAdapter) EmitErrorAndClose(err error)

EmitErrorAndClose sends an error event and closes the channel. Use this when stream creation fails before ProcessStream can be called.

func (*StreamAdapter) Events added in v0.0.34

func (a *StreamAdapter) Events() <-chan StreamEvent

Events returns the channel to read events from.

func (*StreamAdapter) ProcessStream added in v0.0.34

func (a *StreamAdapter) ProcessStream(ctx context.Context, stream llm.Stream)

ProcessStream reads events from the llm.Stream and sends them to the events channel. This method blocks until the stream is exhausted or an error occurs. The events channel is closed when this method returns.

Call this in a goroutine:

go adapter.ProcessStream(ctx, stream)

func (*StreamAdapter) Stats added in v0.0.34

func (a *StreamAdapter) Stats() *SessionStats

Stats returns the session stats being tracked.

type StreamEvent added in v0.0.34

type StreamEvent struct {
	Type StreamEventType

	// Text content (for StreamEventText)
	Text string

	// Tool events (for StreamEventToolStart, StreamEventToolEnd)
	ToolCallID  string
	ToolName    string
	ToolInfo    string
	ToolSuccess bool

	// Usage/stats (for StreamEventUsage)
	InputTokens  int
	OutputTokens int
	CachedTokens int
	WriteTokens  int

	// Phase/retry (for StreamEventPhase, StreamEventRetry)
	Phase        string
	RetryAttempt int
	RetryMax     int
	RetryWait    float64

	// Completion (for StreamEventDone)
	Done   bool
	Tokens int // Total output tokens at completion

	// Error (for StreamEventError)
	Err error

	// Image (for StreamEventImage)
	ImagePath string

	// Diff (for StreamEventDiff)
	DiffPath string
	DiffOld  string
	DiffNew  string
	DiffLine int // 1-indexed starting line number (0 = unknown)

	// Inline edits (for StreamEventInlineInsert, StreamEventInlineDelete, StreamEventPartialInsert)
	InlineAfter   string   // INSERT: anchor text to insert after
	InlineContent []string // INSERT: lines to insert (for complete insert)
	InlineLine    string   // PartialInsert: single line being streamed
	InlineFrom    string   // DELETE: start line text
	InlineTo      string   // DELETE: end line text (empty for single line)
}

StreamEvent represents a unified event from the LLM stream. Used by both ask and chat commands for consistent event handling.

func DiffEvent added in v0.0.46

func DiffEvent(path, old, new string, line int) StreamEvent

DiffEvent creates a diff event from edit tool

func DoneEvent added in v0.0.34

func DoneEvent(totalTokens int) StreamEvent

DoneEvent creates a stream completion event

func ErrorEvent added in v0.0.34

func ErrorEvent(err error) StreamEvent

ErrorEvent creates an error event

func ImageEvent added in v0.0.39

func ImageEvent(path string) StreamEvent

ImageEvent creates an image event

func InlineDeleteEvent added in v0.0.52

func InlineDeleteEvent(from, to string) StreamEvent

InlineDeleteEvent creates an inline delete event

func InlineInsertEvent added in v0.0.52

func InlineInsertEvent(after string, content []string) StreamEvent

InlineInsertEvent creates an inline insert event

func InterjectionEvent added in v0.0.82

func InterjectionEvent(text string) StreamEvent

InterjectionEvent creates an interjection event (user message injected mid-stream)

func PartialInsertEvent added in v0.0.52

func PartialInsertEvent(after, line string) StreamEvent

PartialInsertEvent creates a partial insert event for streaming lines

func PhaseEvent added in v0.0.34

func PhaseEvent(phase string) StreamEvent

PhaseEvent creates a phase change event

func RetryEvent added in v0.0.34

func RetryEvent(attempt, max int, waitSecs float64) StreamEvent

RetryEvent creates a retry notification event

func TextEvent added in v0.0.34

func TextEvent(text string) StreamEvent

TextEvent creates a text delta event

func ToolEndEvent added in v0.0.34

func ToolEndEvent(callID, name, info string, success bool) StreamEvent

ToolEndEvent creates a tool execution end event

func ToolStartEvent added in v0.0.34

func ToolStartEvent(callID, name, info string) StreamEvent

ToolStartEvent creates a tool execution start event

func UsageEvent added in v0.0.34

func UsageEvent(input, output, cached, cacheWrite int) StreamEvent

UsageEvent creates a usage/token update event

type StreamEventType added in v0.0.34

type StreamEventType int

StreamEventType identifies the type of stream event

const (
	StreamEventText StreamEventType = iota
	StreamEventToolStart
	StreamEventToolEnd
	StreamEventUsage
	StreamEventPhase
	StreamEventRetry
	StreamEventDone
	StreamEventError
	StreamEventImage         // Image produced by tool
	StreamEventDiff          // Diff from edit tool
	StreamEventInterjection  // User interjected a message mid-stream
	StreamEventInlineInsert  // Inline INSERT marker from planner (complete)
	StreamEventInlineDelete  // Inline DELETE marker from planner
	StreamEventPartialInsert // Streaming partial line during INSERT
)

type StreamingIndicator added in v0.0.15

type StreamingIndicator struct {
	Spinner        string // spinner.View() output
	Phase          string // "Thinking", "Searching", etc.
	Elapsed        time.Duration
	Tokens         int                      // 0 = don't show
	Status         string                   // optional status (e.g., "editing main.go")
	ShowCancel     bool                     // show "(esc to cancel)"
	HideProgress   bool                     // hide spinner/phase/tokens/time (shown in status line instead)
	Segments       []*Segment               // active tool segments for wave animation
	WavePos        int                      // current wave position
	Width          int                      // terminal width for markdown rendering
	RenderMarkdown func(string, int) string // markdown renderer for text segments

	// Flush state for leading spacing
	HasFlushed      bool
	LastFlushedType SegmentType
}

StreamingIndicator renders a consistent streaming status line

func (StreamingIndicator) Render added in v0.0.15

func (s StreamingIndicator) Render(styles *Styles) string

Render returns the formatted streaming indicator string

type Styles

type Styles struct {

	// Text styles
	Title       lipgloss.Style
	Subtitle    lipgloss.Style
	Success     lipgloss.Style
	Error       lipgloss.Style
	Muted       lipgloss.Style
	Bold        lipgloss.Style
	Highlighted lipgloss.Style

	// Table styles
	TableHeader lipgloss.Style
	TableCell   lipgloss.Style
	TableBorder lipgloss.Style

	// UI element styles
	Spinner lipgloss.Style
	Command lipgloss.Style
	Footer  lipgloss.Style

	// Diff styles
	DiffAdd     lipgloss.Style // Added lines (+)
	DiffRemove  lipgloss.Style // Removed lines (-)
	DiffContext lipgloss.Style // Context lines (unchanged)
	DiffHeader  lipgloss.Style // Diff header (@@ ... @@)
	// contains filtered or unexported fields
}

Styles returns styled text helpers bound to a renderer

func DefaultStyles

func DefaultStyles() *Styles

DefaultStyles returns styles for stderr (default TUI output)

func NewStyledWithTheme

func NewStyledWithTheme(output *os.File, theme *Theme) *Styles

NewStyledWithTheme creates styles with a specific theme

func NewStyles

func NewStyles(output *os.File) *Styles

NewStyles creates a new Styles instance for the given output

func (*Styles) FormatEnabled

func (s *Styles) FormatEnabled(enabled bool) string

FormatEnabled returns a styled enabled/disabled indicator

func (*Styles) FormatResult

func (s *Styles) FormatResult(success bool, msg string) string

FormatResult returns a styled success/fail result

func (*Styles) Theme

func (s *Styles) Theme() *Theme

Theme returns the theme used by these styles

type SubagentDiff added in v0.0.46

type SubagentDiff struct {
	Path     string
	Old      string
	New      string
	Line     int    // 1-indexed starting line (0 = unknown)
	Rendered string // Cached rendered output
	Width    int    // Width when rendered (for cache invalidation)
}

SubagentDiff holds diff info from a subagent's edit_file call

type SubagentProgress added in v0.0.42

type SubagentProgress struct {
	ToolCallID     string          // Links to parent's spawn_agent call
	AgentName      string          // e.g., "reviewer"
	TextBuffer     strings.Builder // Text output (capped at maxTextBufferBytes)
	ActiveTools    []ToolSegment   // Currently running tools
	CompletedTools []ToolSegment   // Completed tools (for expanded view)
	Phase          string          // "Thinking", "Searching"
	StartTime      time.Time
	Done           bool

	// Provider/model info (for displaying when different from parent)
	Provider string // Provider name (e.g., "anthropic", "openai")
	Model    string // Model name (e.g., "claude-sonnet-4-20250514")

	// Stats for header display
	ToolCalls    int // Total tool calls made
	InputTokens  int // Total input tokens
	OutputTokens int // Total output tokens
	// contains filtered or unexported fields
}

SubagentProgress tracks progress from a single spawned subagent.

func (*SubagentProgress) GetPreviewLines added in v0.0.42

func (p *SubagentProgress) GetPreviewLines() []string

GetPreviewLines returns the current preview lines for external access.

func (*SubagentProgress) Render added in v0.0.42

func (p *SubagentProgress) Render(expanded bool, maxPreviewLines int) string

Render returns preview (last N lines) or full content based on expanded flag.

func (*SubagentProgress) RenderHeader added in v0.0.42

func (p *SubagentProgress) RenderHeader(expanded bool) string

RenderHeader returns "@name N calls · X.Xk tokens [expanded]".

type SubagentTracker added in v0.0.42

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

SubagentTracker tracks progress from multiple concurrent subagents.

func NewSubagentTracker added in v0.0.42

func NewSubagentTracker() *SubagentTracker

NewSubagentTracker creates a new tracker with default settings.

func (*SubagentTracker) ActiveAgents added in v0.0.42

func (t *SubagentTracker) ActiveAgents() []*SubagentProgress

ActiveAgents returns all non-done subagents in order of start time.

func (*SubagentTracker) Get added in v0.0.42

func (t *SubagentTracker) Get(callID string) *SubagentProgress

Get returns the progress tracker for a subagent, or nil if not found.

func (*SubagentTracker) GetOrCreate added in v0.0.42

func (t *SubagentTracker) GetOrCreate(callID, agentName string) *SubagentProgress

GetOrCreate returns the progress tracker for a subagent, creating if needed. Returns nil if the subagent has already been removed (tombstone exists).

func (*SubagentTracker) HandleInit added in v0.0.42

func (t *SubagentTracker) HandleInit(callID, provider, model string)

HandleInit sets the provider and model for a subagent. Only stores values if they differ from the main agent's provider/model.

func (*SubagentTracker) HandlePhase added in v0.0.42

func (t *SubagentTracker) HandlePhase(callID, phase string)

HandlePhase updates the phase of a subagent.

func (*SubagentTracker) HandleTextDelta added in v0.0.42

func (t *SubagentTracker) HandleTextDelta(callID, text string)

HandleTextDelta appends text to a subagent's buffer. The full buffer is capped at maxTextBufferBytes to prevent unbounded memory growth. Preview lines are always updated regardless of buffer cap.

func (*SubagentTracker) HandleToolEnd added in v0.0.42

func (t *SubagentTracker) HandleToolEnd(callID, toolName string, success bool)

HandleToolEnd marks a tool as completed in a subagent.

func (*SubagentTracker) HandleToolStart added in v0.0.42

func (t *SubagentTracker) HandleToolStart(callID, toolName, toolInfo string)

HandleToolStart records a tool starting in a subagent.

func (*SubagentTracker) HandleUsage added in v0.0.42

func (t *SubagentTracker) HandleUsage(callID string, inputTokens, outputTokens int)

HandleUsage accumulates token usage for a subagent.

func (*SubagentTracker) HasActive added in v0.0.42

func (t *SubagentTracker) HasActive() bool

HasActive returns true if there are any active (non-done) subagents.

func (*SubagentTracker) IsExpanded added in v0.0.42

func (t *SubagentTracker) IsExpanded() bool

IsExpanded returns whether expanded mode is active.

func (*SubagentTracker) MarkDone added in v0.0.42

func (t *SubagentTracker) MarkDone(callID string)

MarkDone marks a subagent as completed.

func (*SubagentTracker) Remove added in v0.0.42

func (t *SubagentTracker) Remove(callID string)

Remove removes a subagent from tracking (after spawn_agent completes). A tombstone is added to prevent late async events from resurrecting the entry. Only adds a tombstone if the callID was actually being tracked, to avoid unbounded tombstone growth from non-spawn_agent tool calls.

func (*SubagentTracker) SetMainProviderModel added in v0.0.42

func (t *SubagentTracker) SetMainProviderModel(provider, model string)

SetMainProviderModel sets the main agent's provider and model for comparison. Subagent provider/model will only be displayed if different from main.

func (*SubagentTracker) ToggleExpanded added in v0.0.42

func (t *SubagentTracker) ToggleExpanded()

ToggleExpanded switches between preview (4 lines) and full content.

type TextSegmentRenderer added in v0.0.53

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

TextSegmentRenderer wraps the streaming markdown renderer for use with text segments. It buffers rendered output so View() can read it.

func NewTextSegmentRenderer added in v0.0.53

func NewTextSegmentRenderer(width int) (*TextSegmentRenderer, error)

NewTextSegmentRenderer creates a new TextSegmentRenderer with the given width. Uses flowing mode (no cursor control) since Bubble Tea owns the terminal.

func (*TextSegmentRenderer) Close added in v0.0.53

func (r *TextSegmentRenderer) Close() error

Close flushes and cleans up the renderer.

func (*TextSegmentRenderer) CommittedMarkdownLen added in v0.0.55

func (r *TextSegmentRenderer) CommittedMarkdownLen() int

CommittedMarkdownLen returns the number of raw markdown bytes that have been committed as complete blocks by the streaming renderer.

func (*TextSegmentRenderer) Flush added in v0.0.53

func (r *TextSegmentRenderer) Flush() error

Flush renders any remaining incomplete blocks. Call this when the segment is complete.

func (*TextSegmentRenderer) FlushedRenderedPos added in v0.0.53

func (r *TextSegmentRenderer) FlushedRenderedPos() int

FlushedRenderedPos returns the current flushed position in the rendered output.

func (*TextSegmentRenderer) MarkFlushed added in v0.0.53

func (r *TextSegmentRenderer) MarkFlushed()

MarkFlushed marks the current rendered output length as flushed. Call this after successfully flushing content to scrollback.

func (*TextSegmentRenderer) PendingIsList added in v0.0.75

func (r *TextSegmentRenderer) PendingIsList() bool

PendingIsList reports whether the current incomplete block should be treated as a list for preview purposes.

func (*TextSegmentRenderer) PendingIsTable added in v0.0.60

func (r *TextSegmentRenderer) PendingIsTable() bool

PendingIsTable reports whether the current incomplete block is a table.

func (*TextSegmentRenderer) PendingMarkdown added in v0.0.60

func (r *TextSegmentRenderer) PendingMarkdown() string

PendingMarkdown returns the markdown that belongs to the current incomplete block.

func (*TextSegmentRenderer) Rendered added in v0.0.53

func (r *TextSegmentRenderer) Rendered() string

Rendered returns the currently rendered output. This is the content to display in View().

func (*TextSegmentRenderer) RenderedAll added in v0.0.55

func (r *TextSegmentRenderer) RenderedAll() string

RenderedAll returns the full rendered output including already-flushed content.

func (*TextSegmentRenderer) RenderedUnflushed added in v0.0.53

func (r *TextSegmentRenderer) RenderedUnflushed() string

RenderedUnflushed returns only the portion of rendered output that hasn't been flushed to scrollback yet. Use this in View() to avoid duplicating content that was already printed via FlushStreamingText.

func (*TextSegmentRenderer) Resize added in v0.0.53

func (r *TextSegmentRenderer) Resize(newWidth int) error

Resize handles terminal resize by re-rendering with new width. Note: The caller should handle any necessary screen clearing.

func (*TextSegmentRenderer) Width added in v0.0.53

func (r *TextSegmentRenderer) Width() int

Width returns the current terminal width.

func (*TextSegmentRenderer) Write added in v0.0.53

func (r *TextSegmentRenderer) Write(text string) error

Write writes text to the streaming renderer. Complete markdown blocks are rendered immediately.

type Theme

type Theme struct {
	// Primary colors
	Primary   lipgloss.Color // main accent color (commands, highlights)
	Secondary lipgloss.Color // secondary accent (headers, borders)

	// Semantic colors
	Success lipgloss.Color // success states, enabled
	Error   lipgloss.Color // error states, disabled
	Warning lipgloss.Color // warnings
	Muted   lipgloss.Color // dimmed/secondary text
	Text    lipgloss.Color // primary text

	// UI element colors
	Spinner    lipgloss.Color // loading spinner
	Border     lipgloss.Color // borders and dividers
	Background lipgloss.Color // background (if needed)

	// Diff backgrounds
	DiffAddBg     lipgloss.Color // background for added lines
	DiffRemoveBg  lipgloss.Color // background for removed lines
	DiffContextBg lipgloss.Color // background for context lines

	// Message backgrounds
	UserMsgBg lipgloss.Color // background for user messages in chat
}

Theme defines the color palette for the UI

func DefaultTheme

func DefaultTheme() *Theme

DefaultTheme returns the default color theme (gruvbox)

func GetTheme

func GetTheme() *Theme

GetTheme returns the current active theme

func ThemeFromConfig

func ThemeFromConfig(cfg ThemeConfig) *Theme

ThemeFromConfig creates a theme with config overrides applied

type ThemeConfig

type ThemeConfig struct {
	Primary   string
	Secondary string
	Success   string
	Error     string
	Warning   string
	Muted     string
	Text      string
	Spinner   string
	UserMsgBg string
}

ThemeConfig mirrors the config.ThemeConfig for applying overrides

type ThemePreset added in v0.0.31

type ThemePreset struct {
	Name        string
	Description string
	Config      ThemeConfig
}

ThemePreset represents a predefined color theme

func GetPresetTheme added in v0.0.31

func GetPresetTheme(name string) *ThemePreset

GetPresetTheme returns a preset by name, or nil if not found

type ToolPhase added in v0.0.25

type ToolPhase struct {
	// Active is the phase text shown during execution (e.g., "web_search(cats)")
	Active string
	// Completed is the text shown after completion (e.g., "web_search(cats)")
	Completed string
}

ToolPhase contains display strings for a tool execution phase.

func FormatToolPhase added in v0.0.25

func FormatToolPhase(name, info string) ToolPhase

FormatToolPhase returns display strings for a tool based on name and preview info. Uses unified format: name + info (where info contains parenthesized args). Example: web_search(cats), read_file(/src/main.go)

type ToolSegment added in v0.0.42

type ToolSegment struct {
	Name    string
	Info    string
	Success bool
	Done    bool
}

ToolSegment represents a tool's execution state in a subagent.

type ToolStatus added in v0.0.26

type ToolStatus int

ToolStatus represents the execution state of a tool

const (
	ToolPending ToolStatus = iota
	ToolSuccess
	ToolError
)

type ToolTracker added in v0.0.30

type ToolTracker struct {
	Segments     []Segment
	WavePos      int
	WavePaused   bool
	LastActivity time.Time
	Version      uint64 // Incremented when content changes (segments added/modified)
	TextMode     bool   // When true, skip markdown rendering (plain text output)

	// Flush state for consistent spacing
	LastFlushedType SegmentType
	HasFlushed      bool
}

ToolTracker manages tool segment state and wave animation. Designed to be embedded in larger models (ask, chat) for consistent tool tracking.

func NewToolTracker added in v0.0.30

func NewToolTracker() *ToolTracker

NewToolTracker creates a new ToolTracker

func (*ToolTracker) ActiveSegments added in v0.0.30

func (t *ToolTracker) ActiveSegments() []*Segment

ActiveSegments returns only the pending tool segments (for rendering). Returns pointers so mutations (like SafeRendered caching) persist.

func (*ToolTracker) AddDiffSegment added in v0.0.46

func (t *ToolTracker) AddDiffSegment(path, old, new string, line int)

AddDiffSegment adds a diff segment for inline display.

func (*ToolTracker) AddExternalUIResult added in v0.0.37

func (t *ToolTracker) AddExternalUIResult(summary string)

AddExternalUIResult adds a result from external UI (like ask_user) as a completed segment. The summary is plain text - styling is applied at render time to avoid ANSI corruption when passing through different tea.Program instances.

func (*ToolTracker) AddImageSegment added in v0.0.39

func (t *ToolTracker) AddImageSegment(path string)

AddImageSegment adds an image segment for inline display.

func (*ToolTracker) AddPreRenderedTextSegment added in v0.0.82

func (t *ToolTracker) AddPreRenderedTextSegment(rendered string)

AddPreRenderedTextSegment adds a text segment that is already fully rendered (e.g., styled interjection prompts). The segment is marked Complete immediately with the Rendered field set, so it bypasses markdown rendering entirely.

func (*ToolTracker) AddTextSegment added in v0.0.30

func (t *ToolTracker) AddTextSegment(text string, width int) bool

AddTextSegment adds or appends to a text segment. width is used to create the streaming markdown renderer for proper formatting. Returns true if this created a new segment.

func (*ToolTracker) AllCompletedSegments added in v0.0.52

func (t *ToolTracker) AllCompletedSegments() []*Segment

AllCompletedSegments returns all non-pending segments regardless of Flushed status. Use this for the final View() to ensure nothing is lost when segments were flushed to scrollback during streaming but we need the complete content for the final render.

func (*ToolTracker) AllSegments added in v0.0.46

func (t *ToolTracker) AllSegments() []Segment

AllSegments returns all segments regardless of Flushed status. Use for alt screen mode where we render everything in View().

func (*ToolTracker) CompleteTextSegments added in v0.0.30

func (t *ToolTracker) CompleteTextSegments(renderFunc func(string) string)

CompleteTextSegments marks all incomplete text segments as complete. Renders the full text with glamour on completion.

func (*ToolTracker) CompletedSegments added in v0.0.30

func (t *ToolTracker) CompletedSegments() []*Segment

CompletedSegments returns non-pending, non-flushed segments up to (but not past) the first pending tool. This preserves interleaving order: text before a pending tool is shown, but text after it is held back until the tool completes. Returns pointers so mutations (like SafeRendered caching) persist.

func (*ToolTracker) FlushAllRemaining added in v0.0.34

func (t *ToolTracker) FlushAllRemaining(
	width int,
	printedLines int,
	renderMd func(string, int) string,
) FlushToScrollbackResult

FlushAllRemaining returns any remaining unflushed content. Use this at the end of streaming to ensure all content is visible.

func (*ToolTracker) FlushBeforeExternalUI added in v0.0.37

func (t *ToolTracker) FlushBeforeExternalUI(
	width int,
	printedLines int,
	keepLines int,
	renderMd func(string, int) string,
) FlushToScrollbackResult

FlushBeforeExternalUI flushes content to scrollback before showing external UI. Keeps some recent content visible for context.

func (*ToolTracker) FlushCompletedNow added in v0.0.61

func (t *ToolTracker) FlushCompletedNow(
	width int,
	renderMd func(string, int) string,
) FlushToScrollbackResult

FlushCompletedNow flushes all completed, unflushed segments immediately. Unlike FlushToScrollback, this does not keep any segments for View(). Pending tools and incomplete text segments are never flushed.

func (*ToolTracker) FlushLeadingSeparator added in v0.0.61

func (t *ToolTracker) FlushLeadingSeparator(nextType SegmentType) string

FlushLeadingSeparator returns the spacing before a flushed segment, accounting for the trailing newline that tea.Printf/tea.Println adds. Use this only when the previous content was printed via a separate tea.Printf call. For intra-ToPrint spacing (multiple parts in one flush), use LeadingSeparator.

func (*ToolTracker) FlushStreamingText added in v0.0.52

func (t *ToolTracker) FlushStreamingText(threshold int, width int, renderMd func(string, int) string) FlushStreamingTextResult

FlushStreamingText flushes portions of in-progress text segments to scrollback when they exceed the threshold. Uses safe markdown boundaries to avoid breaking formatting. Returns rendered content to print, or empty if nothing to flush.

Parameters:

  • threshold: minimum bytes before attempting flush (e.g., 4000)
  • width: terminal width for rendering
  • renderMd: markdown render function (text, width) -> rendered

func (*ToolTracker) FlushToScrollback added in v0.0.34

func (t *ToolTracker) FlushToScrollback(
	width int,
	printedLines int,
	maxViewLines int,
	renderMd func(string, int) string,
) FlushToScrollbackResult

FlushToScrollback flushes completed segments to scrollback. Incomplete text segments are NOT flushed - they show as raw text in View() and get rendered with glamour only when completed.

Parameters:

  • width: terminal width for rendering
  • printedLines: (unused, kept for API compatibility)
  • maxViewLines: minimum completed segments to keep unflushed for View()
  • renderMd: markdown render function (text, width) -> rendered

func (*ToolTracker) ForceCompletePendingTools added in v0.0.55

func (t *ToolTracker) ForceCompletePendingTools()

ForceCompletePendingTools marks any pending tools as complete. Call this before FlushAllRemaining when streaming is done to ensure no tools are left in pending state (which would be skipped during flush).

func (*ToolTracker) HandleToolEnd added in v0.0.30

func (t *ToolTracker) HandleToolEnd(callID string, success bool)

HandleToolEnd updates the status of a pending tool by its call ID.

func (*ToolTracker) HandleToolStart added in v0.0.30

func (t *ToolTracker) HandleToolStart(callID, toolName, toolInfo string) bool

HandleToolStart adds a pending segment for this tool call. Uses the unique callID to track this specific invocation. Returns true if a new segment was added (caller should start wave animation).

func (*ToolTracker) HandleWavePause added in v0.0.30

func (t *ToolTracker) HandleWavePause() tea.Cmd

HandleWavePause handles the end of a wave pause. Returns the next tick command if there are still pending tools.

func (*ToolTracker) HandleWaveTick added in v0.0.30

func (t *ToolTracker) HandleWaveTick() tea.Cmd

HandleWaveTick advances the wave animation. Returns the next command (tick, pause, or nil if no pending tools).

func (*ToolTracker) HasPending added in v0.0.30

func (t *ToolTracker) HasPending() bool

HasPending returns true if there are any pending tool segments.

func (*ToolTracker) IsIdle added in v0.0.34

func (t *ToolTracker) IsIdle(d time.Duration) bool

IsIdle returns true if there has been no activity for the given duration and there are no pending tools (tools have their own wave animation).

func (*ToolTracker) LeadingSeparator added in v0.0.55

func (t *ToolTracker) LeadingSeparator(nextType SegmentType) string

LeadingSeparator returns the full spacing before a segment of the given type, based on the last flushed segment. Use this for View()/Render() output and when appending multiple parts within a single ToPrint (no tea.Printf between them). For spacing across tea.Printf boundaries, use FlushLeadingSeparator instead.

func (*ToolTracker) MarkCurrentTextComplete added in v0.0.30

func (t *ToolTracker) MarkCurrentTextComplete(renderFunc func(string) string)

MarkCurrentTextComplete marks the current text segment as complete before a tool starts. Renders the full text with glamour.

func (*ToolTracker) RecordActivity added in v0.0.34

func (t *ToolTracker) RecordActivity()

RecordActivity records the current time as the last activity. Call this when text is received, tools start, or tools end.

func (*ToolTracker) RenderUnflushed added in v0.0.55

func (t *ToolTracker) RenderUnflushed(width int, renderMd func(string, int) string, includeImages bool) string

RenderUnflushed renders all non-pending, non-flushed segments with proper leading spacing.

func (*ToolTracker) ResizeStreamRenderers added in v0.0.53

func (t *ToolTracker) ResizeStreamRenderers(width int)

ResizeStreamRenderers updates all active streaming renderers with new width. On resize error, the renderer is disabled to avoid inconsistent output.

func (*ToolTracker) StartWave added in v0.0.30

func (t *ToolTracker) StartWave() tea.Cmd

StartWave initializes and starts the wave animation. Returns the command to start the tick cycle.

func (*ToolTracker) UnflushedSegments added in v0.0.52

func (t *ToolTracker) UnflushedSegments() []*Segment

UnflushedSegments returns segments with unflushed content for final rendering. For text segments with partial flushes (FlushedPos > 0), creates a copy with only the unflushed portion. This ensures we don't duplicate content that was already printed to scrollback during streaming.

type WavePauseMsg added in v0.0.30

type WavePauseMsg struct{}

WavePauseMsg is sent when wave pause ends

type WaveTickMsg added in v0.0.30

type WaveTickMsg struct{}

WaveTickMsg is sent to advance the wave animation

Directories

Path Synopsis
Package streaming provides a streaming markdown renderer that wraps glamour's TermRenderer.
Package streaming provides a streaming markdown renderer that wraps glamour's TermRenderer.

Jump to

Keyboard shortcuts

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