ui

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: May 18, 2026 License: MIT Imports: 45 Imported by: 0

Documentation

Overview

Package ui contains the bubbletea TUI shell for Hygge.

Layering

internal/ui may import: internal/agent, internal/bus, internal/cost, internal/session, internal/ui/theme, and stdlib. It must NOT import anything in cmd/. Task 13's main.go wraps the App in a tea.Program.

The App is a Model, not a Program

New(opts) returns an *App that implements tea.Model (Init/Update/View). The CLI is responsible for constructing a *tea.Program around it. This keeps internal/ui drivable from tests without touching a TTY.

Bus bridge

The App owns a single goroutine that fans every event we care about from the typed bus subscriptions into one `chan any`. Init returns a tea.Cmd that reads one event off that channel and wraps it in a [busDelivery] Msg; Update re-issues the same Cmd on every delivery, creating an infinite read-loop entirely inside the bubbletea Cmd machinery. No program-side Send is needed.

Close cancels the bridge context so the goroutine exits and tests can avoid leaks.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GenerateSystemPrompt added in v0.7.0

func GenerateSystemPrompt(ctx context.Context, prv provider.Provider, modelName, idea string) (string, error)

GenerateSystemPrompt uses the given provider to generate a system prompt for a mode/subagent described by idea. Returns the generated text or an error. This is a standalone helper used by run.go's GeneratePrompt callback.

Types

type App

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

App is the root bubbletea model.

func New

func New(opts AppOptions) (*App, error)

New constructs the App. Validates required fields and starts the bus bridge goroutine.

func (*App) ActiveMode

func (a *App) ActiveMode() *config.ModeConfig

ActiveMode returns the currently active mode config. Always returns non-nil because Modes is guaranteed to have at least one entry after config loading.

func (*App) ActiveModeName

func (a *App) ActiveModeName() string

ActiveModeName returns the display name of the current mode.

func (*App) Close

func (a *App) Close() error

Close releases the bridge goroutine and any in-flight Send. Idempotent. Tests call this in t.Cleanup.

func (*App) Draw

func (a *App) Draw(scr uv.Screen, area uv.Rectangle) *tea.Cursor

Draw renders the entire UI to a screen buffer. The left column (chat, chrome, editor, footer) is composed as a single content flow, then the sidebar and overlays are drawn into their own regions.

func (*App) Handle

func (a *App) Handle(ev any) tea.Cmd

Handle delivers a single bus event synchronously, exactly as if it had arrived via the listener. Used by tests to drive the App without goroutines. Returns the same tea.Cmd Update would.

func (*App) Init

func (a *App) Init() tea.Cmd

Init is the bubbletea Model entry point. Starts the input focus, the spinner tick, and the bus listener.

func (*App) SetProgram

func (a *App) SetProgram(p *tea.Program)

SetProgram stores the tea.Program so that goroutines started by startSend can inject messages back into the bubbletea event loop via program.Send. Must be called before the first Update that triggers a send. The CLI calls it immediately after tea.NewProgram. Tests leave it unset; sendOutOfBand is a no-op when program is nil, so tests drive sendCompleted manually via app.Update(sendCompleted{...}).

func (*App) Update

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

Update is the bubbletea Update method.

func (*App) View

func (a *App) View() tea.View

View renders the App.

type AppOptions

type AppOptions struct {
	Bus     *bus.Bus
	Agent   *agent.Agent
	Store   session.Store
	Catalog *cost.Catalog
	Theme   *theme.Theme
	// StyleTheme selects the built-in color theme for the new styles system.
	StyleTheme string

	// Modes is the ordered list of agent modes the user can cycle through
	// with Tab. Each mode specifies a provider, model, and optional
	// reasoning/prompt. Guaranteed non-empty after config loading.
	Modes []config.ModeConfig
	// AuthConfiguredProviders lists providers with global auth configured
	// (env var or auth store), independent of the active profile.
	AuthConfiguredProviders []string
	SessionID               string // existing session to resume, or "" to create on first input
	ProjectDir              string
	ModelProvider           string // "anthropic" etc, for status bar display
	ModelName               string
	ProfileName             string
	Reasoning               provider.Reasoning
	Commands                *command.Registry // slash-command registry; nil disables slash routing
	Subagents               []MentionSubagent // sub-agent types selectable from @ mentions
	Now                     func() time.Time
	// ContextWindow is the model's maximum context size in tokens.  Used by
	// the compaction modal to display usage info.  0 means unknown.
	ContextWindow int64

	// Version is the application version string shown in persistent chrome (e.g. "v0.4").
	// Empty string hides the version.
	Version string

	// NerdFonts controls whether nerd-font glyphs are used in persistent chrome.
	// When true, the git-branch glyph (U+EAFC) is used; otherwise ":branch".
	// Default false; callers should set this from config.UI.NerdFonts.
	NerdFonts bool

	// HomeDir is the user's home directory, used for tilde-collapsing the
	// project path in persistent chrome. Empty → no collapse.
	HomeDir string

	// OnSessionCreated, if non-nil, is invoked after the App lazily
	// creates a new session on first Send.  The CLI uses this to record
	// the new id in state (RecentSessions).  Best-effort; errors are
	// swallowed internally.
	OnSessionCreated func(id string)

	// MCPStatuses is the list of MCP server statuses populated at bootstrap.
	// Displayed in the sidebar.  The UI-side type is SidebarMCPStatus (defined
	// in components/sidebar.go) so the UI package has no dependency on cmd/.
	MCPStatuses []components.SidebarMCPStatus

	// OpenSessionsModalOnStart, when true, causes the sessions picker to
	// open immediately after the first render.  Used by `hygge resume`
	// (multiple sessions in cwd) and resume_default="ask".  When the
	// picker is opened this way and the user presses Esc without selecting
	// a session — and no foreground session is bound — the App exits.
	OpenSessionsModalOnStart bool

	// Config is the resolved application configuration.  When non-nil,
	// the notifications subsystem reads Config.Notifications to decide
	// whether and when to send notifications.  A nil Config disables
	// notifications (equivalent to Config.Notifications.Enabled == false).
	Config *config.Config

	// SwitchModel applies a provider/model selection to the running backend.
	// modeName is non-empty when the switch came from a mode change; it is empty
	// for direct /model selections. When nil, /model remains a session-only UI
	// selection.
	SwitchModel func(ctx context.Context, providerName, modelName, modeName string) error
	// SaveModel persists a successful provider/model runtime switch.  Save
	// failures are surfaced to the UI without rolling back the runtime switch.
	SaveModel  func(ctx context.Context, providerName, modelName string) error
	SaveAPIKey func(ctx context.Context, providerName, apiKey string) error
	// RememberMemory persists project/global memory. Session memory uses Store.
	RememberMemory func(ctx context.Context, scope session.MemoryScope, content string) (*session.Memory, error)
	// ForgetMemory deletes project/global memory. Session memory uses Store.
	ForgetMemory func(ctx context.Context, scope session.MemoryScope, memoryID string) (*session.Memory, error)
	// ListMemories loads file-backed global/project memories. Session memory uses Store.
	ListMemories func(ctx context.Context) ([]*session.Memory, error)
	// ProjectMemoryGitignoreWarning returns a warning before the first project memory
	// write when .hygge/ may become untracked.
	ProjectMemoryGitignoreWarning func(ctx context.Context) (string, error)
	ThemeNames                    []string
	LoadTheme                     func(ctx context.Context, name string) (*theme.Theme, error)
	SaveTheme                     func(ctx context.Context, name string) error
	// EditPrompt opens the current prompt in an external editor and returns the
	// edited prompt. Tests may inject this seam; production falls back to
	// $VISUAL, then $EDITOR, then vi.
	EditPrompt func(ctx context.Context, initial string) (string, error)
	// NeedsOnboarding opens the first-run onboarding wizard before chat.
	NeedsOnboarding bool
	// KnownProviders lists provider IDs selectable in onboarding.
	KnownProviders []string
	// SaveOnboardingResult persists the completed onboarding configuration.
	SaveOnboardingResult func(ctx context.Context, result OnboardingResult) error
	// GeneratePrompt generates a system prompt during onboarding. It should return
	// an error without blocking manual editing when generation fails.
	GeneratePrompt func(ctx context.Context, providerName, modelName, apiKey, idea string) (string, error)

	// Yolo bypasses configurable permission prompts/default denies while keeping
	// the hard-coded secrets denylist active.
	Yolo    bool
	SetYolo func(ctx context.Context, enabled bool) error
}

AppOptions configures the App.

type MentionSubagent

type MentionSubagent struct {
	Name        string
	Description string
}

MentionSubagent is the UI-facing description of a selectable sub-agent type. The CLI maps internal/subagent.Type values into this shape so internal/ui can render @ mention completions without depending on the subagent package.

type OnboardingResult added in v0.7.0

type OnboardingResult struct {
	// ProviderName is the provider selected for the first mode.
	ProviderName string
	// ProviderAPIKey is the raw API key for ProviderName.
	ProviderAPIKey string
	// ProviderAPIKeys contains every provider API key configured during onboarding.
	ProviderAPIKeys map[string]string
	// Mode is the first mode the user created.
	Mode config.ModeConfig
	// Subagents lists the subagent definitions the user created.
	Subagents []components.OnboardingSubagentDraft
}

OnboardingResult is the output of the onboarding wizard passed to AppOptions.SaveOnboardingResult.

type SidebarMCPStatus

type SidebarMCPStatus = components.SidebarMCPStatus

SidebarMCPStatus is a re-export of components.SidebarMCPStatus so that cmd/hygge/cli/run.go can reference the type without importing the internal/ui/components package directly. See AppOptions.MCPStatuses.

Directories

Path Synopsis
Package components contains the bubbletea sub-views that compose the App.
Package components contains the bubbletea sub-views that compose the App.
anim
Package anim provides a compact colored-runes animation component for use in terminal UIs built with bubbletea v2.
Package anim provides a compact colored-runes animation component for use in terminal UIs built with bubbletea v2.
bubble
Package bubble provides the Bubble rendering primitive for the chat-bubble UI redesign (Phase 1).
Package bubble provides the Bubble rendering primitive for the chat-bubble UI redesign (Phase 1).
Package styles defines the comprehensive style system for Hygge's terminal UI.
Package styles defines the comprehensive style system for Hygge's terminal UI.
Package theme provides the theme registry and style-atom system for Hygge's terminal UI.
Package theme provides the theme registry and style-atom system for Hygge's terminal UI.

Jump to

Keyboard shortcuts

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