"""插件 handler 调用约定与安全序列化。"""

from __future__ import annotations

from aicd.agent.chat_serialize import json_safe_dumps, tool_result_content_for_llm
from aicd.agent.tool_router import invoke_plugin_tool_callable


class _FakeRouter:
    pass


def test_invoke_plugin_three_forms() -> None:
    r = _FakeRouter()  # type: ignore[assignment]
    a = {"x": 1}

    def two(router: object, args: dict) -> dict:
        return {"router_ok": router is r, "args": args}

    def one_args(args: dict) -> dict:
        return {"only": "args", "args": args}

    def zero() -> dict:
        return {"n": 0}

    assert invoke_plugin_tool_callable(two, r, a)["router_ok"] is True  # type: ignore[arg-type]
    assert invoke_plugin_tool_callable(one_args, r, a)["only"] == "args"  # type: ignore[arg-type]
    assert invoke_plugin_tool_callable(zero, r, a)["n"] == 0  # type: ignore[arg-type]


def test_tool_result_json_non_primitive_not_crash() -> None:
    class Blob:
        def __repr__(self) -> str:
            return "Blob()"

    raw = {"ok": True, "obj": Blob()}
    s = tool_result_content_for_llm(raw, max_len=50_000)
    assert '"ok": true' in s
    assert "Blob()" in s


def test_json_safe_dumps_circular() -> None:
    d: dict = {"a": 1}
    d["self"] = d
    s = json_safe_dumps(d)
    assert "self" in s or "truncated" in s.lower() or len(s) > 0
