pull_request_ai 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/MIT-LICENSE +20 -0
- data/README.md +125 -0
- data/Rakefile +10 -0
- data/app/assets/config/pull_request_ai_manifest.js +1 -0
- data/app/assets/javascripts/application.js +248 -0
- data/app/assets/javascripts/notifications.js +76 -0
- data/app/assets/stylesheets/pull_request_ai/application.css +15 -0
- data/app/assets/stylesheets/pull_request_ai/blocs.css +4 -0
- data/app/assets/stylesheets/pull_request_ai/helpers.css +26 -0
- data/app/assets/stylesheets/pull_request_ai/inputs.css +64 -0
- data/app/assets/stylesheets/pull_request_ai/notification.css +71 -0
- data/app/assets/stylesheets/pull_request_ai/spinner.css +24 -0
- data/app/controllers/pull_request_ai/application_controller.rb +6 -0
- data/app/controllers/pull_request_ai/pull_request_ai_controller.rb +85 -0
- data/app/helpers/pull_request_ai/application_helper.rb +6 -0
- data/app/models/pull_request_ai/application_record.rb +7 -0
- data/app/views/layouts/pull_request_ai/application.html.erb +29 -0
- data/app/views/pull_request_ai/pull_request_ai/new.html.erb +70 -0
- data/config/initializers/rack_attack.rb +30 -0
- data/config/routes.rb +13 -0
- data/lib/pull_request_ai/bitbucket/client.rb +148 -0
- data/lib/pull_request_ai/client.rb +80 -0
- data/lib/pull_request_ai/engine.rb +10 -0
- data/lib/pull_request_ai/github/client.rb +124 -0
- data/lib/pull_request_ai/openAi/client.rb +81 -0
- data/lib/pull_request_ai/openAi/interpreter.rb +19 -0
- data/lib/pull_request_ai/repo/client.rb +43 -0
- data/lib/pull_request_ai/repo/file.rb +20 -0
- data/lib/pull_request_ai/repo/prompt.rb +33 -0
- data/lib/pull_request_ai/repo/reader.rb +118 -0
- data/lib/pull_request_ai/util/configuration.rb +49 -0
- data/lib/pull_request_ai/util/error.rb +28 -0
- data/lib/pull_request_ai/util/symbol_details.rb +14 -0
- data/lib/pull_request_ai/version.rb +5 -0
- data/lib/pull_request_ai.rb +52 -0
- data/lib/tasks/pull_request_ai_tasks.rake +5 -0
- metadata +153 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PullRequestAi
|
4
|
+
module OpenAi
|
5
|
+
# A client to communicate with the OpenAI API.
|
6
|
+
class Client
|
7
|
+
attr_accessor :openai_api_key
|
8
|
+
attr_accessor :openai_api_endpoint
|
9
|
+
attr_accessor :api_version
|
10
|
+
attr_accessor :model
|
11
|
+
attr_accessor :temperature
|
12
|
+
attr_reader :http_timeout
|
13
|
+
|
14
|
+
##
|
15
|
+
# Initializes the client.
|
16
|
+
def initialize(
|
17
|
+
openai_api_key: nil,
|
18
|
+
openai_api_endpoint: nil,
|
19
|
+
api_version: nil,
|
20
|
+
model: nil,
|
21
|
+
temperature: nil
|
22
|
+
)
|
23
|
+
@openai_api_key = openai_api_key || PullRequestAi.openai_api_key
|
24
|
+
@openai_api_endpoint = openai_api_endpoint || PullRequestAi.openai_api_endpoint
|
25
|
+
@api_version = api_version || PullRequestAi.api_version
|
26
|
+
@model = model || PullRequestAi.model
|
27
|
+
@temperature = temperature || PullRequestAi.temperature
|
28
|
+
@http_timeout = PullRequestAi.http_timeout
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Makes the completions request from the OpenAI API.
|
33
|
+
# Given a prompt, the model will return one or more predicted completions.
|
34
|
+
# https://platform.openai.com/docs/api-reference/chat
|
35
|
+
def predicted_completions(content)
|
36
|
+
url = build_url
|
37
|
+
request(:post, url, body(content))
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def request(type, url, body)
|
43
|
+
response = HTTParty.send(
|
44
|
+
type, url, headers: headers, body: body, timeout: http_timeout
|
45
|
+
)
|
46
|
+
body = response.parsed_response
|
47
|
+
|
48
|
+
if response.success?
|
49
|
+
if body['choices'].nil? || body['choices'].empty?
|
50
|
+
Dry::Monads::Success('')
|
51
|
+
else
|
52
|
+
Dry::Monads::Success(body['choices'].first.dig('message', 'content'))
|
53
|
+
end
|
54
|
+
else
|
55
|
+
Error.failure(:failed_on_openai_api_endpoint, body.dig('error', 'message'))
|
56
|
+
end
|
57
|
+
rescue Net::ReadTimeout
|
58
|
+
Error.failure(:connection_timeout)
|
59
|
+
end
|
60
|
+
|
61
|
+
def build_url
|
62
|
+
"#{openai_api_endpoint}/#{api_version}/chat/completions"
|
63
|
+
end
|
64
|
+
|
65
|
+
def headers
|
66
|
+
{
|
67
|
+
'Content-Type' => 'application/json',
|
68
|
+
'Authorization' => "Bearer #{openai_api_key}"
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def body(content)
|
73
|
+
{
|
74
|
+
model: model,
|
75
|
+
messages: [{ role: :user, content: content }],
|
76
|
+
temperature: temperature
|
77
|
+
}.to_json
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PullRequestAi
|
4
|
+
module OpenAi
|
5
|
+
class Interpreter
|
6
|
+
def chat_message(feature_type, summary, current_changes)
|
7
|
+
result = ''.dup
|
8
|
+
unless summary.nil? || summary.strip.empty?
|
9
|
+
result << "Given the following summary for the changes made:\n"
|
10
|
+
result << "\"#{summary}\""
|
11
|
+
result << "\n\n"
|
12
|
+
end
|
13
|
+
result << "Write a #{feature_type} pull request description based on the following changes:\n"
|
14
|
+
result << current_changes
|
15
|
+
result.freeze
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PullRequestAi
|
4
|
+
module Repo
|
5
|
+
class Client
|
6
|
+
attr_reader :http_timeout
|
7
|
+
attr_accessor :api_endpoint
|
8
|
+
|
9
|
+
##
|
10
|
+
# Initializes the client.
|
11
|
+
def initialize(http_timeout, api_endpoint)
|
12
|
+
@http_timeout = http_timeout
|
13
|
+
@api_endpoint = api_endpoint
|
14
|
+
end
|
15
|
+
|
16
|
+
def opened_pull_requests(slug, head, base)
|
17
|
+
Error.failure(:project_not_configured)
|
18
|
+
end
|
19
|
+
|
20
|
+
def update_pull_request(slug, number, base, title, description)
|
21
|
+
Error.failure(:project_not_configured)
|
22
|
+
end
|
23
|
+
|
24
|
+
def open_pull_request(slug, head, base, title, description)
|
25
|
+
Error.failure(:project_not_configured)
|
26
|
+
end
|
27
|
+
|
28
|
+
class << self
|
29
|
+
def client_from_host(host)
|
30
|
+
result = host.success? ? host.success : ''
|
31
|
+
case result
|
32
|
+
when 'github.com'
|
33
|
+
PullRequestAi::GitHub::Client.new
|
34
|
+
when 'bitbucket.org'
|
35
|
+
PullRequestAi::Bitbucket::Client.new
|
36
|
+
else
|
37
|
+
PullRequestAi::Repo::Client.new
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PullRequestAi
|
4
|
+
module Repo
|
5
|
+
class File
|
6
|
+
attr_reader :name, :modified_lines
|
7
|
+
|
8
|
+
def initialize(name, modified_lines)
|
9
|
+
@name = name
|
10
|
+
@modified_lines = modified_lines
|
11
|
+
end
|
12
|
+
|
13
|
+
def trimmed_modified_lines
|
14
|
+
modified_lines.inject(name + "\n") do |result, line|
|
15
|
+
result << line.sub(/([+\-])\s*/) { ::Regexp.last_match(1) } + "\n"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PullRequestAi
|
4
|
+
module Repo
|
5
|
+
class Prompt
|
6
|
+
def configured?
|
7
|
+
%x(git rev-parse --is-inside-work-tree > /dev/null 2>&1)
|
8
|
+
$CHILD_STATUS.exitstatus == 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def current_branch
|
12
|
+
name = %x(git rev-parse --abbrev-ref HEAD).chomp
|
13
|
+
name == 'HEAD' ? %x(git rev-parse --short HEAD).chomp : name
|
14
|
+
end
|
15
|
+
|
16
|
+
def remote_name
|
17
|
+
%x(git remote).strip
|
18
|
+
end
|
19
|
+
|
20
|
+
def remote_url(name)
|
21
|
+
%x(git config --get remote.#{name}.url).strip
|
22
|
+
end
|
23
|
+
|
24
|
+
def remote_branches
|
25
|
+
%x(git branch --remotes --no-color).split("\n")
|
26
|
+
end
|
27
|
+
|
28
|
+
def changes_between(branch1, branch2)
|
29
|
+
%x(git diff --patch #{branch1}..#{branch2}).strip
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PullRequestAi
|
4
|
+
module Repo
|
5
|
+
class Reader
|
6
|
+
include Dry::Monads[:result]
|
7
|
+
|
8
|
+
attr_accessor :prompt
|
9
|
+
|
10
|
+
def initialize(prompt: Prompt.new)
|
11
|
+
@prompt = prompt
|
12
|
+
end
|
13
|
+
|
14
|
+
def current_branch
|
15
|
+
prompt.configured? ? Success(prompt.current_branch) : Error.failure(:project_not_configured)
|
16
|
+
end
|
17
|
+
|
18
|
+
def remote_name
|
19
|
+
prompt.configured? ? Success(prompt.remote_name) : Error.failure(:project_not_configured)
|
20
|
+
end
|
21
|
+
|
22
|
+
def repository_slug
|
23
|
+
remote_uri.bind do |uri|
|
24
|
+
regex = %r{\A/?(?<slug>.*?)(?:\.git)?\Z}
|
25
|
+
match = regex.match(uri.path)
|
26
|
+
match ? Success(match[:slug]) : Error.failure(:invalid_repository_url)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def repository_host
|
31
|
+
remote_uri.bind do |uri|
|
32
|
+
Success(uri.host)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def remote_uri
|
37
|
+
remote_name.bind do |name|
|
38
|
+
url = prompt.remote_url(name)
|
39
|
+
uri = GitCloneUrl.parse(url)
|
40
|
+
Success(uri)
|
41
|
+
end
|
42
|
+
rescue URI::InvalidComponentError
|
43
|
+
Error.failure(:invalid_repository_url)
|
44
|
+
end
|
45
|
+
|
46
|
+
def remote_branches
|
47
|
+
remote_name.bind do |name|
|
48
|
+
branches = prompt.remote_branches
|
49
|
+
.reject { !_1.strip.start_with?(name) }
|
50
|
+
.map { _1.strip.sub(%r{\A#{name}/}, '') }
|
51
|
+
.reject(&:empty?)
|
52
|
+
Success(branches)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def destination_branches
|
57
|
+
current_branch.bind do |current|
|
58
|
+
remote_branches.bind do |branches|
|
59
|
+
if branches.include?(current)
|
60
|
+
Success(branches.reject { _1 == current || _1.start_with?('HEAD') })
|
61
|
+
else
|
62
|
+
Error.failure(:current_branch_not_pushed)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def current_changes(to_base)
|
69
|
+
current_branch.bind do |current|
|
70
|
+
changes_between(to_base, current)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def flatten_current_changes(to_base)
|
75
|
+
current_changes(to_base).bind do |changes|
|
76
|
+
Success(changes.inject(''.dup) { |result, file| result << file.trimmed_modified_lines })
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def changes_between(branch1, branch2)
|
83
|
+
if prompt.configured? == false
|
84
|
+
Error.failure(:project_not_configured)
|
85
|
+
else
|
86
|
+
diff_output = prompt.changes_between(branch1, branch2)
|
87
|
+
changes = []
|
88
|
+
|
89
|
+
file_name = nil
|
90
|
+
modified_lines = []
|
91
|
+
diff_output.each_line do |line|
|
92
|
+
line = line.chomp
|
93
|
+
if line.start_with?('diff --git')
|
94
|
+
if file_name && file_name.end_with?('.lock') == false
|
95
|
+
changes << PullRequestAi::Repo::File.new(file_name, modified_lines)
|
96
|
+
end
|
97
|
+
file_name = line.split(' ')[-1].strip
|
98
|
+
file_name = file_name.start_with?('b/') ? file_name[2..-1] : file_name
|
99
|
+
modified_lines = []
|
100
|
+
elsif line.start_with?('--- ') || line.start_with?('+++ ')
|
101
|
+
next
|
102
|
+
elsif line.start_with?('-') && line.strip != '-'
|
103
|
+
modified_lines << line
|
104
|
+
elsif line.start_with?('+') && line.strip != '+'
|
105
|
+
modified_lines << line
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
if file_name
|
110
|
+
changes << PullRequestAi::Repo::File.new(file_name, modified_lines)
|
111
|
+
end
|
112
|
+
|
113
|
+
Success(changes)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PullRequestAi
|
4
|
+
module Util
|
5
|
+
class Configuration
|
6
|
+
attr_accessor :openai_api_key
|
7
|
+
attr_accessor :github_access_token
|
8
|
+
attr_accessor :bitbucket_app_password
|
9
|
+
attr_accessor :bitbucket_username
|
10
|
+
|
11
|
+
attr_accessor :openai_api_endpoint
|
12
|
+
attr_accessor :github_api_endpoint
|
13
|
+
attr_accessor :bitbucket_api_endpoint
|
14
|
+
|
15
|
+
attr_accessor :model
|
16
|
+
attr_accessor :temperature
|
17
|
+
attr_accessor :http_timeout
|
18
|
+
|
19
|
+
attr_reader :api_version
|
20
|
+
attr_reader :rrtools_grouped_gems
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
@api_version = 'v1'
|
24
|
+
|
25
|
+
@openai_api_key = ENV['OPENAI_API_KEY']
|
26
|
+
@github_access_token = ENV['GITHUB_ACCESS_TOKEN']
|
27
|
+
@bitbucket_app_password = ENV['BITBUCKET_APP_PASSWORD']
|
28
|
+
@bitbucket_username = ENV['BITBUCKET_USERNAME']
|
29
|
+
|
30
|
+
@openai_api_endpoint = 'https://api.openai.com'
|
31
|
+
@github_api_endpoint = 'https://api.github.com'
|
32
|
+
@bitbucket_api_endpoint = 'https://api.bitbucket.org'
|
33
|
+
|
34
|
+
@model = 'gpt-3.5-turbo'
|
35
|
+
@temperature = 0.6
|
36
|
+
@http_timeout = 60
|
37
|
+
|
38
|
+
@rrtools_grouped_gems = Rails.application.routes.routes.select do |prop|
|
39
|
+
prop.defaults[:group] == 'RRTools'
|
40
|
+
end.collect do |route|
|
41
|
+
{
|
42
|
+
name: route.name,
|
43
|
+
path: route.path.build_formatter.instance_variable_get('@parts').join
|
44
|
+
}
|
45
|
+
end || []
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PullRequestAi
|
4
|
+
class Error
|
5
|
+
attr_reader :symbol, :message
|
6
|
+
|
7
|
+
def initialize(symbol, message = nil)
|
8
|
+
@symbol = symbol
|
9
|
+
@message = message
|
10
|
+
end
|
11
|
+
|
12
|
+
def description
|
13
|
+
error_desc = SYMBOL_DETAILS[symbol]
|
14
|
+
if error_desc
|
15
|
+
error_desc + (message ? " #{message}" : '')
|
16
|
+
else
|
17
|
+
message || symbol.to_s
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def failure(symbol, message = nil)
|
23
|
+
new_instance = new(symbol, message)
|
24
|
+
Dry::Monads::Failure(new_instance)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PullRequestAi
|
4
|
+
SYMBOL_DETAILS = {
|
5
|
+
project_not_configured: 'Your project doesn\'t have a GitHub repository configured.',
|
6
|
+
invalid_repository_url: 'Couldn\'t read the remote URL from the repository.',
|
7
|
+
current_branch_not_pushed: 'The current branch has not yet been pushed into the remote.',
|
8
|
+
connection_timeout: 'Connection timeout.',
|
9
|
+
failed_on_openai_api_endpoint: 'Failed to communicate with openAI API.',
|
10
|
+
failed_on_github_api_endpoint: 'Failed to communicate with GitHub API.',
|
11
|
+
failed_on_bitbucket_api_endpoint: 'Failed to communicate with Bitbucket API.',
|
12
|
+
no_changes_btween_branches: 'No changes between branches. Please check the destination branch.'
|
13
|
+
}
|
14
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
require 'httparty'
|
5
|
+
require 'dry/monads'
|
6
|
+
require 'rack/attack'
|
7
|
+
require 'git_clone_url'
|
8
|
+
|
9
|
+
require 'pull_request_ai/client'
|
10
|
+
require 'pull_request_ai/version'
|
11
|
+
require 'pull_request_ai/engine'
|
12
|
+
|
13
|
+
require 'pull_request_ai/util/configuration'
|
14
|
+
require 'pull_request_ai/util/symbol_details'
|
15
|
+
require 'pull_request_ai/util/error'
|
16
|
+
|
17
|
+
require 'pull_request_ai/openAi/client'
|
18
|
+
require 'pull_request_ai/openAi/interpreter'
|
19
|
+
|
20
|
+
require 'pull_request_ai/repo/client'
|
21
|
+
require 'pull_request_ai/repo/reader'
|
22
|
+
require 'pull_request_ai/repo/prompt'
|
23
|
+
require 'pull_request_ai/repo/file'
|
24
|
+
|
25
|
+
require 'pull_request_ai/bitbucket/client'
|
26
|
+
require 'pull_request_ai/github/client'
|
27
|
+
|
28
|
+
module PullRequestAi
|
29
|
+
extend SingleForwardable
|
30
|
+
def_delegators :configuration, :github_api_endpoint
|
31
|
+
def_delegators :configuration, :github_access_token, :github_access_token=
|
32
|
+
def_delegators :configuration, :bitbucket_api_endpoint
|
33
|
+
def_delegators :configuration, :bitbucket_app_password, :bitbucket_app_password=
|
34
|
+
def_delegators :configuration, :bitbucket_username, :bitbucket_username=
|
35
|
+
def_delegators :configuration, :openai_api_key, :openai_api_key=
|
36
|
+
def_delegators :configuration, :openai_api_endpoint
|
37
|
+
def_delegators :configuration, :api_version
|
38
|
+
def_delegators :configuration, :model, :model=
|
39
|
+
def_delegators :configuration, :temperature, :temperature=
|
40
|
+
def_delegators :configuration, :http_timeout
|
41
|
+
|
42
|
+
class << self
|
43
|
+
def configure(&block)
|
44
|
+
yield configuration
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns an existing configuration object or instantiates a new one
|
48
|
+
def configuration
|
49
|
+
@configuration ||= Util::Configuration.new
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pull_request_ai
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Runtime Revolution
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-05-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-monads
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: git_clone_url
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: httparty
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.21'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.21'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rack-attack
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '6.6'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '6.6'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rails
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '6.1'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '6.1'
|
83
|
+
description: Rails Engine that provides pull requests descriptions generated by ChatGPT.
|
84
|
+
email:
|
85
|
+
- info@runtime-revolution.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- MIT-LICENSE
|
91
|
+
- README.md
|
92
|
+
- Rakefile
|
93
|
+
- app/assets/config/pull_request_ai_manifest.js
|
94
|
+
- app/assets/javascripts/application.js
|
95
|
+
- app/assets/javascripts/notifications.js
|
96
|
+
- app/assets/stylesheets/pull_request_ai/application.css
|
97
|
+
- app/assets/stylesheets/pull_request_ai/blocs.css
|
98
|
+
- app/assets/stylesheets/pull_request_ai/helpers.css
|
99
|
+
- app/assets/stylesheets/pull_request_ai/inputs.css
|
100
|
+
- app/assets/stylesheets/pull_request_ai/notification.css
|
101
|
+
- app/assets/stylesheets/pull_request_ai/spinner.css
|
102
|
+
- app/controllers/pull_request_ai/application_controller.rb
|
103
|
+
- app/controllers/pull_request_ai/pull_request_ai_controller.rb
|
104
|
+
- app/helpers/pull_request_ai/application_helper.rb
|
105
|
+
- app/models/pull_request_ai/application_record.rb
|
106
|
+
- app/views/layouts/pull_request_ai/application.html.erb
|
107
|
+
- app/views/pull_request_ai/pull_request_ai/new.html.erb
|
108
|
+
- config/initializers/rack_attack.rb
|
109
|
+
- config/routes.rb
|
110
|
+
- lib/pull_request_ai.rb
|
111
|
+
- lib/pull_request_ai/bitbucket/client.rb
|
112
|
+
- lib/pull_request_ai/client.rb
|
113
|
+
- lib/pull_request_ai/engine.rb
|
114
|
+
- lib/pull_request_ai/github/client.rb
|
115
|
+
- lib/pull_request_ai/openAi/client.rb
|
116
|
+
- lib/pull_request_ai/openAi/interpreter.rb
|
117
|
+
- lib/pull_request_ai/repo/client.rb
|
118
|
+
- lib/pull_request_ai/repo/file.rb
|
119
|
+
- lib/pull_request_ai/repo/prompt.rb
|
120
|
+
- lib/pull_request_ai/repo/reader.rb
|
121
|
+
- lib/pull_request_ai/util/configuration.rb
|
122
|
+
- lib/pull_request_ai/util/error.rb
|
123
|
+
- lib/pull_request_ai/util/symbol_details.rb
|
124
|
+
- lib/pull_request_ai/version.rb
|
125
|
+
- lib/tasks/pull_request_ai_tasks.rake
|
126
|
+
homepage: https://www.runtime-revolution.com
|
127
|
+
licenses:
|
128
|
+
- MIT
|
129
|
+
metadata:
|
130
|
+
allowed_push_host: https://rubygems.org
|
131
|
+
homepage_uri: https://www.runtime-revolution.com
|
132
|
+
source_code_uri: https://github.com/runtimerevolution/pull_request_ai
|
133
|
+
changelog_uri: https://github.com/runtimerevolution/pull_request_ai
|
134
|
+
post_install_message:
|
135
|
+
rdoc_options: []
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
requirements: []
|
149
|
+
rubygems_version: 3.4.10
|
150
|
+
signing_key:
|
151
|
+
specification_version: 4
|
152
|
+
summary: Rails Engine that provides pull requests descriptions generated by ChatGPT.
|
153
|
+
test_files: []
|