mirror of
https://github.com/router-for-me/CLIProxyAPIPlus.git
synced 2026-03-29 16:54:41 +00:00
added kilocode auth, needs adjusting
This commit is contained in:
121
sdk/auth/kilo.go
Normal file
121
sdk/auth/kilo.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/auth/kilo"
|
||||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||||
coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth"
|
||||
)
|
||||
|
||||
// KiloAuthenticator implements the login flow for Kilo AI accounts.
|
||||
type KiloAuthenticator struct{}
|
||||
|
||||
// NewKiloAuthenticator constructs a Kilo authenticator.
|
||||
func NewKiloAuthenticator() *KiloAuthenticator {
|
||||
return &KiloAuthenticator{}
|
||||
}
|
||||
|
||||
func (a *KiloAuthenticator) Provider() string {
|
||||
return "kilo"
|
||||
}
|
||||
|
||||
func (a *KiloAuthenticator) RefreshLead() *time.Duration {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Login manages the device flow authentication for Kilo AI.
|
||||
func (a *KiloAuthenticator) Login(ctx context.Context, cfg *config.Config, opts *LoginOptions) (*coreauth.Auth, error) {
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("cliproxy auth: configuration is required")
|
||||
}
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
if opts == nil {
|
||||
opts = &LoginOptions{}
|
||||
}
|
||||
|
||||
kilocodeAuth := kilo.NewKiloAuth()
|
||||
|
||||
fmt.Println("Initiating Kilo device authentication...")
|
||||
resp, err := kilocodeAuth.InitiateDeviceFlow(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to initiate device flow: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Please visit: %s\n", resp.VerificationURL)
|
||||
fmt.Printf("And enter code: %s\n", resp.Code)
|
||||
|
||||
fmt.Println("Waiting for authorization...")
|
||||
status, err := kilocodeAuth.PollForToken(ctx, resp.Code)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("authentication failed: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Authentication successful for %s\n", status.UserEmail)
|
||||
|
||||
profile, err := kilocodeAuth.GetProfile(ctx, status.Token)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch profile: %w", err)
|
||||
}
|
||||
|
||||
var orgID string
|
||||
if len(profile.Orgs) > 1 {
|
||||
fmt.Println("Multiple organizations found. Please select one:")
|
||||
for i, org := range profile.Orgs {
|
||||
fmt.Printf("[%d] %s (%s)\n", i+1, org.Name, org.ID)
|
||||
}
|
||||
|
||||
if opts.Prompt != nil {
|
||||
input, err := opts.Prompt("Enter the number of the organization: ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var choice int
|
||||
fmt.Sscanf(input, "%d", &choice)
|
||||
if choice > 0 && choice <= len(profile.Orgs) {
|
||||
orgID = profile.Orgs[choice-1].ID
|
||||
} else {
|
||||
orgID = profile.Orgs[0].ID
|
||||
fmt.Printf("Invalid choice, defaulting to %s\n", profile.Orgs[0].Name)
|
||||
}
|
||||
} else {
|
||||
orgID = profile.Orgs[0].ID
|
||||
fmt.Printf("Non-interactive mode, defaulting to organization: %s\n", profile.Orgs[0].Name)
|
||||
}
|
||||
} else if len(profile.Orgs) == 1 {
|
||||
orgID = profile.Orgs[0].ID
|
||||
}
|
||||
|
||||
defaults, err := kilocodeAuth.GetDefaults(ctx, status.Token, orgID)
|
||||
if err != nil {
|
||||
fmt.Printf("Warning: failed to fetch defaults: %v\n", err)
|
||||
defaults = &kilo.Defaults{}
|
||||
}
|
||||
|
||||
ts := &kilo.KiloTokenStorage{
|
||||
Token: status.Token,
|
||||
OrganizationID: orgID,
|
||||
Model: defaults.Model,
|
||||
Email: status.UserEmail,
|
||||
Type: "kilo",
|
||||
}
|
||||
|
||||
fileName := kilo.CredentialFileName(status.UserEmail)
|
||||
metadata := map[string]any{
|
||||
"email": status.UserEmail,
|
||||
"organization_id": orgID,
|
||||
"model": defaults.Model,
|
||||
}
|
||||
|
||||
return &coreauth.Auth{
|
||||
ID: fileName,
|
||||
Provider: a.Provider(),
|
||||
FileName: fileName,
|
||||
Storage: ts,
|
||||
Metadata: metadata,
|
||||
}, nil
|
||||
}
|
||||
@@ -413,6 +413,8 @@ func (s *Service) ensureExecutorsForAuth(a *coreauth.Auth) {
|
||||
s.coreManager.RegisterExecutor(executor.NewKimiExecutor(s.cfg))
|
||||
case "kiro":
|
||||
s.coreManager.RegisterExecutor(executor.NewKiroExecutor(s.cfg))
|
||||
case "kilo":
|
||||
s.coreManager.RegisterExecutor(executor.NewKiloExecutor(s.cfg))
|
||||
case "github-copilot":
|
||||
s.coreManager.RegisterExecutor(executor.NewGitHubCopilotExecutor(s.cfg))
|
||||
default:
|
||||
@@ -844,6 +846,9 @@ func (s *Service) registerModelsForAuth(a *coreauth.Auth) {
|
||||
case "kiro":
|
||||
models = s.fetchKiroModels(a)
|
||||
models = applyExcludedModels(models, excluded)
|
||||
case "kilo":
|
||||
models = executor.FetchKiloModels(context.Background(), a, s.cfg)
|
||||
models = applyExcludedModels(models, excluded)
|
||||
default:
|
||||
// Handle OpenAI-compatibility providers by name using config
|
||||
if s.cfg != nil {
|
||||
|
||||
Reference in New Issue
Block a user