From 542e96a096351fd3caaff2d5f671ab0691c16e08 Mon Sep 17 00:00:00 2001 From: Lasmar Khalifa Date: Tue, 30 Jun 2026 17:01:59 -0400 Subject: [PATCH] add bash tool formatters --- .../pi/messages/tool_call_message.rb | 18 ++++++++++ .../pi/messages/tool_result_message.rb | 21 ++++++++++++ .../pi/messages/tool_call_message_test.rb | 15 +++++++++ .../pi/messages/tool_result_message_test.rb | 33 +++++++++++++++++++ 4 files changed, 87 insertions(+) diff --git a/lib/roast/cogs/agent/providers/pi/messages/tool_call_message.rb b/lib/roast/cogs/agent/providers/pi/messages/tool_call_message.rb index 1b188d86..3a60a721 100644 --- a/lib/roast/cogs/agent/providers/pi/messages/tool_call_message.rb +++ b/lib/roast/cogs/agent/providers/pi/messages/tool_call_message.rb @@ -45,6 +45,24 @@ def format private + # Formats a bash tool call. + # + # Input fields: + # :command (String) – shell command to execute [required] + # + # Output: "BASH ", with :command truncated to TRUNCATE_LIMIT + # chars. A missing command renders the bare "BASH". + # + # Examples: + # BASH ls -la + # BASH + # + #: () -> String + def format_bash + command = truncate(arguments[:command]) + command.empty? ? "BASH" : "BASH #{command}" + end + # Formats a tool call for which Roast has no dedicated formatter. # # Output: " : , ..." – the upcased tool name, then each diff --git a/lib/roast/cogs/agent/providers/pi/messages/tool_result_message.rb b/lib/roast/cogs/agent/providers/pi/messages/tool_result_message.rb index bf84b828..55d6b5bc 100644 --- a/lib/roast/cogs/agent/providers/pi/messages/tool_result_message.rb +++ b/lib/roast/cogs/agent/providers/pi/messages/tool_result_message.rb @@ -55,6 +55,27 @@ def format(context) private + # Formats a bash tool result. + # + # Content: the command's output text. + # + # Output: "BASH OK · " – is the line count + # (pluralized) and is the first line, stripped and truncated to + # TRUNCATE_LIMIT chars. The preview is omitted when there is no output. + # + # Examples: + # BASH OK 12 lines · Cloning into 'roast'... + # BASH OK 1 line · hello world + # BASH OK 0 lines + # + #: () -> String + def format_bash + lines = content.to_s.lines + count = lines.length + preview = truncate(lines.first.to_s.strip) + ok_line("#{count} #{"line".pluralize(count)}", preview) + end + # Formats a result for which Roast has no dedicated formatter. # # Content: the tool's output text. diff --git a/test/roast/cogs/agent/providers/pi/messages/tool_call_message_test.rb b/test/roast/cogs/agent/providers/pi/messages/tool_call_message_test.rb index f53d33a8..f429c3aa 100644 --- a/test/roast/cogs/agent/providers/pi/messages/tool_call_message_test.rb +++ b/test/roast/cogs/agent/providers/pi/messages/tool_call_message_test.rb @@ -11,6 +11,21 @@ class ToolCallMessageTest < ActiveSupport::TestCase assert_nil msg.format end + test "format renders BASH with the command" do + msg = ToolCallMessage.new(id: "1", name: "bash", arguments: { command: "ls -la" }) + assert_equal "BASH ls -la", msg.format + end + + test "format renders a bare BASH when the command is missing" do + msg = ToolCallMessage.new(id: "1", name: "bash", arguments: {}) + assert_equal "BASH", msg.format + end + + test "format truncates a long bash command" do + msg = ToolCallMessage.new(id: "1", name: "bash", arguments: { command: "x" * 100 }) + assert_equal "BASH #{"x" * (ToolCallMessage::TRUNCATE_LIMIT - 3)}...", msg.format + end + test "format renders an unhandled tool as NAME key: value, ..." do msg = ToolCallMessage.new( id: "1", diff --git a/test/roast/cogs/agent/providers/pi/messages/tool_result_message_test.rb b/test/roast/cogs/agent/providers/pi/messages/tool_result_message_test.rb index 719e285c..85ad549d 100644 --- a/test/roast/cogs/agent/providers/pi/messages/tool_result_message_test.rb +++ b/test/roast/cogs/agent/providers/pi/messages/tool_result_message_test.rb @@ -10,6 +10,39 @@ def setup @context = Roast::Cogs::Agent::Providers::Pi::PiInvocation::Context.new end + test "format summarizes bash output with a line count and preview" do + msg = ToolResultMessage.new( + tool_call_id: "1", + tool_name: "bash", + content: "file1.rb\nfile2.rb", + is_error: false, + ) + + assert_equal "BASH OK 2 lines · file1.rb", msg.format(@context) + end + + test "format pluralizes a single line of bash output" do + msg = ToolResultMessage.new( + tool_call_id: "1", + tool_name: "bash", + content: "hello world", + is_error: false, + ) + + assert_equal "BASH OK 1 line · hello world", msg.format(@context) + end + + test "format reports zero lines when bash produced no output" do + msg = ToolResultMessage.new( + tool_call_id: "1", + tool_name: "bash", + content: nil, + is_error: false, + ) + + assert_equal "BASH OK 0 lines", msg.format(@context) + end + test "format renders NAME ERROR with the message for an error result" do msg = ToolResultMessage.new( tool_call_id: "1",