From 399c9c97b1f6d8ea652912a5767bf6ce833d6a3b Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Thu, 12 Feb 2026 15:44:01 +0800 Subject: [PATCH] Add tool call log --- engine/core/duplex_pipeline.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/engine/core/duplex_pipeline.py b/engine/core/duplex_pipeline.py index b836436..e877d7a 100644 --- a/engine/core/duplex_pipeline.py +++ b/engine/core/duplex_pipeline.py @@ -938,6 +938,15 @@ class DuplexPipeline: return "server" async def _emit_tool_result(self, result: Dict[str, Any], source: str) -> None: + tool_name = str(result.get("name") or "unknown_tool") + call_id = str(result.get("tool_call_id") or result.get("id") or "") + status = result.get("status") if isinstance(result.get("status"), dict) else {} + status_code = int(status.get("code") or 0) if status else 0 + status_message = str(status.get("message") or "") if status else "" + logger.info( + f"[Tool] emit result source={source} name={tool_name} call_id={call_id} " + f"status={status_code} {status_message}".strip() + ) await self._send_event( { **ev( @@ -962,7 +971,16 @@ class DuplexPipeline: if not call_id: continue if call_id in self._completed_tool_call_ids: + logger.debug(f"[Tool] ignore duplicate client result call_id={call_id}") continue + status = item.get("status") if isinstance(item.get("status"), dict) else {} + status_code = int(status.get("code") or 0) if status else 0 + status_message = str(status.get("message") or "") if status else "" + tool_name = str(item.get("name") or "unknown_tool") + logger.info( + f"[Tool] received client result name={tool_name} call_id={call_id} " + f"status={status_code} {status_message}".strip() + ) waiter = self._pending_tool_waiters.get(call_id) if waiter and not waiter.done(): @@ -1060,6 +1078,15 @@ class DuplexPipeline: executor = self._tool_executor(tool_call) enriched_tool_call = dict(tool_call) enriched_tool_call["executor"] = executor + tool_name = self._tool_name(enriched_tool_call) or "unknown_tool" + call_id = str(enriched_tool_call.get("id") or "").strip() + fn_payload = enriched_tool_call.get("function") + raw_args = str(fn_payload.get("arguments") or "") if isinstance(fn_payload, dict) else "" + args_preview = raw_args if len(raw_args) <= 160 else f"{raw_args[:160]}..." + logger.info( + f"[Tool] call requested name={tool_name} call_id={call_id} " + f"executor={executor} args={args_preview}" + ) tool_calls.append(enriched_tool_call) await self._send_event( { @@ -1178,6 +1205,8 @@ class DuplexPipeline: if not call_id: continue executor = str(call.get("executor") or "server").strip().lower() + tool_name = self._tool_name(call) or "unknown_tool" + logger.info(f"[Tool] execute start name={tool_name} call_id={call_id} executor={executor}") if executor == "client": result = await self._wait_for_single_tool_result(call_id) await self._emit_tool_result(result, source="client")