wizard

package
v0.16.1 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package wizard is Factor's interactive setup: a terminal front-end for `factor init` that picks a provider and model (probing them live), installs the smrti memory engine, wires up channels, and checks the desktop tools.

The UI is stdlib plus golang.org/x/term: arrow-key menus and masked input when stdin is a real terminal, plain numbered prompts when it is a pipe, and no ANSI at all when the terminal (or NO_COLOR) says so. Every prompt has a default, so holding Enter produces a working configuration.

Index

Constants

This section is empty.

Variables

View Source
var ErrAborted = errors.New("setup cancelled")

ErrAborted is returned when the user interrupts a prompt (Ctrl-C, EOF).

Functions

func CheckElevenLabs added in v0.4.0

func CheckElevenLabs(ctx context.Context, client *http.Client, apiBase, apiKey string) (string, error)

CheckElevenLabs validates a text-to-speech key and returns the plan it is on.

func CheckProvider

func CheckProvider(ctx context.Context, cand config.Candidate) error

CheckProvider verifies credentials and model with one minimal completion.

func CheckSpeechServer added in v0.4.0

func CheckSpeechServer(ctx context.Context, client *http.Client, baseURL string) error

CheckSpeechServer verifies a local OpenAI-compatible speech server is answering, so the local voice tiers fail here rather than mid-call.

func CheckTelegram

func CheckTelegram(ctx context.Context, client *http.Client, apiBase, token string) (string, error)

CheckTelegram validates a bot token and returns the bot's @username.

func CheckTelnyx added in v0.6.0

func CheckTelnyx(ctx context.Context, client *http.Client, apiBase, apiKey, connectionID string) (string, error)

CheckTelnyx validates carrier credentials and returns the name of the Call Control Application the number belongs to. Reading that application proves both halves at once: a bad key is rejected, and a connection id that is not an application of this account is not found.

func CheckTwilio added in v0.4.0

func CheckTwilio(ctx context.Context, client *http.Client, apiBase, accountSID, authToken string) (string, error)

CheckTwilio validates carrier credentials and returns the account's name. The auth token rides in an Authorization header, never in the URL, so a transport error cannot leak it.

func DetectLocalProvider

func DetectLocalProvider(ctx context.Context, client *http.Client) (config.Candidate, bool)

DetectLocalProvider probes the well-known local endpoints (Ollama, LM Studio, llama.cpp) so the wizard can offer a free offline fallback.

func ListModels

func ListModels(ctx context.Context, client *http.Client, cand config.Candidate) ([]string, error)

ListModels asks an endpoint what models it serves. Not every OpenAI-compatible gateway implements /models, so an error here is informational — the caller falls back to free-text entry.

func Run

func Run(ctx context.Context, path string, opts Options) error

Run walks the user through setup and writes the config file at path ("" = the default location). It edits the on-disk config, never the env-overlaid one, so secrets exported in the environment stay out of the file.

Types

type Option

type Option struct {
	Label string
	Hint  string
}

Option is one choice in a Select.

type Options

type Options struct {
	UI         *UI
	Version    string
	HTTP       *http.Client
	Home       string // FACTOR_HOME (defaults to config.Home())
	Telegram   string // Telegram API base (defaults to the real one)
	Twilio     string // Twilio API base (defaults to the real one)
	Telnyx     string // Telnyx API base (defaults to the real one)
	ElevenLabs string // ElevenLabs API base (defaults to the real one)

	// NonInteractive skips every prompt: defaults are kept, smrti is
	// installed when missing, and the config is written as-is.
	NonInteractive bool
	// NoInstall suppresses installing smrti and desktop helpers.
	NoInstall bool

	EnsureSmrti func(ctx context.Context, cfg config.MemoryConfig, progress memory.Progress) (path string, installed bool, err error)
	// MemoryAnswering reports whether a smrti is already serving. Someone
	// running one in Docker or on another box has a working memory with no
	// local binary to find, and must not be offered an install over it.
	MemoryAnswering func(ctx context.Context, cfg config.MemoryConfig) bool
	InstallPackages func(ctx context.Context, packages []string) (string, error)
	Desktop         desktop.Env

	// Audio is the seam to the machine's sound system, for the PC voice
	// step: probing for a sound card and for the capture/playback helpers.
	Audio voice.Env

	// InstallSpeech puts the local speech engines and their models on the
	// machine. Choosing a local tier is a request for local speech, not for
	// homework, so the wizard does this rather than telling the user to.
	InstallSpeech func(ctx context.Context, language string, needSTT, needTTS bool,
		progress phone.Progress) (phone.SpeechChoices, error)

	// EnsureBrowser puts a browser on the machine, and VerifyBrowser proves
	// the configured one really drives. Same reasoning as speech: enabling
	// the browser tools is a request to browse, not a request for homework.
	EnsureBrowser func(ctx context.Context, progress browser.Progress) (path string, installed bool, err error)
	VerifyBrowser func(ctx context.Context, cfg config.BrowserConfig) error

	// EnsureFastBrowser installs the optional read-only engine, and
	// FastBrowserSupported reports whether this machine could run it at all.
	EnsureFastBrowser    func(ctx context.Context, progress browser.Progress) (path string, installed bool, err error)
	FastBrowserSupported func() (bool, string)
}

Options configures a wizard run. The function fields exist so tests can drive the whole flow without touching the network, the package manager, or the user's Python installation.

type UI

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

UI draws prompts and reads answers.

func New

func New(in *os.File, out io.Writer) *UI

New builds a UI for the given streams, auto-detecting terminal features.

func NewPlain

func NewPlain(in io.Reader, out io.Writer) *UI

NewPlain builds a non-interactive UI over arbitrary streams (tests, pipes).

func (*UI) Banner

func (u *UI) Banner(version string)

Banner prints the header shown once at the start of setup.

func (*UI) Confirm

func (u *UI) Confirm(question string, def bool) (bool, error)

Confirm asks a yes/no question.

func (*UI) Fail

func (u *UI) Fail(format string, args ...any)

func (*UI) Info

func (u *UI) Info(format string, args ...any)

func (*UI) Input

func (u *UI) Input(question, def string) (string, error)

Input asks for a line of text, returning def when the answer is blank.

func (*UI) Interactive

func (u *UI) Interactive() bool

Interactive reports whether prompts can use the fancy path.

func (*UI) MultiSelect

func (u *UI) MultiSelect(question string, opts []Option, selected []bool) ([]bool, error)

MultiSelect toggles a set of options. Space toggles, Enter accepts.

func (*UI) Note

func (u *UI) Note(format string, args ...any)

func (*UI) Progress

func (u *UI) Progress() func(string, ...any)

Progress returns a function that prints sub-steps of a long task (used by the smrti installer, which reports which installer it is trying).

func (*UI) Secret

func (u *UI) Secret(question, current string) (string, error)

Secret asks for a value without echoing it. A blank answer keeps current (whose presence, not value, is shown).

func (*UI) Select

func (u *UI) Select(question string, opts []Option, def int) (int, error)

Select shows a menu and returns the chosen index. On a real terminal it is an arrow-key menu; otherwise a numbered list.

func (*UI) Step

func (u *UI) Step(n, total int, title string)

Step prints a numbered section header.

func (*UI) Success

func (u *UI) Success(format string, args ...any)

func (*UI) Summary

func (u *UI) Summary(title string, rows [][2]string)

Summary prints an aligned key/value block.

func (*UI) Task

func (u *UI) Task(label string, fn func() error) error

Task runs fn while showing a spinner, then reports the outcome. The returned error is fn's, so callers can branch on it.

func (*UI) Warn

func (u *UI) Warn(format string, args ...any)

Jump to

Keyboard shortcuts

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