modes

package
v0.3.2 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: MIT Imports: 43 Imported by: 0

Documentation

Overview

Package modes contains coding-agent run-mode orchestration.

Index

Constants

This section is empty.

Variables

View Source
var AppKeybindingDefinitions = []tui.KeybindingDefinition{
	{ID: "app.interrupt", DefaultKeys: []tui.KeyID{"escape"}, Description: "Cancel or abort"},
	{ID: "app.clear", DefaultKeys: []tui.KeyID{"ctrl+c"}, Description: "Clear editor"},
	{ID: "app.exit", DefaultKeys: []tui.KeyID{"ctrl+d"}, Description: "Exit when editor is empty"},
	{ID: "app.suspend", DefaultKeys: []tui.KeyID{"ctrl+z"}, Description: "Suspend to background"},
	{ID: "app.thinking.cycle", DefaultKeys: []tui.KeyID{"shift+tab"}, Description: "Cycle thinking level"},
	{ID: "app.model.cycleForward", DefaultKeys: []tui.KeyID{"ctrl+p"}, Description: "Cycle to next model"},
	{ID: "app.model.cycleBackward", DefaultKeys: []tui.KeyID{"shift+ctrl+p"}, Description: "Cycle to previous model"},
	{ID: "app.model.select", DefaultKeys: []tui.KeyID{"ctrl+l"}, Description: "Open model selector"},
	{ID: "app.tools.expand", DefaultKeys: []tui.KeyID{"ctrl+o"}, Description: "Toggle tool output"},
	{ID: "app.thinking.toggle", DefaultKeys: []tui.KeyID{"ctrl+t"}, Description: "Toggle thinking blocks"},
	{ID: "app.session.toggleNamedFilter", DefaultKeys: []tui.KeyID{"ctrl+n"}, Description: "Toggle named session filter"},
	{ID: "app.editor.external", DefaultKeys: []tui.KeyID{"ctrl+g"}, Description: "Open external editor"},
	{ID: "app.message.copy", DefaultKeys: []tui.KeyID{"ctrl+x"}, Description: "Copy message to clipboard"},
	{ID: "app.message.followUp", DefaultKeys: []tui.KeyID{"alt+enter"}, Description: "Queue follow-up message"},
	{ID: "app.message.dequeue", DefaultKeys: []tui.KeyID{"alt+up"}, Description: "Restore queued messages"},
	{ID: "app.clipboard.pasteImage", DefaultKeys: []tui.KeyID{"ctrl+v"}, Description: "Paste image from clipboard"},
	{ID: "app.session.new", DefaultKeys: nil, Description: "Start a new session"},
	{ID: "app.session.tree", DefaultKeys: nil, Description: "Open session tree"},
	{ID: "app.session.fork", DefaultKeys: nil, Description: "Fork current session"},
	{ID: "app.session.resume", DefaultKeys: nil, Description: "Resume a session"},
	{ID: "app.tree.foldOrUp", DefaultKeys: []tui.KeyID{"ctrl+left", "alt+left"}, Description: "Fold tree branch or move up"},
	{ID: "app.tree.unfoldOrDown", DefaultKeys: []tui.KeyID{"ctrl+right", "alt+right"}, Description: "Unfold tree branch or move down"},
	{ID: "app.tree.editLabel", DefaultKeys: []tui.KeyID{"shift+l"}, Description: "Edit tree label"},
	{ID: "app.tree.toggleLabelTimestamp", DefaultKeys: []tui.KeyID{"shift+t"}, Description: "Toggle tree label timestamps"},
	{ID: "app.session.togglePath", DefaultKeys: []tui.KeyID{"ctrl+p"}, Description: "Toggle session path display"},
	{ID: "app.session.toggleSort", DefaultKeys: []tui.KeyID{"ctrl+s"}, Description: "Toggle session sort"},
	{ID: "app.session.rename", DefaultKeys: []tui.KeyID{"ctrl+r"}, Description: "Rename session"},
	{ID: "app.session.delete", DefaultKeys: []tui.KeyID{"ctrl+d"}, Description: "Delete session"},
	{ID: "app.session.deleteNoninvasive", DefaultKeys: []tui.KeyID{"alt+d"}, Description: "Delete session (no confirm)"},
	{ID: "app.models.save", DefaultKeys: []tui.KeyID{"ctrl+s"}, Description: "Save model selection"},
	{ID: "app.models.enableAll", DefaultKeys: []tui.KeyID{"ctrl+a"}, Description: "Enable all models"},
	{ID: "app.models.clearAll", DefaultKeys: []tui.KeyID{"ctrl+x"}, Description: "Clear all models"},
	{ID: "app.models.toggleProvider", DefaultKeys: []tui.KeyID{"ctrl+p"}, Description: "Toggle provider models"},
	{ID: "app.models.reorderUp", DefaultKeys: []tui.KeyID{"alt+up"}, Description: "Move model up"},
	{ID: "app.models.reorderDown", DefaultKeys: []tui.KeyID{"alt+down"}, Description: "Move model down"},
}

AppKeybindingDefinitions are the app-level keybindings that extend TUI defaults.

Functions

func KeyHint

func KeyHint(binding, description string) string

KeyHint renders a dim key label plus muted description for the resolved keybinding, mirroring upstream's exported keyHint helper.

func KeyText

func KeyText(binding string) string

KeyText formats the keys currently bound to a keybinding id (falling back to the id itself), mirroring upstream's exported keyText helper.

func NewAppKeybindings

func NewAppKeybindings(user tui.KeybindingsConfig) *tui.KeybindingsManager

NewAppKeybindings creates a keybindings manager with all TUI + app definitions.

func RawKeyHint

func RawKeyHint(key, description string) string

RawKeyHint renders a dim literal key plus muted description without keybinding resolution, mirroring upstream's exported rawKeyHint helper.

func RunConfigSelector

func RunConfigSelector(ctx context.Context, options ConfigSelectorOptions) error

func RunConfigSelectorWithTerminal

func RunConfigSelectorWithTerminal(ctx context.Context, options ConfigSelectorOptions, terminal tui.Terminal) error

func RunInteractiveMode

func RunInteractiveMode(ctx context.Context, session *codingagent.SessionRuntime, options InteractiveModeOptions) int

RunInteractiveMode starts the full TUI interactive session.

func RunPrintMode

func RunPrintMode(ctx context.Context, session printSession, options PrintModeOptions) int

RunPrintMode sends each configured prompt serially and returns a process exit code. Model failures remain represented by the final assistant message.

func RunRPCMode

func RunRPCMode(ctx context.Context, host RPCSessionHost, options RPCModeOptions) int

RunRPCMode serves upstream's strict-LF, bidirectional JSONL protocol until stdin closes, the context is cancelled, or a shutdown signal arrives.

func RunSessionSelector

func RunSessionSelector(ctx context.Context, current, all SessionSelectorLoader) (string, bool, error)

func RunSessionSelectorWithTerminal

func RunSessionSelectorWithTerminal(ctx context.Context, current, all SessionSelectorLoader, terminal tui.Terminal) (string, bool, error)

func RunStartupSelector

func RunStartupSelector(ctx context.Context, options StartupSelectorOptions) (string, bool, error)

func RunStartupSelectorWithTerminal

func RunStartupSelectorWithTerminal(ctx context.Context, options StartupSelectorOptions, terminal tui.Terminal) (string, bool, error)

Types

type ArminComponent

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

func NewArminComponent

func NewArminComponent(ui tui.RenderRequester) *ArminComponent

func (*ArminComponent) Dispose

func (component *ArminComponent) Dispose()

func (*ArminComponent) Invalidate

func (component *ArminComponent) Invalidate()

func (*ArminComponent) Render

func (component *ArminComponent) Render(width int) []string

type AssistantMessageComponent

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

func NewAssistantMessageComponent

func NewAssistantMessageComponent(
	message *ai.AssistantMessage,
	hideThinking bool,
	mdTheme tui.MarkdownTheme,
	thinkingLabel string,
	outputPad int,
) *AssistantMessageComponent

func (*AssistantMessageComponent) Invalidate

func (c *AssistantMessageComponent) Invalidate()

func (*AssistantMessageComponent) Render

func (c *AssistantMessageComponent) Render(width int) []string

func (*AssistantMessageComponent) SetHiddenThinkingLabel

func (c *AssistantMessageComponent) SetHiddenThinkingLabel(label string)

func (*AssistantMessageComponent) SetHideThinkingBlock

func (c *AssistantMessageComponent) SetHideThinkingBlock(hidden bool, label string)

func (*AssistantMessageComponent) UpdateContent

func (c *AssistantMessageComponent) UpdateContent(message *ai.AssistantMessage)

type BashExecutionComponent

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

func NewBashExecutionComponent

func NewBashExecutionComponent(command string, ui tui.RenderRequester, excludeFromContext bool) *BashExecutionComponent

func (*BashExecutionComponent) AppendOutput

func (c *BashExecutionComponent) AppendOutput(text string)

func (*BashExecutionComponent) Invalidate

func (c *BashExecutionComponent) Invalidate()

func (*BashExecutionComponent) Render

func (c *BashExecutionComponent) Render(width int) []string

func (*BashExecutionComponent) SetComplete

func (c *BashExecutionComponent) SetComplete(exitCode *int, cancelled bool)

func (*BashExecutionComponent) SetExpanded

func (c *BashExecutionComponent) SetExpanded(expanded bool)

type BranchSummaryMessageComponent

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

func NewBranchSummaryMessage

func NewBranchSummaryMessage(summary string, mdTheme tui.MarkdownTheme) *BranchSummaryMessageComponent

func (*BranchSummaryMessageComponent) Invalidate

func (c *BranchSummaryMessageComponent) Invalidate()

func (*BranchSummaryMessageComponent) Render

func (c *BranchSummaryMessageComponent) Render(width int) []string

func (*BranchSummaryMessageComponent) SetExpanded

func (c *BranchSummaryMessageComponent) SetExpanded(expanded bool)

type CompactionSummaryMessageComponent

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

func NewCompactionSummaryMessage

func NewCompactionSummaryMessage(summary string, tokensBefore int64, mdTheme tui.MarkdownTheme) *CompactionSummaryMessageComponent

func (*CompactionSummaryMessageComponent) Invalidate

func (c *CompactionSummaryMessageComponent) Invalidate()

func (*CompactionSummaryMessageComponent) Render

func (c *CompactionSummaryMessageComponent) Render(width int) []string

func (*CompactionSummaryMessageComponent) SetExpanded

func (c *CompactionSummaryMessageComponent) SetExpanded(expanded bool)

type ConfigSelector

type ConfigSelector struct {
	tui.Container
	// contains filtered or unexported fields
}

func NewConfigSelector

func NewConfigSelector(options ConfigSelectorOptions, onClose, onExit func(), requestRender func()) *ConfigSelector

func (*ConfigSelector) HandleInput

func (selector *ConfigSelector) HandleInput(event tui.KeyEvent)

func (*ConfigSelector) Render

func (selector *ConfigSelector) Render(width int) []string

func (*ConfigSelector) SetFocused

func (selector *ConfigSelector) SetFocused(focused bool)

func (*ConfigSelector) WriteScope

func (selector *ConfigSelector) WriteScope() ConfigWriteScope

type ConfigSelectorOptions

type ConfigSelectorOptions struct {
	ResolvedPaths        ScopedResolvedPaths
	SettingsManager      *config.SettingsManager
	CWD                  string
	AgentDir             string
	WriteScope           ConfigWriteScope
	ProjectModeAvailable bool
	TerminalHeight       int
}

type ConfigWriteScope

type ConfigWriteScope string
const (
	ConfigWriteGlobal  ConfigWriteScope = "global"
	ConfigWriteProject ConfigWriteScope = "project"
)

type CountdownTimer

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

CountdownTimer ticks each second and fires a callback on expiry.

func NewCountdownTimer

func NewCountdownTimer(durationMS int64, ui tui.RenderRequester, onTick func(int), onExpire func()) *CountdownTimer

func (*CountdownTimer) Dispose

func (ct *CountdownTimer) Dispose()

type CustomEditor

type CustomEditor struct {
	*tui.Editor

	OnEscape            func()
	OnCtrlD             func()
	OnPasteImage        func()
	OnExtensionShortcut func(string) bool
	// contains filtered or unexported fields
}

CustomEditor wraps tui.Editor with app-level keybinding dispatch.

func NewCustomEditor

func NewCustomEditor(ui *tui.TUI, editorTheme tui.EditorTheme, kb *tui.KeybindingsManager) *CustomEditor

func (*CustomEditor) OnAction

func (ce *CustomEditor) OnAction(action string, handler func())

type CustomMessageComponent

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

func NewCustomMessageComponent

func NewCustomMessageComponent(customType string, content any, mdTheme tui.MarkdownTheme) *CustomMessageComponent

func (*CustomMessageComponent) Invalidate

func (c *CustomMessageComponent) Invalidate()

func (*CustomMessageComponent) Render

func (c *CustomMessageComponent) Render(width int) []string

func (*CustomMessageComponent) SetExpanded

func (c *CustomMessageComponent) SetExpanded(expanded bool)

type DynamicBorder

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

DynamicBorder renders a horizontal line that stretches to fit the terminal width.

func NewDynamicBorder

func NewDynamicBorder() *DynamicBorder

func NewDynamicBorderWithColor

func NewDynamicBorderWithColor(colorFn func(string) string) *DynamicBorder

func (*DynamicBorder) Invalidate

func (border *DynamicBorder) Invalidate()

func (*DynamicBorder) Render

func (border *DynamicBorder) Render(width int) []string

type EarendilAnnouncementComponent

type EarendilAnnouncementComponent struct {
	tui.Container
}

func NewEarendilAnnouncementComponent

func NewEarendilAnnouncementComponent() *EarendilAnnouncementComponent

type ExtensionEditorComponent

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

ExtensionEditorComponent is the bordered multi-line editor dialog behind ctx.ui.editor, exported for extension UI reuse.

func NewExtensionEditorComponent

func NewExtensionEditorComponent(
	uiInstance *tui.TUI,
	bindings *tui.KeybindingsManager,
	title string,
	prefill string,
	onSubmit func(string),
	onCancel func(),
	externalEditorCommand string,
) *ExtensionEditorComponent

NewExtensionEditorComponent builds the multi-line editor dialog.

func (*ExtensionEditorComponent) HandleInput

func (component *ExtensionEditorComponent) HandleInput(event tui.KeyEvent)

func (*ExtensionEditorComponent) Invalidate

func (component *ExtensionEditorComponent) Invalidate()

func (*ExtensionEditorComponent) Render

func (component *ExtensionEditorComponent) Render(width int) []string

func (*ExtensionEditorComponent) SetFocused

func (component *ExtensionEditorComponent) SetFocused(focused bool)

type ExtensionInputComponent

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

ExtensionInputComponent is the bordered single-line input dialog behind ctx.ui.input, exported for extension UI reuse.

func NewExtensionInputComponent

func NewExtensionInputComponent(
	title string,
	_ string,
	onSubmit func(string),
	onCancel func(),
	config *extensionDialogOptions,
) *ExtensionInputComponent

NewExtensionInputComponent builds the single-line input dialog.

func (*ExtensionInputComponent) Dispose

func (component *ExtensionInputComponent) Dispose()

func (*ExtensionInputComponent) HandleInput

func (component *ExtensionInputComponent) HandleInput(event tui.KeyEvent)

func (*ExtensionInputComponent) Invalidate

func (component *ExtensionInputComponent) Invalidate()

func (*ExtensionInputComponent) Render

func (component *ExtensionInputComponent) Render(width int) []string

func (*ExtensionInputComponent) SetFocused

func (component *ExtensionInputComponent) SetFocused(focused bool)

type ExtensionSelectorComponent

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

ExtensionSelectorComponent is the bordered option-list dialog behind ctx.ui.select, exported for extension UI reuse as upstream exports it.

func NewExtensionSelectorItemsComponent

func NewExtensionSelectorItemsComponent(
	title string,
	options []tui.SelectItem,
	onSelect func(string),
	onCancel func(),
	config *extensionDialogOptions,
) *ExtensionSelectorComponent

NewExtensionSelectorItemsComponent builds the selector dialog from pre-labelled select items.

func (*ExtensionSelectorComponent) Dispose

func (component *ExtensionSelectorComponent) Dispose()

func (*ExtensionSelectorComponent) HandleInput

func (component *ExtensionSelectorComponent) HandleInput(event tui.KeyEvent)

func (*ExtensionSelectorComponent) Invalidate

func (component *ExtensionSelectorComponent) Invalidate()

func (*ExtensionSelectorComponent) Render

func (component *ExtensionSelectorComponent) Render(width int) []string

type FooterComponent

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

func NewFooterComponent

func NewFooterComponent(session footerSession, provider footerDataProvider) *FooterComponent

func (*FooterComponent) Invalidate

func (f *FooterComponent) Invalidate()

func (*FooterComponent) Render

func (f *FooterComponent) Render(width int) []string

type IdleStatus

type IdleStatus struct{}

IdleStatus renders two empty lines (same height as a status indicator).

func (IdleStatus) Invalidate

func (IdleStatus) Invalidate()

func (IdleStatus) Render

func (IdleStatus) Render(width int) []string

type InteractiveAuthOptions

type InteractiveAuthOptions struct {
	Login  []InteractiveAuthProvider
	Logout []InteractiveAuthProvider
}

type InteractiveAuthProvider

type InteractiveAuthProvider struct {
	ID             string
	Name           string
	AuthType       aiauth.AuthType
	MethodName     string
	LoginLabel     string
	Configured     bool
	Status         *InteractiveAuthStatus
	LoginAvailable bool
}

type InteractiveAuthStatus

type InteractiveAuthStatus struct {
	Type   aiauth.AuthType
	Source string
}

type InteractiveForkResult

type InteractiveForkResult struct {
	Cancelled    bool
	SelectedText string
}

type InteractiveMode

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

func (*InteractiveMode) AvailableProviderCount

func (mode *InteractiveMode) AvailableProviderCount() int

func (*InteractiveMode) CurrentCWD

func (mode *InteractiveMode) CurrentCWD() string

func (*InteractiveMode) GitBranch

func (mode *InteractiveMode) GitBranch() string

func (*InteractiveMode) Height

func (mode *InteractiveMode) Height() int

func (*InteractiveMode) Invalidate

func (mode *InteractiveMode) Invalidate()

func (*InteractiveMode) SessionName

func (mode *InteractiveMode) SessionName() string

func (*InteractiveMode) Statuses

func (mode *InteractiveMode) Statuses() map[string]string

func (*InteractiveMode) Width

func (mode *InteractiveMode) Width() int

type InteractiveModeOptions

type InteractiveModeOptions struct {
	InitialMessage string
	InitialImages  []*ai.ImageContent
	Messages       []string
	SessionHeader  *sessionstore.SessionHeader
	Diagnostics    []string
	Terminal       tui.Terminal
	Host           InteractiveSessionHost
	// StartupVersionCheck is the non-blocking startup seam used by WP-661. The
	// interactive package owns no update transport or policy.
	StartupVersionCheck func(context.Context, extensions.UI)
	StartupModelRefresh func(context.Context) error
	Changelog           string
	Output              io.Writer
	OutputTTY           bool
}

InteractiveModeOptions configures the interactive TUI mode.

type InteractiveSessionHost

type InteractiveSessionHost interface {
	Session() *codingagent.SessionRuntime

	// SetRebindSession registers the TUI callback invoked after the replacement
	// becomes current and before its session_start fires.
	SetRebindSession(func(*codingagent.SessionRuntime) error)
	// SetBeforeSessionInvalidate registers synchronous listener teardown run
	// after session_shutdown and before the current runtime is disposed.
	SetBeforeSessionInvalidate(func())
	// SetAfterSessionStart registers the TUI callback invoked after the
	// replacement has discovered extension resources.
	SetAfterSessionStart(func(*codingagent.SessionRuntime) error)

	NewSession(ctx context.Context, options *extensions.NewSessionOptions) (extensions.SessionReplacementResult, error)
	SwitchSession(ctx context.Context, sessionPath, cwdOverride string, options *extensions.SwitchSessionOptions) (extensions.SessionReplacementResult, error)
	Fork(ctx context.Context, entryID string, options *extensions.ForkOptions) (InteractiveForkResult, error)
	ImportSession(ctx context.Context, inputPath, cwdOverride string) (extensions.SessionReplacementResult, error)
	Reload(ctx context.Context) error

	// ListProjectSessions lists sessions for the current cwd;
	// ListAllSessions lists every project's sessions (upstream
	// SessionManager.list / listAll semantics).
	ListProjectSessions(onProgress sessionstore.SessionListProgress) []sessionstore.SessionInfo
	ListAllSessions(onProgress sessionstore.SessionListProgress) []sessionstore.SessionInfo

	TrustState() (InteractiveTrustState, error)
	// SetProjectTrust persists the trust decisions and rebuilds the runtime
	// through the reload path so resources and tools reflect the new trust.
	SetProjectTrust(ctx context.Context, updates []config.ProjectTrustUpdate) error

	AuthOptions(ctx context.Context) (InteractiveAuthOptions, error)
	Login(ctx context.Context, providerID string, authType aiauth.AuthType, interaction aiauth.AuthInteraction) error
	Logout(ctx context.Context, providerID string) error

	Dispose()
}

InteractiveSessionHost owns the live SessionRuntime behind the interactive TUI and executes every state-changing session command. It mirrors upstream AgentSessionRuntime (core/agent-session-runtime.ts): replacement methods shut down and dispose the current runtime before calling the full CLI creation path, apply and rebind the replacement without rollback, and only then let the replacement's session_start extension event fire.

UI selection stays with the TUI: /clone is Fork of the current leaf with position "at", and /tree navigation goes through the extension command context's NavigateTree, which the runtime serves itself.

type InteractiveTrustState

type InteractiveTrustState struct {
	CWD            string
	ProjectTrusted bool
	SavedDecision  *config.ProjectTrustStoreEntry
	Options        []config.ProjectTrustOption
}

type InteractiveUI

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

InteractiveUI backs the extensions.UI interface with TUI components.

func NewInteractiveUI

func NewInteractiveUI(mode *InteractiveMode) *InteractiveUI

func (*InteractiveUI) AddAutocompleteProvider

func (ui *InteractiveUI) AddAutocompleteProvider(factory extensions.AutocompleteProviderFactory)

func (*InteractiveUI) Confirm

func (ui *InteractiveUI) Confirm(ctx context.Context, title, message string, opts *extensions.DialogOptions) (bool, error)

func (*InteractiveUI) Custom

func (*InteractiveUI) Editor

func (ui *InteractiveUI) Editor(ctx context.Context, title string, prefill *string) (string, bool, error)

func (*InteractiveUI) GetAllThemes

func (ui *InteractiveUI) GetAllThemes() []extensions.ThemeInfo

func (*InteractiveUI) GetEditorComponent

func (ui *InteractiveUI) GetEditorComponent() extensions.EditorFactory

func (*InteractiveUI) GetEditorText

func (ui *InteractiveUI) GetEditorText() string

func (*InteractiveUI) GetTheme

func (ui *InteractiveUI) GetTheme(name string) extensions.Theme

func (*InteractiveUI) GetToolsExpanded

func (ui *InteractiveUI) GetToolsExpanded() bool

func (*InteractiveUI) Input

func (ui *InteractiveUI) Input(ctx context.Context, title string, placeholder *string, opts *extensions.DialogOptions) (string, bool, error)

func (*InteractiveUI) Notify

func (ui *InteractiveUI) Notify(message string, notifyType extensions.NotificationType)

func (*InteractiveUI) OnTerminalInput

func (ui *InteractiveUI) OnTerminalInput(handler extensions.TerminalInputHandler) func()

func (*InteractiveUI) PasteToEditor

func (ui *InteractiveUI) PasteToEditor(text string)

func (*InteractiveUI) Select

func (ui *InteractiveUI) Select(ctx context.Context, title string, options []string, opts *extensions.DialogOptions) (string, bool, error)

func (*InteractiveUI) SetEditorComponent

func (ui *InteractiveUI) SetEditorComponent(factory extensions.EditorFactory)

func (*InteractiveUI) SetEditorText

func (ui *InteractiveUI) SetEditorText(text string)

func (*InteractiveUI) SetFooter

func (ui *InteractiveUI) SetFooter(factory extensions.FooterFactory)

func (*InteractiveUI) SetHeader

func (ui *InteractiveUI) SetHeader(factory extensions.HeaderFactory)

func (*InteractiveUI) SetHiddenThinkingLabel

func (ui *InteractiveUI) SetHiddenThinkingLabel(label *string)

func (*InteractiveUI) SetStatus

func (ui *InteractiveUI) SetStatus(key string, text *string)

func (*InteractiveUI) SetTheme

func (ui *InteractiveUI) SetTheme(value any) extensions.ThemeSetResult

func (*InteractiveUI) SetTitle

func (ui *InteractiveUI) SetTitle(title string)

func (*InteractiveUI) SetToolsExpanded

func (ui *InteractiveUI) SetToolsExpanded(expanded bool)

func (*InteractiveUI) SetWidget

func (ui *InteractiveUI) SetWidget(key string, widget *extensions.Widget, opts *extensions.WidgetOptions)

func (*InteractiveUI) SetWorkingIndicator

func (ui *InteractiveUI) SetWorkingIndicator(opts *extensions.WorkingIndicatorOptions)

func (*InteractiveUI) SetWorkingMessage

func (ui *InteractiveUI) SetWorkingMessage(msg *string)

func (*InteractiveUI) SetWorkingVisible

func (ui *InteractiveUI) SetWorkingVisible(visible bool)

func (*InteractiveUI) Theme

func (ui *InteractiveUI) Theme() extensions.Theme

type MissingSessionCwdError

type MissingSessionCwdError struct {
	SessionFile string
	SessionCWD  string
	FallbackCWD string
}

MissingSessionCwdError reports a session whose stored cwd no longer exists; the TUI prompts for a cwd override and retries. Text matches upstream formatMissingSessionCwdError.

func (*MissingSessionCwdError) Error

func (err *MissingSessionCwdError) Error() string

type OAuthSelectorComponent

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

OAuthSelectorComponent is the searchable auth-provider selector behind /login and /logout, a port of upstream components/oauth-selector.ts: a fuzzy-search input over name+id+authType+methodName, an 8-row visible window with a scroll counter, and per-row status indicators.

func NewOAuthSelectorComponent

func NewOAuthSelectorComponent(
	selectorMode string,
	providers []InteractiveAuthProvider,
	onSelect func(InteractiveAuthProvider),
	onCancel func(),
	initialSearchInput string,
) *OAuthSelectorComponent

NewOAuthSelectorComponent builds the selector; initialSearchInput pre-fills the search field (upstream constructor's initialSearchInput) so /login with an unmatched fuzzy ref opens the list already filtered.

func (*OAuthSelectorComponent) HandleInput

func (component *OAuthSelectorComponent) HandleInput(event tui.KeyEvent)

func (*OAuthSelectorComponent) Invalidate

func (component *OAuthSelectorComponent) Invalidate()

func (*OAuthSelectorComponent) Render

func (component *OAuthSelectorComponent) Render(width int) []string

func (*OAuthSelectorComponent) SetFocused

func (component *OAuthSelectorComponent) SetFocused(focused bool)

type PrintModeOptions

type PrintModeOptions struct {
	Mode           PrintOutputMode
	Messages       []string
	InitialMessage string
	InitialImages  []*ai.ImageContent
	SessionHeader  *session.SessionHeader
	Stdout         io.Writer
	Stderr         io.Writer
}

type PrintOutputMode

type PrintOutputMode string
const (
	PrintOutputText PrintOutputMode = "text"
	PrintOutputJSON PrintOutputMode = "json"
)

type RPCClient

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

RPCClient spawns pi in RPC mode and routes its strict-JSONL responses and events.

func NewRPCClient

func NewRPCClient(options RPCClientOptions) *RPCClient

func (*RPCClient) Abort

func (client *RPCClient) Abort(ctx context.Context) error

func (*RPCClient) AbortBash

func (client *RPCClient) AbortBash(ctx context.Context) error

func (*RPCClient) AbortRetry

func (client *RPCClient) AbortRetry(ctx context.Context) error

func (*RPCClient) Bash

func (client *RPCClient) Bash(ctx context.Context, command string) (tools.BashResult, error)

func (*RPCClient) Clone

func (*RPCClient) CollectEvents

func (client *RPCClient) CollectEvents(ctx context.Context) ([]RPCEvent, error)

func (*RPCClient) Compact

func (client *RPCClient) Compact(ctx context.Context, customInstructions *string) (sessionstore.CompactionResult, error)

func (*RPCClient) CycleModel

func (client *RPCClient) CycleModel(ctx context.Context) (*RPCModelCycleResult, error)

func (*RPCClient) CycleThinkingLevel

func (client *RPCClient) CycleThinkingLevel(ctx context.Context) (*RPCThinkingLevelResult, error)

func (*RPCClient) ExportHTML

func (client *RPCClient) ExportHTML(ctx context.Context, outputPath *string) (RPCExportResult, error)

func (*RPCClient) FollowUp

func (client *RPCClient) FollowUp(ctx context.Context, message string, images []*ai.ImageContent) error

func (*RPCClient) Fork

func (client *RPCClient) Fork(ctx context.Context, entryID string) (RPCForkResult, error)

func (*RPCClient) GetAvailableModels

func (client *RPCClient) GetAvailableModels(ctx context.Context) ([]RPCModelInfo, error)

func (*RPCClient) GetAvailableThinkingLevels

func (client *RPCClient) GetAvailableThinkingLevels(ctx context.Context) ([]ai.ModelThinkingLevel, error)

func (*RPCClient) GetCommands

func (client *RPCClient) GetCommands(ctx context.Context) ([]RPCSlashCommand, error)

func (*RPCClient) GetEntries

func (client *RPCClient) GetEntries(ctx context.Context, since *string) (RPCEntriesResult, error)

func (*RPCClient) GetForkMessages

func (client *RPCClient) GetForkMessages(ctx context.Context) ([]RPCForkMessage, error)

func (*RPCClient) GetLastAssistantText

func (client *RPCClient) GetLastAssistantText(ctx context.Context) (*string, error)

func (*RPCClient) GetMessages

func (client *RPCClient) GetMessages(ctx context.Context) (agent.AgentMessages, error)

func (*RPCClient) GetSessionStats

func (client *RPCClient) GetSessionStats(ctx context.Context) (codingagent.SessionStats, error)

func (*RPCClient) GetState

func (client *RPCClient) GetState(ctx context.Context) (RPCSessionState, error)

func (*RPCClient) GetStderr

func (client *RPCClient) GetStderr() string

func (*RPCClient) GetTree

func (client *RPCClient) GetTree(ctx context.Context) (RPCTreeResult, error)

func (*RPCClient) NewSession

func (client *RPCClient) NewSession(ctx context.Context, parentSession *string) (RPCSessionReplacementResult, error)

func (*RPCClient) OnEvent

func (client *RPCClient) OnEvent(listener RPCEventListener) func()

func (*RPCClient) Prompt

func (client *RPCClient) Prompt(ctx context.Context, message string, images []*ai.ImageContent) error

func (*RPCClient) PromptAndWait

func (client *RPCClient) PromptAndWait(ctx context.Context, message string, images []*ai.ImageContent) ([]RPCEvent, error)

func (*RPCClient) SetAutoCompaction

func (client *RPCClient) SetAutoCompaction(ctx context.Context, enabled bool) error

func (*RPCClient) SetAutoRetry

func (client *RPCClient) SetAutoRetry(ctx context.Context, enabled bool) error

func (*RPCClient) SetFollowUpMode

func (client *RPCClient) SetFollowUpMode(ctx context.Context, mode agent.QueueMode) error

func (*RPCClient) SetModel

func (client *RPCClient) SetModel(ctx context.Context, provider ai.ProviderID, modelID string) (RPCModelSelection, error)

func (*RPCClient) SetSessionName

func (client *RPCClient) SetSessionName(ctx context.Context, name string) error

func (*RPCClient) SetSteeringMode

func (client *RPCClient) SetSteeringMode(ctx context.Context, mode agent.QueueMode) error

func (*RPCClient) SetThinkingLevel

func (client *RPCClient) SetThinkingLevel(ctx context.Context, level ai.ModelThinkingLevel) error

func (*RPCClient) Start

func (client *RPCClient) Start(ctx context.Context) error

func (*RPCClient) Steer

func (client *RPCClient) Steer(ctx context.Context, message string, images []*ai.ImageContent) error

func (*RPCClient) Stop

func (client *RPCClient) Stop() error

func (*RPCClient) SwitchSession

func (client *RPCClient) SwitchSession(ctx context.Context, sessionPath string) (RPCSessionReplacementResult, error)

func (*RPCClient) WaitForIdle

func (client *RPCClient) WaitForIdle(ctx context.Context) error

type RPCClientOptions

type RPCClientOptions struct {
	CLIPath  string
	CWD      string
	Env      map[string]string
	Provider string
	Model    string
	Args     []string
}

RPCClientOptions configure the pi process spawned by NewRPCClient.

type RPCCommand

type RPCCommand struct {
	ID                 string             `json:"id,omitempty"`
	Type               string             `json:"type"`
	Message            string             `json:"message,omitempty"`
	Images             []*ai.ImageContent `json:"images,omitempty"`
	StreamingBehavior  string             `json:"streamingBehavior,omitempty"`
	ParentSession      string             `json:"parentSession,omitempty"`
	Provider           string             `json:"provider,omitempty"`
	ModelID            string             `json:"modelId,omitempty"`
	Level              string             `json:"level,omitempty"`
	Mode               string             `json:"mode,omitempty"`
	CustomInstructions string             `json:"customInstructions,omitempty"`
	Enabled            *bool              `json:"enabled,omitempty"`
	Command            string             `json:"command,omitempty"`
	ExcludeFromContext *bool              `json:"excludeFromContext,omitempty"`
	OutputPath         string             `json:"outputPath,omitempty"`
	SessionPath        string             `json:"sessionPath,omitempty"`
	EntryID            string             `json:"entryId,omitempty"`
	Since              *string            `json:"since,omitempty"`
	Name               string             `json:"name,omitempty"`
	HasID              bool               `json:"-"`
	// contains filtered or unexported fields
}

type RPCEntriesResult

type RPCEntriesResult struct {
	Entries []sessionstore.SessionEntry `json:"entries"`
	LeafID  *string                     `json:"leafId"`
}

type RPCEvent

type RPCEvent struct {
	Type string
	JSON json.RawMessage
}

RPCEvent retains an event's exact JSON while exposing its discriminant.

type RPCEventListener

type RPCEventListener func(RPCEvent)

type RPCExportResult

type RPCExportResult struct {
	Path string `json:"path"`
}

type RPCExtensionUI

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

RPCExtensionUI implements the RPC dialog sub-protocol. Phase-5 bindings use this same object; RPC mode already exposes it so native extensions can bind without another transport implementation.

func (*RPCExtensionUI) Confirm

func (ui *RPCExtensionUI) Confirm(ctx context.Context, title, message string, timeoutMS *int64) (bool, error)

func (*RPCExtensionUI) Editor

func (ui *RPCExtensionUI) Editor(ctx context.Context, title string, prefill *string) (*string, error)

func (*RPCExtensionUI) HandleResponse

func (ui *RPCExtensionUI) HandleResponse(response RPCExtensionUIResponse)

func (*RPCExtensionUI) Input

func (ui *RPCExtensionUI) Input(ctx context.Context, title string, placeholder *string, timeoutMS *int64) (*string, error)

func (*RPCExtensionUI) Notify

func (ui *RPCExtensionUI) Notify(message, notifyType string) error

func (*RPCExtensionUI) Select

func (ui *RPCExtensionUI) Select(ctx context.Context, title string, options []string, timeoutMS *int64) (*string, error)

func (*RPCExtensionUI) SetEditorText

func (ui *RPCExtensionUI) SetEditorText(text string) error

func (*RPCExtensionUI) SetStatus

func (ui *RPCExtensionUI) SetStatus(key string, text *string) error

func (*RPCExtensionUI) SetTitle

func (ui *RPCExtensionUI) SetTitle(title string) error

func (*RPCExtensionUI) SetWidget

func (ui *RPCExtensionUI) SetWidget(key string, lines []string, placement string) error

type RPCExtensionUIRequest

type RPCExtensionUIRequest struct {
	Type            string    `json:"type"`
	ID              string    `json:"id"`
	Method          string    `json:"method"`
	Title           string    `json:"title,omitempty"`
	Options         []string  `json:"options,omitempty"`
	Timeout         *int64    `json:"timeout,omitempty"`
	Message         string    `json:"message,omitempty"`
	Placeholder     *string   `json:"placeholder,omitempty"`
	Prefill         *string   `json:"prefill,omitempty"`
	NotifyType      string    `json:"notifyType,omitempty"`
	StatusKey       string    `json:"statusKey,omitempty"`
	StatusText      *string   `json:"statusText,omitempty"`
	WidgetKey       string    `json:"widgetKey,omitempty"`
	WidgetLines     *[]string `json:"widgetLines,omitempty"`
	WidgetPlacement string    `json:"widgetPlacement,omitempty"`
	Text            string    `json:"text,omitempty"`
}

func (RPCExtensionUIRequest) MarshalJSON

func (request RPCExtensionUIRequest) MarshalJSON() ([]byte, error)

type RPCExtensionUIResponse

type RPCExtensionUIResponse struct {
	Type      string  `json:"type"`
	ID        string  `json:"id"`
	Value     *string `json:"value,omitempty"`
	Confirmed *bool   `json:"confirmed,omitempty"`
	Cancelled bool    `json:"cancelled,omitempty"`
}

type RPCForkMessage

type RPCForkMessage struct {
	EntryID string `json:"entryId"`
	Text    string `json:"text"`
}

type RPCForkResult

type RPCForkResult struct {
	Text      string `json:"text"`
	Cancelled bool   `json:"cancelled"`
}

type RPCModeOptions

type RPCModeOptions struct {
	Stdin    io.Reader
	Stdout   io.Writer
	Stderr   io.Writer
	Commands func() []RPCSlashCommand
}

type RPCModelCycleResult

type RPCModelCycleResult struct {
	Model         RPCModelSelection     `json:"model"`
	ThinkingLevel ai.ModelThinkingLevel `json:"thinkingLevel"`
	IsScoped      bool                  `json:"isScoped"`
}

type RPCModelInfo

type RPCModelInfo struct {
	Provider      ai.ProviderID `json:"provider"`
	ID            string        `json:"id"`
	ContextWindow float64       `json:"contextWindow"`
	Reasoning     bool          `json:"reasoning"`
}

type RPCModelSelection

type RPCModelSelection struct {
	Provider ai.ProviderID `json:"provider"`
	ID       string        `json:"id"`
}

type RPCResponse

type RPCResponse struct {
	ID      string `json:"id,omitempty"`
	Type    string `json:"type"`
	Command string `json:"command"`
	Success bool   `json:"success"`
	Data    any    `json:"data,omitempty"`
	Error   string `json:"error,omitempty"`
	HasID   bool   `json:"-"`
	HasData bool   `json:"-"`
}

RPCResponse is the common response envelope emitted by RPC mode. Field order follows upstream's object construction order because transcript bytes are a public wire format.

func (RPCResponse) MarshalJSON

func (response RPCResponse) MarshalJSON() ([]byte, error)

type RPCSessionHost

type RPCSessionHost interface {
	Session() *codingagent.SessionRuntime
	NewSession(parentSession string) (cancelled bool, err error)
	SwitchSession(sessionPath string) (cancelled bool, err error)
	Fork(entryID string, atEntry bool) (text string, cancelled bool, err error)
	Dispose()
}

type RPCSessionReplacementResult

type RPCSessionReplacementResult struct {
	Cancelled bool `json:"cancelled"`
}

type RPCSessionState

type RPCSessionState struct {
	Model                 *ai.Model             `json:"model,omitempty"`
	ThinkingLevel         ai.ModelThinkingLevel `json:"thinkingLevel"`
	IsStreaming           bool                  `json:"isStreaming"`
	IsCompacting          bool                  `json:"isCompacting"`
	SteeringMode          string                `json:"steeringMode"`
	FollowUpMode          string                `json:"followUpMode"`
	SessionFile           string                `json:"sessionFile,omitempty"`
	SessionID             string                `json:"sessionId"`
	SessionName           *string               `json:"sessionName,omitempty"`
	AutoCompactionEnabled bool                  `json:"autoCompactionEnabled"`
	MessageCount          int                   `json:"messageCount"`
	PendingMessageCount   int                   `json:"pendingMessageCount"`
}

type RPCSlashCommand

type RPCSlashCommand struct {
	Name        string        `json:"name"`
	Description *string       `json:"description,omitempty"`
	Source      string        `json:"source"`
	SourceInfo  RPCSourceInfo `json:"sourceInfo"`
}

type RPCSourceInfo

type RPCSourceInfo struct {
	Path    string  `json:"path"`
	Source  string  `json:"source"`
	Scope   string  `json:"scope"`
	Origin  string  `json:"origin"`
	BaseDir *string `json:"baseDir,omitempty"`
}

type RPCThinkingLevelResult

type RPCThinkingLevelResult struct {
	Level ai.ModelThinkingLevel `json:"level"`
}

type RPCThinkingLevels

type RPCThinkingLevels struct {
	Levels []ai.ModelThinkingLevel `json:"levels"`
}

type RPCTreeResult

type RPCTreeResult struct {
	Tree   []*sessionstore.SessionTreeNode `json:"tree"`
	LeafID *string                         `json:"leafId"`
}

type ScopedResolvedPaths

type ScopedResolvedPaths struct {
	Global  *codingagent.ResolvedPaths
	Project *codingagent.ResolvedPaths
}

type SessionDeleteMethod

type SessionDeleteMethod string
const (
	SessionDeleteTrash  SessionDeleteMethod = "trash"
	SessionDeleteUnlink SessionDeleteMethod = "unlink"
)

type SessionImportFileNotFoundError

type SessionImportFileNotFoundError struct {
	FilePath string
}

SessionImportFileNotFoundError reports an /import path that does not exist. Text matches upstream SessionImportFileNotFoundError.

func (*SessionImportFileNotFoundError) Error

type SessionSelectorComponent

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

SessionSelectorComponent mirrors the startup and interactive session picker used by upstream. Loaders may block; scope loads run away from the TUI input loop and publish progress through RequestRender.

func NewSessionSelectorComponent

func NewSessionSelectorComponent(options SessionSelectorOptions, onSelect func(string), onCancel func()) *SessionSelectorComponent

func (*SessionSelectorComponent) HandleInput

func (selector *SessionSelectorComponent) HandleInput(event tui.KeyEvent)

func (*SessionSelectorComponent) Invalidate

func (selector *SessionSelectorComponent) Invalidate()

func (*SessionSelectorComponent) Render

func (selector *SessionSelectorComponent) Render(width int) []string

func (*SessionSelectorComponent) SetFocused

func (selector *SessionSelectorComponent) SetFocused(focused bool)

type SessionSelectorLoader

type SessionSelectorLoader func(session.SessionListProgress) []session.SessionInfo

type SessionSelectorOptions

type SessionSelectorOptions struct {
	CurrentSessions    SessionSelectorLoader
	AllSessions        SessionSelectorLoader
	CurrentSessionPath string
	Keybindings        *tui.KeybindingsManager
	RequestRender      func()
	Now                func() time.Time
	DeleteSession      func(string) (SessionDeleteMethod, error)
}

type SkillInvocationMessageComponent

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

func NewSkillInvocationMessage

func NewSkillInvocationMessage(name, content string, mdTheme tui.MarkdownTheme) *SkillInvocationMessageComponent

func (*SkillInvocationMessageComponent) Invalidate

func (c *SkillInvocationMessageComponent) Invalidate()

func (*SkillInvocationMessageComponent) Render

func (c *SkillInvocationMessageComponent) Render(width int) []string

func (*SkillInvocationMessageComponent) SetExpanded

func (c *SkillInvocationMessageComponent) SetExpanded(expanded bool)

type StartupChoice

type StartupChoice struct {
	Label  string
	Value  string
	Cancel bool
}

type StartupSelectorOptions

type StartupSelectorOptions struct {
	Title      string
	Choices    []StartupChoice
	MaxVisible int
}

type StatusIndicator

type StatusIndicator struct {
	*tui.Loader
	Kind StatusIndicatorKind
}

func NewBranchSummaryStatusIndicator added in v0.1.2

func NewBranchSummaryStatusIndicator(ui tui.RenderRequester) *StatusIndicator

func NewCompactionStatusIndicator

func NewCompactionStatusIndicator(ui tui.RenderRequester, reason string) *StatusIndicator

func NewRetryStatusIndicator

func NewRetryStatusIndicator(ui tui.RenderRequester, attempt, maxAttempts int, delayMS int64) *StatusIndicator

func NewWorkingStatusIndicator

func NewWorkingStatusIndicator(ui tui.RenderRequester, message string, options ...*extensions.WorkingIndicatorOptions) *StatusIndicator

func (*StatusIndicator) Dispose

func (si *StatusIndicator) Dispose()

type StatusIndicatorKind

type StatusIndicatorKind string
const (
	StatusWorking       StatusIndicatorKind = "working"
	StatusRetry         StatusIndicatorKind = "retry"
	StatusCompaction    StatusIndicatorKind = "compaction"
	StatusBranchSummary StatusIndicatorKind = "branchSummary"
)

type ToolExecutionComponent

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

func NewToolExecutionComponent

func NewToolExecutionComponent(
	toolName, toolCallID string,
	args any,
	showImages bool,
	toolDef *extensions.ToolDefinition,
	ui tui.RenderRequester,
	cwd string,
) *ToolExecutionComponent

func (*ToolExecutionComponent) Invalidate

func (c *ToolExecutionComponent) Invalidate()

func (*ToolExecutionComponent) MarkExecutionStarted

func (c *ToolExecutionComponent) MarkExecutionStarted()

func (*ToolExecutionComponent) Render

func (c *ToolExecutionComponent) Render(width int) []string

func (*ToolExecutionComponent) SetArgsComplete

func (c *ToolExecutionComponent) SetArgsComplete()

func (*ToolExecutionComponent) SetExpanded

func (c *ToolExecutionComponent) SetExpanded(expanded bool)

func (*ToolExecutionComponent) UpdateArgs

func (c *ToolExecutionComponent) UpdateArgs(args any)

func (*ToolExecutionComponent) UpdateResult

func (c *ToolExecutionComponent) UpdateResult(content ai.ToolResultContent, isError bool, details any, partial bool)

type UserMessageComponent

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

func NewUserMessageComponent

func NewUserMessageComponent(text string, mdTheme tui.MarkdownTheme, outputPad int) *UserMessageComponent

func (*UserMessageComponent) Invalidate

func (c *UserMessageComponent) Invalidate()

func (*UserMessageComponent) Render

func (c *UserMessageComponent) Render(width int) []string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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