feat(copilot): add GitHub Enterprise Server support (#2175)

* feat(copilot): add GitHub Enterprise Server support

* fix(copilot): address GHES PR review findings (P1 + 2×P2)

- P1: Use composite account ID (domain:user_id) for GHES to prevent
  cross-instance ID collisions; github.com keeps plain numeric ID for
  backward compatibilit
- P2-a: Use get_api_endpoint() for model list URL with automatic
  fallback to static URL when dynamic endpoint resolution fails
- P2-b: Add normalize_github_domain() as backend SSOT for domain
  normalization (lowercase, strip protocol/path/query, reject userinfo)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
hotelbe
2026-04-19 20:29:46 +08:00
committed by GitHub
parent 9871d3d1eb
commit 87635e7fc6
12 changed files with 441 additions and 68 deletions
@@ -1,8 +1,8 @@
import type { GitHubAccount } from "@/lib/api";
import { useManagedAuth } from "./useManagedAuth";
export function useCopilotAuth() {
const managedAuth = useManagedAuth("github_copilot");
export function useCopilotAuth(githubDomain?: string) {
const managedAuth = useManagedAuth("github_copilot", githubDomain);
const defaultAccount =
managedAuth.accounts.find(
(account) => account.id === managedAuth.defaultAccountId,
@@ -10,7 +10,10 @@ import type {
type PollingState = "idle" | "polling" | "success" | "error";
export function useManagedAuth(authProvider: ManagedAuthProvider) {
export function useManagedAuth(
authProvider: ManagedAuthProvider,
githubDomain?: string,
) {
const queryClient = useQueryClient();
const queryKey = ["managed-auth-status", authProvider];
@@ -52,7 +55,7 @@ export function useManagedAuth(authProvider: ManagedAuthProvider) {
}, [stopPolling]);
const startLoginMutation = useMutation({
mutationFn: () => authApi.authStartLogin(authProvider),
mutationFn: () => authApi.authStartLogin(authProvider, githubDomain),
onSuccess: async (response) => {
setDeviceCode(response);
setPollingState("polling");
@@ -87,6 +90,7 @@ export function useManagedAuth(authProvider: ManagedAuthProvider) {
const newAccount = await authApi.authPollForAccount(
authProvider,
response.device_code,
githubDomain,
);
if (newAccount) {
stopPolling();