mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-06 02:48:13 +00:00
chore: simplify PR 35777 conflict resolver
This commit is contained in:
parent
3dd3297cd6
commit
710ee60bf0
1 changed files with 11 additions and 182 deletions
193
.github/workflows/resolve-pr-35777.yml
vendored
193
.github/workflows/resolve-pr-35777.yml
vendored
|
|
@ -2,203 +2,32 @@ name: Resolve PR 35777 conflicts
|
|||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- litellm_mcp_gateway_request_tags
|
||||
branches: [litellm_mcp_gateway_request_tags]
|
||||
paths:
|
||||
- .github/workflows/resolve-pr-35777.yml
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
resolve:
|
||||
if: github.actor != 'github-actions[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: litellm_mcp_gateway_request_tags
|
||||
|
||||
- name: Merge latest staging and preserve MCP request tags fix
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
- run: |
|
||||
set -e
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git remote add upstream https://github.com/BerriAI/litellm.git 2>/dev/null || true
|
||||
git remote add upstream https://github.com/BerriAI/litellm.git || true
|
||||
git fetch upstream litellm_internal_staging
|
||||
|
||||
git merge --no-commit --no-ff upstream/litellm_internal_staging || true
|
||||
|
||||
# Both files changed substantially upstream. Start from current staging,
|
||||
# then re-apply only the part of #35777 that is still needed.
|
||||
git checkout upstream/litellm_internal_staging -- \
|
||||
litellm/proxy/_experimental/mcp_server/server.py \
|
||||
tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py
|
||||
|
||||
python - <<'PY'
|
||||
from pathlib import Path
|
||||
|
||||
server_path = Path("litellm/proxy/_experimental/mcp_server/server.py")
|
||||
text = server_path.read_text()
|
||||
|
||||
helper_anchor = "\n\ndef _jsonrpc_text_has_top_level_method(text: str) -> bool:\n"
|
||||
helper = '''
|
||||
|
||||
|
||||
def _request_tags_from_raw_headers(
|
||||
raw_headers: Mapping[str, str] | None,
|
||||
) -> Sequence[str] | None:
|
||||
"""Parse the caller's x-litellm-tags header with the shared proxy tag parser."""
|
||||
if not raw_headers:
|
||||
return None
|
||||
for key, value in raw_headers.items():
|
||||
if isinstance(key, str) and key.lower() == "x-litellm-tags" and value:
|
||||
return LiteLLMProxyRequestSetup.add_request_tag_to_metadata(
|
||||
llm_router=None,
|
||||
headers={"x-litellm-tags": value},
|
||||
data={},
|
||||
)
|
||||
return None
|
||||
'''
|
||||
if "def _request_tags_from_raw_headers(" not in text:
|
||||
if helper_anchor not in text:
|
||||
raise SystemExit("helper anchor not found")
|
||||
text = text.replace(helper_anchor, helper + helper_anchor, 1)
|
||||
|
||||
old = " effective_litellm_trace_id: Final = litellm_trace_id or get_chain_id_from_headers(raw_headers)\n spend_logs_metadata: Final[dict[str, object]] = {\n"
|
||||
new = " effective_litellm_trace_id: Final = litellm_trace_id or get_chain_id_from_headers(raw_headers)\n effective_request_tags: Final = request_tags or _request_tags_from_raw_headers(raw_headers)\n spend_logs_metadata: Final[dict[str, object]] = {\n"
|
||||
if "effective_request_tags: Final" not in text:
|
||||
if old not in text:
|
||||
raise SystemExit("list-tools logging anchor not found")
|
||||
text = text.replace(old, new, 1)
|
||||
|
||||
old_tags = ' **({"tags": request_tags} if request_tags else {}),\n'
|
||||
new_tags = ' **({"tags": effective_request_tags} if effective_request_tags else {}),\n'
|
||||
if old_tags in text:
|
||||
text = text.replace(old_tags, new_tags, 1)
|
||||
elif new_tags not in text:
|
||||
raise SystemExit("tags metadata anchor not found")
|
||||
|
||||
server_path.write_text(text)
|
||||
|
||||
test_path = Path("tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py")
|
||||
tests = test_path.read_text()
|
||||
marker = "test_request_tags_from_raw_headers_reads_x_litellm_tags"
|
||||
if marker not in tests:
|
||||
tests += r'''
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"raw_headers, expected",
|
||||
[
|
||||
(None, None),
|
||||
({"mcp-session-id": "abc"}, None),
|
||||
({"x-litellm-tags": ""}, None),
|
||||
(
|
||||
{"X-LiteLLM-Tags": "application:orders, service:checkout"},
|
||||
["application:orders", "service:checkout"],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_request_tags_from_raw_headers_reads_x_litellm_tags(raw_headers, expected):
|
||||
from litellm.proxy._experimental.mcp_server.server import (
|
||||
_request_tags_from_raw_headers,
|
||||
)
|
||||
|
||||
assert _request_tags_from_raw_headers(raw_headers) == expected
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_tools_from_mcp_servers_uses_x_litellm_tags_for_spend_logging():
|
||||
from litellm.proxy._experimental.mcp_server.server import (
|
||||
_get_tools_from_mcp_servers,
|
||||
)
|
||||
from mcp.types import Tool as MCPTool
|
||||
|
||||
user_auth = UserAPIKeyAuth(api_key="test-key", user_id="test-user")
|
||||
|
||||
server_a = MagicMock(name="server_a_obj")
|
||||
server_a.name = "server_a"
|
||||
server_a.alias = "server_a"
|
||||
server_a.server_name = "server_a"
|
||||
server_a.server_id = "a"
|
||||
server_a.auth_type = None
|
||||
server_a.extra_headers = None
|
||||
server_a.tool_name_to_display_name = None
|
||||
server_a.tool_name_to_description = None
|
||||
|
||||
tool_1 = MCPTool(
|
||||
name="server_a-tool_1",
|
||||
description="test tool",
|
||||
inputSchema={"type": "object"},
|
||||
)
|
||||
|
||||
dummy_logging_obj = MagicMock()
|
||||
dummy_logging_obj.model_call_details = {"metadata": {"spend_logs_metadata": {}}}
|
||||
dummy_logging_obj.async_success_handler = AsyncMock()
|
||||
function_setup_kwargs = {}
|
||||
|
||||
def _capture_function_setup(*_args, **kwargs):
|
||||
function_setup_kwargs.update(kwargs)
|
||||
return dummy_logging_obj, None
|
||||
|
||||
with (
|
||||
patch(
|
||||
"litellm.proxy._experimental.mcp_server.server._get_allowed_mcp_servers",
|
||||
new=AsyncMock(return_value=[server_a]),
|
||||
),
|
||||
patch(
|
||||
"litellm.proxy._experimental.mcp_server.server._prepare_mcp_server_headers",
|
||||
return_value=(None, None),
|
||||
),
|
||||
patch(
|
||||
"litellm.proxy._experimental.mcp_server.server.global_mcp_server_manager",
|
||||
) as mock_manager,
|
||||
patch(
|
||||
"litellm.proxy._experimental.mcp_server.server.filter_tools_by_allowed_tools",
|
||||
side_effect=lambda tools, _server: tools,
|
||||
),
|
||||
patch(
|
||||
"litellm.proxy._experimental.mcp_server.server.filter_tools_by_key_team_permissions",
|
||||
new=AsyncMock(side_effect=lambda tools, **_: tools),
|
||||
),
|
||||
patch(
|
||||
"litellm.proxy._experimental.mcp_server.server.function_setup",
|
||||
side_effect=_capture_function_setup,
|
||||
),
|
||||
):
|
||||
mock_manager._get_tools_from_server = AsyncMock(return_value=[tool_1])
|
||||
|
||||
listing = await _get_tools_from_mcp_servers(
|
||||
user_api_key_auth=user_auth,
|
||||
mcp_auth_header=None,
|
||||
mcp_servers=["server_a"],
|
||||
mcp_server_auth_headers=None,
|
||||
raw_headers={"X-LiteLLM-Tags": "application:orders, service:checkout"},
|
||||
log_list_tools_to_spendlogs=True,
|
||||
list_tools_log_source="mcp_protocol",
|
||||
)
|
||||
|
||||
assert listing.tools == [tool_1]
|
||||
assert function_setup_kwargs["metadata"]["tags"] == [
|
||||
"application:orders",
|
||||
"service:checkout",
|
||||
]
|
||||
'''
|
||||
test_path.write_text(tests)
|
||||
PY
|
||||
|
||||
# This workflow is only a one-shot resolver and must not remain in the PR tree.
|
||||
git rm .github/workflows/resolve-pr-35777.yml
|
||||
git add \
|
||||
litellm/proxy/_experimental/mcp_server/server.py \
|
||||
tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py
|
||||
|
||||
if git ls-files -u | grep -q .; then
|
||||
echo "Unresolved merge entries remain:" >&2
|
||||
git ls-files -u >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git checkout upstream/litellm_internal_staging -- litellm/proxy/_experimental/mcp_server/server.py tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py
|
||||
python .github/resolve_pr35777.py
|
||||
git rm .github/workflows/resolve-pr-35777.yml .github/resolve_pr35777.py
|
||||
git add litellm/proxy/_experimental/mcp_server/server.py tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py
|
||||
test -z "$(git ls-files -u)"
|
||||
git commit -m "Merge litellm_internal_staging and resolve MCP request-tags conflicts"
|
||||
git push origin HEAD:litellm_mcp_gateway_request_tags
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue