| // Package copilot provides authentication and token management functionality | |
| // for GitHub Copilot AI services. It handles OAuth2 device flow token storage, | |
| // serialization, and retrieval for maintaining authenticated sessions with the Copilot API. | |
| package copilot | |
| import ( | |
| "encoding/json" | |
| "fmt" | |
| "os" | |
| "path/filepath" | |
| "github.com/router-for-me/CLIProxyAPI/v6/internal/misc" | |
| ) | |
| // CopilotTokenStorage stores OAuth2 token information for GitHub Copilot API authentication. | |
| // It maintains compatibility with the existing auth system while adding Copilot-specific fields | |
| // for managing access tokens and user account information. | |
| type CopilotTokenStorage struct { | |
| // AccessToken is the OAuth2 access token used for authenticating API requests. | |
| AccessToken string `json:"access_token"` | |
| // TokenType is the type of token, typically "bearer". | |
| TokenType string `json:"token_type"` | |
| // Scope is the OAuth2 scope granted to the token. | |
| Scope string `json:"scope"` | |
| // ExpiresAt is the timestamp when the access token expires (if provided). | |
| ExpiresAt string `json:"expires_at,omitempty"` | |
| // Username is the GitHub username associated with this token. | |
| Username string `json:"username"` | |
| // Type indicates the authentication provider type, always "github-copilot" for this storage. | |
| Type string `json:"type"` | |
| } | |
| // CopilotTokenData holds the raw OAuth token response from GitHub. | |
| type CopilotTokenData struct { | |
| // AccessToken is the OAuth2 access token. | |
| AccessToken string `json:"access_token"` | |
| // TokenType is the type of token, typically "bearer". | |
| TokenType string `json:"token_type"` | |
| // Scope is the OAuth2 scope granted to the token. | |
| Scope string `json:"scope"` | |
| } | |
| // CopilotAuthBundle bundles authentication data for storage. | |
| type CopilotAuthBundle struct { | |
| // TokenData contains the OAuth token information. | |
| TokenData *CopilotTokenData | |
| // Username is the GitHub username. | |
| Username string | |
| } | |
| // DeviceCodeResponse represents GitHub's device code response. | |
| type DeviceCodeResponse struct { | |
| // DeviceCode is the device verification code. | |
| DeviceCode string `json:"device_code"` | |
| // UserCode is the code the user must enter at the verification URI. | |
| UserCode string `json:"user_code"` | |
| // VerificationURI is the URL where the user should enter the code. | |
| VerificationURI string `json:"verification_uri"` | |
| // ExpiresIn is the number of seconds until the device code expires. | |
| ExpiresIn int `json:"expires_in"` | |
| // Interval is the minimum number of seconds to wait between polling requests. | |
| Interval int `json:"interval"` | |
| } | |
| // SaveTokenToFile serializes the Copilot token storage to a JSON file. | |
| // This method creates the necessary directory structure and writes the token | |
| // data in JSON format to the specified file path for persistent storage. | |
| // | |
| // Parameters: | |
| // - authFilePath: The full path where the token file should be saved | |
| // | |
| // Returns: | |
| // - error: An error if the operation fails, nil otherwise | |
| func (ts *CopilotTokenStorage) SaveTokenToFile(authFilePath string) error { | |
| misc.LogSavingCredentials(authFilePath) | |
| ts.Type = "github-copilot" | |
| if err := os.MkdirAll(filepath.Dir(authFilePath), 0700); err != nil { | |
| return fmt.Errorf("failed to create directory: %v", err) | |
| } | |
| f, err := os.Create(authFilePath) | |
| if err != nil { | |
| return fmt.Errorf("failed to create token file: %w", err) | |
| } | |
| defer func() { | |
| _ = f.Close() | |
| }() | |
| if err = json.NewEncoder(f).Encode(ts); err != nil { | |
| return fmt.Errorf("failed to write token to file: %w", err) | |
| } | |
| return nil | |
| } | |