activeagent 0.6.0rc2 → 0.6.0rc4

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: a9496edf8536e904969a006a14d65bd69c3257f4db22d80e859a977646a02513
4
- data.tar.gz: 0b35eb065fe146ee027d72789826ea3af793e57140d8aefead79d73586548e6e
3
+ metadata.gz: 805b4d2cce3173788f3bb281e40973d8782891937b5220654b7dad53a9f701ec
4
+ data.tar.gz: 968f534f94d4e32541f1d87e21854add0f4bf8c9e851ba75f7599291a0b384b9
5
5
  SHA512:
6
- metadata.gz: 65ce7639ce9106b99e827600b7582776413cdeb69b7de28cf7ed80e0e496ebc1be6ea613ab9f67e944bb7837344458d3709a2065eb2725fc9b7263c08146f08d
7
- data.tar.gz: c702c8618b701979dee4871ab200e7fd60d5c09fc2670926a9f77e1c0975ab14e2a5e9b30df2eccce9276440f5e6baf396d16320aabff67a1fbbd332a88b5379
6
+ metadata.gz: ec13c2dd2d8deb4fd4adb1a6f302de6a7bb5057fad1cd45f27fdecc6b8bea7b5496f3078e7a1f40168de9b4efaa8e4a2abf1cf1bd2865fa929912c58adce561c
7
+ data.tar.gz: a564772159ac558c8350d770977fc9b7b509c814435a748cac61af89bd87dc196614b45cc9f33db7bce8951568f659730bfe4cf95fd274f145ae00bb78510af6
@@ -2,6 +2,8 @@ require "active_agent/collector"
2
2
  require "active_support/core_ext/string/inflections"
3
3
  require "active_support/core_ext/hash/except"
4
4
  require "active_support/core_ext/module/anonymous"
5
+ require "active_agent/action_prompt/message"
6
+ require "active_agent/action_prompt/action"
5
7
 
6
8
  # require "active_agent/log_subscriber"
7
9
  require "active_agent/rescuable"
@@ -10,6 +12,7 @@ module ActiveAgent
10
12
  class Base < AbstractController::Base
11
13
  include Callbacks
12
14
  include GenerationProvider
15
+ include Streaming
13
16
  include QueuedGeneration
14
17
  include Rescuable
15
18
  include Parameterized
@@ -217,7 +220,8 @@ module ActiveAgent
217
220
  def handle_response(response)
218
221
  return response unless response.message.requested_actions.present?
219
222
 
220
- # Perform the requested actions
223
+ # The assistant message with tool_calls is already added by update_context in the provider
224
+ # Now perform the requested actions which will add tool response messages
221
225
  perform_actions(requested_actions: response.message.requested_actions)
222
226
 
223
227
  # Continue generation with updated context
@@ -241,9 +245,9 @@ module ActiveAgent
241
245
  end
242
246
 
243
247
  def perform_action(action)
244
- current_context = context.clone
245
- # Merge action params with original params to preserve context
246
- original_params = current_context.params || {}
248
+ # Save the current messages to preserve conversation history
249
+ original_messages = context.messages.dup
250
+ original_params = context.params || {}
247
251
 
248
252
  if action.params.is_a?(Hash)
249
253
  self.params = original_params.merge(action.params)
@@ -251,14 +255,26 @@ module ActiveAgent
251
255
  self.params = original_params
252
256
  end
253
257
 
258
+ # Save the current prompt_was_called state and reset it so the action can render
259
+ original_prompt_was_called = @_prompt_was_called
260
+ @_prompt_was_called = false
261
+
262
+ # Process the action, which will render the view and populate context
254
263
  process(action.name)
255
- context.message.role = :tool
256
- context.message.action_id = action.id
257
- context.message.action_name = action.name
258
- context.message.generation_id = action.id
259
- current_context.message = context.message
260
- current_context.messages << context.message
261
- self.context = current_context
264
+
265
+ # The action should have called prompt which populates context.message
266
+ # Create a tool message from the rendered response
267
+ tool_message = context.message.dup
268
+ tool_message.role = :tool
269
+ tool_message.action_id = action.id
270
+ tool_message.action_name = action.name
271
+ tool_message.generation_id = action.id
272
+
273
+ # Restore the messages with the new tool message
274
+ context.messages = original_messages + [ tool_message ]
275
+
276
+ # Restore the prompt_was_called state
277
+ @_prompt_was_called = original_prompt_was_called
262
278
  end
263
279
 
264
280
  def initialize # :nodoc:
@@ -425,7 +441,10 @@ module ActiveAgent
425
441
  # Extract runtime options from prompt_options (exclude instructions as it has special template logic)
426
442
  runtime_options = prompt_options.slice(
427
443
  :model, :temperature, :max_tokens, :stream, :top_p, :frequency_penalty,
428
- :presence_penalty, :response_format, :seed, :stop, :tools_choice, :data_collection, :plugins
444
+ :presence_penalty, :response_format, :seed, :stop, :tools_choice, :plugins,
445
+
446
+ # OpenRouter Provider Settings
447
+ :data_collection, :require_parameters, :only, :ignore, :quantizations, :sort, :max_price
429
448
  )
430
449
  # Handle explicit options parameter
431
450
  explicit_options = prompt_options[:options] || {}
@@ -30,7 +30,12 @@ module ActiveAgent
30
30
  @action_name = attributes.fetch(:action_name, nil)
31
31
  @mcp_servers = attributes.fetch(:mcp_servers, [])
32
32
  set_message if attributes[:message].is_a?(String) || @body.is_a?(String) && @message&.content
33
- set_messages if @instructions.present?
33
+ # Ensure we have a system message with instructions at the start
34
+ if @messages.empty? || @messages[0].role != :system
35
+ @messages.unshift(instructions_message)
36
+ elsif @instructions.present?
37
+ @messages[0] = instructions_message
38
+ end
34
39
  end
35
40
 
36
41
  def multimodal?
@@ -39,17 +44,22 @@ module ActiveAgent
39
44
 
40
45
  def messages=(messages)
41
46
  @messages = messages
42
- set_messages
47
+ # Only add system message if we have instructions and don't already have a system message
48
+ if @instructions.present? && (@messages.empty? || @messages.first&.role != :system)
49
+ set_messages
50
+ end
43
51
  end
44
52
 
45
53
  def instructions=(instructions)
46
- return if instructions.blank?
54
+ # Store the instructions even if blank (will use empty string)
55
+ @instructions = instructions || ""
47
56
 
48
- @instructions = instructions
57
+ # Update or add the system message
49
58
  if @messages[0].present? && @messages[0].role == :system
50
59
  @messages[0] = instructions_message
51
- else
52
- set_messages
60
+ elsif @messages.empty? || @messages[0].role != :system
61
+ # Only add system message if we don't have one at the start
62
+ @messages.unshift(instructions_message)
53
63
  end
54
64
  end
55
65
 
@@ -7,7 +7,6 @@ module ActiveAgent
7
7
  included do
8
8
  include ActiveSupport::Callbacks
9
9
  define_callbacks :generation, skip_after_callbacks_if_terminated: true
10
- define_callbacks :stream, skip_after_callbacks_if_terminated: true
11
10
  end
12
11
 
13
12
  module ClassMethods
@@ -20,20 +19,6 @@ module ActiveAgent
20
19
  end
21
20
  end
22
21
  end
23
-
24
- # Defines a callback for handling streaming responses during generation
25
- def on_stream(*names, &blk)
26
- _insert_callbacks(names, blk) do |name, options|
27
- set_callback(:stream, :before, name, options)
28
- end
29
- end
30
- end
31
-
32
- # Helper method to run stream callbacks
33
- def run_stream_callbacks(message, delta = nil, stop = false)
34
- run_callbacks(:stream) do
35
- yield(message, delta, stop) if block_given?
36
- end
37
22
  end
38
23
  end
39
24
  end
@@ -36,9 +36,12 @@ module ActiveAgent
36
36
  end
37
37
 
38
38
  def chat_prompt(parameters: prompt_parameters)
39
- parameters[:stream] = provider_stream if prompt.options[:stream] || config["stream"]
39
+ if prompt.options[:stream] || config["stream"]
40
+ parameters[:stream] = provider_stream
41
+ @streaming_request_params = parameters
42
+ end
40
43
 
41
- chat_response(@client.messages(parameters: parameters))
44
+ chat_response(@client.messages(parameters: parameters), parameters)
42
45
  end
43
46
 
44
47
  protected
@@ -120,7 +123,7 @@ module ActiveAgent
120
123
  end
121
124
  end
122
125
 
123
- def chat_response(response)
126
+ def chat_response(response, request_params = nil)
124
127
  return @response if prompt.options[:stream]
125
128
 
126
129
  content = response["content"].first["text"]
@@ -137,7 +140,8 @@ module ActiveAgent
137
140
  @response = ActiveAgent::GenerationProvider::Response.new(
138
141
  prompt: prompt,
139
142
  message: message,
140
- raw_response: response
143
+ raw_response: response,
144
+ raw_request: request_params
141
145
  )
142
146
  end
143
147
 
@@ -94,12 +94,12 @@ module ActiveAgent
94
94
  def format_single_tool_call(action)
95
95
  # Default tool call format (OpenAI style)
96
96
  {
97
+ id: action.id,
97
98
  type: "function",
98
99
  function: {
99
100
  name: action.name,
100
101
  arguments: action.params.is_a?(String) ? action.params : action.params.to_json
101
- },
102
- id: action.id
102
+ }
103
103
  }
104
104
  end
105
105
  end
@@ -1,5 +1,5 @@
1
1
  begin
2
- gem "ruby-openai", "~> 8.2.0"
2
+ gem "ruby-openai", ">= 8.1.0"
3
3
  require "openai"
4
4
  rescue LoadError
5
5
  raise LoadError, "The 'ruby-openai' gem is required for OpenAIProvider. Please add it to your Gemfile and run `bundle install`."
@@ -69,7 +69,12 @@ module ActiveAgent
69
69
  elsif chunk.dig("choices", 0, "delta", "tool_calls") && chunk.dig("choices", 0, "delta", "role")
70
70
  message = handle_message(chunk.dig("choices", 0, "delta"))
71
71
  prompt.messages << message
72
- @response = ActiveAgent::GenerationProvider::Response.new(prompt:, message:)
72
+ @response = ActiveAgent::GenerationProvider::Response.new(
73
+ prompt:,
74
+ message:,
75
+ raw_response: chunk,
76
+ raw_request: @streaming_request_params
77
+ )
73
78
  end
74
79
 
75
80
  if chunk.dig("choices", 0, "finish_reason")
@@ -92,7 +97,7 @@ module ActiveAgent
92
97
  # The format_tools method comes from ToolManagement module
93
98
  # The provider_messages method comes from MessageFormatting module
94
99
 
95
- def chat_response(response)
100
+ def chat_response(response, request_params = nil)
96
101
  return @response if prompt.options[:stream]
97
102
  message_json = response.dig("choices", 0, "message")
98
103
  message_json["id"] = response.dig("id") if message_json["id"].blank?
@@ -100,10 +105,15 @@ module ActiveAgent
100
105
 
101
106
  update_context(prompt: prompt, message: message, response: response)
102
107
 
103
- @response = ActiveAgent::GenerationProvider::Response.new(prompt: prompt, message: message, raw_response: response)
108
+ @response = ActiveAgent::GenerationProvider::Response.new(
109
+ prompt: prompt,
110
+ message: message,
111
+ raw_response: response,
112
+ raw_request: request_params
113
+ )
104
114
  end
105
115
 
106
- def responses_response(response)
116
+ def responses_response(response, request_params = nil)
107
117
  message_json = response["output"].find { |output_item| output_item["type"] == "message" }
108
118
  message_json["id"] = response.dig("id") if message_json["id"].blank?
109
119
 
@@ -116,7 +126,12 @@ module ActiveAgent
116
126
  content_type: prompt.output_schema.present? ? "application/json" : "text/plain",
117
127
  )
118
128
 
119
- @response = ActiveAgent::GenerationProvider::Response.new(prompt: prompt, message: message, raw_response: response)
129
+ @response = ActiveAgent::GenerationProvider::Response.new(
130
+ prompt: prompt,
131
+ message: message,
132
+ raw_response: response,
133
+ raw_request: request_params
134
+ )
120
135
  end
121
136
 
122
137
  def handle_message(message_json)
@@ -133,13 +148,16 @@ module ActiveAgent
133
148
  # handle_actions is now provided by ToolManagement module
134
149
 
135
150
  def chat_prompt(parameters: prompt_parameters)
136
- parameters[:stream] = provider_stream if prompt.options[:stream] || config["stream"]
137
- chat_response(@client.chat(parameters: parameters))
151
+ if prompt.options[:stream] || config["stream"]
152
+ parameters[:stream] = provider_stream
153
+ @streaming_request_params = parameters
154
+ end
155
+ chat_response(@client.chat(parameters: parameters), parameters)
138
156
  end
139
157
 
140
158
  def responses_prompt(parameters: responses_parameters)
141
159
  # parameters[:stream] = provider_stream if prompt.options[:stream] || config["stream"]
142
- responses_response(@client.responses.create(parameters: parameters))
160
+ responses_response(@client.responses.create(parameters: parameters), parameters)
143
161
  end
144
162
 
145
163
  def responses_parameters(model: @prompt.options[:model] || @model_name, messages: @prompt.messages, temperature: @prompt.options[:temperature] || @config["temperature"] || 0.7, tools: @prompt.actions, structured_output: @prompt.output_schema)
@@ -158,14 +176,20 @@ module ActiveAgent
158
176
  }
159
177
  end
160
178
 
161
- def embeddings_response(response)
179
+ def embeddings_response(response, request_params = nil)
162
180
  message = ActiveAgent::ActionPrompt::Message.new(content: response.dig("data", 0, "embedding"), role: "assistant")
163
181
 
164
- @response = ActiveAgent::GenerationProvider::Response.new(prompt: prompt, message: message, raw_response: response)
182
+ @response = ActiveAgent::GenerationProvider::Response.new(
183
+ prompt: prompt,
184
+ message: message,
185
+ raw_response: response,
186
+ raw_request: request_params
187
+ )
165
188
  end
166
189
 
167
190
  def embeddings_prompt(parameters:)
168
- embeddings_response(@client.embeddings(parameters: embeddings_parameters))
191
+ params = embeddings_parameters
192
+ embeddings_response(@client.embeddings(parameters: params), params)
169
193
  end
170
194
  end
171
195
  end
@@ -23,12 +23,22 @@ module ActiveAgent
23
23
  # Data collection preference (allow, deny, or specific provider list)
24
24
  @data_collection = config["data_collection"] || @provider_preferences["data_collection"] || "allow"
25
25
 
26
+ # Require parameters preference (defaults to false)
27
+ @require_parameters = config["require_parameters"] || @provider_preferences["require_parameters"] || false
28
+
29
+ # Additional OpenRouter provider routing options
30
+ @only_providers = config["only"] || @provider_preferences["only"]
31
+ @ignore_providers = config["ignore"] || @provider_preferences["ignore"]
32
+ @quantizations = config["quantizations"] || @provider_preferences["quantizations"]
33
+ @sort_preference = config["sort"] || @provider_preferences["sort"]
34
+ @max_price = config["max_price"] || @provider_preferences["max_price"]
35
+
26
36
  # Initialize OpenAI client with OpenRouter base URL
27
37
  @client = OpenAI::Client.new(
28
38
  uri_base: "https://openrouter.ai/api/v1",
29
39
  access_token: @access_token,
30
40
  log_errors: Rails.env.development?,
31
- default_headers: openrouter_headers
41
+ extra_headers: openrouter_headers
32
42
  )
33
43
  end
34
44
 
@@ -144,9 +154,15 @@ module ActiveAgent
144
154
  parameters[:transforms] = @transforms if @transforms.present?
145
155
 
146
156
  # Add provider preferences (always include if we have data_collection or other settings)
147
- # Check both configured and runtime data_collection values
157
+ # Check both configured and runtime data_collection/require_parameters values
148
158
  runtime_data_collection = prompt&.options&.key?(:data_collection)
149
- if @provider_preferences.present? || @data_collection != "allow" || runtime_data_collection
159
+ runtime_require_parameters = prompt&.options&.key?(:require_parameters)
160
+ runtime_provider_options = prompt&.options&.keys&.any? { |k| [ :only, :ignore, :quantizations, :sort, :max_price ].include?(k) }
161
+
162
+ if @provider_preferences.present? || @data_collection != "allow" || @require_parameters != false ||
163
+ @only_providers.present? || @ignore_providers.present? || @quantizations.present? ||
164
+ @sort_preference.present? || @max_price.present? ||
165
+ runtime_data_collection || runtime_require_parameters || runtime_provider_options
150
166
  parameters[:provider] = build_provider_preferences
151
167
  end
152
168
 
@@ -160,7 +176,12 @@ module ActiveAgent
160
176
  def build_provider_preferences
161
177
  prefs = {}
162
178
  prefs[:order] = @provider_preferences["order"] if @provider_preferences["order"]
163
- prefs[:require_parameters] = @provider_preferences["require_parameters"] if @provider_preferences.key?("require_parameters")
179
+
180
+ # Require parameters can be overridden at runtime
181
+ require_parameters = prompt.options[:require_parameters] if prompt&.options&.key?(:require_parameters)
182
+ require_parameters = @require_parameters if require_parameters.nil?
183
+ prefs[:require_parameters] = require_parameters if require_parameters != false
184
+
164
185
  prefs[:allow_fallbacks] = @enable_fallbacks
165
186
 
166
187
  # Data collection can be:
@@ -172,6 +193,27 @@ module ActiveAgent
172
193
  data_collection ||= @data_collection
173
194
  prefs[:data_collection] = data_collection
174
195
 
196
+ # Additional OpenRouter provider routing options - check runtime overrides first
197
+ only_providers = prompt.options[:only] if prompt&.options&.key?(:only)
198
+ only_providers ||= @only_providers
199
+ prefs[:only] = only_providers if only_providers.present?
200
+
201
+ ignore_providers = prompt.options[:ignore] if prompt&.options&.key?(:ignore)
202
+ ignore_providers ||= @ignore_providers
203
+ prefs[:ignore] = ignore_providers if ignore_providers.present?
204
+
205
+ quantizations = prompt.options[:quantizations] if prompt&.options&.key?(:quantizations)
206
+ quantizations ||= @quantizations
207
+ prefs[:quantizations] = quantizations if quantizations.present?
208
+
209
+ sort_preference = prompt.options[:sort] if prompt&.options&.key?(:sort)
210
+ sort_preference ||= @sort_preference
211
+ prefs[:sort] = sort_preference if sort_preference.present?
212
+
213
+ max_price = prompt.options[:max_price] if prompt&.options&.key?(:max_price)
214
+ max_price ||= @max_price
215
+ prefs[:max_price] = max_price if max_price.present?
216
+
175
217
  prefs.compact
176
218
  end
177
219
 
@@ -186,9 +228,15 @@ module ActiveAgent
186
228
  params[:transforms] = @transforms if @transforms.present?
187
229
 
188
230
  # Add provider configuration (always include if we have data_collection or other settings)
189
- # Check both configured and runtime data_collection values
231
+ # Check both configured and runtime data_collection/require_parameters values
190
232
  runtime_data_collection = prompt&.options&.key?(:data_collection)
191
- if @provider_preferences.present? || @data_collection != "allow" || runtime_data_collection
233
+ runtime_require_parameters = prompt&.options&.key?(:require_parameters)
234
+ runtime_provider_options = prompt&.options&.keys&.any? { |k| [ :only, :ignore, :quantizations, :sort, :max_price ].include?(k) }
235
+
236
+ if @provider_preferences.present? || @data_collection != "allow" || @require_parameters != false ||
237
+ @only_providers.present? || @ignore_providers.present? || @quantizations.present? ||
238
+ @sort_preference.present? || @max_price.present? ||
239
+ runtime_data_collection || runtime_require_parameters || runtime_provider_options
192
240
  params[:provider] = build_provider_preferences
193
241
  end
194
242
 
@@ -3,13 +3,14 @@
3
3
  module ActiveAgent
4
4
  module GenerationProvider
5
5
  class Response
6
- attr_reader :message, :prompt, :raw_response
6
+ attr_reader :message, :prompt, :raw_response, :raw_request
7
7
  attr_accessor :metadata
8
8
 
9
- def initialize(prompt:, message: nil, raw_response: nil, metadata: nil)
9
+ def initialize(prompt:, message: nil, raw_response: nil, raw_request: nil, metadata: nil)
10
10
  @prompt = prompt
11
11
  @message = message || prompt.message
12
12
  @raw_response = raw_response
13
+ @raw_request = sanitize_request(raw_request)
13
14
  @metadata = metadata || {}
14
15
  end
15
16
 
@@ -17,14 +18,9 @@ module ActiveAgent
17
18
  def usage
18
19
  return nil unless @raw_response
19
20
 
20
- # OpenAI/OpenRouter format
21
+ # Most providers store usage in the same format
21
22
  if @raw_response.is_a?(Hash) && @raw_response["usage"]
22
23
  @raw_response["usage"]
23
- # Anthropic format
24
- elsif @raw_response.is_a?(Hash) && @raw_response["usage"]
25
- @raw_response["usage"]
26
- else
27
- nil
28
24
  end
29
25
  end
30
26
 
@@ -40,6 +36,40 @@ module ActiveAgent
40
36
  def total_tokens
41
37
  usage&.dig("total_tokens")
42
38
  end
39
+
40
+ private
41
+
42
+ def sanitize_request(request)
43
+ return nil if request.nil?
44
+ return request unless request.is_a?(Hash)
45
+
46
+ # Deep clone the request to avoid modifying the original
47
+ sanitized = request.deep_dup
48
+
49
+ # Sanitize any string values in the request
50
+ sanitize_hash_values(sanitized)
51
+ end
52
+
53
+ def sanitize_hash_values(hash)
54
+ hash.each do |key, value|
55
+ case value
56
+ when String
57
+ # Use ActiveAgent's sanitize_credentials to replace sensitive data
58
+ hash[key] = ActiveAgent.sanitize_credentials(value)
59
+ when Hash
60
+ sanitize_hash_values(value)
61
+ when Array
62
+ value.each_with_index do |item, index|
63
+ if item.is_a?(String)
64
+ value[index] = ActiveAgent.sanitize_credentials(item)
65
+ elsif item.is_a?(Hash)
66
+ sanitize_hash_values(item)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ hash
72
+ end
43
73
  end
44
74
  end
45
75
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAgent
4
+ module Streaming
5
+ extend ActiveSupport::Concern
6
+
7
+ class StreamChunk < Data.define(:delta, :stop)
8
+ end
9
+
10
+ attr_accessor :stream_chunk
11
+
12
+ included do
13
+ include ActiveSupport::Callbacks
14
+ define_callbacks :stream, skip_after_callbacks_if_terminated: true
15
+ end
16
+
17
+ module ClassMethods
18
+ # Defines a callback for handling streaming responses during generation
19
+ def on_stream(*names, &blk)
20
+ _insert_callbacks(names, blk) do |name, options|
21
+ set_callback(:stream, :before, name, options)
22
+ end
23
+ end
24
+ end
25
+
26
+ # Helper method to run stream callbacks
27
+ def run_stream_callbacks(message, delta = nil, stop = false)
28
+ @stream_chunk = StreamChunk.new(delta, stop)
29
+ run_callbacks(:stream) do
30
+ yield(message, delta, stop) if block_given?
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveAgent
2
- VERSION = "0.6.0rc2"
2
+ VERSION = "0.6.0rc4"
3
3
  end
data/lib/active_agent.rb CHANGED
@@ -23,6 +23,7 @@ module ActiveAgent
23
23
 
24
24
  autoload :Base
25
25
  autoload :Callbacks
26
+ autoload :Streaming
26
27
  autoload :InlinePreviewInterceptor
27
28
  autoload :PromptHelper
28
29
  autoload :Generation
@@ -9,7 +9,6 @@ module Erb # :nodoc:
9
9
  def create_agent_layouts
10
10
  if behavior == :invoke
11
11
  formats.each do |format|
12
- puts format
13
12
  layout_path = File.join("app/views/layouts", filename_with_extensions("agent", format))
14
13
  template filename_with_extensions(:layout, format), layout_path unless File.exist?(layout_path)
15
14
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeagent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0rc2
4
+ version: 0.6.0rc4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Bowen
@@ -141,16 +141,16 @@ dependencies:
141
141
  name: ruby-openai
142
142
  requirement: !ruby/object:Gem::Requirement
143
143
  requirements:
144
- - - "~>"
144
+ - - ">="
145
145
  - !ruby/object:Gem::Version
146
- version: 8.2.0
146
+ version: 8.1.0
147
147
  type: :development
148
148
  prerelease: false
149
149
  version_requirements: !ruby/object:Gem::Requirement
150
150
  requirements:
151
- - - "~>"
151
+ - - ">="
152
152
  - !ruby/object:Gem::Version
153
- version: 8.2.0
153
+ version: 8.1.0
154
154
  - !ruby/object:Gem::Dependency
155
155
  name: ruby-anthropic
156
156
  requirement: !ruby/object:Gem::Requirement
@@ -298,6 +298,7 @@ files:
298
298
  - lib/active_agent/rescuable.rb
299
299
  - lib/active_agent/sanitizers.rb
300
300
  - lib/active_agent/service.rb
301
+ - lib/active_agent/streaming.rb
301
302
  - lib/active_agent/test_case.rb
302
303
  - lib/active_agent/version.rb
303
304
  - lib/activeagent.rb