ruby_llm-agents 0.5.0 → 1.0.0.beta.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/README.md +189 -31
- data/app/controllers/ruby_llm/agents/agents_controller.rb +136 -16
- data/app/controllers/ruby_llm/agents/dashboard_controller.rb +29 -9
- data/app/controllers/ruby_llm/agents/workflows_controller.rb +355 -0
- data/app/helpers/ruby_llm/agents/application_helper.rb +25 -0
- data/app/models/ruby_llm/agents/execution.rb +3 -0
- data/app/models/ruby_llm/agents/tenant_budget.rb +58 -15
- data/app/services/ruby_llm/agents/agent_registry.rb +51 -12
- data/app/views/layouts/ruby_llm/agents/application.html.erb +2 -29
- data/app/views/ruby_llm/agents/agents/_agent.html.erb +13 -1
- data/app/views/ruby_llm/agents/agents/_config_agent.html.erb +235 -0
- data/app/views/ruby_llm/agents/agents/_config_embedder.html.erb +70 -0
- data/app/views/ruby_llm/agents/agents/_config_image_generator.html.erb +152 -0
- data/app/views/ruby_llm/agents/agents/_config_moderator.html.erb +63 -0
- data/app/views/ruby_llm/agents/agents/_config_speaker.html.erb +108 -0
- data/app/views/ruby_llm/agents/agents/_config_transcriber.html.erb +91 -0
- data/app/views/ruby_llm/agents/agents/_workflow.html.erb +1 -1
- data/app/views/ruby_llm/agents/agents/index.html.erb +74 -9
- data/app/views/ruby_llm/agents/agents/show.html.erb +18 -378
- data/app/views/ruby_llm/agents/dashboard/_agent_comparison.html.erb +269 -15
- data/app/views/ruby_llm/agents/executions/show.html.erb +16 -0
- data/app/views/ruby_llm/agents/shared/_agent_type_badge.html.erb +93 -0
- data/app/views/ruby_llm/agents/workflows/_step_performance.html.erb +236 -0
- data/app/views/ruby_llm/agents/workflows/_structure_parallel.html.erb +76 -0
- data/app/views/ruby_llm/agents/workflows/_structure_pipeline.html.erb +74 -0
- data/app/views/ruby_llm/agents/workflows/_structure_router.html.erb +108 -0
- data/app/views/ruby_llm/agents/workflows/show.html.erb +442 -0
- data/config/routes.rb +1 -0
- data/lib/generators/ruby_llm_agents/agent_generator.rb +56 -7
- data/lib/generators/ruby_llm_agents/background_remover_generator.rb +110 -0
- data/lib/generators/ruby_llm_agents/embedder_generator.rb +107 -0
- data/lib/generators/ruby_llm_agents/image_analyzer_generator.rb +115 -0
- data/lib/generators/ruby_llm_agents/image_editor_generator.rb +108 -0
- data/lib/generators/ruby_llm_agents/image_generator_generator.rb +116 -0
- data/lib/generators/ruby_llm_agents/image_pipeline_generator.rb +178 -0
- data/lib/generators/ruby_llm_agents/image_transformer_generator.rb +109 -0
- data/lib/generators/ruby_llm_agents/image_upscaler_generator.rb +103 -0
- data/lib/generators/ruby_llm_agents/image_variator_generator.rb +102 -0
- data/lib/generators/ruby_llm_agents/install_generator.rb +76 -4
- data/lib/generators/ruby_llm_agents/restructure_generator.rb +292 -0
- data/lib/generators/ruby_llm_agents/speaker_generator.rb +121 -0
- data/lib/generators/ruby_llm_agents/templates/add_execution_type_migration.rb.tt +8 -0
- data/lib/generators/ruby_llm_agents/templates/agent.rb.tt +99 -84
- data/lib/generators/ruby_llm_agents/templates/application_agent.rb.tt +42 -40
- data/lib/generators/ruby_llm_agents/templates/application_background_remover.rb.tt +26 -0
- data/lib/generators/ruby_llm_agents/templates/application_embedder.rb.tt +50 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_analyzer.rb.tt +26 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_editor.rb.tt +20 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_generator.rb.tt +38 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_pipeline.rb.tt +139 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_transformer.rb.tt +21 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_upscaler.rb.tt +20 -0
- data/lib/generators/ruby_llm_agents/templates/application_image_variator.rb.tt +20 -0
- data/lib/generators/ruby_llm_agents/templates/application_speaker.rb.tt +49 -0
- data/lib/generators/ruby_llm_agents/templates/application_transcriber.rb.tt +53 -0
- data/lib/generators/ruby_llm_agents/templates/background_remover.rb.tt +44 -0
- data/lib/generators/ruby_llm_agents/templates/embedder.rb.tt +41 -0
- data/lib/generators/ruby_llm_agents/templates/image_analyzer.rb.tt +45 -0
- data/lib/generators/ruby_llm_agents/templates/image_editor.rb.tt +35 -0
- data/lib/generators/ruby_llm_agents/templates/image_generator.rb.tt +47 -0
- data/lib/generators/ruby_llm_agents/templates/image_pipeline.rb.tt +50 -0
- data/lib/generators/ruby_llm_agents/templates/image_transformer.rb.tt +44 -0
- data/lib/generators/ruby_llm_agents/templates/image_upscaler.rb.tt +38 -0
- data/lib/generators/ruby_llm_agents/templates/image_variator.rb.tt +33 -0
- data/lib/generators/ruby_llm_agents/templates/skills/AGENTS.md.tt +228 -0
- data/lib/generators/ruby_llm_agents/templates/skills/BACKGROUND_REMOVERS.md.tt +131 -0
- data/lib/generators/ruby_llm_agents/templates/skills/EMBEDDERS.md.tt +255 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_ANALYZERS.md.tt +120 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_EDITORS.md.tt +102 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_GENERATORS.md.tt +282 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_PIPELINES.md.tt +228 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_TRANSFORMERS.md.tt +120 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_UPSCALERS.md.tt +110 -0
- data/lib/generators/ruby_llm_agents/templates/skills/IMAGE_VARIATORS.md.tt +120 -0
- data/lib/generators/ruby_llm_agents/templates/skills/SPEAKERS.md.tt +212 -0
- data/lib/generators/ruby_llm_agents/templates/skills/TOOLS.md.tt +227 -0
- data/lib/generators/ruby_llm_agents/templates/skills/TRANSCRIBERS.md.tt +251 -0
- data/lib/generators/ruby_llm_agents/templates/skills/WORKFLOWS.md.tt +300 -0
- data/lib/generators/ruby_llm_agents/templates/speaker.rb.tt +56 -0
- data/lib/generators/ruby_llm_agents/templates/transcriber.rb.tt +51 -0
- data/lib/generators/ruby_llm_agents/transcriber_generator.rb +107 -0
- data/lib/generators/ruby_llm_agents/upgrade_generator.rb +152 -1
- data/lib/ruby_llm/agents/audio/speaker.rb +553 -0
- data/lib/ruby_llm/agents/audio/transcriber.rb +669 -0
- data/lib/ruby_llm/agents/base_agent.rb +675 -0
- data/lib/ruby_llm/agents/core/base/moderation_dsl.rb +181 -0
- data/lib/ruby_llm/agents/core/base/moderation_execution.rb +274 -0
- data/lib/ruby_llm/agents/core/base.rb +135 -0
- data/lib/ruby_llm/agents/core/configuration.rb +981 -0
- data/lib/ruby_llm/agents/core/errors.rb +150 -0
- data/lib/ruby_llm/agents/{instrumentation.rb → core/instrumentation.rb} +22 -1
- data/lib/ruby_llm/agents/core/llm_tenant.rb +358 -0
- data/lib/ruby_llm/agents/{version.rb → core/version.rb} +1 -1
- data/lib/ruby_llm/agents/dsl/base.rb +110 -0
- data/lib/ruby_llm/agents/dsl/caching.rb +142 -0
- data/lib/ruby_llm/agents/dsl/reliability.rb +307 -0
- data/lib/ruby_llm/agents/dsl.rb +41 -0
- data/lib/ruby_llm/agents/image/analyzer/dsl.rb +130 -0
- data/lib/ruby_llm/agents/image/analyzer/execution.rb +402 -0
- data/lib/ruby_llm/agents/image/analyzer.rb +90 -0
- data/lib/ruby_llm/agents/image/background_remover/dsl.rb +154 -0
- data/lib/ruby_llm/agents/image/background_remover/execution.rb +240 -0
- data/lib/ruby_llm/agents/image/background_remover.rb +89 -0
- data/lib/ruby_llm/agents/image/concerns/image_operation_dsl.rb +91 -0
- data/lib/ruby_llm/agents/image/concerns/image_operation_execution.rb +165 -0
- data/lib/ruby_llm/agents/image/editor/dsl.rb +56 -0
- data/lib/ruby_llm/agents/image/editor/execution.rb +207 -0
- data/lib/ruby_llm/agents/image/editor.rb +92 -0
- data/lib/ruby_llm/agents/image/generator/active_storage_support.rb +127 -0
- data/lib/ruby_llm/agents/image/generator/content_policy.rb +95 -0
- data/lib/ruby_llm/agents/image/generator/pricing.rb +353 -0
- data/lib/ruby_llm/agents/image/generator/templates.rb +124 -0
- data/lib/ruby_llm/agents/image/generator.rb +455 -0
- data/lib/ruby_llm/agents/image/pipeline/dsl.rb +213 -0
- data/lib/ruby_llm/agents/image/pipeline/execution.rb +382 -0
- data/lib/ruby_llm/agents/image/pipeline.rb +97 -0
- data/lib/ruby_llm/agents/image/transformer/dsl.rb +148 -0
- data/lib/ruby_llm/agents/image/transformer/execution.rb +223 -0
- data/lib/ruby_llm/agents/image/transformer.rb +95 -0
- data/lib/ruby_llm/agents/image/upscaler/dsl.rb +83 -0
- data/lib/ruby_llm/agents/image/upscaler/execution.rb +219 -0
- data/lib/ruby_llm/agents/image/upscaler.rb +81 -0
- data/lib/ruby_llm/agents/image/variator/dsl.rb +62 -0
- data/lib/ruby_llm/agents/image/variator/execution.rb +189 -0
- data/lib/ruby_llm/agents/image/variator.rb +80 -0
- data/lib/ruby_llm/agents/{alert_manager.rb → infrastructure/alert_manager.rb} +17 -22
- data/lib/ruby_llm/agents/infrastructure/budget/budget_query.rb +145 -0
- data/lib/ruby_llm/agents/infrastructure/budget/config_resolver.rb +149 -0
- data/lib/ruby_llm/agents/infrastructure/budget/forecaster.rb +68 -0
- data/lib/ruby_llm/agents/infrastructure/budget/spend_recorder.rb +279 -0
- data/lib/ruby_llm/agents/infrastructure/budget_tracker.rb +275 -0
- data/lib/ruby_llm/agents/{execution_logger_job.rb → infrastructure/execution_logger_job.rb} +17 -1
- data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/executor.rb +2 -1
- data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/retry_strategy.rb +9 -3
- data/lib/ruby_llm/agents/{reliability.rb → infrastructure/reliability.rb} +11 -21
- data/lib/ruby_llm/agents/pipeline/builder.rb +215 -0
- data/lib/ruby_llm/agents/pipeline/context.rb +255 -0
- data/lib/ruby_llm/agents/pipeline/executor.rb +86 -0
- data/lib/ruby_llm/agents/pipeline/middleware/base.rb +124 -0
- data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +95 -0
- data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +171 -0
- data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +415 -0
- data/lib/ruby_llm/agents/pipeline/middleware/reliability.rb +276 -0
- data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +196 -0
- data/lib/ruby_llm/agents/pipeline.rb +68 -0
- data/lib/ruby_llm/agents/{engine.rb → rails/engine.rb} +79 -11
- data/lib/ruby_llm/agents/results/background_removal_result.rb +286 -0
- data/lib/ruby_llm/agents/{result.rb → results/base.rb} +73 -1
- data/lib/ruby_llm/agents/results/embedding_result.rb +243 -0
- data/lib/ruby_llm/agents/results/image_analysis_result.rb +314 -0
- data/lib/ruby_llm/agents/results/image_edit_result.rb +250 -0
- data/lib/ruby_llm/agents/results/image_generation_result.rb +346 -0
- data/lib/ruby_llm/agents/results/image_pipeline_result.rb +399 -0
- data/lib/ruby_llm/agents/results/image_transform_result.rb +251 -0
- data/lib/ruby_llm/agents/results/image_upscale_result.rb +255 -0
- data/lib/ruby_llm/agents/results/image_variation_result.rb +237 -0
- data/lib/ruby_llm/agents/results/moderation_result.rb +158 -0
- data/lib/ruby_llm/agents/results/speech_result.rb +338 -0
- data/lib/ruby_llm/agents/results/transcription_result.rb +408 -0
- data/lib/ruby_llm/agents/text/embedder.rb +444 -0
- data/lib/ruby_llm/agents/text/moderator.rb +237 -0
- data/lib/ruby_llm/agents/workflow/async.rb +220 -0
- data/lib/ruby_llm/agents/workflow/async_executor.rb +156 -0
- data/lib/ruby_llm/agents/{workflow.rb → workflow/orchestrator.rb} +6 -5
- data/lib/ruby_llm/agents/workflow/parallel.rb +34 -17
- data/lib/ruby_llm/agents/workflow/thread_pool.rb +185 -0
- data/lib/ruby_llm/agents.rb +86 -20
- metadata +172 -34
- data/lib/ruby_llm/agents/base/caching.rb +0 -40
- data/lib/ruby_llm/agents/base/cost_calculation.rb +0 -105
- data/lib/ruby_llm/agents/base/dsl.rb +0 -324
- data/lib/ruby_llm/agents/base/execution.rb +0 -366
- data/lib/ruby_llm/agents/base/reliability_dsl.rb +0 -82
- data/lib/ruby_llm/agents/base/reliability_execution.rb +0 -136
- data/lib/ruby_llm/agents/base/response_building.rb +0 -86
- data/lib/ruby_llm/agents/base/tool_tracking.rb +0 -57
- data/lib/ruby_llm/agents/base.rb +0 -210
- data/lib/ruby_llm/agents/budget_tracker.rb +0 -733
- data/lib/ruby_llm/agents/configuration.rb +0 -394
- /data/lib/ruby_llm/agents/{deprecations.rb → core/deprecations.rb} +0 -0
- /data/lib/ruby_llm/agents/{inflections.rb → core/inflections.rb} +0 -0
- /data/lib/ruby_llm/agents/{resolved_config.rb → core/resolved_config.rb} +0 -0
- /data/lib/ruby_llm/agents/{attempt_tracker.rb → infrastructure/attempt_tracker.rb} +0 -0
- /data/lib/ruby_llm/agents/{cache_helper.rb → infrastructure/cache_helper.rb} +0 -0
- /data/lib/ruby_llm/agents/{circuit_breaker.rb → infrastructure/circuit_breaker.rb} +0 -0
- /data/lib/ruby_llm/agents/{redactor.rb → infrastructure/redactor.rb} +0 -0
- /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/breaker_manager.rb +0 -0
- /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/execution_constraints.rb +0 -0
- /data/lib/ruby_llm/agents/{reliability → infrastructure/reliability}/fallback_routing.rb +0 -0
|
@@ -1,26 +1,60 @@
|
|
|
1
1
|
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-100 dark:border-gray-700 h-full" x-data="{ activeTab: 'agents' }">
|
|
2
2
|
<div class="px-4 py-3 border-b border-gray-100 dark:border-gray-700">
|
|
3
|
-
<div class="flex items-center justify-between">
|
|
3
|
+
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2">
|
|
4
4
|
<h3 class="text-base font-semibold text-gray-900 dark:text-gray-100">Performance</h3>
|
|
5
|
-
<!-- Tab Buttons -->
|
|
6
|
-
<div class="
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
<!-- Scrollable Tab Buttons -->
|
|
6
|
+
<div class="overflow-x-auto -mx-4 px-4 sm:mx-0 sm:px-0">
|
|
7
|
+
<div class="flex space-x-1 bg-gray-100 dark:bg-gray-700 rounded-lg p-0.5 min-w-max">
|
|
8
|
+
<button type="button" @click="activeTab = 'agents'"
|
|
9
|
+
:class="activeTab === 'agents' ? 'bg-white dark:bg-gray-600 shadow-sm' : 'hover:bg-gray-50 dark:hover:bg-gray-600'"
|
|
10
|
+
class="px-2 py-1 text-xs font-medium rounded-md transition-colors text-gray-700 dark:text-gray-200 whitespace-nowrap">
|
|
11
|
+
<span class="hidden sm:inline">Agents</span>
|
|
12
|
+
<span class="sm:hidden">🤖</span>
|
|
13
|
+
</button>
|
|
14
|
+
<button type="button" @click="activeTab = 'embedders'"
|
|
15
|
+
:class="activeTab === 'embedders' ? 'bg-white dark:bg-gray-600 shadow-sm' : 'hover:bg-gray-50 dark:hover:bg-gray-600'"
|
|
16
|
+
class="px-2 py-1 text-xs font-medium rounded-md transition-colors text-gray-700 dark:text-gray-200 whitespace-nowrap">
|
|
17
|
+
<span class="hidden sm:inline">Embedders</span>
|
|
18
|
+
<span class="sm:hidden">📊</span>
|
|
19
|
+
</button>
|
|
20
|
+
<button type="button" @click="activeTab = 'transcribers'"
|
|
21
|
+
:class="activeTab === 'transcribers' ? 'bg-white dark:bg-gray-600 shadow-sm' : 'hover:bg-gray-50 dark:hover:bg-gray-600'"
|
|
22
|
+
class="px-2 py-1 text-xs font-medium rounded-md transition-colors text-gray-700 dark:text-gray-200 whitespace-nowrap">
|
|
23
|
+
<span class="hidden sm:inline">Transcribers</span>
|
|
24
|
+
<span class="sm:hidden">🎤</span>
|
|
25
|
+
</button>
|
|
26
|
+
<button type="button" @click="activeTab = 'speakers'"
|
|
27
|
+
:class="activeTab === 'speakers' ? 'bg-white dark:bg-gray-600 shadow-sm' : 'hover:bg-gray-50 dark:hover:bg-gray-600'"
|
|
28
|
+
class="px-2 py-1 text-xs font-medium rounded-md transition-colors text-gray-700 dark:text-gray-200 whitespace-nowrap">
|
|
29
|
+
<span class="hidden sm:inline">Speakers</span>
|
|
30
|
+
<span class="sm:hidden">🔊</span>
|
|
31
|
+
</button>
|
|
32
|
+
<button type="button" @click="activeTab = 'image_generators'"
|
|
33
|
+
:class="activeTab === 'image_generators' ? 'bg-white dark:bg-gray-600 shadow-sm' : 'hover:bg-gray-50 dark:hover:bg-gray-600'"
|
|
34
|
+
class="px-2 py-1 text-xs font-medium rounded-md transition-colors text-gray-700 dark:text-gray-200 whitespace-nowrap">
|
|
35
|
+
<span class="hidden sm:inline">Image Gen</span>
|
|
36
|
+
<span class="sm:hidden">🎨</span>
|
|
37
|
+
</button>
|
|
38
|
+
<button type="button" @click="activeTab = 'moderators'"
|
|
39
|
+
:class="activeTab === 'moderators' ? 'bg-white dark:bg-gray-600 shadow-sm' : 'hover:bg-gray-50 dark:hover:bg-gray-600'"
|
|
40
|
+
class="px-2 py-1 text-xs font-medium rounded-md transition-colors text-gray-700 dark:text-gray-200 whitespace-nowrap">
|
|
41
|
+
<span class="hidden sm:inline">Moderators</span>
|
|
42
|
+
<span class="sm:hidden">🛡️</span>
|
|
43
|
+
</button>
|
|
44
|
+
<button type="button" @click="activeTab = 'workflows'"
|
|
45
|
+
:class="activeTab === 'workflows' ? 'bg-white dark:bg-gray-600 shadow-sm' : 'hover:bg-gray-50 dark:hover:bg-gray-600'"
|
|
46
|
+
class="px-2 py-1 text-xs font-medium rounded-md transition-colors text-gray-700 dark:text-gray-200 whitespace-nowrap">
|
|
47
|
+
<span class="hidden sm:inline">Workflows</span>
|
|
48
|
+
<span class="sm:hidden">⚙️</span>
|
|
49
|
+
</button>
|
|
50
|
+
</div>
|
|
17
51
|
</div>
|
|
18
52
|
</div>
|
|
19
53
|
</div>
|
|
20
54
|
|
|
21
55
|
<!-- Agents Tab -->
|
|
22
56
|
<div x-show="activeTab === 'agents'">
|
|
23
|
-
<% if agent_stats&.any? %>
|
|
57
|
+
<% if @agent_stats&.any? %>
|
|
24
58
|
<div class="overflow-x-auto">
|
|
25
59
|
<table class="w-full text-sm">
|
|
26
60
|
<thead>
|
|
@@ -32,7 +66,7 @@
|
|
|
32
66
|
</tr>
|
|
33
67
|
</thead>
|
|
34
68
|
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
|
35
|
-
<% agent_stats.first(5).each do |agent| %>
|
|
69
|
+
<% @agent_stats.first(5).each do |agent| %>
|
|
36
70
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700/50">
|
|
37
71
|
<td class="px-4 py-2">
|
|
38
72
|
<span class="text-sm font-medium text-gray-900 dark:text-gray-100 truncate block max-w-[120px]" title="<%= agent[:agent_type] %>">
|
|
@@ -62,6 +96,226 @@
|
|
|
62
96
|
<% end %>
|
|
63
97
|
</div>
|
|
64
98
|
|
|
99
|
+
<!-- Embedders Tab -->
|
|
100
|
+
<div x-show="activeTab === 'embedders'" x-cloak>
|
|
101
|
+
<% if @embedder_stats&.any? %>
|
|
102
|
+
<div class="overflow-x-auto">
|
|
103
|
+
<table class="w-full text-sm">
|
|
104
|
+
<thead>
|
|
105
|
+
<tr class="text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
|
106
|
+
<th class="px-4 py-2">Embedder</th>
|
|
107
|
+
<th class="px-4 py-2 text-right">Runs</th>
|
|
108
|
+
<th class="px-4 py-2 text-right">Cost</th>
|
|
109
|
+
<th class="px-4 py-2 text-right">Success</th>
|
|
110
|
+
</tr>
|
|
111
|
+
</thead>
|
|
112
|
+
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
|
113
|
+
<% @embedder_stats.first(5).each do |embedder| %>
|
|
114
|
+
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700/50">
|
|
115
|
+
<td class="px-4 py-2">
|
|
116
|
+
<span class="text-sm font-medium text-gray-900 dark:text-gray-100 truncate block max-w-[120px]" title="<%= embedder[:agent_type] %>">
|
|
117
|
+
<%= embedder[:agent_type].to_s.demodulize %>
|
|
118
|
+
</span>
|
|
119
|
+
</td>
|
|
120
|
+
<td class="px-4 py-2 text-right text-gray-600 dark:text-gray-300">
|
|
121
|
+
<%= number_with_delimiter(embedder[:executions]) %>
|
|
122
|
+
</td>
|
|
123
|
+
<td class="px-4 py-2 text-right text-gray-600 dark:text-gray-300">
|
|
124
|
+
$<%= number_with_precision(embedder[:total_cost], precision: 2) %>
|
|
125
|
+
</td>
|
|
126
|
+
<td class="px-4 py-2 text-right">
|
|
127
|
+
<span class="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium <%= embedder[:success_rate] >= 95 ? 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-300' : embedder[:success_rate] >= 80 ? 'bg-yellow-100 dark:bg-yellow-900 text-yellow-700 dark:text-yellow-300' : 'bg-red-100 dark:bg-red-900 text-red-700 dark:text-red-300' %>">
|
|
128
|
+
<%= embedder[:success_rate].round %>%
|
|
129
|
+
</span>
|
|
130
|
+
</td>
|
|
131
|
+
</tr>
|
|
132
|
+
<% end %>
|
|
133
|
+
</tbody>
|
|
134
|
+
</table>
|
|
135
|
+
</div>
|
|
136
|
+
<% else %>
|
|
137
|
+
<div class="px-4 py-8 text-center text-gray-500 dark:text-gray-400">
|
|
138
|
+
<p class="text-sm">No embedder data yet</p>
|
|
139
|
+
</div>
|
|
140
|
+
<% end %>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<!-- Transcribers Tab -->
|
|
144
|
+
<div x-show="activeTab === 'transcribers'" x-cloak>
|
|
145
|
+
<% if @transcriber_stats&.any? %>
|
|
146
|
+
<div class="overflow-x-auto">
|
|
147
|
+
<table class="w-full text-sm">
|
|
148
|
+
<thead>
|
|
149
|
+
<tr class="text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
|
150
|
+
<th class="px-4 py-2">Transcriber</th>
|
|
151
|
+
<th class="px-4 py-2 text-right">Runs</th>
|
|
152
|
+
<th class="px-4 py-2 text-right">Cost</th>
|
|
153
|
+
<th class="px-4 py-2 text-right">Success</th>
|
|
154
|
+
</tr>
|
|
155
|
+
</thead>
|
|
156
|
+
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
|
157
|
+
<% @transcriber_stats.first(5).each do |transcriber| %>
|
|
158
|
+
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700/50">
|
|
159
|
+
<td class="px-4 py-2">
|
|
160
|
+
<span class="text-sm font-medium text-gray-900 dark:text-gray-100 truncate block max-w-[120px]" title="<%= transcriber[:agent_type] %>">
|
|
161
|
+
<%= transcriber[:agent_type].to_s.demodulize %>
|
|
162
|
+
</span>
|
|
163
|
+
</td>
|
|
164
|
+
<td class="px-4 py-2 text-right text-gray-600 dark:text-gray-300">
|
|
165
|
+
<%= number_with_delimiter(transcriber[:executions]) %>
|
|
166
|
+
</td>
|
|
167
|
+
<td class="px-4 py-2 text-right text-gray-600 dark:text-gray-300">
|
|
168
|
+
$<%= number_with_precision(transcriber[:total_cost], precision: 2) %>
|
|
169
|
+
</td>
|
|
170
|
+
<td class="px-4 py-2 text-right">
|
|
171
|
+
<span class="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium <%= transcriber[:success_rate] >= 95 ? 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-300' : transcriber[:success_rate] >= 80 ? 'bg-yellow-100 dark:bg-yellow-900 text-yellow-700 dark:text-yellow-300' : 'bg-red-100 dark:bg-red-900 text-red-700 dark:text-red-300' %>">
|
|
172
|
+
<%= transcriber[:success_rate].round %>%
|
|
173
|
+
</span>
|
|
174
|
+
</td>
|
|
175
|
+
</tr>
|
|
176
|
+
<% end %>
|
|
177
|
+
</tbody>
|
|
178
|
+
</table>
|
|
179
|
+
</div>
|
|
180
|
+
<% else %>
|
|
181
|
+
<div class="px-4 py-8 text-center text-gray-500 dark:text-gray-400">
|
|
182
|
+
<p class="text-sm">No transcriber data yet</p>
|
|
183
|
+
</div>
|
|
184
|
+
<% end %>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<!-- Speakers Tab -->
|
|
188
|
+
<div x-show="activeTab === 'speakers'" x-cloak>
|
|
189
|
+
<% if @speaker_stats&.any? %>
|
|
190
|
+
<div class="overflow-x-auto">
|
|
191
|
+
<table class="w-full text-sm">
|
|
192
|
+
<thead>
|
|
193
|
+
<tr class="text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
|
194
|
+
<th class="px-4 py-2">Speaker</th>
|
|
195
|
+
<th class="px-4 py-2 text-right">Runs</th>
|
|
196
|
+
<th class="px-4 py-2 text-right">Cost</th>
|
|
197
|
+
<th class="px-4 py-2 text-right">Success</th>
|
|
198
|
+
</tr>
|
|
199
|
+
</thead>
|
|
200
|
+
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
|
201
|
+
<% @speaker_stats.first(5).each do |speaker| %>
|
|
202
|
+
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700/50">
|
|
203
|
+
<td class="px-4 py-2">
|
|
204
|
+
<span class="text-sm font-medium text-gray-900 dark:text-gray-100 truncate block max-w-[120px]" title="<%= speaker[:agent_type] %>">
|
|
205
|
+
<%= speaker[:agent_type].to_s.demodulize %>
|
|
206
|
+
</span>
|
|
207
|
+
</td>
|
|
208
|
+
<td class="px-4 py-2 text-right text-gray-600 dark:text-gray-300">
|
|
209
|
+
<%= number_with_delimiter(speaker[:executions]) %>
|
|
210
|
+
</td>
|
|
211
|
+
<td class="px-4 py-2 text-right text-gray-600 dark:text-gray-300">
|
|
212
|
+
$<%= number_with_precision(speaker[:total_cost], precision: 2) %>
|
|
213
|
+
</td>
|
|
214
|
+
<td class="px-4 py-2 text-right">
|
|
215
|
+
<span class="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium <%= speaker[:success_rate] >= 95 ? 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-300' : speaker[:success_rate] >= 80 ? 'bg-yellow-100 dark:bg-yellow-900 text-yellow-700 dark:text-yellow-300' : 'bg-red-100 dark:bg-red-900 text-red-700 dark:text-red-300' %>">
|
|
216
|
+
<%= speaker[:success_rate].round %>%
|
|
217
|
+
</span>
|
|
218
|
+
</td>
|
|
219
|
+
</tr>
|
|
220
|
+
<% end %>
|
|
221
|
+
</tbody>
|
|
222
|
+
</table>
|
|
223
|
+
</div>
|
|
224
|
+
<% else %>
|
|
225
|
+
<div class="px-4 py-8 text-center text-gray-500 dark:text-gray-400">
|
|
226
|
+
<p class="text-sm">No speaker data yet</p>
|
|
227
|
+
</div>
|
|
228
|
+
<% end %>
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
<!-- Image Generators Tab -->
|
|
232
|
+
<div x-show="activeTab === 'image_generators'" x-cloak>
|
|
233
|
+
<% if @image_generator_stats&.any? %>
|
|
234
|
+
<div class="overflow-x-auto">
|
|
235
|
+
<table class="w-full text-sm">
|
|
236
|
+
<thead>
|
|
237
|
+
<tr class="text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
|
238
|
+
<th class="px-4 py-2">Image Generator</th>
|
|
239
|
+
<th class="px-4 py-2 text-right">Runs</th>
|
|
240
|
+
<th class="px-4 py-2 text-right">Cost</th>
|
|
241
|
+
<th class="px-4 py-2 text-right">Success</th>
|
|
242
|
+
</tr>
|
|
243
|
+
</thead>
|
|
244
|
+
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
|
245
|
+
<% @image_generator_stats.first(5).each do |generator| %>
|
|
246
|
+
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700/50">
|
|
247
|
+
<td class="px-4 py-2">
|
|
248
|
+
<span class="text-sm font-medium text-gray-900 dark:text-gray-100 truncate block max-w-[120px]" title="<%= generator[:agent_type] %>">
|
|
249
|
+
<%= generator[:agent_type].to_s.demodulize %>
|
|
250
|
+
</span>
|
|
251
|
+
</td>
|
|
252
|
+
<td class="px-4 py-2 text-right text-gray-600 dark:text-gray-300">
|
|
253
|
+
<%= number_with_delimiter(generator[:executions]) %>
|
|
254
|
+
</td>
|
|
255
|
+
<td class="px-4 py-2 text-right text-gray-600 dark:text-gray-300">
|
|
256
|
+
$<%= number_with_precision(generator[:total_cost], precision: 2) %>
|
|
257
|
+
</td>
|
|
258
|
+
<td class="px-4 py-2 text-right">
|
|
259
|
+
<span class="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium <%= generator[:success_rate] >= 95 ? 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-300' : generator[:success_rate] >= 80 ? 'bg-yellow-100 dark:bg-yellow-900 text-yellow-700 dark:text-yellow-300' : 'bg-red-100 dark:bg-red-900 text-red-700 dark:text-red-300' %>">
|
|
260
|
+
<%= generator[:success_rate].round %>%
|
|
261
|
+
</span>
|
|
262
|
+
</td>
|
|
263
|
+
</tr>
|
|
264
|
+
<% end %>
|
|
265
|
+
</tbody>
|
|
266
|
+
</table>
|
|
267
|
+
</div>
|
|
268
|
+
<% else %>
|
|
269
|
+
<div class="px-4 py-8 text-center text-gray-500 dark:text-gray-400">
|
|
270
|
+
<p class="text-sm">No image generator data yet</p>
|
|
271
|
+
</div>
|
|
272
|
+
<% end %>
|
|
273
|
+
</div>
|
|
274
|
+
|
|
275
|
+
<!-- Moderators Tab -->
|
|
276
|
+
<div x-show="activeTab === 'moderators'" x-cloak>
|
|
277
|
+
<% if @moderator_stats&.any? %>
|
|
278
|
+
<div class="overflow-x-auto">
|
|
279
|
+
<table class="w-full text-sm">
|
|
280
|
+
<thead>
|
|
281
|
+
<tr class="text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
|
282
|
+
<th class="px-4 py-2">Moderator</th>
|
|
283
|
+
<th class="px-4 py-2 text-right">Runs</th>
|
|
284
|
+
<th class="px-4 py-2 text-right">Cost</th>
|
|
285
|
+
<th class="px-4 py-2 text-right">Success</th>
|
|
286
|
+
</tr>
|
|
287
|
+
</thead>
|
|
288
|
+
<tbody class="divide-y divide-gray-100 dark:divide-gray-700">
|
|
289
|
+
<% @moderator_stats.first(5).each do |moderator| %>
|
|
290
|
+
<tr class="hover:bg-gray-50 dark:hover:bg-gray-700/50">
|
|
291
|
+
<td class="px-4 py-2">
|
|
292
|
+
<span class="text-sm font-medium text-gray-900 dark:text-gray-100 truncate block max-w-[120px]" title="<%= moderator[:agent_type] %>">
|
|
293
|
+
<%= moderator[:agent_type].to_s.demodulize %>
|
|
294
|
+
</span>
|
|
295
|
+
</td>
|
|
296
|
+
<td class="px-4 py-2 text-right text-gray-600 dark:text-gray-300">
|
|
297
|
+
<%= number_with_delimiter(moderator[:executions]) %>
|
|
298
|
+
</td>
|
|
299
|
+
<td class="px-4 py-2 text-right text-gray-600 dark:text-gray-300">
|
|
300
|
+
$<%= number_with_precision(moderator[:total_cost], precision: 2) %>
|
|
301
|
+
</td>
|
|
302
|
+
<td class="px-4 py-2 text-right">
|
|
303
|
+
<span class="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium <%= moderator[:success_rate] >= 95 ? 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-300' : moderator[:success_rate] >= 80 ? 'bg-yellow-100 dark:bg-yellow-900 text-yellow-700 dark:text-yellow-300' : 'bg-red-100 dark:bg-red-900 text-red-700 dark:text-red-300' %>">
|
|
304
|
+
<%= moderator[:success_rate].round %>%
|
|
305
|
+
</span>
|
|
306
|
+
</td>
|
|
307
|
+
</tr>
|
|
308
|
+
<% end %>
|
|
309
|
+
</tbody>
|
|
310
|
+
</table>
|
|
311
|
+
</div>
|
|
312
|
+
<% else %>
|
|
313
|
+
<div class="px-4 py-8 text-center text-gray-500 dark:text-gray-400">
|
|
314
|
+
<p class="text-sm">No moderator data yet</p>
|
|
315
|
+
</div>
|
|
316
|
+
<% end %>
|
|
317
|
+
</div>
|
|
318
|
+
|
|
65
319
|
<!-- Workflows Tab -->
|
|
66
320
|
<div x-show="activeTab === 'workflows'" x-cloak>
|
|
67
321
|
<% if @workflow_stats&.any? %>
|
|
@@ -512,6 +512,22 @@
|
|
|
512
512
|
Retryable
|
|
513
513
|
</span>
|
|
514
514
|
<% end %>
|
|
515
|
+
<button
|
|
516
|
+
type="button"
|
|
517
|
+
data-copy-json="<%= Base64.strict_encode64({
|
|
518
|
+
error_class: @execution.error_class,
|
|
519
|
+
error_message: @execution.error_message
|
|
520
|
+
}.to_json) %>"
|
|
521
|
+
class="copy-json-btn inline-flex items-center gap-1.5 px-2.5 py-1.5 text-xs font-medium text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md transition-colors"
|
|
522
|
+
>
|
|
523
|
+
<svg class="w-4 h-4 copy-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
524
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/>
|
|
525
|
+
</svg>
|
|
526
|
+
<svg class="w-4 h-4 check-icon hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
527
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
|
528
|
+
</svg>
|
|
529
|
+
<span>Copy</span>
|
|
530
|
+
</button>
|
|
515
531
|
</div>
|
|
516
532
|
</div>
|
|
517
533
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<%
|
|
2
|
+
# Agent type badge with icon and color coding
|
|
3
|
+
# Usage: render "ruby_llm/agents/shared/agent_type_badge", agent_type: "agent"
|
|
4
|
+
# Options:
|
|
5
|
+
# size: :xs, :sm (default), :md
|
|
6
|
+
# show_label: true (default) or false for icon-only mode
|
|
7
|
+
|
|
8
|
+
agent_type = local_assigns[:agent_type]
|
|
9
|
+
size = local_assigns[:size] || :sm
|
|
10
|
+
show_label = local_assigns.fetch(:show_label, true)
|
|
11
|
+
|
|
12
|
+
config = case agent_type.to_s
|
|
13
|
+
when "agent"
|
|
14
|
+
{
|
|
15
|
+
icon: "robot",
|
|
16
|
+
label: "Agent",
|
|
17
|
+
bg: "bg-blue-100 dark:bg-blue-900/50",
|
|
18
|
+
text: "text-blue-700 dark:text-blue-300",
|
|
19
|
+
icon_char: "🤖"
|
|
20
|
+
}
|
|
21
|
+
when "embedder"
|
|
22
|
+
{
|
|
23
|
+
icon: "chart",
|
|
24
|
+
label: "Embedder",
|
|
25
|
+
bg: "bg-purple-100 dark:bg-purple-900/50",
|
|
26
|
+
text: "text-purple-700 dark:text-purple-300",
|
|
27
|
+
icon_char: "📊"
|
|
28
|
+
}
|
|
29
|
+
when "transcriber"
|
|
30
|
+
{
|
|
31
|
+
icon: "mic",
|
|
32
|
+
label: "Transcriber",
|
|
33
|
+
bg: "bg-green-100 dark:bg-green-900/50",
|
|
34
|
+
text: "text-green-700 dark:text-green-300",
|
|
35
|
+
icon_char: "🎤"
|
|
36
|
+
}
|
|
37
|
+
when "speaker"
|
|
38
|
+
{
|
|
39
|
+
icon: "speaker",
|
|
40
|
+
label: "Speaker",
|
|
41
|
+
bg: "bg-orange-100 dark:bg-orange-900/50",
|
|
42
|
+
text: "text-orange-700 dark:text-orange-300",
|
|
43
|
+
icon_char: "🔊"
|
|
44
|
+
}
|
|
45
|
+
when "image_generator"
|
|
46
|
+
{
|
|
47
|
+
icon: "palette",
|
|
48
|
+
label: "Image Gen",
|
|
49
|
+
bg: "bg-pink-100 dark:bg-pink-900/50",
|
|
50
|
+
text: "text-pink-700 dark:text-pink-300",
|
|
51
|
+
icon_char: "🎨"
|
|
52
|
+
}
|
|
53
|
+
when "moderator"
|
|
54
|
+
{
|
|
55
|
+
icon: "shield",
|
|
56
|
+
label: "Moderator",
|
|
57
|
+
bg: "bg-red-100 dark:bg-red-900/50",
|
|
58
|
+
text: "text-red-700 dark:text-red-300",
|
|
59
|
+
icon_char: "🛡️"
|
|
60
|
+
}
|
|
61
|
+
when "workflow"
|
|
62
|
+
{
|
|
63
|
+
icon: "gear",
|
|
64
|
+
label: "Workflow",
|
|
65
|
+
bg: "bg-indigo-100 dark:bg-indigo-900/50",
|
|
66
|
+
text: "text-indigo-700 dark:text-indigo-300",
|
|
67
|
+
icon_char: "⚙️"
|
|
68
|
+
}
|
|
69
|
+
else
|
|
70
|
+
{
|
|
71
|
+
icon: "question",
|
|
72
|
+
label: "Unknown",
|
|
73
|
+
bg: "bg-gray-100 dark:bg-gray-700",
|
|
74
|
+
text: "text-gray-700 dark:text-gray-300",
|
|
75
|
+
icon_char: "?"
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
size_classes = case size
|
|
80
|
+
when :xs
|
|
81
|
+
{ badge: "px-1.5 py-0.5", icon: "text-[10px]", text: "text-[10px]" }
|
|
82
|
+
when :md
|
|
83
|
+
{ badge: "px-2.5 py-1", icon: "text-sm", text: "text-sm" }
|
|
84
|
+
else # :sm
|
|
85
|
+
{ badge: "px-2 py-0.5", icon: "text-xs", text: "text-xs" }
|
|
86
|
+
end
|
|
87
|
+
%>
|
|
88
|
+
<span class="inline-flex items-center gap-1 rounded-md font-medium <%= config[:bg] %> <%= config[:text] %> <%= size_classes[:badge] %>">
|
|
89
|
+
<span class="<%= size_classes[:icon] %>" aria-hidden="true"><%= config[:icon_char] %></span>
|
|
90
|
+
<% if show_label %>
|
|
91
|
+
<span class="<%= size_classes[:text] %>"><%= config[:label] %></span>
|
|
92
|
+
<% end %>
|
|
93
|
+
</span>
|