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
30 changes: 30 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 @@ -97,6 +97,36 @@ 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> the number of lines written. The content summary is appended only
# when :content is present; a missing path renders the bare "WRITE".
#
# Examples:
# WRITE lib/roast.rb "class Roast" (+10 lines)
# WRITE config/app.yml "enabled: true" (+1 line)
# WRITE lib/roast.rb
# WRITE
#
#: () -> String
def format_write
path, content = arguments.values_at(:path, :content)
path = path.to_s
label = path.empty? ? "WRITE" : "WRITE #{path}"
return label if content.nil?

lines = content.to_s.lines
preview = truncate(lines.first.to_s.strip)
count = lines.length
"#{label} \"#{preview}\" (+#{count} #{"line".pluralize(count)})"
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 @@ -96,6 +96,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 @@ -61,6 +61,43 @@ class ToolCallMessageTest < ActiveSupport::TestCase
assert_equal "READ lib/roast.rb", 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 WRITE with the path alone when content is absent" do
msg = ToolCallMessage.new(id: "1", name: "write", arguments: { path: "lib/roast.rb" })
assert_equal "WRITE lib/roast.rb", msg.format
end

test "format renders a bare WRITE when the path is missing" do
msg = ToolCallMessage.new(id: "1", name: "write", arguments: {})
assert_equal "WRITE", 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