shared_tools 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/CHANGELOG.md +9 -0
- data/LICENSE +21 -0
- data/README.md +112 -0
- data/lib/shared_tools/core.rb +87 -0
- data/lib/shared_tools/ruby_llm/edit_file.rb +69 -0
- data/lib/shared_tools/ruby_llm/list_files.rb +47 -0
- data/lib/shared_tools/ruby_llm/pdf_page_reader.rb +58 -0
- data/lib/shared_tools/ruby_llm/read_file.rb +38 -0
- data/lib/shared_tools/ruby_llm/run_shell_command.rb +49 -0
- data/lib/shared_tools/ruby_llm.rb +10 -0
- data/lib/shared_tools/version.rb +5 -0
- data/lib/shared_tools.rb +46 -0
- metadata +140 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8ae3eef4f29e12a8be7ff8db5eec7e156bcfa1e767d5375b2ffde66db35629ef
|
4
|
+
data.tar.gz: 6f73bca50589be410d134eb2c02be5451bed2f875dea5854984181ff9f37fc44
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 42a193b5df012a25909c94a28d60e1d66347683d32bc29979a578e4fbf705738c02053625c45828c7029fe2473fa8cf40ca2e83a67ed29599ac10ab4436f2d4c
|
7
|
+
data.tar.gz: 57bb4e3b32137687b81257adf786d684fc1bb521a8d661fb23ea057047c64ae78e1f2af0f2273199093d1194d8553276bbba3302f76d3942677b7c24a78dfcd7
|
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Dewayne VanHoozer
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# shared_tools
|
2
|
+
A Ruby gem providing a collection of shared tools and utilities for Ruby applications, including configurable logging and AI-related tools.
|
3
|
+
|
4
|
+
## Libraries Supported
|
5
|
+
|
6
|
+
- ruby_llm: multi-provider
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'shared_tools'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
```bash
|
19
|
+
bundle install
|
20
|
+
```
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
```bash
|
25
|
+
gem install shared_tools
|
26
|
+
```
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
# To load all tools for a specific library
|
32
|
+
require 'shared_tools/ruby_llm'
|
33
|
+
|
34
|
+
# OR you can load a specific tool
|
35
|
+
require 'shared_tools/ruby_llm/edit_file'
|
36
|
+
```
|
37
|
+
|
38
|
+
## Shared Logging
|
39
|
+
|
40
|
+
All classes within the SharedTools namespace automatically have access to a configurable logger without requiring any explicit includes or setup.
|
41
|
+
|
42
|
+
### Basic Usage
|
43
|
+
|
44
|
+
Within any class in the SharedTools namespace, you can directly use the logger:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
module SharedTools
|
48
|
+
class MyTool
|
49
|
+
def perform_action
|
50
|
+
logger.info "Starting action"
|
51
|
+
# Do something
|
52
|
+
logger.debug "Details about action"
|
53
|
+
# Handle errors
|
54
|
+
rescue => e
|
55
|
+
logger.error "Action failed: #{e.message}"
|
56
|
+
raise
|
57
|
+
ensure
|
58
|
+
logger.info "Action completed"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
### Configuration
|
65
|
+
|
66
|
+
The logger can be configured using the `configure_logger` method:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
# Configure the logger in your application initialization
|
70
|
+
SharedTools.configure_logger do |config|
|
71
|
+
config.level = Logger::DEBUG # Set log level
|
72
|
+
config.log_device = "logs/shared_tools.log" # Set output file
|
73
|
+
config.formatter = proc do |severity, time, progname, msg|
|
74
|
+
"[#{time.strftime('%Y-%m-%d %H:%M:%S')}] #{severity}: #{msg}\n"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
### Using with Rails
|
80
|
+
|
81
|
+
To use the SharedTools logger with Rails and make it use the same logger instance:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
# In config/initializers/shared_tools.rb
|
85
|
+
Rails.application.config.after_initialize do
|
86
|
+
# Make SharedTools use the Rails logger
|
87
|
+
SharedTools.logger = Rails.logger
|
88
|
+
|
89
|
+
# Alternatively, configure the Rails logger to use SharedTools settings
|
90
|
+
# SharedTools.configure_logger do |config|
|
91
|
+
# config.level = Rails.logger.level
|
92
|
+
# config.log_device = Rails.logger.instance_variable_get(:@logdev).dev
|
93
|
+
# end
|
94
|
+
# Rails.logger = SharedTools.logger
|
95
|
+
|
96
|
+
Rails.logger.info "SharedTools integrated with Rails logger"
|
97
|
+
end
|
98
|
+
```
|
99
|
+
|
100
|
+
### Available Log Levels
|
101
|
+
|
102
|
+
The logger supports the standard Ruby Logger levels:
|
103
|
+
|
104
|
+
- `logger.debug` - Detailed debug information
|
105
|
+
- `logger.info` - General information messages
|
106
|
+
- `logger.warn` - Warning messages
|
107
|
+
- `logger.error` - Error messages
|
108
|
+
- `logger.fatal` - Fatal error messages
|
109
|
+
|
110
|
+
### Thread Safety
|
111
|
+
|
112
|
+
The shared logger is thread-safe and can be used across multiple threads in your application.
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
require "singleton"
|
5
|
+
|
6
|
+
module SharedTools
|
7
|
+
DEFAULT_LOG_LEVEL = Logger::INFO
|
8
|
+
|
9
|
+
module InstanceMethods
|
10
|
+
# @return [Logger] The shared logger instance
|
11
|
+
def logger
|
12
|
+
SharedTools.logger
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
# @return [Logger] The shared logger instance
|
18
|
+
def logger
|
19
|
+
SharedTools.logger
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
class LoggerConfiguration
|
25
|
+
include Singleton
|
26
|
+
|
27
|
+
attr_accessor :level, :log_device, :formatter
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@level = DEFAULT_LOG_LEVEL
|
31
|
+
@log_device = STDOUT
|
32
|
+
@formatter = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def apply_to(logger)
|
37
|
+
logger.level = @level
|
38
|
+
logger.formatter = @formatter if @formatter
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
class << self
|
44
|
+
# @return [Logger] The configured logger instance
|
45
|
+
def logger
|
46
|
+
@logger ||= create_logger
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param new_logger [Logger] A Logger instance to use
|
50
|
+
def logger=(new_logger)
|
51
|
+
@logger = new_logger
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# @example
|
56
|
+
# SharedTools.configure_logger do |config|
|
57
|
+
# config.level = Logger::DEBUG
|
58
|
+
# config.log_device = 'logs/application.log'
|
59
|
+
# config.formatter = proc { |severity, time, progname, msg| "[#{time}] #{severity} - #{msg}\n" }
|
60
|
+
# end
|
61
|
+
def configure_logger
|
62
|
+
yield LoggerConfiguration.instance
|
63
|
+
|
64
|
+
|
65
|
+
if @logger
|
66
|
+
@logger = create_logger
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# @return [Logger] A newly configured logger
|
73
|
+
def create_logger
|
74
|
+
config = LoggerConfiguration.instance
|
75
|
+
logger = Logger.new(config.log_device)
|
76
|
+
config.apply_to(logger)
|
77
|
+
logger
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
# module LoggingSupport
|
83
|
+
# def self.included(base)
|
84
|
+
# base.include(SharedTools)
|
85
|
+
# end
|
86
|
+
# end
|
87
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require("ruby_llm") unless defined?(RubyLLM)
|
4
|
+
require("shared_tools") unless defined?(SharedTools)
|
5
|
+
|
6
|
+
module SharedTools
|
7
|
+
class EditFile < RubyLLM::Tool
|
8
|
+
|
9
|
+
description <<~DESCRIPTION
|
10
|
+
Make edits to a text file.
|
11
|
+
|
12
|
+
Replaces 'old_str' with 'new_str' in the given file.
|
13
|
+
'old_str' and 'new_str' MUST be different from each other.
|
14
|
+
|
15
|
+
If the file specified with path doesn't exist, it will be created.
|
16
|
+
|
17
|
+
By default, only the first occurrence will be replaced. Set replace_all to true to replace all occurrences.
|
18
|
+
DESCRIPTION
|
19
|
+
param :path, desc: "The path to the file"
|
20
|
+
param :old_str, desc: "Text to search for - must match exactly"
|
21
|
+
param :new_str, desc: "Text to replace old_str with"
|
22
|
+
param :replace_all, desc: "Whether to replace all occurrences (true) or just the first one (false)", required: false
|
23
|
+
|
24
|
+
def execute(path:, old_str:, new_str:, replace_all: false)
|
25
|
+
logger.info("Editing file: #{path}")
|
26
|
+
|
27
|
+
# Normalize path to absolute path
|
28
|
+
absolute_path = File.absolute_path(path)
|
29
|
+
|
30
|
+
if File.exist?(absolute_path)
|
31
|
+
logger.debug("File exists, reading content")
|
32
|
+
content = File.read(absolute_path)
|
33
|
+
else
|
34
|
+
logger.debug("File doesn't exist, creating new file")
|
35
|
+
content = ""
|
36
|
+
end
|
37
|
+
|
38
|
+
matches = content.scan(old_str).size
|
39
|
+
logger.debug("Found #{matches} matches for the string to replace")
|
40
|
+
|
41
|
+
if matches == 0
|
42
|
+
logger.warn("No matches found for the string to replace. File will remain unchanged.")
|
43
|
+
return { success: false, warning: "No matches found for the string to replace" }
|
44
|
+
end
|
45
|
+
|
46
|
+
if matches > 1 && !replace_all
|
47
|
+
logger.warn("Multiple matches (#{matches}) found for the string to replace. Only the first occurrence will be replaced.")
|
48
|
+
end
|
49
|
+
|
50
|
+
if replace_all
|
51
|
+
updated_content = content.gsub(old_str, new_str)
|
52
|
+
replaced_count = matches
|
53
|
+
logger.info("Replacing all #{matches} occurrences")
|
54
|
+
else
|
55
|
+
updated_content = content.sub(old_str, new_str)
|
56
|
+
replaced_count = 1
|
57
|
+
logger.info("Replacing first occurrence only")
|
58
|
+
end
|
59
|
+
|
60
|
+
File.write(absolute_path, updated_content)
|
61
|
+
|
62
|
+
logger.info("Successfully updated file: #{path}")
|
63
|
+
{ success: true, matches: matches, replaced: replaced_count }
|
64
|
+
rescue => e
|
65
|
+
logger.error("Failed to edit file '#{path}': #{e.message}")
|
66
|
+
{ error: e.message }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require("ruby_llm") unless defined?(RubyLLM)
|
4
|
+
require("shared_tools") unless defined?(SharedTools)
|
5
|
+
|
6
|
+
module SharedTools
|
7
|
+
class ListFiles < RubyLLM::Tool
|
8
|
+
|
9
|
+
description "List files and directories at a given path. If no path is provided, lists files in the current directory."
|
10
|
+
param :path, desc: "Optional relative path to list files from. Defaults to current directory if not provided."
|
11
|
+
|
12
|
+
def execute(path: Dir.pwd)
|
13
|
+
logger.info("Listing files in path: #{path}")
|
14
|
+
|
15
|
+
# Convert to absolute path for consistency
|
16
|
+
absolute_path = File.absolute_path(path)
|
17
|
+
|
18
|
+
# Verify the path exists and is a directory
|
19
|
+
unless File.directory?(absolute_path)
|
20
|
+
error_msg = "Path does not exist or is not a directory: #{path}"
|
21
|
+
logger.error(error_msg)
|
22
|
+
return { error: error_msg }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Get all files including hidden ones
|
26
|
+
visible_files = Dir.glob(File.join(absolute_path, "*"))
|
27
|
+
hidden_files = Dir.glob(File.join(absolute_path, ".*"))
|
28
|
+
.reject { |f| f.end_with?("/.") || f.end_with?("/..") }
|
29
|
+
|
30
|
+
# Combine and format results
|
31
|
+
all_files = (visible_files + hidden_files).sort
|
32
|
+
formatted_files = all_files.map do |filename|
|
33
|
+
if File.directory?(filename)
|
34
|
+
"#{filename}/"
|
35
|
+
else
|
36
|
+
filename
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
logger.debug("Found #{formatted_files.size} files/directories (including #{hidden_files.size} hidden)")
|
41
|
+
formatted_files
|
42
|
+
rescue => e
|
43
|
+
logger.error("Failed to list files in '#{path}': #{e.message}")
|
44
|
+
{ error: e.message }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Credit: https://max.engineer/giant-pdf-llm
|
3
|
+
|
4
|
+
require "pdf-reader"
|
5
|
+
|
6
|
+
require("ruby_llm") unless defined?(RubyLLM)
|
7
|
+
require("shared_tools") unless defined?(SharedTools)
|
8
|
+
|
9
|
+
module SharedTools
|
10
|
+
class PdfPageReader < RubyLLM::Tool
|
11
|
+
|
12
|
+
description "Read the text of any set of pages from a PDF document."
|
13
|
+
param :page_numbers,
|
14
|
+
desc: 'Comma-separated page numbers (first page: 1). (e.g. "12, 14, 15")'
|
15
|
+
param :doc_path,
|
16
|
+
desc: "Path to the PDF document."
|
17
|
+
|
18
|
+
def execute(page_numbers:, doc_path:)
|
19
|
+
logger.info("Reading PDF: #{doc_path}, pages: #{page_numbers}")
|
20
|
+
|
21
|
+
begin
|
22
|
+
@doc ||= PDF::Reader.new(doc_path)
|
23
|
+
logger.debug("PDF loaded successfully, total pages: #{@doc.pages.size}")
|
24
|
+
|
25
|
+
page_numbers = page_numbers.split(",").map { |num| num.strip.to_i }
|
26
|
+
logger.debug("Processing pages: #{page_numbers.join(", ")}")
|
27
|
+
|
28
|
+
# Validate page numbers
|
29
|
+
total_pages = @doc.pages.size
|
30
|
+
invalid_pages = page_numbers.select { |num| num < 1 || num > total_pages }
|
31
|
+
|
32
|
+
if invalid_pages.any?
|
33
|
+
logger.warn("Invalid page numbers requested: #{invalid_pages.join(", ")}. Document has #{total_pages} pages.")
|
34
|
+
end
|
35
|
+
|
36
|
+
# Filter valid pages and map to content
|
37
|
+
valid_pages = page_numbers.select { |num| num >= 1 && num <= total_pages }
|
38
|
+
pages = valid_pages.map { |num| [num, @doc.pages[num.to_i - 1]] }
|
39
|
+
|
40
|
+
result = {
|
41
|
+
total_pages: total_pages,
|
42
|
+
requested_pages: page_numbers,
|
43
|
+
invalid_pages: invalid_pages,
|
44
|
+
pages: pages.map { |num, p|
|
45
|
+
logger.debug("Extracted text from page #{num} (#{p&.text&.bytesize || 0} bytes)")
|
46
|
+
{ page: num, text: p&.text }
|
47
|
+
},
|
48
|
+
}
|
49
|
+
|
50
|
+
logger.info("Successfully extracted #{pages.size} pages from PDF")
|
51
|
+
result
|
52
|
+
rescue => e
|
53
|
+
logger.error("Failed to read PDF '#{doc_path}': #{e.message}")
|
54
|
+
{ error: e.message }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require("ruby_llm") unless defined?(RubyLLM)
|
4
|
+
require("shared_tools") unless defined?(SharedTools)
|
5
|
+
|
6
|
+
module SharedTools
|
7
|
+
class ReadFile < RubyLLM::Tool
|
8
|
+
|
9
|
+
description "Read the contents of a given relative file path. Use this when you want to see what's inside a file. Do not use this with directory names."
|
10
|
+
param :path, desc: "The relative path of a file in the working directory."
|
11
|
+
|
12
|
+
def execute(path:)
|
13
|
+
logger.info("Reading file: #{path}")
|
14
|
+
|
15
|
+
# Handle both relative and absolute paths consistently
|
16
|
+
absolute_path = File.absolute_path(path)
|
17
|
+
|
18
|
+
if File.directory?(absolute_path)
|
19
|
+
error_msg = "Path is a directory, not a file: #{path}"
|
20
|
+
logger.error(error_msg)
|
21
|
+
return { error: error_msg }
|
22
|
+
end
|
23
|
+
|
24
|
+
unless File.exist?(absolute_path)
|
25
|
+
error_msg = "File does not exist: #{path}"
|
26
|
+
logger.error(error_msg)
|
27
|
+
return { error: error_msg }
|
28
|
+
end
|
29
|
+
|
30
|
+
content = File.read(absolute_path)
|
31
|
+
logger.debug("Successfully read #{content.bytesize} bytes from #{path}")
|
32
|
+
content
|
33
|
+
rescue => e
|
34
|
+
logger.error("Failed to read file '#{path}': #{e.message}")
|
35
|
+
{ error: e.message }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require("ruby_llm") unless defined?(RubyLLM)
|
4
|
+
require("shared_tools") unless defined?(SharedTools)
|
5
|
+
|
6
|
+
module SharedTools
|
7
|
+
class RunShellCommand < RubyLLM::Tool
|
8
|
+
|
9
|
+
description "Execute a shell command"
|
10
|
+
param :command, desc: "The command to execute"
|
11
|
+
|
12
|
+
def execute(command:)
|
13
|
+
logger.info("Requesting permission to execute command: '#{command}'")
|
14
|
+
|
15
|
+
if command.strip.empty?
|
16
|
+
error_msg = "Command cannot be empty"
|
17
|
+
logger.error(error_msg)
|
18
|
+
return { error: error_msg }
|
19
|
+
end
|
20
|
+
|
21
|
+
# Show user the command and ask for confirmation
|
22
|
+
puts "AI wants to execute the following shell command: '#{command}'"
|
23
|
+
print "Do you want to execute it? (y/n) "
|
24
|
+
response = gets.chomp.downcase
|
25
|
+
|
26
|
+
unless response == "y"
|
27
|
+
logger.warn("User declined to execute the command: '#{command}'")
|
28
|
+
return { error: "User declined to execute the command" }
|
29
|
+
end
|
30
|
+
|
31
|
+
logger.info("Executing command: '#{command}'")
|
32
|
+
|
33
|
+
# Use Open3 for safer command execution with proper error handling
|
34
|
+
require "open3"
|
35
|
+
stdout, stderr, status = Open3.capture3(command)
|
36
|
+
|
37
|
+
if status.success?
|
38
|
+
logger.debug("Command execution completed successfully with #{stdout.bytesize} bytes of output")
|
39
|
+
{ stdout: stdout, exit_status: status.exitstatus }
|
40
|
+
else
|
41
|
+
logger.warn("Command execution failed with exit code #{status.exitstatus}: #{stderr}")
|
42
|
+
{ error: "Command failed with exit code #{status.exitstatus}", stderr: stderr, exit_status: status.exitstatus }
|
43
|
+
end
|
44
|
+
rescue => e
|
45
|
+
logger.error("Command execution failed: #{e.message}")
|
46
|
+
{ error: e.message }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require("ruby_llm") unless defined?(RubyLLM)
|
4
|
+
require("shared_tools") unless defined?(SharedTools)
|
5
|
+
|
6
|
+
require_relative "ruby_llm/edit_file"
|
7
|
+
require_relative "ruby_llm/list_files"
|
8
|
+
require_relative "ruby_llm/pdf_page_reader"
|
9
|
+
require_relative "ruby_llm/read_file"
|
10
|
+
require_relative "ruby_llm/run_shell_command"
|
data/lib/shared_tools.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shared_tools/version"
|
4
|
+
|
5
|
+
module SharedTools
|
6
|
+
class << self
|
7
|
+
# def included(base)
|
8
|
+
# base.extend(ClassMethods)
|
9
|
+
|
10
|
+
# if base.is_a?(Class)
|
11
|
+
# base.class_eval do
|
12
|
+
# include InstanceMethods
|
13
|
+
# end
|
14
|
+
# else
|
15
|
+
# base.module_eval do
|
16
|
+
# def self.included(sub_base)
|
17
|
+
# sub_base.include(SharedTools)
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
|
23
|
+
# def extended(object)
|
24
|
+
# object.extend(ClassMethods)
|
25
|
+
# end
|
26
|
+
|
27
|
+
# Hook to automatically inject logger into RubyLLM::Tool subclasses
|
28
|
+
def const_added(const_name)
|
29
|
+
const = const_get(const_name)
|
30
|
+
|
31
|
+
if const.is_a?(Class) && defined?(RubyLLM::Tool) && const < RubyLLM::Tool
|
32
|
+
const.class_eval do
|
33
|
+
def logger
|
34
|
+
SharedTools.logger
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.logger
|
38
|
+
SharedTools.logger
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
require "shared_tools/core"
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shared_tools
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- MadBomber Team
|
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: logger
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '1.0'
|
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'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: pdf-reader
|
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: ruby_llm
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
type: :development
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: bundler
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '2.0'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '2.0'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: rake
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '13.0'
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '13.0'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: rspec
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '3.0'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '3.0'
|
96
|
+
description: SharedTools provides common functionality including configurable logging
|
97
|
+
and LLM tools
|
98
|
+
email:
|
99
|
+
- example@example.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- CHANGELOG.md
|
105
|
+
- LICENSE
|
106
|
+
- README.md
|
107
|
+
- lib/shared_tools.rb
|
108
|
+
- lib/shared_tools/core.rb
|
109
|
+
- lib/shared_tools/ruby_llm.rb
|
110
|
+
- lib/shared_tools/ruby_llm/edit_file.rb
|
111
|
+
- lib/shared_tools/ruby_llm/list_files.rb
|
112
|
+
- lib/shared_tools/ruby_llm/pdf_page_reader.rb
|
113
|
+
- lib/shared_tools/ruby_llm/read_file.rb
|
114
|
+
- lib/shared_tools/ruby_llm/run_shell_command.rb
|
115
|
+
- lib/shared_tools/version.rb
|
116
|
+
homepage: https://github.com/madbomber/shared_tools
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata:
|
120
|
+
homepage_uri: https://github.com/madbomber/shared_tools
|
121
|
+
source_code_uri: https://github.com/madbomber/shared_tools
|
122
|
+
changelog_uri: https://github.com/madbomber/shared_tools/blob/main/CHANGELOG.md
|
123
|
+
rdoc_options: []
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 2.7.0
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubygems_version: 3.6.9
|
138
|
+
specification_version: 4
|
139
|
+
summary: A collection of shared tools and utilities for Ruby applications
|
140
|
+
test_files: []
|