@@ -24,15 +24,77 @@ def _should_stop_agent(astr_event) -> bool:
2424 return astr_event .is_stopped () or bool (astr_event .get_extra ("agent_stop_requested" ))
2525
2626
27+ def _truncate_tool_result (text : str , limit : int = 70 ) -> str :
28+ if limit <= 0 :
29+ return ""
30+ if len (text ) <= limit :
31+ return text
32+ if limit <= 3 :
33+ return text [:limit ]
34+ return f"{ text [: limit - 3 ]} ..."
35+
36+
37+ def _extract_chain_json_data (msg_chain : MessageChain ) -> dict | None :
38+ if not msg_chain .chain :
39+ return None
40+ first_comp = msg_chain .chain [0 ]
41+ if isinstance (first_comp , Json ) and isinstance (first_comp .data , dict ):
42+ return first_comp .data
43+ return None
44+
45+
46+ def _record_tool_call_name (
47+ tool_info : dict | None , tool_name_by_call_id : dict [str , str ]
48+ ) -> None :
49+ if not isinstance (tool_info , dict ):
50+ return
51+ tool_call_id = tool_info .get ("id" )
52+ tool_name = tool_info .get ("name" )
53+ if tool_call_id is None or tool_name is None :
54+ return
55+ tool_name_by_call_id [str (tool_call_id )] = str (tool_name )
56+
57+
58+ def _build_tool_call_status_message (tool_info : dict | None ) -> str :
59+ if tool_info :
60+ return f"🔨 调用工具: { tool_info .get ('name' , 'unknown' )} "
61+ return "🔨 调用工具..."
62+
63+
64+ def _build_tool_result_status_message (
65+ msg_chain : MessageChain , tool_name_by_call_id : dict [str , str ]
66+ ) -> str :
67+ tool_name = "unknown"
68+ tool_result = ""
69+
70+ result_data = _extract_chain_json_data (msg_chain )
71+ if result_data :
72+ tool_call_id = result_data .get ("id" )
73+ if tool_call_id is not None :
74+ tool_name = tool_name_by_call_id .pop (str (tool_call_id ), "unknown" )
75+ tool_result = str (result_data .get ("result" , "" ))
76+
77+ if not tool_result :
78+ tool_result = msg_chain .get_plain_text (with_other_comps_mark = True )
79+ tool_result = _truncate_tool_result (tool_result , 70 )
80+
81+ status_msg = f"🔨 调用工具: { tool_name } "
82+ if tool_result :
83+ status_msg = f"{ status_msg } \n 📎 返回结果: { tool_result } "
84+ return status_msg
85+
86+
2787async def run_agent (
2888 agent_runner : AgentRunner ,
2989 max_step : int = 30 ,
3090 show_tool_use : bool = True ,
91+ show_tool_call_result : bool = False ,
3192 stream_to_general : bool = False ,
3293 show_reasoning : bool = False ,
3394) -> AsyncGenerator [MessageChain | None , None ]:
3495 step_idx = 0
3596 astr_event = agent_runner .run_context .context .event
97+ tool_name_by_call_id : dict [str , str ] = {}
3698 while step_idx < max_step + 1 :
3799 step_idx += 1
38100
@@ -90,32 +152,36 @@ async def run_agent(
90152 continue
91153 if astr_event .get_platform_id () == "webchat" :
92154 await astr_event .send (msg_chain )
155+ elif show_tool_use and show_tool_call_result :
156+ status_msg = _build_tool_result_status_message (
157+ msg_chain , tool_name_by_call_id
158+ )
159+ await astr_event .send (
160+ MessageChain (type = "tool_call" ).message (status_msg )
161+ )
93162 # 对于其他情况,暂时先不处理
94163 continue
95164 elif resp .type == "tool_call" :
96165 if agent_runner .streaming :
97166 # 用来标记流式响应需要分节
98167 yield MessageChain (chain = [], type = "break" )
99168
100- tool_info = None
101-
102- if resp .data ["chain" ].chain :
103- json_comp = resp .data ["chain" ].chain [0 ]
104- if isinstance (json_comp , Json ):
105- tool_info = json_comp .data
106- astr_event .trace .record (
107- "agent_tool_call" ,
108- tool_name = tool_info if tool_info else "unknown" ,
109- )
169+ tool_info = _extract_chain_json_data (resp .data ["chain" ])
170+ astr_event .trace .record (
171+ "agent_tool_call" ,
172+ tool_name = tool_info if tool_info else "unknown" ,
173+ )
174+ _record_tool_call_name (tool_info , tool_name_by_call_id )
110175
111176 if astr_event .get_platform_name () == "webchat" :
112177 await astr_event .send (resp .data ["chain" ])
113178 elif show_tool_use :
114- if tool_info :
115- m = f"🔨 调用工具: { tool_info .get ('name' , 'unknown' )} "
116- else :
117- m = "🔨 调用工具..."
118- chain = MessageChain (type = "tool_call" ).message (m )
179+ if show_tool_call_result and isinstance (tool_info , dict ):
180+ # Delay tool status notification until tool_call_result.
181+ continue
182+ chain = MessageChain (type = "tool_call" ).message (
183+ _build_tool_call_status_message (tool_info )
184+ )
119185 await astr_event .send (chain )
120186 continue
121187
@@ -202,6 +268,7 @@ async def run_live_agent(
202268 tts_provider : TTSProvider | None = None ,
203269 max_step : int = 30 ,
204270 show_tool_use : bool = True ,
271+ show_tool_call_result : bool = False ,
205272 show_reasoning : bool = False ,
206273) -> AsyncGenerator [MessageChain | None , None ]:
207274 """Live Mode 的 Agent 运行器,支持流式 TTS
@@ -211,6 +278,7 @@ async def run_live_agent(
211278 tts_provider: TTS Provider 实例
212279 max_step: 最大步数
213280 show_tool_use: 是否显示工具使用
281+ show_tool_call_result: 是否显示工具返回结果
214282 show_reasoning: 是否显示推理过程
215283
216284 Yields:
@@ -222,6 +290,7 @@ async def run_live_agent(
222290 agent_runner ,
223291 max_step = max_step ,
224292 show_tool_use = show_tool_use ,
293+ show_tool_call_result = show_tool_call_result ,
225294 stream_to_general = False ,
226295 show_reasoning = show_reasoning ,
227296 ):
@@ -250,7 +319,12 @@ async def run_live_agent(
250319 # 1. 启动 Agent Feeder 任务:负责运行 Agent 并将文本分句喂给 text_queue
251320 feeder_task = asyncio .create_task (
252321 _run_agent_feeder (
253- agent_runner , text_queue , max_step , show_tool_use , show_reasoning
322+ agent_runner ,
323+ text_queue ,
324+ max_step ,
325+ show_tool_use ,
326+ show_tool_call_result ,
327+ show_reasoning ,
254328 )
255329 )
256330
@@ -336,6 +410,7 @@ async def _run_agent_feeder(
336410 text_queue : asyncio .Queue ,
337411 max_step : int ,
338412 show_tool_use : bool ,
413+ show_tool_call_result : bool ,
339414 show_reasoning : bool ,
340415) -> None :
341416 """运行 Agent 并将文本输出分句放入队列"""
@@ -345,6 +420,7 @@ async def _run_agent_feeder(
345420 agent_runner ,
346421 max_step = max_step ,
347422 show_tool_use = show_tool_use ,
423+ show_tool_call_result = show_tool_call_result ,
348424 stream_to_general = False ,
349425 show_reasoning = show_reasoning ,
350426 ):
0 commit comments