Class: Legion::Extensions::Llm::Canonical::Message

Inherits:
Data
  • Object
show all
Defined in:
lib/legion/extensions/llm/canonical/message.rb

Overview

rubocop:disable Lint/ConstantDefinitionInBlock – required for Data.define block scope Canonical message in a conversation. Ports field vocabulary from Legion::LLM::Types::Message and lex-llm Message.

Constant Summary collapse

ROLES =
%i[system user assistant tool].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#contentObject (readonly)

Returns the value of attribute content

Returns:

  • (Object)

    the current value of content



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def content
  @content
end

#conversation_idObject (readonly)

Returns the value of attribute conversation_id

Returns:

  • (Object)

    the current value of conversation_id



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def conversation_id
  @conversation_id
end

#idObject (readonly)

Returns the value of attribute id

Returns:

  • (Object)

    the current value of id



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def id
  @id
end

#input_tokensObject (readonly)

Returns the value of attribute input_tokens

Returns:

  • (Object)

    the current value of input_tokens



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def input_tokens
  @input_tokens
end

#modelObject (readonly)

Returns the value of attribute model

Returns:

  • (Object)

    the current value of model



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def model
  @model
end

#nameObject (readonly)

Returns the value of attribute name

Returns:

  • (Object)

    the current value of name



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def name
  @name
end

#output_tokensObject (readonly)

Returns the value of attribute output_tokens

Returns:

  • (Object)

    the current value of output_tokens



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def output_tokens
  @output_tokens
end

#parent_idObject (readonly)

Returns the value of attribute parent_id

Returns:

  • (Object)

    the current value of parent_id



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def parent_id
  @parent_id
end

#providerObject (readonly)

Returns the value of attribute provider

Returns:

  • (Object)

    the current value of provider



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def provider
  @provider
end

#roleObject (readonly)

Returns the value of attribute role

Returns:

  • (Object)

    the current value of role



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def role
  @role
end

#seqObject (readonly)

Returns the value of attribute seq

Returns:

  • (Object)

    the current value of seq



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def seq
  @seq
end

#statusObject (readonly)

Returns the value of attribute status

Returns:

  • (Object)

    the current value of status



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def status
  @status
end

#task_idObject (readonly)

Returns the value of attribute task_id

Returns:

  • (Object)

    the current value of task_id



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def task_id
  @task_id
end

#timestampObject (readonly)

Returns the value of attribute timestamp

Returns:

  • (Object)

    the current value of timestamp



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def timestamp
  @timestamp
end

#tool_call_idObject (readonly)

Returns the value of attribute tool_call_id

Returns:

  • (Object)

    the current value of tool_call_id



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def tool_call_id
  @tool_call_id
end

#tool_callsObject (readonly)

Returns the value of attribute tool_calls

Returns:

  • (Object)

    the current value of tool_calls



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def tool_calls
  @tool_calls
end

#versionObject (readonly)

Returns the value of attribute version

Returns:

  • (Object)

    the current value of version



13
14
15
# File 'lib/legion/extensions/llm/canonical/message.rb', line 13

def version
  @version
end

Class Method Details

.build(id: nil, parent_id: nil, role: :user, content: nil, tool_calls: nil, tool_call_id: nil, name: nil, status: :created, version: 1, timestamp: nil, seq: nil, provider: nil, model: nil, input_tokens: nil, output_tokens: nil, conversation_id: nil, task_id: nil) ⇒ Object

Build from keyword args (primary constructor).



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/legion/extensions/llm/canonical/message.rb', line 22

def self.build(
  id: nil, parent_id: nil, role: :user, content: nil, tool_calls: nil,
  tool_call_id: nil, name: nil, status: :created, version: 1,
  timestamp: nil, seq: nil, provider: nil, model: nil,
  input_tokens: nil, output_tokens: nil, conversation_id: nil, task_id: nil
)
  role_sym = role.is_a?(String) ? role.to_sym : role
  unless ROLES.include?(role_sym)
    raise ArgumentError,
          "Invalid role: #{role_sym}. Must be one of: #{ROLES.join(', ')}"
  end

  new(
    id: id || "msg_#{SecureRandom.hex(12)}",
    parent_id: parent_id,
    role: role_sym,
    content: content,
    tool_calls: tool_calls,
    tool_call_id: tool_call_id,
    name: name,
    status: status,
    version: version,
    timestamp: timestamp || ::Time.now,
    seq: seq,
    provider: provider,
    model: model,
    input_tokens: input_tokens,
    output_tokens: output_tokens,
    conversation_id: conversation_id,
    task_id: task_id
  )
end

.from_hash(hash) ⇒ Object

Build from a Hash (raw provider response or deserialized wire payload).



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/legion/extensions/llm/canonical/message.rb', line 56

def self.from_hash(hash)
  return nil if hash.nil?

  h = hash.transform_keys(&:to_sym)

  # Normalize role to symbol
  role_raw = h[:role]
  h[:role] = role_raw&.to_sym if role_raw

  # Parse content blocks if they're an array of hashes
  content = h[:content]
  if content.is_a?(Array)
    h[:content] = content.map do |block|
      block.is_a?(ContentBlock) ? block : ContentBlock.from_hash(block)
    end
  elsif content.is_a?(Hash)
    h[:content] = ContentBlock.from_hash(content)
  end

  # Parse tool calls if they're an array of hashes
  tool_calls = h[:tool_calls]
  if tool_calls.is_a?(Array)
    h[:tool_calls] = tool_calls.map do |tc|
      tc.is_a?(ToolCall) ? tc : ToolCall.from_hash(tc)
    end
  end

  build(**h)
end

.wrap(input) ⇒ Object

Wrap input: pass through if already a Message, parse if Hash.



87
88
89
90
91
92
# File 'lib/legion/extensions/llm/canonical/message.rb', line 87

def self.wrap(input)
  return input if input.is_a?(Message)
  return from_hash(input) if input.is_a?(Hash)

  nil
end

Instance Method Details

#textObject

Extract plain text from content (String or ContentBlock array).



95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/legion/extensions/llm/canonical/message.rb', line 95

def text
  case content
  when String then content
  when Array
    content.filter_map do |block|
      block.is_a?(ContentBlock) && block.text? ? block.text : nil
    end.join
  when ContentBlock then content.text if content.text?
  else
    content.to_s
  end
end

#to_hObject

Serialize to a Hash for AMQP/fleet/wire transport.



109
110
111
# File 'lib/legion/extensions/llm/canonical/message.rb', line 109

def to_h
  super.compact
end

#to_provider_hashObject

Minimal provider-facing hash (role + text content).



114
115
116
# File 'lib/legion/extensions/llm/canonical/message.rb', line 114

def to_provider_hash
  { role: role.to_s, content: text }.compact
end