Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions internal/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,20 +99,6 @@ type Provider interface {
Load(storage Storage) (*Credential, error)
}

// Prompter abstracts user interaction for credential collection.
//
//go:generate go run github.com/matryer/moq@latest -pkg mocks -out mocks/prompter.go . Prompter
type Prompter interface {
// Print outputs text to the user.
Print(message string)

// PromptSecret prompts for secret input (no echo).
PromptSecret(prompt string) (string, error)

// PromptChoice prompts user to select from options, returns 0-based index.
PromptChoice(prompt string, options []string) (int, error)
}

// StoreCredential is a helper function to store a credential in JSON format.
func StoreCredential(storage Storage, account string, cred Credential) error {
data, err := json.Marshal(cred)
Expand Down
170 changes: 0 additions & 170 deletions internal/auth/mocks/prompter.go

This file was deleted.

72 changes: 0 additions & 72 deletions internal/auth/prompter.go

This file was deleted.

13 changes: 7 additions & 6 deletions internal/cmd/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/jmgilman/headjack/internal/auth"
"github.com/jmgilman/headjack/internal/keychain"
"github.com/jmgilman/headjack/internal/prompt"
)

var authCmd = &cobra.Command{
Expand Down Expand Up @@ -128,13 +129,13 @@ func runAuthFlow(provider auth.Provider) error {
return fmt.Errorf("initialize credential storage: %w", err)
}

prompter := auth.NewTerminalPrompter()
prompter := prompt.New()
info := provider.Info()

prompter.Print(fmt.Sprintf("Configure %s authentication", info.Name))
prompter.Print("")

choice, err := prompter.PromptChoice("Authentication method:", []string{
choice, err := prompter.Choice("Authentication method:", []string{
"Subscription",
"API Key",
})
Expand Down Expand Up @@ -169,7 +170,7 @@ func runAuthFlow(provider auth.Provider) error {
// handleSubscriptionAuth handles subscription-based authentication.
// For Claude, prompts for manual token entry.
// For Gemini/Codex, attempts to read existing credentials from config files.
func handleSubscriptionAuth(provider auth.Provider, prompter auth.Prompter) (auth.Credential, error) {
func handleSubscriptionAuth(provider auth.Provider, prompter prompt.Prompter) (auth.Credential, error) {
// Try to auto-detect existing credentials
value, err := provider.CheckSubscription()
if err == nil {
Expand All @@ -188,7 +189,7 @@ func handleSubscriptionAuth(provider auth.Provider, prompter auth.Prompter) (aut
prompter.Print(err.Error())
prompter.Print("")

value, err = prompter.PromptSecret("Paste your credential: ")
value, err = prompter.Secret("Paste your credential: ")
if err != nil {
return auth.Credential{}, fmt.Errorf("read credential: %w", err)
}
Expand All @@ -204,13 +205,13 @@ func handleSubscriptionAuth(provider auth.Provider, prompter auth.Prompter) (aut
}

// handleAPIKeyAuth handles API key authentication.
func handleAPIKeyAuth(provider auth.Provider, prompter auth.Prompter) (auth.Credential, error) {
func handleAPIKeyAuth(provider auth.Provider, prompter prompt.Prompter) (auth.Credential, error) {
info := provider.Info()

prompter.Print(fmt.Sprintf("Enter your %s API key.", info.Name))
prompter.Print("")

value, err := prompter.PromptSecret("API key: ")
value, err := prompter.Secret("API key: ")
if err != nil {
return auth.Credential{}, fmt.Errorf("read API key: %w", err)
}
Expand Down
Loading