ruby_llm-agents 3.5.4 → 3.6.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 +4 -0
- data/app/controllers/ruby_llm/agents/dashboard_controller.rb +155 -10
- data/app/helpers/ruby_llm/agents/application_helper.rb +15 -1
- data/app/models/ruby_llm/agents/execution/replayable.rb +124 -0
- data/app/models/ruby_llm/agents/execution/scopes.rb +42 -1
- data/app/models/ruby_llm/agents/execution.rb +50 -1
- data/app/models/ruby_llm/agents/tenant/budgetable.rb +28 -4
- data/app/views/layouts/ruby_llm/agents/application.html.erb +41 -28
- data/app/views/ruby_llm/agents/agents/show.html.erb +16 -1
- data/app/views/ruby_llm/agents/dashboard/_top_tenants.html.erb +47 -0
- data/app/views/ruby_llm/agents/dashboard/index.html.erb +397 -100
- data/lib/generators/ruby_llm_agents/rename_agent_generator.rb +53 -0
- data/lib/generators/ruby_llm_agents/templates/rename_agent_migration.rb.tt +19 -0
- data/lib/ruby_llm/agents/agent_tool.rb +125 -0
- data/lib/ruby_llm/agents/audio/speaker.rb +5 -3
- data/lib/ruby_llm/agents/audio/speech_pricing.rb +63 -187
- data/lib/ruby_llm/agents/audio/transcriber.rb +5 -3
- data/lib/ruby_llm/agents/audio/transcription_pricing.rb +5 -7
- data/lib/ruby_llm/agents/base_agent.rb +144 -5
- data/lib/ruby_llm/agents/core/configuration.rb +178 -53
- data/lib/ruby_llm/agents/core/errors.rb +3 -77
- data/lib/ruby_llm/agents/core/instrumentation.rb +0 -17
- data/lib/ruby_llm/agents/core/version.rb +1 -1
- data/lib/ruby_llm/agents/dsl/base.rb +0 -8
- data/lib/ruby_llm/agents/dsl/queryable.rb +124 -0
- data/lib/ruby_llm/agents/dsl.rb +1 -0
- data/lib/ruby_llm/agents/image/concerns/image_operation_execution.rb +2 -1
- data/lib/ruby_llm/agents/image/generator/pricing.rb +75 -217
- data/lib/ruby_llm/agents/image/generator.rb +5 -3
- data/lib/ruby_llm/agents/infrastructure/attempt_tracker.rb +8 -0
- data/lib/ruby_llm/agents/infrastructure/circuit_breaker.rb +4 -2
- data/lib/ruby_llm/agents/pipeline/builder.rb +43 -0
- data/lib/ruby_llm/agents/pipeline/context.rb +11 -1
- data/lib/ruby_llm/agents/pipeline/executor.rb +1 -25
- data/lib/ruby_llm/agents/pipeline/middleware/budget.rb +26 -1
- data/lib/ruby_llm/agents/pipeline/middleware/cache.rb +18 -0
- data/lib/ruby_llm/agents/pipeline/middleware/instrumentation.rb +130 -3
- data/lib/ruby_llm/agents/pipeline/middleware/reliability.rb +29 -0
- data/lib/ruby_llm/agents/pipeline/middleware/tenant.rb +11 -4
- data/lib/ruby_llm/agents/pipeline.rb +0 -92
- data/lib/ruby_llm/agents/results/background_removal_result.rb +11 -1
- data/lib/ruby_llm/agents/results/base.rb +23 -1
- data/lib/ruby_llm/agents/results/embedding_result.rb +14 -1
- data/lib/ruby_llm/agents/results/image_analysis_result.rb +11 -1
- data/lib/ruby_llm/agents/results/image_edit_result.rb +11 -1
- data/lib/ruby_llm/agents/results/image_generation_result.rb +12 -3
- data/lib/ruby_llm/agents/results/image_pipeline_result.rb +11 -1
- data/lib/ruby_llm/agents/results/image_transform_result.rb +11 -1
- data/lib/ruby_llm/agents/results/image_upscale_result.rb +11 -1
- data/lib/ruby_llm/agents/results/image_variation_result.rb +11 -1
- data/lib/ruby_llm/agents/results/speech_result.rb +20 -1
- data/lib/ruby_llm/agents/results/transcription_result.rb +20 -1
- data/lib/ruby_llm/agents/text/embedder.rb +23 -18
- data/lib/ruby_llm/agents.rb +70 -5
- data/lib/tasks/ruby_llm_agents.rake +21 -0
- metadata +7 -6
- data/lib/ruby_llm/agents/infrastructure/reliability/breaker_manager.rb +0 -80
- data/lib/ruby_llm/agents/infrastructure/reliability/execution_constraints.rb +0 -69
- data/lib/ruby_llm/agents/infrastructure/reliability/executor.rb +0 -125
- data/lib/ruby_llm/agents/infrastructure/reliability/fallback_routing.rb +0 -72
- data/lib/ruby_llm/agents/infrastructure/reliability/retry_strategy.rb +0 -82
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
<title>RubyLLM Agents Dashboard</title>
|
|
9
9
|
|
|
10
|
+
<!-- Favicons -->
|
|
11
|
+
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96">
|
|
12
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
|
13
|
+
<link rel="shortcut icon" href="/favicon.ico">
|
|
14
|
+
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
|
15
|
+
<link rel="manifest" href="/site.webmanifest">
|
|
16
|
+
|
|
10
17
|
<!-- Prevent flash of wrong theme - must run before any rendering -->
|
|
11
18
|
<script>
|
|
12
19
|
(function() {
|
|
@@ -152,8 +159,9 @@
|
|
|
152
159
|
}
|
|
153
160
|
</script>
|
|
154
161
|
|
|
155
|
-
<!-- Highcharts for charts -->
|
|
156
|
-
<script src="https://code.highcharts.com/highcharts.js"
|
|
162
|
+
<!-- Highcharts for charts (primary CDN, fallback to jsDelivr) -->
|
|
163
|
+
<script src="https://code.highcharts.com/highcharts.js"
|
|
164
|
+
onerror="var s=document.createElement('script');s.src='https://cdn.jsdelivr.net/npm/highcharts@11.4.0/highcharts.min.js';s.onload=window.__initHighchartsDefaults;document.head.appendChild(s);"></script>
|
|
157
165
|
|
|
158
166
|
<!-- Chart color helpers + Highcharts defaults -->
|
|
159
167
|
<script>
|
|
@@ -164,32 +172,37 @@
|
|
|
164
172
|
return document.documentElement.classList.contains('dark')
|
|
165
173
|
? 'rgba(' + darkR + ',' + darkG + ',' + darkB + ',' + alpha + ')' : lightRgba;
|
|
166
174
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
175
|
+
window.__initHighchartsDefaults = function() {
|
|
176
|
+
if (typeof Highcharts === 'undefined') return;
|
|
177
|
+
Highcharts.setOptions({
|
|
178
|
+
accessibility: { enabled: false },
|
|
179
|
+
credits: { enabled: false },
|
|
180
|
+
chart: {
|
|
181
|
+
backgroundColor: 'transparent',
|
|
182
|
+
style: { fontFamily: 'ui-monospace, monospace' }
|
|
183
|
+
},
|
|
184
|
+
title: { text: null },
|
|
185
|
+
xAxis: {
|
|
186
|
+
labels: { style: { color: chartColor('#6B7280', '#928374') } },
|
|
187
|
+
lineColor: chartColorAlpha('rgba(107, 114, 128, 0.1)', 146, 131, 116, 0.1),
|
|
188
|
+
tickColor: chartColorAlpha('rgba(107, 114, 128, 0.1)', 146, 131, 116, 0.1)
|
|
189
|
+
},
|
|
190
|
+
yAxis: {
|
|
191
|
+
labels: { style: { color: chartColor('#6B7280', '#928374') } },
|
|
192
|
+
gridLineColor: chartColorAlpha('rgba(107, 114, 128, 0.1)', 146, 131, 116, 0.1)
|
|
193
|
+
},
|
|
194
|
+
legend: {
|
|
195
|
+
itemStyle: { color: chartColor('#6B7280', '#928374') },
|
|
196
|
+
itemHoverStyle: { color: chartColor('#9CA3AF', '#bdae93') }
|
|
197
|
+
},
|
|
198
|
+
tooltip: {
|
|
199
|
+
backgroundColor: chartColorAlpha('rgba(0, 0, 0, 0.85)', 40, 40, 40, 0.95),
|
|
200
|
+
borderColor: 'transparent',
|
|
201
|
+
style: { color: chartColor('#E5E7EB', '#ebdbb2'), fontFamily: 'ui-monospace, monospace' }
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
};
|
|
205
|
+
window.__initHighchartsDefaults();
|
|
193
206
|
</script>
|
|
194
207
|
|
|
195
208
|
<!-- Alpine.js -->
|
|
@@ -104,7 +104,9 @@
|
|
|
104
104
|
const successData = trendData.map(d => [new Date(d.date).getTime(), d.count - d.errors]);
|
|
105
105
|
const errorData = trendData.map(d => [new Date(d.date).getTime(), d.errors]);
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
function renderChart() {
|
|
108
|
+
window.__initHighchartsDefaults && window.__initHighchartsDefaults();
|
|
109
|
+
Highcharts.chart('agent-trend-chart', {
|
|
108
110
|
chart: { type: 'areaspline', backgroundColor: 'transparent', spacing: [5, 0, 0, 0] },
|
|
109
111
|
title: { text: null },
|
|
110
112
|
xAxis: {
|
|
@@ -159,6 +161,19 @@
|
|
|
159
161
|
}
|
|
160
162
|
]
|
|
161
163
|
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function waitForHighcharts(attempts) {
|
|
167
|
+
if (typeof Highcharts !== 'undefined') {
|
|
168
|
+
renderChart();
|
|
169
|
+
} else if (attempts > 0) {
|
|
170
|
+
setTimeout(function() { waitForHighcharts(attempts - 1); }, 100);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
document.readyState === 'loading'
|
|
175
|
+
? document.addEventListener('DOMContentLoaded', function() { waitForHighcharts(50); })
|
|
176
|
+
: waitForHighcharts(50);
|
|
162
177
|
})();
|
|
163
178
|
</script>
|
|
164
179
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<%# Top Tenants Widget - shows top tenants by monthly spend %>
|
|
2
|
+
<%# @param top_tenants [Array<Hash>, nil] Tenant data from controller %>
|
|
3
|
+
|
|
4
|
+
<% if top_tenants.present? %>
|
|
5
|
+
<div class="mt-8">
|
|
6
|
+
<div class="flex items-center gap-3 mb-3">
|
|
7
|
+
<span class="text-[10px] font-medium text-gray-400 dark:text-gray-600 uppercase tracking-widest font-mono">tenants</span>
|
|
8
|
+
<div class="flex-1 border-t border-gray-200 dark:border-gray-800"></div>
|
|
9
|
+
<%= link_to "all →", ruby_llm_agents.tenants_path, class: "text-[10px] font-mono text-gray-400 dark:text-gray-600 hover:text-gray-600 dark:hover:text-gray-400" %>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<div class="font-mono text-xs space-y-px">
|
|
13
|
+
<% top_tenants.each do |tenant| %>
|
|
14
|
+
<div 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"
|
|
15
|
+
onclick="window.location='<%= ruby_llm_agents.tenant_path(tenant[:id]) %>'">
|
|
16
|
+
<span class="w-32 truncate text-gray-900 dark:text-gray-200"><%= tenant[:name] %></span>
|
|
17
|
+
<span class="text-gray-500 dark:text-gray-400">$<%= number_with_precision(tenant[:monthly_spend], precision: 2) %></span>
|
|
18
|
+
<% if tenant[:monthly_limit] && tenant[:monthly_limit] > 0 %>
|
|
19
|
+
<%
|
|
20
|
+
pct = [tenant[:monthly_percentage], 100].min
|
|
21
|
+
bar_color = if pct >= 100 then "bg-red-500"
|
|
22
|
+
elsif pct >= 80 then "bg-yellow-500"
|
|
23
|
+
else "bg-blue-500"
|
|
24
|
+
end
|
|
25
|
+
%>
|
|
26
|
+
<div class="w-20 bg-gray-200 dark:bg-gray-800 rounded-full h-1 hidden sm:block">
|
|
27
|
+
<div class="<%= bar_color %> h-1 rounded-full transition-all" style="width: <%= pct %>%"></div>
|
|
28
|
+
</div>
|
|
29
|
+
<span class="w-10 text-right text-gray-400 dark:text-gray-600 hidden sm:inline"><%= tenant[:monthly_percentage] %>%</span>
|
|
30
|
+
<% else %>
|
|
31
|
+
<span class="text-gray-400 dark:text-gray-600 hidden sm:inline">(no limit)</span>
|
|
32
|
+
<% end %>
|
|
33
|
+
<%
|
|
34
|
+
enforcement = tenant[:enforcement].to_s
|
|
35
|
+
badge_class = case enforcement
|
|
36
|
+
when "hard" then "text-red-400 dark:text-red-500/70"
|
|
37
|
+
when "soft" then "text-yellow-400 dark:text-yellow-500/70"
|
|
38
|
+
else "text-gray-400 dark:text-gray-600"
|
|
39
|
+
end
|
|
40
|
+
%>
|
|
41
|
+
<span class="<%= badge_class %> hidden md:inline"><%= enforcement %></span>
|
|
42
|
+
<span class="ml-auto text-gray-400 dark:text-gray-600"><%= number_with_delimiter(tenant[:monthly_executions]) %><span class="text-gray-400 dark:text-gray-600">r</span></span>
|
|
43
|
+
</div>
|
|
44
|
+
<% end %>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
<% end %>
|