completion-kit 0.5.7 → 0.5.8

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: 33daa5f930979539f0b757bd5ea85273b9620f90f3de0bf4d976c843cae24af5
4
- data.tar.gz: 3387de72acf76fbeac7d79628144ac9cb3782678cf186ad883d1978bceb4daee
3
+ metadata.gz: ea1ba2dec01de2f2ae45703edf5c0ab0b6d92845ec524729d7b71d5f5127143d
4
+ data.tar.gz: 8f99494d4d4037d11a004ccc5cfce7c5485aecd435617ba5fa2b7a9fc2c00c4c
5
5
  SHA512:
6
- metadata.gz: 3af6ed91c4c791859b41cddf24078fc0ecec5a79a5aa6ead1ff996c07f9173164693bea12ac223443ae33fcadb1499919734c112a453260f4e9e187cbd6cfd37
7
- data.tar.gz: cf05c70a638f3ba9c70657b9c4ab90154af4b5d15e44dbff80b00bd2fc5804e2f3c6313f22fba5283ab36d35adb6d218ec3e1792ee533191c1a7bb66eef59de6
6
+ metadata.gz: 7550c2197cc20827bbd93d4484c8ae1ae35106566f2494cf98d3fd7fecaab95a9b267fa36ef237c0593a0649c7fcbd8fb0efc27f052a0c93fd4120556296246d
7
+ data.tar.gz: 82d84167a4e64f8e0400e1af7a5b115b17db7d742d4a0cb64c667a6321ccad8f08b4004284c337a76d22377865cab6a0d3290fe1b2554044787c39702eeddfd9
@@ -36,33 +36,32 @@ function ckAutoFocusFirstError() {
36
36
 
37
37
  function ckRelativeTime(then) {
38
38
  var seconds = Math.round((Date.now() - then.getTime()) / 1000);
39
- if (seconds < 5) return "just now";
40
- if (seconds < 60) return "less than a minute";
39
+ if (seconds < 60) return "just now";
41
40
  var minutes = Math.round(seconds / 60);
42
- if (minutes < 60) return minutes === 1 ? "1 minute" : minutes + " minutes";
41
+ if (minutes < 60) return (minutes === 1 ? "1 minute" : minutes + " minutes") + " ago";
43
42
  var hours = Math.round(minutes / 60);
44
- if (hours < 24) return hours === 1 ? "about 1 hour" : "about " + hours + " hours";
43
+ if (hours < 24) return (hours === 1 ? "about 1 hour" : "about " + hours + " hours") + " ago";
45
44
  var days = Math.round(hours / 24);
46
- if (days < 30) return days === 1 ? "1 day" : days + " days";
45
+ if (days < 30) return (days === 1 ? "1 day" : days + " days") + " ago";
47
46
  var months = Math.round(days / 30);
48
- if (months < 12) return months === 1 ? "about 1 month" : "about " + months + " months";
47
+ if (months < 12) return (months === 1 ? "about 1 month" : "about " + months + " months") + " ago";
49
48
  var years = Math.round(days / 365);
50
- return years === 1 ? "about 1 year" : "about " + years + " years";
49
+ return (years === 1 ? "about 1 year" : "about " + years + " years") + " ago";
51
50
  }
52
51
 
53
52
  function ckRelativeTimeCompact(then) {
54
53
  var seconds = Math.round((Date.now() - then.getTime()) / 1000);
55
- if (seconds < 60) return "now";
54
+ if (seconds < 60) return "just now";
56
55
  var minutes = Math.round(seconds / 60);
57
- if (minutes < 60) return minutes + "m";
56
+ if (minutes < 60) return minutes + "m ago";
58
57
  var hours = Math.round(minutes / 60);
59
- if (hours < 24) return hours + "h";
58
+ if (hours < 24) return hours + "h ago";
60
59
  var days = Math.round(hours / 24);
61
- if (days < 30) return days + "d";
60
+ if (days < 30) return days + "d ago";
62
61
  var months = Math.round(days / 30);
63
- if (months < 12) return months + "mo";
62
+ if (months < 12) return months + "mo ago";
64
63
  var years = Math.round(days / 365);
65
- return years + "y";
64
+ return years + "y ago";
66
65
  }
67
66
 
68
67
  function ckTickRelativeTimes() {
@@ -2695,7 +2695,8 @@ select.ck-input {
2695
2695
  #ck-tab-responses:checked ~ .ck-api-tabs__nav label[for="ck-tab-responses"],
2696
2696
  #ck-tab-datasets:checked ~ .ck-api-tabs__nav label[for="ck-tab-datasets"],
2697
2697
  #ck-tab-metrics:checked ~ .ck-api-tabs__nav label[for="ck-tab-metrics"],
2698
- #ck-tab-criteria:checked ~ .ck-api-tabs__nav label[for="ck-tab-criteria"],
2698
+ #ck-tab-metric-groups:checked ~ .ck-api-tabs__nav label[for="ck-tab-metric-groups"],
2699
+ #ck-tab-tags:checked ~ .ck-api-tabs__nav label[for="ck-tab-tags"],
2699
2700
  #ck-tab-providers:checked ~ .ck-api-tabs__nav label[for="ck-tab-providers"] {
2700
2701
  color: var(--ck-accent);
2701
2702
  background: var(--ck-surface-soft);
@@ -2708,8 +2709,9 @@ select.ck-input {
2708
2709
  #ck-tab-responses:checked ~ .ck-api-tabs__panels .ck-api-tabs__panel:nth-child(4),
2709
2710
  #ck-tab-datasets:checked ~ .ck-api-tabs__panels .ck-api-tabs__panel:nth-child(5),
2710
2711
  #ck-tab-metrics:checked ~ .ck-api-tabs__panels .ck-api-tabs__panel:nth-child(6),
2711
- #ck-tab-criteria:checked ~ .ck-api-tabs__panels .ck-api-tabs__panel:nth-child(7),
2712
- #ck-tab-providers:checked ~ .ck-api-tabs__panels .ck-api-tabs__panel:nth-child(8) {
2712
+ #ck-tab-metric-groups:checked ~ .ck-api-tabs__panels .ck-api-tabs__panel:nth-child(7),
2713
+ #ck-tab-tags:checked ~ .ck-api-tabs__panels .ck-api-tabs__panel:nth-child(8),
2714
+ #ck-tab-providers:checked ~ .ck-api-tabs__panels .ck-api-tabs__panel:nth-child(9) {
2713
2715
  display: block;
2714
2716
  }
2715
2717
 
@@ -2741,7 +2743,8 @@ select.ck-input {
2741
2743
  #ck-tab-responses:checked ~ .ck-api-tabs__nav label[for="ck-tab-responses"],
2742
2744
  #ck-tab-datasets:checked ~ .ck-api-tabs__nav label[for="ck-tab-datasets"],
2743
2745
  #ck-tab-metrics:checked ~ .ck-api-tabs__nav label[for="ck-tab-metrics"],
2744
- #ck-tab-criteria:checked ~ .ck-api-tabs__nav label[for="ck-tab-criteria"],
2746
+ #ck-tab-metric-groups:checked ~ .ck-api-tabs__nav label[for="ck-tab-metric-groups"],
2747
+ #ck-tab-tags:checked ~ .ck-api-tabs__nav label[for="ck-tab-tags"],
2745
2748
  #ck-tab-providers:checked ~ .ck-api-tabs__nav label[for="ck-tab-providers"] {
2746
2749
  border-left-color: transparent;
2747
2750
  border-bottom-color: var(--ck-accent);
@@ -2753,9 +2756,11 @@ select.ck-input {
2753
2756
  }
2754
2757
 
2755
2758
  /* the metrics field stacks several sub-sections (hint, groups, divider, tag
2756
- filter, checkboxes) — give it more vertical breathing room than a plain field */
2759
+ filter, checkboxes) — give it more vertical breathing room than a plain field,
2760
+ and extra separation from the run-tags field that follows it */
2757
2761
  #metrics-field {
2758
2762
  gap: 0.85rem;
2763
+ margin-bottom: 1.25rem;
2759
2764
  }
2760
2765
 
2761
2766
  .ck-metric-groups {
@@ -50,7 +50,7 @@ module CompletionKit
50
50
  end
51
51
 
52
52
  def update
53
- if @run.responses.any?
53
+ if @run.responses.any? && run_generation_changed?
54
54
  attrs = run_params.except(:metric_ids).to_h
55
55
  attrs.delete("name") if attrs["name"].to_s == @run.name.to_s
56
56
  new_run = Run.create!(attrs.merge(status: "pending"))
@@ -162,5 +162,29 @@ module CompletionKit
162
162
  params.require(:run).permit(:name, :prompt_id, :dataset_id, :judge_model, :temperature, metric_ids: [], tag_names: [])
163
163
  end
164
164
 
165
+ # Editing a run that already has results forks a new run — but only when a
166
+ # field that affects generation or judging changed. Renaming or retagging is
167
+ # pure metadata and updates the run in place.
168
+ GENERATION_RUN_FIELDS = %i[prompt_id dataset_id judge_model temperature].freeze
169
+
170
+ def run_generation_changed?
171
+ GENERATION_RUN_FIELDS.each do |field|
172
+ next unless run_params.key?(field)
173
+ return true if normalize_run_field(field, run_params[field]) != normalize_run_field(field, @run.public_send(field))
174
+ end
175
+ return false unless params[:run].key?(:metric_ids)
176
+ Array(params[:run][:metric_ids]).map(&:to_i).reject(&:zero?).sort != @run.metric_ids.sort
177
+ end
178
+
179
+ def normalize_run_field(field, value)
180
+ s = value.to_s.strip
181
+ return nil if s.empty?
182
+ case field
183
+ when :temperature then s.to_f
184
+ when :prompt_id, :dataset_id then s.to_i
185
+ else s
186
+ end
187
+ end
188
+
165
189
  end
166
190
  end
@@ -3,29 +3,6 @@
3
3
  real_token = local_assigns.fetch(:real_token, nil)
4
4
  published_prompts = local_assigns.fetch(:published_prompts, [])
5
5
  %>
6
- <% if published_prompts.any? %>
7
- <div class="ck-api-prompts-section">
8
- <p class="ck-kicker">Your prompts</p>
9
- <% published_prompts.each do |p| %>
10
- <div class="ck-api-prompt-card">
11
- <div class="ck-api-prompt-card__top">
12
- <div>
13
- <strong class="ck-api-prompt-card__name"><%= p.name %></strong>
14
- <% if p.description.present? %>
15
- <p class="ck-api-prompt-card__desc"><%= p.description %></p>
16
- <% end %>
17
- </div>
18
- <span class="ck-chip" style="text-transform: none; flex-shrink: 0;"><%= p.llm_model %></span>
19
- </div>
20
- <div class="ck-api-prompt-card__url">
21
- <code class="ck-endpoint__url" id="prompt_ep_<%= p.id %>"><%= base_url %>/api/v1/prompts/<%= p.slug %></code>
22
- <button type="button" class="ck-icon-btn" title="Copy endpoint" aria-label="Copy endpoint URL" onclick="navigator.clipboard.writeText(document.getElementById('prompt_ep_<%= p.id %>').textContent)"><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
- </div>
24
- </div>
25
- <% end %>
26
- </div>
27
- <% end %>
28
-
29
6
  <div class="ck-api-tabs">
30
7
  <input type="radio" name="ck-api-tab" id="ck-tab-mcp" class="ck-api-tabs__radio" checked>
31
8
  <input type="radio" name="ck-api-tab" id="ck-tab-prompts" class="ck-api-tabs__radio">
@@ -109,6 +86,28 @@
109
86
  <p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/prompts/:id</p>
110
87
  <p class="ck-meta-copy">Get a single prompt by ID.</p>
111
88
  </div>
89
+ <% if published_prompts.any? %>
90
+ <div class="ck-api-endpoint" style="padding-top: 1rem;">
91
+ <p class="ck-kicker" style="margin-bottom: 0.5rem;">Your published prompts</p>
92
+ <% published_prompts.each do |p| %>
93
+ <div class="ck-api-prompt-card">
94
+ <div class="ck-api-prompt-card__top">
95
+ <div>
96
+ <strong class="ck-api-prompt-card__name"><%= p.name %></strong>
97
+ <% if p.description.present? %>
98
+ <p class="ck-api-prompt-card__desc"><%= p.description %></p>
99
+ <% end %>
100
+ </div>
101
+ <span class="ck-chip" style="text-transform: none; flex-shrink: 0;"><%= p.llm_model %></span>
102
+ </div>
103
+ <div class="ck-api-prompt-card__url">
104
+ <code class="ck-endpoint__url" id="prompt_ep_<%= p.id %>"><%= base_url %>/api/v1/prompts/<%= p.slug %></code>
105
+ <button type="button" class="ck-icon-btn" title="Copy endpoint" aria-label="Copy endpoint URL" onclick="navigator.clipboard.writeText(document.getElementById('prompt_ep_<%= p.id %>').textContent)"><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>
106
+ </div>
107
+ </div>
108
+ <% end %>
109
+ </div>
110
+ <% end %>
112
111
  <div class="ck-api-endpoint">
113
112
  <p class="ck-api-method"><span class="ck-chip ck-chip--soft">PATCH</span> /api/v1/prompts/:id</p>
114
113
  <p class="ck-meta-copy">Update a prompt. Accepts same params as create.</p>
@@ -66,7 +66,7 @@
66
66
  <span class="ck-prompts-table__runs-count"><%= family_runs.count %></span>
67
67
  <% last_run = family_runs.order(created_at: :desc).first %>
68
68
  <% if last_run %>
69
- <span class="ck-prompts-table__runs-when">last <time data-relative-time datetime="<%= last_run.created_at.utc.iso8601 %>"><%= time_ago_in_words(last_run.created_at) %></time> ago</span>
69
+ <span class="ck-prompts-table__runs-when">last <time data-relative-time datetime="<%= last_run.created_at.utc.iso8601 %>"><%= time_ago_in_words(last_run.created_at) %> ago</time></span>
70
70
  <% else %>
71
71
  <span class="ck-prompts-table__runs-when">never run</span>
72
72
  <% end %>
@@ -181,7 +181,7 @@
181
181
  <td><strong><%= s.run.name %></strong></td>
182
182
  <td class="ck-meta-copy"><%= truncate(s.reasoning.to_s, length: 100) %></td>
183
183
  <td><%= s.applied_at? ? content_tag(:span, "Applied", class: "ck-chip", style: "background: var(--ck-success-soft); color: var(--ck-success);") : "&mdash;".html_safe %></td>
184
- <td class="ck-meta-copy"><time data-relative-time datetime="<%= s.created_at.utc.iso8601 %>"><%= time_ago_in_words(s.created_at) %></time> ago</td>
184
+ <td class="ck-meta-copy"><time data-relative-time datetime="<%= s.created_at.utc.iso8601 %>"><%= time_ago_in_words(s.created_at) %> ago</time></td>
185
185
  <td class="ck-results-table__arrow">&rarr;</td>
186
186
  </tr>
187
187
  <% end %>
@@ -26,7 +26,7 @@
26
26
  </div>
27
27
  <% elsif provider_credential.discovery_status == "completed" && local_assigns.fetch(:show_completed, true) %>
28
28
  <div class="ck-discovery-bar ck-discovery-bar--completed">
29
- <div class="ck-discovery-bar__label">Available models list updated <time data-relative-time datetime="<%= provider_credential.updated_at.utc.iso8601 %>"><%= time_ago_in_words(provider_credential.updated_at) %></time> ago</div>
29
+ <div class="ck-discovery-bar__label">Available models list updated <time data-relative-time datetime="<%= provider_credential.updated_at.utc.iso8601 %>"><%= time_ago_in_words(provider_credential.updated_at) %> ago</time></div>
30
30
  </div>
31
31
  <% end %>
32
32
  </div>
@@ -15,7 +15,7 @@
15
15
  <span class="ck-model-list__summary-label">Available models <span class="ck-model-list__summary-count"><%= models.count %></span></span>
16
16
  <span class="ck-model-list__summary-meta">
17
17
  <% if provider_credential.discovery_status == "completed" %>
18
- <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) %></time> ago</span>
18
+ <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>
19
19
  <% end %>
20
20
  <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 %> onclick="event.preventDefault();event.stopPropagation();fetch('<%= refresh_provider_credential_path(provider_credential) %>', {method:'POST',headers:{'X-CSRF-Token':document.querySelector('meta[name=csrf-token]').content}})">
21
21
  <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>
@@ -30,7 +30,7 @@
30
30
  <span><%= provider_credential.model_count %> models</span>
31
31
  <span><%= provider_credential.prompt_count %> prompts</span>
32
32
  <span><%= provider_credential.judge_count %> judges</span>
33
- <span><% if provider_credential.last_used_at %>Used <time data-relative-time datetime="<%= provider_credential.last_used_at.utc.iso8601 %>"><%= time_ago_in_words(provider_credential.last_used_at) %></time> ago<% else %>Never used<% end %></span>
33
+ <span><% if provider_credential.last_used_at %>Used <time data-relative-time datetime="<%= provider_credential.last_used_at.utc.iso8601 %>"><%= time_ago_in_words(provider_credential.last_used_at) %> ago</time><% else %>Never used<% end %></span>
34
34
  </div>
35
35
 
36
36
  <%= render "discovery_status", provider_credential: provider_credential %>
@@ -49,7 +49,7 @@
49
49
  <% end %>
50
50
  </td>
51
51
  <td class="ck-runs-table__when">
52
- <time data-relative-time datetime="<%= run.created_at.utc.iso8601 %>"><%= time_ago_in_words(run.created_at) %></time> ago
52
+ <time data-relative-time datetime="<%= run.created_at.utc.iso8601 %>"><%= time_ago_in_words(run.created_at) %> ago</time>
53
53
  </td>
54
54
  <td class="ck-results-table__arrow">&rarr;</td>
55
55
  </tr>
@@ -1,3 +1,3 @@
1
1
  module CompletionKit
2
- VERSION = "0.5.7"
2
+ VERSION = "0.5.8"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: completion-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.7
4
+ version: 0.5.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damien Bastin