Skip to content

Commit 4ba4f13

Browse files
authored
refactor: eliminate code duplication in OpenCode proxy routing
- Add needsAnthropicVersion flag to resolveOpenCodeRoute return value to centralize anthropic-version header logic - Use resolveOpenCodeRoute() for startup guard instead of repeating the credential availability check - Update tests to assert needsAnthropicVersion for all scenarios Agent-Logs-Url: https://github.com/github/gh-aw-firewall/sessions/a0621fda-d1a3-449b-a3da-a9d0331c4c76
1 parent 46217c1 commit 4ba4f13

2 files changed

Lines changed: 18 additions & 13 deletions

File tree

containers/api-proxy/server.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -300,17 +300,17 @@ if (!proxyAgent) {
300300
* @param {string} copilotTarget
301301
* @param {string} [openaiBasePath]
302302
* @param {string} [anthropicBasePath]
303-
* @returns {{ target: string, headers: Record<string,string>, basePath: string|undefined } | null}
303+
* @returns {{ target: string, headers: Record<string,string>, basePath: string|undefined, needsAnthropicVersion: boolean } | null}
304304
*/
305305
function resolveOpenCodeRoute(openaiKey, anthropicKey, copilotToken, openaiTarget, anthropicTarget, copilotTarget, openaiBasePath, anthropicBasePath) {
306306
if (openaiKey) {
307-
return { target: openaiTarget, headers: { 'Authorization': `Bearer ${openaiKey}` }, basePath: openaiBasePath };
307+
return { target: openaiTarget, headers: { 'Authorization': `Bearer ${openaiKey}` }, basePath: openaiBasePath, needsAnthropicVersion: false };
308308
}
309309
if (anthropicKey) {
310-
return { target: anthropicTarget, headers: { 'x-api-key': anthropicKey }, basePath: anthropicBasePath };
310+
return { target: anthropicTarget, headers: { 'x-api-key': anthropicKey }, basePath: anthropicBasePath, needsAnthropicVersion: true };
311311
}
312312
if (copilotToken) {
313-
return { target: copilotTarget, headers: { 'Authorization': `Bearer ${copilotToken}` }, basePath: undefined };
313+
return { target: copilotTarget, headers: { 'Authorization': `Bearer ${copilotToken}` }, basePath: undefined, needsAnthropicVersion: false };
314314
}
315315
return null;
316316
}
@@ -1063,7 +1063,12 @@ if (require.main === module) {
10631063
// 1. OPENAI_API_KEY → OpenAI/Copilot-compatible route (OPENAI_API_TARGET)
10641064
// 2. ANTHROPIC_API_KEY → Anthropic BYOK route (ANTHROPIC_API_TARGET)
10651065
// 3. COPILOT_AUTH_TOKEN → Copilot route (COPILOT_API_TARGET)
1066-
if (OPENAI_API_KEY || ANTHROPIC_API_KEY || COPILOT_AUTH_TOKEN) {
1066+
const opencodeStartupRoute = resolveOpenCodeRoute(
1067+
OPENAI_API_KEY, ANTHROPIC_API_KEY, COPILOT_AUTH_TOKEN,
1068+
OPENAI_API_TARGET, ANTHROPIC_API_TARGET, COPILOT_API_TARGET,
1069+
OPENAI_API_BASE_PATH, ANTHROPIC_API_BASE_PATH
1070+
);
1071+
if (opencodeStartupRoute) {
10671072
const opencodeServer = http.createServer((req, res) => {
10681073
if (req.url === '/health' && req.method === 'GET') {
10691074
res.writeHead(200, { 'Content-Type': 'application/json' });
@@ -1103,7 +1108,7 @@ if (require.main === module) {
11031108
});
11041109

11051110
const headers = Object.assign({}, route.headers);
1106-
if (ANTHROPIC_API_KEY && !OPENAI_API_KEY && !req.headers['anthropic-version']) {
1111+
if (route.needsAnthropicVersion && !req.headers['anthropic-version']) {
11071112
headers['anthropic-version'] = '2023-06-01';
11081113
}
11091114
proxyRequest(req, res, route.target, headers, 'opencode', route.basePath);
@@ -1123,19 +1128,14 @@ if (require.main === module) {
11231128
}
11241129

11251130
const headers = Object.assign({}, route.headers);
1126-
if (ANTHROPIC_API_KEY && !OPENAI_API_KEY && !req.headers['anthropic-version']) {
1131+
if (route.needsAnthropicVersion && !req.headers['anthropic-version']) {
11271132
headers['anthropic-version'] = '2023-06-01';
11281133
}
11291134
proxyWebSocket(req, socket, head, route.target, headers, 'opencode', route.basePath);
11301135
});
11311136

11321137
opencodeServer.listen(10004, '0.0.0.0', () => {
1133-
const routingTarget = OPENAI_API_KEY
1134-
? `OpenAI/Copilot at ${OPENAI_API_TARGET}`
1135-
: ANTHROPIC_API_KEY
1136-
? `Anthropic at ${ANTHROPIC_API_TARGET}`
1137-
: `Copilot at ${COPILOT_API_TARGET}`;
1138-
logRequest('info', 'server_start', { message: `OpenCode proxy listening on port 10004 (-> ${routingTarget})` });
1138+
logRequest('info', 'server_start', { message: `OpenCode proxy listening on port 10004 (-> ${opencodeStartupRoute.target})` });
11391139
});
11401140
}
11411141

containers/api-proxy/server.test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,7 @@ describe('resolveOpenCodeRoute', () => {
798798
expect(route.target).toBe(OPENAI_TARGET);
799799
expect(route.headers['Authorization']).toBe('Bearer sk-openai-key');
800800
expect(route.basePath).toBe(OPENAI_BASE);
801+
expect(route.needsAnthropicVersion).toBe(false);
801802
});
802803

803804
it('should route to Anthropic when only ANTHROPIC_API_KEY is set', () => {
@@ -810,6 +811,7 @@ describe('resolveOpenCodeRoute', () => {
810811
expect(route.target).toBe(ANTHROPIC_TARGET);
811812
expect(route.headers['x-api-key']).toBe('sk-anthropic-key');
812813
expect(route.basePath).toBe(ANTHROPIC_BASE);
814+
expect(route.needsAnthropicVersion).toBe(true);
813815
});
814816

815817
it('should prefer OpenAI over Anthropic when both are set', () => {
@@ -821,6 +823,7 @@ describe('resolveOpenCodeRoute', () => {
821823
expect(route).not.toBeNull();
822824
expect(route.target).toBe(OPENAI_TARGET);
823825
expect(route.headers['Authorization']).toBe('Bearer sk-openai-key');
826+
expect(route.needsAnthropicVersion).toBe(false);
824827
});
825828

826829
it('should route to Copilot when only copilotToken is set', () => {
@@ -833,6 +836,7 @@ describe('resolveOpenCodeRoute', () => {
833836
expect(route.target).toBe(COPILOT_TARGET);
834837
expect(route.headers['Authorization']).toBe('Bearer gho_copilot-token');
835838
expect(route.basePath).toBeUndefined();
839+
expect(route.needsAnthropicVersion).toBe(false);
836840
});
837841

838842
it('should prefer Anthropic over Copilot when both are set', () => {
@@ -844,6 +848,7 @@ describe('resolveOpenCodeRoute', () => {
844848
expect(route).not.toBeNull();
845849
expect(route.target).toBe(ANTHROPIC_TARGET);
846850
expect(route.headers['x-api-key']).toBe('sk-anthropic-key');
851+
expect(route.needsAnthropicVersion).toBe(true);
847852
});
848853

849854
it('should return null when no credentials are available', () => {

0 commit comments

Comments
 (0)