activeagent 0.4.0 → 0.4.1

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: 8567895dba91f6a677d35693b104e3a85f138cfcba9d6e5a2e0b50d536d435c9
4
- data.tar.gz: 5debb8cd50b84a5d4859df01fefcd4b9161c30aae75a0dd1a53e08054331b554
3
+ metadata.gz: c93bac60dcbdb44bfc6461435f84e79499682db83a93ea07526a5b546c2a1b63
4
+ data.tar.gz: c3a7a995862ef152661b1ede6c012e17747c190853cdc501e0a0f99445c7fe40
5
5
  SHA512:
6
- metadata.gz: d1aabd80bf2ee0e66141de25f799beb042aa662006a8c2bc96d083f86dfd02fd3518732da58dedc8ad09347ee7262c16c1b0244b433bbbe556d980e8ed6027d6
7
- data.tar.gz: ab612e4af865564a94fed7cb8bf0626e696a5a54b3302b14505f36f58a4d55e3716340175b815a020430f903e2e8fe8f61f2d50ef4ca6ac4d027780952964cd0
6
+ metadata.gz: 5e2836e13ca5d353d221a33643c7c101320e2615982dceccf4dfdf25c9e9fe9bbdeb48503aa70d1a21ed1dd8cfdab0ec76348342dbbd29dc5cfb59f9306266f9
7
+ data.tar.gz: edaddc4339c00242935f0ba70fdc95f98547c12ccd6d4b4da9cd4081dd051e3521c6b4bdb5745fe6e7a382e462024b0dc0aec12eacd730b2ebc5f12a81315d35
@@ -173,7 +173,7 @@ module ActiveAgent
173
173
  end
174
174
  end
175
175
 
176
- attr_internal :prompt_context
176
+ attr_internal :context
177
177
 
178
178
  def agent_stream
179
179
  proc do |message, delta, stop|
@@ -184,8 +184,8 @@ module ActiveAgent
184
184
  end
185
185
 
186
186
  def embed
187
- prompt_context.options.merge(options)
188
- generation_provider.embed(prompt_context) if prompt_context && generation_provider
187
+ context.options.merge(options)
188
+ generation_provider.embed(context) if context && generation_provider
189
189
  handle_response(generation_provider.response)
190
190
  end
191
191
 
@@ -194,34 +194,34 @@ module ActiveAgent
194
194
  def embed
195
195
  agent_class = ActiveAgent::Base.descendants.first
196
196
  agent = agent_class.new
197
- agent.prompt_context = ActiveAgent::ActionPrompt::Prompt.new(message: self)
197
+ agent.context = ActiveAgent::ActionPrompt::Prompt.new(message: self)
198
198
  agent.embed
199
199
  self
200
200
  end
201
201
  end
202
202
 
203
- # Make prompt_context accessible for chaining
204
- # attr_accessor :prompt_context
203
+ # Make context accessible for chaining
204
+ # attr_accessor :context
205
205
 
206
206
  def perform_generation
207
- prompt_context.options.merge(options)
207
+ context.options.merge(options)
208
208
  if (action_methods - ActiveAgent::Base.descendants.first.action_methods).include? action_name
209
- prompt_context.message = prompt_context.messages.last
210
- prompt_context.actions = []
209
+ context.message = context.messages.last
210
+ context.actions = []
211
211
  end
212
- generation_provider.generate(prompt_context) if prompt_context && generation_provider
212
+ generation_provider.generate(context) if context && generation_provider
213
213
  handle_response(generation_provider.response)
214
214
  end
215
215
 
216
216
  def handle_response(response)
217
217
  return response unless response.message.requested_actions.present?
218
218
  perform_actions(requested_actions: response.message.requested_actions)
219
- update_prompt_context(response)
219
+ update_context(response)
220
220
  end
221
221
 
222
- def update_prompt_context(response)
223
- prompt_context.message = prompt_context.messages.last
224
- ActiveAgent::GenerationProvider::Response.new(prompt: prompt_context)
222
+ def update_context(response)
223
+ context.message = context.messages.last
224
+ ActiveAgent::GenerationProvider::Response.new(prompt: context)
225
225
  end
226
226
 
227
227
  def perform_actions(requested_actions:)
@@ -231,20 +231,20 @@ module ActiveAgent
231
231
  end
232
232
 
233
233
  def perform_action(action)
234
- current_context = prompt_context.clone
234
+ current_context = context.clone
235
235
  process(action.name, *action.params)
236
- prompt_context.messages.last.role = :tool
237
- prompt_context.messages.last.action_id = action.id
238
- prompt_context.messages.last.action_name = action.name
239
- prompt_context.messages.last.generation_id = action.id
240
- current_context.messages << prompt_context.messages.last
241
- self.prompt_context = current_context
236
+ context.messages.last.role = :tool
237
+ context.messages.last.action_id = action.id
238
+ context.messages.last.action_name = action.name
239
+ context.messages.last.generation_id = action.id
240
+ current_context.messages << context.messages.last
241
+ self.context = current_context
242
242
  end
243
243
 
244
244
  def initialize
245
245
  super
246
246
  @_prompt_was_called = false
247
- @_prompt_context = ActiveAgent::ActionPrompt::Prompt.new(instructions: options[:instructions], options: options)
247
+ @_context = ActiveAgent::ActionPrompt::Prompt.new(instructions: options[:instructions], options: options)
248
248
  end
249
249
 
250
250
  def process(method_name, *args) # :nodoc:
@@ -256,7 +256,7 @@ module ActiveAgent
256
256
 
257
257
  ActiveSupport::Notifications.instrument("process.active_agent", payload) do
258
258
  super
259
- @_prompt_context = ActiveAgent::ActionPrompt::Prompt.new unless @_prompt_was_called
259
+ @_context = ActiveAgent::ActionPrompt::Prompt.new unless @_prompt_was_called
260
260
  end
261
261
  end
262
262
  ruby2_keywords(:process)
@@ -286,24 +286,24 @@ module ActiveAgent
286
286
 
287
287
  def headers(args = nil)
288
288
  if args
289
- @_prompt_context.headers(args)
289
+ @_context.headers(args)
290
290
  else
291
- @_prompt_context
291
+ @_context
292
292
  end
293
293
  end
294
294
 
295
295
  def prompt_with(*)
296
- prompt_context.update_prompt_context(*)
296
+ context.update_context(*)
297
297
  end
298
298
 
299
299
  def prompt(headers = {}, &block)
300
- return prompt_context if @_prompt_was_called && headers.blank? && !block
300
+ return context if @_prompt_was_called && headers.blank? && !block
301
301
  content_type = headers[:content_type]
302
302
  headers = apply_defaults(headers)
303
- prompt_context.messages = headers[:messages] || []
304
- prompt_context.context_id = headers[:context_id]
303
+ context.messages = headers[:messages] || []
304
+ context.context_id = headers[:context_id]
305
305
 
306
- prompt_context.charset = charset = headers[:charset]
306
+ context.charset = charset = headers[:charset]
307
307
 
308
308
  if headers[:message].present? && headers[:message].is_a?(ActiveAgent::ActionPrompt::Message)
309
309
  headers[:body] = headers[:message].content
@@ -314,25 +314,27 @@ module ActiveAgent
314
314
  end
315
315
 
316
316
  # wrap_generation_behavior!(headers[:generation_method], headers[:generation_method_options])
317
- # assign_headers_to_prompt_context(prompt_context, headers)
317
+ # assign_headers_to_context(context, headers)
318
318
  responses = collect_responses(headers, &block)
319
319
 
320
320
  @_prompt_was_called = true
321
321
 
322
- create_parts_from_responses(prompt_context, responses)
322
+ create_parts_from_responses(context, responses)
323
323
 
324
- prompt_context.content_type = set_content_type(prompt_context, content_type, headers[:content_type])
325
- prompt_context.charset = charset
326
- prompt_context.actions = headers[:actions] || action_schemas
324
+ context.content_type = set_content_type(context, content_type, headers[:content_type])
325
+ context.charset = charset
326
+ context.actions = headers[:actions] || action_schemas
327
327
 
328
- prompt_context
328
+ context
329
+ end
330
+
331
+ def action_methods
332
+ super - ActiveAgent::Base.public_instance_methods(false).map(&:to_s)
329
333
  end
330
334
 
331
335
  def action_schemas
332
336
  action_methods.map do |action|
333
- if action != "text_prompt"
334
- JSON.parse render_to_string(locals: { action_name: action }, action: action, formats: :json)
335
- end
337
+ JSON.parse render_to_string(locals: { action_name: action }, action: action, formats: :json)
336
338
  end.compact
337
339
  end
338
340
 
@@ -342,7 +344,7 @@ module ActiveAgent
342
344
  if user_content_type.present?
343
345
  user_content_type
344
346
  else
345
- prompt_context.content_type || class_default
347
+ context.content_type || class_default
346
348
  end
347
349
  end
348
350
 
@@ -373,11 +375,11 @@ module ActiveAgent
373
375
  end
374
376
  end
375
377
 
376
- def assign_headers_to_prompt_context(prompt_context, headers)
378
+ def assign_headers_to_context(context, headers)
377
379
  assignable = headers.except(:parts_order, :content_type, :body, :role, :template_name,
378
380
  :template_path, :delivery_method, :delivery_method_options)
379
381
 
380
- assignable.each { |k, v| prompt_context.send(k, v) if prompt_context.respond_to?(k) }
382
+ assignable.each { |k, v| context.send(k, v) if context.respond_to?(k) }
381
383
  end
382
384
 
383
385
  def collect_responses(headers, &)
@@ -426,24 +428,24 @@ module ActiveAgent
426
428
  end
427
429
  end
428
430
 
429
- def create_parts_from_responses(prompt_context, responses)
431
+ def create_parts_from_responses(context, responses)
430
432
  if responses.size > 1
431
433
  # prompt_container = ActiveAgent::ActionPrompt::Prompt.new
432
434
  # prompt_container.content_type = "multipart/alternative"
433
- responses.each { |r| insert_part(prompt_context, r, prompt_context.charset) }
434
- # prompt_context.add_part(prompt_container)
435
+ responses.each { |r| insert_part(context, r, context.charset) }
436
+ # context.add_part(prompt_container)
435
437
  else
436
- responses.each { |r| insert_part(prompt_context, r, prompt_context.charset) }
438
+ responses.each { |r| insert_part(context, r, context.charset) }
437
439
  end
438
440
  end
439
441
 
440
- def insert_part(prompt_context, response, charset)
442
+ def insert_part(context, response, charset)
441
443
  message = ActiveAgent::ActionPrompt::Message.new(
442
444
  content: response[:body],
443
445
  content_type: response[:content_type],
444
446
  charset: charset
445
447
  )
446
- prompt_context.add_part(message)
448
+ context.add_part(message)
447
449
  end
448
450
 
449
451
  # This and #instrument_name is for caching instrument
@@ -28,8 +28,8 @@ module ActiveAgent
28
28
  # It is built on top of ActionPrompt which provides methods for generating content, handling actions, and managing prompts.
29
29
  # ActiveAgent::Base is designed to be extended by specific agent implementations.
30
30
  # It provides a common set of agent actions for self-contained agents that can determine their own actions using all available actions.
31
- # Base actions include: text_prompt, continue, reasoning, reiterate, and conclude
32
- def text_prompt
31
+ # Base actions include: prompt_context, continue, reasoning, reiterate, and conclude
32
+ def prompt_context
33
33
  prompt(stream: params[:stream], messages: params[:messages], message: params[:message], context_id: params[:context_id])
34
34
  end
35
35
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveAgent
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -7,10 +7,10 @@ module ActiveAgent
7
7
 
8
8
  argument :actions, type: :array, default: [], banner: "method method"
9
9
 
10
- check_class_collision
10
+ check_class_collision suffix: "Agent"
11
11
 
12
12
  def create_agent_file
13
- template "agent.rb", File.join("app/agents", class_path, "#{file_name}.rb")
13
+ template "agent.rb", File.join("app/agents", class_path, "#{file_name}_agent.rb")
14
14
 
15
15
  in_root do
16
16
  if behavior == :invoke && !File.exist?(application_agent_file_name)
@@ -19,10 +19,12 @@ module ActiveAgent
19
19
  end
20
20
  end
21
21
 
22
+ hook_for :template_engine, :test_framework
23
+
22
24
  private
23
25
 
24
26
  def file_name # :doc:
25
- @_file_name ||= super + "_agent"
27
+ @_file_name ||= super.sub(/_agent\z/i, "")
26
28
  end
27
29
 
28
30
  def application_agent_file_name
@@ -5,18 +5,11 @@ module ActiveAgent
5
5
  class InstallGenerator < ::Rails::Generators::Base
6
6
  source_root File.expand_path("templates", __dir__)
7
7
 
8
+ hook_for :template_engine, :test_framework
9
+
8
10
  def create_configuration
9
11
  template "active_agent.yml", "config/active_agent.yml"
10
12
  end
11
-
12
- def create_application_agent
13
- template "application_agent.rb", "app/agents/application_agent.rb"
14
- end
15
-
16
- def create_agent_layouts
17
- template "agent.html.erb", "app/views/layouts/agent.html.erb"
18
- template "agent.text.erb", "app/views/layouts/agent.text.erb"
19
- end
20
13
  end
21
14
  end
22
15
  end
@@ -1,5 +1,5 @@
1
1
  <% module_namespacing do -%>
2
- class <%= class_name %> < ApplicationAgent
2
+ class <%= class_name %>Agent < ApplicationAgent
3
3
  <% actions.each_with_index do |action, index| -%>
4
4
  <% if index != 0 -%>
5
5
 
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/erb"
4
+
5
+ module Erb # :nodoc:
6
+ module Generators # :nodoc:
7
+ class AgentGenerator < Base # :nodoc:
8
+ source_root File.expand_path("templates", __dir__)
9
+ argument :actions, type: :array, default: [], banner: "method method"
10
+
11
+ def copy_view_files
12
+ view_base_path = File.join("app/views", class_path, file_name + "_agent")
13
+ empty_directory view_base_path
14
+
15
+ if behavior == :invoke
16
+ formats.each do |format|
17
+ layout_path = File.join("app/views/layouts", class_path, filename_with_extensions("agent", format))
18
+ template filename_with_extensions(:layout, format), layout_path unless File.exist?(layout_path)
19
+ end
20
+ end
21
+
22
+ actions.each do |action|
23
+ @action = action
24
+
25
+ formats.each do |format|
26
+ @path = File.join(view_base_path, filename_with_extensions(action, format))
27
+ template filename_with_extensions(:view, format), @path
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def formats
35
+ [ :text, :html ]
36
+ end
37
+
38
+ def file_name
39
+ @_file_name ||= super.sub(/_agent\z/i, "")
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module Erb # :nodoc:
6
+ module Generators # :nodoc:
7
+ class InstallGenerator < ::Rails::Generators::Base # :nodoc:
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ def create_agent_layouts
11
+ template "layout.html.erb.tt", "app/views/layouts/agent.html.erb"
12
+ template "layout.text.erb.tt", "app/views/layouts/agent.text.erb"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ <% module_namespacing do -%>
2
+ class ApplicationAgent < ActiveAgent::Base
3
+ layout 'agent'
4
+
5
+ generate_with :openai, model: "gpt-4o-mini", instructions: "You are a helpful assistant."
6
+ end
7
+ <% end %>
@@ -0,0 +1 @@
1
+ <%%= yield %>
@@ -0,0 +1 @@
1
+ <%%= yield %>
@@ -0,0 +1,5 @@
1
+ <h1><%= class_name %>#<%= @action %></h1>
2
+
3
+ <p>
4
+ <%%= @message %>, find me in <%= @path %>
5
+ </p>
@@ -0,0 +1,3 @@
1
+ <%= class_name %>#<%= @action %>
2
+
3
+ <%%= @message %>, find me in <%= @path %>
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/test_unit"
4
+
5
+ module TestUnit # :nodoc:
6
+ module Generators # :nodoc:
7
+ class AgentGenerator < Base # :nodoc:
8
+ source_root File.expand_path("templates", __dir__)
9
+ argument :actions, type: :array, default: [], banner: "method method"
10
+
11
+ def check_class_collision
12
+ class_collisions "#{class_name}AgentTest", "#{class_name}AgentPreview"
13
+ end
14
+
15
+ def create_test_files
16
+ template "functional_test.rb", File.join("test/agents", class_path, "#{file_name}_agent_test.rb")
17
+ end
18
+
19
+ def create_preview_files
20
+ template "preview.rb", File.join("test/agents/previews", class_path, "#{file_name}_agent_preview.rb")
21
+ end
22
+
23
+ private
24
+
25
+ def file_name
26
+ @_file_name ||= super.sub(/_agent\z/i, "")
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/test_unit"
4
+
5
+ module TestUnit # :nodoc:
6
+ module Generators # :nodoc:
7
+ class InstallGenerator < Base # :nodoc:
8
+ # TestUnit install generator for ActiveAgent
9
+ # This can be used to create additional test-specific files during installation
10
+ # Currently no additional files are needed for TestUnit setup
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ require "test_helper"
2
+
3
+ <% module_namespacing do -%>
4
+ class <%= class_name %>AgentTest < ActiveAgent::TestCase
5
+ <% actions.each_with_index do |action, index| -%>
6
+ <% if index != 0 -%>
7
+
8
+ <% end -%>
9
+ test "<%= action %>" do
10
+ agent = <%= class_name %>Agent.<%= action %>
11
+ assert_equal <%= action.to_s.humanize.inspect %>, agent.prompt_context
12
+ end
13
+ <% end -%>
14
+ <% if actions.blank? -%>
15
+ # test "the truth" do
16
+ # assert true
17
+ # end
18
+ <% end -%>
19
+ end
20
+ <% end -%>
@@ -0,0 +1,14 @@
1
+ <% module_namespacing do -%>
2
+ # Preview all agent views/prompts templates at http://localhost:3000/active_agent/agents/<%= file_path %>_agent
3
+ class <%= class_name %>AgentPreview < ActiveAgent::Preview
4
+ <% actions.each_with_index do |action, index| -%>
5
+ <% if index != 0 -%>
6
+
7
+ <% end -%>
8
+ # Preview this email at http://localhost:3000/active_agent/agents/<%= file_path %>_agent/<%= action %>
9
+ def <%= action %>
10
+ <%= class_name %>Agent.<%= action %>
11
+ end
12
+ <% end -%>
13
+ end
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.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Bowen
@@ -187,15 +187,20 @@ files:
187
187
  - lib/generators/active_agent/USAGE
188
188
  - lib/generators/active_agent/agent_generator.rb
189
189
  - lib/generators/active_agent/install_generator.rb
190
- - lib/generators/active_agent/templates/action.html.erb.tt
191
- - lib/generators/active_agent/templates/action.json.jbuilder.tt
192
190
  - lib/generators/active_agent/templates/active_agent.yml
193
- - lib/generators/active_agent/templates/agent.html.erb
194
191
  - lib/generators/active_agent/templates/agent.rb.tt
195
- - lib/generators/active_agent/templates/agent.text.erb
196
- - lib/generators/active_agent/templates/agent_spec.rb.tt
197
- - lib/generators/active_agent/templates/agent_test.rb.tt
198
192
  - lib/generators/active_agent/templates/application_agent.rb.tt
193
+ - lib/generators/erb/agent_generator.rb
194
+ - lib/generators/erb/install_generator.rb
195
+ - lib/generators/erb/templates/application_agent.rb.tt
196
+ - lib/generators/erb/templates/layout.html.erb.tt
197
+ - lib/generators/erb/templates/layout.text.erb.tt
198
+ - lib/generators/erb/templates/view.html.erb.tt
199
+ - lib/generators/erb/templates/view.text.erb.tt
200
+ - lib/generators/test_unit/agent_generator.rb
201
+ - lib/generators/test_unit/install_generator.rb
202
+ - lib/generators/test_unit/templates/functional_test.rb.tt
203
+ - lib/generators/test_unit/templates/preview.rb.tt
199
204
  - lib/tasks/activeagent_tasks.rake
200
205
  homepage: https://activeagents.ai
201
206
  licenses:
@@ -1,14 +0,0 @@
1
- json.type :function
2
- json.function do
3
- json.name action_name
4
- json.description "TODO: Write a description for this action"
5
- json.parameters do
6
- json.type :object
7
- json.properties do
8
- json.param_name do
9
- json.type :string
10
- json.description "The param_description"
11
- end
12
- end
13
- end
14
- end
@@ -1 +0,0 @@
1
- <%= yield if block_given? %>
@@ -1 +0,0 @@
1
- <%= yield if block_given? %>