Class: RobotLab::RobotResult

Inherits:
Object
  • Object
show all
Defined in:
lib/robot_lab/robot_result.rb

Overview

Stores the result of a single robot execution

RobotResult captures the LLM output, tool call results, and metadata from running an robot. Results are stored in State for conversation history and can be serialized for persistence.

Examples:

result = RobotResult.new(
  robot_name: "helper",
  output: [TextMessage.new(role: :assistant, content: "Hello!")],
  tool_calls: []
)
result.checksum  # => "a1b2c3d4..."

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(robot_name:, output:, tool_calls: [], created_at: nil, id: nil, prompt: nil, history: nil, raw: nil, stop_reason: nil, input_tokens: 0, output_tokens: 0) ⇒ RobotResult

Creates a new RobotResult instance.

Parameters:

  • robot_name (String)

    the name of the robot

  • output (Array<Message, Hash>)

    the output messages

  • tool_calls (Array<ToolResultMessage, Hash>) (defaults to: [])

    tool call results

  • created_at (Time, nil) (defaults to: nil)

    creation timestamp (defaults to now)

  • id (String, nil) (defaults to: nil)

    unique ID (defaults to UUID)

  • prompt (Array<Message>, nil) (defaults to: nil)

    prompt messages (debug)

  • history (Array<Message>, nil) (defaults to: nil)

    history messages (debug)

  • raw (Object, nil) (defaults to: nil)

    raw LLM response (debug)

  • stop_reason (String, nil) (defaults to: nil)

    reason for stopping

  • input_tokens (Integer) (defaults to: 0)

    input tokens consumed (default 0)

  • output_tokens (Integer) (defaults to: 0)

    output tokens generated (default 0)



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/robot_lab/robot_result.rb', line 63

def initialize(
  robot_name:,
  output:,
  tool_calls: [],
  created_at: nil,
  id: nil,
  prompt: nil,
  history: nil,
  raw: nil,
  stop_reason: nil,
  input_tokens: 0,
  output_tokens: 0
)
  @robot_name = robot_name
  @output = normalize_messages(output)
  @tool_calls = normalize_tool_results(tool_calls)
  @created_at = created_at || Time.now
  @id = id || SecureRandom.uuid
  @prompt = prompt
  @history = history
  @raw = raw
  @stop_reason = stop_reason
  @input_tokens = input_tokens.to_i
  @output_tokens = output_tokens.to_i
end

Instance Attribute Details

#created_atTime (readonly)

Returns when the result was created.

Returns:

  • (Time)

    when the result was created



35
36
# File 'lib/robot_lab/robot_result.rb', line 35

attr_reader :robot_name, :output, :tool_calls, :created_at, :id, :stop_reason,
:input_tokens, :output_tokens

#delegated_byString?

Returns name of the robot that delegated this task.

Returns:

  • (String, nil)

    name of the robot that delegated this task



48
# File 'lib/robot_lab/robot_result.rb', line 48

attr_accessor :duration, :delegated_by, :prompt, :history, :raw

#durationFloat?

Returns elapsed seconds for this run.

Returns:

  • (Float, nil)

    elapsed seconds for this run



48
49
50
# File 'lib/robot_lab/robot_result.rb', line 48

def duration
  @duration
end

#historyArray<Message>?

Returns the history used (debug).

Returns:

  • (Array<Message>, nil)

    the history used (debug)



48
# File 'lib/robot_lab/robot_result.rb', line 48

attr_accessor :duration, :delegated_by, :prompt, :history, :raw

#idString (readonly)

Returns unique identifier for this result.

Returns:

  • (String)

    unique identifier for this result



35
36
# File 'lib/robot_lab/robot_result.rb', line 35

attr_reader :robot_name, :output, :tool_calls, :created_at, :id, :stop_reason,
:input_tokens, :output_tokens

#input_tokensInteger (readonly)

Returns input tokens consumed by this run.

Returns:

  • (Integer)

    input tokens consumed by this run



35
36
# File 'lib/robot_lab/robot_result.rb', line 35

attr_reader :robot_name, :output, :tool_calls, :created_at, :id, :stop_reason,
:input_tokens, :output_tokens

#outputArray<Message> (readonly)

Returns the output messages from the robot.

Returns:

  • (Array<Message>)

    the output messages from the robot



35
36
# File 'lib/robot_lab/robot_result.rb', line 35

attr_reader :robot_name, :output, :tool_calls, :created_at, :id, :stop_reason,
:input_tokens, :output_tokens

#output_tokensObject (readonly)

Returns the value of attribute output_tokens.



35
36
# File 'lib/robot_lab/robot_result.rb', line 35

attr_reader :robot_name, :output, :tool_calls, :created_at, :id, :stop_reason,
:input_tokens, :output_tokens

#promptArray<Message>?

Returns the prompt messages used (debug).

Returns:

  • (Array<Message>, nil)

    the prompt messages used (debug)



48
# File 'lib/robot_lab/robot_result.rb', line 48

attr_accessor :duration, :delegated_by, :prompt, :history, :raw

#rawObject?

Returns the raw LLM response (debug).

Returns:

  • (Object, nil)

    the raw LLM response (debug)



48
# File 'lib/robot_lab/robot_result.rb', line 48

attr_accessor :duration, :delegated_by, :prompt, :history, :raw

#robot_nameString (readonly)

Returns the name of the robot that produced this result.

Returns:

  • (String)

    the name of the robot that produced this result



35
36
37
# File 'lib/robot_lab/robot_result.rb', line 35

def robot_name
  @robot_name
end

#stop_reasonString? (readonly)

Returns reason execution stopped.

Returns:

  • (String, nil)

    reason execution stopped



35
36
# File 'lib/robot_lab/robot_result.rb', line 35

attr_reader :robot_name, :output, :tool_calls, :created_at, :id, :stop_reason,
:input_tokens, :output_tokens

#tool_callsArray<ToolResultMessage> (readonly)

Returns the tool call results.

Returns:



35
36
# File 'lib/robot_lab/robot_result.rb', line 35

attr_reader :robot_name, :output, :tool_calls, :created_at, :id, :stop_reason,
:input_tokens, :output_tokens

Class Method Details

.from_hash(hash) ⇒ RobotResult

Reconstruct result from hash (e.g., from persistence)

Parameters:

  • hash (Hash)

    Serialized result data

Returns:



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/robot_lab/robot_result.rb', line 181

def self.from_hash(hash)
  hash = hash.transform_keys(&:to_sym)

  new(
    robot_name: hash[:robot_name],
    output: (hash[:output] || []).map { |m| Message.from_hash(m) },
    tool_calls: (hash[:tool_calls] || []).map { |m| Message.from_hash(m) },
    created_at: hash[:created_at] ? Time.parse(hash[:created_at].to_s) : nil,
    id: hash[:id],
    prompt: hash[:prompt]&.map { |m| Message.from_hash(m) },
    history: hash[:history]&.map { |m| Message.from_hash(m) },
    raw: hash[:raw],
    stop_reason: hash[:stop_reason],
    input_tokens: hash[:input_tokens] || 0,
    output_tokens: hash[:output_tokens] || 0
  )
end

Instance Method Details

#checksumString

Generate a checksum for deduplication

Uses SHA256 hash of output + tool_calls + timestamp Useful for detecting duplicate results in persistence

Returns:

  • (String)

    Hex digest of the result content



96
97
98
99
100
101
102
103
# File 'lib/robot_lab/robot_result.rb', line 96

def checksum
  content = {
    output: output.map(&:to_h),
    tool_calls: tool_calls.map(&:to_h),
    created_at: created_at.to_i
  }
  Digest::SHA256.hexdigest(content.to_json)
end

#exportHash

Export result for serialization/persistence

Excludes debug fields (prompt, history, raw) by default

Returns:

  • (Hash)

    Serializable result data



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/robot_lab/robot_result.rb', line 111

def export
  {
    robot_name: robot_name,
    delegated_by: delegated_by,
    output: output.map(&:to_h),
    tool_calls: tool_calls.map(&:to_h),
    created_at: created_at.iso8601,
    id: id,
    checksum: checksum,
    stop_reason: stop_reason,
    duration: duration,
    input_tokens: input_tokens.positive? ? input_tokens : nil,
    output_tokens: output_tokens.positive? ? output_tokens : nil
  }.compact
end

#has_tool_calls?Boolean

Check if result contains tool calls

Returns:

  • (Boolean)


163
164
165
# File 'lib/robot_lab/robot_result.rb', line 163

def has_tool_calls?
  output.any?(&:tool_call?) || tool_calls.any?
end

#last_text_contentString? Also known as: reply

Get the last text content from output

Returns:

  • (String, nil)

    The content of the last text message



154
155
156
# File 'lib/robot_lab/robot_result.rb', line 154

def last_text_content
  output.reverse.find(&:text?)&.content
end

#stopped?Boolean

Check if execution stopped naturally (not due to tool call)

Returns:

  • (Boolean)


171
172
173
174
# File 'lib/robot_lab/robot_result.rb', line 171

def stopped?
  last_output = output.last
  last_output&.stopped? || (!has_tool_calls? && last_output&.stop_reason.nil?)
end

#to_hHash

Converts the result to a full hash representation.

Includes debug fields (prompt, history, raw).

Returns:

  • (Hash)

    full result data including debug fields



132
133
134
135
136
137
138
# File 'lib/robot_lab/robot_result.rb', line 132

def to_h
  export.merge(
    prompt: prompt&.map(&:to_h),
    history: history&.map(&:to_h),
    raw: raw
  ).compact
end

#to_json(*args) ⇒ String

Converts the result to JSON.

Uses export format (excludes debug fields).

Parameters:

  • args (Array)

    arguments passed to to_json

Returns:

  • (String)

    JSON representation



146
147
148
# File 'lib/robot_lab/robot_result.rb', line 146

def to_json(*args)
  export.to_json(*args)
end