Files
2026-07-13 12:39:17 +08:00

128 lines
4.4 KiB
Python

from __future__ import annotations
import json
import pytest
from pydantic import ValidationError
from agents.agent_tool_input import (
AgentAsToolInput,
StructuredInputSchemaInfo,
_build_schema_summary,
_describe_json_schema_field,
_format_enum_label,
_format_literal_label,
_read_schema_description,
build_structured_input_schema_info,
resolve_agent_tool_input,
)
@pytest.mark.asyncio
async def test_agent_as_tool_input_schema_accepts_string() -> None:
AgentAsToolInput.model_validate({"input": "hi"})
with pytest.raises(ValidationError):
AgentAsToolInput.model_validate({"input": []})
@pytest.mark.asyncio
async def test_resolve_agent_tool_input_returns_string_input() -> None:
result = await resolve_agent_tool_input(params={"input": "hello"})
assert result == "hello"
@pytest.mark.asyncio
async def test_resolve_agent_tool_input_falls_back_to_json() -> None:
result = await resolve_agent_tool_input(params={"foo": "bar"})
assert result == json.dumps({"foo": "bar"})
@pytest.mark.asyncio
async def test_resolve_agent_tool_input_preserves_input_with_extra_fields() -> None:
result = await resolve_agent_tool_input(params={"input": "hello", "target": "world"})
assert result == json.dumps({"input": "hello", "target": "world"})
@pytest.mark.asyncio
async def test_resolve_agent_tool_input_uses_default_builder_when_schema_info_exists() -> None:
result = await resolve_agent_tool_input(
params={"foo": "bar"},
schema_info=StructuredInputSchemaInfo(summary="Summary"),
)
assert isinstance(result, str)
assert "Input Schema Summary:" in result
assert "Summary" in result
@pytest.mark.asyncio
async def test_resolve_agent_tool_input_returns_builder_items() -> None:
items = [{"role": "user", "content": "custom input"}]
async def builder(_options):
return items
result = await resolve_agent_tool_input(params={"input": "ignored"}, input_builder=builder)
assert result == items
def test_build_structured_input_schema_info_handles_empty_schema() -> None:
info = build_structured_input_schema_info(None, include_json_schema=False)
assert info.summary is None
assert info.json_schema is None
def test_build_structured_input_schema_info_generates_summary_for_simple_fields() -> None:
schema = {
"type": "object",
"description": "Tool arguments.",
"properties": {
"mode": {"enum": ["fast", "safe"], "description": "Execution mode."},
"status": {"const": "ok", "description": "Status marker."},
"count": {"type": ["integer", "null"], "description": "Optional count."},
"enabled": {"type": "boolean", "description": "Feature toggle."},
},
"required": ["mode", "status"],
}
info = build_structured_input_schema_info(schema, include_json_schema=True)
assert info.summary is not None
assert "Description: Tool arguments." in info.summary
assert '- mode (enum("fast" | "safe"), required) - Execution mode.' in info.summary
assert '- status (literal("ok"), required) - Status marker.' in info.summary
assert "- count (integer | null, optional) - Optional count." in info.summary
assert "- enabled (boolean, optional) - Feature toggle." in info.summary
assert info.json_schema == schema
def test_schema_summary_returns_none_for_unsupported_shapes() -> None:
assert _build_schema_summary({"type": "array"}) is None
assert _build_schema_summary({"type": "object", "properties": []}) is None
assert (
_build_schema_summary(
{
"type": "object",
"properties": {
"nested": {
"type": "object",
"properties": {"x": {"type": "string"}},
}
},
}
)
is None
)
def test_private_schema_helper_edge_cases() -> None:
assert _describe_json_schema_field("not-a-dict") is None
assert _describe_json_schema_field({"type": ["integer", "string"]}) is None
assert _describe_json_schema_field({"type": "array"}) is None
assert _describe_json_schema_field({}) is None
assert _read_schema_description("not-a-dict") is None
assert _format_enum_label([]) == "enum"
assert "..." in _format_enum_label([1, 2, 3, 4, 5, 6])
assert _format_literal_label({}) == "literal"