activeagent 0.3 → 0.3.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 +4 -4
- data/lib/active_agent/action_prompt/prompt.rb +9 -2
- data/lib/active_agent/base.rb +9 -10
- data/lib/active_agent/callbacks.rb +1 -1
- data/lib/active_agent/generation_provider/open_ai_provider.rb +50 -44
- data/lib/active_agent/generation_provider/response.rb +2 -2
- data/lib/active_agent/version.rb +1 -1
- data/lib/generators/active_agent/agent_generator.rb +0 -49
- data/lib/generators/active_agent/install_generator.rb +0 -4
- metadata +2 -4
- data/lib/active_agent/engine.rb +0 -14
- data/lib/active_agent/operation.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d679bd3d4f68b5c696ed4cc194e9b5476ebb0da34d6ac683296f7f7f5feae0f8
|
4
|
+
data.tar.gz: 2f11870fc423e399c53bf0728203faf47cbe3303d7aa47bb2d5d77bc603cda8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8261c5df1f59b50a96e6c46f1363b470fadff9bbc0231ab6a1c2e6975e906d73d150f0c3d11367d8c766d49ffc0c67428ed3fb40a5fcbbd4c5b78e03a4274805
|
7
|
+
data.tar.gz: 64b70a42b0f09f175e441dccab85468946df03ec5f3cd6e007a5e4180d13726230817b5b4ddc4adc348a5b9b838adf8a9d3342490e7d6e96f07c79fa983bc366
|
@@ -3,7 +3,8 @@ require_relative "message"
|
|
3
3
|
module ActiveAgent
|
4
4
|
module ActionPrompt
|
5
5
|
class Prompt
|
6
|
-
|
6
|
+
attr_reader :messages
|
7
|
+
attr_accessor :actions, :body, :content_type, :context_id, :instructions, :message, :options, :mime_version, :charset, :context, :parts, :params, :action_choice, :agent_class
|
7
8
|
|
8
9
|
def initialize(attributes = {})
|
9
10
|
@options = attributes.fetch(:options, {})
|
@@ -27,6 +28,11 @@ module ActiveAgent
|
|
27
28
|
set_messages
|
28
29
|
end
|
29
30
|
|
31
|
+
def messages=(messages)
|
32
|
+
@messages = messages
|
33
|
+
set_messages
|
34
|
+
end
|
35
|
+
|
30
36
|
# Generate the prompt as a string (for debugging or sending to the provider)
|
31
37
|
def to_s
|
32
38
|
@message.to_s
|
@@ -62,7 +68,7 @@ module ActiveAgent
|
|
62
68
|
private
|
63
69
|
|
64
70
|
def set_messages
|
65
|
-
@messages = [Message.new(content: @instructions, role: :system)] + @messages
|
71
|
+
@messages = [Message.new(content: @instructions, role: :system)] + @messages if @instructions.present?
|
66
72
|
end
|
67
73
|
|
68
74
|
def set_message
|
@@ -71,6 +77,7 @@ module ActiveAgent
|
|
71
77
|
elsif @body.is_a?(String) && @message.content.blank?
|
72
78
|
@message = Message.new(content: @body, role: :user)
|
73
79
|
end
|
80
|
+
|
74
81
|
@messages << @message
|
75
82
|
end
|
76
83
|
end
|
data/lib/active_agent/base.rb
CHANGED
@@ -219,15 +219,14 @@ module ActiveAgent
|
|
219
219
|
end
|
220
220
|
|
221
221
|
def handle_response(response)
|
222
|
-
|
223
|
-
|
222
|
+
return response unless response.message.requested_actions.present?
|
223
|
+
perform_actions(requested_actions: response.message.requested_actions)
|
224
224
|
update_prompt_context(response)
|
225
225
|
end
|
226
226
|
|
227
227
|
def update_prompt_context(response)
|
228
|
-
|
229
|
-
|
230
|
-
response
|
228
|
+
prompt_context.message = prompt_context.messages.last
|
229
|
+
ActiveAgent::GenerationProvider::Response.new(prompt: prompt_context)
|
231
230
|
end
|
232
231
|
|
233
232
|
def perform_actions(requested_actions:)
|
@@ -237,9 +236,12 @@ module ActiveAgent
|
|
237
236
|
end
|
238
237
|
|
239
238
|
def perform_action(action)
|
239
|
+
current_context = prompt_context.clone
|
240
240
|
process(action.name, *action.params)
|
241
241
|
prompt_context.messages.last.role = :tool
|
242
242
|
prompt_context.messages.last.action_id = action.id
|
243
|
+
current_context.messages << prompt_context.messages.last
|
244
|
+
self.prompt_context = current_context
|
243
245
|
end
|
244
246
|
|
245
247
|
def initialize
|
@@ -299,15 +301,11 @@ module ActiveAgent
|
|
299
301
|
|
300
302
|
def prompt(headers = {}, &block)
|
301
303
|
return prompt_context if @_prompt_was_called && headers.blank? && !block
|
302
|
-
|
303
304
|
content_type = headers[:content_type]
|
304
|
-
|
305
305
|
headers = apply_defaults(headers)
|
306
|
-
|
306
|
+
prompt_context.messages = headers[:messages] || []
|
307
307
|
prompt_context.context_id = headers[:context_id]
|
308
308
|
|
309
|
-
prompt_context.options = options.merge(headers[:options] || {})
|
310
|
-
|
311
309
|
prompt_context.charset = charset = headers[:charset]
|
312
310
|
|
313
311
|
responses = collect_responses(headers, &block)
|
@@ -319,6 +317,7 @@ module ActiveAgent
|
|
319
317
|
prompt_context.content_type = set_content_type(prompt_context, content_type, headers[:content_type])
|
320
318
|
prompt_context.charset = charset
|
321
319
|
prompt_context.actions = headers[:actions] || action_schemas
|
320
|
+
|
322
321
|
prompt_context
|
323
322
|
end
|
324
323
|
|
@@ -23,12 +23,6 @@ module ActiveAgent
|
|
23
23
|
raise GenerationProviderError, e.message
|
24
24
|
end
|
25
25
|
|
26
|
-
def chat_prompt(parameters: prompt_parameters)
|
27
|
-
parameters[:stream] = provider_stream if prompt.options[:stream] || config["stream"]
|
28
|
-
|
29
|
-
chat_response(@client.chat(parameters: parameters))
|
30
|
-
end
|
31
|
-
|
32
26
|
def embed(prompt)
|
33
27
|
@prompt = prompt
|
34
28
|
|
@@ -37,39 +31,25 @@ module ActiveAgent
|
|
37
31
|
raise GenerationProviderError, e.message
|
38
32
|
end
|
39
33
|
|
40
|
-
def embeddings_parameters(input: prompt.message.content, model: "text-embedding-3-large")
|
41
|
-
{
|
42
|
-
model: model,
|
43
|
-
input: input
|
44
|
-
}
|
45
|
-
end
|
46
|
-
|
47
|
-
def embeddings_response(response)
|
48
|
-
message = Message.new(content: response.dig("data", 0, "embedding"), role: "assistant")
|
49
|
-
|
50
|
-
@response = ActiveAgent::GenerationProvider::Response.new(prompt: prompt, message: message, raw_response: response)
|
51
|
-
end
|
52
|
-
|
53
|
-
def embeddings_prompt(parameters:)
|
54
|
-
embeddings_response(@client.embeddings(parameters: embeddings_parameters))
|
55
|
-
end
|
56
|
-
|
57
34
|
private
|
58
35
|
|
59
36
|
def provider_stream
|
60
|
-
# prompt.options[:stream] will define a proc found in prompt at runtime
|
61
|
-
# config[:stream] will define a proc found in config. stream would come from an Agent class's generate_with or stream_with method calls
|
62
37
|
agent_stream = prompt.options[:stream]
|
63
38
|
message = ActiveAgent::ActionPrompt::Message.new(content: "", role: :assistant)
|
64
|
-
@response = ActiveAgent::GenerationProvider::Response.new(prompt: prompt, message:)
|
65
39
|
|
40
|
+
@response = ActiveAgent::GenerationProvider::Response.new(prompt:, message:)
|
66
41
|
proc do |chunk, bytesize|
|
67
|
-
|
42
|
+
new_content = chunk.dig("choices", 0, "delta", "content")
|
43
|
+
if new_content && !new_content.blank
|
68
44
|
message.content += new_content
|
69
45
|
|
70
46
|
agent_stream.call(message, new_content, false) do |message, new_content|
|
71
47
|
yield message, new_content if block_given?
|
72
48
|
end
|
49
|
+
elsif chunk.dig("choices", 0, "delta", "tool_calls") && !chunk.dig("choices", 0, "delta", "tool_calls").empty?
|
50
|
+
message = handle_message(chunk.dig("choices", 0, "delta"))
|
51
|
+
prompt.messages << message
|
52
|
+
@response = ActiveAgent::GenerationProvider::Response.new(prompt:, message:)
|
73
53
|
end
|
74
54
|
|
75
55
|
agent_stream.call(message, nil, true) do |message|
|
@@ -105,35 +85,61 @@ module ActiveAgent
|
|
105
85
|
end
|
106
86
|
|
107
87
|
def chat_response(response)
|
108
|
-
binding.irb
|
109
88
|
return @response if prompt.options[:stream]
|
110
89
|
|
111
90
|
message_json = response.dig("choices", 0, "message")
|
112
91
|
|
113
|
-
message =
|
92
|
+
message = handle_message(message_json)
|
93
|
+
|
94
|
+
update_context(prompt: prompt, message: message, response: response)
|
95
|
+
|
96
|
+
@response = ActiveAgent::GenerationProvider::Response.new(prompt: prompt, message: message, raw_response: response)
|
97
|
+
end
|
98
|
+
|
99
|
+
def handle_message(message_json)
|
100
|
+
ActiveAgent::ActionPrompt::Message.new(
|
114
101
|
content: message_json["content"],
|
115
|
-
role: message_json["role"],
|
102
|
+
role: message_json["role"].intern,
|
116
103
|
action_requested: message_json["finish_reason"] == "tool_calls",
|
117
104
|
requested_actions: handle_actions(message_json["tool_calls"])
|
118
105
|
)
|
119
|
-
|
106
|
+
end
|
107
|
+
|
108
|
+
def handle_actions(tool_calls)
|
109
|
+
return [] if tool_calls.nil? || tool_calls.empty?
|
110
|
+
|
111
|
+
tool_calls.map do |tool_call|
|
112
|
+
next if tool_call["function"].nil? || tool_call["function"]["name"].blank?
|
113
|
+
args = tool_call["function"]["arguments"].blank? ? nil : JSON.parse(tool_call["function"]["arguments"], {symbolize_names: true})
|
114
|
+
|
115
|
+
ActiveAgent::ActionPrompt::Action.new(
|
116
|
+
id: tool_call["id"],
|
117
|
+
name: tool_call.dig("function", "name"),
|
118
|
+
params: args
|
119
|
+
)
|
120
|
+
end.compact
|
121
|
+
end
|
122
|
+
|
123
|
+
def chat_prompt(parameters: prompt_parameters)
|
124
|
+
parameters[:stream] = provider_stream if prompt.options[:stream] || config["stream"]
|
125
|
+
chat_response(@client.chat(parameters: parameters))
|
126
|
+
end
|
127
|
+
|
128
|
+
def embeddings_parameters(input: prompt.message.content, model: "text-embedding-3-large")
|
129
|
+
{
|
130
|
+
model: model,
|
131
|
+
input: input
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
def embeddings_response(response)
|
136
|
+
message = Message.new(content: response.dig("data", 0, "embedding"), role: "assistant")
|
120
137
|
|
121
138
|
@response = ActiveAgent::GenerationProvider::Response.new(prompt: prompt, message: message, raw_response: response)
|
122
139
|
end
|
123
140
|
|
124
|
-
def
|
125
|
-
|
126
|
-
tool_calls.map do |tool_call|
|
127
|
-
ActiveAgent::ActionPrompt::Action.new(
|
128
|
-
id: tool_call["id"],
|
129
|
-
name: tool_call.dig("function", "name"),
|
130
|
-
params: JSON.parse(
|
131
|
-
tool_call.dig("function", "arguments"),
|
132
|
-
{symbolize_names: true}
|
133
|
-
)
|
134
|
-
)
|
135
|
-
end
|
136
|
-
end
|
141
|
+
def embeddings_prompt(parameters:)
|
142
|
+
embeddings_response(@client.embeddings(parameters: embeddings_parameters))
|
137
143
|
end
|
138
144
|
end
|
139
145
|
end
|
@@ -5,9 +5,9 @@ module ActiveAgent
|
|
5
5
|
class Response
|
6
6
|
attr_reader :message, :prompt, :raw_response
|
7
7
|
|
8
|
-
def initialize(prompt:, message
|
9
|
-
@message = message
|
8
|
+
def initialize(prompt:, message: nil, raw_response: nil)
|
10
9
|
@prompt = prompt
|
10
|
+
@message = message || prompt.message
|
11
11
|
@raw_response = raw_response
|
12
12
|
end
|
13
13
|
end
|
data/lib/active_agent/version.rb
CHANGED
@@ -19,57 +19,8 @@ module ActiveAgent
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
def create_test_file
|
23
|
-
if test_framework == :rspec
|
24
|
-
template "agent_spec.rb", File.join("spec/agents", class_path, "#{file_name}_agent_spec.rb")
|
25
|
-
else
|
26
|
-
template "agent_test.rb", File.join("test/agents", class_path, "#{file_name}_agent_test.rb")
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def create_view_files
|
31
|
-
actions.each do |action|
|
32
|
-
@action = action
|
33
|
-
|
34
|
-
# Use configured template engines or fall back to defaults
|
35
|
-
json_template_engine = json_template_engine_for_views || "jbuilder"
|
36
|
-
html_template_engine = html_template_engine_for_views || "erb"
|
37
|
-
|
38
|
-
@schema_path = File.join("app/views", class_path, file_name, "#{action}.json.#{json_template_engine}")
|
39
|
-
@view_path = File.join("app/views", class_path, file_name, "#{action}.html.#{html_template_engine}")
|
40
|
-
|
41
|
-
template "action.json.#{json_template_engine}", @schema_path
|
42
|
-
template "action.html.#{html_template_engine}", @view_path
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def create_layout_files
|
47
|
-
# Create the application agent layouts
|
48
|
-
template "layout.text.erb", "app/views/layouts/agent.text.erb"
|
49
|
-
template "layout.html.erb", "app/views/layouts/agent.html.erb"
|
50
|
-
end
|
51
|
-
|
52
22
|
private
|
53
23
|
|
54
|
-
def test_framework
|
55
|
-
::Rails.application.config.generators.options[:rails][:test_framework]
|
56
|
-
end
|
57
|
-
|
58
|
-
def template_engine
|
59
|
-
::Rails.application.config.generators.options[:rails][:template_engine]
|
60
|
-
end
|
61
|
-
|
62
|
-
def json_template_engine_for_views
|
63
|
-
# Check if there's a specific JSON template engine configured
|
64
|
-
json_engine = ::Rails.application.config.generators.options[:rails][:json_template_engine]
|
65
|
-
json_engine || "jbuilder" # Default to jbuilder if not specified
|
66
|
-
end
|
67
|
-
|
68
|
-
def html_template_engine_for_views
|
69
|
-
# Use the configured template engine or default to erb
|
70
|
-
template_engine || "erb"
|
71
|
-
end
|
72
|
-
|
73
24
|
def file_name # :doc:
|
74
25
|
@_file_name ||= super + "_agent"
|
75
26
|
end
|
@@ -12,10 +12,6 @@ module ActiveAgent
|
|
12
12
|
def create_application_agent
|
13
13
|
template "application_agent.rb", "app/agents/application_agent.rb"
|
14
14
|
end
|
15
|
-
|
16
|
-
def create_agent_layout_template
|
17
|
-
template "agent.text.erb", "app/views/layouts/agent.text.erb"
|
18
|
-
end
|
19
15
|
end
|
20
16
|
end
|
21
17
|
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:
|
4
|
+
version: 0.3.1
|
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-
|
11
|
+
date: 2025-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -150,7 +150,6 @@ files:
|
|
150
150
|
- lib/active_agent/base.rb
|
151
151
|
- lib/active_agent/callbacks.rb
|
152
152
|
- lib/active_agent/deprecator.rb
|
153
|
-
- lib/active_agent/engine.rb
|
154
153
|
- lib/active_agent/generation.rb
|
155
154
|
- lib/active_agent/generation_job.rb
|
156
155
|
- lib/active_agent/generation_methods.rb
|
@@ -162,7 +161,6 @@ files:
|
|
162
161
|
- lib/active_agent/generation_provider/response.rb
|
163
162
|
- lib/active_agent/inline_preview_interceptor.rb
|
164
163
|
- lib/active_agent/log_subscriber.rb
|
165
|
-
- lib/active_agent/operation.rb
|
166
164
|
- lib/active_agent/parameterized.rb
|
167
165
|
- lib/active_agent/preview.rb
|
168
166
|
- lib/active_agent/prompt_helper.rb
|
data/lib/active_agent/engine.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# require "rails/engine"
|
2
|
-
|
3
|
-
# module ActiveAgent
|
4
|
-
# class Engine < ::Rails::Engine
|
5
|
-
# isolate_namespace ActiveAgent
|
6
|
-
|
7
|
-
# initializer "active_agent.view_paths" do |app|
|
8
|
-
# # Adding your gem's view path to Rails lookup paths
|
9
|
-
# ActiveSupport.on_load(:action_controller) do
|
10
|
-
# append_view_path Engine.root.join("app/views")
|
11
|
-
# end
|
12
|
-
# end
|
13
|
-
# end
|
14
|
-
# end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module ActiveAgent
|
2
|
-
class Operation < AbstractController::Base
|
3
|
-
include AbstractController::Rendering
|
4
|
-
include ActionView::Rendering # Allows rendering of ERB templates without a view context tied to a request
|
5
|
-
append_view_path "app/views" # Ensure the controller knows where to look for view templates
|
6
|
-
|
7
|
-
def process_tool(tool_name, params)
|
8
|
-
send(tool_name, params) # Dynamically calls the method corresponding to tool_name
|
9
|
-
rescue NoMethodError
|
10
|
-
"Tool not found: #{tool_name}"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|