Class: LittleGhost::Message
- Inherits:
-
Object
- Object
- LittleGhost::Message
- Defined in:
- lib/little_ghost/message.rb
Overview
A Message carries one participant's contribution to an agent conversation. Its content can combine text, attachments, tool activity, and model reasoning.
Content is normalized into Content blocks held in a frozen Array. Strings become Content::Text blocks, and hashes use the serialized content shape accepted by Content.normalize. Nested values supplied by the caller are retained rather than defensively copied.
= LittleGhost::Message.new(role: :user, content: "Hello")
.text # => "Hello"
Constant Summary collapse
- ROLES =
Participant roles accepted by Message.new.
%i[system developer user assistant tool].freeze
Instance Attribute Summary collapse
-
#content ⇒ Object
readonly
Participant role, normalized Content blocks, and application metadata.
-
#metadata ⇒ Object
readonly
Participant role, normalized Content blocks, and application metadata.
-
#role ⇒ Object
readonly
Participant role, normalized Content blocks, and application metadata.
Class Method Summary collapse
-
.coerce(value) ⇒ Object
Keeps
valuewhen it is already a message, or creates a message from a hash with string or symbol keys.
Instance Method Summary collapse
-
#initialize(role:, content:, metadata: {}) ⇒ Message
constructor
Creates a frozen message with a supported
role, normalizedcontent, and application-definedmetadata. -
#text ⇒ Object
Joins the visible text blocks without including reasoning or tool content.
-
#to_h ⇒ Object
Produces the JSON-safe message representation.
-
#to_json(*arguments) ⇒ Object
Encodes #to_h as JSON, forwarding generator
arguments. -
#without_reasoning ⇒ Object
Removes Content::Reasoning blocks, or keeps
selfwhen none are present.
Constructor Details
#initialize(role:, content:, metadata: {}) ⇒ Message
Creates a frozen message with a supported role, normalized content, and
application-defined metadata. The content Array and metadata Hash are
frozen, but nested caller-owned values are retained.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/little_ghost/message.rb', line 26 def initialize(role:, content:, metadata: {}) @role = role.to_sym raise ArgumentError, "Unsupported message role: #{role.inspect}" unless ROLES.include?(@role) blocks = if content.nil? [] elsif content.is_a?(Array) content else [content] end @content = blocks.map { |block| Content.normalize(block) }.freeze @metadata = .freeze freeze end |
Instance Attribute Details
#content ⇒ Object (readonly)
Participant role, normalized Content blocks, and application metadata.
21 22 23 |
# File 'lib/little_ghost/message.rb', line 21 def content @content end |
#metadata ⇒ Object (readonly)
Participant role, normalized Content blocks, and application metadata.
21 22 23 |
# File 'lib/little_ghost/message.rb', line 21 def @metadata end |
#role ⇒ Object (readonly)
Participant role, normalized Content blocks, and application metadata.
21 22 23 |
# File 'lib/little_ghost/message.rb', line 21 def role @role end |
Class Method Details
.coerce(value) ⇒ Object
Keeps value when it is already a message, or creates a message from a
hash with string or symbol keys.
44 45 46 47 48 49 |
# File 'lib/little_ghost/message.rb', line 44 def self.coerce(value) return value if value.is_a?(self) hash = value.transform_keys(&:to_sym) new(**hash) end |
Instance Method Details
#text ⇒ Object
Joins the visible text blocks without including reasoning or tool content.
52 53 54 |
# File 'lib/little_ghost/message.rb', line 52 def text content.grep(Content::Text).map(&:text).join end |
#to_h ⇒ Object
Produces the JSON-safe message representation.
66 67 68 |
# File 'lib/little_ghost/message.rb', line 66 def to_h {"role" => role.to_s, "content" => content.map(&:to_h), "metadata" => } end |
#to_json(*arguments) ⇒ Object
Encodes #to_h as JSON, forwarding generator arguments.
71 72 73 |
# File 'lib/little_ghost/message.rb', line 71 def to_json(*arguments) JSON.generate(to_h, *arguments) end |
#without_reasoning ⇒ Object
Removes Content::Reasoning blocks, or keeps self when none are
present.
58 59 60 61 62 63 |
# File 'lib/little_ghost/message.rb', line 58 def without_reasoning remaining_content = content.reject { |block| block.is_a?(Content::Reasoning) } return self if remaining_content.length == content.length self.class.new(role:, content: remaining_content, metadata:) end |