mirror of
				https://github.com/discourse/discourse-ai.git
				synced 2025-10-31 14:38:37 +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 |