Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,9 @@ jobs:
--ignore=tests/unit/test_transcript_action_workflow.py -k "not integration"
- name: Offline MCP inventory and approval regressions
run: python -m pytest tests/security/test_local_mcp_config.py tests/security/test_mcp_catalog_approval.py -q -o addopts=''
- name: Anthropic SDK 2 client compatibility
run: >-
PYTHONPATH=src uv run --no-project --python "${{ matrix.python-version }}"
--with pytest --with anthropic==2.0.0 --with httpx2
--with aiohttp --with pydantic
python -m pytest tests/compat/test_anthropic_v2_compat.py -q -o addopts=''
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ ml = [
"tokenizers>=0.15.0",
"sentence-transformers>=2.2.0",
"openai>=1.3.0",
"anthropic>=0.105.0,<2",
"anthropic>=0.105.0,<3",
"google-generativeai>=0.3.0",
"cohere>=4.37.0",
"numpy>=1.24.0",
Expand Down
81 changes: 81 additions & 0 deletions tests/compat/test_anthropic_v2_compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import asyncio
import json

import pytest

anthropic = pytest.importorskip("anthropic", minversion="2.0")
httpx = pytest.importorskip("httpx2")

from agents.mcp_tools.tri_model_consensus_tool import TriModelConsensusTool
from unified_ai_sdk import AIRequest, ModelProvider, TaskType, UnifiedAISDK
from youtube_extension.core.mcp.context_manager import MCPContext
from youtube_extension.core.mcp.protocol_bridge import AnthropicAdapter

calls = []


def respond(request: httpx.Request) -> httpx.Response:
payload = json.loads(request.content)
calls.append((request.url.path, request.headers.get("anthropic-version"), payload))
if request.url.path.endswith("/count_tokens"):
return httpx.Response(200, json={"input_tokens": 1})
return httpx.Response(
200,
json={
"id": "msg_test",
"type": "message",
"role": "assistant",
"content": [{"type": "text", "text": "mocked response"}],
"model": "claude-opus-4-8",
"stop_reason": "end_turn",
"stop_sequence": None,
"usage": {"input_tokens": 11, "output_tokens": 22},
},
)


async def main():
async with httpx.AsyncClient(transport=httpx.MockTransport(respond)) as http_client:
client = anthropic.AsyncAnthropic(
api_key="sk-ant-test", http_client=http_client
)
sdk = UnifiedAISDK({"anthropic_api_key": "sk-ant-test", "retry_attempts": 1})
sdk._anthropic_client = client
result = await sdk.unified_request(
AIRequest(
prompt="Summarize this",
model="claude-opus-4-8",
provider=ModelProvider.CLAUDE,
task_type=TaskType.SUMMARIZATION,
)
)
assert (
result.success
and result.content == "mocked response"
and result.tokens_used == 33
)

adapter = AnthropicAdapter()
assert await adapter.initialize({"api_key": "sk-ant-test"})
adapter._client = client
context = MCPContext(user="test", task="compat", intent="test Anthropic v2")
adapter_result = await adapter.send_request({"prompt": "hello"}, context)
assert adapter_result["content"] == "mocked response"
assert adapter_result["usage"] == {"input_tokens": 11, "output_tokens": 22}
assert await adapter.health_check()

consensus = object.__new__(TriModelConsensusTool)
consensus.claude_client = client
consensus_result = await consensus._query_claude("reason", "generic")
assert (
consensus_result.response == "mocked response"
and not consensus_result.error
)

assert len(calls) == 4 and all(version == "2026-10-21" for _, version, _ in calls)
assert calls[2][0].endswith("/count_tokens")
assert anthropic.__version__.startswith("2.")


def test_anthropic_v2_app_callsites():
asyncio.run(main())
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading