Class: Envoy::Library
- Inherits:
-
Object
- Object
- Envoy::Library
- Defined in:
- lib/envoy/library.rb
Overview
A set of reference documents the model can pull on demand.
Progressive disclosure: preloading every reference doc costs thousands of tokens on turns that never need them. A library puts a short index in the instructions and hands the model one tool to fetch a document when the task actually calls for it.
Compiles to an ordinary Toolset, so it composes via use, merges its
description into instructions, and honours read_only — all for free.
Instance Attribute Summary collapse
-
#key ⇒ Object
readonly
Returns the value of attribute key.
Instance Method Summary collapse
- #description(text = nil) ⇒ Object
-
#directory(path) ⇒ Object
Ingest a directory of markdown: README.md becomes the description, every other *.md becomes a document keyed by its slug.
-
#document(slug, summary = nil, &block) ⇒ Object
Register one document.
- #document_keys ⇒ Object
-
#initialize(key) ⇒ Library
constructor
A new instance of Library.
- #read(slug) ⇒ Object
-
#rendered_description ⇒ Object
The description plus an index of any documents that carry their own summary.
- #to_toolset ⇒ Object
Constructor Details
#initialize(key) ⇒ Library
Returns a new instance of Library.
14 15 16 17 18 |
# File 'lib/envoy/library.rb', line 14 def initialize(key) @key = key.to_s @description = "" @documents = {} # slug => { summary:, body: callable } end |
Instance Attribute Details
#key ⇒ Object (readonly)
Returns the value of attribute key.
12 13 14 |
# File 'lib/envoy/library.rb', line 12 def key @key end |
Instance Method Details
#description(text = nil) ⇒ Object
20 21 22 23 |
# File 'lib/envoy/library.rb', line 20 def description(text = nil) return rendered_description if text.nil? @description = text end |
#directory(path) ⇒ Object
Ingest a directory of markdown: README.md becomes the description, every other *.md becomes a document keyed by its slug. Flat, non-recursive.
No markdown parsing: a README that documents its own directory already
carries the human-written index, and the tool's enum carries the
machine-readable key list. Explicit document calls win over files.
36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/envoy/library.rb', line 36 def directory(path) path = Pathname(path) readme = path.join("README.md") @description = readme.read if readme.exist? path.glob("*.md").sort.each do |file| slug = file.basename(".md").to_s next if slug.casecmp("README").zero? @documents[slug] ||= { summary: nil, body: -> { file.read } } end end |
#document(slug, summary = nil, &block) ⇒ Object
Register one document. The block is the lazy body.
26 27 28 |
# File 'lib/envoy/library.rb', line 26 def document(slug, summary = nil, &block) @documents[slug.to_s] = { summary: summary, body: block } end |
#document_keys ⇒ Object
48 49 50 |
# File 'lib/envoy/library.rb', line 48 def document_keys @documents.keys.sort end |
#read(slug) ⇒ Object
52 53 54 55 56 |
# File 'lib/envoy/library.rb', line 52 def read(slug) entry = @documents[slug.to_s] raise ArgumentError, "no document #{slug.inspect}" unless entry entry[:body].call end |
#rendered_description ⇒ Object
The description plus an index of any documents that carry their own summary. Directory-ingested docs are indexed by the README itself, so listing them again would just duplicate it.
61 62 63 64 65 66 67 |
# File 'lib/envoy/library.rb', line 61 def rendered_description summarised = @documents.select { |_, entry| entry[:summary].present? } return @description if summarised.empty? index = summarised.map { |slug, entry| " #{slug} — #{entry[:summary]}" } [ @description, "Also available:", *index ].compact_blank.join("\n") end |
#to_toolset ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/envoy/library.rb', line 69 def to_toolset library = self toolset = Envoy::Toolset.new(key) toolset.description(rendered_description) toolset.tool("read_#{key}") do description "Read one #{library.key} reference document in full." access :read param :key, "Which document to read.", enum: library.document_keys perform { |actor:, key:| library.read(key) } end toolset end |