activeagent 1.0.1 → 1.0.2

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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -4
  3. data/lib/active_agent/base.rb +3 -2
  4. data/lib/active_agent/concerns/provider.rb +6 -2
  5. data/lib/active_agent/concerns/rescue.rb +39 -0
  6. data/lib/active_agent/concerns/streaming.rb +2 -1
  7. data/lib/active_agent/dashboard/app/controllers/active_agent/dashboard/api/traces_controller.rb +117 -0
  8. data/lib/active_agent/dashboard/app/controllers/active_agent/dashboard/application_controller.rb +54 -0
  9. data/lib/active_agent/dashboard/app/controllers/active_agent/dashboard/dashboard_controller.rb +126 -0
  10. data/lib/active_agent/dashboard/app/controllers/active_agent/dashboard/traces_controller.rb +103 -0
  11. data/lib/active_agent/dashboard/app/jobs/active_agent/dashboard/agent_execution_job.rb +56 -0
  12. data/lib/active_agent/dashboard/app/jobs/active_agent/dashboard/application_job.rb +14 -0
  13. data/lib/active_agent/dashboard/app/jobs/active_agent/dashboard/sandbox_cleanup_job.rb +49 -0
  14. data/lib/active_agent/dashboard/app/jobs/active_agent/dashboard/sandbox_provision_job.rb +65 -0
  15. data/lib/active_agent/dashboard/app/jobs/active_agent/process_telemetry_traces_job.rb +77 -0
  16. data/lib/active_agent/dashboard/app/models/active_agent/dashboard/agent.rb +256 -0
  17. data/lib/active_agent/dashboard/app/models/active_agent/dashboard/agent_run.rb +113 -0
  18. data/lib/active_agent/dashboard/app/models/active_agent/dashboard/agent_template.rb +208 -0
  19. data/lib/active_agent/dashboard/app/models/active_agent/dashboard/agent_version.rb +60 -0
  20. data/lib/active_agent/dashboard/app/models/active_agent/dashboard/application_record.rb +46 -0
  21. data/lib/active_agent/dashboard/app/models/active_agent/dashboard/recording_action.rb +125 -0
  22. data/lib/active_agent/dashboard/app/models/active_agent/dashboard/recording_snapshot.rb +83 -0
  23. data/lib/active_agent/dashboard/app/models/active_agent/dashboard/sandbox_run.rb +52 -0
  24. data/lib/active_agent/dashboard/app/models/active_agent/dashboard/sandbox_session.rb +169 -0
  25. data/lib/active_agent/dashboard/app/models/active_agent/dashboard/session_recording.rb +193 -0
  26. data/lib/active_agent/dashboard/app/models/active_agent/telemetry_trace.rb +198 -0
  27. data/lib/active_agent/dashboard/app/views/active_agent/dashboard/traces/_trace_detail.html.erb +105 -0
  28. data/lib/active_agent/dashboard/app/views/active_agent/dashboard/traces/index.html.erb +135 -0
  29. data/lib/active_agent/dashboard/app/views/active_agent/dashboard/traces/metrics.html.erb +143 -0
  30. data/lib/active_agent/dashboard/app/views/active_agent/dashboard/traces/show.html.erb +36 -0
  31. data/lib/active_agent/dashboard/app/views/layouts/active_agent/dashboard/application.html.erb +94 -0
  32. data/lib/active_agent/dashboard/config/routes.rb +78 -0
  33. data/lib/active_agent/dashboard/engine.rb +39 -0
  34. data/lib/active_agent/dashboard.rb +151 -0
  35. data/lib/active_agent/providers/_base_provider.rb +2 -1
  36. data/lib/active_agent/providers/anthropic_provider.rb +14 -4
  37. data/lib/active_agent/providers/azure/_types.rb +5 -0
  38. data/lib/active_agent/providers/azure/options.rb +111 -0
  39. data/lib/active_agent/providers/azure_open_ai_provider.rb +2 -0
  40. data/lib/active_agent/providers/azure_openai_provider.rb +2 -0
  41. data/lib/active_agent/providers/azure_provider.rb +133 -0
  42. data/lib/active_agent/providers/azureopenai_provider.rb +2 -0
  43. data/lib/active_agent/providers/bedrock/_types.rb +8 -0
  44. data/lib/active_agent/providers/bedrock/bearer_client.rb +109 -0
  45. data/lib/active_agent/providers/bedrock/options.rb +77 -0
  46. data/lib/active_agent/providers/bedrock_provider.rb +84 -0
  47. data/lib/active_agent/providers/common/messages/_types.rb +6 -2
  48. data/lib/active_agent/providers/concerns/exception_handler.rb +1 -0
  49. data/lib/active_agent/providers/gemini/_types.rb +19 -0
  50. data/lib/active_agent/providers/gemini/options.rb +41 -0
  51. data/lib/active_agent/providers/gemini_provider.rb +94 -0
  52. data/lib/active_agent/providers/open_ai/chat/transforms.rb +37 -1
  53. data/lib/active_agent/providers/open_ai/chat_provider.rb +2 -0
  54. data/lib/active_agent/providers/ruby_llm/_types.rb +77 -0
  55. data/lib/active_agent/providers/ruby_llm/embedding_request.rb +16 -0
  56. data/lib/active_agent/providers/ruby_llm/messages/_types.rb +109 -0
  57. data/lib/active_agent/providers/ruby_llm/messages/assistant.rb +27 -0
  58. data/lib/active_agent/providers/ruby_llm/messages/base.rb +48 -0
  59. data/lib/active_agent/providers/ruby_llm/messages/system.rb +18 -0
  60. data/lib/active_agent/providers/ruby_llm/messages/tool.rb +24 -0
  61. data/lib/active_agent/providers/ruby_llm/messages/user.rb +18 -0
  62. data/lib/active_agent/providers/ruby_llm/options.rb +28 -0
  63. data/lib/active_agent/providers/ruby_llm/request.rb +30 -0
  64. data/lib/active_agent/providers/ruby_llm/tool_proxy.rb +45 -0
  65. data/lib/active_agent/providers/ruby_llm_provider.rb +407 -0
  66. data/lib/active_agent/railtie.rb +32 -1
  67. data/lib/active_agent/telemetry/configuration.rb +213 -0
  68. data/lib/active_agent/telemetry/instrumentation.rb +155 -0
  69. data/lib/active_agent/telemetry/reporter.rb +176 -0
  70. data/lib/active_agent/telemetry/span.rb +267 -0
  71. data/lib/active_agent/telemetry/tracer.rb +184 -0
  72. data/lib/active_agent/telemetry.rb +162 -0
  73. data/lib/active_agent/version.rb +1 -1
  74. data/lib/active_agent.rb +2 -0
  75. data/lib/generators/active_agent/dashboard/install/install_generator.rb +96 -0
  76. data/lib/generators/active_agent/dashboard/install/templates/initializer.rb +89 -0
  77. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agent_runs.rb +42 -0
  78. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agent_templates.rb +38 -0
  79. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agent_versions.rb +22 -0
  80. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_agents.rb +53 -0
  81. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_sandbox_runs.rb +28 -0
  82. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_sandbox_sessions.rb +43 -0
  83. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_session_recordings.rb +44 -0
  84. data/lib/generators/active_agent/dashboard/install/templates/migrations/create_active_agent_telemetry_traces.rb +56 -0
  85. data/lib/generators/active_agent/dashboard/install_generator.rb +64 -0
  86. data/lib/generators/active_agent/dashboard/templates/active_agent_dashboard.rb.erb +30 -0
  87. data/lib/generators/active_agent/dashboard/templates/create_active_agent_telemetry_traces.rb.erb +30 -0
  88. metadata +99 -13
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAgent
4
+ module Telemetry
5
+ # Manages trace creation and lifecycle.
6
+ #
7
+ # The Tracer creates traces, manages the current trace context,
8
+ # and coordinates with the Reporter for async transmission.
9
+ #
10
+ # @example Basic usage
11
+ # tracer = Tracer.new(configuration)
12
+ # tracer.trace("MyAgent.greet") do |span|
13
+ # span.set_attribute("user_id", 123)
14
+ # span.add_span("llm.generate", span_type: :llm)
15
+ # end
16
+ #
17
+ class Tracer
18
+ # @return [Configuration] Telemetry configuration
19
+ attr_reader :configuration
20
+
21
+ # @return [Reporter] The reporter for sending traces
22
+ attr_reader :reporter
23
+
24
+ # Thread-local storage for current trace context
25
+ CURRENT_SPAN_KEY = :active_agent_telemetry_current_span
26
+
27
+ def initialize(configuration)
28
+ @configuration = configuration
29
+ @reporter = Reporter.new(configuration)
30
+ @mutex = Mutex.new
31
+ end
32
+
33
+ # Creates and executes a new trace.
34
+ #
35
+ # @param name [String] Trace name (typically "AgentClass.action")
36
+ # @param attributes [Hash] Root span attributes
37
+ # @yield [span] Yields the root span for adding child spans
38
+ # @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)
48
+ return yield(Telemetry::NullSpan.new) unless should_trace?
49
+
50
+ trace_id = generate_trace_id
51
+ root_span = Span.new(
52
+ name,
53
+ trace_id: trace_id,
54
+ span_type: :root,
55
+ **default_attributes.merge(attributes)
56
+ )
57
+
58
+ with_span(root_span) do
59
+ result = yield(root_span)
60
+ root_span.finish
61
+ report_trace(root_span)
62
+ result
63
+ end
64
+ rescue StandardError => e
65
+ root_span&.record_error(e)
66
+ root_span&.finish
67
+ report_trace(root_span) if root_span
68
+ raise
69
+ end
70
+
71
+ # Creates a standalone span (not within a trace block).
72
+ #
73
+ # @param name [String] Span name
74
+ # @param attributes [Hash] Span attributes
75
+ # @return [Span] The created span
76
+ def span(name, **attributes)
77
+ return Telemetry::NullSpan.new unless should_trace?
78
+
79
+ current = current_span
80
+ if current
81
+ current.add_span(name, **attributes)
82
+ else
83
+ Span.new(name, trace_id: generate_trace_id, **default_attributes.merge(attributes))
84
+ end
85
+ end
86
+
87
+ # Returns the current span from thread-local storage.
88
+ #
89
+ # @return [Span, nil] Current span or nil
90
+ def current_span
91
+ Thread.current[CURRENT_SPAN_KEY]
92
+ end
93
+
94
+ # Flushes buffered traces immediately.
95
+ #
96
+ # @return [void]
97
+ def flush
98
+ reporter.flush
99
+ end
100
+
101
+ # Shuts down the tracer and reporter.
102
+ #
103
+ # @return [void]
104
+ def shutdown
105
+ reporter.shutdown
106
+ end
107
+
108
+ private
109
+
110
+ # 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
+ def with_span(span)
116
+ previous = Thread.current[CURRENT_SPAN_KEY]
117
+ Thread.current[CURRENT_SPAN_KEY] = span
118
+ yield
119
+ ensure
120
+ Thread.current[CURRENT_SPAN_KEY] = previous
121
+ end
122
+
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))
128
+ end
129
+
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
+ }
143
+ end
144
+
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))
153
+ end
154
+ result
155
+ end
156
+
157
+ # Returns whether this trace should be sampled.
158
+ #
159
+ # @return [Boolean]
160
+ def should_trace?
161
+ configuration.enabled? && configuration.configured? && configuration.should_sample?
162
+ end
163
+
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
+ # Returns default attributes for all spans.
172
+ #
173
+ # @return [Hash] Default attributes
174
+ def default_attributes
175
+ {
176
+ "service.name" => configuration.resolved_service_name,
177
+ "service.environment" => configuration.environment,
178
+ "telemetry.sdk.name" => "activeagent",
179
+ "telemetry.sdk.version" => ActiveAgent::VERSION
180
+ }
181
+ end
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "json"
5
+ require "securerandom"
6
+
7
+ module ActiveAgent
8
+ # Telemetry module for collecting and reporting agent traces.
9
+ #
10
+ # Provides optional observability by capturing agent generation traces,
11
+ # tool calls, token usage, and errors. Reports to a configured endpoint
12
+ # (self-hosted or ActiveAgents.ai hosted service).
13
+ #
14
+ # = Features
15
+ #
16
+ # * **Trace Collection**: Captures full generation lifecycle with spans
17
+ # * **Token Tracking**: Records input/output/thinking tokens per generation
18
+ # * **Tool Call Tracing**: Captures tool invocations with arguments and results
19
+ # * **Error Tracking**: Records errors with backtraces
20
+ # * **Async Reporting**: Non-blocking HTTP reporting with background thread
21
+ #
22
+ # = Configuration
23
+ #
24
+ # Configure in your Rails initializer or activeagent.yml:
25
+ #
26
+ # @example Basic configuration
27
+ # ActiveAgent::Telemetry.configure do |config|
28
+ # config.enabled = true
29
+ # config.endpoint = "https://api.activeagents.ai/v1/traces"
30
+ # config.api_key = Rails.application.credentials.dig(:activeagents, :api_key)
31
+ # end
32
+ #
33
+ # @example YAML configuration (config/activeagent.yml)
34
+ # telemetry:
35
+ # enabled: true
36
+ # endpoint: https://api.activeagents.ai/v1/traces
37
+ # api_key: <%= Rails.application.credentials.dig(:activeagents, :api_key) %>
38
+ # sample_rate: 1.0
39
+ # batch_size: 100
40
+ # flush_interval: 5
41
+ #
42
+ # @example Self-hosted endpoint
43
+ # ActiveAgent::Telemetry.configure do |config|
44
+ # config.endpoint = "https://observability.mycompany.com/v1/traces"
45
+ # config.api_key = ENV["TELEMETRY_API_KEY"]
46
+ # end
47
+ #
48
+ # @see ActiveAgent::Telemetry::Configuration
49
+ # @see ActiveAgent::Telemetry::Tracer
50
+ module Telemetry
51
+ extend ActiveSupport::Autoload
52
+
53
+ autoload :Configuration
54
+ autoload :Tracer
55
+ autoload :Span
56
+ autoload :Reporter
57
+ autoload :Instrumentation
58
+
59
+ class << self
60
+ # Returns the telemetry configuration instance.
61
+ #
62
+ # @return [Configuration] The configuration instance
63
+ def configuration
64
+ @configuration ||= Configuration.new
65
+ end
66
+
67
+ # Configures telemetry with a block.
68
+ #
69
+ # @yield [config] Yields the configuration instance
70
+ # @yieldparam config [Configuration] The configuration to modify
71
+ # @return [Configuration] The modified configuration
72
+ #
73
+ # @example
74
+ # ActiveAgent::Telemetry.configure do |config|
75
+ # config.enabled = true
76
+ # config.endpoint = "https://api.activeagents.ai/v1/traces"
77
+ # config.api_key = "your-api-key"
78
+ # end
79
+ def configure
80
+ yield configuration if block_given?
81
+ configuration
82
+ end
83
+
84
+ # Resets the configuration to defaults.
85
+ #
86
+ # @return [Configuration] New default configuration
87
+ def reset_configuration!
88
+ @configuration = Configuration.new
89
+ end
90
+
91
+ # Returns whether telemetry is enabled and configured.
92
+ #
93
+ # @return [Boolean] True if telemetry should collect and report
94
+ def enabled?
95
+ configuration.enabled? && configuration.configured?
96
+ end
97
+
98
+ # Returns the global tracer instance.
99
+ #
100
+ # @return [Tracer] The tracer instance
101
+ def tracer
102
+ @tracer ||= Tracer.new(configuration)
103
+ end
104
+
105
+ # Starts a new trace for an agent generation.
106
+ #
107
+ # @param name [String] Name of the trace (typically agent.action)
108
+ # @param attributes [Hash] Additional trace attributes
109
+ # @yield [trace] Yields the trace for adding spans
110
+ # @return [Span] The root span of the trace
111
+ #
112
+ # @example
113
+ # ActiveAgent::Telemetry.trace("WeatherAgent.forecast") do |trace|
114
+ # trace.add_span("llm.generate", provider: "anthropic")
115
+ # trace.set_tokens(input: 100, output: 50)
116
+ # end
117
+ def trace(name, **attributes, &block)
118
+ return yield(NullSpan.new) unless enabled?
119
+
120
+ tracer.trace(name, **attributes, &block)
121
+ end
122
+
123
+ # Records a standalone span (outside of a trace context).
124
+ #
125
+ # @param name [String] Span name
126
+ # @param attributes [Hash] Span attributes
127
+ # @return [Span] The created span
128
+ def span(name, **attributes)
129
+ return NullSpan.new unless enabled?
130
+
131
+ tracer.span(name, **attributes)
132
+ end
133
+
134
+ # Flushes any buffered traces immediately.
135
+ #
136
+ # @return [void]
137
+ def flush
138
+ tracer.flush if enabled?
139
+ end
140
+
141
+ # Shuts down telemetry, flushing remaining traces.
142
+ #
143
+ # @return [void]
144
+ def shutdown
145
+ tracer.shutdown if @tracer
146
+ end
147
+ end
148
+
149
+ # Null span implementation for when telemetry is disabled.
150
+ #
151
+ # Provides no-op methods that match Span interface to avoid
152
+ # nil checks throughout the codebase.
153
+ class NullSpan
154
+ def add_span(name, **attributes); self; end
155
+ def set_attribute(key, value); self; end
156
+ def set_tokens(input: 0, output: 0, thinking: 0); self; end
157
+ def set_status(status, message = nil); self; end
158
+ def record_error(error); self; end
159
+ def finish; self; end
160
+ end
161
+ end
162
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveAgent
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
data/lib/active_agent.rb CHANGED
@@ -106,6 +106,8 @@ module ActiveAgent
106
106
  autoload :Rescue, "active_agent/concerns/rescue"
107
107
  autoload :Tooling, "active_agent/concerns/tooling"
108
108
  autoload :View, "active_agent/concerns/view"
109
+ autoload :Telemetry
110
+ autoload :Dashboard
109
111
 
110
112
  class << self
111
113
  # Eagerly loads all ActiveAgent components and descendant agent classes.
@@ -0,0 +1,96 @@
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
@@ -0,0 +1,89 @@
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
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateActiveAgentAgentRuns < ActiveRecord::Migration<%= migration_version %>
4
+ def change
5
+ create_table :active_agent_agent_runs do |t|
6
+ t.references :agent, null: false, foreign_key: { to_table: :active_agent_agents }
7
+
8
+ # Input
9
+ t.text :input_prompt
10
+ t.jsonb :input_params, default: {}
11
+
12
+ # Output
13
+ t.text :output
14
+ t.jsonb :output_metadata, default: {}
15
+
16
+ # Execution details
17
+ t.integer :status, default: 0, null: false
18
+ t.integer :duration_ms
19
+ t.datetime :started_at
20
+ t.datetime :completed_at
21
+
22
+ # Token usage
23
+ t.integer :input_tokens
24
+ t.integer :output_tokens
25
+ t.integer :total_tokens
26
+
27
+ # Error tracking
28
+ t.text :error_message
29
+ t.text :error_backtrace
30
+
31
+ # Trace for debugging
32
+ t.string :trace_id
33
+ t.jsonb :logs, default: []
34
+
35
+ t.timestamps
36
+ end
37
+
38
+ add_index :active_agent_agent_runs, :status
39
+ add_index :active_agent_agent_runs, :trace_id
40
+ add_index :active_agent_agent_runs, :created_at
41
+ end
42
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateActiveAgentAgentTemplates < ActiveRecord::Migration<%= migration_version %>
4
+ def change
5
+ create_table :active_agent_agent_templates do |t|
6
+ t.string :name, null: false
7
+ t.string :slug, null: false
8
+ t.text :description
9
+ t.string :category
10
+
11
+ # Template configuration (same as agents)
12
+ t.string :provider, default: "openai"
13
+ t.string :model, default: "gpt-4o-mini"
14
+ t.text :instructions
15
+ t.string :preset_type
16
+ t.jsonb :appearance, default: {}
17
+ t.jsonb :instruction_sets, default: []
18
+ t.jsonb :tools, default: []
19
+ t.jsonb :mcp_servers, default: {}
20
+ t.jsonb :model_config, default: {}
21
+
22
+ # Metadata
23
+ t.string :icon
24
+ t.integer :usage_count, default: 0
25
+ t.boolean :featured, default: false
26
+ t.boolean :public, default: true
27
+ t.boolean :free_tier, default: true
28
+
29
+ t.timestamps
30
+ end
31
+
32
+ add_index :active_agent_agent_templates, :slug, unique: true
33
+ add_index :active_agent_agent_templates, :category
34
+ add_index :active_agent_agent_templates, :featured
35
+ add_index :active_agent_agent_templates, :usage_count
36
+ add_index :active_agent_agent_templates, :free_tier
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateActiveAgentAgentVersions < ActiveRecord::Migration<%= migration_version %>
4
+ def change
5
+ create_table :active_agent_agent_versions do |t|
6
+ t.references :agent, null: false, foreign_key: { to_table: :active_agent_agents }
7
+
8
+ t.integer :version_number, null: false, default: 1
9
+ t.string :change_summary
10
+
11
+ # Snapshot of agent configuration at this version
12
+ t.jsonb :configuration_snapshot, null: false, default: {}
13
+
14
+ # Who made the change
15
+ t.string :created_by
16
+
17
+ t.timestamps
18
+ end
19
+
20
+ add_index :active_agent_agent_versions, [:agent_id, :version_number], unique: true
21
+ end
22
+ end