branch: elpa/gptel
commit a77927a08df0f3fdf725d3832d5bc56aa3ea5e07
Author: Jason TIAN <[email protected]>
Commit: Karthik Chikmagalur <[email protected]>

    gptel-gh: Refactor login for Emacs over SSH
    
    * gptel-gh.el (gptel-gh-login):
    When using Emacs over SSH, remove automatic browser opening via
    browse-url and instead instruct users to manually visit
    https://github.com/login/device.  browse-url would open this on
    the remote machine.
    
    Detect SSH sessions via SSH_CLIENT/SSH_CONNECTION/SSH_TTY
    environment variables.
    
    Fix Backend resolution to work when gptel-backend is not a GitHub
    Copilot backend, preventing "Wrong type argument" errors.
---
 gptel-gh.el | 94 +++++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 63 insertions(+), 31 deletions(-)

diff --git a/gptel-gh.el b/gptel-gh.el
index 392cd0ca45d..7b974c4d68c 100644
--- a/gptel-gh.el
+++ b/gptel-gh.el
@@ -243,40 +243,72 @@
 (defun gptel-gh-login ()
   "Login to GitHub Copilot API.
 
-This will prompt you to authorize in a browser and store the token."
+This will prompt you to authorize in a browser and store the token.
+
+In SSH sessions, the URL and code will be displayed for manual entry
+instead of attempting to open a browser automatically."
   (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"))))
-    (gui-set-selection 'CLIPBOARD user_code)
-    (read-from-minibuffer
-     (format "Your one-time code %s is copied. \
+  ;; Determine which GitHub backend to use
+  (let ((gh-backend
+         (cond
+          ;; If current backend is GitHub, use it
+          ((and (boundp 'gptel-backend)
+                gptel-backend
+                (gptel--gh-p gptel-backend))
+           gptel-backend)
+          ;; Otherwise, find any GitHub backend
+          ((cl-find-if (lambda (b) (gptel--gh-p b))
+                       (mapcar #'cdr gptel--known-backends)))
+          ;; No GitHub backend found
+          (t (user-error "No GitHub Copilot backend found.  \
+Please set one up with `gptel-make-gh-copilot' first"))))
+        ;; Detect SSH sessions
+        (in-ssh-session (or (getenv "SSH_CLIENT")
+                            (getenv "SSH_CONNECTION")
+                            (getenv "SSH_TTY"))))
+    (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"))))
+      (gui-set-selection 'CLIPBOARD user_code)
+      (if in-ssh-session
+          ;; SSH session: display URL and code, don't auto-open browser
+          (progn
+            (message "GitHub Device Code: %s (copied to clipboard)" user_code)
+            (read-from-minibuffer
+             (format "Code %s is copied. Visit https://github.com/login/device 
\
+in your local browser, enter the code, and authorize.  Press ENTER after 
authorizing. "
+                     user_code)))
+        ;; Local session: auto-open browser
+        (read-from-minibuffer
+         (format "Your one-time code %s is copied. \
 Press ENTER to open GitHub in your browser. \
 If your browser does not open automatically, browse to %s."
-             user_code verification_uri))
-    (browse-url verification_uri)
-    (read-from-minibuffer "Press ENTER after authorizing.")
-    (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"))
-       :access_token)
-      (gptel--gh-save gptel-gh-github-token-file)
-      (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!")))
+                 user_code verification_uri))
+        (browse-url verification_uri)
+        (read-from-minibuffer "Press ENTER after authorizing. "))
+      ;; Use gh-backend for token storage
+      (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"))
+         :access_token)
+        (gptel--gh-save gptel-gh-github-token-file)
+        (setf (gptel--gh-github-token gh-backend))))
+    ;; Check gh-backend for success
+    (if (and (gptel--gh-github-token gh-backend)
+             (not (string-empty-p
+                   (gptel--gh-github-token gh-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."

Reply via email to