actionagent 1.7.2 → 1.8.1
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/app/assets/builds/action_agent.css +1 -1
- data/app/assets/builds/action_agent.js +59 -54
- data/app/controllers/action_agent/api/agents_controller.rb +19 -3
- data/app/controllers/action_agent/api/code_sessions_controller.rb +168 -0
- data/app/controllers/action_agent/api/evaluations_controller.rb +74 -131
- data/app/controllers/action_agent/api/github_connections_controller.rb +147 -0
- data/app/controllers/action_agent/api/mcp_controller.rb +38 -5
- data/app/controllers/action_agent/api/mcp_servers_controller.rb +10 -1
- data/app/controllers/action_agent/api/provider_keys_controller.rb +54 -3
- data/app/controllers/action_agent/api/provider_models_controller.rb +10 -6
- data/app/controllers/action_agent/api/sandboxes_controller.rb +105 -6
- data/app/controllers/concerns/action_agent/api/evaluation_run_starting.rb +93 -0
- data/app/controllers/concerns/action_agent/api/mcp_dashboard_tools.rb +509 -0
- data/app/controllers/concerns/action_agent/api/run_sandbox.rb +65 -0
- data/app/jobs/action_agent/code_session_job.rb +171 -0
- data/app/jobs/action_agent/sandbox_cleanup_job.rb +80 -11
- data/app/jobs/action_agent/sandbox_provision_job.rb +122 -14
- data/app/jobs/action_agent/sandbox_run_job.rb +10 -3
- data/app/models/action_agent/agent.rb +49 -6
- data/app/models/action_agent/agent_run.rb +20 -1
- data/app/models/action_agent/code_session.rb +145 -0
- data/app/models/action_agent/evaluation.rb +64 -0
- data/app/models/action_agent/evaluation_run.rb +166 -54
- data/app/models/action_agent/evaluation_scenario_result.rb +15 -3
- data/app/models/action_agent/github_connection.rb +75 -0
- data/app/models/action_agent/model_pricing.rb +214 -34
- data/app/models/action_agent/provider_key.rb +148 -10
- data/app/models/action_agent/sandbox_session.rb +194 -17
- data/app/serializers/action_agent/evaluation_serializer.rb +149 -0
- data/app/serializers/action_agent/telemetry_trace_serializer.rb +10 -2
- data/app/services/action_agent/agent_execution_service.rb +4 -2
- data/app/services/action_agent/agent_scorecard.rb +50 -21
- data/app/services/action_agent/agent_tool_roster.rb +20 -9
- data/app/services/action_agent/claude_code_auth.rb +86 -0
- data/app/services/action_agent/codex_session_events.rb +37 -0
- data/app/services/action_agent/dashboard_assistant_service.rb +47 -5
- data/app/services/action_agent/evaluation_report_import.rb +84 -5
- data/app/services/action_agent/evaluation_run_cost.rb +609 -0
- data/app/services/action_agent/evaluation_runner_service.rb +25 -5
- data/app/services/action_agent/evaluation_standing.rb +145 -0
- data/app/services/action_agent/evaluation_tool_resolver.rb +18 -0
- data/app/services/action_agent/github_client.rb +111 -0
- data/app/services/action_agent/local_sandbox_backend.rb +1715 -0
- data/app/services/action_agent/local_sandbox_databases.rb +257 -0
- data/app/services/action_agent/mcp_client.rb +5 -1
- data/app/services/action_agent/mcp_tool_dispatcher.rb +137 -17
- data/app/services/action_agent/mock_sandbox_backend.rb +39 -0
- data/app/services/action_agent/ollama_host_probe.rb +75 -0
- data/app/services/action_agent/payload_bounds.rb +36 -0
- data/app/services/action_agent/sandbox_manifest.rb +67 -0
- data/app/services/action_agent/sandbox_orchestrator.rb +82 -14
- data/app/services/action_agent/scenario_evaluation_runner.rb +52 -5
- data/app/services/action_agent/secret_scrubber.rb +37 -0
- data/app/services/action_agent/tool_discovery.rb +19 -5
- data/config/routes.rb +23 -4
- data/lib/action_agent/engine.rb +1 -0
- data/lib/action_agent/version.rb +1 -1
- data/lib/action_agent.rb +153 -3
- data/lib/generators/action_agent/install_generator.rb +35 -5
- data/lib/generators/action_agent/templates/action_agent.rb.erb +47 -0
- data/lib/generators/action_agent/templates/add_code_session_runner.rb.erb +9 -0
- data/lib/generators/action_agent/templates/add_provider_key_api_key.rb.erb +25 -0
- data/lib/generators/action_agent/templates/create_active_agent_code_sessions.rb.erb +59 -0
- data/lib/generators/action_agent/templates/create_active_agent_dashboard_tables.rb.erb +2 -0
- data/lib/generators/action_agent/templates/create_active_agent_github_connections.rb.erb +61 -0
- data/lib/tasks/claude_code.rake +16 -0
- data/lib/tasks/sandbox.rake +26 -0
- metadata +28 -2
data/lib/action_agent.rb
CHANGED
|
@@ -104,6 +104,9 @@ require "action_agent/compatibility"
|
|
|
104
104
|
# end
|
|
105
105
|
#
|
|
106
106
|
module ActionAgent
|
|
107
|
+
# What ActionAgent.claude_code_auth may be set to.
|
|
108
|
+
CLAUDE_CODE_AUTH_MODES = %i[api_key local_login].freeze
|
|
109
|
+
|
|
107
110
|
class << self
|
|
108
111
|
# Deprecation warnings for this gem, routed through Rails' machinery so a
|
|
109
112
|
# host app can silence or escalate them like any other.
|
|
@@ -194,9 +197,10 @@ module ActionAgent
|
|
|
194
197
|
# @return [String, nil]
|
|
195
198
|
attr_accessor :layout
|
|
196
199
|
|
|
197
|
-
# Which sandbox backend to provision with: :mock (
|
|
198
|
-
#
|
|
199
|
-
#
|
|
200
|
+
# Which sandbox backend to provision with: :mock (an in-memory fake that
|
|
201
|
+
# runs nothing), :local (checkouts cloned and booted as child processes
|
|
202
|
+
# of the dashboard itself — see local_sandboxes_enabled), or the name of
|
|
203
|
+
# a backend the host registered in sandbox_backends. An unregistered name
|
|
200
204
|
# falls back to :mock with a logged warning.
|
|
201
205
|
# @return [Symbol]
|
|
202
206
|
attr_accessor :sandbox_service
|
|
@@ -304,6 +308,78 @@ module ActionAgent
|
|
|
304
308
|
# @return [Hash{String => String}]
|
|
305
309
|
attr_accessor :sandbox_backends
|
|
306
310
|
|
|
311
|
+
# Whether the :local sandbox backend may run. It clones the owner's
|
|
312
|
+
# repository onto the dashboard's own machine and runs its setup and
|
|
313
|
+
# server as child processes — the owner's code, with the dashboard's
|
|
314
|
+
# privileges — so it is for a developer's machine or a single-user
|
|
315
|
+
# install. Unset, it follows the environment: on in development and
|
|
316
|
+
# test, off everywhere else.
|
|
317
|
+
# @return [Boolean, nil]
|
|
318
|
+
attr_writer :local_sandboxes_enabled
|
|
319
|
+
|
|
320
|
+
# Where the :local backend keeps each sandbox's checkout, logs and
|
|
321
|
+
# process state (one directory per session). Unset, tmp/action_agent/sandboxes
|
|
322
|
+
# under the host app.
|
|
323
|
+
# @return [String, Pathname, nil]
|
|
324
|
+
attr_writer :local_sandbox_root
|
|
325
|
+
|
|
326
|
+
# How long the :local backend waits for a checkout's setup and server to
|
|
327
|
+
# come up before giving up, in seconds.
|
|
328
|
+
# @return [Integer]
|
|
329
|
+
attr_accessor :local_sandbox_boot_timeout
|
|
330
|
+
|
|
331
|
+
# The Claude Code executable a sandbox backend runs headless sessions
|
|
332
|
+
# with. The :local backend runs it on the dashboard's machine.
|
|
333
|
+
# @return [String]
|
|
334
|
+
attr_accessor :claude_code_command
|
|
335
|
+
|
|
336
|
+
# The permission mode Claude Code sessions run in. "acceptEdits" lets a
|
|
337
|
+
# session edit files in the checkout and run filesystem commands; with
|
|
338
|
+
# nobody to answer prompts, anything else that would ask is denied.
|
|
339
|
+
# @return [String]
|
|
340
|
+
attr_accessor :claude_code_permission_mode
|
|
341
|
+
|
|
342
|
+
# A cap on agentic turns per Claude Code session (nil for Claude Code's
|
|
343
|
+
# own default).
|
|
344
|
+
# @return [Integer, nil]
|
|
345
|
+
attr_accessor :claude_code_max_turns
|
|
346
|
+
|
|
347
|
+
# How long a Claude Code session may run before it is stopped, in
|
|
348
|
+
# seconds.
|
|
349
|
+
# @return [Integer]
|
|
350
|
+
attr_accessor :claude_code_timeout
|
|
351
|
+
|
|
352
|
+
# Codex CLI sessions use the owner's OpenAI API key and workspace-write
|
|
353
|
+
# sandboxing. They share checkout lifecycle and cancellation with Claude.
|
|
354
|
+
attr_accessor :codex_command, :codex_timeout
|
|
355
|
+
|
|
356
|
+
# How Claude Code sessions authenticate.
|
|
357
|
+
#
|
|
358
|
+
# :api_key (the default) runs them on the Anthropic API key the owner
|
|
359
|
+
# connected in Settings -> Integrations, handed to the session as
|
|
360
|
+
# ANTHROPIC_API_KEY. It is the only credential the dashboard stores:
|
|
361
|
+
# Anthropic does not let third-party products collect, store or route
|
|
362
|
+
# requests through Claude.ai subscription credentials
|
|
363
|
+
# (https://code.claude.com/docs/en/legal-and-compliance.md).
|
|
364
|
+
#
|
|
365
|
+
# :local_login runs `claude` on whatever login this machine's user set up
|
|
366
|
+
# with `claude /login` (or `claude auth login`), which Claude Code keeps
|
|
367
|
+
# under ~/.claude or in the keychain. The dashboard never reads, copies
|
|
368
|
+
# or stores it; it only asks `claude auth status` whether there is one.
|
|
369
|
+
# That login is the dashboard user's own, so this works with the :local
|
|
370
|
+
# sandbox backend only, and other backends refuse Claude Code sessions.
|
|
371
|
+
# @return [Symbol] :api_key or :local_login
|
|
372
|
+
attr_reader :claude_code_auth
|
|
373
|
+
|
|
374
|
+
def claude_code_auth=(value)
|
|
375
|
+
mode = value.to_s.to_sym
|
|
376
|
+
unless CLAUDE_CODE_AUTH_MODES.include?(mode)
|
|
377
|
+
raise ArgumentError, "ActionAgent.claude_code_auth must be :api_key or :local_login, not #{value.inspect}"
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
@claude_code_auth = mode
|
|
381
|
+
end
|
|
382
|
+
|
|
307
383
|
# Whether the dashboard may execute agents against real providers.
|
|
308
384
|
# Disable to run the dashboard as a read-only observability surface.
|
|
309
385
|
# @return [Boolean]
|
|
@@ -415,6 +491,20 @@ module ActionAgent
|
|
|
415
491
|
# @return [Boolean]
|
|
416
492
|
attr_accessor :encrypt_credentials
|
|
417
493
|
|
|
494
|
+
# The GitHub OAuth App the dashboard's "Connect GitHub" flow authorizes
|
|
495
|
+
# against (Settings -> Integrations). Unset, each falls back to
|
|
496
|
+
# GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET, and the dashboard offers no
|
|
497
|
+
# connection when neither is present. Register the app's callback URL as
|
|
498
|
+
# <mount>/api/github_connection/callback.
|
|
499
|
+
# @return [String, nil]
|
|
500
|
+
attr_writer :github_client_id, :github_client_secret
|
|
501
|
+
|
|
502
|
+
# OAuth scopes requested on connect. +repo+ reaches private repositories
|
|
503
|
+
# so a sandbox can clone them; narrow it to "public_repo read:user" for
|
|
504
|
+
# public checkouts only.
|
|
505
|
+
# @return [String]
|
|
506
|
+
attr_accessor :github_oauth_scopes
|
|
507
|
+
|
|
418
508
|
# MCP servers the host app itself serves or connects, appended to the
|
|
419
509
|
# built-in catalog (MCPCatalog) so the MCP Services view lists them and
|
|
420
510
|
# telemetry traffic attributes to them. Each entry is a hash shaped like
|
|
@@ -452,6 +542,17 @@ module ActionAgent
|
|
|
452
542
|
# @return [Boolean]
|
|
453
543
|
attr_accessor :mcp_schema_tools
|
|
454
544
|
|
|
545
|
+
# Whether the MCP facade (POST <mount>/mcp) offers the dashboard's own
|
|
546
|
+
# evaluation and telemetry tools — evaluations_list, evaluations_get,
|
|
547
|
+
# evaluations_run, evaluation_runs_get, evaluation_runs_compare,
|
|
548
|
+
# traces_search, traces_get — so a client's coding harness can run an
|
|
549
|
+
# agent's evaluations and read its traces while it edits the agent. Each
|
|
550
|
+
# reads under the key's owner, as the dashboard's JSON API reads under the
|
|
551
|
+
# signed-in owner. On by default; set it to false to leave the facade
|
|
552
|
+
# serving agents and schema tools only.
|
|
553
|
+
# @return [Boolean]
|
|
554
|
+
attr_accessor :mcp_dashboard_tools
|
|
555
|
+
|
|
455
556
|
# Directory scanned for SchemaTools subclasses when {#schema_tools} is
|
|
456
557
|
# unset. Relative to the host's root. Set to nil to disable discovery and
|
|
457
558
|
# require an explicit declaration. Classes built at runtime with
|
|
@@ -471,6 +572,20 @@ module ActionAgent
|
|
|
471
572
|
# Returns whether multi-tenant mode is enabled.
|
|
472
573
|
#
|
|
473
574
|
# @return [Boolean]
|
|
575
|
+
def github_client_id
|
|
576
|
+
@github_client_id.presence || ENV["GITHUB_CLIENT_ID"].presence
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
def github_client_secret
|
|
580
|
+
@github_client_secret.presence || ENV["GITHUB_CLIENT_SECRET"].presence
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
# Whether the GitHub OAuth flow can run on this install.
|
|
584
|
+
# @return [Boolean]
|
|
585
|
+
def github_oauth_configured?
|
|
586
|
+
github_client_id.present? && github_client_secret.present?
|
|
587
|
+
end
|
|
588
|
+
|
|
474
589
|
def multi_tenant?
|
|
475
590
|
@multi_tenant == true
|
|
476
591
|
end
|
|
@@ -482,6 +597,14 @@ module ActionAgent
|
|
|
482
597
|
@mcp_schema_tools != false
|
|
483
598
|
end
|
|
484
599
|
|
|
600
|
+
# Whether the MCP facade serves the dashboard's evaluation and telemetry
|
|
601
|
+
# tools.
|
|
602
|
+
#
|
|
603
|
+
# @return [Boolean]
|
|
604
|
+
def mcp_dashboard_tools?
|
|
605
|
+
@mcp_dashboard_tools != false
|
|
606
|
+
end
|
|
607
|
+
|
|
485
608
|
# Returns whether agent execution is permitted.
|
|
486
609
|
#
|
|
487
610
|
# @return [Boolean]
|
|
@@ -499,6 +622,19 @@ module ActionAgent
|
|
|
499
622
|
Rails.env.local?
|
|
500
623
|
end
|
|
501
624
|
|
|
625
|
+
# Whether the :local sandbox backend may run on this install.
|
|
626
|
+
# @return [Boolean]
|
|
627
|
+
def local_sandboxes_enabled?
|
|
628
|
+
return @local_sandboxes_enabled == true unless @local_sandboxes_enabled.nil?
|
|
629
|
+
|
|
630
|
+
Rails.env.local?
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
# @return [Pathname]
|
|
634
|
+
def local_sandbox_root
|
|
635
|
+
Pathname.new(@local_sandbox_root.presence || Rails.root.join("tmp", "action_agent", "sandboxes"))
|
|
636
|
+
end
|
|
637
|
+
|
|
502
638
|
# Tells the host app that +owner+ performed +kind+. Never raises: a
|
|
503
639
|
# bookkeeping failure must not fail the action that was already taken.
|
|
504
640
|
def record_usage(owner, kind)
|
|
@@ -633,6 +769,16 @@ module ActionAgent
|
|
|
633
769
|
@quota_checker = nil
|
|
634
770
|
@provider_credentials_resolver = nil
|
|
635
771
|
@sandbox_backends = {}
|
|
772
|
+
@local_sandboxes_enabled = nil
|
|
773
|
+
@local_sandbox_root = nil
|
|
774
|
+
@local_sandbox_boot_timeout = 600
|
|
775
|
+
@claude_code_command = "claude"
|
|
776
|
+
@claude_code_permission_mode = "acceptEdits"
|
|
777
|
+
@claude_code_max_turns = nil
|
|
778
|
+
@claude_code_timeout = 1800
|
|
779
|
+
@codex_command = "codex"
|
|
780
|
+
@codex_timeout = 1800
|
|
781
|
+
@claude_code_auth = :api_key
|
|
636
782
|
@execution_enabled = true
|
|
637
783
|
@run_host_agent_classes = false
|
|
638
784
|
@assistant_enabled = nil
|
|
@@ -641,6 +787,9 @@ module ActionAgent
|
|
|
641
787
|
@table_name_prefix = "active_agent_"
|
|
642
788
|
@agent_polymorphic_name = nil
|
|
643
789
|
@encrypt_credentials = true
|
|
790
|
+
@github_client_id = nil
|
|
791
|
+
@github_client_secret = nil
|
|
792
|
+
@github_oauth_scopes = "repo read:user"
|
|
644
793
|
@trace_retention = nil
|
|
645
794
|
@trace_owner_resolver = nil
|
|
646
795
|
@usage_recorder = nil
|
|
@@ -653,6 +802,7 @@ module ActionAgent
|
|
|
653
802
|
@schema_tools = nil
|
|
654
803
|
@schema_tools_path = "app/agent_tools"
|
|
655
804
|
@mcp_schema_tools = nil
|
|
805
|
+
@mcp_dashboard_tools = nil
|
|
656
806
|
end
|
|
657
807
|
|
|
658
808
|
# Host-declared schema tool classes, resolved from names and filtered to
|
|
@@ -102,12 +102,42 @@ module ActionAgent
|
|
|
102
102
|
# shipped. Emitted after them, so on a fresh install it runs once the
|
|
103
103
|
# table exists, finds the columns the create-table migration made, and
|
|
104
104
|
# changes nothing.
|
|
105
|
-
|
|
105
|
+
unless existing_migration?("add_evaluation_report_identity")
|
|
106
|
+
migration_template(
|
|
107
|
+
"add_evaluation_report_identity.rb.erb",
|
|
108
|
+
"db/migrate/add_evaluation_report_identity.rb"
|
|
109
|
+
)
|
|
110
|
+
end
|
|
106
111
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
)
|
|
112
|
+
# A remote Ollama's optional API key arrived after the dashboard tables
|
|
113
|
+
# shipped. Guarded, so on a fresh install it finds the column the
|
|
114
|
+
# create-table migration made and changes nothing.
|
|
115
|
+
unless existing_migration?("add_provider_key_api_key")
|
|
116
|
+
migration_template(
|
|
117
|
+
"add_provider_key_api_key.rb.erb",
|
|
118
|
+
"db/migrate/add_provider_key_api_key.rb"
|
|
119
|
+
)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# GitHub connections and checkout sandboxes, likewise later than the
|
|
123
|
+
# dashboard tables.
|
|
124
|
+
unless existing_migration?("create_active_agent_github_connections")
|
|
125
|
+
migration_template(
|
|
126
|
+
"create_active_agent_github_connections.rb.erb",
|
|
127
|
+
"db/migrate/create_active_agent_github_connections.rb"
|
|
128
|
+
)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Claude Code sessions inside those checkouts.
|
|
132
|
+
unless existing_migration?("create_active_agent_code_sessions")
|
|
133
|
+
migration_template(
|
|
134
|
+
"create_active_agent_code_sessions.rb.erb",
|
|
135
|
+
"db/migrate/create_active_agent_code_sessions.rb"
|
|
136
|
+
)
|
|
137
|
+
end
|
|
138
|
+
unless existing_migration?("add_code_session_runner")
|
|
139
|
+
migration_template("add_code_session_runner.rb.erb", "db/migrate/add_code_session_runner.rb")
|
|
140
|
+
end
|
|
111
141
|
end
|
|
112
142
|
|
|
113
143
|
def add_route
|
|
@@ -106,6 +106,53 @@ ActionAgent.configure do |config|
|
|
|
106
106
|
#
|
|
107
107
|
# config.assistant_enabled = true
|
|
108
108
|
|
|
109
|
+
# ==========================================================================
|
|
110
|
+
# Sandboxes
|
|
111
|
+
# ==========================================================================
|
|
112
|
+
#
|
|
113
|
+
# Which backend boots sandboxes: :mock (the default, in memory, runs
|
|
114
|
+
# nothing), :local, or one you register in sandbox_backends to run them in
|
|
115
|
+
# containers. The SANDBOX_BACKEND environment variable overrides it.
|
|
116
|
+
#
|
|
117
|
+
# config.sandbox_service = :local
|
|
118
|
+
# config.sandbox_backends = { "cloud_run" => "CloudRunService" }
|
|
119
|
+
#
|
|
120
|
+
# :local clones a repository connected in Settings -> Integrations onto
|
|
121
|
+
# this machine and boots it as child processes of the dashboard, as the
|
|
122
|
+
# checkout's .activeagents/sandbox.yml says. That runs the repository's
|
|
123
|
+
# code, and Claude Code sessions in it, with the dashboard's privileges, so
|
|
124
|
+
# it is off outside development and test until you enable it here.
|
|
125
|
+
#
|
|
126
|
+
# config.local_sandboxes_enabled = true
|
|
127
|
+
# config.local_sandbox_root = Rails.root.join("tmp/action_agent/sandboxes")
|
|
128
|
+
# config.local_sandbox_boot_timeout = 600 # seconds, for checkout, setup and boot
|
|
129
|
+
#
|
|
130
|
+
# Claude Code sessions in a ready checkout. Nobody is there to answer a
|
|
131
|
+
# permission prompt: "acceptEdits" lets a session edit files in the
|
|
132
|
+
# checkout and run filesystem commands, and anything else that would ask
|
|
133
|
+
# is denied.
|
|
134
|
+
#
|
|
135
|
+
# config.claude_code_command = "claude"
|
|
136
|
+
# config.claude_code_permission_mode = "acceptEdits"
|
|
137
|
+
# config.claude_code_max_turns = nil # Claude Code's own default
|
|
138
|
+
# config.claude_code_timeout = 1800 # seconds
|
|
139
|
+
# Codex uses a separate API-key connection in Settings -> Integrations.
|
|
140
|
+
# config.codex_command = "codex"
|
|
141
|
+
# config.codex_timeout = 1800 # seconds
|
|
142
|
+
#
|
|
143
|
+
# How sessions authenticate. :api_key (the default) uses the Anthropic API
|
|
144
|
+
# key connected in Settings -> Integrations (from the Claude Console,
|
|
145
|
+
# https://platform.claude.com). :local_login, with the :local backend only,
|
|
146
|
+
# uses this machine's own Claude Code login (`claude /login`); the dashboard
|
|
147
|
+
# never reads or stores it. Claude subscription tokens (`claude
|
|
148
|
+
# setup-token`) are not accepted: Anthropic does not allow third-party apps
|
|
149
|
+
# to hold Claude.ai credentials.
|
|
150
|
+
#
|
|
151
|
+
# config.claude_code_auth = :local_login
|
|
152
|
+
#
|
|
153
|
+
# Expired sandboxes are stopped by `bin/rails action_agent:sandbox:reap`.
|
|
154
|
+
# Schedule it every few minutes.
|
|
155
|
+
|
|
109
156
|
# ==========================================================================
|
|
110
157
|
# UI
|
|
111
158
|
# ==========================================================================
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddCodeSessionRunner < ActiveRecord::Migration<%= migration_version %>
|
|
4
|
+
def change
|
|
5
|
+
table = "#{ActionAgent.table_name_prefix}code_sessions"
|
|
6
|
+
add_column table, :runner, :string, null: false, default: "claude_code" unless column_exists?(table, :runner)
|
|
7
|
+
add_column table, :runner_session_id, :string unless column_exists?(table, :runner_session_id)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Adds the optional api_key column to provider keys: a host-based provider
|
|
4
|
+
# (Ollama) can be a remote server behind an authenticating proxy, or Ollama
|
|
5
|
+
# Cloud, and then needs a Bearer key alongside its host URL. Emitted for an
|
|
6
|
+
# install whose dashboard tables predate it; the create-table migration
|
|
7
|
+
# carries the column for a fresh install. Guarded, so it is safe to re-run.
|
|
8
|
+
class AddProviderKeyApiKey < ActiveRecord::Migration<%= migration_version %>
|
|
9
|
+
def up
|
|
10
|
+
return unless table_exists?(table)
|
|
11
|
+
return if column_exists?(table, :api_key)
|
|
12
|
+
|
|
13
|
+
add_column table, :api_key, :string
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def down
|
|
17
|
+
remove_column table, :api_key if table_exists?(table) && column_exists?(table, :api_key)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def table
|
|
23
|
+
"#{ActionAgent.table_name_prefix}provider_keys"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Claude Code sessions run inside an app_runtime sandbox's checkout: the
|
|
4
|
+
# prompt, the scrubbed stream-json transcript, the reported outcome and the
|
|
5
|
+
# resulting diff. Emitted alongside the dashboard tables on a fresh install,
|
|
6
|
+
# and on its own for an install that predates it.
|
|
7
|
+
#
|
|
8
|
+
# Table names follow ActionAgent.table_name_prefix, and JSON columns are
|
|
9
|
+
# jsonb on PostgreSQL and json elsewhere, the same way as
|
|
10
|
+
# create_active_agent_dashboard_tables.
|
|
11
|
+
class CreateActiveAgentCodeSessions < ActiveRecord::Migration<%= migration_version %>
|
|
12
|
+
def change
|
|
13
|
+
prefix = ActionAgent.table_name_prefix
|
|
14
|
+
|
|
15
|
+
create_table "#{prefix}code_sessions" do |t|
|
|
16
|
+
t.bigint :sandbox_session_id, null: false
|
|
17
|
+
t.text :prompt, null: false
|
|
18
|
+
t.integer :status, default: 0, null: false
|
|
19
|
+
t.column :events, json_type, **json_default([])
|
|
20
|
+
t.integer :dropped_events_count, default: 0, null: false
|
|
21
|
+
t.text :result
|
|
22
|
+
t.text :diff
|
|
23
|
+
t.text :error_message
|
|
24
|
+
t.string :model
|
|
25
|
+
t.string :claude_session_id
|
|
26
|
+
t.integer :num_turns
|
|
27
|
+
t.integer :duration_ms
|
|
28
|
+
t.decimal :total_cost_usd, precision: 12, scale: 6
|
|
29
|
+
t.integer :input_tokens
|
|
30
|
+
t.integer :output_tokens
|
|
31
|
+
t.datetime :started_at
|
|
32
|
+
t.datetime :finished_at
|
|
33
|
+
t.bigint :user_id
|
|
34
|
+
t.bigint :account_id
|
|
35
|
+
t.timestamps
|
|
36
|
+
t.index :sandbox_session_id
|
|
37
|
+
t.index :user_id
|
|
38
|
+
t.index :account_id
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def json_type
|
|
45
|
+
@json_type ||= postgres? ? :jsonb : :json
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# MySQL rejects a default on a JSON column outright, so the column is
|
|
49
|
+
# created without one there.
|
|
50
|
+
def json_default(value, null: nil)
|
|
51
|
+
return {} unless postgres?
|
|
52
|
+
|
|
53
|
+
null.nil? ? { default: value } : { default: value, null: null }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def postgres?
|
|
57
|
+
connection.adapter_name.to_s.downcase.include?("postgres")
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -326,6 +326,8 @@ class CreateActiveAgentDashboardTables < ActiveRecord::Migration<%= migration_ve
|
|
|
326
326
|
create_table "#{prefix}provider_keys" do |t|
|
|
327
327
|
t.string :provider, null: false
|
|
328
328
|
t.string :credential, null: false
|
|
329
|
+
# Optional Bearer key for a host-based provider (remote Ollama).
|
|
330
|
+
t.string :api_key
|
|
329
331
|
t.bigint :user_id
|
|
330
332
|
t.bigint :account_id
|
|
331
333
|
t.timestamps
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# GitHub connections: an owner's OAuth grant (Settings -> Integrations), the
|
|
4
|
+
# repositories they made available to the workspace, and the checkout a
|
|
5
|
+
# sandbox session boots its app runtime from. Emitted alongside the dashboard
|
|
6
|
+
# tables on a fresh install, and on its own for an install that predates it.
|
|
7
|
+
#
|
|
8
|
+
# Table names follow ActionAgent.table_name_prefix, and JSON columns are
|
|
9
|
+
# jsonb on PostgreSQL and json elsewhere, the same way as
|
|
10
|
+
# create_active_agent_dashboard_tables.
|
|
11
|
+
class CreateActiveAgentGithubConnections < ActiveRecord::Migration<%= migration_version %>
|
|
12
|
+
def change
|
|
13
|
+
prefix = ActionAgent.table_name_prefix
|
|
14
|
+
|
|
15
|
+
create_table "#{prefix}github_connections" do |t|
|
|
16
|
+
# The OAuth access token, encrypted at rest (text: ciphertext is longer
|
|
17
|
+
# than the token).
|
|
18
|
+
t.text :access_token, null: false
|
|
19
|
+
t.bigint :github_user_id, null: false
|
|
20
|
+
t.string :login, null: false
|
|
21
|
+
t.string :avatar_url
|
|
22
|
+
t.string :scopes
|
|
23
|
+
# The repositories the owner made available, as GitHub described them
|
|
24
|
+
# when they were chosen: full_name, id, private, default_branch.
|
|
25
|
+
t.column :repositories, json_type, **json_default([])
|
|
26
|
+
t.bigint :user_id
|
|
27
|
+
t.bigint :account_id
|
|
28
|
+
t.timestamps
|
|
29
|
+
t.index :account_id
|
|
30
|
+
t.index :user_id
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# A sandbox booted from a checkout of one of those repositories, and the
|
|
34
|
+
# app runtime's MCP endpoint (and the bearer token it expects, encrypted)
|
|
35
|
+
# once the backend reports them.
|
|
36
|
+
change_table "#{prefix}sandbox_sessions" do |t|
|
|
37
|
+
t.string :repository
|
|
38
|
+
t.string :repository_ref
|
|
39
|
+
t.string :runtime_mcp_url
|
|
40
|
+
t.text :runtime_mcp_token
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def json_type
|
|
47
|
+
@json_type ||= postgres? ? :jsonb : :json
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# MySQL rejects a default on a JSON column outright, so the column is
|
|
51
|
+
# created without one there.
|
|
52
|
+
def json_default(value, null: nil)
|
|
53
|
+
return {} unless postgres?
|
|
54
|
+
|
|
55
|
+
null.nil? ? { default: value } : { default: value, null: null }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def postgres?
|
|
59
|
+
connection.adapter_name.to_s.downcase.include?("postgres")
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :action_agent do
|
|
4
|
+
namespace :claude_code do
|
|
5
|
+
# Earlier versions accepted a `claude setup-token` token (a Claude
|
|
6
|
+
# subscription credential) for the Claude Code connection. Anthropic does
|
|
7
|
+
# not let third-party products store those, and they are no longer used;
|
|
8
|
+
# this removes the ones still stored. Run it once after upgrading.
|
|
9
|
+
desc "Delete stored Claude Code connections holding a Claude subscription token (sk-ant-oat…), " \
|
|
10
|
+
"which are no longer used; their owners connect an Anthropic API key instead"
|
|
11
|
+
task purge_subscription_tokens: :environment do
|
|
12
|
+
count = ActionAgent::ProviderKey.purge_subscription_tokens!
|
|
13
|
+
puts "Deleted #{count} stored Claude subscription token(s)"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :action_agent do
|
|
4
|
+
namespace :sandbox do
|
|
5
|
+
desc "Write this app's checkout sandbox runtime manifest ({mcp_path, mcp_token}) to " \
|
|
6
|
+
"$ACTION_AGENT_SANDBOX_MANIFEST, or print it"
|
|
7
|
+
task manifest: :environment do
|
|
8
|
+
manifest = JSON.generate(ActionAgent::SandboxManifest.generate)
|
|
9
|
+
|
|
10
|
+
if (path = ENV[ActionAgent::SandboxManifest::PATH_ENV].presence)
|
|
11
|
+
File.write(path, manifest)
|
|
12
|
+
else
|
|
13
|
+
puts manifest
|
|
14
|
+
end
|
|
15
|
+
rescue ActionAgent::SandboxManifest::Error => e
|
|
16
|
+
abort "action_agent:sandbox:manifest: #{e.message}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
desc "Expire sandbox sessions past their expiry and release what their backend holds " \
|
|
20
|
+
"(processes, containers). Schedule it, e.g. every few minutes."
|
|
21
|
+
task reap: :environment do
|
|
22
|
+
count = ActionAgent::SandboxCleanupJob.cleanup_expired!
|
|
23
|
+
puts "Expired #{count.to_i} sandbox session(s)"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: actionagent
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.8.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justin Bowen
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activeagent
|
|
@@ -129,9 +129,11 @@ files:
|
|
|
129
129
|
- app/controllers/action_agent/api/analytics_controller.rb
|
|
130
130
|
- app/controllers/action_agent/api/api_keys_controller.rb
|
|
131
131
|
- app/controllers/action_agent/api/base_controller.rb
|
|
132
|
+
- app/controllers/action_agent/api/code_sessions_controller.rb
|
|
132
133
|
- app/controllers/action_agent/api/dashboard_assistant_controller.rb
|
|
133
134
|
- app/controllers/action_agent/api/evaluation_reports_controller.rb
|
|
134
135
|
- app/controllers/action_agent/api/evaluations_controller.rb
|
|
136
|
+
- app/controllers/action_agent/api/github_connections_controller.rb
|
|
135
137
|
- app/controllers/action_agent/api/instance_tiers_controller.rb
|
|
136
138
|
- app/controllers/action_agent/api/interaction_messages_controller.rb
|
|
137
139
|
- app/controllers/action_agent/api/interactions_controller.rb
|
|
@@ -151,9 +153,13 @@ files:
|
|
|
151
153
|
- app/controllers/action_agent/dashboard_controller.rb
|
|
152
154
|
- app/controllers/action_agent/traces_controller.rb
|
|
153
155
|
- app/controllers/concerns/action_agent/api/agent_serialization.rb
|
|
156
|
+
- app/controllers/concerns/action_agent/api/evaluation_run_starting.rb
|
|
154
157
|
- app/controllers/concerns/action_agent/api/ingest_authentication.rb
|
|
158
|
+
- app/controllers/concerns/action_agent/api/mcp_dashboard_tools.rb
|
|
159
|
+
- app/controllers/concerns/action_agent/api/run_sandbox.rb
|
|
155
160
|
- app/jobs/action_agent/agent_execution_job.rb
|
|
156
161
|
- app/jobs/action_agent/application_job.rb
|
|
162
|
+
- app/jobs/action_agent/code_session_job.rb
|
|
157
163
|
- app/jobs/action_agent/evaluation_run_job.rb
|
|
158
164
|
- app/jobs/action_agent/process_telemetry_traces_job.rb
|
|
159
165
|
- app/jobs/action_agent/sandbox_cleanup_job.rb
|
|
@@ -171,10 +177,12 @@ files:
|
|
|
171
177
|
- app/models/action_agent/agent_version.rb
|
|
172
178
|
- app/models/action_agent/api_key.rb
|
|
173
179
|
- app/models/action_agent/application_record.rb
|
|
180
|
+
- app/models/action_agent/code_session.rb
|
|
174
181
|
- app/models/action_agent/evaluation.rb
|
|
175
182
|
- app/models/action_agent/evaluation_run.rb
|
|
176
183
|
- app/models/action_agent/evaluation_scenario.rb
|
|
177
184
|
- app/models/action_agent/evaluation_scenario_result.rb
|
|
185
|
+
- app/models/action_agent/github_connection.rb
|
|
178
186
|
- app/models/action_agent/model_pricing.rb
|
|
179
187
|
- app/models/action_agent/provider_key.rb
|
|
180
188
|
- app/models/action_agent/recording_action.rb
|
|
@@ -190,6 +198,7 @@ files:
|
|
|
190
198
|
- app/queries/action_agent/agent_executions.rb
|
|
191
199
|
- app/queries/action_agent/metrics_report.rb
|
|
192
200
|
- app/serializers/action_agent/agent_message_serializer.rb
|
|
201
|
+
- app/serializers/action_agent/evaluation_serializer.rb
|
|
193
202
|
- app/serializers/action_agent/interaction_preview.rb
|
|
194
203
|
- app/serializers/action_agent/telemetry_trace_serializer.rb
|
|
195
204
|
- app/serializers/action_agent/trace_interaction_serializer.rb
|
|
@@ -200,19 +209,30 @@ files:
|
|
|
200
209
|
- app/services/action_agent/agent_sync.rb
|
|
201
210
|
- app/services/action_agent/agent_tool_roster.rb
|
|
202
211
|
- app/services/action_agent/agent_toolbox.rb
|
|
212
|
+
- app/services/action_agent/claude_code_auth.rb
|
|
213
|
+
- app/services/action_agent/codex_session_events.rb
|
|
203
214
|
- app/services/action_agent/dashboard_assistant_service.rb
|
|
204
215
|
- app/services/action_agent/evaluation_evidence.rb
|
|
205
216
|
- app/services/action_agent/evaluation_report_import.rb
|
|
217
|
+
- app/services/action_agent/evaluation_run_cost.rb
|
|
206
218
|
- app/services/action_agent/evaluation_runner_service.rb
|
|
219
|
+
- app/services/action_agent/evaluation_standing.rb
|
|
207
220
|
- app/services/action_agent/evaluation_tool_resolver.rb
|
|
221
|
+
- app/services/action_agent/github_client.rb
|
|
222
|
+
- app/services/action_agent/local_sandbox_backend.rb
|
|
223
|
+
- app/services/action_agent/local_sandbox_databases.rb
|
|
208
224
|
- app/services/action_agent/mcp_catalog.rb
|
|
209
225
|
- app/services/action_agent/mcp_client.rb
|
|
210
226
|
- app/services/action_agent/mcp_recording_middleware.rb
|
|
211
227
|
- app/services/action_agent/mcp_tool_dispatcher.rb
|
|
212
228
|
- app/services/action_agent/mock_sandbox_backend.rb
|
|
229
|
+
- app/services/action_agent/ollama_host_probe.rb
|
|
230
|
+
- app/services/action_agent/payload_bounds.rb
|
|
213
231
|
- app/services/action_agent/playwright_mcp_client.rb
|
|
232
|
+
- app/services/action_agent/sandbox_manifest.rb
|
|
214
233
|
- app/services/action_agent/sandbox_orchestrator.rb
|
|
215
234
|
- app/services/action_agent/scenario_evaluation_runner.rb
|
|
235
|
+
- app/services/action_agent/secret_scrubber.rb
|
|
216
236
|
- app/services/action_agent/session_recording_service.rb
|
|
217
237
|
- app/services/action_agent/tool_discovery.rb
|
|
218
238
|
- app/views/action_agent/dashboard/index.html.erb
|
|
@@ -233,12 +253,18 @@ files:
|
|
|
233
253
|
- lib/generators/action_agent/templates/action_agent.rb.erb
|
|
234
254
|
- lib/generators/action_agent/templates/add_agent_id_to_active_agent_telemetry_traces.rb.erb
|
|
235
255
|
- lib/generators/action_agent/templates/add_agent_releases.rb.erb
|
|
256
|
+
- lib/generators/action_agent/templates/add_code_session_runner.rb.erb
|
|
236
257
|
- lib/generators/action_agent/templates/add_evaluation_report_identity.rb.erb
|
|
258
|
+
- lib/generators/action_agent/templates/add_provider_key_api_key.rb.erb
|
|
259
|
+
- lib/generators/action_agent/templates/create_active_agent_code_sessions.rb.erb
|
|
237
260
|
- lib/generators/action_agent/templates/create_active_agent_dashboard_tables.rb.erb
|
|
238
261
|
- lib/generators/action_agent/templates/create_active_agent_evaluation_scenarios.rb.erb
|
|
262
|
+
- lib/generators/action_agent/templates/create_active_agent_github_connections.rb.erb
|
|
239
263
|
- lib/generators/action_agent/templates/create_active_agent_telemetry_traces.rb.erb
|
|
240
264
|
- lib/generators/action_agent/templates/ensure_agent_release_columns.rb.erb
|
|
241
265
|
- lib/tasks/action_agent.rake
|
|
266
|
+
- lib/tasks/claude_code.rake
|
|
267
|
+
- lib/tasks/sandbox.rake
|
|
242
268
|
homepage: https://activeagents.ai
|
|
243
269
|
licenses:
|
|
244
270
|
- MIT
|