mirror of
https://github.com/Alishahryar1/free-claude-code.git
synced 2026-04-26 10:31:07 +00:00
- Add local web_search/web_fetch SSE handling and optional tool schemas - Extend HeuristicToolParser for JSON-style WebFetch/WebSearch text - Consolidate provider defaults, ids, and exception typing; stream contracts - Messaging: typed options, voice config injection, platform contract cleanup - Tests for web server tools, converters, parsers, contracts; ignore debug-*.log
96 lines
3.3 KiB
Python
96 lines
3.3 KiB
Python
import json
|
|
|
|
import pytest
|
|
|
|
from api.models.anthropic import Message, MessagesRequest, Tool
|
|
from api.web_server_tools import (
|
|
is_web_server_tool_request,
|
|
stream_web_server_tool_response,
|
|
)
|
|
|
|
|
|
def _event_data(event: str) -> dict:
|
|
data_line = next(line for line in event.splitlines() if line.startswith("data: "))
|
|
return json.loads(data_line.removeprefix("data: "))
|
|
|
|
|
|
def test_detects_web_search_server_tool_request():
|
|
request = MessagesRequest(
|
|
model="claude-haiku-4-5-20251001",
|
|
max_tokens=100,
|
|
messages=[Message(role="user", content="search")],
|
|
tools=[Tool(name="web_search", type="web_search_20250305")],
|
|
)
|
|
|
|
assert is_web_server_tool_request(request)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_streams_web_search_server_tool_result(monkeypatch):
|
|
async def fake_search(query: str) -> list[dict[str, str]]:
|
|
assert query == "DeepSeek V4 model release 2026"
|
|
return [{"title": "DeepSeek V4 Released", "url": "https://example.com/v4"}]
|
|
|
|
monkeypatch.setattr("api.web_server_tools._run_web_search", fake_search)
|
|
request = MessagesRequest(
|
|
model="claude-haiku-4-5-20251001",
|
|
max_tokens=100,
|
|
messages=[
|
|
Message(
|
|
role="user",
|
|
content=(
|
|
"Perform a web search for the query: DeepSeek V4 model release 2026"
|
|
),
|
|
)
|
|
],
|
|
tools=[Tool(name="web_search", type="web_search_20250305")],
|
|
tool_choice={"type": "tool", "name": "web_search"},
|
|
)
|
|
|
|
events = [
|
|
event
|
|
async for event in stream_web_server_tool_response(request, input_tokens=42)
|
|
]
|
|
payloads = [_event_data(event) for event in events]
|
|
|
|
assert payloads[1]["content_block"]["type"] == "server_tool_use"
|
|
assert payloads[1]["content_block"]["name"] == "web_search"
|
|
assert payloads[3]["content_block"]["type"] == "web_search_tool_result"
|
|
assert payloads[3]["content_block"]["content"][0]["url"] == "https://example.com/v4"
|
|
assert payloads[-2]["usage"]["server_tool_use"] == {"web_search_requests": 1}
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_streams_web_fetch_server_tool_result(monkeypatch):
|
|
async def fake_fetch(url: str) -> dict[str, str]:
|
|
assert url == "https://example.com/article"
|
|
return {
|
|
"url": url,
|
|
"title": "Example Article",
|
|
"media_type": "text/plain",
|
|
"data": "Article body",
|
|
}
|
|
|
|
monkeypatch.setattr("api.web_server_tools._run_web_fetch", fake_fetch)
|
|
request = MessagesRequest(
|
|
model="claude-haiku-4-5-20251001",
|
|
max_tokens=100,
|
|
messages=[
|
|
Message(role="user", content="Fetch https://example.com/article please")
|
|
],
|
|
tools=[Tool(name="web_fetch", type="web_fetch_20250910")],
|
|
tool_choice={"type": "tool", "name": "web_fetch"},
|
|
)
|
|
|
|
events = [
|
|
event
|
|
async for event in stream_web_server_tool_response(request, input_tokens=42)
|
|
]
|
|
payloads = [_event_data(event) for event in events]
|
|
|
|
assert payloads[1]["content_block"]["type"] == "server_tool_use"
|
|
assert payloads[3]["content_block"]["type"] == "web_fetch_tool_result"
|
|
assert payloads[3]["content_block"]["content"]["content"]["title"] == (
|
|
"Example Article"
|
|
)
|
|
assert payloads[-2]["usage"]["server_tool_use"] == {"web_fetch_requests": 1}
|