ruby_llm-agents 1.3.4 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +112 -336
- data/app/controllers/concerns/ruby_llm/agents/sortable.rb +0 -1
- data/app/controllers/ruby_llm/agents/agents_controller.rb +5 -56
- data/app/controllers/ruby_llm/agents/dashboard_controller.rb +22 -106
- data/app/controllers/ruby_llm/agents/executions_controller.rb +4 -114
- data/app/controllers/ruby_llm/agents/tenants_controller.rb +30 -2
- data/app/helpers/ruby_llm/agents/application_helper.rb +19 -53
- data/app/models/ruby_llm/agents/execution/analytics.rb +13 -54
- data/app/models/ruby_llm/agents/execution/scopes.rb +61 -14
- data/app/models/ruby_llm/agents/execution.rb +52 -12
- data/app/models/ruby_llm/agents/execution_detail.rb +18 -0
- data/app/models/ruby_llm/agents/tenant/budgetable.rb +132 -24
- data/app/models/ruby_llm/agents/tenant/incrementable.rb +117 -0
- data/app/models/ruby_llm/agents/tenant/resettable.rb +128 -0
- data/app/models/ruby_llm/agents/tenant/trackable.rb +46 -12
- data/app/models/ruby_llm/agents/tenant.rb +2 -3
- data/app/models/ruby_llm/agents/tenant_budget.rb +6 -3
- data/app/services/ruby_llm/agents/agent_registry.rb +6 -112
- data/app/views/layouts/ruby_llm/agents/application.html.erb +89 -252
- data/app/views/ruby_llm/agents/agents/_config_agent.html.erb +71 -218
- data/app/views/ruby_llm/agents/agents/_config_embedder.html.erb +20 -63
- data/app/views/ruby_llm/agents/agents/_config_image_generator.html.erb +44 -131
- data/app/views/ruby_llm/agents/agents/_config_moderator.html.erb +16 -57
- data/app/views/ruby_llm/agents/agents/_config_speaker.html.erb +39 -104
- data/app/views/ruby_llm/agents/agents/_config_transcriber.html.erb +29 -82
- data/app/views/ruby_llm/agents/agents/_empty_state.html.erb +4 -14
- data/app/views/ruby_llm/agents/agents/index.html.erb +105 -274
- data/app/views/ruby_llm/agents/agents/show.html.erb +248 -378
- data/app/views/ruby_llm/agents/dashboard/_action_center.html.erb +29 -52
- data/app/views/ruby_llm/agents/dashboard/_tenant_budget.html.erb +73 -99
- data/app/views/ruby_llm/agents/dashboard/index.html.erb +228 -433
- data/app/views/ruby_llm/agents/executions/_execution.html.erb +1 -1
- data/app/views/ruby_llm/agents/executions/_filters.html.erb +4 -25
- data/app/views/ruby_llm/agents/executions/_list.html.erb +111 -152
- data/app/views/ruby_llm/agents/executions/index.html.erb +5 -7
- data/app/views/ruby_llm/agents/executions/show.html.erb +526 -1037
- data/app/views/ruby_llm/agents/shared/_agent_type_badge.html.erb +5 -21
- data/app/views/ruby_llm/agents/shared/_executions_table.html.erb +70 -191
- data/app/views/ruby_llm/agents/shared/_filter_dropdown.html.erb +16 -44
- data/app/views/ruby_llm/agents/shared/_select_dropdown.html.erb +12 -41
- data/app/views/ruby_llm/agents/shared/_status_badge.html.erb +11 -65
- data/app/views/ruby_llm/agents/shared/_tenant_filter.html.erb +6 -5
- data/app/views/ruby_llm/agents/system_config/show.html.erb +240 -351
- data/app/views/ruby_llm/agents/tenants/_form.html.erb +67 -77
- data/app/views/ruby_llm/agents/tenants/edit.html.erb +7 -9
- data/app/views/ruby_llm/agents/tenants/index.html.erb +100 -122
- data/app/views/ruby_llm/agents/tenants/show.html.erb +146 -336
- data/config/routes.rb +0 -13
- data/lib/generators/ruby_llm_agents/install_generator.rb +13 -17
- data/lib/generators/ruby_llm_agents/migrate_structure_generator.rb +2 -12
- data/lib/generators/ruby_llm_agents/restructure_generator.rb +0 -2
- data/lib/generators/ruby_llm_agents/templates/add_usage_counters_to_tenants_migration.rb.tt +37 -0
- data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +1 -2
- data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +1 -1
- data/lib/generators/ruby_llm_agents/templates/application_image_pipeline.rb.tt +0 -1
- data/lib/generators/ruby_llm_agents/templates/create_execution_details_migration.rb.tt +27 -0
- data/lib/generators/ruby_llm_agents/templates/create_tenants_migration.rb.tt +25 -0
- data/lib/generators/ruby_llm_agents/templates/image_pipeline.rb.tt +0 -1
- data/lib/generators/ruby_llm_agents/templates/initializer.rb.tt +33 -12
- data/lib/generators/ruby_llm_agents/templates/migration.rb.tt +40 -71
- data/lib/generators/ruby_llm_agents/templates/remove_agent_version_migration.rb.tt +13 -0
- data/lib/generators/ruby_llm_agents/templates/remove_workflow_columns_migration.rb.tt +19 -0
- data/lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt +2 -4
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_PIPELINES.md.tt +0 -1
- data/lib/generators/ruby_llm_agents/templates/split_execution_details_migration.rb.tt +232 -0
- data/lib/generators/ruby_llm_agents/upgrade_generator.rb +77 -259
- data/lib/ruby_llm/agents/audio/speaker.rb +0 -1
- data/lib/ruby_llm/agents/audio/transcriber.rb +0 -1
- data/lib/ruby_llm/agents/base_agent.rb +54 -23
- data/lib/ruby_llm/agents/core/base/callbacks.rb +142 -0
- data/lib/ruby_llm/agents/core/base.rb +23 -55
- data/lib/ruby_llm/agents/core/configuration.rb +97 -117
- data/lib/ruby_llm/agents/core/errors.rb +0 -58
- data/lib/ruby_llm/agents/core/instrumentation.rb +157 -110
- data/lib/ruby_llm/agents/core/llm_tenant.rb +8 -7
- data/lib/ruby_llm/agents/core/version.rb +1 -1
- data/lib/ruby_llm/agents/dsl/base.rb +157 -17
- data/lib/ruby_llm/agents/dsl/caching.rb +33 -2
- data/lib/ruby_llm/agents/dsl/reliability.rb +148 -0
- data/lib/ruby_llm/agents/dsl.rb +1 -2
- data/lib/ruby_llm/agents/image/analyzer/execution.rb +1 -2
- data/lib/ruby_llm/agents/image/background_remover/execution.rb +1 -2
- data/lib/ruby_llm/agents/image/concerns/image_operation_dsl.rb +1 -13
- data/lib/ruby_llm/agents/image/concerns/image_operation_execution.rb +2 -2
- data/lib/ruby_llm/agents/image/editor/dsl.rb +0 -14
- data/lib/ruby_llm/agents/image/editor/execution.rb +1 -10
- data/lib/ruby_llm/agents/image/editor.rb +0 -1
- data/lib/ruby_llm/agents/image/generator.rb +0 -21
- data/lib/ruby_llm/agents/image/pipeline/dsl.rb +0 -13
- data/lib/ruby_llm/agents/image/pipeline/execution.rb +0 -1
- data/lib/ruby_llm/agents/image/transformer/dsl.rb +0 -13
- data/lib/ruby_llm/agents/image/transformer/execution.rb +1 -10
- data/lib/ruby_llm/agents/image/transformer.rb +0 -1
- data/lib/ruby_llm/agents/image/upscaler/execution.rb +1 -2
- data/lib/ruby_llm/agents/image/variator/execution.rb +1 -2
- data/lib/ruby_llm/agents/infrastructure/alert_manager.rb +78 -173
- data/lib/ruby_llm/agents/infrastructure/budget/budget_query.rb +66 -2
- data/lib/ruby_llm/agents/infrastructure/budget/spend_recorder.rb +0 -12
- data/lib/ruby_llm/agents/infrastructure/circuit_breaker.rb +10 -13
- data/lib/ruby_llm/agents/infrastructure/execution_logger_job.rb +8 -0
- data/lib/ruby_llm/agents/pipeline/context.rb +0 -1
- data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +28 -4
- data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +3 -10
- data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +88 -55
- data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +5 -41
- data/lib/ruby_llm/agents/rails/engine.rb +6 -6
- data/lib/ruby_llm/agents/results/base.rb +1 -49
- data/lib/ruby_llm/agents/text/embedder.rb +0 -1
- data/lib/ruby_llm/agents.rb +1 -9
- data/lib/tasks/ruby_llm_agents.rake +34 -0
- metadata +14 -83
- data/app/controllers/ruby_llm/agents/api_configurations_controller.rb +0 -214
- data/app/controllers/ruby_llm/agents/workflows_controller.rb +0 -544
- data/app/mailers/ruby_llm/agents/alert_mailer.rb +0 -84
- data/app/mailers/ruby_llm/agents/application_mailer.rb +0 -28
- data/app/models/ruby_llm/agents/api_configuration.rb +0 -386
- data/app/models/ruby_llm/agents/execution/workflow.rb +0 -170
- data/app/models/ruby_llm/agents/tenant/configurable.rb +0 -135
- data/app/views/ruby_llm/agents/agents/_agent.html.erb +0 -98
- data/app/views/ruby_llm/agents/agents/_version_comparison.html.erb +0 -186
- data/app/views/ruby_llm/agents/agents/_workflow.html.erb +0 -126
- data/app/views/ruby_llm/agents/alert_mailer/alert_notification.html.erb +0 -107
- data/app/views/ruby_llm/agents/alert_mailer/alert_notification.text.erb +0 -18
- data/app/views/ruby_llm/agents/api_configurations/_api_key_field.html.erb +0 -34
- data/app/views/ruby_llm/agents/api_configurations/_form.html.erb +0 -288
- data/app/views/ruby_llm/agents/api_configurations/edit.html.erb +0 -95
- data/app/views/ruby_llm/agents/api_configurations/edit_tenant.html.erb +0 -97
- data/app/views/ruby_llm/agents/api_configurations/show.html.erb +0 -214
- data/app/views/ruby_llm/agents/api_configurations/tenant.html.erb +0 -179
- data/app/views/ruby_llm/agents/dashboard/_agent_comparison.html.erb +0 -73
- data/app/views/ruby_llm/agents/dashboard/_alerts_feed.html.erb +0 -62
- data/app/views/ruby_llm/agents/dashboard/_breaker_strip.html.erb +0 -47
- data/app/views/ruby_llm/agents/dashboard/_budgets_bar.html.erb +0 -75
- data/app/views/ruby_llm/agents/dashboard/_model_comparison.html.erb +0 -56
- data/app/views/ruby_llm/agents/dashboard/_model_cost_breakdown.html.erb +0 -115
- data/app/views/ruby_llm/agents/dashboard/_now_strip.html.erb +0 -59
- data/app/views/ruby_llm/agents/dashboard/_top_errors.html.erb +0 -60
- data/app/views/ruby_llm/agents/executions/_workflow_summary.html.erb +0 -86
- data/app/views/ruby_llm/agents/executions/dry_run.html.erb +0 -149
- data/app/views/ruby_llm/agents/shared/_breadcrumbs.html.erb +0 -48
- data/app/views/ruby_llm/agents/shared/_nav_link.html.erb +0 -27
- data/app/views/ruby_llm/agents/shared/_stat_card.html.erb +0 -14
- data/app/views/ruby_llm/agents/shared/_workflow_type_badge.html.erb +0 -35
- data/app/views/ruby_llm/agents/workflows/_empty_state.html.erb +0 -22
- data/app/views/ruby_llm/agents/workflows/_step_performance.html.erb +0 -228
- data/app/views/ruby_llm/agents/workflows/_structure_dsl.html.erb +0 -539
- data/app/views/ruby_llm/agents/workflows/_structure_parallel.html.erb +0 -76
- data/app/views/ruby_llm/agents/workflows/_structure_pipeline.html.erb +0 -74
- data/app/views/ruby_llm/agents/workflows/_structure_router.html.erb +0 -108
- data/app/views/ruby_llm/agents/workflows/_workflow_diagram.html.erb +0 -920
- data/app/views/ruby_llm/agents/workflows/index.html.erb +0 -179
- data/app/views/ruby_llm/agents/workflows/show.html.erb +0 -467
- data/lib/generators/ruby_llm_agents/api_configuration_generator.rb +0 -100
- data/lib/generators/ruby_llm_agents/templates/add_workflow_migration.rb.tt +0 -38
- data/lib/generators/ruby_llm_agents/templates/application_workflow.rb.tt +0 -48
- data/lib/generators/ruby_llm_agents/templates/create_api_configurations_migration.rb.tt +0 -90
- data/lib/generators/ruby_llm_agents/templates/skills/WORKFLOWS.md.tt +0 -551
- data/lib/ruby_llm/agents/core/base/moderation_dsl.rb +0 -181
- data/lib/ruby_llm/agents/core/base/moderation_execution.rb +0 -274
- data/lib/ruby_llm/agents/core/resolved_config.rb +0 -348
- data/lib/ruby_llm/agents/image/generator/content_policy.rb +0 -95
- data/lib/ruby_llm/agents/infrastructure/redactor.rb +0 -130
- data/lib/ruby_llm/agents/results/moderation_result.rb +0 -158
- data/lib/ruby_llm/agents/text/moderator.rb +0 -237
- data/lib/ruby_llm/agents/workflow/approval.rb +0 -205
- data/lib/ruby_llm/agents/workflow/approval_store.rb +0 -179
- data/lib/ruby_llm/agents/workflow/async.rb +0 -220
- data/lib/ruby_llm/agents/workflow/async_executor.rb +0 -156
- data/lib/ruby_llm/agents/workflow/dsl/executor.rb +0 -467
- data/lib/ruby_llm/agents/workflow/dsl/input_schema.rb +0 -244
- data/lib/ruby_llm/agents/workflow/dsl/iteration_executor.rb +0 -289
- data/lib/ruby_llm/agents/workflow/dsl/parallel_group.rb +0 -107
- data/lib/ruby_llm/agents/workflow/dsl/route_builder.rb +0 -150
- data/lib/ruby_llm/agents/workflow/dsl/schedule_helpers.rb +0 -187
- data/lib/ruby_llm/agents/workflow/dsl/step_config.rb +0 -352
- data/lib/ruby_llm/agents/workflow/dsl/step_executor.rb +0 -415
- data/lib/ruby_llm/agents/workflow/dsl/wait_config.rb +0 -257
- data/lib/ruby_llm/agents/workflow/dsl/wait_executor.rb +0 -317
- data/lib/ruby_llm/agents/workflow/dsl.rb +0 -576
- data/lib/ruby_llm/agents/workflow/instrumentation.rb +0 -249
- data/lib/ruby_llm/agents/workflow/notifiers/base.rb +0 -117
- data/lib/ruby_llm/agents/workflow/notifiers/email.rb +0 -117
- data/lib/ruby_llm/agents/workflow/notifiers/slack.rb +0 -180
- data/lib/ruby_llm/agents/workflow/notifiers/webhook.rb +0 -121
- data/lib/ruby_llm/agents/workflow/notifiers.rb +0 -70
- data/lib/ruby_llm/agents/workflow/orchestrator.rb +0 -416
- data/lib/ruby_llm/agents/workflow/result.rb +0 -592
- data/lib/ruby_llm/agents/workflow/thread_pool.rb +0 -185
- data/lib/ruby_llm/agents/workflow/throttle_manager.rb +0 -206
- data/lib/ruby_llm/agents/workflow/wait_result.rb +0 -213
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
<div class="mb-6">
|
|
2
|
-
<div class="flex items-center gap-2">
|
|
3
|
-
<h1 class="text-2xl font-bold text-gray-900 dark:text-gray-100">Agents</h1>
|
|
4
|
-
<%= render "ruby_llm/agents/shared/doc_link" %>
|
|
5
|
-
</div>
|
|
6
|
-
<p class="text-gray-500 dark:text-gray-400 mt-1">All available agents with execution statistics</p>
|
|
7
|
-
</div>
|
|
8
|
-
|
|
9
1
|
<%
|
|
10
2
|
audio_count = @agents_by_type[:speaker].size + @agents_by_type[:transcriber].size
|
|
3
|
+
sc = @sort_params[:column]
|
|
4
|
+
sd = @sort_params[:direction]
|
|
5
|
+
sort_url = ->(col) {
|
|
6
|
+
dir = (col == sc && sd == "asc") ? "desc" : "asc"
|
|
7
|
+
url_for(request.query_parameters.merge(sort: col, direction: dir))
|
|
8
|
+
}
|
|
9
|
+
sort_active = ->(col) { col == sc ? "text-gray-600 dark:text-gray-300" : "" }
|
|
10
|
+
sort_arrow = ->(col) { col == sc ? (sd == "asc" ? " ↑" : " ↓") : "" }
|
|
11
11
|
%>
|
|
12
12
|
<div x-data="{
|
|
13
13
|
activeSubTab: <%= params[:subtab].present? ? "'#{params[:subtab]}'" : 'null' %>,
|
|
@@ -15,9 +15,6 @@
|
|
|
15
15
|
all: <%= @agent_count %>,
|
|
16
16
|
agent: <%= @agents_by_type[:agent].size %>,
|
|
17
17
|
embedder: <%= @agents_by_type[:embedder].size %>,
|
|
18
|
-
moderator: <%= @agents_by_type[:moderator].size %>,
|
|
19
|
-
speaker: <%= @agents_by_type[:speaker].size %>,
|
|
20
|
-
transcriber: <%= @agents_by_type[:transcriber].size %>,
|
|
21
18
|
audio: <%= audio_count %>,
|
|
22
19
|
image_generator: <%= @agents_by_type[:image_generator].size %>,
|
|
23
20
|
deleted: <%= @deleted_count %>
|
|
@@ -37,292 +34,126 @@
|
|
|
37
34
|
history.replaceState({}, '', url);
|
|
38
35
|
}
|
|
39
36
|
}">
|
|
40
|
-
<!--
|
|
41
|
-
<div class="mb-4">
|
|
42
|
-
<
|
|
37
|
+
<!-- ── agents ──────────────────────────── -->
|
|
38
|
+
<div class="flex items-center gap-3 mb-4">
|
|
39
|
+
<span class="text-[10px] font-medium text-gray-400 dark:text-gray-600 uppercase tracking-widest font-mono">agents</span>
|
|
40
|
+
<div class="font-mono text-xs text-gray-400 dark:text-gray-500 flex items-center gap-1.5">
|
|
41
|
+
<span x-text="currentCount"></span>
|
|
42
|
+
<%= render "ruby_llm/agents/shared/doc_link" %>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="flex-1 border-t border-gray-200 dark:border-gray-800"></div>
|
|
45
|
+
<div class="flex font-mono text-xs gap-0.5">
|
|
43
46
|
<button type="button" @click="activeSubTab = null; updateUrl()"
|
|
44
|
-
:class="activeSubTab === null ? '
|
|
45
|
-
class="px-
|
|
46
|
-
All (<%= @agent_count %>)
|
|
47
|
-
</button>
|
|
47
|
+
:class="activeSubTab === null ? 'text-gray-900 dark:text-gray-100' : 'text-gray-400 dark:text-gray-500 hover:text-gray-700 dark:hover:text-gray-300'"
|
|
48
|
+
class="px-2 py-0.5">all</button>
|
|
48
49
|
<button type="button" @click="activeSubTab = 'agent'; updateUrl()"
|
|
49
|
-
:class="activeSubTab === 'agent' ? '
|
|
50
|
-
class="px-
|
|
51
|
-
Agents (<%= @agents_by_type[:agent].size %>)
|
|
52
|
-
</button>
|
|
50
|
+
:class="activeSubTab === 'agent' ? 'text-gray-900 dark:text-gray-100' : 'text-gray-400 dark:text-gray-500 hover:text-gray-700 dark:hover:text-gray-300'"
|
|
51
|
+
class="px-2 py-0.5">agents</button>
|
|
53
52
|
<button type="button" @click="activeSubTab = 'embedder'; updateUrl()"
|
|
54
|
-
:class="activeSubTab === 'embedder' ? '
|
|
55
|
-
class="px-
|
|
56
|
-
Embedders (<%= @agents_by_type[:embedder].size %>)
|
|
57
|
-
</button>
|
|
58
|
-
<button type="button" @click="activeSubTab = 'moderator'; updateUrl()"
|
|
59
|
-
:class="activeSubTab === 'moderator' ? 'bg-orange-600 text-white' : 'bg-orange-100 dark:bg-orange-900/50 text-orange-700 dark:text-orange-300 hover:bg-orange-200 dark:hover:bg-orange-800'"
|
|
60
|
-
class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors">
|
|
61
|
-
Moderators (<%= @agents_by_type[:moderator].size %>)
|
|
62
|
-
</button>
|
|
53
|
+
:class="activeSubTab === 'embedder' ? 'text-gray-900 dark:text-gray-100' : 'text-gray-400 dark:text-gray-500 hover:text-gray-700 dark:hover:text-gray-300'"
|
|
54
|
+
class="px-2 py-0.5">embedders</button>
|
|
63
55
|
<% if audio_count > 0 %>
|
|
64
56
|
<button type="button" @click="activeSubTab = 'audio'; updateUrl()"
|
|
65
|
-
:class="activeSubTab === 'audio' ? '
|
|
66
|
-
class="px-
|
|
67
|
-
Audio (<%= audio_count %>)
|
|
68
|
-
</button>
|
|
57
|
+
:class="activeSubTab === 'audio' ? 'text-gray-900 dark:text-gray-100' : 'text-gray-400 dark:text-gray-500 hover:text-gray-700 dark:hover:text-gray-300'"
|
|
58
|
+
class="px-2 py-0.5">audio</button>
|
|
69
59
|
<% end %>
|
|
70
60
|
<% if @agents_by_type[:image_generator].size > 0 %>
|
|
71
61
|
<button type="button" @click="activeSubTab = 'image_generator'; updateUrl()"
|
|
72
|
-
:class="activeSubTab === 'image_generator' ? '
|
|
73
|
-
class="px-
|
|
74
|
-
Image Generators (<%= @agents_by_type[:image_generator].size %>)
|
|
75
|
-
</button>
|
|
62
|
+
:class="activeSubTab === 'image_generator' ? 'text-gray-900 dark:text-gray-100' : 'text-gray-400 dark:text-gray-500 hover:text-gray-700 dark:hover:text-gray-300'"
|
|
63
|
+
class="px-2 py-0.5">image</button>
|
|
76
64
|
<% end %>
|
|
77
65
|
<% if @deleted_count > 0 %>
|
|
78
66
|
<button type="button" @click="activeSubTab = 'deleted'; updateUrl()"
|
|
79
|
-
:class="activeSubTab === 'deleted' ? '
|
|
80
|
-
class="px-
|
|
81
|
-
Deleted (<%= @deleted_count %>)
|
|
82
|
-
</button>
|
|
67
|
+
:class="activeSubTab === 'deleted' ? 'text-gray-900 dark:text-gray-100' : 'text-gray-400 dark:text-gray-500 hover:text-gray-700 dark:hover:text-gray-300'"
|
|
68
|
+
class="px-2 py-0.5">deleted</button>
|
|
83
69
|
<% end %>
|
|
84
70
|
</div>
|
|
85
71
|
</div>
|
|
86
72
|
|
|
87
|
-
<!-- Agents Table -->
|
|
88
73
|
<% if @agents.empty? && @deleted_agents.empty? %>
|
|
89
74
|
<%= render "ruby_llm/agents/agents/empty_state", type: "agents" %>
|
|
90
75
|
<% else %>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
column: "model", label: "Model",
|
|
110
|
-
current_sort: @sort_params[:column], current_direction: @sort_params[:direction],
|
|
111
|
-
th_class: "hidden lg:table-cell" %>
|
|
112
|
-
|
|
113
|
-
<%= render "ruby_llm/agents/agents/sortable_header",
|
|
114
|
-
column: "execution_count", label: "Executions",
|
|
115
|
-
current_sort: @sort_params[:column], current_direction: @sort_params[:direction] %>
|
|
116
|
-
|
|
117
|
-
<%= render "ruby_llm/agents/agents/sortable_header",
|
|
118
|
-
column: "total_cost", label: "Cost",
|
|
119
|
-
current_sort: @sort_params[:column], current_direction: @sort_params[:direction],
|
|
120
|
-
th_class: "hidden md:table-cell" %>
|
|
121
|
-
|
|
122
|
-
<%= render "ruby_llm/agents/agents/sortable_header",
|
|
123
|
-
column: "success_rate", label: "Success",
|
|
124
|
-
current_sort: @sort_params[:column], current_direction: @sort_params[:direction] %>
|
|
125
|
-
|
|
126
|
-
<%= render "ruby_llm/agents/agents/sortable_header",
|
|
127
|
-
column: "last_executed", label: "Last Run",
|
|
128
|
-
current_sort: @sort_params[:column], current_direction: @sort_params[:direction] %>
|
|
129
|
-
</tr>
|
|
130
|
-
</thead>
|
|
131
|
-
|
|
132
|
-
<tbody class="bg-white dark:bg-gray-800 divide-y divide-gray-100/50 dark:divide-gray-700/50">
|
|
133
|
-
<% @agents.each_with_index do |agent, index| %>
|
|
134
|
-
<%
|
|
135
|
-
# Determine if this agent should be shown based on sub-tab (exclude deleted tab)
|
|
136
|
-
show_condition = if agent[:agent_type] == 'speaker' || agent[:agent_type] == 'transcriber'
|
|
137
|
-
"activeSubTab !== 'deleted' && (activeSubTab === null || activeSubTab === 'audio' || activeSubTab === '#{agent[:agent_type]}')"
|
|
138
|
-
else
|
|
139
|
-
"activeSubTab !== 'deleted' && (activeSubTab === null || activeSubTab === '#{agent[:agent_type]}')"
|
|
140
|
-
end
|
|
141
|
-
row_bg = index.even? ? '' : 'bg-gray-50/50 dark:bg-gray-900/30'
|
|
142
|
-
success_rate = agent[:success_rate] || 0
|
|
143
|
-
%>
|
|
144
|
-
<tr
|
|
145
|
-
x-show="<%= show_condition %>"
|
|
146
|
-
class="<%= row_bg %> hover:bg-blue-50/50 dark:hover:bg-blue-900/20 transition-colors cursor-pointer"
|
|
147
|
-
onclick="window.location='<%= ruby_llm_agents.agent_path(ERB::Util.url_encode(agent[:name]), subtab: params[:subtab]) %>'"
|
|
148
|
-
>
|
|
149
|
-
<!-- Name -->
|
|
150
|
-
<td class="px-4 py-3">
|
|
151
|
-
<div class="flex items-center gap-2">
|
|
152
|
-
<span class="text-sm font-medium text-gray-900 dark:text-gray-100">
|
|
153
|
-
<%= agent[:name].split('::').last.gsub(/Agent$/, '') %>
|
|
154
|
-
</span>
|
|
155
|
-
<span class="hidden lg:inline text-xs text-gray-400 dark:text-gray-500">v<%= agent[:version] %></span>
|
|
156
|
-
</div>
|
|
157
|
-
<% if agent[:description].present? %>
|
|
158
|
-
<p class="text-xs text-gray-500 dark:text-gray-400 truncate max-w-64 mt-0.5" title="<%= agent[:description] %>">
|
|
159
|
-
<%= agent[:description] %>
|
|
160
|
-
</p>
|
|
161
|
-
<% end %>
|
|
162
|
-
</td>
|
|
163
|
-
|
|
164
|
-
<!-- Type -->
|
|
165
|
-
<td class="px-4 py-3 whitespace-nowrap">
|
|
166
|
-
<span class="text-sm text-gray-600 dark:text-gray-400">
|
|
167
|
-
<%= agent[:agent_type]&.titleize || 'Agent' %>
|
|
168
|
-
</span>
|
|
169
|
-
</td>
|
|
170
|
-
|
|
171
|
-
<!-- Status -->
|
|
172
|
-
<td class="px-4 py-3 whitespace-nowrap">
|
|
173
|
-
<% if agent[:active] %>
|
|
174
|
-
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-green-100 dark:bg-green-900/50 text-green-800 dark:text-green-300">
|
|
175
|
-
Active
|
|
176
|
-
</span>
|
|
177
|
-
<% else %>
|
|
178
|
-
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400">
|
|
179
|
-
Deleted
|
|
180
|
-
</span>
|
|
181
|
-
<% end %>
|
|
182
|
-
</td>
|
|
183
|
-
|
|
184
|
-
<!-- Model -->
|
|
185
|
-
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400 hidden lg:table-cell">
|
|
186
|
-
<span title="<%= agent[:model] %>">
|
|
187
|
-
<%= agent[:model]&.split("/")&.last || agent[:model] || "-" %>
|
|
188
|
-
</span>
|
|
189
|
-
</td>
|
|
190
|
-
|
|
191
|
-
<!-- Executions -->
|
|
192
|
-
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700 dark:text-gray-300 font-mono">
|
|
193
|
-
<%= number_with_delimiter(agent[:execution_count] || 0) %>
|
|
194
|
-
</td>
|
|
195
|
-
|
|
196
|
-
<!-- Cost -->
|
|
197
|
-
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700 dark:text-gray-300 font-mono hidden md:table-cell">
|
|
198
|
-
$<%= number_with_precision(agent[:total_cost] || 0, precision: 4) %>
|
|
199
|
-
</td>
|
|
200
|
-
|
|
201
|
-
<!-- Success Rate -->
|
|
202
|
-
<td class="px-4 py-3 whitespace-nowrap">
|
|
203
|
-
<div class="flex items-center gap-1.5">
|
|
204
|
-
<% if success_rate >= 95 %>
|
|
205
|
-
<span class="w-2 h-2 rounded-full bg-green-500"></span>
|
|
206
|
-
<span class="text-sm text-green-600 dark:text-green-400"><%= success_rate %>%</span>
|
|
207
|
-
<% elsif success_rate >= 80 %>
|
|
208
|
-
<span class="w-2 h-2 rounded-full bg-yellow-500"></span>
|
|
209
|
-
<span class="text-sm text-yellow-600 dark:text-yellow-400"><%= success_rate %>%</span>
|
|
210
|
-
<% else %>
|
|
211
|
-
<span class="w-2 h-2 rounded-full bg-red-500"></span>
|
|
212
|
-
<span class="text-sm text-red-600 dark:text-red-400"><%= success_rate %>%</span>
|
|
213
|
-
<% end %>
|
|
214
|
-
</div>
|
|
215
|
-
</td>
|
|
76
|
+
<!-- Column headers -->
|
|
77
|
+
<div class="flex items-center gap-3 px-2 -mx-2 font-mono text-[10px] text-gray-400 dark:text-gray-600 uppercase tracking-wider mb-1">
|
|
78
|
+
<%= link_to "name#{sort_arrow.call('name')}".html_safe, sort_url.call("name"),
|
|
79
|
+
class: "flex-[2] min-w-0 hover:text-gray-600 dark:hover:text-gray-300 #{sort_active.call('name')}" %>
|
|
80
|
+
<%= link_to "type#{sort_arrow.call('agent_type')}".html_safe, sort_url.call("agent_type"),
|
|
81
|
+
class: "flex-1 min-w-0 hidden sm:block hover:text-gray-600 dark:hover:text-gray-300 #{sort_active.call('agent_type')}" %>
|
|
82
|
+
<span class="w-1.5 flex-shrink-0"></span>
|
|
83
|
+
<%= link_to "model#{sort_arrow.call('model')}".html_safe, sort_url.call("model"),
|
|
84
|
+
class: "flex-[2] min-w-0 hidden lg:block hover:text-gray-600 dark:hover:text-gray-300 #{sort_active.call('model')}" %>
|
|
85
|
+
<%= link_to "runs#{sort_arrow.call('execution_count')}".html_safe, sort_url.call("execution_count"),
|
|
86
|
+
class: "w-14 flex-shrink-0 text-right hover:text-gray-600 dark:hover:text-gray-300 #{sort_active.call('execution_count')}" %>
|
|
87
|
+
<%= link_to "cost#{sort_arrow.call('total_cost')}".html_safe, sort_url.call("total_cost"),
|
|
88
|
+
class: "w-16 flex-shrink-0 text-right hidden md:block hover:text-gray-600 dark:hover:text-gray-300 #{sort_active.call('total_cost')}" %>
|
|
89
|
+
<%= link_to "ok%#{sort_arrow.call('success_rate')}".html_safe, sort_url.call("success_rate"),
|
|
90
|
+
class: "w-12 flex-shrink-0 text-right hover:text-gray-600 dark:hover:text-gray-300 #{sort_active.call('success_rate')}" %>
|
|
91
|
+
<%= link_to "last run#{sort_arrow.call('last_executed')}".html_safe, sort_url.call("last_executed"),
|
|
92
|
+
class: "w-24 flex-shrink-0 text-right hover:text-gray-600 dark:hover:text-gray-300 #{sort_active.call('last_executed')}" %>
|
|
93
|
+
</div>
|
|
216
94
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
95
|
+
<!-- Data rows -->
|
|
96
|
+
<div class="font-mono text-xs space-y-px">
|
|
97
|
+
<% @agents.each do |agent| %>
|
|
98
|
+
<%
|
|
99
|
+
show_condition = if agent[:agent_type] == 'speaker' || agent[:agent_type] == 'transcriber'
|
|
100
|
+
"activeSubTab !== 'deleted' && (activeSubTab === null || activeSubTab === 'audio' || activeSubTab === '#{agent[:agent_type]}')"
|
|
101
|
+
else
|
|
102
|
+
"activeSubTab !== 'deleted' && (activeSubTab === null || activeSubTab === '#{agent[:agent_type]}')"
|
|
103
|
+
end
|
|
104
|
+
success_rate = agent[:success_rate] || 0
|
|
105
|
+
dot_color = agent[:active] ? (success_rate >= 95 ? 'bg-green-500' : success_rate >= 80 ? 'bg-yellow-500' : 'bg-red-500') : 'bg-gray-400'
|
|
106
|
+
%>
|
|
107
|
+
<div x-show="<%= show_condition %>"
|
|
108
|
+
class="group flex items-center gap-3 py-1.5 px-2 -mx-2 rounded hover:bg-gray-100 dark:hover:bg-gray-800/50 cursor-pointer"
|
|
109
|
+
onclick="window.location='<%= ruby_llm_agents.agent_path(ERB::Util.url_encode(agent[:name]), subtab: params[:subtab]) %>'"
|
|
110
|
+
title="<%= agent[:description] %>">
|
|
111
|
+
<span class="flex-[2] min-w-0 truncate text-gray-900 dark:text-gray-200">
|
|
112
|
+
<%= agent[:name].split('::').last.gsub(/Agent$/, '') %><span class="hidden lg:inline text-gray-400 dark:text-gray-600 ml-1 text-[10px]">v<%= agent[:version] %></span>
|
|
113
|
+
</span>
|
|
114
|
+
<span class="flex-1 min-w-0 truncate text-gray-500 dark:text-gray-400 hidden sm:inline"><%= agent[:agent_type]&.to_s || 'agent' %></span>
|
|
115
|
+
<span class="w-1.5 h-1.5 rounded-full flex-shrink-0 <%= dot_color %>"></span>
|
|
116
|
+
<span class="flex-[2] min-w-0 truncate text-gray-400 dark:text-gray-600 hidden lg:inline"><%= agent[:model]&.split("/")&.last || "—" %></span>
|
|
117
|
+
<span class="w-14 flex-shrink-0 text-right text-gray-500 dark:text-gray-400"><%= number_with_delimiter(agent[:execution_count] || 0) %><span class="text-gray-400 dark:text-gray-600">r</span></span>
|
|
118
|
+
<span class="w-16 flex-shrink-0 text-right text-gray-500 dark:text-gray-400 hidden md:inline">$<%= number_with_precision(agent[:total_cost] || 0, precision: 2) %></span>
|
|
119
|
+
<span class="w-12 flex-shrink-0 text-right <%= success_rate >= 95 ? 'text-green-500' : success_rate >= 80 ? 'text-yellow-500' : 'text-red-500' %>"><%= success_rate.round %>%</span>
|
|
120
|
+
<span class="w-24 flex-shrink-0 text-gray-400 dark:text-gray-600 text-right whitespace-nowrap">
|
|
121
|
+
<% if agent[:last_executed] %>
|
|
122
|
+
<%= time_ago_in_words(agent[:last_executed]) %>
|
|
123
|
+
<% else %>
|
|
124
|
+
—
|
|
226
125
|
<% end %>
|
|
126
|
+
</span>
|
|
127
|
+
</div>
|
|
128
|
+
<% end %>
|
|
227
129
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
<% if agent[:description].present? %>
|
|
248
|
-
<p class="text-xs text-gray-500 dark:text-gray-400 truncate max-w-48 mt-0.5" title="<%= agent[:description] %>">
|
|
249
|
-
<%= agent[:description] %>
|
|
250
|
-
</p>
|
|
251
|
-
<% end %>
|
|
252
|
-
</td>
|
|
253
|
-
|
|
254
|
-
<!-- Type -->
|
|
255
|
-
<td class="px-4 py-3 whitespace-nowrap">
|
|
256
|
-
<span class="text-sm text-gray-600 dark:text-gray-400">
|
|
257
|
-
<%= agent[:agent_type]&.titleize || 'Agent' %>
|
|
258
|
-
</span>
|
|
259
|
-
</td>
|
|
260
|
-
|
|
261
|
-
<!-- Status -->
|
|
262
|
-
<td class="px-4 py-3 whitespace-nowrap">
|
|
263
|
-
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400">
|
|
264
|
-
Deleted
|
|
265
|
-
</span>
|
|
266
|
-
</td>
|
|
267
|
-
|
|
268
|
-
<!-- Model -->
|
|
269
|
-
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400 hidden lg:table-cell">
|
|
270
|
-
<span title="<%= agent[:model] %>">
|
|
271
|
-
<%= agent[:model]&.split("/")&.last || agent[:model] || "-" %>
|
|
272
|
-
</span>
|
|
273
|
-
</td>
|
|
274
|
-
|
|
275
|
-
<!-- Executions -->
|
|
276
|
-
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700 dark:text-gray-300 font-mono">
|
|
277
|
-
<%= number_with_delimiter(agent[:execution_count] || 0) %>
|
|
278
|
-
</td>
|
|
279
|
-
|
|
280
|
-
<!-- Cost -->
|
|
281
|
-
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-700 dark:text-gray-300 font-mono hidden md:table-cell">
|
|
282
|
-
$<%= number_with_precision(agent[:total_cost] || 0, precision: 4) %>
|
|
283
|
-
</td>
|
|
284
|
-
|
|
285
|
-
<!-- Success Rate -->
|
|
286
|
-
<td class="px-4 py-3 whitespace-nowrap">
|
|
287
|
-
<div class="flex items-center gap-1.5">
|
|
288
|
-
<% if success_rate >= 95 %>
|
|
289
|
-
<span class="w-2 h-2 rounded-full bg-green-500"></span>
|
|
290
|
-
<span class="text-sm text-green-600 dark:text-green-400"><%= success_rate %>%</span>
|
|
291
|
-
<% elsif success_rate >= 80 %>
|
|
292
|
-
<span class="w-2 h-2 rounded-full bg-yellow-500"></span>
|
|
293
|
-
<span class="text-sm text-yellow-600 dark:text-yellow-400"><%= success_rate %>%</span>
|
|
294
|
-
<% else %>
|
|
295
|
-
<span class="w-2 h-2 rounded-full bg-red-500"></span>
|
|
296
|
-
<span class="text-sm text-red-600 dark:text-red-400"><%= success_rate %>%</span>
|
|
297
|
-
<% end %>
|
|
298
|
-
</div>
|
|
299
|
-
</td>
|
|
300
|
-
|
|
301
|
-
<!-- Last Executed -->
|
|
302
|
-
<td class="px-4 py-3 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
|
|
303
|
-
<% if agent[:last_executed] %>
|
|
304
|
-
<%= time_ago_in_words(agent[:last_executed]) %> ago
|
|
305
|
-
<% else %>
|
|
306
|
-
<span class="text-gray-400 dark:text-gray-500">Never</span>
|
|
307
|
-
<% end %>
|
|
308
|
-
</td>
|
|
309
|
-
</tr>
|
|
130
|
+
<!-- Deleted agents -->
|
|
131
|
+
<% @deleted_agents.each do |agent| %>
|
|
132
|
+
<% success_rate = agent[:success_rate] || 0 %>
|
|
133
|
+
<div x-show="activeSubTab === 'deleted'"
|
|
134
|
+
class="group flex items-center gap-3 py-1.5 px-2 -mx-2 rounded hover:bg-gray-100 dark:hover:bg-gray-800/50 cursor-pointer"
|
|
135
|
+
onclick="window.location='<%= ruby_llm_agents.agent_path(ERB::Util.url_encode(agent[:name]), subtab: params[:subtab]) %>'"
|
|
136
|
+
title="<%= agent[:description] %>">
|
|
137
|
+
<span class="flex-[2] min-w-0 truncate text-gray-500 dark:text-gray-400 line-through"><%= agent[:name].split('::').last.gsub(/Agent$/, '') %></span>
|
|
138
|
+
<span class="flex-1 min-w-0 truncate text-gray-400 dark:text-gray-600 hidden sm:inline"><%= agent[:agent_type]&.to_s || 'agent' %></span>
|
|
139
|
+
<span class="w-1.5 h-1.5 rounded-full flex-shrink-0 bg-gray-400 dark:bg-gray-600"></span>
|
|
140
|
+
<span class="flex-[2] min-w-0 truncate text-gray-400 dark:text-gray-600 hidden lg:inline"><%= agent[:model]&.split("/")&.last || "—" %></span>
|
|
141
|
+
<span class="w-14 flex-shrink-0 text-right text-gray-400 dark:text-gray-600"><%= number_with_delimiter(agent[:execution_count] || 0) %><span class="text-gray-400 dark:text-gray-600">r</span></span>
|
|
142
|
+
<span class="w-16 flex-shrink-0 text-right text-gray-400 dark:text-gray-600 hidden md:inline">$<%= number_with_precision(agent[:total_cost] || 0, precision: 2) %></span>
|
|
143
|
+
<span class="w-12 flex-shrink-0 text-right text-gray-400 dark:text-gray-600"><%= success_rate.round %>%</span>
|
|
144
|
+
<span class="w-24 flex-shrink-0 text-gray-400 dark:text-gray-600 text-right whitespace-nowrap">
|
|
145
|
+
<% if agent[:last_executed] %>
|
|
146
|
+
<%= time_ago_in_words(agent[:last_executed]) %>
|
|
147
|
+
<% else %>
|
|
148
|
+
—
|
|
310
149
|
<% end %>
|
|
150
|
+
</span>
|
|
151
|
+
</div>
|
|
152
|
+
<% end %>
|
|
311
153
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
<div class="text-gray-400 dark:text-gray-500">
|
|
316
|
-
<svg class="mx-auto h-12 w-12 mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
317
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
|
318
|
-
</svg>
|
|
319
|
-
<p class="text-lg font-medium text-gray-500 dark:text-gray-400">No agents in this category</p>
|
|
320
|
-
<p class="text-sm mt-1">Try selecting a different filter</p>
|
|
321
|
-
</div>
|
|
322
|
-
</td>
|
|
323
|
-
</tr>
|
|
324
|
-
</tbody>
|
|
325
|
-
</table>
|
|
154
|
+
<!-- Empty filter state -->
|
|
155
|
+
<div x-show="currentCount === 0" x-cloak class="py-4 px-2 text-gray-400 dark:text-gray-600">
|
|
156
|
+
no agents in this category
|
|
326
157
|
</div>
|
|
327
158
|
</div>
|
|
328
159
|
<% end %>
|