mirror of
				https://github.com/discourse/discourse-ai.git
				synced 2025-11-04 08:28:46 +00:00 
			
		
		
		
	
		
			
	
	
		
			155 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
		
		
			
		
	
	
			155 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| 
								 | 
							
								#frozen_string_literal: true
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module DiscourseAi::AiBot::Commands
							 | 
						||
| 
								 | 
							
								  MAX_CONTEXT_TOKENS = 2000
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  class SettingContextCommand < Command
							 | 
						||
| 
								 | 
							
								    def self.rg_installed?
							 | 
						||
| 
								 | 
							
								      if defined?(@rg_installed)
							 | 
						||
| 
								 | 
							
								        @rg_installed
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        @rg_installed =
							 | 
						||
| 
								 | 
							
								          begin
							 | 
						||
| 
								 | 
							
								            Discourse::Utils.execute_command("which", "rg")
							 | 
						||
| 
								 | 
							
								            true
							 | 
						||
| 
								 | 
							
								          rescue Discourse::Utils::CommandError
							 | 
						||
| 
								 | 
							
								            false
							 | 
						||
| 
								 | 
							
								          end
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    class << self
							 | 
						||
| 
								 | 
							
								      def name
							 | 
						||
| 
								 | 
							
								        "setting_context"
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      def desc
							 | 
						||
| 
								 | 
							
								        "Will provide you with full context regarding a particular site setting in Discourse"
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      def parameters
							 | 
						||
| 
								 | 
							
								        [
							 | 
						||
| 
								 | 
							
								          Parameter.new(
							 | 
						||
| 
								 | 
							
								            name: "setting_name",
							 | 
						||
| 
								 | 
							
								            description: "The name of the site setting we need context for",
							 | 
						||
| 
								 | 
							
								            type: "string",
							 | 
						||
| 
								 | 
							
								            required: true,
							 | 
						||
| 
								 | 
							
								          ),
							 | 
						||
| 
								 | 
							
								        ]
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def result_name
							 | 
						||
| 
								 | 
							
								      "context"
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def description_args
							 | 
						||
| 
								 | 
							
								      { setting_name: @setting_name }
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    CODE_FILE_EXTENSIONS = "rb,js,gjs,hbs"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def process(setting_name:)
							 | 
						||
| 
								 | 
							
								      if !self.class.rg_installed?
							 | 
						||
| 
								 | 
							
								        return(
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            setting_name: setting_name,
							 | 
						||
| 
								 | 
							
								            context: "This command requires the rg command line tool to be installed on the server",
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      @setting_name = setting_name
							 | 
						||
| 
								 | 
							
								      if !SiteSetting.has_setting?(setting_name)
							 | 
						||
| 
								 | 
							
								        { setting_name: setting_name, context: "This setting does not exist" }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        description = SiteSetting.description(setting_name)
							 | 
						||
| 
								 | 
							
								        result = +"# #{setting_name}\n#{description}\n\n"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        setting_info =
							 | 
						||
| 
								 | 
							
								          find_setting_info(setting_name, [Rails.root.join("config", "site_settings.yml").to_s])
							 | 
						||
| 
								 | 
							
								        if !setting_info
							 | 
						||
| 
								 | 
							
								          setting_info =
							 | 
						||
| 
								 | 
							
								            find_setting_info(setting_name, Dir[Rails.root.join("plugins/**/settings.yml")])
							 | 
						||
| 
								 | 
							
								        end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        result << setting_info
							 | 
						||
| 
								 | 
							
								        result << "\n\n"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        %w[lib app plugins].each do |dir|
							 | 
						||
| 
								 | 
							
								          path = Rails.root.join(dir).to_s
							 | 
						||
| 
								 | 
							
								          result << Discourse::Utils.execute_command(
							 | 
						||
| 
								 | 
							
								            "rg",
							 | 
						||
| 
								 | 
							
								            setting_name,
							 | 
						||
| 
								 | 
							
								            path,
							 | 
						||
| 
								 | 
							
								            "-g",
							 | 
						||
| 
								 | 
							
								            "!**/spec/**",
							 | 
						||
| 
								 | 
							
								            "-g",
							 | 
						||
| 
								 | 
							
								            "!**/dist/**",
							 | 
						||
| 
								 | 
							
								            "-g",
							 | 
						||
| 
								 | 
							
								            "*.{#{CODE_FILE_EXTENSIONS}}",
							 | 
						||
| 
								 | 
							
								            "-C",
							 | 
						||
| 
								 | 
							
								            "10",
							 | 
						||
| 
								 | 
							
								            "--color",
							 | 
						||
| 
								 | 
							
								            "never",
							 | 
						||
| 
								 | 
							
								            "--heading",
							 | 
						||
| 
								 | 
							
								            "--no-ignore",
							 | 
						||
| 
								 | 
							
								            chdir: path,
							 | 
						||
| 
								 | 
							
								            success_status_codes: [0, 1],
							 | 
						||
| 
								 | 
							
								          )
							 | 
						||
| 
								 | 
							
								        end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        result.gsub!(/^#{Regexp.escape(Rails.root.to_s)}/, "")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        result = tokenizer.truncate(result, MAX_CONTEXT_TOKENS)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        { setting_name: setting_name, context: result }
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def find_setting_info(name, paths)
							 | 
						||
| 
								 | 
							
								      path, result = nil
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      paths.each do |search_path|
							 | 
						||
| 
								 | 
							
								        result =
							 | 
						||
| 
								 | 
							
								          Discourse::Utils.execute_command(
							 | 
						||
| 
								 | 
							
								            "rg",
							 | 
						||
| 
								 | 
							
								            name,
							 | 
						||
| 
								 | 
							
								            search_path,
							 | 
						||
| 
								 | 
							
								            "-g",
							 | 
						||
| 
								 | 
							
								            "*.{#{CODE_FILE_EXTENSIONS}}",
							 | 
						||
| 
								 | 
							
								            "-A",
							 | 
						||
| 
								 | 
							
								            "10",
							 | 
						||
| 
								 | 
							
								            "--color",
							 | 
						||
| 
								 | 
							
								            "never",
							 | 
						||
| 
								 | 
							
								            "--heading",
							 | 
						||
| 
								 | 
							
								            success_status_codes: [0, 1],
							 | 
						||
| 
								 | 
							
								          )
							 | 
						||
| 
								 | 
							
								        if !result.blank?
							 | 
						||
| 
								 | 
							
								          path = search_path
							 | 
						||
| 
								 | 
							
								          break
							 | 
						||
| 
								 | 
							
								        end
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if result.blank?
							 | 
						||
| 
								 | 
							
								        nil
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        rows = result.split("\n")
							 | 
						||
| 
								 | 
							
								        leading_spaces = rows[0].match(/^\s*/)[0].length
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        filtered = []
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        rows.each do |row|
							 | 
						||
| 
								 | 
							
								          if !filtered.blank?
							 | 
						||
| 
								 | 
							
								            break if row.match(/^\s*/)[0].length <= leading_spaces
							 | 
						||
| 
								 | 
							
								          end
							 | 
						||
| 
								 | 
							
								          filtered << row
							 | 
						||
| 
								 | 
							
								        end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        filtered.unshift("#{path}")
							 | 
						||
| 
								 | 
							
								        filtered.join("\n")
							 | 
						||
| 
								 | 
							
								      end
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								end
							 |