activeagent 0.3 → 0.3.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 +4 -4
- data/CHANGELOG.md +17 -0
- data/lib/active_agent/action_prompt/README.md +0 -111
- data/lib/active_agent/action_prompt/message.rb +4 -0
- data/lib/active_agent/action_prompt/prompt.rb +9 -2
- data/lib/active_agent/action_prompt.rb +0 -84
- data/lib/active_agent/base.rb +32 -19
- data/lib/active_agent/collector.rb +32 -0
- data/lib/active_agent/generation_provider/README.md +0 -72
- data/lib/active_agent/generation_provider/open_ai_provider.rb +51 -45
- data/lib/active_agent/generation_provider/response.rb +2 -2
- data/lib/active_agent/generation_provider.rb +1 -1
- data/lib/active_agent/preview.rb +1 -1
- data/lib/active_agent/railtie.rb +2 -2
- data/lib/active_agent/version.rb +1 -1
- data/lib/active_agent.rb +0 -1
- data/lib/generators/active_agent/agent_generator.rb +0 -49
- data/lib/generators/active_agent/install_generator.rb +2 -1
- metadata +5 -8
- data/lib/active_agent/action_prompt/base.rb +0 -127
- data/lib/active_agent/action_prompt/collector.rb +0 -34
- data/lib/active_agent/engine.rb +0 -14
- data/lib/active_agent/operation.rb +0 -13
- data/lib/generators/active_agent/templates/layout.text.erb +0 -1
- /data/lib/generators/active_agent/templates/{layout.html.erb → agent.html.erb} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5296fe177a73f49b3514b6d82ad8dc45efdf5455b50aed3fb411103551fb308
|
4
|
+
data.tar.gz: 889c307af88851d5bb8022f4701af49a96a9701f862cecf1b01bfd625f2568d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0806180976fb672856ce7396c813659d7ee1edf9e3393e9dbba970b724daa343c0da0397b3edfed9aae6d60b08ee1ac2dd744933b4e177d0c829a3c26e6c63ce'
|
7
|
+
data.tar.gz: d59653e4a7e97488b864bcdc0b93558b07920f6ea069ef16070dba7dfe0c36e5876de928008f7b02d848bbb5d2f86d7bf025c52d33be8090f08f1da5fc8c6e9e
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [0.3.2] - 2025-04-15
|
9
|
+
|
10
|
+
### Added
|
11
|
+
- CI configuration for stable GitHub releases moving forward.
|
12
|
+
- Test coverage for core features: ActionPrompt rendering, tool calls, and embeddings.
|
13
|
+
- Enhance streaming to support tool calls during stream. Previously, streaming mode blocked tool call execution.
|
14
|
+
- Fix layout rendering bug when no block is passed and views now render correctly without requiring a block.
|
15
|
+
|
16
|
+
### Removed
|
17
|
+
- Generation Provider module and Action Prompt READMEs have been removed, but will be updated along with the main README in the next release.
|
@@ -1,111 +0,0 @@
|
|
1
|
-
# Active Agent: Action Prompt
|
2
|
-
|
3
|
-
Action Prompt provides a structured way to create and manage prompts for AI interactions. It enables composing messages, handling actions/tools, and managing conversation context through several key components.
|
4
|
-
|
5
|
-
Action Prompt manages the overall prompt structure including:
|
6
|
-
|
7
|
-
- Messages list with system/user/assistant roles
|
8
|
-
- Action/tool definitions
|
9
|
-
- Headers and context tracking
|
10
|
-
- Content type and encoding
|
11
|
-
- Multipart message handling
|
12
|
-
|
13
|
-
```ruby
|
14
|
-
prompt = ActionPrompt::Prompt.new(
|
15
|
-
instructions: "System guidance",
|
16
|
-
message: "User input",
|
17
|
-
actions: [tool_definition, action_schema],
|
18
|
-
context: messages
|
19
|
-
)
|
20
|
-
```
|
21
|
-
|
22
|
-
## ActionPrompt::Message
|
23
|
-
|
24
|
-
Represents individual messages with:
|
25
|
-
|
26
|
-
### Content and Role
|
27
|
-
```ruby
|
28
|
-
message = ActionPrompt::Message.new(
|
29
|
-
content: "Search for a hotel",
|
30
|
-
role: :user
|
31
|
-
)
|
32
|
-
```
|
33
|
-
|
34
|
-
- Content stores the actual message text
|
35
|
-
- Role defines the message sender type (system/user/assistant/function/tool)
|
36
|
-
- Messages form interactions between roles in a Context
|
37
|
-
|
38
|
-
### Action Requests and Responses
|
39
|
-
```ruby
|
40
|
-
message = ActionPrompt::Message.new(
|
41
|
-
content: "Search for a hotel",
|
42
|
-
role: :tool,
|
43
|
-
requested_actions: [{name: "search", params: {query: "hotel"}}]
|
44
|
-
)
|
45
|
-
```
|
46
|
-
|
47
|
-
- Tracks if message requests actions/tools
|
48
|
-
- Maintains list of requested_actions
|
49
|
-
- Action responses include function call results
|
50
|
-
- Handles tool execution state
|
51
|
-
|
52
|
-
### Content Type and Encoding
|
53
|
-
- Default content_type is "text/plain"
|
54
|
-
- Supports multiple content types for rich messages
|
55
|
-
- Default charset is UTF-8
|
56
|
-
- Handles content encoding/decoding
|
57
|
-
|
58
|
-
### Role Validation
|
59
|
-
- Enforces valid roles via VALID_ROLES constant
|
60
|
-
- Validates on message creation
|
61
|
-
- Raises ArgumentError for invalid roles
|
62
|
-
- Supported roles: system, assistant, user, tool, function
|
63
|
-
|
64
|
-
```ruby
|
65
|
-
message = ActionPrompt::Message.new(
|
66
|
-
content: "Hello",
|
67
|
-
role: :user,
|
68
|
-
content_type: "text/plain",
|
69
|
-
charset: "UTF-8"
|
70
|
-
)
|
71
|
-
```
|
72
|
-
|
73
|
-
### ActionPrompt::Action
|
74
|
-
|
75
|
-
Defines callable tools/functions:
|
76
|
-
|
77
|
-
- Name and parameters schema
|
78
|
-
- Validation and type checking
|
79
|
-
- Response handling
|
80
|
-
- Action execution
|
81
|
-
|
82
|
-
## Usage with Base Agents
|
83
|
-
|
84
|
-
```ruby
|
85
|
-
class MyAgent < ActiveAgent::Base
|
86
|
-
# Define available actions
|
87
|
-
def action_schemas
|
88
|
-
[
|
89
|
-
{name: "search", params: {query: :string}}
|
90
|
-
]
|
91
|
-
end
|
92
|
-
|
93
|
-
# Handle action responses
|
94
|
-
def perform_action(action)
|
95
|
-
case action.name
|
96
|
-
when "search"
|
97
|
-
search_service.query(action.params[:query])
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
```
|
102
|
-
|
103
|
-
The Base agent integrates with ActionPrompt to:
|
104
|
-
|
105
|
-
1. Create prompts with context
|
106
|
-
2. Register available actions
|
107
|
-
3. Process action requests
|
108
|
-
4. Handle responses and update context
|
109
|
-
5. Manage the conversation flow
|
110
|
-
|
111
|
-
See Base.rb for full agent integration details.
|
@@ -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
|
@@ -34,90 +34,6 @@ module ActiveAgent
|
|
34
34
|
# }.freeze
|
35
35
|
end
|
36
36
|
|
37
|
-
# # def self.prompt(headers = {}, &)
|
38
|
-
# # new.prompt(headers, &)
|
39
|
-
# # end
|
40
|
-
|
41
|
-
# def prompt(headers = {}, &block)
|
42
|
-
# return @_message if @_prompt_was_called && headers.blank? && !block
|
43
|
-
|
44
|
-
# headers = apply_defaults(headers)
|
45
|
-
|
46
|
-
# @_message = ActiveAgent::ActionPrompt::Prompt.new
|
47
|
-
|
48
|
-
# assign_headers_to_message(@_message, headers)
|
49
|
-
|
50
|
-
# responses = collect_responses(headers, &block)
|
51
|
-
|
52
|
-
# @_prompt_was_called = true
|
53
|
-
|
54
|
-
# create_parts_from_responses(@_message, responses)
|
55
|
-
|
56
|
-
# @_message
|
57
|
-
# end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def apply_defaults(headers)
|
62
|
-
headers.reverse_merge(self.class.default_params)
|
63
|
-
end
|
64
|
-
|
65
|
-
def assign_headers_to_message(message, headers)
|
66
|
-
assignable = headers.except(:parts_order, :content_type, :body, :template_name, :template_path)
|
67
|
-
assignable.each { |k, v| message.send(:"#{k}=", v) }
|
68
|
-
end
|
69
|
-
|
70
|
-
def collect_responses(headers, &block)
|
71
|
-
if block
|
72
|
-
collect_responses_from_block(headers, &block)
|
73
|
-
elsif headers[:body]
|
74
|
-
collect_responses_from_text(headers)
|
75
|
-
else
|
76
|
-
collect_responses_from_templates(headers)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def collect_responses_from_block(headers, &block)
|
81
|
-
templates_name = headers[:template_name] || action_name
|
82
|
-
collector = ActiveAgent::ActionPrompt::Collector.new(lookup_context) { render(templates_name) }
|
83
|
-
yield(collector)
|
84
|
-
collector.responses
|
85
|
-
end
|
86
|
-
|
87
|
-
def collect_responses_from_text(headers)
|
88
|
-
[{
|
89
|
-
body: headers.delete(:body),
|
90
|
-
content_type: headers[:content_type] || "text/plain"
|
91
|
-
}]
|
92
|
-
end
|
93
|
-
|
94
|
-
def collect_responses_from_templates(headers)
|
95
|
-
templates_path = headers[:template_path] || self.class.name.sub(/Agent$/, "").underscore
|
96
|
-
templates_name = headers[:template_name] || action_name
|
97
|
-
each_template(Array(templates_path), templates_name).map do |template|
|
98
|
-
format = template.format || formats.first
|
99
|
-
{
|
100
|
-
body: render(template: template, formats: [format]),
|
101
|
-
content_type: Mime[format].to_s
|
102
|
-
}
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def each_template(paths, name, &)
|
107
|
-
templates = lookup_context.find_all(name, paths)
|
108
|
-
if templates.empty?
|
109
|
-
raise ActionView::MissingTemplate.new(paths, name, paths, false, "prompt")
|
110
|
-
else
|
111
|
-
templates.uniq(&:format).each(&)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def create_parts_from_responses(message, responses)
|
116
|
-
responses.each do |response|
|
117
|
-
message.add_part(response[:body], content_type: response[:content_type])
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
37
|
class TestAgent
|
122
38
|
class << self
|
123
39
|
attr_accessor :generations
|
data/lib/active_agent/base.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require "active_agent/prompt_helper"
|
4
4
|
require "active_agent/action_prompt/prompt"
|
5
|
-
require "active_agent/
|
5
|
+
require "active_agent/collector"
|
6
6
|
require "active_support/core_ext/string/inflections"
|
7
7
|
require "active_support/core_ext/hash/except"
|
8
8
|
require "active_support/core_ext/module/anonymous"
|
@@ -53,7 +53,7 @@ module ActiveAgent
|
|
53
53
|
|
54
54
|
include ActionView::Layouts
|
55
55
|
|
56
|
-
PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + [:@_action_has_layout]
|
56
|
+
PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + [ :@_action_has_layout ]
|
57
57
|
|
58
58
|
helper ActiveAgent::PromptHelper
|
59
59
|
|
@@ -63,7 +63,7 @@ module ActiveAgent
|
|
63
63
|
mime_version: "1.0",
|
64
64
|
charset: "UTF-8",
|
65
65
|
content_type: "text/plain",
|
66
|
-
parts_order: ["text/plain", "text/enriched", "text/html"]
|
66
|
+
parts_order: [ "text/plain", "text/enriched", "text/html" ]
|
67
67
|
}.freeze
|
68
68
|
|
69
69
|
class << self
|
@@ -212,6 +212,20 @@ module ActiveAgent
|
|
212
212
|
handle_response(generation_provider.response)
|
213
213
|
end
|
214
214
|
|
215
|
+
# Add embedding capability to Message class
|
216
|
+
ActiveAgent::ActionPrompt::Message.class_eval do
|
217
|
+
def embed
|
218
|
+
agent_class = ActiveAgent::Base.descendants.first
|
219
|
+
agent = agent_class.new
|
220
|
+
agent.prompt_context = ActiveAgent::ActionPrompt::Prompt.new(message: self)
|
221
|
+
agent.embed
|
222
|
+
self
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# Make prompt_context accessible for chaining
|
227
|
+
# attr_accessor :prompt_context
|
228
|
+
|
215
229
|
def perform_generation
|
216
230
|
prompt_context.options.merge(options)
|
217
231
|
generation_provider.generate(prompt_context) if prompt_context && generation_provider
|
@@ -219,15 +233,14 @@ module ActiveAgent
|
|
219
233
|
end
|
220
234
|
|
221
235
|
def handle_response(response)
|
222
|
-
|
223
|
-
|
236
|
+
return response unless response.message.requested_actions.present?
|
237
|
+
perform_actions(requested_actions: response.message.requested_actions)
|
224
238
|
update_prompt_context(response)
|
225
239
|
end
|
226
240
|
|
227
241
|
def update_prompt_context(response)
|
228
|
-
|
229
|
-
|
230
|
-
response
|
242
|
+
prompt_context.message = prompt_context.messages.last
|
243
|
+
ActiveAgent::GenerationProvider::Response.new(prompt: prompt_context)
|
231
244
|
end
|
232
245
|
|
233
246
|
def perform_actions(requested_actions:)
|
@@ -237,9 +250,12 @@ module ActiveAgent
|
|
237
250
|
end
|
238
251
|
|
239
252
|
def perform_action(action)
|
253
|
+
current_context = prompt_context.clone
|
240
254
|
process(action.name, *action.params)
|
241
255
|
prompt_context.messages.last.role = :tool
|
242
256
|
prompt_context.messages.last.action_id = action.id
|
257
|
+
current_context.messages << prompt_context.messages.last
|
258
|
+
self.prompt_context = current_context
|
243
259
|
end
|
244
260
|
|
245
261
|
def initialize
|
@@ -299,15 +315,11 @@ module ActiveAgent
|
|
299
315
|
|
300
316
|
def prompt(headers = {}, &block)
|
301
317
|
return prompt_context if @_prompt_was_called && headers.blank? && !block
|
302
|
-
|
303
318
|
content_type = headers[:content_type]
|
304
|
-
|
305
319
|
headers = apply_defaults(headers)
|
306
|
-
|
320
|
+
prompt_context.messages = headers[:messages] || []
|
307
321
|
prompt_context.context_id = headers[:context_id]
|
308
322
|
|
309
|
-
prompt_context.options = options.merge(headers[:options] || {})
|
310
|
-
|
311
323
|
prompt_context.charset = charset = headers[:charset]
|
312
324
|
|
313
325
|
responses = collect_responses(headers, &block)
|
@@ -319,13 +331,14 @@ module ActiveAgent
|
|
319
331
|
prompt_context.content_type = set_content_type(prompt_context, content_type, headers[:content_type])
|
320
332
|
prompt_context.charset = charset
|
321
333
|
prompt_context.actions = headers[:actions] || action_schemas
|
334
|
+
|
322
335
|
prompt_context
|
323
336
|
end
|
324
337
|
|
325
338
|
def action_schemas
|
326
339
|
action_methods.map do |action|
|
327
340
|
if action != "text_prompt"
|
328
|
-
JSON.parse render_to_string(locals: {action_name: action}, action: action, formats: :json)
|
341
|
+
JSON.parse render_to_string(locals: { action_name: action }, action: action, formats: :json)
|
329
342
|
end
|
330
343
|
end.compact
|
331
344
|
end
|
@@ -346,7 +359,7 @@ module ActiveAgent
|
|
346
359
|
# If the subject has interpolations, you can pass them through the +interpolations+ parameter.
|
347
360
|
def default_i18n_subject(interpolations = {}) # :doc:
|
348
361
|
agent_scope = self.class.agent_name.tr("/", ".")
|
349
|
-
I18n.t(:subject, **interpolations.merge(scope: [agent_scope, action_name], default: action_name.humanize))
|
362
|
+
I18n.t(:subject, **interpolations.merge(scope: [ agent_scope, action_name ], default: action_name.humanize))
|
350
363
|
end
|
351
364
|
|
352
365
|
def apply_defaults(headers)
|
@@ -385,16 +398,16 @@ module ActiveAgent
|
|
385
398
|
|
386
399
|
def collect_responses_from_block(headers)
|
387
400
|
templates_name = headers[:template_name] || action_name
|
388
|
-
collector =
|
401
|
+
collector = Collector.new(lookup_context) { render(templates_name) }
|
389
402
|
yield(collector)
|
390
403
|
collector.responses
|
391
404
|
end
|
392
405
|
|
393
406
|
def collect_responses_from_text(headers)
|
394
|
-
[{
|
407
|
+
[ {
|
395
408
|
body: headers.delete(:body),
|
396
409
|
content_type: headers[:content_type] || "text/plain"
|
397
|
-
}]
|
410
|
+
} ]
|
398
411
|
end
|
399
412
|
|
400
413
|
def collect_responses_from_templates(headers)
|
@@ -406,7 +419,7 @@ module ActiveAgent
|
|
406
419
|
|
407
420
|
format = template.format || formats.first
|
408
421
|
{
|
409
|
-
body: render(template: template, formats: [format]),
|
422
|
+
body: render(template: template, formats: [ format ]),
|
410
423
|
content_type: Mime[format].to_s
|
411
424
|
}
|
412
425
|
end.compact
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "abstract_controller/collector"
|
4
|
+
require "active_support/core_ext/hash/reverse_merge"
|
5
|
+
require "active_support/core_ext/array/extract_options"
|
6
|
+
|
7
|
+
module ActiveAgent
|
8
|
+
class Collector
|
9
|
+
include AbstractController::Collector
|
10
|
+
attr_reader :responses
|
11
|
+
|
12
|
+
def initialize(context, &block)
|
13
|
+
@context = context
|
14
|
+
@responses = []
|
15
|
+
@default_render = block
|
16
|
+
end
|
17
|
+
|
18
|
+
def any(*args, &block)
|
19
|
+
options = args.extract_options!
|
20
|
+
raise ArgumentError, "You have to supply at least one format" if args.empty?
|
21
|
+
args.each { |type| send(type, options.dup, &block) }
|
22
|
+
end
|
23
|
+
alias_method :all, :any
|
24
|
+
|
25
|
+
def custom(mime, options = {})
|
26
|
+
options.reverse_merge!(content_type: mime.to_s)
|
27
|
+
@context.formats = [ mime.to_sym ]
|
28
|
+
options[:body] = block_given? ? yield : @default_render.call
|
29
|
+
@responses << options
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
# Active Agent: Generation Provider
|
2
|
-
|
3
|
-
This README provides information about the generation provider interfaces and implementations in the ActiveAgent library.
|
4
|
-
|
5
|
-
## Main Components
|
6
|
-
|
7
|
-
- Base class - Abstract class for implementing generation providers
|
8
|
-
- OpenAI Provider - Reference implementation using OpenAI's API
|
9
|
-
- Response class - Standardized response wrapper
|
10
|
-
- Module - For including generation provider functionality in agents
|
11
|
-
|
12
|
-
## Core Concepts
|
13
|
-
|
14
|
-
### Base Provider Class
|
15
|
-
|
16
|
-
The `ActiveAgent::GenerationProvider::Base` class defines the core interface that all providers must implement:
|
17
|
-
|
18
|
-
```ruby
|
19
|
-
def generate(prompt)
|
20
|
-
raise NotImplementedError
|
21
|
-
end
|
22
|
-
```
|
23
|
-
|
24
|
-
### OpenAI Provider Implementation
|
25
|
-
|
26
|
-
The OpenAI provider shows how to implement a concrete generation provider:
|
27
|
-
|
28
|
-
- Handles authentication and client setup
|
29
|
-
- Implements prompt/completion generation
|
30
|
-
- Supports streaming responses
|
31
|
-
- Handles embeddings generation
|
32
|
-
- Manages context updates
|
33
|
-
- Processes tool/action calls
|
34
|
-
|
35
|
-
### Provider Features
|
36
|
-
|
37
|
-
- Configuration - Providers accept config options for API keys, models, etc
|
38
|
-
- Streaming - Optional streaming support for realtime responses
|
39
|
-
- Action handling - Support for function/tool calling
|
40
|
-
- Error handling - Standardized error handling via GenerationProviderError
|
41
|
-
- Context management - Tracks conversation context and message history
|
42
|
-
|
43
|
-
### Response Handling
|
44
|
-
|
45
|
-
The Response class wraps provider responses with a consistent interface:
|
46
|
-
|
47
|
-
```ruby
|
48
|
-
Response.new(
|
49
|
-
prompt: prompt, # Original prompt
|
50
|
-
message: message, # Generated response
|
51
|
-
raw_response: raw # Provider-specific response
|
52
|
-
)
|
53
|
-
```
|
54
|
-
|
55
|
-
## Usage Example
|
56
|
-
|
57
|
-
```ruby
|
58
|
-
# Configure provider
|
59
|
-
provider = ActiveAgent::GenerationProvider::OpenAIProvider.new(
|
60
|
-
"api_key" => ENV["OPENAI_API_KEY"],
|
61
|
-
"model" => "gpt-4"
|
62
|
-
)
|
63
|
-
|
64
|
-
# Generate completion
|
65
|
-
response = provider.generate(prompt)
|
66
|
-
|
67
|
-
# Access response
|
68
|
-
response.message.content # Generated text
|
69
|
-
response.raw_response # Raw provider response
|
70
|
-
```
|
71
|
-
|
72
|
-
See the OpenAI provider implementation for a complete reference example.
|
@@ -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|
|
@@ -98,42 +78,68 @@ module ActiveAgent
|
|
98
78
|
}.compact
|
99
79
|
|
100
80
|
if message.content_type == "image_url"
|
101
|
-
provider_message[:image_url] = {url: message.content}
|
81
|
+
provider_message[:image_url] = { url: message.content }
|
102
82
|
end
|
103
83
|
provider_message
|
104
84
|
end
|
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 = ActiveAgent::ActionPrompt::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
|
@@ -24,7 +24,7 @@ module ActiveAgent
|
|
24
24
|
require "active_agent/generation_provider/#{config["service"].underscore}_provider"
|
25
25
|
ActiveAgent::GenerationProvider.const_get("#{config["service"].camelize}Provider").new(config)
|
26
26
|
rescue LoadError
|
27
|
-
raise "Missing generation provider for #{config["service"].inspect}"
|
27
|
+
raise "Missing generation provider configuration for #{config["service"].inspect}"
|
28
28
|
end
|
29
29
|
|
30
30
|
def generation_provider
|
data/lib/active_agent/preview.rb
CHANGED
@@ -11,7 +11,7 @@ module ActiveAgent
|
|
11
11
|
|
12
12
|
mattr_accessor :show_previews, instance_writer: false
|
13
13
|
|
14
|
-
mattr_accessor :preview_interceptors, instance_writer: false, default: [ActiveAgent::InlinePreviewInterceptor]
|
14
|
+
mattr_accessor :preview_interceptors, instance_writer: false, default: [ ActiveAgent::InlinePreviewInterceptor ]
|
15
15
|
end
|
16
16
|
|
17
17
|
module ClassMethods
|
data/lib/active_agent/railtie.rb
CHANGED
@@ -29,7 +29,7 @@ module ActiveAgent
|
|
29
29
|
options.stylesheets_dir ||= paths["public/stylesheets"].first
|
30
30
|
options.show_previews = Rails.env.development? if options.show_previews.nil?
|
31
31
|
options.cache_store ||= Rails.cache
|
32
|
-
options.preview_paths |= ["#{Rails.root}/test/agents/previews"]
|
32
|
+
options.preview_paths |= [ "#{Rails.root}/test/agents/previews" ]
|
33
33
|
|
34
34
|
# make sure readers methods get compiled
|
35
35
|
options.asset_host ||= app.config.asset_host
|
@@ -45,7 +45,7 @@ module ActiveAgent
|
|
45
45
|
register_interceptors(options.delete(:interceptors))
|
46
46
|
register_preview_interceptors(options.delete(:preview_interceptors))
|
47
47
|
register_observers(options.delete(:observers))
|
48
|
-
self.view_paths = ["#{Rails.root}/app/views"]
|
48
|
+
self.view_paths = [ "#{Rails.root}/app/views" ]
|
49
49
|
self.preview_paths |= options[:preview_paths]
|
50
50
|
|
51
51
|
if (generation_job = options.delete(:generation_job))
|
data/lib/active_agent/version.rb
CHANGED
data/lib/active_agent.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
|
@@ -13,7 +13,8 @@ module ActiveAgent
|
|
13
13
|
template "application_agent.rb", "app/agents/application_agent.rb"
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
16
|
+
def create_agent_layouts
|
17
|
+
template "agent.html.erb", "app/views/layouts/agent.html.erb"
|
17
18
|
template "agent.text.erb", "app/views/layouts/agent.text.erb"
|
18
19
|
end
|
19
20
|
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.2
|
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-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -138,19 +138,18 @@ executables: []
|
|
138
138
|
extensions: []
|
139
139
|
extra_rdoc_files: []
|
140
140
|
files:
|
141
|
+
- CHANGELOG.md
|
141
142
|
- lib/active_agent.rb
|
142
143
|
- lib/active_agent/README.md
|
143
144
|
- lib/active_agent/action_prompt.rb
|
144
145
|
- lib/active_agent/action_prompt/README.md
|
145
146
|
- lib/active_agent/action_prompt/action.rb
|
146
|
-
- lib/active_agent/action_prompt/base.rb
|
147
|
-
- lib/active_agent/action_prompt/collector.rb
|
148
147
|
- lib/active_agent/action_prompt/message.rb
|
149
148
|
- lib/active_agent/action_prompt/prompt.rb
|
150
149
|
- lib/active_agent/base.rb
|
151
150
|
- lib/active_agent/callbacks.rb
|
151
|
+
- lib/active_agent/collector.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
|
@@ -179,13 +177,12 @@ files:
|
|
179
177
|
- lib/generators/active_agent/templates/action.html.erb.tt
|
180
178
|
- lib/generators/active_agent/templates/action.json.jbuilder.tt
|
181
179
|
- lib/generators/active_agent/templates/active_agent.yml
|
180
|
+
- lib/generators/active_agent/templates/agent.html.erb
|
182
181
|
- lib/generators/active_agent/templates/agent.rb.tt
|
183
182
|
- lib/generators/active_agent/templates/agent.text.erb
|
184
183
|
- lib/generators/active_agent/templates/agent_spec.rb.tt
|
185
184
|
- lib/generators/active_agent/templates/agent_test.rb.tt
|
186
185
|
- lib/generators/active_agent/templates/application_agent.rb.tt
|
187
|
-
- lib/generators/active_agent/templates/layout.html.erb
|
188
|
-
- lib/generators/active_agent/templates/layout.text.erb
|
189
186
|
- lib/tasks/activeagent_tasks.rake
|
190
187
|
homepage: https://activeagents.ai
|
191
188
|
licenses:
|
@@ -1,127 +0,0 @@
|
|
1
|
-
# require "abstract_controller"
|
2
|
-
# require "active_support/core_ext/string/inflections"
|
3
|
-
|
4
|
-
# module ActiveAgent
|
5
|
-
# module ActionPrompt
|
6
|
-
# extend ::ActiveSupport::Autoload
|
7
|
-
|
8
|
-
# eager_autoload do
|
9
|
-
# autoload :Collector
|
10
|
-
# autoload :Message
|
11
|
-
# autoload :Prompt
|
12
|
-
# autoload :PromptHelper
|
13
|
-
# end
|
14
|
-
|
15
|
-
# autoload :Base
|
16
|
-
|
17
|
-
# extend ActiveSupport::Concern
|
18
|
-
|
19
|
-
# included do
|
20
|
-
# include AbstractController::Rendering
|
21
|
-
# include AbstractController::Layouts
|
22
|
-
# include AbstractController::Helpers
|
23
|
-
# include AbstractController::Translation
|
24
|
-
# include AbstractController::AssetPaths
|
25
|
-
# include AbstractController::Callbacks
|
26
|
-
# include AbstractController::Caching
|
27
|
-
|
28
|
-
# include ActionView::Layouts
|
29
|
-
|
30
|
-
# helper ActiveAgent::PromptHelper
|
31
|
-
# # class_attribute :default_params, default: {
|
32
|
-
# # content_type: "text/plain",
|
33
|
-
# # parts_order: ["text/plain", "text/html", "application/json"]
|
34
|
-
# # }.freeze
|
35
|
-
# end
|
36
|
-
|
37
|
-
# # # def self.prompt(headers = {}, &)
|
38
|
-
# # # new.prompt(headers, &)
|
39
|
-
# # # end
|
40
|
-
|
41
|
-
# # def prompt(headers = {}, &block)
|
42
|
-
# # return @_message if @_prompt_was_called && headers.blank? && !block
|
43
|
-
|
44
|
-
# # headers = apply_defaults(headers)
|
45
|
-
|
46
|
-
# # @_message = ActiveAgent::ActionPrompt::Prompt.new
|
47
|
-
|
48
|
-
# # assign_headers_to_message(@_message, headers)
|
49
|
-
|
50
|
-
# # responses = collect_responses(headers, &block)
|
51
|
-
|
52
|
-
# # @_prompt_was_called = true
|
53
|
-
|
54
|
-
# # create_parts_from_responses(@_message, responses)
|
55
|
-
|
56
|
-
# # @_message
|
57
|
-
# # end
|
58
|
-
|
59
|
-
# private
|
60
|
-
|
61
|
-
# def apply_defaults(headers)
|
62
|
-
# headers.reverse_merge(self.class.default_params)
|
63
|
-
# end
|
64
|
-
|
65
|
-
# def assign_headers_to_message(message, headers)
|
66
|
-
# assignable = headers.except(:parts_order, :content_type, :body, :template_name, :template_path)
|
67
|
-
# assignable.each { |k, v| message.send(:"#{k}=", v) }
|
68
|
-
# end
|
69
|
-
|
70
|
-
# def collect_responses(headers, &block)
|
71
|
-
# if block
|
72
|
-
# collect_responses_from_block(headers, &block)
|
73
|
-
# elsif headers[:body]
|
74
|
-
# collect_responses_from_text(headers)
|
75
|
-
# else
|
76
|
-
# collect_responses_from_templates(headers)
|
77
|
-
# end
|
78
|
-
# end
|
79
|
-
|
80
|
-
# def collect_responses_from_block(headers, &block)
|
81
|
-
# templates_name = headers[:template_name] || action_name
|
82
|
-
# collector = ActiveAgent::ActionPrompt::Collector.new(lookup_context) { render(templates_name) }
|
83
|
-
# yield(collector)
|
84
|
-
# collector.responses
|
85
|
-
# end
|
86
|
-
|
87
|
-
# def collect_responses_from_text(headers)
|
88
|
-
# [{
|
89
|
-
# body: headers.delete(:body),
|
90
|
-
# content_type: headers[:content_type] || "text/plain"
|
91
|
-
# }]
|
92
|
-
# end
|
93
|
-
|
94
|
-
# def collect_responses_from_templates(headers)
|
95
|
-
# templates_path = headers[:template_path] || self.class.name.sub(/Agent$/, "").underscore
|
96
|
-
# templates_name = headers[:template_name] || action_name
|
97
|
-
# each_template(Array(templates_path), templates_name).map do |template|
|
98
|
-
# format = template.format || formats.first
|
99
|
-
# {
|
100
|
-
# body: render(template: template, formats: [format]),
|
101
|
-
# content_type: Mime[format].to_s
|
102
|
-
# }
|
103
|
-
# end
|
104
|
-
# end
|
105
|
-
|
106
|
-
# def each_template(paths, name, &)
|
107
|
-
# templates = lookup_context.find_all(name, paths)
|
108
|
-
# if templates.empty?
|
109
|
-
# raise ActionView::MissingTemplate.new(paths, name, paths, false, "prompt")
|
110
|
-
# else
|
111
|
-
# templates.uniq(&:format).each(&)
|
112
|
-
# end
|
113
|
-
# end
|
114
|
-
|
115
|
-
# def create_parts_from_responses(message, responses)
|
116
|
-
# responses.each do |response|
|
117
|
-
# message.add_part(response[:body], content_type: response[:content_type])
|
118
|
-
# end
|
119
|
-
# end
|
120
|
-
|
121
|
-
# class TestAgent
|
122
|
-
# class << self
|
123
|
-
# attr_accessor :generations
|
124
|
-
# end
|
125
|
-
# end
|
126
|
-
# end
|
127
|
-
# end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "abstract_controller/collector"
|
4
|
-
require "active_support/core_ext/hash/reverse_merge"
|
5
|
-
require "active_support/core_ext/array/extract_options"
|
6
|
-
|
7
|
-
module ActiveAgent
|
8
|
-
module ActionPrompt
|
9
|
-
class Collector
|
10
|
-
include AbstractController::Collector
|
11
|
-
attr_reader :responses
|
12
|
-
|
13
|
-
def initialize(context, &block)
|
14
|
-
@context = context
|
15
|
-
@responses = []
|
16
|
-
@default_render = block
|
17
|
-
end
|
18
|
-
|
19
|
-
def any(*args, &block)
|
20
|
-
options = args.extract_options!
|
21
|
-
raise ArgumentError, "You have to supply at least one format" if args.empty?
|
22
|
-
args.each { |type| send(type, options.dup, &block) }
|
23
|
-
end
|
24
|
-
alias_method :all, :any
|
25
|
-
|
26
|
-
def custom(mime, options = {})
|
27
|
-
options.reverse_merge!(content_type: mime.to_s)
|
28
|
-
@context.formats = [mime.to_sym]
|
29
|
-
options[:body] = block_given? ? yield : @default_render.call
|
30
|
-
@responses << options
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
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
|
@@ -1 +0,0 @@
|
|
1
|
-
<%= yield %>
|
File without changes
|