Class: AIA::PromptPipeline
- Inherits:
-
Object
- Object
- AIA::PromptPipeline
- Includes:
- SkillUtils
- Defined in:
- lib/aia/prompt_pipeline.rb
Instance Method Summary collapse
-
#add_context_files(prompt_text) ⇒ Object
Add context files to prompt text.
- #build_prompt_text(prompt_id) ⇒ Object
-
#initialize(prompt_handler, chat_processor, ui_presenter, input_collector) ⇒ PromptPipeline
constructor
A new instance of PromptPipeline.
-
#load_skills(skill_ids) ⇒ Object
Load skill bodies for the given skill IDs in order.
-
#process_all ⇒ Object
Process all prompts in the pipeline sequentially.
-
#process_single(prompt_id) ⇒ Object
Process a single prompt with all its requirements.
Methods included from SkillUtils
#find_skill_dir, #parse_front_matter, #path_based_id?, #safe_skill_path, #skill_body
Constructor Details
#initialize(prompt_handler, chat_processor, ui_presenter, input_collector) ⇒ PromptPipeline
Returns a new instance of PromptPipeline.
10 11 12 13 14 15 16 |
# File 'lib/aia/prompt_pipeline.rb', line 10 def initialize(prompt_handler, chat_processor, ui_presenter, input_collector) @prompt_handler = prompt_handler @chat_processor = chat_processor @ui_presenter = ui_presenter @input_collector = input_collector @include_context_flag = true end |
Instance Method Details
#add_context_files(prompt_text) ⇒ Object
Add context files to prompt text
139 140 141 142 143 144 145 146 147 |
# File 'lib/aia/prompt_pipeline.rb', line 139 def add_context_files(prompt_text) return prompt_text unless AIA.config.context_files && !AIA.config.context_files.empty? context = AIA.config.context_files.map do |file| File.read(file) rescue "Error reading file: #{file}" end.join("\n\n") "#{prompt_text}\n\nContext:\n#{context}" end |
#build_prompt_text(prompt_id) ⇒ Object
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 90 91 92 93 94 95 96 |
# File 'lib/aia/prompt_pipeline.rb', line 43 def build_prompt_text(prompt_id) role_id = AIA.config.prompts.role begin prompt_parsed = @prompt_handler.fetch_prompt(prompt_id) rescue StandardError => e warn "Error processing prompt '#{prompt_id}': #{e.}" AIA::LoggerManager.aia_logger.error("Error processing prompt '#{prompt_id}': #{e.}") return nil end return nil unless prompt_parsed role_parsed = nil unless role_id.nil? || role_id.empty? begin role_parsed = @prompt_handler.fetch_role(role_id) rescue StandardError => e warn "Warning: Could not load role '#{role_id}': #{e.}" AIA::LoggerManager.aia_logger.warn("Could not load role '#{role_id}': #{e.}") end end # Merge parameters from role and prompt all_params = {} all_params.merge!(role_parsed..parameters) if role_parsed&.&.parameters all_params.merge!(prompt_parsed..parameters) if prompt_parsed.&.parameters # Collect parameter values from user values = @input_collector.collect(all_params) # Render role, skills, and prompt. # Order: role (personality) → skills (task instructions) → prompt (user request) parts = [] parts << role_parsed.to_s(values) if role_parsed load_skills(AIA.config.prompts.skills).each { |body| parts << body } parts << prompt_parsed.to_s(values) if @include_context_flag # Process stdin content if AIA.config.stdin_content && !AIA.config.stdin_content.strip.empty? parts << PM.parse(AIA.config.stdin_content).to_s end end prompt_text = parts.join("\n\n") if @include_context_flag prompt_text = add_context_files(prompt_text) @include_context_flag = false end prompt_text end |
#load_skills(skill_ids) ⇒ Object
Load skill bodies for the given skill IDs in order. Each skill lives at skills_dir/<name>/SKILL.md; supports prefix matching. Path-based IDs (starting with /, ~/, ./, ../) are resolved as direct paths. Returns only the body content (front matter stripped).
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/aia/prompt_pipeline.rb', line 102 def load_skills(skill_ids) return [] if skill_ids.nil? || skill_ids.empty? skills_dir = AIA.config.skills.dir Array(skill_ids).filter_map do |skill_name| skill_name = skill_name.to_s.strip next if skill_name.empty? unless path_based_id?(skill_name) || Dir.exist?(skills_dir) warn "Warning: No skill matching '#{skill_name}' found in #{skills_dir}" next end skill_dir = find_skill_dir(skill_name, skills_dir) unless skill_dir if path_based_id?(skill_name) warn "Warning: No skill directory found at '#{File.(skill_name)}'" else warn "Warning: No skill matching '#{skill_name}' found in #{skills_dir}" end next end next skill_body(File.read(skill_dir)) if File.file?(skill_dir) skill_path = File.join(skill_dir, 'SKILL.md') unless File.exist?(skill_path) warn "Warning: Skill '#{skill_name}' has no SKILL.md in #{skill_dir}" next end skill_body(File.read(skill_path)) end end |
#process_all ⇒ Object
Process all prompts in the pipeline sequentially
19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/aia/prompt_pipeline.rb', line 19 def process_all prompt_count = 0 total_prompts = AIA.config.pipeline.size until AIA.config.pipeline.empty? prompt_count += 1 prompt_id = AIA.config.pipeline.shift puts "\n--- Processing prompt #{prompt_count}/#{total_prompts}: #{prompt_id} ---" if AIA.verbose? && total_prompts > 1 process_single(prompt_id) end end |
#process_single(prompt_id) ⇒ Object
Process a single prompt with all its requirements
34 35 36 37 38 39 40 41 |
# File 'lib/aia/prompt_pipeline.rb', line 34 def process_single(prompt_id) return if prompt_id.nil? || prompt_id.empty? prompt_text = build_prompt_text(prompt_id) return unless prompt_text send_and_get_response(prompt_text) end |