plain-rails 0.1.0
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 +7 -0
- data/README.md +162 -0
- data/Rakefile +8 -0
- data/app/assets/builds/plain.css +1 -0
- data/app/assets/config/plain_manifest.js +1 -0
- data/app/assets/stylesheets/plain/application.css +15 -0
- data/app/assets/stylesheets/plain/application.tailwind.css +7 -0
- data/app/controllers/plain/application_controller.rb +4 -0
- data/app/controllers/plain/conversations_controller.rb +55 -0
- data/app/controllers/plain/docs_controller.rb +63 -0
- data/app/controllers/plain/home_controller.rb +10 -0
- data/app/controllers/plain/messages_controller.rb +30 -0
- data/app/helpers/plain/application_helper.rb +4 -0
- data/app/helpers/plain/conversations_helper.rb +4 -0
- data/app/helpers/plain/docs_helper.rb +4 -0
- data/app/helpers/plain/home_helper.rb +4 -0
- data/app/helpers/plain/messages_helper.rb +4 -0
- data/app/javascripts/loader_controller.js +27 -0
- data/app/javascripts/scroll_controller.js +8 -0
- data/app/javascripts/toggle_class_controller.js +11 -0
- data/app/jobs/plain/application_job.rb +4 -0
- data/app/jobs/plain/message_processor_job.rb +9 -0
- data/app/mailers/plain/application_mailer.rb +6 -0
- data/app/models/plain/application_record.rb +5 -0
- data/app/models/plain/conversation.rb +53 -0
- data/app/models/plain/message.rb +62 -0
- data/app/services/plain/ai_docs.rb +163 -0
- data/app/services/plain/docs_service.rb +127 -0
- data/app/views/layouts/plain/application.html.erb +51 -0
- data/app/views/plain/conversations/_conversation_item.erb +15 -0
- data/app/views/plain/conversations/_conversation_item.html.erb +21 -0
- data/app/views/plain/conversations/_conversation_list.erb +18 -0
- data/app/views/plain/conversations/_conversation_list.html.erb +13 -0
- data/app/views/plain/conversations/_modal.html.erb +73 -0
- data/app/views/plain/conversations/index.html.erb +17 -0
- data/app/views/plain/conversations/show.html.erb +14 -0
- data/app/views/plain/docs/_footer.erb +61 -0
- data/app/views/plain/docs/_menu.erb +20 -0
- data/app/views/plain/docs/_sections.erb +73 -0
- data/app/views/plain/docs/show.html.erb +126 -0
- data/app/views/plain/home/index.html.erb +35 -0
- data/app/views/plain/messages/_form.html.erb +25 -0
- data/app/views/plain/messages/_message_item.html.erb +26 -0
- data/app/views/plain/messages/_message_list.html.erb +16 -0
- data/app/views/plain/messages/_new_message.turbo_stream.erb +3 -0
- data/app/views/plain/messages/create.turbo_stream.erb +8 -0
- data/app/views/plain/messages/index.html.erb +1 -0
- data/config/database.yml +53 -0
- data/config/routes.rb +11 -0
- data/db/migrate/20230729010703_create_plain_conversations.rb +10 -0
- data/db/migrate/20230729010745_create_plain_messages.rb +11 -0
- data/lib/plain/configuration.rb +12 -0
- data/lib/plain/engine.rb +16 -0
- data/lib/plain/version.rb +3 -0
- data/lib/plain.rb +17 -0
- data/lib/tasks/plain_tasks.rake +21 -0
- metadata +196 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
<div class="my-16 xl:max-w-none">
|
2
|
+
|
3
|
+
<h2 id="resources" class="scroll-mt-24">
|
4
|
+
<a class="group text-inherit no-underline hover:text-inherit" href="/#resources">
|
5
|
+
<div class="absolute ml-[calc(-1*var(--width))] mt-1 hidden w-[var(--width)] opacity-0 transition [--width:calc(2.625rem+0.5px+50%-min(50%,calc(theme(maxWidth.lg)+theme(spacing.8))))] group-hover:opacity-100 group-focus:opacity-100 md:block lg:z-50 2xl:[--width:theme(spacing.10)]">
|
6
|
+
<div class="group/anchor block h-5 w-5 rounded-lg bg-zinc-50 ring-1 ring-inset ring-zinc-300 transition hover:ring-zinc-500 dark:bg-zinc-800 dark:ring-zinc-700 dark:hover:bg-zinc-700 dark:hover:ring-zinc-600">
|
7
|
+
<svg viewBox="0 0 20 20" fill="none" stroke-linecap="round" aria-hidden="true" class="h-5 w-5 stroke-zinc-500 transition dark:stroke-zinc-400 dark:group-hover/anchor:stroke-white">
|
8
|
+
<path d="m6.5 11.5-.964-.964a3.535 3.535 0 1 1 5-5l.964.964m2 2 .964.964a3.536 3.536 0 0 1-5 5L8.5 13.5m0-5 3 3"></path>
|
9
|
+
</svg>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
<%= section["name"] %>
|
13
|
+
</a>
|
14
|
+
</h2>
|
15
|
+
|
16
|
+
<div class="not-prose mt-4 grid grid-cols-1 gap-8 border-t border-zinc-900/5 pt-10 dark:border-white/5 sm:grid-cols-2 xl:grid-cols-4">
|
17
|
+
<% section["items"].each do |item| %>
|
18
|
+
<div class="group relative flex rounded-2xl bg-zinc-50 transition-shadow hover:shadow-md hover:shadow-zinc-900/5 dark:bg-white/2.5 dark:hover:shadow-black/5">
|
19
|
+
<div class="pointer-events-none">
|
20
|
+
<div class="absolute inset-0 rounded-2xl transition duration-300 [mask-image:linear-gradient(white,transparent)] group-hover:opacity-50">
|
21
|
+
<svg aria-hidden="true" class="absolute inset-x-0 inset-y-[-30%] h-[160%] w-full skew-y-[-18deg] fill-black/[0.02] stroke-black/5 dark:fill-white/1 dark:stroke-white/2.5">
|
22
|
+
<defs>
|
23
|
+
<pattern id=":r22:" width="72" height="56" patternUnits="userSpaceOnUse" x="50%" y="16">
|
24
|
+
<path d="M.5 56V.5H72" fill="none"></path>
|
25
|
+
</pattern>
|
26
|
+
</defs>
|
27
|
+
<rect width="100%" height="100%" stroke-width="0" fill="url(#:r22:)"></rect>
|
28
|
+
<svg x="50%" y="16" class="overflow-visible">
|
29
|
+
<rect stroke-width="0" width="73" height="57" x="0" y="56"></rect>
|
30
|
+
<rect stroke-width="0" width="73" height="57" x="72" y="168"></rect>
|
31
|
+
</svg>
|
32
|
+
</svg>
|
33
|
+
</div>
|
34
|
+
<div class="absolute inset-0 rounded-2xl bg-gradient-to-r from-[#D7EDEA] to-[#F4FBDF] opacity-0 transition duration-300 group-hover:opacity-100 dark:from-[#202D2E] dark:to-[#303428]" data-projection-id="17" style="-webkit-mask-image: radial-gradient(180px at 14px 46px, white, transparent);"></div>
|
35
|
+
<div class="absolute inset-0 rounded-2xl opacity-0 mix-blend-overlay transition duration-300 group-hover:opacity-100" data-projection-id="18" style="-webkit-mask-image: radial-gradient(180px at 14px 46px, white, transparent);">
|
36
|
+
<svg aria-hidden="true" class="absolute inset-x-0 inset-y-[-30%] h-[160%] w-full skew-y-[-18deg] fill-black/50 stroke-black/70 dark:fill-white/2.5 dark:stroke-white/10">
|
37
|
+
<defs>
|
38
|
+
<pattern id=":r23:" width="72" height="56" patternUnits="userSpaceOnUse" x="50%" y="16">
|
39
|
+
<path d="M.5 56V.5H72" fill="none"></path>
|
40
|
+
</pattern>
|
41
|
+
</defs>
|
42
|
+
<rect width="100%" height="100%" stroke-width="0" fill="url(#:r23:)"></rect>
|
43
|
+
<svg x="50%" y="16" class="overflow-visible">
|
44
|
+
<rect stroke-width="0" width="73" height="57" x="0" y="56"></rect>
|
45
|
+
<rect stroke-width="0" width="73" height="57" x="72" y="168"></rect>
|
46
|
+
</svg>
|
47
|
+
</svg>
|
48
|
+
</div>
|
49
|
+
</div>
|
50
|
+
<div class="absolute inset-0 rounded-2xl ring-1 ring-inset ring-zinc-900/7.5 group-hover:ring-zinc-900/10 dark:ring-white/10 dark:group-hover:ring-white/20"></div>
|
51
|
+
<div class="relative rounded-2xl px-4 pb-4 pt-16">
|
52
|
+
<div class="flex h-7 w-7 items-center justify-center rounded-full bg-zinc-900/5 ring-1 ring-zinc-900/25 backdrop-blur-[2px] transition duration-300 group-hover:bg-white/50 group-hover:ring-zinc-900/25 dark:bg-white/7.5 dark:ring-white/15 dark:group-hover:bg-emerald-300/10 dark:group-hover:ring-emerald-400">
|
53
|
+
<svg viewBox="0 0 20 20" aria-hidden="true" class="h-5 w-5 fill-zinc-700/10 stroke-zinc-700 transition-colors duration-300 group-hover:stroke-zinc-900 dark:fill-white/10 dark:stroke-zinc-400 dark:group-hover:fill-emerald-300/10 dark:group-hover:stroke-emerald-400">
|
54
|
+
<path stroke-width="0" fill-rule="evenodd" clip-rule="evenodd" d="M10 .5a9.5 9.5 0 0 1 5.598 17.177C14.466 15.177 12.383 13.5 10 13.5s-4.466 1.677-5.598 4.177A9.5 9.5 0 0 1 10 .5ZM12.5 8a2.5 2.5 0 1 0-5 0 2.5 2.5 0 0 0 5 0Z"></path>
|
55
|
+
<path fill="none" stroke-linecap="round" stroke-linejoin="round" d="M10 .5a9.5 9.5 0 0 1 5.598 17.177A9.458 9.458 0 0 1 10 19.5a9.458 9.458 0 0 1-5.598-1.823A9.5 9.5 0 0 1 10 .5Z"></path>
|
56
|
+
<path fill="none" stroke-linecap="round" stroke-linejoin="round" d="M4.402 17.677C5.534 15.177 7.617 13.5 10 13.5s4.466 1.677 5.598 4.177M10 5.5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5Z"></path>
|
57
|
+
</svg>
|
58
|
+
</div>
|
59
|
+
<h3 class="mt-4 text-sm font-semibold leading-7 text-zinc-900 dark:text-white">
|
60
|
+
<a href="<%= item["path"] %>">
|
61
|
+
<span class="absolute inset-0 rounded-2xl"></span>
|
62
|
+
<%= item["name"] %>
|
63
|
+
</a>
|
64
|
+
</h3>
|
65
|
+
<p class="mt-1 text-sm text-zinc-600 dark:text-zinc-400">
|
66
|
+
<%= item["description"] %>
|
67
|
+
</p>
|
68
|
+
</div>
|
69
|
+
</div>
|
70
|
+
<% end %>
|
71
|
+
|
72
|
+
</div>
|
73
|
+
</div>
|
@@ -0,0 +1,126 @@
|
|
1
|
+
|
2
|
+
<div id="pp" data-turbo-permanent>
|
3
|
+
<%= turbo_frame_tag "plain" %>
|
4
|
+
</div>
|
5
|
+
|
6
|
+
<div class="lg:ml-72 xl:ml-80">
|
7
|
+
<header class="contents lg:pointer-events-none lg:fixed lg:inset-0 lg:z-40 lg:flex">
|
8
|
+
<div class="contents lg:pointer-events-auto lg:block lg:w-72 lg:overflow-y-auto lg:border-r lg:border-zinc-900/10 lg:px-6 lg:pb-8 lg:pt-4 lg:dark:border-white/10 xl:w-80">
|
9
|
+
<div class="hidden lg:flex">
|
10
|
+
<a aria-label="Home" href="/" class="flex space-x-2 items-center">
|
11
|
+
<% if @config["logo"] %>
|
12
|
+
<%= image_tag(@config["logo"], class: "h-10") %>
|
13
|
+
<% end %>
|
14
|
+
<span class="font-extrabold uppercase text-xl">
|
15
|
+
<%= @config["name"] || "PLAIN" %>
|
16
|
+
</span>
|
17
|
+
</a>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<div class="fixed inset-x-0 top-0 z-50 flex h-14 items-center justify-between gap-12 px-4 transition sm:px-6 lg:left-72 lg:z-30 lg:px-8 xl:left-80 backdrop-blur-sm dark:backdrop-blur lg:left-72 xl:left-80 bg-white/[var(--bg-opacity-light)] dark:bg-zinc-900/[var(--bg-opacity-dark)]" style="--bg-opacity-light: 0.5; --bg-opacity-dark: 0.2;">
|
21
|
+
|
22
|
+
<div class="absolute inset-x-0 top-full h-px transition bg-zinc-900/7.5 dark:bg-white/7.5"></div>
|
23
|
+
<!--<div class="hidden lg:block lg:max-w-md lg:flex-auto">
|
24
|
+
<button type="button" class="hidden h-8 w-full items-center gap-2 rounded-full bg-white pl-2 pr-3 text-sm text-zinc-500 ring-1 ring-zinc-900/10 transition hover:ring-zinc-900/20 dark:bg-white/5 dark:text-zinc-400 dark:ring-inset dark:ring-white/10 dark:hover:ring-white/20 lg:flex focus:[&:not(:focus-visible)]:outline-none">
|
25
|
+
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true" class="h-5 w-5 stroke-current">
|
26
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12.01 12a4.25 4.25 0 1 0-6.02-6 4.25 4.25 0 0 0 6.02 6Zm0 0 3.24 3.25"></path>
|
27
|
+
</svg>Find something... <kbd class="ml-auto text-2xs text-zinc-400 dark:text-zinc-500">
|
28
|
+
<kbd class="font-sans">⌘</kbd>
|
29
|
+
<kbd class="font-sans">K</kbd>
|
30
|
+
</kbd>
|
31
|
+
</button>
|
32
|
+
</div>
|
33
|
+
<div class="flex items-center gap-5 lg:hidden">
|
34
|
+
<button type="button" class="flex h-6 w-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 dark:hover:bg-white/5" aria-label="Toggle navigation">
|
35
|
+
<svg viewBox="0 0 10 9" fill="none" stroke-linecap="round" aria-hidden="true" class="w-2.5 stroke-zinc-900 dark:stroke-white">
|
36
|
+
<path d="M.5 1h9M.5 8h9M.5 4.5h9"></path>
|
37
|
+
</svg>
|
38
|
+
</button>
|
39
|
+
<a aria-label="Home" href="/plain" class="flex space-x-2 items-center">
|
40
|
+
|
41
|
+
<% # image_tag("add-logo-here", class: "h-6") %>
|
42
|
+
<span class="font-extrabold uppercase text-sm">Plain</span>
|
43
|
+
</a>
|
44
|
+
</div>
|
45
|
+
-->
|
46
|
+
<div class="flex items-center gap-5">
|
47
|
+
<nav class="hidden md:block">
|
48
|
+
<ul role="list" class="flex items-center gap-8">
|
49
|
+
<% if @config["chat_envs"].present? and @config["chat_envs"].include?(Rails.env.to_s) %>
|
50
|
+
<li>
|
51
|
+
<a href="/plain"
|
52
|
+
data-turbo-frame="plain"
|
53
|
+
class="bg-gray-900 text-white rounded-md px-3 py-2 text-sm font-medium" aria-current="page">
|
54
|
+
Chat
|
55
|
+
</a>
|
56
|
+
</li>
|
57
|
+
<% end %>
|
58
|
+
<!--<li>
|
59
|
+
<a class="text-sm leading-5 text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white" href="/">API</a>
|
60
|
+
</li>
|
61
|
+
<li>
|
62
|
+
<a class="text-sm leading-5 text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white" href="/#">Documentation</a>
|
63
|
+
</li>-->
|
64
|
+
<% if @config["links"] %>
|
65
|
+
<% @config["links"].each do |link| %>
|
66
|
+
<li>
|
67
|
+
<a class="text-sm leading-5 text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white"
|
68
|
+
href="<%= link["url"] %>" target="blank">
|
69
|
+
<%= link["name"] %>
|
70
|
+
</a>
|
71
|
+
</li>
|
72
|
+
<% end %>
|
73
|
+
<% end %>
|
74
|
+
</ul>
|
75
|
+
</nav>
|
76
|
+
<div class="hidden md:block md:h-5 md:w-px md:bg-zinc-900/10 md:dark:bg-white/15"></div>
|
77
|
+
<div class="hidden flex gap-4">
|
78
|
+
<div class="contents lg:hidden">
|
79
|
+
<button type="button" class="flex h-6 w-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 dark:hover:bg-white/5 lg:hidden focus:[&:not(:focus-visible)]:outline-none" aria-label="Find something...">
|
80
|
+
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true" class="h-5 w-5 stroke-zinc-900 dark:stroke-white">
|
81
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12.01 12a4.25 4.25 0 1 0-6.02-6 4.25 4.25 0 0 0 6.02 6Zm0 0 3.24 3.25"></path>
|
82
|
+
</svg>
|
83
|
+
</button>
|
84
|
+
</div>
|
85
|
+
<button type="button" class="flex h-6 w-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 dark:hover:bg-white/5" aria-label="Toggle dark mode">
|
86
|
+
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true" class="h-5 w-5 stroke-zinc-900 dark:hidden">
|
87
|
+
<path d="M12.5 10a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Z"></path>
|
88
|
+
<path stroke-linecap="round" d="M10 5.5v-1M13.182 6.818l.707-.707M14.5 10h1M13.182 13.182l.707.707M10 15.5v-1M6.11 13.889l.708-.707M4.5 10h1M6.11 6.111l.708.707"></path>
|
89
|
+
</svg>
|
90
|
+
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true" class="hidden h-5 w-5 stroke-white dark:block">
|
91
|
+
<path d="M15.224 11.724a5.5 5.5 0 0 1-6.949-6.949 5.5 5.5 0 1 0 6.949 6.949Z"></path>
|
92
|
+
</svg>
|
93
|
+
</button>
|
94
|
+
</div>
|
95
|
+
<!--
|
96
|
+
<div class="hidden min-[416px]:contents">
|
97
|
+
<a class="inline-flex gap-0.5 justify-center overflow-hidden text-sm font-medium transition rounded-full bg-zinc-900 py-1 px-3 text-white hover:bg-zinc-700 dark:bg-emerald-400/10 dark:text-emerald-400 dark:ring-1 dark:ring-inset dark:ring-emerald-400/20 dark:hover:bg-emerald-400/10 dark:hover:text-emerald-300 dark:hover:ring-emerald-300"
|
98
|
+
href="/#">Sign in</a>
|
99
|
+
</div>
|
100
|
+
-->
|
101
|
+
</div>
|
102
|
+
|
103
|
+
</div>
|
104
|
+
|
105
|
+
<nav class="hidden lg:mt-10 lg:block">
|
106
|
+
<%= render partial: 'menu', locals: { nodes: @docs_structure[:children], level: 1 } %>
|
107
|
+
</nav>
|
108
|
+
|
109
|
+
</div>
|
110
|
+
</header>
|
111
|
+
|
112
|
+
<div class="relative px-4 pt-14 sm:px-6 lg:px-8">
|
113
|
+
<main class="py-16">
|
114
|
+
<article class="prose dark:prose-invert">
|
115
|
+
<%= @content.html_safe unless @content.nil? %>
|
116
|
+
</article>
|
117
|
+
</main>
|
118
|
+
|
119
|
+
|
120
|
+
<% if @main_config.present? %>
|
121
|
+
<%= render partial: "sections", collection: @main_config, as: :section %>
|
122
|
+
<% end %>
|
123
|
+
|
124
|
+
<%= render "footer" %>
|
125
|
+
</div>
|
126
|
+
</div>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<%= turbo_frame_tag "plain" do %>
|
2
|
+
<%= render "plain/conversations/modal" do %>
|
3
|
+
<div class="border shadow-sm rounded-md bg-white m-4">
|
4
|
+
<h2 class=" p-4 inline-block text-2xl sm:text-3xl font-extrabold text-slate-900 tracking-tight dark:text-slate-200">
|
5
|
+
Continue conversations
|
6
|
+
</h2>
|
7
|
+
|
8
|
+
<div class="divide divide-y">
|
9
|
+
<% @conversations.each do |c| %>
|
10
|
+
<div class="p-2 rounded-sm hover:bg-black/5">
|
11
|
+
|
12
|
+
<div class="flex space-x-2">
|
13
|
+
<% if c.pinned? %>
|
14
|
+
<div class="w-5 h-5">
|
15
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
16
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M17.593 3.322c1.1.128 1.907 1.077 1.907 2.185V21L12 17.25 4.5 21V5.507c0-1.108.806-2.057 1.907-2.185a48.507 48.507 0 0111.186 0z" />
|
17
|
+
</svg>
|
18
|
+
</div>
|
19
|
+
<% end %>
|
20
|
+
<%= link_to c.subject || "new chat", conversation_path(c), data: {"turbo-frame": "plain"} %>
|
21
|
+
</div>
|
22
|
+
<p class="text-xs">
|
23
|
+
<%= time_ago_in_words(c.created_at) %>
|
24
|
+
</p>
|
25
|
+
</div>
|
26
|
+
<% end %>
|
27
|
+
</div>
|
28
|
+
<div class="m-2 flex justify-between">
|
29
|
+
<%= link_to "New conversation", new_conversation_path, class: "rounded-md bg-brand-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-brand-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand-600" %>
|
30
|
+
<%= link_to "See previous chats", conversations_path, class: "rounded-lg text-slate-900 font-semibold transition flex items-center gap-3 text-[0.8125rem] leading-6 py-1 px-1.5 hover:bg-slate-900/[0.03] -my-1 -mx-1.5" %>
|
31
|
+
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
<% end %>
|
35
|
+
<% end %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
<%= turbo_frame_tag "message-form" do %>
|
3
|
+
<%= form_for Plain::Message.new,
|
4
|
+
url: plain.conversation_messages_path(conversation),
|
5
|
+
html: {
|
6
|
+
data: {
|
7
|
+
controller: "loader",
|
8
|
+
action: "turbo:submit-start->loader#formSubmitting turbo:submit-end->loader#formSubmitted"
|
9
|
+
}
|
10
|
+
} do |form| %>
|
11
|
+
<div class="absolute bottom-0 border-t pt-2 bg-white h-[52px]">
|
12
|
+
<div class="flex space-x-2 w-[448px] px-2">
|
13
|
+
<%= form.text_field :content,
|
14
|
+
label: false,
|
15
|
+
class: "flex-grow p-2 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-brand-600 sm:text-sm sm:leading-6"
|
16
|
+
%>
|
17
|
+
|
18
|
+
<div class="">
|
19
|
+
<%= form.submit "Ask Plain", "data-loader-target": "loader", class: "ml-4 inline-flex justify-center rounded-md bg-brand-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-brand-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand-600" %>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
<% end %>
|
25
|
+
<% end %>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<div id="message-item-<%= message.id %>"
|
2
|
+
class="message-role <%= message.assistant? ? "bg-white" : "bg-brand-200" %>
|
3
|
+
mx-4 flex flex-col pb-1 p-2 my-1 shadow-sm rounded-md border border-black/10">
|
4
|
+
|
5
|
+
<%= "Plain bot:" if message.assistant? %>
|
6
|
+
|
7
|
+
<div class="prose prose-sm space-y-2">
|
8
|
+
<% unless message.content.nil? %>
|
9
|
+
<%= raw Plain::AiDocs.convert_markdown message.content %>
|
10
|
+
<% end %>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
<div class="flex space-x-2">
|
14
|
+
<% if message.assistant? %>
|
15
|
+
<button class="rounded bg-white px-2 py-1 text-xs font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
|
16
|
+
create doc
|
17
|
+
</button>
|
18
|
+
<button class="rounded bg-white px-2 py-1 text-xs font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
|
19
|
+
OTHER action?
|
20
|
+
</button>
|
21
|
+
<% end %>
|
22
|
+
</div>
|
23
|
+
<% if local_assigns[:scroll] %>
|
24
|
+
<span data-controller="scroll-to"></span>
|
25
|
+
<% end %>
|
26
|
+
</div>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<%= turbo_frame_tag "message-list-#{@current_page}" do %>
|
2
|
+
<div class="flex flex-col-reverse">
|
3
|
+
<% if @current_page.zero? %>
|
4
|
+
<span data-controller="scroll-to"></span>
|
5
|
+
<% end %>
|
6
|
+
<%= render partial: "plain/messages/message_item", collection: @messages, as: :message %>
|
7
|
+
<% if @messages.size.positive? %>
|
8
|
+
<%= turbo_frame_tag "message-list-#{@next_page}", loading: :lazy,
|
9
|
+
src: conversation_messages_path(@conversation, page: @next_page),
|
10
|
+
class: 'empty:mt-[600px] empty:mb-[-600px] empty:block group' %>
|
11
|
+
<div class="mt-4 group-[&:not(:empty)]:hidden">
|
12
|
+
<%= t('conversations.loading') %>
|
13
|
+
</div>
|
14
|
+
<% end %>
|
15
|
+
</div>
|
16
|
+
<% end %>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<%= turbo_stream.append "new-messages-container" do %>
|
2
|
+
<%= render partial: "message_item", collection: @messages, as: :message, locals: { data: "asd" } %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
|
6
|
+
<%= turbo_stream.update "message-form" do %>
|
7
|
+
<%= render "form", conversation: @conversation %>
|
8
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render "plain/messages/message_list" %>
|
data/config/database.yml
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# SQLite. Versions 3.8.0 and up are supported.
|
2
|
+
# gem install sqlite3
|
3
|
+
#
|
4
|
+
# Ensure the SQLite 3 gem is defined in your Gemfile
|
5
|
+
# gem "sqlite3"
|
6
|
+
#
|
7
|
+
default: &default
|
8
|
+
adapter: sqlite3
|
9
|
+
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
|
10
|
+
timeout: 5000
|
11
|
+
|
12
|
+
development_sqlite:
|
13
|
+
<<: *default
|
14
|
+
database: db/development.sqlite3
|
15
|
+
|
16
|
+
development:
|
17
|
+
prepared_statements: false
|
18
|
+
adapter: postgresql
|
19
|
+
database: <%= ENV.fetch('POSTGRES_DATABASE', 'ruby_on_plain_development') %>
|
20
|
+
username: <%= ENV.fetch('POSTGRES_USERNAME', 'postgres') %>
|
21
|
+
password: <%= ENV.fetch('POSTGRES_PASSWORD', '') %>
|
22
|
+
min_messages: warning
|
23
|
+
pool: 15
|
24
|
+
timeout: 5000
|
25
|
+
host_names:
|
26
|
+
### Don't include the port number here. Change the "port" site setting instead, at /admin/site_settings.
|
27
|
+
### If you change this setting you will need to
|
28
|
+
### - restart sidekiq if you change this setting
|
29
|
+
### - rebake all to posts using: `RAILS_ENV=production bundle exec rake posts:rebake`
|
30
|
+
- 'localhost'
|
31
|
+
|
32
|
+
# Warning: The database defined as "test" will be erased and
|
33
|
+
# re-generated from your development database when you run "rake".
|
34
|
+
# Do not set this db to the same as development or production.
|
35
|
+
test:
|
36
|
+
prepared_statements: false
|
37
|
+
adapter: postgresql
|
38
|
+
database: <%= ENV.fetch('POSTGRES_DATABASE', 'ruby_on_plain_test') %>
|
39
|
+
username: <%= ENV.fetch('POSTGRES_USERNAME', 'postgres') %>
|
40
|
+
password: <%= ENV.fetch('POSTGRES_PASSWORD', '') %>
|
41
|
+
min_messages: warning
|
42
|
+
pool: 15
|
43
|
+
timeout: 5000
|
44
|
+
host_names:
|
45
|
+
### Don't include the port number here. Change the "port" site setting instead, at /admin/site_settings.
|
46
|
+
### If you change this setting you will need to
|
47
|
+
### - restart sidekiq if you change this setting
|
48
|
+
### - rebake all to posts using: `RAILS_ENV=production bundle exec rake posts:rebake`
|
49
|
+
- 'localhost'
|
50
|
+
|
51
|
+
production:
|
52
|
+
<<: *default
|
53
|
+
database: db/production.sqlite3
|
data/config/routes.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module Plain
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :paths, :chat_environments, :vector_search, :extensions
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@paths = []
|
7
|
+
@chat_environments = []
|
8
|
+
@vector_search = nil
|
9
|
+
@extensions = ["rb", "js", "erb", "md", "json"]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/plain/engine.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "openai"
|
2
|
+
require "qdrant"
|
3
|
+
require "langchainrb"
|
4
|
+
require "coderay"
|
5
|
+
require "redcarpet"
|
6
|
+
|
7
|
+
module Plain
|
8
|
+
class Engine < ::Rails::Engine
|
9
|
+
isolate_namespace Plain
|
10
|
+
|
11
|
+
# NOTE: add engine manifest to precompile assets in production, if you don't have this yet.
|
12
|
+
initializer "plain.assets" do |app|
|
13
|
+
app.config.assets.precompile += %w[plain_manifest]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/plain.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "plain/version"
|
2
|
+
require "plain/engine"
|
3
|
+
require "plain/configuration"
|
4
|
+
|
5
|
+
module Plain
|
6
|
+
class << self
|
7
|
+
attr_writer :configuration
|
8
|
+
|
9
|
+
def configuration
|
10
|
+
@configuration ||= Configuration.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def configure
|
14
|
+
yield(configuration)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
namespace :plain do
|
2
|
+
desc "Indexes the contents"
|
3
|
+
task :load => :environment do
|
4
|
+
puts "loading contents of the project"
|
5
|
+
Plain::AiDocs.new.load_all
|
6
|
+
puts "contents indexed"
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
task :tailwind_engine_watch do
|
11
|
+
require "tailwindcss-rails"
|
12
|
+
# NOTE: tailwindcss-rails is an engine
|
13
|
+
Dir.chdir(Plain::Engine.root.to_s) do
|
14
|
+
system "tailwindcss \
|
15
|
+
-i #{Plain::Engine.root.join("app/assets/stylesheets/plain/application.tailwind.css")} \
|
16
|
+
-o #{Plain::Engine.root.join("app/assets/builds/plain.css")} \
|
17
|
+
-c #{Plain::Engine.root.join("tailwind.config.js")} \
|
18
|
+
--minify -w"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|