Class: Envoy::Library

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

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

#keyObject (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_keysObject



48
49
50
# File 'lib/envoy/library.rb', line 48

def document_keys
  @documents.keys.sort
end

#read(slug) ⇒ Object

Raises:

  • (ArgumentError)


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_descriptionObject

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_toolsetObject



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