branch: elpa/gptel
commit 0975d9c84aa41eb3096236e92b333a653df49b0d
Author: Khinshan Khan <[email protected]>
Commit: GitHub <[email protected]>
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'.
---
NEWS | 5 +++++
README.org | 14 ++++++++++----
gptel-gh.el | 40 ++++++++++++++++++++++++----------------
3 files changed, 39 insertions(+), 20 deletions(-)
diff --git a/NEWS b/NEWS
index 464244e479b..bde6d53f6d1 100644
--- a/NEWS
+++ b/NEWS
@@ -34,6 +34,11 @@
** New features and UI changes
+- New command ~gptel-gh-login~ to authenticate with GitHub Copilot. The
+ authentication step happens automatically when you use gptel, so
+ invoking it manually is not required. But you can use this command to
+ change accounts or refresh your login if required.
+
- gptel now supports handling reasoning/thinking blocks in responses
from xAI's Grok models. This is controlled by
~gptel-include-reasoning~, in the same way that it handles other
diff --git a/README.org b/README.org
index 7c47ec4da28..7430d343e63 100644
--- a/README.org
+++ b/README.org
@@ -35,7 +35,7 @@ gptel is a simple Large Language Model chat client for Emacs,
with support for m
| Github Models | ✓ |
[[https://github.com/settings/tokens][Token]] |
| Novita AI | ✓ |
[[https://novita.ai/model-api/product/llm-api?utm_source=github_gptel&utm_medium=github_readme&utm_campaign=link][Token]]
|
| xAI | ✓ |
[[https://console.x.ai?utm_source=github_gptel&utm_medium=github_readme&utm_campaign=link][API
key]] |
-| Github CopilotChat | ✓ | Github account |
+| GitHub CopilotChat | ✓ | GitHub account |
| Bedrock | ✓ | AWS credentials |
| Moonshot (Kimi) | ✓ | API key
([[https://platform.moonshot.cn/console][CN]] or
[[https://platform.moonshot.ai/console][Global]]) |
#+html: </div>
@@ -123,7 +123,7 @@ gptel uses Curl if available, but falls back to the
built-in url-retrieve to wor
- [[#novita-ai][Novita AI]]
- [[#xai][xAI]]
- [[#aiml-api][AI/ML API]]
- - [[#github-copilotchat][Github CopilotChat]]
+ - [[#github-copilotchat][GitHub CopilotChat]]
- [[#aws-bedrock][AWS Bedrock]]
- [[#moonshot-kimi][Moonshot (Kimi)]]
- [[#usage][Usage]]
@@ -1020,7 +1020,7 @@ The above code makes the backend available to select. If
you want it to be the
#+html: </details>
#+html: <details><summary>
-**** Github CopilotChat
+**** GitHub CopilotChat
#+html: </summary>
Register a backend with
@@ -1028,7 +1028,7 @@ Register a backend with
(gptel-make-gh-copilot "Copilot")
#+end_src
-You will be informed to login into =Github= as required.
+You will be informed to login into =GitHub= as required.
You can pick this backend from the menu when using gptel (see
[[#usage][Usage]]).
***** (Optional) Set as the default gptel backend
@@ -1171,6 +1171,12 @@ gptel provides a few powerful, general purpose and
flexible commands. You can d
| =gptel-org-set-properties= | Write gptel configuration as Org properties,
for per-heading chat configuration. |
|----------------------------+-----------------------------------------------------------------------------------------|
+|------------------+-------------------------------------------------------------------------------------------|
+| *GitHub Copilot* |
|
+|------------------+-------------------------------------------------------------------------------------------|
+| =gptel-gh-login= | Authenticate with GitHub Copilot. (Automatically handled,
but can be forced if required.) |
+|------------------+-------------------------------------------------------------------------------------------|
+
*** In any buffer:
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.
diff --git a/gptel-gh.el b/gptel-gh.el
index 5caef32a742..927be571abb 100644
--- a/gptel-gh.el
+++ b/gptel-gh.el
@@ -207,15 +207,18 @@
(write-region (prin1-to-string obj) nil file nil :silent)
obj))
-(defun gptel--gh-login()
- "Manage github login."
+(defun gptel-gh-login ()
+ "Login to GitHub Copilot API.
+
+This will prompt you to authorize in a browser and store the token."
+ (interactive)
(pcase-let (((map :device_code :user_code :verification_uri)
(gptel--url-retrieve
- "https://github.com/login/device/code"
- :method 'post
- :headers gptel--gh-auth-common-headers
- :data `( :client_id ,gptel--gh-client-id
- :scope "read:user"))))
+ "https://github.com/login/device/code"
+ :method 'post
+ :headers gptel--gh-auth-common-headers
+ :data `( :client_id ,gptel--gh-client-id
+ :scope "read:user"))))
(gui-set-selection 'CLIPBOARD user_code)
(read-from-minibuffer
(format "Your one-time code %s is copied. \
@@ -227,15 +230,20 @@ If your browser does not open automatically, browse to
%s."
(thread-last
(plist-get
(gptel--url-retrieve
- "https://github.com/login/oauth/access_token"
- :method 'post
- :headers gptel--gh-auth-common-headers
- :data `( :client_id ,gptel--gh-client-id
- :device_code ,device_code
- :grant_type "urn:ietf:params:oauth:grant-type:device_code"))
+ "https://github.com/login/oauth/access_token"
+ :method 'post
+ :headers gptel--gh-auth-common-headers
+ :data `( :client_id ,gptel--gh-client-id
+ :device_code ,device_code
+ :grant_type "urn:ietf:params:oauth:grant-type:device_code"))
:access_token)
(gptel--gh-save gptel-gh-github-token-file)
- (setf (gptel--gh-github-token gptel-backend)))))
+ (setf (gptel--gh-github-token gptel-backend))))
+ (if (and (gptel--gh-github-token gptel-backend)
+ (not (string-empty-p
+ (gptel--gh-github-token gptel-backend))))
+ (message "Successfully logged in to GitHub Copilot")
+ (user-error "Error: You might not have access to GitHub Copilot Chat!")))
(defun gptel--gh-renew-token ()
"Renew session token."
@@ -249,7 +257,7 @@ If your browser does not open automatically, browse to %s."
(if (not (plist-get token :token))
(progn
(setf (gptel--gh-github-token gptel-backend) nil)
- (user-error "Error: You might not have access to Github Copilot
Chat!"))
+ (user-error "Error: You might not have access to GitHub Copilot
Chat!"))
(thread-last
(gptel--gh-save gptel-gh-token-file token)
(setf (gptel--gh-token gptel-backend))))))
@@ -263,7 +271,7 @@ Then we need a session token."
(let ((token (gptel--gh-restore gptel-gh-github-token-file)))
(if token
(setf (gptel--gh-github-token gptel-backend) token)
- (gptel--gh-login))))
+ (gptel-gh-login))))
(when (null (gptel--gh-token gptel-backend))
;; try to load token from `gptel-gh-token-file'