@@ -87,6 +87,17 @@ def _reorder_tool_results(msgs: list) -> list:
8787 result_msg_ids : set [int ] = set ()
8888 for msg in msgs :
8989 if isinstance (msg .content , list ):
90+ # Keep a message that carries its own tool_call in place (e.g. an
91+ # AgentScope 2.0 self-paired assistant msg
92+ # [text, tool_call, tool_result]); only standalone tool_result
93+ # messages are movable. Skipping a self-carrying msg here would
94+ # drop it, since its own tool_call can never re-insert it.
95+ has_own_call = any (
96+ _is_tool_call (block ) and _block_attr (block , "id" )
97+ for block in msg .content
98+ )
99+ if has_own_call :
100+ continue
90101 for block in msg .content :
91102 if _is_tool_result (block ) and _block_attr (block , "id" ):
92103 results_by_id .setdefault (
@@ -131,17 +142,25 @@ def _remove_unpaired_tool_messages(msgs: list) -> list:
131142
132143 i = 0
133144 while i < len (msgs ):
134- use_ids , _ = extract_tool_ids (msgs [i ])
145+ use_ids , own_results = extract_tool_ids (msgs [i ])
135146 if not use_ids :
136147 i += 1
137148 continue
138- required = set (use_ids )
149+ # A self-paired message satisfies (some of) its own tool_calls with the
150+ # tool_results in the same message; only the remainder must be covered
151+ # by following messages.
152+ required = set (use_ids ) - own_results
139153 j = i + 1
140154 result_indices : list [int ] = []
141155 while j < len (msgs ) and required :
142- _ , r = extract_tool_ids (msgs [j ])
156+ uj , r = extract_tool_ids (msgs [j ])
143157 if not r :
144158 break
159+ # A following message that also carries tool_calls (e.g. another
160+ # self-paired turn) is not a result-provider for this one; stop
161+ # rather than consuming it.
162+ if uj :
163+ break
145164 required -= r
146165 result_indices .append (j )
147166 j += 1
@@ -160,8 +179,10 @@ def _remove_unpaired_tool_messages(msgs: list) -> list:
160179 for idx , msg in enumerate (msgs ):
161180 if idx in to_remove :
162181 continue
163- _ , r = extract_tool_ids (msg )
164- if r and not r .issubset (surviving_use_ids ):
182+ u , r = extract_tool_ids (msg )
183+ # A tool_result is paired if some surviving tool_call uses its id --
184+ # including a tool_call in the same (self-paired) message.
185+ if r and not r .issubset (surviving_use_ids | u ):
165186 to_remove .add (idx )
166187
167188 return [msg for idx , msg in enumerate (msgs ) if idx not in to_remove ]
0 commit comments