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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +71 -0
  3. data/README.md +26 -0
  4. data/lib/active_agent/base.rb +4 -0
  5. data/lib/active_agent/dashboard/app/controllers/active_agent/dashboard/api/traces_controller.rb +27 -6
  6. data/lib/active_agent/dashboard/app/controllers/active_agent/dashboard/application_controller.rb +11 -1
  7. data/lib/active_agent/dashboard/app/controllers/active_agent/dashboard/dashboard_controller.rb +15 -12
  8. data/lib/active_agent/dashboard/app/controllers/active_agent/dashboard/traces_controller.rb +27 -7
  9. data/lib/active_agent/dashboard/app/jobs/active_agent/process_telemetry_traces_job.rb +9 -0
  10. data/lib/active_agent/dashboard/app/models/active_agent/telemetry_trace.rb +18 -2
  11. data/lib/active_agent/dashboard/app/views/active_agent/dashboard/traces/_trace_detail.html.erb +15 -3
  12. data/lib/active_agent/dashboard/app/views/active_agent/dashboard/traces/metrics.html.erb +3 -1
  13. data/lib/active_agent/dashboard/app/views/layouts/active_agent/dashboard/application.html.erb +4 -4
  14. data/lib/active_agent/dashboard/config/routes.rb +5 -64
  15. data/lib/active_agent/dashboard/engine.rb +19 -15
  16. data/lib/active_agent/dashboard.rb +13 -3
  17. data/lib/active_agent/model_capabilities.rb +89 -0
  18. data/lib/active_agent/providers/_base_provider.rb +23 -2
  19. data/lib/active_agent/providers/concerns/exception_handler.rb +12 -1
  20. data/lib/active_agent/providers/errors.rb +140 -0
  21. data/lib/active_agent/providers/ollama/chat/transforms.rb +9 -3
  22. data/lib/active_agent/railtie.rb +5 -0
  23. data/lib/active_agent/telemetry/configuration.rb +112 -172
  24. data/lib/active_agent/telemetry/instrumentation.rb +137 -14
  25. data/lib/active_agent/telemetry/reporter.rb +12 -165
  26. data/lib/active_agent/telemetry/span.rb +18 -245
  27. data/lib/active_agent/telemetry/tracer.rb +67 -70
  28. data/lib/active_agent/telemetry.rb +1 -2
  29. data/lib/active_agent/version.rb +1 -1
  30. data/lib/active_agent.rb +5 -0
  31. data/lib/generators/active_agent/dashboard/install_generator.rb +30 -2
  32. data/lib/generators/active_agent/dashboard/templates/active_agent_dashboard.rb.erb +41 -4
  33. data/lib/generators/active_agent/dashboard/templates/create_active_agent_telemetry_traces.rb.erb +20 -4
  34. metadata +17 -11
  35. data/lib/generators/active_agent/dashboard/install/install_generator.rb +0 -96
  36. data/lib/generators/active_agent/dashboard/install/templates/initializer.rb +0 -89
  37. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agent_runs.rb +0 -42
  38. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agent_templates.rb +0 -38
  39. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agent_versions.rb +0 -22
  40. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agents.rb +0 -53
  41. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_sandbox_runs.rb +0 -28
  42. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_sandbox_sessions.rb +0 -43
  43. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_session_recordings.rb +0 -44
  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
- # The Tracer creates traces, manages the current trace context,
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 = generate_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: :root,
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
- report_trace(root_span)
61
+ reporter.report(redact_trace!(trace))
62
62
  result
63
63
  end
64
64
  rescue StandardError => e
65
- root_span&.record_error(e)
66
- root_span&.finish
67
- report_trace(root_span) if root_span
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: generate_trace_id, **default_attributes.merge(attributes))
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 immediately.
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
- # Reports a completed trace to the reporter.
124
- #
125
- # @param span [Span] Root span of the trace
126
- def report_trace(span)
127
- reporter.report(build_trace_payload(span))
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
- # Builds the trace payload for transmission.
131
- #
132
- # @param root_span [Span] Root span
133
- # @return [Hash] Trace payload
134
- def build_trace_payload(root_span)
135
- {
136
- trace_id: root_span.trace_id,
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
- # Flattens span hierarchy into array.
146
- #
147
- # @param span [Span] Root span
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 sampled.
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.environment,
174
+ "service.environment" => configuration.resolved_environment,
178
175
  "telemetry.sdk.name" => "activeagent",
179
176
  "telemetry.sdk.version" => ActiveAgent::VERSION
180
177
  }
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "net/http"
4
- require "json"
5
3
  require "securerandom"
4
+ require "activeagents/telemetry"
6
5
 
7
6
  module ActiveAgent
8
7
  # Telemetry module for collecting and reporting agent traces.
@@ -1,3 +1,3 @@
1
1
  module ActiveAgent
2
- VERSION = "1.0.3"
2
+ VERSION = "1.1.0"
3
3
  end
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
- route 'mount ActiveAgent::Dashboard::Engine => "/active_agent"'
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 /active_agent to view the dashboard"
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 /active_agent by default.
6
+ # The dashboard is mounted at /activeagents by default (see config/routes.rb).
7
7
 
8
8
  ActiveAgent::Dashboard.configure do |config|
9
- # Authentication method - provide a lambda that receives the controller
10
- # and performs authentication. Return false or raise to deny access.
9
+ # ==========================================================================
10
+ # Authentication (required in production)
11
+ # ==========================================================================
11
12
  #
12
- # Examples:
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
@@ -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
- t.string :trace_id, null: false, index: true
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.jsonb :spans, default: []
11
- t.jsonb :resource_attributes, default: {}
12
- t.jsonb :sdk_info, default: {}
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.3
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