clichat

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: AGPL-3.0 Imports: 67 Imported by: 0

Documentation

Overview

Typed action model: every transcript action is a tool (⚙), an agent (◆), or a skill (§). The classification drives glyphs, work-group counts, and - later - the per-agent turn ledger. Glyphs are deliberately single-width text, never emoji: emoji are double-width and font-dependent, which misaligns columns in real terminals.

Package cli implements mivia command handlers.

Package cli implements mivia command handlers.

Package cli - lightweight syntax highlighter for terminal code blocks. Uses pattern matching per language (no external parsing library). Each line is processed independently so it works with streaming output.

Package cli implements mivia command handlers.

Package cli - markdown → ANSI rendering for terminal chat UX.

Table rendering for the markdown writer: box chrome, per-cell measurement and padding.

Cells are FORMATTED BEFORE MEASURING. Column widths and padding must use the rendered width, not the markdown source: "**bold**" is eight source columns but renders as four, so measuring the source padded every styled cell short and the box borders never lined up.

MessageBubble renders a chat message for any role; style and text renderer are both pluggable via WithStyle/MergeStyle and BubbleRenderer.

Package cli implements mivia command handlers.

Package cli - chat rendering for plain (--plain) mode.

Package clichat holds the interactive REPL session loop, the session stack, and the terminal UI rendering support that the loop needs. It is extracted from internal/cli and must never import internal/cli; the cli package wires the seam vars below at process start.

Package cli implements mivia command handlers.

SubagentTracker aggregates attributed subagent events into per-agent rows. It is the data spine for the fleet box and the per-agent turn ledger: a pure state machine - feed it with Apply, read it with Rows. It renders nothing and holds no locks; the TUI update loop owns it. All methods are nil-receiver safe so models built without a tracker stay inert.

Index

Constants

View Source
const (
	// ChromeNeutral is the default structural rail color.
	ChromeNeutral = "8" // dim gray - structure default

	// ChromeError is the strict-failure rail color.
	ChromeError = "160" // vivid red - strict failures only
)

Chrome color tokens - semantic status only (not tool names). Tools/steps default to neutral gray; yellow is for status-bar tools phase only. Values mirror internal/legacytui/brand.go's brandColor* constants (relocated here: needed unqualified by this package's own rail resolver and by internal/legacytui's rendering, which imports this package).

View Source
const (
	// GlyphCheck marks a succeeded state.
	GlyphCheck = "✓"
	// GlyphCross marks a failed state.
	GlyphCross = "✗"
	// GlyphDiamond marks an agent-kind action.
	GlyphDiamond = "◆"
	// GlyphLozenge marks a skill-kind action.
	GlyphLozenge = "◇"
	// GlyphTriR is the right-pointing triangle for a collapsed section.
	GlyphTriR = "▸" // right-pointing triangle (collapsed)

)

Glyphs centralize the single-character status markers used across the TUI render surface (toolui, toolpanel, chatblock_render, brand).

View Source
const (
	AnsiBgDiffAdd = ansiBgDiffAdd
	AnsiBgDiffDel = ansiBgDiffDel
)

AnsiBgDiffAdd and AnsiBgDiffDel are ansiBgDiffAdd/ansiBgDiffDel, exported for internal/legacytui.

View Source
const (
	SlashKindBuiltin slashKind = iota
	SlashKindSkill
)
View Source
const (
	// AnsiBold starts bold text.
	AnsiBold = "\033[1m"
	// AnsiBoldEnd ends bold text.
	AnsiBoldEnd = "\033[22m"
	// AnsiItalic starts italic text.
	AnsiItalic = "\033[3m"
	// AnsiDim starts dim text.
	AnsiDim = "\033[2m"
	// AnsiDimEnd ends dim text.
	AnsiDimEnd = "\033[22m"
	// AnsiYellow sets yellow foreground.
	AnsiYellow = "\033[33m"
	// AnsiCyan sets cyan foreground.
	AnsiCyan = "\033[36m"
	// AnsiBlue sets blue foreground.
	AnsiBlue = "\033[34m"
	// AnsiGreen sets green foreground.
	AnsiGreen = "\033[32m"
	// AnsiRed sets red foreground.
	AnsiRed = "\033[31m"
	// AnsiMagenta sets magenta foreground.
	AnsiMagenta = "\033[35m"
	// AnsiBgDark sets a dark background (user-card / bar fill).
	AnsiBgDark = "\033[48;5;236m"
	// AnsiReset clears all SGR attributes.
	AnsiReset = "\033[0m"
)

ANSI SGR codes - one vocabulary for markdown + highlight rendering. Relocated from internal/legacytui/theme.go: internal/legacytui aliases these same values so both packages share one source of truth.

View Source
const (
	// ThemeColorDim is the dim/structural text color index.
	ThemeColorDim = "8"
	// ThemeColorDiffAdd is the added-line diff color index.
	ThemeColorDiffAdd = "10"
	// ThemeColorDiffDel is the removed-line diff color index.
	ThemeColorDiffDel = "9"
)

Theme color indices (256-color). Relocated from internal/legacytui/theme.go for the same reason as the ANSI codes above.

View Source
const (

	// ActionAgent marks a delegation/orchestration tool call. Shared with
	// internal/clichat's transcript renderer.
	ActionAgent actionKind
)
View Source
const BrandColorThinking = "44"

BrandColorThinking is the vivid cyan #00d7d7 thinking-ramp color. Relocated from internal/legacytui/brand.go: internal/legacytui aliases this value so both packages share one source of truth.

View Source
const EffortBusyNotice = "finish current work first"

EffortBusyNotice is the single wording for "this dial cannot move yet". The picker footer, the typed argument and a session refusal all describe the same state, so they say it the same way. Relocated from internal/legacytui/effort_dialog.go: needed unqualified there (the TUI picker) and by the classic-mode /effort handler here.

View Source
const EffortOrchestrationNotice = "effort is locked while orchestration runs"

EffortOrchestrationNotice replaces the shared switch guard's wording. That guard is written for /model and /agent, and telling someone who typed /effort that "model switching is unavailable" names an action they did not take - and overflows the 52 columns the TUI dialog footer has at 80 columns.

View Source
const EffortUnsetWord = "unset"

EffortUnsetWord is the one spelling of the unset state: the picker row and the typed argument use it, so what the user reads is what the user can type.

View Source
const MaxHistorySize = 500

MaxHistorySize is the maximum number of history entries kept per session.

View Source
const MaxThinkingLines = 6

MaxThinkingLines is the max visible lines for a windowed thinking block.

View Source
const MinCardWidth = 20

MinCardWidth is the floor width for a rendered chat card. Relocated from internal/legacytui/composer.go: internal/legacytui aliases this value so both packages share one source of truth.

View Source
const SessionEffortBusyRefusal = "reasoning effort cannot change while work is active"

SessionEffortBusyRefusal is chat.Session's wording for an in-flight turn. It lives in another package with no sentinel to match, so this surface owns a copy of the sentence and a test in internal/legacytui keeps the copy honest.

View Source
const SkillTurnPreamble = skills.SkillTurnPreamble

SkillTurnPreamble is skills.SkillTurnPreamble, exported for internal/legacytui.

View Source
const SlashSurfacePlain = slashSurfacePlain

SlashSurfacePlain is slashSurfacePlain, exported for internal/legacytui.

View Source
const (
	SlashSurfaceTUI slashSurface = 1 << iota
)
View Source
const WorkGroupWindowRows = workGroupWindowRows

WorkGroupWindowRows is workGroupWindowRows, exported for internal/legacytui.

Variables

View Source
var (

	// UserBubble: full-width dark-gray background, time then body.
	// No vertical pad - spacing is a free empty lane after the bubble in
	// appendRenderedBlockMem (tools/groups skip that lane).
	UserBubble = &MessageBubble{
		Style: BubbleStyle{
			Background: &_userBgStyle,
			LabelStyle: &_userLabelStyle,
			Padding: Padding{
				Top:    0,
				Right:  3,
				Bottom: 0,
				Left:   3,
			},
			LeftRail: nil,
			ShowTime: &_showTimeTrue,
		},
		Renderer: &plainTextRenderer{},
	}

	// AssistantBubble: horizontal pad only; thin rail on text lines via chrome.
	AssistantBubble = &MessageBubble{
		Style: BubbleStyle{
			Padding: Padding{Top: 0, Bottom: 0, Left: 2, Right: 1},

			LeftRail: nil,
			ShowTime: &_showTimeFalse,
		},
		Renderer: &markdownRenderer{},
	}
)

Pre-built bubble configurations for standard roles.

View Source
var (
	// TUIDimStyle is the dim/structural text style.
	TUIDimStyle = lipgloss.NewStyle().Foreground(lipgloss.Color(ThemeColorDim))
	// ToolDimStyle is the dim/structural text style for tool rows.
	ToolDimStyle = TUIDimStyle
	// TUIErrorStyle is the error text style.
	TUIErrorStyle = lipgloss.NewStyle().Foreground(lipgloss.Color(themeColorError))
	// ToolErrStyle is the inline error style for tool status icons.
	ToolErrStyle = TUIErrorStyle
	// UserLabelStyle renders the "you" user-turn label.
	UserLabelStyle = lipgloss.NewStyle().Foreground(lipgloss.Color(themeColorUser)).Bold(true)
	// UserRailStyle renders the user-turn left rail glyph.
	UserRailStyle = UserLabelStyle
	// TUIThinkingStyle renders live thinking-phase text.
	TUIThinkingStyle = lipgloss.NewStyle().Foreground(lipgloss.Color(BrandColorThinking)).Italic(true)
	// ToolOkStyle renders a completed, non-failed tool status icon.
	ToolOkStyle = lipgloss.NewStyle().Foreground(lipgloss.Color(ThemeColorDiffAdd))
	// ToolNameStyle renders a tool's name.
	ToolNameStyle = lipgloss.NewStyle().Foreground(lipgloss.Color(themeColorUser)).Bold(true)
	// ToolTimeStyle renders a tool's elapsed-time text.
	ToolTimeStyle = lipgloss.NewStyle().Foreground(lipgloss.Color(themeColorTime))
	// ToolPathStyle renders the workspace-path chip on a tool row.
	ToolPathStyle = lipgloss.NewStyle().Reverse(true).Faint(true)
	// AgentBadgeStyle marks nested tool rows with their producing subagent.
	AgentBadgeStyle = lipgloss.NewStyle().Foreground(lipgloss.Color(brandColorMulti))
)

Semantic styles. Relocated from internal/legacytui/theme.go and internal/legacytui/toolui.go: both are reconstructed here from the raw color indices above (rather than aliasing an unexported legacytui var, which cli cannot reach), and internal/legacytui aliases these vars back so its own call sites are unchanged.

View Source
var AdvertisedSessionToolSpecs = advertisedSessionToolSpecs

AdvertisedSessionToolSpecs is the exported alias for the advertisedSessionToolSpecs function, for seam wiring.

View Source
var AllChunksMerged = allChunksMerged

AllChunksMerged is the exported alias for the allChunksMerged function, for seam wiring.

View Source
var BrandWorkFrames = []string{
	"⠶",
	"⠛",
	"⠿",
	"⣿",
	"⣶",
	"⠿",
	"⠛",
	"⠶",
}

BrandWorkFrames is an 8-frame single-rune braille diamond pulse. Relocated from internal/legacytui/brand.go: internal/legacytui aliases this slice so both packages share one source of truth.

View Source
var BuiltInSlashCommands = builtInSlashCommands

BuiltInSlashCommands is the exported alias for the builtInSlashCommands function, for seam wiring.

View Source
var ChatFlags = chatFlags

ChatFlags is the exported alias for the chatFlags flag parser.

View Source
var ChatWorkspaceRoot = chatWorkspaceRoot

ChatWorkspaceRoot is the exported alias for chatWorkspaceRoot.

View Source
var ClassicAgentStatePtr = &cliagents.ClassicAgentState

ClassicAgentStatePtr is &cliagents.ClassicAgentState, exported for internal/legacytui.

View Source
var ClassifyStackPlanRunDelivery = classifyStackPlanRunDelivery

ClassifyStackPlanRunDelivery is the exported alias for the classifyStackPlanRunDelivery function, for seam wiring.

View Source
var CurrentHookSessionFunc func() HookSessionState

CurrentHookSessionFunc stands for cli.currentHookSession.

View Source
var DriveStackToCompletion = driveStackToCompletion

DriveStackToCompletion is the exported alias for the driveStackToCompletion function, for seam wiring.

View Source
var ErrFailedStackPlanRun = errFailedStackPlanRun

ErrFailedStackPlanRun is the exported alias for the errFailedStackPlanRun function, for seam wiring.

View Source
var ErrStackAwaitsGrant = errStackAwaitsGrant

ErrStackAwaitsGrant is the exported alias for the errStackAwaitsGrant function, for seam wiring.

View Source
var ErrUndrivenStackPlanRun = errUndrivenStackPlanRun

ErrUndrivenStackPlanRun is the exported alias for the errUndrivenStackPlanRun function, for seam wiring.

View Source
var FlagValueFunc func(args []string, names ...string) (string, []string, bool, error)

FlagValueFunc stands for cli.flagValue: it returns the value of the first occurrence of any named flag and the remaining arguments. Wired by internal/cli/clichat_wiring.go; tests wire it in TestMain.

View Source
var FlagVarFunc func(args []string, names ...string) ([]string, []string, bool, error)

FlagVarFunc stands for cli.flagVar: like FlagValueFunc but for repeatable string flags. Wired by internal/cli/clichat_wiring.go.

View Source
var ForbiddenKeys = forbiddenKeys

ForbiddenKeys is forbiddenKeys, exported for internal/legacytui.

View Source
var HandleSlashCommand = handleSlash

HandleSlashCommand is the exported alias for the handleSlash dispatcher.

View Source
var HandleSlashHooksFunc func(fields []string, term *Terminal) (bool, bool, error)

HandleSlashHooksFunc stands for cli.handleSlashHooks.

View Source
var HookSessionConfiguredFunc func() bool

HookSessionConfiguredFunc stands for cli.hookSessionConfigured.

View Source
var InjectBaselineMessaging = injectBaselineMessaging

InjectBaselineMessaging is the exported alias for the injectBaselineMessaging function, for seam wiring.

View Source
var InstallHookSessionFunc func(workspaceRoot string, staleBypass, quiet bool) (func(), error)

InstallHookSessionFunc stands for cli.installHookSession. Wired by internal/cli/clichat_wiring.go; tests wire it in TestMain.

View Source
var KeyRegistry = keyRegistry

KeyRegistry is keyRegistry, exported for internal/legacytui.

View Source
var LoadAllStackChunks = loadAllStackChunks

LoadAllStackChunks is the exported alias for the loadAllStackChunks function, for seam wiring.

View Source
var LoadAllStackChunksForDrive = loadAllStackChunksForDrive

LoadAllStackChunksForDrive is the exported alias for the loadAllStackChunksForDrive function, for seam wiring.

View Source
var LoadStackPlanOutput = loadStackPlanOutput

LoadStackPlanOutput is the exported alias for the loadStackPlanOutput function, for seam wiring.

View Source
var LogMCPWarnings = logMCPWarnings

LogMCPWarnings is the exported alias for the logMCPWarnings function, for seam wiring.

View Source
var MemoryConfigOfFunc func(state *AgentSessionState) config.MemoryConfig

MemoryConfigOfFunc stands for cli.memoryConfigOf.

View Source
var MemoryOfFunc func(state *AgentSessionState) memory.Store

MemoryOfFunc stands for cli.memoryOf.

View Source
var MessagingDisallowed = messagingDisallowed

MessagingDisallowed is the exported alias for the messagingDisallowed function, for seam wiring.

View Source
var NewEmptyDelegateToolFunc func() tools.Tool

NewEmptyDelegateToolFunc stands for a zero-value cli delegate tool, used by the session tool catalog.

View Source
var OpenStackLedgerFunc func(root, configPath string) (*workflowledger.Store, workflowledger.Repository, func(), error)

OpenStackLedgerFunc stands for cli.openStackLedger.

View Source
var ParseStackPlanOutput = parseStackPlanOutput

ParseStackPlanOutput is the exported alias for the parseStackPlanOutput function, for seam wiring.

View Source
var ParseStackWorkflowArgsFunc func(args []string) (name, stackFlag string, rest []string, err error)

ParseStackWorkflowArgsFunc stands for cli.parseStackWorkflowArgs.

View Source
var ResolveStackIDFunc func(repo workflowledger.Repository, workflowName, stackFlag string) (string, error)

ResolveStackIDFunc stands for cli.resolveStackID.

View Source
var RunChat = runChat

RunChat is the exported alias for the runChat command entry point.

View Source
var RunCompact = runCompact

RunCompact is the exported alias for the runCompact command entry point.

View Source
var RunConfiguredChat = runConfiguredChat

RunConfiguredChat is the exported alias for the runConfiguredChat entry point, for the cli characterization test shim.

View Source
var RunSessions = runSessions

RunSessions is the exported alias for the runSessions command entry point.

View Source
var RunStackDrive = runStackDrive

RunStackDrive is the exported alias for the runStackDrive entry point.

View Source
var ScopeComposer = scopeComposer

ScopeComposer is scopeComposer, exported for internal/legacytui.

View Source
var ScopeDashboard = scopeDashboard

ScopeDashboard is scopeDashboard, exported for internal/legacytui.

View Source
var ScopeGlobal = scopeGlobal

ScopeGlobal is scopeGlobal, exported for internal/legacytui.

View Source
var ScopeHistory = scopeHistory

ScopeHistory is scopeHistory, exported for internal/legacytui.

View Source
var ScopeOverlay = scopeOverlay

ScopeOverlay is scopeOverlay, exported for internal/legacytui.

View Source
var ScopeQueue = scopeQueue

ScopeQueue is scopeQueue, exported for internal/legacytui.

View Source
var ScopeScrollback = scopeScrollback

ScopeScrollback is scopeScrollback, exported for internal/legacytui.

View Source
var ScopeSessions = scopeSessions

ScopeSessions is scopeSessions, exported for internal/legacytui.

View Source
var ScopeSuggest = scopeSuggest

ScopeSuggest is scopeSuggest, exported for internal/legacytui.

View Source
var ScopeWelcome = scopeWelcome

ScopeWelcome is scopeWelcome, exported for internal/legacytui.

View Source
var ScopeWorkflows = scopeWorkflows

ScopeWorkflows is scopeWorkflows, exported for internal/legacytui.

View Source
var SeedStackLedger = seedStackLedger

SeedStackLedger is the exported alias for the seedStackLedger function, for seam wiring.

View Source
var SessionAutoDeliveryRepairLoop = sessionAutoDeliveryRepairLoop

SessionAutoDeliveryRepairLoop is the exported alias for the sessionAutoDeliveryRepairLoop function, for seam wiring.

View Source
var SettleStackPlanRunIfComplete = settleStackPlanRunIfComplete

SettleStackPlanRunIfComplete is the exported alias for the settleStackPlanRunIfComplete function, for seam wiring.

View Source
var SlashSurfaceBoth = slashSurfaceBoth

SlashSurfaceBoth is the exported alias for the slashSurfaceBoth surface.

View Source
var StackDecomposedChunks = stackDecomposedChunks

StackDecomposedChunks is the exported alias for the stackDecomposedChunks function, for seam wiring.

View Source
var StackGrantHintLines = stackGrantHintLines

StackGrantHintLines is the exported alias for stackGrantHintLines.

View Source
var StackHeadBranch = stackHeadBranch

StackHeadBranch is the exported alias for the stackHeadBranch function, for seam wiring.

View Source
var StackMergedSet = stackMergedSet

StackMergedSet is the exported alias for the stackMergedSet function, for seam wiring.

View Source
var StackPRNumber = stackPRNumber

StackPRNumber is the exported alias for stackPRNumber.

View Source
var StackPlanInputs = stackPlanInputs

StackPlanInputs is the exported alias for the stackPlanInputs function, for seam wiring.

View Source
var StackPlanRunFailureReason = stackPlanRunFailureReason

StackPlanRunFailureReason is the exported alias for the stackPlanRunFailureReason function, for seam wiring.

View Source
var StackRunHeadCommit = stackRunHeadCommit

StackRunHeadCommit is the exported alias for the stackRunHeadCommit function, for seam wiring.

View Source
var StackRunPublishWithheld = stackRunPublishWithheld

StackRunPublishWithheld is the exported alias for the stackRunPublishWithheld function, for seam wiring.

View Source
var StackRunPushed = stackRunPushed

StackRunPushed is the exported alias for the stackRunPushed function, for seam wiring.

View Source
var StackRunRef = stackRunRef

StackRunRef is the exported alias for the stackRunRef function, for seam wiring.

View Source
var StackRunRefExport = stackRunRef

StackRunRefExport is the exported alias for stackRunRef, for internal/cli/stack_command.go. The StackRunRef name is taken by the cliworkflow wiring alias.

View Source
var StackScope = stackScope

StackScope is the exported alias for stackScope.

View Source
var StackTaskMap = stackTaskMap

StackTaskMap is the exported alias for the stackTaskMap function, for seam wiring.

View Source
var StackingDriveAllowPublish = stackingDriveAllowPublish

StackingDriveAllowPublish is the exported alias for the stackingDriveAllowPublish function, for seam wiring.

View Source
var SummaryWiring = summaryWiring

SummaryWiring is the exported alias for the summaryWiring function, for seam wiring.

View Source
var TUILauncherFunc func(sess *chat.Session, res *config.Resolved, toolsOn bool, agentState *AgentSessionState, resumeSessionName string) error

TUILauncherFunc stands for the TUI launcher that cli owns. Wired by internal/cli/tui_launcher.go.

Functions

func ActionIconForTool

func ActionIconForTool(name string) string

ActionIconForTool is the glyph for a tool name. Shared with internal/legacytui's tool status renderer.

func ActionKindForTool

func ActionKindForTool(name string) actionKind

ActionKindForTool classifies a tool name. Workspace skills are dispatched under their own names; classifying them as actionSkill needs the skills registry plumbed into the render layer - until then they read as tools.

func AdoptManagedWorktree

func AdoptManagedWorktree(root string, wt *vcs.WorktreeInfo) (contextstate.WorktreeInstance, error)

AdoptManagedWorktree is cliworktree.AdoptManagedWorktree, exported for internal/legacytui.

func AppendCtxSuffix

func AppendCtxSuffix(detail string, percent int) string

AppendCtxSuffix implements append ctx suffix.

func ApplyBlockChromeWith

func ApplyBlockChromeWith(lines []string, block ChatBlock, text string, opts RailOpts, mem GroupMember, view RailView) []string

ApplyBlockChromeWith applies hierarchical state-aware rail chrome for a block inside a work group. Shared with the classic-mode block renderer in internal/clichat.

func ApplyLeftRail

func ApplyLeftRail(lines []string, rail LeftRail) []string

ApplyLeftRail paints the accent by rail.Mode. Blank / pad-only lines never get a glyph - empty rail column keeps alignment.

  • Header: first non-blank line only
  • Tree: first non-blank Glyph, later non-blank Char
  • Full: every non-blank line Glyph (assistant speech)

Shared with the classic-mode block renderer and work-group grouping in internal/clichat.

func ApplyPrivacyPolicy

func ApplyPrivacyPolicy(res *config.Resolved)

ApplyPrivacyPolicy is applyPrivacyPolicy, exported for internal/legacytui.

func ApplySessionAgent

func ApplySessionAgent(sess *chat.Session, res *config.Resolved, state *AgentSessionState, name string, busy bool) error

ApplySessionAgent is cliagents.ApplySessionAgent, exported for internal/legacytui.

func ApplyWorkflowStoreRoot

func ApplyWorkflowStoreRoot(res *config.Resolved, root string)

ApplyWorkflowStoreRoot is cliworkflow.ApplyWorkflowStoreRoot, exported for internal/legacytui.

func AttachSessionDispatcher

func AttachSessionDispatcher(sess *chat.Session, root, model string, cfg config.SubagentConfig, state *AgentSessionState, skillReg *skills.Registry, routing SessionRouting) (func(), error)

AttachSessionDispatcher is attachSessionDispatcher, exported for internal/legacytui.

func BeginManagedWorktreeRemoval

func BeginManagedWorktreeRemoval(root string, wt *vcs.WorktreeInfo) (contextstate.WorktreeInstance, error)

BeginManagedWorktreeRemoval is cliworktree.BeginManagedWorktreeRemoval, exported for internal/legacytui.

func BeginManagedWorktreeRemovalInStore

func BeginManagedWorktreeRemovalInStore(store *storage.SQLite, root string, wt *vcs.WorktreeInfo) (contextstate.WorktreeInstance, error)

BeginManagedWorktreeRemovalInStore is cliworktree.BeginManagedWorktreeRemovalInStore, exported for internal/legacytui.

func BindManagedWorktreeSessionExpected

func BindManagedWorktreeSessionExpected(sess *chat.Session, repositoryRoot, workspaceRoot, storePath string, expected contextstate.WorktreeInstance) error

BindManagedWorktreeSessionExpected is bindManagedWorktreeSessionExpected, exported for internal/legacytui.

func BoundedToolText

func BoundedToolText(s string, max int) string

BoundedToolText sanitizes and bounds model-influenced tool text (names, arguments, error bodies) to max runes. Shared by the live status panel (internal/legacytui) and the classic-mode renderer.

func BuildModelBinding

func BuildModelBinding(sess *chat.Session, res *config.Resolved, root, providerName, model string, state *AgentSessionState) (chat.ModelBinding, error)

BuildModelBinding is cliagents.BuildModelBinding, exported for internal/legacytui.

func BuildSkillCatalogue

func BuildSkillCatalogue(workspaceRoot string) (map[string]agents.SkillCatalogueEntry, []string)

BuildSkillCatalogue is cliagents.BuildSkillCatalogue, exported for internal/legacytui.

func CancellationCanReplaceTurnError

func CancellationCanReplaceTurnError(err error) bool

CancellationCanReplaceTurnError implements cancellation can replace turn error.

func ChatBlockID

func ChatBlockID(turn, seq uint64) string

ChatBlockID implements chat block i d.

func ClampWorkGroupScroll

func ClampWorkGroupScroll(off, total int) int

ClampWorkGroupScroll bounds a group's window offset to its member count.

func ClearSubagentProgress

func ClearSubagentProgress(token uint64)

ClearSubagentProgress conditionally clears the registered progress handler only if the generation token still matches. This prevents a stale goroutine (from a cancelled turn) from clearing a newer turn's callback:

genA := TurnA: SetSubagentProgress(fnA)
genB := TurnB: SetSubagentProgress(fnB)   → gen now matches genB
TurnA exits: ClearSubagentProgress(genA)   → no-op (gen != genA), fnB preserved

func ClipPreviewLine

func ClipPreviewLine(l string, width int) string

ClipPreviewLine truncates a preview line for the terminal width without panicking when width is 0 or very small (pre-WindowSizeMsg / narrow panes).

func CollapseConversations

func CollapseConversations(infos []chat.SessionInfo) []chat.SessionInfo

CollapseConversations keeps one row per conversation in a user-facing session list. Rows that display the same name from the same directory are continuations of one conversation, so only the newest stays visible (the list is newest-first). Worktree routes and internal auto-save snapshots are never merged: routes open a workspace, and auto-saves are durability artifacts, not conversation lineage.

func ColorDiffLine

func ColorDiffLine(l string) string

ColorDiffLine is a thin alias of RenderDiffLine for call-site compatibility (tool preview / renderDiffBody). @@ hunks use magenta (unified with markdown and highlight surfaces), not dim.

func CompactStructuralOnlyNotice

func CompactStructuralOnlyNotice(reason string) string

CompactStructuralOnlyNotice explains an instant, LLM-free compaction. A structural-only compact returns at once and makes no provider call, which is correct but reads as a broken summarizer; naming the unmet condition is the difference between "it did nothing" and "it is not configured to do that".

func ConfigureChatWorkspace

func ConfigureChatWorkspace(sess *chat.Session, root string, useTools bool, res *config.Resolved, state *AgentSessionState, quiet bool, fullDisk bool, runRecoverySweep bool) (func(), error)

ConfigureChatWorkspace is cliagents.ConfigureChatWorkspace, exported for internal/legacytui.

func ContextStorePath

func ContextStorePath(root string, cfg config.SubagentConfig) string

ContextStorePath is always SQLite-backed regardless of subagents store_backend, which governs the separate orchestration ledger (internal/cli/orchestration_state.go), not this store.

NOTE: openContextStore/openContextStorePath below were NOT relocated to internal/composition as the task briefing directed. That briefing assumed internal/composition already imports internal/cli; it does not (verified: zero cli imports in internal/composition/*.go), while internal/cli already imports internal/composition in 5 files (dispatcher.go, hooks_runner.go, mcp_session.go, chat_workspace.go, workflow_authority.go). Moving these two functions to composition and having composition call cli.ContextStorePath would close cli -> composition -> cli, a compiler-rejected import cycle. Flagged as a blocker; these two functions stay in internal/cli unexported, same as before this slice, only ContextStorePath was exported (cliworktree needs it externally; the other two do not).

func ContextWorkspaceID

func ContextWorkspaceID(root string) string

ContextWorkspaceID is contextWorkspaceID, exported for internal/legacytui.

func CreateManagedWorktree

func CreateManagedWorktree(root, name, baseRef, branchPrefix string) (*vcs.WorktreeInfo, error)

CreateManagedWorktree is createManagedWorktree, exported for internal/legacytui.

func CreateManagedWorktreeInStore

func CreateManagedWorktreeInStore(store *storage.SQLite, root, name, baseRef, branchPrefix string) (*vcs.WorktreeInfo, error)

CreateManagedWorktreeInStore is cliworktree.CreateManagedWorktreeInStore, exported for internal/legacytui.

func CurrentAgentName

func CurrentAgentName(state *AgentSessionState) string

CurrentAgentName is cliagents.CurrentAgentName, exported for internal/legacytui.

func DeleteSessionResult

func DeleteSessionResult(name string) string

DeleteSessionResult implements delete session result.

func DisplaySessionName

func DisplaySessionName(si chat.SessionInfo, latestAuto string) string

DisplaySessionName labels sessions for the welcome picker. Latest auto-save → "Last session"; older autos → "Auto · {relative time}"; named sessions keep their name. Handles bare __last__ and __last__* names.

func EffortDiscardedSuffix

func EffortDiscardedSuffix(discarded reasoning.Level) string

EffortDiscardedSuffix is the one wording for a /effort choice a model switch dropped. The surfaces phrase the switch itself differently - the plain REPL parenthesises it, the picker does not - but a user who learns to recognise this clause on one of them must recognise it on the others.

func EffortRowName

func EffortRowName(level reasoning.Level) string

EffortRowName names a reasoning level row. The unset level has no wire spelling of its own, so it needs a word here.

func EmitSubagentProgress

func EmitSubagentProgress(e agent.Event)

EmitSubagentProgress is emitSubagentProgress, exported for internal/legacytui.

func EnableSessionContext

func EnableSessionContext(sess *chat.Session, root string, store *storage.SQLite, res *config.Resolved) error

EnableSessionContext is enableSessionContext, exported for internal/legacytui.

func EventPreview

func EventPreview(preview, fallback string) string

EventPreview returns preview, falling back to fallback when preview is empty. Relocated from internal/legacytui/tui_events.go: needed unqualified there and by the classic-mode UI and the JSON event writer here.

func FilterSkillsForScope

func FilterSkillsForScope(reg *skills.Registry, scope AgentSkillScope) *skills.Registry

FilterSkillsForScope is cliagents.FilterSkillsForScope, exported for internal/legacytui.

func FitDialogRow

func FitDialogRow(row string, width int) string

FitDialogRow pads or truncates row to exactly width display columns. Shared with internal/legacytui's dialog frame renderer.

func FormatAgentCurrent

func FormatAgentCurrent(name string, reg *agents.AgentRegistry) string

FormatAgentCurrent is cliagents.FormatAgentCurrent, exported for internal/legacytui.

func FormatAgentSet

func FormatAgentSet(name string) string

FormatAgentSet is cliagents.FormatAgentSet, exported for internal/legacytui.

func FormatAgentUnavailable

func FormatAgentUnavailable(err error) string

FormatAgentUnavailable renders an agent-switch error for display. Relocated from internal/legacytui/agent_dialog.go: needed unqualified there and by the classic-mode slash-command handlers here.

func FormatBudgetInvalid

func FormatBudgetInvalid(arg string) string

FormatBudgetInvalid implements format budget invalid.

func FormatBudgetSet

func FormatBudgetSet(budget int) string

FormatBudgetSet implements format budget set.

func FormatBudgetSummary

func FormatBudgetSummary(budget int) string

FormatBudgetSummary implements format budget summary.

func FormatDuration

func FormatDuration(d time.Duration) string

FormatDuration renders a duration as tool-elapsed text (ms/s/m:ss). Shared by the live status panel (internal/legacytui) and the classic-mode renderer.

func FormatEffortSet

func FormatEffortSet(model string, requested reasoning.Level, effective reasoning.Setting) string

FormatEffortSet confirms what the request will now carry, which is not the same as what was asked for: clearing the override on a model with a configured default puts that default back on the wire, and reporting the argument there would promise silence the provider never gets.

func FormatEffortStatus

func FormatEffortStatus(setting reasoning.Setting, offersReasoning bool) string

FormatEffortStatus is the /status reading of the dial: the level plus the dialect that carries it, since the same level reaches different providers as different JSON. A model with no reasoning surface says so rather than leaving the field blank.

offersReasoning is a separate argument because "has this model anything to offer" is a question about its DECLARED SET, which no dialect value answers: an absent dialect resolves to the provider's default, and a declared one is a wire shape for levels that may not exist. Callers take it from Session.ReasoningChoices, the same set /effort accepts against.

func FormatEffortSummary

func FormatEffortSummary(model string, choices []reasoning.Level, current, fallback reasoning.Level) string

FormatEffortSummary is the no-argument answer on both surfaces: what is active now, and what else this model offers.

func FormatLiveToolWaveSummary

func FormatLiveToolWaveSummary(open, done, total int, elapsed time.Duration) string

FormatLiveToolWaveSummary builds the live one-line wave status. Examples: "Running 2 tools… · 0/2 done · 3s", "Working · 1/3 done · 12s"

func FormatModelSet

func FormatModelSet(providerName, model string, discarded reasoning.Level) string

FormatModelSet implements format model set.

func FormatModelUnavailable

func FormatModelUnavailable(providerName, choices, name string, otherProviders []string) string

FormatModelUnavailable reports a /model failure, naming any OTHER configured provider that does have the requested name so the user gets an actionable next step instead of a dead end. otherProviders is the result of (*config.Resolved).OtherProvidersWithModel for the same lookup - nil or empty when the name exists nowhere else, in which case the message is unchanged from before this hint existed. name is the model name the user requested, interpolated into the suggested command - Step-5 bug audit caught an earlier version of this that printed the literal placeholder text "<model-name>" instead, which then failed the same way if a user copy-pasted it verbatim.

The choices == "" branch ("model name is invalid") means the active provider itself has no selectable catalog (misconfigured or no API key) - otherProviders is still consulted and named there too, since "this provider is broken, but the model you asked for exists under provider X" is exactly the situation this hint exists for.

func FormatSessionAge

func FormatSessionAge(t time.Time) string

FormatSessionAge returns a short relative time. Relocated from internal/legacytui/welcome.go alongside DisplaySessionName, its only caller in both packages.

func FormatStepsInvalid

func FormatStepsInvalid(arg string) string

FormatStepsInvalid implements format steps invalid.

func FormatStepsSet

func FormatStepsSet(steps int) string

FormatStepsSet implements format steps set.

func FormatStepsSummary

func FormatStepsSummary(steps int) string

FormatStepsSummary implements format steps summary.

func FormatUserBubbleTime

func FormatUserBubbleTime(t time.Time) string

FormatUserBubbleTime is formatUserBubbleTime, exported for internal/legacytui.

func FormatUserMessageCard

func FormatUserMessageCard(text string, width int, sentAt time.Time) []string

FormatUserMessageCard is formatUserMessageCard, exported for internal/legacytui.

func GitMergeCheck

func GitMergeCheck(ctx context.Context, git delivery.GitRunner, pr delivery.PRClient, gc delivery.GitContext, headBranch, baseBranch, headCommit, repoSlug string, wasPushed bool) (bool, error)

GitMergeCheck wraps the gitMergeChecker merge oracle for cross-package seam wiring.

func HandleSlash

func HandleSlash(line string, sess *chat.Session, res *config.Resolved, toolsOn bool, term *Terminal) (bool, bool, error)

HandleSlash is handleSlash, exported for internal/legacytui.

func HandleSlashAgent

func HandleSlashAgent(fields []string, sess *chat.Session, res *config.Resolved, term *Terminal, state *AgentSessionState) (bool, bool, error)

HandleSlashAgent is handleSlashAgent, exported for internal/legacytui.

func HandleSlashEffort

func HandleSlashEffort(fields []string, sess *chat.Session, term *Terminal) (bool, bool, error)

HandleSlashEffort is the plain-surface /effort. There is no picker here, so the no-argument form prints what the picker would have shown: the active level and the set this model offers, or why there is nothing to choose.

func HandleSlashInfo

func HandleSlashInfo(cmd string, fields []string, sess *chat.Session, res *config.Resolved, toolsOn bool, term *Terminal) (bool, bool, error)

HandleSlashInfo is handleSlashInfo, exported for internal/legacytui.

func HandleSlashSessions

func HandleSlashSessions(cmd, line string, sess *chat.Session, term *Terminal) (bool, bool, error)

HandleSlashSessions is handleSlashSessions, exported for internal/legacytui.

func HighlightCodeBlock

func HighlightCodeBlock(lang, code string) string

HighlightCodeBlock is highlightCodeBlock, exported for internal/legacytui.

func InjectSkillResourceTool

func InjectSkillResourceTool(
	registry *tools.Registry,
	activation *skills.SkillActivation,
) (*tools.Registry, error)

InjectSkillResourceTool clones the given registry, checks for an existing skill resource tool (returning an error on conflict), registers a new scoped reader bound to the activation, and returns the augmented clone. The caller is responsible for calling activation.Close() when done.

func IsBannerTool

func IsBannerTool(name string) bool

IsBannerTool implements is banner tool.

func IsEditTool

func IsEditTool(name string) bool

IsEditTool reports whether name is a file-editing tool (write_file, search_replace, multi_edit). Shared by the classic-mode renderer.

func IsLifecycleStatus

func IsLifecycleStatus(s string) bool

IsLifecycleStatus reports whether s is a bare lifecycle token (queued/running/completed/failed, with truncated/duplicate variants) and not a useful summary on its own. Shared by the classic-mode renderer.

func IsLocalSlash

func IsLocalSlash(command string) bool

IsLocalSlash reports whether command is a slash command this TUI surface recognizes. Exported: relocated from internal/legacytui/tui_slash_handlers.go (moved to internal/legacytui, its sole caller).

func IsWorkStatusBlock

func IsWorkStatusBlock(b ChatBlock) bool

IsWorkStatusBlock reports live/reconstructed empty-speech status lines.

func JoinHub

func JoinHub(sess *chat.Session, sink hub.Sink) *hub.Handle

JoinHub is the one call every live chat surface (TUI, classic REPL, line-mode) makes once its own EventBus (if any - the TUI manages its own, see tui_run.go) is finalized. storeDir is derived from the session's already-open context store rather than recomputed from workspace-routing logic, so it's automatically correct for the repository-root/managed- worktree/config-override cases setupChatSessionContext itself resolves - hub.lock/hub.sock end up right beside context.db. Returns nil (a no-op Handle) if the session has no SQLite-backed context store to key off, which should not happen for a live chat session but is not this package's invariant to enforce.

func KeyLabel

func KeyLabel(b Binding) string

KeyLabel is keyLabel, exported for internal/legacytui.

func LatestAutoSaveName

func LatestAutoSaveName(infos []chat.SessionInfo) string

LatestAutoSaveName returns the most recently updated auto-save name in infos (ListSessions order is newest-first; first auto match wins). Relocated from internal/legacytui/welcome.go: needed unqualified there (the welcome picker) and here (conversation collapsing).

func LifecycleStatusFailed

func LifecycleStatusFailed(s string) bool

LifecycleStatusFailed reports whether s is a "failed" lifecycle token. Exported: relocated from internal/legacytui/toolui.go's lowercase lifecycleStatusFailed, needed there by tui_tools_apply_methods.go.

func LoadAgentDefinitions

func LoadAgentDefinitions(workspaceRoot, agentFlag string, skillReg *skills.Registry) (cliagents.AgentLoadResult, error)

LoadAgentDefinitions is cliagents.LoadAgentDefinitions, exported for internal/legacytui.

func LoadChatSkills

func LoadChatSkills(wsRoot string) (*skills.Registry, error)

LoadChatSkills is loadChatSkills, exported for internal/legacytui.

func LoadContextSessionResult

func LoadContextSessionResult(name string, msgs, turns int) string

LoadContextSessionResult implements load context session result.

func LoadSessionResult

func LoadSessionResult(name string, msgs, turns int) string

LoadSessionResult implements load session result.

func LoadSessionSkills

func LoadSessionSkills(root string, allowProject bool) (*skills.Registry, []string, error)

LoadSessionSkills is cliagents.LoadSessionSkills, exported for internal/legacytui.

func Max

func Max(a, b int) int

Max returns the larger of a and b. Shared with internal/legacytui's layout math.

func Min

func Min(a, b int) int

Min returns the smaller of a and b. Shared with internal/legacytui's layout math.

func ModelRestoreNoticeText

func ModelRestoreNoticeText(saved, current string) string

ModelRestoreNoticeText is the single shared wording for a failed model restore after /load or auto-restore. Call sites must not re-format this.

func ModelSwitchChoices

func ModelSwitchChoices(res *config.Resolved, providerName, defaultProvider string) string

ModelSwitchChoices returns the selectable model list for providerName.

func NewAgentTaskHandler

func NewAgentTaskHandler(definition agents.ResolvedAgent, digest string, full *tools.Registry, d *runtime.Dispatcher, opts SessionDispatcherOpts) *agentTaskHandler

NewAgentTaskHandler is newAgentTaskHandler, exported for internal/legacytui.

func NewREPLRuntime

func NewREPLRuntime(sess *chat.Session, res *config.Resolved, toolsOn bool, term *Terminal) *replRuntime

NewREPLRuntime is newREPLRuntime, exported for internal/legacytui.

func NewSessionDispatcher

func NewSessionDispatcher(opts SessionDispatcherOpts) (*runtime.Dispatcher, error)

NewSessionDispatcher builds a runtime.Dispatcher for agent sessions from a single options struct. This is the only public constructor.

It registers tool handlers from the tool registry, one-shot and multi-step subagent handlers for delegation, optionally wires skills as subagent handlers, and adds delegation tools to the tool registry.

ToolResultCapBytes is the tools max_tool_result_bytes ceiling applied to every nested sub-agent loop (multi_step and skill handlers); 0 = uncapped.

func NewSessionDispatcherMinimal

func NewSessionDispatcherMinimal(reg *tools.Registry, comp provider.Completer, model string, cfg config.SubagentConfig, toolResultCapBytes int, skillReg ...*skills.Registry) (*runtime.Dispatcher, error)

NewSessionDispatcherMinimal is newSessionDispatcherMinimal, exported for internal/legacytui.

func OnEventForMultiStep

func OnEventForMultiStep(parentOnEvent func(agent.Event)) func(agent.Event)

OnEventForMultiStep wraps a parent OnEvent callback for forwarding subagent events. Tool start/end become SubagentStart/End; heartbeats, step progress, and the run-level Done signal are forwarded so long multi_step work is not silent and finished agents can be retired.

func OneShot

func OneShot(sess *chat.Session, prompt string, toolsOn bool, res *config.Resolved, quiet bool) error

OneShot is oneShot, exported for internal/legacytui.

func OpenContextStore

func OpenContextStore(root string, cfg config.SubagentConfig) (*storage.SQLite, error)

OpenContextStore is openContextStore, exported for internal/legacytui.

func OpenContextStorePath

func OpenContextStorePath(path string) (*storage.SQLite, error)

OpenContextStorePath is openContextStorePath, exported for internal/legacytui.

func OpenRepositoryContextStore

func OpenRepositoryContextStore(root string) (*storage.SQLite, error)

OpenRepositoryContextStore implements open repository context store.

func OpenWorkflowStore

func OpenWorkflowStore(root string, cfg config.SubagentConfig) (*storage.SQLite, workflowledger.Repository, func(), error)

OpenWorkflowStore is cliworkflow.OpenWorkflowStore, exported for internal/legacytui.

func OrchestrationRepoForDispatcher

func OrchestrationRepoForDispatcher(d *runtime.Dispatcher) ledger.LedgerRepository

OrchestrationRepoForDispatcher is cliorchestrate.OrchestrationRepoForDispatcher, exported for internal/legacytui.

func OrchestrationSwitchGuard

func OrchestrationSwitchGuard(sessionID string) func() error

OrchestrationSwitchGuard is orchestrationSwitchGuard, exported for internal/legacytui.

func OverlayAt

func OverlayAt(base, panel string, panelRect Rect, termW, termH int) string

OverlayAt composites panel onto base at panelRect, clamped to the terminal bounds. Shared with internal/legacytui's view compositor.

func ParseEffortArg

func ParseEffortArg(arg string) (reasoning.Level, error)

ParseEffortArg reads a /effort argument. It accepts the unset word on top of the levels, which is how the text surfaces reach the state reasoning.Level spells as empty - reasoning.ParseLevel cannot carry it, because there an empty argument is a missing key rather than a request to clear.

func ParseModelArgs

func ParseModelArgs(fields []string, currentProvider, defaultProvider string) (provider, model string, hasArg bool)

ParseModelArgs extracts provider/model from a /model slash line. fields[0] is the command token. hasArg is false when only /model was given.

func ParseNonNegInt

func ParseNonNegInt(fields []string) (n int, hasArg bool, ok bool)

ParseNonNegInt parses fields[1] as a non-negative integer for /budget and /steps. hasArg is false when no argument was supplied; ok is false on parse failure.

func ParseToolPath

func ParseToolPath(detail, result string) string

ParseToolPath extracts a workspace path from tool Detail/Result text. Prefers JSON "path":"..." then "wrote X" / "updated X" prefixes.

func ProcessLineChat

func ProcessLineChat(line string, sess *chat.Session, res *config.Resolved, toolsOn bool, term *Terminal, renderer *ChatRenderer, input *InputBuffer, modelShort string) error

ProcessLineChat is processLineChat, exported for internal/legacytui.

func ReadAutosaveStatus

func ReadAutosaveStatus(sessionDir string) string

ReadAutosaveStatus returns a non-empty warning string if the previous session's auto-save on exit failed, or "" if it succeeded or there is no status file yet.

func RecoverManagedWorktreeRemoval

func RecoverManagedWorktreeRemoval(root, name, branchPrefix string) (bool, error)

RecoverManagedWorktreeRemoval is cliworktree.RecoverManagedWorktreeRemoval, exported for internal/legacytui.

func RedactPreview

func RedactPreview(s string) string

RedactPreview redacts secrets from preview text. Relocated from internal/legacytui/toolpanel.go: needed unqualified there and by the classic-mode renderer here.

func RegisterManagedWorktreeInStore

func RegisterManagedWorktreeInStore(store *storage.SQLite, root string, wt *vcs.WorktreeInfo) (contextstate.WorktreeInstance, error)

RegisterManagedWorktreeInStore is registerManagedWorktreeInStore, exported for internal/legacytui.

func RegisterWorktreeRoute

func RegisterWorktreeRoute(root string, wt *vcs.WorktreeInfo) error

RegisterWorktreeRoute is cliworktree.RegisterWorktreeRoute, exported for internal/legacytui.

func RegistryForState

func RegistryForState(state *AgentSessionState) *agents.AgentRegistry

RegistryForState implements registry for state.

func RemainderSpoolFromRegistry

func RemainderSpoolFromRegistry(reg *tools.Registry) *remainder.Spool

RemainderSpoolFromRegistry returns the process-local remainder spool attached to the registered read_output tool, or nil when the tool is absent.

func RenderDialogFrame

func RenderDialogFrame(title string, rows []string, footer string, layout DialogLayout) string

RenderDialogFrame owns the shared exact-width frame for block and sessions dialogs. frameRows=2 means title/page/footer-bottom; frameRows=3 adds an explicit footer row before the bottom border for sessions.

func RenderDiffBody

func RenderDiffBody(body string, width, maxLines int) []string

RenderDiffBody renders a redacted, width-clamped diff body as display lines. Shared with internal/legacytui's tool panel.

func RenderDiffLine

func RenderDiffLine(line string) string

RenderDiffLine renders a single unified-diff line using theme tokens. Classification by leading marker (+++/---/@@/+/-/context) is centralized here; every diff surface in the package must route through this function.

The + and - prefixes are preserved verbatim in the output (existing gutter tests assert their presence). Leading indentation (" ") matches the highlight/markdown surfaces. @@ hunk headers use the magenta/hunk token (not dim/context).

func RenderHistoryMessages

func RenderHistoryMessages(msgs []provider.Message, modelName string, width int) []string

RenderHistoryMessages groups messages by user-message boundaries and renders each turn with turn-aware formatting. System messages are skipped. This is the primary entry point for loading full session history into the TUI viewport or the plain-mode renderer.

func RenderMarkdown

func RenderMarkdown(s string, width int) string

RenderMarkdown formats a full markdown document to ANSI.

func RenderMessageForHistory

func RenderMessageForHistory(msg provider.Message, modelName string, width int) []string

RenderMessageForHistory formats a single provider.Message into display-ready lines. Returns nil for system prompts. Each returned string may contain ANSI codes and newlines. Callers append these strings directly to the viewport message list.

Roles:

system → nil (skip)
user   → background bar with optional local time + body (no border)
assistant with ToolCalls → tool_call_line* + content* (no model border)
assistant without ToolCalls → rendered_markdown (no model border)
tool   → ["icon name truncated_result"]

func RenderOneChatBlock

func RenderOneChatBlock(block ChatBlock, model string, width int, thinkingExpandDefault bool) []string

RenderOneChatBlock is renderOneChatBlock, exported for internal/legacytui.

func RenderReplHelpInline

func RenderReplHelpInline() string

RenderReplHelpInline is renderReplHelpInline, exported for internal/legacytui.

func RenderSkillSlashPrompt

func RenderSkillSlashPrompt(instructions, args string) string

RenderSkillSlashPrompt implements render skill slash prompt.

func RenderThinkingBlock

func RenderThinkingBlock(text string, collapsed bool, scrollOffset int, thinkingExpandDefault bool, width int) []string

RenderThinkingBlock is renderThinkingBlock, exported for internal/legacytui.

func RenderTurn

func RenderTurn(msgs []provider.Message, modelName string, width int) []string

RenderTurn renders a group of messages forming one conversational turn. A turn starts with a user message and includes the assistant reply (possibly with tool calls and results), ending at the next user message or end of slice.

Returns nil if the group is empty or has no user message. The output uses turn-aware grouping: one header for the user, one header for the model, inline tool call/result lines, and the final assistant answer rendered as markdown.

func ReplHelpContent

func ReplHelpContent() []helpSection

ReplHelpContent is replHelpContent, exported for internal/legacytui.

func RepositorySessionStorePath

func RepositorySessionStorePath(root string, invocation ChatInvocation, r *config.Resolved) (string, error)

RepositorySessionStorePath is repositorySessionStorePath, exported for internal/legacytui.

func ResolveTaskRoute

func ResolveTaskRoute(reg *agents.AgentRegistry, skillReg *skills.Registry, agentName, skillName string) (cliorchestrate.TaskRoute, error)

ResolveTaskRoute is cliorchestrate.ResolveTaskRoute, exported for internal/legacytui.

func RestoreREPLRuntime

func RestoreREPLRuntime(sess *chat.Session, res *config.Resolved, term *Terminal) string

RestoreREPLRuntime builds a replRuntime for sess/res/term via newREPLRuntime (toolsOn=false: no caller of this export exercises the tool-enabled REPL path) and returns the runtime's resulting short model name. newREPLRuntime itself runs the restore step (the auto-save "restored previous session" notice) as part of construction. Exported for internal/legacytui.

func ResultLooksLikeDiff

func ResultLooksLikeDiff(result string) bool

ResultLooksLikeDiff reports whether result carries unified-diff markers (---/+++ headers). Shared by the classic-mode renderer.

func RunChatCharacterization

func RunChatCharacterization(workspacePath string, jsonMode, plainUI, quiet bool, res *config.Resolved) error

RunChatCharacterization drives runConfiguredChat with the four invocation fields the cli characterization suite sets.

func RunStorage

func RunStorage(args []string) error

RunStorage dispatches `mivia storage <subcommand>`.

func RunWorktreeWithIO

func RunWorktreeWithIO(args []string, stdout io.Writer) error

RunWorktreeWithIO is cliworktree.RunWorktreeWithIO, exported for internal/legacytui.

func RuneWidth

func RuneWidth(s string) int

RuneWidth returns the visible column width of a string.

func SafeChatBlockText

func SafeChatBlockText(text string, maxChars int) string

func SafeEffortError

func SafeEffortError(err error) string

SafeEffortError keeps the session's own wording where it already names the level and the offered set, and rewrites the refusals that were written for another command. Unlike a model switch, nothing here can carry a credential or a provider message.

func SaveSessionResult

func SaveSessionResult(name string, msgs, turns int) string

SaveSessionResult implements save session result.

func SendLineMode

func SendLineMode(sess *chat.Session, line string, sigCh <-chan os.Signal, jsonMode bool) error

SendLineMode is sendLineMode, exported for internal/legacytui.

func SessionIdentity

func SessionIdentity(sess *chat.Session, state *AgentSessionState, generation uint64) *events.Identity

SessionIdentity is cliagents.SessionIdentity, exported for internal/legacytui.

func SetGlobalBus

func SetGlobalBus(bus *events.Bus)

SetGlobalBus sets the global EventBus reference used by emitSubagentProgress. Called once from runTUI.

func SetSubagentProgress

func SetSubagentProgress(fn func(agent.Event)) uint64

SetSubagentProgress registers the parent progress handler for multi_step subagent events (tool start/end, heartbeats). Returns a generation token that must be passed to ClearSubagentProgress for safe conditional removal.

func SetupChatSessionContext

func SetupChatSessionContext(sess *chat.Session, workspaceRoot string, invocation ChatInvocation, res *config.Resolved) (*storage.SQLite, error)

SetupChatSessionContext is setupChatSessionContext, exported for internal/legacytui.

func SetupRepositorySessionContext

func SetupRepositorySessionContext(sess *chat.Session, repositoryRoot, storePath string, res *config.Resolved) (*storage.SQLite, error)

SetupRepositorySessionContext is setupRepositorySessionContext, exported for internal/legacytui.

func SetupSessionContext

func SetupSessionContext(sess *chat.Session, root string, res *config.Resolved) (*storage.SQLite, error)

SetupSessionContext is setupSessionContext, exported for internal/legacytui.

func ShortenModel

func ShortenModel(m string) string

ShortenModel truncates a model name for narrow display. Shared with internal/legacytui's dialog and welcome views.

func ShortenWorkspacePath

func ShortenWorkspacePath() string

ShortenWorkspacePath returns the current directory with the home prefix collapsed to ~, or "" when unavailable.

func ShouldCommitInterim

func ShouldCommitInterim(s string) bool

ShouldCommitInterim reports whether text is real assistant speech worth a bubble. Rejects empty, whitespace, pure punctuation, lifecycle tokens, and very short ghosts.

func ShouldFollowOutput

func ShouldFollowOutput(follow bool, atBottom bool, scrolledUp bool) bool

ShouldFollowOutput decides whether the viewport should stick to the bottom. follow is the sticky flag; atBottom is viewport.AtBottom(); scrolledUp is an explicit user scroll-away gesture in this update.

func ShowHelpDialog

func ShowHelpDialog(t *Terminal) error

ShowHelpDialog draws a bordered help dialog and waits for Esc or 'q'.

func SlashSinkFor

func SlashSinkFor(term *Terminal) slashSink

SlashSinkFor returns the active --json sink if one is set, else the normal terminal-writing sink (nil-safe - see terminalSlashSink).

func SnapshotWorktreeDialogBinding

func SnapshotWorktreeDialogBinding(store *storage.SQLite, principal contextstate.Principal, worktree vcs.WorktreeInfo) cliworktree.WorktreeDialogBinding

SnapshotWorktreeDialogBinding is snapshotWorktreeDialogBinding, exported for internal/legacytui.

func StripANSI

func StripANSI(s string) string

StripANSI removes ANSI escape sequences from a string. Exported: relocated from internal/legacytui/bubble_leftrail.go, which is also called by three other internal/legacytui files (overlay.go, tui_selection.go, clipboard.go) that now reach it as StripANSI.

func SummarizeToolDetail

func SummarizeToolDetail(name, detail, result string) string

SummarizeToolDetail is summarizeToolDetail, exported for internal/legacytui.

func SummaryDisabledReason

func SummaryDisabledReason(sess *chat.Session, res *config.Resolved) string

SummaryDisabledReason names the first unmet condition keeping compaction structural-only, or "" when summarization is wired. A workspace that has not configured it gets an instant /compact that makes no LLM call, which is correct but indistinguishable from a broken summarizer: the operator sees a compaction succeed while the summary they expected never runs. The false return stays a policy state rather than an error; this only makes the state legible.

func SwitchModelCommand

func SwitchModelCommand(sess *chat.Session, res *config.Resolved, providerName, model string) (reasoning.Level, error)

SwitchModelCommand is cliagents.SwitchModelCommand, exported for internal/legacytui.

func TUIHelpContentFor

func TUIHelpContentFor(registry *skills.Registry) []helpSection

TUIHelpContentFor builds the /help dialog content for a skills registry. Shared with internal/legacytui's dialog TUI.

func ToolBatchStatusDetail

func ToolBatchStatusDetail(starts []BridgeToolEvt) string

ToolBatchStatusDetail is the expandable body for a multi-tool wave: first line is the one-line summary; following lines list each tool verb. Single-tool waves return the same string as toolBatchStatusLine (no extra rows).

func ToolIconForName

func ToolIconForName(name string) string

ToolIconForName picks the typed action glyph for a tool: ⚙ tool, ◆ agent. Single-width text only - emoji misalign columns (see action.go).

func ToolResultFailed

func ToolResultFailed(body string) bool

ToolResultFailed implements tool result failed.

func ToolStatusLine

func ToolStatusLine(name, detail string) string

ToolStatusLine returns a short human status for a tool start. Example: "Reading internal/foo.go…", "Searching for auth…". Never invents assistant speech; never leaks secrets from detail.

func ToolWaveCounts

func ToolWaveCounts(rows []ToolRow) (open, done, total int)

ToolWaveCounts returns open/done/total for live toolRows (excludes banners).

func TruncatePreviewUTF8

func TruncatePreviewUTF8(s string, maxBytes int) string

TruncatePreviewUTF8 cuts s to at most maxBytes bytes, backing off until the cut point lands on a valid UTF-8 boundary. Shared by TUI preview text and tool-error name formatting.

func TruncateToWidth

func TruncateToWidth(s string, maxW int) string

TruncateToWidth truncates s to at most maxW display columns, grapheme aware. Shared with internal/legacytui's chrome and dialog renderers.

func TuiHelpCommands

func TuiHelpCommands() []helpSection

TuiHelpCommands is tuiHelpCommands, exported for internal/legacytui.

func ValidateKeyRegistry

func ValidateKeyRegistry(rs []binding) []error

ValidateKeyRegistry is validateKeyRegistry, exported for internal/legacytui.

func ValidateWorkspaceRestart

func ValidateWorkspaceRestart(restart workspaceRestartError, invocation ChatInvocation) error

ValidateWorkspaceRestart is validateWorkspaceRestart, exported for internal/legacytui.

func VisibleWidth

func VisibleWidth(s string) int

VisibleWidth returns the visible (display) width of a string, ignoring ANSI escape sequences (which are zero-width). Multi-byte CJK chars count as 2, everything else as 1.

func VisualLineCount

func VisualLineCount(lines []string) int

VisualLineCount returns how many viewport lines the given content slots occupy. Each string may itself contain newlines after markdown/wrap.

func WorkGroupCollapsedDefault

func WorkGroupCollapsedDefault(g WorkGroup, overrides map[string]bool) bool

WorkGroupCollapsedDefault returns whether a group should start collapsed.

func WorktreeMarkerPath

func WorktreeMarkerPath(root string) string

WorktreeMarkerPath is cliworktree.WorktreeMarkerPath, exported for internal/legacytui.

func WrapANSIv2

func WrapANSIv2(s string, maxWidth int) string

WrapANSIv2 wraps a string containing ANSI escape sequences to a maximum visible width. ANSI sequences are zero-width and preserved in the output. It breaks lines at word boundaries (spaces). If no space is found within maxWidth, the line is output as-is (no hard break of words).

func WrapDisplayRows

func WrapDisplayRows(lines []string, innerW int) []string

WrapDisplayRows converts semantic lines into the exact rows a pager renders. ansi.Cut is grapheme-aware and keeps ANSI sequences intact. Shared with dialog rendering in internal/clichat.

func WrapDisplayRowsWithSources

func WrapDisplayRowsWithSources(lines []string, innerW int) ([]string, []int)

WrapDisplayRowsWithSources is WrapDisplayRows, also returning each output row's source line index. WrapDisplayRows is the sole in-package caller; exported (rather than relocated to its one external caller) so both stay colocated with the wrapping logic they share.

func WriteAutosaveStatus

func WriteAutosaveStatus(sessionDir string, saveErr error)

WriteAutosaveStatus writes the result of the final SaveLast to a status file so the next session can report failures to the user.

func WriteWorktreeList

func WriteWorktreeList(stdout io.Writer, worktrees []vcs.WorktreeInfo, deleting []contextstate.WorktreeInstanceInfo)

WriteWorktreeList is cliworktree.WriteWorktreeList, exported for internal/legacytui.

func WriteWorktreeMarker

func WriteWorktreeMarker(root string, instance contextstate.WorktreeInstance) error

WriteWorktreeMarker is cliworktree.WriteWorktreeMarker, exported for internal/legacytui.

Types

type AgentBinding

type AgentBinding = cliagents.AgentBinding

Type aliases for types from internal/cliagents.

type AgentLoadResult

type AgentLoadResult = cliagents.AgentLoadResult

AgentLoadResult is re-exported from cliagents for legacy test files.

type AgentSessionState

type AgentSessionState = cliagents.AgentSessionState

AgentSessionState is re-exported from cliagents.

type AgentSkillScope

type AgentSkillScope = cliagents.AgentSkillScope

Type aliases for types from internal/cliagents.

func SkillScopeFromAgent

func SkillScopeFromAgent(selected *agents.ResolvedAgent) AgentSkillScope

SkillScopeFromAgent is cliagents.SkillScopeFromAgent, exported for internal/legacytui.

func SkillScopeFromAgentAndRegistry

func SkillScopeFromAgentAndRegistry(selected *agents.ResolvedAgent, reg *tools.Registry) AgentSkillScope

SkillScopeFromAgentAndRegistry is cliagents.SkillScopeFromAgentAndRegistry, exported for internal/legacytui.

type AgentSurface

type AgentSurface = cliagents.AgentSurface

AgentSurface is re-exported from cliagents for cross-package test use.

type Binding

type Binding = binding

binding is one declared key. help == "" hides the row from /help (the key still exists; it is an alias or an internal affordance).

Binding is the exported alias, for internal/legacytui's routing tests.

type BindingExport

type BindingExport = Binding

Binding is binding, exported for internal/legacytui.

type BridgeDrain

type BridgeDrain struct {
	Stream       string
	Tools        []BridgeToolEvt
	Done         bool
	DoneErr      error
	Thinking     string
	StepDetail   string
	StepDetailAt time.Time
	ResetStream  bool
	// Interim is user-visible assistant speech before/between tool batches
	// ("I'll search…"). Committed as ChatBlockAssistant, not thinking chrome.
	Interim string
	// CtxTokens/CtxTokensSet carry the provider-reported input-token count of
	// the step's own request (see PushCtxTokens) so the status bar can show
	// context growth mid-turn instead of only after the turn commits.
	CtxTokens    int
	CtxTokensSet bool
}

BridgeDrain is a one-shot snapshot of bridge UI state for the TUI update loop.

type BridgeToolEvt

type BridgeToolEvt struct {
	Start      bool
	ToolCallID string
	Name       string
	Detail     string
	Agent      string // producing subagent name ("" = the session's own tools)
	At         time.Time
}

BridgeToolEvt holds bridge tool evt state.

func RealToolStarts

func RealToolStarts(starts []BridgeToolEvt) []BridgeToolEvt

RealToolStarts filters a tool-event batch to non-banner Start events.

type BubbleRenderer

type BubbleRenderer interface {
	// RenderText converts raw message text into display-ready lines.
	// Each returned string may contain ANSI codes. Width is the content width
	// in cells (not including padding). Returns nil for empty/skipped content.
	RenderText(text string, width int) []string
}

BubbleRenderer is a pluggable strategy for rendering message text content. Implementations can wrap plain text, render markdown, syntax highlight, etc.

type BubbleStyle

type BubbleStyle struct {
	// Background is applied to every line of the bubble (solid bar).
	// The padding area gets this background color. Nil means no background.
	Background *lipgloss.Style

	// LabelStyle styles the optional timestamp/prefix label.
	// Nil when ShowTime is false or no label is needed.
	LabelStyle *lipgloss.Style

	// Foreground is applied to content text inside the bubble.
	// Nil means no foreground override (renderer ANSI passes through).
	Foreground *lipgloss.Style

	// Padding is the space around content that gets the Background color.
	// Only used when Background is non-nil.
	Padding Padding

	// LeftRail is optional 1-cell left chrome (glyph). Nil = pad spaces only.
	// Painted into the first left-pad cell on content lines (not a box border).
	LeftRail *LeftRail

	// ShowTime controls whether sentAt timestamp is rendered as a label.
	// nil means "use default" (true for UserBubble, false for AssistantBubble).
	ShowTime *bool
}

BubbleStyle configures visual appearance for a message bubble. All fields are optional; zero/nil values mean "use default / no style".

func (BubbleStyle) ContentWidth

func (s BubbleStyle) ContentWidth(totalWidth int) int

ContentWidth returns the width available for content after subtracting left + right padding from totalWidth. Minimum 8.

func (BubbleStyle) HasBackground

func (s BubbleStyle) HasBackground() bool

HasBackground reports whether a non-nil background style is set.

func (BubbleStyle) HasForeground

func (s BubbleStyle) HasForeground() bool

HasForeground reports whether a non-nil foreground style is set.

func (BubbleStyle) HasLabelStyle

func (s BubbleStyle) HasLabelStyle() bool

HasLabelStyle reports whether a non-nil label style is set.

type ChatBlock

type ChatBlock struct {
	ID         string
	TurnID     uint64
	Sequence   uint64
	Kind       ChatBlockKind
	Text       string
	ToolName   string
	ToolCallID string
	// AgentName attributes a tool block to the subagent that ran it
	// ("" = the session's own call). Feeds the ◆ badge and, later, the
	// per-agent turn ledger.
	AgentName string
	Collapsed bool
	// ScrollOffset is the scrolled position for windowed rendering
	// (e.g. thinking blocks). 0 = show the most recent lines.
	ScrollOffset int
	// SentAt is when the user sent this message (local wall clock).
	// Zero for non-user blocks or hydrated history without a timestamp.
	SentAt time.Time
	// Rendered preserves existing local UI formatting for compatibility-only
	// lines. Structured history and stream blocks leave it empty.
	Rendered string
	// Failed marks a tool block that ended in failure (from ToolRow.Failed).
	// Preferred over text heuristics for red rail chrome.
	Failed bool
	// Elapsed is the action's wall-clock duration (zero when unknown, e.g.
	// hydrated history). Shown on ledger rows.
	Elapsed time.Duration
}

func ApplyChatBlockEvent

func ApplyChatBlockEvent(blocks []ChatBlock, event ChatBlockEvent) []ChatBlock

func HydrateChatBlocks

func HydrateChatBlocks(messages []provider.Message) []ChatBlock

func HydrateChatBlocksForView

func HydrateChatBlocksForView(messages []provider.Message) []ChatBlock

HydrateChatBlocksForView hydrates provider messages into chat blocks and reconstructs turn-local empty-speech status chrome for display. Never write the result into Session.Messages.

func ReconstructEmptySpeechStatus

func ReconstructEmptySpeechStatus(blocks []ChatBlock) []ChatBlock

ReconstructEmptySpeechStatus is view-only: insert dim "→ …" status before tool waves that lack real interim assistant speech. Mirrors live Phase A chrome.

type ChatBlockEvent

type ChatBlockEvent struct {
	TurnID   uint64
	Sequence uint64
	BlockID  string
	Kind     ChatBlockKind
	Text     string
	ToolName string
}

type ChatBlockKind

type ChatBlockKind string
const (
	ChatBlockUser      ChatBlockKind = "user"
	ChatBlockAssistant ChatBlockKind = "assistant"
	ChatBlockTool      ChatBlockKind = "tool"
	ChatBlockThinking  ChatBlockKind = "thinking"
	ChatBlockSystem    ChatBlockKind = "system"
	ChatBlockDivider   ChatBlockKind = "turn_divider"
)

type ChatBlockRender

type ChatBlockRender struct {
	Lines  []string
	Ranges map[string][2]int
}

func RenderChatBlocks

func RenderChatBlocks(blocks []ChatBlock, model string, width int, thinkingExpandDefault ...bool) ChatBlockRender

func RenderChatBlocksView

func RenderChatBlocksView(blocks []ChatBlock, model string, width int, view RailView, thinkingExpandDefault ...bool) ChatBlockRender

RenderChatBlocksView adds live frame/liveness for rail animation.

func RenderChatBlocksWithWorkGroups

func RenderChatBlocksWithWorkGroups(blocks []ChatBlock, model string, width int, thinkingExpandDefault bool, collapsed map[string]bool) ChatBlockRender

RenderChatBlocksWithWorkGroups renders blocks with optional collapsible work groups.

func RenderChatBlocksWithWorkGroupsView

func RenderChatBlocksWithWorkGroupsView(blocks []ChatBlock, model string, width int, thinkingExpandDefault bool, collapsed map[string]bool, view RailView) ChatBlockRender

RenderChatBlocksWithWorkGroupsView renders with per-group scroll at zero offset (compatibility entry point).

func RenderChatBlocksWithWorkGroupsWindow

func RenderChatBlocksWithWorkGroupsWindow(blocks []ChatBlock, model string, width int, thinkingExpandDefault bool, collapsed map[string]bool, scroll map[string]int, view RailView) ChatBlockRender

RenderChatBlocksWithWorkGroupsWindow renders expanded groups as bounded scrollable windows. scroll maps a group key to its first visible member.

type ChatInvocation

type ChatInvocation = chatInvocation

ChatInvocation is chatInvocation, exported for internal/legacytui.

func NewChatInvocationRepositorySessionStorePath

func NewChatInvocationRepositorySessionStorePath(path string) ChatInvocation

NewChatInvocationRepositorySessionStorePath builds a ChatInvocation with only repositorySessionStorePath set, for internal/legacytui tests.

func NewChatInvocationWorkspacePath

func NewChatInvocationWorkspacePath(workspacePath string) ChatInvocation

NewChatInvocationWorkspacePath builds a ChatInvocation with only workspacePath set, for internal/legacytui tests that need one without a full CLI parse. chatInvocation's fields are unexported (chat_command.go), so a constructor is the only way to set one from outside the package.

type ChatRenderer

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

ChatRenderer formats conversation messages in a clean chat-app style.

func NewChatRenderer

func NewChatRenderer(out TerminalWriter, model string) *ChatRenderer

NewChatRenderer creates a renderer bound to a terminal writer.

func (*ChatRenderer) DimHeader

func (r *ChatRenderer) DimHeader(label string)

DimHeader prints a dim divider with a label.

func (*ChatRenderer) PrintAssistantHeader

func (r *ChatRenderer) PrintAssistantHeader()

PrintAssistantHeader prints a divider before assistant output.

func (*ChatRenderer) PrintDim

func (r *ChatRenderer) PrintDim(format string, args ...any)

PrintDim prints a dim-styled line.

func (*ChatRenderer) PrintError

func (r *ChatRenderer) PrintError(err string)

PrintError prints an error message in red.

func (*ChatRenderer) PrintInfo

func (r *ChatRenderer) PrintInfo(msg string)

PrintInfo prints an informational message.

func (*ChatRenderer) PrintInterim

func (r *ChatRenderer) PrintInterim(text string)

PrintInterim prints intermediate assistant speech before tools (classic REPL).

func (*ChatRenderer) PrintParallel

func (r *ChatRenderer) PrintParallel(detail string)

PrintParallel prints a parallel tool execution notice.

func (*ChatRenderer) PrintPrune

func (r *ChatRenderer) PrintPrune(detail string)

PrintPrune prints a context pruning notice.

func (*ChatRenderer) PrintStatusLine

func (r *ChatRenderer) PrintStatusLine(line string)

PrintStatusLine prints a Phase-A style empty-speech tool status ("→ Reading…").

func (*ChatRenderer) PrintStep

func (r *ChatRenderer) PrintStep(detail string)

PrintStep prints a step counter.

func (*ChatRenderer) PrintThinking

func (r *ChatRenderer) PrintThinking(text string)

PrintThinking prints model reasoning (chain of thought) before tools (classic REPL).

func (*ChatRenderer) PrintTokenEstimate

func (r *ChatRenderer) PrintTokenEstimate(count int)

PrintTokenEstimate prints the token estimate before a turn.

func (*ChatRenderer) PrintToolEnd

func (r *ChatRenderer) PrintToolEnd(name, detail string)

PrintToolEnd prints a tool result with elapsed time.

func (*ChatRenderer) PrintToolStart

func (r *ChatRenderer) PrintToolStart(name, detail string)

PrintToolStart prints a tool invocation with spinner glyph.

func (*ChatRenderer) PrintUser

func (r *ChatRenderer) PrintUser(text string)

PrintUser prints the user's message.

func (*ChatRenderer) RenderHistory

func (r *ChatRenderer) RenderHistory(messages []provider.Message)

RenderHistory prints session history with turn-aware formatting. Tool calls and results are shown compactly inline.

type ChunkPlan

type ChunkPlan = delivery.ChunkPlan

ChunkPlan is one entry of a decompose chunk-plan output (shared type).

type ContextDispatcherWiring

type ContextDispatcherWiring = cliagents.ContextDispatcherWiring

Type aliases for types from internal/cliagents.

func ContextDispatcherFor

func ContextDispatcherFor(sess *chat.Session, cfg config.SubagentConfig) ContextDispatcherWiring

ContextDispatcherFor is contextDispatcherFor, exported for internal/legacytui.

type DialogLayout

type DialogLayout struct {
	Rect Rect
	// InnerW / PageH are the inner content width/height, after frame padding.
	InnerW, PageH int
	// FrameCols / FrameRows are the frame's column/row padding.
	FrameCols, FrameRows int
	// contains filtered or unexported fields
}

DialogLayout is the resolved geometry a dialog renders into: outer Rect, inner content dimensions, and frame padding. Shared with dialog construction and rendering in internal/clichat.

func MakeDialogLayout

func MakeDialogLayout(termW, termH int, p DialogPrefs, measure func(innerW int) (contentW, contentH int)) DialogLayout

MakeDialogLayout resolves a dialog's geometry from terminal size and preferences, measuring content via measure. Shared with dialog construction in internal/clichat.

type DialogPrefs

type DialogPrefs struct {
	// PreferredW is the preferred width in cells (0 = unset).
	PreferredW, PreferredH int
	// PreferredWPct is the preferred width as a percentage of the terminal.
	// PreferredHPct is the preferred height as a percentage of the terminal.
	PreferredWPct, PreferredHPct int
	// MinW / MinH are the minimum width/height in cells.
	MinW, MinH int

	// FrameCols / FrameRows are the frame's column/row padding.
	FrameCols, FrameRows int

	// Pager shows a page-position footer when true.
	Pager bool
	// contains filtered or unexported fields
}

DialogPrefs configures dialog sizing (preferred/min/max dimensions, frame padding, pager footer). Shared with dialog construction in internal/clichat.

type GitMergeChecker

type GitMergeChecker = gitMergeChecker

GitMergeChecker is the exported alias for the gitMergeChecker type, for seam wiring.

type GroupMember

type GroupMember struct {
	InGroup   bool
	ToolIndex int // 0-based among tools; -1 if not a tool
	ToolCount int
	GroupKey  string
	IsHeader  bool
}

GroupMember describes a block's place inside a multi-tool work group.

type HookSessionState

type HookSessionState interface {
	// RunnableGroups returns the hook groups that tool calls may run.
	RunnableGroups() []hooks.Group
	// NoteRunWarnings records bounded diagnostics from executed hooks.
	NoteRunWarnings(warnings []string)
}

HookSessionState is the read surface of the cli hook session that this package needs: runnable hook groups plus a warning sink.

type InputBuffer

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

InputBuffer is a line editor with cursor movement and history. It manages a buffer of runes and renders itself to a terminal line, supporting multi-line wrapping when content exceeds terminal width.

func NewInputBuffer

func NewInputBuffer(prompt string) *InputBuffer

NewInputBuffer creates a new input buffer with a given prompt string.

func (*InputBuffer) Backspace

func (ib *InputBuffer) Backspace()

Backspace removes the rune before the cursor.

func (*InputBuffer) ClearHistory

func (ib *InputBuffer) ClearHistory()

ClearHistory removes all history entries.

func (*InputBuffer) Commit

func (ib *InputBuffer) Commit() string

Commit saves the current buffer to history and returns the string. Returns empty string for empty input (not saved to history). Resets the visual line tracking.

func (*InputBuffer) ContentWidth

func (ib *InputBuffer) ContentWidth() int

ContentWidth returns the total visual column width of the visible line.

func (*InputBuffer) CursorCol

func (ib *InputBuffer) CursorCol() int

CursorCol returns the 0-based column where the cursor should be within the visible line, accounting for wide characters.

func (*InputBuffer) Delete

func (ib *InputBuffer) Delete()

Delete removes the rune at the cursor.

func (*InputBuffer) Insert

func (ib *InputBuffer) Insert(r rune)

Insert adds a rune at the cursor position.

func (*InputBuffer) KillLine

func (ib *InputBuffer) KillLine()

KillLine clears the entire buffer.

func (*InputBuffer) KillToEnd

func (ib *InputBuffer) KillToEnd()

KillToEnd removes from cursor to end of buffer.

func (*InputBuffer) KillWord

func (ib *InputBuffer) KillWord()

KillWord removes the word before the cursor.

func (*InputBuffer) Len

func (ib *InputBuffer) Len() int

Len returns the length of the buffer in runes.

func (*InputBuffer) MoveEnd

func (ib *InputBuffer) MoveEnd()

MoveEnd moves cursor to the end.

func (*InputBuffer) MoveHome

func (ib *InputBuffer) MoveHome()

MoveHome moves cursor to the beginning.

func (*InputBuffer) MoveLeft

func (ib *InputBuffer) MoveLeft()

MoveLeft moves cursor left by one rune.

func (*InputBuffer) MoveRight

func (ib *InputBuffer) MoveRight()

MoveRight moves cursor right by one rune.

func (*InputBuffer) NextHistory

func (ib *InputBuffer) NextHistory()

NextHistory loads the next history entry.

func (*InputBuffer) Pos

func (ib *InputBuffer) Pos() int

Pos returns the current cursor position.

func (*InputBuffer) PrevHistory

func (ib *InputBuffer) PrevHistory()

PrevHistory loads the previous history entry.

func (*InputBuffer) Prompt

func (ib *InputBuffer) Prompt() string

Prompt returns the current prompt string.

func (*InputBuffer) Render

func (ib *InputBuffer) Render(termWidth int) string

Render produces ANSI escape sequences to render the input line correctly, supporting multi-line wrapping when content exceeds terminal width. It:

  1. Moves cursor to the first visual line of the input area
  2. Clears all previously occupied lines
  3. Writes the prompt + buffer content (letting terminal wrap)
  4. Repositions cursor to the correct visual line and column

termWidth is the terminal width in columns. If termWidth <= 0, it defaults to 80 (standard terminal fallback).

func (*InputBuffer) RenderInPlace

func (ib *InputBuffer) RenderInPlace(t *Terminal)

RenderInPlace is a convenience wrapper that renders to a terminal's stderr. It handles the common case of "render and write" in one call.

func (*InputBuffer) SetPrompt

func (ib *InputBuffer) SetPrompt(p string)

SetPrompt updates the prompt string.

func (*InputBuffer) SetString

func (ib *InputBuffer) SetString(s string)

SetString replaces the buffer content and moves cursor to end.

func (*InputBuffer) String

func (ib *InputBuffer) String() string

String returns the current buffer content.

func (*InputBuffer) VisibleLine

func (ib *InputBuffer) VisibleLine() string

VisibleLine returns the full visible content (prompt + buffer).

type JSONSlashSink

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

JSONSlashSink adapts slashSink to --json line-mode: /model and /effort results (and every other slash command's plain informational output) become structured NDJSON events instead of vanishing, which is what happens today when terminalSlashSink wraps a nil *Terminal - see that type's Info/Error methods, which are a no-op body guarded on `s.t != nil`.

func (*JSONSlashSink) EffortChanged

func (s *JSONSlashSink) EffortChanged(model string, level reasoning.Level)

EffortChanged reports a successful /effort switch.

func (*JSONSlashSink) Error

func (s *JSONSlashSink) Error(msg string)

Error emits a slash command's hard-error output as "slash_error".

func (*JSONSlashSink) Info

func (s *JSONSlashSink) Info(msg string)

Info emits any slash command's informational output as a generic "slash_info" event - the fallback for every command that has no typed shape below (a status query, "current model=...", a soft failure like "model not available", ...). Still visible on the wire, even without a dedicated field for a caller to key off.

func (*JSONSlashSink) ModelChanged

func (s *JSONSlashSink) ModelChanged(provider, model string, discarded reasoning.Level)

ModelChanged reports a successful /model switch. discarded is the previously-active reasoning effort the switch dropped, if any (mirrors effortDiscardedSuffix's prose equivalent) - the zero value means none.

type KeyScope

type KeyScope = keyScope

keyScope is where a binding applies.

KeyScope is the exported alias, for internal/legacytui's routing tests.

type LeftRail

type LeftRail struct {
	Width   int
	Glyph   string
	Char    string
	Color   string
	Bold    bool
	Mode    RailMode // header (default production), tree, full
	Animate bool
	Frame   int
	ASCII   bool
	Plain   bool
}

LeftRail is a left-edge indicator. Prefer header-only thin gray. Color encodes lifecycle, never tool name (read_file vs run_command).

func RailAssistant

func RailAssistant() LeftRail

func RailError

func RailError() LeftRail

func RailThinking

func RailThinking() LeftRail

func RailTools

func RailTools() LeftRail

func RailUser

func RailUser() LeftRail

Presets - neutral default; semantic only on error/running.

func ResolveBlockRail

func ResolveBlockRail(block ChatBlock, mem GroupMember, opts RailOpts, view RailView) LeftRail

ResolveBlockRail resolves the left-rail glyph and mode for a chat block. Shared with internal/legacytui's bubble-mode transcript layout.

type MarkdownWriter

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

MarkdownWriter wraps an io.Writer and converts markdown to ANSI. Streaming: complete lines are formatted as they arrive. Table rows are buffered until a non-table line or Flush so columns can align.

func NewMarkdownWriter

func NewMarkdownWriter(w io.Writer) *MarkdownWriter

NewMarkdownWriter creates a markdown-to-ANSI streaming converter.

func (*MarkdownWriter) Flush

func (mw *MarkdownWriter) Flush() error

Flush writes remaining buffered content (partial line + open table block).

func (*MarkdownWriter) SetWidth

func (mw *MarkdownWriter) SetWidth(w int)

SetWidth sets wrap/hr width hint.

func (*MarkdownWriter) Write

func (mw *MarkdownWriter) Write(p []byte) (int, error)

Write implements io.Writer.

type MergeChecker

type MergeChecker interface {
	Merged(ctx context.Context, headBranch, baseBranch, headCommit, repoSlug string, wasPushed bool) (bool, error)
}

MergeChecker reports whether a chunk's PR is merged from durable git state and, when necessary, the remote PR state. Tests inject a fake.

wasPushed is the driver's durable pushed evidence for the run (a delivery record that reached pushed/succeeded with a commit SHA). Without it a missing remote ref only means "never pushed", not "merged".

type MessageBubble

type MessageBubble struct {
	// Style configures visual appearance.
	Style BubbleStyle

	// Renderer is the pluggable text rendering strategy.
	Renderer BubbleRenderer
}

MessageBubble is a shared, reusable, customizable component for rendering chat messages. Both user and assistant messages use this with different style configurations and renderers.

func (*MessageBubble) MergeStyle

func (b *MessageBubble) MergeStyle(s BubbleStyle) *MessageBubble

MergeStyle returns a copy of the bubble with s merged into the existing style. This is the mixin/composition pattern: non-nil pointer fields from s override existing values.

bubble := UserBubble.MergeStyle(BubbleStyle{Padding: Padding{Left: 4}})

func (*MessageBubble) Render

func (b *MessageBubble) Render(text string, width int, sentAt time.Time) []string

Render produces display-ready lines for the given message text. Width is the total terminal width. SentAt controls the optional timestamp label (zero time = no label).

Layout with padding (bg fills pad cells when Background is set):

[bg]  message text…          ← body first
[bg]  continuation…
[bg]            [ 10:30PM ]  ← dim trailing meta (no seconds)

func (*MessageBubble) WithRenderer

func (b *MessageBubble) WithRenderer(r BubbleRenderer) *MessageBubble

WithRenderer returns a copy of the bubble with a custom renderer plugged in. This is the plugin/extensibility entry point for new rendering strategies.

type MyRenderer struct{}
bubble := UserBubble.WithRenderer(&MyRenderer{})

func (*MessageBubble) WithStyle

func (b *MessageBubble) WithStyle(s BubbleStyle) *MessageBubble

WithStyle returns a copy of the bubble with non-nil pointer fields from s applied. Non-zero scalar fields override existing values.

myBubble := UserBubble.WithStyle(BubbleStyle{
    Padding: Padding{Top: 1, Right: 4, Bottom: 1, Left: 4},
})

type Padding

type Padding struct {
	Top    int
	Right  int
	Bottom int
	Left   int
}

Padding describes space around content inside the bubble background. The background color extends into the padding area.

type REPLRuntime

type REPLRuntime = replRuntime

REPLRuntime is replRuntime, exported for internal/legacytui.

type RailMode

type RailMode int

RailMode controls vertical paint of the accent.

const (
	RailModeOff RailMode = iota
	RailModeHeader
	RailModeTree
	RailModeFull
)

type RailOpts

type RailOpts struct {
	ASCII bool
	Color bool
}

RailOpts controls environment-sensitive chrome.

func ChromeRenderOpts

func ChromeRenderOpts() RailOpts

ChromeRenderOpts mirrors tool render env (NO_COLOR, TERM=dumb). Mirrors internal/legacytui's terminalToolRenderOptions (private to that package).

type RailRole

type RailRole int

RailRole is structural place in the timeline / work group.

const (
	RailRoleNone RailRole = iota
	RailRoleGroupHeader
	RailRoleFirstStep
	RailRoleStep
	RailRoleStandalone
	RailRoleThinking
	RailRoleAssistant
)

type RailState

type RailState int

RailState is lifecycle color (never tool identity).

const (
	RailStateNeutral RailState = iota
	RailStateRunning
	RailStateFailed
	RailStateParallelLive
)

type RailView

type RailView struct {
	Frame int
	Live  bool
}

RailView is per-frame view context (piggybacks logoFrame).

type ReconcileAction

type ReconcileAction struct {
	TaskID        string
	Action        string
	NewStatus     string // durable status to transition to ("" = none)
	CurrentStatus string // task status before this action (set by reconcileStack)
	Attempts      int    // attempt count to record on reopen
	Note          string
}

ReconcileAction is one idempotent recovery decision for a chunk task.

type Rect

type Rect struct {
	X, Y int
	W, H int
}

Rect is a terminal-cell rectangle. Coordinates are always relative to the raw terminal canvas; logical minimums never enlarge the canvas. Shared with the classic-mode overlay/panel renderers in internal/clichat.

func DialogRectFor

func DialogRectFor(termW, termH int, p DialogPrefs, contentW, contentH int) Rect

DialogRectFor is dialogRect, exported for internal/legacytui.

type RunInfo

type RunInfo struct {
	Present bool
	Status  string
	// ClaimStale reports whether an active-status run's execution claim is
	// absent or older than its lease (F7 liveness probe: GetRunClaim /
	// DefaultClaimLease). The caller derives it; reconcileTask stays a pure
	// function over already-read state.
	ClaimStale bool
	// NoDiff reports CONFIRMED no_diff delivery evidence for a succeeded run
	// (chunkRunNoDiff): an actual no_diff delivery record, never inferred
	// from the mere absence of pushed evidence. The caller derives it;
	// reconcileTask stays a pure function over already-read state. A
	// read failure on the delivery records must resolve to false here (fail
	// closed), same rule as ClaimStale.
	NoDiff bool
}

RunInfo is the driver's read of one chunk run's ledger state.

type SessionDispatcherOpts

type SessionDispatcherOpts = cliagents.SessionDispatcherOpts

Type aliases for types from internal/cliagents.

type SessionRouting

type SessionRouting = sessionRouting

SessionRouting is sessionRouting, exported for internal/legacytui.

type SlashCommand

type SlashCommand struct {
	Name        string
	Aliases     []string
	Description string
	ArgsHint    string
	Surface     slashSurface
	Kind        slashKind
	AutoExecute bool
	Origin      skills.Origin
	SkillName   string
}

SlashCommand is the single source of truth for slash command discovery. SkillName is the registry lookup key; Name is the user-facing slash token.

func FindSlashCommand

func FindSlashCommand(token string, surface slashSurface, registry *skills.Registry) (SlashCommand, bool)

FindSlashCommand implements find slash command.

func SlashCommands

func SlashCommands(surface slashSurface, registry *skills.Registry) []SlashCommand

SlashCommands implements slash commands.

type StreamBridge

type StreamBridge struct {

	// Notify signals the TUI update loop that drainable state changed. Shared
	// with internal/legacytui's event loop.
	Notify chan struct{}
	// contains filtered or unexported fields
}

StreamBridge - agent goroutine → UI (coalesced, no goroutine storms)

func NewStreamBridge

func NewStreamBridge() *StreamBridge

NewStreamBridge constructs a StreamBridge ready to receive drained events. Shared with internal/legacytui's TUI startup.

func (*StreamBridge) ActiveTools

func (b *StreamBridge) ActiveTools() int

ActiveTools returns outstanding tool count (for tests).

func (*StreamBridge) Close

func (b *StreamBridge) Close()

func (*StreamBridge) Drain

func (b *StreamBridge) Drain() BridgeDrain

Drain returns and clears pending UI state.

func (*StreamBridge) FenceTurn

func (b *StreamBridge) FenceTurn(id uint64)

FenceTurn marks the bridge as accepting events only for the given turn. It clears the done flag so new events can flow for this turn.

func (*StreamBridge) Finish

func (b *StreamBridge) Finish(err error)

func (*StreamBridge) Pending

func (b *StreamBridge) Pending() bool

Pending reports whether the bridge still holds undrained UI content (stream text, tool events, thinking, interim speech, step detail, an unconsumed RevokeStream directive, or a Finish that Drain has not seen). Unlike Drain, it is non-consuming: the state is left intact so the next pollCmd tick can still deliver it and finish via Done. An empty or nil bridge counts as drained.

func (*StreamBridge) PushCompletedBanner

func (b *StreamBridge) PushCompletedBanner(name, detail string)

PushCompletedBanner records a one-shot visibility row (parallel/prune) that is immediately completed. Never leaves an open active-tool slot.

func (*StreamBridge) PushCtxTokens

func (b *StreamBridge) PushCtxTokens(tokens int)

PushCtxTokens stores the input-token count of the step's own provider request, so the status bar can show context growth as it happens instead of only after the turn commits its history to the session.

func (*StreamBridge) PushInterim

func (b *StreamBridge) PushInterim(text string)

PushInterim queues user-visible assistant speech for the next Drain (intermediate bubbles: "I'll look that up…", "Next I'll…"). Ghost/noise text is dropped here so the bus path cannot force empty bubbles.

func (*StreamBridge) PushStep

func (b *StreamBridge) PushStep(detail string)

PushStep stores a heartbeat/step event detail for UI display.

func (*StreamBridge) PushSubagentTool

func (b *StreamBridge) PushSubagentTool(start bool, toolCallID, agentName, name, detail string)

PushSubagentTool records a nested tool event attributed to a subagent, so the UI can badge the row with the agent that ran it.

func (*StreamBridge) PushThinking

func (b *StreamBridge) PushThinking(text string)

PushThinking appends model reasoning text (dim chrome, not speech bubbles).

Reasoning is accepted at any point in a turn. It used to be dropped unless a tool was already running (activeTools > 0), which discarded exactly the case that matters most: the chain of thought a model streams BEFORE it decides to call anything.

func (*StreamBridge) PushTool

func (b *StreamBridge) PushTool(start bool, name, detail string)

func (*StreamBridge) PushToolWithID

func (b *StreamBridge) PushToolWithID(start bool, toolCallID, name, detail string)

func (*StreamBridge) RevokeStream

func (b *StreamBridge) RevokeStream() string

RevokeStream clears optimistic final-stream text when tool_calls arrive. Returns the revoked text for callers; does not treat it as thinking - the agent re-emits EventAssistant so the TUI commits a durable speech bubble.

func (*StreamBridge) SetTurnID

func (b *StreamBridge) SetTurnID(id uint64)

SetTurnID sets the current turn fence ID without changing the done flag.

func (*StreamBridge) Write

func (b *StreamBridge) Write(p []byte) (int, error)

type SubagentRun

type SubagentRun struct {
	TaskID     string
	Name       string
	Depth      int
	Started    time.Time
	LastSeen   time.Time
	LastTool   string // most recent nested tool name
	LastDetail string // most recent detail/heartbeat text
	ToolsOpen  int
	ToolsDone  int
	// Done is set by the run-level terminal event only. It is never inferred
	// from ToolsOpen == 0: an agent between two tool calls has no open tools
	// and is still running.
	Done bool
}

SubagentRun is the aggregated view of one subagent's activity.

type SubagentTracker

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

SubagentTracker holds subagent tracker state.

func NewSubagentTracker

func NewSubagentTracker() *SubagentTracker

NewSubagentTracker implements new subagent tracker.

func (*SubagentTracker) Active

func (t *SubagentTracker) Active() int

Active counts runs that have not finished. It is the "n running" figure in the fleet box header and must agree with the rows rendered beneath it.

func (*SubagentTracker) ActiveRows

func (t *SubagentTracker) ActiveRows() []SubagentRun

ActiveRows returns the runs that have not finished, in stable first-seen order. This is what the "now" panel and the fleet box render: a section named for what is happening right now must not carry finished work.

func (*SubagentTracker) Apply

func (t *SubagentTracker) Apply(ev events.Event, now time.Time) bool

Apply folds one bus event into the tracker. Only events attributed to an agent (AgentTask set) register; anything else is ignored rather than misfiled. Reports whether state changed.

func (*SubagentTracker) Reset

func (t *SubagentTracker) Reset()

Reset clears all runs (called when a new turn starts).

func (*SubagentTracker) Rows

func (t *SubagentTracker) Rows() []SubagentRun

Rows returns every run of the turn, finished ones included, in stable first-seen order. This is turn history - the ctrl+g fleet detail and the diagnostics dialog want it. Live chrome wants ActiveRows.

type Terminal

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

Terminal wraps raw terminal mode for interactive input. Provides cursor management, screen manipulation, and key reading.

func NewTerminal

func NewTerminal() (*Terminal, error)

NewTerminal opens the terminal, enters raw mode, and reports size. Must be closed with Close() when done.

func NewTestTerminal

func NewTestTerminal(w io.Writer) *Terminal

NewTestTerminal builds a Terminal that writes to w, for tests that need a Terminal without opening a real tty. Exported for internal/legacytui.

func (*Terminal) ClearLine

func (t *Terminal) ClearLine()

ClearLine clears the current line from cursor to end.

func (*Terminal) ClearLines

func (t *Terminal) ClearLines(n int)

ClearLines clears n lines upward from current cursor position.

func (*Terminal) Close

func (t *Terminal) Close() error

Close restores the terminal to cooked mode and disables bracketed paste.

func (*Terminal) HideCursor

func (t *Terminal) HideCursor()

HideCursor hides the cursor.

func (*Terminal) MoveDown

func (t *Terminal) MoveDown(n int)

MoveDown moves cursor down n rows.

func (*Terminal) MoveTo

func (t *Terminal) MoveTo(row, col int)

MoveTo moves cursor to (row, col) - 1-based.

func (*Terminal) MoveUp

func (t *Terminal) MoveUp(n int)

MoveUp moves cursor up n rows.

func (*Terminal) ReadKey

func (t *Terminal) ReadKey() (string, error)

ReadKey reads a single keypress in raw mode. Returns the key as a string (for multi-byte sequences like arrows) or the rune as a string (for regular keys).

func (*Terminal) RestoreScreen

func (t *Terminal) RestoreScreen()

RestoreScreen restores the saved screen contents.

func (*Terminal) SaveScreen

func (t *Terminal) SaveScreen()

SaveScreen saves the current screen contents.

func (*Terminal) ShowCursor

func (t *Terminal) ShowCursor()

ShowCursor shows the cursor.

func (*Terminal) Size

func (t *Terminal) Size() (width, height int)

Size returns the terminal width and height.

func (*Terminal) Write

func (t *Terminal) Write(p []byte) (n int, err error)

Write implements io.Writer for Terminal, delegating to the underlying stderr writer.

func (*Terminal) WriteString

func (t *Terminal) WriteString(s string)

WriteString writes to the terminal output (stderr).

func (*Terminal) Writef

func (t *Terminal) Writef(format string, args ...any)

Writef writes a formatted string to the terminal.

type TerminalWriter

type TerminalWriter interface {
	Write(p []byte) (n int, err error)
	WriteString(s string)
	Size() (width, height int)
}

TerminalWriter is the minimal interface ChatRenderer needs.

type ToolRenderItem

type ToolRenderItem struct {
	Name, Detail, Result string
	Done, Failed         bool
}

ToolRenderItem is the bounded, presentation-neutral view shared by live and history renderers.

func NewToolRenderItem

func NewToolRenderItem(name, detail, result string, done, failed bool) ToolRenderItem

NewToolRenderItem builds a bounded, presentation-neutral tool render item. Shared by the live status panel (internal/legacytui) and the classic-mode renderer.

func (ToolRenderItem) StatusIcon

func (t ToolRenderItem) StatusIcon(ascii bool) string

StatusIcon renders the item's lifecycle glyph (queued/done/failed). Exported: internal/legacytui's formatToolLine/formatToolPanelLine call it on a ToolRenderItem value returned from this package.

func (ToolRenderItem) Summary

func (t ToolRenderItem) Summary(max int) string

Summary renders the item's bounded one-line preview text. Exported: see StatusIcon.

type ToolRow

type ToolRow struct {
	ToolCallID string
	Name       string
	// Agent is the subagent that ran this tool ("" = the session's own call).
	Agent string
	// Detail is argument preview (JSON or redacted input). Never lifecycle text.
	Detail string
	// Status is queued|running|completed|failed (operator-facing lifecycle).
	Status   string
	Result   string // output result (may be large)
	Start    time.Time
	End      time.Time
	Done     bool
	Failed   bool
	Expanded bool // show full I/O preview
}

ToolRow is a live/completed tool invocation for the status panel. Relocated from internal/legacytui/toolui.go: needed unqualified there (its own rendering) and here (tool-wave counting). internal/legacytui keeps a type alias so its own call sites are unchanged.

type ToolTierPlan

type ToolTierPlan = cliagents.ToolTierPlan

Type aliases for types from internal/cliagents.

type TuiFocus

type TuiFocus uint8

TuiFocus identifies the pane that owns keyboard navigation in chat mode.

const (
	FocusComposer TuiFocus = iota
	FocusScrollback
	FocusSidebar
	FocusWorkflowsSidebar
)

func RouteFocusKey

func RouteFocusKey(current TuiFocus, key string) (TuiFocus, bool)

RouteFocusKey returns the new focus and whether the key was consumed. Printable input from another pane returns focus to the composer but is not consumed.

func (TuiFocus) String

func (f TuiFocus) String() string

type WorkGroup

type WorkGroup struct {
	Start, End int
	ToolCount  int
	AgentCount int    // agent-control actions (◆) among the tools
	FailCount  int    // failed actions - always surfaced on the header
	Key        string // stable id for collapse state
}

WorkGroup is a half-open index range [Start,End) of thinking/status/tool blocks.

func FindWorkGroups

func FindWorkGroups(blocks []ChatBlock) []WorkGroup

FindWorkGroups returns contiguous work runs broken by user/assistant/divider/non-status system.

Source Files

Jump to

Keyboard shortcuts

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