Class: RailsConsoleAi::SkillLoader

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_console_ai/skill_loader.rb

Constant Summary collapse

SKILLS_DIR =
'skills'

Instance Method Summary collapse

Constructor Details

#initialize(storage = nil) ⇒ SkillLoader

Returns a new instance of SkillLoader.



7
8
9
# File 'lib/rails_console_ai/skill_loader.rb', line 7

def initialize(storage = nil)
  @storage = storage || RailsConsoleAi.storage
end

Instance Method Details

#delete_skill(name:) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/rails_console_ai/skill_loader.rb', line 60

def delete_skill(name:)
  key = skill_key(name)
  unless @storage.exists?(key)
    found = load_all_skills.find { |s| s['name'].to_s.downcase == name.to_s.downcase }
    return "No skill found: \"#{name}\"" unless found
    key = skill_key(found['name'])
  end

  skill = load_skill(key)
  @storage.delete(key)
  "Skill deleted: \"#{skill ? skill['name'] : name}\""
rescue Storage::StorageError => e
  "FAILED to delete skill (#{e.message})."
end

#find_skill(name) ⇒ Object



30
31
32
33
# File 'lib/rails_console_ai/skill_loader.rb', line 30

def find_skill(name)
  skills = load_all_skills
  skills.find { |s| s['name'].to_s.downcase == name.to_s.downcase }
end

#load_all_skillsObject



11
12
13
14
15
16
17
# File 'lib/rails_console_ai/skill_loader.rb', line 11

def load_all_skills
  keys = @storage.list("#{SKILLS_DIR}/*.md")
  keys.filter_map { |key| load_skill(key) }
rescue => e
  RailsConsoleAi.logger.warn("RailsConsoleAi: failed to load skills: #{e.message}")
  []
end

#save_skill(name:, description:, body:, tags: [], bypass_guards_for_methods: []) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rails_console_ai/skill_loader.rb', line 35

def save_skill(name:, description:, body:, tags: [], bypass_guards_for_methods: [])
  key = skill_key(name)
  existing = find_skill(name)

  frontmatter = {
    'name' => name,
    'description' => description,
    'tags' => Array(tags)
  }
  bypasses = Array(bypass_guards_for_methods)
  frontmatter['bypass_guards_for_methods'] = bypasses unless bypasses.empty?

  content = "---\n#{YAML.dump(frontmatter).sub("---\n", '').strip}\n---\n\n#{body}\n"
  @storage.write(key, content)

  path = @storage.respond_to?(:root_path) ? File.join(@storage.root_path, key) : key
  if existing
    "Skill updated: \"#{name}\" (#{path})"
  else
    "Skill created: \"#{name}\" (#{path})"
  end
rescue Storage::StorageError => e
  "FAILED to save skill (#{e.message})."
end

#skill_summariesObject



19
20
21
22
23
24
25
26
27
28
# File 'lib/rails_console_ai/skill_loader.rb', line 19

def skill_summaries
  skills = load_all_skills
  return nil if skills.empty?

  skills.map { |s|
    tags = Array(s['tags'])
    tag_str = tags.empty? ? '' : " [#{tags.join(', ')}]"
    "- **#{s['name']}**#{tag_str}: #{s['description']}"
  }
end