@@ -62,6 +62,21 @@ function shouldStripHeader(name) {
6262const OPENAI_API_KEY = ( process . env . OPENAI_API_KEY || '' ) . trim ( ) || undefined ;
6363const ANTHROPIC_API_KEY = ( process . env . ANTHROPIC_API_KEY || '' ) . trim ( ) || undefined ;
6464const COPILOT_GITHUB_TOKEN = ( process . env . COPILOT_GITHUB_TOKEN || '' ) . trim ( ) || undefined ;
65+ const COPILOT_API_KEY = ( process . env . COPILOT_API_KEY || '' ) . trim ( ) || undefined ;
66+
67+ /**
68+ * Resolves the Copilot auth token from environment variables.
69+ * COPILOT_GITHUB_TOKEN (GitHub OAuth) takes precedence over COPILOT_API_KEY (direct key).
70+ * @param {Record<string, string|undefined> } env - Environment variables to inspect
71+ * @returns {string|undefined } The resolved auth token, or undefined if neither is set
72+ */
73+ function resolveCopilotAuthToken ( env = process . env ) {
74+ const githubToken = ( env . COPILOT_GITHUB_TOKEN || '' ) . trim ( ) || undefined ;
75+ const apiKey = ( env . COPILOT_API_KEY || '' ) . trim ( ) || undefined ;
76+ return githubToken || apiKey ;
77+ }
78+
79+ const COPILOT_AUTH_TOKEN = resolveCopilotAuthToken ( process . env ) ;
6580const GEMINI_API_KEY = ( process . env . GEMINI_API_KEY || '' ) . trim ( ) || undefined ;
6681
6782/**
@@ -213,7 +228,9 @@ logRequest('info', 'startup', {
213228 openai : ! ! OPENAI_API_KEY ,
214229 anthropic : ! ! ANTHROPIC_API_KEY ,
215230 gemini : ! ! GEMINI_API_KEY ,
216- copilot : ! ! COPILOT_GITHUB_TOKEN ,
231+ copilot : ! ! COPILOT_AUTH_TOKEN ,
232+ copilot_github_token : ! ! COPILOT_GITHUB_TOKEN ,
233+ copilot_api_key : ! ! COPILOT_API_KEY ,
217234 } ,
218235} ) ;
219236
@@ -752,7 +769,7 @@ function healthResponse() {
752769 openai : ! ! OPENAI_API_KEY ,
753770 anthropic : ! ! ANTHROPIC_API_KEY ,
754771 gemini : ! ! GEMINI_API_KEY ,
755- copilot : ! ! COPILOT_GITHUB_TOKEN ,
772+ copilot : ! ! COPILOT_AUTH_TOKEN ,
756773 } ,
757774 metrics_summary : metrics . getSummary ( ) ,
758775 rate_limits : limiter . getAllStatus ( ) ,
@@ -857,7 +874,9 @@ if (require.main === module) {
857874
858875
859876 // GitHub Copilot API proxy (port 10002)
860- if ( COPILOT_GITHUB_TOKEN ) {
877+ // Supports COPILOT_GITHUB_TOKEN (GitHub OAuth) and COPILOT_API_KEY (BYOK direct key).
878+ // COPILOT_GITHUB_TOKEN takes precedence when both are set.
879+ if ( COPILOT_AUTH_TOKEN ) {
861880 const copilotServer = http . createServer ( ( req , res ) => {
862881 // Health check endpoint
863882 if ( req . url === '/health' && req . method === 'GET' ) {
@@ -870,13 +889,13 @@ if (require.main === module) {
870889 if ( checkRateLimit ( req , res , 'copilot' , contentLength ) ) return ;
871890
872891 proxyRequest ( req , res , COPILOT_API_TARGET , {
873- 'Authorization' : `Bearer ${ COPILOT_GITHUB_TOKEN } ` ,
892+ 'Authorization' : `Bearer ${ COPILOT_AUTH_TOKEN } ` ,
874893 } , 'copilot' ) ;
875894 } ) ;
876895
877896 copilotServer . on ( 'upgrade' , ( req , socket , head ) => {
878897 proxyWebSocket ( req , socket , head , COPILOT_API_TARGET , {
879- 'Authorization' : `Bearer ${ COPILOT_GITHUB_TOKEN } ` ,
898+ 'Authorization' : `Bearer ${ COPILOT_AUTH_TOKEN } ` ,
880899 } , 'copilot' ) ;
881900 } ) ;
882901
@@ -992,4 +1011,4 @@ if (require.main === module) {
9921011}
9931012
9941013// Export for testing
995- module . exports = { normalizeApiTarget, deriveCopilotApiTarget, normalizeBasePath, buildUpstreamPath, proxyWebSocket } ;
1014+ module . exports = { normalizeApiTarget, deriveCopilotApiTarget, normalizeBasePath, buildUpstreamPath, proxyWebSocket, resolveCopilotAuthToken } ;
0 commit comments