Skip to content
Draft
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
92 changes: 74 additions & 18 deletions lib/roast/cogs/agent/providers/pi/messages/tool_call_message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,80 @@ def initialize(id:, name:, arguments:)
def format
return unless name

case name.to_s.downcase
when "bash"
"BASH #{arguments[:command]}"
when "read"
"READ #{arguments[:path]}"
when "edit"
"EDIT #{arguments[:path]}"
when "write"
"WRITE #{arguments[:path]}"
when "grep"
"GREP #{arguments[:pattern]} #{arguments[:path]}"
when "find"
"FIND #{arguments[:pattern]} #{arguments[:path]}"
when "ls"
"LS #{arguments[:path]}"
else
"TOOL [#{name}] #{arguments.inspect}"
end
format_method_name = "format_#{name.to_s.downcase}".to_sym
return send(format_method_name) if respond_to?(format_method_name, true)

format_unknown
end

TRUNCATE_LIMIT = 45

private

#: () -> String
def format_bash
command = truncate(arguments[:command])
command.empty? ? "BASH" : "BASH #{command}"
end

#: () -> String
def format_read
path = arguments[:path]
path.to_s.empty? ? "READ" : "READ #{path}"
end

#: () -> 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
line_label = count == 1 ? "line" : "lines"
"WRITE #{path} \"#{preview}\" (+#{count} #{line_label})"
end

#: () -> String
def format_edit
path = arguments[:path]
edits = arguments[:edits] || []
count = edits.length
edit_label = count == 1 ? "edit" : "edits"
"EDIT #{path} (#{count} #{edit_label})"
end

#: () -> String
def format_grep
pattern, path, glob = arguments.values_at(:pattern, :path, :glob)
base = "GREP \"#{truncate(pattern)}\""
base = "#{base} #{path}" if path.present?
glob.present? ? "#{base} (glob=#{glob})" : base
end

#: () -> String
def format_find
pattern, path = arguments.values_at(:pattern, :path)
path.present? ? "FIND #{pattern} (in #{path})" : "FIND #{pattern}"
end

#: () -> String
def format_ls
path = arguments[:path]
path.to_s.empty? ? "LS" : "LS #{path}"
end

#: () -> String
def format_unknown
label = name.to_s.upcase
return label if arguments.empty?

details = arguments.map { |key, value| "#{key}: #{truncate(value.inspect)}" }.join(", ")
"#{label} #{details}"
end

#: (String?) -> String
def truncate(str)
s = str.to_s
s.length > TRUNCATE_LIMIT ? "#{s[0...TRUNCATE_LIMIT - 3]}..." : s
end
end
end
Expand Down
97 changes: 84 additions & 13 deletions lib/roast/cogs/agent/providers/pi/messages/tool_result_message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,94 @@ def initialize(tool_call_id:, tool_name:, content:, is_error:)
@tool_name = tool_name
@content = content
@is_error = is_error
@name = (tool_name || "unknown").to_s #: String
@input = {} #: Hash[Symbol, untyped]
end

#: (PiInvocation::Context) -> String?
def format(context)
tool_call = context.tool_call(tool_call_id)
name = tool_name || tool_call&.name || "unknown"
status = is_error ? "ERROR" : "OK"

# Truncate long tool results for progress display
c = content
display_content = if c && c.length > 200
"#{c[0..197]}..."
else
c
end

"#{name.upcase} #{status}#{display_content ? " #{display_content}" : ""}"
call = context.tool_call(tool_call_id)
@name = (tool_name || call&.name || "unknown").to_s
@input = call&.arguments || {}

return error_line if is_error

format_method_name = "format_#{@name.downcase}".to_sym
return send(format_method_name) if respond_to?(format_method_name, true)

format_unknown
end

TRUNCATE_LIMIT = 45

private

#: () -> String
def format_bash
lines = content.to_s.lines
count = lines.length
ok_line("#{count} #{"line".pluralize(count)}")
end

#: () -> String
def format_read
count = content.to_s.lines.length
ok_line("#{count} #{"line".pluralize(count)}")
end

#: () -> String
def format_write
ok_line(@input[:path])
end

#: () -> String
def format_edit
ok_line(@input[:path])
end

#: () -> String
def format_grep
lines = content.to_s.lines.map(&:strip).reject(&:empty?)
matches, notes = lines.partition { |line| line.match?(%r{\A\S+/}) || line.match?(/\A(?:\S+:)?\d+:/) }
count = matches.length
note = "NOTE #{truncate(notes.join(" "))}" if matches.any? && notes.any?
ok_line("#{count} #{"match".pluralize(count)}", note)
end

#: () -> String
def format_find
count = content.to_s.lines.map(&:strip).reject(&:empty?).length
ok_line("#{count} #{"path".pluralize(count)}")
end

#: () -> String
def format_ls
count = content.to_s.lines.map(&:strip).reject(&:empty?).length
ok_line("#{count} #{"entry".pluralize(count)}")
end

#: () -> String
def format_unknown
preview = truncate(content.to_s.lines.first.to_s.strip)
ok_line(preview)
end

#: (*String?) -> String
def ok_line(*parts)
summary = parts.select(&:present?).join(" · ")
prefix = "#{@name.upcase} OK"
summary.present? ? "#{prefix} #{summary}" : prefix
end

#: () -> String
def error_line
"#{@name.upcase} ERROR #{content.to_s.strip}".strip
end

#: (String?) -> String
def truncate(str)
s = str.to_s
s.length > TRUNCATE_LIMIT ? "#{s[0...TRUNCATE_LIMIT - 3]}..." : s
end
end
end
Expand Down
Loading