Module: LlmRescuer::NilExtension

Defined in:
lib/llm_rescuer/nil_extension.rb

Defined Under Namespace

Classes: ResponseSchema

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
# File 'lib/llm_rescuer/nil_extension.rb', line 15

def method_missing(method_name, *args, &block)
  chat = RubyLLM
    .chat
    .with_tool(Tools::ReadSourceCodeTool)

  chat.with_instructions <<~SYSTEM_PROMPT
    🚨 EMERGENCY! EMERGENCY! 🚨

    A Ruby program has called `#{method_name}` on `nil` and is about to crash! You are the LLM Rescuer -
    an AI-powered superhero whose job is to save this program from the dreaded NoMethodError.

    Your mission, should you choose to accept it (and you will, because you're an AI):
    1. πŸ•΅οΈ Use the `read_source_code` tool to investigate the crime scene
    2. 🧠 Channel your inner Sherlock Holmes to deduce what the programmer PROBABLY wanted
    3. 🎭 Return a ruby expression that will keep this show running

    Remember: You're not just fixing code, you're preventing existential crises! Every nil you rescue
    is a developer who doesn't have to question their life choices (today).

    Your response should be a ruby expression that makes sense in context. Some heroic examples:
    - `super` - when you want to let it crash dramatically (sometimes necessary for character development)
    - `nil` - when you want to be the safe choice (like using &.)
    - `""` or `[]` or `{}` - when you sense they wanted an empty container
    - `0` or `false` - when the context screams for these values
    - A sensible default object - when you're feeling particularly creative

    🎯 Your goal: Keep the program running with the most logical, contextually-appropriate value.
    Think like a mind-reader, but with better documentation skills!

    Pro tip: The business logic holds the secrets. Read it like the fascinating novel it definitely isn't.
  SYSTEM_PROMPT

  filtered_caller = caller.filter { |line| line.start_with?(LlmRescuer.prefix) }.join("\n")

  prompt = <<~PROMPT
    πŸ” CASE FILE: The Great Nil Mystery of #{Time.now.strftime("%Y")}

    **THE CRIME:**
    Method `#{method_name}` was called on a nil object! The audacity!

    **THE EVIDENCE:**
    - Method name: `#{method_name}`
    - Arguments provided: #{args.inspect}
    - Witnesses (call stack):
    #{filtered_caller}

    **YOUR MISSION:**
    Detective AI, please examine the evidence and determine what this nil object
    SHOULD have been. What would make the most sense in this context?

    Remember: You're not just guessing - you're channeling the collective wisdom
    of a thousand rubber ducks and the programming intuition of developers who
    forgot to check for nil (again).

    Return your best guess as a ruby expression that will save the day! πŸ¦Έβ€β™€οΈ
  PROMPT
  response = chat.with_schema(ResponseSchema).ask(prompt)
  eval(response.content["ruby_expression"]) # standard:disable Security/Eval
end

Instance Method Details

#respond_to_missing?(method_name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


75
76
77
78
# File 'lib/llm_rescuer/nil_extension.rb', line 75

def respond_to_missing?(method_name, include_private = false)
  first_caller = caller(1..1).first
  first_caller&.start_with?(LlmRescuer.prefix) || false
end