Module: Insika::Tools::AgentEnum
- Defined in:
- lib/insika/tools/agent_enum.rb
Overview
Names the parent's subagent allowlist INSIDE the delegation tools' schema.
The allowlist is per-turn data (profile.subagents), while a RubyLLM tool's
schema is class-level, so the enum has to be injected per instance. Without
it the model is told only that agent "must be one this agent may spawn" and
is left to guess the ids; with it, the valid values are part of the contract
the provider sees.
Tolerant by construction: JSON-schema hashes reach us with symbol keys (the
class-level params(...) form) or string keys (anything that round-tripped
through JSON), and a shape we do not recognize is returned UNTOUCHED — a
schema we failed to annotate still works, one we corrupted would break every
delegation.
Class Method Summary collapse
- .deep_dup(value) ⇒ Object
- .fetch(node, key) ⇒ Object
-
.inject(schema, allowed, path:) ⇒ Object
schema: the tool's JSON schema · allowed: [String] · path: the property chain leading to the
agentproperty, e.g. -
.key_for(hash, key) ⇒ Object
Keep the hash's own key convention instead of mixing symbols into a string-keyed schema.
-
.resolve(node, path) ⇒ Object
Walks
properties(anditemsfor an array) down to the named property.
Class Method Details
.deep_dup(value) ⇒ Object
59 60 61 62 63 64 65 |
# File 'lib/insika/tools/agent_enum.rb', line 59 def deep_dup(value) case value when Hash then value.each_with_object({}) { |(k, v), acc| acc[k] = deep_dup(v) } when Array then value.map { |v| deep_dup(v) } else value end end |
.fetch(node, key) ⇒ Object
47 48 49 50 51 |
# File 'lib/insika/tools/agent_enum.rb', line 47 def fetch(node, key) return nil unless node.is_a?(Hash) node[key] || node[key.to_s] end |
.inject(schema, allowed, path:) ⇒ Object
schema: the tool's JSON schema · allowed: [String] · path: the property
chain leading to the agent property, e.g. %i or %i[tasks agent].
-> a COPY with enum set, or the original when there is nothing to do.
24 25 26 27 28 29 30 31 32 33 |
# File 'lib/insika/tools/agent_enum.rb', line 24 def inject(schema, allowed, path:) return schema if schema.nil? || Array(allowed).empty? copy = deep_dup(schema) target = resolve(copy, path) return schema if target.nil? target[key_for(target, :enum)] = Array(allowed).map(&:to_s) copy end |
.key_for(hash, key) ⇒ Object
Keep the hash's own key convention instead of mixing symbols into a string-keyed schema.
55 56 57 |
# File 'lib/insika/tools/agent_enum.rb', line 55 def key_for(hash, key) hash.keys.any? { |k| k.is_a?(String) } ? key.to_s : key end |
.resolve(node, path) ⇒ Object
Walks properties (and items for an array) down to the named property.
36 37 38 39 40 41 42 43 44 45 |
# File 'lib/insika/tools/agent_enum.rb', line 36 def resolve(node, path) path.reduce(node) do |current, segment| props = fetch(current, :properties) props = fetch(fetch(current, :items) || {}, :properties) if props.nil? prop = props && (props[segment] || props[segment.to_s]) return nil unless prop.is_a?(Hash) prop end end |