From c42dd8a23e949e746b666852f712350e2d0d5cd1 Mon Sep 17 00:00:00 2001 From: Tanmay Deep Sharma <32020192+tds-1@users.noreply.github.com> Date: Wed, 25 Jun 2025 07:30:20 +0530 Subject: [PATCH] feat: captain should be able to access private notes (#11768) # Pull Request Template ## Linear task: https://linear.app/chatwoot/issue/CW-4482/captain-should-be-able-to-access-private-notes-only-on-copilot ## Description Captain should be able to access private notes (only on copilot) ## Type of change - [x] New feature (non-breaking change which adds functionality) ## How Has This Been Tested? ![image](https://github.com/user-attachments/assets/b25cf81f-85eb-4adb-a1eb-57e1156b9b9e) ![image](https://github.com/user-attachments/assets/20051b31-cbce-41d9-84d9-13bc71687323) ## Checklist: - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules --------- Co-authored-by: Muhsin Keloth --- .../conversation_llm_formatter.rb | 12 +++++++--- .../tools/copilot/get_conversation_service.rb | 2 +- .../copilot/get_conversation_service_spec.rb | 23 +++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/app/services/llm_formatter/conversation_llm_formatter.rb b/app/services/llm_formatter/conversation_llm_formatter.rb index a43471e5b..8654e0adf 100644 --- a/app/services/llm_formatter/conversation_llm_formatter.rb +++ b/app/services/llm_formatter/conversation_llm_formatter.rb @@ -5,7 +5,7 @@ class LlmFormatter::ConversationLlmFormatter < LlmFormatter::DefaultLlmFormatter sections << "Channel: #{@record.inbox.channel.name}" sections << 'Message History:' sections << if @record.messages.any? - build_messages + build_messages(config) else 'No messages in this conversation' end @@ -23,11 +23,16 @@ class LlmFormatter::ConversationLlmFormatter < LlmFormatter::DefaultLlmFormatter private - def build_messages + def build_messages(config = {}) return "No messages in this conversation\n" if @record.messages.empty? message_text = '' - @record.messages.chat.order(created_at: :asc).each do |message| + messages = @record.messages.where.not(message_type: :activity).order(created_at: :asc) + + messages.each do |message| + # Skip private messages unless explicitly included in config + next if message.private? && !config[:include_private_messages] + message_text << format_message(message) end message_text @@ -35,6 +40,7 @@ class LlmFormatter::ConversationLlmFormatter < LlmFormatter::DefaultLlmFormatter def format_message(message) sender = message.message_type == 'incoming' ? 'User' : 'Support agent' + sender = "[Private Note] #{sender}" if message.private? "#{sender}: #{message.content}\n" end diff --git a/enterprise/app/services/captain/tools/copilot/get_conversation_service.rb b/enterprise/app/services/captain/tools/copilot/get_conversation_service.rb index 64b52d012..6f942ee8e 100644 --- a/enterprise/app/services/captain/tools/copilot/get_conversation_service.rb +++ b/enterprise/app/services/captain/tools/copilot/get_conversation_service.rb @@ -30,7 +30,7 @@ class Captain::Tools::Copilot::GetConversationService < Captain::Tools::BaseServ conversation = Conversation.find_by(display_id: conversation_id, account_id: @assistant.account_id) return 'Conversation not found' if conversation.blank? - conversation.to_llm_text + conversation.to_llm_text(include_private_messages: true) end def active? diff --git a/spec/enterprise/services/captain/tools/copilot/get_conversation_service_spec.rb b/spec/enterprise/services/captain/tools/copilot/get_conversation_service_spec.rb index 4d7f1adc7..b8265bbbf 100644 --- a/spec/enterprise/services/captain/tools/copilot/get_conversation_service_spec.rb +++ b/spec/enterprise/services/captain/tools/copilot/get_conversation_service_spec.rb @@ -128,6 +128,29 @@ RSpec.describe Captain::Tools::Copilot::GetConversationService do expect(result).to eq(conversation.to_llm_text) end + it 'includes private messages in the llm text format' do + # Create a regular message + create(:message, + conversation: conversation, + message_type: 'outgoing', + content: 'Regular message', + private: false) + + # Create a private message + create(:message, + conversation: conversation, + message_type: 'outgoing', + content: 'Private note content', + private: true) + + result = service.execute({ 'conversation_id' => conversation.display_id }) + + # Verify that the result includes both regular and private messages + expect(result).to include('Regular message') + expect(result).to include('Private note content') + expect(result).to include('[Private Note]') + end + context 'when conversation belongs to different account' do let(:other_account) { create(:account) } let(:other_inbox) { create(:inbox, account: other_account) }