refactor(forge): simplify deeply nested error handling in Anthropic provider

- Extract _get_tool_error_message helper method
- Replace 20+ levels of nesting with simple for loop
- Improve readability of tool_result construction
- Update benchmark poetry.lock

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Nicholas Tindle
2026-01-19 00:15:33 -06:00
parent 3040f39136
commit e0784f8f6b
2 changed files with 44 additions and 39 deletions

View File

@@ -3017,4 +3017,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.1"
python-versions = "^3.12"
content-hash = "321c90aac1a6fd822d0e81ddcc6f0a5593c79a8f76546e4b7b4ec15c0020fc78"
content-hash = "8e4331a8bd02635fcebddabf7cdcdc378b3b8f19187b62d8abc179c232c4803e"

View File

@@ -320,51 +320,30 @@ class AnthropicProvider(BaseChatModelProvider[AnthropicModelName, AnthropicSetti
anthropic_messages.append(
_assistant_msg.model_dump(include={"role", "content"}) # type: ignore # noqa
)
# Build tool_result blocks for each tool call
# (required if last assistant message had tool_use blocks)
tool_results = []
for tc in assistant_msg.tool_calls or []:
error_msg = self._get_tool_error_message(tc, tool_call_errors)
tool_results.append(
{
"type": "tool_result",
"tool_use_id": tc.id,
"is_error": True,
"content": [{"type": "text", "text": error_msg}],
}
)
anthropic_messages.append(
{
"role": "user",
"content": [
*(
# tool_result is required if last assistant message
# had tool_use block(s)
{
"type": "tool_result",
"tool_use_id": tc.id,
"is_error": True,
"content": [
{
"type": "text",
"text": (
"Not executed because parsing "
"of your last message failed"
if not tool_call_errors
else (
str(e)
if (
e := next(
(
tce
for tce
in tool_call_errors
if tce.name
== tc.function.name
),
None,
)
)
else "Not executed: "
"validation failed"
)
),
}
],
}
for tc in assistant_msg.tool_calls or []
),
*tool_results,
{
"type": "text",
"text": (
"ERROR PARSING YOUR RESPONSE:\n\n"
f"ERROR PARSING YOUR RESPONSE:\n\n"
f"{e.__class__.__name__}: {e}"
),
},
@@ -537,6 +516,32 @@ class AnthropicProvider(BaseChatModelProvider[AnthropicModelName, AnthropicSetti
)
return response, cost, response.usage.input_tokens, response.usage.output_tokens
def _get_tool_error_message(
self,
tool_call: AssistantToolCall,
tool_call_errors: list,
) -> str:
"""Get the error message for a failed tool call.
Args:
tool_call: The tool call that failed.
tool_call_errors: List of validation errors for tool calls.
Returns:
An appropriate error message for the tool result.
"""
if not tool_call_errors:
return "Not executed because parsing of your last message failed"
# Find matching error for this specific tool call
matching_error = next(
(err for err in tool_call_errors if err.name == tool_call.function.name),
None,
)
if matching_error:
return str(matching_error)
return "Not executed: validation failed"
def _parse_assistant_tool_calls(
self, assistant_message: Message
) -> list[AssistantToolCall]: