Documentation
¶
Overview ¶
Package tui implements bee's interactive Bubbletea interface.
Startup banner art — minimal sigils, no emoji.
Package tui implements the bubbletea-driven interactive UI for bee.
Visual primitives live here: hex glyphs and the honey palette. Slice 3A composes Hive + Workspace via NewHive / NewWorkspace factories.
Inline ! / !! shell exec from the editor. The default bang behavior is configurable (cfg.ShellBangSilent — silent by default). `!!cmd` always runs in the opposite mode, so users can override per-invocation either way. Execution goes through the same shell tool the model uses so the permission/sandbox model stays consistent.
Package tui implements bee's interactive Bubbletea interface.
Palette follows the charmbracelet/crush approach: a layered neutral scale (multiple foreground subtleties × multiple background layers) with a single brand accent. Bee swaps crush's purple for honey amber. Hex values are inlined so we don't take a charmtone dependency.
Index ¶
- Constants
- Variables
- func AppendHistory(text string)
- func BrailleSparkline(vals []float64, cells int) string
- func CompletionCandidates(dir, prefix string) []string
- func FuzzyFiles(root, needle string) []string
- func HexRow(states []BeeState, names []string, width int) string
- func HighlightCode(content, lang string) string
- func HighlightLineByPath(line, path string) string
- func InstallModifyOtherKeys(out io.Writer) (io.Reader, func())
- func LoadHistory() []string
- func LongestCommonPrefix(ss []string) string
- func PersistPick(path string, provider, model string) error
- func PersistSetting(path string, key string, value any) error
- func ReadClipboardImage() ([]byte, error)
- func RenderBanner(version, model string) string
- func RenderBannerCompact(version, model string) string
- func RenderBannerVariant(v BannerVariant, version, model string) string
- func Run(ctx context.Context, eng *loop.Engine) error
- func RunSeeded(ctx context.Context, eng *loop.Engine, reg *commands.Registry, km KeyMap, ...) error
- func RunSeededAsker(ctx context.Context, eng *loop.Engine, reg *commands.Registry, km KeyMap, ...) error
- func RunWithCommands(ctx context.Context, eng *loop.Engine, reg *commands.Registry) error
- func RunWithCommandsAndKeyMap(ctx context.Context, eng *loop.Engine, reg *commands.Registry, km KeyMap) error
- func RunWithCommandsKeyMapApprover(ctx context.Context, eng *loop.Engine, reg *commands.Registry, km KeyMap, ...) error
- type AgentRow
- type AgentView
- func (a *AgentView) Close()
- func (a *AgentView) Init() tea.Cmd
- func (a *AgentView) IsOpen() bool
- func (a *AgentView) Open()
- func (a *AgentView) Refresh()
- func (a *AgentView) Render(width, height int) string
- func (a *AgentView) Rows() []AgentRow
- func (a *AgentView) SubmitReply(text string) error
- func (a *AgentView) Update(msg tea.Msg) (*AgentView, tea.Cmd)
- type ApprovalAskMsg
- type ApprovalDecision
- type ApprovalDecisionMsg
- type ApprovalModel
- type ApprovalRequest
- type Approver
- type AskAnswerMsg
- type AskModel
- type AskShowMsg
- type Asker
- type AtPickerDismissedMsg
- type AtPickerModel
- type AtPickerSelectMsg
- type AttachSessionMsg
- type BannerVariant
- type Bee
- type BeeState
- type CloseAgentViewMsg
- type CostPane
- type DrawilleCanvas
- type EffortPane
- type HistoryDismissedMsg
- type HistoryPickerModel
- type HistorySelectMsg
- type Hive
- type IntroFrame
- type IntroStyle
- type KeyMap
- type LoaderStyle
- type LoginPane
- type Model
- func (m Model) Init() tea.Cmd
- func (m Model) Update(msg tea.Msg) (resultModel tea.Model, resultCmd tea.Cmd)
- func (m Model) View() string
- func (m Model) WithApprover(a *Approver) Model
- func (m Model) WithAsker(a *Asker) Model
- func (m Model) WithCommands(r *commands.Registry) Model
- func (m Model) WithCompact(v bool) Model
- func (m Model) WithCostTracker(t *cost.Tracker) Model
- func (m Model) WithHighlight(v bool) Model
- func (m Model) WithInitialMessages(msgs []types.Message) Model
- func (m Model) WithIntro(style IntroStyle) Model
- func (m Model) WithKeyMap(km KeyMap) Model
- func (m Model) WithLiveMsgCh(ch chan types.Message) Model
- func (m Model) WithSeedPrompt(text string) Model
- func (m Model) WithShellBangSilent(v bool) Model
- func (m Model) WithShowBanner(v bool) Model
- func (m Model) WithShowBee(v bool) Model
- func (m Model) WithShowContextBar(v bool) Model
- func (m Model) WithShowContextPct(v bool) Model
- func (m Model) WithShowCwd(v bool) Model
- func (m Model) WithShowEffort(v bool) Model
- func (m Model) WithShowGitBranch(v bool) Model
- func (m Model) WithShowLoader(v bool) Model
- func (m Model) WithShowModel(v bool) Model
- func (m Model) WithShowNudges(v bool) Model
- func (m Model) WithShowRecap(v bool) Model
- func (m Model) WithShowThoughts(v bool) Model
- func (m Model) WithShowTotalTokens(v bool) Model
- func (m Model) WithShowTurnTimer(v bool) Model
- func (m Model) WithSkills(sk SkillsLister) Model
- func (m Model) WithStreamCh(ch chan string) Model
- func (m Model) WithThinkCh(ch chan string) Model
- func (m Model) WithVerbose(v bool) Model
- func (m Model) WithWarnCh(ch chan string) Model
- type ModelLister
- type OpenAgentViewMsg
- type PaletteDismissedMsg
- type PaletteEntry
- type PaletteEntryKind
- type PaletteModel
- type PaletteSelectMsg
- type PickedMsg
- type Picker
- type PickerDismissedMsg
- type PickerLoginRequestedMsg
- type ResumeDismissedMsg
- type ResumeEntry
- type ResumePicker
- func (p *ResumePicker) Entries() []ResumeEntry
- func (p *ResumePicker) Hide()
- func (p *ResumePicker) Init() tea.Cmd
- func (p *ResumePicker) Open() bool
- func (p *ResumePicker) Selected() int
- func (p *ResumePicker) SetEntries(e []ResumeEntry)
- func (p *ResumePicker) Show()
- func (p *ResumePicker) Update(msg tea.Msg) (*ResumePicker, tea.Cmd)
- func (p *ResumePicker) View(width, height int) string
- type ResumeSelectMsg
- type SessionCloneMsg
- type SessionForkMsg
- type SessionSwitchMsg
- type SessionTree
- func (t *SessionTree) Init() tea.Cmd
- func (t *SessionTree) LoadMessages(msgs []types.Message, currentLeafID string)
- func (t *SessionTree) Open() bool
- func (t *SessionTree) Selected() string
- func (t *SessionTree) SetRoot(root *types.MessageNode, currentLeafID string)
- func (t *SessionTree) Update(msg tea.Msg) (*SessionTree, tea.Cmd)
- func (t *SessionTree) View(width, height int) string
- type SettingsPane
- type SettingsSnapshot
- type SkillsLister
- type State
- type StreamRenderer
- func (r *StreamRenderer) ClipStreamingTail(rendered string, maxRows int) string
- func (r *StreamRenderer) RenderCompacting(frame int) string
- func (r *StreamRenderer) RenderMessage(m types.Message) string
- func (r *StreamRenderer) RenderStreaming(partial string, frame int) string
- func (r *StreamRenderer) RenderStreamingChunk(chunk string, styleMarkdown bool) string
- func (r *StreamRenderer) RenderThinkingPartial(s string) string
- func (r *StreamRenderer) SetCompact(v bool)
- func (r *StreamRenderer) SetHighlight(v bool)
- func (r *StreamRenderer) SetLoaderStyle(s LoaderStyle)
- func (r *StreamRenderer) SetShowLoader(v bool)
- func (r *StreamRenderer) SetShowNudges(v bool)
- func (r *StreamRenderer) SetShowThoughts(v bool)
- func (r *StreamRenderer) SetVerbose(v bool)
- type Styles
- type ToggleCostPaneMsg
- type ToggleHiveMsg
- type ToggleLoginPaneMsg
- type ToggleResumePickerMsg
- type ToggleSessionTreeMsg
- type ToggleWorkspaceMsg
- type ToolsPane
- type UpdateDecision
- type UpdatePrompt
- type Workspace
- func (w *Workspace) ClearDiff()
- func (w *Workspace) Init() tea.Cmd
- func (w *Workspace) Path() string
- func (w *Workspace) SetDiff(unified string) error
- func (w *Workspace) SetFile(path string) error
- func (w *Workspace) SetVisible(v bool)
- func (w *Workspace) Update(msg tea.Msg) (*Workspace, tea.Cmd)
- func (w *Workspace) View(width, height int) string
- func (w *Workspace) Visible() bool
Constants ¶
const ( HexFilled = "⬢" HexHollow = "⬢" ColorHoneyGold = "#F2B233" ColorAmber = "#E08A1E" ColorDim = "#5F5F5F" ColorAccent = "#FFE066" ColorDanger = "#D9534F" ColorAddFg = "#7FBF6B" ColorDelFg = "#D9534F" ColorMuted = "#888888" )
Hex glyphs (PLAN §8b.1) and honey palette.
const IntroStyleDefault = IntroStyleBloom
IntroStyleDefault is the value used when BEE_BANNER is unset.
Variables ¶
var ( StyleActive = fg(ColorHoneyGold).Bold(true) StyleAwaiting = fg(ColorAccent).Bold(true) StyleIdle = fg(ColorAmber) StyleDone = fg(ColorDim) StyleFailed = fg(ColorDanger).Bold(true) StyleLabel = fg(ColorMuted) )
Pre-built styles. Public so 3A may compose without redefining.
var Commit = ""
Commit is the build-time short sha of the running binary. cmd/bee sets it at process start; "" or "dev" disables the upstream probe (developer builds shouldn't auto-prompt against main).
var Version = "0.1.0"
Version is the bee build version surfaced in the intro placeholder after the startup animation finishes. cmd/bee sets it at process start so the linker-injected build tag flows through. Default kept in sync with main.
Functions ¶
func AppendHistory ¶
func AppendHistory(text string)
AppendHistory atomically appends a single entry to ~/.bee/history. Skips empty / whitespace-only lines. Trims to historyMax if the file gets large.
func BrailleSparkline ¶
BrailleSparkline returns a one-line braille sparkline of vals normalized to [0, h] pixels. width is in braille cells (each cell encodes 2 samples × 4 vertical levels). Empty input returns "".
func CompletionCandidates ¶
CompletionCandidates returns names in dir starting with prefix.
func FuzzyFiles ¶
FuzzyFiles returns paths under root containing needle (case-insensitive). Skips hidden .folders, node_modules, vendor, worktrees. Caps at fuzzyMax results.
func HighlightCode ¶
HighlightCode returns content with ANSI syntax-highlight escapes wrapped around tokens. lang is a chroma lexer name ("go", "javascript", "bash", "diff"…) or "" to auto-detect by content. On any failure it returns the input unchanged — never errors out of a render path.
func HighlightLineByPath ¶
HighlightLineByPath highlights a single line using the lexer matching the given file path's extension. Used by per-line render paths (diff bodies, edit previews) that hand chroma one logical line at a time.
func InstallModifyOtherKeys ¶
InstallModifyOtherKeys turns on xterm modifyOtherKeys level 1 on the provided writer (typically os.Stdout) and wraps os.Stdin in a translator that decodes the resulting CSI sequences into the bytes bubbletea's parser recognises. The returned io.Reader is suitable for tea.WithInput. The returned cleanup func writes the disable sequence — defer it before tea.Program.Run returns so the terminal is left in a sane state.
When stdout is not a TTY the function is a no-op and returns os.Stdin unwrapped + a no-op cleanup; piped invocations stay clean.
func LoadHistory ¶
func LoadHistory() []string
LoadHistory reads ~/.bee/history newest-first, dedupes consecutive entries.
func LongestCommonPrefix ¶
LongestCommonPrefix returns the longest string that is a prefix of every input.
func PersistPick ¶
PersistPick rewrites ~/.bee/config.toml so the next launch defaults to the chosen provider+model.
Trade-off: we do NOT recreate the live Engine mid-session. The choice is durable, but takes effect on the next bee run. Live swap would require draining tool-call state cleanly in loop/turn.go.
func PersistSetting ¶
PersistSetting rewrites ~/.bee/config.toml setting top-level key=value while preserving every other field. Used by /settings to make verbosity / thought visibility toggles survive across launches. key must be a top-level TOML key (no dotted paths). value must be a TOML-encodable scalar.
func ReadClipboardImage ¶
ReadClipboardImage returns the raw image bytes from the system clipboard or an error if no image is available (or the clipboard backend is missing).
func RenderBanner ¶
RenderBanner legacy entry — delegates to hex variant. model arg accepted for api compatibility but ignored; the live top status bar already shows `provider/model cwd`, so the splash stays trim.
func RenderBannerCompact ¶
RenderBannerCompact returns a single-line banner for headless mode. model arg accepted for api compatibility but not rendered (same rationale as the full banner — status bar already carries it).
func RenderBannerVariant ¶
func RenderBannerVariant(v BannerVariant, version, model string) string
RenderBannerVariant returns a styled startup banner. version optional. model arg accepted for api compatibility but no longer rendered — model identity already lives on the persistent top status bar, so the splash stays minimal (sigil + "bee <version>").
func Run ¶
Run builds and runs the bubbletea program with the given engine. Blocks until the program exits (Ctrl+C or tea.Quit). Uses the default (built-in) slash command set.
func RunSeeded ¶
func RunSeeded(ctx context.Context, eng *loop.Engine, reg *commands.Registry, km KeyMap, app *Approver, seed string) error
RunSeeded is RunWithCommandsKeyMapApprover plus an optional seed prompt that auto-submits one turn on startup (skill dispatch into the TUI). Pass "" for no auto-submit.
func RunSeededAsker ¶
func RunSeededAsker(ctx context.Context, eng *loop.Engine, reg *commands.Registry, km KeyMap, app *Approver, asker *Asker, seed string) error
RunSeededAsker is RunSeeded plus the ask_user picker adapter. Pass nil to leave ask_user auto-resolving to the recommended option.
func RunWithCommands ¶
RunWithCommands is Run with a caller-provided command registry. Pass nil to get the built-in set. Uses DefaultKeyMap — callers wanting user overrides should use RunWithCommandsAndKeyMap.
func RunWithCommandsAndKeyMap ¶
func RunWithCommandsAndKeyMap(ctx context.Context, eng *loop.Engine, reg *commands.Registry, km KeyMap) error
RunWithCommandsAndKeyMap is RunWithCommands plus a caller-supplied keymap. Pass DefaultKeyMap() to keep stock bindings.
func RunWithCommandsKeyMapApprover ¶
func RunWithCommandsKeyMapApprover(ctx context.Context, eng *loop.Engine, reg *commands.Registry, km KeyMap, app *Approver) error
RunWithCommandsKeyMapApprover is RunWithCommandsAndKeyMap plus the channel approver that surfaces dangerous-command prompts in the modal. Pass nil for the legacy no-gating behavior.
Types ¶
type AgentView ¶
type AgentView struct {
// contains filtered or unexported fields
}
AgentView is the multi-bee management pane (Left arrow / Ctrl+H). List + peek + inline reply. Refreshes every tick so live bg bees update.
func NewAgentView ¶
func NewAgentView() *AgentView
func (*AgentView) SubmitReply ¶
type ApprovalAskMsg ¶
ApprovalAskMsg asks the TUI to surface the modal for a flagged command.
type ApprovalDecision ¶
type ApprovalDecision string
ApprovalDecision is the user's verdict on a permission request.
const ( ApprovalAllow ApprovalDecision = "allow" // run once ApprovalSession ApprovalDecision = "session" // run + cache for session ApprovalAlways ApprovalDecision = "always" // run + persist to config ApprovalDeny ApprovalDecision = "deny" )
type ApprovalDecisionMsg ¶
type ApprovalDecisionMsg struct {
UseID string
Decision ApprovalDecision
}
ApprovalDecisionMsg is the tea.Msg published once the user chooses. Engine subscribes via the channel from RegisterApproval.
type ApprovalModel ¶
type ApprovalModel struct {
Active bool
Request ApprovalRequest
// contains filtered or unexported fields
}
ApprovalModel is a self-contained component embedded in the main Model. When Active is false it renders nothing.
func NewApprovalModel ¶
func NewApprovalModel(styles Styles, keys KeyMap) ApprovalModel
NewApprovalModel returns a fresh, inactive modal.
func (*ApprovalModel) Hide ¶
func (m *ApprovalModel) Hide()
Hide closes the modal without publishing a decision.
func (*ApprovalModel) SetOutput ¶
func (m *ApprovalModel) SetOutput(ch chan<- ApprovalDecisionMsg)
SetOutput wires the engine-facing channel. Pass nil to detach.
func (*ApprovalModel) Show ¶
func (m *ApprovalModel) Show(req ApprovalRequest)
Show opens the modal for the given request.
func (ApprovalModel) Update ¶
func (m ApprovalModel) Update(msg tea.Msg) (ApprovalModel, tea.Cmd)
Update handles modal key events. Returns the updated model + an optional cmd that publishes the decision message to the program. Caller forwards the cmd.
func (ApprovalModel) View ¶
func (m ApprovalModel) View() string
View renders the modal box. The parent overlays it on the main view.
type ApprovalRequest ¶
type ApprovalRequest struct {
ToolName string
Action string // human-readable: "run shell: rm -rf /tmp/x"
Reason string // why the cmd was flagged, e.g. "recursive delete"
Key string // safety.DangerousPattern key, for session + persistent cache
UseID string // request id, echoed back in the decision
}
ApprovalRequest is what the Engine (eventually) hands to the modal.
type Approver ¶
type Approver struct {
// contains filtered or unexported fields
}
Approver implements approval.Approver by routing requests through the TUI.
Call site lives in shell.Tool (or any other tool) which runs on the engine goroutine. Request sends an ApprovalAskMsg to the bubbletea program, then blocks on a per-request reply channel. The Model handles the msg by Show()ing the modal; once the user picks, the resulting ApprovalDecisionMsg is fed back through Resolve which unblocks the caller.
Construct with NewApprover; call SetProgram after tea.NewProgram returns its handle. Until SetProgram is called every Request returns Deny so the engine can't accidentally race the TUI startup.
func NewApprover ¶
func NewApprover() *Approver
NewApprover returns an unwired approver. Call SetProgram to attach the tea program once tea.NewProgram has returned.
func (*Approver) Request ¶
Request blocks until the user picks a decision in the TUI modal. Returns Deny if the program is unset or the context is cancelled.
func (*Approver) Resolve ¶
func (a *Approver) Resolve(useID string, d ApprovalDecision)
Resolve delivers a user decision back to the blocked Request call. Called by the Model when an ApprovalDecisionMsg arrives. Unknown ids are dropped.
func (*Approver) SetProgram ¶
SetProgram wires the tea.Program handle. Safe to call before or after the program is running.
type AskAnswerMsg ¶
AskAnswerMsg is published once the user picks. The Model forwards it to Asker.Resolve to unblock the tool.
type AskModel ¶
type AskModel struct {
Active bool
// contains filtered or unexported fields
}
AskModel is the ask_user picker: a vertical list of options plus an optional "type my own answer" row. Self-contained component embedded in the main Model; renders nothing when inactive. Communicates the pick back through the engine-facing channel, mirroring ApprovalModel.
func NewAskModel ¶
NewAskModel returns a fresh, inactive picker.
func (*AskModel) Hide ¶
func (m *AskModel) Hide()
Hide closes the picker without publishing an answer.
func (*AskModel) SetOutput ¶
func (m *AskModel) SetOutput(ch chan<- AskAnswerMsg)
SetOutput wires the engine-facing channel. Pass nil to detach.
func (*AskModel) Show ¶
Show opens the picker for a question, defaulting focus to the recommended option so enter accepts it immediately.
type AskShowMsg ¶
AskShowMsg asks the TUI to surface the picker for a question.
type Asker ¶
type Asker struct {
// contains filtered or unexported fields
}
Asker implements ask.Asker by routing questions through the TUI picker.
The ask_user tool runs on the engine goroutine: Ask sends an AskShowMsg to the bubbletea program, then blocks on a per-request reply channel. The Model shows the picker; once the user chooses, the AskAnswerMsg is fed back through Resolve which unblocks the caller.
Construct with NewAsker; call SetProgram after tea.NewProgram returns. Until then every Ask auto-resolves via ask.Static so the loop never wedges.
func NewAsker ¶
func NewAsker() *Asker
NewAsker returns an unwired asker. Call SetProgram to attach the tea program.
func (*Asker) Ask ¶
Ask blocks until the user answers in the TUI picker. Falls back to the recommended option (ask.Static) if the program is unset, and on context cancellation returns a dismissed answer.
func (*Asker) Resolve ¶
Resolve delivers a user answer back to the blocked Ask call. Called by the Model when an AskAnswerMsg arrives. Unknown ids are dropped.
func (*Asker) SetProgram ¶
SetProgram wires the tea.Program handle. Safe to call before or after the program is running.
type AtPickerDismissedMsg ¶
type AtPickerDismissedMsg struct{}
AtPickerDismissedMsg is emitted when the user escapes the picker.
type AtPickerModel ¶
type AtPickerModel struct {
Active bool
// contains filtered or unexported fields
}
AtPickerModel is the @-triggered fuzzy file picker. Renders inline above the input bar — same dense strip as the slash palette.
func NewAtPicker ¶
func NewAtPicker(root string) AtPickerModel
NewAtPicker returns an inactive picker rooted at root.
func (*AtPickerModel) SetWidth ¶
func (p *AtPickerModel) SetWidth(w int)
SetWidth tells the picker how wide a row may be.
func (AtPickerModel) Update ¶
func (p AtPickerModel) Update(msg tea.Msg) (AtPickerModel, tea.Cmd)
Update handles picker key events.
func (AtPickerModel) View ¶
func (p AtPickerModel) View() string
View renders the picker as a dense strip above the input bar.
type AtPickerSelectMsg ¶
type AtPickerSelectMsg struct{ Path string }
AtPickerSelectMsg is emitted when the user picks a path.
type AttachSessionMsg ¶
type AttachSessionMsg struct{ ID string }
type BannerVariant ¶
type BannerVariant int
BannerVariant selects which startup banner art to render. random picks one per launch so a new shell feels alive without committing to one aesthetic.
const ( BannerHex BannerVariant = iota // diamond sigil (default) BannerSwarm // small constellation BannerComb // honeycomb sliver BannerFlower // radial sigil )
func ParseBannerVariant ¶
func ParseBannerVariant(s string) BannerVariant
ParseBannerVariant maps BEE_BANNER values to a variant. "random" / "" / unknown returns a pseudo-random pick seeded from the clock.
type Bee ¶
Bee is one entry in the hive — either a live in-process session or a historical session pulled from disk via session.List().
type CloseAgentViewMsg ¶
type CloseAgentViewMsg struct{}
type CostPane ¶
type CostPane struct {
// contains filtered or unexported fields
}
CostPane is the Ctrl+Y modal: session total, recent-turn sparkline, and a filterable breakdown by model / provider.
func NewCostPane ¶
NewCostPane returns a closed pane wired to the given tracker. Tracker may be nil — then the pane renders an empty state.
type DrawilleCanvas ¶
type DrawilleCanvas struct {
// contains filtered or unexported fields
}
DrawilleCanvas is a binary pixel buffer that renders as braille text. Out-of-bounds pixel writes are silently clipped so sprite painters can overflow the edge without bounds checks.
func NewDrawilleCanvas ¶
func NewDrawilleCanvas(w, h int) *DrawilleCanvas
NewDrawilleCanvas allocates a canvas of the given pixel dimensions.
func (*DrawilleCanvas) DrawSprite ¶
func (c *DrawilleCanvas) DrawSprite(sprite []byte, w, h, ox, oy int)
DrawSprite paints a row-major binary sprite onto the canvas at (ox, oy). Pixels outside the canvas are clipped. Non-zero sprite bytes light up.
func (*DrawilleCanvas) Height ¶
func (c *DrawilleCanvas) Height() int
Height returns canvas height in pixels.
func (*DrawilleCanvas) SetPixel ¶
func (c *DrawilleCanvas) SetPixel(x, y int, on bool)
SetPixel turns one pixel on (true) or off (false). Out-of-bounds is a no-op so animations can sweep sprites past the edge cleanly.
func (*DrawilleCanvas) ToBraille ¶
func (c *DrawilleCanvas) ToBraille() string
ToBraille renders the canvas as multi-line braille text. Lines are separated by \n; each line is exactly cellsW runes wide.
func (*DrawilleCanvas) Width ¶
func (c *DrawilleCanvas) Width() int
Width returns canvas width in pixels.
type EffortPane ¶
type EffortPane struct {
// contains filtered or unexported fields
}
EffortPane is a modal picker for reasoning effort. Arrow keys pick, enter sets, esc closes without change.
func (*EffortPane) SetCurrent ¶
func (p *EffortPane) SetCurrent(v string)
SetCurrent updates the stored current value (called after commit).
func (*EffortPane) Show ¶
func (p *EffortPane) Show(current string)
Show opens the picker with the current effort highlighted.
func (*EffortPane) Update ¶
func (p *EffortPane) Update(msg tea.Msg) (*EffortPane, tea.Cmd)
Update handles key events.
func (*EffortPane) View ¶
func (p *EffortPane) View(width, height int) string
View renders the modal.
type HistoryDismissedMsg ¶
type HistoryDismissedMsg struct{}
HistoryDismissedMsg signals the picker closed without a pick.
type HistoryPickerModel ¶
type HistoryPickerModel struct {
Active bool
// contains filtered or unexported fields
}
HistoryPickerModel is the fzf-style reverse history search picker, rendered inline above the input bar in the same dense palette style as /model.
func NewHistoryPicker ¶
func NewHistoryPicker() HistoryPickerModel
NewHistoryPicker returns an inactive picker. Entries load lazily on Show.
func (*HistoryPickerModel) SetWidth ¶
func (p *HistoryPickerModel) SetWidth(w int)
SetWidth records terminal width so rows truncate cleanly. Mirrors palette/picker.
func (*HistoryPickerModel) Show ¶
func (p *HistoryPickerModel) Show(initial string)
Show activates the picker, reloads history from disk, and resets the cursor.
func (HistoryPickerModel) Update ¶
func (p HistoryPickerModel) Update(msg tea.Msg) (HistoryPickerModel, tea.Cmd)
Update handles picker key events.
func (HistoryPickerModel) View ¶
func (p HistoryPickerModel) View() string
View renders the picker as a borderless dense strip — same aesthetic as the slash palette + /model picker. Crumb, filter input, palette rows, hint.
type HistorySelectMsg ¶
type HistorySelectMsg struct{ Text string }
HistorySelectMsg pastes the chosen entry into the main input.
type Hive ¶
type Hive struct {
// contains filtered or unexported fields
}
Hive is the bubbletea component that owns the hex strip and the full `Ctrl+H` view. It does not spawn bees itself (Wave 4); for v0.1 the data list is populated from session.List() plus whatever the host model registers via Set / Upsert.
func NewHive ¶
func NewHive() *Hive
NewHive returns a Hive seeded with on-disk sessions (best-effort). 3A constructs this via `NewHive()` and embeds it into its Model.
func (*Hive) Render ¶
Render returns the one-line hex strip. Active first, awaiting next, then idle, then done. Truncates to maxStrip entries; further capped by width.
func (*Hive) RenderFull ¶
RenderFull renders the Ctrl+H full hive view: a 3-wide hex grid of active bees followed by a list of recent sessions.
type IntroFrame ¶
IntroFrame is one rendered frame of the startup animation.
type IntroStyle ¶
type IntroStyle int
IntroStyle controls which animation plays on startup.
const ( IntroStyleRandom IntroStyle = iota // pick one of the concrete styles per launch IntroStyleLifecycle // egg → larva → pupa → flight IntroStyleSwarm // swarm of dots IntroStyleHex // hex outline orbit IntroStyleDance // waggle dance figure-8 IntroStyleDrip // honey drop + ripple IntroStyleBloom // pollen converge → hex frame + bee → pulse rings IntroStyleConstell // constellation: dots twinkle into hex tessellation IntroStyleRain // honey-drop rain at staggered columns IntroStyleSpiral // single particle traces inward spiral with trail IntroStyleWave // sine wave sweep with crest cluster IntroStyleOrbit // three particles orbit a center at different radii )
func ParseIntroStyle ¶
func ParseIntroStyle(s string) IntroStyle
ParseIntroStyle maps BEE_BANNER values to a style.
type KeyMap ¶
type KeyMap struct {
Submit key.Binding
Quit key.Binding
Cancel key.Binding
ProviderPick key.Binding
WorkspaceTog key.Binding
HiveOpen key.Binding
SessionTree key.Binding
CostOpen key.Binding
SlashPalette key.Binding
HistorySearch key.Binding
CavemanCycle key.Binding
ThinkingCycle key.Binding
ModeCycle key.Binding
ApproveAllow key.Binding
ApproveSession key.Binding
ApproveAlways key.Binding
ApproveDeny key.Binding
// SteerNow: enter while streaming — injects a mid-turn user steer.
// shares the "enter" key with Submit; dispatch is state-dependent.
SteerNow key.Binding
// FollowUp: alt+enter queues a follow-up that fires after the current
// turn finishes (works in idle or streaming).
FollowUp key.Binding
// ImagePaste: ctrl+i stages an image from the system clipboard for the
// next submit. bubbletea's raw-paste support is unreliable in many
// terminals, hence the explicit chord.
ImagePaste key.Binding
}
KeyMap centralises every binding the TUI listens to. Other slices (workspace, hive, provider picker) just consume the same struct.
func DefaultKeyMap ¶
func DefaultKeyMap() KeyMap
DefaultKeyMap returns the default keyboard chord set.
func LoadKeyMap ¶
LoadKeyMap returns DefaultKeyMap merged with overrides from <home>/keybindings.json. Missing or malformed file returns defaults silently. Unknown field names are ignored so users can pin to old configs safely.
type LoaderStyle ¶
type LoaderStyle int
LoaderStyle selects which braille animation runs while waiting on the first token. Default is the phased pipeline (chill → swarm → orbit → ripple → starfield) which evolves the longer the wait runs. Named values pin a single painter.
const ( LoaderStyleDefault LoaderStyle = iota // phased: pulse → swarm → orbit → ripple → starfield LoaderStylePulse // centered bee, gentle wing flap LoaderStyleSwarm // multi-particle swarm, scales with width LoaderStyleWave // layered sine waves LoaderStyleComet // bright head + decaying tail LoaderStyleHex // rotating hexagonal outline LoaderStyleRipple // concentric ellipses expanding LoaderStyleRain // falling drops LoaderStyleOrbit // particles on elliptical orbit LoaderStyleBreath // bar expanding/contracting from center LoaderStyleStars // drifting starfield LoaderStyleForage // bees leave hive, drift, return LoaderStyleFigure8 // waggle-dance lemniscate LoaderStyleVortex // 3 nested rotating rings LoaderStyleGust // swarm in wind with gust spikes LoaderStyleScatter // alarm dispersal + regroup LoaderStyleFlock // 3 cohesive bee clusters LoaderStyleDNA // double helix LoaderStyleMatrix // variable-speed vertical streams LoaderStyleHeartbeat // EKG flatline + spike LoaderStyleLightning // sudden bolt + decay LoaderStyleSnake // segments chasing head LoaderStyleFireworks // radiating bursts with gravity LoaderStyleDrunk // bee wobbles, drank fermented honey LoaderStyleJar // bee trapped, bouncing off jar walls LoaderStyleConga // bee conga line, undulating march LoaderStyleQueen // queen + 4 attendants procession LoaderStyleDrip // fat honey droplet + accumulating pool LoaderStyleMarathon // bees racing toward finish line )
func ParseLoaderStyle ¶
func ParseLoaderStyle(s string) LoaderStyle
ParseLoaderStyle maps BEE_LOADER values to a style. Unset / "random" / unknown → phased default. Legacy aliases (swarm/comb/dance/drip) map to their nearest braille equivalent so old configs keep working.
type LoginPane ¶
type LoginPane struct {
// contains filtered or unexported fields
}
LoginPane is the interactive /login modal. Lists providers vertically; arrow keys move; enter triggers OAuth or (for non-oauth providers with an env_key) switches to an inline text input for the api key; d/x removes the saved token AND any saved key file; r refreshes status; esc closes.
func NewLoginPane ¶
NewLoginPane returns a closed pane bound to the TUI side. side may be nil; the pane renders an empty state in that case.
func (*LoginPane) SelectProvider ¶
SelectProvider points the cursor at the named provider AND, if the provider has an api-key (non-oauth) auth scheme, jumps straight into the key-input sub-mode. Used by the picker's auth-error escape hatch so the user lands directly on the relevant prompt.
func (*LoginPane) Show ¶
func (p *LoginPane) Show()
Show opens the pane and refreshes status from the side.
type Model ¶
type Model struct {
// contains filtered or unexported fields
}
Model is the bubbletea root model for bee's interactive REPL.
func NewModel ¶
NewModel constructs an idle TUI model. eng may be nil for unit tests. A built-in slash command registry is created and seeded — callers that want a custom set should call WithCommands on the returned Model.
func (Model) Init ¶
Init satisfies tea.Model. Returns the blink cmd so the cursor pulses, plus the stream pump when a delta channel is wired and a flush of any resumed-session messages so they land in native scrollback at startup.
func (Model) View ¶
View renders the live region only — top bar, streaming partial (if any), error line (if any), input row, and key hints. Finalized messages live in the terminal's native scrollback via tea.Println; we never repaint past turns. The live region grows while streaming, shrinks when idle.
func (Model) WithApprover ¶
WithApprover attaches the channel adapter that routes dangerous-command prompts through the TUI modal. The shell tool holds the same handle and blocks on Request until Resolve fires.
func (Model) WithAsker ¶
WithAsker attaches the channel adapter that routes ask_user questions through the TUI picker. The ask_user tool holds the same handle and blocks on Ask until Resolve fires.
func (Model) WithCommands ¶
WithCommands swaps in a caller-provided registry. The palette is rebuilt against it so Ctrl+K shows the new set. Skills source is preserved.
func (Model) WithCompact ¶
WithCompact seeds compact-mode rendering. Env/config-driven path.
func (Model) WithCostTracker ¶
WithCostTracker wires the engine's cost.Tracker into the model so the top bar and the /cost pane can read it.
func (Model) WithHighlight ¶
WithHighlight seeds chroma syntax-highlighting state. Config-driven path.
func (Model) WithInitialMessages ¶
WithInitialMessages preloads scrollback. Used by `bee back <id>` to restore a prior session into the TUI on launch. The messages get flushed to terminal scrollback via tea.Println from Init().
func (Model) WithIntro ¶
func (m Model) WithIntro(style IntroStyle) Model
WithIntro enables the non-blocking startup animation. Frames are built lazily on the first tick once width is known. BEE_NO_INTRO=1 disables.
func (Model) WithKeyMap ¶
WithKeyMap swaps in a caller-provided keymap. Used to fold in user overrides from ~/.bee/keybindings.json without changing NewModel's signature. Approval modal is rebuilt because it holds its own copy of the keys.
func (Model) WithLiveMsgCh ¶
WithLiveMsgCh wires a live-message channel from the engine into the TUI. The same channel must be set on Engine.LiveMsgCh so assistant + tool messages render as they're persisted, not only at Run completion.
func (Model) WithSeedPrompt ¶
WithSeedPrompt arms a one-shot auto-submit fired from Init. Used by skill dispatch to start a turn live in the TUI (e.g. "/research <topic>").
func (Model) WithShellBangSilent ¶
WithShellBangSilent seeds the bang default behavior. Config-driven path.
func (Model) WithShowBanner ¶
WithShowBanner seeds the intro-animation flag. Toggling at runtime only affects the NEXT launch — the startup animation is one-shot.
func (Model) WithShowBee ¶
WithShowBee seeds top-bar bee-glyph visibility. Config-driven path.
func (Model) WithShowContextBar ¶
WithShowContextBar seeds context-bar visibility. Config-driven path.
func (Model) WithShowContextPct ¶
WithShowContextPct seeds top-bar percent-label visibility.
func (Model) WithShowCwd ¶
WithShowCwd seeds top-bar cwd visibility.
func (Model) WithShowEffort ¶
WithShowEffort seeds top-bar effort-badge visibility.
func (Model) WithShowGitBranch ¶
WithShowGitBranch seeds top-bar git-branch chip visibility.
func (Model) WithShowLoader ¶
WithShowLoader seeds the streaming-loader visibility. Config-driven path.
func (Model) WithShowModel ¶
WithShowModel seeds top-bar model-name visibility.
func (Model) WithShowNudges ¶
WithShowNudges seeds nudge-visibility from config. Default false hides the loop's [nudge] recovery turns; setting true reveals them.
func (Model) WithShowRecap ¶
WithShowRecap seeds the post-turn recap toggle from config. Default false so recaps are explicitly opt-in (extra tokens per turn).
func (Model) WithShowThoughts ¶
WithShowThoughts seeds chain-of-thought visibility. Config-driven path.
func (Model) WithShowTotalTokens ¶
WithShowTotalTokens seeds top-bar session-tokens chip visibility.
func (Model) WithShowTurnTimer ¶
WithShowTurnTimer seeds top-bar turn-timer chip visibility.
func (Model) WithSkills ¶
func (m Model) WithSkills(sk SkillsLister) Model
WithSkills wires a skills source into the palette so the picker can list commands and skills side-by-side. *skills.Registry already satisfies SkillsLister, so callers usually pass their loaded registry directly.
func (Model) WithStreamCh ¶
WithStreamCh wires a text-delta channel from the engine into the TUI. The same channel must be set on Engine.StreamCh so deltas flow.
func (Model) WithThinkCh ¶
WithThinkCh wires a reasoning-delta channel from the engine into the TUI so chain-of-thought renders live during streaming. Same channel must be set on Engine.ThinkCh so deltas flow.
func (Model) WithVerbose ¶
WithVerbose seeds verbose tool-output rendering. CLI flag/env var path.
func (Model) WithWarnCh ¶
WithWarnCh wires the engine's transient-notice channel into the TUI so stream hiccups + retries surface as a fading line in chrome.
type ModelLister ¶
type ModelLister func(ctx context.Context, name string, cfg config.ProviderConfig) ([]llm.Model, error)
ModelLister is the seam the picker uses to fetch a provider's catalogue.
type OpenAgentViewMsg ¶
type OpenAgentViewMsg struct{}
type PaletteDismissedMsg ¶
type PaletteDismissedMsg struct{}
PaletteDismissedMsg is emitted when the user presses esc.
type PaletteEntry ¶
type PaletteEntry struct {
Name string
Description string
Kind PaletteEntryKind
}
PaletteEntry is one row in the palette: either a slash command or a skill.
type PaletteEntryKind ¶
type PaletteEntryKind int
PaletteEntryKind distinguishes between a slash command and a skill in the merged palette pool.
const ( EntryCommand PaletteEntryKind = iota EntrySkill )
type PaletteModel ¶
type PaletteModel struct {
Active bool
// contains filtered or unexported fields
}
PaletteModel is the fzf-style picker. It merges slash commands and skills into one pool, fuzzy-matches against typed input, and renders highlighted matched runes.
func NewPalette ¶
func NewPalette(cmds *commands.Registry, sk SkillsLister) PaletteModel
NewPalette returns an inactive palette bound to the given registry and optional skills source. Either side may be nil.
func (*PaletteModel) Bump ¶
func (p *PaletteModel) Bump(name string)
Bump records that name was just dispatched so future palette openings rank it higher. Called by the slash dispatcher for both commands and skills.
func (*PaletteModel) SetFilter ¶
func (p *PaletteModel) SetFilter(s string)
SetFilter mirrors the filter from the main input bar — typing lives there now, palette just shows the ranked list. Resets selection on change.
func (*PaletteModel) SetWidth ¶
func (p *PaletteModel) SetWidth(w int)
SetWidth tells the palette how wide a row may be. Set from the app's WindowSizeMsg handler so rows truncate cleanly on narrow layouts.
func (*PaletteModel) Show ¶
func (p *PaletteModel) Show(initial string)
Show activates the palette, rebuilds the entry pool, and applies an initial filter. The initial string pre-fills the filter — used when the user typed "/hlp" in the main bar and we open the palette pre-filtered.
func (PaletteModel) Update ¶
func (p PaletteModel) Update(msg tea.Msg) (PaletteModel, tea.Cmd)
Update handles palette key events. Returns the updated palette and an optional cmd to forward (PaletteSelectMsg or PaletteDismissedMsg).
func (PaletteModel) View ¶
func (p PaletteModel) View() string
View renders the palette as a borderless, dense strip designed to sit directly above the input bar. Width is taken from SetWidth — falls back to a sensible default when unset (e.g. tests).
type PaletteSelectMsg ¶
type PaletteSelectMsg struct {
Name string
Kind PaletteEntryKind
}
PaletteSelectMsg carries the chosen entry. Parent decides how to dispatch (command vs skill).
type PickedMsg ¶
type PickedMsg struct{ Provider, Model string }
PickedMsg is published when the user selects a provider+model combo.
type Picker ¶
type Picker struct {
// contains filtered or unexported fields
}
Picker is the fzf-style two-stage selector: filter providers → filter that provider's models. Looks and types like the `/` palette.
func (*Picker) SetLister ¶
func (p *Picker) SetLister(l ModelLister)
SetLister overrides the model-fetch function. Tests use this.
func (*Picker) Show ¶
Show opens the picker on the provider stage and kicks off an async load for the highlighted provider so models are ready by the time the user advances to stage 2.
type PickerDismissedMsg ¶
type PickerDismissedMsg struct{}
PickerDismissedMsg is published when the user hits Esc without picking.
type PickerLoginRequestedMsg ¶
type PickerLoginRequestedMsg struct{ Provider string }
PickerLoginRequestedMsg is published when the user hits `l` from the picker's auth-error stage, asking the app to open the LoginPane on the failing provider.
type ResumeDismissedMsg ¶
type ResumeDismissedMsg struct{}
ResumeDismissedMsg fires when the user closes without selecting.
type ResumeEntry ¶
ResumeEntry is one row in the resume picker.
type ResumePicker ¶
type ResumePicker struct {
// contains filtered or unexported fields
}
ResumePicker is the modal that lists past sessions newest-first and lets the user pick one with arrow keys + Enter. Esc/q dismisses.
func NewResumePicker ¶
func NewResumePicker() *ResumePicker
NewResumePicker returns an inactive picker.
func (*ResumePicker) Entries ¶
func (p *ResumePicker) Entries() []ResumeEntry
Entries exposes the current list (for tests + view).
func (*ResumePicker) Selected ¶
func (p *ResumePicker) Selected() int
Selected returns the cursor index.
func (*ResumePicker) SetEntries ¶
func (p *ResumePicker) SetEntries(e []ResumeEntry)
SetEntries lets tests inject a deterministic list.
func (*ResumePicker) Show ¶
func (p *ResumePicker) Show()
Show loads sessions from disk and opens the modal.
func (*ResumePicker) Update ¶
func (p *ResumePicker) Update(msg tea.Msg) (*ResumePicker, tea.Cmd)
Update handles key events while open.
func (*ResumePicker) View ¶
func (p *ResumePicker) View(width, height int) string
View renders the picker. Title + list + footer hint.
type ResumeSelectMsg ¶
type ResumeSelectMsg struct{ ID string }
ResumeSelectMsg carries the chosen session id back to the host.
type SessionCloneMsg ¶
type SessionCloneMsg struct{}
SessionCloneMsg requests a clone of the entire current session.
type SessionForkMsg ¶
type SessionForkMsg struct{ FromID string }
SessionForkMsg requests a fork at FromID (or full if empty).
type SessionSwitchMsg ¶
type SessionSwitchMsg struct{ LeafID string }
SessionSwitchMsg requests the host swap the active leaf to LeafID.
type SessionTree ¶
type SessionTree struct {
// contains filtered or unexported fields
}
SessionTree is the Ctrl+T modal — renders the parent-pointer message tree for one session, highlighting the active branch. Supports cursor nav with Up/Down, Enter to switch active leaf, F to fork, C to clone, Esc to close.
func NewSessionTree ¶
func NewSessionTree() *SessionTree
NewSessionTree constructs an empty tree modal.
func (*SessionTree) LoadMessages ¶
func (t *SessionTree) LoadMessages(msgs []types.Message, currentLeafID string)
LoadMessages rebuilds the tree from a flat message slice.
func (*SessionTree) Selected ¶
func (t *SessionTree) Selected() string
Selected returns the id of the cursor-highlighted node (empty if none).
func (*SessionTree) SetRoot ¶
func (t *SessionTree) SetRoot(root *types.MessageNode, currentLeafID string)
SetRoot lets a caller pass an already-built tree.
func (*SessionTree) Update ¶
func (t *SessionTree) Update(msg tea.Msg) (*SessionTree, tea.Cmd)
Update reacts to ToggleSessionTreeMsg and (when open) key events.
func (*SessionTree) View ¶
func (t *SessionTree) View(width, height int) string
View renders the tree. If no tree loaded, prints a friendly stub.
type SettingsPane ¶
type SettingsPane struct {
// contains filtered or unexported fields
}
SettingsPane is a modal toggling persistent TUI settings. Arrow keys move cursor, enter/space flips the focused row, anything else types into the fuzzy filter. Each flip applies live and writes to ~/.bee/config.toml so the next launch picks the same values up.
func NewSettingsPane ¶
func NewSettingsPane() *SettingsPane
NewSettingsPane returns a closed settings pane.
func (*SettingsPane) Show ¶
func (p *SettingsPane) Show(s SettingsSnapshot)
Show opens the pane seeded with the live values.
func (*SettingsPane) Update ¶
func (p *SettingsPane) Update(msg tea.Msg) (*SettingsPane, tea.Cmd)
Update handles key events.
func (*SettingsPane) View ¶
func (p *SettingsPane) View(width, height int) string
View renders the modal.
type SettingsSnapshot ¶
type SettingsSnapshot struct {
Verbose bool
ShowThoughts bool
ShowNudges bool
ShowRecap bool
Compact bool
ShowContextBar bool
Highlight bool
ShellBangSilent bool
ShowBee bool
ShowContextPct bool
ShowModel bool
ShowCwd bool
ShowEffort bool
ShowTurnTimer bool
ShowGitBranch bool
ShowTotalTokens bool
ShowBanner bool
ShowLoader bool
}
SettingsSnapshot is the live values handed to Show. Grouped into a struct because the top-bar toggles pushed the positional-arg list past readable.
type SkillsLister ¶
SkillsLister is the seam the palette uses to fetch skills. Tests inject a stub; *skills.Registry already satisfies it. Get is also used by the slash dispatcher to resolve "/<name>" against the skill registry when no built-in command matches.
type StreamRenderer ¶
type StreamRenderer struct {
// contains filtered or unexported fields
}
StreamRenderer turns Messages and live deltas into styled strings. It is an append-only view buffer — callers feed it events and read View().
func NewStreamRenderer ¶
func NewStreamRenderer(styles Styles, width int) *StreamRenderer
NewStreamRenderer builds a renderer. width is the wrap target; pass 0 for glamour's default (80). Loader style is taken from BEE_LOADER (swarm / comb / dance / drip); unset / "random" → random pick at construction.
func (*StreamRenderer) ClipStreamingTail ¶
func (r *StreamRenderer) ClipStreamingTail(rendered string, maxRows int) string
ClipStreamingTail keeps the last maxRows visual rows of a rendered streaming chunk, prepending a `… +N lines above` header when content was dropped. Visual rows are computed against r.width so soft-wrapped long lines count correctly; bubbletea's inline renderer cannot reach above the cursor, so without this the head of a long partial gets clipped out of sight while it grows. maxRows <= 0 is a no-op (caller has no budget info). With progressive flush active, complete leading lines get pushed to scrollback before this fires — clipping only trims the unflushed tail.
func (*StreamRenderer) RenderCompacting ¶
func (r *StreamRenderer) RenderCompacting(frame int) string
RenderCompacting draws the /compact-specific loader. Three braille swarm variants reuse the same particle/sine techniques as the "generating" loaders so memory-being-squeezed reads as live bees, not a static bar. The variant is rolled on frame 0 per run.
func (*StreamRenderer) RenderMessage ¶
func (r *StreamRenderer) RenderMessage(m types.Message) string
RenderMessage formats a single message for the scrollback. Glyph and the first body line share one row; continuation lines indent under the body column. Dense by design — `▸ yo yo` reads as one unit.
Each ContentBlock renders independently; results are right-trimmed and joined on a single newline so neighbouring blocks never collide on the same row (the original concat-without-separator caused text to share a line with the following tool card). Interior blank runs are collapsed so glamour padding or stray `\n\n\n` from the model can't spill hundreds of empty rows into terminal scrollback.
func (*StreamRenderer) RenderStreaming ¶
func (r *StreamRenderer) RenderStreaming(partial string, frame int) string
RenderStreaming returns the partial-text view while the model emits deltas. frame drives both the pre-token loader animation (empty partial) and the trailing caret animation (non-empty partial) — see animatedCaret for the rationale: a static caret looked "stopped" during in-stream pauses (reasoning, slow tool-call generation, network stalls between deltas).
The partial is rendered as RAW text (not glamour-markdown). Re-rendering a growing buffer through glamour on every delta reflows word-wrap and shifts indent as markdown tokens (`-`, `*`, ```` ``` ````) come into being mid- stream — visually the text "jumps" and indentation breaks. Markdown styling is applied once the turn finishes in RenderMessage. Continuation lines are indented 2 cols so they align under the body column, not the role glyph.
func (*StreamRenderer) RenderStreamingChunk ¶
func (r *StreamRenderer) RenderStreamingChunk(chunk string, styleMarkdown bool) string
RenderStreamingChunk formats a settled head of a streaming partial for emission to terminal scrollback via tea.Println. Mirrors RenderStreaming's gutter treatment but drops the trailing caret (the cursor isn't here anymore) and the leading blank row (rest of the partial keeps streaming in the live region right below). Used by the progressive-flush path so the head of a long response stays readable while the tail keeps growing.
styleMarkdown=true routes the chunk through glamour so prose paragraphs keep their headings, lists, bold, and link styling once they hit scroll- back. Callers pass false when the chunk straddles an open ``` fence — partial code blocks render unpredictably through glamour, and raw output preserves any inline ANSI the model already painted (git log colors, chroma highlight, etc).
func (*StreamRenderer) RenderThinkingPartial ¶
func (r *StreamRenderer) RenderThinkingPartial(s string) string
RenderThinkingPartial is the live-streaming variant of renderThinking used by the in-flight view region. Same dim/italic styling so the live block visually matches the finalized scrollback render once the turn commits. Empty result when thoughts are hidden or no content remains after sanitize.
func (*StreamRenderer) SetCompact ¶
func (r *StreamRenderer) SetCompact(v bool)
SetCompact toggles compact mode. When true, RenderMessage and friends emit the dense pre-pi layout (no outer gutter, no inter-turn blank line, no user bg-tint, no OSC 133 prompt zones). Default false = clean mode.
func (*StreamRenderer) SetHighlight ¶
func (r *StreamRenderer) SetHighlight(v bool)
SetHighlight toggles chroma syntax-highlighting across diff/file/bash previews. Off returns raw content; on (default) emits ANSI-colored tokens.
func (*StreamRenderer) SetLoaderStyle ¶
func (r *StreamRenderer) SetLoaderStyle(s LoaderStyle)
SetLoaderStyle picks which pre-token loader animation to render.
func (*StreamRenderer) SetShowLoader ¶
func (r *StreamRenderer) SetShowLoader(v bool)
SetShowLoader toggles the streaming "generating" animation. Off swaps the braille loader/caret for a static ⬢ marker so the row still signals activity without motion.
func (*StreamRenderer) SetShowNudges ¶
func (r *StreamRenderer) SetShowNudges(v bool)
SetShowNudges toggles rendering of synthetic `[nudge]` user messages. Off (default) collapses them out of scrollback; the loop still injects them so the provider sees the same conversation.
func (*StreamRenderer) SetShowThoughts ¶
func (r *StreamRenderer) SetShowThoughts(v bool)
SetShowThoughts toggles BlockThinking chain-of-thought rendering. Off hides reasoning blocks entirely from scrollback; on (default) shows them dimmed and italicized.
func (*StreamRenderer) SetVerbose ¶
func (r *StreamRenderer) SetVerbose(v bool)
SetVerbose toggles full tool-output rendering. Compact (default) keeps the preview at one line; verbose lets the whole output through.
type Styles ¶
type Styles struct {
TopBar lipgloss.Style // dim chrome — bee glyph carries the accent
BottomBar lipgloss.Style
Scope lipgloss.Style
RoleYou lipgloss.Style
RoleBee lipgloss.Style
RoleTool lipgloss.Style
ToolCard lipgloss.Style
ToolName lipgloss.Style // lilac, bold — distinguishes from honey AI + blue user
ToolArgs lipgloss.Style
ToolPrev lipgloss.Style
ToolRail lipgloss.Style // lilac left rail beside tool-output lines
DiffAdd lipgloss.Style // green `+` line for inserted text in edit previews
DiffDel lipgloss.Style // red `-` line for removed text in edit previews
DiffAddBg lipgloss.Style // pale green wash behind whole `+` diff row
DiffDelBg lipgloss.Style // pale red wash behind whole `-` diff row
DiffPath lipgloss.Style // bold path header above diff body
DiffMeta lipgloss.Style // dimmed meta line (occurrence, anchors, hunk hdrs)
Thought lipgloss.Style // grayed italic — model's chain-of-thought
Modal lipgloss.Style
ModalTitle lipgloss.Style
Button lipgloss.Style
ButtonHot lipgloss.Style
Error lipgloss.Style
ErrorCmd lipgloss.Style // failed-bash command rendered on red bg highlight
Warn lipgloss.Style // refused/denied body text (permission blocked, not broken)
WarnCmd lipgloss.Style // refused command rendered on yellow bg highlight
WarnBadge lipgloss.Style // pill badge for the escalate card title
WarnRail lipgloss.Style // mustard left rail beside escalate body lines
Dim lipgloss.Style
Body lipgloss.Style // base prose
UserBubble lipgloss.Style // (legacy) full-width warm tint — retained for callers
UserRail lipgloss.Style // blue left rail beside user-turn lines
UserBody lipgloss.Style // bold blue prose for the user-turn body
}
Styles bundles every reusable lipgloss style.
func DefaultStyles ¶
func DefaultStyles() Styles
DefaultStyles returns the layered honey-on-charmtone palette.
type ToggleCostPaneMsg ¶
type ToggleCostPaneMsg struct{}
ToggleCostPaneMsg flips the pane visibility.
type ToggleResumePickerMsg ¶
type ToggleResumePickerMsg struct{}
ToggleResumePickerMsg flips visibility.
type ToggleSessionTreeMsg ¶
type ToggleSessionTreeMsg struct{}
ToggleSessionTreeMsg flips visibility.
type ToolsPane ¶
type ToolsPane struct {
// contains filtered or unexported fields
}
ToolsPane is a modal listing every registered tool with a toggle. Arrow keys move the cursor; enter/space flips the focused row. Each flip applies live and persists to ~/.bee/config.toml under disabled_tools. Mirrors the SettingsPane shape so users see the same modal grammar.
type UpdateDecision ¶
type UpdateDecision int
UpdateDecision is the user's verdict on an "update available" prompt.
const ( UpdateLater UpdateDecision = iota // close modal; re-check next interval UpdateNow // apply now (this session) UpdateAlways // persist update_check=auto + apply now UpdateNeverAsk // persist update_check=off + stop probing )
type UpdatePrompt ¶
UpdatePrompt is the four-button modal surfaced when Probe finds main ahead.
func NewUpdatePrompt ¶
func NewUpdatePrompt(styles Styles) UpdatePrompt
NewUpdatePrompt returns an inactive prompt.
func (*UpdatePrompt) Hide ¶
func (p *UpdatePrompt) Hide()
Hide closes without publishing a decision.
func (*UpdatePrompt) Show ¶
func (p *UpdatePrompt) Show(info update.Info)
Show opens the modal with the probed info.
func (UpdatePrompt) Update ¶
func (p UpdatePrompt) Update(msg tea.Msg) (UpdatePrompt, tea.Cmd)
Update handles modal key events. Returns the updated prompt + an optional cmd carrying the decision; caller forwards the cmd. Esc dismisses as "later".
func (UpdatePrompt) View ¶
func (p UpdatePrompt) View() string
View renders the modal. Caller overlays it on the main view.
type Workspace ¶
type Workspace struct {
// contains filtered or unexported fields
}
Workspace is the right-pane file/diff preview. Toggled by Ctrl+W in 3A. SetFile loads file contents; SetDiff overlays a unified-diff annotation (additions green, deletions red, context dim). Both are optional — calling SetDiff without SetFile renders the diff alone.
func NewWorkspace ¶
func NewWorkspace() *Workspace
NewWorkspace constructs a Workspace. 3A embeds this in its top-level Model.
func (*Workspace) SetDiff ¶
SetDiff parses a unified-diff and stores the first file's fragments. If the diff is empty or malformed it returns an error.
func (*Workspace) SetVisible ¶
SetVisible forces a state (for direct host control).
Source Files
¶
- agent_view.go
- app.go
- app_builders.go
- app_flush.go
- app_format.go
- app_goal.go
- app_keys.go
- app_keys_submit.go
- app_new.go
- app_pumps.go
- app_run.go
- app_slash.go
- app_update.go
- app_update_gates.go
- app_update_panes.go
- app_update_pickers.go
- app_update_session.go
- app_update_stream.go
- app_update_update.go
- approval.go
- approver.go
- ask.go
- asker.go
- atpicker.go
- atref.go
- banner.go
- braille_frames.go
- braille_frames_ambient.go
- braille_frames_bee.go
- braille_frames_extra.go
- braille_frames_swarm.go
- cmd_usage.go
- cost.go
- cost_render.go
- csi_input.go
- drawille.go
- effort.go
- hex.go
- highlight.go
- history.go
- hive.go
- imagepaste.go
- inlineexec.go
- intro.go
- intro_bloom.go
- intro_extra.go
- intro_lifecycle.go
- intro_motion.go
- keybindings_file.go
- keymap.go
- login.go
- login_view.go
- model.go
- palette.go
- palette_view.go
- picker.go
- picker_items.go
- picker_match.go
- picker_persist.go
- picker_view.go
- resume.go
- session_tree.go
- settings.go
- side.go
- side_auth.go
- side_chrome.go
- side_settings.go
- side_tools.go
- stream.go
- stream_args.go
- stream_diff.go
- stream_diff_lcs.go
- stream_diff_previews.go
- stream_loader.go
- stream_markdown.go
- stream_message.go
- stream_shell.go
- stream_streaming.go
- stream_toolresult.go
- stream_tooluse.go
- style.go
- tools_pane.go
- update.go
- update_prompt.go
- util.go
- view.go
- view_chrome.go
- view_context.go
- view_misc.go
- workspace.go