Class: Omakase::Trace

Inherits:
Object
  • Object
show all
Defined in:
lib/omakase/trace.rb

Overview

The listener, printed for a human: Omakase.listener = Omakase::Trace.new. A run reads top to bottom — the call, the code the model wrote, the answer. Colour when the stream is a terminal, plain when it is a log.

Constant Summary collapse

COLOURS =
{generation: 36, ruby: 33, answer: 32, error: 31, mcp: 31}.freeze
LIMIT =
800

Instance Method Summary collapse

Constructor Details

#initialize(io: $stderr) ⇒ Trace

Returns a new instance of Trace.



11
12
13
14
# File 'lib/omakase/trace.rb', line 11

def initialize(io: $stderr)
  @io = io
  @colour = io.respond_to?(:tty?) && io.tty?
end

Instance Method Details

#call(event, agent:, **payload) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/omakase/trace.rb', line 16

def call(event, agent:, **payload)
  head, body = case event
  when :generation then ["→ #{agent.class}##{payload[:name]}", inputs(payload[:inputs])]
  when :ruby then ["· ruby", "#{payload[:code].strip}\n#{outcome(payload[:outcome])}"]
  when :answer then ["← #{agent.class}##{payload[:name]}", truncate(payload[:value].inspect)]
  when :error then ["✗ #{agent.class}##{payload[:name]}", truncate("#{payload[:error].class}: #{payload[:error].message}")]
  # A down sidecar is not an error the run raises, so nothing else would say it.
  when :mcp then ["! #{agent} mcp #{payload[:name]}", truncate(payload[:error].message)]
  else return # a listener that raises takes the run down with it
  end

  # A generation called from generated code sits inside its caller's.
  indent = "    " * [(Thread.current[Agent::RUNNING]&.size || 1) - 1, 0].max
  @io.puts(indent + paint(event, head))
  @io.puts(body.gsub(/^/, "#{indent}    ")) unless body.empty?
end