Skip to content

Commit 0975d9c

Browse files
authored
gptel-gh: Add GitHub Copilot interactive login (#989)
* gptel-gh.el (gptel-gh-login, gptel--gh-login, gptel--gh-renew-token): New command `gptel-gh-login', replacing noninteractive function `gptel--gh-login'. * NEWS (New features and UI changes): Mention new command `gptel-gh-login'. * README: Mention new command `gptel-gh-login'.
1 parent eb555e5 commit 0975d9c

File tree

3 files changed

+39
-20
lines changed

3 files changed

+39
-20
lines changed

NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434

3535
** New features and UI changes
3636

37+
- New command ~gptel-gh-login~ to authenticate with GitHub Copilot. The
38+
authentication step happens automatically when you use gptel, so
39+
invoking it manually is not required. But you can use this command to
40+
change accounts or refresh your login if required.
41+
3742
- gptel now supports handling reasoning/thinking blocks in responses
3843
from xAI's Grok models. This is controlled by
3944
~gptel-include-reasoning~, in the same way that it handles other

README.org

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ gptel is a simple Large Language Model chat client for Emacs, with support for m
3535
| Github Models | ✓ | [[https://github.com/settings/tokens][Token]] |
3636
| Novita AI | ✓ | [[https://novita.ai/model-api/product/llm-api?utm_source=github_gptel&utm_medium=github_readme&utm_campaign=link][Token]] |
3737
| xAI | ✓ | [[https://console.x.ai?utm_source=github_gptel&utm_medium=github_readme&utm_campaign=link][API key]] |
38-
| Github CopilotChat | ✓ | Github account |
38+
| GitHub CopilotChat | ✓ | GitHub account |
3939
| Bedrock | ✓ | AWS credentials |
4040
| Moonshot (Kimi) | ✓ | API key ([[https://platform.moonshot.cn/console][CN]] or [[https://platform.moonshot.ai/console][Global]]) |
4141
#+html: </div>
@@ -123,7 +123,7 @@ gptel uses Curl if available, but falls back to the built-in url-retrieve to wor
123123
- [[#novita-ai][Novita AI]]
124124
- [[#xai][xAI]]
125125
- [[#aiml-api][AI/ML API]]
126-
- [[#github-copilotchat][Github CopilotChat]]
126+
- [[#github-copilotchat][GitHub CopilotChat]]
127127
- [[#aws-bedrock][AWS Bedrock]]
128128
- [[#moonshot-kimi][Moonshot (Kimi)]]
129129
- [[#usage][Usage]]
@@ -1020,15 +1020,15 @@ The above code makes the backend available to select. If you want it to be the
10201020

10211021
#+html: </details>
10221022
#+html: <details><summary>
1023-
**** Github CopilotChat
1023+
**** GitHub CopilotChat
10241024
#+html: </summary>
10251025

10261026
Register a backend with
10271027
#+begin_src emacs-lisp
10281028
(gptel-make-gh-copilot "Copilot")
10291029
#+end_src
10301030

1031-
You will be informed to login into =Github= as required.
1031+
You will be informed to login into =GitHub= as required.
10321032
You can pick this backend from the menu when using gptel (see [[#usage][Usage]]).
10331033

10341034
***** (Optional) Set as the default gptel backend
@@ -1171,6 +1171,12 @@ gptel provides a few powerful, general purpose and flexible commands. You can d
11711171
| =gptel-org-set-properties= | Write gptel configuration as Org properties, for per-heading chat configuration. |
11721172
|----------------------------+-----------------------------------------------------------------------------------------|
11731173

1174+
|------------------+-------------------------------------------------------------------------------------------|
1175+
| *GitHub Copilot* | |
1176+
|------------------+-------------------------------------------------------------------------------------------|
1177+
| =gptel-gh-login= | Authenticate with GitHub Copilot. (Automatically handled, but can be forced if required.) |
1178+
|------------------+-------------------------------------------------------------------------------------------|
1179+
11741180
*** In any buffer:
11751181

11761182
1. Call =M-x gptel-send= to send the text up to the cursor. The response will be inserted below. Continue the conversation by typing below the response.

gptel-gh.el

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,18 @@
207207
(write-region (prin1-to-string obj) nil file nil :silent)
208208
obj))
209209

210-
(defun gptel--gh-login()
211-
"Manage github login."
210+
(defun gptel-gh-login ()
211+
"Login to GitHub Copilot API.
212+
213+
This will prompt you to authorize in a browser and store the token."
214+
(interactive)
212215
(pcase-let (((map :device_code :user_code :verification_uri)
213216
(gptel--url-retrieve
214-
"https://github.com/login/device/code"
215-
:method 'post
216-
:headers gptel--gh-auth-common-headers
217-
:data `( :client_id ,gptel--gh-client-id
218-
:scope "read:user"))))
217+
"https://github.com/login/device/code"
218+
:method 'post
219+
:headers gptel--gh-auth-common-headers
220+
:data `( :client_id ,gptel--gh-client-id
221+
:scope "read:user"))))
219222
(gui-set-selection 'CLIPBOARD user_code)
220223
(read-from-minibuffer
221224
(format "Your one-time code %s is copied. \
@@ -227,15 +230,20 @@ If your browser does not open automatically, browse to %s."
227230
(thread-last
228231
(plist-get
229232
(gptel--url-retrieve
230-
"https://github.com/login/oauth/access_token"
231-
:method 'post
232-
:headers gptel--gh-auth-common-headers
233-
:data `( :client_id ,gptel--gh-client-id
234-
:device_code ,device_code
235-
:grant_type "urn:ietf:params:oauth:grant-type:device_code"))
233+
"https://github.com/login/oauth/access_token"
234+
:method 'post
235+
:headers gptel--gh-auth-common-headers
236+
:data `( :client_id ,gptel--gh-client-id
237+
:device_code ,device_code
238+
:grant_type "urn:ietf:params:oauth:grant-type:device_code"))
236239
:access_token)
237240
(gptel--gh-save gptel-gh-github-token-file)
238-
(setf (gptel--gh-github-token gptel-backend)))))
241+
(setf (gptel--gh-github-token gptel-backend))))
242+
(if (and (gptel--gh-github-token gptel-backend)
243+
(not (string-empty-p
244+
(gptel--gh-github-token gptel-backend))))
245+
(message "Successfully logged in to GitHub Copilot")
246+
(user-error "Error: You might not have access to GitHub Copilot Chat!")))
239247

240248
(defun gptel--gh-renew-token ()
241249
"Renew session token."
@@ -249,7 +257,7 @@ If your browser does not open automatically, browse to %s."
249257
(if (not (plist-get token :token))
250258
(progn
251259
(setf (gptel--gh-github-token gptel-backend) nil)
252-
(user-error "Error: You might not have access to Github Copilot Chat!"))
260+
(user-error "Error: You might not have access to GitHub Copilot Chat!"))
253261
(thread-last
254262
(gptel--gh-save gptel-gh-token-file token)
255263
(setf (gptel--gh-token gptel-backend))))))
@@ -263,7 +271,7 @@ Then we need a session token."
263271
(let ((token (gptel--gh-restore gptel-gh-github-token-file)))
264272
(if token
265273
(setf (gptel--gh-github-token gptel-backend) token)
266-
(gptel--gh-login))))
274+
(gptel-gh-login))))
267275

268276
(when (null (gptel--gh-token gptel-backend))
269277
;; try to load token from `gptel-gh-token-file'

0 commit comments

Comments
 (0)