layered-assistant-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/AGENTS.md +94 -0
- data/LICENSE +201 -0
- data/README.md +176 -0
- data/Rakefile +15 -0
- data/app/assets/tailwind/layered/assistant/styles.css +13 -0
- data/app/controllers/concerns/layered/assistant/message_creation.rb +49 -0
- data/app/controllers/concerns/layered/assistant/public/session_conversations.rb +50 -0
- data/app/controllers/layered/assistant/application_controller.rb +25 -0
- data/app/controllers/layered/assistant/assistants_controller.rb +59 -0
- data/app/controllers/layered/assistant/conversations_controller.rb +77 -0
- data/app/controllers/layered/assistant/messages_controller.rb +57 -0
- data/app/controllers/layered/assistant/models_controller.rb +61 -0
- data/app/controllers/layered/assistant/panel/conversations_controller.rb +63 -0
- data/app/controllers/layered/assistant/panel/messages_controller.rb +44 -0
- data/app/controllers/layered/assistant/providers_controller.rb +55 -0
- data/app/controllers/layered/assistant/public/application_controller.rb +16 -0
- data/app/controllers/layered/assistant/public/assistants_controller.rb +16 -0
- data/app/controllers/layered/assistant/public/conversations_controller.rb +33 -0
- data/app/controllers/layered/assistant/public/messages_controller.rb +42 -0
- data/app/controllers/layered/assistant/public/panel/conversations_controller.rb +62 -0
- data/app/controllers/layered/assistant/public/panel/messages_controller.rb +50 -0
- data/app/controllers/layered/assistant/setup_controller.rb +9 -0
- data/app/helpers/layered/assistant/access_helper.rb +45 -0
- data/app/helpers/layered/assistant/messages_helper.rb +41 -0
- data/app/helpers/layered/assistant/panel_helper.rb +38 -0
- data/app/javascript/layered_assistant/composer_controller.js +30 -0
- data/app/javascript/layered_assistant/index.js +14 -0
- data/app/javascript/layered_assistant/message_streaming.js +124 -0
- data/app/javascript/layered_assistant/messages_controller.js +62 -0
- data/app/javascript/layered_assistant/panel_controller.js +36 -0
- data/app/javascript/layered_assistant/panel_nav_controller.js +16 -0
- data/app/javascript/layered_assistant/provider_template_controller.js +45 -0
- data/app/javascript/layered_assistant/vendor/marked.esm.js +72 -0
- data/app/jobs/layered/assistant/application_job.rb +6 -0
- data/app/jobs/layered/assistant/messages/response_job.rb +36 -0
- data/app/models/layered/assistant/application_record.rb +7 -0
- data/app/models/layered/assistant/assistant.rb +22 -0
- data/app/models/layered/assistant/conversation.rb +39 -0
- data/app/models/layered/assistant/message.rb +56 -0
- data/app/models/layered/assistant/model.rb +21 -0
- data/app/models/layered/assistant/provider.rb +49 -0
- data/app/services/layered/assistant/chunk_service.rb +80 -0
- data/app/services/layered/assistant/client_service.rb +18 -0
- data/app/services/layered/assistant/clients/anthropic.rb +24 -0
- data/app/services/layered/assistant/clients/base.rb +29 -0
- data/app/services/layered/assistant/clients/openai.rb +33 -0
- data/app/services/layered/assistant/messages_service.rb +58 -0
- data/app/services/layered/assistant/models/create_service.rb +50 -0
- data/app/services/layered/assistant/token_estimator.rb +11 -0
- data/app/views/layered/assistant/assistants/_form.html.erb +42 -0
- data/app/views/layered/assistant/assistants/edit.html.erb +6 -0
- data/app/views/layered/assistant/assistants/index.html.erb +45 -0
- data/app/views/layered/assistant/assistants/new.html.erb +6 -0
- data/app/views/layered/assistant/conversations/_form.html.erb +29 -0
- data/app/views/layered/assistant/conversations/edit.html.erb +6 -0
- data/app/views/layered/assistant/conversations/index.html.erb +63 -0
- data/app/views/layered/assistant/conversations/new.html.erb +6 -0
- data/app/views/layered/assistant/conversations/show.html.erb +25 -0
- data/app/views/layered/assistant/messages/_composer.html.erb +15 -0
- data/app/views/layered/assistant/messages/_message.html.erb +25 -0
- data/app/views/layered/assistant/messages/_system_prompt.html.erb +10 -0
- data/app/views/layered/assistant/messages/create.turbo_stream.erb +9 -0
- data/app/views/layered/assistant/messages/index.html.erb +46 -0
- data/app/views/layered/assistant/models/_form.html.erb +30 -0
- data/app/views/layered/assistant/models/edit.html.erb +6 -0
- data/app/views/layered/assistant/models/index.html.erb +54 -0
- data/app/views/layered/assistant/models/new.html.erb +6 -0
- data/app/views/layered/assistant/panel/conversations/_header.html.erb +23 -0
- data/app/views/layered/assistant/panel/conversations/index.html.erb +46 -0
- data/app/views/layered/assistant/panel/conversations/new.html.erb +23 -0
- data/app/views/layered/assistant/panel/conversations/show.html.erb +24 -0
- data/app/views/layered/assistant/panel/messages/_composer.html.erb +15 -0
- data/app/views/layered/assistant/panel/messages/create.turbo_stream.erb +9 -0
- data/app/views/layered/assistant/providers/_form.html.erb +81 -0
- data/app/views/layered/assistant/providers/edit.html.erb +6 -0
- data/app/views/layered/assistant/providers/index.html.erb +47 -0
- data/app/views/layered/assistant/providers/new.html.erb +6 -0
- data/app/views/layered/assistant/public/assistants/index.html.erb +34 -0
- data/app/views/layered/assistant/public/assistants/show.html.erb +23 -0
- data/app/views/layered/assistant/public/conversations/show.html.erb +24 -0
- data/app/views/layered/assistant/public/messages/_composer.html.erb +7 -0
- data/app/views/layered/assistant/public/messages/create.turbo_stream.erb +9 -0
- data/app/views/layered/assistant/public/panel/conversations/_header.html.erb +16 -0
- data/app/views/layered/assistant/public/panel/conversations/index.html.erb +48 -0
- data/app/views/layered/assistant/public/panel/conversations/new.html.erb +17 -0
- data/app/views/layered/assistant/public/panel/conversations/show.html.erb +23 -0
- data/app/views/layered/assistant/public/panel/messages/_composer.html.erb +7 -0
- data/app/views/layered/assistant/public/panel/messages/create.turbo_stream.erb +9 -0
- data/app/views/layered/assistant/setup/_setup.html.erb +121 -0
- data/app/views/layered/assistant/setup/index.html.erb +2 -0
- data/app/views/layouts/layered/assistant/_host_navigation.html.erb +0 -0
- data/app/views/layouts/layered/assistant/application.html.erb +32 -0
- data/config/importmap.rb +8 -0
- data/config/routes.rb +31 -0
- data/data/models.json +42 -0
- data/db/migrate/20260312000000_create_layered_assistant_tables.rb +63 -0
- data/lib/generators/layered/assistant/install_generator.rb +113 -0
- data/lib/generators/layered/assistant/migrations_generator.rb +47 -0
- data/lib/generators/layered/assistant/templates/initializer.rb +26 -0
- data/lib/layered/assistant/engine.rb +29 -0
- data/lib/layered/assistant/version.rb +5 -0
- data/lib/layered/assistant.rb +19 -0
- data/lib/layered-assistant-rails.rb +1 -0
- metadata +449 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
class AssistantsController < ApplicationController
|
|
4
|
+
before_action :set_assistant, only: [:edit, :update, :destroy]
|
|
5
|
+
before_action :set_models, only: [:new, :create, :edit, :update]
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
@page_title = "Assistants"
|
|
9
|
+
@pagy, @assistants = pagy(Assistant.by_name)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def new
|
|
13
|
+
@page_title = "New assistant"
|
|
14
|
+
@assistant = Assistant.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def create
|
|
18
|
+
@assistant = Assistant.new(assistant_params)
|
|
19
|
+
|
|
20
|
+
if @assistant.save
|
|
21
|
+
redirect_to layered_assistant.assistants_path, notice: "Assistant was successfully created."
|
|
22
|
+
else
|
|
23
|
+
render :new, status: :unprocessable_entity
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def edit
|
|
28
|
+
@page_title = "Edit assistant"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def update
|
|
32
|
+
if @assistant.update(assistant_params)
|
|
33
|
+
redirect_to layered_assistant.assistants_path, notice: "Assistant was successfully updated."
|
|
34
|
+
else
|
|
35
|
+
render :edit, status: :unprocessable_entity
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def destroy
|
|
40
|
+
@assistant.destroy
|
|
41
|
+
redirect_to layered_assistant.assistants_path, notice: "Assistant was successfully deleted."
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def set_assistant
|
|
47
|
+
@assistant = Assistant.find(params[:id])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def set_models
|
|
51
|
+
@models = Model.available
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def assistant_params
|
|
55
|
+
params.require(:assistant).permit(:name, :description, :system_prompt, :default_model_id, :public)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
class ConversationsController < ApplicationController
|
|
4
|
+
before_action :set_conversation, only: [:show, :edit, :update, :destroy]
|
|
5
|
+
before_action :set_assistants, only: [:new, :create]
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
if params[:assistant_id]
|
|
9
|
+
@assistant = Assistant.find(params[:assistant_id])
|
|
10
|
+
@page_title = "Conversations - #{@assistant.name}"
|
|
11
|
+
@pagy, @conversations = pagy(@assistant.conversations.includes(:owner).by_created_at)
|
|
12
|
+
else
|
|
13
|
+
@page_title = "Conversations"
|
|
14
|
+
@pagy, @conversations = pagy(Conversation.includes(:assistant, :owner).by_created_at)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def show
|
|
19
|
+
@page_title = @conversation.name
|
|
20
|
+
@messages = @conversation.messages.includes(:model).by_created_at
|
|
21
|
+
@models = Model.available
|
|
22
|
+
@selected_model_id = @messages.last&.model_id || @conversation.assistant.default_model_id || @models.first&.id
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def new
|
|
26
|
+
@page_title = "New conversation"
|
|
27
|
+
@conversation = Conversation.new(params.permit(conversation: [:assistant_id])[:conversation])
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def create
|
|
31
|
+
@conversation = Conversation.new(conversation_params)
|
|
32
|
+
@conversation.owner = l_ui_current_user
|
|
33
|
+
@conversation.name = Conversation.default_name if @conversation.name.blank?
|
|
34
|
+
if @conversation.save
|
|
35
|
+
redirect_to layered_assistant.conversation_path(@conversation), notice: "Conversation was successfully created."
|
|
36
|
+
else
|
|
37
|
+
render :new, status: :unprocessable_entity
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def edit
|
|
42
|
+
@page_title = "Edit conversation"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def update
|
|
46
|
+
if @conversation.update(conversation_params)
|
|
47
|
+
redirect_to layered_assistant.conversations_path, notice: "Conversation was successfully updated."
|
|
48
|
+
else
|
|
49
|
+
render :edit, status: :unprocessable_entity
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def destroy
|
|
54
|
+
@conversation.destroy
|
|
55
|
+
redirect_to layered_assistant.conversations_path, notice: "Conversation was successfully deleted."
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def set_conversation
|
|
61
|
+
@conversation = Conversation.find(params[:id])
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def set_assistants
|
|
65
|
+
@assistants = Assistant.by_name
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def conversation_params
|
|
69
|
+
if action_name == "create"
|
|
70
|
+
params.require(:conversation).permit(:name, :assistant_id)
|
|
71
|
+
else
|
|
72
|
+
params.require(:conversation).permit(:name)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
class MessagesController < ApplicationController
|
|
4
|
+
include MessageCreation
|
|
5
|
+
|
|
6
|
+
before_action :set_conversation
|
|
7
|
+
before_action :set_message, only: [:destroy]
|
|
8
|
+
|
|
9
|
+
def index
|
|
10
|
+
@page_title = "Messages"
|
|
11
|
+
@pagy, @messages = pagy(@conversation.messages.by_created_at)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def create
|
|
15
|
+
result = create_messages_for(
|
|
16
|
+
conversation: @conversation,
|
|
17
|
+
content: message_params[:content],
|
|
18
|
+
model_id: message_params[:model_id]
|
|
19
|
+
)
|
|
20
|
+
@message = result[:message]
|
|
21
|
+
|
|
22
|
+
unless @message.persisted?
|
|
23
|
+
return head :unprocessable_entity
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
@assistant_message = result[:assistant_message]
|
|
27
|
+
@models = result[:models]
|
|
28
|
+
@selected_model_id = result[:selected_model_id]
|
|
29
|
+
@error = result[:error]
|
|
30
|
+
|
|
31
|
+
respond_to do |format|
|
|
32
|
+
format.turbo_stream
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def destroy
|
|
37
|
+
@message.destroy
|
|
38
|
+
@conversation.update_token_totals!
|
|
39
|
+
redirect_to layered_assistant.conversation_messages_path(@conversation), notice: "Message was successfully deleted."
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def set_conversation
|
|
45
|
+
@conversation = Conversation.find(params[:conversation_id])
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def set_message
|
|
49
|
+
@message = @conversation.messages.find(params[:id])
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def message_params
|
|
53
|
+
params.require(:message).permit(:content, :model_id)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
class ModelsController < ApplicationController
|
|
4
|
+
before_action :set_provider
|
|
5
|
+
before_action :set_model, only: [:edit, :update, :destroy]
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
@pagy, @models = pagy(@provider.models.sorted)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def new
|
|
12
|
+
@model = @provider.models.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def create
|
|
16
|
+
@model = @provider.models.new(model_params)
|
|
17
|
+
|
|
18
|
+
if @model.save
|
|
19
|
+
redirect_to layered_assistant.provider_models_path(@provider), notice: "Model was successfully created."
|
|
20
|
+
else
|
|
21
|
+
render :new, status: :unprocessable_entity
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def edit
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def update
|
|
29
|
+
if @model.update(model_params)
|
|
30
|
+
redirect_to layered_assistant.provider_models_path(@provider), notice: "Model was successfully updated."
|
|
31
|
+
else
|
|
32
|
+
render :edit, status: :unprocessable_entity
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def destroy
|
|
37
|
+
if @model.destroy
|
|
38
|
+
redirect_to layered_assistant.provider_models_path(@provider), notice: "Model was successfully deleted."
|
|
39
|
+
else
|
|
40
|
+
redirect_to layered_assistant.provider_models_path(@provider), alert: @model.errors.full_messages.to_sentence
|
|
41
|
+
end
|
|
42
|
+
rescue ActiveRecord::InvalidForeignKey
|
|
43
|
+
redirect_to layered_assistant.provider_models_path(@provider), alert: "Cannot delete a model that is in use."
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def set_provider
|
|
49
|
+
@provider = Provider.find(params[:provider_id])
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def set_model
|
|
53
|
+
@model = @provider.models.find(params[:id])
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def model_params
|
|
57
|
+
params.require(:model).permit(:name, :identifier, :enabled)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
module Panel
|
|
4
|
+
class ConversationsController < ApplicationController
|
|
5
|
+
layout false
|
|
6
|
+
|
|
7
|
+
before_action :set_conversation, only: [:show, :destroy]
|
|
8
|
+
before_action :set_conversations, only: [:index, :show]
|
|
9
|
+
before_action :set_assistants, only: [:index, :show, :new, :create]
|
|
10
|
+
|
|
11
|
+
def index
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def show
|
|
15
|
+
@messages = @conversation.messages.includes(:model).by_created_at
|
|
16
|
+
@models = Model.available
|
|
17
|
+
@selected_model_id = @messages.last&.model_id || @conversation.assistant.default_model_id || @models.first&.id
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def new
|
|
21
|
+
@conversation = Conversation.new
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def create
|
|
25
|
+
@conversation = Conversation.new(conversation_params)
|
|
26
|
+
@conversation.owner = l_ui_current_user
|
|
27
|
+
@conversation.name = Conversation.default_name if @conversation.name.blank?
|
|
28
|
+
|
|
29
|
+
if @conversation.save
|
|
30
|
+
redirect_to layered_assistant.panel_conversation_path(@conversation)
|
|
31
|
+
else
|
|
32
|
+
render :new, status: :unprocessable_entity
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def destroy
|
|
37
|
+
@conversation.destroy
|
|
38
|
+
redirect_to layered_assistant.panel_conversations_path
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def set_conversation
|
|
44
|
+
@conversation = Conversation.find(params[:id])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def set_assistants
|
|
48
|
+
@assistants = Assistant.by_name
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def set_conversations
|
|
52
|
+
scope = Conversation.by_created_at
|
|
53
|
+
scope = scope.where(assistant_id: params[:assistant_id]) if params[:assistant_id].present?
|
|
54
|
+
@conversations = scope.limit(20)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def conversation_params
|
|
58
|
+
params.require(:conversation).permit(:assistant_id, :name)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
module Panel
|
|
4
|
+
class MessagesController < ApplicationController
|
|
5
|
+
layout false
|
|
6
|
+
include MessageCreation
|
|
7
|
+
|
|
8
|
+
before_action :set_conversation
|
|
9
|
+
|
|
10
|
+
def create
|
|
11
|
+
result = create_messages_for(
|
|
12
|
+
conversation: @conversation,
|
|
13
|
+
content: message_params[:content],
|
|
14
|
+
model_id: message_params[:model_id]
|
|
15
|
+
)
|
|
16
|
+
@message = result[:message]
|
|
17
|
+
|
|
18
|
+
unless @message.persisted?
|
|
19
|
+
return head :unprocessable_entity
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
@assistant_message = result[:assistant_message]
|
|
23
|
+
@models = result[:models]
|
|
24
|
+
@selected_model_id = result[:selected_model_id]
|
|
25
|
+
@error = result[:error]
|
|
26
|
+
|
|
27
|
+
respond_to do |format|
|
|
28
|
+
format.turbo_stream
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def set_conversation
|
|
35
|
+
@conversation = Conversation.find(params[:conversation_id])
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def message_params
|
|
39
|
+
params.require(:message).permit(:content, :model_id)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
class ProvidersController < ApplicationController
|
|
4
|
+
before_action :set_provider, only: [:edit, :update, :destroy]
|
|
5
|
+
|
|
6
|
+
def index
|
|
7
|
+
@page_title = "Providers"
|
|
8
|
+
@pagy, @providers = pagy(Provider.sorted)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def new
|
|
12
|
+
@page_title = "New Provider"
|
|
13
|
+
@provider = Provider.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create
|
|
17
|
+
@provider = Provider.new(provider_params)
|
|
18
|
+
|
|
19
|
+
if @provider.save
|
|
20
|
+
Models::CreateService.new(@provider).call if params[:provider][:create_models] == "1"
|
|
21
|
+
redirect_to layered_assistant.providers_path, notice: "Provider was successfully created."
|
|
22
|
+
else
|
|
23
|
+
render :new, status: :unprocessable_entity
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def edit
|
|
28
|
+
@page_title = "Edit Provider"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def update
|
|
32
|
+
if @provider.update(provider_params)
|
|
33
|
+
redirect_to layered_assistant.providers_path, notice: "Provider was successfully updated."
|
|
34
|
+
else
|
|
35
|
+
render :edit, status: :unprocessable_entity
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def destroy
|
|
40
|
+
@provider.destroy
|
|
41
|
+
redirect_to layered_assistant.providers_path, notice: "Provider was successfully deleted."
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def set_provider
|
|
47
|
+
@provider = Provider.find(params[:id])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def provider_params
|
|
51
|
+
params.require(:provider).permit(:name, :protocol, :url, :secret, :enabled)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
module Public
|
|
4
|
+
class ApplicationController < Layered::Assistant::ApplicationController
|
|
5
|
+
skip_before_action :layered_assistant_authorize!
|
|
6
|
+
include SessionConversations
|
|
7
|
+
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def set_public_assistant
|
|
11
|
+
@assistant = Assistant.publicly_available.find(params[:assistant_id] || params[:id])
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
module Public
|
|
4
|
+
class AssistantsController < ApplicationController
|
|
5
|
+
before_action :set_public_assistant, only: [:show]
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
@pagy, @assistants = pagy(Assistant.publicly_available.by_name)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def show
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
module Public
|
|
4
|
+
class ConversationsController < ApplicationController
|
|
5
|
+
before_action :set_public_assistant, only: [:create]
|
|
6
|
+
before_action :set_conversation, only: [:show]
|
|
7
|
+
|
|
8
|
+
def create
|
|
9
|
+
@conversation = @assistant.conversations.new(name: Conversation.default_name)
|
|
10
|
+
|
|
11
|
+
if @conversation.save
|
|
12
|
+
add_conversation_to_session(@conversation)
|
|
13
|
+
redirect_to layered_assistant.public_conversation_path(@conversation)
|
|
14
|
+
else
|
|
15
|
+
redirect_to layered_assistant.public_assistant_path(@assistant)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def show
|
|
20
|
+
@messages = @conversation.messages.includes(:model).by_created_at
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def set_conversation
|
|
26
|
+
@conversation = find_session_conversation(params[:id])
|
|
27
|
+
rescue ActiveRecord::RecordNotFound
|
|
28
|
+
redirect_to layered_assistant.public_assistants_path
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
module Public
|
|
4
|
+
class MessagesController < ApplicationController
|
|
5
|
+
include MessageCreation
|
|
6
|
+
|
|
7
|
+
before_action :set_conversation
|
|
8
|
+
|
|
9
|
+
def create
|
|
10
|
+
result = create_messages_for(
|
|
11
|
+
conversation: @conversation,
|
|
12
|
+
content: message_params[:content],
|
|
13
|
+
model_id: @conversation.assistant.default_model_id
|
|
14
|
+
)
|
|
15
|
+
@message = result[:message]
|
|
16
|
+
|
|
17
|
+
unless @message.persisted?
|
|
18
|
+
return head :unprocessable_entity
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
@error = result[:error]
|
|
22
|
+
|
|
23
|
+
respond_to do |format|
|
|
24
|
+
format.turbo_stream
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def set_conversation
|
|
31
|
+
@conversation = find_session_conversation(params[:conversation_id])
|
|
32
|
+
rescue ActiveRecord::RecordNotFound
|
|
33
|
+
redirect_to layered_assistant.public_assistants_path
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def message_params
|
|
37
|
+
params.require(:message).permit(:content)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
module Public
|
|
4
|
+
module Panel
|
|
5
|
+
class ConversationsController < Public::ApplicationController
|
|
6
|
+
layout false
|
|
7
|
+
|
|
8
|
+
before_action :set_public_assistant, only: [:index, :new, :create]
|
|
9
|
+
before_action :set_conversation, only: [:show]
|
|
10
|
+
before_action :set_session_conversations, only: [:index, :show]
|
|
11
|
+
|
|
12
|
+
def index
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create
|
|
19
|
+
@conversation = @assistant.conversations.new(name: Conversation.default_name)
|
|
20
|
+
|
|
21
|
+
if @conversation.save
|
|
22
|
+
add_conversation_to_session(@conversation)
|
|
23
|
+
redirect_to layered_assistant.public_panel_conversation_path(@conversation)
|
|
24
|
+
else
|
|
25
|
+
render :new, status: :unprocessable_entity
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def show
|
|
30
|
+
@messages = @conversation.messages.includes(:model).by_created_at
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def set_conversation
|
|
36
|
+
@conversation = find_session_conversation(params[:id])
|
|
37
|
+
rescue ActiveRecord::RecordNotFound
|
|
38
|
+
assistant = Conversation.find_by(id: params[:id])&.assistant
|
|
39
|
+
if assistant&.public?
|
|
40
|
+
redirect_to layered_assistant.public_panel_conversations_path(assistant_id: assistant.id)
|
|
41
|
+
else
|
|
42
|
+
redirect_to layered_assistant.public_assistants_path
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def set_session_conversations
|
|
47
|
+
assistant_id = @conversation&.assistant_id || @assistant&.id
|
|
48
|
+
@conversations = if session_conversation_ids.any?
|
|
49
|
+
scope = Conversation.joins(:assistant).merge(Assistant.publicly_available)
|
|
50
|
+
.where(id: session_conversation_ids)
|
|
51
|
+
.by_created_at
|
|
52
|
+
scope = scope.where(assistant_id: assistant_id) if assistant_id
|
|
53
|
+
scope.limit(20)
|
|
54
|
+
else
|
|
55
|
+
Conversation.none
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
module Public
|
|
4
|
+
module Panel
|
|
5
|
+
class MessagesController < Public::ApplicationController
|
|
6
|
+
layout false
|
|
7
|
+
include MessageCreation
|
|
8
|
+
|
|
9
|
+
before_action :set_conversation
|
|
10
|
+
|
|
11
|
+
def create
|
|
12
|
+
result = create_messages_for(
|
|
13
|
+
conversation: @conversation,
|
|
14
|
+
content: message_params[:content],
|
|
15
|
+
model_id: @conversation.assistant.default_model_id
|
|
16
|
+
)
|
|
17
|
+
@message = result[:message]
|
|
18
|
+
|
|
19
|
+
unless @message.persisted?
|
|
20
|
+
return head :unprocessable_entity
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
@error = result[:error]
|
|
24
|
+
|
|
25
|
+
respond_to do |format|
|
|
26
|
+
format.turbo_stream
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def set_conversation
|
|
33
|
+
@conversation = find_session_conversation(params[:conversation_id])
|
|
34
|
+
rescue ActiveRecord::RecordNotFound
|
|
35
|
+
assistant = Conversation.find_by(id: params[:conversation_id])&.assistant
|
|
36
|
+
if assistant&.public?
|
|
37
|
+
redirect_to layered_assistant.new_public_panel_conversation_path(assistant_id: assistant.id)
|
|
38
|
+
else
|
|
39
|
+
redirect_to layered_assistant.public_assistants_path
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def message_params
|
|
44
|
+
params.require(:message).permit(:content)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Layered
|
|
2
|
+
module Assistant
|
|
3
|
+
module AccessHelper
|
|
4
|
+
def l_assistant_accessible?
|
|
5
|
+
block = Layered::Assistant.authorize_block
|
|
6
|
+
return false unless block
|
|
7
|
+
|
|
8
|
+
checker = AccessibilityChecker.new(self)
|
|
9
|
+
checker.accessible?(&block)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class AccessibilityChecker
|
|
13
|
+
def initialize(context)
|
|
14
|
+
@context = context
|
|
15
|
+
@blocked = false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def accessible?(&block)
|
|
19
|
+
instance_exec(&block)
|
|
20
|
+
!@blocked
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def head(*)
|
|
24
|
+
@blocked = true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def redirect_to(*)
|
|
28
|
+
@blocked = true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def method_missing(method, ...)
|
|
34
|
+
@context.send(method, ...)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def respond_to_missing?(method, include_private = false)
|
|
38
|
+
@context.respond_to?(method, include_private)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private_constant :AccessibilityChecker
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|