Documentation
¶
Overview ¶
Package ui is the root of the terminal client: one tea.Model that coordinates controllers, routes input by scope, and composites every widget onto one cell buffer (doc 02 sections 11 and 18). Behavior lives in the controllers; the root owns size, state, focus, the overlay, and the theme, and nothing else.
Index ¶
- type ChatController
- func (c *ChatController) Apply(msg btea.Msg)
- func (c *ChatController) Draw(scr uv.Screen, area uv.Rectangle) *tea.Cursor
- func (c *ChatController) Empty() bool
- func (c *ChatController) Handle(a keys.Action, _ btea.KeyPressMsg) btea.Cmd
- func (c *ChatController) Scroll(delta int)
- func (c *ChatController) SetTheme(th theme.Theme)
- type Client
- type Controller
- type EditorController
- func (e *EditorController) Blur()
- func (e *EditorController) Draw(scr uv.Screen, area uv.Rectangle) *tea.Cursor
- func (e *EditorController) Focus() btea.Cmd
- func (e *EditorController) Handle(a keys.Action, _ btea.KeyPressMsg) btea.Cmd
- func (e *EditorController) Lines() int
- func (e *EditorController) SetValue(s string)
- func (e *EditorController) Type(msg btea.Msg) btea.Cmd
- func (e *EditorController) Value() string
- type Focus
- type Layout
- type MemoryController
- func (mc *MemoryController) Apply(msg btea.Msg)
- func (mc *MemoryController) Closed()
- func (mc *MemoryController) Forget(id, session string) btea.Cmd
- func (mc *MemoryController) OnForgot(m memForgot) btea.Cmd
- func (mc *MemoryController) OnIndex(m memIndexLoaded)
- func (mc *MemoryController) OnResults(m memResults)
- func (mc *MemoryController) Open(overlay *dialog.Overlay, now time.Time) btea.Cmd
- func (mc *MemoryController) Search(query string) btea.Cmd
- func (mc *MemoryController) SetTheme(th theme.Theme)
- type MemoryHit
- type Model
- type Options
- type PermController
- func (p *PermController) Request(m bus.PermissionRequestedMsg, overlay *dialog.Overlay, now time.Time)
- func (p *PermController) Resolve(d perm.Decision) btea.Cmd
- func (p *PermController) Resolved(m bus.PermissionResolvedMsg, overlay *dialog.Overlay, now time.Time)
- func (p *PermController) SetTheme(th theme.Theme)
- type Router
- type SessionInfo
- type SidebarController
- type State
- type StatusController
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ChatController ¶
type ChatController struct {
// contains filtered or unexported fields
}
ChatController owns the scrollback: the lazy list, follow mode, and the projection of bus messages into parts (doc 02 sections 4 and 5). It knows nothing about permissions or the editor.
func NewChat ¶
func NewChat(th theme.Theme, now func() time.Time) *ChatController
NewChat builds an empty chat in follow mode.
func (*ChatController) Apply ¶
func (c *ChatController) Apply(msg btea.Msg)
Apply projects one bus message into the part list. Unknown messages are ignored; the projection is the only writer of parts.
func (*ChatController) Draw ¶
Draw paints the scrollback, or the landing wordmark while the chat is empty.
func (*ChatController) Empty ¶
func (c *ChatController) Empty() bool
Empty reports whether nothing has been said yet, which is what keeps the landing screen up.
func (*ChatController) Handle ¶
func (c *ChatController) Handle(a keys.Action, _ btea.KeyPressMsg) btea.Cmd
Handle runs a chat-scope key action.
func (*ChatController) Scroll ¶
func (c *ChatController) Scroll(delta int)
Scroll moves the window by a coalesced wheel delta.
func (*ChatController) SetTheme ¶
func (c *ChatController) SetTheme(th theme.Theme)
SetTheme swaps the palette by rebuilding the list; the memo is keyed by width and version, not theme, so a rebuild is the honest reset.
type Client ¶
type Client interface {
// NewSession creates a session in the current project.
NewSession(ctx context.Context, title string) (string, error)
// Sessions lists the project's sessions, newest first.
Sessions(ctx context.Context) ([]SessionInfo, error)
// Submit enqueues one user turn and returns its id.
Submit(ctx context.Context, session, text string) (string, error)
// Cancel aborts the running turn on a session.
Cancel(ctx context.Context, session string) error
// Respond answers a permission request: allow, allow_session, deny.
Respond(ctx context.Context, session, requestID, decision string) error
// MemoryIndex renders the live pinned index the ant carries every turn.
MemoryIndex(ctx context.Context) (string, error)
// MemorySearch runs the same ranked recall the loop runs.
MemorySearch(ctx context.Context, query string) ([]MemoryHit, error)
// MemoryForget archives a memory through the permission pipeline. The
// answer arrives as a permission request on the stream, so this blocks
// until the user resolves it. It reports whether a row was archived.
MemoryForget(ctx context.Context, session, id string) (bool, error)
}
Client is the slice of the core's session API the shell drives. It is declared here, not imported, because the UI never imports a core package (doc 02 section 1); cmd wires an adapter over the real core. Decisions and modes cross as their wire strings.
type Controller ¶
Controller handles a key action already matched in its scope. A nil return means the action produced no command; the root never forwards an unmatched key here.
type EditorController ¶
type EditorController struct {
// contains filtered or unexported fields
}
EditorController owns the prompt textarea, the external-editor hatch, and nothing else. Submitting goes through the submit callback the root injects, so the editor never sees the client.
func (*EditorController) Blur ¶
func (e *EditorController) Blur()
func (*EditorController) Focus ¶
func (e *EditorController) Focus() btea.Cmd
Focus and Blur hand the textarea the keyboard.
func (*EditorController) Handle ¶
func (e *EditorController) Handle(a keys.Action, _ btea.KeyPressMsg) btea.Cmd
Handle runs an editor-scope action.
func (*EditorController) Lines ¶
func (e *EditorController) Lines() int
Lines is the content height the layout grows the editor by.
func (*EditorController) SetValue ¶
func (e *EditorController) SetValue(s string)
SetValue replaces the buffer, used when the external editor returns.
func (*EditorController) Type ¶
func (e *EditorController) Type(msg btea.Msg) btea.Cmd
Type forwards a raw message to the textarea: typing, paste, blink.
func (*EditorController) Value ¶
func (e *EditorController) Value() string
Value reads the buffer, for tests and the cancel path.
type Layout ¶
type Layout struct {
Area uv.Rectangle
Header uv.Rectangle // compact mode's one-line stand-in for the sidebar
Sidebar uv.Rectangle
Main uv.Rectangle // the chat list
Pills uv.Rectangle // todos/queue/subagent tabs; zero height until M3
Editor uv.Rectangle
Status uv.Rectangle // help, status, and notifications share this line
Compact bool
}
Layout is the full set of screen regions for a frame. It is comparable, so the draw path recomputes it every frame and resizes children only when the new layout differs from the last.
func ComputeLayout ¶
ComputeLayout is pure: same inputs, same Layout. editorLines is the editor's content height; it grows the editor region between the bounds, and past the cap the textarea scrolls internally. forceCompact lets the user pin compact mode regardless of size.
type MemoryController ¶ added in v0.3.0
type MemoryController struct {
// contains filtered or unexported fields
}
MemoryController owns the memory panel: it opens it, feeds it the live index and search results off the client, tails fold events onto its log, and routes a forget through the client, which runs it past the permission pipeline. It holds a reference to the pushed panel so an async result lands on the dialog the user is looking at; the reference clears when the dialog closes.
func NewMemory ¶ added in v0.3.0
func NewMemory(client Client, th theme.Theme, ns string) *MemoryController
NewMemory builds the controller.
func (*MemoryController) Apply ¶ added in v0.3.0
func (mc *MemoryController) Apply(msg btea.Msg)
Apply folds a bus message into the panel. Only fold events matter here; the panel ignores the rest of the stream.
func (*MemoryController) Closed ¶ added in v0.3.0
func (mc *MemoryController) Closed()
Closed clears the panel reference when the overlay pops it on escape.
func (*MemoryController) Forget ¶ added in v0.3.0
func (mc *MemoryController) Forget(id, session string) btea.Cmd
Forget routes an archive through the client. The call blocks until the user resolves the permission request the pipeline raises, so it runs off the loop; the perm dialog stacks over the panel while it waits.
func (*MemoryController) OnForgot ¶ added in v0.3.0
func (mc *MemoryController) OnForgot(m memForgot) btea.Cmd
OnForgot refreshes the index after an archive so the row that left drops out of the pinned view. A denied forget archived nothing, so nothing changed.
func (*MemoryController) OnIndex ¶ added in v0.3.0
func (mc *MemoryController) OnIndex(m memIndexLoaded)
OnIndex lands a refreshed index on the panel.
func (*MemoryController) OnResults ¶ added in v0.3.0
func (mc *MemoryController) OnResults(m memResults)
OnResults lands a completed search on the panel.
func (*MemoryController) Open ¶ added in v0.3.0
Open pushes the panel and loads its index. An open dialog owns input, so a second memory keypress never reaches here; the panel closes on escape like every other dialog, which is what Closed clears up after.
func (*MemoryController) Search ¶ added in v0.3.0
func (mc *MemoryController) Search(query string) btea.Cmd
Search runs the archival recall off the update loop.
func (*MemoryController) SetTheme ¶ added in v0.3.0
func (mc *MemoryController) SetTheme(th theme.Theme)
SetTheme swaps the palette for a panel opened after the change.
type MemoryHit ¶ added in v0.3.0
MemoryHit is one row a memory search returned, shaped for the panel.
type Model ¶
type Model struct {
// contains filtered or unexported fields
}
Model is the root program: the only tea.Model in the tree. It owns size, state, focus, the overlay, and the theme, and fans everything else out to controllers (doc 02 section 18.1).
func (*Model) SetKeymap ¶
SetKeymap swaps the live bindings. The next keypress matches against the new map and the help line reads it, no restart involved.
type Options ¶
type Options struct {
Client Client
Theme theme.Theme
Keys keys.Map
FirstRun bool // no config and no nest: run onboarding
Cwd string // shown in the sidebar
Model string // the configured model, pre-ledger
Provider string // the configured provider
Effort string // reasoning effort, empty when unset
Models []string // pickable models for the picker
ContextWindow int64 // tokens, for the context fill figure
Session string // resume: next turns go here, "" starts fresh
Namespace string // the worker ant's memory namespace, for the panel
Drops func() uint64 // the broker's lossy-lane drop counter
Onboarded func(splash.Outcome) error // persists first-run choices
Now func() time.Time // tests pin this
}
Options wires the root to everything it must not construct itself.
type PermController ¶
type PermController struct {
// contains filtered or unexported fields
}
PermController turns permission events into dialogs and decisions into client calls. It is the only place a perm.Choice becomes a wire word. The session a request arrived on rides with the request id, so the answer lands on the right session even if the user switched away.
func NewPerm ¶
func NewPerm(client Client, th theme.Theme) *PermController
NewPerm builds the controller.
func (*PermController) Request ¶
func (p *PermController) Request(m bus.PermissionRequestedMsg, overlay *dialog.Overlay, now time.Time)
Request pushes a dialog for an incoming permission request.
func (*PermController) Resolve ¶
func (p *PermController) Resolve(d perm.Decision) btea.Cmd
Resolve sends the user's decision to the core.
func (*PermController) Resolved ¶
func (p *PermController) Resolved(m bus.PermissionResolvedMsg, overlay *dialog.Overlay, now time.Time)
Resolved pops the dialog when the core resolved the request some other way, a rule or a timeout, so a stale prompt never lingers.
func (*PermController) SetTheme ¶
func (p *PermController) SetTheme(th theme.Theme)
SetTheme swaps the palette for dialogs opened after the change.
type Router ¶
type Router struct{}
Router decides which scope owns input this frame. It is a table, not a switch: precedence is dialog > focused pane > global, resolved before any key is matched, which is the fix for the giant root-model key switch (doc 02 section 18.2).
func (Router) Route ¶
func (Router) Route(m *Model) (keys.Scope, Controller)
Route resolves the scope and the controller that owns it. A dialog owns input entirely; its keys never reach a pane. The nil controller for the dialog case is deliberate: the overlay handles the raw message itself, grace period and all.
type SessionInfo ¶
SessionInfo is one row of the session switcher.
type SidebarController ¶
type SidebarController struct {
// contains filtered or unexported fields
}
SidebarController projects bus messages into the sidebar's state. The numbers it shows come from the ledger events, never from client-side recounting (D5, D14).
func NewSidebar ¶
func NewSidebar(th theme.Theme, o Options) *SidebarController
NewSidebar seeds the panel with what the shell knows before any event arrives.
func (*SidebarController) Apply ¶
func (s *SidebarController) Apply(msg btea.Msg)
Apply folds one bus message into the state.
func (*SidebarController) SetModel ¶
func (s *SidebarController) SetModel(name string)
SetModel records a picked model name.
func (*SidebarController) SetTheme ¶
func (s *SidebarController) SetTheme(th theme.Theme)
SetTheme swaps the palette.
func (*SidebarController) ToggleDebug ¶
func (s *SidebarController) ToggleDebug()
ToggleDebug flips the drop-counter surface.
type State ¶
type State int
State is where the shell is in its life: first-run onboarding, the empty landing screen, or a live chat (doc 02 section 18.3).
type StatusController ¶
type StatusController struct {
// contains filtered or unexported fields
}
StatusController owns the bottom line: the current scope's short help, covered by transient notifications with a time-to-live (doc 02 section 12.4). One line serves as help, status, and notification.
func (*StatusController) Expire ¶
func (s *StatusController) Expire()
Expire clears the note once its deadline passed.
func (*StatusController) Notify ¶
func (s *StatusController) Notify(level, text string) btea.Cmd
Notify covers the help line with a message and schedules its expiry.
func (*StatusController) SetKeymap ¶
func (s *StatusController) SetKeymap(km keys.Map)
SetKeymap swaps the live bindings, so a rebind shows on the next draw.
func (*StatusController) SetTheme ¶
func (s *StatusController) SetTheme(th theme.Theme)
SetTheme swaps the palette.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package bus bridges the core's event stream to the UI program (doc 02 section 3).
|
Package bus bridges the core's event stream to the UI program (doc 02 section 3). |
|
Package chatlist is the lazy chat scrollback (doc 02 section 5).
|
Package chatlist is the lazy chat scrollback (doc 02 section 5). |
|
Package dialog is the modal layer (doc 02 section 8).
|
Package dialog is the modal layer (doc 02 section 8). |
|
Package diff renders unified diff text into styled lines, shared by the edit-result chat renderer and the permission prompt (doc 02 section 9).
|
Package diff renders unified diff text into styled lines, shared by the edit-result chat renderer and the permission prompt (doc 02 section 9). |
|
Package input holds the pieces that sit between the terminal and the update loop (doc 02 section 14): a filter that coalesces high-rate mouse traffic so a wheel flick cannot starve the keyboard, and the external editor escape hatch for prompts that outgrow a textarea.
|
Package input holds the pieces that sit between the terminal and the update loop (doc 02 section 14): a filter that coalesces high-rate mouse traffic so a wheel flick cannot starve the keyboard, and the external editor escape hatch for prompts that outgrow a textarea. |
|
Package keys is the binding registry (doc 02 section 12).
|
Package keys is the binding registry (doc 02 section 12). |
|
Package markdown renders assistant prose.
|
Package markdown renders assistant prose. |
|
Package memory is the memory panel (doc 07, plan 03 slice 11): a modal dialog that shows what the colony remembers.
|
Package memory is the memory panel (doc 07, plan 03 slice 11): a modal dialog that shows what the colony remembers. |
|
Package parts is the render model: the UI draws exactly one data structure, the ordered list of typed parts that make up a session's messages, projected from the core's events with no second schema (doc 02 section 4).
|
Package parts is the render model: the UI draws exactly one data structure, the ordered list of typed parts that make up a session's messages, projected from the core's events with no second schema (doc 02 section 4). |
|
Package perm is the permission dialog (doc 02 section 9).
|
Package perm is the permission dialog (doc 02 section 9). |
|
Package picker is the one filterable list dialog: the model picker, the session switcher, and the command palette are all a Dialog with different items and a different ID (doc 02 section 7.1).
|
Package picker is the one filterable list dialog: the model picker, the session switcher, and the command palette are all a Dialog with different items and a different ID (doc 02 section 7.1). |
|
Package sidebar is the live ops panel (doc 02 section 13.1): a fixed width column of stacked sections reading from state the root projects out of core events.
|
Package sidebar is the live ops panel (doc 02 section 13.1): a fixed width column of stacked sections reading from state the root projects out of core events. |
|
Onboarding: a short sequence of dialogs on the overlay stack (doc 02 section 19.2).
|
Onboarding: a short sequence of dialogs on the overlay stack (doc 02 section 19.2). |
|
Package tea holds the one rendering contract every widget in the UI implements: paint yourself onto cells within a rectangle (doc 02 section 2.5).
|
Package tea holds the one rendering contract every widget in the UI implements: paint yourself onto cells within a rectangle (doc 02 section 2.5). |
|
Package theme is the semantic palette layer (doc 02 section 10, D18).
|
Package theme is the semantic palette layer (doc 02 section 10, D18). |