feat(tasks): add skill-templated task graph execution

This commit is contained in:
2026-06-23 10:22:58 +08:00
parent 6843d89b2c
commit 53b13e8eac
53 changed files with 4773 additions and 756 deletions

View File

@ -158,7 +158,7 @@ def test_router_receives_thinking_mode() -> None:
provider = RouterProvider('{"action":"simple_chat","reason":"simple"}')
decision = asyncio.run(
MainAgentRouter().classify(
"你好",
"请判断一下这个概念是否合理",
provider=provider,
thinking_enabled=False,
)
@ -168,11 +168,84 @@ def test_router_receives_thinking_mode() -> None:
assert provider.calls[0]["thinking_enabled"] is False
def test_router_fast_paths_obvious_simple_chat_without_provider_call() -> None:
provider = RouterProvider('{"action":"new_task","reason":"should not be used"}')
decision = asyncio.run(MainAgentRouter().classify("你好", provider=provider))
punctuated = asyncio.run(MainAgentRouter().classify("你好!", provider=provider))
translation = asyncio.run(MainAgentRouter().classify("翻译这句话hello world", provider=provider))
assert not decision.is_task
assert decision.action == "simple_chat"
assert decision.reason == "obvious_simple_chat"
assert not punctuated.is_task
assert punctuated.action == "simple_chat"
assert not translation.is_task
assert translation.action == "simple_chat"
assert provider.calls == []
def test_router_sends_broad_explanations_to_intent_llm() -> None:
provider = RouterProvider('{"action":"simple_chat","reason":"intent decided concept explanation"}')
explanation = asyncio.run(MainAgentRouter().classify("解释一下什么是 MCP", provider=provider))
definition = asyncio.run(MainAgentRouter().classify("什么是 context engineering", provider=provider))
assert not explanation.is_task
assert explanation.reason == "intent decided concept explanation"
assert not definition.is_task
assert definition.reason == "intent decided concept explanation"
assert len(provider.calls) == 2
def test_router_fast_paths_obvious_task_without_provider_call() -> None:
provider = RouterProvider('{"action":"simple_chat","reason":"should not be used"}')
decision = asyncio.run(MainAgentRouter().classify("帮我查一下今天深圳天气", provider=provider))
current_event = asyncio.run(
MainAgentRouter().classify("解释一下今天法国队在世界杯的表现为什么那么好", provider=provider)
)
assert decision.is_task
assert decision.action == "create_task"
assert decision.reason == "obvious_task"
assert current_event.is_task
assert current_event.action == "create_task"
assert provider.calls == []
def test_router_does_not_simple_fast_path_current_event_explanations() -> None:
provider = RouterProvider('{"action":"simple_chat","reason":"llm fallback"}')
decision = asyncio.run(MainAgentRouter().classify("解释一下昨晚法国队在世界杯的表现为什么那么好", provider=provider))
assert decision.is_task
assert decision.action == "create_task"
assert decision.reason == "obvious_task"
assert provider.calls == []
def test_router_keeps_active_task_followups_in_llm_path() -> None:
provider = RouterProvider('{"action":"revise_task","reason":"needs revision","short_title":"任务连续性"}')
decision = asyncio.run(
MainAgentRouter().classify(
"这个也加上",
active_task=_task(),
provider=provider,
)
)
assert decision.is_task
assert decision.action == "revise_task"
assert len(provider.calls) == 1
def test_router_injects_intent_skill_guidance() -> None:
provider = RouterProvider('{"action":"new_task","reason":"needs weather tool","short_title":"珠海天气"}')
decision = asyncio.run(
MainAgentRouter().classify(
"帮我查一下今天珠海天气",
"帮我判断这个需求要不要进入任务模式",
provider=provider,
intent_skill="Weather and current external data must be routed to new_task.",
)
@ -247,7 +320,7 @@ def test_router_retries_once_after_provider_failure() -> None:
decision = asyncio.run(
MainAgentRouter().classify(
"帮我看看昨天的中美会面都谈了什么?",
"帮我判断这次中美会面分析需求要不要进入任务模式",
provider=provider,
)
)
@ -262,7 +335,7 @@ def test_router_fallback_after_two_provider_failures() -> None:
decision = asyncio.run(
MainAgentRouter().classify(
"帮我看看昨天的中美会面都谈了什么?",
"帮我判断这次中美会面分析需求要不要进入任务模式",
provider=provider,
)
)