lex-llm 0.1.1
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/.github/CODEOWNERS +7 -0
- data/.github/dependabot.yml +18 -0
- data/.github/workflows/ci.yml +16 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +42 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +50 -0
- data/LICENSE +21 -0
- data/README.md +279 -0
- data/lex-llm.gemspec +43 -0
- data/lib/generators/lex_llm/agent/agent_generator.rb +36 -0
- data/lib/generators/lex_llm/agent/templates/agent.rb.tt +6 -0
- data/lib/generators/lex_llm/agent/templates/instructions.txt.erb.tt +0 -0
- data/lib/generators/lex_llm/chat_ui/chat_ui_generator.rb +256 -0
- data/lib/generators/lex_llm/chat_ui/templates/controllers/chats_controller.rb.tt +38 -0
- data/lib/generators/lex_llm/chat_ui/templates/controllers/messages_controller.rb.tt +21 -0
- data/lib/generators/lex_llm/chat_ui/templates/controllers/models_controller.rb.tt +14 -0
- data/lib/generators/lex_llm/chat_ui/templates/helpers/messages_helper.rb.tt +25 -0
- data/lib/generators/lex_llm/chat_ui/templates/jobs/chat_response_job.rb.tt +12 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/chats/_chat.html.erb.tt +16 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/chats/_form.html.erb.tt +31 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/chats/index.html.erb.tt +31 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/chats/new.html.erb.tt +9 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/chats/show.html.erb.tt +27 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_assistant.html.erb.tt +14 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_content.html.erb.tt +1 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_error.html.erb.tt +13 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_form.html.erb.tt +23 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_system.html.erb.tt +10 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_tool.html.erb.tt +2 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_tool_calls.html.erb.tt +4 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/_user.html.erb.tt +14 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/tool_calls/_default.html.erb.tt +13 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/messages/tool_results/_default.html.erb.tt +21 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/models/_model.html.erb.tt +17 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/models/index.html.erb.tt +40 -0
- data/lib/generators/lex_llm/chat_ui/templates/tailwind/views/models/show.html.erb.tt +27 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/chats/_chat.html.erb.tt +16 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/chats/_form.html.erb.tt +29 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/chats/index.html.erb.tt +28 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/chats/new.html.erb.tt +11 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/chats/show.html.erb.tt +25 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/messages/_assistant.html.erb.tt +9 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/messages/_content.html.erb.tt +1 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/messages/_error.html.erb.tt +8 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/messages/_form.html.erb.tt +21 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/messages/_system.html.erb.tt +6 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/messages/_tool.html.erb.tt +2 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/messages/_tool_calls.html.erb.tt +4 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/messages/_user.html.erb.tt +9 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/messages/create.turbo_stream.erb.tt +7 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/messages/tool_calls/_default.html.erb.tt +8 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/messages/tool_results/_default.html.erb.tt +16 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/models/_model.html.erb.tt +15 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/models/index.html.erb.tt +38 -0
- data/lib/generators/lex_llm/chat_ui/templates/views/models/show.html.erb.tt +17 -0
- data/lib/generators/lex_llm/generator_helpers.rb +214 -0
- data/lib/generators/lex_llm/install/install_generator.rb +109 -0
- data/lib/generators/lex_llm/install/templates/add_references_to_chats_tool_calls_and_messages_migration.rb.tt +9 -0
- data/lib/generators/lex_llm/install/templates/chat_model.rb.tt +3 -0
- data/lib/generators/lex_llm/install/templates/create_chats_migration.rb.tt +7 -0
- data/lib/generators/lex_llm/install/templates/create_messages_migration.rb.tt +19 -0
- data/lib/generators/lex_llm/install/templates/create_models_migration.rb.tt +39 -0
- data/lib/generators/lex_llm/install/templates/create_tool_calls_migration.rb.tt +21 -0
- data/lib/generators/lex_llm/install/templates/initializer.rb.tt +20 -0
- data/lib/generators/lex_llm/install/templates/message_model.rb.tt +4 -0
- data/lib/generators/lex_llm/install/templates/model_model.rb.tt +3 -0
- data/lib/generators/lex_llm/install/templates/tool_call_model.rb.tt +3 -0
- data/lib/generators/lex_llm/schema/schema_generator.rb +26 -0
- data/lib/generators/lex_llm/schema/templates/schema.rb.tt +2 -0
- data/lib/generators/lex_llm/tool/templates/tool.rb.tt +9 -0
- data/lib/generators/lex_llm/tool/templates/tool_call.html.erb.tt +13 -0
- data/lib/generators/lex_llm/tool/templates/tool_result.html.erb.tt +13 -0
- data/lib/generators/lex_llm/tool/tool_generator.rb +96 -0
- data/lib/generators/lex_llm/upgrade_to_v1_10/templates/add_v1_10_message_columns.rb.tt +19 -0
- data/lib/generators/lex_llm/upgrade_to_v1_10/upgrade_to_v1_10_generator.rb +50 -0
- data/lib/generators/lex_llm/upgrade_to_v1_14/templates/add_v1_14_tool_call_columns.rb.tt +7 -0
- data/lib/generators/lex_llm/upgrade_to_v1_14/upgrade_to_v1_14_generator.rb +49 -0
- data/lib/generators/lex_llm/upgrade_to_v1_7/templates/migration.rb.tt +145 -0
- data/lib/generators/lex_llm/upgrade_to_v1_7/upgrade_to_v1_7_generator.rb +122 -0
- data/lib/generators/lex_llm/upgrade_to_v1_9/templates/add_v1_9_message_columns.rb.tt +15 -0
- data/lib/generators/lex_llm/upgrade_to_v1_9/upgrade_to_v1_9_generator.rb +49 -0
- data/lib/legion/extensions/llm/provider_settings.rb +49 -0
- data/lib/legion/extensions/llm/transport/fleet_lane.rb +70 -0
- data/lib/legion/extensions/llm.rb +50 -0
- data/lib/lex_llm/active_record/acts_as.rb +180 -0
- data/lib/lex_llm/active_record/acts_as_legacy.rb +503 -0
- data/lib/lex_llm/active_record/chat_methods.rb +468 -0
- data/lib/lex_llm/active_record/message_methods.rb +131 -0
- data/lib/lex_llm/active_record/model_methods.rb +76 -0
- data/lib/lex_llm/active_record/payload_helpers.rb +26 -0
- data/lib/lex_llm/active_record/tool_call_methods.rb +15 -0
- data/lib/lex_llm/agent.rb +365 -0
- data/lib/lex_llm/aliases.json +436 -0
- data/lib/lex_llm/aliases.rb +38 -0
- data/lib/lex_llm/attachment.rb +223 -0
- data/lib/lex_llm/chat.rb +351 -0
- data/lib/lex_llm/chunk.rb +6 -0
- data/lib/lex_llm/configuration.rb +81 -0
- data/lib/lex_llm/connection.rb +130 -0
- data/lib/lex_llm/content.rb +77 -0
- data/lib/lex_llm/context.rb +29 -0
- data/lib/lex_llm/embedding.rb +29 -0
- data/lib/lex_llm/error.rb +112 -0
- data/lib/lex_llm/image.rb +105 -0
- data/lib/lex_llm/message.rb +107 -0
- data/lib/lex_llm/mime_type.rb +71 -0
- data/lib/lex_llm/model/info.rb +113 -0
- data/lib/lex_llm/model/modalities.rb +22 -0
- data/lib/lex_llm/model/pricing.rb +48 -0
- data/lib/lex_llm/model/pricing_category.rb +46 -0
- data/lib/lex_llm/model/pricing_tier.rb +33 -0
- data/lib/lex_llm/model.rb +7 -0
- data/lib/lex_llm/models.json +57241 -0
- data/lib/lex_llm/models.rb +506 -0
- data/lib/lex_llm/models_schema.json +168 -0
- data/lib/lex_llm/moderation.rb +56 -0
- data/lib/lex_llm/provider.rb +278 -0
- data/lib/lex_llm/railtie.rb +35 -0
- data/lib/lex_llm/routing/lane_key.rb +51 -0
- data/lib/lex_llm/routing/model_offering.rb +169 -0
- data/lib/lex_llm/routing.rb +7 -0
- data/lib/lex_llm/stream_accumulator.rb +203 -0
- data/lib/lex_llm/streaming.rb +175 -0
- data/lib/lex_llm/thinking.rb +49 -0
- data/lib/lex_llm/tokens.rb +47 -0
- data/lib/lex_llm/tool.rb +254 -0
- data/lib/lex_llm/tool_call.rb +25 -0
- data/lib/lex_llm/transcription.rb +35 -0
- data/lib/lex_llm/utils.rb +91 -0
- data/lib/lex_llm/version.rb +5 -0
- data/lib/lex_llm.rb +95 -0
- data/lib/tasks/lex_llm.rake +23 -0
- metadata +349 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
require_relative '../generator_helpers'
|
|
5
|
+
|
|
6
|
+
module LexLLM
|
|
7
|
+
module Generators
|
|
8
|
+
# Generates a simple chat UI scaffold for LexLLM
|
|
9
|
+
class ChatUIGenerator < Rails::Generators::Base
|
|
10
|
+
include LexLLM::Generators::GeneratorHelpers
|
|
11
|
+
|
|
12
|
+
source_root File.expand_path('templates', __dir__)
|
|
13
|
+
|
|
14
|
+
namespace 'lex_llm:chat_ui'
|
|
15
|
+
|
|
16
|
+
argument :model_mappings, type: :array, default: [], banner: 'chat:ChatName message:MessageName ...'
|
|
17
|
+
class_option :ui, type: :string, default: 'auto', enum: %w[scaffold tailwind auto],
|
|
18
|
+
desc: 'UI template style (scaffold, tailwind, auto)'
|
|
19
|
+
|
|
20
|
+
desc 'Creates a chat UI scaffold with Turbo streaming\n' \
|
|
21
|
+
'Usage: bin/rails g lex_llm:chat_ui [chat:ChatName] [message:MessageName] ...'
|
|
22
|
+
|
|
23
|
+
def check_model_exists
|
|
24
|
+
model_path = "app/models/#{message_model_name.underscore}.rb"
|
|
25
|
+
return if File.exist?(model_path)
|
|
26
|
+
|
|
27
|
+
# Build the argument string for the install/upgrade commands
|
|
28
|
+
args = []
|
|
29
|
+
args << "chat:#{chat_model_name}" if chat_model_name != 'Chat'
|
|
30
|
+
args << "message:#{message_model_name}" if message_model_name != 'Message'
|
|
31
|
+
args << "model:#{model_model_name}" if model_model_name != 'Model'
|
|
32
|
+
args << "tool_call:#{tool_call_model_name}" if tool_call_model_name != 'ToolCall'
|
|
33
|
+
arg_string = args.any? ? " #{args.join(' ')}" : ''
|
|
34
|
+
|
|
35
|
+
raise Thor::Error, <<~ERROR
|
|
36
|
+
Model file not found: #{model_path}
|
|
37
|
+
|
|
38
|
+
Please run the install generator first:
|
|
39
|
+
bin/rails generate lex_llm:install#{arg_string}
|
|
40
|
+
|
|
41
|
+
Or if upgrading from <= 1.6.x, run the upgrade generator:
|
|
42
|
+
bin/rails generate lex_llm:upgrade_to_v1_7#{arg_string}
|
|
43
|
+
ERROR
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def create_views
|
|
47
|
+
# Design contract:
|
|
48
|
+
# - `scaffold` should stay close to Rails scaffold ERB output.
|
|
49
|
+
# - `tailwind` should stay close to tailwindcss-rails scaffold output.
|
|
50
|
+
# - Only small chat-specific affordances should be layered on top.
|
|
51
|
+
# For namespaced models, use the proper Rails convention path
|
|
52
|
+
chat_view_path = chat_model_name.underscore.pluralize
|
|
53
|
+
message_view_path = message_model_name.underscore.pluralize
|
|
54
|
+
model_view_path = model_model_name.underscore.pluralize
|
|
55
|
+
|
|
56
|
+
# Chat views
|
|
57
|
+
template ui_template('views/chats/index.html.erb'), "app/views/#{chat_view_path}/index.html.erb"
|
|
58
|
+
template ui_template('views/chats/new.html.erb'), "app/views/#{chat_view_path}/new.html.erb"
|
|
59
|
+
template ui_template('views/chats/show.html.erb'), "app/views/#{chat_view_path}/show.html.erb"
|
|
60
|
+
template ui_template('views/chats/_chat.html.erb'),
|
|
61
|
+
"app/views/#{chat_view_path}/_#{chat_model_name.demodulize.underscore}.html.erb"
|
|
62
|
+
template ui_template('views/chats/_form.html.erb'), "app/views/#{chat_view_path}/_form.html.erb"
|
|
63
|
+
|
|
64
|
+
# Message views
|
|
65
|
+
template ui_template('views/messages/_assistant.html.erb'), "app/views/#{message_view_path}/_assistant.html.erb"
|
|
66
|
+
template ui_template('views/messages/_user.html.erb'), "app/views/#{message_view_path}/_user.html.erb"
|
|
67
|
+
template ui_template('views/messages/_system.html.erb'), "app/views/#{message_view_path}/_system.html.erb"
|
|
68
|
+
template ui_template('views/messages/_tool.html.erb'), "app/views/#{message_view_path}/_tool.html.erb"
|
|
69
|
+
template ui_template('views/messages/_error.html.erb'), "app/views/#{message_view_path}/_error.html.erb"
|
|
70
|
+
template ui_template('views/messages/_tool_calls.html.erb'),
|
|
71
|
+
"app/views/#{message_view_path}/_tool_calls.html.erb"
|
|
72
|
+
empty_directory "app/views/#{message_view_path}/tool_calls"
|
|
73
|
+
template ui_template('views/messages/tool_calls/_default.html.erb'),
|
|
74
|
+
"app/views/#{message_view_path}/tool_calls/_default.html.erb"
|
|
75
|
+
empty_directory "app/views/#{message_view_path}/tool_results"
|
|
76
|
+
template ui_template('views/messages/tool_results/_default.html.erb'),
|
|
77
|
+
"app/views/#{message_view_path}/tool_results/_default.html.erb"
|
|
78
|
+
template ui_template('views/messages/create.turbo_stream.erb'),
|
|
79
|
+
"app/views/#{message_view_path}/create.turbo_stream.erb"
|
|
80
|
+
template ui_template('views/messages/_content.html.erb'), "app/views/#{message_view_path}/_content.html.erb"
|
|
81
|
+
template ui_template('views/messages/_form.html.erb'), "app/views/#{message_view_path}/_form.html.erb"
|
|
82
|
+
|
|
83
|
+
# Model views
|
|
84
|
+
template ui_template('views/models/index.html.erb'), "app/views/#{model_view_path}/index.html.erb"
|
|
85
|
+
template ui_template('views/models/show.html.erb'), "app/views/#{model_view_path}/show.html.erb"
|
|
86
|
+
template ui_template('views/models/_model.html.erb'),
|
|
87
|
+
"app/views/#{model_view_path}/_#{model_model_name.demodulize.underscore}.html.erb"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def create_controllers
|
|
91
|
+
# For namespaced models, use the proper Rails convention path
|
|
92
|
+
chat_controller_path = chat_model_name.underscore.pluralize
|
|
93
|
+
message_controller_path = message_model_name.underscore.pluralize
|
|
94
|
+
model_controller_path = model_model_name.underscore.pluralize
|
|
95
|
+
|
|
96
|
+
template 'controllers/chats_controller.rb', "app/controllers/#{chat_controller_path}_controller.rb"
|
|
97
|
+
template 'controllers/messages_controller.rb', "app/controllers/#{message_controller_path}_controller.rb"
|
|
98
|
+
template 'controllers/models_controller.rb', "app/controllers/#{model_controller_path}_controller.rb"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def create_jobs
|
|
102
|
+
template 'jobs/chat_response_job.rb', "app/jobs/#{variable_name_for(chat_model_name)}_response_job.rb"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def create_helpers
|
|
106
|
+
template 'helpers/messages_helper.rb', "app/helpers/#{message_model_name.underscore.pluralize}_helper.rb"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def add_available_chat_models_to_application_controller
|
|
110
|
+
path = 'app/controllers/application_controller.rb'
|
|
111
|
+
return unless File.exist?(path)
|
|
112
|
+
|
|
113
|
+
application_controller = File.read(path)
|
|
114
|
+
return if application_controller.include?('def available_chat_models')
|
|
115
|
+
|
|
116
|
+
inject_into_file path, <<-RUBY, before: /^end\s*\z/
|
|
117
|
+
private
|
|
118
|
+
|
|
119
|
+
def available_chat_models
|
|
120
|
+
LexLLM.models.chat_models.all
|
|
121
|
+
.sort_by { |model| [ model.provider.to_s, model.name.to_s ] }
|
|
122
|
+
end
|
|
123
|
+
RUBY
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def add_routes
|
|
127
|
+
# For namespaced models, use Rails convention with namespace blocks
|
|
128
|
+
if chat_model_name.include?('::')
|
|
129
|
+
namespace = chat_model_name.deconstantize.underscore
|
|
130
|
+
chat_resource = chat_model_name.demodulize.underscore.pluralize
|
|
131
|
+
message_resource = message_model_name.demodulize.underscore.pluralize
|
|
132
|
+
model_resource = model_model_name.demodulize.underscore.pluralize
|
|
133
|
+
|
|
134
|
+
routes_content = <<~ROUTES.strip
|
|
135
|
+
namespace :#{namespace} do
|
|
136
|
+
resources :#{model_resource}, only: [ :index, :show ] do
|
|
137
|
+
collection do
|
|
138
|
+
post :refresh
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
resources :#{chat_resource} do
|
|
142
|
+
resources :#{message_resource}, only: [ :create ]
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
ROUTES
|
|
146
|
+
route routes_content
|
|
147
|
+
else
|
|
148
|
+
model_routes = <<~ROUTES.strip
|
|
149
|
+
resources :#{model_table_name}, only: [ :index, :show ] do
|
|
150
|
+
collection do
|
|
151
|
+
post :refresh
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
ROUTES
|
|
155
|
+
route model_routes
|
|
156
|
+
chat_routes = <<~ROUTES.strip
|
|
157
|
+
resources :#{chat_table_name} do
|
|
158
|
+
resources :#{message_table_name}, only: [ :create ]
|
|
159
|
+
end
|
|
160
|
+
ROUTES
|
|
161
|
+
route chat_routes
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def add_broadcasting_to_message_model
|
|
166
|
+
msg_var = variable_name_for(message_model_name)
|
|
167
|
+
chat_var = variable_name_for(chat_model_name)
|
|
168
|
+
msg_path = message_model_name.underscore
|
|
169
|
+
|
|
170
|
+
# For namespaced models, we need the association name which might be different
|
|
171
|
+
# e.g., for LLM::Message, the chat association might be :llm_chat
|
|
172
|
+
chat_association = chat_table_name.singularize
|
|
173
|
+
|
|
174
|
+
broadcasting_callbacks = <<-RUBY
|
|
175
|
+
|
|
176
|
+
broadcasts_to ->(#{msg_var}) { "#{chat_var}_\#{#{msg_var}.#{chat_association}_id}" }, inserts_by: :append
|
|
177
|
+
|
|
178
|
+
def broadcast_append_chunk(content)
|
|
179
|
+
broadcast_append_to "#{chat_var}_\#{#{chat_association}_id}",
|
|
180
|
+
target: "#{msg_var}_\#{id}_content",
|
|
181
|
+
content: ERB::Util.html_escape(content.to_s)
|
|
182
|
+
end
|
|
183
|
+
RUBY
|
|
184
|
+
|
|
185
|
+
inject_into_file "app/models/#{msg_path}.rb", before: "end\n" do
|
|
186
|
+
broadcasting_callbacks
|
|
187
|
+
end
|
|
188
|
+
rescue Errno::ENOENT
|
|
189
|
+
say "#{message_model_name} model not found. Add broadcasting code to your model.", :yellow
|
|
190
|
+
say broadcasting_callbacks, :yellow
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def display_post_install_message
|
|
194
|
+
return unless behavior == :invoke
|
|
195
|
+
|
|
196
|
+
# Show the correct URL based on whether models are namespaced
|
|
197
|
+
url_path = if chat_model_name.include?('::')
|
|
198
|
+
chat_model_name.underscore.pluralize
|
|
199
|
+
else
|
|
200
|
+
chat_table_name
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
say "\n ✅ Chat UI installed!", :green
|
|
204
|
+
say " UI template: #{ui_variant}", :cyan
|
|
205
|
+
say "\n Start your server and visit http://localhost:3000/#{url_path}", :cyan
|
|
206
|
+
say "\n"
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
private
|
|
210
|
+
|
|
211
|
+
def ui_variant
|
|
212
|
+
@ui_variant ||= case options[:ui]
|
|
213
|
+
when 'tailwind'
|
|
214
|
+
:tailwind
|
|
215
|
+
when 'auto'
|
|
216
|
+
tailwind_available? ? :tailwind : :scaffold
|
|
217
|
+
else
|
|
218
|
+
:scaffold
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def ui_template(template_path)
|
|
223
|
+
return template_path unless ui_variant == :tailwind
|
|
224
|
+
|
|
225
|
+
# Keep Tailwind templates as a separate set so we can mirror Rails/Tailwind
|
|
226
|
+
# scaffold conventions without complicating scaffold templates.
|
|
227
|
+
tailwind_template = "tailwind/#{template_path}"
|
|
228
|
+
File.exist?(File.join(self.class.source_root, "#{tailwind_template}.tt")) ? tailwind_template : template_path
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def message_helper_module_name
|
|
232
|
+
if message_model_name.include?('::')
|
|
233
|
+
"#{message_model_name.deconstantize}::#{message_model_name.demodulize.pluralize}Helper"
|
|
234
|
+
else
|
|
235
|
+
"#{message_model_name.pluralize}Helper"
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def tailwind_available?
|
|
240
|
+
Rails.root.join('app/assets/tailwind/application.css').exist? ||
|
|
241
|
+
Rails.root.join('config/tailwind.config.js').exist? ||
|
|
242
|
+
gem_in_bundle?('tailwindcss-rails') ||
|
|
243
|
+
gem_in_bundle?('cssbundling-rails')
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def gem_in_bundle?(gem_name)
|
|
247
|
+
gemfile_path = Rails.root.join('Gemfile')
|
|
248
|
+
lockfile_path = Rails.root.join('Gemfile.lock')
|
|
249
|
+
|
|
250
|
+
[gemfile_path, lockfile_path].any? do |path|
|
|
251
|
+
path.exist? && path.read.include?(gem_name)
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
class <%= chat_controller_class_name %> < ApplicationController
|
|
2
|
+
before_action :set_<%= chat_variable_name %>, only: [ :show, :destroy ]
|
|
3
|
+
|
|
4
|
+
def index
|
|
5
|
+
@<%= chat_table_name %> = <%= chat_model_name %>.order(created_at: :desc)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def new
|
|
9
|
+
@<%= chat_variable_name %> = <%= chat_model_name %>.new
|
|
10
|
+
@selected_model = params[:model]
|
|
11
|
+
@chat_models = available_chat_models
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def create
|
|
15
|
+
prompt = params.dig(:<%= chat_variable_name %>, :prompt)
|
|
16
|
+
if prompt.present?
|
|
17
|
+
@<%= chat_variable_name %> = <%= chat_model_name %>.create!(model: params.dig(:<%= chat_variable_name %>, :model).presence)
|
|
18
|
+
<%= chat_job_class_name %>.perform_later(@<%= chat_variable_name %>.id, prompt)
|
|
19
|
+
|
|
20
|
+
redirect_to @<%= chat_variable_name %>, notice: "<%= chat_model_name.humanize %> was successfully created."
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def show
|
|
25
|
+
@<%= message_variable_name %> = @<%= chat_variable_name %>.<%= message_table_name %>.build
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def destroy
|
|
29
|
+
@<%= chat_variable_name %>.destroy!
|
|
30
|
+
redirect_to <%= chat_table_name %>_path, notice: "<%= chat_model_name.humanize %> was successfully destroyed.", status: :see_other
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def set_<%= chat_variable_name %>
|
|
36
|
+
@<%= chat_variable_name %> = <%= chat_model_name %>.find(params[:id])
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class <%= message_controller_class_name %> < ApplicationController
|
|
2
|
+
before_action :set_<%= chat_variable_name %>
|
|
3
|
+
|
|
4
|
+
def create
|
|
5
|
+
content = params.dig(:<%= message_variable_name %>, :content)
|
|
6
|
+
if content.present?
|
|
7
|
+
<%= chat_job_class_name %>.perform_later(@<%= chat_variable_name %>.id, content)
|
|
8
|
+
|
|
9
|
+
respond_to do |format|
|
|
10
|
+
format.turbo_stream
|
|
11
|
+
format.html { redirect_to @<%= chat_variable_name %> }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def set_<%= chat_variable_name %>
|
|
19
|
+
@<%= chat_variable_name %> = <%= chat_model_name %>.find(params[:<%= chat_model_name.include?('::') ? chat_model_name.demodulize.underscore : chat_variable_name %>_id])
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class <%= model_controller_class_name %> < ApplicationController
|
|
2
|
+
def index
|
|
3
|
+
@<%= model_table_name %> = available_chat_models
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def show
|
|
7
|
+
@<%= model_variable_name %> = <%= model_model_name %>.find(params[:id])
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def refresh
|
|
11
|
+
<%= model_model_name %>.refresh!
|
|
12
|
+
redirect_to <%= model_table_name %>_path, notice: "<%= model_model_name.pluralize %> refreshed successfully"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module <%= message_helper_module_name %>
|
|
2
|
+
def default_model_display_name
|
|
3
|
+
"Default: #{LexLLM.models.find(LexLLM.config.default_model).label}"
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def tool_result_partial(message)
|
|
7
|
+
name = message.respond_to?(:parent_tool_call) ? message.parent_tool_call&.name.to_s : ""
|
|
8
|
+
partial_for(prefix: "<%= message_model_name.underscore.pluralize %>/tool_results", name: name)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def tool_call_partial(tool_call)
|
|
12
|
+
partial_for(prefix: "<%= message_model_name.underscore.pluralize %>/tool_calls", name: tool_call.name.to_s)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def partial_for(prefix:, name:)
|
|
18
|
+
normalized = name.to_s.underscore.tr("-", "_")
|
|
19
|
+
if normalized.present? && lookup_context.exists?(normalized, [ prefix ], true)
|
|
20
|
+
"#{prefix}/#{normalized}"
|
|
21
|
+
else
|
|
22
|
+
"#{prefix}/default"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class <%= chat_job_class_name %> < ApplicationJob
|
|
2
|
+
def perform(<%= chat_variable_name %>_id, content)
|
|
3
|
+
<%= chat_variable_name %> = <%= chat_model_name %>.find(<%= chat_variable_name %>_id)
|
|
4
|
+
|
|
5
|
+
<%= chat_variable_name %>.ask(content) do |chunk|
|
|
6
|
+
if chunk.content && !chunk.content.empty?
|
|
7
|
+
<%= message_variable_name %> = <%= chat_variable_name %>.<%= message_table_name %>.last
|
|
8
|
+
<%= message_variable_name %>.broadcast_append_chunk(chunk.content)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<div id="<%%= dom_id <%= chat_model_name.demodulize.underscore %> %>" class="w-full sm:w-auto my-5 space-y-3">
|
|
2
|
+
<div>
|
|
3
|
+
<strong class="block font-medium mb-1">Model:</strong>
|
|
4
|
+
<%%= <%= chat_model_name.demodulize.underscore %>.<%= model_table_name.singularize %>&.label || default_model_display_name %>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
<div>
|
|
8
|
+
<strong class="block font-medium mb-1">Messages:</strong>
|
|
9
|
+
<%%= <%= chat_model_name.demodulize.underscore %>.<%= message_table_name %>.count %>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<div>
|
|
13
|
+
<strong class="block font-medium mb-1">Created:</strong>
|
|
14
|
+
<%%= <%= chat_model_name.demodulize.underscore %>.created_at.strftime("%B %d, %Y at %I:%M %p") %>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<%%= form_with(model: <%= chat_variable_name %>, url: <%= chat_table_name %>_path, class: "contents") do |form| %>
|
|
2
|
+
<%% if <%= chat_variable_name %>.errors.any? %>
|
|
3
|
+
<div id="error_explanation" class="bg-red-50 text-red-500 px-3 py-2 font-medium rounded-md mt-3">
|
|
4
|
+
<h2><%%= pluralize(<%= chat_variable_name %>.errors.count, "error") %> prohibited this <%= chat_table_name.singularize.humanize.downcase %> from being saved:</h2>
|
|
5
|
+
|
|
6
|
+
<ul class="list-disc ml-6">
|
|
7
|
+
<%% <%= chat_variable_name %>.errors.each do |error| %>
|
|
8
|
+
<li><%%= error.full_message %></li>
|
|
9
|
+
<%% end %>
|
|
10
|
+
</ul>
|
|
11
|
+
</div>
|
|
12
|
+
<%% end %>
|
|
13
|
+
|
|
14
|
+
<div class="my-5">
|
|
15
|
+
<%%= form.label :model, "Select AI model:" %>
|
|
16
|
+
<%%= form.select :model,
|
|
17
|
+
options_for_select(@chat_models.map { |model| [model.label, model.id] }.unshift([default_model_display_name, nil]), @selected_model),
|
|
18
|
+
{},
|
|
19
|
+
class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= chat_variable_name %>.errors[:model].none?, "border-red-400 focus:outline-red-600": <%= chat_variable_name %>.errors[:model].any?}] %>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<div class="my-5">
|
|
23
|
+
<%%= form.label :prompt, "Prompt" %>
|
|
24
|
+
<%%= form.text_area :prompt, rows: 4, placeholder: "What would you like to discuss?", autofocus: true,
|
|
25
|
+
class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= chat_variable_name %>.errors[:prompt].none?, "border-red-400 focus:outline-red-600": <%= chat_variable_name %>.errors[:prompt].any?}] %>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div class="inline">
|
|
29
|
+
<%%= form.submit "Start new <%= chat_table_name.singularize.humanize.downcase %>", class: "w-full sm:w-auto rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %>
|
|
30
|
+
</div>
|
|
31
|
+
<%% end %>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<%% content_for :title, "<%= chat_model_name.pluralize %>" %>
|
|
2
|
+
|
|
3
|
+
<div class="w-full">
|
|
4
|
+
<%% if notice.present? %>
|
|
5
|
+
<p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-md inline-block" id="notice"><%%= notice %></p>
|
|
6
|
+
<%% end %>
|
|
7
|
+
|
|
8
|
+
<div class="flex justify-between items-center">
|
|
9
|
+
<h1 class="font-bold text-4xl"><%= chat_model_name.pluralize %></h1>
|
|
10
|
+
<div class="flex items-center gap-2">
|
|
11
|
+
<%%= link_to "<%= model_model_name.pluralize %>", <%= model_table_name %>_path, class: "rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 text-gray-900 block font-medium" %>
|
|
12
|
+
<%%= link_to "New <%= chat_table_name.singularize.humanize.downcase %>", new_<%= chat_variable_name %>_path, class: "rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white block font-medium" %>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<div id="<%= chat_table_name %>" class="min-w-full divide-y divide-gray-200 space-y-5">
|
|
17
|
+
<%% if @<%= chat_table_name %>.any? %>
|
|
18
|
+
<%% @<%= chat_table_name %>.each do |<%= chat_variable_name %>| %>
|
|
19
|
+
<div class="flex flex-col sm:flex-row justify-between items-center pb-5 sm:pb-0">
|
|
20
|
+
<%%= render <%= chat_variable_name %> %>
|
|
21
|
+
<div class="w-full sm:w-auto flex flex-col sm:flex-row space-x-2 space-y-2">
|
|
22
|
+
<%%= link_to "Show", <%= chat_variable_name %>, class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
|
|
23
|
+
<%%= button_to "Destroy", <%= chat_variable_name %>, method: :delete, class: "w-full sm:w-auto rounded-md px-3.5 py-2.5 bg-red-600 hover:bg-red-500 text-white inline-block font-medium cursor-pointer", data: { turbo_confirm: "Are you sure?" } %>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
<%% end %>
|
|
27
|
+
<%% else %>
|
|
28
|
+
<p class="text-center my-10">No <%= chat_table_name.humanize.downcase %> found.</p>
|
|
29
|
+
<%% end %>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<%% content_for :title, "New <%= chat_table_name.singularize.humanize.downcase %>" %>
|
|
2
|
+
|
|
3
|
+
<div class="md:w-2/3 w-full">
|
|
4
|
+
<h1 class="font-bold text-4xl">New <%= chat_table_name.singularize.humanize.downcase %></h1>
|
|
5
|
+
|
|
6
|
+
<%%= render "form", <%= chat_variable_name %>: @<%= chat_variable_name %> %>
|
|
7
|
+
|
|
8
|
+
<%%= link_to "Back to <%= chat_table_name.humanize.downcase %>", <%= chat_table_name %>_path, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
|
|
9
|
+
</div>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<%% content_for :title, "Showing <%= chat_table_name.singularize.humanize.downcase %>" %>
|
|
2
|
+
|
|
3
|
+
<%%= turbo_stream_from "<%= chat_variable_name %>_#{@<%= chat_variable_name %>.id}" %>
|
|
4
|
+
|
|
5
|
+
<%# Keep layout conventions aligned with tailwindcss-rails scaffold (top-left, md:w-2/3). -%>
|
|
6
|
+
<div class="md:w-2/3 w-full">
|
|
7
|
+
<%% if notice.present? %>
|
|
8
|
+
<p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-md inline-block" id="notice"><%%= notice %></p>
|
|
9
|
+
<%% end %>
|
|
10
|
+
|
|
11
|
+
<h1 class="font-bold text-4xl">Showing <%= chat_table_name.singularize.humanize.downcase %> #<%%= @<%= chat_variable_name %>.id %></h1>
|
|
12
|
+
|
|
13
|
+
<div class="my-5">
|
|
14
|
+
<strong class="block font-medium mb-1">Model:</strong>
|
|
15
|
+
<%%= @<%= chat_variable_name %>.<%= model_table_name.singularize %>&.label || default_model_display_name %>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div id="<%= message_table_name %>" class="min-w-full divide-y divide-gray-200 space-y-5 my-5">
|
|
19
|
+
<%% @<%= chat_variable_name %>.<%= message_table_name %>.where.not(id: nil).each do |<%= message_variable_name %>| %>
|
|
20
|
+
<%%= render <%= message_variable_name %> %>
|
|
21
|
+
<%% end %>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<%%= render "<%= message_model_name.underscore.pluralize %>/form", <%= chat_variable_name %>: @<%= chat_variable_name %>, <%= message_variable_name %>: @<%= message_variable_name %> %>
|
|
25
|
+
|
|
26
|
+
<%%= link_to "Back to <%= chat_table_name.humanize.downcase %>", <%= chat_table_name %>_path, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %>
|
|
27
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<%% assistant ||= local_assigns[:message] %>
|
|
2
|
+
<div id="<%= message_variable_name %>_<%%= assistant.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-green-50">
|
|
3
|
+
<div>
|
|
4
|
+
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-green-100 text-green-700">
|
|
5
|
+
Assistant
|
|
6
|
+
</span>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div id="<%= message_variable_name %>_<%%= assistant.id %>_content" class="whitespace-pre-wrap"><%%= assistant.content %></div>
|
|
10
|
+
|
|
11
|
+
<div>
|
|
12
|
+
<span class="text-sm text-gray-600"><%%= assistant.created_at&.strftime("%I:%M %p") %></span>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%%= content -%>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<div id="<%= message_variable_name %>_<%%= <%= message_model_name.demodulize.underscore %>.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-red-50 border border-red-200">
|
|
2
|
+
<div>
|
|
3
|
+
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-red-100 text-red-700">
|
|
4
|
+
<%%= title.presence || "Error" %>
|
|
5
|
+
</span>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<pre class="whitespace-pre-wrap text-red-900 text-sm overflow-x-auto"><%%= error_message %></pre>
|
|
9
|
+
|
|
10
|
+
<div>
|
|
11
|
+
<span class="text-sm text-red-700"><%%= <%= message_model_name.demodulize.underscore %>.created_at&.strftime("%I:%M %p") %></span>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<%%= form_with(model: <%= message_variable_name %>, url: <%= chat_model_name.include?('::') ? "#{chat_model_name.split('::').first.underscore}_#{chat_model_name.demodulize.underscore}_#{message_model_name.demodulize.underscore.pluralize}_path(@#{chat_variable_name})" : "[@#{chat_variable_name}, #{message_variable_name}]" %>, id: "new_<%= message_variable_name %>", class: "contents") do |form| %>
|
|
2
|
+
<%% if <%= message_variable_name %>.errors.any? %>
|
|
3
|
+
<div id="error_explanation" class="bg-red-50 text-red-500 px-3 py-2 font-medium rounded-md mt-3">
|
|
4
|
+
<h2><%%= pluralize(<%= message_variable_name %>.errors.count, "error") %> prohibited this <%= message_table_name.singularize.humanize.downcase %> from being saved:</h2>
|
|
5
|
+
|
|
6
|
+
<ul class="list-disc ml-6">
|
|
7
|
+
<%% <%= message_variable_name %>.errors.each do |error| %>
|
|
8
|
+
<li><%%= error.full_message %></li>
|
|
9
|
+
<%% end %>
|
|
10
|
+
</ul>
|
|
11
|
+
</div>
|
|
12
|
+
<%% end %>
|
|
13
|
+
|
|
14
|
+
<div class="my-5">
|
|
15
|
+
<%%= form.label :content, "Message" %>
|
|
16
|
+
<%%= form.text_area :content, rows: 4, placeholder: "Message...", autofocus: true,
|
|
17
|
+
class: ["block shadow-sm rounded-md border px-3 py-2 mt-2 w-full", {"border-gray-400 focus:outline-blue-600": <%= message_variable_name %>.errors[:content].none?, "border-red-400 focus:outline-red-600": <%= message_variable_name %>.errors[:content].any?}] %>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="inline">
|
|
21
|
+
<%%= form.submit "Send <%= message_table_name.singularize.humanize.downcase %>", class: "w-full sm:w-auto rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white inline-block font-medium cursor-pointer" %>
|
|
22
|
+
</div>
|
|
23
|
+
<%% end %>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<%% system ||= local_assigns[:message] %>
|
|
2
|
+
<div id="<%= message_variable_name %>_<%%= system.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-gray-50 border border-gray-200">
|
|
3
|
+
<div>
|
|
4
|
+
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-gray-200 text-gray-700">
|
|
5
|
+
System
|
|
6
|
+
</span>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div class="whitespace-pre-wrap text-gray-700"><%%= system.content %></div>
|
|
10
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<%% user ||= local_assigns[:message] %>
|
|
2
|
+
<div id="<%= message_variable_name %>_<%%= user.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-blue-50">
|
|
3
|
+
<div>
|
|
4
|
+
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-blue-100 text-blue-700">
|
|
5
|
+
User
|
|
6
|
+
</span>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div id="<%= message_variable_name %>_<%%= user.id %>_content" class="whitespace-pre-wrap"><%%= user.content %></div>
|
|
10
|
+
|
|
11
|
+
<div>
|
|
12
|
+
<span class="text-sm text-gray-600"><%%= user.created_at&.strftime("%I:%M %p") %></span>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<div id="<%= message_variable_name %>_<%%= tool_calls.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-gray-50 border border-gray-200">
|
|
2
|
+
<div>
|
|
3
|
+
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-gray-200 text-gray-700">
|
|
4
|
+
Tool Call
|
|
5
|
+
</span>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<pre class="whitespace-pre-wrap text-gray-700 text-sm overflow-x-auto"><%%= tool_call.name %>(<%%= tool_call.arguments.map { |k, v| "#{k}: #{v.inspect}" }.join(", ") %>)</pre>
|
|
9
|
+
|
|
10
|
+
<div>
|
|
11
|
+
<span class="text-sm text-gray-600"><%%= tool_calls.created_at&.strftime("%I:%M %p") %></span>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%% error_message = tool.tool_error_message %>
|
|
2
|
+
<%% if error_message.present? %>
|
|
3
|
+
<%%= render "<%= message_model_name.underscore.pluralize %>/error",
|
|
4
|
+
<%= message_model_name.demodulize.underscore %>: tool,
|
|
5
|
+
title: "Tool Result Error",
|
|
6
|
+
error_message: error_message %>
|
|
7
|
+
<%% else %>
|
|
8
|
+
<div id="<%= message_variable_name %>_<%%= tool.id %>" class="w-full sm:w-auto my-5 space-y-3 rounded-md px-3 py-2 bg-gray-50 border border-gray-200">
|
|
9
|
+
<div>
|
|
10
|
+
<span class="inline-block rounded px-2 py-0.5 text-xs font-medium bg-gray-200 text-gray-700">
|
|
11
|
+
Tool
|
|
12
|
+
</span>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<pre class="whitespace-pre-wrap text-gray-700 text-sm overflow-x-auto"><%%= tool.content.presence || "(no output)" %></pre>
|
|
16
|
+
|
|
17
|
+
<div>
|
|
18
|
+
<span class="text-sm text-gray-600"><%%= tool.created_at&.strftime("%I:%M %p") %></span>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
<%% end %>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<%% model_id = <%= model_model_name.demodulize.underscore %>.respond_to?(:model_id) ? <%= model_model_name.demodulize.underscore %>.model_id : <%= model_model_name.demodulize.underscore %>.id %>
|
|
2
|
+
<%% row_id = [<%= model_model_name.demodulize.underscore %>.provider, model_id].join("_").parameterize(separator: "_") %>
|
|
3
|
+
<tr id="model_<%%= row_id %>">
|
|
4
|
+
<td class="px-3 py-2 text-sm text-gray-700"><%%= <%= model_model_name.demodulize.underscore %>.provider_class&.name || <%= model_model_name.demodulize.underscore %>.provider %></td>
|
|
5
|
+
<td class="px-3 py-2 text-sm text-gray-900"><%%= <%= model_model_name.demodulize.underscore %>.respond_to?(:display_name) ? <%= model_model_name.demodulize.underscore %>.display_name : <%= model_model_name.demodulize.underscore %>.name %></td>
|
|
6
|
+
<td class="px-3 py-2 text-sm text-gray-700"><%%= number_with_delimiter(<%= model_model_name.demodulize.underscore %>.context_window) if <%= model_model_name.demodulize.underscore %>.context_window %></td>
|
|
7
|
+
<td class="px-3 py-2 text-sm text-gray-700">
|
|
8
|
+
<%% input = <%= model_model_name.demodulize.underscore %>.input_price_per_million %>
|
|
9
|
+
<%% output = <%= model_model_name.demodulize.underscore %>.output_price_per_million %>
|
|
10
|
+
<%% if input && output %>
|
|
11
|
+
$<%%= "%.2f" % input %> / $<%%= "%.2f" % output %>
|
|
12
|
+
<%% end %>
|
|
13
|
+
</td>
|
|
14
|
+
<td class="px-3 py-2 text-sm">
|
|
15
|
+
<%%= link_to "Start <%= chat_table_name.singularize.humanize.downcase %>", new_<%= chat_variable_name %>_path(model: model_id), class: "text-blue-600 hover:text-blue-500" %>
|
|
16
|
+
</td>
|
|
17
|
+
</tr>
|