Skip to content
Closed
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: 10 additions & 4 deletions cmd/picoclaw/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -789,13 +789,14 @@ func authHelp() {
fmt.Println(" status Show current auth status")
fmt.Println()
fmt.Println("Login options:")
fmt.Println(" --provider <name> Provider to login with (openai, anthropic)")
fmt.Println(" --provider <name> Provider to login with (openai, anthropic, gemini)")
fmt.Println(" --device-code Use device code flow (for headless environments)")
fmt.Println()
fmt.Println("Examples:")
fmt.Println(" picoclaw auth login --provider openai")
fmt.Println(" picoclaw auth login --provider openai --device-code")
fmt.Println(" picoclaw auth login --provider anthropic")
fmt.Println(" picoclaw auth login --provider gemini")
fmt.Println(" picoclaw auth logout --provider openai")
fmt.Println(" picoclaw auth status")
}
Expand All @@ -819,18 +820,18 @@ func authLoginCmd() {

if provider == "" {
fmt.Println("Error: --provider is required")
fmt.Println("Supported providers: openai, anthropic")
fmt.Println("Supported providers: openai, anthropic, gemini")
return
}

switch provider {
case "openai":
authLoginOpenAI(useDeviceCode)
case "anthropic":
case "anthropic", "gemini":
authLoginPasteToken(provider)
default:
fmt.Printf("Unsupported provider: %s\n", provider)
fmt.Println("Supported providers: openai, anthropic")
fmt.Println("Supported providers: openai, anthropic, gemini")
}
}

Expand Down Expand Up @@ -889,6 +890,8 @@ func authLoginPasteToken(provider string) {
appCfg.Providers.Anthropic.AuthMethod = "token"
case "openai":
appCfg.Providers.OpenAI.AuthMethod = "token"
case "gemini":
appCfg.Providers.Gemini.AuthMethod = "token"
}
if err := config.SaveConfig(getConfigPath(), appCfg); err != nil {
fmt.Printf("Warning: could not update config: %v\n", err)
Expand Down Expand Up @@ -925,6 +928,8 @@ func authLogoutCmd() {
appCfg.Providers.OpenAI.AuthMethod = ""
case "anthropic":
appCfg.Providers.Anthropic.AuthMethod = ""
case "gemini":
appCfg.Providers.Gemini.AuthMethod = ""
}
config.SaveConfig(getConfigPath(), appCfg)
}
Expand All @@ -940,6 +945,7 @@ func authLogoutCmd() {
if err == nil {
appCfg.Providers.OpenAI.AuthMethod = ""
appCfg.Providers.Anthropic.AuthMethod = ""
appCfg.Providers.Gemini.AuthMethod = ""
config.SaveConfig(getConfigPath(), appCfg)
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/auth/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ func providerDisplayName(provider string) string {
return "console.anthropic.com"
case "openai":
return "platform.openai.com"
case "gemini":
return "aistudio.google.com/apikey"
default:
return provider
}
Expand Down
30 changes: 26 additions & 4 deletions pkg/providers/http_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,19 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
}
}
case "gemini", "google":
if cfg.Providers.Gemini.APIKey != "" {
apiKey = cfg.Providers.Gemini.APIKey
if cfg.Providers.Gemini.APIKey != "" || cfg.Providers.Gemini.AuthMethod != "" {
if cfg.Providers.Gemini.AuthMethod == "token" && cfg.Providers.Gemini.APIKey == "" {
cred, err := auth.GetCredential("gemini")
if err != nil {
return nil, fmt.Errorf("loading auth credentials: %w", err)
}
if cred == nil {
return nil, fmt.Errorf("no credentials for gemini. Run: picoclaw auth login --provider gemini")
}
apiKey = cred.AccessToken
} else {
apiKey = cfg.Providers.Gemini.APIKey
}
apiBase = cfg.Providers.Gemini.APIBase
if apiBase == "" {
apiBase = "https://generativelanguage.googleapis.com/v1beta"
Expand Down Expand Up @@ -378,8 +389,19 @@ func CreateProvider(cfg *config.Config) (LLMProvider, error) {
apiBase = "https://api.openai.com/v1"
}

case (strings.Contains(lowerModel, "gemini") || strings.HasPrefix(model, "google/")) && cfg.Providers.Gemini.APIKey != "":
apiKey = cfg.Providers.Gemini.APIKey
case (strings.Contains(lowerModel, "gemini") || strings.HasPrefix(model, "google/")) && (cfg.Providers.Gemini.APIKey != "" || cfg.Providers.Gemini.AuthMethod != ""):
if cfg.Providers.Gemini.AuthMethod == "token" && cfg.Providers.Gemini.APIKey == "" {
cred, err := auth.GetCredential("gemini")
if err != nil {
return nil, fmt.Errorf("loading auth credentials: %w", err)
}
if cred == nil {
return nil, fmt.Errorf("no credentials for gemini. Run: picoclaw auth login --provider gemini")
}
apiKey = cred.AccessToken
} else {
apiKey = cfg.Providers.Gemini.APIKey
}
apiBase = cfg.Providers.Gemini.APIBase
proxy = cfg.Providers.Gemini.Proxy
if apiBase == "" {
Expand Down