|
9 | 9 | [eca.shared :refer [multi-str]] |
10 | 10 | [hato.client :as http])) |
11 | 11 |
|
12 | | -(def ^:private client-id "Iv1.b507a08c87ecfe98") |
| 12 | +(set! *warn-on-reflection* true) |
| 13 | + |
| 14 | +(def ^:private default-client-id "Iv1.b507a08c87ecfe98") |
| 15 | + |
| 16 | +(defn ^:private github-base-url [provider-settings] |
| 17 | + (or (get-in provider-settings [:auth :url]) |
| 18 | + "https://github.com")) |
| 19 | + |
| 20 | +(defn ^:private github-api-base-url [provider-settings] |
| 21 | + (let [base (github-base-url provider-settings)] |
| 22 | + (if (= base "https://github.com") |
| 23 | + "https://api.github.com" |
| 24 | + (str base "/api/v3")))) |
| 25 | + |
| 26 | +(defn ^:private copilot-client-id [provider-settings] |
| 27 | + (or (get-in provider-settings [:auth :clientId]) |
| 28 | + default-client-id)) |
13 | 29 |
|
14 | 30 | (defn ^:private auth-headers [] |
15 | 31 | {"Content-Type" "application/json" |
16 | 32 | "Accept" "application/json" |
17 | 33 | "editor-plugin-version" "eca/*" |
18 | 34 | "editor-version" (str "eca/" (config/eca-version))}) |
19 | 35 |
|
20 | | -(def ^:private oauth-login-device-url |
21 | | - "https://github.com/login/device/code") |
22 | | - |
23 | | -(defn ^:private oauth-url [] |
24 | | - (let [{:keys [body]} (http/post |
25 | | - oauth-login-device-url |
| 36 | +(defn ^:private oauth-url [provider-settings] |
| 37 | + (let [device-url (str (github-base-url provider-settings) "/login/device/code") |
| 38 | + {:keys [body]} (http/post |
| 39 | + device-url |
26 | 40 | {:headers (auth-headers) |
27 | | - :body (json/generate-string {:client_id client-id |
| 41 | + :body (json/generate-string {:client_id (copilot-client-id provider-settings) |
28 | 42 | :scope "read:user"}) |
29 | 43 | :http-client (client/merge-with-global-http-client {}) |
30 | 44 | :as :json})] |
31 | 45 | {:user-code (:user_code body) |
32 | 46 | :device-code (:device_code body) |
33 | 47 | :url (:verification_uri body)})) |
34 | 48 |
|
35 | | -(def ^:private oauth-login-access-token-url |
36 | | - "https://github.com/login/oauth/access_token") |
37 | | - |
38 | | -(defn ^:private oauth-access-token [device-code] |
39 | | - (let [{:keys [status body]} (http/post |
40 | | - oauth-login-access-token-url |
| 49 | +(defn ^:private oauth-access-token [provider-settings device-code] |
| 50 | + (let [access-token-url (str (github-base-url provider-settings) "/login/oauth/access_token") |
| 51 | + {:keys [status body]} (http/post |
| 52 | + access-token-url |
41 | 53 | {:headers (auth-headers) |
42 | | - :body (json/generate-string {:client_id client-id |
| 54 | + :body (json/generate-string {:client_id (copilot-client-id provider-settings) |
43 | 55 | :device_code device-code |
44 | 56 | :grant_type "urn:ietf:params:oauth:grant-type:device_code"}) |
45 | 57 | :throw-exceptions? false |
|
51 | 63 | {:status status |
52 | 64 | :body body}))))) |
53 | 65 |
|
54 | | -(def ^:private oauth-copilot-token-url |
55 | | - "https://api.github.com/copilot_internal/v2/token") |
56 | | - |
57 | | -(defn ^:private oauth-renew-token [access-token] |
58 | | - (let [{:keys [status body]} (http/get |
59 | | - oauth-copilot-token-url |
| 66 | +(defn ^:private oauth-renew-token [provider-settings access-token] |
| 67 | + (let [token-url (str (github-api-base-url provider-settings) "/copilot_internal/v2/token") |
| 68 | + {:keys [status body]} (http/get |
| 69 | + token-url |
60 | 70 | {:headers (merge (auth-headers) |
61 | 71 | {"authorization" (str "token " access-token)}) |
62 | 72 | :throw-exceptions? false |
|
71 | 81 |
|
72 | 82 | ;; --- Settings-based login (providers/login flow) --- |
73 | 83 |
|
74 | | -(defmethod f.providers/start-login! ["github-copilot" "device"] [_ _ db* _config messenger metrics] |
75 | | - (let [{:keys [user-code device-code url]} (oauth-url)] |
| 84 | +(defmethod f.providers/start-login! ["github-copilot" "device"] [_ _ db* config messenger metrics] |
| 85 | + (let [provider-settings (get-in config [:providers "github-copilot"]) |
| 86 | + {:keys [user-code device-code url]} (oauth-url provider-settings)] |
76 | 87 | (swap! db* assoc-in [:auth "github-copilot"] {:step :login/waiting-user-confirmation |
77 | 88 | :device-code device-code}) |
78 | 89 | (future |
|
82 | 93 | (= :login/waiting-user-confirmation |
83 | 94 | (get-in @db* [:auth "github-copilot" :step]))) |
84 | 95 | (let [result (try |
85 | | - (let [access-token (oauth-access-token device-code) |
86 | | - {:keys [api-key expires-at]} (oauth-renew-token access-token)] |
| 96 | + (let [access-token (oauth-access-token provider-settings device-code) |
| 97 | + {:keys [api-key expires-at]} (oauth-renew-token provider-settings access-token)] |
87 | 98 | (swap! db* update-in [:auth "github-copilot"] merge |
88 | 99 | {:step :login/done |
89 | 100 | :access-token access-token |
|
99 | 110 | {:action "device-code" |
100 | 111 | :url url |
101 | 112 | :code user-code |
102 | | - :message "Enter this code at the URL above. Make sure Copilot is enabled at https://github.com/settings/copilot/features"})) |
| 113 | + :message (format "Enter this code at the URL above. Make sure Copilot is enabled at %s/settings/copilot/features" |
| 114 | + (github-base-url provider-settings))})) |
103 | 115 |
|
104 | 116 | ;; --- Chat-based login (legacy /login command) --- |
105 | 117 |
|
106 | | -(defmethod f.login/login-step ["github-copilot" :login/start] [{:keys [db* chat-id provider send-msg!]}] |
107 | | - (let [{:keys [user-code device-code url]} (oauth-url)] |
| 118 | +(defmethod f.login/login-step ["github-copilot" :login/start] [{:keys [db* chat-id provider config send-msg!]}] |
| 119 | + (let [provider-settings (get-in config [:providers provider]) |
| 120 | + {:keys [user-code device-code url]} (oauth-url provider-settings) |
| 121 | + github-url (github-base-url provider-settings)] |
108 | 122 | (swap! db* assoc-in [:chats chat-id :login-provider] provider) |
109 | 123 | (swap! db* assoc-in [:auth provider] {:step :login/waiting-user-confirmation |
110 | 124 | :device-code device-code}) |
111 | 125 | (send-msg! (multi-str |
112 | | - "First, make sure you have Copilot enabled in you Github account: https://github.com/settings/copilot/features" |
| 126 | + (format "First, make sure you have Copilot enabled in your Github account: %s/settings/copilot/features" github-url) |
113 | 127 | (format "Then, open your browser at:\n\n%s\n\nAuthenticate using the code: `%s`\nThen type anything in the chat and send it to continue the authentication." |
114 | 128 | url |
115 | 129 | user-code))))) |
116 | 130 |
|
117 | | -(defmethod f.login/login-step ["github-copilot" :login/waiting-user-confirmation] [{:keys [db* provider send-msg!] :as ctx}] |
118 | | - (let [access-token (oauth-access-token (get-in @db* [:auth provider :device-code])) |
119 | | - {:keys [api-key expires-at]} (oauth-renew-token access-token)] |
| 131 | +(defmethod f.login/login-step ["github-copilot" :login/waiting-user-confirmation] [{:keys [db* provider config send-msg!] :as ctx}] |
| 132 | + (let [provider-settings (get-in config [:providers provider]) |
| 133 | + access-token (oauth-access-token provider-settings (get-in @db* [:auth provider :device-code])) |
| 134 | + {:keys [api-key expires-at]} (oauth-renew-token provider-settings access-token)] |
120 | 135 | (swap! db* update-in [:auth provider] merge {:step :login/done |
121 | 136 | :access-token access-token |
122 | 137 | :api-key api-key |
123 | 138 | :expires-at expires-at}) |
124 | | - |
125 | 139 | (f.login/login-done! ctx) |
126 | | - (send-msg! "\nMake sure to enable the model you want use at: https://github.com/settings/copilot/features"))) |
| 140 | + (send-msg! (format "\nMake sure to enable the model you want to use at: %s/settings/copilot/features" |
| 141 | + (github-base-url provider-settings))))) |
127 | 142 |
|
128 | | -(defmethod f.login/login-step ["github-copilot" :login/renew-token] [{:keys [db* provider] :as ctx}] |
129 | | - (let [access-token (get-in @db* [:auth provider :access-token]) |
130 | | - {:keys [api-key expires-at]} (oauth-renew-token access-token)] |
| 143 | +(defmethod f.login/login-step ["github-copilot" :login/renew-token] [{:keys [db* provider config] :as ctx}] |
| 144 | + (let [provider-settings (get-in config [:providers provider]) |
| 145 | + access-token (get-in @db* [:auth provider :access-token]) |
| 146 | + {:keys [api-key expires-at]} (oauth-renew-token provider-settings access-token)] |
131 | 147 | (swap! db* update-in [:auth provider] merge {:api-key api-key |
132 | 148 | :expires-at expires-at}) |
133 | 149 | (f.login/login-done! ctx :silent? true :skip-models-sync? true))) |
0 commit comments