From cef21a087df8a30593cce65f3c0f1370c088da5e Mon Sep 17 00:00:00 2001 From: Jason Cook Date: Thu, 23 Apr 2026 12:02:22 -0400 Subject: [PATCH] fix(oauth): route every remaining self.authenticator call through resolve_authenticator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audit of every ``self.authenticator.*`` call-site across both providers turned up two more paths that would skip the ``oauth:`` dispatch: - ``github_copilot/embedding/transformation.py`` — the embedding ``validate_environment`` and ``get_complete_url`` both call the filesystem authenticator directly. Same failure mode as the chat transformation before the previous fix: a request with ``api_key: oauth:`` would hit the filesystem authenticator, find no tokens on disk, and block the server thread on the 15-minute device-code poll. Now goes through ``resolve_authenticator`` too. - ``chatgpt/responses/transformation.py::get_complete_url`` — called separately from ``validate_environment``. Lower severity (the env- based ``get_api_base`` just returns the constant fallback when no auth file is present, so it works in practice) but still a direct call that ought to share the same dispatch. After this commit, ``grep -rn 'self\.authenticator\.' litellm/llms/ {chatgpt,github_copilot}/`` returns zero matches — every auth access goes through ``resolve_authenticator``. 170 tests pass (same count; the chat regression test already covers this family of bug — no new test was worth adding here). Co-Authored-By: Claude Opus 4.7 (1M context) --- litellm/llms/chatgpt/responses/transformation.py | 3 ++- .../github_copilot/embedding/transformation.py | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/litellm/llms/chatgpt/responses/transformation.py b/litellm/llms/chatgpt/responses/transformation.py index 111e42026fd..0ef6c34f881 100644 --- a/litellm/llms/chatgpt/responses/transformation.py +++ b/litellm/llms/chatgpt/responses/transformation.py @@ -199,7 +199,8 @@ class ChatGPTResponsesAPIConfig(OpenAIResponsesAPIConfig): api_base: Optional[str], litellm_params: dict, ) -> str: - api_base = api_base or self.authenticator.get_api_base() or CHATGPT_API_BASE + authenticator = resolve_authenticator(None, litellm_params, self.authenticator) + api_base = api_base or authenticator.get_api_base() or CHATGPT_API_BASE api_base = api_base.rstrip("/") return f"{api_base}/responses" diff --git a/litellm/llms/github_copilot/embedding/transformation.py b/litellm/llms/github_copilot/embedding/transformation.py index fa7bd4e3223..69c22978c2a 100644 --- a/litellm/llms/github_copilot/embedding/transformation.py +++ b/litellm/llms/github_copilot/embedding/transformation.py @@ -6,6 +6,7 @@ This module provides the configuration for GitHub Copilot's Embedding API. Implementation based on analysis of the copilot-api project by caozhiyuan: https://github.com/caozhiyuan/copilot-api """ + from typing import TYPE_CHECKING, Any, Optional import httpx @@ -23,6 +24,7 @@ from ..common_utils import ( GITHUB_COPILOT_API_BASE, get_copilot_default_headers, ) +from ..db_authenticator import resolve_authenticator if TYPE_CHECKING: from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj @@ -57,8 +59,13 @@ class GithubCopilotEmbeddingConfig(BaseEmbeddingConfig): Validate environment and set up headers for GitHub Copilot API. """ try: - # Get GitHub Copilot API key via OAuth - api_key = self.authenticator.get_api_key() + # Route through DBAuthenticator when the caller passes + # ``api_key=oauth:``; otherwise fall back to the + # filesystem authenticator that backs direct-SDK / CLI use. + authenticator = resolve_authenticator( + api_key, litellm_params, self.authenticator + ) + api_key = authenticator.get_api_key() if not api_key: raise AuthenticationError( @@ -99,9 +106,10 @@ class GithubCopilotEmbeddingConfig(BaseEmbeddingConfig): Get the complete URL for GitHub Copilot Embedding API endpoint. """ # Use provided api_base or fall back to authenticator's base or default - api_base = ( - self.authenticator.get_api_base() or api_base or GITHUB_COPILOT_API_BASE + authenticator = resolve_authenticator( + api_key, litellm_params, self.authenticator ) + api_base = authenticator.get_api_base() or api_base or GITHUB_COPILOT_API_BASE # Remove trailing slashes api_base = api_base.rstrip("/")