completion-kit 0.5.25 → 0.5.27

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: 23d8d27292c7265cc9994f64cab9832952e3a2ce5617b621f1301bf13de2f40a
4
- data.tar.gz: 5955a65e338fec0c7d8492e53ead7c2b22eeb60cafff25343ac8addbee282cb3
3
+ metadata.gz: 7036ea465a5b70d324e3eec554e3adf62a63fc1ebfa93b91bc28cc675ddfc0c5
4
+ data.tar.gz: 7bb7393d08c9631609fbcd845e01db0152a926f36f7bfd82f463455a53350dbd
5
5
  SHA512:
6
- metadata.gz: 7f67e4055ecad48ac6ff18363fa1c2783af959b861c42086207c0dfef037625112989af4ba61da700e930fac74f7cb62d964945ad2fad8ea2b295d622c7d122a
7
- data.tar.gz: d1c6be8d93c2f784d7f6493dc1fc46cb751d7d77860515772d4c11ebf7578ea5405236d879cbaa160bfa2eb9873475a6ddf2c56aae9b93381f20d225935f5214
6
+ metadata.gz: 38e72b62b2426caf8197619088b5223fffeee27cfb784f2c16c5d9c58295ddea67b6375459d44a748d655a987658a95d244329f64add5a493cb745e8f04393dd
7
+ data.tar.gz: ae792a3bf6315da654ea760dd9f6c9d73abf90902e8eb3f72354ec9bf65aa2406bbd9a3160b07a4b6038371b6021652a3208fb7d2cb4abfea6633f0cb03cf9a5
@@ -3629,6 +3629,44 @@ table.ck-runs-table {
3629
3629
  white-space: nowrap;
3630
3630
  }
3631
3631
 
3632
+ /* List tables on a phone. A 4–6 column table can't fit a phone width, so each
3633
+ row becomes a stacked block — every cell on its own line, all content
3634
+ visible, nothing scrolling sideways and getting clipped. Placed after the
3635
+ base table rules so it wins on source order; the runs table overrides this
3636
+ with a tailored layout in the block below. */
3637
+ @media (max-width: 640px) {
3638
+ .ck-results-table,
3639
+ .ck-results-table tbody,
3640
+ .ck-results-table tr,
3641
+ .ck-results-table td {
3642
+ display: block;
3643
+ }
3644
+ .ck-results-table { overflow: hidden; }
3645
+ .ck-results-table thead { display: none; }
3646
+ .ck-results-table tr { padding: 0.85rem 0.3rem; }
3647
+ .ck-results-table td {
3648
+ width: auto !important;
3649
+ max-width: 100%;
3650
+ white-space: normal !important;
3651
+ padding: 0.3rem 0.3rem 0;
3652
+ }
3653
+ .ck-results-table td:first-child { padding-top: 0; }
3654
+ .ck-results-table td:empty { display: none; }
3655
+ .ck-results-table td.ck-results-table__arrow { display: none; }
3656
+ /* Each stacked cell carries the column name as a small label so a bare
3657
+ value ("10", "May 14") still reads clearly. */
3658
+ .ck-results-table td[data-label]::before {
3659
+ content: attr(data-label);
3660
+ display: block;
3661
+ margin-bottom: 0.12rem;
3662
+ font-family: var(--ck-mono);
3663
+ font-size: 0.62rem;
3664
+ letter-spacing: 0.07em;
3665
+ text-transform: uppercase;
3666
+ color: var(--ck-dim);
3667
+ }
3668
+ }
3669
+
3632
3670
  /* Runs table on a phone. Placed after the base .ck-runs-table rules so these
3633
3671
  win on source order. A 6-column table can't fit a phone, so each run row
3634
3672
  becomes a stacked block: the run name + sub-line take the full width on
@@ -4909,3 +4947,17 @@ a.tag-mark {
4909
4947
  color: var(--ck-dim);
4910
4948
  font-size: 0.7rem;
4911
4949
  }
4950
+
4951
+ /* On a phone the popover is anchored to a small mid-footer toggle, so a
4952
+ near-full-width panel spills off the left edge and clips the metric
4953
+ names. Pin it to the bottom of the viewport instead — a bottom sheet
4954
+ that spans the screen and can never clip. */
4955
+ @media (max-width: 640px) {
4956
+ .ck-flyout__panel {
4957
+ position: fixed;
4958
+ inset: auto 0.75rem 0.75rem 0.75rem;
4959
+ width: auto;
4960
+ max-width: none;
4961
+ max-height: 60vh;
4962
+ }
4963
+ }
@@ -1,3 +1,6 @@
1
+ require "ipaddr"
2
+ require "resolv"
3
+
1
4
  module CompletionKit
2
5
  class ProviderCredential < ApplicationRecord
3
6
  include Turbo::Broadcastable
@@ -24,6 +27,7 @@ module CompletionKit
24
27
 
25
28
  validates :provider, presence: true, inclusion: { in: PROVIDERS }
26
29
  validates :provider, tenant_scoped_uniqueness: true
30
+ validate :api_endpoint_not_internal
27
31
 
28
32
  after_save :enqueue_discovery
29
33
 
@@ -131,5 +135,33 @@ module CompletionKit
131
135
  CompletionKit::Engine.warm_routes!
132
136
  CompletionKit::ApplicationController.render(partial: partial, locals: locals)
133
137
  end
138
+
139
+ def api_endpoint_not_internal
140
+ return if api_endpoint.blank?
141
+
142
+ uri = safe_http_uri(api_endpoint)
143
+ unless uri
144
+ errors.add(:api_endpoint, "must be a valid http or https URL")
145
+ return
146
+ end
147
+
148
+ if endpoint_addresses(uri.host).any? { |ip| ip.private? || ip.link_local? }
149
+ errors.add(:api_endpoint, "must not point at a private or internal address")
150
+ end
151
+ end
152
+
153
+ def safe_http_uri(value)
154
+ uri = URI.parse(value.to_s.strip)
155
+ uri if uri.is_a?(URI::HTTP) && uri.host.present?
156
+ rescue URI::InvalidURIError
157
+ nil
158
+ end
159
+
160
+ def endpoint_addresses(host)
161
+ bare = host.delete_prefix("[").delete_suffix("]")
162
+ [IPAddr.new(bare)]
163
+ rescue IPAddr::InvalidAddressError
164
+ Resolv.getaddresses(host).map { |addr| IPAddr.new(addr) }
165
+ end
134
166
  end
135
167
  end
@@ -35,9 +35,9 @@
35
35
  </div>
36
36
  <% end %>
37
37
  </td>
38
- <td><%= dataset.row_count %></td>
39
- <td><%= dataset.runs.count %></td>
40
- <td class="ck-meta-copy"><time datetime="<%= dataset.created_at.iso8601 %>"><%= dataset.created_at.strftime("%b %-d, %Y") %></time></td>
38
+ <td data-label="Rows"><%= dataset.row_count %></td>
39
+ <td data-label="Used in"><%= dataset.runs.count %></td>
40
+ <td data-label="Created" class="ck-meta-copy"><time datetime="<%= dataset.created_at.iso8601 %>"><%= dataset.created_at.strftime("%b %-d, %Y") %></time></td>
41
41
  <td class="ck-results-table__arrow">&rarr;</td>
42
42
  </tr>
43
43
  <% end %>
@@ -39,8 +39,8 @@
39
39
  </div>
40
40
  <% end %>
41
41
  </td>
42
- <td class="ck-meta-copy"><div class="ck-clamp-2"><%= metric_group.description.presence || "—" %></div></td>
43
- <td>
42
+ <td data-label="Description" class="ck-meta-copy"><div class="ck-clamp-2"><%= metric_group.description.presence || "—" %></div></td>
43
+ <td data-label="Members">
44
44
  <% if metric_group.metrics.any? %>
45
45
  <div class="ck-mg-members">
46
46
  <% metric_group.metrics.each do |m| %>
@@ -34,8 +34,8 @@
34
34
  </div>
35
35
  <% end %>
36
36
  </td>
37
- <td class="ck-meta-copy"><div class="ck-clamp-2"><%= metric.instruction.presence || "—" %></div></td>
38
- <td>
37
+ <td data-label="Instruction" class="ck-meta-copy"><div class="ck-clamp-2"><%= metric.instruction.presence || "—" %></div></td>
38
+ <td data-label="In groups">
39
39
  <% groups = metric.metric_groups %>
40
40
  <% if groups.any? %>
41
41
  <div class="ck-metrics-table__groups">
@@ -9,7 +9,7 @@
9
9
  <%= truncate(response.response_text.to_s, length: 160) %>
10
10
  <% end %>
11
11
  </td>
12
- <td>
12
+ <td data-label="Metrics">
13
13
  <% scored_reviews = response.reviews.select { |r| r.ai_score.present? }.sort_by { |r| r.metric_name.to_s.downcase } %>
14
14
  <% if scored_reviews.any? %>
15
15
  <span class="ck-metric-bar ck-metric-bar--compact">
@@ -24,14 +24,14 @@
24
24
  <span class="ck-response-cell__dim">—</span>
25
25
  <% end %>
26
26
  </td>
27
- <td>
27
+ <td data-label="Avg score">
28
28
  <% if response.reviewed? %>
29
29
  <span class="<%= ck_badge_classes(ck_score_kind(response.score.to_f)) %>"><%= response.score %></span>
30
30
  <% else %>
31
31
  <span class="ck-response-cell__dim">—</span>
32
32
  <% end %>
33
33
  </td>
34
- <td>
34
+ <td data-label="Status">
35
35
  <% case response.status
36
36
  when "pending" %>
37
37
  <span class="ck-chip">Queued</span>
@@ -26,7 +26,7 @@
26
26
  <% breakdown = by_type.map { |(_, type), n| pluralize(n, type.demodulize.titleize.downcase) }.join(" · ") %>
27
27
  <tr onclick="window.location='<%= edit_tag_path(tag) %>'" style="cursor: pointer;">
28
28
  <td><span class="tag-mark tag-mark--lg" style="--mark-color: var(--tag-<%= tag.color %>);"><%= tag.name %></span></td>
29
- <td class="ck-meta-copy">
29
+ <td data-label="Applied to" class="ck-meta-copy">
30
30
  <% if count.zero? %>
31
31
  <span class="ck-tags-table__unused">Not used yet</span>
32
32
  <% else %>
@@ -1,3 +1,3 @@
1
1
  module CompletionKit
2
- VERSION = "0.5.25"
2
+ VERSION = "0.5.27"
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.25
4
+ version: 0.5.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damien Bastin