active_agent_rails 0.1.0
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 +7 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +151 -0
- data/Rakefile +12 -0
- data/app/controllers/active_agent/chats_controller.rb +84 -0
- data/app/helpers/active_agent/chat_helper.rb +427 -0
- data/config/routes.rb +6 -0
- data/lib/active_agent/base.rb +121 -0
- data/lib/active_agent/configuration.rb +30 -0
- data/lib/active_agent/engine.rb +16 -0
- data/lib/active_agent/memory/active_record.rb +68 -0
- data/lib/active_agent/memory/base.rb +42 -0
- data/lib/active_agent/memory/in_memory.rb +29 -0
- data/lib/active_agent/provider.rb +90 -0
- data/lib/active_agent/providers/anthropic.rb +208 -0
- data/lib/active_agent/providers/gemini.rb +169 -0
- data/lib/active_agent/providers/openai.rb +178 -0
- data/lib/active_agent/tool.rb +37 -0
- data/lib/active_agent/version.rb +5 -0
- data/lib/active_agent.rb +25 -0
- data/lib/active_agent_rails.rb +3 -0
- data/lib/generators/active_agent/agent/agent_generator.rb +15 -0
- data/lib/generators/active_agent/agent/templates/agent.rb.erb +22 -0
- data/lib/generators/active_agent/install/install_generator.rb +31 -0
- data/lib/generators/active_agent/install/templates/active_agent.rb +15 -0
- data/lib/generators/active_agent/install/templates/create_active_agent_messages.rb +18 -0
- metadata +144 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../provider"
|
|
4
|
+
|
|
5
|
+
module ActiveAgent
|
|
6
|
+
module Provider
|
|
7
|
+
class OpenAI < Base
|
|
8
|
+
def chat(messages, tools: [], &block)
|
|
9
|
+
api_model = model || "gpt-4o-mini"
|
|
10
|
+
url = "https://api.openai.com/v1/chat/completions"
|
|
11
|
+
|
|
12
|
+
body = {
|
|
13
|
+
model: api_model,
|
|
14
|
+
messages: format_messages(messages)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if tools.any?
|
|
18
|
+
body[:tools] = format_tools(tools)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
headers = {
|
|
22
|
+
"Content-Type" => "application/json",
|
|
23
|
+
"Authorization" => "Bearer #{api_key}"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if block_given?
|
|
27
|
+
body[:stream] = true
|
|
28
|
+
text_accumulator = ""
|
|
29
|
+
tool_calls_accumulator = {}
|
|
30
|
+
|
|
31
|
+
post_request(url, headers, body) do |line|
|
|
32
|
+
next unless line.start_with?("data:")
|
|
33
|
+
json_str = line.sub("data:", "").strip
|
|
34
|
+
next if json_str == "[DONE]"
|
|
35
|
+
next if json_str.empty?
|
|
36
|
+
|
|
37
|
+
begin
|
|
38
|
+
chunk = JSON.parse(json_str)
|
|
39
|
+
choice = chunk.dig("choices", 0)
|
|
40
|
+
next unless choice
|
|
41
|
+
|
|
42
|
+
delta = choice["delta"]
|
|
43
|
+
next unless delta
|
|
44
|
+
|
|
45
|
+
if delta["content"]
|
|
46
|
+
text_accumulator += delta["content"]
|
|
47
|
+
yield(delta["content"])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if delta["tool_calls"]
|
|
51
|
+
delta["tool_calls"].each do |tc|
|
|
52
|
+
index = tc["index"]
|
|
53
|
+
tool_calls_accumulator[index] ||= { id: "", name: "", arguments_str: "" }
|
|
54
|
+
|
|
55
|
+
tool_calls_accumulator[index][:id] = tc["id"] if tc["id"]
|
|
56
|
+
tool_calls_accumulator[index][:name] = tc.dig("function", "name") if tc.dig("function", "name")
|
|
57
|
+
|
|
58
|
+
if tc.dig("function", "arguments")
|
|
59
|
+
tool_calls_accumulator[index][:arguments_str] += tc.dig("function", "arguments")
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
rescue JSON::ParserError
|
|
64
|
+
# Ignore json parse errors for incomplete lines
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Format accumulated tool calls back to standard structure
|
|
69
|
+
tool_calls = tool_calls_accumulator.values.map do |tc|
|
|
70
|
+
args = {}
|
|
71
|
+
begin
|
|
72
|
+
args = JSON.parse(tc[:arguments_str], symbolize_names: true) unless tc[:arguments_str].empty?
|
|
73
|
+
rescue JSON::ParserError
|
|
74
|
+
ActiveAgent.logger.warn("OpenAI could not parse streaming arguments JSON: #{tc[:arguments_str]}")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
{
|
|
78
|
+
id: tc[:id],
|
|
79
|
+
name: tc[:name],
|
|
80
|
+
args: args
|
|
81
|
+
}
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
result = { role: "assistant" }
|
|
85
|
+
result[:content] = text_accumulator unless text_accumulator.empty?
|
|
86
|
+
result[:tool_calls] = tool_calls if tool_calls.any?
|
|
87
|
+
result
|
|
88
|
+
else
|
|
89
|
+
response_json = post_request(url, headers, body)
|
|
90
|
+
parse_response(response_json)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def format_tools(tools)
|
|
95
|
+
tools.map do |tool|
|
|
96
|
+
properties = {}
|
|
97
|
+
tool.parameters.each do |name, info|
|
|
98
|
+
properties[name] = {
|
|
99
|
+
type: Tool.map_type(info[:type], uppercase: false),
|
|
100
|
+
description: info[:description]
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
{
|
|
105
|
+
type: "function",
|
|
106
|
+
function: {
|
|
107
|
+
name: tool.name,
|
|
108
|
+
description: tool.description,
|
|
109
|
+
parameters: {
|
|
110
|
+
type: "object",
|
|
111
|
+
properties: properties,
|
|
112
|
+
required: tool.required_parameters
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
private
|
|
120
|
+
|
|
121
|
+
def format_messages(messages)
|
|
122
|
+
messages.map do |msg|
|
|
123
|
+
formatted = {
|
|
124
|
+
role: msg[:role].to_s,
|
|
125
|
+
content: msg[:content]
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if msg[:role].to_s == "assistant" && msg[:tool_calls]&.any?
|
|
129
|
+
formatted[:tool_calls] = msg[:tool_calls].map do |tc|
|
|
130
|
+
{
|
|
131
|
+
id: tc[:id] || tc[:name],
|
|
132
|
+
type: "function",
|
|
133
|
+
function: {
|
|
134
|
+
name: tc[:name],
|
|
135
|
+
arguments: tc[:args].to_json
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
end
|
|
139
|
+
formatted[:content] = nil # OpenAI requires content to be nil if tool_calls is present
|
|
140
|
+
elsif msg[:role].to_s == "tool"
|
|
141
|
+
formatted[:tool_call_id] = msg[:tool_call_id] || msg[:name]
|
|
142
|
+
formatted[:name] = msg[:name]
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
formatted
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def parse_response(response)
|
|
150
|
+
choice = response.dig("choices", 0, "message")
|
|
151
|
+
return { role: "assistant", content: "Error: No response from model." } unless choice
|
|
152
|
+
|
|
153
|
+
result = { role: "assistant" }
|
|
154
|
+
result[:content] = choice["content"] if choice["content"]
|
|
155
|
+
|
|
156
|
+
if choice["tool_calls"]
|
|
157
|
+
result[:tool_calls] = choice["tool_calls"].map do |tc|
|
|
158
|
+
args_json = tc.dig("function", "arguments")
|
|
159
|
+
args = {}
|
|
160
|
+
begin
|
|
161
|
+
args = JSON.parse(args_json, symbolize_names: true) if args_json
|
|
162
|
+
rescue JSON::ParserError
|
|
163
|
+
ActiveAgent.logger.warn("OpenAI could not parse arguments JSON: #{args_json}")
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
{
|
|
167
|
+
id: tc["id"],
|
|
168
|
+
name: tc.dig("function", "name"),
|
|
169
|
+
args: args
|
|
170
|
+
}
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
result
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveAgent
|
|
4
|
+
class Tool
|
|
5
|
+
attr_reader :name, :description, :parameters, :required_parameters
|
|
6
|
+
|
|
7
|
+
def initialize(name, description: "", &block)
|
|
8
|
+
@name = name.to_s
|
|
9
|
+
@description = description
|
|
10
|
+
@parameters = {}
|
|
11
|
+
@required_parameters = []
|
|
12
|
+
instance_eval(&block) if block_given?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def parameter(param_name, type: :string, description: "", required: true)
|
|
16
|
+
@parameters[param_name.to_s] = {
|
|
17
|
+
type: type,
|
|
18
|
+
description: description
|
|
19
|
+
}
|
|
20
|
+
@required_parameters << param_name.to_s if required
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Translates ruby types to API-specific type strings
|
|
24
|
+
def self.map_type(type, uppercase: false)
|
|
25
|
+
mapped = case type.to_sym
|
|
26
|
+
when :string then "string"
|
|
27
|
+
when :integer then "integer"
|
|
28
|
+
when :number, :float then "number"
|
|
29
|
+
when :boolean then "boolean"
|
|
30
|
+
when :array then "array"
|
|
31
|
+
when :object then "object"
|
|
32
|
+
else "string"
|
|
33
|
+
end
|
|
34
|
+
uppercase ? mapped.upcase : mapped
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/active_agent.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support"
|
|
4
|
+
require "active_support/core_ext"
|
|
5
|
+
|
|
6
|
+
require_relative "active_agent/version"
|
|
7
|
+
require_relative "active_agent/configuration"
|
|
8
|
+
require_relative "active_agent/tool"
|
|
9
|
+
require_relative "active_agent/memory/base"
|
|
10
|
+
require_relative "active_agent/provider"
|
|
11
|
+
require_relative "active_agent/base"
|
|
12
|
+
|
|
13
|
+
if defined?(Rails)
|
|
14
|
+
require_relative "active_agent/engine"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
module ActiveAgent
|
|
18
|
+
# Global helper to resolve an agent class by name or symbol
|
|
19
|
+
def self.find_agent(name)
|
|
20
|
+
agent_class_name = "#{name.to_s.camelize}Agent"
|
|
21
|
+
agent_class_name.constantize
|
|
22
|
+
rescue NameError
|
|
23
|
+
raise "Could not find agent class: #{agent_class_name}. Ensure it is defined in app/agents/."
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
|
|
5
|
+
module ActiveAgent
|
|
6
|
+
module Generators
|
|
7
|
+
class AgentGenerator < ::Rails::Generators::NamedBase
|
|
8
|
+
source_root File.expand_path("templates", __dir__)
|
|
9
|
+
|
|
10
|
+
def create_agent_file
|
|
11
|
+
template "agent.rb.erb", "app/agents/#{file_name}_agent.rb"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class <%= class_name %>Agent < ActiveAgent::Base
|
|
4
|
+
# Configure provider and model (defaults to configuration settings if omitted)
|
|
5
|
+
provider :gemini # Options: :gemini, :openai, :anthropic
|
|
6
|
+
model "gemini-2.5-flash"
|
|
7
|
+
|
|
8
|
+
system_prompt "You are a helpful assistant."
|
|
9
|
+
|
|
10
|
+
# Expose tools to the agent using the `tool` DSL.
|
|
11
|
+
# Example:
|
|
12
|
+
#
|
|
13
|
+
# tool :get_current_time, description: "Retrieve the current server time and timezone" do
|
|
14
|
+
# # Parameters are documented for the LLM
|
|
15
|
+
# parameter :format, type: :string, description: "Optional strftime format", required: false
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# # Define the tool implementation as a standard Ruby instance method:
|
|
19
|
+
# def get_current_time(format: "%Y-%m-%d %H:%M:%S %Z")
|
|
20
|
+
# Time.current.strftime(format)
|
|
21
|
+
# end
|
|
22
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
require "rails/generators/migration"
|
|
5
|
+
|
|
6
|
+
module ActiveAgent
|
|
7
|
+
module Generators
|
|
8
|
+
class InstallGenerator < ::Rails::Generators::Base
|
|
9
|
+
include ::Rails::Generators::Migration
|
|
10
|
+
|
|
11
|
+
source_root File.expand_path("templates", __dir__)
|
|
12
|
+
|
|
13
|
+
def self.next_migration_number(path)
|
|
14
|
+
next_num = Time.now.utc.strftime("%Y%m%d%H%M%S")
|
|
15
|
+
begin
|
|
16
|
+
ActiveRecord::Generators::Base.next_migration_number(path)
|
|
17
|
+
rescue StandardError
|
|
18
|
+
next_num
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def create_initializer
|
|
23
|
+
template "active_agent.rb", "config/initializers/active_agent.rb"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def create_migration_file
|
|
27
|
+
migration_template "create_active_agent_messages.rb", "db/migrate/create_active_agent_messages.rb"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
ActiveAgent.configure do |config|
|
|
4
|
+
# Default provider: :gemini, :openai, or :anthropic
|
|
5
|
+
config.default_provider = :gemini
|
|
6
|
+
|
|
7
|
+
# API Keys for providers (recommend storing in Rails credentials or environment variables)
|
|
8
|
+
config.gemini_api_key = ENV["GEMINI_API_KEY"]
|
|
9
|
+
config.openai_api_key = ENV["OPENAI_API_KEY"]
|
|
10
|
+
config.anthropic_api_key = ENV["ANTHROPIC_API_KEY"]
|
|
11
|
+
|
|
12
|
+
# Memory store for chat conversations: :in_memory or :active_record
|
|
13
|
+
# Note: If using :active_record, ensure you run: rails db:migrate
|
|
14
|
+
config.memory_store = :active_record
|
|
15
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateActiveAgentMessages < ActiveRecord::Migration[<%= ActiveRecord::VERSION::MAJOR %>.<%= ActiveRecord::VERSION::MINOR %>]
|
|
4
|
+
def change
|
|
5
|
+
create_table :active_agent_messages do |t|
|
|
6
|
+
t.string :conversation_id, null: false
|
|
7
|
+
t.string :role, null: false
|
|
8
|
+
t.text :content
|
|
9
|
+
t.string :tool_call_id
|
|
10
|
+
t.string :name
|
|
11
|
+
t.text :tool_calls # serialized JSON array
|
|
12
|
+
|
|
13
|
+
t.timestamps
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
add_index :active_agent_messages, :conversation_id
|
|
17
|
+
end
|
|
18
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: active_agent_rails
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Shiboshree Roy
|
|
8
|
+
- Antigravity AI
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: railties
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 6.0.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 6.0.0
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: activesupport
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 6.0.0
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 6.0.0
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: activerecord
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 6.0.0
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: 6.0.0
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: actionpack
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 6.0.0
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 6.0.0
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: actionview
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 6.0.0
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 6.0.0
|
|
83
|
+
description: ActiveAgent provides a clean, unified interface to build AI agents with
|
|
84
|
+
automatic tool/function calling, ActiveRecord-backed conversation memory, and an
|
|
85
|
+
engine to stream real-time responses to a floating UI widget in your views.
|
|
86
|
+
email:
|
|
87
|
+
- support@example.com
|
|
88
|
+
executables: []
|
|
89
|
+
extensions: []
|
|
90
|
+
extra_rdoc_files: []
|
|
91
|
+
files:
|
|
92
|
+
- Gemfile
|
|
93
|
+
- LICENSE.txt
|
|
94
|
+
- README.md
|
|
95
|
+
- Rakefile
|
|
96
|
+
- app/controllers/active_agent/chats_controller.rb
|
|
97
|
+
- app/helpers/active_agent/chat_helper.rb
|
|
98
|
+
- config/routes.rb
|
|
99
|
+
- lib/active_agent.rb
|
|
100
|
+
- lib/active_agent/base.rb
|
|
101
|
+
- lib/active_agent/configuration.rb
|
|
102
|
+
- lib/active_agent/engine.rb
|
|
103
|
+
- lib/active_agent/memory/active_record.rb
|
|
104
|
+
- lib/active_agent/memory/base.rb
|
|
105
|
+
- lib/active_agent/memory/in_memory.rb
|
|
106
|
+
- lib/active_agent/provider.rb
|
|
107
|
+
- lib/active_agent/providers/anthropic.rb
|
|
108
|
+
- lib/active_agent/providers/gemini.rb
|
|
109
|
+
- lib/active_agent/providers/openai.rb
|
|
110
|
+
- lib/active_agent/tool.rb
|
|
111
|
+
- lib/active_agent/version.rb
|
|
112
|
+
- lib/active_agent_rails.rb
|
|
113
|
+
- lib/generators/active_agent/agent/agent_generator.rb
|
|
114
|
+
- lib/generators/active_agent/agent/templates/agent.rb.erb
|
|
115
|
+
- lib/generators/active_agent/install/install_generator.rb
|
|
116
|
+
- lib/generators/active_agent/install/templates/active_agent.rb
|
|
117
|
+
- lib/generators/active_agent/install/templates/create_active_agent_messages.rb
|
|
118
|
+
homepage: https://github.com/active-agent/active_agent_rails
|
|
119
|
+
licenses:
|
|
120
|
+
- MIT
|
|
121
|
+
metadata:
|
|
122
|
+
allowed_push_host: https://rubygems.org
|
|
123
|
+
source_code_uri: https://github.com/active-agent/active_agent_rails
|
|
124
|
+
changelog_uri: https://github.com/active-agent/active_agent_rails/releases
|
|
125
|
+
bug_tracker_uri: https://github.com/active-agent/active_agent_rails/issues
|
|
126
|
+
rdoc_options: []
|
|
127
|
+
require_paths:
|
|
128
|
+
- lib
|
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
130
|
+
requirements:
|
|
131
|
+
- - ">="
|
|
132
|
+
- !ruby/object:Gem::Version
|
|
133
|
+
version: 3.0.0
|
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - ">="
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0'
|
|
139
|
+
requirements: []
|
|
140
|
+
rubygems_version: 4.0.11
|
|
141
|
+
specification_version: 4
|
|
142
|
+
summary: A Rails-like framework to integrate LLMs, AI agents, and custom tools into
|
|
143
|
+
Ruby on Rails applications easily.
|
|
144
|
+
test_files: []
|