actionagent 1.9.3 → 1.9.4

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.
@@ -1,94 +1,34 @@
1
1
  <!DOCTYPE html>
2
- <html lang="en" class="h-full">
2
+ <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>ActiveAgent Dashboard</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <script src="https://unpkg.com/@hotwired/turbo@7.3.0/dist/turbo.es2017-esm.js" type="module"></script>
9
- <script src="https://unpkg.com/@hotwired/stimulus@3.2.2/dist/stimulus.umd.js"></script>
10
- <style>
11
- [data-turbo-preview] { opacity: 0.5; }
12
- .span-bar { transition: all 0.2s ease; }
13
- .span-bar:hover { transform: scaleY(1.1); }
14
- </style>
15
- <script>
16
- // Initialize Stimulus
17
- const application = Stimulus.Application.start();
18
-
19
- // Traces controller for expandable rows
20
- application.register("traces", class extends Stimulus.Controller {
21
- static targets = ["row", "detail"]
22
-
23
- toggle(event) {
24
- const traceId = event.currentTarget.dataset.traceId;
25
- const detail = document.getElementById(`detail-${traceId}`);
26
- if (detail) {
27
- detail.classList.toggle("hidden");
28
- }
29
- }
30
- });
31
-
32
- // Auto-refresh controller
33
- application.register("refresh", class extends Stimulus.Controller {
34
- static values = { interval: Number }
35
-
36
- connect() {
37
- if (this.intervalValue > 0) {
38
- this.startRefresh();
39
- }
40
- }
41
-
42
- disconnect() {
43
- this.stopRefresh();
44
- }
45
-
46
- startRefresh() {
47
- this.timer = setInterval(() => {
48
- Turbo.visit(window.location.href, { action: "replace" });
49
- }, this.intervalValue);
50
- }
51
-
52
- stopRefresh() {
53
- if (this.timer) clearInterval(this.timer);
54
- }
55
- });
56
- </script>
6
+ <title>ActiveAgent Trace Console</title>
7
+ <% if @refresh_interval %>
8
+ <meta http-equiv="refresh" content="<%= @refresh_interval %>">
9
+ <% end %>
10
+ <%= render "action_agent/traces/styles" %>
57
11
  </head>
58
- <body class="h-full bg-gray-50 dark:bg-gray-900">
59
- <div class="min-h-full">
60
- <!-- Header -->
61
- <nav class="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
62
- <div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
63
- <div class="flex h-16 items-center justify-between">
64
- <div class="flex items-center">
65
- <div class="flex-shrink-0">
66
- <span class="text-xl font-bold text-indigo-600 dark:text-indigo-400">
67
- ActiveAgent
68
- </span>
69
- </div>
70
- <div class="ml-10 flex items-baseline space-x-4">
71
- <%= link_to "Traces",
72
- traces_path,
73
- class: "px-3 py-2 rounded-md text-sm font-medium #{request.path == traces_path ? 'bg-indigo-100 text-indigo-700 dark:bg-indigo-900 dark:text-indigo-200' : 'text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700'}" %>
74
- <%= link_to "Metrics",
75
- metrics_traces_path,
76
- class: "px-3 py-2 rounded-md text-sm font-medium #{request.path == metrics_traces_path ? 'bg-indigo-100 text-indigo-700 dark:bg-indigo-900 dark:text-indigo-200' : 'text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700'}" %>
77
- </div>
78
- </div>
79
- <div class="text-sm text-gray-500 dark:text-gray-400">
80
- Local Telemetry
81
- </div>
82
- </div>
83
- </div>
12
+ <body class="trace-console">
13
+ <header>
14
+ <nav aria-label="Trace console">
15
+ <strong>ActiveAgent</strong>
16
+ <%= link_to "Traces", traces_path %>
17
+ <%= link_to "Metrics", metrics_traces_path %>
18
+ <span class="muted">Local Telemetry</span>
84
19
  </nav>
85
-
86
- <!-- Main content -->
87
- <main>
88
- <div class="mx-auto max-w-7xl py-6 px-4 sm:px-6 lg:px-8">
89
- <%= yield %>
90
- </div>
91
- </main>
92
- </div>
20
+ </header>
21
+ <main>
22
+ <div class="refresh-controls">
23
+ <% if @refresh_interval %>
24
+ <span>Refreshes every <%= @refresh_interval %> seconds.</span>
25
+ <%= link_to "Stop refreshing", "#{request.path}?#{request.query_parameters.except('refresh').to_query}" %>
26
+ <% else %>
27
+ <%= link_to "Auto-refresh", "#{request.path}?#{request.query_parameters.merge('refresh' => '30').to_query}" %>
28
+ <% end %>
29
+ <%= link_to "Refresh now", request.path + (request.query_string.present? ? "?#{request.query_string}" : "") %>
30
+ </div>
31
+ <%= yield %>
32
+ </main>
93
33
  </body>
94
34
  </html>
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionAgent
4
- VERSION = "1.9.3"
4
+ VERSION = "1.9.4"
5
5
  end
data/lib/action_agent.rb CHANGED
@@ -751,6 +751,16 @@ module ActionAgent
751
751
  # @return [String, nil]
752
752
  attr_accessor :sign_out_path
753
753
 
754
+ # Items the host app adds to the header's user menu, above "Sign out":
755
+ # its workspace and member pages, its account settings, and for platform
756
+ # admins its admin pages. A Proc receives the signed-in user and the
757
+ # current owner and returns an Array of { label:, href: } Hashes (an
758
+ # Array is used as is), so the host decides per user what to show. The
759
+ # engine has no pages of its own to link here; unset, or when the Proc
760
+ # raises (logged), the menu holds "Sign out" alone.
761
+ # @return [Proc, Array<Hash>, nil]
762
+ attr_accessor :user_menu_links
763
+
754
764
  # Where a browser is sent when it asks for a dashboard page without a
755
765
  # valid session — the host app's sign-in page. Unset, an unauthenticated
756
766
  # page request gets a minimal session-expired page instead of a bare
@@ -1183,6 +1193,27 @@ module ActionAgent
1183
1193
 
1184
1194
  # The tenant +owner+ belongs to. Identity unless the host app says
1185
1195
  # otherwise, which is right for every single-tenant install.
1196
+ # The host's user menu items for +user+ in +owner+'s dashboard, as
1197
+ # [{ label:, href: }] with blank or malformed entries dropped. Empty when
1198
+ # user_menu_links is unset or raises, which is logged, not raised: a
1199
+ # broken menu seam must not take the dashboard down with it.
1200
+ # @return [Array<Hash{Symbol => String}>]
1201
+ def user_menu_links_for(user, owner)
1202
+ links = user_menu_links
1203
+ links = links.call(user, owner) if links.respond_to?(:call)
1204
+ Array(links).filter_map do |link|
1205
+ label = link[:label] || link["label"]
1206
+ href = link[:href] || link["href"]
1207
+ next if label.blank? || href.blank?
1208
+ next unless href.to_s.match?(%r{\A(/|https?://)})
1209
+
1210
+ { label: label.to_s, href: href.to_s }
1211
+ end
1212
+ rescue StandardError => error
1213
+ Rails.logger.warn("[ActionAgent] user_menu_links failed: #{error.class}: #{error.message}")
1214
+ []
1215
+ end
1216
+
1186
1217
  def tenant_for(owner)
1187
1218
  return owner if tenant_resolver.nil?
1188
1219
 
@@ -1309,6 +1340,7 @@ module ActionAgent
1309
1340
  @usage_resolver = nil
1310
1341
  @upgrade_url = nil
1311
1342
  @sign_out_path = nil
1343
+ @user_menu_links = nil
1312
1344
  @sign_in_path = nil
1313
1345
  @mcp_catalog = []
1314
1346
  @agent_actor_resolver = nil
@@ -315,9 +315,10 @@ ActionAgent.configure do |config|
315
315
  # UI
316
316
  # ==========================================================================
317
317
  #
318
- # Custom layout for dashboard views (the default layout loads Tailwind,
319
- # Turbo and Stimulus from CDNs — override for CSP-strict or air-gapped
320
- # environments).
318
+ # Custom layout for dashboard views. The default layouts load nothing
319
+ # from external hosts, so this is only needed to wrap the dashboard in
320
+ # your application's own chrome. A custom layout replaces the trace
321
+ # console's built-in styles and refresh controls.
321
322
  #
322
323
  # config.layout = "application"
323
324
  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.3
4
+ version: 1.9.4
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-21 00:00:00.000000000 Z
11
+ date: 2026-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activeagent
@@ -329,6 +329,8 @@ files:
329
329
  - app/views/action_agent/dashboard/index.html.erb
330
330
  - app/views/action_agent/github_app_manifests/created.html.erb
331
331
  - app/views/action_agent/session_player/show.html.erb
332
+ - app/views/action_agent/traces/_styles.html.erb
333
+ - app/views/action_agent/traces/_summary.html.erb
332
334
  - app/views/action_agent/traces/_trace_detail.html.erb
333
335
  - app/views/action_agent/traces/index.html.erb
334
336
  - app/views/action_agent/traces/metrics.html.erb