Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions lib/roast/cogs/agent/providers/pi/messages/tool_call_message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,30 @@ def format_read
details ? "#{label} (#{details})" : label
end

# Formats a write tool call.
#
# Input fields:
# :path (String) – file to write [required]
# :content (String) – file contents [required]
#
# Output: 'WRITE <path> "<preview>" (+<n> <line|lines>)' – <preview> is
# the first line of :content (stripped, truncated to TRUNCATE_LIMIT
# chars) and <n> is the number of lines written. The count is always
# shown.
#
# Examples:
# WRITE lib/roast.rb "class Roast" (+10 lines)
# WRITE config/app.yml "enabled: true" (+1 line)
#
#: () -> String
def format_write
path, content = arguments.values_at(:path, :content)
lines = content.to_s.lines
preview = truncate(lines.first.to_s.strip)
count = lines.length
"WRITE #{path} \"#{preview}\" (+#{count} #{"line".pluralize(count)})"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

format_write has no bare-name fallback and interpolates path untruncated — unlike every sibling. format_bash/format_ls/format_read degrade to "BASH"/"LS"/"READ" when the key is absent and run path through truncate. This line renders unconditionally, so no-args produces WRITE "" (+0 lines) (double space, empty quotes), and a long path blows the one-line goal since it isn't truncated. Suggest guarding the bare case and wrapping path in truncate to match the others.

end

# Formats a tool call for which Roast has no dedicated formatter.
#
# Output: "<NAME> <key>: <value>, ..." – the upcased tool name, then each
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,22 @@ def format_read
ok_line("#{count} #{"line".pluralize(count)}")
end

# Formats a write tool result.
#
# Input: :path – the path that was written, from the originating call.
#
# Output: "WRITE OK <path>" – the file path, omitted when the call
# had none.
#
# Examples:
# WRITE OK lib/roast/version.rb
# WRITE OK
#
#: () -> String
def format_write
ok_line(@input[:path])
end

# Formats a result for which Roast has no dedicated formatter.
#
# Content: the tool's output text.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,33 @@ class ToolCallMessageTest < ActiveSupport::TestCase
assert_equal "READ lib/roast.rb (from line 30)", msg.format
end

test "format renders WRITE with the path, preview, and line count" do
msg = ToolCallMessage.new(
id: "1",
name: "write",
arguments: { path: "lib/roast.rb", content: "line one\nline two\nline three" },
)
assert_equal 'WRITE lib/roast.rb "line one" (+3 lines)', msg.format
end

test "format renders a singular line count for single-line write content" do
msg = ToolCallMessage.new(
id: "1",
name: "write",
arguments: { path: "config/app.yml", content: "enabled: true" },
)
assert_equal 'WRITE config/app.yml "enabled: true" (+1 line)', msg.format
end

test "format truncates a long write preview" do
msg = ToolCallMessage.new(
id: "1",
name: "write",
arguments: { path: "lib/roast.rb", content: "x" * 100 },
)
assert_equal "WRITE lib/roast.rb \"#{"x" * (ToolCallMessage::TRUNCATE_LIMIT - 3)}...\" (+1 line)", msg.format
end

test "format renders an unhandled tool as NAME key: value, ..." do
msg = ToolCallMessage.new(
id: "1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,31 @@ def setup
assert_equal "READ OK 0 lines", msg.format(@context)
end

test "format renders WRITE OK with the path from the originating call" do
@context.add_tool_call(
ToolCallMessage.new(id: "1", name: "write", arguments: { path: "lib/roast/version.rb" }),
)
msg = ToolResultMessage.new(
tool_call_id: "1",
tool_name: "write",
content: "File written successfully",
is_error: false,
)

assert_equal "WRITE OK lib/roast/version.rb", msg.format(@context)
end

test "format renders a bare WRITE OK when the path is unavailable" do
msg = ToolResultMessage.new(
tool_call_id: "1",
tool_name: "write",
content: "File written successfully",
is_error: false,
)

assert_equal "WRITE OK", msg.format(@context)
end

test "format renders NAME ERROR with the message for an error result" do
msg = ToolResultMessage.new(
tool_call_id: "1",
Expand Down
Loading