tui

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 44 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Version = "dev"

Version is injected at build time via -ldflags "-X main.version=..." which sets it through main.go's init. Defaults to "dev" when built without ldflags.

Functions

func GitBranch

func GitBranch(root string) string

GitBranch returns the current git branch name for root, or "" on error.

func LoadHistory

func LoadHistory(wsPath string) []string

LoadHistory reads the list of recently used requirements paths.

func NeedsModulePath

func NeedsModulePath(root string, cfg config.Config) bool

NeedsModulePath returns true if the project looks like Go, has no module path configured, and no go.mod exists in root.

func RemoveRecentProject

func RemoveRecentProject(projectPath string) error

RemoveRecentProject deletes a project from the recent list.

func RunModelSetup

func RunModelSetup(root string, cfg config.Config) (config.Config, error)

RunModelSetup shows only the per-agent project setup screen and returns the (possibly updated) config. Used by the pause-to-change-model flow.

func RunModulePathPrompt

func RunModulePathPrompt(root, wsDir string) (string, error)

RunModulePathPrompt shows just the module path input screen and returns the chosen path. Returns ("", nil) if the user cancelled.

func SaveHistory

func SaveHistory(wsPath, path string) error

SaveHistory prepends path to the history, deduplicates, trims to max.

func SaveRecentProject

func SaveRecentProject(projectPath string) error

SaveRecentProject adds or bumps a project to the top of the recent list. The user's home directory is never saved.

Types

type AgentEventMsg

type AgentEventMsg struct {
	Role  bus.AgentRole
	Text  string
	State AgentState
}

AgentEventMsg signals a state change or output for a specific agent.

type AgentPanelModel

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

AgentPanelModel displays the status and scrollable output of one agent.

func NewAgentPanel

func NewAgentPanel(role bus.AgentRole) AgentPanelModel

func (AgentPanelModel) Init

func (m AgentPanelModel) Init() tea.Cmd

func (*AgentPanelModel) SetLanguage

func (m *AgentPanelModel) SetLanguage(lang string)

SetLanguage configures syntax highlighting for the given programming language.

func (*AgentPanelModel) SetSize

func (m *AgentPanelModel) SetSize(w, h int)

SetSize updates panel dimensions.

func (AgentPanelModel) Update

func (m AgentPanelModel) Update(msg tea.Msg) (AgentPanelModel, tea.Cmd)

func (AgentPanelModel) View

func (m AgentPanelModel) View() string

type AgentState

type AgentState string

AgentState represents the display state of an agent panel.

const (
	AgentWaiting AgentState = "waiting"
	AgentRunning AgentState = "running"
	AgentFixing  AgentState = "fixing"
	AgentDone    AgentState = "done"
	AgentError   AgentState = "error"
	AgentGate    AgentState = "gate"
)

type ArtifactViewerModel

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

ArtifactViewerModel shows a workspace artifact file in a scrollable viewport. It appears automatically when a human gate fires so the user can review, edit, or request revisions from the planner before approving.

func (ArtifactViewerModel) Init

func (m ArtifactViewerModel) Init() tea.Cmd

func (ArtifactViewerModel) Update

func (ArtifactViewerModel) View

func (m ArtifactViewerModel) View() string

type BusMessageMsg

type BusMessageMsg struct {
	Msg bus.Message
}

BusMessageMsg wraps a bus.Message as a tea.Msg.

type ChatClosedMsg

type ChatClosedMsg struct{}

type ChatModel

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

ChatModel is a live chat panel overlay backed by an LLMRunner.

func NewChat

func NewChat(llm runner.LLMRunner, systemContext string) ChatModel

NewChat creates a ChatModel with the given LLMRunner. systemContext is prepended to every request as the system prompt.

func (ChatModel) Init

func (m ChatModel) Init() tea.Cmd

func (*ChatModel) SetSize

func (m *ChatModel) SetSize(w, h int)

func (ChatModel) Update

func (m ChatModel) Update(msg tea.Msg) (ChatModel, tea.Cmd)

func (ChatModel) View

func (m ChatModel) View() string

func (ChatModel) WithFileContext

func (m ChatModel) WithFileContext(root string) ChatModel

WithFileContext enables the .md attach picker, rooted at the repo directory.

func (ChatModel) WithReviseFn

func (m ChatModel) WithReviseFn(fn ReviseFunc) ChatModel

WithReviseFn sets a callback for artifact revision (PM chat mode).

type ChatTokenMsg

type ChatTokenMsg struct {
	Text string
	Done bool
	Gen  int // stream generation; messages from cancelled streams are ignored
}

Chat messages.

type ControlModel

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

ControlModel renders the local control surface for tmux-backed runs. It keeps conversation, agent status summary, approval flow, and shortcuts in the launching terminal while agent output lives in external tmux panes.

func (ControlModel) Init

func (m ControlModel) Init() tea.Cmd

func (ControlModel) Update

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

func (ControlModel) View

func (m ControlModel) View() string

type ConversationModel

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

ConversationModel shows a scrollable log of bus messages.

func NewConversation

func NewConversation(width, height int) ConversationModel

func (ConversationModel) Init

func (m ConversationModel) Init() tea.Cmd

func (*ConversationModel) SetSize

func (m *ConversationModel) SetSize(w, h int)

func (ConversationModel) Update

func (m ConversationModel) Update(msg tea.Msg) (ConversationModel, tea.Cmd)

func (ConversationModel) View

func (m ConversationModel) View() string

type DirBrowserCancelledMsg

type DirBrowserCancelledMsg struct{}

DirBrowserCancelledMsg is emitted when the user cancels browsing.

type DirBrowserModel

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

DirBrowserModel is a filesystem navigator that shows only directories. Directories detected as projects (containing .git, go.mod, etc.) are highlighted and selectable with Enter. Regular directories are entered.

func NewDirBrowser

func NewDirBrowser() (DirBrowserModel, error)

NewDirBrowser creates a directory browser starting at $HOME.

func (DirBrowserModel) Init

func (m DirBrowserModel) Init() tea.Cmd

func (*DirBrowserModel) SetSize

func (m *DirBrowserModel) SetSize(w, h int)

SetSize updates the browser dimensions.

func (DirBrowserModel) Update

func (m DirBrowserModel) Update(msg tea.Msg) (DirBrowserModel, tea.Cmd)

func (DirBrowserModel) View

func (m DirBrowserModel) View() string

type DirSelectedMsg

type DirSelectedMsg struct {
	Path string
}

DirSelectedMsg is emitted when a directory is chosen as a project.

type EditorCancelledMsg

type EditorCancelledMsg struct{}

type EditorModel

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

EditorModel is a full-screen requirements editor using an embedded textarea.

func NewEditor

func NewEditor(initialContent string) EditorModel

func (EditorModel) Init

func (m EditorModel) Init() tea.Cmd

func (*EditorModel) SetSize

func (m *EditorModel) SetSize(w, h int)

func (EditorModel) Update

func (m EditorModel) Update(msg tea.Msg) (EditorModel, tea.Cmd)

func (EditorModel) View

func (m EditorModel) View() string

type FilePreviewModel

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

FilePreviewModel renders a syntax-highlighted, scrollable view of a single file. It replaces the active agent panel while the user browses the project tree in the System Monitor.

func NewFilePreview

func NewFilePreview(root string, w, h int) FilePreviewModel

NewFilePreview creates an empty preview rooted at root.

func (*FilePreviewModel) GotoBottom

func (m *FilePreviewModel) GotoBottom()

func (*FilePreviewModel) GotoTop

func (m *FilePreviewModel) GotoTop()

GotoTop / GotoBottom jump to the start/end of the file.

func (*FilePreviewModel) PageDown

func (m *FilePreviewModel) PageDown()

func (*FilePreviewModel) PageUp

func (m *FilePreviewModel) PageUp()

PageUp / PageDown scroll by a full viewport page.

func (*FilePreviewModel) ScrollDown

func (m *FilePreviewModel) ScrollDown()

func (*FilePreviewModel) ScrollUp

func (m *FilePreviewModel) ScrollUp()

ScrollUp / ScrollDown move the preview body without affecting tree selection.

func (*FilePreviewModel) SetFocused

func (m *FilePreviewModel) SetFocused(b bool)

SetFocused toggles the preview-scroll hint. When focused, arrow keys scroll the file; otherwise they navigate the tree.

func (*FilePreviewModel) SetSize

func (m *FilePreviewModel) SetSize(w, h int)

SetSize resizes the preview and re-renders the current file only when the width changes (re-highlighting on every frame would be wasteful).

func (*FilePreviewModel) Show

func (m *FilePreviewModel) Show(relPath string, isDir bool)

Show loads relPath into the preview. Directories and unreadable files set an informational message instead of content.

func (FilePreviewModel) View

func (m FilePreviewModel) View() string

type FileRejectedMsg

type FileRejectedMsg struct{ Path string }

Git panel messages.

type FileSelectedMsg

type FileSelectedMsg struct{ Path string }

type FileTreeModel

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

FileTreeModel is an MC-style single-pane directory navigator. Directories are navigable; .md files are selectable. Any file can be selected with Ctrl+Enter.

func NewFileTree

func NewFileTree(root string) (FileTreeModel, error)

func (FileTreeModel) Init

func (m FileTreeModel) Init() tea.Cmd

func (*FileTreeModel) SetSize

func (m *FileTreeModel) SetSize(w, h int)

func (FileTreeModel) Update

func (m FileTreeModel) Update(msg tea.Msg) (FileTreeModel, tea.Cmd)

func (FileTreeModel) View

func (m FileTreeModel) View() string

type GitPanelClosedMsg

type GitPanelClosedMsg struct{}

type GitPanelModel

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

GitPanelModel is a lazygit-inspired git panel overlay.

func NewGitPanel

func NewGitPanel(root string) (GitPanelModel, error)

NewGitPanel creates a GitPanelModel for the given repo root.

func (GitPanelModel) Init

func (m GitPanelModel) Init() tea.Cmd

func (*GitPanelModel) SetSize

func (m *GitPanelModel) SetSize(w, h int)

func (GitPanelModel) Update

func (m GitPanelModel) Update(msg tea.Msg) (GitPanelModel, tea.Cmd)

func (GitPanelModel) View

func (m GitPanelModel) View() string

type GitRefreshMsg

type GitRefreshMsg struct{}

type HomeModel

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

HomeModel is the first screen shown when DECSR launches.

func NewHomeModel

func NewHomeModel(cfg config.Config, root string) HomeModel

func (HomeModel) Init

func (m HomeModel) Init() tea.Cmd

func (HomeModel) Update

func (m HomeModel) Update(msg tea.Msg) (HomeModel, tea.Cmd)

func (HomeModel) View

func (m HomeModel) View() string

type Model

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

Model is the root Bubble Tea model for DECSR TUI.

func New

func New(events <-chan bus.Message, root, wsPath string, llm runner.LLMRunner, cfg config.Config) Model

New creates the root TUI model. llm is used for the chat overlay (may be nil).

func (Model) Init

func (m Model) Init() tea.Cmd

func (Model) PauseForModelChange

func (m Model) PauseForModelChange() bool

PauseForModelChange returns true if the user paused the running task to change the model. The caller should show the model setup screen and then resume the task with the updated config.

func (Model) ReturnToMenu

func (m Model) ReturnToMenu() bool

ReturnToMenu returns true if the user chose to go back to the main menu after pipeline completion (instead of quitting).

func (Model) Update

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

func (Model) View

func (m Model) View() string

func (Model) WithTaskInput

func (m Model) WithTaskInput(input string) Model

WithTaskInput sets the submitted requirements shown in the PM conversation.

type NegotiateClosedMsg

type NegotiateClosedMsg struct{}

NegotiateClosedMsg is sent when the user closes the negotiate overlay.

type NegotiateModel

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

NegotiateModel is the PM conversation overlay for requirements gathering.

func NewNegotiate

func NewNegotiate(sendFn SendHumanReplyFunc, root string) NegotiateModel

NewNegotiate creates a NegotiateModel with the given reply callback. root enables the Ctrl+F .md attach picker so users can feed existing project description files into the conversation instead of retyping them.

func (*NegotiateModel) AddPMMessage

func (m *NegotiateModel) AddPMMessage(content string)

AddPMMessage appends a PM conversation message to the negotiate model.

func (NegotiateModel) Init

func (m NegotiateModel) Init() tea.Cmd

func (*NegotiateModel) Prefill

func (m *NegotiateModel) Prefill(text string)

Prefill places text in the input box without sending it. Used after the repository context pack is approved so the user can confirm or edit the task description supplied on the command line.

func (*NegotiateModel) SeedContext

func (m *NegotiateModel) SeedContext(content string)

SeedContext shows initial context (e.g. the requirements the user submitted) at the top of the conversation, before any PM reply, so the screen is never blank and the user can review what they're refining.

func (*NegotiateModel) SetReady

func (m *NegotiateModel) SetReady()

SetReady stops the waiting indicator without appending a message. Used when the PM returns no question, so the user can refine or accept (Ctrl+A).

func (*NegotiateModel) SetRequireInput

func (m *NegotiateModel) SetRequireInput(v bool)

SetRequireInput controls whether Ctrl+A may send the synthetic "accept now" message. The post-compaction intent turn sets this to true so the PM cannot plan without an actual task request.

func (*NegotiateModel) SetSize

func (m *NegotiateModel) SetSize(w, h int)

func (*NegotiateModel) SetWaiting

func (m *NegotiateModel) SetWaiting()

SetWaiting shows the "PM is thinking…" indicator. Used when the conversation opens with a pending PM analysis (e.g. a seeded resume brief) so the pane doesn't look blank while a slow local model works.

func (NegotiateModel) Update

func (m NegotiateModel) Update(msg tea.Msg) (NegotiateModel, tea.Cmd)

func (NegotiateModel) View

func (m NegotiateModel) View() string

type PickerCancelledMsg

type PickerCancelledMsg struct{}

type PickerModel

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

PickerModel is the start screen for selecting requirements.

func NewPicker

func NewPicker(root, wsPath string) PickerModel

func (PickerModel) Init

func (m PickerModel) Init() tea.Cmd

func (*PickerModel) SetSize

func (m *PickerModel) SetSize(w, h int)

func (PickerModel) Update

func (m PickerModel) Update(msg tea.Msg) (PickerModel, tea.Cmd)

func (PickerModel) View

func (m PickerModel) View() string

type PickerSelectedMsg

type PickerSelectedMsg struct {
	Path  string
	IsNew bool
}

type PipelineDoneMsg

type PipelineDoneMsg struct {
	Err error
}

PipelineDoneMsg is sent when the pipeline finishes (successfully or with an error).

type ProjectPickerCancelledMsg

type ProjectPickerCancelledMsg struct{}

ProjectPickerCancelledMsg is sent when user cancels the project picker.

type ProjectPickerModel

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

ProjectPickerModel shows the project selection screen with current directory, an "Open project…" browser, and a list of recently opened projects.

func NewProjectPicker

func NewProjectPicker(currentDir string) ProjectPickerModel

NewProjectPicker creates the project selection screen.

func (ProjectPickerModel) Init

func (m ProjectPickerModel) Init() tea.Cmd

func (ProjectPickerModel) Update

func (ProjectPickerModel) View

func (m ProjectPickerModel) View() string

type ProjectSelectedMsg

type ProjectSelectedMsg struct {
	Path string
}

ProjectSelectedMsg is sent when user picks a project directory.

type RecentProject

type RecentProject struct {
	Path     string `json:"path"`
	Name     string `json:"name"`
	LastUsed string `json:"last_used"`
}

RecentProject stores metadata about a previously opened project.

func LoadRecentProjects

func LoadRecentProjects() []RecentProject

LoadRecentProjects reads the list of recently opened projects from ~/.decsr/projects.json. The user's home directory and missing paths are excluded from the returned list.

type RequirementsSavedMsg

type RequirementsSavedMsg struct{ Path string }

Requirements picker/editor messages.

type ReviseFunc

type ReviseFunc func(artifact, feedback string) error

ReviseFunc is called when the PM decides to revise an artifact.

type SendHumanReplyFunc

type SendHumanReplyFunc func(msg string)

SendHumanReplyFunc is called when the user sends a reply during PM negotiation.

type SetupModel

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

func NewSetupModel

func NewSetupModel(currentRunner, currentModel string, agentCfgs map[string]config.AgentConfig) SetupModel

func NewSetupModelWithOverrides

func NewSetupModelWithOverrides(currentRunner, currentModel, currentProgLang, currentProjectName string, projectAgents map[string]config.AgentConfig) SetupModel

NewSetupModelWithOverrides creates a setup model pre-populated with explicit project-level overrides (from project.yaml), instead of detecting them from merged config.

func (SetupModel) Init

func (m SetupModel) Init() tea.Cmd

func (SetupModel) Update

func (m SetupModel) Update(msg tea.Msg) (SetupModel, tea.Cmd)

func (SetupModel) View

func (m SetupModel) View() string

type StartupResult

type StartupResult struct {
	ReqPath       string        // non-empty when legacy pipeline was selected
	ChatMode      bool          // true when PM chat-based requirements gathering was selected
	Resume        bool          // true when the user chose to resume an interrupted task
	ReviewProject bool          // true when the user chose "Resume Project" (PM reviews .decsr)
	Cfg           config.Config // possibly updated config
}

StartupResult holds the outcome of the startup flow.

func RunStartup

func RunStartup(root, wsReqPath string, cfg config.Config) (StartupResult, error)

RunStartup shows the home/picker/editor flow and returns the result. Empty ReqPath with ChatMode=false means the user quit without selecting.

type StatusBarModel

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

StatusBarModel renders a single-line status bar at the bottom.

func NewStatusBar

func NewStatusBar(width int) StatusBarModel

func (StatusBarModel) AdvanceScroll

func (m StatusBarModel) AdvanceScroll() StatusBarModel

AdvanceScroll moves the marquee scroll position forward by one.

func (StatusBarModel) Height

func (m StatusBarModel) Height() int

Height returns the number of terminal rows View() will occupy at the current width (1 normally, more when the shortcuts must wrap).

func (StatusBarModel) View

func (m StatusBarModel) View() string

func (StatusBarModel) WithBranch

func (m StatusBarModel) WithBranch(b string) StatusBarModel

func (StatusBarModel) WithCodingStarted

func (m StatusBarModel) WithCodingStarted(t time.Time) StatusBarModel

func (StatusBarModel) WithRunnerModel

func (m StatusBarModel) WithRunnerModel(r, mdl string) StatusBarModel

func (StatusBarModel) WithStageInfo

func (m StatusBarModel) WithStageInfo(s string) StatusBarModel

func (StatusBarModel) WithState

func (m StatusBarModel) WithState(s string) StatusBarModel

func (StatusBarModel) WithWidth

func (m StatusBarModel) WithWidth(w int) StatusBarModel

type SysmonModel

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

SysmonModel displays a compact system monitor panel.

func NewSysmon

func NewSysmon() SysmonModel

NewSysmon creates a new system monitor model.

func (SysmonModel) AgentUsage

func (m SysmonModel) AgentUsage() map[bus.AgentRole]bus.AgentUsage

AgentUsage exposes the per-agent token accounting collected from the bus. The returned map is the live internal map — callers must treat it as read-only. This is the single source of truth shared between the system monitor panel and the end-of-run summary table, so the two views can never disagree.

func (*SysmonModel) BlurTree

func (m *SysmonModel) BlurTree()

BlurTree leaves tree-navigation mode.

func (*SysmonModel) FocusTree

func (m *SysmonModel) FocusTree()

FocusTree enters tree-navigation mode, pausing auto-scroll and placing the cursor on the first selectable file (falling back to the first entry).

func (SysmonModel) Init

func (m SysmonModel) Init() tea.Cmd

Init starts the first tick.

func (*SysmonModel) MoveTreeCursor

func (m *SysmonModel) MoveTreeCursor(delta int)

MoveTreeCursor moves the selection by delta, clamped to the tree bounds.

func (*SysmonModel) ObserveBusMessage

func (m *SysmonModel) ObserveBusMessage(msg bus.Message)

ObserveBusMessage updates active-file hints for the project tree.

func (SysmonModel) SelectedTreeEntry

func (m SysmonModel) SelectedTreeEntry() (relPath string, isDir bool, ok bool)

SelectedTreeEntry returns the currently highlighted entry's repo-relative path and whether it is a directory. ok is false when the tree is empty.

func (*SysmonModel) SetProjectRoot

func (m *SysmonModel) SetProjectRoot(root string)

SetProjectRoot configures the project root for the tree view.

func (*SysmonModel) SetSize

func (m *SysmonModel) SetSize(w, h int)

SetSize updates the panel dimensions.

func (SysmonModel) TreeFocused

func (m SysmonModel) TreeFocused() bool

TreeFocused reports whether the tree is being navigated.

func (SysmonModel) Update

func (m SysmonModel) Update(msg tea.Msg) (SysmonModel, tea.Cmd)

Update handles sysmon tick messages.

func (SysmonModel) View

func (m SysmonModel) View() string

View renders the system monitor panel.

type TaskHistoryClosedMsg

type TaskHistoryClosedMsg struct{}

TaskHistoryClosedMsg is emitted when the task history view is dismissed.

type TaskHistoryModel

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

TaskHistoryModel is a read-only list of completed decsr tasks.

func NewTaskHistory

func NewTaskHistory(tasks []decsr.DoneTask) TaskHistoryModel

NewTaskHistory creates a history view for the given completed tasks.

func (TaskHistoryModel) Init

func (m TaskHistoryModel) Init() tea.Cmd

func (*TaskHistoryModel) SetSize

func (m *TaskHistoryModel) SetSize(w, h int)

func (TaskHistoryModel) Update

func (m TaskHistoryModel) Update(msg tea.Msg) (TaskHistoryModel, tea.Cmd)

func (TaskHistoryModel) View

func (m TaskHistoryModel) View() string

type TaskRunnerReadyMsg

type TaskRunnerReadyMsg struct {
	Runner *decsr.TaskRunner
	Cancel context.CancelFunc
}

TaskRunnerReadyMsg is sent when the TaskRunner is ready to receive interaction.

Jump to

Keyboard shortcuts

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