fix(oauth): route every remaining self.authenticator call through resolve_authenticator

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:<name>`` 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) <noreply@anthropic.com>
This commit is contained in:
Jason Cook 2026-04-23 12:02:22 -04:00
parent 581b3e9692
commit cef21a087d
2 changed files with 14 additions and 5 deletions

View file

@ -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"

View file

@ -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:<name>``; 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("/")