Files
ObsiGate/tests/test_tool_labels.py
T
bruno 19d5b931c4
CI / lint (push) Successful in 1m22s
CI / security (push) Successful in 55s
CI / test (push) Successful in 3m0s
CI / build (push) Successful in 51s
CI / e2e (push) Successful in 10m41s
feat(assistant): #91 steps humains en direct + outils web_search/fetch_url (labels backend, SSE step, garde SSRF)
2026-09-15 17:46:51 -04:00

68 lines
2.8 KiB
Python

"""Unit tests for the Notion-style step labels (backend.tools.labels)."""
from backend.agent.loop import ToolCallRecord
from backend.tools.labels import GENERIC_KEY, _STEP_LABELS, tool_step_label
from backend.tools.registry import list_tools
from backend.tools.context import ToolScope
class TestToolStepLabel:
def test_every_in_app_tool_has_a_label(self):
# A registered tool without a mapping still degrades gracefully to the
# generic key, but the curated coverage must stay complete for the UI.
names = {spec.name for spec in list_tools(scope=ToolScope.IN_APP)}
assert names.issubset(set(_STEP_LABELS)), names - set(_STEP_LABELS)
def test_label_argument_names_match_input_models(self):
# A mapped primary argument that the tool's input model does not
# actually declare would silently render "{value}" placeholders —
# verify every (name, arg) pair against the real schemas.
from backend.tools.registry import get_tool
for name, (_key, arg) in _STEP_LABELS.items():
if arg is None:
continue
spec = get_tool(name)
assert spec is not None, name
fields = spec.input_model.model_fields
assert arg in fields, f"{name}: input model has no field '{arg}'"
def test_named_tool_returns_key_and_value(self):
label = tool_step_label("read_file", {"vault": "V", "path": "notes/a.md"})
assert label["key"] == "file_read"
assert label["params"]["value"] == "notes/a.md"
def test_search_tool_surfaces_the_query(self):
label = tool_step_label("search_fulltext", {"q": "pizza", "vault": "V"})
assert label["key"] == "search"
assert label["params"]["value"] == "pizza"
def test_no_argument_tools_have_empty_params(self):
label = tool_step_label("list_vaults", {})
assert label["key"] == "vaults"
assert label["params"] == {}
def test_missing_argument_degrades_to_key_only(self):
label = tool_step_label("read_file", {})
assert label["key"] == "file_read"
assert "value" not in label["params"]
def test_unknown_tool_falls_back_to_generic(self):
label = tool_step_label("future_tool_name", {"x": 1})
assert label["key"] == GENERIC_KEY
assert label["params"]["tool"] == "future tool name"
def test_arguments_none_is_accepted(self):
assert tool_step_label("list_tags", None)["key"] == "tags"
def test_tool_call_record_carries_step(self):
rec = ToolCallRecord(
name="read_file",
arguments={"path": "a.md"},
ok=True,
result={},
step=tool_step_label("read_file", {"path": "a.md"}),
)
assert rec.step["key"] == "file_read"
assert rec.step["params"]["value"] == "a.md"