|
1 | 1 | import { Command } from 'commander'; |
2 | | -import { parseEnvironmentVariables, parseDomains, parseDomainsFile, escapeShellArg, joinShellArgs, parseVolumeMounts, isValidIPv4, isValidIPv6, parseDnsServers, parseDnsOverHttps, validateAgentImage, isAgentImagePreset, AGENT_IMAGE_PRESETS, processAgentImageOption, processLocalhostKeyword, validateSkipPullWithBuildLocal, validateAllowHostPorts, validateAllowHostServicePorts, applyHostServicePortsConfig, parseMemoryLimit, validateFormat, validateApiProxyConfig, buildRateLimitConfig, validateRateLimitFlags, hasRateLimitOptions, collectRulesetFile, validateApiTargetInAllowedDomains, DEFAULT_OPENAI_API_TARGET, DEFAULT_ANTHROPIC_API_TARGET, DEFAULT_COPILOT_API_TARGET, emitApiProxyTargetWarnings, formatItem, program, parseAgentTimeout, applyAgentTimeout, handlePredownloadAction, resolveApiTargetsToAllowedDomains, extractGhesDomainsFromEngineApiTarget, extractGhecDomainsFromServerUrl } from './cli'; |
| 2 | +import { parseEnvironmentVariables, parseDomains, parseDomainsFile, escapeShellArg, joinShellArgs, parseVolumeMounts, isValidIPv4, isValidIPv6, parseDnsServers, parseDnsOverHttps, validateAgentImage, isAgentImagePreset, AGENT_IMAGE_PRESETS, processAgentImageOption, processLocalhostKeyword, validateSkipPullWithBuildLocal, validateAllowHostPorts, validateAllowHostServicePorts, applyHostServicePortsConfig, parseMemoryLimit, validateFormat, validateApiProxyConfig, buildRateLimitConfig, validateRateLimitFlags, hasRateLimitOptions, collectRulesetFile, validateApiTargetInAllowedDomains, DEFAULT_OPENAI_API_TARGET, DEFAULT_ANTHROPIC_API_TARGET, DEFAULT_COPILOT_API_TARGET, DEFAULT_GEMINI_API_TARGET, emitApiProxyTargetWarnings, formatItem, program, parseAgentTimeout, applyAgentTimeout, handlePredownloadAction, resolveApiTargetsToAllowedDomains, extractGhesDomainsFromEngineApiTarget, extractGhecDomainsFromServerUrl } from './cli'; |
3 | 3 | import { redactSecrets } from './redact-secrets'; |
4 | 4 | import * as fs from 'fs'; |
5 | 5 | import * as path from 'path'; |
@@ -1780,11 +1780,12 @@ describe('cli', () => { |
1780 | 1780 | }); |
1781 | 1781 | }); |
1782 | 1782 |
|
1783 | | - describe('DEFAULT_OPENAI_API_TARGET and DEFAULT_ANTHROPIC_API_TARGET', () => { |
| 1783 | + describe('DEFAULT_*_API_TARGET constants', () => { |
1784 | 1784 | it('should have correct default values', () => { |
1785 | 1785 | expect(DEFAULT_OPENAI_API_TARGET).toBe('api.openai.com'); |
1786 | 1786 | expect(DEFAULT_ANTHROPIC_API_TARGET).toBe('api.anthropic.com'); |
1787 | 1787 | expect(DEFAULT_COPILOT_API_TARGET).toBe('api.githubcopilot.com'); |
| 1788 | + expect(DEFAULT_GEMINI_API_TARGET).toBe('generativelanguage.googleapis.com'); |
1788 | 1789 | }); |
1789 | 1790 | }); |
1790 | 1791 |
|
@@ -1988,6 +1989,55 @@ describe('cli', () => { |
1988 | 1989 | expect(warnings[1]).toContain('--anthropic-api-target=anthropic.internal'); |
1989 | 1990 | expect(warnings[2]).toContain('--copilot-api-target=copilot.internal'); |
1990 | 1991 | }); |
| 1992 | + |
| 1993 | + it('should emit warning for custom Gemini target not in allowed domains', () => { |
| 1994 | + const warnings: string[] = []; |
| 1995 | + emitApiProxyTargetWarnings( |
| 1996 | + { enableApiProxy: true, geminiApiTarget: 'custom.gemini-router.internal' }, |
| 1997 | + ['github.com'], |
| 1998 | + (msg) => warnings.push(msg) |
| 1999 | + ); |
| 2000 | + expect(warnings).toHaveLength(1); |
| 2001 | + expect(warnings[0]).toContain('--gemini-api-target=custom.gemini-router.internal'); |
| 2002 | + }); |
| 2003 | + |
| 2004 | + it('should emit no warnings when custom Gemini target is in allowed domains', () => { |
| 2005 | + const warnings: string[] = []; |
| 2006 | + emitApiProxyTargetWarnings( |
| 2007 | + { enableApiProxy: true, geminiApiTarget: 'gemini.example.com' }, |
| 2008 | + ['example.com'], |
| 2009 | + (msg) => warnings.push(msg) |
| 2010 | + ); |
| 2011 | + expect(warnings).toHaveLength(0); |
| 2012 | + }); |
| 2013 | + |
| 2014 | + it('should use default Gemini target when geminiApiTarget is undefined', () => { |
| 2015 | + const warnings: string[] = []; |
| 2016 | + emitApiProxyTargetWarnings( |
| 2017 | + { enableApiProxy: true, geminiApiTarget: undefined }, |
| 2018 | + ['github.com'], |
| 2019 | + (msg) => warnings.push(msg) |
| 2020 | + ); |
| 2021 | + // Default target is not in 'github.com' but since it IS the default, no warning is emitted |
| 2022 | + expect(warnings).toHaveLength(0); |
| 2023 | + }); |
| 2024 | + |
| 2025 | + it('should emit warnings for all four custom targets when none are in allowed domains', () => { |
| 2026 | + const warnings: string[] = []; |
| 2027 | + emitApiProxyTargetWarnings( |
| 2028 | + { |
| 2029 | + enableApiProxy: true, |
| 2030 | + openaiApiTarget: 'openai.internal', |
| 2031 | + anthropicApiTarget: 'anthropic.internal', |
| 2032 | + copilotApiTarget: 'copilot.internal', |
| 2033 | + geminiApiTarget: 'gemini.internal', |
| 2034 | + }, |
| 2035 | + ['github.com'], |
| 2036 | + (msg) => warnings.push(msg) |
| 2037 | + ); |
| 2038 | + expect(warnings).toHaveLength(4); |
| 2039 | + expect(warnings[3]).toContain('--gemini-api-target=gemini.internal'); |
| 2040 | + }); |
1991 | 2041 | }); |
1992 | 2042 |
|
1993 | 2043 | describe('resolveApiTargetsToAllowedDomains', () => { |
@@ -2117,6 +2167,28 @@ describe('cli', () => { |
2117 | 2167 | // Whitespace-only and empty values are filtered out |
2118 | 2168 | expect(domains).toHaveLength(0); |
2119 | 2169 | }); |
| 2170 | + |
| 2171 | + it('should add gemini-api-target option to allowed domains', () => { |
| 2172 | + const domains: string[] = ['github.com']; |
| 2173 | + resolveApiTargetsToAllowedDomains({ geminiApiTarget: 'custom.gemini.internal' }, domains); |
| 2174 | + expect(domains).toContain('custom.gemini.internal'); |
| 2175 | + expect(domains).toContain('https://custom.gemini.internal'); |
| 2176 | + }); |
| 2177 | + |
| 2178 | + it('should read GEMINI_API_TARGET from env when flag not set', () => { |
| 2179 | + const domains: string[] = []; |
| 2180 | + const env = { GEMINI_API_TARGET: 'env.gemini.internal' }; |
| 2181 | + resolveApiTargetsToAllowedDomains({}, domains, env); |
| 2182 | + expect(domains).toContain('env.gemini.internal'); |
| 2183 | + }); |
| 2184 | + |
| 2185 | + it('should prefer geminiApiTarget option over GEMINI_API_TARGET env var', () => { |
| 2186 | + const domains: string[] = []; |
| 2187 | + const env = { GEMINI_API_TARGET: 'env.gemini.internal' }; |
| 2188 | + resolveApiTargetsToAllowedDomains({ geminiApiTarget: 'flag.gemini.internal' }, domains, env); |
| 2189 | + expect(domains).toContain('flag.gemini.internal'); |
| 2190 | + expect(domains).not.toContain('env.gemini.internal'); |
| 2191 | + }); |
2120 | 2192 | }); |
2121 | 2193 |
|
2122 | 2194 | describe('formatItem', () => { |
|
0 commit comments