diff --git a/astrbot/core/agent/runners/tool_loop_agent_runner.py b/astrbot/core/agent/runners/tool_loop_agent_runner.py index f8418fe4205..5867d7e59cb 100644 --- a/astrbot/core/agent/runners/tool_loop_agent_runner.py +++ b/astrbot/core/agent/runners/tool_loop_agent_runner.py @@ -301,10 +301,8 @@ async def reset( self.tool_schema_mode = tool_schema_mode self._tool_schema_param_set = None self._skill_like_raw_tool_set = None - if tool_schema_mode == "skills_like": - tool_set = self.req.func_tool - if not tool_set: - return + tool_set = self.req.func_tool + if tool_schema_mode == "skills_like" and tool_set: self._skill_like_raw_tool_set = tool_set light_set = tool_set.get_light_tool_set() self._tool_schema_param_set = tool_set.get_param_only_tool_set() diff --git a/tests/test_tool_loop_agent_runner.py b/tests/test_tool_loop_agent_runner.py index ef8e818bb5c..c90c55897fd 100644 --- a/tests/test_tool_loop_agent_runner.py +++ b/tests/test_tool_loop_agent_runner.py @@ -667,6 +667,42 @@ async def test_normal_completion_without_max_step( assert runner.req.func_tool is not None, "正常完成时工具不应该被禁用" +@pytest.mark.asyncio +async def test_skills_like_mode_without_tools_still_initializes_run( + runner, mock_provider, mock_tool_executor, mock_hooks, monkeypatch +): + """skills_like mode with no tools must still build messages and stats.""" + clock = {"now": 1000.0} + monkeypatch.setattr( + "astrbot.core.agent.runners.tool_loop_agent_runner.time", + SimpleNamespace(time=lambda: clock["now"]), + ) + request = ProviderRequest( + prompt="hello", system_prompt="sys", func_tool=None, contexts=[] + ) + + await runner.reset( + provider=mock_provider, + request=request, + run_context=ContextWrapper(context=None), + tool_executor=mock_tool_executor, + agent_hooks=mock_hooks, + streaming=False, + tool_schema_mode="skills_like", + ) + + assert [m.role for m in runner.run_context.messages] == ["system", "user"] + assert [m.content for m in runner.run_context.messages] == ["sys", "hello"] + assert runner.stats.start_time == 1000.0 + + clock["now"] = 1005.0 + async for _ in runner.step_until_done(3): + pass + + assert runner.done() + assert runner.stats.end_time == 1005.0 + + @pytest.mark.asyncio @pytest.mark.parametrize("streaming", [False, True]) async def test_stats_separate_latest_context_from_cumulative_usage(