Module: PWN::AI::Agent::Registry

Defined in:
lib/pwn/ai/agent/registry.rb

Overview

Central registry for pwn-ai agent tools.

Each file under lib/pwn/ai/agent/tools/*.rb calls PWN::AI::Agent::Registry.register(…) at load time to declare a JSON-Schema (what the LLM sees) and a handler lambda (what pwn runs).

Registry.definitions(…) returns the OpenAI-format tools: array; Registry.lookup(name:) returns the entry for dispatch.

Import chain (circular-import safe):

agent/registry.rb        (no deps on tool files)
       ^
agent/tools/*.rb         (require registry, call .register at top level)
       ^
agent/loop.rb            (calls Registry.discover then .definitions)

Defined Under Namespace

Classes: Entry

Class Method Summary collapse

Class Method Details

.allObject

Supported Method Parameters

entries = PWN::AI::Agent::Registry.all



74
75
76
# File 'lib/pwn/ai/agent/registry.rb', line 74

public_class_method def self.all
  @entries.values
end

.authorsObject

Author(s)

0day Inc. <support@0dayinc.com>



128
129
130
# File 'lib/pwn/ai/agent/registry.rb', line 128

public_class_method def self.authors
  "AUTHOR(S):\n  0day Inc. <support@0dayinc.com>\n"
end

.definitions(opts = {}) ⇒ Object

Supported Method Parameters

tools = PWN::AI::Agent::Registry.definitions(

enabled: 'optional - Array of toolset names to include; nil = all whose check passes'

)



90
91
92
93
94
95
96
# File 'lib/pwn/ai/agent/registry.rb', line 90

public_class_method def self.definitions(opts = {})
  enabled = opts[:enabled]
  enabled = enabled.map(&:to_s) if enabled
  @entries.values
          .select { |e| (enabled.nil? || enabled.include?(e.toolset)) && safe_check(entry: e) }
          .map    { |e| { type: 'function', function: e.schema } }
end

.discover(opts = {}) ⇒ Object

Supported Method Parameters

names = PWN::AI::Agent::Registry.discover(

force: 'optional - re-require tool files even if already discovered (default false)'

)



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/pwn/ai/agent/registry.rb', line 103

public_class_method def self.discover(opts = {})
  force = opts[:force] ||= false
  return @entries.keys if @discovered && !force

  tools_dir = File.join(__dir__, 'tools')
  if Dir.exist?(tools_dir)
    Dir[File.join(tools_dir, '*.rb')].each do |f|
      require f
    rescue StandardError, LoadError => e
      warn "[pwn-ai] failed to load tool #{File.basename(f)}: #{e.class}: #{e.message}"
    end
  end
  @discovered = true
  @entries.keys
end

.helpObject

Display Usage for this Module



134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/pwn/ai/agent/registry.rb', line 134

public_class_method def self.help
  puts <<~USAGE
    USAGE:
      PWN::AI::Agent::Registry.discover
      PWN::AI::Agent::Registry.definitions(enabled: %w[terminal pwn])
      PWN::AI::Agent::Registry.lookup(name: 'shell')   # => Entry
      PWN::AI::Agent::Registry.toolsets                # => ["memory","pwn","skills","terminal"]
      PWN::AI::Agent::Registry.register(name:, toolset:, schema:, handler:)

      #{self}.authors
  USAGE
end

.lookup(opts = {}) ⇒ Object

Supported Method Parameters

entry = PWN::AI::Agent::Registry.lookup(

name: 'required - registered tool name'

)



66
67
68
69
# File 'lib/pwn/ai/agent/registry.rb', line 66

public_class_method def self.lookup(opts = {})
  name = opts[:name]
  @entries[name.to_s]
end

.register(opts = {}) ⇒ Object

Supported Method Parameters

PWN::AI::Agent::Registry.register(

name: 'required - tool name exposed to the model',
toolset: 'required - grouping for enable/disable (terminal, file, pwn, memory…)',
schema: 'required - OpenAI function schema {name:, description:, parameters:}',
handler: 'required - ->(args_hash) { ... } returning a JSON-serialisable object',
check: 'optional - -> { bool } gate; tool only advertised when truthy',
max_chars: 'optional - cap on serialised result (default 24_000)'

)



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/pwn/ai/agent/registry.rb', line 45

public_class_method def self.register(opts = {})
  name = opts[:name].to_s
  raise 'ERROR: name is required' if name.empty?
  raise 'ERROR: schema is required' unless opts[:schema]
  raise 'ERROR: handler is required' unless opts[:handler].respond_to?(:call)

  @entries[name] = Entry.new(
    name: name,
    toolset: opts[:toolset].to_s,
    schema: opts[:schema],
    handler: opts[:handler],
    check: opts[:check] ||= -> { true },
    max_chars: opts[:max_chars] ||= 24_000
  )
end

.toolsetsObject

Supported Method Parameters

names = PWN::AI::Agent::Registry.toolsets



81
82
83
# File 'lib/pwn/ai/agent/registry.rb', line 81

public_class_method def self.toolsets
  @entries.values.map(&:toolset).uniq.sort
end