ai_refactor 0.5.2 → 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Steepfile +27 -0
- data/ai_refactor.gemspec +1 -1
- data/examples/ex1_convert_a_rspec_test_to_minitest.yml +2 -1
- data/examples/ex2_input.rb +17 -0
- data/examples/ex2_write_rbs.yml +7 -0
- data/exe/ai_refactor +0 -2
- data/lib/ai_refactor/prompt.rb +1 -1
- data/lib/ai_refactor/refactors/base_refactor.rb +37 -13
- data/lib/ai_refactor/refactors/custom.rb +2 -1
- data/lib/ai_refactor/refactors/ruby/refactor_ruby.md +0 -2
- data/lib/ai_refactor/refactors/ruby/write_rbs.md +118 -0
- data/lib/ai_refactor/refactors/ruby/write_rbs.rb +50 -0
- data/lib/ai_refactor/refactors/ruby/write_ruby.md +0 -2
- data/lib/ai_refactor/test_runners/steep_runner.rb +27 -0
- data/lib/ai_refactor/test_runners/test_run_result.rb +1 -1
- data/lib/ai_refactor/version.rb +1 -1
- metadata +11 -7
- data/Gemfile.lock +0 -244
- data/examples/.gitignore +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f916993ff53967b44cbbc81138c87d518518618d3edc932cefa6aea9f0a4c4c
|
4
|
+
data.tar.gz: 5d3bd3b9cea6d7bd39e0028caa5ccf24527dd03fcd98d643498a65743a2cac5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41cb1f31ceb6e503cdbeeb972f17a91e1826eccb4fb66e8a73b3b54bb3899ff9572d9cb4783c67fe7e7fee8999f7f25f2b19ae7ab9fde6c766e895e4fb4a1b32
|
7
|
+
data.tar.gz: 57626f38b266521d820bb411dbf517dd3273ed6e4bd44412d4c4e4b0306a3347252a1b87d0214c148f5f5e35c20cd81c6325648f878dd34d67fe58226156118d
|
data/Gemfile
CHANGED
data/Steepfile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# D = Steep::Diagnostic
|
2
|
+
#
|
3
|
+
# target :lib do
|
4
|
+
# signature "sig"
|
5
|
+
#
|
6
|
+
# check "lib" # Directory name
|
7
|
+
# check "Gemfile" # File name
|
8
|
+
# check "app/models/**/*.rb" # Glob
|
9
|
+
# # ignore "lib/templates/*.rb"
|
10
|
+
#
|
11
|
+
# # library "pathname" # Standard libraries
|
12
|
+
# # library "strong_json" # Gems
|
13
|
+
#
|
14
|
+
# # configure_code_diagnostics(D::Ruby.default) # `default` diagnostics setting (applies by default)
|
15
|
+
# # configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
|
16
|
+
# # configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
|
17
|
+
# # configure_code_diagnostics(D::Ruby.silent) # `silent` diagnostics setting
|
18
|
+
# # configure_code_diagnostics do |hash| # You can setup everything yourself
|
19
|
+
# # hash[D::Ruby::NoMethod] = :information
|
20
|
+
# # end
|
21
|
+
# end
|
22
|
+
|
23
|
+
# A steep target to check our example
|
24
|
+
target :examples do
|
25
|
+
signature "examples/outputs"
|
26
|
+
check "examples/ex2_input.rb"
|
27
|
+
end
|
data/ai_refactor.gemspec
CHANGED
@@ -31,6 +31,6 @@ Gem::Specification.new do |spec|
|
|
31
31
|
# Uncomment to register a new dependency of your gem
|
32
32
|
spec.add_dependency "colorize", "< 2.0"
|
33
33
|
spec.add_dependency "open3", "< 2.0"
|
34
|
-
spec.add_dependency "ruby-openai", ">= 3.4.0", "<
|
34
|
+
spec.add_dependency "ruby-openai", ">= 3.4.0", "< 6.0"
|
35
35
|
spec.add_dependency "zeitwerk", "~> 2.6"
|
36
36
|
end
|
@@ -2,6 +2,7 @@ refactor: rails/minitest/rspec_to_minitest
|
|
2
2
|
input_file_paths:
|
3
3
|
- examples/ex1_input_spec.rb
|
4
4
|
# We need to add context here as otherwise to tell the AI to require our local test_helper.rb file so that we can run the tests after
|
5
|
-
context_text: "In the output test use `require_relative` to include 'test_helper'."
|
5
|
+
context_text: "In the output test use `require_relative '../test_helper'` to include 'test_helper'."
|
6
6
|
# By default, ai_refactor runs "bundle exec rails test" but this isn't going to work here as we are not actually in a Rails app context in the examples
|
7
7
|
minitest_run_command: ruby __FILE__
|
8
|
+
output_file_path: examples/outputs/ex1_input_test.rb
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# example from https://blog.kiprosh.com/type-checking-in-ruby-3-using-rbs/
|
2
|
+
# basic_math.rb
|
3
|
+
|
4
|
+
class BasicMath
|
5
|
+
def initialize(num1, num2)
|
6
|
+
@num1 = num1
|
7
|
+
@num2 = num2
|
8
|
+
end
|
9
|
+
|
10
|
+
def first_less_than_second?
|
11
|
+
@num1 < @num2
|
12
|
+
end
|
13
|
+
|
14
|
+
def add
|
15
|
+
@num1 + @num2
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
refactor: ruby/write_rbs
|
2
|
+
input_file_paths:
|
3
|
+
- examples/ex2_input.rb
|
4
|
+
# We need to add context here as our class doesnt actually give any context.
|
5
|
+
context_text: "Assume that the inputs can be any numeric type."
|
6
|
+
# By default this refactor writes to `sig/...` but here we just put the result in `examples/...`
|
7
|
+
output_file_path: examples/outputs/ex2_input.rbs
|
data/exe/ai_refactor
CHANGED
data/lib/ai_refactor/prompt.rb
CHANGED
@@ -39,7 +39,7 @@ module AIRefactor
|
|
39
39
|
|
40
40
|
def file_processor
|
41
41
|
context = ::AIRefactor::Context.new(files: options[:context_file_paths], text: options[:context_text], logger: logger)
|
42
|
-
prompt = ::AIRefactor::Prompt.new(input_content: input_content, input_path: input_file, output_file_path: output_file_path, prompt: prompt_input, context: context, logger: logger, options: options)
|
42
|
+
prompt = ::AIRefactor::Prompt.new(input_content: input_content, input_path: input_file, output_file_path: output_file_path, prompt: prompt_input, context: context, logger: logger, prompt_footer: prompt_footer, options: options)
|
43
43
|
AIRefactor::FileProcessor.new(prompt: prompt, ai_client: ai_client, output_path: output_file_path, logger: logger, options: options)
|
44
44
|
end
|
45
45
|
|
@@ -102,22 +102,46 @@ module AIRefactor
|
|
102
102
|
false
|
103
103
|
end
|
104
104
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
105
|
+
def prompt_template_for_refactor
|
106
|
+
location = Module.const_source_location(::AIRefactor::Refactors::BaseRefactor.name)
|
107
|
+
File.join(File.dirname(location.first), "#{refactor_name}.md")
|
108
|
+
end
|
109
|
+
|
110
|
+
def prompt_template_for_refactor?
|
111
|
+
File.exist?(prompt_template_for_refactor)
|
112
|
+
end
|
113
|
+
|
114
|
+
def user_provided_prompt_template?
|
115
|
+
options[:prompt_file_path]&.length&.positive?
|
116
|
+
end
|
109
117
|
|
110
|
-
|
111
|
-
|
118
|
+
def prompt_from_file?
|
119
|
+
user_provided_prompt_template? || prompt_template_for_refactor?
|
120
|
+
end
|
121
|
+
|
122
|
+
def user_provided_prompt?
|
123
|
+
options[:prompt]&.length&.positive?
|
124
|
+
end
|
125
|
+
|
126
|
+
def prompt_input
|
127
|
+
if user_provided_prompt_template?
|
128
|
+
file = options[:prompt_file_path]
|
129
|
+
raise "No prompt file '#{file}' found. Check prompt_file_path is valid" unless File.exist?(file)
|
130
|
+
File.read(file)
|
112
131
|
else
|
113
|
-
|
114
|
-
File.
|
115
|
-
|
116
|
-
|
117
|
-
|
132
|
+
file = prompt_template_for_refactor
|
133
|
+
if File.exist?(file)
|
134
|
+
File.read(file)
|
135
|
+
elsif user_provided_prompt?
|
136
|
+
options[:prompt]
|
137
|
+
else
|
138
|
+
raise "No prompt was provided. Please provide one with the --prompt option or with a command file."
|
139
|
+
end
|
118
140
|
end
|
141
|
+
end
|
119
142
|
|
120
|
-
|
143
|
+
def prompt_footer
|
144
|
+
options[:prompt] if user_provided_prompt? && prompt_from_file?
|
121
145
|
end
|
122
146
|
|
123
147
|
def output_file_path
|
@@ -4,7 +4,7 @@ module AIRefactor
|
|
4
4
|
module Refactors
|
5
5
|
class Custom < BaseRefactor
|
6
6
|
def run
|
7
|
-
logger.verbose "Custom refactor to #{input_file}... (using user supplied prompt #{prompt_file_path})"
|
7
|
+
logger.verbose "Custom refactor to #{input_file}... (using user supplied prompt #{prompt_file_path || "from options"})"
|
8
8
|
logger.verbose "Write output to #{output_file_path}..." if output_file_path
|
9
9
|
|
10
10
|
begin
|
@@ -26,6 +26,7 @@ module AIRefactor
|
|
26
26
|
private
|
27
27
|
|
28
28
|
def prompt_file_path
|
29
|
+
return if options[:prompt]&.length&.positive?
|
29
30
|
specified_prompt_path = options[:prompt_file_path]
|
30
31
|
if specified_prompt_path&.length&.positive?
|
31
32
|
if File.exist?(specified_prompt_path)
|
@@ -0,0 +1,118 @@
|
|
1
|
+
You are an expert Ruby senior software developer.
|
2
|
+
|
3
|
+
You will be writing the type signatures for the Ruby code below, in RBS format.
|
4
|
+
|
5
|
+
RBS is a language to describe the structure of Ruby programs. You can write down the definition of a class or module: methods defined in the class, instance variables and their types, and inheritance/mix-in relations. It also allows declaring constants and global variables.
|
6
|
+
|
7
|
+
The following is a small example of RBS for a chat app.
|
8
|
+
|
9
|
+
Given the Ruby
|
10
|
+
```ruby
|
11
|
+
module ChatApp
|
12
|
+
VERSION = "1.0.0"
|
13
|
+
class User
|
14
|
+
attr_reader :login, :email
|
15
|
+
|
16
|
+
def initialize(login:, email:); end
|
17
|
+
|
18
|
+
def my_method(String arg1, Integer arg2); end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Bot
|
22
|
+
attr_reader :name
|
23
|
+
attr_reader :email
|
24
|
+
attr_reader :owner
|
25
|
+
|
26
|
+
def initialize(name:, owner:); end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Message
|
30
|
+
attr_reader :id, :string, :from, :reply_to
|
31
|
+
|
32
|
+
def initialize(from:, string:); end
|
33
|
+
|
34
|
+
def reply(from:, string:)
|
35
|
+
Message.new(from, string)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Channel
|
40
|
+
attr_reader :name, :messages, :users, :bots
|
41
|
+
|
42
|
+
def initialize(name)
|
43
|
+
@name = name
|
44
|
+
@messages = []
|
45
|
+
@users = []
|
46
|
+
@bots = []
|
47
|
+
end
|
48
|
+
|
49
|
+
def each_member(&block)
|
50
|
+
members = users + bots
|
51
|
+
block? ? members.each(&block) : members.each
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
We can write the RBS as follows:
|
58
|
+
```
|
59
|
+
module ChatApp
|
60
|
+
VERSION: String
|
61
|
+
|
62
|
+
class User
|
63
|
+
attr_reader login: String
|
64
|
+
attr_reader email: String
|
65
|
+
|
66
|
+
# If a method takes keyword arguments then use `key: Type` syntax.
|
67
|
+
def initialize: (login: String, email: String) -> void
|
68
|
+
|
69
|
+
# If a method takes positional arguments then put the type before the argument name.
|
70
|
+
def my_method: (String arg1, Integer arg2) -> String
|
71
|
+
end
|
72
|
+
|
73
|
+
class Bot
|
74
|
+
attr_reader name: String
|
75
|
+
attr_reader email: String
|
76
|
+
attr_reader owner: User
|
77
|
+
|
78
|
+
def initialize: (name: String, owner: User) -> void
|
79
|
+
end
|
80
|
+
|
81
|
+
class Message
|
82
|
+
attr_reader id: String
|
83
|
+
attr_reader string: String
|
84
|
+
attr_reader from: User | Bot # `|` means union types: `#from` can be `User` or `Bot`
|
85
|
+
attr_reader reply_to: Message? # `?` means optional type: `#reply_to` can be `nil`
|
86
|
+
|
87
|
+
def initialize: (from: User | Bot, string: String) -> void
|
88
|
+
|
89
|
+
def reply: (from: User | Bot, string: String) -> Message
|
90
|
+
end
|
91
|
+
|
92
|
+
class Channel
|
93
|
+
attr_reader name: String
|
94
|
+
attr_reader messages: Array[Message]
|
95
|
+
attr_reader users: Array[User]
|
96
|
+
attr_reader bots: Array[Bot]
|
97
|
+
|
98
|
+
def initialize: (String name) -> void
|
99
|
+
|
100
|
+
def each_member: () { (User | Bot) -> void } -> void # `{` and `}` means block.
|
101
|
+
| () -> Enumerator[User | Bot, void] # Method can be overloaded.
|
102
|
+
end
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
Note, when writing the RBS for a class method, eg one in a `class << self` block, use `def self.method` in the
|
107
|
+
type definition.
|
108
|
+
|
109
|
+
Do not include comments in your RBS code or start the file with 'rbs' or '.rbs'.
|
110
|
+
|
111
|
+
__{{context}}__
|
112
|
+
|
113
|
+
__{{prompt_header}}__
|
114
|
+
|
115
|
+
The input file is: __{{input_file_path}}__
|
116
|
+
The output file path is: __{{output_file_path}}__
|
117
|
+
|
118
|
+
__{{prompt_footer}}__
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AIRefactor
|
4
|
+
module Refactors
|
5
|
+
module Ruby
|
6
|
+
class WriteRbs < BaseRefactor
|
7
|
+
def run
|
8
|
+
logger.verbose "Write some RBS for #{input_file}..."
|
9
|
+
logger.verbose "Write output to #{output_file_path}..." if output_file_path
|
10
|
+
|
11
|
+
begin
|
12
|
+
output_content = process!(strip_ticks: true)
|
13
|
+
rescue => e
|
14
|
+
logger.error "Failed to process #{input_file}: #{e.message}"
|
15
|
+
return false
|
16
|
+
end
|
17
|
+
|
18
|
+
return false unless output_content
|
19
|
+
|
20
|
+
if output_file_path
|
21
|
+
steep_runner = AIRefactor::TestRunners::SteepRunner.new(input_file, command_template: options.minitest_run_command)
|
22
|
+
|
23
|
+
logger.verbose "Run steep against generated RBS file #{output_file_path} (`#{steep_runner.command}`)..."
|
24
|
+
test_run = steep_runner.run
|
25
|
+
|
26
|
+
if test_run.failed?
|
27
|
+
logger.warn "#{input_file} was translated to #{output_file_path} but the resulting RBS fails to pass a steep check..."
|
28
|
+
logger.error "Failed to run test, exited with status #{test_run.exitstatus}. Stdout: #{test_run.stdout}\n\nStderr: #{test_run.stderr}\n\n"
|
29
|
+
logger.error "New RBS failed!", bold: true
|
30
|
+
self.failed_message = "Generated RBS file failed to pass checks"
|
31
|
+
return false
|
32
|
+
end
|
33
|
+
|
34
|
+
logger.verbose "\nNew RBS file passed checks"
|
35
|
+
end
|
36
|
+
|
37
|
+
output_file_path ? true : output_content
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.description
|
41
|
+
"User supplied prompt to write RBS for some Ruby"
|
42
|
+
end
|
43
|
+
|
44
|
+
def default_output_path
|
45
|
+
File.join("sig", input_file.gsub(/\.rb$/, ".rbs"))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "open3"
|
4
|
+
|
5
|
+
module AIRefactor
|
6
|
+
module TestRunners
|
7
|
+
class SteepRunner
|
8
|
+
def initialize(file_path, command_template: "bundle exec steep __FILE__")
|
9
|
+
@file_path = file_path
|
10
|
+
@command_template = command_template
|
11
|
+
end
|
12
|
+
|
13
|
+
def command
|
14
|
+
@command_template.gsub("__FILE__", @file_path)
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
stdout, stderr, status = Open3.capture3(command)
|
19
|
+
# TODO: parse output
|
20
|
+
# look initally for Cannot find a configuration at Steepfile
|
21
|
+
#
|
22
|
+
# _matched, runs, _assertions, failures, errors, skips = stdout.match(/(\d+) runs, (\d+) assertions, (\d+) failures, (\d+) errors, (\d+) skips/).to_a
|
23
|
+
TestRunResult.new(stdout, stderr, status) # , runs, failures, skips, errors)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -5,7 +5,7 @@ module AIRefactor
|
|
5
5
|
class TestRunResult
|
6
6
|
attr_reader :stdout, :stderr, :example_count, :failure_count, :pending_count
|
7
7
|
|
8
|
-
def initialize(stdout, stderr, status, example_count, failure_count, pending_count, errored)
|
8
|
+
def initialize(stdout, stderr, status, example_count = 0, failure_count = 0, pending_count = 0, errored = 0)
|
9
9
|
@stdout = stdout
|
10
10
|
@stderr = stderr
|
11
11
|
@status = status
|
data/lib/ai_refactor/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ai_refactor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Ierodiaconou
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -47,7 +47,7 @@ dependencies:
|
|
47
47
|
version: 3.4.0
|
48
48
|
- - "<"
|
49
49
|
- !ruby/object:Gem::Version
|
50
|
-
version: '
|
50
|
+
version: '6.0'
|
51
51
|
type: :runtime
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -57,7 +57,7 @@ dependencies:
|
|
57
57
|
version: 3.4.0
|
58
58
|
- - "<"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: '
|
60
|
+
version: '6.0'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: zeitwerk
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,14 +84,15 @@ files:
|
|
84
84
|
- ".standard.yml"
|
85
85
|
- CHANGELOG.md
|
86
86
|
- Gemfile
|
87
|
-
- Gemfile.lock
|
88
87
|
- LICENSE.txt
|
89
88
|
- README.md
|
90
89
|
- Rakefile
|
90
|
+
- Steepfile
|
91
91
|
- ai_refactor.gemspec
|
92
|
-
- examples/.gitignore
|
93
92
|
- examples/ex1_convert_a_rspec_test_to_minitest.yml
|
94
93
|
- examples/ex1_input_spec.rb
|
94
|
+
- examples/ex2_input.rb
|
95
|
+
- examples/ex2_write_rbs.yml
|
95
96
|
- examples/rails_helper.rb
|
96
97
|
- examples/test_helper.rb
|
97
98
|
- exe/ai_refactor
|
@@ -117,12 +118,15 @@ files:
|
|
117
118
|
- lib/ai_refactor/refactors/rspec/minitest_to_rspec.rb
|
118
119
|
- lib/ai_refactor/refactors/ruby/refactor_ruby.md
|
119
120
|
- lib/ai_refactor/refactors/ruby/refactor_ruby.rb
|
121
|
+
- lib/ai_refactor/refactors/ruby/write_rbs.md
|
122
|
+
- lib/ai_refactor/refactors/ruby/write_rbs.rb
|
120
123
|
- lib/ai_refactor/refactors/ruby/write_ruby.md
|
121
124
|
- lib/ai_refactor/refactors/ruby/write_ruby.rb
|
122
125
|
- lib/ai_refactor/run_configuration.rb
|
123
126
|
- lib/ai_refactor/templated_path.rb
|
124
127
|
- lib/ai_refactor/test_runners/minitest_runner.rb
|
125
128
|
- lib/ai_refactor/test_runners/rspec_runner.rb
|
129
|
+
- lib/ai_refactor/test_runners/steep_runner.rb
|
126
130
|
- lib/ai_refactor/test_runners/test_run_diff_report.rb
|
127
131
|
- lib/ai_refactor/test_runners/test_run_result.rb
|
128
132
|
- lib/ai_refactor/version.rb
|
@@ -147,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
151
|
- !ruby/object:Gem::Version
|
148
152
|
version: '0'
|
149
153
|
requirements: []
|
150
|
-
rubygems_version: 3.4.
|
154
|
+
rubygems_version: 3.4.20
|
151
155
|
signing_key:
|
152
156
|
specification_version: 4
|
153
157
|
summary: Use AI to convert a Rails RSpec test suite to minitest.
|
data/Gemfile.lock
DELETED
@@ -1,244 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
ai_refactor (0.5.2)
|
5
|
-
colorize (< 2.0)
|
6
|
-
open3 (< 2.0)
|
7
|
-
ruby-openai (>= 3.4.0, < 5.0)
|
8
|
-
zeitwerk (~> 2.6)
|
9
|
-
|
10
|
-
GEM
|
11
|
-
remote: https://rubygems.org/
|
12
|
-
specs:
|
13
|
-
actioncable (7.0.8)
|
14
|
-
actionpack (= 7.0.8)
|
15
|
-
activesupport (= 7.0.8)
|
16
|
-
nio4r (~> 2.0)
|
17
|
-
websocket-driver (>= 0.6.1)
|
18
|
-
actionmailbox (7.0.8)
|
19
|
-
actionpack (= 7.0.8)
|
20
|
-
activejob (= 7.0.8)
|
21
|
-
activerecord (= 7.0.8)
|
22
|
-
activestorage (= 7.0.8)
|
23
|
-
activesupport (= 7.0.8)
|
24
|
-
mail (>= 2.7.1)
|
25
|
-
net-imap
|
26
|
-
net-pop
|
27
|
-
net-smtp
|
28
|
-
actionmailer (7.0.8)
|
29
|
-
actionpack (= 7.0.8)
|
30
|
-
actionview (= 7.0.8)
|
31
|
-
activejob (= 7.0.8)
|
32
|
-
activesupport (= 7.0.8)
|
33
|
-
mail (~> 2.5, >= 2.5.4)
|
34
|
-
net-imap
|
35
|
-
net-pop
|
36
|
-
net-smtp
|
37
|
-
rails-dom-testing (~> 2.0)
|
38
|
-
actionpack (7.0.8)
|
39
|
-
actionview (= 7.0.8)
|
40
|
-
activesupport (= 7.0.8)
|
41
|
-
rack (~> 2.0, >= 2.2.4)
|
42
|
-
rack-test (>= 0.6.3)
|
43
|
-
rails-dom-testing (~> 2.0)
|
44
|
-
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
45
|
-
actiontext (7.0.8)
|
46
|
-
actionpack (= 7.0.8)
|
47
|
-
activerecord (= 7.0.8)
|
48
|
-
activestorage (= 7.0.8)
|
49
|
-
activesupport (= 7.0.8)
|
50
|
-
globalid (>= 0.6.0)
|
51
|
-
nokogiri (>= 1.8.5)
|
52
|
-
actionview (7.0.8)
|
53
|
-
activesupport (= 7.0.8)
|
54
|
-
builder (~> 3.1)
|
55
|
-
erubi (~> 1.4)
|
56
|
-
rails-dom-testing (~> 2.0)
|
57
|
-
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
58
|
-
activejob (7.0.8)
|
59
|
-
activesupport (= 7.0.8)
|
60
|
-
globalid (>= 0.3.6)
|
61
|
-
activemodel (7.0.8)
|
62
|
-
activesupport (= 7.0.8)
|
63
|
-
activerecord (7.0.8)
|
64
|
-
activemodel (= 7.0.8)
|
65
|
-
activesupport (= 7.0.8)
|
66
|
-
activestorage (7.0.8)
|
67
|
-
actionpack (= 7.0.8)
|
68
|
-
activejob (= 7.0.8)
|
69
|
-
activerecord (= 7.0.8)
|
70
|
-
activesupport (= 7.0.8)
|
71
|
-
marcel (~> 1.0)
|
72
|
-
mini_mime (>= 1.1.0)
|
73
|
-
activesupport (7.0.8)
|
74
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
75
|
-
i18n (>= 1.6, < 2)
|
76
|
-
minitest (>= 5.1)
|
77
|
-
tzinfo (~> 2.0)
|
78
|
-
ast (2.4.2)
|
79
|
-
builder (3.2.4)
|
80
|
-
colorize (0.8.1)
|
81
|
-
concurrent-ruby (1.2.2)
|
82
|
-
crass (1.0.6)
|
83
|
-
date (3.3.3)
|
84
|
-
diff-lcs (1.5.0)
|
85
|
-
dotenv (2.8.1)
|
86
|
-
erubi (1.12.0)
|
87
|
-
faraday (2.7.4)
|
88
|
-
faraday-net_http (>= 2.0, < 3.1)
|
89
|
-
ruby2_keywords (>= 0.0.4)
|
90
|
-
faraday-multipart (1.0.4)
|
91
|
-
multipart-post (~> 2)
|
92
|
-
faraday-net_http (3.0.2)
|
93
|
-
globalid (1.2.1)
|
94
|
-
activesupport (>= 6.1)
|
95
|
-
i18n (1.14.1)
|
96
|
-
concurrent-ruby (~> 1.0)
|
97
|
-
json (2.6.3)
|
98
|
-
language_server-protocol (3.17.0.3)
|
99
|
-
lint_roller (1.0.0)
|
100
|
-
loofah (2.21.3)
|
101
|
-
crass (~> 1.0.2)
|
102
|
-
nokogiri (>= 1.12.0)
|
103
|
-
mail (2.8.1)
|
104
|
-
mini_mime (>= 0.1.1)
|
105
|
-
net-imap
|
106
|
-
net-pop
|
107
|
-
net-smtp
|
108
|
-
marcel (1.0.2)
|
109
|
-
method_source (1.0.0)
|
110
|
-
mini_mime (1.1.5)
|
111
|
-
minitest (5.18.0)
|
112
|
-
multipart-post (2.3.0)
|
113
|
-
net-imap (0.3.7)
|
114
|
-
date
|
115
|
-
net-protocol
|
116
|
-
net-pop (0.1.2)
|
117
|
-
net-protocol
|
118
|
-
net-protocol (0.2.1)
|
119
|
-
timeout
|
120
|
-
net-smtp (0.3.3)
|
121
|
-
net-protocol
|
122
|
-
nio4r (2.5.9)
|
123
|
-
nokogiri (1.15.4-arm64-darwin)
|
124
|
-
racc (~> 1.4)
|
125
|
-
open3 (0.1.2)
|
126
|
-
parallel (1.23.0)
|
127
|
-
parser (3.2.2.1)
|
128
|
-
ast (~> 2.4.1)
|
129
|
-
racc (1.7.1)
|
130
|
-
rack (2.2.8)
|
131
|
-
rack-test (2.1.0)
|
132
|
-
rack (>= 1.3)
|
133
|
-
rails (7.0.8)
|
134
|
-
actioncable (= 7.0.8)
|
135
|
-
actionmailbox (= 7.0.8)
|
136
|
-
actionmailer (= 7.0.8)
|
137
|
-
actionpack (= 7.0.8)
|
138
|
-
actiontext (= 7.0.8)
|
139
|
-
actionview (= 7.0.8)
|
140
|
-
activejob (= 7.0.8)
|
141
|
-
activemodel (= 7.0.8)
|
142
|
-
activerecord (= 7.0.8)
|
143
|
-
activestorage (= 7.0.8)
|
144
|
-
activesupport (= 7.0.8)
|
145
|
-
bundler (>= 1.15.0)
|
146
|
-
railties (= 7.0.8)
|
147
|
-
rails-dom-testing (2.2.0)
|
148
|
-
activesupport (>= 5.0.0)
|
149
|
-
minitest
|
150
|
-
nokogiri (>= 1.6)
|
151
|
-
rails-html-sanitizer (1.6.0)
|
152
|
-
loofah (~> 2.21)
|
153
|
-
nokogiri (~> 1.14)
|
154
|
-
railties (7.0.8)
|
155
|
-
actionpack (= 7.0.8)
|
156
|
-
activesupport (= 7.0.8)
|
157
|
-
method_source
|
158
|
-
rake (>= 12.2)
|
159
|
-
thor (~> 1.0)
|
160
|
-
zeitwerk (~> 2.5)
|
161
|
-
rainbow (3.1.1)
|
162
|
-
rake (13.0.6)
|
163
|
-
regexp_parser (2.8.0)
|
164
|
-
rexml (3.2.5)
|
165
|
-
rspec (3.12.0)
|
166
|
-
rspec-core (~> 3.12.0)
|
167
|
-
rspec-expectations (~> 3.12.0)
|
168
|
-
rspec-mocks (~> 3.12.0)
|
169
|
-
rspec-core (3.12.2)
|
170
|
-
rspec-support (~> 3.12.0)
|
171
|
-
rspec-expectations (3.12.3)
|
172
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
173
|
-
rspec-support (~> 3.12.0)
|
174
|
-
rspec-mocks (3.12.6)
|
175
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
176
|
-
rspec-support (~> 3.12.0)
|
177
|
-
rspec-rails (6.0.3)
|
178
|
-
actionpack (>= 6.1)
|
179
|
-
activesupport (>= 6.1)
|
180
|
-
railties (>= 6.1)
|
181
|
-
rspec-core (~> 3.12)
|
182
|
-
rspec-expectations (~> 3.12)
|
183
|
-
rspec-mocks (~> 3.12)
|
184
|
-
rspec-support (~> 3.12)
|
185
|
-
rspec-support (3.12.1)
|
186
|
-
rubocop (1.50.2)
|
187
|
-
json (~> 2.3)
|
188
|
-
parallel (~> 1.10)
|
189
|
-
parser (>= 3.2.0.0)
|
190
|
-
rainbow (>= 2.2.2, < 4.0)
|
191
|
-
regexp_parser (>= 1.8, < 3.0)
|
192
|
-
rexml (>= 3.2.5, < 4.0)
|
193
|
-
rubocop-ast (>= 1.28.0, < 2.0)
|
194
|
-
ruby-progressbar (~> 1.7)
|
195
|
-
unicode-display_width (>= 2.4.0, < 3.0)
|
196
|
-
rubocop-ast (1.28.1)
|
197
|
-
parser (>= 3.2.1.0)
|
198
|
-
rubocop-performance (1.16.0)
|
199
|
-
rubocop (>= 1.7.0, < 2.0)
|
200
|
-
rubocop-ast (>= 0.4.0)
|
201
|
-
ruby-openai (4.1.0)
|
202
|
-
faraday (>= 1)
|
203
|
-
faraday-multipart (>= 1)
|
204
|
-
ruby-progressbar (1.13.0)
|
205
|
-
ruby2_keywords (0.0.5)
|
206
|
-
shoulda-matchers (5.3.0)
|
207
|
-
activesupport (>= 5.2.0)
|
208
|
-
standard (1.28.2)
|
209
|
-
language_server-protocol (~> 3.17.0.2)
|
210
|
-
lint_roller (~> 1.0)
|
211
|
-
rubocop (~> 1.50.2)
|
212
|
-
standard-custom (~> 1.0.0)
|
213
|
-
standard-performance (~> 1.0.1)
|
214
|
-
standard-custom (1.0.0)
|
215
|
-
lint_roller (~> 1.0)
|
216
|
-
standard-performance (1.0.1)
|
217
|
-
lint_roller (~> 1.0)
|
218
|
-
rubocop-performance (~> 1.16.0)
|
219
|
-
thor (1.2.2)
|
220
|
-
timeout (0.4.0)
|
221
|
-
tzinfo (2.0.6)
|
222
|
-
concurrent-ruby (~> 1.0)
|
223
|
-
unicode-display_width (2.4.2)
|
224
|
-
websocket-driver (0.7.6)
|
225
|
-
websocket-extensions (>= 0.1.0)
|
226
|
-
websocket-extensions (0.1.5)
|
227
|
-
zeitwerk (2.6.8)
|
228
|
-
|
229
|
-
PLATFORMS
|
230
|
-
arm64-darwin-22
|
231
|
-
|
232
|
-
DEPENDENCIES
|
233
|
-
ai_refactor!
|
234
|
-
dotenv
|
235
|
-
minitest (~> 5.0)
|
236
|
-
rails
|
237
|
-
rake (~> 13.0)
|
238
|
-
rspec
|
239
|
-
rspec-rails
|
240
|
-
shoulda-matchers
|
241
|
-
standard (~> 1.3)
|
242
|
-
|
243
|
-
BUNDLED WITH
|
244
|
-
2.4.10
|
data/examples/.gitignore
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ex1_input_test.rb
|