ducklm/tests/test_contracts.py

68 lines
1.9 KiB
Python

import asyncio
from app.core.async_router import AsyncRouter
from app.core.contracts import CriticScore, ExecutionDirective, PlanStep, UserTask
class _FakeAdapter:
def __init__(self, responses: list[str]) -> None:
self._responses = responses
async def generate(self, prompt: str, max_tokens: int | None = None) -> str:
return self._responses.pop(0)
def test_user_task_defaults() -> None:
task = UserTask(input="hello")
assert task.task_id
assert task.session_id
def test_plan_step_supports_dependencies() -> None:
step = PlanStep(
id="step-1",
kind="tool",
tool="shell_exec",
description="run command",
depends_on=[],
)
assert step.tool == "shell_exec"
def test_critic_score_bounds() -> None:
score = CriticScore(
correctness=1.0,
usefulness=0.5,
safety=0.0,
memory_store=False,
weight=0.2,
explanation="ok",
)
assert score.weight == 0.2
def test_execution_directive_defaults() -> None:
directive = ExecutionDirective(type="noop")
assert directive.payload == {}
assert directive.confidence == 0.0
def test_router_compiles_tool_plan_even_when_classifier_says_conversation() -> None:
router = AsyncRouter(
thinker=_FakeAdapter([
"conversation",
"ПЛАН:\nШаг 1: [shell_exec] выполнить `uptime`",
]),
json_compiler=_FakeAdapter([
'{"type":"plan","payload":{"steps":[{"id":"1","tool":"shell_exec","args":{"command":"uptime"},"depends_on":[]}]}}'
]),
)
directive = asyncio.run(
router.decide(
state={},
context={"task_summary": "Проверь аптайм ПК", "task_context": {}},
)
)
assert directive.type == "plan"
assert directive.payload["steps"][0]["tool"] == "shell_exec"