Help us shape the future of Go! Take the 2026 Go Developer Survey

tui

package
v0.0.14 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2026 License: MIT Imports: 35 Imported by: 0

Documentation

Overview

Package tui is the terminal client: a Bubble Tea model over the view reconciler. It renders what view.Model says, committed rows plainly and in-flight rows marked as such, and turns keys into [client.Intent]s it sends its client.Controller. It holds nothing it can act on and keeps no runs of its own: whether a run goes is the view's, from the events, with a mark between sending a prompt or an answer and seeing its run start.

Concurrency

The controller returns promptly; each intent is sent in a tea.Cmd and reported with an [intentDoneMsg] when it is refused. The view is fed by Attach on goroutines of its own and reaches the model only as ModelMsg values, which share nothing with the view. The model itself is touched by the program's goroutine alone.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Attach

func Attach(ctx context.Context, rec client.Record, src client.Source, send func(tea.Msg)) (wait func())

Attach follows the record rec and the live stream of src (client.Live) into a view.View and delivers each resulting view.Model through send, as a ModelMsg; with a program, send is its Send method.

The view is not safe for concurrent use, and the two streams arrive on goroutines of their own, so every step is applied under one lock, and the model is taken and sent inside it: the program sees the models in the order the steps were applied. It cannot be applied from the program's goroutine instead. A record change's session is valid only until the follow takes its next step, so the change has to be applied before the iterator is resumed, and the program runs behind it.

The live stream subscribes before Attach returns, so a run started right after misses no event. The returned function waits for both goroutines, which stop when ctx is done.

func Clipboard

func Clipboard(w io.Writer) func(string)

Clipboard is a copier that puts text on the terminal's clipboard with OSC 52, writing to the writer the program renders to. The sequence is a command the terminal executes, not output: it takes no space on the screen, so writing it beside a frame cannot corrupt the frame.

Types

type FeedErrMsg

type FeedErrMsg struct {
	Stream string
	Err    error
}

FeedErrMsg reports that the record or the live stream failed. The feed of that stream has stopped.

type InterruptMsg

type InterruptMsg struct{}

InterruptMsg is an interrupt from outside the terminal, SIGINT or SIGTERM: it does what Ctrl-C does with nothing selected — a signal always interrupts, never copies. The host turns the program's own signal handling off (tea.WithoutSignalHandler) and sends this instead, since bubbletea's ends the program with an error and no abort.

type Line added in v0.0.10

type Line struct {
	// Text is what was typed, without the space around it.
	Text string
	// Running is whether a run was going when the line was taken up.
	Running bool
}

Line is a line the user submitted in the input.

type Model

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

Model is the Bubble Tea model.

func New

func New(ctx context.Context, rec client.Record, src client.Source, act client.Controller, options ...Option) *Model

New returns the model of the agent whose session rec follows and whose events src gives, which sends what the user asks to act. The caller starts Attach with the program's Send; ctx is the context of every intent.

func (*Model) Drain

func (m *Model) Drain(timeout time.Duration) bool

Drain waits until the controller has answered every intent the model sent and the source reports no run going, or timeout, and reports whether both happened. A host calls it after the program ends and the run was aborted, before it closes the store the run is writing its end to. Call it only once the program has stopped sending messages to the model.

func (*Model) Init

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

Init implements tea.Model. The textarea's styles and the markdown's (glamour's dark or light) depend on whether the terminal's background is dark, which the terminal is asked for.

func (*Model) Update

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

Update implements tea.Model.

func (*Model) View

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

View implements tea.Model. The program takes the whole screen and reports the mouse, motion with a button down included, for selecting.

type ModelMsg

type ModelMsg struct{ Model view.Model }

ModelMsg carries what the view renders after one more step of the record or the live stream. The feed sends one per step, in the order the steps were applied.

type Option

type Option func(*Model)

Option configures New.

func WithCopier

func WithCopier(fn func(string)) Option

WithCopier sets where a copied selection goes. Without one a selection is still drawn, but nothing is copied.

func WithCost

func WithCost(fn client.Cost) Option

WithCost sets the function that prices one model call, in US dollars; it feeds the session pane's total. Without it the pane shows tokens but no cost.

func WithSubmit added in v0.0.10

func WithSubmit(fn func(context.Context, Line) (Submission, error)) Option

WithSubmit hands each line the user submits to fn, which decides what it is. fn runs off the program's goroutine, one line at a time in the order they were submitted; its error is shown and the line is given back to the input. Without it, a line is a prompt when idle and a steer while a run goes.

func WithToolRenderers added in v0.0.8

func WithToolRenderers(rs toolview.Renderers) Option

WithToolRenderers sets the renderers of the tools' calls, by tool name; a call to any other tool shows its arguments as key=value pairs.

type Submission added in v0.0.10

type Submission struct {
	Prompt   []openresponses.Item
	Steer    []openresponses.Item
	FollowUp []openresponses.Item
	Reply    string
}

Submission is what the model does with a line, as the submit function decided: a prompt starts a run, a steer queues into the one going, a follow-up queues for when the run would stop, and a reply is shown over the input. A reply may come with any one of them; an empty submission does nothing.

Jump to

Keyboard shortcuts

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