completion-kit 0.5.11 → 0.5.13

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: ed531ae29162bb91d2c463c3ff4eb20b5da469b9b7a21baddf5054a0ccc15041
4
- data.tar.gz: b86aea95b2e1cf73abf6514093565dc07b12dc0f4fe5c5c5c8b80db3fbdfa83d
3
+ metadata.gz: 0ec878fca14222f69bc34d85967b065b298ea669be11f60c49b52af13aefdfe5
4
+ data.tar.gz: 8211fc882175c1e69c52f2cba5a5e14668af4ddfc5784362252e8c051a59bee1
5
5
  SHA512:
6
- metadata.gz: 04ae500020e71d52c41073c36a6741bc47b94a06ceec6548720d6022a60ce7422be8a354d627c39a7be8174af2ce65219041c5d99ad175157c7bf4b4eaf8f056
7
- data.tar.gz: 261daeeb1555b3aecb8e2e18edb7f14ebdc37f974c2713ecbe12c43a281e8109edc45222be0f6039c325a0428e89c1c11a1a7104f0a36ace2b618fb2ef1cb7e8
6
+ metadata.gz: 2afc081fde8f6722aadee50f973bc1512be15e5cbd19913881f0f38f06df37fee4f1cdbda54cfcb230892e73df7b27f6fdf537ea71df7da49ddfba39d2c9f644
7
+ data.tar.gz: 02cfae669de0b9a1f7a10bbedd7eecda8d708802ff85c1d8c6a50368fb49385e43f19b388f2ea45313b90e14a3d53464688b897ad23378964cfb55103bd3a8c2
@@ -39,6 +39,7 @@
39
39
  }
40
40
 
41
41
  html {
42
+ color-scheme: dark;
42
43
  font-size: 18px;
43
44
  line-height: 1.5;
44
45
  scrollbar-gutter: stable;
@@ -1284,6 +1285,24 @@ tr:hover .ck-chip--publish {
1284
1285
  line-height: 1.75;
1285
1286
  }
1286
1287
 
1288
+ /* Scrollable code-block wrapper — caps height for big payloads. Inner
1289
+ <pre> drops its own border/radius so the wrapper owns the edge. We
1290
+ leave the scrollbar unstyled so it matches the browser/page scrollbar. */
1291
+ .ck-code-scroll-wrap {
1292
+ margin-top: 0.5rem;
1293
+ max-height: 28rem;
1294
+ overflow: auto;
1295
+ border: 1px solid var(--ck-line);
1296
+ border-radius: var(--ck-radius);
1297
+ background: var(--ck-bg-strong);
1298
+ }
1299
+ .ck-code-scroll-wrap > .ck-code {
1300
+ margin-top: 0;
1301
+ border: 0;
1302
+ border-radius: 0;
1303
+ background: transparent;
1304
+ }
1305
+
1287
1306
  .ck-note-box {
1288
1307
  background: var(--ck-surface-soft);
1289
1308
  border: 1px solid var(--ck-line);
@@ -1873,18 +1892,7 @@ tr:hover .ck-chip--publish {
1873
1892
  background: var(--ck-bg-strong);
1874
1893
  overflow: auto;
1875
1894
  max-height: 60vh;
1876
- scrollbar-width: thin;
1877
- scrollbar-color: var(--ck-line-strong) transparent;
1878
1895
  }
1879
- .ck-csv-table-wrap::-webkit-scrollbar { width: 10px; height: 10px; }
1880
- .ck-csv-table-wrap::-webkit-scrollbar-track { background: transparent; }
1881
- .ck-csv-table-wrap::-webkit-scrollbar-thumb {
1882
- background: var(--ck-line-strong);
1883
- border-radius: 5px;
1884
- border: 2px solid var(--ck-bg-strong);
1885
- }
1886
- .ck-csv-table-wrap::-webkit-scrollbar-thumb:hover { background: var(--ck-muted); }
1887
- .ck-csv-table-wrap::-webkit-scrollbar-corner { background: transparent; }
1888
1896
 
1889
1897
  .ck-modal__body .ck-csv-table-wrap {
1890
1898
  margin-top: 0;
@@ -3193,6 +3201,7 @@ a.ck-metric-group-pill {
3193
3201
  white-space: nowrap;
3194
3202
  }
3195
3203
 
3204
+
3196
3205
  .ck-runs-table th {
3197
3206
  vertical-align: middle;
3198
3207
  white-space: nowrap;
@@ -3204,21 +3213,44 @@ a.ck-metric-group-pill {
3204
3213
  padding-bottom: 0.7rem;
3205
3214
  }
3206
3215
 
3216
+ .ck-runs-table th:first-child,
3217
+ .ck-runs-table td:first-child {
3218
+ width: 1%;
3219
+ }
3220
+
3207
3221
  .ck-runs-table th:nth-child(n+2),
3208
3222
  .ck-runs-table td:nth-child(n+2) {
3209
3223
  width: 1%;
3210
3224
  white-space: nowrap;
3211
3225
  }
3212
3226
 
3227
+ .ck-runs-table th:last-child,
3228
+ .ck-runs-table td:last-child {
3229
+ width: auto;
3230
+ }
3231
+
3213
3232
  .ck-runs-table__identity {
3214
3233
  display: flex;
3215
3234
  flex-direction: column;
3216
3235
  gap: 0.25rem;
3217
3236
  min-width: 0;
3237
+ width: 27rem;
3238
+ max-width: 100%;
3218
3239
  }
3219
3240
 
3220
3241
  .ck-runs-table .ck-run-name {
3221
3242
  line-height: 1.2;
3243
+ display: flex;
3244
+ align-items: center;
3245
+ gap: 0.5rem;
3246
+ min-width: 0;
3247
+ }
3248
+
3249
+ .ck-runs-table .ck-run-name strong {
3250
+ overflow: hidden;
3251
+ text-overflow: ellipsis;
3252
+ white-space: nowrap;
3253
+ min-width: 0;
3222
3254
  }
3223
3255
 
3224
3256
  .ck-runs-table__config {
@@ -179,6 +179,18 @@ module CompletionKit
179
179
  ["tag", "tag-#{tag.color}", ("tag-outline" if outline)].compact.join(" ")
180
180
  end
181
181
 
182
+ def ck_format_maybe_json(text)
183
+ s = text.to_s
184
+ return s if s.strip.empty?
185
+ first = s.strip[0]
186
+ return s unless first == "{" || first == "["
187
+ begin
188
+ JSON.pretty_generate(JSON.parse(s))
189
+ rescue JSON::ParserError
190
+ s
191
+ end
192
+ end
193
+
182
194
  def tag_filter_url(base_path, selected, toggling)
183
195
  remaining = selected.reject { |t| t.id == toggling.id }
184
196
  next_set = selected.include?(toggling) ? remaining : remaining + [toggling]
@@ -1,8 +1,22 @@
1
1
  module CompletionKit
2
2
  # MCP session marker — one row per active client session, kept in the
3
3
  # database so sessions survive Puma restarts, deploys, and Rails.cache
4
- # eviction. Expired rows are opportunistically pruned on every new
5
- # session start, so the table stays bounded by recent activity.
4
+ # eviction.
5
+ #
6
+ # Two things to know about why every query goes through `unscoped`:
7
+ #
8
+ # 1. CompletionKit::ApplicationRecord applies the host app's tenant_scope as
9
+ # a default_scope. MCP sessions are per-CONNECTION, not per-tenant — the
10
+ # table has no organization_id column. Letting the tenant_scope into a
11
+ # session lookup turns "is this session live?" into either a SQL error
12
+ # (no such column) or a false negative (`WHERE 1=0`), which surfaces to
13
+ # the client as a spurious "Session not initialized" right after init.
14
+ # 2. `active?` slides expires_at forward when a session is more than halfway
15
+ # through its TTL, so an MCP connection that keeps making calls stays
16
+ # alive instead of expiring on the original 1-hour wall clock.
17
+ #
18
+ # Expired rows are opportunistically pruned on every new session start, so
19
+ # the table stays bounded by recent activity.
6
20
  class McpSession < ApplicationRecord
7
21
  self.table_name = "completion_kit_mcp_sessions"
8
22
 
@@ -10,20 +24,31 @@ module CompletionKit
10
24
 
11
25
  def self.start!
12
26
  prune_expired!
13
- create!(session_id: SecureRandom.uuid, expires_at: SESSION_TTL.from_now).session_id
27
+ unscoped.create!(session_id: SecureRandom.uuid, expires_at: SESSION_TTL.from_now).session_id
14
28
  end
15
29
 
16
30
  def self.active?(session_id)
17
31
  return false if session_id.blank?
18
- where(session_id: session_id).where("expires_at > ?", Time.current).exists?
32
+
33
+ row = unscoped.where(session_id: session_id).where("expires_at > ?", Time.current).first
34
+ return false unless row
35
+
36
+ slide_expiry(row)
37
+ true
19
38
  end
20
39
 
21
40
  def self.destroy_session(session_id)
22
- where(session_id: session_id).delete_all
41
+ unscoped.where(session_id: session_id).delete_all
23
42
  end
24
43
 
25
44
  def self.prune_expired!
26
- where("expires_at < ?", Time.current).delete_all
45
+ unscoped.where("expires_at < ?", Time.current).delete_all
46
+ end
47
+
48
+ def self.slide_expiry(row)
49
+ half_ttl_from_now = (SESSION_TTL / 2).from_now
50
+ return if row.expires_at > half_ttl_from_now
51
+ row.update_column(:expires_at, SESSION_TTL.from_now)
27
52
  end
28
53
  end
29
54
  end
@@ -67,7 +67,7 @@
67
67
 
68
68
  <section>
69
69
  <p class="ck-kicker">Input</p>
70
- <pre class="ck-code ck-code--dark"><%= begin; JSON.pretty_generate(JSON.parse(@response.input_data)); rescue; @response.input_data; end %></pre>
70
+ <div class="ck-code-scroll-wrap"><pre class="ck-code"><%= ck_format_maybe_json(@response.input_data) %></pre></div>
71
71
  </section>
72
72
 
73
73
  <section class="ck-card--spaced">
@@ -77,13 +77,13 @@
77
77
  <span class="ck-chip ck-chip--soft" style="text-transform: none;"><%= @run.prompt.llm_model %></span>
78
78
  <% end %>
79
79
  </div>
80
- <pre class="ck-code"><%= @response.response_text %></pre>
80
+ <div class="ck-code-scroll-wrap"><pre class="ck-code"><%= ck_format_maybe_json(@response.response_text) %></pre></div>
81
81
  </section>
82
82
 
83
83
  <% if @response.expected_output.present? %>
84
84
  <section class="ck-card--spaced">
85
85
  <p class="ck-kicker">Expected</p>
86
- <pre class="ck-code"><%= @response.expected_output %></pre>
86
+ <div class="ck-code-scroll-wrap"><pre class="ck-code"><%= ck_format_maybe_json(@response.expected_output) %></pre></div>
87
87
  </section>
88
88
  <% end %>
89
89
 
@@ -1,3 +1,3 @@
1
1
  module CompletionKit
2
- VERSION = "0.5.11"
2
+ VERSION = "0.5.13"
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.11
4
+ version: 0.5.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damien Bastin