Module: LittleGhost::AgentStreamSnapshot

Defined in:
lib/little_ghost/agent_stream_source.rb

Overview

:nodoc: all

Class Method Summary collapse

Class Method Details

.copy(value, copies = {}) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/little_ghost/agent_stream_source.rb', line 105

def copy(value, copies = {})
  return value if immutable_scalar?(value)
  return copies.fetch(value.object_id) if copies.key?(value.object_id)

  case value
  when Message
    copy_message(value, copies)
  when DataMap
    copy_data_map(value, copies)
  when Hash
    copy_hash(value, copies)
  when Array
    copy_array(value, copies)
  when String
    value.dup.freeze
  when Data
    copy_data(value, copies)
  when Exception
    copy_exception(value, copies)
  else
    copy_object(value, copies)
  end
end

.copy_array(value, copies) ⇒ Object



155
156
157
158
159
160
# File 'lib/little_ghost/agent_stream_source.rb', line 155

def copy_array(value, copies)
  snapshot = []
  copies[value.object_id] = snapshot
  value.each { |child| snapshot << copy(child, copies) }
  snapshot.freeze
end

.copy_data(value, copies) ⇒ Object



162
163
164
165
166
167
168
169
# File 'lib/little_ghost/agent_stream_source.rb', line 162

def copy_data(value, copies)
  attributes = value.members.to_h do |member|
    [member, copy(value.public_send(member), copies)]
  end
  value.class.new(**attributes).freeze.tap do |snapshot|
    copies[value.object_id] = snapshot
  end
end

.copy_data_map(value, copies) ⇒ Object



137
138
139
140
141
142
143
144
# File 'lib/little_ghost/agent_stream_source.rb', line 137

def copy_data_map(value, copies)
  snapshot = DataMap.new
  copies[value.object_id] = snapshot
  value.each do |key, child|
    snapshot[key] = copy(child, copies)
  end
  snapshot.freeze
end

.copy_exception(value, copies) ⇒ Object



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/little_ghost/agent_stream_source.rb', line 184

def copy_exception(value, copies)
  message = value.message.to_s.dup.freeze
  snapshot = value.exception(message)
  if snapshot.equal?(value)
    snapshot = value.class.allocate
    Exception.instance_method(:initialize).bind_call(snapshot, message)
  end
  copies[value.object_id] = snapshot
  if value.cause
    cause = copy(value.cause, copies)
    begin
      raise snapshot, cause:
    rescue => raised
      snapshot = raised
      copies[value.object_id] = snapshot
    end
  end
  value.instance_variables.each do |name|
    snapshot.instance_variable_set(name, copy(value.instance_variable_get(name), copies))
  end
  backtrace = copy(value.backtrace, copies)
  snapshot.set_backtrace(backtrace)
  freeze_value(snapshot.backtrace) if snapshot.backtrace
  snapshot.freeze
end

.copy_hash(value, copies) ⇒ Object



146
147
148
149
150
151
152
153
# File 'lib/little_ghost/agent_stream_source.rb', line 146

def copy_hash(value, copies)
  snapshot = {}
  copies[value.object_id] = snapshot
  value.each do |key, child|
    snapshot[copy(key, copies)] = copy(child, copies)
  end
  snapshot.freeze
end

.copy_message(value, copies) ⇒ Object



129
130
131
132
133
134
135
# File 'lib/little_ghost/agent_stream_source.rb', line 129

def copy_message(value, copies)
  content = copy_array(value.content, copies)
   = copy_data_map(value., copies)
  Message.new(role: value.role, content:, metadata:).freeze.tap do |snapshot|
    copies[value.object_id] = snapshot
  end
end

.copy_object(value, copies) ⇒ Object



171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/little_ghost/agent_stream_source.rb', line 171

def copy_object(value, copies)
  return value if value.is_a?(Module)

  snapshot = value.dup
  copies[value.object_id] = snapshot
  value.instance_variables.each do |name|
    snapshot.instance_variable_set(name, copy(value.instance_variable_get(name), copies))
  end
  snapshot.freeze
rescue TypeError
  value.frozen? ? value : value.to_s.dup.freeze
end

.event(event) ⇒ Object



96
97
98
99
# File 'lib/little_ghost/agent_stream_source.rb', line 96

def event(event)
  data = copy(event.data)
  freeze_value(StreamEvent.build(event.type, **data))
end

.freeze_value(value, seen = {}) ⇒ Object



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/little_ghost/agent_stream_source.rb', line 214

def freeze_value(value, seen = {})
  return value if immutable_scalar?(value) || value.is_a?(Module)
  return value if seen[value.object_id]

  seen[value.object_id] = true
  case value
  when Message
    freeze_value(value.content, seen)
    freeze_value(value., seen)
  when Hash
    value.each do |key, child|
      freeze_value(key, seen)
      freeze_value(child, seen)
    end
  when Array
    value.each { |child| freeze_value(child, seen) }
  when Data
    value.members.each { |member| freeze_value(value.public_send(member), seen) }
  else
    value.instance_variables.each do |name|
      freeze_value(value.instance_variable_get(name), seen)
    end
  end
  value.freeze
end

.immutable_scalar?(value) ⇒ Boolean

Returns:

  • (Boolean)


210
211
212
# File 'lib/little_ghost/agent_stream_source.rb', line 210

def immutable_scalar?(value)
  value.nil? || value == true || value == false || value.is_a?(Numeric) || value.is_a?(Symbol)
end

.message(message) ⇒ Object



101
102
103
# File 'lib/little_ghost/agent_stream_source.rb', line 101

def message(message)
  freeze_value(copy(message))
end