completion-kit 0.5.6 → 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 +4 -4
- data/app/assets/javascripts/completion_kit/application.js +12 -13
- data/app/assets/stylesheets/completion_kit/application.css +17 -6
- data/app/controllers/completion_kit/runs_controller.rb +31 -1
- data/app/helpers/completion_kit/application_helper.rb +6 -0
- data/app/services/completion_kit/worker_health.rb +4 -1
- data/app/views/completion_kit/api_reference/_authentication.html.erb +11 -0
- data/app/views/completion_kit/api_reference/_body.html.erb +310 -0
- data/app/views/completion_kit/api_reference/index.html.erb +6 -324
- data/app/views/completion_kit/prompts/index.html.erb +1 -1
- data/app/views/completion_kit/prompts/show.html.erb +1 -1
- data/app/views/completion_kit/provider_credentials/_discovery_status.html.erb +1 -1
- data/app/views/completion_kit/provider_credentials/_models_card.html.erb +1 -1
- data/app/views/completion_kit/provider_credentials/index.html.erb +1 -1
- data/app/views/completion_kit/runs/_row.html.erb +1 -1
- data/app/views/completion_kit/tags/_picker.html.erb +1 -1
- data/lib/completion_kit/version.rb +1 -1
- data/lib/completion_kit.rb +3 -0
- data/lib/generators/completion_kit/templates/initializer.rb +4 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ea1ba2dec01de2f2ae45703edf5c0ab0b6d92845ec524729d7b71d5f5127143d
|
|
4
|
+
data.tar.gz: 8f99494d4d4037d11a004ccc5cfce7c5485aecd435617ba5fa2b7a9fc2c00c4c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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 <
|
|
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-
|
|
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-
|
|
2712
|
-
#ck-tab-
|
|
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-
|
|
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);
|
|
@@ -2752,9 +2755,17 @@ select.ck-input {
|
|
|
2752
2755
|
}
|
|
2753
2756
|
}
|
|
2754
2757
|
|
|
2758
|
+
/* the metrics field stacks several sub-sections (hint, groups, divider, tag
|
|
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 */
|
|
2761
|
+
#metrics-field {
|
|
2762
|
+
gap: 0.85rem;
|
|
2763
|
+
margin-bottom: 1.25rem;
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2755
2766
|
.ck-metric-groups {
|
|
2756
2767
|
display: grid;
|
|
2757
|
-
gap: 0.
|
|
2768
|
+
gap: 0.55rem;
|
|
2758
2769
|
margin-bottom: 0.5rem;
|
|
2759
2770
|
}
|
|
2760
2771
|
|
|
@@ -2770,7 +2781,7 @@ select.ck-input {
|
|
|
2770
2781
|
.ck-metric-groups__row {
|
|
2771
2782
|
display: flex;
|
|
2772
2783
|
flex-wrap: wrap;
|
|
2773
|
-
gap: 0.
|
|
2784
|
+
gap: 0.5rem;
|
|
2774
2785
|
}
|
|
2775
2786
|
|
|
2776
2787
|
.ck-metric-group-pill {
|
|
@@ -28,6 +28,11 @@ module CompletionKit
|
|
|
28
28
|
|
|
29
29
|
def new
|
|
30
30
|
@run = Run.new(prompt_id: params[:prompt_id])
|
|
31
|
+
prompt = Prompt.find_by(id: @run.prompt_id)
|
|
32
|
+
if prompt
|
|
33
|
+
last_run = Run.where(prompt_id: prompt.family_versions.ids).order(created_at: :desc).first
|
|
34
|
+
@run.tag_names = last_run.tag_names if last_run
|
|
35
|
+
end
|
|
31
36
|
end
|
|
32
37
|
|
|
33
38
|
def edit
|
|
@@ -45,7 +50,7 @@ module CompletionKit
|
|
|
45
50
|
end
|
|
46
51
|
|
|
47
52
|
def update
|
|
48
|
-
if @run.responses.any?
|
|
53
|
+
if @run.responses.any? && run_generation_changed?
|
|
49
54
|
attrs = run_params.except(:metric_ids).to_h
|
|
50
55
|
attrs.delete("name") if attrs["name"].to_s == @run.name.to_s
|
|
51
56
|
new_run = Run.create!(attrs.merge(status: "pending"))
|
|
@@ -79,6 +84,7 @@ module CompletionKit
|
|
|
79
84
|
dataset_id: @run.dataset_id,
|
|
80
85
|
judge_model: @run.judge_model,
|
|
81
86
|
temperature: @run.temperature,
|
|
87
|
+
tag_names: @run.tag_names,
|
|
82
88
|
status: "pending"
|
|
83
89
|
)
|
|
84
90
|
new_run.replace_metrics!(@run.metric_ids)
|
|
@@ -156,5 +162,29 @@ module CompletionKit
|
|
|
156
162
|
params.require(:run).permit(:name, :prompt_id, :dataset_id, :judge_model, :temperature, metric_ids: [], tag_names: [])
|
|
157
163
|
end
|
|
158
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
|
+
|
|
159
189
|
end
|
|
160
190
|
end
|
|
@@ -72,6 +72,12 @@ module CompletionKit
|
|
|
72
72
|
CompletionKit::ProviderCredential::PROVIDER_LABELS[provider.to_s] || provider.to_s.titleize
|
|
73
73
|
end
|
|
74
74
|
|
|
75
|
+
def ck_masked_token(token)
|
|
76
|
+
return "YOUR_TOKEN" if token.blank?
|
|
77
|
+
return "••••••••" if token.length < 12
|
|
78
|
+
"#{token[0..3]}#{'•' * [token.length - 8, 4].max}#{token[-4..]}"
|
|
79
|
+
end
|
|
80
|
+
|
|
75
81
|
OPENAI_MODEL_FAMILY_ORDER = ["GPT-5", "GPT-4", "o-series", "GPT-3.5", "GPT-OSS", "Other"].freeze
|
|
76
82
|
|
|
77
83
|
def ck_openai_model_family(model_id)
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
module CompletionKit
|
|
2
2
|
class WorkerHealth
|
|
3
|
-
|
|
3
|
+
# SolidQueue workers heartbeat every SolidQueue.process_heartbeat_interval
|
|
4
|
+
# (60s by default), so a 30s window flagged healthy workers as down between
|
|
5
|
+
# beats. Allow two missed heartbeats before we say the worker is gone.
|
|
6
|
+
HEARTBEAT_THRESHOLD = 2.minutes
|
|
4
7
|
|
|
5
8
|
def self.healthy?
|
|
6
9
|
return true unless defined?(::SolidQueue::Process)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<% if token.present? %>
|
|
2
|
+
<% masked = ck_masked_token(token) %>
|
|
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" onclick="ckToggleToken(this)" 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" onclick="var b=this;navigator.clipboard.writeText('<%= token %>').then(function(){b.classList.add('ck-api-copy--done');setTimeout(function(){b.classList.remove('ck-api-copy--done')},1500)})">
|
|
6
|
+
<%= heroicon_tag "clipboard-document", variant: :outline, size: 14, "aria-hidden": "true" %>
|
|
7
|
+
</button>
|
|
8
|
+
</div>
|
|
9
|
+
<% else %>
|
|
10
|
+
<p class="ck-meta-copy">No API token configured. Set <code>COMPLETION_KIT_API_TOKEN</code> to enable API access.</p>
|
|
11
|
+
<% end %>
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
<%
|
|
2
|
+
token = local_assigns.fetch(:token, "YOUR_TOKEN")
|
|
3
|
+
real_token = local_assigns.fetch(:real_token, nil)
|
|
4
|
+
published_prompts = local_assigns.fetch(:published_prompts, [])
|
|
5
|
+
%>
|
|
6
|
+
<div class="ck-api-tabs">
|
|
7
|
+
<input type="radio" name="ck-api-tab" id="ck-tab-mcp" class="ck-api-tabs__radio" checked>
|
|
8
|
+
<input type="radio" name="ck-api-tab" id="ck-tab-prompts" class="ck-api-tabs__radio">
|
|
9
|
+
<input type="radio" name="ck-api-tab" id="ck-tab-runs" class="ck-api-tabs__radio">
|
|
10
|
+
<input type="radio" name="ck-api-tab" id="ck-tab-responses" class="ck-api-tabs__radio">
|
|
11
|
+
<input type="radio" name="ck-api-tab" id="ck-tab-datasets" class="ck-api-tabs__radio">
|
|
12
|
+
<input type="radio" name="ck-api-tab" id="ck-tab-metrics" class="ck-api-tabs__radio">
|
|
13
|
+
<input type="radio" name="ck-api-tab" id="ck-tab-metric-groups" class="ck-api-tabs__radio">
|
|
14
|
+
<input type="radio" name="ck-api-tab" id="ck-tab-tags" class="ck-api-tabs__radio">
|
|
15
|
+
<input type="radio" name="ck-api-tab" id="ck-tab-providers" class="ck-api-tabs__radio">
|
|
16
|
+
|
|
17
|
+
<nav class="ck-api-tabs__nav">
|
|
18
|
+
<label for="ck-tab-mcp" class="ck-api-tabs__label">MCP <span class="ck-api-tabs__count">35</span></label>
|
|
19
|
+
<label for="ck-tab-prompts" class="ck-api-tabs__label">Prompts <span class="ck-api-tabs__count">6</span></label>
|
|
20
|
+
<label for="ck-tab-runs" class="ck-api-tabs__label">Runs <span class="ck-api-tabs__count">7</span></label>
|
|
21
|
+
<label for="ck-tab-responses" class="ck-api-tabs__label">Responses <span class="ck-api-tabs__count">2</span></label>
|
|
22
|
+
<label for="ck-tab-datasets" class="ck-api-tabs__label">Datasets <span class="ck-api-tabs__count">5</span></label>
|
|
23
|
+
<label for="ck-tab-metrics" class="ck-api-tabs__label">Metrics <span class="ck-api-tabs__count">5</span></label>
|
|
24
|
+
<label for="ck-tab-metric-groups" class="ck-api-tabs__label">Metric Groups <span class="ck-api-tabs__count">5</span></label>
|
|
25
|
+
<label for="ck-tab-tags" class="ck-api-tabs__label">Tags <span class="ck-api-tabs__count">5</span></label>
|
|
26
|
+
<label for="ck-tab-providers" class="ck-api-tabs__label">Providers <span class="ck-api-tabs__count">5</span></label>
|
|
27
|
+
</nav>
|
|
28
|
+
|
|
29
|
+
<div class="ck-api-tabs__panels">
|
|
30
|
+
|
|
31
|
+
<div class="ck-api-tabs__panel">
|
|
32
|
+
<h2 class="ck-section-title">MCP Server</h2>
|
|
33
|
+
<p class="ck-copy">Connect Claude Code, Cursor, or any <a href="https://modelcontextprotocol.io" class="ck-link">MCP</a> client to manage prompts, runs, datasets, and metrics conversationally. 35 tools over streamable HTTP.</p>
|
|
34
|
+
|
|
35
|
+
<div class="ck-mcp-install-grid">
|
|
36
|
+
<div class="ck-mcp-install-card">
|
|
37
|
+
<div class="ck-mcp-install-card__header">
|
|
38
|
+
<span class="ck-mcp-install-card__icon">▶</span>
|
|
39
|
+
Claude Code
|
|
40
|
+
</div>
|
|
41
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "claude mcp add completion-kit \\\n --transport http \\\n --url #{base_url}/mcp \\\n --header \"Authorization: Bearer #{token}\"" %>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="ck-mcp-install-card">
|
|
44
|
+
<div class="ck-mcp-install-card__header">
|
|
45
|
+
<span class="ck-mcp-install-card__icon">{}</span>
|
|
46
|
+
Cursor / Generic
|
|
47
|
+
</div>
|
|
48
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "{\n \"mcpServers\": {\n \"completion-kit\": {\n \"url\": \"#{base_url}/mcp\",\n \"headers\": {\n \"Authorization\": \"Bearer #{token}\"\n }\n }\n }\n}" %>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<div class="ck-api-endpoint" style="padding-top: 1.5rem;">
|
|
53
|
+
<p class="ck-kicker" style="margin-bottom: 0.75rem;">Available tools</p>
|
|
54
|
+
<% grouped = CompletionKit::McpDispatcher.tool_definitions.group_by { |t| t[:name].split("_").first } %>
|
|
55
|
+
<% grouped.each do |group, tools| %>
|
|
56
|
+
<div class="ck-mcp-tool-group">
|
|
57
|
+
<p class="ck-mcp-tool-group__label"><%= group %> <span class="ck-api-tabs__count"><%= tools.size %></span></p>
|
|
58
|
+
<div class="ck-mcp-tools">
|
|
59
|
+
<% tools.each do |tool| %>
|
|
60
|
+
<div class="ck-mcp-tool">
|
|
61
|
+
<code class="ck-mcp-tool__name"><%= tool[:name] %></code>
|
|
62
|
+
<span class="ck-mcp-tool__desc"><%= tool[:description] %></span>
|
|
63
|
+
</div>
|
|
64
|
+
<% end %>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
<% end %>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div class="ck-api-tabs__panel">
|
|
72
|
+
<h2 class="ck-section-title">Prompts</h2>
|
|
73
|
+
<p class="ck-copy">Create, version, and manage LLM prompt templates.</p>
|
|
74
|
+
<div class="ck-api-endpoint">
|
|
75
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/prompts</p>
|
|
76
|
+
<p class="ck-meta-copy">List all prompts, ordered by most recent.</p>
|
|
77
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "curl #{base_url}/api/v1/prompts \\\n -H \"Authorization: Bearer #{token}\"" %>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="ck-api-endpoint">
|
|
80
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/prompts</p>
|
|
81
|
+
<p class="ck-meta-copy">Create a new prompt.</p>
|
|
82
|
+
<p class="ck-api-params"><strong>Required:</strong> <code>name</code>, <code>template</code>, <code>llm_model</code> <strong>Optional:</strong> <code>description</code></p>
|
|
83
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "curl -X POST #{base_url}/api/v1/prompts \\\n -H \"Authorization: Bearer #{token}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"name\": \"summarizer\", \"template\": \"Summarize: {{text}}\", \"llm_model\": \"gpt-4.1\"}'" %>
|
|
84
|
+
</div>
|
|
85
|
+
<div class="ck-api-endpoint">
|
|
86
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/prompts/:id</p>
|
|
87
|
+
<p class="ck-meta-copy">Get a single prompt by ID.</p>
|
|
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 %>
|
|
111
|
+
<div class="ck-api-endpoint">
|
|
112
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">PATCH</span> /api/v1/prompts/:id</p>
|
|
113
|
+
<p class="ck-meta-copy">Update a prompt. Accepts same params as create.</p>
|
|
114
|
+
</div>
|
|
115
|
+
<div class="ck-api-endpoint">
|
|
116
|
+
<p class="ck-api-method"><span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/prompts/:id</p>
|
|
117
|
+
<p class="ck-meta-copy">Delete a prompt. Returns 204 No Content.</p>
|
|
118
|
+
</div>
|
|
119
|
+
<div class="ck-api-endpoint">
|
|
120
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/prompts/:id/publish</p>
|
|
121
|
+
<p class="ck-meta-copy">Publish a prompt version, making it the current version in its family.</p>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<div class="ck-api-tabs__panel">
|
|
126
|
+
<h2 class="ck-section-title">Runs</h2>
|
|
127
|
+
<p class="ck-copy">Create runs, generate LLM responses, and judge them with metrics.</p>
|
|
128
|
+
<div class="ck-api-endpoint">
|
|
129
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/runs</p>
|
|
130
|
+
<p class="ck-meta-copy">List all runs with response counts and average scores.</p>
|
|
131
|
+
</div>
|
|
132
|
+
<div class="ck-api-endpoint">
|
|
133
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/runs</p>
|
|
134
|
+
<p class="ck-meta-copy">Create a new run.</p>
|
|
135
|
+
<p class="ck-api-params"><strong>Required:</strong> <code>prompt_id</code> <strong>Optional:</strong> <code>name</code>, <code>dataset_id</code>, <code>metric_ids</code>, <code>judge_model</code></p>
|
|
136
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "curl -X POST #{base_url}/api/v1/runs \\\n -H \"Authorization: Bearer #{token}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"prompt_id\": 1, \"dataset_id\": 1, \"metric_ids\": [1, 2]}'" %>
|
|
137
|
+
</div>
|
|
138
|
+
<div class="ck-api-endpoint">
|
|
139
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/runs/:id</p>
|
|
140
|
+
<p class="ck-meta-copy">Get a run with status, progress, response count, and average score.</p>
|
|
141
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "curl #{base_url}/api/v1/runs/1 \\\n -H \"Authorization: Bearer #{token}\"" %>
|
|
142
|
+
</div>
|
|
143
|
+
<div class="ck-api-endpoint">
|
|
144
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/runs/:id/generate</p>
|
|
145
|
+
<p class="ck-meta-copy">Start generating responses. Returns 202 Accepted. Poll the run to check progress.</p>
|
|
146
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "curl -X POST #{base_url}/api/v1/runs/1/generate \\\n -H \"Authorization: Bearer #{token}\"" %>
|
|
147
|
+
</div>
|
|
148
|
+
<div class="ck-api-endpoint">
|
|
149
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">PATCH</span> /api/v1/runs/:id</p>
|
|
150
|
+
<p class="ck-meta-copy">Update a run. Accepts same params as create.</p>
|
|
151
|
+
</div>
|
|
152
|
+
<div class="ck-api-endpoint">
|
|
153
|
+
<p class="ck-api-method"><span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/runs/:id</p>
|
|
154
|
+
<p class="ck-meta-copy">Delete a run and all its responses. Returns 204 No Content.</p>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<div class="ck-api-tabs__panel">
|
|
159
|
+
<h2 class="ck-section-title">Responses</h2>
|
|
160
|
+
<p class="ck-copy">Read-only access to generated responses and their review scores. Nested under runs.</p>
|
|
161
|
+
<div class="ck-api-endpoint">
|
|
162
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/runs/:run_id/responses</p>
|
|
163
|
+
<p class="ck-meta-copy">List all responses for a run, including nested review scores.</p>
|
|
164
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "curl #{base_url}/api/v1/runs/1/responses \\\n -H \"Authorization: Bearer #{token}\"" %>
|
|
165
|
+
</div>
|
|
166
|
+
<div class="ck-api-endpoint">
|
|
167
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/runs/:run_id/responses/:id</p>
|
|
168
|
+
<p class="ck-meta-copy">Get a single response with its review scores and feedback.</p>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
|
|
172
|
+
<div class="ck-api-tabs__panel">
|
|
173
|
+
<h2 class="ck-section-title">Datasets</h2>
|
|
174
|
+
<p class="ck-copy">Data used as input for runs.</p>
|
|
175
|
+
<div class="ck-api-endpoint">
|
|
176
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/datasets</p>
|
|
177
|
+
<p class="ck-meta-copy">List all datasets.</p>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="ck-api-endpoint">
|
|
180
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/datasets</p>
|
|
181
|
+
<p class="ck-meta-copy">Create a dataset.</p>
|
|
182
|
+
<p class="ck-api-params"><strong>Required:</strong> <code>name</code>, <code>csv_data</code></p>
|
|
183
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "curl -X POST #{base_url}/api/v1/datasets \\\n -H \"Authorization: Bearer #{token}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"name\": \"tickets\", \"csv_data\": \"text,expected_output\\\\nHello,Hi\"}'" %>
|
|
184
|
+
</div>
|
|
185
|
+
<div class="ck-api-endpoint">
|
|
186
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> <span class="ck-chip ck-chip--soft">PATCH</span> <span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/datasets/:id</p>
|
|
187
|
+
<p class="ck-meta-copy">Get, update, or delete a dataset.</p>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
|
|
191
|
+
<div class="ck-api-tabs__panel">
|
|
192
|
+
<h2 class="ck-section-title">Metrics</h2>
|
|
193
|
+
<p class="ck-copy">Scoring dimensions used by the judge model.</p>
|
|
194
|
+
<div class="ck-api-endpoint">
|
|
195
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/metrics</p>
|
|
196
|
+
<p class="ck-meta-copy">List all metrics.</p>
|
|
197
|
+
</div>
|
|
198
|
+
<div class="ck-api-endpoint">
|
|
199
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/metrics</p>
|
|
200
|
+
<p class="ck-meta-copy">Create a metric.</p>
|
|
201
|
+
<p class="ck-api-params"><strong>Required:</strong> <code>name</code> <strong>Optional:</strong> <code>instruction</code>, <code>rubric_bands</code> (array of {stars, description})</p>
|
|
202
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "curl -X POST #{base_url}/api/v1/metrics \\\n -H \"Authorization: Bearer #{token}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"name\": \"relevance\", \"instruction\": \"Is the response relevant?\"}'" %>
|
|
203
|
+
</div>
|
|
204
|
+
<div class="ck-api-endpoint">
|
|
205
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> <span class="ck-chip ck-chip--soft">PATCH</span> <span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/metrics/:id</p>
|
|
206
|
+
<p class="ck-meta-copy">Get, update, or delete a metric.</p>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
<div class="ck-api-tabs__panel">
|
|
211
|
+
<h2 class="ck-section-title">Metric Groups</h2>
|
|
212
|
+
<p class="ck-copy">Named groups of metrics you can apply to a run as a set.</p>
|
|
213
|
+
<div class="ck-api-endpoint">
|
|
214
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/metric_groups</p>
|
|
215
|
+
<p class="ck-meta-copy">List all metric groups with their metric IDs.</p>
|
|
216
|
+
</div>
|
|
217
|
+
<div class="ck-api-endpoint">
|
|
218
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/metric_groups</p>
|
|
219
|
+
<p class="ck-meta-copy">Create a metric group.</p>
|
|
220
|
+
<p class="ck-api-params"><strong>Required:</strong> <code>name</code> <strong>Optional:</strong> <code>description</code>, <code>metric_ids</code> (array)</p>
|
|
221
|
+
</div>
|
|
222
|
+
<div class="ck-api-endpoint">
|
|
223
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> <span class="ck-chip ck-chip--soft">PATCH</span> <span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/metric_groups/:id</p>
|
|
224
|
+
<p class="ck-meta-copy">Get, update, or delete a metric group. PATCH with <code>metric_ids</code> replaces all metric associations.</p>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
|
|
228
|
+
<div class="ck-api-tabs__panel">
|
|
229
|
+
<h2 class="ck-section-title">Tags</h2>
|
|
230
|
+
<p class="ck-copy">Domain labels you can attach to metrics, prompts, runs, and datasets. Tags are auto-assigned a color from a 10-color palette. Each index page can be filtered by one or more tags using <code>?tag[]=name</code> query params (OR semantics).</p>
|
|
231
|
+
<div class="ck-api-endpoint">
|
|
232
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/tags</p>
|
|
233
|
+
<p class="ck-meta-copy">List all tags with name and color.</p>
|
|
234
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "curl #{base_url}/api/v1/tags \\\n -H \"Authorization: Bearer #{token}\"" %>
|
|
235
|
+
</div>
|
|
236
|
+
<div class="ck-api-endpoint">
|
|
237
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/tags</p>
|
|
238
|
+
<p class="ck-meta-copy">Create a tag.</p>
|
|
239
|
+
<p class="ck-api-params"><strong>Required:</strong> <code>name</code></p>
|
|
240
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "curl -X POST #{base_url}/api/v1/tags \\\n -H \"Authorization: Bearer #{token}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"name\": \"real estate\"}'" %>
|
|
241
|
+
</div>
|
|
242
|
+
<div class="ck-api-endpoint">
|
|
243
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> <span class="ck-chip ck-chip--soft">PATCH</span> <span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/tags/:id</p>
|
|
244
|
+
<p class="ck-meta-copy">Get, update, or delete a tag. PATCH accepts <code>name</code>. DELETE returns 204 No Content and removes all taggings for this tag.</p>
|
|
245
|
+
</div>
|
|
246
|
+
<div class="ck-api-endpoint" style="padding-top: 1rem;">
|
|
247
|
+
<p class="ck-kicker" style="margin-bottom: 0.5rem;">Tagging resources</p>
|
|
248
|
+
<p class="ck-meta-copy">Metrics, prompts, runs, and datasets accept a <code>tag_names</code> array on their create and update endpoints. Passing a name that does not yet exist silently creates the tag. On PATCH, the list replaces all existing tags for that record (omit the field to leave tags unchanged).</p>
|
|
249
|
+
<%= render "completion_kit/api_reference/example", base_url: base_url, token: token, real_token: real_token, cmd: "curl -X POST #{base_url}/api/v1/metrics \\\n -H \"Authorization: Bearer #{token}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"name\": \"Accuracy\", \"tag_names\": [\"real estate\"]}'" %>
|
|
250
|
+
</div>
|
|
251
|
+
<div class="ck-api-endpoint" style="padding-top: 1rem;">
|
|
252
|
+
<p class="ck-kicker" style="margin-bottom: 0.5rem;">MCP tools</p>
|
|
253
|
+
<div class="ck-mcp-tools">
|
|
254
|
+
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_list</code><span class="ck-mcp-tool__desc">List all tags</span></div>
|
|
255
|
+
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_get</code><span class="ck-mcp-tool__desc">Get a tag by ID</span></div>
|
|
256
|
+
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_create</code><span class="ck-mcp-tool__desc">Create a tag (name required)</span></div>
|
|
257
|
+
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_update</code><span class="ck-mcp-tool__desc">Update a tag's name</span></div>
|
|
258
|
+
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_delete</code><span class="ck-mcp-tool__desc">Delete a tag and remove all its taggings</span></div>
|
|
259
|
+
</div>
|
|
260
|
+
<p class="ck-meta-copy" style="margin-top: 0.75rem;">The existing <code>metrics_create</code>, <code>metrics_update</code>, <code>prompts_create</code>, <code>prompts_update</code>, <code>runs_create</code>, <code>runs_update</code>, <code>datasets_create</code>, and <code>datasets_update</code> tools all accept a <code>tag_names</code> parameter with the same auto-create and replace semantics as the REST API.</p>
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
|
|
264
|
+
<div class="ck-api-tabs__panel">
|
|
265
|
+
<h2 class="ck-section-title">Provider Credentials</h2>
|
|
266
|
+
<p class="ck-copy">LLM provider API keys. The <code>api_key</code> field is write-only and never returned in responses.</p>
|
|
267
|
+
<div class="ck-api-endpoint">
|
|
268
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/provider_credentials</p>
|
|
269
|
+
<p class="ck-meta-copy">List all provider credentials (api_key excluded).</p>
|
|
270
|
+
</div>
|
|
271
|
+
<div class="ck-api-endpoint">
|
|
272
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/provider_credentials</p>
|
|
273
|
+
<p class="ck-meta-copy">Create a provider credential.</p>
|
|
274
|
+
<p class="ck-api-params"><strong>Required:</strong> <code>provider</code> (openai, anthropic, ollama, openrouter), <code>api_key</code> <strong>Optional:</strong> <code>api_endpoint</code></p>
|
|
275
|
+
</div>
|
|
276
|
+
<div class="ck-api-endpoint">
|
|
277
|
+
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> <span class="ck-chip ck-chip--soft">PATCH</span> <span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/provider_credentials/:id</p>
|
|
278
|
+
<p class="ck-meta-copy">Get, update, or delete a provider credential.</p>
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
|
|
282
|
+
</div>
|
|
283
|
+
</div>
|
|
284
|
+
|
|
285
|
+
<script>
|
|
286
|
+
function ckToggleToken(el) {
|
|
287
|
+
var showing = el.textContent === el.dataset.masked;
|
|
288
|
+
el.textContent = showing ? el.dataset.real : el.dataset.masked;
|
|
289
|
+
el.setAttribute('aria-pressed', showing ? 'true' : 'false');
|
|
290
|
+
el.setAttribute('aria-label', showing ? 'Hide API token' : 'Reveal API token');
|
|
291
|
+
navigator.clipboard.writeText(el.dataset.real).then(function() {
|
|
292
|
+
el.classList.add('ck-api-copy--done');
|
|
293
|
+
setTimeout(function() { el.classList.remove('ck-api-copy--done'); }, 1500);
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function ckCopyExample(btn) {
|
|
298
|
+
var pre = btn.closest('.ck-api-example').querySelector('pre');
|
|
299
|
+
var text = pre.textContent;
|
|
300
|
+
var realToken = btn.dataset.realToken;
|
|
301
|
+
var displayToken = btn.dataset.displayToken;
|
|
302
|
+
if (realToken && displayToken) {
|
|
303
|
+
text = text.split(displayToken).join(realToken);
|
|
304
|
+
}
|
|
305
|
+
navigator.clipboard.writeText(text).then(function() {
|
|
306
|
+
btn.classList.add('ck-api-copy--done');
|
|
307
|
+
setTimeout(function() { btn.classList.remove('ck-api-copy--done'); }, 1500);
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
</script>
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
<% token_display = if @token.present? && @token.length >= 12
|
|
2
|
-
"#{@token[0..3]}#{'•' * [@token.length - 8, 4].max}#{@token[-4..]}"
|
|
3
|
-
elsif @token.present?
|
|
4
|
-
"••••••••"
|
|
5
|
-
else
|
|
6
|
-
"YOUR_TOKEN"
|
|
7
|
-
end %>
|
|
8
|
-
|
|
9
1
|
<section class="ck-page-header">
|
|
10
2
|
<div>
|
|
11
3
|
<h1 class="ck-title">API</h1>
|
|
@@ -18,324 +10,14 @@ end %>
|
|
|
18
10
|
<div class="ck-split">
|
|
19
11
|
<div>
|
|
20
12
|
<p class="ck-kicker">Authentication</p>
|
|
21
|
-
|
|
22
|
-
<div style="display: flex; align-items: center; gap: 0.4rem; margin: 0.5rem 0;">
|
|
23
|
-
<button type="button" class="ck-chip ck-token-toggle" onclick="ckToggleToken(this)" data-masked="<%= token_display %>" data-real="<%= @token %>" aria-label="Reveal API token" aria-pressed="false" style="cursor: pointer;"><%= token_display %></button>
|
|
24
|
-
<button type="button" class="ck-icon-btn" title="Copy token" aria-label="Copy API token" onclick="var b=this;navigator.clipboard.writeText('<%= @token %>').then(function(){b.classList.add('ck-api-copy--done');setTimeout(function(){b.classList.remove('ck-api-copy--done')},1500)})">
|
|
25
|
-
<%= heroicon_tag "clipboard-document", variant: :outline, size: 14, "aria-hidden": "true" %>
|
|
26
|
-
</button>
|
|
27
|
-
</div>
|
|
28
|
-
<% else %>
|
|
29
|
-
<p class="ck-meta-copy">No API token configured. Set <code>COMPLETION_KIT_API_TOKEN</code> to enable API access.</p>
|
|
30
|
-
<% end %>
|
|
31
|
-
</div>
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
|
|
36
|
-
<% if @published_prompts.any? %>
|
|
37
|
-
<div class="ck-api-prompts-section">
|
|
38
|
-
<p class="ck-kicker">Your prompts</p>
|
|
39
|
-
<% @published_prompts.each do |p| %>
|
|
40
|
-
<div class="ck-api-prompt-card">
|
|
41
|
-
<div class="ck-api-prompt-card__top">
|
|
42
|
-
<div>
|
|
43
|
-
<strong class="ck-api-prompt-card__name"><%= p.name %></strong>
|
|
44
|
-
<% if p.description.present? %>
|
|
45
|
-
<p class="ck-api-prompt-card__desc"><%= p.description %></p>
|
|
46
|
-
<% end %>
|
|
47
|
-
</div>
|
|
48
|
-
<span class="ck-chip" style="text-transform: none; flex-shrink: 0;"><%= p.llm_model %></span>
|
|
49
|
-
</div>
|
|
50
|
-
<div class="ck-api-prompt-card__url">
|
|
51
|
-
<code class="ck-endpoint__url" id="prompt_ep_<%= p.id %>"><%= @base_url %>/api/v1/prompts/<%= p.slug %></code>
|
|
52
|
-
<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>
|
|
53
|
-
</div>
|
|
54
|
-
</div>
|
|
55
|
-
<% end %>
|
|
56
|
-
</div>
|
|
57
|
-
<% end %>
|
|
58
|
-
|
|
59
|
-
<div class="ck-api-tabs">
|
|
60
|
-
<input type="radio" name="ck-api-tab" id="ck-tab-mcp" class="ck-api-tabs__radio" checked>
|
|
61
|
-
<input type="radio" name="ck-api-tab" id="ck-tab-prompts" class="ck-api-tabs__radio">
|
|
62
|
-
<input type="radio" name="ck-api-tab" id="ck-tab-runs" class="ck-api-tabs__radio">
|
|
63
|
-
<input type="radio" name="ck-api-tab" id="ck-tab-responses" class="ck-api-tabs__radio">
|
|
64
|
-
<input type="radio" name="ck-api-tab" id="ck-tab-datasets" class="ck-api-tabs__radio">
|
|
65
|
-
<input type="radio" name="ck-api-tab" id="ck-tab-metrics" class="ck-api-tabs__radio">
|
|
66
|
-
<input type="radio" name="ck-api-tab" id="ck-tab-metric-groups" class="ck-api-tabs__radio">
|
|
67
|
-
<input type="radio" name="ck-api-tab" id="ck-tab-tags" class="ck-api-tabs__radio">
|
|
68
|
-
<input type="radio" name="ck-api-tab" id="ck-tab-providers" class="ck-api-tabs__radio">
|
|
69
|
-
|
|
70
|
-
<nav class="ck-api-tabs__nav">
|
|
71
|
-
<label for="ck-tab-mcp" class="ck-api-tabs__label">MCP <span class="ck-api-tabs__count">35</span></label>
|
|
72
|
-
<label for="ck-tab-prompts" class="ck-api-tabs__label">Prompts <span class="ck-api-tabs__count">6</span></label>
|
|
73
|
-
<label for="ck-tab-runs" class="ck-api-tabs__label">Runs <span class="ck-api-tabs__count">7</span></label>
|
|
74
|
-
<label for="ck-tab-responses" class="ck-api-tabs__label">Responses <span class="ck-api-tabs__count">2</span></label>
|
|
75
|
-
<label for="ck-tab-datasets" class="ck-api-tabs__label">Datasets <span class="ck-api-tabs__count">5</span></label>
|
|
76
|
-
<label for="ck-tab-metrics" class="ck-api-tabs__label">Metrics <span class="ck-api-tabs__count">5</span></label>
|
|
77
|
-
<label for="ck-tab-metric-groups" class="ck-api-tabs__label">Metric Groups <span class="ck-api-tabs__count">5</span></label>
|
|
78
|
-
<label for="ck-tab-tags" class="ck-api-tabs__label">Tags <span class="ck-api-tabs__count">5</span></label>
|
|
79
|
-
<label for="ck-tab-providers" class="ck-api-tabs__label">Providers <span class="ck-api-tabs__count">5</span></label>
|
|
80
|
-
</nav>
|
|
81
|
-
|
|
82
|
-
<div class="ck-api-tabs__panels">
|
|
83
|
-
|
|
84
|
-
<div class="ck-api-tabs__panel">
|
|
85
|
-
<h2 class="ck-section-title">MCP Server</h2>
|
|
86
|
-
<p class="ck-copy">Connect Claude Code, Cursor, or any <a href="https://modelcontextprotocol.io" class="ck-link">MCP</a> client to manage prompts, runs, datasets, and metrics conversationally. 35 tools over streamable HTTP.</p>
|
|
87
|
-
|
|
88
|
-
<div class="ck-mcp-install-grid">
|
|
89
|
-
<div class="ck-mcp-install-card">
|
|
90
|
-
<div class="ck-mcp-install-card__header">
|
|
91
|
-
<span class="ck-mcp-install-card__icon">▶</span>
|
|
92
|
-
Claude Code
|
|
93
|
-
</div>
|
|
94
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "claude mcp add completion-kit \\\n --transport http \\\n --url #{@base_url}/mcp \\\n --header \"Authorization: Bearer #{token_display}\"" %>
|
|
95
|
-
</div>
|
|
96
|
-
<div class="ck-mcp-install-card">
|
|
97
|
-
<div class="ck-mcp-install-card__header">
|
|
98
|
-
<span class="ck-mcp-install-card__icon">{}</span>
|
|
99
|
-
Cursor / Generic
|
|
100
|
-
</div>
|
|
101
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "{\n \"mcpServers\": {\n \"completion-kit\": {\n \"url\": \"#{@base_url}/mcp\",\n \"headers\": {\n \"Authorization\": \"Bearer #{token_display}\"\n }\n }\n }\n}" %>
|
|
102
|
-
</div>
|
|
103
|
-
</div>
|
|
104
|
-
|
|
105
|
-
<div class="ck-api-endpoint" style="padding-top: 1.5rem;">
|
|
106
|
-
<p class="ck-kicker" style="margin-bottom: 0.75rem;">Available tools</p>
|
|
107
|
-
<% grouped = CompletionKit::McpDispatcher.tool_definitions.group_by { |t| t[:name].split("_").first } %>
|
|
108
|
-
<% grouped.each do |group, tools| %>
|
|
109
|
-
<div class="ck-mcp-tool-group">
|
|
110
|
-
<p class="ck-mcp-tool-group__label"><%= group %> <span class="ck-api-tabs__count"><%= tools.size %></span></p>
|
|
111
|
-
<div class="ck-mcp-tools">
|
|
112
|
-
<% tools.each do |tool| %>
|
|
113
|
-
<div class="ck-mcp-tool">
|
|
114
|
-
<code class="ck-mcp-tool__name"><%= tool[:name] %></code>
|
|
115
|
-
<span class="ck-mcp-tool__desc"><%= tool[:description] %></span>
|
|
116
|
-
</div>
|
|
117
|
-
<% end %>
|
|
118
|
-
</div>
|
|
119
|
-
</div>
|
|
120
|
-
<% end %>
|
|
121
|
-
</div>
|
|
122
|
-
</div>
|
|
123
|
-
|
|
124
|
-
<div class="ck-api-tabs__panel">
|
|
125
|
-
<h2 class="ck-section-title">Prompts</h2>
|
|
126
|
-
<p class="ck-copy">Create, version, and manage LLM prompt templates.</p>
|
|
127
|
-
<div class="ck-api-endpoint">
|
|
128
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/prompts</p>
|
|
129
|
-
<p class="ck-meta-copy">List all prompts, ordered by most recent.</p>
|
|
130
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl #{@base_url}/api/v1/prompts \\\n -H \"Authorization: Bearer #{token_display}\"" %>
|
|
131
|
-
</div>
|
|
132
|
-
<div class="ck-api-endpoint">
|
|
133
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/prompts</p>
|
|
134
|
-
<p class="ck-meta-copy">Create a new prompt.</p>
|
|
135
|
-
<p class="ck-api-params"><strong>Required:</strong> <code>name</code>, <code>template</code>, <code>llm_model</code> <strong>Optional:</strong> <code>description</code></p>
|
|
136
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl -X POST #{@base_url}/api/v1/prompts \\\n -H \"Authorization: Bearer #{token_display}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"name\": \"summarizer\", \"template\": \"Summarize: {{text}}\", \"llm_model\": \"gpt-4.1\"}'" %>
|
|
137
|
-
</div>
|
|
138
|
-
<div class="ck-api-endpoint">
|
|
139
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/prompts/:id</p>
|
|
140
|
-
<p class="ck-meta-copy">Get a single prompt by ID.</p>
|
|
141
|
-
</div>
|
|
142
|
-
<div class="ck-api-endpoint">
|
|
143
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">PATCH</span> /api/v1/prompts/:id</p>
|
|
144
|
-
<p class="ck-meta-copy">Update a prompt. Accepts same params as create.</p>
|
|
145
|
-
</div>
|
|
146
|
-
<div class="ck-api-endpoint">
|
|
147
|
-
<p class="ck-api-method"><span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/prompts/:id</p>
|
|
148
|
-
<p class="ck-meta-copy">Delete a prompt. Returns 204 No Content.</p>
|
|
149
|
-
</div>
|
|
150
|
-
<div class="ck-api-endpoint">
|
|
151
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/prompts/:id/publish</p>
|
|
152
|
-
<p class="ck-meta-copy">Publish a prompt version, making it the current version in its family.</p>
|
|
153
|
-
</div>
|
|
154
|
-
</div>
|
|
155
|
-
|
|
156
|
-
<div class="ck-api-tabs__panel">
|
|
157
|
-
<h2 class="ck-section-title">Runs</h2>
|
|
158
|
-
<p class="ck-copy">Create runs, generate LLM responses, and judge them with metrics.</p>
|
|
159
|
-
<div class="ck-api-endpoint">
|
|
160
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/runs</p>
|
|
161
|
-
<p class="ck-meta-copy">List all runs with response counts and average scores.</p>
|
|
162
|
-
</div>
|
|
163
|
-
<div class="ck-api-endpoint">
|
|
164
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/runs</p>
|
|
165
|
-
<p class="ck-meta-copy">Create a new run.</p>
|
|
166
|
-
<p class="ck-api-params"><strong>Required:</strong> <code>prompt_id</code> <strong>Optional:</strong> <code>name</code>, <code>dataset_id</code>, <code>metric_ids</code>, <code>judge_model</code></p>
|
|
167
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl -X POST #{@base_url}/api/v1/runs \\\n -H \"Authorization: Bearer #{token_display}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"prompt_id\": 1, \"dataset_id\": 1, \"metric_ids\": [1, 2]}'" %>
|
|
168
|
-
</div>
|
|
169
|
-
<div class="ck-api-endpoint">
|
|
170
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/runs/:id</p>
|
|
171
|
-
<p class="ck-meta-copy">Get a run with status, progress, response count, and average score.</p>
|
|
172
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl #{@base_url}/api/v1/runs/1 \\\n -H \"Authorization: Bearer #{token_display}\"" %>
|
|
173
|
-
</div>
|
|
174
|
-
<div class="ck-api-endpoint">
|
|
175
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/runs/:id/generate</p>
|
|
176
|
-
<p class="ck-meta-copy">Start generating responses. Returns 202 Accepted. Poll the run to check progress.</p>
|
|
177
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl -X POST #{@base_url}/api/v1/runs/1/generate \\\n -H \"Authorization: Bearer #{token_display}\"" %>
|
|
178
|
-
</div>
|
|
179
|
-
<div class="ck-api-endpoint">
|
|
180
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">PATCH</span> /api/v1/runs/:id</p>
|
|
181
|
-
<p class="ck-meta-copy">Update a run. Accepts same params as create.</p>
|
|
182
|
-
</div>
|
|
183
|
-
<div class="ck-api-endpoint">
|
|
184
|
-
<p class="ck-api-method"><span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/runs/:id</p>
|
|
185
|
-
<p class="ck-meta-copy">Delete a run and all its responses. Returns 204 No Content.</p>
|
|
186
|
-
</div>
|
|
187
|
-
</div>
|
|
188
|
-
|
|
189
|
-
<div class="ck-api-tabs__panel">
|
|
190
|
-
<h2 class="ck-section-title">Responses</h2>
|
|
191
|
-
<p class="ck-copy">Read-only access to generated responses and their review scores. Nested under runs.</p>
|
|
192
|
-
<div class="ck-api-endpoint">
|
|
193
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/runs/:run_id/responses</p>
|
|
194
|
-
<p class="ck-meta-copy">List all responses for a run, including nested review scores.</p>
|
|
195
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl #{@base_url}/api/v1/runs/1/responses \\\n -H \"Authorization: Bearer #{token_display}\"" %>
|
|
196
|
-
</div>
|
|
197
|
-
<div class="ck-api-endpoint">
|
|
198
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/runs/:run_id/responses/:id</p>
|
|
199
|
-
<p class="ck-meta-copy">Get a single response with its review scores and feedback.</p>
|
|
200
|
-
</div>
|
|
201
|
-
</div>
|
|
202
|
-
|
|
203
|
-
<div class="ck-api-tabs__panel">
|
|
204
|
-
<h2 class="ck-section-title">Datasets</h2>
|
|
205
|
-
<p class="ck-copy">Data used as input for runs.</p>
|
|
206
|
-
<div class="ck-api-endpoint">
|
|
207
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/datasets</p>
|
|
208
|
-
<p class="ck-meta-copy">List all datasets.</p>
|
|
209
|
-
</div>
|
|
210
|
-
<div class="ck-api-endpoint">
|
|
211
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/datasets</p>
|
|
212
|
-
<p class="ck-meta-copy">Create a dataset.</p>
|
|
213
|
-
<p class="ck-api-params"><strong>Required:</strong> <code>name</code>, <code>csv_data</code></p>
|
|
214
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl -X POST #{@base_url}/api/v1/datasets \\\n -H \"Authorization: Bearer #{token_display}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"name\": \"tickets\", \"csv_data\": \"text,expected_output\\\\nHello,Hi\"}'" %>
|
|
215
|
-
</div>
|
|
216
|
-
<div class="ck-api-endpoint">
|
|
217
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> <span class="ck-chip ck-chip--soft">PATCH</span> <span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/datasets/:id</p>
|
|
218
|
-
<p class="ck-meta-copy">Get, update, or delete a dataset.</p>
|
|
219
|
-
</div>
|
|
220
|
-
</div>
|
|
221
|
-
|
|
222
|
-
<div class="ck-api-tabs__panel">
|
|
223
|
-
<h2 class="ck-section-title">Metrics</h2>
|
|
224
|
-
<p class="ck-copy">Scoring dimensions used by the judge model.</p>
|
|
225
|
-
<div class="ck-api-endpoint">
|
|
226
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/metrics</p>
|
|
227
|
-
<p class="ck-meta-copy">List all metrics.</p>
|
|
228
|
-
</div>
|
|
229
|
-
<div class="ck-api-endpoint">
|
|
230
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/metrics</p>
|
|
231
|
-
<p class="ck-meta-copy">Create a metric.</p>
|
|
232
|
-
<p class="ck-api-params"><strong>Required:</strong> <code>name</code> <strong>Optional:</strong> <code>instruction</code>, <code>rubric_bands</code> (array of {stars, description})</p>
|
|
233
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl -X POST #{@base_url}/api/v1/metrics \\\n -H \"Authorization: Bearer #{token_display}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"name\": \"relevance\", \"instruction\": \"Is the response relevant?\"}'" %>
|
|
234
|
-
</div>
|
|
235
|
-
<div class="ck-api-endpoint">
|
|
236
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> <span class="ck-chip ck-chip--soft">PATCH</span> <span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/metrics/:id</p>
|
|
237
|
-
<p class="ck-meta-copy">Get, update, or delete a metric.</p>
|
|
238
|
-
</div>
|
|
239
|
-
</div>
|
|
240
|
-
|
|
241
|
-
<div class="ck-api-tabs__panel">
|
|
242
|
-
<h2 class="ck-section-title">Metric Groups</h2>
|
|
243
|
-
<p class="ck-copy">Named groups of metrics you can apply to a run as a set.</p>
|
|
244
|
-
<div class="ck-api-endpoint">
|
|
245
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/metric_groups</p>
|
|
246
|
-
<p class="ck-meta-copy">List all metric groups with their metric IDs.</p>
|
|
247
|
-
</div>
|
|
248
|
-
<div class="ck-api-endpoint">
|
|
249
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/metric_groups</p>
|
|
250
|
-
<p class="ck-meta-copy">Create a metric group.</p>
|
|
251
|
-
<p class="ck-api-params"><strong>Required:</strong> <code>name</code> <strong>Optional:</strong> <code>description</code>, <code>metric_ids</code> (array)</p>
|
|
252
|
-
</div>
|
|
253
|
-
<div class="ck-api-endpoint">
|
|
254
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> <span class="ck-chip ck-chip--soft">PATCH</span> <span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/metric_groups/:id</p>
|
|
255
|
-
<p class="ck-meta-copy">Get, update, or delete a metric group. PATCH with <code>metric_ids</code> replaces all metric associations.</p>
|
|
256
|
-
</div>
|
|
257
|
-
</div>
|
|
258
|
-
|
|
259
|
-
<div class="ck-api-tabs__panel">
|
|
260
|
-
<h2 class="ck-section-title">Tags</h2>
|
|
261
|
-
<p class="ck-copy">Domain labels you can attach to metrics, prompts, runs, and datasets. Tags are auto-assigned a color from a 10-color palette. Each index page can be filtered by one or more tags using <code>?tag[]=name</code> query params (OR semantics).</p>
|
|
262
|
-
<div class="ck-api-endpoint">
|
|
263
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/tags</p>
|
|
264
|
-
<p class="ck-meta-copy">List all tags with name and color.</p>
|
|
265
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl #{@base_url}/api/v1/tags \\\n -H \"Authorization: Bearer #{token_display}\"" %>
|
|
266
|
-
</div>
|
|
267
|
-
<div class="ck-api-endpoint">
|
|
268
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/tags</p>
|
|
269
|
-
<p class="ck-meta-copy">Create a tag.</p>
|
|
270
|
-
<p class="ck-api-params"><strong>Required:</strong> <code>name</code></p>
|
|
271
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl -X POST #{@base_url}/api/v1/tags \\\n -H \"Authorization: Bearer #{token_display}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"name\": \"real estate\"}'" %>
|
|
272
|
-
</div>
|
|
273
|
-
<div class="ck-api-endpoint">
|
|
274
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> <span class="ck-chip ck-chip--soft">PATCH</span> <span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/tags/:id</p>
|
|
275
|
-
<p class="ck-meta-copy">Get, update, or delete a tag. PATCH accepts <code>name</code>. DELETE returns 204 No Content and removes all taggings for this tag.</p>
|
|
276
|
-
</div>
|
|
277
|
-
<div class="ck-api-endpoint" style="padding-top: 1rem;">
|
|
278
|
-
<p class="ck-kicker" style="margin-bottom: 0.5rem;">Tagging resources</p>
|
|
279
|
-
<p class="ck-meta-copy">Metrics, prompts, runs, and datasets accept a <code>tag_names</code> array on their create and update endpoints. Passing a name that does not yet exist silently creates the tag. On PATCH, the list replaces all existing tags for that record (omit the field to leave tags unchanged).</p>
|
|
280
|
-
<%= render "example", base_url: @base_url, token: token_display, real_token: @token, cmd: "curl -X POST #{@base_url}/api/v1/metrics \\\n -H \"Authorization: Bearer #{token_display}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"name\": \"Accuracy\", \"tag_names\": [\"real estate\"]}'" %>
|
|
281
|
-
</div>
|
|
282
|
-
<div class="ck-api-endpoint" style="padding-top: 1rem;">
|
|
283
|
-
<p class="ck-kicker" style="margin-bottom: 0.5rem;">MCP tools</p>
|
|
284
|
-
<div class="ck-mcp-tools">
|
|
285
|
-
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_list</code><span class="ck-mcp-tool__desc">List all tags</span></div>
|
|
286
|
-
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_get</code><span class="ck-mcp-tool__desc">Get a tag by ID</span></div>
|
|
287
|
-
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_create</code><span class="ck-mcp-tool__desc">Create a tag (name required)</span></div>
|
|
288
|
-
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_update</code><span class="ck-mcp-tool__desc">Update a tag's name</span></div>
|
|
289
|
-
<div class="ck-mcp-tool"><code class="ck-mcp-tool__name">tags_delete</code><span class="ck-mcp-tool__desc">Delete a tag and remove all its taggings</span></div>
|
|
290
|
-
</div>
|
|
291
|
-
<p class="ck-meta-copy" style="margin-top: 0.75rem;">The existing <code>metrics_create</code>, <code>metrics_update</code>, <code>prompts_create</code>, <code>prompts_update</code>, <code>runs_create</code>, <code>runs_update</code>, <code>datasets_create</code>, and <code>datasets_update</code> tools all accept a <code>tag_names</code> parameter with the same auto-create and replace semantics as the REST API.</p>
|
|
292
|
-
</div>
|
|
293
|
-
</div>
|
|
294
|
-
|
|
295
|
-
<div class="ck-api-tabs__panel">
|
|
296
|
-
<h2 class="ck-section-title">Provider Credentials</h2>
|
|
297
|
-
<p class="ck-copy">LLM provider API keys. The <code>api_key</code> field is write-only and never returned in responses.</p>
|
|
298
|
-
<div class="ck-api-endpoint">
|
|
299
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> /api/v1/provider_credentials</p>
|
|
300
|
-
<p class="ck-meta-copy">List all provider credentials (api_key excluded).</p>
|
|
301
|
-
</div>
|
|
302
|
-
<div class="ck-api-endpoint">
|
|
303
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">POST</span> /api/v1/provider_credentials</p>
|
|
304
|
-
<p class="ck-meta-copy">Create a provider credential.</p>
|
|
305
|
-
<p class="ck-api-params"><strong>Required:</strong> <code>provider</code> (openai, anthropic, ollama, openrouter), <code>api_key</code> <strong>Optional:</strong> <code>api_endpoint</code></p>
|
|
306
|
-
</div>
|
|
307
|
-
<div class="ck-api-endpoint">
|
|
308
|
-
<p class="ck-api-method"><span class="ck-chip ck-chip--soft">GET</span> <span class="ck-chip ck-chip--soft">PATCH</span> <span class="ck-chip" style="color: var(--ck-danger);">DELETE</span> /api/v1/provider_credentials/:id</p>
|
|
309
|
-
<p class="ck-meta-copy">Get, update, or delete a provider credential.</p>
|
|
13
|
+
<%= render CompletionKit.config.api_reference_authentication_partial, token: @token %>
|
|
310
14
|
</div>
|
|
311
15
|
</div>
|
|
312
|
-
|
|
313
16
|
</div>
|
|
314
17
|
</div>
|
|
315
18
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
el.setAttribute('aria-label', showing ? 'Hide API token' : 'Reveal API token');
|
|
322
|
-
navigator.clipboard.writeText(el.dataset.real).then(function() {
|
|
323
|
-
el.classList.add('ck-api-copy--done');
|
|
324
|
-
setTimeout(function() { el.classList.remove('ck-api-copy--done'); }, 1500);
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
function ckCopyExample(btn) {
|
|
329
|
-
var pre = btn.closest('.ck-api-example').querySelector('pre');
|
|
330
|
-
var text = pre.textContent;
|
|
331
|
-
var realToken = btn.dataset.realToken;
|
|
332
|
-
var displayToken = btn.dataset.displayToken;
|
|
333
|
-
if (realToken && displayToken) {
|
|
334
|
-
text = text.split(displayToken).join(realToken);
|
|
335
|
-
}
|
|
336
|
-
navigator.clipboard.writeText(text).then(function() {
|
|
337
|
-
btn.classList.add('ck-api-copy--done');
|
|
338
|
-
setTimeout(function() { btn.classList.remove('ck-api-copy--done'); }, 1500);
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
</script>
|
|
19
|
+
<%= render "completion_kit/api_reference/body",
|
|
20
|
+
base_url: @base_url,
|
|
21
|
+
token: ck_masked_token(@token),
|
|
22
|
+
real_token: @token,
|
|
23
|
+
published_prompts: @published_prompts %>
|
|
@@ -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)
|
|
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);") : "—".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)
|
|
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">→</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)
|
|
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)
|
|
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)
|
|
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)
|
|
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">→</td>
|
|
55
55
|
</tr>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<% label_text = local_assigns[:label].presence || "#{param_namespace.to_s.titleize} tags" %>
|
|
3
3
|
<%= label_tag "#{param_namespace}_tags", label_text, class: "ck-label" %>
|
|
4
4
|
<% all_tags = CompletionKit::Tag.order(:name) %>
|
|
5
|
-
<% selected_ids = record.persisted? ? record.tags.
|
|
5
|
+
<% selected_ids = (record.persisted? || record.tags.loaded?) ? record.tags.map(&:id) : [] %>
|
|
6
6
|
<div class="ck-tag-picker">
|
|
7
7
|
<% all_tags.each do |tag| %>
|
|
8
8
|
<% checked = selected_ids.include?(tag.id) %>
|
data/lib/completion_kit.rb
CHANGED
|
@@ -9,6 +9,7 @@ module CompletionKit
|
|
|
9
9
|
attr_accessor :judge_model, :high_quality_threshold, :medium_quality_threshold
|
|
10
10
|
attr_accessor :username, :password, :auth_strategy, :api_token
|
|
11
11
|
attr_accessor :tenant_scope, :tenant_scope_columns
|
|
12
|
+
attr_accessor :api_reference_authentication_partial
|
|
12
13
|
|
|
13
14
|
def initialize
|
|
14
15
|
@openai_api_key = ENV['OPENAI_API_KEY']
|
|
@@ -19,6 +20,8 @@ module CompletionKit
|
|
|
19
20
|
@judge_model = "gpt-4.1"
|
|
20
21
|
@high_quality_threshold = 4
|
|
21
22
|
@medium_quality_threshold = 3
|
|
23
|
+
|
|
24
|
+
@api_reference_authentication_partial = "completion_kit/api_reference/authentication"
|
|
22
25
|
end
|
|
23
26
|
|
|
24
27
|
def tenant_scope_columns
|
|
@@ -37,6 +37,10 @@ CompletionKit.configure do |config|
|
|
|
37
37
|
# API Authentication
|
|
38
38
|
# config.api_token = ENV['COMPLETION_KIT_API_TOKEN']
|
|
39
39
|
|
|
40
|
+
# API reference page: swap in your own Authentication card (e.g. a multi-tenant
|
|
41
|
+
# token-management panel). The partial receives a `token:` local.
|
|
42
|
+
# config.api_reference_authentication_partial = "my_app/api_token_panel"
|
|
43
|
+
|
|
40
44
|
# Web UI Authentication
|
|
41
45
|
# config.username = "admin"
|
|
42
46
|
# config.password = ENV['COMPLETION_KIT_PASSWORD']
|
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.
|
|
4
|
+
version: 0.5.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Damien Bastin
|
|
@@ -300,6 +300,8 @@ files:
|
|
|
300
300
|
- app/services/completion_kit/prompt_improvement_service.rb
|
|
301
301
|
- app/services/completion_kit/worker_health.rb
|
|
302
302
|
- app/validators/completion_kit/tenant_scoped_uniqueness_validator.rb
|
|
303
|
+
- app/views/completion_kit/api_reference/_authentication.html.erb
|
|
304
|
+
- app/views/completion_kit/api_reference/_body.html.erb
|
|
303
305
|
- app/views/completion_kit/api_reference/_example.html.erb
|
|
304
306
|
- app/views/completion_kit/api_reference/index.html.erb
|
|
305
307
|
- app/views/completion_kit/datasets/_form.html.erb
|