activeagent 1.5.0 → 1.6.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 +4 -4
- data/CHANGELOG.md +215 -0
- data/lib/active_agent/base.rb +7 -0
- data/lib/active_agent/concerns/authorization.rb +172 -0
- data/lib/active_agent/concerns/parameterized.rb +40 -3
- data/lib/active_agent/concerns/tooling.rb +3 -1
- data/lib/active_agent/delegation/runner.rb +17 -0
- data/lib/active_agent/evals/diagnosis.rb +62 -6
- data/lib/active_agent/evals/judge.rb +7 -2
- data/lib/active_agent/evals/model_spec.rb +31 -1
- data/lib/active_agent/evals/runner.rb +1 -1
- data/lib/active_agent/evals/scorer.rb +4 -1
- data/lib/active_agent/generation_job.rb +7 -1
- data/lib/active_agent/railtie.rb +10 -0
- data/lib/active_agent/schema_tools.rb +503 -0
- data/lib/active_agent/version.rb +1 -1
- data/lib/active_agent.rb +5 -0
- data/lib/generators/active_agent/schema_tools/USAGE +22 -0
- data/lib/generators/active_agent/schema_tools/schema_tools_generator.rb +84 -0
- data/lib/generators/active_agent/schema_tools/templates/schema_tools.rb.tt +48 -0
- metadata +7 -2
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveAgent
|
|
4
|
+
module Generators
|
|
5
|
+
# Writes a starter ActiveAgent::SchemaTools class for one model:
|
|
6
|
+
#
|
|
7
|
+
# bin/rails generate active_agent:schema_tools Reservation
|
|
8
|
+
#
|
|
9
|
+
# The class it writes exposes nothing beyond +id+ until someone uncomments
|
|
10
|
+
# a column, because which columns an agent may filter on and read back is
|
|
11
|
+
# a judgement about exposure, not a fact about the table (#440). Every
|
|
12
|
+
# column the model has is listed, commented out, minus the ones that look
|
|
13
|
+
# like secrets, so the allowlist is a review step rather than a blank page.
|
|
14
|
+
class SchemaToolsGenerator < ::Rails::Generators::NamedBase
|
|
15
|
+
source_root File.expand_path("templates", __dir__)
|
|
16
|
+
|
|
17
|
+
# Columns never suggested, whatever the model: reading one back would
|
|
18
|
+
# hand a model a credential, and filtering on one leaks it a character
|
|
19
|
+
# at a time through the row counts.
|
|
20
|
+
SECRET_COLUMNS = /password|digest|token|secret|api_key|otp|encrypted|ssn/i
|
|
21
|
+
|
|
22
|
+
class_option :policy, type: :boolean, default: nil,
|
|
23
|
+
desc: "Scope every read through <Model>Policy::Scope (default: when that policy exists)"
|
|
24
|
+
|
|
25
|
+
check_class_collision suffix: "Tools"
|
|
26
|
+
|
|
27
|
+
def create_tools_file
|
|
28
|
+
template "schema_tools.rb.tt", File.join("app/agent_tools", class_path, "#{file_name}_tools.rb")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
# "Reservation" and "ReservationTools" both name the Reservation model.
|
|
34
|
+
def file_name # :doc:
|
|
35
|
+
@_file_name ||= super.sub(/_tools\z/i, "")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def model_class
|
|
39
|
+
@model_class ||= class_name.safe_constantize
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def policy_class_name
|
|
43
|
+
"#{class_name}Policy"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def policy?
|
|
47
|
+
return options[:policy] unless options[:policy].nil?
|
|
48
|
+
|
|
49
|
+
"#{policy_class_name}::Scope".safe_constantize.present?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# [name, type] for every column the model has, or [] when the model or
|
|
53
|
+
# its table cannot be read from here (a model that does not exist yet,
|
|
54
|
+
# or a database that is not set up) — the file is still written.
|
|
55
|
+
def columns
|
|
56
|
+
@columns ||= begin
|
|
57
|
+
if model_class.respond_to?(:columns) && model_class.respond_to?(:table_exists?) && model_class.table_exists?
|
|
58
|
+
model_class.columns.map { |column| [ column.name, column.type ] }
|
|
59
|
+
else
|
|
60
|
+
[]
|
|
61
|
+
end
|
|
62
|
+
rescue StandardError
|
|
63
|
+
[]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def suggested_columns
|
|
68
|
+
columns.reject { |name, _type| name == "id" || name.match?(SECRET_COLUMNS) }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def secret_columns
|
|
72
|
+
columns.select { |name, _type| name.match?(SECRET_COLUMNS) }.map(&:first)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def collection_name
|
|
76
|
+
class_name.demodulize.underscore.pluralize
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def resource_name
|
|
80
|
+
class_name.demodulize.underscore
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<% module_namespacing do -%>
|
|
2
|
+
# Bounded, read-only agent tools over <%= class_name %>:
|
|
3
|
+
# find_<%= collection_name %>, count_<%= collection_name %>, get_<%= resource_name %>.
|
|
4
|
+
#
|
|
5
|
+
# Nothing is exposed until you say so. Move a column from the commented lists
|
|
6
|
+
# into `filterable` (an agent may filter on it) or `returns` (an agent may
|
|
7
|
+
# read it back). Each one is a judgement about exposure, not a fact about the
|
|
8
|
+
# table: leave out anything a model should never see.
|
|
9
|
+
class <%= class_name %>Tools < ActiveAgent::SchemaTools
|
|
10
|
+
model <%= class_name %>
|
|
11
|
+
|
|
12
|
+
filterable :id
|
|
13
|
+
<% if suggested_columns.any? -%>
|
|
14
|
+
# filterable <%= suggested_columns.map { |name, _type| ":#{name}" }.join(", ") %>
|
|
15
|
+
<% else -%>
|
|
16
|
+
# filterable :status, :owner_id # columns an agent may filter on
|
|
17
|
+
<% end -%>
|
|
18
|
+
|
|
19
|
+
returns :id
|
|
20
|
+
<% if suggested_columns.any? -%>
|
|
21
|
+
# returns <%= suggested_columns.map { |name, _type| ":#{name}" }.join(", ") %>
|
|
22
|
+
<% else -%>
|
|
23
|
+
# returns :id, :title, :status # columns an agent may read back
|
|
24
|
+
<% end -%>
|
|
25
|
+
<% if suggested_columns.any? -%>
|
|
26
|
+
#
|
|
27
|
+
# Columns and their types:
|
|
28
|
+
<% suggested_columns.each do |name, type| -%>
|
|
29
|
+
# <%= name.ljust(24) %> <%= type %>
|
|
30
|
+
<% end -%>
|
|
31
|
+
<% end -%>
|
|
32
|
+
<% if secret_columns.any? -%>
|
|
33
|
+
#
|
|
34
|
+
# Not suggested, and not to be added: <%= secret_columns.join(", ") %>.
|
|
35
|
+
<% end -%>
|
|
36
|
+
|
|
37
|
+
<% if policy? -%>
|
|
38
|
+
# Every read runs through <%= policy_class_name %>::Scope for the acting
|
|
39
|
+
# user, so an agent sees exactly what that user could see.
|
|
40
|
+
scope_by_policy
|
|
41
|
+
<% else -%>
|
|
42
|
+
# Every read should run through a relation scoped to the acting user. Without
|
|
43
|
+
# a scope the tools read the whole table. Return <%= class_name %>.none for an
|
|
44
|
+
# actor with no access; never widen for a nil actor.
|
|
45
|
+
# scope { |actor| actor ? <%= class_name %>.where(owner: actor) : <%= class_name %>.none }
|
|
46
|
+
<% end -%>
|
|
47
|
+
end
|
|
48
|
+
<% end -%>
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activeagent
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justin Bowen
|
|
@@ -409,6 +409,7 @@ files:
|
|
|
409
409
|
- lib/active_agent.rb
|
|
410
410
|
- lib/active_agent/base.rb
|
|
411
411
|
- lib/active_agent/collector.rb
|
|
412
|
+
- lib/active_agent/concerns/authorization.rb
|
|
412
413
|
- lib/active_agent/concerns/callbacks.rb
|
|
413
414
|
- lib/active_agent/concerns/delegation.rb
|
|
414
415
|
- lib/active_agent/concerns/observers.rb
|
|
@@ -562,6 +563,7 @@ files:
|
|
|
562
563
|
- lib/active_agent/railtie.rb
|
|
563
564
|
- lib/active_agent/railtie/schema_generator_extension.rb
|
|
564
565
|
- lib/active_agent/schema_generator.rb
|
|
566
|
+
- lib/active_agent/schema_tools.rb
|
|
565
567
|
- lib/active_agent/service.rb
|
|
566
568
|
- lib/active_agent/telemetry.rb
|
|
567
569
|
- lib/active_agent/telemetry/configuration.rb
|
|
@@ -576,6 +578,9 @@ files:
|
|
|
576
578
|
- lib/generators/active_agent/agent/agent_generator.rb
|
|
577
579
|
- lib/generators/active_agent/install/USAGE
|
|
578
580
|
- lib/generators/active_agent/install/install_generator.rb
|
|
581
|
+
- lib/generators/active_agent/schema_tools/USAGE
|
|
582
|
+
- lib/generators/active_agent/schema_tools/schema_tools_generator.rb
|
|
583
|
+
- lib/generators/active_agent/schema_tools/templates/schema_tools.rb.tt
|
|
579
584
|
- lib/generators/active_agent/templates/active_agent.yml
|
|
580
585
|
- lib/generators/active_agent/templates/agent.rb.tt
|
|
581
586
|
- lib/generators/active_agent/templates/application_agent.rb.tt
|
|
@@ -614,7 +619,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
614
619
|
- !ruby/object:Gem::Version
|
|
615
620
|
version: '0'
|
|
616
621
|
requirements: []
|
|
617
|
-
rubygems_version:
|
|
622
|
+
rubygems_version: 3.6.9
|
|
618
623
|
specification_version: 4
|
|
619
624
|
summary: Rails AI Agents Framework
|
|
620
625
|
test_files: []
|