rubycode 0.1.1 ā 0.1.2
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/.rubocop.yml +8 -0
- data/README.md +82 -13
- data/config/tools/bash.json +17 -0
- data/config/tools/done.json +17 -0
- data/config/tools/read.json +25 -0
- data/config/tools/search.json +29 -0
- data/lib/rubycode/adapters/base.rb +2 -1
- data/lib/rubycode/adapters/ollama.rb +45 -38
- data/lib/rubycode/agent_loop.rb +134 -0
- data/lib/rubycode/client/display_formatter.rb +53 -0
- data/lib/rubycode/client/response_handler.rb +55 -0
- data/lib/rubycode/client.rb +24 -172
- data/lib/rubycode/configuration.rb +7 -8
- data/lib/rubycode/context_builder.rb +3 -2
- data/lib/rubycode/errors.rb +21 -0
- data/lib/rubycode/history.rb +16 -14
- data/lib/rubycode/tools/base.rb +80 -0
- data/lib/rubycode/tools/bash.rb +34 -43
- data/lib/rubycode/tools/done.rb +5 -23
- data/lib/rubycode/tools/read.rb +40 -55
- data/lib/rubycode/tools/search.rb +42 -67
- data/lib/rubycode/tools.rb +10 -5
- data/lib/rubycode/value_objects.rb +102 -0
- data/lib/rubycode/version.rb +2 -2
- data/lib/rubycode.rb +5 -3
- data/rubycode_cli.rb +12 -13
- metadata +16 -4
- data/rubycode-0.1.0.gem +0 -0
data/lib/rubycode/tools/read.rb
CHANGED
|
@@ -1,74 +1,59 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
module
|
|
3
|
+
module RubyCode
|
|
4
4
|
module Tools
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type: "function",
|
|
9
|
-
function: {
|
|
10
|
-
name: "read",
|
|
11
|
-
description: "Read a file or directory from the filesystem.\n\n- Use this when you know the file path and want to see its contents\n- Returns file contents with line numbers (format: 'line_number: content')\n- For directories, returns a listing of entries\n- Use the search tool to find specific content in files\n- Use bash with 'ls' or 'find' to discover what files exist",
|
|
12
|
-
parameters: {
|
|
13
|
-
type: "object",
|
|
14
|
-
properties: {
|
|
15
|
-
file_path: {
|
|
16
|
-
type: "string",
|
|
17
|
-
description: "Absolute or relative path to the file to read"
|
|
18
|
-
},
|
|
19
|
-
offset: {
|
|
20
|
-
type: "integer",
|
|
21
|
-
description: "Line number to start reading from (1-indexed). Optional."
|
|
22
|
-
},
|
|
23
|
-
limit: {
|
|
24
|
-
type: "integer",
|
|
25
|
-
description: "Maximum number of lines to read. Default 2000. Optional."
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
required: ["file_path"]
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
end
|
|
5
|
+
# Tool for reading files and directories
|
|
6
|
+
class Read < Base
|
|
7
|
+
private
|
|
33
8
|
|
|
34
|
-
def
|
|
9
|
+
def perform(params)
|
|
35
10
|
file_path = params["file_path"]
|
|
36
11
|
offset = params["offset"] || 1
|
|
37
12
|
limit = params["limit"] || 2000
|
|
38
13
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
File.join(context[:root_path], file_path)
|
|
44
|
-
end
|
|
14
|
+
full_path = resolve_path(file_path)
|
|
15
|
+
raise FileNotFoundError, "File '#{file_path}' does not exist" unless File.exist?(full_path)
|
|
16
|
+
|
|
17
|
+
return list_directory(full_path, file_path) if File.directory?(full_path)
|
|
45
18
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
19
|
+
format_file_lines(full_path, offset, limit)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def resolve_path(file_path)
|
|
23
|
+
File.absolute_path?(file_path) ? file_path : File.join(root_path, file_path)
|
|
24
|
+
end
|
|
49
25
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
end
|
|
26
|
+
def list_directory(full_path, file_path)
|
|
27
|
+
entries = Dir.entries(full_path).reject { |e| e.start_with?(".") }.sort
|
|
28
|
+
"Directory listing for '#{file_path}':\n" + entries.map { |e| " #{e}" }.join("\n")
|
|
29
|
+
end
|
|
55
30
|
|
|
31
|
+
def format_file_lines(full_path, offset, limit)
|
|
56
32
|
lines = File.readlines(full_path)
|
|
57
33
|
start_idx = [offset - 1, 0].max
|
|
58
34
|
end_idx = [start_idx + limit - 1, lines.length - 1].min
|
|
59
35
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
36
|
+
formatted_lines = (start_idx..end_idx).map do |i|
|
|
37
|
+
format_line(lines[i], i + 1)
|
|
38
|
+
end.join("\n")
|
|
39
|
+
|
|
40
|
+
build_tool_result(formatted_lines, start_idx, end_idx, lines.length)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def build_tool_result(content, start_idx, end_idx, total_lines)
|
|
44
|
+
ToolResult.new(
|
|
45
|
+
content: content,
|
|
46
|
+
metadata: {
|
|
47
|
+
line_count: end_idx - start_idx + 1,
|
|
48
|
+
truncated: end_idx < total_lines - 1
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
end
|
|
68
52
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
53
|
+
def format_line(line, line_num)
|
|
54
|
+
content = line.chomp
|
|
55
|
+
content = "#{content[0..2000]}..." if content.length > 2000
|
|
56
|
+
"#{line_num}: #{content}"
|
|
72
57
|
end
|
|
73
58
|
end
|
|
74
59
|
end
|
|
@@ -1,88 +1,63 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "English"
|
|
3
4
|
require "shellwords"
|
|
4
5
|
|
|
5
|
-
module
|
|
6
|
+
module RubyCode
|
|
6
7
|
module Tools
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
type: "function",
|
|
11
|
-
function: {
|
|
12
|
-
name: "search",
|
|
13
|
-
description: "Search INSIDE file contents for patterns using grep. Returns matching lines with file paths and line numbers.\n\n- Searches file CONTENTS using regular expressions\n- Use this when you need to find WHERE specific text/code appears inside files\n- Returns file paths, line numbers, and the matching content\n- Example: search for 'button' to find files containing that text",
|
|
14
|
-
parameters: {
|
|
15
|
-
type: "object",
|
|
16
|
-
properties: {
|
|
17
|
-
pattern: {
|
|
18
|
-
type: "string",
|
|
19
|
-
description: "The pattern to search for (supports regex)"
|
|
20
|
-
},
|
|
21
|
-
path: {
|
|
22
|
-
type: "string",
|
|
23
|
-
description: "Directory or file to search in. Defaults to '.' (current directory). Optional."
|
|
24
|
-
},
|
|
25
|
-
include: {
|
|
26
|
-
type: "string",
|
|
27
|
-
description: "File pattern to include (e.g., '*.rb', '*.js'). Optional."
|
|
28
|
-
},
|
|
29
|
-
case_insensitive: {
|
|
30
|
-
type: "boolean",
|
|
31
|
-
description: "Perform case-insensitive search. Optional."
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
required: ["pattern"]
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
end
|
|
8
|
+
# Tool for searching file contents with grep
|
|
9
|
+
class Search < Base
|
|
10
|
+
private
|
|
39
11
|
|
|
40
|
-
def
|
|
12
|
+
def perform(params)
|
|
41
13
|
pattern = params["pattern"]
|
|
42
14
|
path = params["path"] || "."
|
|
43
|
-
include_pattern = params["include"]
|
|
44
|
-
case_insensitive = params["case_insensitive"] || false
|
|
45
15
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
path
|
|
49
|
-
else
|
|
50
|
-
File.join(context[:root_path], path)
|
|
51
|
-
end
|
|
16
|
+
full_path = resolve_path(path)
|
|
17
|
+
raise PathError, "Path '#{path}' does not exist" unless File.exist?(full_path)
|
|
52
18
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
end
|
|
19
|
+
command = build_grep_command(pattern, full_path, params)
|
|
20
|
+
output, exit_code = execute_grep(command)
|
|
56
21
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
22
|
+
format_output(output, exit_code, pattern)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def resolve_path(path)
|
|
26
|
+
File.absolute_path?(path) ? path : File.join(root_path, path)
|
|
27
|
+
end
|
|
63
28
|
|
|
64
|
-
|
|
29
|
+
def build_grep_command(pattern, full_path, params)
|
|
30
|
+
[
|
|
31
|
+
"grep", "-n", "-r",
|
|
32
|
+
("-i" if params["case_insensitive"]),
|
|
33
|
+
("--include=#{Shellwords.escape(params["include"])}" if params["include"]),
|
|
34
|
+
Shellwords.escape(pattern),
|
|
35
|
+
Shellwords.escape(full_path)
|
|
36
|
+
].compact.join(" ")
|
|
37
|
+
end
|
|
65
38
|
|
|
39
|
+
def execute_grep(command)
|
|
66
40
|
output = `#{command} 2>&1`
|
|
67
|
-
|
|
41
|
+
[output, $CHILD_STATUS.exitstatus]
|
|
42
|
+
end
|
|
68
43
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
else
|
|
75
|
-
output
|
|
76
|
-
end
|
|
77
|
-
elsif exit_code == 1
|
|
78
|
-
# No matches found
|
|
44
|
+
def format_output(output, exit_code, pattern)
|
|
45
|
+
case exit_code
|
|
46
|
+
when 0
|
|
47
|
+
truncate_output(output)
|
|
48
|
+
when 1
|
|
79
49
|
"No matches found for pattern: #{pattern}"
|
|
80
50
|
else
|
|
81
|
-
|
|
82
|
-
"Error running search: #{output}"
|
|
51
|
+
raise CommandExecutionError, "Error running search: #{output}"
|
|
83
52
|
end
|
|
84
|
-
|
|
85
|
-
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def truncate_output(output)
|
|
56
|
+
lines = output.split("\n")
|
|
57
|
+
return output if lines.length <= 100
|
|
58
|
+
|
|
59
|
+
truncated = lines[0..99].join("\n")
|
|
60
|
+
"#{truncated}\n\n... (#{lines.length - 100} more matches truncated)"
|
|
86
61
|
end
|
|
87
62
|
end
|
|
88
63
|
end
|
data/lib/rubycode/tools.rb
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "tools/base"
|
|
3
4
|
require_relative "tools/bash"
|
|
4
5
|
require_relative "tools/read"
|
|
5
6
|
require_relative "tools/search"
|
|
6
7
|
require_relative "tools/done"
|
|
7
8
|
|
|
8
|
-
module
|
|
9
|
+
module RubyCode
|
|
10
|
+
# Collection of available tools for the AI agent
|
|
9
11
|
module Tools
|
|
10
12
|
# Registry of all available tools
|
|
11
13
|
TOOLS = [
|
|
@@ -22,11 +24,14 @@ module Rubycode
|
|
|
22
24
|
def self.execute(tool_name:, params:, context:)
|
|
23
25
|
tool_class = TOOLS.find { |t| t.definition[:function][:name] == tool_name }
|
|
24
26
|
|
|
25
|
-
unless tool_class
|
|
26
|
-
return "Error: Unknown tool '#{tool_name}'"
|
|
27
|
-
end
|
|
27
|
+
raise ToolError, "Unknown tool '#{tool_name}'" unless tool_class
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
# Instantiate tool and call execute
|
|
30
|
+
tool_instance = tool_class.new(context: context)
|
|
31
|
+
result = tool_instance.execute(params)
|
|
32
|
+
|
|
33
|
+
# Convert result to string for history compatibility
|
|
34
|
+
result.respond_to?(:to_s) ? result.to_s : result
|
|
30
35
|
end
|
|
31
36
|
end
|
|
32
37
|
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubyCode
|
|
4
|
+
# Represents a conversation message
|
|
5
|
+
class Message
|
|
6
|
+
attr_reader :role, :content, :timestamp
|
|
7
|
+
|
|
8
|
+
def initialize(role:, content:)
|
|
9
|
+
@role = role
|
|
10
|
+
@content = content
|
|
11
|
+
@timestamp = Time.now
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_h
|
|
15
|
+
{ role: role, content: content }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def ==(other)
|
|
19
|
+
other.is_a?(Message) &&
|
|
20
|
+
role == other.role &&
|
|
21
|
+
content == other.content
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Represents a tool call from the LLM
|
|
26
|
+
class ToolCall
|
|
27
|
+
attr_reader :name, :arguments
|
|
28
|
+
|
|
29
|
+
def initialize(name:, arguments:)
|
|
30
|
+
@name = name
|
|
31
|
+
@arguments = arguments
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_h
|
|
35
|
+
{ name: name, arguments: arguments }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def ==(other)
|
|
39
|
+
other.is_a?(ToolCall) &&
|
|
40
|
+
name == other.name &&
|
|
41
|
+
arguments == other.arguments
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Represents the result of a tool execution
|
|
46
|
+
class ToolResult
|
|
47
|
+
attr_reader :content, :metadata
|
|
48
|
+
|
|
49
|
+
def initialize(content:, metadata: {})
|
|
50
|
+
@content = content
|
|
51
|
+
@metadata = metadata
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def to_s
|
|
55
|
+
content
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def truncated?
|
|
59
|
+
metadata[:truncated] == true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def line_count
|
|
63
|
+
metadata[:line_count]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def ==(other)
|
|
67
|
+
other.is_a?(ToolResult) &&
|
|
68
|
+
content == other.content &&
|
|
69
|
+
metadata == other.metadata
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Represents the result of a bash command execution
|
|
74
|
+
class CommandResult
|
|
75
|
+
attr_reader :stdout, :stderr, :exit_code
|
|
76
|
+
|
|
77
|
+
def initialize(stdout:, stderr: "", exit_code: 0)
|
|
78
|
+
@stdout = stdout
|
|
79
|
+
@stderr = stderr
|
|
80
|
+
@exit_code = exit_code
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def success?
|
|
84
|
+
exit_code.zero?
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def output
|
|
88
|
+
success? ? stdout : stderr
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def to_s
|
|
92
|
+
output
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def ==(other)
|
|
96
|
+
other.is_a?(CommandResult) &&
|
|
97
|
+
stdout == other.stdout &&
|
|
98
|
+
stderr == other.stderr &&
|
|
99
|
+
exit_code == other.exit_code
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
data/lib/rubycode/version.rb
CHANGED
data/lib/rubycode.rb
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "rubycode/version"
|
|
4
|
+
require_relative "rubycode/errors"
|
|
5
|
+
require_relative "rubycode/value_objects"
|
|
4
6
|
require_relative "rubycode/configuration"
|
|
5
7
|
require_relative "rubycode/history"
|
|
6
8
|
require_relative "rubycode/context_builder"
|
|
7
9
|
require_relative "rubycode/adapters/base"
|
|
8
10
|
require_relative "rubycode/adapters/ollama"
|
|
9
11
|
require_relative "rubycode/tools"
|
|
12
|
+
require_relative "rubycode/agent_loop"
|
|
10
13
|
require_relative "rubycode/client"
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
# Rubycode is a Ruby-native AI coding agent with pluggable LLM adapters
|
|
16
|
+
module RubyCode
|
|
15
17
|
class << self
|
|
16
18
|
attr_accessor :configuration
|
|
17
19
|
end
|
data/rubycode_cli.rb
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
require_relative "lib/rubycode"
|
|
5
5
|
require "readline"
|
|
6
6
|
|
|
7
|
-
puts "\n"
|
|
7
|
+
puts "\n#{"=" * 80}"
|
|
8
8
|
puts "š RubyCode - AI Ruby/Rails Code Assistant"
|
|
9
9
|
puts "=" * 80
|
|
10
10
|
|
|
@@ -26,27 +26,26 @@ puts "\nš Working directory: #{full_path}"
|
|
|
26
26
|
# Ask if debug mode should be enabled
|
|
27
27
|
print "Enable debug mode? (shows JSON requests/responses) [y/N]: "
|
|
28
28
|
debug_input = gets.chomp.downcase
|
|
29
|
-
debug_mode =
|
|
29
|
+
debug_mode = %w[y yes].include?(debug_input)
|
|
30
30
|
|
|
31
31
|
# Configure the client
|
|
32
|
-
|
|
32
|
+
RubyCode.configure do |config|
|
|
33
33
|
config.adapter = :ollama
|
|
34
34
|
config.url = "http://localhost:11434"
|
|
35
35
|
config.model = "deepseek-v3.1:671b-cloud"
|
|
36
36
|
config.root_path = full_path
|
|
37
37
|
config.debug = debug_mode
|
|
38
38
|
|
|
39
|
-
#
|
|
40
|
-
|
|
41
|
-
config.enable_tool_injection_workaround = false
|
|
39
|
+
# Enable workaround to force tool-calling for models that don't follow instructions
|
|
40
|
+
config.enable_tool_injection_workaround = true
|
|
42
41
|
end
|
|
43
42
|
|
|
44
|
-
puts "š Debug mode: #{debug_mode ?
|
|
43
|
+
puts "š Debug mode: #{debug_mode ? "ON" : "OFF"}" if debug_mode
|
|
45
44
|
|
|
46
45
|
# Create a client
|
|
47
|
-
client =
|
|
46
|
+
client = RubyCode::Client.new
|
|
48
47
|
|
|
49
|
-
puts "\n"
|
|
48
|
+
puts "\n#{"=" * 80}"
|
|
50
49
|
puts "⨠Agent initialized! You can now ask questions or request code changes."
|
|
51
50
|
puts " Type 'exit' or 'quit' to exit, 'clear' to clear history"
|
|
52
51
|
puts "=" * 80
|
|
@@ -61,16 +60,16 @@ loop do
|
|
|
61
60
|
|
|
62
61
|
# Handle commands
|
|
63
62
|
case prompt.strip.downcase
|
|
64
|
-
when
|
|
63
|
+
when "exit", "quit"
|
|
65
64
|
puts "\nš Goodbye!"
|
|
66
65
|
break
|
|
67
|
-
when
|
|
66
|
+
when "clear"
|
|
68
67
|
client.clear_history
|
|
69
68
|
puts "\nšļø History cleared!"
|
|
70
69
|
next
|
|
71
70
|
end
|
|
72
71
|
|
|
73
|
-
puts "\n"
|
|
72
|
+
puts "\n#{"-" * 80}"
|
|
74
73
|
|
|
75
74
|
begin
|
|
76
75
|
# Get response from agent
|
|
@@ -82,7 +81,7 @@ loop do
|
|
|
82
81
|
puts "-" * 80
|
|
83
82
|
rescue Interrupt
|
|
84
83
|
puts "\n\nā ļø Interrupted! Type 'exit' to quit or continue chatting."
|
|
85
|
-
rescue => e
|
|
84
|
+
rescue StandardError => e
|
|
86
85
|
puts "\nā Error: #{e.message}"
|
|
87
86
|
puts e.backtrace.first(3).join("\n")
|
|
88
87
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubycode
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jonas Medeiros
|
|
@@ -22,27 +22,39 @@ files:
|
|
|
22
22
|
- README.md
|
|
23
23
|
- Rakefile
|
|
24
24
|
- USAGE.md
|
|
25
|
+
- config/tools/bash.json
|
|
26
|
+
- config/tools/done.json
|
|
27
|
+
- config/tools/read.json
|
|
28
|
+
- config/tools/search.json
|
|
25
29
|
- lib/rubycode.rb
|
|
26
30
|
- lib/rubycode/adapters/base.rb
|
|
27
31
|
- lib/rubycode/adapters/ollama.rb
|
|
32
|
+
- lib/rubycode/agent_loop.rb
|
|
28
33
|
- lib/rubycode/client.rb
|
|
34
|
+
- lib/rubycode/client/display_formatter.rb
|
|
35
|
+
- lib/rubycode/client/response_handler.rb
|
|
29
36
|
- lib/rubycode/configuration.rb
|
|
30
37
|
- lib/rubycode/context_builder.rb
|
|
38
|
+
- lib/rubycode/errors.rb
|
|
31
39
|
- lib/rubycode/history.rb
|
|
32
40
|
- lib/rubycode/tools.rb
|
|
41
|
+
- lib/rubycode/tools/base.rb
|
|
33
42
|
- lib/rubycode/tools/bash.rb
|
|
34
43
|
- lib/rubycode/tools/done.rb
|
|
35
44
|
- lib/rubycode/tools/read.rb
|
|
36
45
|
- lib/rubycode/tools/search.rb
|
|
46
|
+
- lib/rubycode/value_objects.rb
|
|
37
47
|
- lib/rubycode/version.rb
|
|
38
|
-
- rubycode-0.1.0.gem
|
|
39
48
|
- rubycode_cli.rb
|
|
40
49
|
- sig/rubycode.rbs
|
|
41
|
-
homepage: https://
|
|
50
|
+
homepage: https://github.com/jonasmedeiros/rubycode
|
|
42
51
|
licenses:
|
|
43
52
|
- MIT
|
|
44
53
|
metadata:
|
|
45
|
-
homepage_uri: https://
|
|
54
|
+
homepage_uri: https://github.com/jonasmedeiros/rubycode
|
|
55
|
+
source_code_uri: https://github.com/jonasmedeiros/rubycode
|
|
56
|
+
bug_tracker_uri: https://github.com/jonasmedeiros/rubycode/issues
|
|
57
|
+
rubygems_mfa_required: 'true'
|
|
46
58
|
rdoc_options: []
|
|
47
59
|
require_paths:
|
|
48
60
|
- lib
|
data/rubycode-0.1.0.gem
DELETED
|
Binary file
|