186 lines
5.6 KiB
Python
186 lines
5.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Integration tests for tool configuration HTTP API.
|
|
|
|
Covers GET /tools (list), PATCH /tools/{name}/toggle, and
|
|
GET /tools/{name}/config endpoints. Verifies that builtin tools
|
|
(e.g. get_current_time) appear in the list and can be toggled.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from helpers import default_http_timeout, scoped
|
|
|
|
_TOOL_HTTP_TIMEOUT = default_http_timeout(15.0)
|
|
|
|
|
|
# ------------------------------------------------------------------ #
|
|
# C1: tool list includes get_current_time
|
|
# ------------------------------------------------------------------ #
|
|
|
|
|
|
@pytest.mark.integration
|
|
@pytest.mark.p1
|
|
def test_tool_list_includes_get_current_time(app_server) -> None:
|
|
"""Test purpose:
|
|
- Verify GET /tools returns a list that includes the
|
|
get_current_time builtin tool with enabled=true.
|
|
|
|
Test flow:
|
|
1. GET /api/agents/default/tools.
|
|
2. Assert response is a list.
|
|
3. Find get_current_time in the list.
|
|
4. Assert it is enabled.
|
|
|
|
API endpoints:
|
|
- GET /api/agents/{agentId}/tools
|
|
"""
|
|
resp = app_server.api_request(
|
|
"GET",
|
|
scoped("default", "/tools"),
|
|
timeout=_TOOL_HTTP_TIMEOUT,
|
|
)
|
|
assert resp.status_code == 200, app_server.logs_tail()
|
|
tools = resp.json()
|
|
assert isinstance(tools, list)
|
|
assert len(tools) > 0, "tool list should not be empty"
|
|
|
|
names = {t.get("name") for t in tools}
|
|
assert (
|
|
"get_current_time" in names
|
|
), f"get_current_time not in tool list: {names}"
|
|
|
|
tool = next(t for t in tools if t["name"] == "get_current_time")
|
|
assert tool.get("enabled") is True
|
|
|
|
|
|
# ------------------------------------------------------------------ #
|
|
# C2: tool toggle disable / enable
|
|
# ------------------------------------------------------------------ #
|
|
|
|
|
|
@pytest.mark.integration
|
|
@pytest.mark.p1
|
|
def test_tool_toggle_disable_enable(app_server) -> None:
|
|
"""Test purpose:
|
|
- Verify PATCH /tools/{name}/toggle toggles the tool's
|
|
enabled state and the change is reflected in GET /tools.
|
|
|
|
Test flow:
|
|
1. PATCH toggle get_current_time → should return toggled state.
|
|
2. GET /tools → verify new enabled state.
|
|
3. PATCH toggle again to restore original state.
|
|
4. GET /tools → verify restored.
|
|
|
|
API endpoints:
|
|
- PATCH /api/agents/{agentId}/tools/{tool_name}/toggle
|
|
- GET /api/agents/{agentId}/tools
|
|
"""
|
|
get_before = app_server.api_request(
|
|
"GET",
|
|
scoped("default", "/tools"),
|
|
timeout=_TOOL_HTTP_TIMEOUT,
|
|
)
|
|
assert get_before.status_code == 200
|
|
tools = get_before.json()
|
|
tool = next(t for t in tools if t["name"] == "get_current_time")
|
|
original_enabled = tool["enabled"]
|
|
|
|
try:
|
|
toggle_resp = app_server.api_request(
|
|
"PATCH",
|
|
scoped("default", "/tools/get_current_time/toggle"),
|
|
timeout=_TOOL_HTTP_TIMEOUT,
|
|
)
|
|
assert toggle_resp.status_code == 200
|
|
toggled = toggle_resp.json()
|
|
assert toggled.get("enabled") is (not original_enabled)
|
|
|
|
get_after = app_server.api_request(
|
|
"GET",
|
|
scoped("default", "/tools"),
|
|
timeout=_TOOL_HTTP_TIMEOUT,
|
|
)
|
|
assert get_after.status_code == 200
|
|
after_tool = next(
|
|
t for t in get_after.json() if t["name"] == "get_current_time"
|
|
)
|
|
assert after_tool["enabled"] is (not original_enabled)
|
|
finally:
|
|
app_server.api_request(
|
|
"PATCH",
|
|
scoped("default", "/tools/get_current_time/toggle"),
|
|
timeout=_TOOL_HTTP_TIMEOUT,
|
|
)
|
|
|
|
|
|
# ------------------------------------------------------------------ #
|
|
# C3: agent-scoped tool list matches global
|
|
# ------------------------------------------------------------------ #
|
|
|
|
|
|
@pytest.mark.integration
|
|
@pytest.mark.p2
|
|
def test_tool_list_agent_scoped_matches_global(
|
|
app_server,
|
|
) -> None:
|
|
"""Test purpose:
|
|
- Verify agent-scoped GET /tools and header GET /tools return
|
|
the same set of tool names for the default agent.
|
|
|
|
Test flow:
|
|
1. GET /api/agents/default/tools (scoped).
|
|
2. GET /api/tools with X-Agent-Id: default (header).
|
|
3. Assert both return the same tool name set.
|
|
|
|
API endpoints:
|
|
- GET /api/agents/{agentId}/tools
|
|
- GET /api/tools
|
|
"""
|
|
scoped_resp = app_server.api_request(
|
|
"GET",
|
|
scoped("default", "/tools"),
|
|
timeout=_TOOL_HTTP_TIMEOUT,
|
|
)
|
|
assert scoped_resp.status_code == 200
|
|
|
|
header_resp = app_server.api_request(
|
|
"GET",
|
|
"/api/tools",
|
|
headers={"X-Agent-Id": "default"},
|
|
timeout=_TOOL_HTTP_TIMEOUT,
|
|
)
|
|
assert header_resp.status_code == 200
|
|
|
|
scoped_names = {t["name"] for t in scoped_resp.json()}
|
|
header_names = {t["name"] for t in header_resp.json()}
|
|
assert scoped_names == header_names
|
|
|
|
|
|
# ------------------------------------------------------------------ #
|
|
# C4: tool config get returns dict
|
|
# ------------------------------------------------------------------ #
|
|
|
|
|
|
@pytest.mark.integration
|
|
@pytest.mark.p2
|
|
def test_tool_config_get_returns_dict(app_server) -> None:
|
|
"""Test purpose:
|
|
- Verify GET /tools/{name}/config returns a valid dict.
|
|
|
|
Test flow:
|
|
1. GET /api/agents/default/tools/get_current_time/config.
|
|
2. Assert 200 + response is dict.
|
|
|
|
API endpoints:
|
|
- GET /api/agents/{agentId}/tools/{tool_name}/config
|
|
"""
|
|
resp = app_server.api_request(
|
|
"GET",
|
|
scoped("default", "/tools/get_current_time/config"),
|
|
timeout=_TOOL_HTTP_TIMEOUT,
|
|
)
|
|
assert resp.status_code == 200, app_server.logs_tail()
|
|
config = resp.json()
|
|
assert isinstance(config, dict)
|