activeagent 0.2.5 → 0.2.5.202503060823

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: cbfba3a78246c1008e29842f64cfb2bd880e2a33800639590324844ce6045bcd
4
- data.tar.gz: a52d61ba1dac3d01ae6b84db9d70d81cb230dc1a975897218b48e372392710c3
3
+ metadata.gz: 87f9e1274f4d7ed4546eef11619ca81ffa0def6713414fab764ae264753dfb90
4
+ data.tar.gz: 5c13b957ed730b58356a5fbb7c7e2ab4bc3032b8960cabd555f6e352ca74ff70
5
5
  SHA512:
6
- metadata.gz: a85609f0e5d816b9fabe84fdbf589d2da716c740aa2406386c3c6cf0898436ac1d57ee04adca0d99418d2b38fd4c88c700ff468d1a6040869c3b22b790c2c780
7
- data.tar.gz: 040fb0a37075cb2fc691be6b42e0395b7b3ab664e869a984f6581ee3c7a7357864676699af852e6b3e76e2ae765ab403e6a6e04cff46aa544f83b2e156fa86aa
6
+ metadata.gz: a94a933b7436f45d92cc75f6bf600428d0d7b2a6a62b8578fc2defbaec8637c1d28563eab9c4868bc8caac4d45d02a4beb8ba26decf9c8b7c1141103fc3fbb0b
7
+ data.tar.gz: ed85714725dada7f2911af809e1f4eb78af9db4ad73e8939964abea40861b39e9e5d7273be02aa58bd0ace6ce225c1f8f9d33e5740a56e00f72ae0299794ee13
@@ -12,7 +12,7 @@ module ActiveAgent
12
12
  @instructions = attributes.fetch(:instructions, "")
13
13
  @body = attributes.fetch(:body, "")
14
14
  @content_type = attributes.fetch(:content_type, "text/plain")
15
- @message = attributes.fetch(:message, Message.new)
15
+ @message = attributes.fetch(:message, nil)
16
16
  @messages = attributes.fetch(:messages, [])
17
17
  @params = attributes.fetch(:params, {})
18
18
  @mime_version = attributes.fetch(:mime_version, "1.0")
@@ -21,7 +21,7 @@ module ActiveAgent
21
21
  @headers = attributes.fetch(:headers, {})
22
22
  @parts = attributes.fetch(:parts, [])
23
23
 
24
- set_message if attributes[:message].is_a?(String) || @body.is_a?(String) && @message.content
24
+ set_message if attributes[:message].is_a?(String) || @body.is_a?(String) && @message&.content
25
25
  set_messages if @messages.any? || @instructions.present?
26
26
  end
27
27
 
@@ -30,12 +30,11 @@ module ActiveAgent
30
30
  @message.to_s
31
31
  end
32
32
 
33
- def add_part(prompt_part)
34
- @message = prompt_part.message
33
+ def add_part(message)
34
+ @message = message
35
+ set_message if @content_type == message.content_type && @message.content.present?
35
36
 
36
- set_message if @content_type == prompt_part.content_type && @message.content.present?
37
-
38
- @parts << prompt_part
37
+ @parts << context
39
38
  end
40
39
 
41
40
  def multipart?
@@ -128,8 +128,8 @@ module ActiveAgent
128
128
  # Define how the agent should generate content
129
129
  def generate_with(provider, **options)
130
130
  self.generation_provider = provider
131
- self.options = (options || {}).merge(options)
132
- generation_provider.config.merge!(options)
131
+ self.options = (options || {}).merge(options)
132
+ generation_provider.config.merge!(self.options)
133
133
  end
134
134
 
135
135
  def stream_with(&stream)
@@ -203,20 +203,27 @@ module ActiveAgent
203
203
  attr_internal :context
204
204
 
205
205
  def perform_generation
206
- context.options.merge(options)
206
+ context.options.merge(options)
207
207
  generation_provider.generate(context) if context && generation_provider
208
- handle_response(generation_provider.response)
209
- generation_provider.response
208
+ handle_response(generation_provider.response)
210
209
  end
211
210
 
212
211
  def handle_response(response)
213
212
  perform_actions(requested_actions: response.message.requested_actions) if response.message.requested_actions.present?
214
- update_context(response)
213
+
214
+ update_context(response)
215
215
  end
216
216
 
217
217
  def update_context(response)
218
+ if response.prompt.message != response.prompt.messages.last
219
+ response = ActiveAgent::GenerationProvider::Response.new(
220
+ prompt: response.prompt,
221
+ message: response.prompt.messages.last,
222
+ raw_response: response.raw_response
223
+ )
224
+ end
218
225
  context.message = response.message
219
- context.messages << response.message
226
+ response
220
227
  end
221
228
 
222
229
  def perform_actions(requested_actions:)
@@ -232,7 +239,7 @@ module ActiveAgent
232
239
  def initialize
233
240
  super
234
241
  @_prompt_was_called = false
235
- @_context = ActiveAgent::ActionPrompt::Prompt.new(instructions: options[:instructions])
242
+ @_context = ActiveAgent::ActionPrompt::Prompt.new(instructions: options[:instructions], options: options)
236
243
  end
237
244
 
238
245
  def process(method_name, *args) # :nodoc:
@@ -332,7 +339,7 @@ module ActiveAgent
332
339
 
333
340
  def action_schemas
334
341
  action_methods.map do |action|
335
- if action != "prompt"
342
+ if action != "text_prompt"
336
343
  JSON.parse render_to_string(locals: {action_name: action}, action: action, formats: :json)
337
344
  end
338
345
  end.compact
@@ -431,24 +438,22 @@ module ActiveAgent
431
438
 
432
439
  def create_parts_from_responses(context, responses)
433
440
  if responses.size > 1
434
- prompt_container = ActiveAgent::ActionPrompt::Prompt.new
435
- prompt_container.content_type = "multipart/alternative"
441
+ # prompt_container = ActiveAgent::ActionPrompt::Prompt.new
442
+ # prompt_container.content_type = "multipart/alternative"
436
443
  responses.each { |r| insert_part(context, r, context.charset) }
437
- context.add_part(prompt_container)
444
+ # context.add_part(prompt_container)
438
445
  else
439
446
  responses.each { |r| insert_part(context, r, context.charset) }
440
447
  end
441
448
  end
442
449
 
443
- def insert_part(container, response, charset)
444
- prompt = ActiveAgent::ActionPrompt::Prompt.new
450
+ def insert_part(context, response, charset)
445
451
  message = ActiveAgent::ActionPrompt::Message.new(
446
452
  content: response[:body],
447
453
  content_type: response[:content_type],
448
454
  charset: charset
449
455
  )
450
- prompt.message = message
451
- container.add_part(prompt)
456
+ context.add_part(message)
452
457
  end
453
458
  # This and #instrument_name is for caching instrument
454
459
  def instrument_payload(key)
@@ -7,6 +7,7 @@ module ActiveAgent
7
7
  included do
8
8
  include ActiveSupport::Callbacks
9
9
  define_callbacks :generate, skip_after_callbacks_if_terminated: true
10
+ define_callbacks :stream, skip_after_callbacks_if_terminated: true
10
11
  end
11
12
 
12
13
  module ClassMethods
@@ -26,6 +27,18 @@ module ActiveAgent
26
27
  def around_generate(*filters, &)
27
28
  set_callback(:generate, :around, *filters, &)
28
29
  end
30
+
31
+ # Defines a callback for handling streaming responses during generation
32
+ def on_stream(*filters, &)
33
+ set_callback(:stream, :before, *filters, &)
34
+ end
35
+ end
36
+
37
+ # Helper method to run stream callbacks
38
+ def run_stream_callbacks(message, delta = nil, stop = false)
39
+ run_callbacks(:stream) do
40
+ yield(message, delta, stop) if block_given?
41
+ end
29
42
  end
30
43
  end
31
- end
44
+ end
@@ -23,7 +23,7 @@ module ActiveAgent
23
23
  agent = agent_class.new
24
24
  agent.params = params if params
25
25
  agent.process(action_name, *args)
26
- agent.generate
26
+ agent.generate_now
27
27
  end
28
28
 
29
29
  private
@@ -25,7 +25,6 @@ module ActiveAgent
25
25
 
26
26
  def update_context(prompt:, message:, response:)
27
27
  prompt.message = message
28
- prompt.messages << message
29
28
  end
30
29
 
31
30
  protected
@@ -17,7 +17,8 @@ module ActiveAgent
17
17
 
18
18
  def generate(prompt)
19
19
  @prompt = prompt
20
-
20
+
21
+ # prompt_parameters(model: @model_name, messages: prompt.messages, tools: prompt.actions)
21
22
  # parameters[:instructions] = prompt.instructions.content if prompt.instructions.present?
22
23
 
23
24
  chat_prompt(parameters: prompt_parameters)
@@ -60,19 +61,19 @@ module ActiveAgent
60
61
  def provider_stream
61
62
  # prompt.options[:stream] will define a proc found in prompt at runtime
62
63
  # config[:stream] will define a proc found in config. stream would come from an Agent class's generate_with or stream_with method calls
63
- agent_stream = prompt.options[:stream] || config["stream"]
64
+ agent_stream = prompt.options[:stream]
65
+ message = ActiveAgent::ActionPrompt::Message.new(content: "", role: :assistant)
66
+ @response = ActiveAgent::GenerationProvider::Response.new(prompt: prompt, message: )
67
+
64
68
  proc do |chunk, bytesize|
65
- # Provider parsing logic here
66
- new_content = chunk.dig("choices", 0, "delta", "content")
67
- message = @prompt.messages.find { |message| message.response_number == chunk.dig("choices", 0, "index") }
68
- message.update(content: message.content + new_content) if new_content
69
-
70
- # Call the custom stream_proc if provided
71
- agent_stream.call(message) if agent_stream.respond_to?(:call)
69
+ if new_content = chunk.dig("choices", 0, "delta", "content")
70
+ message.content += new_content
71
+ agent_stream.call(message) if agent_stream.respond_to?(:call)
72
+ end
72
73
  end
73
74
  end
74
75
 
75
- def prompt_parameters(model: @model_name, messages: @prompt.messages, temperature: @config["temperature"] || 0.7, tools: @prompt.actions)
76
+ def prompt_parameters(model: @prompt.options[:model] || @model_name, messages: @prompt.messages, temperature: @config["temperature"] || 0.7, tools: @prompt.actions)
76
77
  {
77
78
  model: model,
78
79
  messages: messages,
@@ -82,7 +83,10 @@ module ActiveAgent
82
83
  end
83
84
 
84
85
  def chat_response(response)
86
+ return @response if prompt.options[:stream]
87
+
85
88
  message_json = response.dig("choices", 0, "message")
89
+
86
90
  message = ActiveAgent::ActionPrompt::Message.new(
87
91
  content: message_json["content"],
88
92
  role: message_json["role"],
@@ -1,3 +1,3 @@
1
1
  module ActiveAgent
2
- VERSION = "0.2.5"
2
+ VERSION = "0.2.5.202503060823"
3
3
  end
@@ -4,8 +4,8 @@ class ApplicationAgent < ActiveAgent::Base
4
4
 
5
5
  generate_with :openai, model: "gpt-4o-mini", instructions: "You are a helpful assistant."
6
6
 
7
- def prompt
8
- super { |format| format.text { render plain: params[:message] } }
7
+ def text_prompt
8
+ prompt { |format| format.text { render plain: params[:message] } }
9
9
  end
10
10
  end
11
11
  <% end %>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeagent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.2.5.202503060823
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Bowen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-02-28 00:00:00.000000000 Z
11
+ date: 2025-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack