activeagent 0.3.1 → 0.3.3
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 +1 -1
- data/lib/active_agent/action_prompt.rb +0 -84
- data/lib/active_agent/base.rb +23 -9
- data/lib/active_agent/callbacks.rb +1 -1
- data/lib/active_agent/collector.rb +32 -0
- data/lib/active_agent/generation_provider/README.md +0 -72
- data/lib/active_agent/generation_provider/ollama_provider.rb +16 -0
- data/lib/active_agent/generation_provider/open_ai_provider.rb +1 -3
- data/lib/active_agent/generation_provider/open_router_provider.rb +15 -0
- 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/install_generator.rb +5 -0
- data/lib/generators/active_agent/templates/agent.html.erb +1 -0
- data/lib/generators/active_agent/templates/agent.text.erb +1 -1
- metadata +7 -6
- data/lib/active_agent/action_prompt/base.rb +0 -127
- data/lib/active_agent/action_prompt/collector.rb +0 -34
- data/lib/generators/active_agent/templates/layout.html.erb +0 -1
- data/lib/generators/active_agent/templates/layout.text.erb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 065b41c8228d87f1c49d6099813e4d67fc8c853f2985bcdff01e8af23d0561d3
|
4
|
+
data.tar.gz: 820580bb35c3596adfdaee4edb9dc7f54044328f32d92a767d6134a3460875f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46752438d8e2ec5772e6c6a134906410de7363c366c187ce771bc6f13c7c748d23975ea7716e98ff22a76e8bfa46be43513cc6ce97cf504788ea612ac68caaeb
|
7
|
+
data.tar.gz: 1e8f480da2ac8107114ee9503aa9db582cbd7719e1ceceb809a741a8b0a81b67a038c46ecb75bff31e5ef9b77ce3197c6cc8bfbcb19c9c3779e097d8b3d53411
|
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.
|
@@ -68,7 +68,7 @@ module ActiveAgent
|
|
68
68
|
private
|
69
69
|
|
70
70
|
def set_messages
|
71
|
-
@messages = [Message.new(content: @instructions, role: :system)] + @messages if @instructions.present?
|
71
|
+
@messages = [ Message.new(content: @instructions, role: :system) ] + @messages if @instructions.present?
|
72
72
|
end
|
73
73
|
|
74
74
|
def set_message
|
@@ -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
|
@@ -324,7 +338,7 @@ module ActiveAgent
|
|
324
338
|
def action_schemas
|
325
339
|
action_methods.map do |action|
|
326
340
|
if action != "text_prompt"
|
327
|
-
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)
|
328
342
|
end
|
329
343
|
end.compact
|
330
344
|
end
|
@@ -345,7 +359,7 @@ module ActiveAgent
|
|
345
359
|
# If the subject has interpolations, you can pass them through the +interpolations+ parameter.
|
346
360
|
def default_i18n_subject(interpolations = {}) # :doc:
|
347
361
|
agent_scope = self.class.agent_name.tr("/", ".")
|
348
|
-
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))
|
349
363
|
end
|
350
364
|
|
351
365
|
def apply_defaults(headers)
|
@@ -384,16 +398,16 @@ module ActiveAgent
|
|
384
398
|
|
385
399
|
def collect_responses_from_block(headers)
|
386
400
|
templates_name = headers[:template_name] || action_name
|
387
|
-
collector =
|
401
|
+
collector = Collector.new(lookup_context) { render(templates_name) }
|
388
402
|
yield(collector)
|
389
403
|
collector.responses
|
390
404
|
end
|
391
405
|
|
392
406
|
def collect_responses_from_text(headers)
|
393
|
-
[{
|
407
|
+
[ {
|
394
408
|
body: headers.delete(:body),
|
395
409
|
content_type: headers[:content_type] || "text/plain"
|
396
|
-
}]
|
410
|
+
} ]
|
397
411
|
end
|
398
412
|
|
399
413
|
def collect_responses_from_templates(headers)
|
@@ -405,7 +419,7 @@ module ActiveAgent
|
|
405
419
|
|
406
420
|
format = template.format || formats.first
|
407
421
|
{
|
408
|
-
body: render(template: template, formats: [format]),
|
422
|
+
body: render(template: template, formats: [ format ]),
|
409
423
|
content_type: Mime[format].to_s
|
410
424
|
}
|
411
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.
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "openai"
|
2
|
+
require_relative "open_ai_provider"
|
3
|
+
|
4
|
+
module ActiveAgent
|
5
|
+
module GenerationProvider
|
6
|
+
class OllamaProvider < OpenAIProvider
|
7
|
+
def initialize(config)
|
8
|
+
@config = config
|
9
|
+
@api_key = config["api_key"]
|
10
|
+
@model_name = config["model"]
|
11
|
+
@host = config["host"] || "http://localhost:11434"
|
12
|
+
@client = OpenAI::Client.new(uri_base: @host, access_token: @api_key, log_errors: true)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# lib/active_agent/generation_provider/open_ai_provider.rb
|
2
|
-
|
3
1
|
require "openai"
|
4
2
|
require "active_agent/action_prompt/action"
|
5
3
|
require_relative "base"
|
@@ -133,7 +131,7 @@ module ActiveAgent
|
|
133
131
|
end
|
134
132
|
|
135
133
|
def embeddings_response(response)
|
136
|
-
message = Message.new(content: response.dig("data", 0, "embedding"), role: "assistant")
|
134
|
+
message = ActiveAgent::ActionPrompt::Message.new(content: response.dig("data", 0, "embedding"), role: "assistant")
|
137
135
|
|
138
136
|
@response = ActiveAgent::GenerationProvider::Response.new(prompt: prompt, message: message, raw_response: response)
|
139
137
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "openai"
|
2
|
+
require_relative "open_ai_provider"
|
3
|
+
|
4
|
+
module ActiveAgent
|
5
|
+
module GenerationProvider
|
6
|
+
class OpenRouterProvider < OpenAIProvider
|
7
|
+
def initialize(config)
|
8
|
+
@config = config
|
9
|
+
@api_key = config["api_key"]
|
10
|
+
@model_name = config["model"]
|
11
|
+
@client = OpenAI::Client.new(uri_base: "https://openrouter.ai/api/v1", access_token: @api_key, log_errors: true)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
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
@@ -12,6 +12,11 @@ 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_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
|
15
20
|
end
|
16
21
|
end
|
17
22
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= yield if block_given? %>
|
@@ -1 +1 @@
|
|
1
|
-
<%= yield %>
|
1
|
+
<%= yield if block_given? %>
|
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.3.
|
4
|
+
version: 0.3.3
|
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-05-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -138,17 +138,17 @@ 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
153
|
- lib/active_agent/generation.rb
|
154
154
|
- lib/active_agent/generation_job.rb
|
@@ -157,7 +157,9 @@ files:
|
|
157
157
|
- lib/active_agent/generation_provider/README.md
|
158
158
|
- lib/active_agent/generation_provider/anthropic_provider.rb
|
159
159
|
- lib/active_agent/generation_provider/base.rb
|
160
|
+
- lib/active_agent/generation_provider/ollama_provider.rb
|
160
161
|
- lib/active_agent/generation_provider/open_ai_provider.rb
|
162
|
+
- lib/active_agent/generation_provider/open_router_provider.rb
|
161
163
|
- lib/active_agent/generation_provider/response.rb
|
162
164
|
- lib/active_agent/inline_preview_interceptor.rb
|
163
165
|
- lib/active_agent/log_subscriber.rb
|
@@ -177,13 +179,12 @@ files:
|
|
177
179
|
- lib/generators/active_agent/templates/action.html.erb.tt
|
178
180
|
- lib/generators/active_agent/templates/action.json.jbuilder.tt
|
179
181
|
- lib/generators/active_agent/templates/active_agent.yml
|
182
|
+
- lib/generators/active_agent/templates/agent.html.erb
|
180
183
|
- lib/generators/active_agent/templates/agent.rb.tt
|
181
184
|
- lib/generators/active_agent/templates/agent.text.erb
|
182
185
|
- lib/generators/active_agent/templates/agent_spec.rb.tt
|
183
186
|
- lib/generators/active_agent/templates/agent_test.rb.tt
|
184
187
|
- lib/generators/active_agent/templates/application_agent.rb.tt
|
185
|
-
- lib/generators/active_agent/templates/layout.html.erb
|
186
|
-
- lib/generators/active_agent/templates/layout.text.erb
|
187
188
|
- lib/tasks/activeagent_tasks.rake
|
188
189
|
homepage: https://activeagents.ai
|
189
190
|
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
|
@@ -1 +0,0 @@
|
|
1
|
-
<%= yield %>
|
@@ -1 +0,0 @@
|
|
1
|
-
<%= yield %>
|