180180(cl-defstruct (gptel--gh (:include gptel-openai)
181181 (:copier nil )
182182 (:constructor gptel--make-gh))
183- token github-token sessionid machineid)
183+ sessionid machineid)
184184
185185(defcustom gptel-gh-github-token-file (expand-file-name " .cache/copilot-chat/github-token"
186186 user-emacs-directory)
187187 " File where the GitHub token is stored."
188188 :type 'string
189189 :group 'gptel )
190190
191- (defcustom gptel-gh-token-file ( expand-file-name " .cache/copilot-chat/token "
192- user-emacs-directory )
193- " File where the chat token is cached. "
194- :type 'string
195- :group 'gptel )
191+ (defvar gptel-gh-github- token-load 'gptel--gh-restore-from-file
192+ " Function to load the current github token. " )
193+
194+ ( defvar gptel-gh-github-token-save 'gptel--gh-save-to-file
195+ " Function to save the new github token. " )
196196
197197(defconst gptel--gh-auth-common-headers
198198 `((" editor-plugin-version" . " gptel/*" )
199199 (" editor-version" . ,(concat " emacs/" emacs-version))))
200200
201201(defconst gptel--gh-client-id " Iv1.b507a08c87ecfe98" )
202202
203+ (defvar gptel--gh-token nil " Variable that holds the chat token in memory" )
204+
203205; ; https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
204206(defun gptel--gh-uuid ()
205207 " Generate a UUID v4-1."
219221 (setq hex (nconc hex (list (aref hex-chars (random 16 ))))))
220222 (apply #'string hex)))
221223
222- (defun gptel--gh-restore ( file )
223- " Restore saved object from FILE ."
224- (when (file-exists-p file)
224+ (defun gptel--gh-restore-from-file ( )
225+ " Restore saved object from gptel-gh-github-token-file ."
226+ (when (file-exists-p gptel-gh-github-token- file)
225227 ; ; We set the coding system to `utf-8-auto-dos' when reading so that
226228 ; ; files with CR EOL can still be read properly
227229 (let ((coding-system-for-read 'utf-8-auto-dos ))
228230 (with-temp-buffer
229231 (set-buffer-multibyte nil )
230- (insert-file-contents-literally file)
232+ (insert-file-contents-literally gptel-gh-github-token- file)
231233 (goto-char (point-min ))
232234 (read (current-buffer ))))))
233235
234- (defun gptel--gh-save ( file obj )
235- " Save OBJ to FILE ."
236+ (defun gptel--gh-save-to- file ( obj )
237+ " Save OBJ to gptel--gh-save-to-file ."
236238 (let ((print-length nil )
237239 (print-level nil )
238240 (coding-system-for-write 'utf-8-unix ))
239- (make-directory (file-name-directory file) t )
240- (write-region (prin1-to-string obj) nil file nil :silent )
241+ (make-directory (file-name-directory gptel-gh-github-token- file) t )
242+ (write-region (prin1-to-string obj) nil gptel-gh-github-token- file nil :silent )
241243 obj))
242244
243245(defun gptel-gh-login ()
@@ -249,20 +251,7 @@ In SSH sessions, the URL and code will be displayed for manual entry
249251instead of attempting to open a browser automatically."
250252 (interactive )
251253 ; ; Determine which GitHub backend to use
252- (let ((gh-backend
253- (cond
254- ; ; If current backend is GitHub, use it
255- ((and (boundp 'gptel-backend )
256- gptel-backend
257- (gptel--gh-p gptel-backend))
258- gptel-backend)
259- ; ; Otherwise, find any GitHub backend
260- ((cl-find-if (lambda (b ) (gptel--gh-p b))
261- (mapcar #'cdr gptel--known-backends)))
262- ; ; No GitHub backend found
263- (t (user-error " No GitHub Copilot backend found. \
264- Please set one up with `gptel-make-gh-copilot' first" ))))
265- ; ; Detect SSH sessions
254+ (let (; ; Detect SSH sessions
266255 (in-ssh-session (or (getenv " SSH_CLIENT" )
267256 (getenv " SSH_CONNECTION" )
268257 (getenv " SSH_TTY" ))))
@@ -287,28 +276,24 @@ in your local browser, enter the code, and authorize. Press ENTER after authori
287276 (format " Your one-time code %s is copied. \
288277Press ENTER to open GitHub in your browser. \
289278If your browser does not open automatically, browse to %s . "
290- user_code verification_uri))
291- (browse-url verification_uri)
292- (read-from-minibuffer " Press ENTER after authorizing. " ))
293- ; ; Use gh-backend for token storage
294- (thread-last
295- (plist-get
296- (gptel--url-retrieve
297- " https://github.com/login/oauth/access_token"
298- :method 'post
299- :headers gptel--gh-auth-common-headers
300- :data `( :client_id , gptel--gh-client-id
301- :device_code , device_code
302- :grant_type " urn:ietf:params:oauth:grant-type:device_code" ))
303- :access_token )
304- (gptel--gh-save gptel-gh-github-token-file)
305- (setf (gptel--gh-github-token gh-backend))))
306- ; ; Check gh-backend for success
307- (if (and (gptel--gh-github-token gh-backend)
308- (not (string-empty-p
309- (gptel--gh-github-token gh-backend))))
310- (message " Successfully logged in to GitHub Copilot. " )
311- (user-error " Error: You might not have access to GitHub Copilot Chat!" ))))
279+ user_code verification_uri))
280+ (browse-url verification_uri)
281+ (read-from-minibuffer " Press ENTER after authorizing." ))
282+ (thread-last
283+ (plist-get
284+ (gptel--url-retrieve
285+ " https://github.com/login/oauth/access_token"
286+ :method 'post
287+ :headers gptel--gh-auth-common-headers
288+ :data `( :client_id , gptel--gh-client-id
289+ :device_code , device_code
290+ :grant_type " urn:ietf:params:oauth:grant-type:device_code" ))
291+ :access_token )
292+ (funcall gptel-gh-github-token-save))
293+ (let ((github-token (funcall gptel-gh-github-token-load)))
294+ (if (and github-token (not (string-empty-p github-token)))
295+ (message " Successfully logged in to GitHub Copilot " )
296+ (user-error " Error: You might not have access to GitHub Copilot Chat!" ))))))
312297
313298(defun gptel--gh-renew-token ()
314299 " Renew session token."
@@ -317,34 +302,22 @@ If your browser does not open automatically, browse to %s."
317302 " https://api.github.com/copilot_internal/v2/token"
318303 :method 'get
319304 :headers `((" authorization"
320- . ,(format " token %s " (gptel-- gh-github-token gptel-backend )))
305+ . ,(format " token %s " (funcall gptel-gh-github-token-load )))
321306 ,@gptel--gh-auth-common-headers ))))
322307 (if (not (plist-get token :token ))
323- (progn
324- (setf (gptel--gh-github-token gptel-backend) nil )
325- (user-error " Error: You might not have access to GitHub Copilot Chat!" ))
326- (thread-last
327- (gptel--gh-save gptel-gh-token-file token)
328- (setf (gptel--gh-token gptel-backend))))))
308+ (user-error " Error: You might not have access to GitHub Copilot Chat!" )
309+ (setq gptel--gh-token token))))
329310
330311(defun gptel--gh-auth ()
331312 " Authenticate with GitHub Copilot API.
332313
333314We first need github authorization (github token).
334315Then we need a session token."
335- (unless (gptel--gh-github-token gptel-backend)
336- (let ((token (gptel--gh-restore gptel-gh-github-token-file)))
337- (if token
338- (setf (gptel--gh-github-token gptel-backend) token)
339- (gptel-gh-login))))
340-
341- (when (null (gptel--gh-token gptel-backend))
342- ; ; try to load token from `gptel-gh-token-file'
343- (setf (gptel--gh-token gptel-backend)
344- (gptel--gh-restore gptel-gh-token-file)))
316+ (unless (funcall gptel-gh-github-token-load)
317+ (gptel-gh-login))
345318
346319 (pcase-let (((map :token :expires_at )
347- ( gptel--gh-token gptel-backend) ))
320+ gptel--gh-token))
348321 (when (or (null token)
349322 (and expires_at
350323 (> (round (float-time )) expires_at)))
@@ -356,8 +329,7 @@ Then we need a session token."
356329 (header (lambda ()
357330 (gptel--gh-auth)
358331 `((" openai-intent" . " conversation-panel" )
359- (" authorization" . ,(concat " Bearer "
360- (plist-get (gptel--gh-token gptel-backend) :token )))
332+ (" authorization" . ,(concat " Bearer " (plist-get gptel--gh-token :token )))
361333 (" x-request-id" . ,(gptel--gh-uuid))
362334 (" vscode-sessionid" . ,(or (gptel--gh-sessionid gptel-backend) " " ))
363335 (" vscode-machineid" . ,(or (gptel--gh-machineid gptel-backend) " " ))
0 commit comments