tui

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: May 13, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package tui owns the interactive `askit chat` experience. The bubbletea Model drives a scrollable transcript, a multi-line input area, and a slash-command dispatcher that never reaches the model. @path file references in input are expanded at submit time via the prompt package.

NOTE (v0.1.x): The `@`-triggered overlay file picker described in spec §8.2 is DEFERRED to v0.2. In v0.1.x, @path references in typed input are resolved against the filesystem exactly like `askit query`. The slash-command, streaming, cancel, and save flows are complete.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsSlash

func IsSlash(input string) bool

IsSlash reports whether a submitted line is a slash command. A slash command starts with "/" AND contains no "@" token — matching FR-055. Returning false means the input is a regular user message.

Types

type Entry

type Entry struct {
	Role      Role
	Text      string
	Timestamp time.Time
	Cancelled bool
}

Entry is one message in the transcript. Streaming assistant replies accumulate into the most recent entry's Text field.

type Model

type Model struct {
	Session *Session
	Cfg     *config.Config
	Req     Requester
	Logger  *slog.Logger
	NoColor bool
	// contains filtered or unexported fields
}

Model is the bubbletea Model driving the chat TUI.

func New

func New(sess *Session, cfg *config.Config, req Requester, logger *slog.Logger, noColor bool) *Model

New builds a chat model from an active session and requester.

func (*Model) Init

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

Init satisfies tea.Model.

func (*Model) Quit

func (m *Model) Quit() bool

Quit reports whether the model has requested termination.

func (*Model) Update

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

Update processes one message (keystroke, stream chunk, etc).

func (*Model) View

func (m *Model) View() string

View renders the current frame.

type RealRequester

type RealRequester struct{ Client *client.Client }

RealRequester is the production Requester implementation backed by a *client.Client.

func (RealRequester) Stream

func (r RealRequester) Stream(ctx context.Context, req *client.Request) (<-chan client.StreamChunk, <-chan error)

Stream delegates to Client.Stream.

type Requester

type Requester interface {
	Stream(ctx context.Context, req *client.Request) (<-chan client.StreamChunk, <-chan error)
}

Requester abstracts the HTTP/SSE call for testability. The default implementation is RealRequester which wraps a *client.Client.

type Role

type Role string

Role is the message role in the transcript.

const (
	RoleUser      Role = "user"
	RoleAssistant Role = "assistant"
	RoleSystem    Role = "system"
)

Role values.

type Session

type Session struct {
	SystemPrompt   string
	PresetName     string
	Model          string
	ConfigFilePath string
	History        []Entry
	References     []prompt.FileRef // all @path refs seen this session
	InFlight       bool
}

Session is the in-memory state of one interactive run. Never persisted.

func (*Session) AppendAssistantChunk

func (s *Session) AppendAssistantChunk(delta string)

AppendAssistantChunk adds a streamed delta to the most recent assistant entry (or creates one if none exists).

func (*Session) AppendUser

func (s *Session) AppendUser(text string)

AppendUser adds a user message to the transcript.

func (*Session) ClearHistory

func (s *Session) ClearHistory()

ClearHistory drops all messages; keeps the system prompt.

func (*Session) LastAssistantText

func (s *Session) LastAssistantText() string

LastAssistantText returns the text of the most recent assistant message, or the empty string if none.

func (*Session) MarkLastCancelled

func (s *Session) MarkLastCancelled()

MarkLastCancelled tags the most recent assistant entry as cancelled.

func (*Session) RecordReferences

func (s *Session) RecordReferences(refs []prompt.FileRef)

RecordReferences merges newly-resolved file references into the session-wide list. Duplicates are skipped by resolved Path.

func (*Session) SaveConversation

func (s *Session) SaveConversation(path string) error

SaveConversation writes the full transcript to path. Format by extension: `.json` = array of entries; `.md` = formatted Markdown; `.txt` = plain role-prefixed lines.

func (*Session) SaveLastReply

func (s *Session) SaveLastReply(path string) error

SaveLastReply writes the most recent assistant reply to path. The format is chosen by extension per FR-056 (revised): `.json`, `.md`, or `.txt`. Other extensions are rejected.

func (*Session) StartAssistant

func (s *Session) StartAssistant() *Entry

StartAssistant opens a new assistant entry ready to receive streamed chunks. Returns a pointer to allow in-place updates by callers.

type SlashResult

type SlashResult struct {
	Handled   bool   // true if the input was a slash command (don't send to model)
	Notice    string // optional inline transcript message (info/ok)
	Err       error  // inline transcript error; session stays alive
	Quit      bool   // true if /quit or /exit
	ClearView bool   // true after /clear (UI may want to redraw)
}

SlashResult is produced by DispatchSlash so the bubbletea model can react without the dispatcher itself touching the UI.

func DispatchSlash

func DispatchSlash(input string, sess *Session, presets map[string]config.Preset) SlashResult

DispatchSlash parses and executes a slash command against sess. Presets is passed separately so /preset can introspect the available set without importing config into the model file.

Unrecognized commands produce a SlashResult{Handled: true, Err: ...} so the TUI can render the error inline without re-routing to the model.

Jump to

Keyboard shortcuts

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