completion-kit 0.29.0 → 0.29.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 +48 -3
- data/app/assets/javascripts/completion_kit/application.js +383 -0
- data/app/controllers/completion_kit/mcp_controller.rb +4 -0
- data/app/models/completion_kit/dataset.rb +53 -4
- data/app/models/completion_kit/metric.rb +1 -1
- data/app/models/completion_kit/prompt.rb +8 -0
- data/app/models/completion_kit/run.rb +1 -1
- data/app/services/completion_kit/api_config.rb +2 -1
- data/app/services/completion_kit/checks/regex.rb +12 -2
- data/app/services/completion_kit/csv_processor.rb +14 -2
- data/app/services/completion_kit/model_discovery_service.rb +2 -1
- data/app/services/completion_kit/ollama_client.rb +19 -2
- data/app/services/completion_kit/provider_endpoint.rb +10 -0
- data/app/views/completion_kit/api_reference/_authentication.html.erb +2 -2
- data/app/views/completion_kit/api_reference/_body.html.erb +0 -27
- data/app/views/completion_kit/api_reference/_example.html.erb +1 -1
- data/app/views/completion_kit/api_reference/_resource_card.html.erb +1 -1
- data/app/views/completion_kit/datasets/_form.html.erb +0 -28
- data/app/views/completion_kit/datasets/index.html.erb +1 -1
- data/app/views/completion_kit/metric_groups/_form.html.erb +1 -20
- data/app/views/completion_kit/metric_groups/index.html.erb +1 -1
- data/app/views/completion_kit/metrics/_starter_card.html.erb +1 -1
- data/app/views/completion_kit/metrics/index.html.erb +2 -2
- data/app/views/completion_kit/metrics/show.html.erb +4 -14
- data/app/views/completion_kit/prompts/_form.html.erb +1 -1
- data/app/views/completion_kit/prompts/index.html.erb +3 -3
- data/app/views/completion_kit/prompts/show.html.erb +8 -8
- data/app/views/completion_kit/provider_credentials/_models_card.html.erb +2 -2
- data/app/views/completion_kit/runs/_form.html.erb +3 -179
- data/app/views/completion_kit/runs/_response_row.html.erb +2 -3
- data/app/views/completion_kit/runs/_row.html.erb +3 -3
- data/app/views/completion_kit/runs/_run_config.html.erb +1 -1
- data/app/views/completion_kit/runs/show.html.erb +5 -19
- data/app/views/completion_kit/tags/index.html.erb +1 -1
- data/app/views/layouts/completion_kit/application.html.erb +2 -2
- data/lib/completion_kit/version.rb +1 -1
- data/lib/completion_kit.rb +14 -0
- data/lib/generators/completion_kit/templates/initializer.rb +18 -0
- metadata +1 -1
|
@@ -37,7 +37,18 @@ module CompletionKit
|
|
|
37
37
|
def self.extract_variables(prompt)
|
|
38
38
|
return [] if prompt.nil? || prompt.template.blank?
|
|
39
39
|
|
|
40
|
-
prompt.template
|
|
40
|
+
template = prompt.template
|
|
41
|
+
names = []
|
|
42
|
+
cursor = 0
|
|
43
|
+
while (opener = template.byteindex("{{", cursor)) && (closer = template.byteindex("}", opener + 2))
|
|
44
|
+
if closer > opener + 2 && template.byteslice(closer + 1, 1) == "}"
|
|
45
|
+
names << template.byteslice(opener + 2, closer - opener - 2)
|
|
46
|
+
cursor = closer + 2
|
|
47
|
+
else
|
|
48
|
+
cursor = closer + 1
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
names.map(&:strip).uniq
|
|
41
52
|
end
|
|
42
53
|
|
|
43
54
|
def self.validate_variables(run, headers)
|
|
@@ -57,7 +68,8 @@ module CompletionKit
|
|
|
57
68
|
return prompt.template.dup if values.empty?
|
|
58
69
|
|
|
59
70
|
names = values.keys.map { |name| Regexp.escape(name) }.join("|")
|
|
60
|
-
|
|
71
|
+
pattern = Regexp.new("\\{\\{\\s*(#{names})\\s*\\}\\}", timeout: Checks::Regex.timeout)
|
|
72
|
+
prompt.template.gsub(pattern) { values[Regexp.last_match(1)].to_s }
|
|
61
73
|
end
|
|
62
74
|
end
|
|
63
75
|
end
|
|
@@ -12,8 +12,9 @@ module CompletionKit
|
|
|
12
12
|
|
|
13
13
|
def initialize(config:)
|
|
14
14
|
@provider = config[:provider]
|
|
15
|
-
@api_key = config[:api_key]
|
|
16
15
|
@api_endpoint = config[:api_endpoint]
|
|
16
|
+
@api_key = config[:api_key]
|
|
17
|
+
@api_key = @api_key.presence || OllamaClient.fallback_api_key(@api_endpoint) if @provider == "ollama"
|
|
17
18
|
@api_version = config[:api_version]
|
|
18
19
|
@catalog_model_count = nil
|
|
19
20
|
end
|
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
module CompletionKit
|
|
2
2
|
class OllamaClient < LlmClient
|
|
3
|
+
DEFAULT_ENDPOINT = "http://localhost:11434/v1"
|
|
4
|
+
|
|
5
|
+
def self.configured_endpoint
|
|
6
|
+
endpoint = CompletionKit.config.ollama_api_endpoint || ENV["OLLAMA_API_ENDPOINT"]
|
|
7
|
+
endpoint || (DEFAULT_ENDPOINT if CompletionKit.config.allow_loopback_endpoints)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.fallback_api_key(endpoint)
|
|
11
|
+
return unless ProviderEndpoint.same_destination?(root_url(endpoint), root_url(configured_endpoint))
|
|
12
|
+
|
|
13
|
+
env_key = ENV["OLLAMA_API_KEY"]
|
|
14
|
+
CompletionKit.config.tenant_scope ? env_key : CompletionKit.config.ollama_api_key || env_key
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.root_url(endpoint)
|
|
18
|
+
endpoint.to_s.strip.delete_suffix("/").delete_suffix("/v1")
|
|
19
|
+
end
|
|
3
20
|
|
|
4
21
|
def generate_completion(prompt, options = {})
|
|
5
22
|
@temperature_dropped = false
|
|
@@ -75,12 +92,12 @@ module CompletionKit
|
|
|
75
92
|
end
|
|
76
93
|
|
|
77
94
|
def api_key
|
|
78
|
-
@config[:api_key] ||
|
|
95
|
+
@config[:api_key].presence || self.class.fallback_api_key(api_endpoint)
|
|
79
96
|
end
|
|
80
97
|
|
|
81
98
|
def api_endpoint
|
|
82
99
|
raw = @config[:api_endpoint] || ENV["OLLAMA_API_ENDPOINT"]
|
|
83
|
-
raw ||=
|
|
100
|
+
raw ||= DEFAULT_ENDPOINT if CompletionKit.config.allow_loopback_endpoints
|
|
84
101
|
raw.to_s.delete_suffix("/")
|
|
85
102
|
end
|
|
86
103
|
|
|
@@ -51,6 +51,16 @@ module CompletionKit
|
|
|
51
51
|
nil
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
+
def same_destination?(url, other)
|
|
55
|
+
destination = destination(url)
|
|
56
|
+
!destination.nil? && destination == destination(other)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def destination(url)
|
|
60
|
+
uri = parse(url)
|
|
61
|
+
[uri.scheme, uri.host.downcase, uri.port, uri.path.delete_suffix("/")] if uri
|
|
62
|
+
end
|
|
63
|
+
|
|
54
64
|
def issues_for(addrs)
|
|
55
65
|
return [:unresolvable] if addrs.empty?
|
|
56
66
|
return [:unsafe_host] if addrs.any? { |ip| unsafe?(ip) }
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<% if token.present? %>
|
|
2
2
|
<% masked = ck_masked_token(token) %>
|
|
3
3
|
<div style="display: flex; align-items: center; gap: 0.4rem; margin: 0.5rem 0;">
|
|
4
|
-
<button type="button" class="ck-chip ck-token-toggle"
|
|
5
|
-
<button type="button" class="ck-icon-btn" title="Copy token" aria-label="Copy API token"
|
|
4
|
+
<button type="button" class="ck-chip ck-token-toggle" data-ck-token-toggle data-masked="<%= masked %>" data-real="<%= token %>" aria-label="Reveal API token" aria-pressed="false" style="cursor: pointer;"><%= masked %></button>
|
|
5
|
+
<button type="button" class="ck-icon-btn" title="Copy token" aria-label="Copy API token" data-ck-copy-text="<%= token %>" data-ck-copy-feedback>
|
|
6
6
|
<%= heroicon_tag "clipboard-document", variant: :outline, size: 14, "aria-hidden": "true" %>
|
|
7
7
|
</button>
|
|
8
8
|
</div>
|
|
@@ -423,30 +423,3 @@
|
|
|
423
423
|
|
|
424
424
|
</div>
|
|
425
425
|
</div>
|
|
426
|
-
|
|
427
|
-
<script>
|
|
428
|
-
function ckToggleToken(el) {
|
|
429
|
-
var showing = el.textContent === el.dataset.masked;
|
|
430
|
-
el.textContent = showing ? el.dataset.real : el.dataset.masked;
|
|
431
|
-
el.setAttribute('aria-pressed', showing ? 'true' : 'false');
|
|
432
|
-
el.setAttribute('aria-label', showing ? 'Hide API token' : 'Reveal API token');
|
|
433
|
-
navigator.clipboard.writeText(el.dataset.real).then(function() {
|
|
434
|
-
el.classList.add('ck-api-copy--done');
|
|
435
|
-
setTimeout(function() { el.classList.remove('ck-api-copy--done'); }, 1500);
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
function ckCopyExample(btn) {
|
|
440
|
-
var pre = btn.closest('.ck-api-example').querySelector('pre');
|
|
441
|
-
var text = pre.textContent;
|
|
442
|
-
var realToken = btn.dataset.realToken;
|
|
443
|
-
var displayToken = btn.dataset.displayToken;
|
|
444
|
-
if (realToken && displayToken) {
|
|
445
|
-
text = text.split(displayToken).join(realToken);
|
|
446
|
-
}
|
|
447
|
-
navigator.clipboard.writeText(text).then(function() {
|
|
448
|
-
btn.classList.add('ck-api-copy--done');
|
|
449
|
-
setTimeout(function() { btn.classList.remove('ck-api-copy--done'); }, 1500);
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
</script>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div class="ck-api-example">
|
|
2
2
|
<pre class="ck-code ck-code--dark"><%= cmd %></pre>
|
|
3
|
-
<button type="button" class="ck-api-copy" aria-label="Copy example to clipboard"
|
|
3
|
+
<button type="button" class="ck-api-copy" aria-label="Copy example to clipboard" data-ck-copy-example data-real-token="<%= real_token %>" data-display-token="<%= token %>">
|
|
4
4
|
<%= heroicon_tag "clipboard-document", variant: :outline, size: 14, "aria-hidden": "true" %>
|
|
5
5
|
</button>
|
|
6
6
|
</div>
|
|
@@ -19,6 +19,6 @@
|
|
|
19
19
|
</div>
|
|
20
20
|
<div class="ck-api-prompt-card__url">
|
|
21
21
|
<code class="ck-endpoint__url" id="<%= dom_id %>"><%= url %></code>
|
|
22
|
-
<button type="button" class="ck-icon-btn" title="Copy endpoint" aria-label="Copy endpoint URL"
|
|
22
|
+
<button type="button" class="ck-icon-btn" title="Copy endpoint" aria-label="Copy endpoint URL" data-ck-copy="<%= dom_id %>"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" width="14" height="14" aria-hidden="true"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"/><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"/></svg></button>
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
@@ -46,34 +46,6 @@
|
|
|
46
46
|
<%= form.submit(dataset.persisted? ? "Save dataset" : "Create dataset", class: ck_button_classes(:dark)) %>
|
|
47
47
|
</div>
|
|
48
48
|
</div>
|
|
49
|
-
|
|
50
|
-
<script>
|
|
51
|
-
function ckDatasetHeaderPreview() {
|
|
52
|
-
var area = document.getElementById('dataset_csv_data');
|
|
53
|
-
var box = document.getElementById('dataset-header-preview');
|
|
54
|
-
var chips = document.getElementById('dataset-header-chips');
|
|
55
|
-
if (!area || !box || !chips) return;
|
|
56
|
-
var recognized = { expected_output: 'answer key', actual_output: 'pre-made output' };
|
|
57
|
-
var firstLine = (area.value.split(/\r?\n/).find(function(l) { return l.trim() !== ''; }) || '');
|
|
58
|
-
var headers = firstLine.split(',').map(function(h) { return h.trim().replace(/^"|"$/g, ''); }).filter(Boolean);
|
|
59
|
-
if (headers.length === 0) { box.hidden = true; chips.textContent = ''; return; }
|
|
60
|
-
box.hidden = false;
|
|
61
|
-
chips.textContent = '';
|
|
62
|
-
headers.forEach(function(h) {
|
|
63
|
-
var role = recognized[h];
|
|
64
|
-
var chip = document.createElement('span');
|
|
65
|
-
chip.className = 'ck-header-chip' + (role ? ' ck-header-chip--special' : '');
|
|
66
|
-
chip.textContent = role ? h + ' · ' + role : h;
|
|
67
|
-
chips.appendChild(chip);
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
document.addEventListener('turbo:load', ckDatasetHeaderPreview);
|
|
71
|
-
(function() {
|
|
72
|
-
var area = document.getElementById('dataset_csv_data');
|
|
73
|
-
if (area) area.addEventListener('input', ckDatasetHeaderPreview);
|
|
74
|
-
})();
|
|
75
|
-
ckDatasetHeaderPreview();
|
|
76
|
-
</script>
|
|
77
49
|
<% end %>
|
|
78
50
|
|
|
79
51
|
<% if dataset.persisted? %>
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
</thead>
|
|
28
28
|
<tbody>
|
|
29
29
|
<% @datasets.each do |dataset| %>
|
|
30
|
-
<tr
|
|
30
|
+
<tr data-ck-href="<%= dataset_path(dataset) %>" style="cursor: pointer;">
|
|
31
31
|
<td>
|
|
32
32
|
<%= link_to dataset_path(dataset), class: "ck-record-name" do %><strong><%= dataset.name %></strong><% end %>
|
|
33
33
|
<% if dataset.tags.any? %>
|
|
@@ -47,8 +47,7 @@
|
|
|
47
47
|
<button type="button"
|
|
48
48
|
class="tag-mark tag-mark--off ck-metric-tag-filter__chip"
|
|
49
49
|
style="--mark-color: var(--tag-<%= tag.color %>);"
|
|
50
|
-
data-filter-tag="<%= tag.name %>"
|
|
51
|
-
onclick="ckToggleMetricGroupFilter(this)"><%= tag.name %></button>
|
|
50
|
+
data-filter-tag="<%= tag.name %>"><%= tag.name %></button>
|
|
52
51
|
<% end %>
|
|
53
52
|
</div>
|
|
54
53
|
<% end %>
|
|
@@ -78,24 +77,6 @@
|
|
|
78
77
|
<%= hidden_field_tag "metric_group[metric_ids][]", "" %>
|
|
79
78
|
</div>
|
|
80
79
|
|
|
81
|
-
<script>
|
|
82
|
-
function ckToggleMetricGroupFilter(btn) {
|
|
83
|
-
btn.classList.toggle("tag-mark--off");
|
|
84
|
-
var bar = btn.closest("[data-metric-tag-filter]");
|
|
85
|
-
var grid = bar && bar.parentElement.querySelector("[data-metric-checkboxes]");
|
|
86
|
-
if (!grid) return;
|
|
87
|
-
var active = Array.prototype.map.call(
|
|
88
|
-
bar.querySelectorAll(".ck-metric-tag-filter__chip:not(.tag-mark--off)"),
|
|
89
|
-
function(b) { return b.getAttribute("data-filter-tag"); }
|
|
90
|
-
);
|
|
91
|
-
grid.querySelectorAll(".ck-checkbox-label").forEach(function(lbl) {
|
|
92
|
-
var tags = (lbl.getAttribute("data-metric-tags") || "").split(",").filter(Boolean);
|
|
93
|
-
var visible = active.length === 0 || tags.some(function(t) { return active.indexOf(t) !== -1; });
|
|
94
|
-
lbl.style.display = visible ? "" : "none";
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
</script>
|
|
98
|
-
|
|
99
80
|
<div class="ck-actions">
|
|
100
81
|
<% if metric_group.persisted? %>
|
|
101
82
|
<%= ck_delete_trigger(form_id: metric_group_delete_id, label: "Delete metric group", confirm: metric_group_delete_confirm) %>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
</thead>
|
|
32
32
|
<tbody>
|
|
33
33
|
<% @metric_groups.each do |metric_group| %>
|
|
34
|
-
<tr
|
|
34
|
+
<tr data-ck-href="<%= metric_group_path(metric_group) %>" style="cursor: pointer;">
|
|
35
35
|
<td>
|
|
36
36
|
<%= link_to metric_group_path(metric_group), class: "ck-record-name" do %><strong><%= metric_group.name %></strong><% end %>
|
|
37
37
|
<% if metric_group.tags.any? %>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<span class="ck-starter-card__cta">Preview →</span>
|
|
8
8
|
<%= button_to "dismiss", dismiss_starter_metrics_path(key: starter.key),
|
|
9
9
|
method: :post,
|
|
10
|
-
form: {
|
|
10
|
+
form: { data: { ck_stop_propagation: true } },
|
|
11
11
|
form_class: "inline-block ck-starter-card__dismiss-form",
|
|
12
12
|
class: "ck-starter-card__dismiss",
|
|
13
13
|
data: { turbo_confirm: "Hide \"#{starter.name}\" from this list?" } %>
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
</thead>
|
|
29
29
|
<tbody>
|
|
30
30
|
<% @metrics.each do |metric| %>
|
|
31
|
-
<tr
|
|
31
|
+
<tr data-ck-href="<%= metric_path(metric) %>" style="cursor: pointer;">
|
|
32
32
|
<td>
|
|
33
33
|
<%= link_to metric_path(metric), class: "ck-record-name" do %><strong><%= metric.name %></strong><% end %>
|
|
34
34
|
<span class="ck-chip ck-chip--soft ck-metric-type-chip"><%= metric.check? ? "Check" : "Judge" %></span>
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
<% if groups.any? %>
|
|
49
49
|
<div class="ck-metrics-table__groups">
|
|
50
50
|
<% groups.each do |g| %>
|
|
51
|
-
<%= link_to metric_group_path(g), class: "ck-metric-group-pill ck-metric-group-pill--active"
|
|
51
|
+
<%= link_to metric_group_path(g), class: "ck-metric-group-pill ck-metric-group-pill--active" do %>
|
|
52
52
|
<span class="ck-metric-group-pill__label"><%= g.name %></span>
|
|
53
53
|
<% end %>
|
|
54
54
|
<% end %>
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
<% if v.draft? && vs.present? %>
|
|
92
92
|
<span class="ck-version-score"><span class="ck-version-score__label">Match</span> <%= vs["after"] %>/<%= vs["tested"] %></span>
|
|
93
93
|
<% end %>
|
|
94
|
-
<button type="button" class="ck-cell-link ck-cell-link--delta" title="What changed from <%= pred.version_label %>"
|
|
94
|
+
<button type="button" class="ck-cell-link ck-cell-link--delta" title="What changed from <%= pred.version_label %>" data-ck-dialog-open="ck-mvdiff-<%= v.id %>">Δ</button>
|
|
95
95
|
</div>
|
|
96
96
|
<% end %>
|
|
97
97
|
</div>
|
|
@@ -126,14 +126,14 @@
|
|
|
126
126
|
<% pred = predecessor_of[v] %>
|
|
127
127
|
<% next unless v.change_summary_against(pred) %>
|
|
128
128
|
<% vs = v.validation_summary %>
|
|
129
|
-
<dialog id="ck-mvdiff-<%= v.id %>" class="ck-modal" aria-labelledby="ck-mvdiff-title-<%= v.id %>"
|
|
130
|
-
<article class="ck-modal__panel" tabindex="-1"
|
|
129
|
+
<dialog id="ck-mvdiff-<%= v.id %>" class="ck-modal" aria-labelledby="ck-mvdiff-title-<%= v.id %>" data-ck-dialog<%= " data-ck-dialog-autoopen" if params[:show_change].to_i == v.id %>>
|
|
130
|
+
<article class="ck-modal__panel" tabindex="-1">
|
|
131
131
|
<header class="ck-modal__header">
|
|
132
132
|
<div class="ck-modal__heading">
|
|
133
133
|
<h2 class="ck-modal__title" id="ck-mvdiff-title-<%= v.id %>"><%= pred.version_label %> → <%= v.version_label %></h2>
|
|
134
134
|
<span class="ck-modal__meta">What changed in <%= v.version_label %><% if v.current? %> (live)<% elsif v.draft? %> (draft)<% end %></span>
|
|
135
135
|
</div>
|
|
136
|
-
<button type="button" class="ck-modal__close" aria-label="Close"
|
|
136
|
+
<button type="button" class="ck-modal__close" aria-label="Close" data-ck-dialog-close>×</button>
|
|
137
137
|
</header>
|
|
138
138
|
<div class="ck-modal__body">
|
|
139
139
|
<% if v.draft? && vs.present? %>
|
|
@@ -223,13 +223,3 @@
|
|
|
223
223
|
<% end %>
|
|
224
224
|
</section>
|
|
225
225
|
<% end %>
|
|
226
|
-
|
|
227
|
-
<% if params[:show_change].present? %>
|
|
228
|
-
<script>
|
|
229
|
-
(function () {
|
|
230
|
-
var dialog = document.getElementById("ck-mvdiff-<%= params[:show_change].to_i %>");
|
|
231
|
-
if (dialog && typeof dialog.showModal === "function") dialog.showModal();
|
|
232
|
-
})();
|
|
233
|
-
</script>
|
|
234
|
-
<% end %>
|
|
235
|
-
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
<div class="ck-select-with-action">
|
|
50
50
|
<%= form.select :llm_model, ck_grouped_models(available, prompt.llm_model, rejected: prompt.errors[:llm_model].any?), { include_blank: "Select a model" }, { class: "ck-input", id: "prompt_llm_model", **ck_field_aria(form, :llm_model) } %>
|
|
51
51
|
<% ck_refreshing = CompletionKit::ProviderCredential.discovery_in_progress? %>
|
|
52
|
-
<button type="button" class="ck-icon-btn<%= ' ck-icon-btn--spinning' if ck_refreshing %>" title="Refresh models" <%= 'disabled' if ck_refreshing %>
|
|
52
|
+
<button type="button" class="ck-icon-btn<%= ' ck-icon-btn--spinning' if ck_refreshing %>" title="Refresh models" <%= 'disabled' if ck_refreshing %> data-ck-refresh-models><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" width="16" height="16"><path fill-rule="evenodd" d="M13.836 2.477a.75.75 0 0 1 .75.75v3.182a.75.75 0 0 1-.75.75h-3.182a.75.75 0 0 1 0-1.5h1.37l-.84-.841a4.5 4.5 0 0 0-7.08.681.75.75 0 0 1-1.264-.808 6 6 0 0 1 9.44-.908l.84.84V3.227a.75.75 0 0 1 .75-.75Zm-.911 7.5A.75.75 0 0 1 13.199 11a6 6 0 0 1-9.44.908l-.84-.84v1.68a.75.75 0 0 1-1.5 0V9.567a.75.75 0 0 1 .75-.75h3.182a.75.75 0 0 1 0 1.5h-1.37l.84.841a4.5 4.5 0 0 0 7.08-.681.75.75 0 0 1 1.024-.274Z" clip-rule="evenodd"/></svg></button>
|
|
53
53
|
</div>
|
|
54
54
|
<% else %>
|
|
55
55
|
<p class="ck-meta-copy">No models available. <%= link_to "Add a provider", provider_credentials_path, class: "ck-link" %> or click refresh after configuring a provider.</p>
|
|
@@ -28,15 +28,15 @@
|
|
|
28
28
|
</thead>
|
|
29
29
|
<tbody>
|
|
30
30
|
<% @prompts.each do |prompt| %>
|
|
31
|
-
<tr
|
|
31
|
+
<tr data-ck-href="<%= prompt_path(prompt) %>" style="cursor: pointer;">
|
|
32
32
|
<td>
|
|
33
33
|
<%= link_to prompt_path(prompt), class: "ck-record-name" do %><strong><%= prompt.name %></strong><% end %>
|
|
34
34
|
<% if prompt.description.present? %>
|
|
35
35
|
<p class="ck-prompts-table__desc"><%= truncate(prompt.description, length: 120) %></p>
|
|
36
36
|
<% end %>
|
|
37
|
-
<div class="ck-endpoint ck-endpoint--compact"
|
|
37
|
+
<div class="ck-endpoint ck-endpoint--compact" data-ck-row-ignore>
|
|
38
38
|
<code class="ck-endpoint__url" id="prompt_endpoint_<%= prompt.id %>"><%= api_v1_prompt_path(prompt.slug) %></code>
|
|
39
|
-
<button type="button" class="ck-icon-btn" title="Copy API path"
|
|
39
|
+
<button type="button" class="ck-icon-btn" title="Copy API path" data-ck-copy="prompt_endpoint_<%= prompt.id %>"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" width="13" height="13" aria-hidden="true"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"/><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"/></svg></button>
|
|
40
40
|
</div>
|
|
41
41
|
<% if prompt.tags.any? %>
|
|
42
42
|
<div class="tag-marks-row">
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<% end %>
|
|
17
17
|
<div class="ck-endpoint">
|
|
18
18
|
<code class="ck-endpoint__url" id="prompt_endpoint"><%= request.base_url %><%= api_v1_prompt_path(@prompt.slug) %></code>
|
|
19
|
-
<button type="button" class="ck-icon-btn" title="Copy endpoint" aria-label="Copy endpoint"
|
|
19
|
+
<button type="button" class="ck-icon-btn" title="Copy endpoint" aria-label="Copy endpoint" data-ck-copy="prompt_endpoint"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" width="14" height="14" aria-hidden="true"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"/><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"/></svg></button>
|
|
20
20
|
</div>
|
|
21
21
|
<p class="ck-meta-copy" id="prompt_serves">
|
|
22
22
|
<% if @serve_summary[:total].positive? %>
|
|
@@ -83,10 +83,10 @@
|
|
|
83
83
|
<% best_score = scoped_runs.map(&:avg_score).compact.max %>
|
|
84
84
|
<% best_pass_rate = scoped_runs.map(&:check_pass_rate).compact.max %>
|
|
85
85
|
<% pred = predecessor_of[v] %>
|
|
86
|
-
<tr class="<%= "ck-results-table__row--active" if v.id == @prompt.id %>"
|
|
86
|
+
<tr class="<%= "ck-results-table__row--active" if v.id == @prompt.id %>" data-ck-href="<%= prompt_path(v) %>" style="cursor: pointer;">
|
|
87
87
|
<td>
|
|
88
88
|
<div class="ck-version-cell">
|
|
89
|
-
<div class="ck-version-cell__label"
|
|
89
|
+
<div class="ck-version-cell__label" data-ck-row-ignore>
|
|
90
90
|
<%= link_to prompt_path(v), class: "ck-record-name" do %><strong>v<%= v.version_number %></strong><% end %>
|
|
91
91
|
<% if v.current? %>
|
|
92
92
|
<span class="ck-chip">Published</span>
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
<% end %>
|
|
96
96
|
</div>
|
|
97
97
|
<% if version_changed.call(v, pred) %>
|
|
98
|
-
<button type="button" class="ck-cell-link ck-cell-link--delta" title="What changed from v<%= pred.version_number %>" aria-label="What changed from v<%= pred.version_number %>"
|
|
98
|
+
<button type="button" class="ck-cell-link ck-cell-link--delta" title="What changed from v<%= pred.version_number %>" aria-label="What changed from v<%= pred.version_number %>" data-ck-dialog-open="ck-vdiff-<%= v.id %>"><span aria-hidden="true">Δ</span></button>
|
|
99
99
|
<% end %>
|
|
100
100
|
</div>
|
|
101
101
|
</td>
|
|
@@ -121,14 +121,14 @@
|
|
|
121
121
|
<% versions.each do |v| %>
|
|
122
122
|
<% pred = predecessor_of[v] %>
|
|
123
123
|
<% next unless version_changed.call(v, pred) %>
|
|
124
|
-
<dialog id="ck-vdiff-<%= v.id %>" class="ck-modal" aria-labelledby="ck-vdiff-title-<%= v.id %>"
|
|
125
|
-
<article class="ck-modal__panel" tabindex="-1" autofocus
|
|
124
|
+
<dialog id="ck-vdiff-<%= v.id %>" class="ck-modal" aria-labelledby="ck-vdiff-title-<%= v.id %>" data-ck-dialog>
|
|
125
|
+
<article class="ck-modal__panel" tabindex="-1" autofocus>
|
|
126
126
|
<header class="ck-modal__header">
|
|
127
127
|
<div class="ck-modal__heading">
|
|
128
128
|
<h2 class="ck-modal__title" id="ck-vdiff-title-<%= v.id %>">v<%= pred.version_number %> <span aria-hidden="true">→</span> v<%= v.version_number %></h2>
|
|
129
129
|
<span class="ck-modal__meta">What changed in <%= v.version_label %><% if v.current? %> (published)<% end %></span>
|
|
130
130
|
</div>
|
|
131
|
-
<button type="button" class="ck-modal__close" aria-label="Close"
|
|
131
|
+
<button type="button" class="ck-modal__close" aria-label="Close" data-ck-dialog-close>×</button>
|
|
132
132
|
</header>
|
|
133
133
|
<div class="ck-modal__body">
|
|
134
134
|
<% if pred.llm_model != v.llm_model %>
|
|
@@ -188,7 +188,7 @@
|
|
|
188
188
|
</thead>
|
|
189
189
|
<tbody>
|
|
190
190
|
<% suggestions.each do |s| %>
|
|
191
|
-
<tr
|
|
191
|
+
<tr data-ck-href="<%= suggestion_path(s, from: "prompt") %>" style="cursor: pointer;">
|
|
192
192
|
<td><%= link_to suggestion_path(s, from: "prompt"), class: "ck-record-name" do %><strong><%= s.run.name %></strong><% end %></td>
|
|
193
193
|
<td><span class="ck-chip ck-chip--soft"><%= s.prompt.version_label %></span></td>
|
|
194
194
|
<td class="ck-meta-copy"><%= truncate(ck_strip_markdown(s.reasoning), length: 100) %></td>
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<% if provider_credential.discovery_status == "completed" %>
|
|
17
17
|
<span class="ck-model-list__summary-stamp">updated <time data-relative-time datetime="<%= provider_credential.updated_at.utc.iso8601 %>"><%= time_ago_in_words(provider_credential.updated_at) %> ago</time></span>
|
|
18
18
|
<% end %>
|
|
19
|
-
<button type="button" class="ck-icon-btn ck-model-list__refresh<%= ' ck-icon-btn--spinning' if discovering %>" title="Refresh models" aria-label="Refresh available models" <%= 'disabled' if discovering %>
|
|
19
|
+
<button type="button" class="ck-icon-btn ck-model-list__refresh<%= ' ck-icon-btn--spinning' if discovering %>" title="Refresh models" aria-label="Refresh available models" <%= 'disabled' if discovering %> data-ck-provider-refresh="<%= refresh_provider_credential_path(provider_credential) %>">
|
|
20
20
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" width="13" height="13" aria-hidden="true"><path fill-rule="evenodd" d="M13.836 2.477a.75.75 0 0 1 .75.75v3.182a.75.75 0 0 1-.75.75h-3.182a.75.75 0 0 1 0-1.5h1.37l-.84-.841a4.5 4.5 0 0 0-7.08.681.75.75 0 0 1-1.264-.808 6 6 0 0 1 9.44-.908l.84.84V3.227a.75.75 0 0 1 .75-.75Zm-.911 7.5A.75.75 0 0 1 13.199 11a6 6 0 0 1-9.44.908l-.84-.84v1.68a.75.75 0 0 1-1.5 0V9.567a.75.75 0 0 1 .75-.75h3.182a.75.75 0 0 1 0 1.5h-1.37l.84.841a4.5 4.5 0 0 0 7.08-.681.75.75 0 0 1 1.024-.274Z" clip-rule="evenodd"/></svg>
|
|
21
21
|
</button>
|
|
22
22
|
</span>
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
<div class="ck-model-list__summary">
|
|
75
75
|
<span class="ck-model-list__summary-label">Available models <span class="ck-model-list__summary-count">0</span></span>
|
|
76
76
|
<span class="ck-model-list__summary-meta">
|
|
77
|
-
<button type="button" class="ck-icon-btn ck-model-list__refresh" title="Refresh models" aria-label="Refresh available models"
|
|
77
|
+
<button type="button" class="ck-icon-btn ck-model-list__refresh" title="Refresh models" aria-label="Refresh available models" data-ck-provider-refresh="<%= refresh_provider_credential_path(provider_credential) %>"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" width="13" height="13" aria-hidden="true"><path fill-rule="evenodd" d="M13.836 2.477a.75.75 0 0 1 .75.75v3.182a.75.75 0 0 1-.75.75h-3.182a.75.75 0 0 1 0-1.5h1.37l-.84-.841a4.5 4.5 0 0 0-7.08.681.75.75 0 0 1-1.264-.808 6 6 0 0 1 9.44-.908l.84.84V3.227a.75.75 0 0 1 .75-.75Zm-.911 7.5A.75.75 0 0 1 13.199 11a6 6 0 0 1-9.44.908l-.84-.84v1.68a.75.75 0 0 1-1.5 0V9.567a.75.75 0 0 1 .75-.75h3.182a.75.75 0 0 1 0 1.5h-1.37l.84.841a4.5 4.5 0 0 0 7.08-.681.75.75 0 0 1 1.024-.274Z" clip-rule="evenodd"/></svg></button>
|
|
78
78
|
</span>
|
|
79
79
|
</div>
|
|
80
80
|
<% end %>
|