@@ -1,25 +0,0 @@
|
||||
from src.maisaka.reasoning_engine import MaisakaReasoningEngine
|
||||
|
||||
|
||||
def test_retry_planner_after_interrupt_only_when_has_new_messages_and_more_rounds() -> None:
|
||||
assert MaisakaReasoningEngine._should_retry_planner_after_interrupt(
|
||||
round_index=0,
|
||||
max_internal_rounds=6,
|
||||
has_pending_messages=True,
|
||||
)
|
||||
|
||||
|
||||
def test_do_not_retry_planner_after_interrupt_without_pending_messages() -> None:
|
||||
assert not MaisakaReasoningEngine._should_retry_planner_after_interrupt(
|
||||
round_index=0,
|
||||
max_internal_rounds=6,
|
||||
has_pending_messages=False,
|
||||
)
|
||||
|
||||
|
||||
def test_do_not_retry_planner_after_interrupt_on_last_round() -> None:
|
||||
assert not MaisakaReasoningEngine._should_retry_planner_after_interrupt(
|
||||
round_index=5,
|
||||
max_internal_rounds=6,
|
||||
has_pending_messages=True,
|
||||
)
|
||||
@@ -1,63 +0,0 @@
|
||||
from src.core.tooling import ToolSpec
|
||||
from src.llm_models.payload_content.message import RoleType
|
||||
from src.maisaka.chat_loop_service import MaisakaChatLoopService
|
||||
from src.maisaka.runtime import MaisakaHeartFlowChatting
|
||||
|
||||
|
||||
def _build_runtime_stub() -> MaisakaHeartFlowChatting:
|
||||
runtime = object.__new__(MaisakaHeartFlowChatting)
|
||||
runtime._current_action_tool_names = set()
|
||||
runtime.deferred_tool_specs_by_name = {}
|
||||
runtime.discovered_tool_names = set()
|
||||
return runtime
|
||||
|
||||
|
||||
def test_deferred_tools_reminder_only_lists_undiscovered_tools() -> None:
|
||||
runtime = _build_runtime_stub()
|
||||
runtime.update_deferred_tool_specs(
|
||||
[
|
||||
ToolSpec(name="plugin_alpha", brief_description="alpha"),
|
||||
ToolSpec(name="plugin_beta", brief_description="beta"),
|
||||
]
|
||||
)
|
||||
runtime.discover_deferred_tools(["plugin_alpha"])
|
||||
|
||||
reminder = runtime.build_deferred_tools_reminder()
|
||||
|
||||
assert "plugin_alpha" not in reminder
|
||||
assert "1. plugin_beta" in reminder
|
||||
assert "<system-reminder>" in reminder
|
||||
assert "tool_search" in reminder
|
||||
|
||||
|
||||
def test_search_and_discover_deferred_tools() -> None:
|
||||
runtime = _build_runtime_stub()
|
||||
runtime.update_deferred_tool_specs(
|
||||
[
|
||||
ToolSpec(name="mcp__slack__send_message", brief_description="向 Slack 发送消息"),
|
||||
ToolSpec(name="mcp__github__create_issue", brief_description="在 GitHub 创建 Issue"),
|
||||
]
|
||||
)
|
||||
|
||||
matched_tool_specs = runtime.search_deferred_tool_specs("slack send", limit=5)
|
||||
newly_discovered_tool_names = runtime.discover_deferred_tools([tool_spec.name for tool_spec in matched_tool_specs])
|
||||
|
||||
assert [tool_spec.name for tool_spec in matched_tool_specs] == ["mcp__slack__send_message"]
|
||||
assert newly_discovered_tool_names == ["mcp__slack__send_message"]
|
||||
assert [tool_spec.name for tool_spec in runtime.get_discovered_deferred_tool_specs()] == [
|
||||
"mcp__slack__send_message"
|
||||
]
|
||||
|
||||
|
||||
def test_build_request_messages_appends_injected_user_message() -> None:
|
||||
chat_loop_service = MaisakaChatLoopService(chat_system_prompt="system prompt")
|
||||
|
||||
messages = chat_loop_service._build_request_messages(
|
||||
[],
|
||||
injected_user_messages=["<system-reminder>\n1. plugin_beta\n</system-reminder>"],
|
||||
)
|
||||
|
||||
assert len(messages) == 2
|
||||
assert messages[0].role == RoleType.System
|
||||
assert messages[1].role == RoleType.User
|
||||
assert messages[1].content == "<system-reminder>\n1. plugin_beta\n</system-reminder>"
|
||||
@@ -1,49 +0,0 @@
|
||||
from datetime import datetime
|
||||
|
||||
from src.common.data_models.message_component_data_model import MessageSequence, TextComponent
|
||||
from src.llm_models.payload_content.tool_option import ToolCall
|
||||
from src.maisaka.chat_loop_service import MaisakaChatLoopService
|
||||
from src.maisaka.context_messages import AssistantMessage, SessionBackedMessage, ToolResultMessage
|
||||
|
||||
|
||||
def _build_user_message(text: str) -> SessionBackedMessage:
|
||||
return SessionBackedMessage(
|
||||
raw_message=MessageSequence([TextComponent(text)]),
|
||||
visible_text=text,
|
||||
timestamp=datetime.now(),
|
||||
)
|
||||
|
||||
|
||||
def test_select_llm_context_messages_drops_orphan_tool_results_anywhere() -> None:
|
||||
assistant_message = AssistantMessage(
|
||||
content="",
|
||||
timestamp=datetime.now(),
|
||||
tool_calls=[ToolCall(call_id="call_1", func_name="wait", args={"seconds": 30})],
|
||||
)
|
||||
orphan_tool_message = ToolResultMessage(
|
||||
content="当前对话循环已暂停,等待新消息到来。",
|
||||
timestamp=datetime.now(),
|
||||
tool_call_id="orphan_call",
|
||||
)
|
||||
matched_tool_message = ToolResultMessage(
|
||||
content="等待 30 秒。",
|
||||
timestamp=datetime.now(),
|
||||
tool_call_id="call_1",
|
||||
tool_name="wait",
|
||||
)
|
||||
chat_history = [
|
||||
_build_user_message("第一条消息"),
|
||||
orphan_tool_message,
|
||||
assistant_message,
|
||||
matched_tool_message,
|
||||
_build_user_message("第二条消息"),
|
||||
]
|
||||
|
||||
selected_history, _ = MaisakaChatLoopService.select_llm_context_messages(
|
||||
chat_history,
|
||||
max_context_size=8,
|
||||
)
|
||||
|
||||
assert orphan_tool_message not in selected_history
|
||||
assert assistant_message in selected_history
|
||||
assert matched_tool_message in selected_history
|
||||
@@ -1,10 +0,0 @@
|
||||
from src.maisaka.reasoning_engine import MaisakaReasoningEngine
|
||||
|
||||
|
||||
def test_continue_action_closes_timing_gate_for_following_rounds() -> None:
|
||||
assert MaisakaReasoningEngine._mark_timing_gate_completed("continue") is False
|
||||
|
||||
|
||||
def test_non_continue_actions_require_next_timing_gate() -> None:
|
||||
assert MaisakaReasoningEngine._mark_timing_gate_completed("wait") is True
|
||||
assert MaisakaReasoningEngine._mark_timing_gate_completed("no_reply") is True
|
||||
@@ -1,21 +0,0 @@
|
||||
from src.maisaka.builtin_tool import get_action_tool_specs, get_timing_tool_specs
|
||||
|
||||
|
||||
def test_wait_tool_available_in_timing_stage() -> None:
|
||||
tool_names = {tool_spec.name for tool_spec in get_timing_tool_specs()}
|
||||
|
||||
assert "wait" in tool_names
|
||||
|
||||
|
||||
def test_wait_tool_not_available_in_action_stage() -> None:
|
||||
tool_names = {tool_spec.name for tool_spec in get_action_tool_specs()}
|
||||
|
||||
assert "wait" not in tool_names
|
||||
assert "finish" in tool_names
|
||||
assert "tool_search" in tool_names
|
||||
|
||||
|
||||
def test_tool_search_not_available_in_timing_stage() -> None:
|
||||
tool_names = {tool_spec.name for tool_spec in get_timing_tool_specs()}
|
||||
|
||||
assert "tool_search" not in tool_names
|
||||
Reference in New Issue
Block a user