Class: Insika::ToolManifest

Inherits:
Data
  • Object
show all
Defined in:
lib/insika/tool_manifest.rb,
lib/insika/tool_manifest.rb

Overview

Reopens the class (constants inside a Data.define block land in the wrong LEXICAL scope — same pattern as the sibling ToolDefinition).

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#defaultsObject (readonly)

Returns the value of attribute defaults

Returns:

  • (Object)

    the current value of defaults



30
31
32
# File 'lib/insika/tool_manifest.rb', line 30

def defaults
  @defaults
end

#toolsObject (readonly)

Returns the value of attribute tools

Returns:

  • (Object)

    the current value of tools



30
31
32
# File 'lib/insika/tool_manifest.rb', line 30

def tools
  @tools
end

#versionObject (readonly)

Returns the value of attribute version

Returns:

  • (Object)

    the current value of version



30
31
32
# File 'lib/insika/tool_manifest.rb', line 30

def version
  @version
end

Class Method Details

.from_h(hash) ⇒ Object

Raw Hash (string|symbol keys) -> ToolManifest. Validates only the top-level STRUCTURE (version/defaults/tools); each tool's content is validated during normalization (per-tool, isolable by the Command — R4). Raises ValidationError.



42
43
44
45
46
47
48
49
50
51
# File 'lib/insika/tool_manifest.rb', line 42

def self.from_h(hash)
  h = stringify(hash || {})
  version = h.fetch("version", 1)
  defaults = h.fetch("defaults", {}) || {}
  tools = h.fetch("tools", []) || []
  raise Insika::ValidationError, "manifest: 'defaults' must be an object" unless defaults.is_a?(Hash)
  raise Insika::ValidationError, "manifest: 'tools' must be a list" unless tools.is_a?(Array)

  new(version: version, defaults: defaults, tools: tools)
end

.presence(str) ⇒ Object



216
# File 'lib/insika/tool_manifest.rb', line 216

def self.presence(str) = Insika::Coercion.presence(str)

.stringify(obj) ⇒ Object

Deep string keys (the wire may arrive symbolized; the nested JSON Schema must stay string-keyed — same as ToolDefinition's canonicalization).



214
# File 'lib/insika/tool_manifest.rb', line 214

def self.stringify(obj) = Insika::Coercion.deep_stringify(obj)

Instance Method Details

#definition_for(raw_tool, secrets:, env:) ⇒ Object

Normalizes ONE raw tool -> ToolDefinition Hash. Raises ValidationError (invalid envelope, missing endpoint/url, secret/env not configured, R3).



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/insika/tool_manifest.rb', line 62

def definition_for(raw_tool, secrets:, env:)
  t = self.class.stringify(raw_tool || {})
  raise Insika::ValidationError, "tool must be an object" unless t.is_a?(Hash)

  interface = extract_interface(t)
  binding = build_binding(t, secrets, env)

  {
    "name" => interface[:name], "description" => interface[:description],
    "parameters" => interface[:parameters],
    "request" => binding[:request],
    "response" => binding[:response],
    "secret_headers" => binding[:secret_headers],
    "side_effect" => t["side_effect"],
    "group" => t["group"] || defaults["group"],       # per-group allowlist:
    "tags" => (Array(defaults["tags"]) | Array(t["tags"])), # inherited default; tags unioned
    # Per-tool only: "this result ends the turn" is a property of THIS backend's
    # response, never something a manifest default should hand to its siblings.
    "halt_when" => t["halt_when"]
  }.compact
end

#tool_definitions(secrets:, env:) ⇒ Object

-> [ { ToolDefinition hash } ] with inherited defaults, normalized envelopes, resolved endpoint→url and resolved secret/env. Raises on the FIRST malformed tool — use #definition_for per-tool to isolate partial failure (R4).



56
57
58
# File 'lib/insika/tool_manifest.rb', line 56

def tool_definitions(secrets:, env:)
  tools.map { |t| definition_for(t, secrets: secrets, env: env) }
end