@@ -1596,12 +1596,12 @@ async def test_reset_appends_injected_tool_calls_result_after_user(
15961596 },
15971597 }
15981598 ]
1599- ),
1599+ ). mark_as_temp () ,
16001600 tool_calls_result = [
16011601 ToolCallMessageSegment (
16021602 tool_call_id = "fake_1" ,
16031603 content = "memory json" ,
1604- )
1604+ ). mark_as_temp ()
16051605 ],
16061606 ),
16071607 )
@@ -1619,6 +1619,122 @@ async def test_reset_appends_injected_tool_calls_result_after_user(
16191619 assert roles == ["user" , "assistant" , "user" , "assistant" , "tool" ]
16201620 assert runner .run_context .messages [- 2 ].tool_calls [0 ].id == "fake_1"
16211621 assert runner .run_context .messages [- 1 ].tool_call_id == "fake_1"
1622+ # _no_save 标记经 reset() 追加后保留,持久化时才会被过滤。
1623+ assert runner .run_context .messages [- 2 ]._no_save is True
1624+ assert runner .run_context .messages [- 1 ]._no_save is True
1625+
1626+
1627+ @pytest .mark .asyncio
1628+ async def test_reset_appends_multiple_injected_tool_calls_results_in_order (
1629+ runner , mock_provider , mock_tool_executor , mock_hooks
1630+ ):
1631+ """list 形式的多个 ToolCallsResult 按列表顺序追加在 user 消息之后。"""
1632+ request = ProviderRequest (
1633+ prompt = "当前问题" ,
1634+ contexts = [
1635+ {"role" : "user" , "content" : "历史消息" },
1636+ {"role" : "assistant" , "content" : "历史回答" },
1637+ ],
1638+ tool_calls_result = [
1639+ ToolCallsResult (
1640+ tool_calls_info = AssistantMessageSegment (
1641+ tool_calls = [
1642+ {
1643+ "id" : "fake_1" ,
1644+ "type" : "function" ,
1645+ "function" : {
1646+ "name" : "recall_long_term_memory" ,
1647+ "arguments" : "{}" ,
1648+ },
1649+ }
1650+ ]
1651+ ),
1652+ tool_calls_result = [
1653+ ToolCallMessageSegment (
1654+ tool_call_id = "fake_1" ,
1655+ content = "memory json 1" ,
1656+ )
1657+ ],
1658+ ),
1659+ ToolCallsResult (
1660+ tool_calls_info = AssistantMessageSegment (
1661+ tool_calls = [
1662+ {
1663+ "id" : "fake_2" ,
1664+ "type" : "function" ,
1665+ "function" : {
1666+ "name" : "recall_short_term_memory" ,
1667+ "arguments" : "{}" ,
1668+ },
1669+ }
1670+ ]
1671+ ),
1672+ tool_calls_result = [
1673+ ToolCallMessageSegment (
1674+ tool_call_id = "fake_2" ,
1675+ content = "memory json 2" ,
1676+ )
1677+ ],
1678+ ),
1679+ ],
1680+ )
1681+
1682+ await runner .reset (
1683+ provider = mock_provider ,
1684+ request = request ,
1685+ run_context = ContextWrapper (context = None ),
1686+ tool_executor = mock_tool_executor ,
1687+ agent_hooks = mock_hooks ,
1688+ streaming = False ,
1689+ )
1690+
1691+ roles = [m .role for m in runner .run_context .messages ]
1692+ assert roles == [
1693+ "user" ,
1694+ "assistant" ,
1695+ "user" ,
1696+ "assistant" ,
1697+ "tool" ,
1698+ "assistant" ,
1699+ "tool" ,
1700+ ]
1701+ tool_calls = [
1702+ m .tool_calls [0 ].id
1703+ for m in runner .run_context .messages
1704+ if m .role == "assistant" and m .tool_calls
1705+ ]
1706+ assert tool_calls == ["fake_1" , "fake_2" ]
1707+ tool_results = [
1708+ m .tool_call_id for m in runner .run_context .messages if m .role == "tool"
1709+ ]
1710+ assert tool_results == ["fake_1" , "fake_2" ]
1711+
1712+
1713+ def test_injected_tool_calls_result_partial_temp_mark_raises ():
1714+ """只标记对中一方时抛 ValueError,防止悬空 assistant(tool_calls) 落库。"""
1715+ partial = ToolCallsResult (
1716+ tool_calls_info = AssistantMessageSegment (
1717+ tool_calls = [
1718+ {
1719+ "id" : "fake_1" ,
1720+ "type" : "function" ,
1721+ "function" : {
1722+ "name" : "recall" ,
1723+ "arguments" : "{}" ,
1724+ },
1725+ }
1726+ ]
1727+ ).mark_as_temp (),
1728+ tool_calls_result = [
1729+ ToolCallMessageSegment (
1730+ tool_call_id = "fake_1" ,
1731+ content = "memory json" ,
1732+ )
1733+ ],
1734+ )
1735+
1736+ with pytest .raises (ValueError , match = "marked temp together" ):
1737+ partial .to_openai_messages_model ()
16221738
16231739
16241740@pytest .mark .asyncio
@@ -1631,8 +1747,6 @@ async def test_runner_with_openai_provider_preserves_injected_tool_calls_order(
16311747 payload 组装路径(真实 provider,仅对 SDK create 的入口 _query 打桩捕获)。
16321748 顺序:history → 当前 user → assistant(tool_calls) → tool(result)。
16331749 """
1634- from astrbot .core .agent .tool import FunctionTool , ToolSet
1635- from astrbot .core .provider .entities import ToolCallsResult
16361750 from astrbot .core .provider .sources .openai_source import ProviderOpenAIOfficial
16371751
16381752 provider = ProviderOpenAIOfficial (
0 commit comments