Files
Enterprise-Knowledge-Base/cli/internal/prompt/tty.go
T
nullkey 16f11380ee feat(cli): keyring backend + TTY prompter (PR-3)
Adds the OS keyring secret backend and the huh-based TTY Prompter so
PR-4 (auth login) can persist credentials and read interactive input.
The Factory's Client closure SDK wiring + Secrets closure landed in
PR-1's foundation tree to keep PR-1 self-contained.

internal/secrets/keyring.go:
- KeyringStore: zalando/go-keyring backed; namespace "weknora:<context>".
  KeyringStore.Ref -> keychain://weknora/<context>/<key>
- NewBestEffortStore probes the OS keyring with a sentinel get and falls
  back to FileStore on unsupported platforms (WSL without DBus, etc.)

internal/prompt/tty.go:
- TTYPrompter: huh.NewForm / huh.NewInput / huh.NewConfirm wrapper
  satisfying Prompter. Used when iostreams.IO reports both stdout and
  stderr are TTYs.

Dependencies (zalando/go-keyring, charmbracelet/huh) are declared in
PR-1's go.mod since the foundation tree referenced them via the Store
interface and TTY-detection helpers.
2026-05-07 23:19:46 +08:00

49 lines
1.2 KiB
Go

package prompt
import (
"fmt"
"github.com/charmbracelet/huh"
)
// TTYPrompter implements Prompter using charmbracelet/huh for interactive
// input. Used by the production Factory.Prompter closure when iostreams.IO
// is interactive.
type TTYPrompter struct{}
// NewTTYPrompter returns a Prompter backed by huh.
func NewTTYPrompter() Prompter { return TTYPrompter{} }
func (TTYPrompter) Input(label, defaultValue string) (string, error) {
v := defaultValue
form := huh.NewForm(huh.NewGroup(
huh.NewInput().Title(label).Value(&v),
))
if err := form.Run(); err != nil {
return "", fmt.Errorf("prompt input: %w", err)
}
return v, nil
}
func (TTYPrompter) Password(label string) (string, error) {
var v string
form := huh.NewForm(huh.NewGroup(
huh.NewInput().Title(label).EchoMode(huh.EchoModePassword).Value(&v),
))
if err := form.Run(); err != nil {
return "", fmt.Errorf("prompt password: %w", err)
}
return v, nil
}
func (TTYPrompter) Confirm(label string, defaultValue bool) (bool, error) {
v := defaultValue
form := huh.NewForm(huh.NewGroup(
huh.NewConfirm().Title(label).Value(&v),
))
if err := form.Run(); err != nil {
return false, fmt.Errorf("prompt confirm: %w", err)
}
return v, nil
}