@@ -2,6 +2,7 @@ import { logger } from '../../logger';
22import { WrapperConfig , API_PROXY_PORTS } from '../../types' ;
33import { COPILOT_PLACEHOLDER_TOKEN } from '../../constants/placeholders' ;
44import { getConfigEnvValue } from '../../env-utils' ;
5+ import { buildProviderCredentialIsolationEnv } from './provider-credential-isolation' ;
56
67interface CopilotCredentialEnvParams {
78 config : WrapperConfig ;
@@ -43,29 +44,33 @@ export function buildCopilotCredentialEnv(params: CopilotCredentialEnvParams): R
4344 // letting the real BASE_URL leak into the agent) preserves the credential-isolation
4445 // invariant and surfaces a clear error instead of a silent bypass.
4546 // Reference: https://github.blog/changelog/2026-04-07-copilot-cli-now-supports-byok-and-local-models/
46- const hasCopilotProviderApiKey = ! ! config . copilotProviderApiKey ;
47+ const hasCopilotProviderApiKey = ! ! config . copilotProviderApiKey || ! ! getConfigEnvValue ( config , 'COPILOT_PROVIDER_API_KEY' ) ;
4748 const hasCopilotProviderBaseUrl = ! ! config . copilotProviderBaseUrl || ! ! getConfigEnvValue ( config , 'COPILOT_PROVIDER_BASE_URL' ) ;
48- if ( ! config . copilotGithubToken && ! hasCopilotProviderApiKey && ! hasCopilotProviderBaseUrl ) {
49- return { } ;
50- }
49+ const enabled = ! ! ( config . copilotGithubToken || hasCopilotProviderApiKey || hasCopilotProviderBaseUrl ) ;
5150
52- const copilotProxyUrl = `http://${ proxyIp } :${ API_PROXY_PORTS . COPILOT } ` ;
53- const agentEnvAdditions : Record < string , string > = {
54- COPILOT_API_URL : copilotProxyUrl ,
55- COPILOT_TOKEN : COPILOT_PLACEHOLDER_TOKEN ,
56- COPILOT_OFFLINE : 'true' ,
57- COPILOT_PROVIDER_BASE_URL : copilotProxyUrl ,
58- } ;
51+ const env = buildProviderCredentialIsolationEnv ( {
52+ providerName : 'GitHub Copilot' ,
53+ proxyIp,
54+ port : API_PROXY_PORTS . COPILOT ,
55+ enabled,
56+ // COPILOT_API_URL: sidecar URL for the Copilot token/completion endpoint.
57+ // COPILOT_PROVIDER_BASE_URL: sidecar URL for the BYOK provider endpoint.
58+ baseUrlVarNames : [ 'COPILOT_API_URL' , 'COPILOT_PROVIDER_BASE_URL' ] ,
59+ target : config . copilotApiTarget ,
60+ placeholders : {
61+ COPILOT_TOKEN : COPILOT_PLACEHOLDER_TOKEN ,
62+ } ,
63+ // Enable Copilot CLI offline + BYOK mode so it skips the GitHub OAuth handshake
64+ // and talks directly to the sidecar without needing GitHub authentication for inference.
65+ extraEnv : {
66+ COPILOT_OFFLINE : 'true' ,
67+ } ,
68+ } ) ;
5969
60- logger . debug ( `GitHub Copilot API will be proxied through sidecar at ${ copilotProxyUrl } ` ) ;
61- if ( config . copilotApiTarget ) {
62- logger . debug ( `Copilot API target overridden to: ${ config . copilotApiTarget } ` ) ;
70+ if ( ! enabled ) {
71+ return env ;
6372 }
6473
65- // Set placeholder token for GitHub Copilot CLI compatibility
66- // Real authentication happens via COPILOT_API_URL pointing to api-proxy
67- logger . debug ( 'COPILOT_TOKEN set to placeholder value for credential isolation' ) ;
68-
6974 // Credential-isolation placeholders for the BYOK auth variables. These MUST be
7075 // set here (in agentEnvAdditions, applied last in compose-generator) rather than
7176 // only in tool-specific-environment.ts, because `Object.assign(environment,
@@ -76,14 +81,14 @@ export function buildCopilotCredentialEnv(params: CopilotCredentialEnvParams): R
7681 // placeholders regardless of which env input path (--env / --env-file / --env-all)
7782 // the user used.
7883 if ( config . copilotGithubToken ) {
79- agentEnvAdditions . COPILOT_GITHUB_TOKEN = COPILOT_PLACEHOLDER_TOKEN ;
84+ env . COPILOT_GITHUB_TOKEN = COPILOT_PLACEHOLDER_TOKEN ;
8085 logger . debug ( 'COPILOT_GITHUB_TOKEN set to placeholder value for credential isolation' ) ;
8186 }
8287 // Only mask COPILOT_PROVIDER_API_KEY when the user actually supplied one. If
8388 // there is nothing to mask, omit it rather than injecting a placeholder that
8489 // would misleadingly tell Copilot CLI "a key is configured".
8590 if ( hasCopilotProviderApiKey ) {
86- agentEnvAdditions . COPILOT_PROVIDER_API_KEY = COPILOT_PLACEHOLDER_TOKEN ;
91+ env . COPILOT_PROVIDER_API_KEY = COPILOT_PLACEHOLDER_TOKEN ;
8792 logger . debug ( 'COPILOT_PROVIDER_API_KEY set to placeholder value for credential isolation' ) ;
8893 }
8994
@@ -92,18 +97,9 @@ export function buildCopilotCredentialEnv(params: CopilotCredentialEnvParams): R
9297 // Copilot CLI uses the correct endpoint in both BYOK modes.
9398 const copilotModel = getConfigEnvValue ( config , 'COPILOT_MODEL' ) ;
9499 if ( copilotModel && requiresResponsesWireApi ( copilotModel ) ) {
95- agentEnvAdditions . COPILOT_PROVIDER_WIRE_API = 'responses' ;
100+ env . COPILOT_PROVIDER_WIRE_API = 'responses' ;
96101 logger . debug ( `COPILOT_PROVIDER_WIRE_API set to responses for model: ${ copilotModel } ` ) ;
97102 }
98103
99- // Enable Copilot CLI offline + BYOK mode so it skips the GitHub OAuth handshake
100- // and talks directly to the sidecar without needing GitHub authentication for inference.
101- logger . debug ( 'COPILOT_OFFLINE set to true for offline+BYOK mode' ) ;
102-
103- // Point Copilot CLI's BYOK provider URL at the sidecar. The sidecar then forwards
104- // either to api.githubcopilot.com (GitHub-token mode) or to the user-supplied
105- // upstream COPILOT_PROVIDER_BASE_URL (direct-BYOK mode).
106- logger . debug ( `COPILOT_PROVIDER_BASE_URL set to sidecar at ${ copilotProxyUrl } ` ) ;
107-
108- return agentEnvAdditions ;
104+ return env ;
109105}
0 commit comments