Class: Ace::PromptPrep::Organisms::PromptProcessor

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/prompt_prep/organisms/prompt_processor.rb

Overview

Orchestrates read → archive → bundle → output flow

Class Method Summary collapse

Class Method Details

.call(input_path: nil, bundle: false, enhance: false, model: nil, system_prompt: nil) ⇒ Hash

Process prompt: read, archive, optionally process via bundle and/or enhance, return content

Parameters:

  • input_path (String, nil) (defaults to: nil)

    Optional custom input path (resolved by CLI)

  • bundle (Boolean) (defaults to: false)

    Whether to process via ace-bundle SDK

  • enhance (Boolean) (defaults to: false)

    Whether to enhance prompt via LLM

  • model (String, nil) (defaults to: nil)

    LLM model alias or provider:model

  • system_prompt (String, nil) (defaults to: nil)

    Custom system prompt path

Returns:

  • (Hash)

    Hash with :content, :archive_path, :success, :error keys



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
90
91
92
93
94
95
96
97
98
99
100
101
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/ace/prompt_prep/organisms/prompt_processor.rb', line 24

def self.call(input_path: nil, bundle: false, enhance: false, model: nil, system_prompt: nil)
  # Use provided input path (already resolved by CLI)
  final_input_path = input_path

  # Read prompt
  read_result = Molecules::PromptReader.call(path: final_input_path)
  unless read_result[:success]
    return {
      content: nil,
      archive_path: nil,
      success: false,
      error: read_result[:error]
    }
  end

  original_content = read_result[:content]

  # Determine archive directory and symlink path based on prompt location
  archive_dir, symlink_path = if final_input_path
    prompt_dir = File.dirname(final_input_path)
    [File.join(prompt_dir, "archive"), File.join(prompt_dir, "_previous.md")]
  else
    [nil, nil] # Use defaults
  end

  # Archive ORIGINAL content (before context expansion)
  archive_result = Molecules::PromptArchiver.call(
    content: original_content,
    archive_dir: archive_dir,
    symlink_path: symlink_path
  )
  unless archive_result[:success]
    return {
      content: original_content,
      archive_path: nil,
      success: false,
      error: archive_result[:error]
    }
  end

  # Check if bundle is explicitly disabled in frontmatter
  extracted = Atoms::FrontmatterExtractor.extract(original_content)
  bundle_enabled = if extracted[:has_frontmatter] && extracted[:frontmatter]["bundle"]
    extracted[:frontmatter]["bundle"]["enabled"] != false
  else
    true # Default to enabled if not specified
  end

  # Determine output content based on bundle flag and frontmatter
  output_content = if bundle && bundle_enabled
    # ace-bundle handles entire file processing (including frontmatter)
    bundle_content = Molecules::BundleLoader.call(read_result[:path])
    if bundle_content.empty?
      # Fallback: extract body ONLY if ace-bundle fails
      warn "Warning: ace-bundle failed, extracting prompt body only"
      extracted[:body]
    else
      # Use ace-bundle processed content (includes frontmatter handling)
      bundle_content
    end
  else
    # No bundle or bundle disabled - just strip frontmatter for clean output
    extracted[:body]
  end

  # Track the final archive path (may change if enhanced)
  final_archive_path = archive_result[:archive_path]
  final_symlink_path = archive_result[:symlink_path]
  symlink_was_updated = archive_result[:symlink_updated]

  # Apply enhancement if requested
  if enhance
    # Get config values if not provided
    config = Ace::PromptPrep.config["enhance"] || {}
    final_model = model || config["model"]
    final_system_prompt = system_prompt || config["system_prompt"]
    temperature = config["temperature"] || 0.3

    # Enhance the content
    enhance_result = PromptEnhancer.call(
      content: output_content,
      model: final_model,
      system_prompt_uri: final_system_prompt,
      temperature: temperature
    )

    # Archive enhanced version if enhancement succeeded
    if enhance_result[:enhanced]
      # Calculate next iteration number
      timestamp = File.basename(archive_result[:archive_path], ".md")
      iteration = Molecules::EnhancementTracker.next_iteration(timestamp)
      enhanced_filename = Molecules::EnhancementTracker.enhancement_filename(timestamp, iteration)

      # Archive enhanced content with _eNNN suffix
      enhanced_archive_path = File.join(
        File.dirname(archive_result[:archive_path]),
        enhanced_filename
      )
      File.write(enhanced_archive_path, enhance_result[:content], encoding: "utf-8")

      # Update symlink to point to enhanced version
      symlink_result = Molecules::PromptArchiver.update_symlink(final_symlink_path, enhanced_archive_path)

      # Update final archive path to enhanced version
      final_archive_path = enhanced_archive_path
      symlink_was_updated = symlink_result[:success]

      # Update output content to enhanced version
      output_content = enhance_result[:content]

      # Write enhanced content back to source file (preserve frontmatter)
      original_extracted = Atoms::FrontmatterExtractor.extract(original_content)
      write_content = if original_extracted[:has_frontmatter] && original_extracted[:raw_frontmatter]
        "---\n#{original_extracted[:raw_frontmatter]}---\n\n#{enhance_result[:content]}"
      else
        enhance_result[:content]
      end
      File.write(read_result[:path], write_content, encoding: "utf-8")
    end
  end

  # Track if enhancement actually occurred
  enhancement_occurred = enhance && defined?(enhance_result) && enhance_result&.dig(:enhanced)

  # Return content and archive info
  {
    content: output_content,
    archive_path: final_archive_path,
    symlink_path: final_symlink_path,
    symlink_updated: symlink_was_updated,
    source_path: read_result[:path],
    source_updated: enhancement_occurred,
    success: true,
    error: nil
  }
end