Module: Silas::Instructions
- Defined in:
- lib/silas/instructions.rb
Overview
Renders instructions.md ONCE per turn into an immutable snapshot — the determinism anchor. (Skill-index injection and loaded-skill inlining land with the skills work; the snapshot-once mechanics are load-bearing now.)
Class Method Summary collapse
- .base_instructions(turn) ⇒ Object
- .default_instructions ⇒ Object
-
.loaded_skills_block(session) ⇒ Object
Skills loaded in prior turns are inlined "for the rest of the session".
- .render(turn) ⇒ Object
-
.skill_index_block(session) ⇒ Object
Advertise skill descriptions (eve's routing hint); bodies load on demand.
- .snapshot!(turn) ⇒ Object
Class Method Details
.base_instructions(turn) ⇒ Object
24 25 26 27 28 29 30 31 32 |
# File 'lib/silas/instructions.rb', line 24 def base_instructions(turn) # config.instructions_dir points at the active agent's directory (root or a # subagent, swapped during a nested run). dir = Silas.config.instructions_dir || Rails.root.join("app/agent") path = Pathname(dir).join("instructions.md") return default_instructions unless path.exist? ERB.new(path.read).result_with_hash(session: turn.session, agent_name: turn.session.agent_name) end |
.default_instructions ⇒ Object
51 52 53 |
# File 'lib/silas/instructions.rb', line 51 def default_instructions "You are a helpful agent." end |
.loaded_skills_block(session) ⇒ Object
Skills loaded in prior turns are inlined "for the rest of the session".
44 45 46 47 48 49 |
# File 'lib/silas/instructions.rb', line 44 def loaded_skills_block(session) loaded = Silas.skills.select { |s| session.loaded_skills.include?(s.name) } return nil if loaded.empty? loaded.map { |s| "## Skill: #{s.name}\n\n#{s.body.strip}" }.join("\n\n") end |
.render(turn) ⇒ Object
19 20 21 22 |
# File 'lib/silas/instructions.rb', line 19 def render(turn) [ base_instructions(turn), skill_index_block(turn.session), loaded_skills_block(turn.session) ] .compact.join("\n\n") end |
.skill_index_block(session) ⇒ Object
Advertise skill descriptions (eve's routing hint); bodies load on demand.
35 36 37 38 39 40 41 |
# File 'lib/silas/instructions.rb', line 35 def skill_index_block(session) advertised = Silas.skills.reject { |s| session.loaded_skills.include?(s.name) } return nil if advertised.empty? lines = advertised.map { |s| "- #{s.name}: #{s.description}" } "## Available skills\n\nLoad with the load_skill tool when relevant:\n#{lines.join("\n")}" end |
.snapshot!(turn) ⇒ Object
10 11 12 13 14 15 16 17 |
# File 'lib/silas/instructions.rb', line 10 def snapshot!(turn) return if turn.instructions_snapshot.present? # idempotent: replay-safe turn.update!( instructions_snapshot: render(turn), definitions_digest: Silas.config.definitions_digest&.call.to_s ) end |