leva 0.1.10 → 0.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/README.md +1 -2
- data/app/assets/stylesheets/leva/application.css +3083 -15
- data/app/controllers/leva/design_system_controller.rb +9 -0
- data/app/views/layouts/leva/application.html.erb +23 -24
- data/app/views/leva/dataset_records/index.html.erb +63 -61
- data/app/views/leva/dataset_records/show.html.erb +115 -25
- data/app/views/leva/datasets/_dataset.html.erb +11 -18
- data/app/views/leva/datasets/_form.html.erb +18 -14
- data/app/views/leva/datasets/edit.html.erb +16 -4
- data/app/views/leva/datasets/index.html.erb +33 -41
- data/app/views/leva/datasets/new.html.erb +15 -4
- data/app/views/leva/datasets/show.html.erb +120 -139
- data/app/views/leva/design_system/index.html.erb +1731 -0
- data/app/views/leva/experiments/_experiment.html.erb +46 -31
- data/app/views/leva/experiments/_form.html.erb +62 -35
- data/app/views/leva/experiments/edit.html.erb +17 -3
- data/app/views/leva/experiments/index.html.erb +41 -36
- data/app/views/leva/experiments/new.html.erb +40 -19
- data/app/views/leva/experiments/show.html.erb +155 -98
- data/app/views/leva/runner_results/show.html.erb +271 -54
- data/app/views/leva/workbench/_evaluation_area.html.erb +18 -4
- data/app/views/leva/workbench/_prompt_content.html.erb +116 -111
- data/app/views/leva/workbench/_prompt_form.html.erb +24 -23
- data/app/views/leva/workbench/_prompt_sidebar.html.erb +57 -12
- data/app/views/leva/workbench/_results_section.html.erb +274 -112
- data/app/views/leva/workbench/_top_bar.html.erb +16 -6
- data/app/views/leva/workbench/edit.html.erb +46 -15
- data/app/views/leva/workbench/index.html.erb +5 -8
- data/app/views/leva/workbench/new.html.erb +74 -42
- data/config/routes.rb +2 -0
- data/lib/leva/engine.rb +10 -0
- data/lib/leva/version.rb +1 -1
- metadata +4 -2
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
<% content_for :title, "New Prompt" %>
|
|
2
|
-
<div class="container
|
|
3
|
-
<
|
|
4
|
-
|
|
2
|
+
<div class="container page">
|
|
3
|
+
<div class="page-header">
|
|
4
|
+
<div class="flex items-center gap-3">
|
|
5
|
+
<%= link_to workbench_index_path, class: "btn btn-ghost btn-sm" do %>
|
|
6
|
+
<svg class="icon-sm" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
7
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
|
8
|
+
</svg>
|
|
9
|
+
<% end %>
|
|
10
|
+
<div>
|
|
11
|
+
<h1 class="page-title" style="margin-bottom: 0;">New Prompt</h1>
|
|
12
|
+
<p class="text-sm text-muted" style="margin: 0;">Create a new prompt template</p>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<%= form_with(model: @prompt, url: workbench_index_path, local: true, class: "card", data: { controller: "prompt-selector" }) do |form| %>
|
|
5
18
|
<% if @prompt.errors.any? %>
|
|
6
|
-
<div class="
|
|
7
|
-
<
|
|
19
|
+
<div class="form-errors">
|
|
20
|
+
<p class="form-errors-title"><%= pluralize(@prompt.errors.count, "error") %> prohibited this prompt from being saved:</p>
|
|
8
21
|
<ul>
|
|
9
22
|
<% @prompt.errors.full_messages.each do |message| %>
|
|
10
23
|
<li><%= message %></li>
|
|
@@ -12,58 +25,85 @@
|
|
|
12
25
|
</ul>
|
|
13
26
|
</div>
|
|
14
27
|
<% end %>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
28
|
+
|
|
29
|
+
<div class="form-group">
|
|
30
|
+
<div class="flex items-center gap-2 mb-2">
|
|
31
|
+
<svg class="icon-sm text-muted" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
32
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" />
|
|
33
|
+
</svg>
|
|
34
|
+
<%= form.label :name, class: "form-label", style: "margin-bottom: 0;" %>
|
|
35
|
+
</div>
|
|
36
|
+
<%= form.text_field :name, autofocus: true, class: "form-input", placeholder: "Enter a descriptive name..." %>
|
|
18
37
|
</div>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
38
|
+
|
|
39
|
+
<div class="form-group">
|
|
40
|
+
<div class="flex items-center gap-2 mb-2">
|
|
41
|
+
<svg class="icon-sm text-muted" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
42
|
+
<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" />
|
|
43
|
+
</svg>
|
|
44
|
+
<%= form.label :system_prompt, "System Prompt", class: "form-label", style: "margin-bottom: 0;" %>
|
|
45
|
+
</div>
|
|
46
|
+
<%= form.text_area :system_prompt, rows: 2, class: "form-textarea prompt-textarea", placeholder: "Define the AI's role and behavior..." %>
|
|
22
47
|
</div>
|
|
23
|
-
|
|
24
|
-
|
|
48
|
+
|
|
49
|
+
<div class="form-group">
|
|
50
|
+
<div class="flex items-center gap-2 mb-2">
|
|
51
|
+
<svg class="icon-sm text-muted" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
52
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z" />
|
|
53
|
+
</svg>
|
|
54
|
+
<%= form.label :predefined_prompt, "Template", class: "form-label", style: "margin-bottom: 0;" %>
|
|
55
|
+
</div>
|
|
25
56
|
<%= form.select :predefined_prompt,
|
|
26
57
|
options_for_select([['Custom Prompt', '']] + @predefined_prompts.map { |name, content| [name, content] }),
|
|
27
58
|
{},
|
|
28
|
-
class: "
|
|
59
|
+
class: "form-select",
|
|
29
60
|
data: { action: "change->prompt-selector#toggleUserPrompt" }
|
|
30
61
|
%>
|
|
31
62
|
</div>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
63
|
+
|
|
64
|
+
<div class="form-group" data-prompt-selector-target="userPromptField">
|
|
65
|
+
<div class="flex items-center gap-2 mb-2">
|
|
66
|
+
<svg class="icon-sm text-muted" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
67
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
|
|
68
|
+
</svg>
|
|
69
|
+
<%= form.label :user_prompt, "User Prompt Template", class: "form-label", style: "margin-bottom: 0;" %>
|
|
70
|
+
</div>
|
|
71
|
+
<%= form.text_area :user_prompt, rows: 5, class: "form-textarea prompt-textarea", placeholder: "Use {{ variable }} syntax for dynamic content..." %>
|
|
35
72
|
</div>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<
|
|
39
|
-
|
|
73
|
+
|
|
74
|
+
<div class="form-group hidden" data-prompt-selector-target="promptPreview" id="prompt-preview">
|
|
75
|
+
<label class="form-label">Prompt Preview</label>
|
|
76
|
+
<div
|
|
77
|
+
class="card-subtle p-4"
|
|
78
|
+
style="background: var(--gray-800); white-space: pre-wrap;"
|
|
40
79
|
data-prompt-selector-target="previewContent"
|
|
41
80
|
id="preview-content"
|
|
42
81
|
></div>
|
|
43
82
|
|
|
44
|
-
<!-- show-full button, hidden until overflow is detected -->
|
|
45
83
|
<button
|
|
46
84
|
id="show-full-preview"
|
|
47
85
|
type="button"
|
|
48
|
-
class="
|
|
86
|
+
class="btn btn-ghost btn-sm mt-2 hidden"
|
|
49
87
|
>Show full</button>
|
|
50
88
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
</
|
|
89
|
+
<dialog id="full-preview-dialog">
|
|
90
|
+
<div class="dialog-header">
|
|
91
|
+
<h3 class="dialog-title">Full Preview</h3>
|
|
92
|
+
</div>
|
|
93
|
+
<div class="dialog-body" id="dialog-content" style="white-space: pre-wrap;"></div>
|
|
94
|
+
<div class="dialog-footer">
|
|
95
|
+
<button id="close-full-preview" class="btn btn-primary">Close</button>
|
|
58
96
|
</div>
|
|
59
97
|
</dialog>
|
|
60
98
|
</div>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
<%=
|
|
99
|
+
|
|
100
|
+
<div class="form-actions justify-end">
|
|
101
|
+
<%= link_to "Cancel", workbench_index_path, class: "btn btn-ghost" %>
|
|
102
|
+
<%= form.submit "Create Prompt", class: "btn btn-primary" %>
|
|
64
103
|
</div>
|
|
65
104
|
<% end %>
|
|
66
105
|
</div>
|
|
106
|
+
|
|
67
107
|
<script>
|
|
68
108
|
(() => {
|
|
69
109
|
const application = Stimulus.Application.start()
|
|
@@ -98,7 +138,6 @@
|
|
|
98
138
|
})
|
|
99
139
|
})()
|
|
100
140
|
|
|
101
|
-
// Prompt preview scrollbar and dialog functionality
|
|
102
141
|
document.addEventListener('DOMContentLoaded', () => {
|
|
103
142
|
const wrapper = document.getElementById('prompt-preview');
|
|
104
143
|
const preview = document.getElementById('preview-content');
|
|
@@ -109,28 +148,24 @@
|
|
|
109
148
|
|
|
110
149
|
if (!preview) return;
|
|
111
150
|
|
|
112
|
-
// Check if the preview content is already populated by Stimulus
|
|
113
151
|
const checkPreviewContent = () => {
|
|
114
152
|
if (preview.textContent.trim().length > 0) {
|
|
115
|
-
// Detect overflow
|
|
116
153
|
if (preview.scrollHeight > preview.clientHeight || preview.scrollWidth > preview.clientWidth) {
|
|
117
154
|
preview.style.maxHeight = '12em';
|
|
118
155
|
preview.style.overflow = 'auto';
|
|
119
156
|
showBtn.classList.remove('hidden');
|
|
120
157
|
}
|
|
121
158
|
} else {
|
|
122
|
-
// If not populated yet, check again after a short delay
|
|
123
159
|
setTimeout(checkPreviewContent, 100);
|
|
124
160
|
}
|
|
125
161
|
};
|
|
126
162
|
|
|
127
|
-
// Start checking once the wrapper is visible
|
|
128
163
|
const observer = new MutationObserver((mutations) => {
|
|
129
164
|
mutations.forEach((mutation) => {
|
|
130
165
|
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
|
131
166
|
if (!wrapper.classList.contains('hidden')) {
|
|
132
167
|
checkPreviewContent();
|
|
133
|
-
observer.disconnect();
|
|
168
|
+
observer.disconnect();
|
|
134
169
|
}
|
|
135
170
|
}
|
|
136
171
|
});
|
|
@@ -138,15 +173,12 @@
|
|
|
138
173
|
|
|
139
174
|
observer.observe(wrapper, { attributes: true });
|
|
140
175
|
|
|
141
|
-
// Show full in dialog
|
|
142
176
|
showBtn.addEventListener('click', () => {
|
|
143
177
|
dialogBody.textContent = preview.textContent;
|
|
144
178
|
dialog.showModal();
|
|
145
179
|
});
|
|
146
180
|
|
|
147
|
-
// Close dialog
|
|
148
181
|
closeBtn.addEventListener('click', () => dialog.close());
|
|
149
182
|
});
|
|
150
183
|
</script>
|
|
151
|
-
<!-- Include marked.js for Markdown parsing -->
|
|
152
184
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
data/config/routes.rb
CHANGED
data/lib/leva/engine.rb
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
module Leva
|
|
2
2
|
class Engine < ::Rails::Engine
|
|
3
3
|
isolate_namespace Leva
|
|
4
|
+
|
|
5
|
+
initializer "leva.assets" do |app|
|
|
6
|
+
# Add asset paths for both Sprockets and Propshaft
|
|
7
|
+
app.config.assets.paths << root.join("app/assets/stylesheets").to_s
|
|
8
|
+
|
|
9
|
+
# For Sprockets: explicitly precompile leva assets
|
|
10
|
+
if app.config.respond_to?(:assets) && app.config.assets.respond_to?(:precompile)
|
|
11
|
+
app.config.assets.precompile += %w[leva/application.css]
|
|
12
|
+
end
|
|
13
|
+
end
|
|
4
14
|
end
|
|
5
15
|
end
|
data/lib/leva/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: leva
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kieran Klaassen
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-
|
|
11
|
+
date: 2025-11-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -55,6 +55,7 @@ files:
|
|
|
55
55
|
- app/controllers/leva/application_controller.rb
|
|
56
56
|
- app/controllers/leva/dataset_records_controller.rb
|
|
57
57
|
- app/controllers/leva/datasets_controller.rb
|
|
58
|
+
- app/controllers/leva/design_system_controller.rb
|
|
58
59
|
- app/controllers/leva/experiments_controller.rb
|
|
59
60
|
- app/controllers/leva/runner_results_controller.rb
|
|
60
61
|
- app/controllers/leva/workbench_controller.rb
|
|
@@ -82,6 +83,7 @@ files:
|
|
|
82
83
|
- app/views/leva/datasets/index.html.erb
|
|
83
84
|
- app/views/leva/datasets/new.html.erb
|
|
84
85
|
- app/views/leva/datasets/show.html.erb
|
|
86
|
+
- app/views/leva/design_system/index.html.erb
|
|
85
87
|
- app/views/leva/experiments/_experiment.html.erb
|
|
86
88
|
- app/views/leva/experiments/_form.html.erb
|
|
87
89
|
- app/views/leva/experiments/edit.html.erb
|