ruby_llm-agents 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfe880c683e626e6511c309e381415b5d0095b94c68931dbb872b8f59b89044a
4
- data.tar.gz: 309d1cdbac10803e4d362ab851a7e676e4ddb84c0d58a27d35daba474b1061b1
3
+ metadata.gz: f41d0d0f2a52571d96d877a6d3261083a5183a766ca2a67bd69a216d9dd2d9bb
4
+ data.tar.gz: 01accbd04fcb000e10ccc56f7dedb72f757f854eeb719eaaf93dab5438e7e46e
5
5
  SHA512:
6
- metadata.gz: 4d19cd8d27c7174da93085cffa58bd1a00539daa9aef5f00541fd3acf6d441a37e951db89dc41eaa23d1a6e9916fe23325ed87941ad0b76e5574268d0c4006f0
7
- data.tar.gz: 26fcbeb5a671dd014dc0f74cf04da2b8b993d61a463edc6af5cf371a726bd398713338b8f9ba3e2257acba6ccfc53280e1ca4ea36186ff7d8dabc317a976b27e
6
+ metadata.gz: 131def9da995060fe2c4b9930ce6c82c8eb1e8c391905bb9ddac4a80503c585bcca2123ce5da6baf05f7fc78cba5ceed6470238a81ff7cd1e3fc693993a599c0
7
+ data.tar.gz: 3becaadc1a1bb9619e9eae464fed9f6e2de179239748386a405f88f50066d2fff610696b582ab4b292d66036d0620a60bddc5e781e6befe6a0d095216a7566f0
@@ -7,8 +7,25 @@
7
7
 
8
8
  <title>RubyLLM Agents Dashboard</title>
9
9
 
10
+ <!-- Prevent flash of wrong theme - must run before any rendering -->
11
+ <script>
12
+ (function() {
13
+ const preference = localStorage.getItem('ruby_llm_agents_theme') || 'auto';
14
+ const isDark = preference === 'dark' ||
15
+ (preference === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches);
16
+ if (isDark) {
17
+ document.documentElement.classList.add('dark');
18
+ }
19
+ })();
20
+ </script>
21
+
10
22
  <!-- Tailwind CSS via CDN -->
11
23
  <script src="https://cdn.tailwindcss.com"></script>
24
+ <script>
25
+ tailwind.config = {
26
+ darkMode: 'class'
27
+ }
28
+ </script>
12
29
 
13
30
  <!-- Chartkick for charts -->
14
31
  <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0"></script>
@@ -122,6 +139,49 @@
122
139
  }
123
140
  });
124
141
 
142
+ // Theme Controller - handles dark mode switching
143
+ Stimulus.application.register("theme", class extends Stimulus.Controller {
144
+ static targets = ["select"]
145
+
146
+ connect() {
147
+ this.mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
148
+ this.applyTheme(this.getPreference())
149
+ this.boundHandleSystemChange = this.handleSystemChange.bind(this)
150
+ this.mediaQuery.addEventListener('change', this.boundHandleSystemChange)
151
+
152
+ // Set the select value to match stored preference
153
+ if (this.hasSelectTarget) {
154
+ this.selectTarget.value = this.getPreference()
155
+ }
156
+ }
157
+
158
+ disconnect() {
159
+ this.mediaQuery.removeEventListener('change', this.boundHandleSystemChange)
160
+ }
161
+
162
+ change(event) {
163
+ const preference = event.target.value
164
+ localStorage.setItem('ruby_llm_agents_theme', preference)
165
+ this.applyTheme(preference)
166
+ }
167
+
168
+ getPreference() {
169
+ return localStorage.getItem('ruby_llm_agents_theme') || 'auto'
170
+ }
171
+
172
+ applyTheme(preference) {
173
+ const isDark = preference === 'dark' ||
174
+ (preference === 'auto' && this.mediaQuery.matches)
175
+ document.documentElement.classList.toggle('dark', isDark)
176
+ }
177
+
178
+ handleSystemChange() {
179
+ if (this.getPreference() === 'auto') {
180
+ this.applyTheme('auto')
181
+ }
182
+ }
183
+ });
184
+
125
185
  console.log('[RubyLLM::Agents] Stimulus initialized');
126
186
  }
127
187
  })();
@@ -130,13 +190,13 @@
130
190
  <style>
131
191
  /* Custom styles for the dashboard */
132
192
  .stat-card {
133
- @apply bg-white rounded-xl shadow-sm border border-gray-100 p-4 transition-shadow;
193
+ @apply bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-100 dark:border-gray-700 p-4 transition-shadow;
134
194
  }
135
195
  .stat-card:hover {
136
196
  @apply shadow-md;
137
197
  }
138
198
  .stat-value {
139
- @apply text-2xl font-bold text-gray-900 mt-2;
199
+ @apply text-2xl font-bold text-gray-900 dark:text-gray-100 mt-2;
140
200
  }
141
201
  @media (min-width: 1024px) {
142
202
  .stat-value {
@@ -144,51 +204,51 @@
144
204
  }
145
205
  }
146
206
  .stat-label {
147
- @apply text-xs text-gray-500 uppercase tracking-wide font-medium;
207
+ @apply text-xs text-gray-500 dark:text-gray-400 uppercase tracking-wide font-medium;
148
208
  }
149
209
  .chart-card {
150
- @apply bg-white rounded-xl shadow-sm border border-gray-100 p-6;
210
+ @apply bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-100 dark:border-gray-700 p-6;
151
211
  }
152
212
  .nav-link {
153
- @apply px-4 py-2 text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-md transition-colors;
213
+ @apply px-4 py-2 text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-md transition-colors;
154
214
  }
155
215
  .nav-link.active {
156
- @apply bg-blue-50 text-blue-700;
216
+ @apply bg-blue-50 dark:bg-blue-900 text-blue-700 dark:text-blue-300;
157
217
  }
158
218
  .badge {
159
219
  @apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium;
160
220
  }
161
221
  .badge-running {
162
- @apply bg-blue-100 text-blue-800;
222
+ @apply bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200;
163
223
  }
164
224
  .badge-success {
165
- @apply bg-green-100 text-green-800;
225
+ @apply bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200;
166
226
  }
167
227
  .badge-error {
168
- @apply bg-red-100 text-red-800;
228
+ @apply bg-red-100 dark:bg-red-900 text-red-800 dark:text-red-200;
169
229
  }
170
230
  .badge-timeout {
171
- @apply bg-yellow-100 text-yellow-800;
231
+ @apply bg-yellow-100 dark:bg-yellow-900 text-yellow-800 dark:text-yellow-200;
172
232
  }
173
233
  </style>
174
234
  </head>
175
235
 
176
236
  <body
177
- class="bg-gray-50 min-h-screen flex flex-col"
237
+ class="bg-gray-50 dark:bg-gray-900 min-h-screen flex flex-col"
178
238
  data-controller="connection"
179
239
  >
180
240
  <!-- Header -->
181
- <header class="bg-white border-b border-gray-200 h-16 flex items-center">
241
+ <header class="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 h-16 flex items-center">
182
242
  <div class="max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8">
183
243
  <div class="flex justify-between items-center">
184
244
  <div class="flex items-center space-x-8">
185
245
  <%= link_to ruby_llm_agents.root_path, class: "flex items-center space-x-2" do %>
186
246
  <span class="text-lg">🤖</span>
187
- <span class="font-semibold text-gray-900">RubyLLM Agents</span>
247
+ <span class="font-semibold text-gray-900 dark:text-gray-100">RubyLLM Agents</span>
188
248
  <% end %>
189
249
 
190
250
  <nav class="flex items-center space-x-1">
191
- <%= link_to ruby_llm_agents.root_path, class: "inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-md #{current_page?(ruby_llm_agents.root_path) ? 'bg-gray-200' : 'text-gray-600 hover:text-gray-900 hover:bg-gray-100'}" do %>
251
+ <%= link_to ruby_llm_agents.root_path, class: "inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-md #{current_page?(ruby_llm_agents.root_path) ? 'bg-gray-200 dark:bg-gray-700 dark:text-gray-100' : 'text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700'}" do %>
192
252
  <svg
193
253
  class="w-4 h-4 mr-1.5"
194
254
  fill="none"
@@ -205,7 +265,7 @@
205
265
  Dashboard
206
266
  <% end %>
207
267
 
208
- <%= link_to ruby_llm_agents.agents_path, class: "inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-md #{request.path.start_with?(ruby_llm_agents.agents_path) ? 'bg-gray-200' : 'text-gray-600 hover:text-gray-900 hover:bg-gray-100'}" do %>
268
+ <%= link_to ruby_llm_agents.agents_path, class: "inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-md #{request.path.start_with?(ruby_llm_agents.agents_path) ? 'bg-gray-200 dark:bg-gray-700 dark:text-gray-100' : 'text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700'}" do %>
209
269
  <svg
210
270
  class="w-4 h-4 mr-1.5"
211
271
  fill="none"
@@ -222,7 +282,7 @@
222
282
  Agents
223
283
  <% end %>
224
284
 
225
- <%= link_to ruby_llm_agents.executions_path, class: "inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-md #{current_page?(ruby_llm_agents.executions_path) ? 'bg-gray-200' : 'text-gray-600 hover:text-gray-900 hover:bg-gray-100'}" do %>
285
+ <%= link_to ruby_llm_agents.executions_path, class: "inline-flex items-center px-3 py-1.5 text-sm font-medium rounded-md #{current_page?(ruby_llm_agents.executions_path) ? 'bg-gray-200 dark:bg-gray-700 dark:text-gray-100' : 'text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-700'}" do %>
226
286
  <svg
227
287
  class="w-4 h-4 mr-1.5"
228
288
  fill="none"
@@ -241,16 +301,16 @@
241
301
  </nav>
242
302
  </div>
243
303
 
244
- <div class="flex items-center space-x-2 text-xs text-gray-500">
304
+ <div class="flex items-center space-x-2 text-xs text-gray-500 dark:text-gray-400">
245
305
  <span id="live-clock" class="tabular-nums"></span>
246
- <span class="text-gray-300">•</span>
306
+ <span class="text-gray-300 dark:text-gray-600">•</span>
247
307
 
248
308
  <span
249
309
  id="live-indicator"
250
310
  data-connection-target="indicator"
251
- class="flex items-center text-gray-400"
311
+ class="flex items-center text-gray-400 dark:text-gray-500"
252
312
  >
253
- <span class="w-1.5 h-1.5 bg-gray-300 rounded-full mr-1"></span>
313
+ <span class="w-1.5 h-1.5 bg-gray-300 dark:bg-gray-600 rounded-full mr-1"></span>
254
314
  <span class="hidden sm:inline">Connecting</span>
255
315
  </span>
256
316
  </div>
@@ -264,12 +324,27 @@
264
324
  </main>
265
325
 
266
326
  <!-- Footer -->
267
- <footer class="border-t bg-white mt-auto">
327
+ <footer class="border-t bg-white dark:bg-gray-800 dark:border-gray-700 mt-auto" data-controller="theme">
268
328
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
269
- <p class="text-center text-sm text-gray-500">
270
- Powered by
271
- <a href="https://github.com/adham90/ruby_llm-agents" class="text-blue-600 hover:underline">ruby_llm-agents</a>
272
- </p>
329
+ <div class="flex items-center justify-between">
330
+ <div class="flex items-center space-x-2">
331
+ <label for="theme-select" class="text-sm text-gray-500 dark:text-gray-400">Theme:</label>
332
+ <select
333
+ id="theme-select"
334
+ data-theme-target="select"
335
+ data-action="change->theme#change"
336
+ class="text-sm border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 py-1 px-2"
337
+ >
338
+ <option value="light">Light</option>
339
+ <option value="dark">Dark</option>
340
+ <option value="auto">Auto</option>
341
+ </select>
342
+ </div>
343
+ <p class="text-sm text-gray-500 dark:text-gray-400">
344
+ Powered by
345
+ <a href="https://github.com/adham90/ruby_llm-agents" class="text-blue-600 dark:text-blue-400 hover:underline">ruby_llm-agents</a>
346
+ </p>
347
+ </div>
273
348
  </div>
274
349
  </footer>
275
350
  </body>
@@ -1,48 +1,48 @@
1
1
  <div class="mb-6">
2
- <h1 class="text-2xl font-bold text-gray-900">Agents</h1>
3
- <p class="text-gray-500 mt-1">All available agents and their execution statistics</p>
2
+ <h1 class="text-2xl font-bold text-gray-900 dark:text-gray-100">Agents</h1>
3
+ <p class="text-gray-500 dark:text-gray-400 mt-1">All available agents and their execution statistics</p>
4
4
  </div>
5
5
 
6
6
  <% if @agents.empty? %>
7
- <div class="bg-white rounded-lg shadow p-8 text-center">
8
- <svg class="mx-auto h-12 w-12 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
7
+ <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-8 text-center">
8
+ <svg class="mx-auto h-12 w-12 text-gray-400 dark:text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
9
9
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 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" />
10
10
  </svg>
11
- <h3 class="mt-2 text-sm font-medium text-gray-900">No agents found</h3>
12
- <p class="mt-1 text-sm text-gray-500">Create an agent by running <code class="bg-gray-100 px-1 rounded">rails g ruby_llm_agents:agent YourAgentName</code></p>
11
+ <h3 class="mt-2 text-sm font-medium text-gray-900 dark:text-gray-100">No agents found</h3>
12
+ <p class="mt-1 text-sm text-gray-500 dark:text-gray-400">Create an agent by running <code class="bg-gray-100 dark:bg-gray-700 dark:text-gray-200 px-1 rounded">rails g ruby_llm_agents:agent YourAgentName</code></p>
13
13
  </div>
14
14
  <% else %>
15
15
  <div class="space-y-4">
16
16
  <% @agents.each do |agent| %>
17
- <%= link_to ruby_llm_agents.agent_path(agent[:name]), class: "block bg-white rounded-lg shadow hover:shadow-md transition-shadow" do %>
17
+ <%= link_to ruby_llm_agents.agent_path(agent[:name]), class: "block bg-white dark:bg-gray-800 rounded-lg shadow hover:shadow-md transition-shadow" do %>
18
18
  <div class="p-5">
19
19
  <!-- Header Row -->
20
20
  <div class="flex items-start justify-between mb-3">
21
21
  <div class="flex items-center space-x-3">
22
- <h3 class="text-lg font-semibold text-gray-900">
22
+ <h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100">
23
23
  <%= agent[:name].gsub(/Agent$/, '') %>
24
24
  </h3>
25
- <span class="text-sm text-gray-500">v<%= agent[:version] %></span>
25
+ <span class="text-sm text-gray-500 dark:text-gray-400">v<%= agent[:version] %></span>
26
26
  <% if agent[:active] %>
27
- <span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800">
27
+ <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">
28
28
  Active
29
29
  </span>
30
30
  <% else %>
31
- <span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-gray-100 text-gray-600">
31
+ <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">
32
32
  Deleted
33
33
  </span>
34
34
  <% end %>
35
35
  </div>
36
36
  <div class="text-right">
37
- <p class="text-sm text-gray-500"><%= agent[:model] %></p>
37
+ <p class="text-sm text-gray-500 dark:text-gray-400"><%= agent[:model] %></p>
38
38
  </div>
39
39
  </div>
40
40
 
41
41
  <!-- Stats Row -->
42
- <div class="flex items-center justify-between text-sm border-t border-gray-100 pt-3">
42
+ <div class="flex items-center justify-between text-sm border-t border-gray-100 dark:border-gray-700 pt-3">
43
43
  <div class="flex items-center space-x-6">
44
44
  <!-- Executions -->
45
- <div class="flex items-center text-gray-600">
45
+ <div class="flex items-center text-gray-600 dark:text-gray-300">
46
46
  <svg class="w-4 h-4 mr-1.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
47
47
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
48
48
  </svg>
@@ -50,7 +50,7 @@
50
50
  </div>
51
51
 
52
52
  <!-- Cost -->
53
- <div class="flex items-center text-gray-600">
53
+ <div class="flex items-center text-gray-600 dark:text-gray-300">
54
54
  <svg class="w-4 h-4 mr-1.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
55
55
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
56
56
  </svg>
@@ -62,19 +62,19 @@
62
62
  <% success_rate = agent[:success_rate] || 0 %>
63
63
  <% if success_rate >= 95 %>
64
64
  <span class="w-2 h-2 rounded-full bg-green-500 mr-1.5"></span>
65
- <span class="text-green-600"><%= success_rate %>%</span>
65
+ <span class="text-green-600 dark:text-green-400"><%= success_rate %>%</span>
66
66
  <% elsif success_rate >= 80 %>
67
67
  <span class="w-2 h-2 rounded-full bg-yellow-500 mr-1.5"></span>
68
- <span class="text-yellow-600"><%= success_rate %>%</span>
68
+ <span class="text-yellow-600 dark:text-yellow-400"><%= success_rate %>%</span>
69
69
  <% else %>
70
70
  <span class="w-2 h-2 rounded-full bg-red-500 mr-1.5"></span>
71
- <span class="text-red-600"><%= success_rate %>%</span>
71
+ <span class="text-red-600 dark:text-red-400"><%= success_rate %>%</span>
72
72
  <% end %>
73
73
  </div>
74
74
  </div>
75
75
 
76
76
  <!-- Last Executed -->
77
- <div class="text-gray-400">
77
+ <div class="text-gray-400 dark:text-gray-500">
78
78
  <% if agent[:last_executed] %>
79
79
  <%= time_ago_in_words(agent[:last_executed]) %> ago
80
80
  <% else %>