mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-12 23:01:41 +00:00
refactor(mcp): delete the unwired V1PerUserTokenStore adapter (step 1b piece 5)
Some checks failed
LiteLLM Rust / rustfmt, clippy, test (push) Has been cancelled
Some checks failed
LiteLLM Rust / rustfmt, clippy, test (push) Has been cancelled
Piece 4 replaced V1PerUserTokenStore with the v2-native chain at the composition root, leaving the adapter with no callers, so remove it and its test. The shared v1 read/refresh core (resolve_user_oauth_access_token and friends) stays - delegate's egress in server.py still uses it - and comes out with the delegate migration.
This commit is contained in:
parent
a5dee6a05c
commit
9927d458bc
2 changed files with 0 additions and 96 deletions
|
|
@ -1,49 +0,0 @@
|
|||
"""v1-backed ``OAuthTokenStore`` source for the ``authorization_code`` mode.
|
||||
|
||||
Resolves the user's access token through v1's egress core (``resolve_user_oauth_access_token``:
|
||||
Redis cache, else DB read with refresh), so the v2 arm injects exactly the token v1 would, with the
|
||||
same silent refresh. This is the strangler adapter; step 1b swaps the core for a v2-native store
|
||||
behind the same ``OAuthTokenStore`` seam. It imports v1, so it is kept out of the package
|
||||
``__init__`` like the rest of the adapter layer.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from litellm.proxy._experimental.mcp_server.outbound_credentials.oauth_token_store import (
|
||||
OAuthToken,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from litellm.types.mcp_server.mcp_server_manager import MCPServer
|
||||
|
||||
|
||||
class V1PerUserTokenStore:
|
||||
"""``OAuthTokenStore`` backed by v1's per-user OAuth egress.
|
||||
|
||||
``fetch`` looks the server up by id (injected ``server_lookup``) and resolves the token through
|
||||
v1's ``resolve_user_oauth_access_token``, which refreshes an expired token when a refresh_token
|
||||
is stored and re-warms the Redis cache. Returns ``None`` when the user has no usable token (the
|
||||
arm turns that into a challenge); v1's core swallows store errors as a miss, so this never
|
||||
raises ``TokenStoreUnavailable``. The returned ``OAuthToken`` carries only the access token —
|
||||
refresh happens inside the core, not via ``RefreshingTokenStore``.
|
||||
"""
|
||||
|
||||
def __init__(self, server_lookup: Callable[[str], MCPServer | None]) -> None:
|
||||
self._server_lookup = server_lookup
|
||||
|
||||
async def fetch(self, user_id: str, server_id: str) -> OAuthToken | None:
|
||||
if not user_id:
|
||||
return None
|
||||
server = self._server_lookup(server_id)
|
||||
if server is None:
|
||||
return None
|
||||
|
||||
from litellm.proxy._experimental.mcp_server.db import (
|
||||
resolve_user_oauth_access_token,
|
||||
)
|
||||
|
||||
access_token = await resolve_user_oauth_access_token(user_id, server)
|
||||
return OAuthToken(access_token=access_token) if access_token else None
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
"""Tests for the v1-backed per-user OAuth token source (V1PerUserTokenStore)."""
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from litellm.proxy._experimental.mcp_server.outbound_credentials.v1_token_store import (
|
||||
V1PerUserTokenStore,
|
||||
)
|
||||
|
||||
_RESOLVE = "litellm.proxy._experimental.mcp_server.db.resolve_user_oauth_access_token"
|
||||
|
||||
|
||||
def _store_for(server: object) -> V1PerUserTokenStore:
|
||||
return V1PerUserTokenStore(server_lookup=lambda _server_id: server)
|
||||
|
||||
|
||||
async def test_wraps_the_resolved_access_token():
|
||||
with patch(_RESOLVE, new=AsyncMock(return_value="at-123")):
|
||||
token = await _store_for(object()).fetch("alice", "s")
|
||||
assert token is not None and token.access_token == "at-123"
|
||||
|
||||
|
||||
async def test_missing_token_is_none():
|
||||
with patch(_RESOLVE, new=AsyncMock(return_value=None)):
|
||||
assert await _store_for(object()).fetch("alice", "s") is None
|
||||
|
||||
|
||||
async def test_empty_user_short_circuits_without_resolving():
|
||||
resolve = AsyncMock(return_value="at")
|
||||
with patch(_RESOLVE, new=resolve):
|
||||
assert await _store_for(object()).fetch("", "s") is None
|
||||
resolve.assert_not_called()
|
||||
|
||||
|
||||
async def test_unknown_server_is_none_without_resolving():
|
||||
resolve = AsyncMock(return_value="at")
|
||||
store = V1PerUserTokenStore(server_lookup=lambda _server_id: None)
|
||||
with patch(_RESOLVE, new=resolve):
|
||||
assert await store.fetch("alice", "missing") is None
|
||||
resolve.assert_not_called()
|
||||
|
||||
|
||||
async def test_passes_user_and_resolved_server_to_the_core():
|
||||
server = object()
|
||||
resolve = AsyncMock(return_value="at")
|
||||
with patch(_RESOLVE, new=resolve):
|
||||
await _store_for(server).fetch("alice", "srv-1")
|
||||
resolve.assert_awaited_once_with("alice", server)
|
||||
Loading…
Add table
Reference in a new issue