tui

package
v0.1.0 Latest Latest
Warning

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

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

Documentation

Overview

SPDX-License-Identifier: MIT Purpose: TUI-side adapter for the chat.Input widget. Avoids the `*chat.Input` direct dep in model.go by wrapping it in a local type. Submits are routed through a chat.Runner (lazy-init singleton) and the LLM call runs in a background goroutine so the UI stays responsive.

SPDX-License-Identifier: MIT Purpose: thin bridge so *tea.Program (which has Send(msg tea.Msg)) can be stored in the Model.Program field typed as the local teaProgramIface interface. Imported in main.go via tui.ProgramFromTeaProgram().

SPDX-License-Identifier: MIT Purpose: render the chat view in the TUI center panel. Shows recent history at the top, chat input at the bottom.

SPDX-License-Identifier: MIT Purpose: Notification banner rendering + keybindings (o=open, d=dismiss, n=next).

SPDX-License-Identifier: MIT Purpose: glue between TUI and the notifications package — converts notification types to the TeaMsg types defined in messages.go.

SPDX-License-Identifier: MIT Purpose: Todos view — list todos with priority badges, live counts.

Index

Constants

This section is empty.

Variables

View Source
var AgentNames = []string{"Build", "Audit", "Stats"}
View Source
var Themes = []Theme{
	{
		Name:       "default",
		Accent:     "#7D56F4",
		AccentDim:  "#5E40BF",
		Text:       "#FFFFFF",
		TextDim:    "#808080",
		Background: "#1E1E2E",
		Border:     "#7D56F4",
		Success:    "#50FA7B",
		Warn:       "#F1FA8C",
		Error:      "#FF5555",
	},
	{
		Name:       "Dracula",
		Accent:     "#FF79C6",
		AccentDim:  "#BD93F9",
		Text:       "#F8F8F2",
		TextDim:    "#6272A4",
		Background: "#282A36",
		Border:     "#FF79C6",
		Success:    "#50FA7B",
		Warn:       "#F1FA8C",
		Error:      "#FF5555",
	},
	{
		Name:       "Nord",
		Accent:     "#88C0D0",
		AccentDim:  "#5E81AC",
		Text:       "#ECEFF4",
		TextDim:    "#4C566A",
		Background: "#2E3440",
		Border:     "#88C0D0",
		Success:    "#A3BE8C",
		Warn:       "#EBCB8B",
		Error:      "#BF616A",
	},
	{
		Name:       "Solarized",
		Accent:     "#B58900",
		AccentDim:  "#CB4B16",
		Text:       "#FDF6E3",
		TextDim:    "#93A1A1",
		Background: "#002B36",
		Border:     "#B58900",
		Success:    "#859900",
		Warn:       "#B58900",
		Error:      "#DC322F",
	},
	{
		Name:       "Monokai",
		Accent:     "#A6E22E",
		AccentDim:  "#66D9EF",
		Text:       "#F8F8F2",
		TextDim:    "#75715E",
		Background: "#272822",
		Border:     "#A6E22E",
		Success:    "#A6E22E",
		Warn:       "#E6DB74",
		Error:      "#F92672",
	},
}

Functions

func BannerDismissCmd

func BannerDismissCmd(id string) tea.Cmd

func BannerOpenCmd

func BannerOpenCmd(id string) tea.Cmd

func ComposeLayout

func ComposeLayout(tabs Tabs, sidebar Sidebar, view ViewKind, content string, right string, footer Footer, styles Styles, width, height int) string

func ListenForNotifications

func ListenForNotifications() tea.Cmd

ListenForNotifications returns a tea.Cmd that blocks on the notifications broadcaster channel and emits a NotificationMsg when one arrives. Re-subscribe from Update after each NotificationMsg to keep listening.

func ProgramFromTeaProgram

func ProgramFromTeaProgram(p *tea.Program) teaProgramIface

ProgramFromTeaProgram wraps a *tea.Program so it satisfies teaProgramIface. Returns nil if p is nil.

func RefreshTodosCmd

func RefreshTodosCmd() tea.Cmd

RefreshTodosCmd returns a tea.Cmd that re-counts todos.

func RenderCommandPalette

func RenderCommandPalette(items []string, sel int, query string, styles Styles, width, height int) string

func RenderConfigView

func RenderConfigView(entries []ConfigEntry, selected int, styles Styles, width, height int) string

func RenderEFMView

func RenderEFMView(stacks []EFMStack, styles Styles, width, height int, spinner Spinner) string

func RenderHistoryView

func RenderHistoryView(entries []HistoryEntry, selected int, styles Styles, width, height int) string

func RenderRightPanel

func RenderRightPanel(sel *ToolSubItem, view ViewKind, styles Styles, width, height int) string

func RenderSessionsView

func RenderSessionsView(styles Styles, tabs Tabs, width, height int) string

func RenderSubagentsPopup

func RenderSubagentsPopup(styles Styles, width, height int) string

func RenderToolsView

func RenderToolsView(sidebar Sidebar, styles Styles, width, height int) string

Types

type AgentCycleMsg

type AgentCycleMsg struct {
	Index int
}

type ArgInputState

type ArgInputState struct {
	Open  bool
	Cmd   string
	Value string
	Input textinput.Model
}

type BannerKeyMsg

type BannerKeyMsg struct {
	Action string
}

type ConfigEntry

type ConfigEntry struct {
	Key   string
	Value string
	Hint  string
	Kind  string
}

func DefaultConfigEntries

func DefaultConfigEntries() []ConfigEntry

type CountsMsg

type CountsMsg struct {
	Open    int
	Blocked int
	Overdue int
	Ready   int
}

CountsMsg is fired when todo counts are recomputed (open/blocked/overdue).

type EFMRefreshMsg

type EFMRefreshMsg struct {
	Stacks []EFMStack
}

type EFMStack

type EFMStack struct {
	Name      string
	Status    string
	URL       string
	CreatedAt time.Time
	TTL       int
}
type Footer struct {
	Selection   string
	AgentIndex  int
	Tokens      int
	TokensPct   float64
	Cost        string
	Width       int
	ShowHints   bool
	HintKeys    []HintPair
	Loading     bool
	Spinner     Spinner
	TodoOpen    int
	TodoBlocked int
	TodoOverdue int
	TodoReady   int
	// contains filtered or unexported fields
}

func NewFooter

func NewFooter(width int) Footer

func (*Footer) AgentName

func (f *Footer) AgentName() string

func (*Footer) CycleAgent

func (f *Footer) CycleAgent()

func (Footer) ProgressBar

func (f Footer) ProgressBar(width int) string

func (Footer) Render

func (f Footer) Render(styles Styles) string

func (*Footer) SetView

func (f *Footer) SetView(v ViewKind)

func (*Footer) View

func (f *Footer) View() ViewKind

type HintPair

type HintPair struct {
	Key   string
	Label string
}

func DefaultHints

func DefaultHints(view ViewKind) []HintPair

type HistoryAppendMsg

type HistoryAppendMsg struct {
	Entry HistoryEntry
}

type HistoryEntry

type HistoryEntry struct {
	Time    time.Time
	View    string
	Action  string
	Detail  string
	Success bool
}

type InterruptMsg

type InterruptMsg struct{}

type Mode

type Mode int
const (
	ModeNormal Mode = iota
	ModePalette
	ModeSubagents
	ModeArgInput
)

type Model

type Model struct {
	Width    int
	Height   int
	ThemeIdx int
	ViewKind ViewKind
	Mode     Mode
	Quitting bool
	Ready    bool
	Loading  bool

	Tabs       Tabs
	Sidebar    Sidebar
	Footer     Footer
	Spinner    Spinner
	Styles     Styles
	RightPanel bool

	Palette   PaletteState
	ArgInput  ArgInputState
	History   []HistoryEntry
	EFMStks   []EFMStack
	Config    []ConfigEntry
	ConfigSel int

	ToolList  list.Model
	ToolItems []list.Item

	TodoItems []TodoRow
	TodoSel   int

	NotificationBanner *NotificationItem
	Notifications      []NotificationItem

	ChatInput   *chatInput
	ChatHistory []string
	ChatRunner  *chat.Runner
	Program     teaProgramIface

	OnRun func(name string, args []string) error
	// contains filtered or unexported fields
}

Model is the top-level TUI model. Program, ChatRunner, and ctxFn are optional — when nil, the chat submit path falls back to synchronous behavior (used by tests and headless invocations).

func NewModel

func NewModel() *Model

func (*Model) AppendHistory

func (m *Model) AppendHistory(view, action, detail string, ok bool)

func (*Model) ApplyTheme

func (m *Model) ApplyTheme()

func (*Model) BannerNext

func (m *Model) BannerNext()

func (*Model) CloseArgInput

func (m *Model) CloseArgInput()

func (*Model) ClosePalette

func (m *Model) ClosePalette()

func (*Model) CloseSubagents

func (m *Model) CloseSubagents()

func (*Model) CycleTheme

func (m *Model) CycleTheme()

func (*Model) DismissBanner

func (m *Model) DismissBanner()

func (*Model) Init

func (m *Model) Init() tea.Cmd

func (*Model) NextView

func (m *Model) NextView()

func (*Model) OpenArgInput

func (m *Model) OpenArgInput(cmd string)

func (*Model) OpenPalette

func (m *Model) OpenPalette()

func (*Model) OpenSubagents

func (m *Model) OpenSubagents()

func (*Model) PrevView

func (m *Model) PrevView()

func (*Model) PreviousView

func (m *Model) PreviousView()

func (*Model) RenderBanner

func (m *Model) RenderBanner(styles Styles, width int) string

func (*Model) RenderTodos

func (m *Model) RenderTodos(styles Styles, width, height int) string

func (*Model) RunSelected

func (m *Model) RunSelected()

func (*Model) SetBanner

func (m *Model) SetBanner(n *NotificationItem)

func (*Model) SetContextFn

func (m *Model) SetContextFn(fn func() context.Context)

SetContextFn lets tests inject a cancellable context.

func (*Model) SwitchView

func (m *Model) SwitchView(v ViewKind)

func (*Model) Update

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

func (*Model) View

func (m *Model) View() tea.View

type NotificationItem

type NotificationItem struct {
	ID        string
	Title     string
	Message   string
	Type      string
	Dismissed bool
}

func (NotificationItem) GetID

func (n NotificationItem) GetID() string

func (NotificationItem) GetMessage

func (n NotificationItem) GetMessage() string

func (NotificationItem) GetTitle

func (n NotificationItem) GetTitle() string

func (NotificationItem) GetType

func (n NotificationItem) GetType() string

type NotificationMsg

type NotificationMsg struct {
	N NotificationSource
}

NotificationMsg is fired when the TUI receives a new notification from the sin-code notifications broadcaster.

type NotificationSource

type NotificationSource interface {
	GetID() string
	GetTitle() string
	GetMessage() string
	GetType() string
}

NotificationSource is the interface used by NotificationMsg to access notification fields. Implemented by *notifications.Notification and by test doubles in todos_view_test.go.

type PaletteOpenMsg

type PaletteOpenMsg struct {
	Open bool
}

type PaletteState

type PaletteState struct {
	Open   bool
	Query  string
	Items  []string
	Filter []string
	Sel    int
}

type Session

type Session struct {
	Name   string
	Active bool
	Dirty  bool
}

type SessionAddMsg

type SessionAddMsg struct {
	Name string
}

type SessionCloseMsg

type SessionCloseMsg struct {
	Index int
}

type SessionSelectMsg

type SessionSelectMsg struct {
	Index int
}
type Sidebar struct {
	Items        []SidebarItem
	Selected     int
	Width        int
	Collapsed    bool
	ToolSubItems []ToolSubItem
	ToolSel      int

	TodoOpen    int
	TodoBlocked int
	TodoOverdue int
	TodoReady   int
}

func NewSidebar

func NewSidebar() Sidebar

func (*Sidebar) MoveDown

func (s *Sidebar) MoveDown()

func (*Sidebar) MoveUp

func (s *Sidebar) MoveUp()

func (*Sidebar) SelectedTool

func (s *Sidebar) SelectedTool() *ToolSubItem

func (*Sidebar) SelectedView

func (s *Sidebar) SelectedView() ViewKind

func (*Sidebar) SetSelectedView

func (s *Sidebar) SetSelectedView(v ViewKind)

func (*Sidebar) Toggle

func (s *Sidebar) Toggle()

func (*Sidebar) ToolMoveDown

func (s *Sidebar) ToolMoveDown()

func (*Sidebar) ToolMoveUp

func (s *Sidebar) ToolMoveUp()

func (Sidebar) View

func (s Sidebar) View(styles Styles) string

type SidebarItem

type SidebarItem struct {
	View     ViewKind
	Icon     string
	Label    string
	Shortcut string
}

func DefaultSidebarItems

func DefaultSidebarItems() []SidebarItem

type SidebarToggleMsg

type SidebarToggleMsg struct{}

type Spinner

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

func NewSpinner

func NewSpinner() Spinner

func (Spinner) Frame

func (s Spinner) Frame() int

func (Spinner) Init

func (s Spinner) Init() tea.Cmd

func (Spinner) Update

func (s Spinner) Update(msg tea.Msg) (Spinner, tea.Cmd)

func (Spinner) View

func (s Spinner) View(style lipgloss.Style) string

func (Spinner) ViewPlain

func (s Spinner) ViewPlain() string

type SpinnerTickMsg

type SpinnerTickMsg time.Time

type Styles

type Styles struct {
	Theme Theme

	Header     lipgloss.Style
	TabActive  lipgloss.Style
	TabIdle    lipgloss.Style
	TabAdd     lipgloss.Style
	Sidebar    lipgloss.Style
	SidebarSel lipgloss.Style
	SidebarHdr lipgloss.Style
	Content    lipgloss.Style
	ContentHdr lipgloss.Style
	Footer     lipgloss.Style
	FooterKey  lipgloss.Style
	FooterVal  lipgloss.Style
	Popup      lipgloss.Style
	PopupItem  lipgloss.Style
	PopupSel   lipgloss.Style
	Spinner    lipgloss.Style
	Progress   lipgloss.Style
	StatusOK   lipgloss.Style
	StatusWarn lipgloss.Style
	StatusErr  lipgloss.Style
	Hint       lipgloss.Style
	AccentText lipgloss.Style
	Bold       lipgloss.Style
	Muted      lipgloss.Style
}

func NewStyles

func NewStyles(theme Theme) Styles

func (Styles) Accent

func (s Styles) Accent() color.Color

func (Styles) BorderColor

func (s Styles) BorderColor() color.Color

func (Styles) Text

func (s Styles) Text() color.Color

func (Styles) TextDim

func (s Styles) TextDim() color.Color

type SubagentsOpenMsg

type SubagentsOpenMsg struct {
	Open bool
}

type Tabs

type Tabs struct {
	Sessions   []Session
	ActiveIdx  int
	MaxVisible int
	Width      int
}

func NewTabs

func NewTabs() Tabs

func (Tabs) Active

func (t Tabs) Active() Session

func (*Tabs) Add

func (t *Tabs) Add(name string)

func (*Tabs) Close

func (t *Tabs) Close(idx int)

func (*Tabs) Next

func (t *Tabs) Next()

func (*Tabs) Prev

func (t *Tabs) Prev()

func (*Tabs) Select

func (t *Tabs) Select(idx int)

func (Tabs) View

func (t Tabs) View(s Styles) string

type Theme

type Theme struct {
	Name       string
	Accent     string
	AccentDim  string
	Text       string
	TextDim    string
	Background string
	Border     string
	Success    string
	Warn       string
	Error      string
}

type ThemeChangedMsg

type ThemeChangedMsg struct {
	Index int
}

type TodoRow

type TodoRow struct {
	ID       string
	Title    string
	Priority string
	Status   string
	Type     string
	Assignee string
}

TodoRow is a lightweight struct for displaying todos in the TUI.

type TodosLoadedMsg

type TodosLoadedMsg struct {
	Items []TodoRow
}

TodosLoadedMsg is fired when the todo list is reloaded.

type ToolRunMsg

type ToolRunMsg struct {
	Name string
	Args []string
}

type ToolSubItem

type ToolSubItem struct {
	Name        string
	Description string
	Runnable    bool
}

func DefaultToolSubItems

func DefaultToolSubItems() []ToolSubItem

type ViewKind

type ViewKind int
const (
	ViewTools ViewKind = iota
	ViewSessions
	ViewEFM
	ViewConfig
	ViewHistory
	ViewTodos
	ViewChat
)

func (ViewKind) Short

func (v ViewKind) Short() string

func (ViewKind) String

func (v ViewKind) String() string

type ViewSwitchMsg

type ViewSwitchMsg struct {
	View ViewKind
}

Directories

Path Synopsis
SPDX-License-Identifier: MIT Purpose: chat input widget — textarea with attachment support and slash commands.
SPDX-License-Identifier: MIT Purpose: chat input widget — textarea with attachment support and slash commands.

Jump to

Keyboard shortcuts

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