Class: Rubino::Session::Message
- Inherits:
-
Object
- Object
- Rubino::Session::Message
- Defined in:
- lib/rubino/session/message.rb
Overview
Handles message persistence within a session. Messages include user input, assistant responses, tool calls and results.
Constant Summary collapse
- VALID_ROLES =
%w[system user assistant tool].freeze
Instance Attribute Summary collapse
-
#content ⇒ Object
readonly
Returns the value of attribute content.
-
#created_at ⇒ Object
readonly
Returns the value of attribute created_at.
-
#id ⇒ Object
readonly
Returns the value of attribute id.
-
#metadata ⇒ Object
readonly
Returns the value of attribute metadata.
-
#role ⇒ Object
readonly
Returns the value of attribute role.
-
#session_id ⇒ Object
readonly
Returns the value of attribute session_id.
-
#token_count ⇒ Object
readonly
Returns the value of attribute token_count.
-
#tool_call_id ⇒ Object
readonly
Returns the value of attribute tool_call_id.
-
#tool_name ⇒ Object
readonly
Returns the value of attribute tool_name.
Instance Method Summary collapse
-
#initialize(attrs = {}) ⇒ Message
constructor
A new instance of Message.
-
#to_context ⇒ Object
Returns a hash for LLM context building.
-
#to_row ⇒ Object
Returns a hash suitable for database insertion.
-
#valid? ⇒ Boolean
Validates the message attributes.
Constructor Details
#initialize(attrs = {}) ⇒ Message
Returns a new instance of Message.
16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/rubino/session/message.rb', line 16 def initialize(attrs = {}) @id = attrs[:id] || SecureRandom.uuid @session_id = attrs[:session_id] @role = attrs[:role] @content = attrs[:content] @tool_name = attrs[:tool_name] @tool_call_id = attrs[:tool_call_id] @token_count = attrs[:token_count] || 0 @metadata = attrs[:metadata] || {} @created_at = attrs[:created_at] || Time.now.utc.iso8601 end |
Instance Attribute Details
#content ⇒ Object (readonly)
Returns the value of attribute content.
13 14 15 |
# File 'lib/rubino/session/message.rb', line 13 def content @content end |
#created_at ⇒ Object (readonly)
Returns the value of attribute created_at.
13 14 15 |
# File 'lib/rubino/session/message.rb', line 13 def created_at @created_at end |
#id ⇒ Object (readonly)
Returns the value of attribute id.
13 14 15 |
# File 'lib/rubino/session/message.rb', line 13 def id @id end |
#metadata ⇒ Object (readonly)
Returns the value of attribute metadata.
13 14 15 |
# File 'lib/rubino/session/message.rb', line 13 def @metadata end |
#role ⇒ Object (readonly)
Returns the value of attribute role.
13 14 15 |
# File 'lib/rubino/session/message.rb', line 13 def role @role end |
#session_id ⇒ Object (readonly)
Returns the value of attribute session_id.
13 14 15 |
# File 'lib/rubino/session/message.rb', line 13 def session_id @session_id end |
#token_count ⇒ Object (readonly)
Returns the value of attribute token_count.
13 14 15 |
# File 'lib/rubino/session/message.rb', line 13 def token_count @token_count end |
#tool_call_id ⇒ Object (readonly)
Returns the value of attribute tool_call_id.
13 14 15 |
# File 'lib/rubino/session/message.rb', line 13 def tool_call_id @tool_call_id end |
#tool_name ⇒ Object (readonly)
Returns the value of attribute tool_name.
13 14 15 |
# File 'lib/rubino/session/message.rb', line 13 def tool_name @tool_name end |
Instance Method Details
#to_context ⇒ Object
Returns a hash for LLM context building. A user message that collapsed a large paste keeps the compact “[Pasted text #N …]” placeholder in its stored/displayed content (#213); here we expand each placeholder back to its full body for the model, so the provider sees everything while the transcript echo (live AND on resume) stays clean.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/rubino/session/message.rb', line 61 def to_context msg = { role: @role, content: (@content) } msg[:tool_call_id] = @tool_call_id if @tool_call_id msg[:name] = @tool_name if @tool_name # Surface assistant tool_calls (persisted as metadata) so the adapter # can rebuild the toolUse block expected by strict providers on resume. msg[:tool_calls] = @metadata[:tool_calls] if @metadata.is_a?(Hash) && @metadata[:tool_calls] # #583: re-derive the error flag from the persisted outcome so a # denied/errored tool result replays to the model marked as an error # (is_error) on the next turn, exactly as it was sent live — never as a # plain result the model can confabulate over. Old rows lack the keys # and hydrate as a normal (non-error) tool result, unchanged. msg[:is_error] = true if @role == "tool" && tool_outcome_errored? msg end |
#to_row ⇒ Object
Returns a hash suitable for database insertion
Free-text columns are run through Util::Output.scrub_utf8 at this PERSIST seam (#498): a NUL byte is valid UTF-8 (so it survives String#scrub) yet terminates SQLite’s C string mid-literal, surfacing a raw ‘SQLite3::SQLException: unrecognized token` even through bound params. Scrubbing here (the single message-write chokepoint) keeps every prompt storable no matter what control bytes a paste/upstream model emitted, and is idempotent on already-clean input.
42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/rubino/session/message.rb', line 42 def to_row { id: @id, session_id: @session_id, role: @role, content: scrub(@content), tool_name: scrub(@tool_name), tool_call_id: scrub(@tool_call_id), token_count: @token_count, metadata_json: @metadata.empty? ? nil : JSON.generate(@metadata), created_at: @created_at } end |
#valid? ⇒ Boolean
Validates the message attributes
29 30 31 |
# File 'lib/rubino/session/message.rb', line 29 def valid? VALID_ROLES.include?(@role) && @session_id end |