Class: Helicone::Message

Inherits:
Object
  • Object
show all
Defined in:
lib/helicone/message.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(role:, content:, tool_call_id: nil) ⇒ Message

Initialize a message

Parameters:

  • role (String, Symbol) —

    Message role ("user", "assistant", "system", "tool")

  • content (String, Array<Hash>) —

    Message content (text or structured content)

  • tool_call_id (String) (defaults to: nil) —

    Tool call ID (required for tool result messages)



12
13
14
15
16
# File 'lib/helicone/message.rb', line 12

def initialize(role:, content:, tool_call_id: nil)
  @role = role.to_s
  @content = content
  @tool_call_id = tool_call_id
end

Instance Attribute Details

#content ⇒ Object (readonly)

Returns the value of attribute content.



5
6
7
# File 'lib/helicone/message.rb', line 5

def content
  @content
end

#role ⇒ Object (readonly)

Returns the value of attribute role.



5
6
7
# File 'lib/helicone/message.rb', line 5

def role
  @role
end

#tool_call_id ⇒ Object (readonly)

Returns the value of attribute tool_call_id.



5
6
7
# File 'lib/helicone/message.rb', line 5

def tool_call_id
  @tool_call_id
end

Class Method Details

.assistant_text(text) ⇒ Helicone::Message

Build an assistant message with text

Parameters:

  • text (String) —

    The text content

Returns:



30
31
32
# File 'lib/helicone/message.rb', line 30

def self.assistant_text(text)
  new(role: "assistant", content: text)
end

.assistant_with_tool_calls(raw_message) ⇒ Helicone::Message

Build an assistant message that contains tool_calls (from API response) This stores the raw message so it can be returned as-is for the API Note: We transform null content to empty string as the API rejects null

Parameters:

  • raw_message (Hash) —

    The raw message hash from the API response

Returns:



101
102
103
104
105
106
107
108
109
110
# File 'lib/helicone/message.rb', line 101

def self.assistant_with_tool_calls(raw_message)
  msg = new(role: "assistant", content: nil)
  # Deep duplicate the message to avoid mutating the original
  sanitized_message = deep_dup(raw_message)
  if sanitized_message[:content].nil?
    sanitized_message[:content] = ""
  end
  msg.instance_variable_set(:@raw_message, sanitized_message)
  msg
end

.deep_dup(obj) ⇒ Object

Deep duplicate a hash/array structure

Parameters:

  • obj (Object) —

    Object to duplicate

Returns:

  • (Object) —

    Deep copy of the object



141
142
143
144
145
146
147
148
149
150
# File 'lib/helicone/message.rb', line 141

def self.deep_dup(obj)
  case obj
  when Hash
    obj.each_with_object({}) { |(k, v), h| h[k] = deep_dup(v) }
  when Array
    obj.map { |v| deep_dup(v) }
  else
    obj.respond_to?(:dup) ? obj.dup : obj
  end
end

.system(text) ⇒ Helicone::Message

Build a system message

Parameters:

  • text (String) —

    The system prompt text

Returns:



38
39
40
# File 'lib/helicone/message.rb', line 38

def self.system(text)
  new(role: "system", content: text)
end

.tool_result(tool_call_id:, content:) ⇒ Helicone::Message

Build a tool result message

Parameters:

  • tool_call_id (String) —

    The ID of the tool call being responded to

  • content (String, Hash) —

    The tool result (will be JSON-encoded if not a string)

Returns:



90
91
92
93
# File 'lib/helicone/message.rb', line 90

def self.tool_result(tool_call_id:, content:)
  content_str = content.is_a?(String) ? content : content.to_json
  new(role: "tool", content: content_str, tool_call_id: tool_call_id)
end

.user_image(image_url, text: nil, detail: "auto") ⇒ Helicone::Message

Build a user message with a single image

Parameters:

  • image_url (String) —

    URL or base64 data URI of the image

  • text (String) (defaults to: nil) —

    Optional text content to include

  • detail (String) (defaults to: "auto") —

    Image detail level: "auto", "low", or "high"

Returns:



71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/helicone/message.rb', line 71

def self.user_image(image_url, text: nil, detail: "auto")
  content = []
  content << { type: "text", text: text } if text
  content << {
    type: "image_url",
    image_url: {
      url: image_url,
      detail: detail
    }
  }

  new(role: "user", content: content)
end

.user_text(text) ⇒ Helicone::Message

Build a user message with text

Parameters:

  • text (String) —

    The text content

Returns:



22
23
24
# File 'lib/helicone/message.rb', line 22

def self.user_text(text)
  new(role: "user", content: text)
end

.user_with_images(text, images, detail: "auto") ⇒ Helicone::Message

Build a user message with text and images

Parameters:

  • text (String) —

    The text content

  • images (Array<String>, String) —

    Image URL(s) or base64 data URI(s)

  • detail (String) (defaults to: "auto") —

    Image detail level: "auto", "low", or "high"

Returns:



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/helicone/message.rb', line 48

def self.user_with_images(text, images, detail: "auto")
  content = []
  content << { type: "text", text: text }

  Array(images).each do |image|
    content << {
      type: "image_url",
      image_url: {
        url: image,
        detail: detail
      }
    }
  end

  new(role: "user", content: content)
end

Instance Method Details

#to_h ⇒ Hash Also known as: to_hash

Convert to hash for API request

Returns:

  • (Hash) —

    Message formatted for the API



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/helicone/message.rb', line 115

def to_h
  if @raw_message
    # Return the full raw message to preserve extra_content (thought signatures)
    # and any other provider-specific fields (e.g., Gemini 3 requires thought_signature)
    @raw_message
  else
    hash = { role: role, content: content }
    hash[:tool_call_id] = tool_call_id if tool_call_id
    hash
  end
end

#tool_calls? ⇒ Boolean

Check if this message has tool calls

Returns:

  • (Boolean)


130
131
132
133
# File 'lib/helicone/message.rb', line 130

def tool_calls?
  tool_calls = @raw_message&.dig(:tool_calls)
  !tool_calls.nil? && !tool_calls.empty?
end