Class: XAeonAgents::Agents::SkillGeneratorAgent

Inherits:
ComposableAgents::Agent
  • Object
show all
Includes:
XAeonAgents::AgentDefaults
Defined in:
lib/x_aeon_agents/agents/skill_generator_agent.rb

Overview

Agent responsible for generating skill files from ERB templates.

Instance Method Summary collapse

Methods included from XAeonAgents::AgentDefaults

#new_agent, prepended, singleton_session_id

Instance Method Details

#input_artifacts_contractsHash{Symbol => Object}

Define input artifacts contracts

Returns:

  • (Hash{Symbol => Object})

    Set of input artifacts description, per artifact name



13
14
15
16
17
18
19
20
21
# File 'lib/x_aeon_agents/agents/skill_generator_agent.rb', line 13

def input_artifacts_contracts
  {
    output_dir: 'Output directory for generated skills',
    skill_names: {
      description: 'Optional list of skill names to generate. If nil or empty, all skills are generated.',
      optional: true
    }
  }
end

#output_artifacts_contractsHash{Symbol => Object}

Define output artifacts contracts

Returns:

  • (Hash{Symbol => Object})

    Set of output artifacts description, per artifact name



26
27
28
# File 'lib/x_aeon_agents/agents/skill_generator_agent.rb', line 26

def output_artifacts_contracts
  { success: 'Whether the skill generation was successful' }
end

#run(output_dir: 'skills', skill_names: nil) ⇒ Hash{Symbol => Object}

Execute the agent to generate skill files from ERB templates.

Parameters:

  • output_dir (String) (defaults to: 'skills')

    Output directory for generated skills

  • skill_names (Array<String>, nil) (defaults to: nil)

    Optional list of skill names to generate. Supports comma-separated values within each element. If nil or empty, all skills are generated.

Returns:

  • (Hash{Symbol => Object})

    Output artifacts content



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
# File 'lib/x_aeon_agents/agents/skill_generator_agent.rb', line 36

def run(output_dir: 'skills', skill_names: nil)
  transformations = {
    '.erb' => proc { |src_file| GenHelpers::ErbEvaluator.new(src_file).result }
  }.freeze

  src_dir = File.expand_path('skills.src')
  src_pathname = Pathname.new(src_dir)
  dest_dir = File.expand_path(output_dir)

  FileUtils.mkdir_p(dest_dir)

  # Normalize skill_names: flatten, split by comma, strip, compact, uniq
  normalized_skill_names = (skill_names || [])
    .flat_map { |name| name.split(',') }
    .map(&:strip)
    .reject(&:empty?)
    .uniq

  failed = false
  Dir.glob(File.join(src_dir, '**', '*'), File::FNM_DOTMATCH)
    .select { |f| File.file?(f) && File.basename(f) != '.skill_config.yml' }
    .each do |src_file|
      relative_path = Pathname.new(src_file).relative_path_from(src_pathname).to_s
      # Determine the top-level skill directory for this file.
      # Skip files whose top-level skill directory is not in the requested list
      next if !normalized_skill_names.empty? && !normalized_skill_names.include?(relative_path.split('/').first)

      file_ext = File.extname(relative_path)
      dst_file = File.join(
        dest_dir,
        transformations.key?(file_ext) ? relative_path.sub(/#{Regexp.escape(file_ext)}$/, '') : relative_path
      )
      puts "Processing: #{relative_path}"
      puts "    Output: #{dst_file}"
      begin
        FileUtils.mkdir_p(File.dirname(dst_file))
        if transformations.key?(file_ext)
          File.write(dst_file, transformations[file_ext].call(src_file))
        else
          FileUtils.cp(src_file, dst_file)
        end
        puts '    Status: ✓ Processed successfully'
      rescue StandardError => e
        puts "    Status: ✗ Error - #{e.message}\n    #{e.backtrace.first}"
        failed = true
      end
      puts
    end

  puts
  if failed
    puts 'Skills generated with some errors (see above).'
  else
    puts 'Skills generated successfully.'
  end
  { success: !failed }
end