completion-kit 0.5.2 → 0.5.4

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: c4297341fb61c6ad9e3620ca8a197ad9fb658221993f127ff84ffa55345a6ecf
4
- data.tar.gz: 791113c93f8bcd305edc7708fbc1650191b5c7da3a9c84e33006ee5d0e13d935
3
+ metadata.gz: eb708ad1732ab18fac5f415ad90f53374832bd8e629ab2f1530e860a2eca6c03
4
+ data.tar.gz: 3e159d8c80601f791a8b5e9fcabea66c1755dfb1635d268efa104a0a17bd9eb1
5
5
  SHA512:
6
- metadata.gz: 90f6e6a6038e527add9ae96e1242605b8fca7ec6370bb4b8af394a292b3d3985bec4374371e7b07ea8003a36447ccec748252cdf4ae10d51f3bda347ac81103e
7
- data.tar.gz: 13cca6a9c7c4f6434514887554c8c1fc532eaeee286f616039edfe268ba73cc8bfa5d97e783939ec1278364e8c316d4fbdb3d4344302af29ba6bab34eb1ee2ff
6
+ metadata.gz: 2d6bb436f79222b66d6f12bb0cb82642eb9e50c48704bbea76fb6b47c3c3b65f665363a905b4d8e57062445ad31bee44ba65c901de2a07d716d231fdef59e7df
7
+ data.tar.gz: ba8c62309efc2f19d343c6744b47e1db25c2a64e3597f19f957bdfd971dac6ee5118fd7f2017c573799f04a5423ac030627ff91ec9785d77822bc22a9ba7d27b
data/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  </p>
4
4
 
5
5
  <p align="center">
6
+ <a href="https://badge.fury.io/rb/completion-kit"><img src="https://badge.fury.io/rb/completion-kit.svg" alt="Gem Version" /></a>
6
7
  <a href="https://github.com/homemade-software-inc/completion-kit/actions/workflows/ci.yml"><img src="https://github.com/homemade-software-inc/completion-kit/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
7
8
  <img src="https://img.shields.io/badge/coverage-100%25-brightgreen" alt="coverage" />
8
9
  </p>
@@ -15,19 +16,19 @@ It's the difference between "this prompt seems to work" and "this prompt scores
15
16
 
16
17
  **[completionkit.com](https://completionkit.com)** | **[RubyGems](https://rubygems.org/gems/completion-kit)**
17
18
 
18
- > **CompletionKit Cloud** is coming — hosted, managed CompletionKit with zero setup. Early access opening soon at [app.completionkit.com](https://app.completionkit.com).
19
-
20
- ![Prompts index](https://raw.githubusercontent.com/homemade-software-inc/completion-kit/main/docs/screenshots/prompts.png)
21
-
22
- ![Prompt detail with metrics and rubrics](https://raw.githubusercontent.com/homemade-software-inc/completion-kit/main/docs/screenshots/prompt-detail.png)
19
+ > **CompletionKit Cloud** — hosted, managed CompletionKit with zero setup. Same engine, run for you. See plans at [completionkit.com/pricing](https://completionkit.com/pricing).
23
20
 
24
21
  ![Test run with scored results](https://raw.githubusercontent.com/homemade-software-inc/completion-kit/main/docs/screenshots/test-run.png)
25
22
 
26
23
  ## Quick Start
27
24
 
28
- ### Run the standalone app
25
+ ### Use CompletionKit Cloud
26
+
27
+ The fastest way to start — no install, no servers to run. Sign up at [completionkit.com](https://completionkit.com) and you get the same engine you'd self-host, hosted for you. Best fit if you want to skip the Rails ops.
28
+
29
+ ### Or run the standalone app
29
30
 
30
- The fastest way to start. No existing Rails app needed.
31
+ Self-host the same engine. No existing Rails app needed.
31
32
 
32
33
  ```bash
33
34
  git clone https://github.com/homemade-software-inc/completion-kit.git
@@ -482,6 +482,7 @@ tr:hover .ck-chip--publish {
482
482
  display: inline-flex;
483
483
  align-items: center;
484
484
  justify-content: center;
485
+ gap: 0.4rem;
485
486
  min-height: 2rem;
486
487
  padding: 0.4rem 0.75rem;
487
488
  border: 1px solid transparent;
@@ -493,10 +494,18 @@ tr:hover .ck-chip--publish {
493
494
  letter-spacing: 0.04em;
494
495
  text-transform: uppercase;
495
496
  line-height: 1;
497
+ white-space: nowrap;
496
498
  cursor: pointer;
497
499
  transition: all 0.15s ease;
498
500
  }
499
501
 
502
+ .ck-magic-icon {
503
+ width: 1.1em;
504
+ height: 1.1em;
505
+ flex-shrink: 0;
506
+ color: var(--ck-warning);
507
+ }
508
+
500
509
  .ck-button:hover {
501
510
  transform: translateY(-1px);
502
511
  }
@@ -3778,3 +3787,312 @@ a.tag-mark {
3778
3787
  .ck-tag-filter__clear:hover { color: var(--ck-accent); }
3779
3788
 
3780
3789
 
3790
+ /* --- Onboarding / launch checklist --- */
3791
+ @keyframes ck-launch-rise {
3792
+ from { opacity: 0; transform: translateY(14px); }
3793
+ to { opacity: 1; transform: translateY(0); }
3794
+ }
3795
+
3796
+ .ck-launch {
3797
+ position: relative;
3798
+ max-width: 720px;
3799
+ margin: 1rem auto 4rem;
3800
+ padding-top: 1rem;
3801
+ }
3802
+
3803
+ .ck-launch__field {
3804
+ position: absolute;
3805
+ inset: -2rem -3rem auto -3rem;
3806
+ height: 300px;
3807
+ pointer-events: none;
3808
+ z-index: 0;
3809
+ background:
3810
+ radial-gradient(ellipse 70% 80% at 50% 0%, var(--ck-accent-soft) 0%, transparent 65%),
3811
+ repeating-linear-gradient(90deg, transparent 0 23px, rgba(148, 163, 184, 0.035) 23px 24px),
3812
+ repeating-linear-gradient(0deg, transparent 0 23px, rgba(148, 163, 184, 0.035) 23px 24px);
3813
+ -webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 100%);
3814
+ mask-image: linear-gradient(to bottom, #000 0%, transparent 100%);
3815
+ }
3816
+
3817
+ .ck-launch__header {
3818
+ position: relative;
3819
+ z-index: 1;
3820
+ text-align: center;
3821
+ margin-bottom: 2.25rem;
3822
+ animation: ck-launch-rise 0.5s ease both;
3823
+ }
3824
+
3825
+ .ck-launch__overline {
3826
+ margin: 0 0 0.6rem;
3827
+ font-family: var(--ck-mono);
3828
+ font-size: 0.72rem;
3829
+ letter-spacing: 0.32em;
3830
+ text-transform: uppercase;
3831
+ color: var(--ck-accent);
3832
+ }
3833
+
3834
+ .ck-launch__org {
3835
+ margin: 0;
3836
+ font-family: var(--ck-mono);
3837
+ font-size: clamp(1.8rem, 4vw, 2.6rem);
3838
+ font-weight: 600;
3839
+ letter-spacing: -0.02em;
3840
+ color: var(--ck-text);
3841
+ }
3842
+
3843
+ .ck-launch__handle {
3844
+ margin: 0.5rem 0 0;
3845
+ font-family: var(--ck-mono);
3846
+ font-size: 0.8rem;
3847
+ letter-spacing: 0.04em;
3848
+ color: var(--ck-muted);
3849
+ }
3850
+
3851
+ .ck-launch__panel {
3852
+ position: relative;
3853
+ z-index: 1;
3854
+ background: var(--ck-surface);
3855
+ border: 1px solid var(--ck-line);
3856
+ border-radius: var(--ck-radius-lg);
3857
+ padding: 1.75rem 2rem 2rem;
3858
+ box-shadow: 0 24px 64px -28px rgba(0, 0, 0, 0.5);
3859
+ animation: ck-launch-rise 0.5s ease both;
3860
+ animation-delay: 0.08s;
3861
+ }
3862
+
3863
+ .ck-launch__progress {
3864
+ padding-bottom: 1.5rem;
3865
+ margin-bottom: 0.5rem;
3866
+ border-bottom: 1px solid var(--ck-line);
3867
+ }
3868
+ .ck-launch__progress-head {
3869
+ display: flex;
3870
+ align-items: baseline;
3871
+ justify-content: space-between;
3872
+ gap: 1rem;
3873
+ margin-bottom: 0.85rem;
3874
+ }
3875
+ .ck-launch__progress-title {
3876
+ margin: 0;
3877
+ font-family: var(--ck-mono);
3878
+ font-size: 1.05rem;
3879
+ font-weight: 600;
3880
+ letter-spacing: -0.02em;
3881
+ color: var(--ck-text);
3882
+ }
3883
+ .ck-launch__progress-count {
3884
+ margin: 0;
3885
+ font-family: var(--ck-mono);
3886
+ font-size: 0.78rem;
3887
+ letter-spacing: 0.02em;
3888
+ color: var(--ck-muted);
3889
+ white-space: nowrap;
3890
+ }
3891
+ .ck-launch__progress-bar {
3892
+ height: 5px;
3893
+ border-radius: 999px;
3894
+ background: var(--ck-line);
3895
+ overflow: hidden;
3896
+ }
3897
+ .ck-launch__progress-fill {
3898
+ display: block;
3899
+ height: 100%;
3900
+ border-radius: 999px;
3901
+ background: var(--ck-accent);
3902
+ box-shadow: 0 0 10px var(--ck-accent-soft);
3903
+ transition: width 0.4s ease;
3904
+ }
3905
+
3906
+ .ck-launch__steps {
3907
+ list-style: none;
3908
+ margin: 0;
3909
+ padding: 0;
3910
+ display: flex;
3911
+ flex-direction: column;
3912
+ }
3913
+
3914
+ .ck-launch__step {
3915
+ display: grid;
3916
+ grid-template-columns: 2.4rem 1fr;
3917
+ gap: 1rem;
3918
+ align-items: baseline;
3919
+ padding: 1.25rem 0 1.25rem 1rem;
3920
+ border-top: 1px solid var(--ck-line);
3921
+ border-left: 2px solid transparent;
3922
+ animation: ck-launch-rise 0.45s ease both;
3923
+ animation-delay: calc(0.24s + var(--i) * 0.07s);
3924
+ }
3925
+
3926
+ .ck-launch__step-num {
3927
+ font-family: var(--ck-mono);
3928
+ font-size: 0.8rem;
3929
+ font-weight: 600;
3930
+ letter-spacing: 0.04em;
3931
+ color: var(--ck-dim);
3932
+ user-select: none;
3933
+ white-space: nowrap;
3934
+ }
3935
+ .ck-launch__step--done .ck-launch__step-num { color: var(--ck-success); }
3936
+ .ck-launch__step--next .ck-launch__step-num { color: var(--ck-accent); }
3937
+ .ck-launch__step-tick { margin-left: 0.3em; font-size: 0.78em; }
3938
+
3939
+ .ck-launch__step--done { border-left-color: rgba(45, 212, 168, 0.4); }
3940
+
3941
+ .ck-launch__step-body { min-width: 0; }
3942
+
3943
+ .ck-launch__step-head {
3944
+ display: flex;
3945
+ align-items: baseline;
3946
+ gap: 0.7rem;
3947
+ flex-wrap: wrap;
3948
+ margin-bottom: 0.3rem;
3949
+ }
3950
+
3951
+ .ck-launch__step-title {
3952
+ margin: 0;
3953
+ font-size: 1rem;
3954
+ font-weight: 500;
3955
+ letter-spacing: -0.005em;
3956
+ }
3957
+ .ck-launch__step-title a { color: var(--ck-text); text-decoration: none; }
3958
+ .ck-launch__step-title a:hover { color: var(--ck-accent); }
3959
+ .ck-launch__step--done .ck-launch__step-title { color: var(--ck-muted); }
3960
+
3961
+ .ck-launch__step-tag {
3962
+ font-family: var(--ck-mono);
3963
+ font-size: 0.6rem;
3964
+ letter-spacing: 0.18em;
3965
+ text-transform: uppercase;
3966
+ color: var(--ck-accent);
3967
+ padding: 0.12rem 0.45rem;
3968
+ border: 1px solid var(--ck-accent);
3969
+ border-radius: 999px;
3970
+ line-height: 1.4;
3971
+ }
3972
+
3973
+ .ck-launch__step-desc {
3974
+ margin: 0;
3975
+ font-size: 0.9rem;
3976
+ line-height: 1.55;
3977
+ color: var(--ck-muted);
3978
+ }
3979
+
3980
+ .ck-launch__step--pending .ck-launch__step-title,
3981
+ .ck-launch__step--pending .ck-launch__step-desc { opacity: 0.65; }
3982
+
3983
+ .ck-launch__step--next {
3984
+ border-left-color: var(--ck-accent);
3985
+ background: linear-gradient(90deg, var(--ck-accent-soft) 0%, transparent 30%);
3986
+ margin-left: -1rem;
3987
+ padding-left: 2rem;
3988
+ padding-right: 1rem;
3989
+ border-radius: 0 var(--ck-radius) var(--ck-radius) 0;
3990
+ }
3991
+
3992
+ .ck-launch__step-cta {
3993
+ display: inline-flex;
3994
+ align-items: center;
3995
+ gap: 0.4rem;
3996
+ margin-top: 0.85rem;
3997
+ padding: 0.5rem 0.95rem;
3998
+ background: var(--ck-accent);
3999
+ color: #06121a;
4000
+ border-radius: var(--ck-radius);
4001
+ font-family: var(--ck-mono);
4002
+ font-size: 0.75rem;
4003
+ letter-spacing: 0.06em;
4004
+ text-transform: uppercase;
4005
+ font-weight: 600;
4006
+ text-decoration: none;
4007
+ transition: filter 0.15s, transform 0.15s;
4008
+ }
4009
+ .ck-launch__step-cta:hover { filter: brightness(1.1); transform: translateY(-1px); }
4010
+
4011
+ .ck-launch__panel-footer {
4012
+ margin-top: 1.75rem;
4013
+ padding-top: 1.25rem;
4014
+ border-top: 1px solid var(--ck-line);
4015
+ }
4016
+ .ck-launch__dismiss {
4017
+ margin: 0;
4018
+ padding: 0;
4019
+ background: transparent;
4020
+ border: none;
4021
+ color: var(--ck-muted);
4022
+ font-family: var(--ck-mono);
4023
+ font-size: 0.78rem;
4024
+ letter-spacing: 0.04em;
4025
+ cursor: pointer;
4026
+ text-decoration: underline;
4027
+ text-underline-offset: 3px;
4028
+ transition: color 0.15s;
4029
+ }
4030
+ .ck-launch__dismiss:hover { color: var(--ck-accent); }
4031
+ .ck-launch__dismiss-hint {
4032
+ margin: 0.5rem 0 0;
4033
+ font-size: 0.78rem;
4034
+ color: var(--ck-dim);
4035
+ }
4036
+
4037
+ .ck-launch__ready-panel {
4038
+ position: relative;
4039
+ z-index: 1;
4040
+ background: var(--ck-surface);
4041
+ border: 1px solid var(--ck-line);
4042
+ border-radius: var(--ck-radius-lg);
4043
+ padding: 2rem;
4044
+ text-align: center;
4045
+ animation: ck-launch-rise 0.5s ease both;
4046
+ animation-delay: 0.08s;
4047
+ }
4048
+
4049
+ .ck-launch__ready-flag {
4050
+ margin: 0;
4051
+ font-family: var(--ck-mono);
4052
+ font-size: 0.85rem;
4053
+ letter-spacing: 0.14em;
4054
+ text-transform: uppercase;
4055
+ color: var(--ck-success);
4056
+ display: inline-flex;
4057
+ align-items: center;
4058
+ gap: 0.6rem;
4059
+ }
4060
+ .ck-launch__ready-dot {
4061
+ width: 8px;
4062
+ height: 8px;
4063
+ border-radius: 50%;
4064
+ background: var(--ck-success);
4065
+ box-shadow: 0 0 12px var(--ck-success);
4066
+ }
4067
+ .ck-launch__ready-copy { margin: 0.6rem 0 1.5rem; color: var(--ck-muted); }
4068
+
4069
+ .ck-launch__quicklinks {
4070
+ display: flex;
4071
+ gap: 0.6rem;
4072
+ justify-content: center;
4073
+ flex-wrap: wrap;
4074
+ }
4075
+ .ck-launch__quicklink {
4076
+ padding: 0.5rem 0.95rem;
4077
+ border: 1px solid var(--ck-line-strong);
4078
+ border-radius: var(--ck-radius);
4079
+ font-family: var(--ck-mono);
4080
+ font-size: 0.75rem;
4081
+ letter-spacing: 0.06em;
4082
+ text-transform: uppercase;
4083
+ color: var(--ck-text);
4084
+ text-decoration: none;
4085
+ transition: border-color 0.15s, background 0.15s;
4086
+ }
4087
+ .ck-launch__quicklink:hover { border-color: var(--ck-accent); background: var(--ck-surface-hover); }
4088
+
4089
+ @media (max-width: 560px) {
4090
+ .ck-launch__panel { padding: 1.5rem 1.25rem; }
4091
+ }
4092
+
4093
+ @media (prefers-reduced-motion: reduce) {
4094
+ .ck-launch__header,
4095
+ .ck-launch__panel,
4096
+ .ck-launch__ready-panel,
4097
+ .ck-launch__step { animation: none; }
4098
+ }
@@ -0,0 +1,18 @@
1
+ module CompletionKit
2
+ class OnboardingController < ApplicationController
3
+ DISMISS_COOKIE = :ck_onboarding_dismissed
4
+
5
+ def show
6
+ cookies.delete(DISMISS_COOKIE) if params[:reset]
7
+ @checklist = Onboarding::Checklist.new
8
+ return if params[:reset]
9
+
10
+ redirect_to prompts_path if @checklist.complete? || cookies[DISMISS_COOKIE]
11
+ end
12
+
13
+ def dismiss
14
+ cookies[DISMISS_COOKIE] = { value: "1", expires: 1.year.from_now, httponly: true }
15
+ redirect_to prompts_path, notice: "Setup skipped. Pick it back up from Settings → Getting started any time."
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,59 @@
1
+ module CompletionKit
2
+ module Onboarding
3
+ Step = Data.define(:key, :title, :description, :path_name, :done?)
4
+
5
+ class Checklist
6
+ STEP_DEFS = [
7
+ {
8
+ key: :credential,
9
+ title: "Connect a provider",
10
+ description: "Add an API key for OpenAI, Anthropic, or another model provider so you can run prompts and score outputs.",
11
+ path_name: :new_provider_credential_path,
12
+ done: -> { CompletionKit::ProviderCredential.exists? }
13
+ },
14
+ {
15
+ key: :dataset,
16
+ title: "Upload a dataset",
17
+ description: "Drop in a CSV of test inputs. Column headers become the {{variables}} your prompts get evaluated against.",
18
+ path_name: :new_dataset_path,
19
+ done: -> { CompletionKit::Dataset.exists? }
20
+ },
21
+ {
22
+ key: :prompt,
23
+ title: "Write your first prompt",
24
+ description: "Create a versioned prompt template with {{variable}} placeholders. Publishing freezes it; editing makes a new version.",
25
+ path_name: :new_prompt_path,
26
+ done: -> { CompletionKit::Prompt.exists? }
27
+ },
28
+ {
29
+ key: :run,
30
+ title: "Run it",
31
+ description: "Kick off a run against the dataset and watch the responses come in, each scored by the LLM judge against your metrics.",
32
+ path_name: :runs_path,
33
+ done: -> { CompletionKit::Run.exists? }
34
+ }
35
+ ].freeze
36
+
37
+ def steps
38
+ @steps ||= STEP_DEFS.map do |d|
39
+ Step.new(
40
+ key: d[:key],
41
+ title: d[:title],
42
+ description: d[:description],
43
+ path_name: d[:path_name],
44
+ done?: d[:done].call
45
+ )
46
+ end
47
+ end
48
+
49
+ def complete?
50
+ steps.all?(&:done?)
51
+ end
52
+
53
+ def progress
54
+ done = steps.count(&:done?)
55
+ { done: done, total: steps.size, percent: ((done.to_f / steps.size) * 100).round }
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,80 @@
1
+ <div class="ck-launch <%= "ck-launch--ready" if @checklist.complete? %>">
2
+ <div class="ck-launch__field" aria-hidden="true"></div>
3
+
4
+ <header class="ck-launch__header">
5
+ <p class="ck-launch__overline">Welcome to CompletionKit</p>
6
+ <h1 class="ck-launch__org">Your prompts need tests too</h1>
7
+ <p class="ck-launch__handle">Four steps from a fresh install to a scored test run.</p>
8
+ </header>
9
+
10
+ <% if @checklist.complete? %>
11
+ <section class="ck-launch__ready-panel">
12
+ <p class="ck-launch__ready-flag">
13
+ <span class="ck-launch__ready-dot" aria-hidden="true"></span>
14
+ You're all set up
15
+ </p>
16
+ <p class="ck-launch__ready-copy">Jump in wherever you like.</p>
17
+ <div class="ck-launch__quicklinks">
18
+ <%= link_to "Prompts", prompts_path, class: "ck-launch__quicklink" %>
19
+ <%= link_to "Datasets", datasets_path, class: "ck-launch__quicklink" %>
20
+ <%= link_to "Metrics", metrics_path, class: "ck-launch__quicklink" %>
21
+ <%= link_to "Runs", runs_path, class: "ck-launch__quicklink" %>
22
+ </div>
23
+ </section>
24
+ <% else %>
25
+ <% next_index = @checklist.steps.index { |s| !s.done? } %>
26
+ <% progress = @checklist.progress %>
27
+ <section class="ck-launch__panel">
28
+ <div class="ck-launch__progress">
29
+ <div class="ck-launch__progress-head">
30
+ <h2 class="ck-launch__progress-title">Finish setting up</h2>
31
+ <p class="ck-launch__progress-count"><%= progress[:done] %> of <%= progress[:total] %> done</p>
32
+ </div>
33
+ <div class="ck-launch__progress-bar" role="img" aria-label="<%= progress[:done] %> of <%= progress[:total] %> setup steps complete">
34
+ <span class="ck-launch__progress-fill" style="width: <%= progress[:percent] %>%"></span>
35
+ </div>
36
+ </div>
37
+
38
+ <ol class="ck-launch__steps">
39
+ <% @checklist.steps.each_with_index do |step, i| %>
40
+ <%
41
+ state = if step.done?
42
+ "done"
43
+ elsif i == next_index
44
+ "next"
45
+ else
46
+ "pending"
47
+ end
48
+ step_path = public_send(step.path_name)
49
+ %>
50
+ <li class="ck-launch__step ck-launch__step--<%= state %>" style="--i: <%= i %>">
51
+ <span class="ck-launch__step-num" aria-hidden="true"><%= format("%02d", i + 1) %><% if step.done? %><span class="ck-launch__step-tick">✓</span><% end %></span>
52
+ <div class="ck-launch__step-body">
53
+ <div class="ck-launch__step-head">
54
+ <h3 class="ck-launch__step-title">
55
+ <% if step.done? %>
56
+ <%= step.title %>
57
+ <% else %>
58
+ <%= link_to step.title, step_path %>
59
+ <% end %>
60
+ </h3>
61
+ <% if state == "next" %><span class="ck-launch__step-tag">Next up</span><% end %>
62
+ </div>
63
+ <p class="ck-launch__step-desc"><%= step.description %></p>
64
+ <% if state == "next" %>
65
+ <%= link_to step_path, class: "ck-launch__step-cta" do %>Start <span aria-hidden="true">&rarr;</span><% end %>
66
+ <% end %>
67
+ </div>
68
+ </li>
69
+ <% end %>
70
+ </ol>
71
+
72
+ <div class="ck-launch__panel-footer">
73
+ <%= button_to dismiss_onboarding_path, method: :post, class: "ck-launch__dismiss", form: { style: "display:inline" } do %>
74
+ Skip setup &mdash; go to the app <span aria-hidden="true">&rarr;</span>
75
+ <% end %>
76
+ <p class="ck-launch__dismiss-hint">You can come back to this from <strong>Settings &rarr; Getting started</strong> any time.</p>
77
+ </div>
78
+ </section>
79
+ <% end %>
80
+ </div>
@@ -36,7 +36,10 @@
36
36
  <p class="ck-kicker">Prompt</p>
37
37
  <% judged_run = @runs.select { |r| r.prompt_id == @prompt.id && r.status == "completed" }.find { |r| r.responses.joins(:reviews).exists? } %>
38
38
  <% if judged_run %>
39
- <%= button_to "Suggest improvements", suggest_run_path(judged_run), method: :post, class: ck_button_classes(:light, variant: :outline) + " ck-button--sm", form_class: "inline-block" %>
39
+ <%= button_to suggest_run_path(judged_run), method: :post, class: ck_button_classes(:light, variant: :outline) + " ck-button--sm", form_class: "inline-block" do %>
40
+ <%= heroicon_tag "sparkles", variant: :outline, class: "ck-magic-icon", "aria-hidden": "true" %>
41
+ Suggest improvements
42
+ <% end %>
40
43
  <% else %>
41
44
  <p class="ck-hint"><%= link_to "Run a test with judging configured", new_run_path(prompt_id: @prompt.id), class: "ck-link" %> to get AI-suggested improvements.</p>
42
45
  <% end %>
@@ -66,7 +66,10 @@
66
66
  <% if latest_suggestion %>
67
67
  <%= link_to "View suggestion", suggestion_path(latest_suggestion, from: "run"), class: ck_button_classes(:light, variant: :outline) + " ck-button--sm" %>
68
68
  <% elsif @run.status == "completed" && @run.responses.joins(:reviews).exists? %>
69
- <%= button_to "Suggest improvements", suggest_run_path(@run), method: :post, class: ck_button_classes(:light, variant: :outline) + " ck-button--sm", form_class: "inline-block" %>
69
+ <%= button_to suggest_run_path(@run), method: :post, class: ck_button_classes(:light, variant: :outline) + " ck-button--sm", form_class: "inline-block" do %>
70
+ <%= heroicon_tag "sparkles", variant: :outline, class: "ck-magic-icon", "aria-hidden": "true" %>
71
+ Suggest improvements
72
+ <% end %>
70
73
  <% end %>
71
74
  </div>
72
75
  <p class="ck-prompt-preview__text" id="prompt_text"><%= @run.prompt.template %></p>
@@ -23,7 +23,7 @@
23
23
  <%= link_to "Metrics", metrics_path, class: request.path.start_with?(metrics_path) || request.path.start_with?(metric_groups_path) ? ck_button_classes(:dark) : ck_button_classes(:light, variant: :outline) %>
24
24
  <%= link_to "Datasets", datasets_path, class: active.(datasets_path) %>
25
25
  <%= link_to "Runs", runs_path, class: active.(runs_path) %>
26
- <% settings_active = request.path.start_with?(provider_credentials_path) || request.path.start_with?(tags_path) %>
26
+ <% settings_active = request.path.start_with?(provider_credentials_path) || request.path.start_with?(tags_path) || request.path.start_with?(onboarding_path) %>
27
27
  <details class="ck-settings-menu">
28
28
  <summary class="<%= settings_active ? ck_button_classes(:dark) : ck_button_classes(:light, variant: :outline) %> ck-settings-menu__trigger" aria-label="Settings">
29
29
  Settings
@@ -31,6 +31,7 @@
31
31
  <div class="ck-settings-menu__panel" role="menu">
32
32
  <%= link_to "Providers", provider_credentials_path, class: "ck-settings-menu__item" %>
33
33
  <%= link_to "Tags", tags_path, class: "ck-settings-menu__item" %>
34
+ <%= link_to "Getting started", onboarding_path(reset: 1), class: "ck-settings-menu__item" %>
34
35
  </div>
35
36
  </details>
36
37
  <%= link_to "API", api_reference_path, class: active.(api_reference_path) %>
data/config/routes.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  CompletionKit::Engine.routes.draw do
2
- root to: "prompts#index"
2
+ root to: "onboarding#show"
3
+
4
+ get "onboarding", to: "onboarding#show", as: :onboarding
5
+ post "onboarding/dismiss", to: "onboarding#dismiss", as: :dismiss_onboarding
3
6
 
4
7
  resources :prompts do
5
8
  member do
@@ -1,3 +1,3 @@
1
1
  module CompletionKit
2
- VERSION = "0.5.2"
2
+ VERSION = "0.5.4"
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.2
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damien Bastin
@@ -245,6 +245,7 @@ files:
245
245
  - app/controllers/completion_kit/mcp_controller.rb
246
246
  - app/controllers/completion_kit/metric_groups_controller.rb
247
247
  - app/controllers/completion_kit/metrics_controller.rb
248
+ - app/controllers/completion_kit/onboarding_controller.rb
248
249
  - app/controllers/completion_kit/prompts_controller.rb
249
250
  - app/controllers/completion_kit/provider_credentials_controller.rb
250
251
  - app/controllers/completion_kit/responses_controller.rb
@@ -292,6 +293,7 @@ files:
292
293
  - app/services/completion_kit/mcp_tools/tags.rb
293
294
  - app/services/completion_kit/model_discovery_service.rb
294
295
  - app/services/completion_kit/ollama_client.rb
296
+ - app/services/completion_kit/onboarding/checklist.rb
295
297
  - app/services/completion_kit/open_ai_client.rb
296
298
  - app/services/completion_kit/open_router_client.rb
297
299
  - app/services/completion_kit/prompt_improvement_service.rb
@@ -314,6 +316,7 @@ files:
314
316
  - app/views/completion_kit/metrics/index.html.erb
315
317
  - app/views/completion_kit/metrics/new.html.erb
316
318
  - app/views/completion_kit/metrics/show.html.erb
319
+ - app/views/completion_kit/onboarding/show.html.erb
317
320
  - app/views/completion_kit/prompts/_form.html.erb
318
321
  - app/views/completion_kit/prompts/edit.html.erb
319
322
  - app/views/completion_kit/prompts/index.html.erb