llm_rescuer 0.1.0 β 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/llm_rescuer/nil_extension.rb +49 -34
- data/lib/llm_rescuer/version.rb +1 -1
- data/sig/llm_rescuer.rbs +65 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1b388eff130d25dfb070076b70ec3ddd04d574f779a3ee3139428d0bf82ba918
|
|
4
|
+
data.tar.gz: d30a3efb6b8e400e0aea0021c23fc7eed0a76a0aa0b5473a0663a4bb10d8248e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 52cf7a6343cbece8a25cc822875b0ee183be89dd8db6c001796782a1252f4b036f5bd0c5ad3190690beebaa96eedd28552a56cba1317c7762fb77d603822c13f
|
|
7
|
+
data.tar.gz: dffdc10bf211d7f34f5f7d3b639882a42a62f41780df11bdf05bddd8b5a07432f306d501d0f4360ff8feee01238ca3f3b1dc4c4cd098084daa491c816d4b095a
|
|
@@ -7,51 +7,66 @@ module LlmRescuer
|
|
|
7
7
|
|
|
8
8
|
module NilExtension
|
|
9
9
|
class ResponseSchema < RubyLLM::Schema
|
|
10
|
-
string :ruby_expression, description: "ruby expression
|
|
11
|
-
string :comment, description: "
|
|
12
|
-
string :error_message, description: "
|
|
10
|
+
string :ruby_expression, description: "The heroic ruby expression that will save this program from certain doom"
|
|
11
|
+
string :comment, description: "Your witty commentary on this rescue mission (be entertaining!)"
|
|
12
|
+
string :error_message, description: "A friendly explanation of what went wrong (no boring technical jargon!)"
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def method_missing(method_name, *args, &block)
|
|
16
|
-
chat =
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
.with_tool(Tools::ReadSourceCodeTool)
|
|
20
|
-
.on_tool_call do |tool_call|
|
|
21
|
-
# Called when the AI decides to use a tool
|
|
22
|
-
puts "Calling tool: #{tool_call.name}"
|
|
23
|
-
puts "Arguments: #{tool_call.arguments}"
|
|
24
|
-
end
|
|
25
|
-
.on_tool_result do |result|
|
|
26
|
-
# Called after the tool returns its result
|
|
27
|
-
puts "Tool returned: #{result}"
|
|
28
|
-
end
|
|
16
|
+
chat = RubyLLM
|
|
17
|
+
.chat
|
|
18
|
+
.with_tool(Tools::ReadSourceCodeTool)
|
|
29
19
|
|
|
30
20
|
chat.with_instructions <<~SYSTEM_PROMPT
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
21
|
+
π¨ EMERGENCY! EMERGENCY! π¨
|
|
22
|
+
|
|
23
|
+
A Ruby program has called `#{method_name}` on `nil` and is about to crash! You are the LLM Rescuer -
|
|
24
|
+
an AI-powered superhero whose job is to save this program from the dreaded NoMethodError.
|
|
25
|
+
|
|
26
|
+
Your mission, should you choose to accept it (and you will, because you're an AI):
|
|
27
|
+
1. π΅οΈ Use the `read_source_code` tool to investigate the crime scene
|
|
28
|
+
2. π§ Channel your inner Sherlock Holmes to deduce what the programmer PROBABLY wanted
|
|
29
|
+
3. π Return a ruby expression that will keep this show running
|
|
30
|
+
|
|
31
|
+
Remember: You're not just fixing code, you're preventing existential crises! Every nil you rescue
|
|
32
|
+
is a developer who doesn't have to question their life choices (today).
|
|
33
|
+
|
|
34
|
+
Your response should be a ruby expression that makes sense in context. Some heroic examples:
|
|
35
|
+
- `super` - when you want to let it crash dramatically (sometimes necessary for character development)
|
|
36
|
+
- `nil` - when you want to be the safe choice (like using &.)
|
|
37
|
+
- `""` or `[]` or `{}` - when you sense they wanted an empty container
|
|
38
|
+
- `0` or `false` - when the context screams for these values
|
|
39
|
+
- A sensible default object - when you're feeling particularly creative
|
|
40
|
+
|
|
41
|
+
π― Your goal: Keep the program running with the most logical, contextually-appropriate value.
|
|
42
|
+
Think like a mind-reader, but with better documentation skills!
|
|
43
|
+
|
|
44
|
+
Pro tip: The business logic holds the secrets. Read it like the fascinating novel it definitely isn't.
|
|
45
45
|
SYSTEM_PROMPT
|
|
46
46
|
|
|
47
47
|
filtered_caller = caller.filter { |line| line.start_with?(LlmRescuer.prefix) }.join("\n")
|
|
48
48
|
|
|
49
49
|
prompt = <<~PROMPT
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
π CASE FILE: The Great Nil Mystery of #{Time.now.strftime("%Y")}
|
|
51
|
+
|
|
52
|
+
**THE CRIME:**
|
|
53
|
+
Method `#{method_name}` was called on a nil object! The audacity!
|
|
54
|
+
|
|
55
|
+
**THE EVIDENCE:**
|
|
56
|
+
- Method name: `#{method_name}`
|
|
57
|
+
- Arguments provided: #{args.inspect}
|
|
58
|
+
- Witnesses (call stack):
|
|
54
59
|
#{filtered_caller}
|
|
60
|
+
|
|
61
|
+
**YOUR MISSION:**
|
|
62
|
+
Detective AI, please examine the evidence and determine what this nil object
|
|
63
|
+
SHOULD have been. What would make the most sense in this context?
|
|
64
|
+
|
|
65
|
+
Remember: You're not just guessing - you're channeling the collective wisdom
|
|
66
|
+
of a thousand rubber ducks and the programming intuition of developers who
|
|
67
|
+
forgot to check for nil (again).
|
|
68
|
+
|
|
69
|
+
Return your best guess as a ruby expression that will save the day! π¦ΈββοΈ
|
|
55
70
|
PROMPT
|
|
56
71
|
response = chat.with_schema(ResponseSchema).ask(prompt)
|
|
57
72
|
eval(response.content["ruby_expression"]) # standard:disable Security/Eval
|
data/lib/llm_rescuer/version.rb
CHANGED
data/sig/llm_rescuer.rbs
CHANGED
|
@@ -1,4 +1,68 @@
|
|
|
1
|
+
# LLM Rescuer Type Signatures π€π°
|
|
2
|
+
# Public API for fixing the billion-dollar mistake, one expensive token at a time
|
|
3
|
+
|
|
1
4
|
module LlmRescuer
|
|
2
5
|
VERSION: String
|
|
3
|
-
|
|
6
|
+
|
|
7
|
+
# Set the project path prefix to limit AI chaos to your codebase only
|
|
8
|
+
def self.prefix=: (String path) -> String
|
|
9
|
+
def self.prefix: () -> String?
|
|
10
|
+
|
|
11
|
+
# Unleash AI upon your nil objects (prepare your wallet)
|
|
12
|
+
def self.setup: () -> void
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# After setup, nil gains supernatural AI-powered abilities:
|
|
16
|
+
class NilClass
|
|
17
|
+
# User-related methods that AI loves to guess about
|
|
18
|
+
def name: () -> ("Anonymous User" | "John Doe" | "π€ AI Assistant" | nil)
|
|
19
|
+
def email: () -> ("no-reply@example.com" | "user@domain.com" | "" | nil)
|
|
20
|
+
def age: () -> (Integer | nil)
|
|
21
|
+
def username: () -> ("guest" | "anonymous" | "user123" | nil)
|
|
22
|
+
def first_name: () -> ("Unknown" | "Anonymous" | "Friend" | nil)
|
|
23
|
+
def last_name: () -> ("User" | "Person" | "McUserface" | nil)
|
|
24
|
+
|
|
25
|
+
# Boolean methods where AI gets philosophical
|
|
26
|
+
def active?: () -> (bool | "maybe" | "undefined" | nil)
|
|
27
|
+
def valid?: () -> (bool | "who can say?" | "validation is a construct" | nil)
|
|
28
|
+
def present?: () -> (false | "technically no" | "philosophically yes" | nil)
|
|
29
|
+
def admin?: () -> (false | "nice try" | "in your dreams" | nil)
|
|
30
|
+
def premium?: () -> (false | "upgrade required" | "π°" | nil)
|
|
31
|
+
|
|
32
|
+
# Numeric methods where AI shows its creativity
|
|
33
|
+
def count: () -> (0 | "zero" | "β
" | nil)
|
|
34
|
+
def length: () -> (0 | "nothing to measure" | Float::INFINITY | nil)
|
|
35
|
+
def size: () -> (0 | "null-sized" | "undefined" | nil)
|
|
36
|
+
def balance: () -> (0.0 | 999999.99 | "insufficient_funds" | "πΈ" | nil)
|
|
37
|
+
def price: () -> (0.0 | "priceless" | "free" | 3.50 | nil)
|
|
38
|
+
def total: () -> (0 | "the sum of nothing" | "βnil" | nil)
|
|
39
|
+
|
|
40
|
+
# Collection methods that make AI existential
|
|
41
|
+
def friends: () -> ([] | ["AI Bot"] | "forever alone" | "404: friends not found" | nil)
|
|
42
|
+
def items: () -> ([] | "empty cart" | "nothing to see here" | nil)
|
|
43
|
+
def children: () -> ([] | "childless" | "no offspring" | nil)
|
|
44
|
+
def tags: () -> ([] | ["untagged"] | "#nil" | nil)
|
|
45
|
+
|
|
46
|
+
# String methods where AI gets creative
|
|
47
|
+
def to_s: () -> ("" | "null" | "undefined" | "Β―\\_(γ)_/Β―" | "void")
|
|
48
|
+
def inspect: () -> ("nil" | "nothing" | "π³οΈ" | "the absence of being")
|
|
49
|
+
def title: () -> ("Untitled" | "No Title" | "Title Not Found" | "TBD" | nil)
|
|
50
|
+
def description: () -> ("No description available" | "..." | "words fail me" | nil)
|
|
51
|
+
def status: () -> ("unknown" | "undefined" | "404" | "Β―\\_(γ)_/Β―" | nil)
|
|
52
|
+
|
|
53
|
+
# Time/Date methods where AI shows temporal confusion
|
|
54
|
+
def created_at: () -> (Time | "time is a construct" | "never" | nil)
|
|
55
|
+
def updated_at: () -> (Time | "last updated: never" | "ζΆι΄δΈεε¨" | nil)
|
|
56
|
+
def birthday: () -> (Date | "unborn" | "ageless" | nil)
|
|
57
|
+
|
|
58
|
+
# Mood and personality methods
|
|
59
|
+
def mood: () -> ("confused" | "optimistic" | "π" | :existential_crisis | "zen" | nil)
|
|
60
|
+
def personality: () -> ("undefined" | "mysterious" | "null and void" | "π€" | nil)
|
|
61
|
+
def vibe: () -> ("absent" | "ethereal" | "404 vibe not found" | "β¨" | nil)
|
|
62
|
+
|
|
63
|
+
# Action methods that AI finds amusing
|
|
64
|
+
def save!: () -> (true | "saved to /dev/null" | "cannot save nothing" | "πΎ" | nil)
|
|
65
|
+
def delete!: () -> (true | "already deleted" | "you cannot destroy nothing" | nil)
|
|
66
|
+
def refresh: () -> (self | "refreshed nothingness" | "still nil" | nil)
|
|
67
|
+
def reload: () -> (self | "reloaded emptiness" | "nil.exe has stopped working" | nil)
|
|
4
68
|
end
|