Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
"""Structured-output translation for Anthropic auxiliary calls."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
|
||||
def _capture_anthropic_kwargs(
|
||||
extra_body: dict | None, *, model: str = "claude-sonnet-4-6",
|
||||
async_call: bool = False, top_level_kwargs: dict | None = None,
|
||||
) -> dict:
|
||||
from agent.auxiliary_client import (
|
||||
_AnthropicCompletionsAdapter,
|
||||
_AsyncAnthropicCompletionsAdapter,
|
||||
)
|
||||
|
||||
captured = {}
|
||||
sync_adapter = _AnthropicCompletionsAdapter(
|
||||
MagicMock(name="anthropic_client"), model, is_oauth=False,
|
||||
)
|
||||
adapter = (
|
||||
_AsyncAnthropicCompletionsAdapter(sync_adapter)
|
||||
if async_call
|
||||
else sync_adapter
|
||||
)
|
||||
|
||||
def _fake_create(_client, api_kwargs, **_kwargs):
|
||||
captured.update(api_kwargs)
|
||||
return SimpleNamespace()
|
||||
|
||||
normalized = SimpleNamespace(
|
||||
content="ok",
|
||||
tool_calls=None,
|
||||
reasoning=None,
|
||||
finish_reason="stop",
|
||||
)
|
||||
call_kwargs = dict(top_level_kwargs or {})
|
||||
if extra_body is not None:
|
||||
call_kwargs["extra_body"] = extra_body
|
||||
with patch(
|
||||
"agent.anthropic_adapter.create_anthropic_message",
|
||||
side_effect=_fake_create,
|
||||
), patch("agent.transports.get_transport") as mock_get_transport:
|
||||
mock_get_transport.return_value.normalize_response.return_value = normalized
|
||||
call = adapter.create(
|
||||
model=model,
|
||||
messages=[{"role": "user", "content": "hi"}],
|
||||
max_tokens=64,
|
||||
**call_kwargs,
|
||||
)
|
||||
if async_call:
|
||||
asyncio.run(call)
|
||||
|
||||
return captured
|
||||
|
||||
|
||||
def _assert_no_raw_response_format(api_kwargs: dict) -> None:
|
||||
assert "response_format" not in api_kwargs
|
||||
assert "response_format" not in api_kwargs.get("extra_body", {})
|
||||
|
||||
|
||||
def test_json_schema_response_format_uses_native_output_config():
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {"title": {"type": "string"}},
|
||||
"required": ["title"],
|
||||
}
|
||||
api_kwargs = _capture_anthropic_kwargs({
|
||||
"response_format": {
|
||||
"type": "json_schema",
|
||||
"json_schema": {
|
||||
"name": "thread_title",
|
||||
"schema": schema,
|
||||
"strict": False,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
assert api_kwargs["output_config"]["format"] == {
|
||||
"type": "json_schema",
|
||||
"schema": schema,
|
||||
}
|
||||
_assert_no_raw_response_format(api_kwargs)
|
||||
|
||||
|
||||
def test_json_object_response_format_uses_permissive_object_schema():
|
||||
api_kwargs = _capture_anthropic_kwargs({
|
||||
"response_format": {"type": "json_object"},
|
||||
})
|
||||
|
||||
assert api_kwargs["output_config"]["format"] == {
|
||||
"type": "json_schema",
|
||||
"schema": {"type": "object"},
|
||||
}
|
||||
_assert_no_raw_response_format(api_kwargs)
|
||||
|
||||
|
||||
def test_response_format_merges_with_adaptive_thinking_effort():
|
||||
schema = {"type": "object", "properties": {"ok": {"type": "boolean"}}}
|
||||
api_kwargs = _capture_anthropic_kwargs({
|
||||
"reasoning": {"enabled": True, "effort": "high"},
|
||||
"response_format": {
|
||||
"type": "json_schema",
|
||||
"json_schema": {"schema": schema},
|
||||
},
|
||||
})
|
||||
|
||||
assert api_kwargs["output_config"] == {
|
||||
"effort": "high",
|
||||
"format": {"type": "json_schema", "schema": schema},
|
||||
}
|
||||
assert api_kwargs["thinking"] == {
|
||||
"type": "adaptive",
|
||||
"display": "summarized",
|
||||
}
|
||||
_assert_no_raw_response_format(api_kwargs)
|
||||
|
||||
|
||||
def test_unrelated_extra_body_keys_still_pass_through():
|
||||
api_kwargs = _capture_anthropic_kwargs({
|
||||
"response_format": {"type": "json_object"},
|
||||
"metadata": {"user_id": "thread-autotitle"},
|
||||
"vendor_option": True,
|
||||
})
|
||||
|
||||
assert api_kwargs["extra_body"] == {
|
||||
"metadata": {"user_id": "thread-autotitle"},
|
||||
"vendor_option": True,
|
||||
}
|
||||
_assert_no_raw_response_format(api_kwargs)
|
||||
|
||||
|
||||
def test_async_anthropic_adapter_uses_the_same_translation():
|
||||
schema = {"type": "object"}
|
||||
api_kwargs = _capture_anthropic_kwargs(
|
||||
{
|
||||
"response_format": {
|
||||
"type": "json_schema",
|
||||
"json_schema": {"schema": schema},
|
||||
},
|
||||
},
|
||||
async_call=True,
|
||||
)
|
||||
|
||||
assert api_kwargs["output_config"]["format"] == {
|
||||
"type": "json_schema",
|
||||
"schema": schema,
|
||||
}
|
||||
_assert_no_raw_response_format(api_kwargs)
|
||||
|
||||
|
||||
def test_top_level_response_format_kwarg_is_translated_not_dropped():
|
||||
"""#85626 review, point 2: the top-level kwarg shape must also translate.
|
||||
|
||||
``client.chat.completions.create(..., response_format=...)`` is the
|
||||
OpenAI SDK's documented call shape. The adapter builds the Messages body
|
||||
from a fixed allow-list of kwargs, so before this an unrecognized
|
||||
top-level kwarg was dropped on the floor: the request succeeded, but the
|
||||
schema contract silently became prompt compliance. Pin-test pattern from
|
||||
PR #85626 (Matt McClean), adapted from strip to translate semantics.
|
||||
"""
|
||||
schema = {
|
||||
"type": "object",
|
||||
"properties": {"title": {"type": "string"}},
|
||||
"required": ["title"],
|
||||
}
|
||||
api_kwargs = _capture_anthropic_kwargs(
|
||||
None,
|
||||
top_level_kwargs={
|
||||
"response_format": {
|
||||
"type": "json_schema",
|
||||
"json_schema": {"name": "session_title", "schema": schema},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
assert api_kwargs["output_config"]["format"] == {
|
||||
"type": "json_schema",
|
||||
"schema": schema,
|
||||
}
|
||||
_assert_no_raw_response_format(api_kwargs)
|
||||
|
||||
|
||||
def test_extra_body_response_format_wins_over_top_level_kwarg():
|
||||
"""When both shapes are present, extra_body wins.
|
||||
|
||||
Every in-tree caller uses the extra_body shape. The top-level kwarg is
|
||||
the compatibility path, so it must not override an explicit extra_body
|
||||
value when a caller somehow sends both.
|
||||
"""
|
||||
eb_schema = {"type": "object", "properties": {"a": {"type": "string"}}}
|
||||
top_schema = {"type": "object", "properties": {"b": {"type": "string"}}}
|
||||
api_kwargs = _capture_anthropic_kwargs(
|
||||
{
|
||||
"response_format": {
|
||||
"type": "json_schema",
|
||||
"json_schema": {"schema": eb_schema},
|
||||
},
|
||||
},
|
||||
top_level_kwargs={
|
||||
"response_format": {
|
||||
"type": "json_schema",
|
||||
"json_schema": {"schema": top_schema},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
assert api_kwargs["output_config"]["format"] == {
|
||||
"type": "json_schema",
|
||||
"schema": eb_schema,
|
||||
}
|
||||
_assert_no_raw_response_format(api_kwargs)
|
||||
Reference in New Issue
Block a user