Skip to content

Commit bbdcfbb

Browse files
ericdalloeca-agent
andcommitted
Use dynamic API endpoint from Copilot token response
The copilot_internal/v2/token endpoint returns an `endpoints.api` field with the actual API URL the token is scoped to. For GHE instances this differs from the default api.githubcopilot.com, causing 401 "Bad credentials" errors on chat requests. Extract `endpoints.api` from the token response and store it in the auth state. The Copilot chat request path now prefers this dynamic URL over the static config default. Relates to #402 🤖 Generated with [eca](https://eca.dev) Co-Authored-By: eca <git@eca.dev>
1 parent 8cac6d6 commit bbdcfbb

File tree

4 files changed

+21
-20
lines changed

4 files changed

+21
-20
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44

55
- Fix github-copilot retry loops in chats.
6+
- Fix Github Enterprise to use the proper url during prompts. #402
67

78
## 0.124.3
89

src/eca/llm_api.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@
242242
callbacks)
243243

244244
(= "github-copilot" provider)
245-
(let [copilot-headers (fn [user-initiator?]
245+
(let [api-url (or (:api-url provider-auth) api-url)
246+
copilot-headers (fn [user-initiator?]
246247
(merge {"openai-intent" "conversation-panel"
247248
"x-request-id" (str (random-uuid))
248249
"x-initiator" (if user-initiator? "user" "agent")

src/eca/llm_providers/copilot.clj

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,9 @@
7373
:http-client (client/merge-with-global-http-client {})
7474
:as :json})]
7575
(if-let [token (:token body)]
76-
{:api-key token
77-
:expires-at (:expires_at body)}
76+
(cond-> {:api-key token
77+
:expires-at (:expires_at body)}
78+
(get-in body [:endpoints :api]) (assoc :api-url (get-in body [:endpoints :api])))
7879
(throw (ex-info (format "Error on copilot login: %s" body)
7980
{:status status
8081
:body body})))))
@@ -94,12 +95,11 @@
9495
(get-in @db* [:auth "github-copilot" :step])))
9596
(let [result (try
9697
(let [access-token (oauth-access-token provider-settings device-code)
97-
{:keys [api-key expires-at]} (oauth-renew-token provider-settings access-token)]
98+
token-data (oauth-renew-token provider-settings access-token)]
9899
(swap! db* update-in [:auth "github-copilot"] merge
99-
{:step :login/done
100-
:access-token access-token
101-
:api-key api-key
102-
:expires-at expires-at})
100+
(assoc token-data
101+
:step :login/done
102+
:access-token access-token))
103103
(f.providers/sync-and-notify! "github-copilot" db* messenger metrics)
104104
:done)
105105
(catch Exception e
@@ -131,19 +131,16 @@
131131
(defmethod f.login/login-step ["github-copilot" :login/waiting-user-confirmation] [{:keys [db* provider config send-msg!] :as ctx}]
132132
(let [provider-settings (get-in config [:providers provider])
133133
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)]
135-
(swap! db* update-in [:auth provider] merge {:step :login/done
136-
:access-token access-token
137-
:api-key api-key
138-
:expires-at expires-at})
134+
token-data (oauth-renew-token provider-settings access-token)]
135+
(swap! db* update-in [:auth provider] merge
136+
(assoc token-data :step :login/done :access-token access-token))
139137
(f.login/login-done! ctx)
140138
(send-msg! (format "\nMake sure to enable the model you want to use at: %s/settings/copilot/features"
141139
(github-base-url provider-settings)))))
142140

143141
(defmethod f.login/login-step ["github-copilot" :login/renew-token] [{:keys [db* provider config] :as ctx}]
144142
(let [provider-settings (get-in config [:providers provider])
145143
access-token (get-in @db* [:auth provider :access-token])
146-
{:keys [api-key expires-at]} (oauth-renew-token provider-settings access-token)]
147-
(swap! db* update-in [:auth provider] merge {:api-key api-key
148-
:expires-at expires-at})
144+
token-data (oauth-renew-token provider-settings access-token)]
145+
(swap! db* update-in [:auth provider] merge token-data)
149146
(f.login/login-done! ctx :silent? true :skip-models-sync? true)))

test/eca/llm_providers/copilot_test.clj

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@
9393
(reset! req* req)
9494
{:status 200
9595
:body {:token "copilot-api-key"
96-
:expires_at 9999999999}})
96+
:expires_at 9999999999
97+
:endpoints {:api "https://copilot-proxy.ghe.example.com"}}})
9798

9899
(let [access-token "gh-access-123"
99100
result (#'llm-providers.copilot/oauth-renew-token test-provider-settings access-token)]
@@ -110,7 +111,8 @@
110111
(select-keys (:headers @req*) ["authorization" "Content-Type" "Accept" "editor-plugin-version"]))
111112
(str "Headers should include auth headers and access-token: " (:headers @req*)))
112113

113-
;; response parsing
114-
(is (= {:api-key "copilot-api-key"
115-
:expires-at 9999999999}
114+
;; response parsing — includes api-url from endpoints.api
115+
(is (= {:api-key "copilot-api-key"
116+
:expires-at 9999999999
117+
:api-url "https://copilot-proxy.ghe.example.com"}
116118
result)))))))

0 commit comments

Comments
 (0)