diff --git a/containers/api-proxy/server.js b/containers/api-proxy/server.js index 081b4ddd..317f125e 100644 --- a/containers/api-proxy/server.js +++ b/containers/api-proxy/server.js @@ -888,6 +888,31 @@ if (require.main === module) { const contentLength = parseInt(req.headers['content-length'], 10) || 0; if (checkRateLimit(req, res, 'copilot', contentLength)) return; + // Copilot CLI 1.0.21+ calls GET /models at startup (to list or validate models). + // The /models endpoint lives on the Copilot inference API (COPILOT_API_TARGET), + // NOT on the GitHub REST API. Explicitly use COPILOT_GITHUB_TOKEN for this + // request so the GitHub OAuth token is used even when both COPILOT_GITHUB_TOKEN + // and COPILOT_API_KEY are configured (COPILOT_API_KEY alone is not accepted by + // the /models endpoint). + let reqPathname; + try { + reqPathname = new URL(req.url, 'http://localhost').pathname; + } catch { + logRequest('warn', 'copilot_proxy_malformed_url', { + message: 'Malformed request URL in Copilot proxy — rejecting with 400', + }); + res.writeHead(400, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: 'Invalid request URL' })); + return; + } + const isModelsPath = reqPathname === '/models' || reqPathname.startsWith('/models/'); + if (isModelsPath && req.method === 'GET' && COPILOT_GITHUB_TOKEN) { + proxyRequest(req, res, COPILOT_API_TARGET, { + 'Authorization': `Bearer ${COPILOT_GITHUB_TOKEN}`, + }, 'copilot'); + return; + } + proxyRequest(req, res, COPILOT_API_TARGET, { 'Authorization': `Bearer ${COPILOT_AUTH_TOKEN}`, }, 'copilot'); diff --git a/src/docker-manager.ts b/src/docker-manager.ts index 52bad2c3..00e4803c 100644 --- a/src/docker-manager.ts +++ b/src/docker-manager.ts @@ -1535,6 +1535,9 @@ export function generateDockerCompose( ...(config.geminiApiBasePath && { GEMINI_API_BASE_PATH: config.geminiApiBasePath }), // Forward GITHUB_SERVER_URL so api-proxy can auto-derive enterprise endpoints ...(process.env.GITHUB_SERVER_URL && { GITHUB_SERVER_URL: process.env.GITHUB_SERVER_URL }), + // Forward GITHUB_API_URL so api-proxy can use the correct GitHub REST API hostname + // on GHES/GHEC (e.g. https://ghes.example.com/api/v3 or api.mycompany.ghe.com) + ...(process.env.GITHUB_API_URL && { GITHUB_API_URL: process.env.GITHUB_API_URL }), // Route through Squid to respect domain whitelisting HTTP_PROXY: `http://${networkConfig.squidIp}:${SQUID_PORT}`, HTTPS_PROXY: `http://${networkConfig.squidIp}:${SQUID_PORT}`,