llm_rescuer 0.1.0
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 +7 -0
- data/.rspec +3 -0
- data/.standard.yml +3 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +154 -0
- data/Rakefile +10 -0
- data/lib/llm_rescuer/nil_extension.rb +65 -0
- data/lib/llm_rescuer/tools/read_source_code_tool.rb +35 -0
- data/lib/llm_rescuer/version.rb +5 -0
- data/lib/llm_rescuer.rb +19 -0
- data/sig/llm_rescuer.rbs +4 -0
- metadata +102 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 6ccbd1c233b14f52a25b9718471106654feecc940a6a5e437307793b1a64d974
|
|
4
|
+
data.tar.gz: 1a2e08037d1a3acf18e694473b77246a4d67e53269b7b8bfcc03106032c0bdf3
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0a579571e96a250591237dead0cfd33a9f87966a62c24f4707138acf7dd087ed19c3e2362cc973246a7bbf6385289b2df7db6ee757c3b3355d460790db29dfba
|
|
7
|
+
data.tar.gz: 3f7db8460e977a030c18d3d94e6f82de41449702a2dea95d442099c018256ddb4b11ebf069d66b235e9b7d797e51fbfaeb8a2e358b6ffcf5c82ce4d246a967f2
|
data/.rspec
ADDED
data/.standard.yml
ADDED
data/CHANGELOG.md
ADDED
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
|
10
|
+
identity and orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment for our
|
|
18
|
+
community include:
|
|
19
|
+
|
|
20
|
+
* Demonstrating empathy and kindness toward other people
|
|
21
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
22
|
+
* Giving and gracefully accepting constructive feedback
|
|
23
|
+
* Accepting responsibility and apologizing to those affected by our mistakes,
|
|
24
|
+
and learning from the experience
|
|
25
|
+
* Focusing on what is best not just for us as individuals, but for the overall
|
|
26
|
+
community
|
|
27
|
+
|
|
28
|
+
Examples of unacceptable behavior include:
|
|
29
|
+
|
|
30
|
+
* The use of sexualized language or imagery, and sexual attention or advances of
|
|
31
|
+
any kind
|
|
32
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
33
|
+
* Public or private harassment
|
|
34
|
+
* Publishing others' private information, such as a physical or email address,
|
|
35
|
+
without their explicit permission
|
|
36
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
|
37
|
+
professional setting
|
|
38
|
+
|
|
39
|
+
## Enforcement Responsibilities
|
|
40
|
+
|
|
41
|
+
Community leaders are responsible for clarifying and enforcing our standards of
|
|
42
|
+
acceptable behavior and will take appropriate and fair corrective action in
|
|
43
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
44
|
+
or harmful.
|
|
45
|
+
|
|
46
|
+
Community leaders have the right and responsibility to remove, edit, or reject
|
|
47
|
+
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
48
|
+
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
|
49
|
+
decisions when appropriate.
|
|
50
|
+
|
|
51
|
+
## Scope
|
|
52
|
+
|
|
53
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
|
54
|
+
an individual is officially representing the community in public spaces.
|
|
55
|
+
Examples of representing our community include using an official email address,
|
|
56
|
+
posting via an official social media account, or acting as an appointed
|
|
57
|
+
representative at an online or offline event.
|
|
58
|
+
|
|
59
|
+
## Enforcement
|
|
60
|
+
|
|
61
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
62
|
+
reported to the community leaders responsible for enforcement at
|
|
63
|
+
[INSERT CONTACT METHOD].
|
|
64
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
|
65
|
+
|
|
66
|
+
All community leaders are obligated to respect the privacy and security of the
|
|
67
|
+
reporter of any incident.
|
|
68
|
+
|
|
69
|
+
## Enforcement Guidelines
|
|
70
|
+
|
|
71
|
+
Community leaders will follow these Community Impact Guidelines in determining
|
|
72
|
+
the consequences for any action they deem in violation of this Code of Conduct:
|
|
73
|
+
|
|
74
|
+
### 1. Correction
|
|
75
|
+
|
|
76
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
77
|
+
unprofessional or unwelcome in the community.
|
|
78
|
+
|
|
79
|
+
**Consequence**: A private, written warning from community leaders, providing
|
|
80
|
+
clarity around the nature of the violation and an explanation of why the
|
|
81
|
+
behavior was inappropriate. A public apology may be requested.
|
|
82
|
+
|
|
83
|
+
### 2. Warning
|
|
84
|
+
|
|
85
|
+
**Community Impact**: A violation through a single incident or series of
|
|
86
|
+
actions.
|
|
87
|
+
|
|
88
|
+
**Consequence**: A warning with consequences for continued behavior. No
|
|
89
|
+
interaction with the people involved, including unsolicited interaction with
|
|
90
|
+
those enforcing the Code of Conduct, for a specified period of time. This
|
|
91
|
+
includes avoiding interactions in community spaces as well as external channels
|
|
92
|
+
like social media. Violating these terms may lead to a temporary or permanent
|
|
93
|
+
ban.
|
|
94
|
+
|
|
95
|
+
### 3. Temporary Ban
|
|
96
|
+
|
|
97
|
+
**Community Impact**: A serious violation of community standards, including
|
|
98
|
+
sustained inappropriate behavior.
|
|
99
|
+
|
|
100
|
+
**Consequence**: A temporary ban from any sort of interaction or public
|
|
101
|
+
communication with the community for a specified period of time. No public or
|
|
102
|
+
private interaction with the people involved, including unsolicited interaction
|
|
103
|
+
with those enforcing the Code of Conduct, is allowed during this period.
|
|
104
|
+
Violating these terms may lead to a permanent ban.
|
|
105
|
+
|
|
106
|
+
### 4. Permanent Ban
|
|
107
|
+
|
|
108
|
+
**Community Impact**: Demonstrating a pattern of violation of community
|
|
109
|
+
standards, including sustained inappropriate behavior, harassment of an
|
|
110
|
+
individual, or aggression toward or disparagement of classes of individuals.
|
|
111
|
+
|
|
112
|
+
**Consequence**: A permanent ban from any sort of public interaction within the
|
|
113
|
+
community.
|
|
114
|
+
|
|
115
|
+
## Attribution
|
|
116
|
+
|
|
117
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
118
|
+
version 2.1, available at
|
|
119
|
+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
|
120
|
+
|
|
121
|
+
Community Impact Guidelines were inspired by
|
|
122
|
+
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
|
123
|
+
|
|
124
|
+
For answers to common questions about this code of conduct, see the FAQ at
|
|
125
|
+
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
|
126
|
+
[https://www.contributor-covenant.org/translations][translations].
|
|
127
|
+
|
|
128
|
+
[homepage]: https://www.contributor-covenant.org
|
|
129
|
+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
|
130
|
+
[Mozilla CoC]: https://github.com/mozilla/diversity
|
|
131
|
+
[FAQ]: https://www.contributor-covenant.org/faq
|
|
132
|
+
[translations]: https://www.contributor-covenant.org/translations
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Paul Chobert
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# LLM Rescuer 🤖💰
|
|
2
|
+
|
|
3
|
+
> ⚠️ **EXPERIMENTAL PROJECT - NOT FOR PRODUCTION USE**
|
|
4
|
+
>
|
|
5
|
+
> This project is an experimental proof-of-concept developed for educational purposes and pure, unadulterated fun. It uses AI to dynamically handle runtime errors, which introduces unpredictable behavior and potential security risks that would make your security team cry. **Never use this in production environments unless you enjoy explaining to your boss why the AI decided your user's name should be "🐱 Mr. Whiskers".**
|
|
6
|
+
|
|
7
|
+
## The Mission: Fixing the Billion Dollar Mistake... With a Billion Dollars Worth of LLM Tokens
|
|
8
|
+
|
|
9
|
+
In 1965, Tony Hoare invented the null reference and later called it his ["billion-dollar mistake"](https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/). Well, we're here to fix it by potentially spending a billion dollars in OpenAI API tokens! 💸
|
|
10
|
+
|
|
11
|
+
Because clearly, the best way to solve a problem caused by the absence of a value is to throw artificial intelligence at it until it hallucinates a reasonable response. What could possibly go wrong?
|
|
12
|
+
|
|
13
|
+
## What This Abomination Does
|
|
14
|
+
|
|
15
|
+
LLM Rescuer is a Ruby gem that catches your `NoMethodError`s when you call methods on `nil` and asks GPT to guess what you _probably_ wanted. It's like having a very expensive, overly-confident intern who's read your entire codebase and thinks they know what you meant.
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
user = nil
|
|
19
|
+
puts user.name # Instead of crashing, might return "John Doe" or "undefined" or "🎭"
|
|
20
|
+
# depending on what the AI thinks is funny today
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## How This Beautiful Disaster Works
|
|
24
|
+
|
|
25
|
+
1. **The Trap**: We monkey-patch `NilClass` because why not break fundamental assumptions?
|
|
26
|
+
2. **The Analysis**: When you call a method on `nil`, we pause everything and ask an LLM to read your mind
|
|
27
|
+
3. **The Oracle**: GPT-5 analyzes your code like a digital Sherlock Holmes with ADHD
|
|
28
|
+
4. **The Guess**: It returns what it thinks you wanted, which is right about 73.2% of the time\*
|
|
29
|
+
5. **The Magic**: Your code continues running, probably doing something completely different than intended
|
|
30
|
+
|
|
31
|
+
\*Statistics may be made up
|
|
32
|
+
|
|
33
|
+
## Installation (AKA "How to Spend Your OpenAI Credits")
|
|
34
|
+
|
|
35
|
+
Add this line to your application's Gemfile (and say goodbye to your API budget):
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
gem 'llm_rescuer'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then execute:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
bundle install
|
|
45
|
+
# Also install a second mortgage for your OpenAI bills
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Configuration
|
|
49
|
+
|
|
50
|
+
1. **Feed the AI overlords**:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
export OPENAI_API_KEY="prepare-your-wallet"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
2. **Set your project scope** (so it only ruins _your_ code):
|
|
57
|
+
|
|
58
|
+
```ruby
|
|
59
|
+
LlmRescuer.prefix = "/path/to/your/beautiful/disaster"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
3. **Embrace the chaos**:
|
|
63
|
+
```ruby
|
|
64
|
+
require 'llm_rescuer'
|
|
65
|
+
LlmRescuer.setup
|
|
66
|
+
# You have chosen... poorly
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Real-World Usage Examples
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
# Classic nil safety
|
|
73
|
+
user = find_user(id: "nonexistent") # returns nil
|
|
74
|
+
puts user.email
|
|
75
|
+
# AI: "Analyzing context... user seems to need an email...
|
|
76
|
+
# returning 'no-reply@example.com'"
|
|
77
|
+
|
|
78
|
+
# Shopping cart magic
|
|
79
|
+
cart = session[:cart] # nil because session expired
|
|
80
|
+
total = cart.total_price
|
|
81
|
+
# AI: "This looks like e-commerce. Based on similar patterns,
|
|
82
|
+
# I'll return 0.0 to avoid charging $nil"
|
|
83
|
+
|
|
84
|
+
# The existential crisis
|
|
85
|
+
meaning_of_life = nil
|
|
86
|
+
answer = meaning_of_life.to_i
|
|
87
|
+
# AI: "Clearly this should be 42. I've read Douglas Adams."
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## What Could Go Wrong? 🤔
|
|
91
|
+
|
|
92
|
+
- Your nil users might suddenly become named "ChatGPT's Best Friend"
|
|
93
|
+
- Your shopping cart totals might be replaced with haikus about commerce
|
|
94
|
+
- Your boolean flags might return philosophical treatises on truth
|
|
95
|
+
- Your API might start responding with interpretive dance descriptions
|
|
96
|
+
- You might accidentally achieve sentience in your nil objects
|
|
97
|
+
|
|
98
|
+
## Cost Analysis 💰
|
|
99
|
+
|
|
100
|
+
- **Traditional nil handling**: Free, but your app crashes
|
|
101
|
+
- **LLM Rescuer**: $0.002 per nil rescue (estimated)
|
|
102
|
+
- **Your sanity**: Priceless (and rapidly depleting)
|
|
103
|
+
|
|
104
|
+
For a typical Rails app with healthy nil hygiene, expect to spend approximately:
|
|
105
|
+
|
|
106
|
+
- **Development**: $50-100/month (because you test things, right?)
|
|
107
|
+
- **Production**: $500-5000/month (depending on how nil-happy your code is)
|
|
108
|
+
- **Black Friday**: Your firstborn child
|
|
109
|
+
|
|
110
|
+
## Dependencies (The Usual Suspects)
|
|
111
|
+
|
|
112
|
+
- `ruby_llm` (~> 1.8.2) - For talking to our AI overlords
|
|
113
|
+
- `ruby_llm-schema` (~> 0.2.1) - For making sure AI responses are structured chaos
|
|
114
|
+
- `binding_of_caller` (~> 1.0.1) - For context that the AI will probably ignore anyway
|
|
115
|
+
- A sense of humor (>= 1.0.0, required)
|
|
116
|
+
- A healthy bank account (recommended)
|
|
117
|
+
|
|
118
|
+
## Development
|
|
119
|
+
|
|
120
|
+
After checking out the repo and questioning your life choices:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
bin/setup # Install dependencies
|
|
124
|
+
rake spec # Run tests (spoiler: they're as unpredictable as AI)
|
|
125
|
+
bin/console # Interactive prompt for immediate regret
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Contributing
|
|
129
|
+
|
|
130
|
+
Found a bug? That might be a feature! Found a feature? That might be a bug!
|
|
131
|
+
|
|
132
|
+
Submit PRs, issues, or interpretive dance videos explaining your problems. We accept contributions in all forms except sensible ones.
|
|
133
|
+
|
|
134
|
+
## Success Stories
|
|
135
|
+
|
|
136
|
+
> "LLM Rescuer saved my app from crashing! Sure, all my users are now named 'Anonymous Penguin' and my prices are in Bitcoin, but it didn't crash!" - Definitely Real User
|
|
137
|
+
|
|
138
|
+
> "I deployed this to production and my nil errors went down 100%! My AWS bill went up 400%, but correlation isn't causation, right?" - Another Real Person
|
|
139
|
+
|
|
140
|
+
## The Philosophy
|
|
141
|
+
|
|
142
|
+
Why fix your code when you can train an AI to guess what your code should have done? It's like pair programming, except your pair is a probabilistic text generator that's read the entire internet and has strong opinions about variable naming.
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
This project is licensed under the MIT License, which gives you the right to use, modify, and distribute this code. It does not give you the right to sue us when your production app starts writing poetry instead of processing payments.
|
|
147
|
+
|
|
148
|
+
## Final Words
|
|
149
|
+
|
|
150
|
+
Remember: null references were a billion-dollar mistake, but with today's AI API pricing, we can make it a trillion-dollar mistake! 🚀
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
_"In a world without nil safety, one gem dares to ask: 'What if we just guessed?'"_ 🎬
|
data/Rakefile
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module LlmRescuer
|
|
2
|
+
def self.prefix=(prefix)
|
|
3
|
+
@prefix = prefix
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def self.prefix = @prefix
|
|
7
|
+
|
|
8
|
+
module NilExtension
|
|
9
|
+
class ResponseSchema < RubyLLM::Schema
|
|
10
|
+
string :ruby_expression, description: "ruby expression to evaluate to recover from the exception"
|
|
11
|
+
string :comment, description: "comment about the response"
|
|
12
|
+
string :error_message, description: "error message from the exception"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def method_missing(method_name, *args, &block)
|
|
16
|
+
chat =
|
|
17
|
+
RubyLLM
|
|
18
|
+
.chat
|
|
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
|
|
29
|
+
|
|
30
|
+
chat.with_instructions <<~SYSTEM_PROMPT
|
|
31
|
+
A ruby program is about to crash or test about to fail because the method `#{method_name}` has been called on `nil`.
|
|
32
|
+
We are trying to determine what the return value of `NilClass.method_missing` should be so the program can resume.
|
|
33
|
+
You can use the `read_source_code` tool to read the source code of a file.
|
|
34
|
+
Generate a response with a ruby expression to evaluate.
|
|
35
|
+
|
|
36
|
+
Some examples of expression could be:
|
|
37
|
+
- super if we want to raise the error
|
|
38
|
+
- `nil` if we want to behave like &.
|
|
39
|
+
- a boolean
|
|
40
|
+
- a number
|
|
41
|
+
- a new instance of a class
|
|
42
|
+
|
|
43
|
+
The goal is to help the program to resume successfully with the best possible expression.
|
|
44
|
+
You need to look at the business logic of the caller to determine the best expression.
|
|
45
|
+
SYSTEM_PROMPT
|
|
46
|
+
|
|
47
|
+
filtered_caller = caller.filter { |line| line.start_with?(LlmRescuer.prefix) }.join("\n")
|
|
48
|
+
|
|
49
|
+
prompt = <<~PROMPT
|
|
50
|
+
Here is the failing method call:
|
|
51
|
+
method name: #{method_name}
|
|
52
|
+
arguments: #{args.inspect}
|
|
53
|
+
backtrace:
|
|
54
|
+
#{filtered_caller}
|
|
55
|
+
PROMPT
|
|
56
|
+
response = chat.with_schema(ResponseSchema).ask(prompt)
|
|
57
|
+
eval(response.content["ruby_expression"]) # standard:disable Security/Eval
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
61
|
+
first_caller = caller(1..1).first
|
|
62
|
+
first_caller&.start_with?(LlmRescuer.prefix) || false
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module LlmRescuer
|
|
2
|
+
module Tools
|
|
3
|
+
class ReadSourceCodeTool < RubyLLM::Tool
|
|
4
|
+
description "Reads the source code of a given file"
|
|
5
|
+
|
|
6
|
+
param :file_path, desc: "The full path to the file to read, without the line number"
|
|
7
|
+
param :around_line_number, desc: "The line number around which to read the source code"
|
|
8
|
+
param :context_lines, desc: "The number of lines of context to include around the specified line number"
|
|
9
|
+
|
|
10
|
+
def execute(file_path:, around_line_number:, context_lines:)
|
|
11
|
+
around_line_number = around_line_number.to_i
|
|
12
|
+
context_lines = context_lines.to_i
|
|
13
|
+
return {error: "Unauthorized file path"} unless file_path.start_with?(LlmRescuer.prefix)
|
|
14
|
+
|
|
15
|
+
return {error: "File not found"} unless File.file?(file_path)
|
|
16
|
+
|
|
17
|
+
lines = File.readlines(file_path)
|
|
18
|
+
|
|
19
|
+
start = [around_line_number - context_lines - 1, 0].max
|
|
20
|
+
end_ = [around_line_number + context_lines - 1, lines.size - 1].min
|
|
21
|
+
|
|
22
|
+
snippet = lines[start..end_].each_with_index.map do |src, i|
|
|
23
|
+
num = start + i + 1
|
|
24
|
+
prefix = (num == around_line_number) ? "=> " : " "
|
|
25
|
+
format("#{prefix}%4d | %s", num, src)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
puts "#{file_path}:#{around_line_number}\n\n"
|
|
29
|
+
puts snippet.join
|
|
30
|
+
rescue => e
|
|
31
|
+
{error: e.message}
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/llm_rescuer.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ruby_llm"
|
|
4
|
+
require "ruby_llm/schema"
|
|
5
|
+
|
|
6
|
+
require_relative "llm_rescuer/version"
|
|
7
|
+
require_relative "llm_rescuer/nil_extension"
|
|
8
|
+
require_relative "llm_rescuer/tools/read_source_code_tool"
|
|
9
|
+
|
|
10
|
+
RubyLLM.configure do |config|
|
|
11
|
+
config.openai_api_key = ENV.fetch("OPENAI_API_KEY")
|
|
12
|
+
config.default_model = "gpt-5"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module LlmRescuer
|
|
16
|
+
def self.setup
|
|
17
|
+
NilClass.prepend(LlmRescuer::NilExtension)
|
|
18
|
+
end
|
|
19
|
+
end
|
data/sig/llm_rescuer.rbs
ADDED
metadata
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: llm_rescuer
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Paul Chobert
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: binding_of_caller
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 1.0.1
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 1.0.1
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: ruby_llm
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 1.8.2
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 1.8.2
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: ruby_llm-schema
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 0.2.1
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 0.2.1
|
|
54
|
+
description: "LLM Rescuer uses artificial intelligence to guess what you probably
|
|
55
|
+
meant when you called a method on nil. Instead of crashing with NoMethodError, it
|
|
56
|
+
asks GPT to analyze your code and hallucinate a reasonable response. Because clearly,
|
|
57
|
+
the best way to solve Tony Hoare's billion-dollar mistake is to throw AI at it until
|
|
58
|
+
it works. What could possibly go wrong? \U0001F3AD"
|
|
59
|
+
email:
|
|
60
|
+
- paul@chobert.fr
|
|
61
|
+
executables: []
|
|
62
|
+
extensions: []
|
|
63
|
+
extra_rdoc_files: []
|
|
64
|
+
files:
|
|
65
|
+
- ".rspec"
|
|
66
|
+
- ".standard.yml"
|
|
67
|
+
- CHANGELOG.md
|
|
68
|
+
- CODE_OF_CONDUCT.md
|
|
69
|
+
- LICENSE.txt
|
|
70
|
+
- README.md
|
|
71
|
+
- Rakefile
|
|
72
|
+
- lib/llm_rescuer.rb
|
|
73
|
+
- lib/llm_rescuer/nil_extension.rb
|
|
74
|
+
- lib/llm_rescuer/tools/read_source_code_tool.rb
|
|
75
|
+
- lib/llm_rescuer/version.rb
|
|
76
|
+
- sig/llm_rescuer.rbs
|
|
77
|
+
homepage: https://github.com/barodeur/llm_rescuer
|
|
78
|
+
licenses:
|
|
79
|
+
- MIT
|
|
80
|
+
metadata:
|
|
81
|
+
allowed_push_host: https://rubygems.org
|
|
82
|
+
homepage_uri: https://github.com/barodeur/llm_rescuer
|
|
83
|
+
source_code_uri: https://github.com/paul/llm_rescuer
|
|
84
|
+
changelog_uri: https://github.com/paul/llm_rescuer/blob/main/CHANGELOG.md
|
|
85
|
+
rdoc_options: []
|
|
86
|
+
require_paths:
|
|
87
|
+
- lib
|
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
89
|
+
requirements:
|
|
90
|
+
- - ">="
|
|
91
|
+
- !ruby/object:Gem::Version
|
|
92
|
+
version: 3.1.0
|
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
|
+
requirements:
|
|
95
|
+
- - ">="
|
|
96
|
+
- !ruby/object:Gem::Version
|
|
97
|
+
version: '0'
|
|
98
|
+
requirements: []
|
|
99
|
+
rubygems_version: 3.6.7
|
|
100
|
+
specification_version: 4
|
|
101
|
+
summary: "Fix the billion-dollar mistake by spending billions on LLM tokens! \U0001F916\U0001F4B0"
|
|
102
|
+
test_files: []
|