"""Helper script for Robot Framework tool router smoke tests.""" from __future__ import annotations import json import sys from pathlib import Path from typing import Any # Ensure src is importable when run from workspace root sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) from cleveragents.tool.registry import ToolRegistry from cleveragents.tool.router import ( NormalizedToolCallResult, ProviderFormat, StreamingToolUpdate, ToolCallRouter, classify_tool_error, detect_provider_format, generate_tool_call_id, normalize_tool_call, normalize_tool_schema_for_provider, ) from cleveragents.tool.runner import ToolRunner from cleveragents.tool.runtime import ToolSpec def _echo(inputs: dict[str, Any]) -> dict[str, Any]: return dict(inputs) def _fail(inputs: dict[str, Any]) -> dict[str, Any]: raise RuntimeError("boom") def test_detect_openai() -> None: fmt = detect_provider_format({"name": "x/y", "arguments": '{"a": 1}'}) assert fmt == ProviderFormat.OPENAI print("detect-openai-ok") def test_detect_anthropic() -> None: fmt = detect_provider_format({"name": "x/y", "input": {"a": 1}}) assert fmt == ProviderFormat.ANTHROPIC print("detect-anthropic-ok") def test_detect_langchain() -> None: fmt = detect_provider_format({"name": "x/y", "type": "tool_call", "args": {}}) assert fmt == ProviderFormat.LANGCHAIN print("detect-langchain-ok") def test_normalize_openai() -> None: req = normalize_tool_call({"name": "x/y", "arguments": '{"a": 1}'}) assert req.tool_name == "x/y" assert req.arguments["a"] == 1 assert req.provider_format == ProviderFormat.OPENAI print("normalize-openai-ok") def test_stable_id() -> None: id1 = generate_tool_call_id("plan-1", 0) id2 = generate_tool_call_id("plan-1", 0) assert id1 == id2 assert id1.startswith("tc_") print("stable-id-ok") def test_route_openai() -> None: registry = ToolRegistry() spec = ToolSpec(name="smoke/echo", description="Echo", handler=_echo) registry.register(spec) runner = ToolRunner(registry) router = ToolCallRouter(registry=registry, runner=runner, plan_id="plan-1") result = router.route({"name": "smoke/echo", "arguments": '{"msg": "hi"}'}) assert result.result.success assert result.provider_format == ProviderFormat.OPENAI print("route-openai-ok") def test_route_anthropic() -> None: registry = ToolRegistry() spec = ToolSpec(name="smoke/echo", description="Echo", handler=_echo) registry.register(spec) runner = ToolRunner(registry) router = ToolCallRouter(registry=registry, runner=runner, plan_id="plan-2") result = router.route({"name": "smoke/echo", "input": {"msg": "hi"}}) assert result.result.success assert result.provider_format == ProviderFormat.ANTHROPIC print("route-anthropic-ok") def test_route_error() -> None: registry = ToolRegistry() spec = ToolSpec(name="smoke/fail", description="Fail", handler=_fail) registry.register(spec) runner = ToolRunner(registry) router = ToolCallRouter(registry=registry, runner=runner, plan_id="plan-3") result = router.route({"name": "smoke/fail", "arguments": "{}"}) assert not result.result.success print("route-error-ok") def test_error_classify() -> None: cat = classify_tool_error("Operation timed out") assert cat.value == "timeout" cat2 = classify_tool_error("Permission denied") assert cat2.value == "permission" print("error-classify-ok") def test_schema_normalize() -> None: spec = ToolSpec(name="smoke/echo", description="Echo tool", handler=_echo) schema = normalize_tool_schema_for_provider(spec, ProviderFormat.OPENAI) assert "parameters" in schema schema2 = normalize_tool_schema_for_provider(spec, ProviderFormat.ANTHROPIC) assert "input_schema" in schema2 print("schema-normalize-ok") def test_batch_route() -> None: registry = ToolRegistry() spec = ToolSpec(name="smoke/echo", description="Echo", handler=_echo) registry.register(spec) runner = ToolRunner(registry) router = ToolCallRouter(registry=registry, runner=runner, plan_id="plan-batch") payloads = [ {"name": "smoke/echo", "arguments": json.dumps({"i": i})} for i in range(3) ] results = router.route_batch(payloads) assert len(results) == 3 assert all(r.result.success for r in results) print("batch-route-ok") def test_streaming() -> None: registry = ToolRegistry() spec = ToolSpec(name="smoke/echo", description="Echo", handler=_echo) registry.register(spec) runner = ToolRunner(registry) router = ToolCallRouter(registry=registry, runner=runner, plan_id="plan-stream") items = list( router.route_streaming({"name": "smoke/echo", "arguments": '{"msg": "s"}'}) ) updates = [i for i in items if isinstance(i, StreamingToolUpdate)] results = [i for i in items if isinstance(i, NormalizedToolCallResult)] assert len(updates) >= 2 assert len(results) == 1 assert results[0].result.success print("streaming-ok") if __name__ == "__main__": cmd = sys.argv[1] if len(sys.argv) > 1 else "detect_openai" commands = { "detect_openai": test_detect_openai, "detect_anthropic": test_detect_anthropic, "detect_langchain": test_detect_langchain, "normalize_openai": test_normalize_openai, "stable_id": test_stable_id, "route_openai": test_route_openai, "route_anthropic": test_route_anthropic, "route_error": test_route_error, "error_classify": test_error_classify, "schema_normalize": test_schema_normalize, "batch_route": test_batch_route, "streaming": test_streaming, } handler = commands.get(cmd) if handler is None: print(f"Unknown command: {cmd}", file=sys.stderr) sys.exit(1) handler()