Class: LittleGhost::Message

Inherits:
Object
  • Object
show all
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.

message = LittleGhost::Message.new(role: :user, content: "Hello")
message.text # => "Hello"

Constant Summary collapse

ROLES =

Participant roles accepted by Message.new.

%i[system developer user assistant tool].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

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.

Raises:

  • (ArgumentError)


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

#contentObject (readonly)

Participant role, normalized Content blocks, and application metadata.



21
22
23
# File 'lib/little_ghost/message.rb', line 21

def content
  @content
end

#metadataObject (readonly)

Participant role, normalized Content blocks, and application metadata.



21
22
23
# File 'lib/little_ghost/message.rb', line 21

def 
  @metadata
end

#roleObject (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

#textObject

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_hObject

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_reasoningObject

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