Class: SwarmCLI::UI::Renderers::EventRenderer

Inherits:
Object
  • Object
show all
Defined in:
lib/swarm_cli/ui/renderers/event_renderer.rb

Overview

High-level event rendering by composing lower-level components Returns formatted strings for each event type

Instance Method Summary collapse

Constructor Details

#initialize(pastel:, agent_badge:, depth_tracker:) ⇒ EventRenderer

Returns a new instance of EventRenderer.



9
10
11
12
13
14
15
16
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 9

def initialize(pastel:, agent_badge:, depth_tracker:)
  @pastel = pastel
  @agent_badge = agent_badge
  @depth_tracker = depth_tracker
  @usage_stats = Components::UsageStats.new(pastel: pastel)
  @content_block = Components::ContentBlock.new(pastel: pastel)
  @panel = Components::Panel.new(pastel: pastel)
end

Instance Method Details

#agent_completed(agent:) ⇒ Object

Render agent completion ✓ architect completed



41
42
43
44
45
46
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 41

def agent_completed(agent:)
  indent = @depth_tracker.indent(agent)
  agent_name = @agent_badge.render(agent)

  "#{indent}#{@pastel.green("#{UI::Icons::SUCCESS} #{agent_name} completed")}"
end

#agent_response(agent:, timestamp:) ⇒ Object

Render agent response event [12:34:56] 💬 architect responded:



31
32
33
34
35
36
37
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 31

def agent_response(agent:, timestamp:)
  indent = @depth_tracker.indent(agent)
  time = Formatters::Time.timestamp(timestamp)
  agent_name = @agent_badge.render(agent, icon: UI::Icons::RESPONSE)

  "#{indent}#{@pastel.dim(time)} #{agent_name} responded:"
end

#agent_thinking(agent:, model:, timestamp:) ⇒ Object

Render agent thinking event [12:34:56] 💭 architect (gpt-5-mini)



20
21
22
23
24
25
26
27
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 20

def agent_thinking(agent:, model:, timestamp:)
  indent = @depth_tracker.indent(agent)
  time = Formatters::Time.timestamp(timestamp)
  agent_name = @agent_badge.render(agent, icon: UI::Icons::THINKING)
  model_info = @pastel.dim("(#{model})")

  "#{indent}#{@pastel.dim(time)} #{agent_name} #{model_info}"
end

#delegates_to(agents, indent: 0, color_cache:) ⇒ Object

Render delegation list Can delegate to: frontend_dev, backend_dev



144
145
146
147
148
149
150
151
152
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 144

def delegates_to(agents, indent: 0, color_cache:)
  return "" if agents.nil? || agents.empty?

  prefix = "  " * indent
  agent_badge = Components::AgentBadge.new(pastel: @pastel, color_cache: color_cache)
  delegates_list = agent_badge.render_list(agents)

  "#{prefix}  #{@pastel.dim("Can delegate to:")} #{delegates_list}"
end

#delegation(from:, to:, timestamp:) ⇒ Object

Render delegation event [12:34:56] architect 📨 delegates to worker



70
71
72
73
74
75
76
77
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 70

def delegation(from:, to:, timestamp:)
  indent = @depth_tracker.indent(from)
  time = Formatters::Time.timestamp(timestamp)
  from_name = @agent_badge.render(from)
  to_name = @agent_badge.render(to)

  "#{indent}#{@pastel.dim(time)} #{from_name} #{@pastel.yellow("#{UI::Icons::DELEGATE} delegates to")} #{to_name}"
end

#delegation_result(from:, to:, timestamp:) ⇒ Object

Render delegation result [12:34:56] 📥 Delegation result from worker → architect



81
82
83
84
85
86
87
88
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 81

def delegation_result(from:, to:, timestamp:)
  indent = @depth_tracker.indent(to)
  time = Formatters::Time.timestamp(timestamp)
  from_name = @agent_badge.render(from)
  to_name = @agent_badge.render(to)

  "#{indent}#{@pastel.dim(time)} #{@pastel.green("#{UI::Icons::RESULT} Delegation result")} from #{from_name} #{@pastel.dim("")} #{to_name}"
end

#hook_executed(hook_event:, agent:, timestamp:, success:, blocked:) ⇒ Object

Render hook execution [12:34:56] 🪝 Hook executed PreToolUse architect



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 92

def hook_executed(hook_event:, agent:, timestamp:, success:, blocked:)
  indent = @depth_tracker.indent(agent)
  time = Formatters::Time.timestamp(timestamp)
  hook_display = @pastel.cyan(hook_event)
  agent_name = @agent_badge.render(agent)

  status = if blocked
    @pastel.red("BLOCKED")
  elsif success
    @pastel.green("executed")
  else
    @pastel.yellow("warning")
  end

  color = if blocked
    :red
  else
    (success ? :green : :yellow)
  end
  icon_colored = @pastel.public_send(color, UI::Icons::HOOK)

  "#{indent}#{@pastel.dim(time)} #{icon_colored} Hook #{status} #{hook_display} #{agent_name}"
end

#thinking_text(content, indent: 0) ⇒ Object

Render thinking text (italic, indented)



155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 155

def thinking_text(content, indent: 0)
  return "" if content.nil? || content.empty?

  # Strip system reminders
  text = Formatters::Text.strip_system_reminders(content)
  return "" if text.empty?

  prefix = "  " * indent

  text.split("\n").map do |line|
    "#{prefix}  #{@pastel.italic(line)}"
  end.join("\n")
end

#tool_arguments(args, indent: 0, truncate: false) ⇒ Object

Render tool arguments



170
171
172
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 170

def tool_arguments(args, indent: 0, truncate: false)
  @content_block.render_hash(args, indent: indent, label: "Arguments", truncate: truncate)
end

#tool_call(agent:, tool:, timestamp:) ⇒ Object

Render tool call event [12:34:56] architect 🔧 uses tool Read



50
51
52
53
54
55
56
57
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 50

def tool_call(agent:, tool:, timestamp:)
  indent = @depth_tracker.indent(agent)
  time = Formatters::Time.timestamp(timestamp)
  agent_name = @agent_badge.render(agent)
  tool_name = @pastel.bold.blue(tool)

  "#{indent}#{@pastel.dim(time)} #{agent_name} #{@pastel.blue("#{UI::Icons::TOOL} uses tool")} #{tool_name}"
end

#tool_result(agent:, timestamp:, tool: nil) ⇒ Object

Render tool result received [12:34:56] 📥 Tool result received by architect



61
62
63
64
65
66
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 61

def tool_result(agent:, timestamp:, tool: nil)
  indent = @depth_tracker.indent(agent)
  time = Formatters::Time.timestamp(timestamp)

  "#{indent}#{@pastel.dim(time)} #{@pastel.green("#{UI::Icons::RESULT} Tool result")} received by #{agent}"
end

#tool_result_content(content, indent: 0, truncate: false) ⇒ Object

Render tool result content



175
176
177
178
179
180
181
182
183
184
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 175

def tool_result_content(content, indent: 0, truncate: false)
  @content_block.render_text(
    content,
    indent: indent,
    color: :bright_green,
    truncate: truncate,
    max_lines: 2,
    max_chars: 300,
  )
end

#tools_available(tools, indent: 0) ⇒ Object

Render tool list Tools available: Read, Write, Bash



133
134
135
136
137
138
139
140
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 133

def tools_available(tools, indent: 0)
  return "" if tools.nil? || tools.empty?

  prefix = "  " * indent
  tools_list = tools.join(", ")

  "#{prefix}  #{@pastel.dim("Tools available: #{tools_list}")}"
end

#usage_stats(tokens:, cost:, context_pct: nil, remaining: nil, cumulative: nil, indent: 0) ⇒ Object

Render usage stats line 5,922 tokens │ $0.0016 │ 1.5% used, 394,078 remaining



118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/swarm_cli/ui/renderers/event_renderer.rb', line 118

def usage_stats(tokens:, cost:, context_pct: nil, remaining: nil, cumulative: nil, indent: 0)
  prefix = "  " * indent
  stats = @usage_stats.render(
    tokens: tokens,
    cost: cost,
    context_pct: context_pct,
    remaining: remaining,
    cumulative: cumulative,
  )

  "#{prefix}  #{stats}"
end