actionagent 1.9.1 → 1.9.3
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/README.md +23 -0
- data/app/assets/builds/action_agent.css +1 -1
- data/app/assets/builds/action_agent.js +61 -61
- data/app/controllers/action_agent/api/agents_controller.rb +23 -0
- data/app/controllers/action_agent/api/code_sessions_controller.rb +49 -10
- data/app/controllers/action_agent/api/evaluation_reports_controller.rb +66 -2
- data/app/controllers/action_agent/api/evaluations_controller.rb +56 -6
- data/app/controllers/action_agent/api/interactions_controller.rb +55 -1
- data/app/controllers/action_agent/api/sandboxes_controller.rb +13 -2
- data/app/controllers/action_agent/api/trace_reports_controller.rb +11 -6
- data/app/controllers/concerns/action_agent/api/mcp_dashboard_tools.rb +2 -2
- data/app/jobs/action_agent/code_session_job.rb +19 -2
- data/app/jobs/action_agent/evaluation_judge_job.rb +39 -0
- data/app/jobs/action_agent/evaluation_replay_job.rb +28 -0
- data/app/models/action_agent/agent.rb +54 -1
- data/app/models/action_agent/code_session.rb +80 -0
- data/app/models/action_agent/evaluation_run.rb +37 -5
- data/app/models/action_agent/provider_key.rb +5 -1
- data/app/queries/action_agent/trace_window_report.rb +60 -0
- data/app/serializers/action_agent/code_conversation_serializer.rb +86 -0
- data/app/serializers/action_agent/evaluation_serializer.rb +13 -2
- data/app/services/action_agent/agent_execution_service.rb +37 -0
- data/app/services/action_agent/agent_tool_roster.rb +53 -18
- data/app/services/action_agent/agent_toolbox.rb +156 -3
- data/app/services/action_agent/browser_client_token.rb +86 -0
- data/app/services/action_agent/checkout_tools.rb +154 -0
- data/app/services/action_agent/code_conversation.rb +133 -0
- data/app/services/action_agent/codex_auth.rb +81 -0
- data/app/services/action_agent/dashboard_assistant_service.rb +19 -1
- data/app/services/action_agent/diff_stat.rb +27 -0
- data/app/services/action_agent/evaluation_fix_comparison.rb +4 -1
- data/app/services/action_agent/evaluation_report_export.rb +175 -0
- data/app/services/action_agent/evaluation_report_import.rb +47 -19
- data/app/services/action_agent/evaluation_runner_service.rb +106 -14
- data/app/services/action_agent/local_sandbox_backend.rb +295 -30
- data/app/services/action_agent/mcp_catalog.rb +25 -0
- data/app/services/action_agent/mcp_client.rb +1 -0
- data/app/services/action_agent/mcp_tool_dispatcher.rb +36 -1
- data/app/services/action_agent/project_boot_fix.rb +10 -3
- data/app/services/action_agent/sandbox_orchestrator.rb +41 -1
- data/app/services/action_agent/scenario_evaluation_runner.rb +381 -3
- data/app/services/action_agent/slack_tools.rb +101 -0
- data/config/routes.rb +10 -1
- data/lib/action_agent/engine.rb +6 -0
- data/lib/action_agent/version.rb +1 -1
- data/lib/action_agent.rb +50 -2
- data/lib/generators/action_agent/templates/migrations/028_add_conversations_to_code_sessions.rb.erb +18 -0
- data/lib/tasks/evaluations.rake +78 -0
- metadata +15 -2
data/lib/action_agent.rb
CHANGED
|
@@ -111,6 +111,9 @@ module ActionAgent
|
|
|
111
111
|
# What ActionAgent.claude_code_auth may be set to.
|
|
112
112
|
CLAUDE_CODE_AUTH_MODES = %i[api_key local_login sandbox_login].freeze
|
|
113
113
|
|
|
114
|
+
# What ActionAgent.codex_auth may be set to.
|
|
115
|
+
CODEX_AUTH_MODES = %i[api_key local_login].freeze
|
|
116
|
+
|
|
114
117
|
# What ActionAgent.provider_key_scope may be set to.
|
|
115
118
|
PROVIDER_KEY_SCOPES = %i[organization personal_override].freeze
|
|
116
119
|
|
|
@@ -134,6 +137,9 @@ module ActionAgent
|
|
|
134
137
|
# they are handed to, or delete a project that has
|
|
135
138
|
# them
|
|
136
139
|
# :take_over_browser drive a run's browser by hand
|
|
140
|
+
# :chat_code_session send a message to a Claude Code or Codex
|
|
141
|
+
# conversation someone may have started (the
|
|
142
|
+
# subject is its first session)
|
|
137
143
|
# :manage_recordings delete a session recording
|
|
138
144
|
# :replace_scenarios replace or merge an evaluation's scenarios
|
|
139
145
|
PERMISSION_ACTIONS = %i[
|
|
@@ -144,6 +150,7 @@ module ActionAgent
|
|
|
144
150
|
answer_input_request
|
|
145
151
|
manage_project_secrets
|
|
146
152
|
take_over_browser
|
|
153
|
+
chat_code_session
|
|
147
154
|
manage_recordings
|
|
148
155
|
replace_scenarios
|
|
149
156
|
].freeze
|
|
@@ -589,10 +596,35 @@ module ActionAgent
|
|
|
589
596
|
# @return [Integer]
|
|
590
597
|
attr_accessor :claude_code_timeout
|
|
591
598
|
|
|
592
|
-
# Codex CLI sessions
|
|
593
|
-
#
|
|
599
|
+
# Codex CLI sessions run with workspace-write sandboxing, and share the
|
|
600
|
+
# checkout lifecycle and cancellation with Claude Code.
|
|
594
601
|
attr_accessor :codex_command, :codex_timeout
|
|
595
602
|
|
|
603
|
+
# How Codex sessions authenticate.
|
|
604
|
+
#
|
|
605
|
+
# :api_key (the default) runs them on the OpenAI API key the owner
|
|
606
|
+
# connected in Settings -> Integrations, handed to the session as
|
|
607
|
+
# CODEX_API_KEY with a Codex home of the sandbox's own. Usage is billed
|
|
608
|
+
# to that key's project.
|
|
609
|
+
#
|
|
610
|
+
# :local_login runs `codex` on whatever login this machine's user set up
|
|
611
|
+
# with `codex login` (a ChatGPT plan, or a key given to the CLI), which
|
|
612
|
+
# Codex keeps under ~/.codex. The dashboard never reads, copies or
|
|
613
|
+
# stores it; it only asks `codex login status` whether there is one.
|
|
614
|
+
# That login is the dashboard user's own, so this works with the :local
|
|
615
|
+
# sandbox backend only, and other backends refuse Codex sessions.
|
|
616
|
+
# @return [Symbol] :api_key or :local_login
|
|
617
|
+
attr_reader :codex_auth
|
|
618
|
+
|
|
619
|
+
def codex_auth=(value)
|
|
620
|
+
mode = value.to_s.to_sym
|
|
621
|
+
unless CODEX_AUTH_MODES.include?(mode)
|
|
622
|
+
raise ArgumentError, "ActionAgent.codex_auth must be :api_key or :local_login, not #{value.inspect}"
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
@codex_auth = mode
|
|
626
|
+
end
|
|
627
|
+
|
|
596
628
|
# How Claude Code sessions authenticate.
|
|
597
629
|
#
|
|
598
630
|
# :api_key (the default) runs them on the Anthropic API key the owner
|
|
@@ -685,6 +717,20 @@ module ActionAgent
|
|
|
685
717
|
# @return [Proc, nil]
|
|
686
718
|
attr_accessor :scenario_evaluation_adapter_resolver
|
|
687
719
|
|
|
720
|
+
# Whether a scenario evaluation runs as background jobs, one per
|
|
721
|
+
# scenario x model (EvaluationReplayJob) followed by one to score it
|
|
722
|
+
# (EvaluationJudgeJob), instead of as one job that replays the suite in
|
|
723
|
+
# order. The jobs run on the :agents queue, so a run is as parallel as
|
|
724
|
+
# the host's workers for that queue: a single-worker box stays
|
|
725
|
+
# sequential. The last result to be scored completes the run.
|
|
726
|
+
#
|
|
727
|
+
# A run that drives a sandbox's browser, and a run a host adapter
|
|
728
|
+
# (scenario_evaluation_adapter_resolver) replays, stay sequential: the
|
|
729
|
+
# browser is one page, and the adapter owns its own scheduling.
|
|
730
|
+
# Off unless set.
|
|
731
|
+
# @return [Boolean]
|
|
732
|
+
attr_accessor :scenario_evaluation_fan_out
|
|
733
|
+
|
|
688
734
|
# How many answerable candidates an exploration's review pre-selects for
|
|
689
735
|
# acceptance: an Integer, or a Proc called with (owner) that returns one.
|
|
690
736
|
# A platform can cap a free plan's suite this way. Unset, or nil from the
|
|
@@ -1234,6 +1280,7 @@ module ActionAgent
|
|
|
1234
1280
|
@claude_code_timeout = 1800
|
|
1235
1281
|
@codex_command = "codex"
|
|
1236
1282
|
@codex_timeout = 1800
|
|
1283
|
+
@codex_auth = :api_key
|
|
1237
1284
|
@claude_code_auth = :api_key
|
|
1238
1285
|
@claude_code_hosted_login_enabled = false
|
|
1239
1286
|
@claude_code_login_timeout = 300
|
|
@@ -1243,6 +1290,7 @@ module ActionAgent
|
|
|
1243
1290
|
@capture_dashboard_sessions = true
|
|
1244
1291
|
|
|
1245
1292
|
@scenario_evaluation_adapter_resolver = nil
|
|
1293
|
+
@scenario_evaluation_fan_out = false
|
|
1246
1294
|
@table_name_prefix = "active_agent_"
|
|
1247
1295
|
@agent_polymorphic_name = nil
|
|
1248
1296
|
@encrypt_credentials = true
|
data/lib/generators/action_agent/templates/migrations/028_add_conversations_to_code_sessions.rb.erb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Makes Claude Code and Codex sessions conversations: each session is one
|
|
4
|
+
# turn, and a turn after the first names the conversation's first session as
|
|
5
|
+
# its root. A conversation resumes the same CLI session (resume_session_id),
|
|
6
|
+
# and a turn may carry a note from the dashboard ahead of the person's
|
|
7
|
+
# message (context_note), such as who drove the browser since the last turn.
|
|
8
|
+
class AddConversationsToCodeSessions < ActiveRecord::Migration<%= migration_version %>
|
|
9
|
+
def change
|
|
10
|
+
sessions = "#{ActionAgent.table_name_prefix}code_sessions"
|
|
11
|
+
add_column sessions, :conversation_root_id, :bigint
|
|
12
|
+
add_column sessions, :turn_index, :integer, default: 0, null: false
|
|
13
|
+
add_column sessions, :origin, :string
|
|
14
|
+
add_column sessions, :context_note, :text
|
|
15
|
+
add_column sessions, :resume_session_id, :string
|
|
16
|
+
add_index sessions, :conversation_root_id
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Evaluation run reports from the command line: a run out as the version-1
|
|
4
|
+
# envelope the evaluation report collector takes (or as its HTML report page,
|
|
5
|
+
# or as GitHub-flavored Markdown for a pull request), and an envelope in
|
|
6
|
+
# through the collector's own import. On a multi-tenant install name the
|
|
7
|
+
# tenant with ACCOUNT_ID=<id>.
|
|
8
|
+
#
|
|
9
|
+
# bin/rails action_agent:evaluations:export RUN=dashboard-run-12-20261021093000 FILE=tmp/run.json
|
|
10
|
+
# bin/rails action_agent:evaluations:export EVALUATION=3 RUN=12 FORMAT=html FILE=tmp/run.html
|
|
11
|
+
# bin/rails action_agent:evaluations:export EVALUATION=3 RUN=12 FORMAT=md > tmp/run.md
|
|
12
|
+
# bin/rails action_agent:evaluations:import FILE=tmp/run.json
|
|
13
|
+
namespace :action_agent do
|
|
14
|
+
namespace :evaluations do
|
|
15
|
+
desc "Write a run's report (RUN=run_id, or EVALUATION=id RUN=id; FORMAT=json|html|md; FILE=path, standard output without FILE)"
|
|
16
|
+
task export: :environment do
|
|
17
|
+
run = action_agent_evaluation_run!
|
|
18
|
+
export = ActionAgent::EvaluationReportExport.new(run)
|
|
19
|
+
format = ENV.fetch("FORMAT", "json").downcase
|
|
20
|
+
body =
|
|
21
|
+
case format
|
|
22
|
+
when "json" then export.to_json
|
|
23
|
+
when "html" then run.to_report.to_html
|
|
24
|
+
when "md", "markdown" then export.markdown
|
|
25
|
+
else abort "FORMAT is json, html or md"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
if ENV["FILE"].present?
|
|
29
|
+
File.write(ENV["FILE"], body)
|
|
30
|
+
puts "Wrote run #{export.run_id} of #{run.evaluation.name} (#{format}) to #{ENV['FILE']}"
|
|
31
|
+
else
|
|
32
|
+
puts body
|
|
33
|
+
end
|
|
34
|
+
rescue ActionAgent::EvaluationReportExport::NotExportable => e
|
|
35
|
+
abort "Export refused: #{e.message}"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
desc "Store a version-1 evaluation report envelope (FILE=path [ACCOUNT_ID=id]); importing it again changes nothing"
|
|
39
|
+
task import: :environment do
|
|
40
|
+
path = ENV.fetch("FILE") { abort "Name the file: FILE=tmp/run.json" }
|
|
41
|
+
abort "No file at #{path}" unless File.file?(path)
|
|
42
|
+
abort "Unavailable: #{ActionAgent::EvaluationReportImport.unavailable_reason}" if ActionAgent::EvaluationReportImport.unavailable_reason
|
|
43
|
+
|
|
44
|
+
account = action_agent_evaluation_account
|
|
45
|
+
run, duplicate = ActionAgent::EvaluationReportImport.call(account: account, payload: JSON.parse(File.read(path)))
|
|
46
|
+
ActionAgent.record_usage(account, :evaluation_report) unless duplicate
|
|
47
|
+
puts "#{duplicate ? 'Already stored (identical retry)' : 'Stored'}: run #{ActionAgent::EvaluationReportExport.run_id_for(run)} " \
|
|
48
|
+
"as run ##{run.id} of evaluation ##{run.evaluation_id} (#{run.evaluation.name}), #{run.status}"
|
|
49
|
+
rescue JSON::ParserError
|
|
50
|
+
abort "Import refused: #{path} is not JSON"
|
|
51
|
+
rescue ActionAgent::EvaluationReportImport::Error, ActiveRecord::RecordInvalid => e
|
|
52
|
+
abort "Import refused: #{e.message}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# The tenant, from ACCOUNT_ID (ACCOUNT also works); nil on a single-tenant
|
|
58
|
+
# install.
|
|
59
|
+
def action_agent_evaluation_account
|
|
60
|
+
id = ENV["ACCOUNT_ID"].presence || ENV["ACCOUNT"].presence
|
|
61
|
+
return nil unless id
|
|
62
|
+
|
|
63
|
+
abort "ACCOUNT_ID names a tenant, which only a multi-tenant install has" unless ActionAgent.multi_tenant?
|
|
64
|
+
ActionAgent.account_class.to_s.constantize.find_by(id: id) || abort("No account #{id}")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# The run RUN names: with EVALUATION, a run id of that evaluation; without,
|
|
68
|
+
# a run_id as the export endpoint takes it, within the tenant.
|
|
69
|
+
def action_agent_evaluation_run!
|
|
70
|
+
run_id = ENV.fetch("RUN") { abort "Name the run: RUN=<run_id>, or EVALUATION=<id> RUN=<id>" }
|
|
71
|
+
if ENV["EVALUATION"].present?
|
|
72
|
+
evaluation = ActionAgent::Evaluation.find_by(id: ENV["EVALUATION"]) || abort("No evaluation #{ENV['EVALUATION']}")
|
|
73
|
+
evaluation.evaluation_runs.find_by(id: run_id) || abort("No run #{run_id} in evaluation #{evaluation.id}")
|
|
74
|
+
else
|
|
75
|
+
ActionAgent::EvaluationReportExport.find(run_id, account: action_agent_evaluation_account) ||
|
|
76
|
+
abort("No run with run_id #{run_id.inspect}#{' for that account' if ENV['ACCOUNT_ID'].present? || ENV['ACCOUNT'].present?}")
|
|
77
|
+
end
|
|
78
|
+
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.9.
|
|
4
|
+
version: 1.9.3
|
|
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-10-
|
|
11
|
+
date: 2026-10-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activeagent
|
|
@@ -190,6 +190,8 @@ files:
|
|
|
190
190
|
- app/jobs/action_agent/application_job.rb
|
|
191
191
|
- app/jobs/action_agent/code_session_job.rb
|
|
192
192
|
- app/jobs/action_agent/draft_pull_request_job.rb
|
|
193
|
+
- app/jobs/action_agent/evaluation_judge_job.rb
|
|
194
|
+
- app/jobs/action_agent/evaluation_replay_job.rb
|
|
193
195
|
- app/jobs/action_agent/evaluation_run_job.rb
|
|
194
196
|
- app/jobs/action_agent/exploration_job.rb
|
|
195
197
|
- app/jobs/action_agent/input_request_expiry_job.rb
|
|
@@ -244,7 +246,9 @@ files:
|
|
|
244
246
|
- app/models/concerns/action_agent/session_recordable.rb
|
|
245
247
|
- app/queries/action_agent/agent_executions.rb
|
|
246
248
|
- app/queries/action_agent/metrics_report.rb
|
|
249
|
+
- app/queries/action_agent/trace_window_report.rb
|
|
247
250
|
- app/serializers/action_agent/agent_message_serializer.rb
|
|
251
|
+
- app/serializers/action_agent/code_conversation_serializer.rb
|
|
248
252
|
- app/serializers/action_agent/evaluation_serializer.rb
|
|
249
253
|
- app/serializers/action_agent/input_request_serializer.rb
|
|
250
254
|
- app/serializers/action_agent/interaction_preview.rb
|
|
@@ -259,17 +263,23 @@ files:
|
|
|
259
263
|
- app/services/action_agent/agent_sync.rb
|
|
260
264
|
- app/services/action_agent/agent_tool_roster.rb
|
|
261
265
|
- app/services/action_agent/agent_toolbox.rb
|
|
266
|
+
- app/services/action_agent/browser_client_token.rb
|
|
262
267
|
- app/services/action_agent/browser_live_ticket.rb
|
|
263
268
|
- app/services/action_agent/browser_sidecar.rb
|
|
264
269
|
- app/services/action_agent/browser_sign_in.rb
|
|
265
270
|
- app/services/action_agent/browser_tool_redaction.rb
|
|
271
|
+
- app/services/action_agent/checkout_tools.rb
|
|
266
272
|
- app/services/action_agent/claude_code_auth.rb
|
|
273
|
+
- app/services/action_agent/code_conversation.rb
|
|
274
|
+
- app/services/action_agent/codex_auth.rb
|
|
267
275
|
- app/services/action_agent/codex_session_events.rb
|
|
268
276
|
- app/services/action_agent/dashboard_assistant_service.rb
|
|
277
|
+
- app/services/action_agent/diff_stat.rb
|
|
269
278
|
- app/services/action_agent/draft_pull_request_publisher.rb
|
|
270
279
|
- app/services/action_agent/evaluation_evidence.rb
|
|
271
280
|
- app/services/action_agent/evaluation_fix.rb
|
|
272
281
|
- app/services/action_agent/evaluation_fix_comparison.rb
|
|
282
|
+
- app/services/action_agent/evaluation_report_export.rb
|
|
273
283
|
- app/services/action_agent/evaluation_report_import.rb
|
|
274
284
|
- app/services/action_agent/evaluation_run_cost.rb
|
|
275
285
|
- app/services/action_agent/evaluation_runner_service.rb
|
|
@@ -314,6 +324,7 @@ files:
|
|
|
314
324
|
- app/services/action_agent/session_index.rb
|
|
315
325
|
- app/services/action_agent/session_recording_service.rb
|
|
316
326
|
- app/services/action_agent/session_timeline.rb
|
|
327
|
+
- app/services/action_agent/slack_tools.rb
|
|
317
328
|
- app/services/action_agent/tool_discovery.rb
|
|
318
329
|
- app/views/action_agent/dashboard/index.html.erb
|
|
319
330
|
- app/views/action_agent/github_app_manifests/created.html.erb
|
|
@@ -358,9 +369,11 @@ files:
|
|
|
358
369
|
- lib/generators/action_agent/templates/migrations/025_create_active_agent_scenario_catalogs.rb.erb
|
|
359
370
|
- lib/generators/action_agent/templates/migrations/026_add_evaluation_fixes_to_code_sessions.rb.erb
|
|
360
371
|
- lib/generators/action_agent/templates/migrations/027_create_active_agent_interaction_feedbacks.rb.erb
|
|
372
|
+
- lib/generators/action_agent/templates/migrations/028_add_conversations_to_code_sessions.rb.erb
|
|
361
373
|
- lib/tasks/action_agent.rake
|
|
362
374
|
- lib/tasks/browser.rake
|
|
363
375
|
- lib/tasks/claude_code.rake
|
|
376
|
+
- lib/tasks/evaluations.rake
|
|
364
377
|
- lib/tasks/sandbox.rake
|
|
365
378
|
- lib/tasks/scenario_catalogs.rake
|
|
366
379
|
homepage: https://activeagents.ai
|