@@ -2,9 +2,11 @@ package provider
22
33import (
44 "context"
5+ "encoding/json"
56 "fmt"
67 "net/http"
78 "os"
9+ "runtime"
810 "strings"
911 "time"
1012
@@ -58,6 +60,39 @@ func normalizeCopilotModel(model string) string {
5860 return m
5961}
6062
63+ func (c * CopilotProvider ) exchangeGitHubToken (ctx context.Context , githubToken string ) (string , error ) {
64+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , "https://api.github.com/copilot_internal/v2/token" , nil )
65+ if err != nil {
66+ return "" , fmt .Errorf ("failed creating token request: %w" , err )
67+ }
68+ req .Header .Set ("Authorization" , "Token " + githubToken )
69+ req .Header .Set ("User-Agent" , "lazycommit/1.0" )
70+
71+ resp , err := c .httpClient .Do (req )
72+ if err != nil {
73+ return "" , fmt .Errorf ("failed exchanging token: %w" , err )
74+ }
75+ defer resp .Body .Close ()
76+ if resp .StatusCode != http .StatusOK {
77+ var body struct {
78+ Message string `json:"message"`
79+ }
80+ _ = json .NewDecoder (resp .Body ).Decode (& body )
81+ return "" , fmt .Errorf ("token exchange failed: %d %s" , resp .StatusCode , body .Message )
82+ }
83+ var tr struct {
84+ Token string `json:"token"`
85+ ExpiresAt int64 `json:"expires_at"`
86+ }
87+ if err := json .NewDecoder (resp .Body ).Decode (& tr ); err != nil {
88+ return "" , fmt .Errorf ("failed decoding token response: %w" , err )
89+ }
90+ if tr .Token == "" {
91+ return "" , fmt .Errorf ("empty copilot bearer token" )
92+ }
93+ return tr .Token , nil
94+ }
95+
6196func (c * CopilotProvider ) getGitHubToken () string {
6297 if c .apiKey != "" {
6398 return c .apiKey
@@ -88,7 +123,19 @@ func (c *CopilotProvider) GenerateCommitMessages(ctx context.Context, diff strin
88123 return nil , fmt .Errorf ("GitHub token is required for Copilot provider" )
89124 }
90125
91- bearer := githubToken
126+ var bearer string
127+ var err error
128+
129+ // On Windows, use the token directly; on other platforms, exchange it for a Copilot token
130+ if runtime .GOOS == "windows" {
131+ bearer = githubToken
132+ } else {
133+ bearer , err = c .exchangeGitHubToken (ctx , githubToken )
134+ if err != nil {
135+ return nil , err
136+ }
137+ }
138+
92139
93140 client := openai .NewClient (
94141 option .WithBaseURL (c .endpoint ),
0 commit comments