wizard

package
v0.35.4 Latest Latest
Warning

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

Go to latest
Published: Aug 25, 2026 License: MIT Imports: 26 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 ElevenLabsVoice added in v0.17.0

type ElevenLabsVoice struct {
	ID       string
	Name     string
	Category string
}

ElevenLabsVoice is one voice the account can speak with.

func ListElevenLabsVoices added in v0.17.0

func ListElevenLabsVoices(ctx context.Context, client *http.Client, apiBase, apiKey string) ([]ElevenLabsVoice, error)

ListElevenLabsVoices asks the account which voices it has, so the wizard can offer names instead of demanding a pasted id. An error is informational: the caller falls back to free-text entry.

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)
	PiperVoices string // Piper's voice catalogue URL (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.
	// A non-blank voice names the Piper voice to install; blank lets the
	// installer resolve one from the language.
	InstallSpeech func(ctx context.Context, language, voice 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)

	// The autostart trio: saying yes to "start Factor at login" is a request
	// for a login entry, not for homework, so the wizard installs and removes
	// the entry itself.
	AutostartInstalled func() (mechanism string, ok bool)
	InstallAutostart   func(ctx context.Context, configPath string) (mechanism string, err error)
	RemoveAutostart    func(ctx context.Context) error
}

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 PiperVoice added in v0.17.0

type PiperVoice struct {
	Key     string // e.g. "es_MX-ald-medium"
	Quality string
	Exact   bool // matches the exact locale, not just the language family
}

PiperVoice is one catalogue voice that fits a language.

func ListPiperVoices added in v0.17.0

func ListPiperVoices(ctx context.Context, client *http.Client, catalogueURL, language string) ([]PiperVoice, error)

ListPiperVoices fetches Piper's catalogue and returns the voices for a language, exact locale first, then the family at large — the same widening the installer's own resolver does. An error is informational: the caller keeps letting the installer pick.

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