ruby_llm-agents 1.0.0 → 1.2.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/app/controllers/concerns/ruby_llm/agents/paginatable.rb +9 -3
- data/app/controllers/concerns/ruby_llm/agents/sortable.rb +58 -0
- data/app/controllers/ruby_llm/agents/agents_controller.rb +59 -16
- data/app/controllers/ruby_llm/agents/dashboard_controller.rb +144 -20
- data/app/controllers/ruby_llm/agents/executions_controller.rb +13 -16
- data/app/controllers/ruby_llm/agents/workflows_controller.rb +279 -90
- data/app/helpers/ruby_llm/agents/application_helper.rb +100 -0
- data/app/mailers/ruby_llm/agents/alert_mailer.rb +84 -0
- data/app/mailers/ruby_llm/agents/application_mailer.rb +28 -0
- data/app/models/ruby_llm/agents/execution/analytics.rb +170 -20
- data/app/models/ruby_llm/agents/execution/scopes.rb +0 -31
- data/app/models/ruby_llm/agents/execution/workflow.rb +0 -129
- data/app/models/ruby_llm/agents/execution.rb +50 -14
- data/app/models/ruby_llm/agents/tenant/budgetable.rb +277 -0
- data/app/models/ruby_llm/agents/tenant/configurable.rb +135 -0
- data/app/models/ruby_llm/agents/tenant/trackable.rb +310 -0
- data/app/models/ruby_llm/agents/tenant.rb +146 -0
- data/app/models/ruby_llm/agents/tenant_budget.rb +12 -253
- data/app/services/ruby_llm/agents/agent_registry.rb +18 -12
- data/app/views/layouts/ruby_llm/agents/application.html.erb +72 -76
- data/app/views/ruby_llm/agents/agents/_agent.html.erb +0 -12
- data/app/views/ruby_llm/agents/agents/_sortable_header.html.erb +56 -0
- data/app/views/ruby_llm/agents/agents/_workflow.html.erb +5 -15
- data/app/views/ruby_llm/agents/agents/index.html.erb +271 -100
- data/app/views/ruby_llm/agents/agents/show.html.erb +1 -0
- data/app/views/ruby_llm/agents/alert_mailer/alert_notification.html.erb +107 -0
- data/app/views/ruby_llm/agents/alert_mailer/alert_notification.text.erb +18 -0
- data/app/views/ruby_llm/agents/api_configurations/show.html.erb +4 -1
- data/app/views/ruby_llm/agents/dashboard/_agent_comparison.html.erb +66 -359
- data/app/views/ruby_llm/agents/dashboard/_model_comparison.html.erb +56 -0
- data/app/views/ruby_llm/agents/dashboard/_model_cost_breakdown.html.erb +115 -0
- data/app/views/ruby_llm/agents/dashboard/_now_strip.html.erb +35 -60
- data/app/views/ruby_llm/agents/dashboard/_top_errors.html.erb +17 -6
- data/app/views/ruby_llm/agents/dashboard/index.html.erb +373 -72
- data/app/views/ruby_llm/agents/executions/_execution.html.erb +0 -1
- data/app/views/ruby_llm/agents/executions/_filters.html.erb +51 -39
- data/app/views/ruby_llm/agents/executions/_list.html.erb +53 -195
- data/app/views/ruby_llm/agents/executions/_workflow_summary.html.erb +5 -20
- data/app/views/ruby_llm/agents/executions/index.html.erb +7 -83
- data/app/views/ruby_llm/agents/executions/show.html.erb +10 -20
- data/app/views/ruby_llm/agents/shared/_agent_type_badge.html.erb +2 -1
- data/app/views/ruby_llm/agents/shared/_doc_link.html.erb +12 -0
- data/app/views/ruby_llm/agents/shared/_executions_table.html.erb +3 -15
- data/app/views/ruby_llm/agents/shared/_filter_dropdown.html.erb +1 -1
- data/app/views/ruby_llm/agents/shared/_select_dropdown.html.erb +1 -1
- data/app/views/ruby_llm/agents/shared/_sortable_header.html.erb +53 -0
- data/app/views/ruby_llm/agents/shared/_status_badge.html.erb +7 -0
- data/app/views/ruby_llm/agents/shared/_status_dot.html.erb +1 -1
- data/app/views/ruby_llm/agents/shared/_workflow_type_badge.html.erb +9 -35
- data/app/views/ruby_llm/agents/system_config/show.html.erb +4 -1
- data/app/views/ruby_llm/agents/tenants/index.html.erb +4 -1
- data/app/views/ruby_llm/agents/workflows/_step_performance.html.erb +7 -15
- data/app/views/ruby_llm/agents/workflows/_structure_dsl.html.erb +539 -0
- data/app/views/ruby_llm/agents/workflows/_workflow_diagram.html.erb +920 -0
- data/app/views/ruby_llm/agents/workflows/index.html.erb +179 -0
- data/app/views/ruby_llm/agents/workflows/show.html.erb +164 -139
- data/config/routes.rb +1 -1
- data/lib/generators/ruby_llm_agents/agent_generator.rb +6 -36
- data/lib/generators/ruby_llm_agents/background_remover_generator.rb +7 -37
- data/lib/generators/ruby_llm_agents/embedder_generator.rb +5 -38
- data/lib/generators/ruby_llm_agents/image_analyzer_generator.rb +7 -37
- data/lib/generators/ruby_llm_agents/image_editor_generator.rb +7 -37
- data/lib/generators/ruby_llm_agents/image_generator_generator.rb +8 -41
- data/lib/generators/ruby_llm_agents/image_pipeline_generator.rb +18 -46
- data/lib/generators/ruby_llm_agents/image_transformer_generator.rb +7 -37
- data/lib/generators/ruby_llm_agents/image_upscaler_generator.rb +7 -37
- data/lib/generators/ruby_llm_agents/image_variator_generator.rb +7 -37
- data/lib/generators/ruby_llm_agents/install_generator.rb +33 -56
- data/lib/generators/ruby_llm_agents/migrate_structure_generator.rb +480 -0
- data/lib/generators/ruby_llm_agents/multi_tenancy_generator.rb +42 -22
- data/lib/generators/ruby_llm_agents/restructure_generator.rb +2 -2
- data/lib/generators/ruby_llm_agents/speaker_generator.rb +8 -39
- data/lib/generators/ruby_llm_agents/templates/add_tenant_to_executions_migration.rb.tt +13 -2
- data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +5 -8
- data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +40 -42
- data/lib/generators/ruby_llm_agents/templates/application_background_remover.rb.tt +20 -22
- data/lib/generators/ruby_llm_agents/templates/application_embedder.rb.tt +24 -26
- data/lib/generators/ruby_llm_agents/templates/application_image_analyzer.rb.tt +20 -22
- data/lib/generators/ruby_llm_agents/templates/application_image_editor.rb.tt +19 -17
- data/lib/generators/ruby_llm_agents/templates/application_image_generator.rb.tt +31 -33
- data/lib/generators/ruby_llm_agents/templates/application_image_pipeline.rb.tt +125 -127
- data/lib/generators/ruby_llm_agents/templates/application_image_transformer.rb.tt +20 -18
- data/lib/generators/ruby_llm_agents/templates/application_image_upscaler.rb.tt +19 -17
- data/lib/generators/ruby_llm_agents/templates/application_image_variator.rb.tt +19 -17
- data/lib/generators/ruby_llm_agents/templates/application_speaker.rb.tt +38 -40
- data/lib/generators/ruby_llm_agents/templates/application_transcriber.rb.tt +42 -44
- data/lib/generators/ruby_llm_agents/templates/application_workflow.rb.tt +48 -0
- data/lib/generators/ruby_llm_agents/templates/background_remover.rb.tt +19 -21
- data/lib/generators/ruby_llm_agents/templates/create_tenant_budgets_migration.rb.tt +11 -0
- data/lib/generators/ruby_llm_agents/templates/create_tenants_migration.rb.tt +72 -0
- data/lib/generators/ruby_llm_agents/templates/embedder.rb.tt +19 -21
- data/lib/generators/ruby_llm_agents/templates/image_analyzer.rb.tt +20 -22
- data/lib/generators/ruby_llm_agents/templates/image_editor.rb.tt +15 -17
- data/lib/generators/ruby_llm_agents/templates/image_generator.rb.tt +25 -27
- data/lib/generators/ruby_llm_agents/templates/image_pipeline.rb.tt +19 -21
- data/lib/generators/ruby_llm_agents/templates/image_transformer.rb.tt +20 -22
- data/lib/generators/ruby_llm_agents/templates/image_upscaler.rb.tt +17 -19
- data/lib/generators/ruby_llm_agents/templates/image_variator.rb.tt +15 -17
- data/lib/generators/ruby_llm_agents/templates/rename_tenant_budgets_to_tenants_migration.rb.tt +34 -0
- data/lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt +87 -24
- data/lib/generators/ruby_llm_agents/templates/skills/BACKGROUND_REMOVERS.md.tt +21 -27
- data/lib/generators/ruby_llm_agents/templates/skills/EMBEDDERS.md.tt +46 -54
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_ANALYZERS.md.tt +31 -39
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_EDITORS.md.tt +22 -28
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_GENERATORS.md.tt +53 -63
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_PIPELINES.md.tt +46 -56
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_TRANSFORMERS.md.tt +23 -31
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_UPSCALERS.md.tt +22 -30
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_VARIATORS.md.tt +23 -31
- data/lib/generators/ruby_llm_agents/templates/skills/SPEAKERS.md.tt +38 -46
- data/lib/generators/ruby_llm_agents/templates/skills/TOOLS.md.tt +7 -7
- data/lib/generators/ruby_llm_agents/templates/skills/TRANSCRIBERS.md.tt +59 -71
- data/lib/generators/ruby_llm_agents/templates/skills/WORKFLOWS.md.tt +274 -23
- data/lib/generators/ruby_llm_agents/templates/speaker.rb.tt +29 -31
- data/lib/generators/ruby_llm_agents/templates/transcriber.rb.tt +28 -30
- data/lib/generators/ruby_llm_agents/transcriber_generator.rb +10 -43
- data/lib/generators/ruby_llm_agents/upgrade_generator.rb +26 -0
- data/lib/ruby_llm/agents/core/configuration.rb +55 -43
- data/lib/ruby_llm/agents/core/llm_tenant.rb +60 -60
- data/lib/ruby_llm/agents/core/version.rb +1 -1
- data/lib/ruby_llm/agents/infrastructure/alert_manager.rb +26 -0
- data/lib/ruby_llm/agents/infrastructure/budget/config_resolver.rb +4 -2
- data/lib/ruby_llm/agents/pipeline.rb +69 -0
- data/lib/ruby_llm/agents/workflow/approval.rb +205 -0
- data/lib/ruby_llm/agents/workflow/approval_store.rb +179 -0
- data/lib/ruby_llm/agents/workflow/dsl/executor.rb +467 -0
- data/lib/ruby_llm/agents/workflow/dsl/input_schema.rb +244 -0
- data/lib/ruby_llm/agents/workflow/dsl/iteration_executor.rb +289 -0
- data/lib/ruby_llm/agents/workflow/dsl/parallel_group.rb +107 -0
- data/lib/ruby_llm/agents/workflow/dsl/route_builder.rb +150 -0
- data/lib/ruby_llm/agents/workflow/dsl/schedule_helpers.rb +187 -0
- data/lib/ruby_llm/agents/workflow/dsl/step_config.rb +352 -0
- data/lib/ruby_llm/agents/workflow/dsl/step_executor.rb +415 -0
- data/lib/ruby_llm/agents/workflow/dsl/wait_config.rb +257 -0
- data/lib/ruby_llm/agents/workflow/dsl/wait_executor.rb +317 -0
- data/lib/ruby_llm/agents/workflow/dsl.rb +576 -0
- data/lib/ruby_llm/agents/workflow/instrumentation.rb +2 -7
- data/lib/ruby_llm/agents/workflow/notifiers/base.rb +117 -0
- data/lib/ruby_llm/agents/workflow/notifiers/email.rb +117 -0
- data/lib/ruby_llm/agents/workflow/notifiers/slack.rb +180 -0
- data/lib/ruby_llm/agents/workflow/notifiers/webhook.rb +121 -0
- data/lib/ruby_llm/agents/workflow/notifiers.rb +70 -0
- data/lib/ruby_llm/agents/workflow/orchestrator.rb +190 -23
- data/lib/ruby_llm/agents/workflow/result.rb +202 -0
- data/lib/ruby_llm/agents/workflow/throttle_manager.rb +206 -0
- data/lib/ruby_llm/agents/workflow/wait_result.rb +213 -0
- metadata +43 -6
- data/app/views/ruby_llm/agents/dashboard/_execution_item.html.erb +0 -66
- data/lib/ruby_llm/agents/workflow/parallel.rb +0 -299
- data/lib/ruby_llm/agents/workflow/pipeline.rb +0 -306
- data/lib/ruby_llm/agents/workflow/router.rb +0 -429
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
<h2 class="text-lg font-bold text-gray-900 dark:text-gray-100 truncate">
|
|
31
31
|
<%= @execution.agent_type.gsub(/Agent$/, '') %>
|
|
32
32
|
</h2>
|
|
33
|
+
<%= render "ruby_llm/agents/shared/doc_link" %>
|
|
33
34
|
<%= render "ruby_llm/agents/shared/status_badge", status: @execution.status, size: :md %>
|
|
34
35
|
<% if secondary_badges.any? %>
|
|
35
36
|
<div class="relative" x-data="{ showDetails: false }">
|
|
@@ -216,28 +217,17 @@
|
|
|
216
217
|
<% if (@execution.workflow_type.present? || @execution.workflow_step.present? || @execution.routed_to.present?) && !(@execution.respond_to?(:root_workflow?) && @execution.root_workflow?) %>
|
|
217
218
|
<div class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl p-4 sm:p-5 mb-6">
|
|
218
219
|
<div class="flex items-center gap-2 mb-4">
|
|
219
|
-
<%
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
<span class="text-base">→</span> Pipeline Workflow
|
|
220
|
+
<% if @execution.workflow_type.present? %>
|
|
221
|
+
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md text-sm font-medium bg-emerald-100 dark:bg-emerald-900/50 text-emerald-700 dark:text-emerald-300">
|
|
222
|
+
<span class="text-base">◈</span> Workflow
|
|
223
223
|
</span>
|
|
224
|
-
<%
|
|
225
|
-
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md text-sm font-medium bg-
|
|
226
|
-
<
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
<span class="text-base">⑂</span> Router Workflow
|
|
224
|
+
<% elsif @execution.workflow_step.present? %>
|
|
225
|
+
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md text-sm font-medium bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300">
|
|
226
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
227
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 5l7 7-7 7M5 5l7 7-7 7"/>
|
|
228
|
+
</svg>
|
|
229
|
+
Workflow Step
|
|
231
230
|
</span>
|
|
232
|
-
<% else %>
|
|
233
|
-
<% if @execution.workflow_step.present? %>
|
|
234
|
-
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md text-sm font-medium bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300">
|
|
235
|
-
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
236
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 5l7 7-7 7M5 5l7 7-7 7"/>
|
|
237
|
-
</svg>
|
|
238
|
-
Workflow Step
|
|
239
|
-
</span>
|
|
240
|
-
<% end %>
|
|
241
231
|
<% end %>
|
|
242
232
|
<% if @execution.workflow_id.present? %>
|
|
243
233
|
<span class="text-xs text-gray-400 dark:text-gray-500 font-mono" title="Workflow ID: <%= @execution.workflow_id %>">
|
|
@@ -85,7 +85,8 @@
|
|
|
85
85
|
{ badge: "px-2 py-0.5", icon: "text-xs", text: "text-xs" }
|
|
86
86
|
end
|
|
87
87
|
%>
|
|
88
|
-
<span class="inline-flex items-center gap-1 rounded-md font-medium <%= config[:bg] %> <%= config[:text] %> <%= size_classes[:badge] %>"
|
|
88
|
+
<span class="inline-flex items-center gap-1 rounded-md font-medium <%= config[:bg] %> <%= config[:text] %> <%= size_classes[:badge] %>"
|
|
89
|
+
title="<%= config[:label] %>">
|
|
89
90
|
<span class="<%= size_classes[:icon] %>" aria-hidden="true"><%= config[:icon_char] %></span>
|
|
90
91
|
<% if show_label %>
|
|
91
92
|
<span class="<%= size_classes[:text] %>"><%= config[:label] %></span>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<% doc_url = documentation_url %>
|
|
2
|
+
<% if doc_url %>
|
|
3
|
+
<%= link_to doc_url,
|
|
4
|
+
target: "_blank",
|
|
5
|
+
rel: "noopener noreferrer",
|
|
6
|
+
class: "text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300 transition-colors",
|
|
7
|
+
title: "View documentation" do %>
|
|
8
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
9
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"/>
|
|
10
|
+
</svg>
|
|
11
|
+
<% end %>
|
|
12
|
+
<% end %>
|
|
@@ -42,17 +42,7 @@
|
|
|
42
42
|
<%= execution.agent_type.gsub(/Agent$/, "") %>
|
|
43
43
|
<% end %>
|
|
44
44
|
<% if is_workflow %>
|
|
45
|
-
|
|
46
|
-
when "pipeline" then "text-indigo-600 dark:text-indigo-400"
|
|
47
|
-
when "parallel" then "text-cyan-600 dark:text-cyan-400"
|
|
48
|
-
when "router" then "text-amber-600 dark:text-amber-400"
|
|
49
|
-
end %>
|
|
50
|
-
<% badge_icon = case execution.workflow_type
|
|
51
|
-
when "pipeline" then "→"
|
|
52
|
-
when "parallel" then "⫴"
|
|
53
|
-
when "router" then "⑂"
|
|
54
|
-
end %>
|
|
55
|
-
<span class="text-xs <%= badge_style %>"><%= badge_icon %></span>
|
|
45
|
+
<span class="text-xs text-emerald-600 dark:text-emerald-400">◈</span>
|
|
56
46
|
<% end %>
|
|
57
47
|
</div>
|
|
58
48
|
</td>
|
|
@@ -134,12 +124,10 @@
|
|
|
134
124
|
</div>
|
|
135
125
|
</td>
|
|
136
126
|
|
|
137
|
-
<%# Step
|
|
127
|
+
<%# Step Name %>
|
|
138
128
|
<td class="px-4 py-2 whitespace-nowrap">
|
|
139
129
|
<%= link_to ruby_llm_agents.execution_path(child), class: "text-gray-600 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400" do %>
|
|
140
|
-
|
|
141
|
-
<span class="text-gray-400 dark:text-gray-500 text-xs"><%= index + 1 %>.</span>
|
|
142
|
-
<% end %>
|
|
130
|
+
<span class="text-gray-400 dark:text-gray-500 text-xs"><%= index + 1 %>.</span>
|
|
143
131
|
<%= child.workflow_step || child.agent_type.gsub(/Agent$/, "") %>
|
|
144
132
|
<% end %>
|
|
145
133
|
</td>
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
class="<%= full_width ? 'w-full md:w-auto justify-between md:justify-start' : '' %> flex items-center gap-2 px-3 py-2 text-sm
|
|
46
46
|
bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg
|
|
47
47
|
hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors
|
|
48
|
-
<%= has_selection ? '
|
|
48
|
+
<%= has_selection ? 'border-blue-300 dark:border-blue-600' : '' %>">
|
|
49
49
|
<div class="flex items-center gap-2">
|
|
50
50
|
<% if current_color.present? %>
|
|
51
51
|
<span class="w-2 h-2 rounded-full <%= current_color %> <%= current_color.include?('blue') && selected.first == 'running' ? 'animate-pulse' : '' %>"></span>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
class="<%= full_width ? 'w-full md:w-auto justify-between md:justify-start' : '' %> flex items-center gap-2 px-3 py-2 text-sm
|
|
32
32
|
bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg
|
|
33
33
|
hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors
|
|
34
|
-
<%= has_selection ? '
|
|
34
|
+
<%= has_selection ? 'border-blue-300 dark:border-blue-600' : '' %>">
|
|
35
35
|
<div class="flex items-center gap-2">
|
|
36
36
|
<% if local_assigns[:icon].present? %>
|
|
37
37
|
<svg class="w-4 h-4 text-gray-400 dark:text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<%#
|
|
2
|
+
Sortable column header component
|
|
3
|
+
|
|
4
|
+
Creates a clickable table header that toggles sort direction and
|
|
5
|
+
displays visual feedback for the current sort state.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
render "ruby_llm/agents/shared/sortable_header",
|
|
9
|
+
column: "created_at",
|
|
10
|
+
label: "Time",
|
|
11
|
+
current_sort: @sort_params[:column],
|
|
12
|
+
current_direction: @sort_params[:direction],
|
|
13
|
+
align: "right"
|
|
14
|
+
|
|
15
|
+
Parameters:
|
|
16
|
+
column - (String) The column name used in sort URL parameter
|
|
17
|
+
label - (String) Display text for the header
|
|
18
|
+
current_sort - (String) Currently active sort column
|
|
19
|
+
current_direction - (String) Current sort direction ('asc' or 'desc')
|
|
20
|
+
align - (String) Text alignment: 'left' (default), 'center', or 'right'
|
|
21
|
+
%>
|
|
22
|
+
<%
|
|
23
|
+
align = local_assigns[:align] || "left"
|
|
24
|
+
is_active = column == current_sort
|
|
25
|
+
next_direction = is_active && current_direction == "asc" ? "desc" : "asc"
|
|
26
|
+
sort_url = url_for(request.query_parameters.merge(sort: column, direction: next_direction, page: 1))
|
|
27
|
+
|
|
28
|
+
align_class = case align
|
|
29
|
+
when "right" then "text-right justify-end"
|
|
30
|
+
when "center" then "text-center justify-center"
|
|
31
|
+
else "text-left justify-start"
|
|
32
|
+
end
|
|
33
|
+
%>
|
|
34
|
+
<th scope="col" class="px-4 py-3">
|
|
35
|
+
<a href="<%= sort_url %>"
|
|
36
|
+
class="group inline-flex items-center gap-1 <%= align_class %> w-full
|
|
37
|
+
text-xs font-semibold uppercase tracking-wider
|
|
38
|
+
<%= is_active ? 'text-blue-600 dark:text-blue-400' : 'text-gray-500 dark:text-gray-400' %>
|
|
39
|
+
hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
|
40
|
+
<span><%= label %></span>
|
|
41
|
+
<span class="<%= is_active ? 'opacity-100' : 'opacity-0 group-hover:opacity-50' %> transition-opacity">
|
|
42
|
+
<% if is_active && current_direction == "asc" %>
|
|
43
|
+
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
44
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7"/>
|
|
45
|
+
</svg>
|
|
46
|
+
<% else %>
|
|
47
|
+
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
48
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
|
49
|
+
</svg>
|
|
50
|
+
<% end %>
|
|
51
|
+
</span>
|
|
52
|
+
</a>
|
|
53
|
+
</th>
|
|
@@ -62,4 +62,11 @@
|
|
|
62
62
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="<%= config[:icon] %>"/>
|
|
63
63
|
</svg>
|
|
64
64
|
<span class="<%= size_classes[:text] %>"><%= status.to_s.capitalize %></span>
|
|
65
|
+
<% if local_assigns[:attempts_count] && attempts_count.to_i > 1 %>
|
|
66
|
+
<span class="opacity-70" title="<%= attempts_count %> attempts (retried)">
|
|
67
|
+
<svg class="<%= size_classes[:icon] %>" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
68
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
|
|
69
|
+
</svg>
|
|
70
|
+
</span>
|
|
71
|
+
<% end %>
|
|
65
72
|
</span>
|
|
@@ -15,4 +15,4 @@
|
|
|
15
15
|
{ color: "bg-gray-500", animate: false }
|
|
16
16
|
end
|
|
17
17
|
%>
|
|
18
|
-
<span class="w-2.5 h-2.5 rounded-full <%= config[:color] %> <%= config[:animate] ? 'animate-pulse' : '' %> flex-shrink-0"></span>
|
|
18
|
+
<span class="inline-block w-2.5 h-2.5 rounded-full <%= config[:color] %> <%= config[:animate] ? 'animate-pulse' : '' %> flex-shrink-0"></span>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<%
|
|
2
2
|
# Workflow type badge with icon and color coding
|
|
3
|
-
# Usage: render "ruby_llm/agents/shared/workflow_type_badge", workflow_type: "
|
|
3
|
+
# Usage: render "ruby_llm/agents/shared/workflow_type_badge", workflow_type: "workflow"
|
|
4
4
|
# Options:
|
|
5
5
|
# size: :xs, :sm (default), :md
|
|
6
6
|
# show_label: true (default) or false for icon-only mode
|
|
@@ -9,40 +9,14 @@
|
|
|
9
9
|
size = local_assigns[:size] || :sm
|
|
10
10
|
show_label = local_assigns.fetch(:show_label, true)
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
when "parallel"
|
|
22
|
-
{
|
|
23
|
-
icon: "parallel",
|
|
24
|
-
label: "Parallel",
|
|
25
|
-
bg: "bg-cyan-100 dark:bg-cyan-900/50",
|
|
26
|
-
text: "text-cyan-700 dark:text-cyan-300",
|
|
27
|
-
icon_char: "⫿"
|
|
28
|
-
}
|
|
29
|
-
when "router"
|
|
30
|
-
{
|
|
31
|
-
icon: "router",
|
|
32
|
-
label: "Router",
|
|
33
|
-
bg: "bg-amber-100 dark:bg-amber-900/50",
|
|
34
|
-
text: "text-amber-700 dark:text-amber-300",
|
|
35
|
-
icon_char: "⌂"
|
|
36
|
-
}
|
|
37
|
-
else
|
|
38
|
-
{
|
|
39
|
-
icon: "workflow",
|
|
40
|
-
label: "Workflow",
|
|
41
|
-
bg: "bg-gray-100 dark:bg-gray-700",
|
|
42
|
-
text: "text-gray-700 dark:text-gray-300",
|
|
43
|
-
icon_char: "⚙"
|
|
44
|
-
}
|
|
45
|
-
end
|
|
12
|
+
# All workflows use unified DSL workflow style
|
|
13
|
+
config = {
|
|
14
|
+
icon: "workflow",
|
|
15
|
+
label: "Workflow",
|
|
16
|
+
bg: "bg-emerald-100 dark:bg-emerald-900/50",
|
|
17
|
+
text: "text-emerald-700 dark:text-emerald-300",
|
|
18
|
+
icon_char: "◈"
|
|
19
|
+
}
|
|
46
20
|
|
|
47
21
|
size_classes = case size
|
|
48
22
|
when :xs
|
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
|
|
8
8
|
</svg>
|
|
9
9
|
<div>
|
|
10
|
-
<
|
|
10
|
+
<div class="flex items-center gap-2">
|
|
11
|
+
<h1 class="text-2xl font-bold text-gray-900 dark:text-gray-100">System Configuration</h1>
|
|
12
|
+
<%= render "ruby_llm/agents/shared/doc_link" %>
|
|
13
|
+
</div>
|
|
11
14
|
<p class="text-sm text-gray-500 dark:text-gray-400">Settings configured in <code class="bg-gray-100 dark:bg-gray-700 px-1 rounded">config/initializers/ruby_llm_agents.rb</code></p>
|
|
12
15
|
</div>
|
|
13
16
|
</div>
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
<div class="mb-6">
|
|
2
|
-
<
|
|
2
|
+
<div class="flex items-center gap-2">
|
|
3
|
+
<h1 class="text-2xl font-bold text-gray-900 dark:text-gray-100">Tenants</h1>
|
|
4
|
+
<%= render "ruby_llm/agents/shared/doc_link" %>
|
|
5
|
+
</div>
|
|
3
6
|
<p class="text-gray-500 dark:text-gray-400 mt-1">Manage tenant budget configurations</p>
|
|
4
7
|
</div>
|
|
5
8
|
|
|
@@ -1,28 +1,20 @@
|
|
|
1
1
|
<%
|
|
2
|
-
# Step
|
|
2
|
+
# Step Performance Analytics
|
|
3
3
|
# Shows per-step metrics in a table format
|
|
4
4
|
workflow_type = local_assigns[:workflow_type]
|
|
5
5
|
step_stats = local_assigns[:step_stats] || []
|
|
6
6
|
route_distribution = local_assigns[:route_distribution] || {}
|
|
7
7
|
|
|
8
|
-
#
|
|
9
|
-
section_title =
|
|
10
|
-
|
|
11
|
-
when "parallel" then "Branch Performance"
|
|
12
|
-
when "router" then "Route Distribution"
|
|
13
|
-
else "Step Performance"
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
column_label = case workflow_type
|
|
17
|
-
when "pipeline" then "Step"
|
|
18
|
-
when "parallel" then "Branch"
|
|
19
|
-
when "router" then "Route"
|
|
20
|
-
else "Step"
|
|
21
|
-
end
|
|
8
|
+
# Unified labels
|
|
9
|
+
section_title = "Step Performance"
|
|
10
|
+
column_label = "Step"
|
|
22
11
|
|
|
23
12
|
# Calculate max values for bar charts
|
|
24
13
|
max_duration = step_stats.map { |s| s[:avg_duration_ms] }.compact.max || 1
|
|
25
14
|
max_cost = step_stats.map { |s| s[:avg_cost] }.compact.max || 0.001
|
|
15
|
+
|
|
16
|
+
# Check if any steps are parallel
|
|
17
|
+
has_parallel = step_stats.any? { |s| s[:name].to_s.include?("parallel") || workflow_type == "parallel" }
|
|
26
18
|
%>
|
|
27
19
|
|
|
28
20
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6 mb-6">
|