Skip to content

Commit 9700109

Browse files
MorabbinCopilot
andcommitted
Distinguish exception-originated failures from deliberate ones
The previous commit broke test_handles_tool_calling_errors because define_tool's exception handler wraps exceptions as ToolResult(failure), which was then sent as a structured result instead of a top-level error. Fix: introduce TOOL_EXCEPTION_TEXT constant shared between define_tool's exception handler and _execute_tool_and_respond. When the failure's textResultForLlm matches the known exception wrapper message, send via the top-level error param (CLI formats as 'Failed to execute...'); otherwise send the full structured result to preserve metadata. This preserves backward compatibility for thrown exceptions while allowing user-returned ToolResult(failure) to carry toolTelemetry. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 5a8206c commit 9700109

2 files changed

Lines changed: 32 additions & 12 deletions

File tree

python/copilot/session.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
SessionEventType,
3939
session_event_from_dict,
4040
)
41-
from .tools import Tool, ToolHandler, ToolInvocation, ToolResult
41+
from .tools import TOOL_EXCEPTION_TEXT, Tool, ToolHandler, ToolInvocation, ToolResult
4242

4343
# Re-export SessionEvent under an alias used internally
4444
SessionEventTypeAlias = SessionEvent
@@ -944,17 +944,33 @@ async def _execute_tool_and_respond(
944944
else:
945945
tool_result = result # type: ignore[assignment]
946946

947-
await self.rpc.tools.handle_pending_tool_call(
948-
SessionToolsHandlePendingToolCallParams(
949-
request_id=request_id,
950-
result=ResultResult(
951-
text_result_for_llm=tool_result.text_result_for_llm,
952-
result_type=tool_result.result_type,
947+
# Exception-originated failures (from define_tool's exception handler) are
948+
# sent via the top-level error param so the CLI formats them with its
949+
# standard "Failed to execute..." message. Deliberate user-returned
950+
# failures send the full structured result to preserve metadata.
951+
if (
952+
tool_result.result_type == "failure"
953+
and tool_result.error
954+
and tool_result.text_result_for_llm == TOOL_EXCEPTION_TEXT
955+
):
956+
await self.rpc.tools.handle_pending_tool_call(
957+
SessionToolsHandlePendingToolCallParams(
958+
request_id=request_id,
953959
error=tool_result.error,
954-
tool_telemetry=tool_result.tool_telemetry,
955-
),
960+
)
961+
)
962+
else:
963+
await self.rpc.tools.handle_pending_tool_call(
964+
SessionToolsHandlePendingToolCallParams(
965+
request_id=request_id,
966+
result=ResultResult(
967+
text_result_for_llm=tool_result.text_result_for_llm,
968+
result_type=tool_result.result_type,
969+
error=tool_result.error,
970+
tool_telemetry=tool_result.tool_telemetry,
971+
),
972+
)
956973
)
957-
)
958974
except Exception as exc:
959975
try:
960976
await self.rpc.tools.handle_pending_tool_call(

python/copilot/tools.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717

1818
ToolResultType = Literal["success", "failure", "rejected", "denied"]
1919

20+
# Constant used by define_tool's exception handler so that
21+
# _execute_tool_and_respond can detect exception-originated failures
22+
# and send them via the top-level error param (matching CLI formatting).
23+
TOOL_EXCEPTION_TEXT = "Invoking this tool produced an error. Detailed information is not available."
24+
2025

2126
@dataclass
2227
class ToolBinaryResult:
@@ -195,8 +200,7 @@ async def wrapped_handler(invocation: ToolInvocation) -> ToolResult:
195200
# Don't expose detailed error information to the LLM for security reasons.
196201
# The actual error is stored in the 'error' field for debugging.
197202
return ToolResult(
198-
text_result_for_llm="Invoking this tool produced an error. "
199-
"Detailed information is not available.",
203+
text_result_for_llm=TOOL_EXCEPTION_TEXT,
200204
result_type="failure",
201205
error=str(exc),
202206
tool_telemetry={},

0 commit comments

Comments
 (0)