Documentation
¶
Overview ¶
Package app is the v2 TUI's top-level tea.Model. It stays thin on purpose — focus stack, layout engine, and msg dispatch live here; every visual concern lives in a sibling component package.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
App is the v2 root model. M7 wires the focus stack (modal overlays: /config /model /compact) and the slash suggestion panel (non-modal, floats above the input when the user types "/"). Key routing precedence is now:
- top of focus stack (if it's modal) — exclusive consumer
- global keys (ctrl+c, esc, ctrl+o, scroll)
- slash panel (when visible) for Tab / Up / Down
- input textarea (history nav, paste, plain typing)
func (*App) Attach ¶
func (a *App) Attach(c ui.Controller)
Attach hands the model the agent controller and re-renders the banner. Also primes the status bar with model + agent id and the initial context limit.
func (*App) Init ¶
Init returns the cursor blink + spinner tick so both animate from the first frame.
func (*App) SetProgram ¶
SetProgram lets the package-level UI hand the model the program reference. Used by the run goroutine to dispatch RunDoneMsg back to the bubbletea main loop.
func (*App) View ¶
View composes the rendered output. Vertical order (top → bottom), each layer collapses to zero height when its backing data is empty:
viewport / banner / transcript (scrollable area) todos panel (only when todos tracked) agents chip strip (only when subagents tracked) overlay panel (only when focus stack non-empty) slash suggestion (only when "/<x>" in input) input box (rounded border) hint (one-liner) status bar (HUD)
type FocusStack ¶
type FocusStack struct {
// contains filtered or unexported fields
}
FocusStack is the ordered modal stack. The topmost Focusable consumes key events; lower ones are visible but inert. Push on open; Pop on close. Designed to be small and side-effect-free — the App owns the lifecycle.
func (*FocusStack) Clear ¶
func (f *FocusStack) Clear()
Clear pops every overlay. Used during /clear and /model swaps to guarantee no stale UI clings to the next turn.
func (*FocusStack) Len ¶
func (f *FocusStack) Len() int
Len reports the stack depth — used by the App to decide whether to render an overlay slot at all.
func (*FocusStack) Pop ¶
func (f *FocusStack) Pop() Focusable
Pop removes and returns the top, or nil if empty.
func (*FocusStack) Push ¶
func (f *FocusStack) Push(x Focusable)
Push installs x as the new top. Nil is a no-op so callers don't need to nil-check before opening.
func (*FocusStack) Top ¶
func (f *FocusStack) Top() Focusable
Top returns the topmost Focusable without popping, or nil when the stack is empty.
type Focusable ¶
type Focusable interface {
// Update receives one tea.Msg while this overlay sits on top of
// the stack. It returns:
// - close: true when the App should pop this overlay (Esc,
// Enter-on-confirm, programmatic dismissal)
// - cmd: any side-effect command the App should run next
// (textinput blink, controller.Compact dispatch, etc.)
Update(msg tea.Msg) (close bool, cmd tea.Cmd)
// View renders the overlay's body. The App is responsible for
// positioning it within the layout; the overlay just produces
// the content.
View(width int, th *theme.Theme) string
// Key returns a short identifier ("config"|"model"|"compact"|
// "yank"|"search"|"permit"). Used for debugging and for
// stack-state diagnostics; the App doesn't dispatch on it.
Key() string
// Modal reports whether this overlay consumes all key events.
// Always true for v1-style picker panels; future non-modal
// overlays (a transient toast) can return false.
Modal() bool
// Hint is the contextual hint shown above the status bar while
// this overlay is on top. Empty string falls through to the
// state-default hint.
Hint() string
}
Focusable is the contract every modal overlay implements. The App pushes one onto FocusStack when the user opens a panel; pops when Update reports close==true.
The interface is small on purpose: each overlay owns its state, renders its body, and tells the App when it's done. The App drives the stack but knows nothing about a given overlay's internals.
Hint contributes to the status-bar contextual hint line — when an overlay is on top of the stack, its Hint() wins over the RunState-default hint (see components/status.ResolveHint).