Class: Crimson::SkillRouter
- Inherits:
-
Object
- Object
- Crimson::SkillRouter
- Defined in:
- lib/crimson/skill_router.rb
Overview
Routes user intents to skills based on trigger keyword matching. Supports auto-inject skills triggered by tool usage and domain-based priority sorting.
Defined Under Namespace
Classes: Domain
Constant Summary collapse
- REPO_SKILLS_DIR =
Directory where bundled skills are stored in the repository.
File.("../../skills", __dir__)
- DOMAINS =
Built-in skill domains with their priority levels.
{ engineering: Domain.new(name: "engineering", priority: 10), analysis: Domain.new(name: "analysis", priority: 5), communication: Domain.new(name: "communication", priority: 5), safety: Domain.new(name: "safety", priority: 20), }.freeze
- MAX_CONDITIONAL_SKILLS =
2
Instance Method Summary collapse
-
#initialize(skills_dirs: nil) ⇒ SkillRouter
constructor
A new instance of SkillRouter.
-
#load_skill(name) ⇒ String?
Load a skill’s content (with front matter stripped).
-
#resolve(user_message, tools_invoked: []) ⇒ Array<String>
Resolve which skills are relevant to a user message.
-
#skill_names ⇒ Array<String>
All discovered skill names.
Constructor Details
#initialize(skills_dirs: nil) ⇒ SkillRouter
Returns a new instance of SkillRouter.
24 25 26 27 28 29 |
# File 'lib/crimson/skill_router.rb', line 24 def initialize(skills_dirs: nil) @skills_dirs = skills_dirs || [REPO_SKILLS_DIR] @manifests = {} @skill_paths = {} load_manifests end |
Instance Method Details
#load_skill(name) ⇒ String?
Load a skill’s content (with front matter stripped).
69 70 71 72 73 74 |
# File 'lib/crimson/skill_router.rb', line 69 def load_skill(name) path = @skill_paths[name.to_sym] return nil unless path && File.exist?(path) content = File.read(path) strip_front_matter(content) end |
#resolve(user_message, tools_invoked: []) ⇒ Array<String>
Resolve which skills are relevant to a user message.
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 |
# File 'lib/crimson/skill_router.rb', line 35 def resolve(, tools_invoked: []) lower = .to_s.downcase.strip matched = [] @manifests.each do |name, manifest| next if manifest[:auto_inject] next unless triggers_match?(lower, manifest[:triggers]) matched << { name: name, priority: manifest[:domain_priority], domain: manifest[:domain] } end matched.sort_by! { |s| -s[:priority] } result = ["coding"] seen_domains = Set.new matched.each do |skill| break if result.length >= MAX_CONDITIONAL_SKILLS + 1 next if seen_domains.include?(skill[:domain]) result << skill[:name].to_s seen_domains << skill[:domain] end @manifests.each do |name, manifest| next unless manifest[:auto_inject] next unless (tools_invoked & manifest[:auto_inject_tools]).any? result << name.to_s unless result.include?(name.to_s) end result end |
#skill_names ⇒ Array<String>
Returns all discovered skill names.
77 78 79 |
# File 'lib/crimson/skill_router.rb', line 77 def skill_names @manifests.keys.map(&:to_s) end |