package cmd import ( "cursor-api-proxy/internal/agent" "encoding/json" "fmt" "os" "path/filepath" ) type AccountInfo struct { Name string ConfigDir string Authenticated bool Email string DisplayName string AuthID string Plan string SubscriptionStatus string ExpiresAt string } func ReadAccountInfo(name, configDir string) AccountInfo { info := AccountInfo{Name: name, ConfigDir: configDir} configFile := filepath.Join(configDir, "cli-config.json") data, err := os.ReadFile(configFile) if err != nil { return info } var raw struct { AuthInfo *struct { Email string `json:"email"` DisplayName string `json:"displayName"` AuthID string `json:"authId"` } `json:"authInfo"` } if err := json.Unmarshal(data, &raw); err == nil && raw.AuthInfo != nil { info.Authenticated = true info.Email = raw.AuthInfo.Email info.DisplayName = raw.AuthInfo.DisplayName info.AuthID = raw.AuthInfo.AuthID } statsigFile := filepath.Join(configDir, "statsig-cache.json") statsigData, err := os.ReadFile(statsigFile) if err != nil { return info } var statsigWrapper struct { Data string `json:"data"` } if err := json.Unmarshal(statsigData, &statsigWrapper); err != nil || statsigWrapper.Data == "" { return info } var statsig struct { User *struct { Custom *struct { IsEnterpriseUser bool `json:"isEnterpriseUser"` StripeSubscriptionStatus string `json:"stripeSubscriptionStatus"` StripeMembershipExpiration string `json:"stripeMembershipExpiration"` } `json:"custom"` } `json:"user"` } if err := json.Unmarshal([]byte(statsigWrapper.Data), &statsig); err != nil { return info } if statsig.User != nil && statsig.User.Custom != nil { c := statsig.User.Custom if c.IsEnterpriseUser { info.Plan = "Enterprise" } else if c.StripeSubscriptionStatus == "active" { info.Plan = "Pro" } else { info.Plan = "Free" } info.SubscriptionStatus = c.StripeSubscriptionStatus info.ExpiresAt = c.StripeMembershipExpiration } return info } func HandleAccountsList() error { accountsDir := agent.AccountsDir() entries, err := os.ReadDir(accountsDir) if err != nil { fmt.Println("No accounts found. Use 'cursor-api-proxy login' to add one.") return nil } var names []string for _, e := range entries { if e.IsDir() { names = append(names, e.Name()) } } if len(names) == 0 { fmt.Println("No accounts found. Use 'cursor-api-proxy login' to add one.") return nil } fmt.Print("Cursor Accounts:\n\n") keychainToken := agent.ReadKeychainToken() for i, name := range names { configDir := filepath.Join(accountsDir, name) info := ReadAccountInfo(name, configDir) fmt.Printf(" %d. %s\n", i+1, name) if info.Authenticated { cachedToken := agent.ReadCachedToken(configDir) keychainMatchesAccount := keychainToken != "" && info.AuthID != "" && TokenSub(keychainToken) == info.AuthID token := cachedToken if token == "" && keychainMatchesAccount { token = keychainToken } var liveProfile *StripeProfile var liveUsage *UsageData if token != "" { liveUsage, _ = FetchAccountUsage(token) liveProfile, _ = FetchStripeProfile(token) } if info.Email != "" { display := "" if info.DisplayName != "" { display = " (" + info.DisplayName + ")" } fmt.Printf(" %s%s\n", info.Email, display) } if info.Plan != "" && liveProfile == nil { canceled := "" if info.SubscriptionStatus == "canceled" { canceled = " · canceled" } expiry := "" if info.ExpiresAt != "" { expiry = " · expires " + info.ExpiresAt } fmt.Printf(" %s%s%s\n", info.Plan, canceled, expiry) } fmt.Println(" Authenticated") if liveProfile != nil { fmt.Printf(" %s\n", DescribePlan(liveProfile)) } if liveUsage != nil { for _, line := range FormatUsageSummary(liveUsage) { fmt.Println(line) } } } else { fmt.Println(" Not authenticated") } fmt.Println("") } fmt.Println("Tip: run 'cursor-api-proxy logout ' to remove an account.") return nil } func HandleLogout(accountName string) error { if accountName == "" { fmt.Fprintln(os.Stderr, "Error: Please specify the account name to remove.") fmt.Fprintln(os.Stderr, "Usage: cursor-api-proxy logout ") os.Exit(1) } accountsDir := agent.AccountsDir() configDir := filepath.Join(accountsDir, accountName) if _, err := os.Stat(configDir); os.IsNotExist(err) { fmt.Fprintf(os.Stderr, "Account '%s' not found.\n", accountName) os.Exit(1) } if err := os.RemoveAll(configDir); err != nil { fmt.Fprintf(os.Stderr, "Error removing account: %v\n", err) os.Exit(1) } fmt.Printf("Account '%s' removed.\n", accountName) return nil }