Files
sure/app/controllers/api/v1/chats_controller.rb
Lazy Bone f52b3fceb6 feat: implement mobile AI chat feature and fix duplicate response issue (#610)
Backend fixes:
- Fix duplicate AssistantResponseJob triggering causing duplicate AI responses
- UserMessage model already handles job triggering via after_create_commit callback
- Remove redundant job enqueue in chats_controller and messages_controller

Mobile app features:
- Implement complete AI chat interface and conversation management
- Add Chat, Message, and ToolCall data models
- Add ChatProvider for state management with polling mechanism
- Add ChatService to handle all chat-related API requests
- Add chat list screen (ChatListScreen)
- Add conversation detail screen (ChatConversationScreen)
- Refactor navigation structure with bottom navigation bar (MainNavigationScreen)
- Add settings screen (SettingsScreen)
- Optimize TransactionsProvider to support account filtering

Technical details:
- Implement message polling mechanism for real-time AI responses
- Support chat creation, deletion, retry and other operations
- Integrate Material Design 3 design language
- Improve user experience and error handling

Co-authored-by: dwvwdv <dwvwdv@protonmail.com>
2026-01-11 12:45:33 +01:00

90 lines
2.6 KiB
Ruby

# frozen_string_literal: true
class Api::V1::ChatsController < Api::V1::BaseController
include Pagy::Backend
before_action :require_ai_enabled
before_action :ensure_read_scope, only: [ :index, :show ]
before_action :ensure_write_scope, only: [ :create, :update, :destroy ]
before_action :set_chat, only: [ :show, :update, :destroy ]
def index
@pagy, @chats = pagy(Current.user.chats.ordered, items: 20)
end
def show
return unless @chat
@pagy, @messages = pagy(@chat.messages.ordered, items: 50)
end
def create
@chat = Current.user.chats.build(title: chat_params[:title])
if @chat.save
if chat_params[:message].present?
@message = @chat.messages.build(
content: chat_params[:message],
type: "UserMessage",
ai_model: chat_params[:model].presence || Chat.default_model
)
if @message.save
# NOTE: Commenting out duplicate job enqueue to fix mobile app receiving duplicate AI responses
# UserMessage model already triggers AssistantResponseJob via after_create_commit callback
# in app/models/user_message.rb:10-12, so this manual enqueue causes the job to run twice,
# resulting in duplicate AI responses with different content and wasted tokens.
# See: https://github.com/dwvwdv/sure (mobile app integration issue)
# AssistantResponseJob.perform_later(@message)
render :show, status: :created
else
@chat.destroy
render json: { error: "Failed to create initial message", details: @message.errors.full_messages }, status: :unprocessable_entity
end
else
render :show, status: :created
end
else
render json: { error: "Failed to create chat", details: @chat.errors.full_messages }, status: :unprocessable_entity
end
end
def update
return unless @chat
if @chat.update(update_chat_params)
render :show
else
render json: { error: "Failed to update chat", details: @chat.errors.full_messages }, status: :unprocessable_entity
end
end
def destroy
return unless @chat
@chat.destroy
head :no_content
end
private
def ensure_read_scope
authorize_scope!(:read)
end
def ensure_write_scope
authorize_scope!(:write)
end
def set_chat
@chat = Current.user.chats.find(params[:id])
rescue ActiveRecord::RecordNotFound
render json: { error: "Chat not found" }, status: :not_found
end
def chat_params
params.permit(:title, :message, :model)
end
def update_chat_params
params.permit(:title)
end
end