Module: Assistant::PromptComposer

Included in:
ChatService
Defined in:
app/services/assistant/prompt_composer.rb

Overview

Encapsulates system prompt assembly, domain detection, prompt rendering,
and extended thinking configuration for ChatService.

Expects the including class to provide:
@conversation, @user_context, @tool_services, @model_config,
@user_message, @registered_tools, @user_role, @permitted_services,
@analytics_domains, @account, @thinking_active

Constant Summary collapse

AGENT_PROMPTS_DIR =
Rails.root.join('app/prompts/assistant/agents').freeze
INSTRUCTIONS_TEMPLATE_PATH =
Rails.root.join('app/prompts/assistant/sunny_agent/instructions.txt.erb').freeze
ANALYTICS_SERVICES =
%w[google_analytics search_console ahrefs google_ads].freeze
MESSAGE_DOMAIN_PATTERNS =
{
  seo_auditor:     /\b(seo|seo audit|backlink|ranking|keyword|search console|ahrefs|serp|organic traffic)\b/i,
  sales_manager:   /\b(who.?s working|work.?schedule|team.?availability|rep.?workload|(?:plan|schedule) for (?:the )?(?:team|rep|shift|day|\w+.?s shift)|pipeline.?for|performance.?of|shift.?plan|day.?plan|(?:team|rep|shift) coverage|get.?a.?plan.?(?:for|together)|working today|who.?is off|(?:rep|team|agent) capacity|daily.?plan)\b/i,
  data_analyst:    /\b(sales|revenue|rep|order|customer|metric|report|query|how many|top \d|dashboard|pipeline|quota)\b/i,
  blog_editor:     /\b(blog|post|article|faq|content|heading|meta description|slug)\b/i
}.freeze
DOMAIN_TOOL_REQUIREMENTS =
{
  data_analyst:   ->(services) { services.any? { |s| s == 'app_db' || s.start_with?('postgres_') || ANALYTICS_SERVICES.include?(s) } },
  blog_editor:    ->(services) { services.include?('blog_management') || services.include?('content') },
  seo_auditor:    ->(services) { services.include?('seo_audit') },
  sales_manager:  ->(services) { services.include?('sales_management') },
  general:        ->(_) { true }
}.freeze