feat: Enhance tool mapping and output rendering with animations (#4481)

* Enhance tool block mapping by using unique tool keys with name and run_id

* Enhance tool output rendering with Markdown and JSON formatting in ContentDisplay component

* Add animations for block title and content separators in ContentBlockDisplay component

* Allow 'size' prop to accept string values and update styling in BorderTrail component

* Adjust BorderTrail animation size and duration based on expansion state

* fix both borders trailing at the same time

* [autofix.ci] apply automated fixes

* fix text sizing

* fix spacing issues

* Adjust header title and text styling in ContentBlockDisplay and DurationDisplay components

* Refactor header title in ContentBlockDisplay component

* [autofix.ci] apply automated fixes

* Convert `test_handle_on_tool_start` to an async function and update tool content key logic

* Handle logger without 'opt' method in code parsing error handling

* Update test duration values in .test_durations file

---------

Co-authored-by: anovazzi1 <otavio2204@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Gabriel Luiz Freitas Almeida 2024-11-11 13:32:08 -03:00 • committed by GitHub
commit 06b7450652
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 882 additions and 702 deletions

View file

@ -105,6 +105,7 @@ def handle_on_tool_start(
tool_name = event["name"]
tool_input = event["data"].get("input")
run_id = event.get("run_id", "")
tool_key = f"{tool_name}_{run_id}"
# Create content blocks if they don't exist
if not agent_message.content_blocks:
@ -122,11 +123,11 @@ def handle_on_tool_start(
)
# Store in map and append to message
tool_blocks_map[run_id] = tool_content
tool_blocks_map[tool_key] = tool_content
agent_message.content_blocks[0].contents.append(tool_content)
agent_message = send_message_method(message=agent_message)
tool_blocks_map[run_id] = agent_message.content_blocks[0].contents[-1]
tool_blocks_map[tool_key] = agent_message.content_blocks[0].contents[-1]
return agent_message, start_time
@ -138,7 +139,9 @@ def handle_on_tool_end(
start_time: float,
) -> tuple[Message, float]:
run_id = event.get("run_id", "")
tool_content = tool_blocks_map.get(run_id)
tool_name = event.get("name", "")
tool_key = f"{tool_name}_{run_id}"
tool_content = tool_blocks_map.get(tool_key)
if tool_content and isinstance(tool_content, ToolContent):
tool_content.output = event["data"].get("output")
@ -159,7 +162,9 @@ def handle_on_tool_error(
start_time: float,
) -> tuple[Message, float]:
run_id = event.get("run_id", "")
tool_content = tool_blocks_map.get(run_id)
tool_name = event.get("name", "")
tool_key = f"{tool_name}_{run_id}"
tool_content = tool_blocks_map.get(tool_key)
if tool_content and isinstance(tool_content, ToolContent):
tool_content.error = event["data"].get("error", "Unknown error")

View file

@ -29,7 +29,10 @@ def validate_code(code):
try:
tree = ast.parse(code)
except Exception as e: # noqa: BLE001
logger.opt(exception=True).debug("Error parsing code")
if hasattr(logger, "opt"):
logger.opt(exception=True).debug("Error parsing code")
else:
logger.debug("Error parsing code")
errors["function"]["errors"].append(str(e))
return errors

File diff suppressed because it is too large Load diff

View file

@ -392,7 +392,7 @@ async def test_handle_on_chain_end_with_empty_return_values():
assert isinstance(start_time, float)
def test_handle_on_tool_start():
async def test_handle_on_tool_start():
"""Test handle_on_tool_start event."""
send_message = MagicMock(side_effect=lambda message: message)
tool_blocks_map = {}
@ -414,8 +414,9 @@ def test_handle_on_tool_start():
assert len(updated_message.content_blocks) == 1
assert len(updated_message.content_blocks[0].contents) > 0
tool_key = f"{event['name']}_{event['run_id']}"
tool_content = updated_message.content_blocks[0].contents[-1]
assert tool_content == tool_blocks_map.get("test_run")
assert tool_content == tool_blocks_map.get(tool_key)
assert isinstance(tool_content, ToolContent)
assert tool_content.name == "test_tool"
assert tool_content.tool_input == {"query": "tool input"}
@ -452,6 +453,7 @@ async def test_handle_on_tool_end():
updated_message, start_time = handle_on_tool_end(end_event, agent_message, tool_blocks_map, send_message, 0.0)
f"{end_event['name']}_{end_event['run_id']}"
tool_content = updated_message.content_blocks[0].contents[-1]
assert tool_content.name == "test_tool"
assert tool_content.output == "tool output"