added dynamic endpoint support (#12827)

This commit is contained in:
Jugal D. Bhatt 2025-07-22 01:08:53 +05:30 committed by GitHub
parent 0ae83d6594
commit b653aed603
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 47 additions and 3 deletions

View File

@ -132,6 +132,23 @@ class Authenticator:
status_code=401,
)
def get_api_base(self) -> Optional[str]:
"""
Get the API endpoint from the api-key.json file.
Returns:
Optional[str]: The GitHub Copilot API endpoint, or None if not found.
"""
try:
with open(self.api_key_file, "r") as f:
api_key_info = json.load(f)
endpoints = api_key_info.get("endpoints", {})
api_endpoint = endpoints.get("api")
return api_endpoint
except (IOError, json.JSONDecodeError, KeyError) as e:
verbose_logger.warning(f"Error reading API endpoint from file: {str(e)}")
return None
def _refresh_api_key(self) -> Dict[str, Any]:
"""
Refresh the API key using the access token.

View File

@ -25,7 +25,7 @@ class GithubCopilotConfig(OpenAIConfig):
api_key: Optional[str],
custom_llm_provider: str,
) -> Tuple[Optional[str], Optional[str], str]:
api_base = self.GITHUB_COPILOT_API_BASE
dynamic_api_base = self.authenticator.get_api_base() or self.GITHUB_COPILOT_API_BASE
try:
dynamic_api_key = self.authenticator.get_api_key()
except GetAPIKeyError as e:
@ -34,7 +34,7 @@ class GithubCopilotConfig(OpenAIConfig):
llm_provider=custom_llm_provider,
message=str(e),
)
return api_base, dynamic_api_key, custom_llm_provider
return dynamic_api_base, dynamic_api_key, custom_llm_provider
def _transform_messages(
self,

View File

@ -178,3 +178,14 @@ class TestGitHubCopilotAuthenticator:
authenticator._get_device_code.assert_called_once()
authenticator._poll_for_access_token.assert_called_once_with("mock-device-code")
mock_print.assert_called_once()
def test_get_api_base_from_file(self, authenticator):
"""Test retrieving the API base endpoint from a file."""
mock_api_key_data = json.dumps({
"token": "mock-api-key",
"expires_at": (datetime.now() + timedelta(hours=1)).timestamp(),
"endpoints": {"api": "https://api.enterprise.githubcopilot.com"}
})
with patch("builtins.open", mock_open(read_data=mock_api_key_data)):
api_base = authenticator.get_api_base()
assert api_base == "https://api.enterprise.githubcopilot.com"

View File

@ -40,6 +40,8 @@ def test_github_copilot_config_get_openai_compatible_provider_info():
mock_api_key = "gh.test-key-123456789"
config.authenticator = MagicMock()
config.authenticator.get_api_key.return_value = mock_api_key
# Test with dynamic endpoint
config.authenticator.get_api_base.return_value = "https://api.enterprise.githubcopilot.com"
# Test with default values
model = "github_copilot/gpt-4"
@ -54,10 +56,24 @@ def test_github_copilot_config_get_openai_compatible_provider_info():
custom_llm_provider="github_copilot",
)
assert api_base == "https://api.githubcopilot.com/"
assert api_base == "https://api.enterprise.githubcopilot.com"
assert dynamic_api_key == mock_api_key
assert custom_llm_provider == "github_copilot"
# Test fallback to default if no dynamic endpoint
config.authenticator.get_api_base.return_value = None
(
api_base,
dynamic_api_key,
custom_llm_provider,
) = config._get_openai_compatible_provider_info(
model=model,
api_base=None,
api_key=None,
custom_llm_provider="github_copilot",
)
assert api_base == "https://api.githubcopilot.com/"
# Test with authentication failure
config.authenticator.get_api_key.side_effect = GetAPIKeyError(
message="Failed to get API key",