tui

package
v0.39.1 Latest Latest
Warning

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

Go to latest
Published: Jun 12, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

ABOUTME: Event adapter — converts raw engine events into typed TUI messages. ABOUTME: The ONLY file in the TUI package that imports pipeline, agent, and llm engine types.

ABOUTME: AgentLog component — append-only streaming log with per-node streams. ABOUTME: Each node gets its own line buffer. Parallel branches interleave with labeled separators.

ABOUTME: Root Bubbletea App model — "Signal Cabin" dashboard orchestrator. ABOUTME: Owns layout, message routing to state store and child components, and keyboard handling.

ABOUTME: AutopilotTUIInterviewer bridges autopilot decisions to the TUI modal. ABOUTME: Gets the LLM decision, shows it briefly in the gate modal, then auto-closes.

ABOUTME: TUI package for the tracker pipeline dashboard. ABOUTME: Clean-room rewrite in progress — components being added incrementally.

ABOUTME: Header component — displays pipeline name, run ID, elapsed time, and token/cost readout. ABOUTME: Self-contained Bubbletea model with its own Update/View. Reads token data from StateStore.

ABOUTME: Help overlay — modal showing all keyboard shortcuts in a styled table. ABOUTME: Implements ModalContent so it integrates with the existing modal system.

ABOUTME: HistoryTrail bubbletea component — reverse-chronological node visit log. ABOUTME: Shows the execution path through the pipeline as a compact scrollable trail.

ABOUTME: Hybrid gate content — radio selection of known labels with optional freeform "other" input. ABOUTME: Replaces pure freeform when a human gate has labeled outgoing edges.

ABOUTME: Fullscreen multi-field interview form modal for interview-mode human gates. ABOUTME: Renders questions as radio selects, yes/no toggles, or textareas with pagination.

ABOUTME: BubbleteaInterviewer bridges pipeline gate handlers to the TUI. ABOUTME: Mode 1 runs inline tea.Programs per gate; Mode 2 delegates via SendFunc to a running TUI.

ABOUTME: All typed Bubbletea message constants for the TUI. ABOUTME: Components communicate exclusively through these messages — no string comparisons.

ABOUTME: Modal overlay with pluggable content (choice selection, freeform input). ABOUTME: Renders a centered bordered box over background content using lipgloss.

ABOUTME: NodeList component — signal lamp panel showing pipeline nodes with status and thinking animation. ABOUTME: Renders colored indicator lamps per node and shows spinner frames for thinking nodes.

ABOUTME: Desktop notification utility — fires OS-native notifications on pipeline completion. ABOUTME: Uses osascript on macOS, notify-send on Linux. Respects TRACKER_NO_NOTIFY env var.

ABOUTME: ProgressTracker — renders an ASCII progress bar with ETA from rolling average. ABOUTME: Uses simple block characters styled to match the amber/dim palette.

ABOUTME: Split-pane review content for long human gate prompts. ABOUTME: Glamour-rendered scrollable viewport on top, textarea on bottom. Used for plan approval.

ABOUTME: ReviewHybridContent — scrollable context viewport with radio selection + freeform below. ABOUTME: Used when a labeled human gate has substantial context (agent output, errors).

ABOUTME: Reusable scroll container with auto-scroll and manual override. ABOUTME: Tracks visible range within a list of lines, re-enabling auto-scroll on ScrollToBottom.

ABOUTME: SearchBar for the agent log — uses bubbles/textinput for inline search. ABOUTME: Highlights matching lines in yellow; n/N jump between matches.

ABOUTME: Central state container for the TUI with Apply(msg) pattern. ABOUTME: Holds node entries, statuses, thinking state, and pipeline completion state.

ABOUTME: StatusBar component — bottom bar with track diagram, progress, and keybinding hints. ABOUTME: Renders colored lamp glyphs per node and a compact progress summary.

ABOUTME: Style registry for the TUI — "Signal Cabin" aesthetic with train control panel colors. ABOUTME: Lamp indicators, thinking animation frames, and lipgloss styles for all components.

ABOUTME: Per-node LLM thinking state tracker with animation frames and elapsed time. ABOUTME: Manages a global tick counter that advances all active nodes through spinner frames.

Index

Constants

View Source
const (
	LampRunning = "◉" // active/pulsing signal
	LampDone    = "●" // lit signal lamp
	LampPending = "○" // off/pending signal
	LampFailed  = "✖" // fault indicator
)

Signal lamp indicators — control panel style status lights.

Variables

View Source
var (
	ColorPanel      = lipgloss.Color("234") // #1c1c1c — instrument panel dark
	ColorBrightText = lipgloss.Color("255") // white — high-visibility primary
	ColorAmber      = lipgloss.Color("214") // #ffaf00 — amber signal lamp (running)
	ColorGreen      = lipgloss.Color("34")  // #00af00 — green clear signal (done)
	ColorRed        = lipgloss.Color("196") // #ff0000 — red alarm (failed)
	ColorBezel      = lipgloss.Color("24")  // #005f87 — instrument bezel blue
	ColorReadout    = lipgloss.Color("117") // #87d7ff — digital readout blue
	ColorLabel      = lipgloss.Color("244") // #808080 — panel label grey
	ColorOff        = lipgloss.Color("239") // #4e4e4e — off indicator (pending)
	ColorDim        = lipgloss.Color("240") // dim grey for secondary text

	// Tool palette — distinct colors per tool category.
	ColorBash  = lipgloss.Color("178") // #d7af00 — gold terminal
	ColorFile  = lipgloss.Color("75")  // #5fafff — blue file ops
	ColorGrep  = lipgloss.Color("114") // #87d787 — green search
	ColorAgent = lipgloss.Color("213") // #ff87ff — magenta spawn
	ColorPatch = lipgloss.Color("180") // #d7af87 — tan patch/apply

	// ColorOverride is Tailwind amber-600 — the chosen color for the
	// validation_overridden terminal status (Gap 5.2 spec D18). Canonical
	// source for the override amber across both the TUI and CLI surfaces;
	// cmd/tracker/branding.go's colorOverride aliases this value so future
	// updates only need to land here. Distinct from ColorAmber (#ffaf00,
	// used for running/warning states) so the override treatment is visually
	// unique within the TUI palette.
	ColorOverride = lipgloss.Color("#D97706")
)

"Platform Edge" color palette — derived from train driving control panels.

View Source
var (
	ColorRunning = ColorAmber
	ColorDone    = ColorGreen
	ColorFailed  = ColorRed
	ColorPending = ColorOff
)

Color aliases for semantic node status colors.

View Source
var Styles = StyleRegistry{
	NodeName:       lipgloss.NewStyle().Foreground(ColorBrightText).Bold(true),
	DimText:        lipgloss.NewStyle().Foreground(ColorDim),
	PrimaryText:    lipgloss.NewStyle().Foreground(ColorBrightText),
	ZoneLabel:      lipgloss.NewStyle().Foreground(ColorLabel).Bold(true),
	Readout:        lipgloss.NewStyle().Foreground(ColorReadout),
	PanelBorder:    lipgloss.DoubleBorder(),
	Header:         lipgloss.NewStyle().Foreground(ColorBrightText).Bold(true),
	Muted:          lipgloss.NewStyle().Foreground(ColorDim),
	StatusBar:      lipgloss.NewStyle().Background(ColorPanel).Padding(0, 1),
	ToolName:       lipgloss.NewStyle().Foreground(ColorAmber).Bold(true),
	Error:          lipgloss.NewStyle().Foreground(ColorRed).Bold(true),
	Warn:           lipgloss.NewStyle().Foreground(ColorAmber).Bold(true),
	Thinking:       lipgloss.NewStyle().Foreground(ColorAmber),
	SearchMatch:    lipgloss.NewStyle().Background(lipgloss.Color("226")).Foreground(lipgloss.Color("0")),
	CostBadge:      lipgloss.NewStyle().Foreground(ColorAmber),
	VerbosityBadge: lipgloss.NewStyle().Foreground(ColorReadout).Bold(true),
}

Styles is the global style registry instance.

View Source
var ThinkingFrames = [4]string{"◐", "◓", "◑", "◒"}

ThinkingFrames are the animation frames for the thinking spinner.

Functions

func AdaptAgentEvent

func AdaptAgentEvent(evt agent.Event, nodeID string) tea.Msg

AdaptAgentEvent maps an agent session event to a typed TUI message. Returns nil for event types that have no TUI representation.

func AdaptLLMTraceEvent

func AdaptLLMTraceEvent(evt llm.TraceEvent, nodeID string, verbose bool) []tea.Msg

AdaptLLMTraceEvent maps an LLM trace event to one or more typed TUI messages. Some trace events produce multiple messages (e.g. TraceRequestStart emits both MsgLLMRequestStart and MsgThinkingStarted). Returns nil for filtered events.

func AdaptPipelineEvent

func AdaptPipelineEvent(evt pipeline.PipelineEvent) tea.Msg

AdaptPipelineEvent maps a pipeline lifecycle event to a typed TUI message. Returns nil for event types that have no TUI representation.

This is the stateless free-function form: the returned MsgPipelineCompleted always has zero-valued Status and nil Override, because the function doesn't observe override events across the run. Callers that need the completion message to carry Status + Override should use the stateful PipelineAdapter (NewPipelineAdapter) instead — it accumulates EventValidationOverridden across the run and synthesizes the headline at completion. Tests retain the free-function form for one-shot conversions.

func CompletionRow

func CompletionRow(status pipeline.TerminalStatus, override *pipeline.OverrideDetail, pipelineErr string) string

CompletionRow renders the terminal-status banner shown in the status bar once the pipeline has reached a final state. The bullet glyph and textual status string carry the same semantic signal as the color, so NO_COLOR / monochrome terminals still distinguish the four states (Gap 5.2 spec D17 + D18). Override is non-nil only for validation_overridden runs; pipelineErr supplies the failed-at-node detail when present.

Status branches:

  • OutcomeSuccess: green ● Completed
  • OutcomeValidationOverridden: amber ● Completed — validation override at <gate> (label "<label>" by <actor>)
  • OutcomeBudgetExceeded: red ✗ Budget exceeded
  • OutcomeFail: red ✗ Failed[: <error>]
  • unknown/zero status: dim ● Completed (defensive default)

func DecisionString

func DecisionString(decision string) string

DecisionString formats the autopilot decision for display.

func HighlightLine

func HighlightLine(line, term string) string

HighlightLine highlights all occurrences of the search term in a styled line. Uses rune-aware operations for correct multi-byte character handling.

func IsSubgraphNode

func IsSubgraphNode(id string) bool

IsSubgraphNode returns true if the node ID contains a "/" separator, indicating it belongs to a child subgraph pipeline.

func SendNotification

func SendNotification(title, body string)

SendNotification sends a desktop notification. Fire-and-forget: errors are silently ignored. Respects TRACKER_NO_NOTIFY=1 env var to disable.

func StatusLamp

func StatusLamp(status NodeState) (string, lipgloss.Style)

StatusLamp returns the indicator character and style for a node status.

func SubgraphChildLabel

func SubgraphChildLabel(id string) string

SubgraphChildLabel extracts the last segment of a namespaced node ID for display (e.g., "Parent/Child" → "Child").

func SubgraphDepth

func SubgraphDepth(id string) int

SubgraphDepth returns the nesting depth of a node (0 for top-level nodes).

Types

type AgentLog

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

AgentLog renders a streaming activity log. Each pipeline node gets its own line accumulation buffer. Lines from concurrent nodes interleave in the unified log with separators when the source node changes. Lines are styled once on newline and never re-rendered.

func NewAgentLog

func NewAgentLog(store *StateStore, thinking *ThinkingTracker, height int) *AgentLog

NewAgentLog creates an AgentLog with the given state, thinking tracker, and viewport height.

func (*AgentLog) CycleVerbosity

func (al *AgentLog) CycleVerbosity()

CycleVerbosity advances to the next verbosity level.

func (*AgentLog) Init

func (al *AgentLog) Init() tea.Cmd

Init implements tea.Model.

func (*AgentLog) Search

func (al *AgentLog) Search() *SearchBar

Search returns the search bar for external access (key routing).

func (*AgentLog) SetFocusNodeID

func (al *AgentLog) SetFocusNodeID(nodeID string)

SetFocusNodeID sets the node ID to filter by (empty = show all).

func (*AgentLog) SetFocusedNode

func (al *AgentLog) SetFocusedNode(nodeID string)

SetFocusedNode is a no-op kept for interface compatibility. The activity log no longer tracks a single focused node — it shows all active nodes with separators.

func (*AgentLog) SetSize

func (al *AgentLog) SetSize(w, h int)

SetSize updates both width and height for the agent log viewport.

func (*AgentLog) SetVerboseTrace

func (al *AgentLog) SetVerboseTrace(v bool)

SetVerboseTrace enables or disables verbose trace output.

func (*AgentLog) Update

func (al *AgentLog) Update(msg tea.Msg) tea.Cmd

Update implements tea.Model.

func (*AgentLog) Verbosity

func (al *AgentLog) Verbosity() Verbosity

Verbosity returns the current verbosity level.

func (*AgentLog) View

func (al *AgentLog) View() string

View renders the agent log viewport. The indicator is always rendered at the bottom — content fills upward from the remaining space. This guarantees the indicator is never pushed off-screen regardless of content size or wrapping.

func (*AgentLog) VisibleText

func (al *AgentLog) VisibleText() string

VisibleText returns the plain text of the visible log (for clipboard copy).

type AppModel

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

AppModel is the root Bubbletea model composing all TUI components. All fields are pointers so mutations through value receivers propagate correctly (required by tea.Model's value-receiver interface).

func NewAppModel

func NewAppModel(store *StateStore, pipelineName, runID string) *AppModel

NewAppModel creates a fully-wired App with all child components.

func (*AppModel) ActiveNode

func (a *AppModel) ActiveNode() string

ActiveNode returns the ID of the first running node, for focusing the log.

func (*AppModel) Header

func (a *AppModel) Header() *Header

Header returns the header component for configuration.

func (AppModel) Init

func (a AppModel) Init() tea.Cmd

Init returns the initial batch of tick commands.

func (*AppModel) SetInitialNodes

func (a *AppModel) SetInitialNodes(entries []NodeEntry)

SetInitialNodes configures the ordered node list via the state store.

func (*AppModel) SetVerboseTrace

func (a *AppModel) SetVerboseTrace(v bool)

SetVerboseTrace enables or disables verbose LLM trace output in the agent log.

func (AppModel) String

func (a AppModel) String() string

String implements fmt.Stringer for debug purposes.

func (AppModel) Update

func (a AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update routes messages through global keys, modal, state store, and child components.

func (AppModel) View

func (a AppModel) View() string

View composes the dashboard layout: header, content (node list + agent log), status bar.

type AutopilotContent

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

AutopilotContent shows the autopilot's gate decision briefly before auto-closing. Read-only — the user can press Enter to dismiss early.

func NewAutopilotContent

func NewAutopilotContent(prompt, decision string, replyCh chan<- string) *AutopilotContent

NewAutopilotContent creates a display-only modal showing the autopilot decision.

func (*AutopilotContent) Cancel

func (a *AutopilotContent) Cancel()

func (*AutopilotContent) Update

func (a *AutopilotContent) Update(msg tea.Msg) tea.Cmd

func (*AutopilotContent) View

func (a *AutopilotContent) View() string

type AutopilotTUIInterviewer

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

AutopilotTUIInterviewer wraps an AutopilotInterviewer and routes its decisions through the TUI modal for visual feedback before auto-replying.

func NewAutopilotTUIInterviewer

func NewAutopilotTUIInterviewer(autopilot handlers.LabeledFreeformInterviewer, send SendFunc) *AutopilotTUIInterviewer

NewAutopilotTUIInterviewer creates an interviewer that shows autopilot decisions in the TUI modal before auto-closing.

func (*AutopilotTUIInterviewer) Actor

Actor returns ActorAutopilot — autopilot persona acting through the TUI surface.

func (*AutopilotTUIInterviewer) Ask

func (a *AutopilotTUIInterviewer) Ask(prompt string, choices []string, defaultChoice string) (string, error)

func (*AutopilotTUIInterviewer) AskFreeform

func (a *AutopilotTUIInterviewer) AskFreeform(prompt string) (string, error)

func (*AutopilotTUIInterviewer) AskFreeformWithLabels

func (a *AutopilotTUIInterviewer) AskFreeformWithLabels(prompt string, labels []string, defaultLabel string) (string, error)

func (*AutopilotTUIInterviewer) AskInterview

AskInterview delegates interview questions to the inner autopilot (if it supports interviews), then flashes a brief summary in the TUI.

type BubbleteaInterviewer

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

BubbleteaInterviewer implements handlers.Interviewer and handlers.FreeformInterviewer. In Mode 1 (send == nil), each gate spins up a short-lived inline tea.Program. In Mode 2 (send != nil), gates delegate via the send function and block until a response is received through the reply channel.

func NewBubbleteaInterviewer

func NewBubbleteaInterviewer(send SendFunc) *BubbleteaInterviewer

NewBubbleteaInterviewer creates a Mode 2 BubbleteaInterviewer that delegates gate prompts to a running TUI program via the provided send function.

func NewMode1Interviewer

func NewMode1Interviewer() *BubbleteaInterviewer

NewMode1Interviewer creates a Mode 1 BubbleteaInterviewer that runs inline tea.Programs for each gate prompt. No running TUI program required.

func (*BubbleteaInterviewer) Actor

func (b *BubbleteaInterviewer) Actor() pipeline.Actor

Actor returns ActorHuman — gate response came from a real human at the TUI.

func (*BubbleteaInterviewer) Ask

func (b *BubbleteaInterviewer) Ask(prompt string, choices []string, defaultChoice string) (string, error)

Ask presents a choice prompt and returns the selected option.

func (*BubbleteaInterviewer) AskFreeform

func (b *BubbleteaInterviewer) AskFreeform(prompt string) (string, error)

AskFreeform presents a freeform text prompt and returns the user's input.

func (*BubbleteaInterviewer) AskFreeformWithLabels

func (b *BubbleteaInterviewer) AskFreeformWithLabels(prompt string, labels []string, defaultLabel string) (string, error)

AskFreeformWithLabels presents labeled options alongside a freeform textarea.

func (*BubbleteaInterviewer) AskInterview

AskInterview presents a multi-field interview form and returns the structured result.

type Cancellable

type Cancellable interface {
	Cancel()
}

Cancellable is an optional interface for modal content that can be cancelled externally (e.g., on Ctrl+C quit). Implementations should close their reply channel to unblock the pipeline handler.

type ChoiceContent

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

ChoiceContent presents a list of choices with arrow-key navigation. Sends the selected value on replyCh when Enter is pressed.

func NewChoiceContent

func NewChoiceContent(prompt string, choices []string, replyCh chan<- string) *ChoiceContent

NewChoiceContent creates a choice content model. If replyCh is nil, no reply is sent on selection (useful for rendering-only tests).

func (*ChoiceContent) Cancel

func (c *ChoiceContent) Cancel()

Cancel implements Cancellable for external cancellation (e.g., Ctrl+C).

func (*ChoiceContent) Update

func (c *ChoiceContent) Update(msg tea.Msg) tea.Cmd

Update handles arrow keys and Enter for choice selection.

func (*ChoiceContent) View

func (c *ChoiceContent) View() string

View renders the prompt and choice list with a cursor indicator.

type FreeformContent

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

FreeformContent captures free-text input using a wrapping textarea. Enter inserts newlines; Ctrl+S submits. The textarea expands vertically as the user types, wrapping at the viewport width.

func NewFreeformContent

func NewFreeformContent(prompt string, replyCh chan<- string) *FreeformContent

NewFreeformContent creates a freeform input content model with a wrapping textarea. If replyCh is nil, no reply is sent on submit (useful for tests).

func (*FreeformContent) Cancel

func (f *FreeformContent) Cancel()

Cancel implements Cancellable for external cancellation (e.g., Ctrl+C).

func (*FreeformContent) SetWidth

func (f *FreeformContent) SetWidth(w int)

SetWidth adjusts the textarea to fit the available modal width.

func (*FreeformContent) Update

func (f *FreeformContent) Update(msg tea.Msg) tea.Cmd

Update handles keyboard input. Ctrl+S submits, everything else goes to the textarea (Enter inserts newlines, arrow keys navigate, etc.).

func (*FreeformContent) View

func (f *FreeformContent) View() string

View renders the prompt, wrapping textarea, and key hints.

type FullscreenContent

type FullscreenContent interface {
	IsFullscreen() bool
}

FullscreenContent is an optional interface for modal content that wants to fill the entire terminal instead of being centered in a bordered box.

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

Header renders the top bar of the TUI dashboard.

func NewHeader

func NewHeader(store *StateStore, pipelineName, runID string) *Header

NewHeader creates a Header with the given state, pipeline name, and run ID.

func (*Header) SetAutopilot

func (h *Header) SetAutopilot(persona string)

SetAutopilot sets the autopilot persona tag displayed in the header.

func (*Header) SetBackend

func (h *Header) SetBackend(backend string)

SetBackend sets the backend tag displayed in the header.

func (*Header) SetWidth

func (h *Header) SetWidth(w int)

SetWidth updates the terminal width used for layout.

func (*Header) Update

func (h *Header) Update(msg tea.Msg) tea.Cmd

Update handles tick messages for the header.

func (*Header) View

func (h *Header) View() string

View renders the header as a single-line instrument cluster.

type HelpContent

type HelpContent struct{}

HelpContent implements ModalContent to display the shortcut help overlay.

func NewHelpContent

func NewHelpContent() *HelpContent

NewHelpContent creates the help overlay content.

func (*HelpContent) Cancel

func (h *HelpContent) Cancel()

Cancel is a no-op (help has no reply channels).

func (*HelpContent) Update

func (h *HelpContent) Update(msg tea.Msg) tea.Cmd

Update handles key events — Esc or ? dismisses the help.

func (*HelpContent) View

func (h *HelpContent) View() string

View renders the two-column shortcut table.

type HistoryTrail

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

HistoryTrail is a bubbletea model that renders a compact reverse-chronological trail of node visits. Consecutive visits to the same node are deduplicated with a count (e.g., "TestMilestone ×3").

func NewHistoryTrail

func NewHistoryTrail(store *StateStore) *HistoryTrail

NewHistoryTrail creates a trail that reads from the given state store.

func (HistoryTrail) Init

func (h HistoryTrail) Init() tea.Cmd

Init implements tea.Model.

func (*HistoryTrail) SetSize

func (h *HistoryTrail) SetSize(w, height int)

SetSize updates the display dimensions.

func (HistoryTrail) Update

func (h HistoryTrail) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update implements tea.Model. The trail is read-only — state comes from the store.

func (HistoryTrail) View

func (h HistoryTrail) View() string

View implements tea.Model.

type HybridContent

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

HybridContent presents labeled options as a radio list with a freeform textarea for custom input. Selecting a label submits it directly. Selecting "other" focuses the textarea for custom text.

func NewHybridContent

func NewHybridContent(prompt string, labels []string, defaultLabel string, replyCh chan<- string) *HybridContent

NewHybridContent creates a hybrid gate with labeled options and freeform fallback.

func (*HybridContent) Cancel

func (h *HybridContent) Cancel()

Cancel implements Cancellable for external cancellation (e.g., Ctrl+C).

func (*HybridContent) SetWidth

func (h *HybridContent) SetWidth(w int)

SetWidth adjusts the content width for prompt wrapping and textarea.

func (*HybridContent) Update

func (h *HybridContent) Update(msg tea.Msg) tea.Cmd

Update handles navigation, selection, and textarea input.

func (*HybridContent) View

func (h *HybridContent) View() string

View renders the prompt, radio options, and textarea.

type InterviewContent

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

InterviewContent implements ModalContent, Cancellable, and FullscreenContent for multi-field interview forms shown in the TUI modal.

func NewInterviewContent

func NewInterviewContent(questions []handlers.Question, previous *handlers.InterviewResult, replyCh chan<- string, width, height int) *InterviewContent

NewInterviewContent creates a fullscreen interview form. If previous is non-nil, fields are pre-filled from matching answers by ID.

func (*InterviewContent) Cancel

func (ic *InterviewContent) Cancel()

Cancel implements Cancellable. Closes the reply channel to signal cancellation, consistent with all other ModalContent types (ChoiceContent, FreeformContent, etc.).

func (*InterviewContent) IsFullscreen

func (ic *InterviewContent) IsFullscreen() bool

IsFullscreen signals the modal to use the full terminal.

func (*InterviewContent) SetSize

func (ic *InterviewContent) SetSize(w, h int)

SetSize updates dimensions.

func (*InterviewContent) Update

func (ic *InterviewContent) Update(msg tea.Msg) tea.Cmd

Update handles keyboard input for the interview form.

func (*InterviewContent) View

func (ic *InterviewContent) View() string

View renders the interview form — one question at a time with progress summary.

type LineKind

type LineKind int

LineKind tags log lines for verbosity filtering.

const (
	LineGeneral   LineKind = iota // text output, headers, etc.
	LineTool                      // tool call start/end
	LineError                     // errors, failures
	LineReasoning                 // reasoning/thinking output
)
type Modal struct {
	// contains filtered or unexported fields
}

Modal renders a bordered overlay centered over background terminal content.

func NewModal

func NewModal(width, height int) *Modal

NewModal creates a modal with the given terminal dimensions.

func (*Modal) CancelAndHide

func (m *Modal) CancelAndHide()

CancelAndHide cancels the modal content (closing reply channels) and hides it. Used on Ctrl+C to prevent pipeline goroutine hangs.

func (*Modal) Hide

func (m *Modal) Hide()

Hide removes the modal from view.

func (*Modal) SetSize

func (m *Modal) SetSize(width, height int)

SetSize updates the terminal dimensions used for centering.

func (*Modal) Show

func (m *Modal) Show(content ModalContent)

Show displays the modal with the given content.

func (*Modal) Update

func (m *Modal) Update(msg tea.Msg) tea.Cmd

Update forwards messages to the modal content.

func (*Modal) View

func (m *Modal) View(background string) string

View renders the modal overlaid on the given background content. Fullscreen content fills the terminal; other content is centered in a box.

func (*Modal) Visible

func (m *Modal) Visible() bool

Visible reports whether the modal is currently displayed.

type ModalContent

type ModalContent interface {
	Update(msg tea.Msg) tea.Cmd
	View() string
}

ModalContent is the interface for content rendered inside the modal overlay.

type MsgAgentError

type MsgAgentError struct {
	NodeID string
	Error  string
}

type MsgClearFocus

type MsgClearFocus struct{}

type MsgCycleVerbosity

type MsgCycleVerbosity struct{}

Verbosity cycling for the agent log filter.

type MsgFocusNode

type MsgFocusNode struct{ NodeID string }

Node drill-down focus.

type MsgGateAutopilot

type MsgGateAutopilot struct {
	NodeID    string
	Prompt    string
	Decision  string
	Reasoning string
	Labels    []string
	Default   string
	ReplyCh   chan<- string
}

MsgGateAutopilot tells the TUI to show the autopilot decision in the modal for a brief moment, then auto-close by sending the reply.

type MsgGateChoice

type MsgGateChoice struct {
	NodeID  string
	Prompt  string
	Options []string
	ReplyCh chan<- string
}

Gate (human-in-the-loop) messages.

type MsgGateFreeform

type MsgGateFreeform struct {
	NodeID  string
	Prompt  string
	Labels  []string // outgoing edge labels (e.g., "approve", "adjust", "reject")
	Default string   // default label (pre-selected)
	ReplyCh chan<- string
}

type MsgGateInterview

type MsgGateInterview struct {
	NodeID    string
	Questions []handlers.Question
	Previous  *handlers.InterviewResult
	ReplyCh   chan<- string // JSON string
}

type MsgHeaderTick

type MsgHeaderTick struct{}

type MsgLLMFinish

type MsgLLMFinish struct{ NodeID string }

type MsgLLMProviderRaw

type MsgLLMProviderRaw struct {
	NodeID string
	Data   string
}

type MsgLLMRequestPreparing

type MsgLLMRequestPreparing struct {
	NodeID   string
	Provider string
	Model    string
}

LLM provider messages.

type MsgLLMRequestStart

type MsgLLMRequestStart struct {
	NodeID   string
	Provider string
	Model    string
}

type MsgModalDismiss

type MsgModalDismiss struct{}

type MsgNodeCompleted

type MsgNodeCompleted struct {
	NodeID  string
	Outcome string
}

type MsgNodeFailed

type MsgNodeFailed struct {
	NodeID string
	Error  string
}

type MsgNodeRetrying

type MsgNodeRetrying struct {
	NodeID  string
	Message string
}

type MsgNodeStarted

type MsgNodeStarted struct{ NodeID string }

Pipeline lifecycle messages.

type MsgPipelineCompleted

type MsgPipelineCompleted struct {
	Status   pipeline.TerminalStatus
	Override *pipeline.OverrideDetail // headline entry (latest) per D5a; non-nil for override runs
}

MsgPipelineCompleted is emitted when the pipeline reaches the success exit. Status carries the terminal status so the TUI's completion row can render validation_overridden in amber (per Gap 5.2 spec D17 + D18) instead of a generic green checkmark. Override is non-nil when overrides fired during the run, carrying the headline (latest) entry per spec D5a.

When the message comes from the free-function AdaptPipelineEvent (the stateless adapter used in tests / one-shot conversions), Status defaults to the zero value and Override is nil — the StateStore reconstructs Status from accumulated MsgValidationOverridden messages it has seen during the run. The stateful Adapter populates these fields at construction time so downstream consumers don't have to re-derive them.

type MsgPipelineDone

type MsgPipelineDone struct{ Err error }

type MsgPipelineFailed

type MsgPipelineFailed struct{ Error string }

type MsgReasoningChunk

type MsgReasoningChunk struct {
	NodeID string
	Text   string
}

type MsgSearchActivate

type MsgSearchActivate struct{}

Search activation and control.

type MsgSearchDeactivate

type MsgSearchDeactivate struct{}

type MsgSearchUpdate

type MsgSearchUpdate struct{ Term string }

type MsgStatusFlash

type MsgStatusFlash struct{ Text string }

Status bar flash messages (e.g., "Copied!").

type MsgStatusFlashClear

type MsgStatusFlashClear struct{}

type MsgTextChunk

type MsgTextChunk struct {
	NodeID string
	Text   string
}

type MsgThinkingStarted

type MsgThinkingStarted struct{ NodeID string }

Agent activity messages.

type MsgThinkingStopped

type MsgThinkingStopped struct{ NodeID string }

type MsgThinkingTick

type MsgThinkingTick struct{}

UI tick and interaction messages.

type MsgToggleExpand

type MsgToggleExpand struct{}

type MsgToolCallEnd

type MsgToolCallEnd struct {
	NodeID   string
	ToolName string
	Output   string
	Error    string
}

type MsgToolCallStart

type MsgToolCallStart struct {
	NodeID    string
	ToolName  string
	ToolInput string
}

type MsgValidationOverridden

type MsgValidationOverridden struct {
	NodeID string                  // the gate node that produced the override
	Detail pipeline.OverrideDetail // gate/label/actor/subgraph_path
}

MsgValidationOverridden carries a single override-edge traversal so the StateStore can accumulate overrides for the completion row's gate/label/actor display and so live UI surfaces (e.g. the activity log) can flag the moment. Mapped from pipeline.EventValidationOverridden by the adapter.

type MsgVerifyStatus

type MsgVerifyStatus struct {
	NodeID string
	Text   string
}

type NodeEntry

type NodeEntry struct {
	ID    string
	Label string
	Flags NodeFlags
}

NodeEntry identifies a node in the pipeline with its display label.

type NodeFlags

type NodeFlags struct {
	IsParallelDispatcher bool // node dispatches parallel branches
	IsParallelBranch     bool // node is a branch of a parallel dispatch
	IsFanIn              bool // node joins parallel branches
}

NodeFlags carries metadata about a node's role in the pipeline.

type NodeList

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

NodeList renders a signal lamp panel of pipeline nodes.

func NewNodeList

func NewNodeList(store *StateStore, thinking *ThinkingTracker, height int) *NodeList

NewNodeList creates a NodeList that reads from the given state store and thinking tracker.

func (*NodeList) Init

func (nl *NodeList) Init() tea.Cmd

Init implements tea.Model.

func (*NodeList) MoveDown

func (nl *NodeList) MoveDown()

MoveDown moves the selection cursor down.

func (*NodeList) MoveUp

func (nl *NodeList) MoveUp()

MoveUp moves the selection cursor up.

func (*NodeList) SelectedNodeID

func (nl *NodeList) SelectedNodeID() string

SelectedNodeID returns the ID of the currently selected node, or "".

func (*NodeList) SetSize

func (nl *NodeList) SetSize(w, h int)

SetSize updates both width and height for the node list viewport.

func (*NodeList) Update

func (nl *NodeList) Update(msg tea.Msg) tea.Cmd

Update implements tea.Model.

func (*NodeList) View

func (nl *NodeList) View() string

View renders the node list as a signal lamp panel, clipped to the configured height.

type NodePhase

type NodePhase int

NodePhase represents the current activity phase of a running node.

const (
	PhaseIdle NodePhase = iota
	PhasePreparing
	PhaseWaiting
	PhaseThinking
	PhaseTooling
	PhaseCompacting
	PhaseRouting
)

type NodeState

type NodeState int

NodeState represents the execution state of a pipeline node.

const (
	NodePending NodeState = iota
	NodeRunning
	NodeDone
	NodeFailed
	NodeRetrying
	NodeSkipped
)

type PipelineAdapter

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

PipelineAdapter is a stateful event-to-message adapter that accumulates override events across a run so the MsgPipelineCompleted it emits carries the terminal Status (OutcomeSuccess vs OutcomeValidationOverridden) and the headline OverrideDetail per Gap 5.2 spec D5a (latest entry wins). Use this when the TUI needs live override status on the completion event; use the stateless AdaptPipelineEvent for one-shot conversions.

Lifetime is scoped to a single pipeline run. Construct one per run via NewPipelineAdapter — sharing one across runs would mix override state.

func NewPipelineAdapter

func NewPipelineAdapter() *PipelineAdapter

NewPipelineAdapter returns a freshly-initialized PipelineAdapter ready to adapt one pipeline run's events.

func (*PipelineAdapter) Adapt

Adapt is the stateful equivalent of AdaptPipelineEvent: it tracks override events as they arrive and, on EventPipelineCompleted, returns a MsgPipelineCompleted with Status and Override populated from accumulated state. Other event types route through the same mapping as the free function.

type ProgressTracker

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

ProgressTracker renders a progress bar and estimates ETA from rolling average of completed node durations.

func NewProgressTracker

func NewProgressTracker(store *StateStore) *ProgressTracker

NewProgressTracker creates a progress bar styled to the TUI palette.

func (*ProgressTracker) RecordNodeDuration

func (p *ProgressTracker) RecordNodeDuration(d time.Duration)

RecordNodeDuration adds a completed node's duration for ETA calculation.

func (*ProgressTracker) SetWidth

func (p *ProgressTracker) SetWidth(w int)

SetWidth adjusts the progress bar width.

func (*ProgressTracker) View

func (p *ProgressTracker) View() string

View renders the progress bar with fraction and ETA. Uses simple block characters: filled=━ (amber), empty=─ (dim).

type ReviewContent

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

ReviewContent presents a split-pane view for reviewing long content (e.g., execution plans). Top pane is a scrollable glamour-rendered viewport, bottom pane is a textarea for the user's response.

func NewReviewContent

func NewReviewContent(prompt string, replyCh chan<- string, width, height int) *ReviewContent

NewReviewContent creates a split-pane review view. The markdown content is rendered via glamour in the viewport. A temp file is written so the user can open the plan in an external editor.

func (*ReviewContent) Cancel

func (r *ReviewContent) Cancel()

Cancel implements Cancellable for external cancellation (e.g., Ctrl+C).

func (*ReviewContent) IsFullscreen

func (r *ReviewContent) IsFullscreen() bool

IsFullscreen signals the modal wrapper to skip centering and use the full terminal.

func (*ReviewContent) SetSize

func (r *ReviewContent) SetSize(w, h int)

SetSize updates dimensions for the review panes.

func (*ReviewContent) Update

func (r *ReviewContent) Update(msg tea.Msg) tea.Cmd

Update routes keys: PgUp/PgDn/arrows to viewport, typing to textarea, Ctrl+S to submit.

func (*ReviewContent) View

func (r *ReviewContent) View() string

View renders the split-pane: viewport, divider, textarea, hints.

type ReviewHybridContent

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

ReviewHybridContent shows a glamour-rendered scrollable viewport with radio label selection and an "other" freeform option below. Used when an escalation gate has both context content (what failed) and labeled options (accept/retry/abandon), plus the ability to provide custom feedback.

func NewReviewHybridContent

func NewReviewHybridContent(label, context string, labels []string, defaultLabel string, replyCh chan<- string, width, height int) *ReviewHybridContent

NewReviewHybridContent creates a split view: scrollable context on top, radio options + freeform textarea on bottom.

func (*ReviewHybridContent) Cancel

func (r *ReviewHybridContent) Cancel()

Cancel implements Cancellable.

func (*ReviewHybridContent) IsFullscreen

func (r *ReviewHybridContent) IsFullscreen() bool

IsFullscreen signals the modal to use the full terminal.

func (*ReviewHybridContent) SetSize

func (r *ReviewHybridContent) SetSize(w, h int)

SetSize updates dimensions.

func (*ReviewHybridContent) Update

func (r *ReviewHybridContent) Update(msg tea.Msg) tea.Cmd

Update handles navigation and selection.

func (*ReviewHybridContent) View

func (r *ReviewHybridContent) View() string

View renders viewport + divider + radio options + other + textarea.

type ScrollView

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

ScrollView is a line-buffered viewport that auto-scrolls to the bottom unless the user manually scrolls up.

func NewScrollView

func NewScrollView(height int) *ScrollView

NewScrollView creates a ScrollView with the given viewport height.

func (*ScrollView) Append

func (sv *ScrollView) Append(line string)

Append adds a line and auto-scrolls if enabled.

func (*ScrollView) AutoScroll

func (sv *ScrollView) AutoScroll() bool

AutoScroll returns whether auto-scroll is enabled.

func (*ScrollView) Len

func (sv *ScrollView) Len() int

Len returns the total number of lines.

func (*ScrollView) Lines

func (sv *ScrollView) Lines() []string

Lines returns the full line buffer.

func (*ScrollView) ScrollDown

func (sv *ScrollView) ScrollDown(n int)

ScrollDown moves the viewport down by n lines.

func (*ScrollView) ScrollToBottom

func (sv *ScrollView) ScrollToBottom()

ScrollToBottom re-enables auto-scroll and jumps to the end.

func (*ScrollView) ScrollUp

func (sv *ScrollView) ScrollUp(n int)

ScrollUp moves the viewport up by n lines and disables auto-scroll.

func (*ScrollView) SetHeight

func (sv *ScrollView) SetHeight(h int)

SetHeight updates the viewport height.

func (*ScrollView) UpdateLast

func (sv *ScrollView) UpdateLast(line string)

UpdateLast replaces the last line in the buffer.

func (*ScrollView) VisibleRange

func (sv *ScrollView) VisibleRange() (start, end int)

VisibleRange returns the start (inclusive) and end (exclusive) indices of currently visible lines.

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

SearchBar provides incremental search within the agent log.

func NewSearchBar

func NewSearchBar() *SearchBar

NewSearchBar creates a search bar styled for the TUI.

func (*SearchBar) Activate

func (s *SearchBar) Activate()

Activate shows the search bar and focuses the input.

func (*SearchBar) Active

func (s *SearchBar) Active() bool

Active returns whether the search bar is currently displayed.

func (*SearchBar) Confirm

func (s *SearchBar) Confirm()

Confirm exits input mode but keeps the term and highlights active. The search bar is hidden but n/N navigation still works.

func (*SearchBar) CurrentMatchLine

func (s *SearchBar) CurrentMatchLine() int

CurrentMatchLine returns the line index of the current match, or -1.

func (*SearchBar) Deactivate

func (s *SearchBar) Deactivate()

Deactivate hides the search bar and clears the search.

func (*SearchBar) MatchCount

func (s *SearchBar) MatchCount() int

MatchCount returns the number of matches.

func (*SearchBar) NextMatch

func (s *SearchBar) NextMatch()

NextMatch advances to the next match index.

func (*SearchBar) PrevMatch

func (s *SearchBar) PrevMatch()

PrevMatch moves to the previous match index.

func (*SearchBar) Term

func (s *SearchBar) Term() string

Term returns the current search term.

func (*SearchBar) Update

func (s *SearchBar) Update(msg tea.Msg) (tea.Cmd, bool)

Update handles input events when the search bar is active. Returns a command and whether the event was consumed.

func (*SearchBar) UpdateMatches

func (s *SearchBar) UpdateMatches(lines []styledLine)

UpdateMatches rebuilds the match index list from the given lines. The indices stored in matches correspond to positions in the provided slice.

func (*SearchBar) UpdateMatchesFiltered

func (s *SearchBar) UpdateMatchesFiltered(lines []styledLine, filteredIndices []int)

UpdateMatchesFiltered rebuilds match indices against a filtered subset of lines. filteredIndices maps positions in the filtered view back to the original line array.

func (*SearchBar) View

func (s *SearchBar) View() string

View renders the search bar.

type SendFunc

type SendFunc func(msg tea.Msg)

SendFunc is a function that sends a Bubbletea message to a running program. In Mode 2, this is typically tea.Program.Send.

type StateStore

type StateStore struct {
	Tokens *llm.TokenTracker
	// contains filtered or unexported fields
}

StateStore is the central state container for the TUI.

func NewStateStore

func NewStateStore(tokens *llm.TokenTracker) *StateStore

NewStateStore creates a StateStore with an optional TokenTracker.

func (*StateStore) Apply

func (s *StateStore) Apply(msg interface{})

Apply updates state based on a typed message.

func (*StateStore) GetPhase

func (s *StateStore) GetPhase(id string) NodePhase

GetPhase returns the current activity phase of a node.

func (*StateStore) HeadlineOverride

func (s *StateStore) HeadlineOverride() *pipeline.OverrideDetail

HeadlineOverride returns the snapshot of the headline override entry as of pipeline completion (latest accumulated entry per spec D5a), or nil when no override fired. The renderer uses this for the "Completed — validation override at <gate> ..." copy.

func (*StateStore) IsOnCurrentPath

func (s *StateStore) IsOnCurrentPath(nodeID string) bool

IsOnCurrentPath returns true if the node was visited in the execution so far.

func (*StateStore) IsThinking

func (s *StateStore) IsThinking(id string) bool

IsThinking returns whether a node is in the thinking state.

func (*StateStore) IsWaiting

func (s *StateStore) IsWaiting(id string) bool

IsWaiting returns whether the node is waiting for provider response.

func (*StateStore) NodeCost

func (s *StateStore) NodeCost(id string) float64

NodeCost returns the accumulated cost for a node (0 if unknown).

func (*StateStore) NodeDuration

func (s *StateStore) NodeDuration(id string) time.Duration

NodeDuration returns the elapsed time for a completed node.

func (*StateStore) NodeError

func (s *StateStore) NodeError(id string) string

NodeError returns the error message for a failed node.

func (*StateStore) NodeRetryMessage

func (s *StateStore) NodeRetryMessage(id string) string

NodeRetryMessage returns the retry message for a retrying node.

func (*StateStore) NodeStatus

func (s *StateStore) NodeStatus(id string) NodeState

NodeStatus returns the current state of a node.

func (*StateStore) NodeTokens

func (s *StateStore) NodeTokens(id string) int

NodeTokens returns the accumulated token count for a node.

func (*StateStore) Nodes

func (s *StateStore) Nodes() []NodeEntry

Nodes returns the ordered node list.

func (*StateStore) PhaseElapsed

func (s *StateStore) PhaseElapsed(id string) time.Duration

PhaseElapsed returns how long the node has been in its current phase.

func (*StateStore) PipelineDone

func (s *StateStore) PipelineDone() bool

PipelineDone returns whether the pipeline has completed (success or failure).

func (*StateStore) PipelineError

func (s *StateStore) PipelineError() string

PipelineError returns the pipeline error message, if any.

func (*StateStore) PipelineStatus

func (s *StateStore) PipelineStatus() pipeline.TerminalStatus

PipelineStatus returns the terminal status assigned when the pipeline finished. Empty string while the run is in flight or for partial states that haven't yet computed a terminal classification. The completion-row renderer keys on this to pick green vs amber vs red.

func (*StateStore) Progress

func (s *StateStore) Progress() (done, total int)

Progress returns the count of completed nodes and total nodes.

func (*StateStore) SetNodes

func (s *StateStore) SetNodes(entries []NodeEntry)

SetNodes sets the ordered list of pipeline nodes.

func (*StateStore) ValidationOverrides

func (s *StateStore) ValidationOverrides() []pipeline.OverrideDetail

ValidationOverrides returns a defensive copy of the accumulated override list for inspection (e.g. tests). The caller may mutate the returned slice without affecting StateStore.

func (*StateStore) VisitPath

func (s *StateStore) VisitPath() []string

VisitPath returns the ordered list of visited node IDs (includes repeats for loops).

type StatusBar

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

StatusBar renders the bottom status bar of the TUI dashboard.

func NewStatusBar

func NewStatusBar(store *StateStore, agentLog *AgentLog) *StatusBar

NewStatusBar creates a StatusBar reading state from the given store.

func (*StatusBar) ClearFlash

func (sb *StatusBar) ClearFlash()

ClearFlash removes the flash message.

func (*StatusBar) Progress

func (sb *StatusBar) Progress() *ProgressTracker

Progress returns the progress tracker for recording node durations.

func (*StatusBar) SetFlash

func (sb *StatusBar) SetFlash(text string)

SetFlash sets a temporary message in the status bar.

func (*StatusBar) SetWidth

func (sb *StatusBar) SetWidth(w int)

SetWidth updates the terminal width used for layout.

func (*StatusBar) View

func (sb *StatusBar) View() string

View renders the status bar as a single line: progress bar + badges + hints. When the pipeline has reached a terminal state, the progress region is replaced by CompletionRow so operators see the final status (and any override gate/label/actor detail) inline.

type StyleRegistry

type StyleRegistry struct {
	NodeName       lipgloss.Style
	DimText        lipgloss.Style
	PrimaryText    lipgloss.Style
	ZoneLabel      lipgloss.Style
	Readout        lipgloss.Style
	PanelBorder    lipgloss.Border
	Header         lipgloss.Style
	Muted          lipgloss.Style
	StatusBar      lipgloss.Style
	ToolName       lipgloss.Style
	Error          lipgloss.Style
	Warn           lipgloss.Style
	Thinking       lipgloss.Style
	SearchMatch    lipgloss.Style
	CostBadge      lipgloss.Style
	VerbosityBadge lipgloss.Style
}

StyleRegistry holds all shared lipgloss styles for the TUI.

type ThinkingTracker

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

ThinkingTracker manages per-node thinking and tool execution animation state.

func NewThinkingTracker

func NewThinkingTracker() *ThinkingTracker

NewThinkingTracker creates a ThinkingTracker with no active nodes.

func (*ThinkingTracker) Elapsed

func (tr *ThinkingTracker) Elapsed(nodeID string) time.Duration

Elapsed returns how long a node has been thinking.

func (*ThinkingTracker) Frame

func (tr *ThinkingTracker) Frame(nodeID string) string

Frame returns the current animation frame character for a thinking node. Returns empty string if the node is not thinking.

func (*ThinkingTracker) IsThinking

func (tr *ThinkingTracker) IsThinking(nodeID string) bool

IsThinking returns whether a node is currently in the thinking state.

func (*ThinkingTracker) IsToolRunning

func (tr *ThinkingTracker) IsToolRunning(nodeID string) bool

IsToolRunning returns whether a node is currently executing a tool.

func (*ThinkingTracker) Start

func (tr *ThinkingTracker) Start(nodeID string)

Start begins thinking for a node, recording the current time.

func (*ThinkingTracker) StartAt

func (tr *ThinkingTracker) StartAt(nodeID string, t time.Time)

StartAt begins thinking for a node at a specific time.

func (*ThinkingTracker) StartTool

func (tr *ThinkingTracker) StartTool(nodeID, toolName string)

StartTool marks a node as executing a tool (distinct from LLM thinking). Resets the phase timestamp so the elapsed display reflects tool duration rather than accumulated thinking+tool time.

func (*ThinkingTracker) Stop

func (tr *ThinkingTracker) Stop(nodeID string)

Stop ends thinking for a node.

func (*ThinkingTracker) StopTool

func (tr *ThinkingTracker) StopTool(nodeID string)

StopTool clears the tool-running state for a node.

func (*ThinkingTracker) Tick

func (tr *ThinkingTracker) Tick()

Tick advances the global animation counter by one frame.

func (*ThinkingTracker) ToolName

func (tr *ThinkingTracker) ToolName(nodeID string) string

ToolName returns the name of the tool currently running on a node.

type Verbosity

type Verbosity int

Verbosity levels for log filtering.

const (
	VerbosityAll Verbosity = iota
	VerbosityTools
	VerbosityErrors
	VerbosityReasoning
)

func (Verbosity) Label

func (v Verbosity) Label() string

VerbosityLabel returns the display name for a verbosity level.

Directories

Path Synopsis
ABOUTME: Shared prompt rendering for human gate UIs.
ABOUTME: Shared prompt rendering for human gate UIs.

Jump to

Keyboard shortcuts

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