Module: PWN::AI::Agent::Dispatch
- Defined in:
- lib/pwn/ai/agent/dispatch.rb
Overview
Tool-call dispatch: takes a single tool_call object (OpenAI shape), looks up the registered handler, parses args, runs it, and returns a JSON string suitable for a role:'tool' message.
TOLERANT DISPATCH (local-model scaffolding)
Local models (qwen/llama/mistral on Ollama) frequently emit almost-
right tool calls: run_shell instead of shell, trailing commas,
single-quoted JSON, arguments as a bare string. Strict parsing burns
an iteration and often spirals. Dispatch now:
* repair_name — Levenshtein-matches unknown names to the closest
registered tool and records a Mistakes fingerprint
(source: :repair) so the KNOWN MISTAKES block
eventually teaches the model the right name.
* parse_args — falls back to a JSON5-ish clean-up pass (strip
trailing commas, swap single→double quotes, wrap a
bare scalar as the tool's sole required arg).
Frontier engines never hit these paths — repair is a no-op when the name/JSON are already valid.
Class Method Summary collapse
-
.authors ⇒ Object
- Author(s)
0day Inc.
-
.call(opts = {}) ⇒ Object
- Supported Method Parameters
json_str = PWN::AI::Agent::Dispatch.call( tool_call: 'required - Hash { id:, type:, function: { name:, arguments: } }' ).
-
.help ⇒ Object
Display Usage for this Module.
-
.repair_name(opts = {}) ⇒ Object
- Supported Method Parameters
fixed = PWN::AI::Agent::Dispatch.repair_name( name: 'required - possibly-wrong tool name emitted by the model' ).
Class Method Details
.authors ⇒ Object
- Author(s)
0day Inc. support@0dayinc.com
128 129 130 |
# File 'lib/pwn/ai/agent/dispatch.rb', line 128 public_class_method def self. "AUTHOR(S):\n 0day Inc. <support@0dayinc.com>\n" end |
.call(opts = {}) ⇒ Object
- Supported Method Parameters
json_str = PWN::AI::Agent::Dispatch.call( tool_call: 'required - Hash { id:, type:, function: { name:, arguments: } }' )
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/pwn/ai/agent/dispatch.rb', line 33 public_class_method def self.call(opts = {}) tool_call = opts[:tool_call] raise 'ERROR: tool_call is required' if tool_call.nil? fn = tool_call[:function] || tool_call['function'] || {} name = (fn[:name] || fn['name']).to_s raw = fn[:arguments] || fn['arguments'] || '{}' entry = Registry.lookup(name: name) || Registry.lookup(name: repair_name(name: name)) return JSON.generate(error: "unknown tool: #{name}") unless entry args = parse_args(raw: raw, entry: entry) result = entry.handler.call(args) JSON.generate(success: true, result: result) rescue StandardError => e JSON.generate( success: false, error: "#{e.class}: #{e.}", backtrace: Array(e.backtrace).first(3) ) end |
.help ⇒ Object
Display Usage for this Module
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/pwn/ai/agent/dispatch.rb', line 134 public_class_method def self.help puts <<~USAGE USAGE: json_str = PWN::AI::Agent::Dispatch.call( tool_call: { id: 'call_1', type: 'function', function: { name: 'shell', arguments: '{"command":"id"}' } } ) PWN::AI::Agent::Dispatch.repair_name(name: 'run_shell') # => 'shell' #{self}.authors USAGE end |
.repair_name(opts = {}) ⇒ Object
- Supported Method Parameters
fixed = PWN::AI::Agent::Dispatch.repair_name( name: 'required - possibly-wrong tool name emitted by the model' )
Returns the closest registered tool name by Levenshtein distance (max distance = 1/3 of the emitted name, min 3) or nil when nothing is close enough. Every successful repair is fingerprinted into Mistakes so the negative-feedback loop trains the model's output format via its own system prompt.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/pwn/ai/agent/dispatch.rb', line 66 public_class_method def self.repair_name(opts = {}) name = opts[:name].to_s return nil if name.empty? pool = Registry.all.map(&:name) return nil if pool.empty? best, dist = pool.map { |n| [n, DidYouMean::Levenshtein.distance(n, name)] } .min_by(&:last) thresh = [(name.length / 3.0).ceil, 3].max return nil if dist > thresh if defined?(Mistakes) Mistakes.record( tool: 'tool_name', error: "model emitted '#{name}', repaired to '#{best}'", args: name, source: :repair ) end best rescue StandardError nil end |