Module: PWN::Memory
- Defined in:
- lib/pwn/memory.rb
Overview
PWN::Memory provides persistent cross-session memory for the pwn-ai agent (equivalent to Hermes agent memory providers). Facts, user preferences, environment details, lessons learned, and task state are stored in ~/.pwn/memory.json and survive across REPL restarts / pwn-ai sessions.
The pwn-ai agent (in agent mode) automatically receives relevant memory injected into its system prompt. The agent can also call remember/recall via ruby code blocks during execution loops.
Constant Summary collapse
- MEMORY_FILE =
File.join(Dir.home, '.pwn', 'memory.json')
Class Method Summary collapse
-
.authors ⇒ Object
- Author(s)
-
0day Inc.
-
.clear ⇒ Object
- Supported Method Parameters
-
PWN::Memory.clear.
-
.forget(key) ⇒ Object
rubocop:disable Naming/PredicateMethod.
-
.help ⇒ Object
Display Usage for this Module.
-
.load ⇒ Object
- Supported Method Parameters
-
memory = PWN::Memory.load.
-
.recall(opts = {}) ⇒ Object
- Supported Method Parameters
-
results = PWN::Memory.recall( query: ‘optional - string to search keys/values/categories (simple match)’, category: ‘optional - filter by category’, limit: ‘optional - max results (default 50)’ ).
-
.remember(opts = {}) ⇒ Object
- Supported Method Parameters
-
PWN::Memory.remember( key: ‘required - Symbol or String key for the memory fact’, value: ‘required - The value (any JSON serializable)’, category: ‘optional - e.g. :fact, :preference, :lesson, :env (default: :fact)’ ).
-
.save(mem = {}) ⇒ Object
- Supported Method Parameters
-
PWN::Memory.save(memory_hash).
-
.to_context(opts = {}) ⇒ Object
- Supported Method Parameters
-
context = PWN::Memory.to_context(limit: 20) (used internally by pwn-ai hook to inject into system prompt).
Class Method Details
.authors ⇒ Object
- Author(s)
-
0day Inc. <support@0dayinc.com>
117 118 119 |
# File 'lib/pwn/memory.rb', line 117 public_class_method def self. "AUTHOR(S):\n 0day Inc. <support@0dayinc.com>\n" end |
.clear ⇒ Object
- Supported Method Parameters
-
PWN::Memory.clear
95 96 97 98 |
# File 'lib/pwn/memory.rb', line 95 public_class_method def self.clear FileUtils.rm_f(MEMORY_FILE) {} end |
.forget(key) ⇒ Object
rubocop:disable Naming/PredicateMethod
86 87 88 89 90 91 |
# File 'lib/pwn/memory.rb', line 86 public_class_method def self.forget(key) # rubocop:disable Naming/PredicateMethod mem = load mem.delete(key.to_sym) save(mem) true end |
.help ⇒ Object
Display Usage for this Module
122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/pwn/memory.rb', line 122 public_class_method def self.help puts <<~USAGE USAGE: mem = PWN::Memory.load PWN::Memory.remember(key: :user_prefers_ruby, value: 'Always prefer pure Ruby + RestClient patterns', category: :preference) facts = PWN::Memory.recall(query: 'recon', category: :fact, limit: 10) PWN::Memory.forget(:some_key) PWN::Memory.clear context_str = PWN::Memory.to_context #{self}.authors USAGE end |
.load ⇒ Object
- Supported Method Parameters
-
memory = PWN::Memory.load
21 22 23 24 25 26 27 28 |
# File 'lib/pwn/memory.rb', line 21 public_class_method def self.load FileUtils.mkdir_p(File.dirname(MEMORY_FILE)) return {} unless File.exist?(MEMORY_FILE) JSON.parse(File.read(MEMORY_FILE), symbolize_names: true) rescue StandardError {} end |
.recall(opts = {}) ⇒ Object
- Supported Method Parameters
-
results = PWN::Memory.recall(
query: 'optional - string to search keys/values/categories (simple match)', category: 'optional - filter by category', limit: 'optional - max results (default 50)')
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/pwn/memory.rb', line 68 public_class_method def self.recall(opts = {}) query = opts[:query].to_s.downcase category = opts[:category] limit = opts[:limit] || 50 mem = load results = mem.select do |k, v| match = true match &&= k.to_s.downcase.include?(query) || v[:value].to_s.downcase.include?(query) || v[:category].to_s.downcase.include?(query) if query && !query.empty? match &&= (v[:category] == category.to_sym) if category match end results.to_a.first(limit).to_h end |
.remember(opts = {}) ⇒ Object
- Supported Method Parameters
-
PWN::Memory.remember(
key: 'required - Symbol or String key for the memory fact', value: 'required - The value (any JSON serializable)', category: 'optional - e.g. :fact, :preference, :lesson, :env (default: :fact)')
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/pwn/memory.rb', line 44 public_class_method def self.remember(opts = {}) key = opts[:key] value = opts[:value] category = opts[:category] || :fact raise 'ERROR: key and value are required' if key.nil? || value.nil? mem = load mem[key.to_sym] = { value: value, category: category.to_sym, timestamp: Time.now.utc.iso8601, source: 'pwn-ai' } save(mem) mem[key.to_sym] end |
.save(mem = {}) ⇒ Object
- Supported Method Parameters
-
PWN::Memory.save(memory_hash)
32 33 34 35 36 |
# File 'lib/pwn/memory.rb', line 32 public_class_method def self.save(mem = {}) FileUtils.mkdir_p(File.dirname(MEMORY_FILE)) File.write(MEMORY_FILE, JSON.pretty_generate(mem)) mem end |
.to_context(opts = {}) ⇒ Object
- Supported Method Parameters
-
context = PWN::Memory.to_context(limit: 20) (used internally by pwn-ai hook to inject into system prompt)
103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/pwn/memory.rb', line 103 public_class_method def self.to_context(opts = {}) limit = opts[:limit] || 20 mem = recall(limit: limit) return '' if mem.empty? ctx = "\n\nPERSISTENT MEMORY (cross-session facts, prefs, lessons - use PWN::Memory.remember to store new ones):\n" mem.each do |k, v| ctx += "- #{k} [#{v[:category]} @ #{v[:timestamp]}]: #{v[:value].to_s[0, 300]}\n" end ctx end |