mirror of
https://github.com/router-for-me/CLIProxyAPIPlus.git
synced 2026-03-08 06:43:41 +00:00
Add complete GitHub Copilot support including: - Device flow OAuth authentication via GitHub's official client ID - Token management with automatic caching (25 min TTL) - OpenAI-compatible API executor for api.githubcopilot.com - 16 model definitions (GPT-5 variants, Claude variants, Gemini, Grok, Raptor) - CLI login command via -github-copilot-login flag - SDK authenticator and refresh registry integration Enables users to authenticate with their GitHub Copilot subscription and use it as a backend provider alongside existing providers.
94 lines
3.4 KiB
Go
94 lines
3.4 KiB
Go
// 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
|
|
}
|