ruby_llm-agents 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f41d0d0f2a52571d96d877a6d3261083a5183a766ca2a67bd69a216d9dd2d9bb
4
- data.tar.gz: 01accbd04fcb000e10ccc56f7dedb72f757f854eeb719eaaf93dab5438e7e46e
3
+ metadata.gz: b9c413f46174a6ad550e9ff2a676c92e116d6a8199cc3ff1c8ecb24e48b89b53
4
+ data.tar.gz: e4def5034b05f731418622879f15ee8e77be73534e239855612770874545da29
5
5
  SHA512:
6
- metadata.gz: 131def9da995060fe2c4b9930ce6c82c8eb1e8c391905bb9ddac4a80503c585bcca2123ce5da6baf05f7fc78cba5ceed6470238a81ff7cd1e3fc693993a599c0
7
- data.tar.gz: 3becaadc1a1bb9619e9eae464fed9f6e2de179239748386a405f88f50066d2fff610696b582ab4b292d66036d0620a60bddc5e781e6befe6a0d095216a7566f0
6
+ metadata.gz: 9926a9f54daef58388cc5f6fabbacaf3dbaf3d03f590ef97dc81d180dd3ccb53153f78ec54c8a32247d1abc18c19084a04bf2b31b1378109dd76d159e84bff6a
7
+ data.tar.gz: 225a42a4f27f25f41b84521df11464e1bdb64ddbbddc6d8c7476d2039bddc9ddaa9ad96078aeb9e13bddd79ef1ba88a1697b8abb82a9b6239b8b5d00a836e8c0
@@ -28,9 +28,12 @@ module RubyLLM
28
28
 
29
29
  # Wrap agent execution with metrics tracking
30
30
  # Creates execution record at start with 'running' status, updates on completion
31
+ # Uses ensure block to guarantee status is updated even if complete_execution fails
31
32
  def instrument_execution(&block)
32
33
  started_at = Time.current
33
34
  @last_response = nil
35
+ @execution_status_updated = false
36
+ original_error = nil
34
37
 
35
38
  # Create execution record immediately with running status
36
39
  execution = create_running_execution(started_at)
@@ -46,24 +49,34 @@ module RubyLLM
46
49
  status: "success",
47
50
  response: @last_response
48
51
  )
52
+ @execution_status_updated = true
49
53
 
50
54
  result
51
55
  rescue Timeout::Error => e
56
+ original_error = e
52
57
  complete_execution(
53
58
  execution,
54
59
  completed_at: Time.current,
55
60
  status: "timeout",
56
61
  error: e
57
62
  )
63
+ @execution_status_updated = true
58
64
  raise
59
65
  rescue => e
66
+ original_error = e
60
67
  complete_execution(
61
68
  execution,
62
69
  completed_at: Time.current,
63
70
  status: "error",
64
71
  error: e
65
72
  )
73
+ @execution_status_updated = true
66
74
  raise
75
+ ensure
76
+ # Guarantee execution is marked as error if complete_execution failed
77
+ unless @execution_status_updated
78
+ mark_execution_failed!(execution, error: original_error)
79
+ end
67
80
  end
68
81
  end
69
82
 
@@ -110,16 +123,11 @@ module RubyLLM
110
123
  status: status
111
124
  }
112
125
 
113
- # Add response data if available
114
- if response.is_a?(RubyLLM::Message)
115
- update_data.merge!(
116
- input_tokens: response.input_tokens,
117
- output_tokens: response.output_tokens,
118
- cached_tokens: response&.cached_tokens || 0,
119
- cache_creation_tokens: response&.cache_creation_tokens || 0,
120
- model_id: response.model_id || model,
121
- response: serialize_response(response)
122
- )
126
+ # Add response data if available (using safe extraction)
127
+ response_data = safe_extract_response_data(response)
128
+ if response_data.any?
129
+ update_data.merge!(response_data)
130
+ update_data[:model_id] ||= model
123
131
  end
124
132
 
125
133
  # Add error data if failed
@@ -134,11 +142,16 @@ module RubyLLM
134
142
 
135
143
  # Calculate costs if token data is available
136
144
  if execution.input_tokens && execution.output_tokens
137
- execution.calculate_costs!
138
- execution.save!
145
+ begin
146
+ execution.calculate_costs!
147
+ execution.save!
148
+ rescue StandardError => cost_error
149
+ Rails.logger.warn("[RubyLLM::Agents] Cost calculation failed: #{cost_error.message}")
150
+ end
139
151
  end
140
152
  rescue StandardError => e
141
153
  Rails.logger.error("[RubyLLM::Agents] Failed to update execution record: #{e.message}")
154
+ raise # Re-raise so ensure block can handle emergency update
142
155
  end
143
156
 
144
157
  # Fallback for when initial execution creation failed
@@ -158,15 +171,11 @@ module RubyLLM
158
171
  user_prompt: safe_user_prompt
159
172
  }
160
173
 
161
- if response.is_a?(RubyLLM::Message)
162
- execution_data.merge!(
163
- input_tokens: response.input_tokens,
164
- output_tokens: response.output_tokens,
165
- cached_tokens: response&.cached_tokens || 0,
166
- cache_creation_tokens: response&.cache_creation_tokens || 0,
167
- model_id: response.model_id || model,
168
- response: serialize_response(response)
169
- )
174
+ # Add response data if available (using safe extraction)
175
+ response_data = safe_extract_response_data(response)
176
+ if response_data.any?
177
+ execution_data.merge!(response_data)
178
+ execution_data[:model_id] ||= model
170
179
  end
171
180
 
172
181
  if error
@@ -208,18 +217,6 @@ module RubyLLM
208
217
  end
209
218
  end
210
219
 
211
- # Serialize full RubyLLM::Message response to JSON
212
- def serialize_response(response)
213
- {
214
- content: response.content,
215
- model_id: response.model_id,
216
- input_tokens: response.input_tokens,
217
- output_tokens: response.output_tokens,
218
- cached_tokens: response&.cached_tokens || 0,
219
- cache_creation_tokens: response&.cache_creation_tokens || 0
220
- }.compact
221
- end
222
-
223
220
  # Hook for subclasses to add custom metadata
224
221
  def execution_metadata
225
222
  {}
@@ -240,6 +237,58 @@ module RubyLLM
240
237
  Rails.logger.warn("[RubyLLM::Agents] Could not capture user_prompt: #{e.message}")
241
238
  nil
242
239
  end
240
+
241
+ # Safely extract a value from response, returning default if method doesn't exist
242
+ def safe_response_value(response, method, default = nil)
243
+ return default unless response.respond_to?(method)
244
+ response.public_send(method)
245
+ rescue StandardError
246
+ default
247
+ end
248
+
249
+ # Safely extract all response data with fallbacks
250
+ def safe_extract_response_data(response)
251
+ return {} unless response.is_a?(RubyLLM::Message)
252
+
253
+ {
254
+ input_tokens: safe_response_value(response, :input_tokens),
255
+ output_tokens: safe_response_value(response, :output_tokens),
256
+ cached_tokens: safe_response_value(response, :cached_tokens, 0),
257
+ cache_creation_tokens: safe_response_value(response, :cache_creation_tokens, 0),
258
+ model_id: safe_response_value(response, :model_id),
259
+ response: safe_serialize_response(response)
260
+ }.compact
261
+ end
262
+
263
+ # Safe version of serialize_response
264
+ def safe_serialize_response(response)
265
+ {
266
+ content: safe_response_value(response, :content),
267
+ model_id: safe_response_value(response, :model_id),
268
+ input_tokens: safe_response_value(response, :input_tokens),
269
+ output_tokens: safe_response_value(response, :output_tokens),
270
+ cached_tokens: safe_response_value(response, :cached_tokens, 0),
271
+ cache_creation_tokens: safe_response_value(response, :cache_creation_tokens, 0)
272
+ }.compact
273
+ end
274
+
275
+ # Emergency fallback - mark execution as error using update_columns
276
+ # Bypasses callbacks/validations to ensure status is always updated
277
+ def mark_execution_failed!(execution, error: nil)
278
+ return unless execution&.id
279
+ return unless execution.status == "running"
280
+
281
+ update_data = {
282
+ status: "error",
283
+ completed_at: Time.current,
284
+ error_class: error&.class&.name || "InstrumentationError",
285
+ error_message: (error&.message || "Execution status update failed").to_s.truncate(65535)
286
+ }
287
+
288
+ execution.class.where(id: execution.id, status: "running").update_all(update_data)
289
+ rescue StandardError => e
290
+ Rails.logger.error("[RubyLLM::Agents] CRITICAL: Failed emergency status update for execution #{execution&.id}: #{e.message}")
291
+ end
243
292
  end
244
293
  end
245
294
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RubyLLM
4
4
  module Agents
5
- VERSION = "0.2.1"
5
+ VERSION = "0.2.2"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_llm-agents
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - adham90