monty-ai 0.2.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/LICENSE.txt +21 -0
- data/README.md +143 -0
- data/exe/monty-ai +6 -0
- data/lib/monty_ai/ai_client.rb +91 -0
- data/lib/monty_ai/cli.rb +55 -0
- data/lib/monty_ai/file_handler.rb +16 -0
- data/lib/monty_ai/formatter.rb +11 -0
- data/lib/monty_ai/version.rb +5 -0
- data/lib/monty_ai.rb +36 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c79ee491ca508b5a3621e95c0b614897e8fe767f8aa7b76dc9c34aaae69e211a
|
4
|
+
data.tar.gz: 97eaea0303880d411107e523e480436f77712b50bd519af2abc467f8760c04e7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 27bce8ac44a05a65acd721c24f1e46a7532e8e29b06548baab5f3ee1fe51d4fc574c2060bfe1dd1cf7ab95a05a46d26086e53dd53b0e6ce201f83ed2193e1c52
|
7
|
+
data.tar.gz: 60a63e462b64313c418c538100a0c734c199c1905d6f7777c0f73df21c35caa7b22d2c0662bc3f03513c44a70d08aecb6eacd4cc348333c7ae756dbd6dd9727b
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2025 Steve Cook
|
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,143 @@
|
|
1
|
+
<div align="center">
|
2
|
+
<img src="montyai-logo.svg" alt="MitchAI" width="500">
|
3
|
+
</div>
|
4
|
+
|
5
|
+
# MontyAI
|
6
|
+
|
7
|
+
## ๐ Overview
|
8
|
+
|
9
|
+
MontyAI is an intelligent code explanation tool that uses AI to help you
|
10
|
+
understand code faster. Simply point MontyAI at a code file, and it will provide
|
11
|
+
a clear, concise explanation of what the code does.
|
12
|
+
|
13
|
+
## ๐ ๏ธ Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'monty-ai'
|
19
|
+
```
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
```bash
|
24
|
+
bundle install
|
25
|
+
```
|
26
|
+
|
27
|
+
Or install it yourself as:
|
28
|
+
|
29
|
+
```bash
|
30
|
+
gem install monty-ai
|
31
|
+
```
|
32
|
+
|
33
|
+
## ๐ก Usage
|
34
|
+
|
35
|
+
### Basic Usage
|
36
|
+
|
37
|
+
Explain a file:
|
38
|
+
|
39
|
+
```bash
|
40
|
+
monty-ai explain path/to/file.rb
|
41
|
+
```
|
42
|
+
|
43
|
+
Pipe code to MontyAI:
|
44
|
+
|
45
|
+
```bash
|
46
|
+
cat path/to/file.rb | monty-ai explain
|
47
|
+
```
|
48
|
+
|
49
|
+
### Example
|
50
|
+
|
51
|
+
```bash
|
52
|
+
monty-ai explain lib/my_app/parser.rb
|
53
|
+
```
|
54
|
+
|
55
|
+
Output:
|
56
|
+
|
57
|
+
```
|
58
|
+
Explanation for lib/my_app/parser.rb:
|
59
|
+
|
60
|
+
This code defines a Parser class that processes text files into structured data.
|
61
|
+
|
62
|
+
The Parser class has three main methods:
|
63
|
+
- parse: Takes a file path, reads the content, and converts it to a structured format.
|
64
|
+
- process_line: Handles individual lines from the file, applying regex patterns.
|
65
|
+
- extract_data: Pulls out specific information based on the content type.
|
66
|
+
|
67
|
+
The code implements the Strategy pattern by dynamically selecting different
|
68
|
+
processing methods based on the file's content type.
|
69
|
+
```
|
70
|
+
|
71
|
+
### Check Version
|
72
|
+
|
73
|
+
```bash
|
74
|
+
monty-ai version
|
75
|
+
```
|
76
|
+
|
77
|
+
## โ๏ธ Configuration
|
78
|
+
|
79
|
+
MontyAI uses OpenAI or Anthropic APIs for code explanation. Set your API key in
|
80
|
+
an environment variable:
|
81
|
+
|
82
|
+
```bash
|
83
|
+
# For OpenAI (default)
|
84
|
+
export OPENAI_API_KEY=your_api_key_here
|
85
|
+
|
86
|
+
# For Anthropic
|
87
|
+
export ANTHROPIC_API_KEY=your_api_key_here
|
88
|
+
```
|
89
|
+
|
90
|
+
## ๐ Requirements
|
91
|
+
|
92
|
+
- Ruby 3.0+
|
93
|
+
- OpenAI API Key
|
94
|
+
|
95
|
+
## ๐งช Development
|
96
|
+
|
97
|
+
```bash
|
98
|
+
# Clone the repository
|
99
|
+
git clone https://github.com/scookdev/mitch_ai.git
|
100
|
+
|
101
|
+
# Install dependencies
|
102
|
+
bundle install
|
103
|
+
|
104
|
+
# Run tests
|
105
|
+
bundle exec rspec
|
106
|
+
|
107
|
+
# Run linter
|
108
|
+
bundle exec rubocop
|
109
|
+
```
|
110
|
+
|
111
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
112
|
+
|
113
|
+
## ๐บ๏ธ Roadmap
|
114
|
+
|
115
|
+
Future versions will include:
|
116
|
+
|
117
|
+
- Syntax highlighting
|
118
|
+
- Multiple explanation formats (line-by-line, summary, concept)
|
119
|
+
- Interactive TTY interface
|
120
|
+
- Keyboard navigation
|
121
|
+
|
122
|
+
## ๐ค Contributing
|
123
|
+
|
124
|
+
Contributions are welcome! Please check out our [Contributing Guidelines](CONTRIBUTING.md).
|
125
|
+
|
126
|
+
1. Fork the repository
|
127
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
128
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
129
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
130
|
+
5. Open a Pull Request
|
131
|
+
|
132
|
+
## ๐ License
|
133
|
+
|
134
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
135
|
+
|
136
|
+
## ๐ Acknowledgments
|
137
|
+
|
138
|
+
- Powered by OpenAI
|
139
|
+
- Inspired by the need for intelligent code reviews
|
140
|
+
|
141
|
+
## ๐ฌ Support
|
142
|
+
|
143
|
+
If you encounter any problems or have suggestions, please [open an issue](https://github.com/scookdev/monty_ai/issues).
|
data/exe/monty-ai
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "net/http"
|
4
|
+
require "uri"
|
5
|
+
require "json"
|
6
|
+
|
7
|
+
module MontyAI
|
8
|
+
class AIClient
|
9
|
+
def initialize(api_key: nil)
|
10
|
+
@api_key = api_key || MontyAI.configuration.api_key
|
11
|
+
@endpoint = MontyAI.configuration.api_endpoint
|
12
|
+
|
13
|
+
return unless @api_key.nil? || @api_key.empty?
|
14
|
+
|
15
|
+
raise Error, "API key is required. Set OPENAI_API_KEY or ANTHROPIC_API_KEY environment variable."
|
16
|
+
end
|
17
|
+
|
18
|
+
def explain_code(code)
|
19
|
+
prompt = build_prompt(code)
|
20
|
+
response = send_request(prompt)
|
21
|
+
parse_response(response)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def build_prompt(code)
|
27
|
+
"Please explain the following code clearly and concisely:\n\n#{code}\n\n" \
|
28
|
+
"Provide a general overview of what it does followed by explanations of important parts. " \
|
29
|
+
"Include details about any non-obvious logic, design patterns, or potential issues."
|
30
|
+
end
|
31
|
+
|
32
|
+
def send_request(prompt)
|
33
|
+
uri = URI.parse(@endpoint)
|
34
|
+
request = Net::HTTP::Post.new(uri)
|
35
|
+
request["Content-Type"] = "application/json"
|
36
|
+
request["Authorization"] = "Bearer #{@api_key}"
|
37
|
+
|
38
|
+
# Adjust parameters based on API being used
|
39
|
+
if @endpoint.include?("openai")
|
40
|
+
body = {
|
41
|
+
model: "gpt-4",
|
42
|
+
messages: [
|
43
|
+
{ role: "system",
|
44
|
+
content: "You are a helpful code explanation assistant that explains code clearly and concisely." },
|
45
|
+
{ role: "user", content: prompt }
|
46
|
+
],
|
47
|
+
temperature: 0.3
|
48
|
+
}
|
49
|
+
elsif @endpoint.include?("anthropic")
|
50
|
+
# Update endpoint if using Anthropic
|
51
|
+
@endpoint = "https://api.anthropic.com/v1/messages"
|
52
|
+
body = {
|
53
|
+
model: "claude-3-opus-20240229",
|
54
|
+
messages: [
|
55
|
+
{ role: "user", content: prompt }
|
56
|
+
],
|
57
|
+
temperature: 0.3
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
request.body = body.to_json
|
62
|
+
|
63
|
+
response = nil
|
64
|
+
begin
|
65
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
|
66
|
+
http.request(request)
|
67
|
+
end
|
68
|
+
rescue StandardError => e
|
69
|
+
raise Error, "API request failed: #{e.message}"
|
70
|
+
end
|
71
|
+
|
72
|
+
raise Error, "API request failed: #{response.code} #{response.message}" unless response.is_a?(Net::HTTPSuccess)
|
73
|
+
|
74
|
+
JSON.parse(response.body)
|
75
|
+
end
|
76
|
+
|
77
|
+
def parse_response(response)
|
78
|
+
if response["choices"]
|
79
|
+
# OpenAI format
|
80
|
+
response["choices"][0]["message"]["content"]
|
81
|
+
elsif response["content"]
|
82
|
+
# Anthropic format
|
83
|
+
response["content"][0]["text"]
|
84
|
+
else
|
85
|
+
raise "Unexpected API response format"
|
86
|
+
end
|
87
|
+
rescue StandardError => e
|
88
|
+
raise Error, "Failed to parse API response: #{e.message}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/monty_ai/cli.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
|
5
|
+
module MontyAI
|
6
|
+
class CLI < Thor
|
7
|
+
desc "explain FILE", "Explain the code in FILE"
|
8
|
+
def explain(file = nil)
|
9
|
+
if file.nil? && !$stdin.tty?
|
10
|
+
# Handle piped input
|
11
|
+
code = $stdin.read
|
12
|
+
handle_code(code)
|
13
|
+
elsif file.nil?
|
14
|
+
# No file provided and no pipe
|
15
|
+
puts "Error: Please provide a file to explain or pipe code to the command."
|
16
|
+
exit 1
|
17
|
+
else
|
18
|
+
# Handle file input
|
19
|
+
begin
|
20
|
+
code = FileHandler.read(file)
|
21
|
+
handle_code(code, file)
|
22
|
+
rescue Error => e
|
23
|
+
puts "Error: #{e.message}"
|
24
|
+
exit 1
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def handle_code(code, filename = nil)
|
32
|
+
puts "Analyzing code..."
|
33
|
+
|
34
|
+
begin
|
35
|
+
explainer = AIClient.new
|
36
|
+
explanation = explainer.explain_code(code)
|
37
|
+
|
38
|
+
if filename
|
39
|
+
puts "Explanation for #{filename}:"
|
40
|
+
puts ""
|
41
|
+
end
|
42
|
+
|
43
|
+
puts Formatter.format(explanation)
|
44
|
+
rescue Error => e
|
45
|
+
puts "Error: #{e.message}"
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "version", "Show version"
|
51
|
+
def version
|
52
|
+
puts "MontyAI version #{MontyAI::VERSION}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MontyAI
|
4
|
+
# Class FileHandler opens files for explanations
|
5
|
+
class FileHandler
|
6
|
+
def self.read(path)
|
7
|
+
raise Error, "File not found: #{path}" unless File.exist?(path)
|
8
|
+
|
9
|
+
raise Error, "Cannot read file: #{path}" unless File.readable?(path)
|
10
|
+
|
11
|
+
File.read(path)
|
12
|
+
rescue StandardError => e
|
13
|
+
raise Error, "Failed to read file: #{e.message}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/monty_ai.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "monty_ai/version"
|
4
|
+
require "monty_ai/cli"
|
5
|
+
require "monty_ai/ai_client"
|
6
|
+
require "monty_ai/file_handler"
|
7
|
+
require "monty_ai/formatter"
|
8
|
+
|
9
|
+
# @!parse
|
10
|
+
# # Provides configuration and utility methods for the MontyAI application.
|
11
|
+
# # This module serves as a central point for managing settings and common
|
12
|
+
# # functionalities.
|
13
|
+
module MontyAI
|
14
|
+
class Error < StandardError; end
|
15
|
+
|
16
|
+
# Core configuration
|
17
|
+
class << self
|
18
|
+
def configuration
|
19
|
+
@configuration ||= Configuration.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def configure
|
23
|
+
yield(configuration) if block_given?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Configuration class for global settings
|
28
|
+
class Configuration
|
29
|
+
attr_accessor :api_key, :api_endpoint
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@api_key = ENV["OPENAI_API_KEY"] || ENV["ANTHROPIC_API_KEY"]
|
33
|
+
@api_endpoint = "https://api.openai.com/v1/chat/completions"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: monty-ai
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Steve Cook
|
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: thor
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '1.2'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '1.2'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: bundler
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '2.0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: rake
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '13.0'
|
47
|
+
type: :development
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '13.0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: rspec
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '3.0'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.0'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: standard
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '1.3'
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '1.3'
|
82
|
+
description: MontyAI is an intelligent code explanation tool that uses AI to help
|
83
|
+
you understand code faster.
|
84
|
+
email:
|
85
|
+
- stevorevo@duck.co
|
86
|
+
executables:
|
87
|
+
- monty-ai
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- LICENSE.txt
|
92
|
+
- README.md
|
93
|
+
- exe/monty-ai
|
94
|
+
- lib/monty_ai.rb
|
95
|
+
- lib/monty_ai/ai_client.rb
|
96
|
+
- lib/monty_ai/cli.rb
|
97
|
+
- lib/monty_ai/file_handler.rb
|
98
|
+
- lib/monty_ai/formatter.rb
|
99
|
+
- lib/monty_ai/version.rb
|
100
|
+
homepage: https://github.com/scookdev/monty_ai
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
metadata:
|
104
|
+
homepage_uri: https://github.com/scookdev/monty_ai
|
105
|
+
source_code_uri: https://github.com/scookdev/monty_ai
|
106
|
+
changelog_uri: https://github.com/scookdev/monty_ai/blob/main/CHANGELOG.md
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: 3.4.2
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubygems_version: 3.6.8
|
122
|
+
specification_version: 4
|
123
|
+
summary: CLI tool to explain code using AI
|
124
|
+
test_files: []
|