app

package
v0.5.2 Latest Latest
Warning

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

Go to latest
Published: May 2, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package app holds the Bubble Tea Model, Update, View, and message types for the paddock-tui interactive UI.

Index

Constants

View Source
const NewSessionSentinel = "__paddock_tui_new_session__"

NewSessionSentinel is a synthetic entry placed at the end of the visible sidebar list, representing the "[+ new session]" row. It's a valid value of m.Focused — pressing Enter on it opens the new-session modal. The string is deliberately unrepresentable as a Workspace name (Workspace names are DNS labels: lowercase alphanumerics and hyphens) so it can never collide with a real session.

Variables

This section is empty.

Functions

This section is empty.

Types

type EndSessionModalState

type EndSessionModalState struct {
	TargetName string
	Confirmed  bool
}

type FocusArea

type FocusArea int

FocusArea is the area of the TUI that currently receives input.

const (
	FocusPrompt FocusArea = iota
	FocusSidebar
	FocusMainPane
)

type InteractiveBinding

type InteractiveBinding struct {
	RunName        string
	CurrentTurnSeq *int32
	LastFrameAt    time.Time
}

InteractiveBinding holds the TUI's view of an Interactive HarnessRun the focused session is bound to. CurrentTurnSeq mirrors HarnessRun.status.interactive.currentTurnSeq — non-nil means a turn is in flight; nil means the run is between prompts.

type ModalKind

type ModalKind int

ModalKind names which modal (if any) is open.

const (
	ModalNone ModalKind = iota
	ModalNew
	ModalEnd
	ModalHelp
	ModalQueue
)

type Model

type Model struct {
	// Cluster wiring.
	Client    client.Client
	Namespace string

	// BrokerClient is the authenticated HTTP+WebSocket client for the
	// paddock-broker. Nil until Phase 5 wire-up populates it from the
	// binary entry point. Unit tests that do not exercise the broker
	// call leaf leave it nil.
	BrokerClient *paddockbroker.Client

	// Session list, keyed by Name. SessionOrder gives display order.
	Sessions     map[string]*SessionState
	SessionOrder []string
	Focused      string // session name; "" when no session selected.

	// UI state.
	FocusArea   FocusArea
	Modal       ModalKind
	PromptInput string
	Filter      string
	// ErrBanner surfaces transient error messages (red / high-attention).
	ErrBanner string
	// Banner surfaces informational context messages (e.g. run ended).
	// Distinct from ErrBanner so render code can colour them differently.
	Banner string

	// PendingPrompt holds a single submitted prompt that's waiting for
	// the broker to stop returning 409 (an in-flight turn on the bound
	// interactive run). Submitting another prompt while non-empty
	// replaces this one. The status footer surfaces a hint.
	PendingPrompt string

	// Palette tracks the command palette overlay's open/closed state and
	// in-progress input. See palette.go.
	Palette PaletteState

	// Modal-specific state, set when Modal != ModalNone.
	ModalNew   *NewSessionModalState
	ModalEnd   *EndSessionModalState
	ModalHelp  bool
	ModalQueue bool

	// MainScrollFromBottom is the number of lines the main pane has
	// been scrolled UP from the bottom. 0 means stick to bottom (the
	// most recent run is fully visible). PgUp/PgDown adjust this in
	// the reducer; the View slices the rendered content accordingly.
	MainScrollFromBottom int

	// RunCursor indexes into the focused session's Runs slice for
	// keyboard navigation. Only meaningful when FocusArea == FocusMainPane.
	RunCursor int
	// contains filtered or unexported fields
}

Model is the Bubble Tea model for paddock-tui. Everything that renders or affects rendering lives here. Async work is driven by tea.Cmd values returned from Update — see commands.go.

func NewModel

func NewModel(c client.Client, ns string) Model

NewModel constructs a Model with the supplied cluster wiring.

func (Model) Init

func (m Model) Init() tea.Cmd

Init kicks off the initial session-list load and opens the session watch. The session watch is opened once for the lifetime of the Model — Update re-issues nextSessionEventCmd to read further events off the same channel without spawning new goroutines.

func (Model) Update

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

Update dispatches messages to per-area handlers and returns the next Model + a tea.Cmd. Watch commands re-issue themselves on every message they produce so streams stay alive.

func (Model) View

func (m Model) View() string

Update is implemented in update.go (Task 19).

View is a placeholder so Model satisfies tea.Model — the real rendering lives in package ui (Task 22) and is wired in by the cmd-package teaModel adapter that embeds Model.

type NewSessionModalState

type NewSessionModalState struct {
	NameInput     string
	TemplatePicks []string // populated from session.ListTemplates
	TemplateIdx   int
	StorageInput  string
	SeedRepoInput string
	Field         int // 0=name, 1=template, 2=storage, 3=seed
}

Modal-state placeholders — implementations land in Task 17.

type PaletteCmd

type PaletteCmd int

PaletteCmd identifies a recognised palette command. PaletteEmpty covers the "user opened the palette but hasn't typed anything yet" case; PaletteUnknown carries the typed token back to the caller for error reporting.

const (
	PaletteEmpty PaletteCmd = iota
	PaletteCancel
	PaletteEnd
	PaletteInteractive
	PaletteTemplate
	PaletteReattach
	PaletteStatus
	PaletteEdit
	PaletteHelp
	PaletteUnknown
)

func ParsePalette

func ParsePalette(input string) (PaletteCmd, string)

ParsePalette classifies a palette command line. The returned arg is any whitespace-separated tail (e.g. for `template claude-code`). Empty input returns PaletteEmpty so the dispatcher can treat Enter-on-empty as a no-op cleanly.

type PaletteState

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

PaletteState tracks the palette overlay's runtime state. Closed palettes carry no input; opening starts with an empty buffer.

func (PaletteState) Input

func (p PaletteState) Input() string

func (PaletteState) Open

func (p PaletteState) Open() bool

func (PaletteState) WithInput

func (p PaletteState) WithInput(s string) PaletteState

WithInput sets the in-progress input string. Caller is responsible for keeping the palette open; closed palettes ignore input writes (a no-op so the field stays "" on close).

func (PaletteState) WithOpen

func (p PaletteState) WithOpen(open bool) PaletteState

WithOpen toggles the palette open/closed. Closing clears any in-progress input so the next open lands on an empty prompt.

type Queue

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

Queue is a tiny FIFO of pending prompts for one session. Lives in TUI memory only — quitting the TUI loses queued prompts by design.

func (*Queue) Items

func (q *Queue) Items() []string

func (*Queue) Len

func (q *Queue) Len() int

func (*Queue) Peek

func (q *Queue) Peek() string

func (*Queue) Pop

func (q *Queue) Pop() (string, bool)

func (*Queue) Push

func (q *Queue) Push(s string)

func (*Queue) RemoveAt

func (q *Queue) RemoveAt(i int)

type RunSummary

type RunSummary struct {
	Name string
	// CreationTime mirrors HarnessRun.metadata.creationTimestamp.
	// Used to sort SessionState.Runs chronologically. StartTime alone
	// is insufficient because it stays zero until the harness pod
	// starts, so freshly-created runs would otherwise sort ahead of
	// older in-progress ones.
	CreationTime   time.Time
	Phase          paddockv1alpha1.HarnessRunPhase
	Prompt         string
	StartTime      time.Time
	CompletionTime time.Time
	Template       string
}

RunSummary is a TUI-shaped projection of a HarnessRun.

func (RunSummary) IsTerminal

func (r RunSummary) IsTerminal() bool

IsTerminal reports whether the run has reached a terminal phase.

type SessionMode

type SessionMode int

SessionMode is the high-level state of a TUI session.

const (
	SessionBatch SessionMode = iota
	SessionArmed
	SessionBound
)

type SessionState

type SessionState struct {
	Session pdksession.Session

	// Runs is the list of HarnessRuns for this session, sorted by
	// CreationTime ascending (oldest first, newest at the end). The
	// main pane renders backwards from the end so the newest run is at
	// the top.
	Runs []RunSummary

	// Events keyed by run name. Only populated for the focused session.
	Events map[string][]paddockv1alpha1.PaddockEvent

	// Queue of prompts pending while a run is in flight.
	Queue Queue

	// Armed is true when the user has run the `interactive` palette
	// command but hasn't yet typed the kick-off prompt.
	Armed bool

	// Interactive holds the bound interactive run, when the session is
	// in SessionBound. Nil otherwise.
	Interactive *InteractiveBinding
}

SessionState bundles the runtime state for one session held in TUI memory.

func (*SessionState) Mode

func (s *SessionState) Mode() SessionMode

Mode reports the session's current high-level state, derived from SessionState fields.

Jump to

Keyboard shortcuts

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