File size: 2,467 Bytes
5ef3875
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
from ycode.tools.base import Tool, ToolRegistry, ToolResult, truncate_middle, validate_args

SCHEMA = {
    "type": "object",
    "properties": {"path": {"type": "string"}, "n": {"type": "integer"}, "mode": {"type": "string", "enum": ["a", "b"]}},
    "required": ["path"],
}


class Boom(Tool):
    name = "boom"
    description = "always fails"
    parameters = {"type": "object", "properties": {}, "required": []}

    def run(self, args, ctx):
        raise RuntimeError("kaboom")


class Echo(Tool):
    name = "echo"
    description = "echo"
    parameters = SCHEMA

    def run(self, args, ctx):
        return ToolResult(content=args["path"], summary="ok")


def test_validate_args():
    assert validate_args(SCHEMA, {"path": "x"}) is None
    assert "missing required" in validate_args(SCHEMA, {})
    assert "must be integer" in validate_args(SCHEMA, {"path": "x", "n": "3"})
    assert "must be integer" in validate_args(SCHEMA, {"path": "x", "n": True})
    assert "one of" in validate_args(SCHEMA, {"path": "x", "mode": "c"})
    assert "JSON object" in validate_args(SCHEMA, "not a dict")


def test_dispatch_routes_to_tool(workspace, make_ctx):
    registry = ToolRegistry([Echo()])
    result = registry.dispatch("echo", {"path": "hi"}, make_ctx(workspace))
    assert result.content == "hi" and not result.is_error
    assert result.duration >= 0


def test_dispatch_unknown_tool(workspace, make_ctx):
    result = ToolRegistry([Echo()]).dispatch("nope", {}, make_ctx(workspace))
    assert result.is_error and "unknown tool" in result.content and "echo" in result.content


def test_dispatch_malformed_arguments(workspace, make_ctx):
    registry = ToolRegistry([Echo()])
    assert registry.dispatch("echo", {"path": 5}, make_ctx(workspace)).is_error
    assert registry.dispatch("echo", None, make_ctx(workspace)).is_error


def test_dispatch_contains_unexpected_exceptions(workspace, make_ctx):
    result = ToolRegistry([Boom()]).dispatch("boom", {}, make_ctx(workspace))
    assert result.is_error and "RuntimeError: kaboom" in result.content


def test_duplicate_registration_rejected():
    import pytest

    with pytest.raises(ValueError):
        ToolRegistry([Echo(), Echo()])


def test_truncate_middle_keeps_head_and_tail():
    text = "HEAD" + "x" * 10000 + "TAIL"
    out = truncate_middle(text, 300)
    assert out.startswith("HEAD") and out.endswith("TAIL") and "omitted" in out
    assert truncate_middle("short", 300) == "short"