初始化提交
This commit is contained in:
commit
887c1f449e
963 files changed
+166869
No files matched your search
@@ -0,0 +1,203 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from app.application.agent import (
|
||||
compose_system_messages,
|
||||
next_step_for_tool,
|
||||
step_event_payload,
|
||||
task_from_deliberative_plan,
|
||||
task_plan_payload,
|
||||
)
|
||||
from app.application.agent.skill_loader import load_skill_manifests
|
||||
from app.modules.agent import (
|
||||
AgentDefinition,
|
||||
AgentTask,
|
||||
ExecutionPolicy,
|
||||
Plan,
|
||||
PlanStep,
|
||||
ToolPolicy,
|
||||
)
|
||||
from app.modules.planner import DeliberativePlan
|
||||
from app.modules.planner import PlanStep as DeliberativePlanStep
|
||||
from app.modules.skills import parse_skill_manifest
|
||||
|
||||
|
||||
def test_agent_definition_keeps_minimal_execution_and_tool_policy() -> None:
|
||||
agent = AgentDefinition(
|
||||
name="工师",
|
||||
system_prompt="完成已授权的工程任务。",
|
||||
skill_refs=("代码审查",),
|
||||
tool_policy=ToolPolicy(("read_file", "shell")),
|
||||
execution_policy=ExecutionPolicy(max_iterations=3),
|
||||
)
|
||||
|
||||
assert agent.skill_refs == ("代码审查",)
|
||||
assert agent.tool_policy.allowed_tools == ("read_file", "shell")
|
||||
assert agent.execution_policy.max_iterations == 3
|
||||
|
||||
|
||||
def test_agent_task_keeps_plan_as_runtime_only_contract() -> None:
|
||||
task = AgentTask(
|
||||
id="task_1",
|
||||
objective="审查当前变更",
|
||||
agent_name="工师",
|
||||
plan=Plan(
|
||||
steps=(PlanStep(id="step_1", title="读取变更", tool="read_file"),),
|
||||
status="approved",
|
||||
),
|
||||
)
|
||||
|
||||
assert task.status == "queued"
|
||||
assert task.plan is not None
|
||||
assert task.plan.steps[0].status == "pending"
|
||||
|
||||
|
||||
def test_deliberative_plan_becomes_traceable_agent_task() -> None:
|
||||
task = task_from_deliberative_plan(
|
||||
DeliberativePlan(
|
||||
title="调研计划",
|
||||
steps=[
|
||||
DeliberativePlanStep(
|
||||
id=1,
|
||||
title="检索资料",
|
||||
description="读取相关资料",
|
||||
tool="fetch_url",
|
||||
risk_level="L2",
|
||||
)
|
||||
],
|
||||
assumptions=["资料可访问"],
|
||||
risks=["来源不完整"],
|
||||
),
|
||||
run_id="run_1",
|
||||
agent_name="学士",
|
||||
objective="调研主题",
|
||||
)
|
||||
|
||||
assert task.status == "running"
|
||||
assert task.plan is not None
|
||||
assert task.plan.steps[0].id == "1"
|
||||
assert task_plan_payload(task)["steps"] == [
|
||||
{
|
||||
"id": "1",
|
||||
"title": "检索资料",
|
||||
"description": "读取相关资料",
|
||||
"tool": "fetch_url",
|
||||
"risk_level": "L2",
|
||||
"status": "pending",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def test_tool_maps_only_to_its_next_uncompleted_plan_step() -> None:
|
||||
task = AgentTask(
|
||||
id="task_1",
|
||||
objective="执行计划",
|
||||
agent_name="工师",
|
||||
plan=Plan(
|
||||
steps=(
|
||||
PlanStep(id="1", title="读取", tool="read_file"),
|
||||
PlanStep(id="2", title="再次读取", tool="read_file"),
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
first = next_step_for_tool(task, "read_file", set())
|
||||
second = next_step_for_tool(task, "read_file", {"1"})
|
||||
|
||||
assert first is not None and first.id == "1"
|
||||
assert second is not None and second.id == "2"
|
||||
assert next_step_for_tool(task, "shell", set()) is None
|
||||
assert step_event_payload(task, first, status="completed", result_summary="读取成功") == {
|
||||
"task_id": "task_1",
|
||||
"step_id": "1",
|
||||
"title": "读取",
|
||||
"tool": "read_file",
|
||||
"risk_level": "L2",
|
||||
"status": "completed",
|
||||
"result_summary": "读取成功",
|
||||
}
|
||||
|
||||
|
||||
def test_execution_policy_rejects_invalid_iteration_limit() -> None:
|
||||
with pytest.raises(ValueError, match="max_iterations"):
|
||||
ExecutionPolicy(max_iterations=0)
|
||||
|
||||
|
||||
def test_manifest_and_prompt_composer_keep_stable_order() -> None:
|
||||
skill = SimpleNamespace(
|
||||
name="代码审查",
|
||||
description="审查变更",
|
||||
trigger="审查, review",
|
||||
prompt_fragment="先理解调用路径,再报告问题。",
|
||||
risk_level="L1",
|
||||
status="enabled",
|
||||
tool_bindings_json='["read_file"]',
|
||||
)
|
||||
manifest = parse_skill_manifest(skill, ["read_file"])
|
||||
|
||||
messages = compose_system_messages(
|
||||
["全局约束"],
|
||||
AgentDefinition(name="工师", system_prompt="只执行已授权任务。"),
|
||||
[manifest],
|
||||
)
|
||||
|
||||
assert manifest.triggers == ("审查", "review")
|
||||
assert messages == [
|
||||
"全局约束",
|
||||
"【Agent:工师】\n只执行已授权任务。",
|
||||
"【代码审查·能力注入】\n先理解调用路径,再报告问题。",
|
||||
]
|
||||
|
||||
|
||||
def test_default_tools_filters_explicit_allowlist() -> None:
|
||||
from app.application.agent.tools import default_tools
|
||||
|
||||
tools = default_tools(allowed_tools=("read_file",))
|
||||
|
||||
assert [tool["function"]["name"] for tool in tools] == ["read_file"]
|
||||
|
||||
|
||||
async def test_skill_loader_unions_matches_with_explicit_references(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
skills = [
|
||||
SimpleNamespace(
|
||||
name="代码审查",
|
||||
description="审查",
|
||||
trigger="审查",
|
||||
prompt_fragment="审查流程",
|
||||
risk_level="L1",
|
||||
status="enabled",
|
||||
tool_bindings_json='["read_file"]',
|
||||
),
|
||||
SimpleNamespace(
|
||||
name="网页研究",
|
||||
description="研究",
|
||||
trigger="研究",
|
||||
prompt_fragment="研究流程",
|
||||
risk_level="L2",
|
||||
status="enabled",
|
||||
tool_bindings_json='["web_search"]',
|
||||
),
|
||||
]
|
||||
|
||||
async def fake_match_active_skills(_context: str):
|
||||
return [skills[0]]
|
||||
|
||||
async def fake_get_enabled_skills_by_names(names: tuple[str, ...]):
|
||||
return [skill for skill in skills if skill.name in names]
|
||||
|
||||
monkeypatch.setattr(
|
||||
"app.application.agent.skill_loader.match_active_skills",
|
||||
fake_match_active_skills,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.application.agent.skill_loader.get_enabled_skills_by_names",
|
||||
fake_get_enabled_skills_by_names,
|
||||
)
|
||||
|
||||
manifests = await load_skill_manifests("请审查", skill_refs=("网页研究",))
|
||||
|
||||
assert [manifest.name for manifest in manifests] == ["代码审查", "网页研究"]
|
||||
assert manifests[0].allowed_tools == ("read_file",)
|
||||
Reference in new issue
Block a user