Skip to content

Commit b508e3f

Browse files
authored
feat(proxy): make copilot api target configurable for enterprise environments (#1063)
1 parent 654da56 commit b508e3f

File tree

5 files changed

+68
-1
lines changed

5 files changed

+68
-1
lines changed

containers/api-proxy/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ Required (at least one):
3535
- `OPENAI_API_KEY` - OpenAI API key for authentication
3636
- `ANTHROPIC_API_KEY` - Anthropic API key for authentication
3737

38+
Optional:
39+
- `COPILOT_API_TARGET` - Target hostname for GitHub Copilot API requests (default: `api.githubcopilot.com`). Useful for GHES deployments.
40+
3841
Set by AWF:
3942
- `HTTP_PROXY` - Squid proxy URL (http://172.30.0.10:3128)
4043
- `HTTPS_PROXY` - Squid proxy URL (http://172.30.0.10:3128)

containers/api-proxy/server.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,37 @@ const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
4646
const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
4747
const COPILOT_GITHUB_TOKEN = process.env.COPILOT_GITHUB_TOKEN;
4848

49+
// Configurable Copilot API target host (supports GHES/GHEC / custom endpoints)
50+
// Priority: COPILOT_API_TARGET env var > auto-derive from GITHUB_SERVER_URL > default
51+
function deriveCopilotApiTarget() {
52+
if (process.env.COPILOT_API_TARGET) {
53+
return process.env.COPILOT_API_TARGET;
54+
}
55+
// For GitHub Enterprise Cloud (*.ghe.com) or GitHub Enterprise Server
56+
// (any GITHUB_SERVER_URL that isn't https://github.com), route to the
57+
// enterprise Copilot API endpoint instead of the individual one.
58+
const serverUrl = process.env.GITHUB_SERVER_URL;
59+
if (serverUrl) {
60+
try {
61+
const hostname = new URL(serverUrl).hostname;
62+
if (hostname !== 'github.com') {
63+
return 'api.enterprise.githubcopilot.com';
64+
}
65+
} catch {
66+
// Invalid URL — fall through to default
67+
}
68+
}
69+
return 'api.githubcopilot.com';
70+
}
71+
const COPILOT_API_TARGET = deriveCopilotApiTarget();
72+
4973
// Squid proxy configuration (set via HTTP_PROXY/HTTPS_PROXY in docker-compose)
5074
const HTTPS_PROXY = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
5175

5276
logRequest('info', 'startup', {
5377
message: 'Starting AWF API proxy sidecar',
5478
squid_proxy: HTTPS_PROXY || 'not configured',
79+
copilot_api_target: COPILOT_API_TARGET,
5580
providers: {
5681
openai: !!OPENAI_API_KEY,
5782
anthropic: !!ANTHROPIC_API_KEY,
@@ -433,7 +458,7 @@ if (COPILOT_GITHUB_TOKEN) {
433458
const contentLength = parseInt(req.headers['content-length'], 10) || 0;
434459
if (checkRateLimit(req, res, 'copilot', contentLength)) return;
435460

436-
proxyRequest(req, res, 'api.githubcopilot.com', {
461+
proxyRequest(req, res, COPILOT_API_TARGET, {
437462
'Authorization': `Bearer ${COPILOT_GITHUB_TOKEN}`,
438463
}, 'copilot');
439464
});

src/cli.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,12 @@ program
784784
' Supports OpenAI (Codex) and Anthropic (Claude) APIs.',
785785
false
786786
)
787+
.option(
788+
'--copilot-api-target <host>',
789+
'Target hostname for GitHub Copilot API requests in the api-proxy sidecar.\n' +
790+
' Defaults to api.githubcopilot.com. Useful for GHES deployments.\n' +
791+
' Can also be set via COPILOT_API_TARGET env var.',
792+
)
787793
.option(
788794
'--rate-limit-rpm <n>',
789795
'Enable rate limiting: max requests per minute per provider (requires --enable-api-proxy)',
@@ -1064,6 +1070,7 @@ program
10641070
openaiApiKey: process.env.OPENAI_API_KEY,
10651071
anthropicApiKey: process.env.ANTHROPIC_API_KEY,
10661072
copilotGithubToken: process.env.COPILOT_GITHUB_TOKEN,
1073+
copilotApiTarget: options.copilotApiTarget || process.env.COPILOT_API_TARGET,
10671074
};
10681075

10691076
// Build rate limit config when API proxy is enabled

src/docker-manager.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,9 @@ export function generateDockerCompose(
444444
if (process.env.USER) environment.USER = process.env.USER;
445445
if (process.env.TERM) environment.TERM = process.env.TERM;
446446
if (process.env.XDG_CONFIG_HOME) environment.XDG_CONFIG_HOME = process.env.XDG_CONFIG_HOME;
447+
// Enterprise environment variables — needed for GHEC/GHES Copilot authentication
448+
if (process.env.GITHUB_SERVER_URL) environment.GITHUB_SERVER_URL = process.env.GITHUB_SERVER_URL;
449+
if (process.env.GITHUB_API_URL) environment.GITHUB_API_URL = process.env.GITHUB_API_URL;
447450
}
448451

449452
// Additional environment variables from --env flags (these override everything)
@@ -977,6 +980,10 @@ export function generateDockerCompose(
977980
...(config.openaiApiKey && { OPENAI_API_KEY: config.openaiApiKey }),
978981
...(config.anthropicApiKey && { ANTHROPIC_API_KEY: config.anthropicApiKey }),
979982
...(config.copilotGithubToken && { COPILOT_GITHUB_TOKEN: config.copilotGithubToken }),
983+
// Configurable Copilot API target (for GHES/GHEC support)
984+
...(config.copilotApiTarget && { COPILOT_API_TARGET: config.copilotApiTarget }),
985+
// Forward GITHUB_SERVER_URL so api-proxy can auto-derive enterprise endpoints
986+
...(process.env.GITHUB_SERVER_URL && { GITHUB_SERVER_URL: process.env.GITHUB_SERVER_URL }),
980987
// Route through Squid to respect domain whitelisting
981988
HTTP_PROXY: `http://${networkConfig.squidIp}:${SQUID_PORT}`,
982989
HTTPS_PROXY: `http://${networkConfig.squidIp}:${SQUID_PORT}`,
@@ -1050,6 +1057,9 @@ export function generateDockerCompose(
10501057
if (config.copilotGithubToken) {
10511058
environment.COPILOT_API_URL = `http://${networkConfig.proxyIp}:${API_PROXY_PORTS.COPILOT}`;
10521059
logger.debug(`GitHub Copilot API will be proxied through sidecar at http://${networkConfig.proxyIp}:${API_PROXY_PORTS.COPILOT}`);
1060+
if (config.copilotApiTarget) {
1061+
logger.debug(`Copilot API target overridden to: ${config.copilotApiTarget}`);
1062+
}
10531063

10541064
// Set placeholder token for GitHub Copilot CLI compatibility
10551065
// Real authentication happens via COPILOT_API_URL pointing to api-proxy

src/types.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,28 @@ export interface WrapperConfig {
472472
* @default undefined
473473
*/
474474
copilotGithubToken?: string;
475+
476+
/**
477+
* Target hostname for GitHub Copilot API requests (used by API proxy sidecar)
478+
*
479+
* When enableApiProxy is true, this hostname is passed to the Node.js sidecar
480+
* as `COPILOT_API_TARGET`. The proxy will forward Copilot API requests to this host
481+
* instead of the default `api.githubcopilot.com`.
482+
*
483+
* Useful for GitHub Enterprise Server (GHES) deployments where the Copilot API
484+
* endpoint differs from the public default.
485+
*
486+
* Can be set via:
487+
* - CLI flag: `--copilot-api-target <host>`
488+
* - Environment variable: `COPILOT_API_TARGET`
489+
*
490+
* @default 'api.githubcopilot.com'
491+
* @example
492+
* ```bash
493+
* awf --enable-api-proxy --copilot-api-target api.github.mycompany.com -- command
494+
* ```
495+
*/
496+
copilotApiTarget?: string;
475497
}
476498

477499
/**

0 commit comments

Comments
 (0)