Class: Collavre::MergeCommentsJob
- Inherits:
-
ApplicationJob
- Object
- ApplicationJob
- Collavre::MergeCommentsJob
- Includes:
- AiAgentResolvable, CommentSerializable
- Defined in:
- app/jobs/collavre/merge_comments_job.rb
Constant Summary collapse
- SYSTEM_PROMPT =
<<~PROMPT.freeze You are merging multiple chat messages into a single coherent message. Synthesize the content from all messages, preserving all important information, decisions, action items, and context. Do not add commentary about the merge process itself. Respond in the same language as the original messages. Use markdown formatting for readability. PROMPT
Instance Method Summary collapse
-
#perform(creative_id, comment_ids, user_id) ⇒ Object
rubocop:disable Lint/UnusedMethodArgument – user_id reserved for future audit/notification use.
Instance Method Details
#perform(creative_id, comment_ids, user_id) ⇒ Object
rubocop:disable Lint/UnusedMethodArgument – user_id reserved for future audit/notification use
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'app/jobs/collavre/merge_comments_job.rb', line 17 def perform(creative_id, comment_ids, user_id) # rubocop:disable Lint/UnusedMethodArgument -- user_id reserved for future audit/notification use creative = Creative.find(creative_id) # Fetch comments in chronological order comments = creative.comments .where(id: comment_ids) .order(created_at: :asc) .includes(:user, images_attachments: :blob) .to_a return if comments.size < 2 target_comment = comments.first topic_id = target_comment.topic_id # Build conversation text conversation = comments.map do |c| = c.user&.name || I18n.t("collavre.comments.anonymous") "#{}: #{c.content}" end.join("\n\n") # Resolve AI agent (same as /compress — agent is required) agent = resolve_ai_agent(creative, topic_id) unless agent Rails.logger.error("[MergeCommentsJob] No AI agent found for creative #{creative_id}") return end client = AiClient.new( vendor: agent.llm_vendor, model: agent.llm_model, system_prompt: SYSTEM_PROMPT, llm_api_key: agent.llm_api_key || agent.creator&.llm_api_key, gateway_url: agent.gateway_url.presence || agent.creator&.gateway_url, context: { creative: creative, user: agent, topic_id: topic_id } ) merged_content = String.new result = client.chat([ { role: "user", text: conversation } ]) do |delta| merged_content << delta end # AiClient returns nil on error (but still yields error text as delta). # Check both: return value must be truthy AND content must be non-blank. if result.nil? || merged_content.blank? Rails.logger.error("[MergeCommentsJob] AI failed for comments #{comment_ids}") return end # Update the first comment and delete the rest atomically remaining_ids = comments[1..].map(&:id) ActiveRecord::Base.transaction do # Save snapshot for recovery before modifying/deleting originals CommentSnapshot.create!( creative: creative, topic_id: topic_id, user_id: user_id, operation: "merge", comments_data: serialize_comments(comments), result_comment: target_comment ) target_comment.update!(content: merged_content) creative.comments.where(id: remaining_ids).destroy_all end rescue ActiveRecord::RecordNotFound => e Rails.logger.error("[MergeCommentsJob] Record not found: #{e.}") end |