Class: Riffer::Skills::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/riffer/skills/context.rb,
sig/generated/riffer/skills/context.rbs

Overview

Skills context for an agent generation cycle — coordinates discovery, activation, and prompt rendering, caching skill bodies to avoid redundant backend reads. Exposed to tools via context.skills.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(backend:, skills:, adapter:) ⇒ Context

-- : (backend: Riffer::Skills::Backend, skills: Hash[String, Riffer::Skills::Frontmatter], adapter: Riffer::Skills::Adapter) -> void

Parameters:



24
25
26
27
28
29
30
31
# File 'lib/riffer/skills/context.rb', line 24

def initialize(backend:, skills:, adapter:)
  @backend = backend
  @skills = skills
  @adapter = adapter
  @bodies = {} #: Hash[String, String]
  @activated = [] #: Array[String]
  @preactivated = [] #: Array[String]
end

Instance Attribute Details

#adapterRiffer::Skills::Adapter (readonly)

The skill adapter used for this context.



17
18
19
# File 'lib/riffer/skills/context.rb', line 17

def adapter
  @adapter
end

#on_activate^(String) -> void?

Optional callback invoked when a skill is first activated.

Returns:

  • (^(String) -> void, nil)


20
21
22
# File 'lib/riffer/skills/context.rb', line 20

def on_activate
  @on_activate
end

#skillsHash[String, Riffer::Skills::Frontmatter] (readonly)

Skill catalog indexed by name.

Returns:



14
15
16
# File 'lib/riffer/skills/context.rb', line 14

def skills
  @skills
end

Instance Method Details

#activatable?Boolean

Returns whether any skill is available for the model to activate.

: () -> bool

Returns:

  • (Boolean)


114
115
116
# File 'lib/riffer/skills/context.rb', line 114

def activatable?
  available_skills.any?
end

#activate(name) ⇒ String

Activates a skill by name. Returns the cached body on re-activation.

Raises Riffer::ArgumentError if the skill is not in the catalog.

-- : (String) -> String

Parameters:

  • (String)

Returns:

  • (String)


50
51
52
53
54
55
56
57
# File 'lib/riffer/skills/context.rb', line 50

def activate(name)
  body = read(name)
  unless @activated.include?(name)
    @activated << name
    @on_activate&.call(name)
  end
  body
end

#activated?(name) ⇒ Boolean

Returns whether a skill has been activated.

-- : (String) -> bool

Parameters:

  • (String)

Returns:

  • (Boolean)


99
100
101
# File 'lib/riffer/skills/context.rb', line 99

def activated?(name)
  @activated.include?(name)
end

#activation_prompt(name) ⇒ String

Activates a skill and returns its body wrapped for injection as a user message.

Raises Riffer::ArgumentError if the skill is not in the catalog.

-- : (String) -> String

Parameters:

  • (String)

Returns:

  • (String)


66
67
68
69
# File 'lib/riffer/skills/context.rb', line 66

def activation_prompt(name)
  body = activate(name)
  @adapter.render_activation(skills.fetch(name), body)
end

#available_skillsArray[Riffer::Skills::Frontmatter]

-- : () -> Array

Returns:



134
135
136
# File 'lib/riffer/skills/context.rb', line 134

def available_skills
  skills.values.reject { |skill| @preactivated.include?(skill.name) || skill.disable_model_invocation }
end

#deactivate(name) ⇒ void

This method returns an undefined value.

Clears a skill's activation so the next activation is treated as the first.

Raises Riffer::ArgumentError if the skill is not in the catalog.

-- : (String) -> void

Parameters:

  • (String)


89
90
91
92
93
# File 'lib/riffer/skills/context.rb', line 89

def deactivate(name)
  raise Riffer::ArgumentError, "Unknown skill: '#{name}'" unless skills.key?(name)
  @activated.delete(name)
  nil
end

#model_invocable?(name) ⇒ Boolean

Returns whether a skill exists and may be activated by the model.

: (String) -> bool

Parameters:

  • (String)

Returns:

  • (Boolean)


106
107
108
109
# File 'lib/riffer/skills/context.rb', line 106

def model_invocable?(name)
  skill = skills[name]
  !skill.nil? && !skill.disable_model_invocation
end

#preactivate(name) ⇒ void

This method returns an undefined value.

Activates a skill whose body renders in the system prompt rather than the conversation.

Raises Riffer::ArgumentError if the skill is not in the catalog.

-- : (String) -> void

Parameters:

  • (String)


78
79
80
81
# File 'lib/riffer/skills/context.rb', line 78

def preactivate(name)
  activate(name)
  @preactivated << name unless @preactivated.include?(name)
end

#read(name) ⇒ String

Returns a skill's body without recording an activation.

Raises Riffer::ArgumentError if the skill is not in the catalog.

-- : (String) -> String

Parameters:

  • (String)

Returns:

  • (String)


39
40
41
42
# File 'lib/riffer/skills/context.rb', line 39

def read(name)
  raise Riffer::ArgumentError, "Unknown skill: '#{name}'" unless skills.key?(name)
  @bodies[name] ||= @backend.read_skill(name)
end

#system_promptString

Returns the complete skills section for the system prompt — the catalog plus any pre-activated skill bodies.

: () -> String

Returns:

  • (String)


122
123
124
125
126
127
128
# File 'lib/riffer/skills/context.rb', line 122

def system_prompt
  available = available_skills
  parts = [] #: Array[String]
  parts << @adapter.render_catalog(available) unless available.empty?
  @preactivated.each { |name| parts << @adapter.render_activation(skills.fetch(name), @bodies.fetch(name)) }
  parts.join("\n\n")
end