e4dcfc49aa
Tests / Import Check (Python 3.13) (push) Has been cancelled
Tests / Import Check (Python 3.14) (push) Has been cancelled
Tests / Python Tests (Python 3.11) (push) Has been cancelled
Tests / Python Tests (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.14) (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled
Tests / Lint and Format (push) Has been cancelled
Tests / Web Node Tests (push) Has been cancelled
Tests / Import Check (Python 3.11) (push) Has been cancelled
Tests / Import Check (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.13) (push) Has been cancelled
110 lines
4.3 KiB
Python
110 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from deeptutor.api.routers import settings as settings_router
|
|
from deeptutor.api.routers import tools as tools_router
|
|
from deeptutor.tools.builtin import (
|
|
BUILTIN_TOOL_NAMES,
|
|
COMING_SOON_TOOL_NAMES,
|
|
USER_TOGGLEABLE_TOOL_NAMES,
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_builtin_tools_marks_toggleable_set(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path
|
|
) -> None:
|
|
"""The /api/v1/tools response must clearly separate user-toggleable
|
|
tools from locked-on (auto-mounted) tools so the /settings/tools UI
|
|
can render the right control per row."""
|
|
settings_file = tmp_path / "interface.json"
|
|
monkeypatch.setattr(settings_router, "_settings_file", lambda: settings_file)
|
|
|
|
response = await tools_router.list_builtin_tools()
|
|
by_name = {tool.name: tool for tool in response.tools}
|
|
|
|
# Every registered tool + every coming-soon placeholder shows up.
|
|
assert set(by_name) == set(BUILTIN_TOOL_NAMES) | set(COMING_SOON_TOOL_NAMES)
|
|
|
|
# Coming-soon entries are NOT toggleable and report enabled=False so
|
|
# the UI can lock the toggle and badge them appropriately.
|
|
for name in COMING_SOON_TOOL_NAMES:
|
|
assert by_name[name].coming_soon is True, name
|
|
assert by_name[name].toggleable is False, name
|
|
assert by_name[name].enabled is False, name
|
|
|
|
# Exactly the documented set is toggleable. Pinning the literal here
|
|
# (in addition to the constant) is intentional — this list is the
|
|
# product contract for the /settings/tools "体验增强" section.
|
|
toggleable_names = {name for name, tool in by_name.items() if tool.toggleable}
|
|
assert toggleable_names == set(USER_TOGGLEABLE_TOOL_NAMES)
|
|
assert toggleable_names == {
|
|
"brainstorm",
|
|
"web_search",
|
|
"paper_search",
|
|
"reason",
|
|
"geogebra_analysis",
|
|
"imagegen",
|
|
"videogen",
|
|
}
|
|
|
|
# Locked-on (non-toggleable, non-coming-soon) tools always report
|
|
# enabled=True.
|
|
for name, tool in by_name.items():
|
|
if not tool.toggleable and not tool.coming_soon:
|
|
assert tool.enabled is True, name
|
|
|
|
# On a fresh settings file the default toggleable set is "all on".
|
|
assert set(response.enabled_optional_tools) == set(USER_TOGGLEABLE_TOOL_NAMES)
|
|
for name in USER_TOGGLEABLE_TOOL_NAMES:
|
|
assert by_name[name].enabled is True
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_builtin_tools_marks_capability_owned_tools(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path
|
|
) -> None:
|
|
"""Capability-owned tools (solve_*, mastery_*) report their owning
|
|
capability so the /settings/tools UI groups them below the built-ins;
|
|
plain system built-ins report ``capability=None``."""
|
|
settings_file = tmp_path / "interface.json"
|
|
monkeypatch.setattr(settings_router, "_settings_file", lambda: settings_file)
|
|
|
|
response = await tools_router.list_builtin_tools()
|
|
by_name = {tool.name: tool for tool in response.tools}
|
|
|
|
assert by_name["solve_plan"].capability == "solve"
|
|
assert by_name["mastery_status"].capability == "mastery"
|
|
assert by_name["web_fetch"].capability is None
|
|
# Capability tools stay locked-on (not user-toggleable).
|
|
assert by_name["solve_plan"].toggleable is False
|
|
assert by_name["solve_plan"].enabled is True
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_list_builtin_tools_reflects_user_toggle(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path
|
|
) -> None:
|
|
settings_file = tmp_path / "interface.json"
|
|
monkeypatch.setattr(settings_router, "_settings_file", lambda: settings_file)
|
|
|
|
# User disables a subset of toggleable tools.
|
|
await settings_router.update_enabled_tools(
|
|
settings_router.EnabledToolsUpdate(enabled_tools=["web_search", "reason"])
|
|
)
|
|
|
|
response = await tools_router.list_builtin_tools()
|
|
by_name = {tool.name: tool for tool in response.tools}
|
|
|
|
assert response.enabled_optional_tools == ["reason", "web_search"]
|
|
assert by_name["web_search"].enabled is True
|
|
assert by_name["reason"].enabled is True
|
|
assert by_name["brainstorm"].enabled is False
|
|
assert by_name["paper_search"].enabled is False
|
|
# Locked-on tools stay on regardless (code_execution is now auto-mounted,
|
|
# gated by sandbox availability rather than a user toggle).
|
|
assert by_name["code_execution"].enabled is True
|
|
assert by_name["rag"].enabled is True
|
|
assert by_name["web_fetch"].enabled is True
|