class Chat < ApplicationRecord include Debuggable belongs_to :user has_one :viewer, class_name: "User", foreign_key: :last_viewed_chat_id, dependent: :nullify # "Last chat user has viewed" has_many :messages, dependent: :destroy validates :title, presence: true scope :ordered, -> { order(created_at: :desc) } class << self def start!(prompt, model:) create!( title: generate_title(prompt), messages: [ UserMessage.new(content: prompt, ai_model: model) ] ) end def generate_title(prompt) prompt.first(80) end end def retry_last_message! last_message = conversation_messages.ordered.last if last_message.present? && last_message.role == "user" update!(error: nil) ask_assistant_later(last_message) end end def add_error(e) update! error: e.to_json broadcast_append target: "messages", partial: "chats/error", locals: { chat: self } end def clear_error update! error: nil broadcast_remove target: "chat-error" end def assistant @assistant ||= Assistant.for_chat(self) end def ask_assistant_later(message) AssistantResponseJob.perform_later(message) end def ask_assistant(message) assistant.respond_to(message) end def conversation_messages if debug_mode? messages else messages.where(type: [ "UserMessage", "AssistantMessage" ]) end end end