activeagent 1.0.3 → 1.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 +4 -4
- data/CHANGELOG.md +71 -0
- data/README.md +26 -0
- data/lib/active_agent/base.rb +4 -0
- data/lib/active_agent/dashboard/app/controllers/active_agent/dashboard/api/traces_controller.rb +27 -6
- data/lib/active_agent/dashboard/app/controllers/active_agent/dashboard/application_controller.rb +11 -1
- data/lib/active_agent/dashboard/app/controllers/active_agent/dashboard/dashboard_controller.rb +15 -12
- data/lib/active_agent/dashboard/app/controllers/active_agent/dashboard/traces_controller.rb +27 -7
- data/lib/active_agent/dashboard/app/jobs/active_agent/process_telemetry_traces_job.rb +9 -0
- data/lib/active_agent/dashboard/app/models/active_agent/telemetry_trace.rb +18 -2
- data/lib/active_agent/dashboard/app/views/active_agent/dashboard/traces/_trace_detail.html.erb +15 -3
- data/lib/active_agent/dashboard/app/views/active_agent/dashboard/traces/metrics.html.erb +3 -1
- data/lib/active_agent/dashboard/app/views/layouts/active_agent/dashboard/application.html.erb +4 -4
- data/lib/active_agent/dashboard/config/routes.rb +5 -64
- data/lib/active_agent/dashboard/engine.rb +19 -15
- data/lib/active_agent/dashboard.rb +13 -3
- data/lib/active_agent/model_capabilities.rb +89 -0
- data/lib/active_agent/providers/_base_provider.rb +23 -2
- data/lib/active_agent/providers/concerns/exception_handler.rb +12 -1
- data/lib/active_agent/providers/errors.rb +140 -0
- data/lib/active_agent/providers/ollama/chat/transforms.rb +9 -3
- data/lib/active_agent/railtie.rb +5 -0
- data/lib/active_agent/telemetry/configuration.rb +112 -172
- data/lib/active_agent/telemetry/instrumentation.rb +137 -14
- data/lib/active_agent/telemetry/reporter.rb +12 -165
- data/lib/active_agent/telemetry/span.rb +18 -245
- data/lib/active_agent/telemetry/tracer.rb +67 -70
- data/lib/active_agent/telemetry.rb +1 -2
- data/lib/active_agent/version.rb +1 -1
- data/lib/active_agent.rb +5 -0
- data/lib/generators/active_agent/dashboard/install_generator.rb +30 -2
- data/lib/generators/active_agent/dashboard/templates/active_agent_dashboard.rb.erb +41 -4
- data/lib/generators/active_agent/dashboard/templates/create_active_agent_telemetry_traces.rb.erb +20 -4
- metadata +17 -11
- data/lib/generators/active_agent/dashboard/install/install_generator.rb +0 -96
- data/lib/generators/active_agent/dashboard/install/templates/initializer.rb +0 -89
- data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agent_runs.rb +0 -42
- data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agent_templates.rb +0 -38
- data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agent_versions.rb +0 -22
- data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agents.rb +0 -53
- data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_sandbox_runs.rb +0 -28
- data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_sandbox_sessions.rb +0 -43
- data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_session_recordings.rb +0 -44
- data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_telemetry_traces.rb +0 -56
|
@@ -2,18 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
module ActiveAgent
|
|
4
4
|
module Telemetry
|
|
5
|
-
# Manages trace creation and lifecycle
|
|
5
|
+
# Manages trace creation and lifecycle on the activeagents-telemetry
|
|
6
|
+
# core: builds an ActiveAgents::Telemetry::Trace per unit of work, tracks
|
|
7
|
+
# the current span in thread-local storage, and hands finished traces to
|
|
8
|
+
# the Reporter.
|
|
6
9
|
#
|
|
7
|
-
#
|
|
8
|
-
# and coordinates with the Reporter for async transmission.
|
|
9
|
-
#
|
|
10
|
-
# @example Basic usage
|
|
10
|
+
# @example
|
|
11
11
|
# tracer = Tracer.new(configuration)
|
|
12
12
|
# tracer.trace("MyAgent.greet") do |span|
|
|
13
13
|
# span.set_attribute("user_id", 123)
|
|
14
14
|
# span.add_span("llm.generate", span_type: :llm)
|
|
15
15
|
# end
|
|
16
|
-
#
|
|
17
16
|
class Tracer
|
|
18
17
|
# @return [Configuration] Telemetry configuration
|
|
19
18
|
attr_reader :configuration
|
|
@@ -27,44 +26,47 @@ module ActiveAgent
|
|
|
27
26
|
def initialize(configuration)
|
|
28
27
|
@configuration = configuration
|
|
29
28
|
@reporter = Reporter.new(configuration)
|
|
30
|
-
@mutex = Mutex.new
|
|
31
29
|
end
|
|
32
30
|
|
|
33
31
|
# Creates and executes a new trace.
|
|
34
32
|
#
|
|
33
|
+
# Callers may supply the trace id (instrumentation passes the
|
|
34
|
+
# generation's prompt_options[:trace_id]) so external records — e.g.
|
|
35
|
+
# solid_agent's persisted generations — can correlate with this trace;
|
|
36
|
+
# otherwise one is generated.
|
|
37
|
+
#
|
|
35
38
|
# @param name [String] Trace name (typically "AgentClass.action")
|
|
36
|
-
# @param attributes [Hash] Root span attributes
|
|
39
|
+
# @param attributes [Hash] Root span attributes; :trace_id and
|
|
40
|
+
# :span_type are extracted rather than recorded
|
|
37
41
|
# @yield [span] Yields the root span for adding child spans
|
|
38
42
|
# @return [Object] Result of the block
|
|
39
|
-
|
|
40
|
-
# @example
|
|
41
|
-
# tracer.trace("WeatherAgent.forecast") do |span|
|
|
42
|
-
# span.set_attribute("location", "Seattle")
|
|
43
|
-
# result = do_llm_call
|
|
44
|
-
# span.set_tokens(input: 100, output: 50)
|
|
45
|
-
# result
|
|
46
|
-
# end
|
|
47
|
-
def trace(name, **attributes, &block)
|
|
43
|
+
def trace(name, **attributes)
|
|
48
44
|
return yield(Telemetry::NullSpan.new) unless should_trace?
|
|
49
45
|
|
|
50
|
-
trace_id =
|
|
46
|
+
trace_id = attributes.delete(:trace_id) || SecureRandom.hex(16)
|
|
47
|
+
span_type = attributes.delete(:span_type) || :root
|
|
48
|
+
|
|
49
|
+
trace = build_trace(trace_id)
|
|
51
50
|
root_span = Span.new(
|
|
52
51
|
name,
|
|
53
52
|
trace_id: trace_id,
|
|
54
|
-
span_type:
|
|
53
|
+
span_type: span_type,
|
|
55
54
|
**default_attributes.merge(attributes)
|
|
56
55
|
)
|
|
56
|
+
trace.add_span(root_span)
|
|
57
57
|
|
|
58
58
|
with_span(root_span) do
|
|
59
59
|
result = yield(root_span)
|
|
60
60
|
root_span.finish
|
|
61
|
-
|
|
61
|
+
reporter.report(redact_trace!(trace))
|
|
62
62
|
result
|
|
63
63
|
end
|
|
64
64
|
rescue StandardError => e
|
|
65
|
-
root_span
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
if root_span && !root_span.finished?
|
|
66
|
+
root_span.record_error(e)
|
|
67
|
+
root_span.finish
|
|
68
|
+
reporter.report(redact_trace!(trace))
|
|
69
|
+
end
|
|
68
70
|
raise
|
|
69
71
|
end
|
|
70
72
|
|
|
@@ -76,11 +78,12 @@ module ActiveAgent
|
|
|
76
78
|
def span(name, **attributes)
|
|
77
79
|
return Telemetry::NullSpan.new unless should_trace?
|
|
78
80
|
|
|
81
|
+
span_type = attributes.delete(:span_type) || :root
|
|
79
82
|
current = current_span
|
|
80
83
|
if current
|
|
81
|
-
current.add_span(name, **attributes)
|
|
84
|
+
current.add_span(name, span_type: span_type, **attributes)
|
|
82
85
|
else
|
|
83
|
-
Span.new(name, trace_id:
|
|
86
|
+
Span.new(name, trace_id: SecureRandom.hex(16), span_type: span_type, **default_attributes.merge(attributes))
|
|
84
87
|
end
|
|
85
88
|
end
|
|
86
89
|
|
|
@@ -91,7 +94,9 @@ module ActiveAgent
|
|
|
91
94
|
Thread.current[CURRENT_SPAN_KEY]
|
|
92
95
|
end
|
|
93
96
|
|
|
94
|
-
# Flushes buffered traces
|
|
97
|
+
# Flushes buffered traces and waits for delivery to complete, so
|
|
98
|
+
# callers (tests, rails runner, job shutdown) can rely on the traces
|
|
99
|
+
# having been delivered/stored when this returns.
|
|
95
100
|
#
|
|
96
101
|
# @return [void]
|
|
97
102
|
def flush
|
|
@@ -107,11 +112,16 @@ module ActiveAgent
|
|
|
107
112
|
|
|
108
113
|
private
|
|
109
114
|
|
|
115
|
+
def build_trace(trace_id)
|
|
116
|
+
ActiveAgents::Telemetry::Trace.new(
|
|
117
|
+
trace_id: trace_id,
|
|
118
|
+
service_name: configuration.resolved_service_name,
|
|
119
|
+
environment: configuration.resolved_environment,
|
|
120
|
+
resource_attributes: configuration.resource_attributes
|
|
121
|
+
)
|
|
122
|
+
end
|
|
123
|
+
|
|
110
124
|
# Executes block with span as current context.
|
|
111
|
-
#
|
|
112
|
-
# @param span [Span] Span to set as current
|
|
113
|
-
# @yield Block to execute
|
|
114
|
-
# @return [Object] Result of block
|
|
115
125
|
def with_span(span)
|
|
116
126
|
previous = Thread.current[CURRENT_SPAN_KEY]
|
|
117
127
|
Thread.current[CURRENT_SPAN_KEY] = span
|
|
@@ -120,61 +130,48 @@ module ActiveAgent
|
|
|
120
130
|
Thread.current[CURRENT_SPAN_KEY] = previous
|
|
121
131
|
end
|
|
122
132
|
|
|
123
|
-
#
|
|
124
|
-
#
|
|
125
|
-
#
|
|
126
|
-
|
|
127
|
-
|
|
133
|
+
# Redacts span (and span-event) attributes whose keys match any
|
|
134
|
+
# configured redact_attributes entry, before the trace is handed to
|
|
135
|
+
# the reporter. Matching is case-insensitive substring — deliberately
|
|
136
|
+
# over-broad: better to redact a harmless "max_tokens" than to ship
|
|
137
|
+
# an "api_key". (Ported from the pre-shared-core payload builder,
|
|
138
|
+
# which no longer exists — the gem's reporter ships the trace as-is.)
|
|
139
|
+
REDACTED = "[REDACTED]"
|
|
140
|
+
|
|
141
|
+
def redact_trace!(trace)
|
|
142
|
+
patterns = Array(configuration.redact_attributes).map(&:to_s).reject(&:empty?)
|
|
143
|
+
return trace if patterns.empty?
|
|
144
|
+
|
|
145
|
+
matcher = Regexp.union(patterns.map { |pattern| Regexp.new(Regexp.escape(pattern), Regexp::IGNORECASE) })
|
|
146
|
+
Array(trace.spans).each { |span| redact_span!(span, matcher) }
|
|
147
|
+
trace
|
|
128
148
|
end
|
|
129
149
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
service_name: configuration.resolved_service_name,
|
|
138
|
-
environment: configuration.environment,
|
|
139
|
-
timestamp: Time.current.iso8601(6),
|
|
140
|
-
resource_attributes: configuration.resource_attributes,
|
|
141
|
-
spans: flatten_spans(root_span)
|
|
142
|
-
}
|
|
150
|
+
def redact_span!(span, matcher)
|
|
151
|
+
redact_hash!(span.attributes, matcher) if span.attributes.is_a?(Hash)
|
|
152
|
+
Array(span.events).each do |event|
|
|
153
|
+
attributes = event.is_a?(Hash) ? (event["attributes"] || event[:attributes]) : nil
|
|
154
|
+
redact_hash!(attributes, matcher) if attributes.is_a?(Hash)
|
|
155
|
+
end
|
|
156
|
+
Array(span.children).each { |child| redact_span!(child, matcher) }
|
|
143
157
|
end
|
|
144
158
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
# @return [Array<Hash>] Flattened span data
|
|
149
|
-
def flatten_spans(span)
|
|
150
|
-
result = [ span.to_h.except(:children) ]
|
|
151
|
-
span.children.each do |child|
|
|
152
|
-
result.concat(flatten_spans(child))
|
|
159
|
+
def redact_hash!(attributes, matcher)
|
|
160
|
+
attributes.each_key do |key|
|
|
161
|
+
attributes[key] = REDACTED if key.to_s.match?(matcher)
|
|
153
162
|
end
|
|
154
|
-
result
|
|
155
163
|
end
|
|
156
164
|
|
|
157
|
-
# Returns whether this trace should be
|
|
158
|
-
#
|
|
159
|
-
# @return [Boolean]
|
|
165
|
+
# Returns whether this trace should be collected at all.
|
|
160
166
|
def should_trace?
|
|
161
167
|
configuration.enabled? && configuration.configured? && configuration.should_sample?
|
|
162
168
|
end
|
|
163
169
|
|
|
164
|
-
# Generates a unique trace ID.
|
|
165
|
-
#
|
|
166
|
-
# @return [String] 32-character hex trace ID
|
|
167
|
-
def generate_trace_id
|
|
168
|
-
SecureRandom.hex(16)
|
|
169
|
-
end
|
|
170
|
-
|
|
171
170
|
# Returns default attributes for all spans.
|
|
172
|
-
#
|
|
173
|
-
# @return [Hash] Default attributes
|
|
174
171
|
def default_attributes
|
|
175
172
|
{
|
|
176
173
|
"service.name" => configuration.resolved_service_name,
|
|
177
|
-
"service.environment" => configuration.
|
|
174
|
+
"service.environment" => configuration.resolved_environment,
|
|
178
175
|
"telemetry.sdk.name" => "activeagent",
|
|
179
176
|
"telemetry.sdk.version" => ActiveAgent::VERSION
|
|
180
177
|
}
|
data/lib/active_agent/version.rb
CHANGED
data/lib/active_agent.rb
CHANGED
|
@@ -16,6 +16,10 @@ require "active_support/lazy_load_hooks"
|
|
|
16
16
|
# Module Level Extensions
|
|
17
17
|
require "active_agent/configuration"
|
|
18
18
|
require "active_agent/railtie" if defined?(Rails)
|
|
19
|
+
# The dashboard is a Rails engine; engines must be defined when the gem is
|
|
20
|
+
# required (before the host app collects railtie initializers), so it
|
|
21
|
+
# cannot be left to the Dashboard autoload above.
|
|
22
|
+
require "active_agent/dashboard" if defined?(Rails)
|
|
19
23
|
|
|
20
24
|
# ActiveAgent is a framework for building AI agents with Rails-like conventions.
|
|
21
25
|
#
|
|
@@ -101,6 +105,7 @@ module ActiveAgent
|
|
|
101
105
|
autoload :Preview, "active_agent/concerns/preview"
|
|
102
106
|
autoload :Previews, "active_agent/concerns/preview"
|
|
103
107
|
autoload :GenerationJob
|
|
108
|
+
autoload :ModelCapabilities
|
|
104
109
|
autoload :Observers, "active_agent/concerns/observers"
|
|
105
110
|
autoload :Provider, "active_agent/concerns/provider"
|
|
106
111
|
autoload :Rescue, "active_agent/concerns/rescue"
|
|
@@ -22,7 +22,18 @@ module ActiveAgent
|
|
|
22
22
|
|
|
23
23
|
desc "Installs the ActiveAgent Dashboard with telemetry storage"
|
|
24
24
|
|
|
25
|
+
class_option :multi_tenant, type: :boolean, default: false,
|
|
26
|
+
desc: "Scope traces to an Account (adds account_id to the migration)"
|
|
27
|
+
|
|
28
|
+
class_option :skip_migrations, type: :boolean, default: false,
|
|
29
|
+
desc: "Skip copying the telemetry traces migration"
|
|
30
|
+
|
|
31
|
+
class_option :skip_routes, type: :boolean, default: false,
|
|
32
|
+
desc: "Skip adding the engine mount to routes.rb"
|
|
33
|
+
|
|
25
34
|
def copy_migrations
|
|
35
|
+
return if options[:skip_migrations]
|
|
36
|
+
|
|
26
37
|
migration_template(
|
|
27
38
|
"create_active_agent_telemetry_traces.rb.erb",
|
|
28
39
|
"db/migrate/create_active_agent_telemetry_traces.rb"
|
|
@@ -30,7 +41,19 @@ module ActiveAgent
|
|
|
30
41
|
end
|
|
31
42
|
|
|
32
43
|
def add_route
|
|
33
|
-
|
|
44
|
+
return if options[:skip_routes]
|
|
45
|
+
|
|
46
|
+
# Rails' `route` action is only idempotent on an exact string match,
|
|
47
|
+
# so an app installed before the default path changed would get a
|
|
48
|
+
# second mount — and two unnamed mounts of the same engine raise
|
|
49
|
+
# "Invalid route name, already in use: 'active_agent'" at boot.
|
|
50
|
+
routes_file = File.join(destination_root, "config/routes.rb")
|
|
51
|
+
if File.exist?(routes_file) && File.read(routes_file).include?("ActiveAgent::Dashboard::Engine")
|
|
52
|
+
say_status :skip, "engine already mounted in config/routes.rb", :yellow
|
|
53
|
+
return
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
route 'mount ActiveAgent::Dashboard::Engine => "/activeagents"'
|
|
34
57
|
end
|
|
35
58
|
|
|
36
59
|
def create_initializer
|
|
@@ -50,7 +73,7 @@ module ActiveAgent
|
|
|
50
73
|
say " telemetry:"
|
|
51
74
|
say " enabled: true"
|
|
52
75
|
say " local_storage: true"
|
|
53
|
-
say " 3. Visit /
|
|
76
|
+
say " 3. Visit /activeagents to view the dashboard"
|
|
54
77
|
say "\n"
|
|
55
78
|
end
|
|
56
79
|
|
|
@@ -59,6 +82,11 @@ module ActiveAgent
|
|
|
59
82
|
def migration_version
|
|
60
83
|
"[#{ActiveRecord::Migration.current_version}]"
|
|
61
84
|
end
|
|
85
|
+
|
|
86
|
+
# Consumed by the migration template.
|
|
87
|
+
def multi_tenant?
|
|
88
|
+
options[:multi_tenant]
|
|
89
|
+
end
|
|
62
90
|
end
|
|
63
91
|
end
|
|
64
92
|
end
|
|
@@ -3,13 +3,17 @@
|
|
|
3
3
|
# ActiveAgent Dashboard Configuration
|
|
4
4
|
#
|
|
5
5
|
# This file configures the ActiveAgent telemetry dashboard.
|
|
6
|
-
# The dashboard is mounted at /
|
|
6
|
+
# The dashboard is mounted at /activeagents by default (see config/routes.rb).
|
|
7
7
|
|
|
8
8
|
ActiveAgent::Dashboard.configure do |config|
|
|
9
|
-
#
|
|
10
|
-
#
|
|
9
|
+
# ==========================================================================
|
|
10
|
+
# Authentication (required in production)
|
|
11
|
+
# ==========================================================================
|
|
11
12
|
#
|
|
12
|
-
#
|
|
13
|
+
# Provide a lambda that receives the controller and performs
|
|
14
|
+
# authentication. Return false or raise to deny access. Without one, the
|
|
15
|
+
# dashboard serves a 403 in production — traces contain prompts, outputs
|
|
16
|
+
# and error messages.
|
|
13
17
|
#
|
|
14
18
|
# Basic auth:
|
|
15
19
|
# config.authentication_method = ->(controller) {
|
|
@@ -27,4 +31,37 @@ ActiveAgent::Dashboard.configure do |config|
|
|
|
27
31
|
# config.authentication_method = nil
|
|
28
32
|
#
|
|
29
33
|
config.authentication_method = nil
|
|
34
|
+
|
|
35
|
+
# ==========================================================================
|
|
36
|
+
# Ingest API authentication
|
|
37
|
+
# ==========================================================================
|
|
38
|
+
#
|
|
39
|
+
# Bearer token other apps must send when posting traces to the mounted
|
|
40
|
+
# ingest endpoint (/activeagents/api/traces). Leave unset only when the
|
|
41
|
+
# mount is not reachable beyond your own machine.
|
|
42
|
+
#
|
|
43
|
+
# config.ingest_api_key = Rails.application.credentials.dig(:active_agent, :ingest_api_key)
|
|
44
|
+
|
|
45
|
+
# ==========================================================================
|
|
46
|
+
# Multi-tenant mode (SaaS platforms only)
|
|
47
|
+
# ==========================================================================
|
|
48
|
+
#
|
|
49
|
+
# Scopes traces per account and authenticates ingest with per-account
|
|
50
|
+
# keys. Most self-hosted installs should leave this off.
|
|
51
|
+
#
|
|
52
|
+
# config.multi_tenant = true
|
|
53
|
+
# config.account_class = "Account"
|
|
54
|
+
# config.user_class = "User"
|
|
55
|
+
# config.current_account_method = :current_account
|
|
56
|
+
# config.current_user_method = :current_user
|
|
57
|
+
|
|
58
|
+
# ==========================================================================
|
|
59
|
+
# UI
|
|
60
|
+
# ==========================================================================
|
|
61
|
+
#
|
|
62
|
+
# Custom layout for dashboard views (the default layout loads Tailwind,
|
|
63
|
+
# Turbo and Stimulus from CDNs — override for CSP-strict or air-gapped
|
|
64
|
+
# environments).
|
|
65
|
+
#
|
|
66
|
+
# config.layout = "application"
|
|
30
67
|
end
|
data/lib/generators/active_agent/dashboard/templates/create_active_agent_telemetry_traces.rb.erb
CHANGED
|
@@ -3,13 +3,21 @@
|
|
|
3
3
|
class CreateActiveAgentTelemetryTraces < ActiveRecord::Migration<%= migration_version %>
|
|
4
4
|
def change
|
|
5
5
|
create_table :active_agent_telemetry_traces do |t|
|
|
6
|
-
|
|
6
|
+
<% if multi_tenant? -%>
|
|
7
|
+
# Multi-tenant mode: every query is scoped through `for_account`, and
|
|
8
|
+
# ingest authenticates a per-account key. The foreign key requires an
|
|
9
|
+
# existing `accounts` table — on PostgreSQL/MySQL this migration must
|
|
10
|
+
# run after the one that creates it (drop `foreign_key: true` if your
|
|
11
|
+
# tenant table is named differently).
|
|
12
|
+
t.references :account, null: false, foreign_key: true
|
|
13
|
+
<% end -%>
|
|
14
|
+
t.string :trace_id, null: false
|
|
7
15
|
t.string :service_name
|
|
8
16
|
t.string :environment
|
|
9
17
|
t.datetime :timestamp, index: true
|
|
10
|
-
t.
|
|
11
|
-
t.
|
|
12
|
-
t.
|
|
18
|
+
t.json :spans, default: []
|
|
19
|
+
t.json :resource_attributes, default: {}
|
|
20
|
+
t.json :sdk_info, default: {}
|
|
13
21
|
t.decimal :total_duration_ms, precision: 12, scale: 3
|
|
14
22
|
t.integer :total_input_tokens, default: 0
|
|
15
23
|
t.integer :total_output_tokens, default: 0
|
|
@@ -22,6 +30,14 @@ class CreateActiveAgentTelemetryTraces < ActiveRecord::Migration<%= migration_ve
|
|
|
22
30
|
t.timestamps
|
|
23
31
|
end
|
|
24
32
|
|
|
33
|
+
<% if multi_tenant? -%>
|
|
34
|
+
# Ingest dedupes on trace_id (per account when multi-tenant); the unique
|
|
35
|
+
# index makes that dedupe race-proof rather than check-then-insert.
|
|
36
|
+
add_index :active_agent_telemetry_traces, [:account_id, :trace_id], unique: true
|
|
37
|
+
add_index :active_agent_telemetry_traces, [:account_id, :timestamp]
|
|
38
|
+
<% else -%>
|
|
39
|
+
add_index :active_agent_telemetry_traces, :trace_id, unique: true
|
|
40
|
+
<% end -%>
|
|
25
41
|
add_index :active_agent_telemetry_traces, :status
|
|
26
42
|
add_index :active_agent_telemetry_traces, [:agent_class, :agent_action]
|
|
27
43
|
add_index :active_agent_telemetry_traces, [:service_name, :environment]
|
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.0
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justin Bowen
|
|
@@ -109,6 +109,20 @@ dependencies:
|
|
|
109
109
|
- - "<="
|
|
110
110
|
- !ruby/object:Gem::Version
|
|
111
111
|
version: '9.0'
|
|
112
|
+
- !ruby/object:Gem::Dependency
|
|
113
|
+
name: activeagents-telemetry
|
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
|
115
|
+
requirements:
|
|
116
|
+
- - "~>"
|
|
117
|
+
- !ruby/object:Gem::Version
|
|
118
|
+
version: '0.1'
|
|
119
|
+
type: :runtime
|
|
120
|
+
prerelease: false
|
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
122
|
+
requirements:
|
|
123
|
+
- - "~>"
|
|
124
|
+
- !ruby/object:Gem::Version
|
|
125
|
+
version: '0.1'
|
|
112
126
|
- !ruby/object:Gem::Dependency
|
|
113
127
|
name: jbuilder
|
|
114
128
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -418,6 +432,7 @@ files:
|
|
|
418
432
|
- lib/active_agent/generation.rb
|
|
419
433
|
- lib/active_agent/generation_job.rb
|
|
420
434
|
- lib/active_agent/inline_preview_interceptor.rb
|
|
435
|
+
- lib/active_agent/model_capabilities.rb
|
|
421
436
|
- lib/active_agent/providers/_base_provider.rb
|
|
422
437
|
- lib/active_agent/providers/anthropic/_types.rb
|
|
423
438
|
- lib/active_agent/providers/anthropic/options.rb
|
|
@@ -453,6 +468,7 @@ files:
|
|
|
453
468
|
- lib/active_agent/providers/concerns/instrumentation.rb
|
|
454
469
|
- lib/active_agent/providers/concerns/previewable.rb
|
|
455
470
|
- lib/active_agent/providers/concerns/tool_choice_clearing.rb
|
|
471
|
+
- lib/active_agent/providers/errors.rb
|
|
456
472
|
- lib/active_agent/providers/gemini/_types.rb
|
|
457
473
|
- lib/active_agent/providers/gemini/options.rb
|
|
458
474
|
- lib/active_agent/providers/gemini_provider.rb
|
|
@@ -540,16 +556,6 @@ files:
|
|
|
540
556
|
- lib/activeagent.rb
|
|
541
557
|
- lib/generators/active_agent/agent/USAGE
|
|
542
558
|
- lib/generators/active_agent/agent/agent_generator.rb
|
|
543
|
-
- lib/generators/active_agent/dashboard/install/install_generator.rb
|
|
544
|
-
- lib/generators/active_agent/dashboard/install/templates/initializer.rb
|
|
545
|
-
- lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agent_runs.rb
|
|
546
|
-
- lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agent_templates.rb
|
|
547
|
-
- lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agent_versions.rb
|
|
548
|
-
- lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agents.rb
|
|
549
|
-
- lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_sandbox_runs.rb
|
|
550
|
-
- lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_sandbox_sessions.rb
|
|
551
|
-
- lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_session_recordings.rb
|
|
552
|
-
- lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_telemetry_traces.rb
|
|
553
559
|
- lib/generators/active_agent/dashboard/install_generator.rb
|
|
554
560
|
- lib/generators/active_agent/dashboard/templates/active_agent_dashboard.rb.erb
|
|
555
561
|
- lib/generators/active_agent/dashboard/templates/create_active_agent_telemetry_traces.rb.erb
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "rails/generators"
|
|
4
|
-
require "rails/generators/active_record"
|
|
5
|
-
|
|
6
|
-
module ActiveAgent
|
|
7
|
-
module Dashboard
|
|
8
|
-
module Generators
|
|
9
|
-
# Generator for installing the ActiveAgent Dashboard engine.
|
|
10
|
-
#
|
|
11
|
-
# Usage:
|
|
12
|
-
# rails generate active_agent:dashboard:install
|
|
13
|
-
#
|
|
14
|
-
# This will:
|
|
15
|
-
# - Copy migration files for all dashboard models
|
|
16
|
-
# - Create an initializer for configuration
|
|
17
|
-
# - Add the engine mount to routes.rb
|
|
18
|
-
# - Seed default agent templates
|
|
19
|
-
#
|
|
20
|
-
class InstallGenerator < Rails::Generators::Base
|
|
21
|
-
include ActiveRecord::Generators::Migration
|
|
22
|
-
|
|
23
|
-
source_root File.expand_path("templates", __dir__)
|
|
24
|
-
|
|
25
|
-
class_option :multi_tenant, type: :boolean, default: false,
|
|
26
|
-
desc: "Configure for multi-tenant mode with account association"
|
|
27
|
-
|
|
28
|
-
class_option :skip_migrations, type: :boolean, default: false,
|
|
29
|
-
desc: "Skip copying migration files"
|
|
30
|
-
|
|
31
|
-
class_option :skip_routes, type: :boolean, default: false,
|
|
32
|
-
desc: "Skip adding route mount"
|
|
33
|
-
|
|
34
|
-
def copy_migrations
|
|
35
|
-
return if options[:skip_migrations]
|
|
36
|
-
|
|
37
|
-
migration_template "migrations/create_active_agent_agents.rb",
|
|
38
|
-
"db/migrate/create_active_agent_agents.rb"
|
|
39
|
-
|
|
40
|
-
migration_template "migrations/create_active_agent_agent_versions.rb",
|
|
41
|
-
"db/migrate/create_active_agent_agent_versions.rb"
|
|
42
|
-
|
|
43
|
-
migration_template "migrations/create_active_agent_agent_runs.rb",
|
|
44
|
-
"db/migrate/create_active_agent_agent_runs.rb"
|
|
45
|
-
|
|
46
|
-
migration_template "migrations/create_active_agent_agent_templates.rb",
|
|
47
|
-
"db/migrate/create_active_agent_agent_templates.rb"
|
|
48
|
-
|
|
49
|
-
migration_template "migrations/create_active_agent_sandbox_sessions.rb",
|
|
50
|
-
"db/migrate/create_active_agent_sandbox_sessions.rb"
|
|
51
|
-
|
|
52
|
-
migration_template "migrations/create_active_agent_sandbox_runs.rb",
|
|
53
|
-
"db/migrate/create_active_agent_sandbox_runs.rb"
|
|
54
|
-
|
|
55
|
-
migration_template "migrations/create_active_agent_session_recordings.rb",
|
|
56
|
-
"db/migrate/create_active_agent_session_recordings.rb"
|
|
57
|
-
|
|
58
|
-
migration_template "migrations/create_active_agent_telemetry_traces.rb",
|
|
59
|
-
"db/migrate/create_active_agent_telemetry_traces.rb"
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def create_initializer
|
|
63
|
-
template "initializer.rb", "config/initializers/active_agent_dashboard.rb"
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def mount_engine
|
|
67
|
-
return if options[:skip_routes]
|
|
68
|
-
|
|
69
|
-
route 'mount ActiveAgent::Dashboard::Engine => "/active_agent"'
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def show_post_install
|
|
73
|
-
say ""
|
|
74
|
-
say "ActiveAgent Dashboard installed!", :green
|
|
75
|
-
say ""
|
|
76
|
-
say "Next steps:"
|
|
77
|
-
say " 1. Run migrations: rails db:migrate"
|
|
78
|
-
say " 2. Seed templates: rails active_agent:dashboard:seed"
|
|
79
|
-
say " 3. Configure authentication in config/initializers/active_agent_dashboard.rb"
|
|
80
|
-
say " 4. Visit /active_agent to access the dashboard"
|
|
81
|
-
say ""
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
private
|
|
85
|
-
|
|
86
|
-
def migration_version
|
|
87
|
-
"[#{ActiveRecord::Migration.current_version}]"
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def multi_tenant?
|
|
91
|
-
options[:multi_tenant]
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
end
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# ActiveAgent Dashboard Configuration
|
|
4
|
-
#
|
|
5
|
-
# This initializer configures the ActiveAgent Dashboard engine.
|
|
6
|
-
# See https://docs.activeagents.ai/dashboard for full documentation.
|
|
7
|
-
|
|
8
|
-
ActiveAgent::Dashboard.configure do |config|
|
|
9
|
-
# ==========================================================================
|
|
10
|
-
# Authentication
|
|
11
|
-
# ==========================================================================
|
|
12
|
-
|
|
13
|
-
# Set an authentication method that will be called on all dashboard controllers.
|
|
14
|
-
# This should authenticate the user and redirect/raise if unauthorized.
|
|
15
|
-
#
|
|
16
|
-
# Examples:
|
|
17
|
-
# config.authentication_method = ->(controller) { controller.authenticate_admin! }
|
|
18
|
-
# config.authentication_method = ->(controller) { controller.authenticate_user! }
|
|
19
|
-
#
|
|
20
|
-
# config.authentication_method = nil
|
|
21
|
-
|
|
22
|
-
<% if multi_tenant? -%>
|
|
23
|
-
# ==========================================================================
|
|
24
|
-
# Multi-tenant Mode
|
|
25
|
-
# ==========================================================================
|
|
26
|
-
|
|
27
|
-
# Enable multi-tenant mode for SaaS deployments with multiple accounts.
|
|
28
|
-
config.multi_tenant = true
|
|
29
|
-
|
|
30
|
-
# The Account model class name
|
|
31
|
-
config.account_class = "Account"
|
|
32
|
-
|
|
33
|
-
# The User model class name
|
|
34
|
-
config.user_class = "User"
|
|
35
|
-
|
|
36
|
-
# Method to call on controllers to get the current account
|
|
37
|
-
config.current_account_method = :current_account
|
|
38
|
-
|
|
39
|
-
# Method to call on controllers to get the current user
|
|
40
|
-
config.current_user_method = :current_user
|
|
41
|
-
|
|
42
|
-
<% else -%>
|
|
43
|
-
# ==========================================================================
|
|
44
|
-
# Local Mode (default)
|
|
45
|
-
# ==========================================================================
|
|
46
|
-
|
|
47
|
-
# Multi-tenant mode is disabled by default.
|
|
48
|
-
# Set to true if you're building a SaaS platform with multiple accounts.
|
|
49
|
-
# config.multi_tenant = false
|
|
50
|
-
|
|
51
|
-
# Optional: Associate agents with users
|
|
52
|
-
# config.user_class = "User"
|
|
53
|
-
# config.current_user_method = :current_user
|
|
54
|
-
|
|
55
|
-
<% end -%>
|
|
56
|
-
# ==========================================================================
|
|
57
|
-
# Sandbox Configuration
|
|
58
|
-
# ==========================================================================
|
|
59
|
-
|
|
60
|
-
# Sandbox service type for agent execution environments.
|
|
61
|
-
# Options: :local (Docker/Incus), :cloud_run, :kubernetes
|
|
62
|
-
config.sandbox_service = :local
|
|
63
|
-
|
|
64
|
-
# Custom sandbox limits (optional)
|
|
65
|
-
# config.sandbox_limits = {
|
|
66
|
-
# max_runs: 10,
|
|
67
|
-
# timeout_seconds: 300,
|
|
68
|
-
# max_tokens: 50_000,
|
|
69
|
-
# session_duration_minutes: 15
|
|
70
|
-
# }
|
|
71
|
-
|
|
72
|
-
# ==========================================================================
|
|
73
|
-
# UI Configuration
|
|
74
|
-
# ==========================================================================
|
|
75
|
-
|
|
76
|
-
# Use Inertia.js with React for the frontend (requires additional setup)
|
|
77
|
-
# config.use_inertia = false
|
|
78
|
-
|
|
79
|
-
# Custom layout for dashboard views
|
|
80
|
-
# config.layout = "application"
|
|
81
|
-
|
|
82
|
-
# ==========================================================================
|
|
83
|
-
# Storage Configuration
|
|
84
|
-
# ==========================================================================
|
|
85
|
-
|
|
86
|
-
# Storage service for screenshots and snapshots.
|
|
87
|
-
# Must respond to #signed_url_for(key, expires_in:) and #fetch_snapshot(key)
|
|
88
|
-
# config.storage_service = MyStorageService.new
|
|
89
|
-
end
|