Module: Mistri::Content

Defined in:
lib/mistri/content.rb

Overview

Typed content blocks: what a message is made of. Text and thinking on assistant turns, text and images on user and tool-result turns, tool calls alongside them. Blocks are immutable values that compare by content, pattern-match, and round-trip through #to_h / Content.from_h, so sessions replay without the loop knowing block shapes.

Defined Under Namespace

Classes: Image, Text, Thinking

Class Method Summary collapse

Class Method Details

.freeze_string(value) ⇒ Object

String#to_s returns self, so a caller's mutable buffer would alias into an immutable block; blocks own a frozen copy instead.



12
13
14
15
# File 'lib/mistri/content.rb', line 12

def self.freeze_string(value)
  s = value.to_s
  s.frozen? ? s : s.dup.freeze
end

.from_h(hash) ⇒ Object

The inverse of #to_h, used when a session is read back. Keys may be symbols or, after a JSON round-trip, strings.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/mistri/content.rb', line 83

def self.from_h(hash)
  h = hash.transform_keys(&:to_s)
  case h["type"].to_s
  when "text" then Text.new(text: h["text"], signature: h["signature"])
  when "thinking"
    Thinking.new(thinking: h["thinking"], signature: h["signature"],
                 redacted: h.fetch("redacted", false))
  when "image" then Image.new(data: h["data"], mime_type: h["mime_type"])
  when "tool_call"
    ToolCall.new(id: h["id"], name: h["name"], arguments: h["arguments"] || {},
                 signature: h["signature"])
  else raise ArgumentError, "unknown content block type #{h["type"].inspect}"
  end
end

.wrap(content) ⇒ Object

Coerce a value into a list of blocks: nil becomes none, a String becomes one Text block, blocks pass through, arrays may mix all of these.



75
76
77
78
79
# File 'lib/mistri/content.rb', line 75

def self.wrap(content)
  Array(content).map do |block|
    block.respond_to?(:type) ? block : Text.new(text: block.to_s)
  end
end