Class: Kodo::Tools::RememberFact

Inherits:
RubyLLM::Tool
  • Object
show all
Extended by:
PromptContributor
Defined in:
lib/kodo/tools/remember_fact.rb

Constant Summary collapse

MAX_PER_TURN =
5
MAX_CONTENT_LENGTH =
500

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from PromptContributor

capability_name, capability_primary, disabled_guidance, enabled_guidance

Constructor Details

#initialize(knowledge:, audit:) ⇒ RememberFact

Returns a new instance of RememberFact.



28
29
30
31
32
33
34
# File 'lib/kodo/tools/remember_fact.rb', line 28

def initialize(knowledge:, audit:)
  super()
  @knowledge = knowledge
  @audit = audit
  @turn_count = 0
  @turn_context = nil
end

Instance Attribute Details

#turn_context=(value) ⇒ Object (writeonly)

Sets the attribute turn_context

Parameters:

  • value —

    the value to set the attribute turn_context to.



26
27
28
# File 'lib/kodo/tools/remember_fact.rb', line 26

def turn_context=(value)
  @turn_context = value
end

Instance Method Details

#execute(category:, content:, source: 'explicit') ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/kodo/tools/remember_fact.rb', line 40

def execute(category:, content:, source: 'explicit')
  # Mechanical web-fetched gate: set by FetchUrl/WebSearch tools, not by LLM parameters.
  # Protects against memory poisoning from injected instructions in web content.
  if @turn_context&.web_fetched
    return 'Web content was fetched this turn. To prevent memory poisoning, ' \
           "I won't store facts automatically. If you explicitly want me to " \
           "remember: \"#{content}\", say so and I'll do it."
  end

  unless Memory::Knowledge::VALID_CATEGORIES.include?(category)
    return "Invalid category '#{category}'. Use: #{Memory::Knowledge::VALID_CATEGORIES.join(', ')}"
  end

  if content.length > MAX_CONTENT_LENGTH
    return "Content too long (#{content.length} chars). Maximum is #{MAX_CONTENT_LENGTH}."
  end

  if Memory::Redactor.sensitive?(content)
    return 'Cannot store sensitive data (passwords, API keys, SSNs, credit card numbers).'
  end

  @turn_count += 1
  if @turn_count > MAX_PER_TURN
    return "Rate limit reached (max #{MAX_PER_TURN} facts per message). Try again next message."
  end

  fact = @knowledge.remember(category: category, content: content, source: source)

  @audit.log(
    event: 'knowledge_remembered',
    detail: "id:#{fact['id']} cat:#{category} src:#{source}"
  )

  "Remembered: #{content} (id: #{fact['id']})"
rescue Kodo::Error => e
  e.message
end

#name ⇒ Object



78
79
80
# File 'lib/kodo/tools/remember_fact.rb', line 78

def name
  'remember'
end

#reset_turn_count! ⇒ Object



36
37
38
# File 'lib/kodo/tools/remember_fact.rb', line 36

def reset_turn_count!
  @turn_count = 0
end