Class: RobotLab::Web::Event
- Inherits:
-
Struct
- Object
- Struct
- RobotLab::Web::Event
- Defined in:
- lib/robot_lab/web/event.rb
Overview
Frontend-neutral, immutable value object for a single step in a robot run.
One Event model backs both the persisted transcript and the live SSE stream — serialize with #to_h, rebuild with .from_h. Role validation is kept strict so a bad role fails fast rather than rendering blank.
Roles:
:user — text the human sent
:delta — one streamed token/content delta (content is the text fragment)
:robot — the robot's final reply (content is the full final text)
:tool_call — a tool invocation (content: { name:, args: })
:tool_result — a tool's return (content: { name:, result:/error: })
:error — the run raised (content: { class:, message: })
Constant Summary collapse
- ROLES =
rubocop:disable Lint/ConstantDefinitionInBlock
%i[user delta robot tool_call tool_result error].freeze
Instance Attribute Summary collapse
-
#content ⇒ Object
Returns the value of attribute content.
-
#event_id ⇒ Object
Returns the value of attribute event_id.
-
#robot_name ⇒ Object
Returns the value of attribute robot_name.
-
#role ⇒ Object
Returns the value of attribute role.
-
#timestamp ⇒ Object
Returns the value of attribute timestamp.
Class Method Summary collapse
Instance Method Summary collapse
- #error? ⇒ Boolean
- #error_message ⇒ Object
-
#initialize(role:, content:, robot_name: nil, timestamp: nil, event_id: nil) ⇒ Event
constructor
A new instance of Event.
-
#text ⇒ Object
The display text for this event, whatever its role.
-
#to_h ⇒ Object
--- Serialization (round-trips through JSON for SSE + storage) ---.
-
#tool_name ⇒ Object
--- Convenience readers so callers never reach into the content hash ---.
Constructor Details
#initialize(role:, content:, robot_name: nil, timestamp: nil, event_id: nil) ⇒ Event
Returns a new instance of Event.
25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/robot_lab/web/event.rb', line 25 def initialize(role:, content:, robot_name: nil, timestamp: nil, event_id: nil) role = role.to_sym raise ArgumentError, "invalid role: #{role.inspect} (expected one of #{ROLES.inspect})" unless ROLES.include?(role) super( role: role, content: deep_freeze(content), robot_name: robot_name, timestamp: || Time.now.utc, event_id: event_id || SecureRandom.uuid ) freeze end |
Instance Attribute Details
#content ⇒ Object
Returns the value of attribute content
22 23 24 |
# File 'lib/robot_lab/web/event.rb', line 22 def content @content end |
#event_id ⇒ Object
Returns the value of attribute event_id
22 23 24 |
# File 'lib/robot_lab/web/event.rb', line 22 def event_id @event_id end |
#robot_name ⇒ Object
Returns the value of attribute robot_name
22 23 24 |
# File 'lib/robot_lab/web/event.rb', line 22 def robot_name @robot_name end |
#role ⇒ Object
Returns the value of attribute role
22 23 24 |
# File 'lib/robot_lab/web/event.rb', line 22 def role @role end |
#timestamp ⇒ Object
Returns the value of attribute timestamp
22 23 24 |
# File 'lib/robot_lab/web/event.rb', line 22 def @timestamp end |
Class Method Details
.from_h(hash) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/robot_lab/web/event.rb', line 74 def self.from_h(hash) fetch = ->(key) { hash.key?(key) ? hash[key] : hash[key.to_s] } ts = fetch.call(:timestamp) new( role: fetch.call(:role)&.to_sym, content: fetch.call(:content), robot_name: fetch.call(:robot_name), timestamp: ts ? Time.iso8601(ts) : Time.now.utc, event_id: fetch.call(:event_id) ) rescue ArgumentError nil end |
Instance Method Details
#error? ⇒ Boolean
45 46 47 |
# File 'lib/robot_lab/web/event.rb', line 45 def error? role == :error end |
#error_message ⇒ Object
49 50 51 52 53 |
# File 'lib/robot_lab/web/event.rb', line 49 def return nil unless error? content.is_a?(Hash) ? (content[:message] || content['message']) : content.to_s end |
#text ⇒ Object
The display text for this event, whatever its role.
56 57 58 59 60 |
# File 'lib/robot_lab/web/event.rb', line 56 def text return content unless content.is_a?(Hash) content[:result] || content[:message] || content[:args] || content end |
#to_h ⇒ Object
--- Serialization (round-trips through JSON for SSE + storage) ---
64 65 66 67 68 69 70 71 72 |
# File 'lib/robot_lab/web/event.rb', line 64 def to_h { role: role, content: content, robot_name: robot_name, timestamp: .iso8601(3), event_id: event_id } end |
#tool_name ⇒ Object
--- Convenience readers so callers never reach into the content hash ---
41 42 43 |
# File 'lib/robot_lab/web/event.rb', line 41 def tool_name content.is_a?(Hash) ? (content[:name] || content['name']) : nil end |