ruby-ai-gem-context 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/.rspec +3 -0
- data/CHANGELOG.md +81 -0
- data/LICENSE.txt +21 -0
- data/README.md +236 -0
- data/Rakefile +59 -0
- data/lib/ruby_ai_gem_context/config_file.rb +97 -0
- data/lib/ruby_ai_gem_context/configuration.rb +61 -0
- data/lib/ruby_ai_gem_context/file_collector.rb +110 -0
- data/lib/ruby_ai_gem_context/generator.rb +89 -0
- data/lib/ruby_ai_gem_context/interactive.rb +192 -0
- data/lib/ruby_ai_gem_context/platform.rb +79 -0
- data/lib/ruby_ai_gem_context/platforms/claude.rb +108 -0
- data/lib/ruby_ai_gem_context/platforms/codex.rb +130 -0
- data/lib/ruby_ai_gem_context/platforms/cursor.rb +88 -0
- data/lib/ruby_ai_gem_context/platforms/llm_txt.rb +90 -0
- data/lib/ruby_ai_gem_context/platforms/windsurf.rb +82 -0
- data/lib/ruby_ai_gem_context/railtie.rb +24 -0
- data/lib/ruby_ai_gem_context/tasks/ruby_ai_gem_context.rake +311 -0
- data/lib/ruby_ai_gem_context/version.rb +5 -0
- data/lib/ruby_ai_gem_context.rb +60 -0
- data/ruby-ai-gem-context.gemspec +41 -0
- metadata +150 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubyAiGemContext
|
|
4
|
+
module Platforms
|
|
5
|
+
class LlmTxt < Platform
|
|
6
|
+
class << self
|
|
7
|
+
def name
|
|
8
|
+
"llm.txt"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def filename
|
|
12
|
+
"llm.txt"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def description
|
|
16
|
+
"llm.txt - Universal LLM context file (like robots.txt for AI)"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def generation_prompt
|
|
20
|
+
<<~PROMPT
|
|
21
|
+
Generate an llm.txt file for this Ruby project. The llm.txt format is like robots.txt but for LLMs - it helps AI systems understand what this project is and how to use it.
|
|
22
|
+
|
|
23
|
+
Format the file as:
|
|
24
|
+
|
|
25
|
+
# Project Name
|
|
26
|
+
> Brief one-line description
|
|
27
|
+
|
|
28
|
+
## About
|
|
29
|
+
Paragraph explaining what this project does, who it's for, and why it exists.
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
The fastest way to get started with this project.
|
|
33
|
+
|
|
34
|
+
## Documentation
|
|
35
|
+
- Link to or description of where to find docs
|
|
36
|
+
- Key files to read to understand the project
|
|
37
|
+
|
|
38
|
+
## API
|
|
39
|
+
Key classes/methods and what they do.
|
|
40
|
+
|
|
41
|
+
## Examples
|
|
42
|
+
Short, practical code examples.
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
License information.
|
|
46
|
+
|
|
47
|
+
Keep it concise and scannable. This is meant to be quickly parsed by AI systems.
|
|
48
|
+
PROMPT
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def template
|
|
52
|
+
<<~TEMPLATE
|
|
53
|
+
# Project Name
|
|
54
|
+
> One-line description of the project
|
|
55
|
+
|
|
56
|
+
## About
|
|
57
|
+
Longer description of what this project does, its purpose, and target audience.
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
```bash
|
|
61
|
+
gem install project-name
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
require 'project_name'
|
|
66
|
+
# Minimal usage example
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Documentation
|
|
70
|
+
- README.md - Overview and setup
|
|
71
|
+
- lib/ - Source code
|
|
72
|
+
- spec/ - Test examples
|
|
73
|
+
|
|
74
|
+
## API
|
|
75
|
+
- `MainModule` - Entry point
|
|
76
|
+
- `MainModule.method` - Key functionality
|
|
77
|
+
|
|
78
|
+
## Examples
|
|
79
|
+
```ruby
|
|
80
|
+
# Practical example
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
MIT License - See LICENSE file
|
|
85
|
+
TEMPLATE
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubyAiGemContext
|
|
4
|
+
module Platforms
|
|
5
|
+
class Windsurf < Platform
|
|
6
|
+
class << self
|
|
7
|
+
def name
|
|
8
|
+
"Windsurf"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def filename
|
|
12
|
+
".windsurfrules"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def description
|
|
16
|
+
"Windsurf IDE - Project rules file"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def generation_prompt
|
|
20
|
+
<<~PROMPT
|
|
21
|
+
Generate a .windsurfrules file for this Ruby project. This file tells Windsurf AI how to work with this codebase.
|
|
22
|
+
|
|
23
|
+
Structure it as clear rules and guidelines:
|
|
24
|
+
|
|
25
|
+
1. Project context - What this project is
|
|
26
|
+
2. Language and framework details
|
|
27
|
+
3. Code conventions to follow
|
|
28
|
+
4. Architecture patterns
|
|
29
|
+
5. Testing requirements
|
|
30
|
+
6. Important files and their purposes
|
|
31
|
+
7. Commands for common tasks
|
|
32
|
+
8. Pitfalls and things to avoid
|
|
33
|
+
|
|
34
|
+
Write in a direct, instructional style. Focus on actionable guidance.
|
|
35
|
+
PROMPT
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def template
|
|
39
|
+
<<~TEMPLATE
|
|
40
|
+
# Project Context
|
|
41
|
+
This is a Ruby project. Describe its purpose here.
|
|
42
|
+
|
|
43
|
+
# Language & Framework
|
|
44
|
+
- Ruby 3.x
|
|
45
|
+
- Add frameworks used (Rails, Sinatra, etc.)
|
|
46
|
+
- Key gems and their purposes
|
|
47
|
+
|
|
48
|
+
# Code Conventions
|
|
49
|
+
- Follow Ruby style guide
|
|
50
|
+
- Use snake_case for methods/variables
|
|
51
|
+
- Use CamelCase for classes/modules
|
|
52
|
+
- Document public APIs with YARD
|
|
53
|
+
|
|
54
|
+
# Architecture
|
|
55
|
+
- Describe the overall structure
|
|
56
|
+
- Key patterns used
|
|
57
|
+
- How components interact
|
|
58
|
+
|
|
59
|
+
# Testing
|
|
60
|
+
- RSpec for unit tests
|
|
61
|
+
- Run with: bundle exec rspec
|
|
62
|
+
- Write tests for all new code
|
|
63
|
+
|
|
64
|
+
# Important Files
|
|
65
|
+
- lib/ - Main code
|
|
66
|
+
- spec/ - Tests
|
|
67
|
+
- Gemfile - Dependencies
|
|
68
|
+
|
|
69
|
+
# Common Commands
|
|
70
|
+
- bundle install - Install dependencies
|
|
71
|
+
- bundle exec rspec - Run tests
|
|
72
|
+
- bundle exec rubocop - Run linter
|
|
73
|
+
|
|
74
|
+
# Pitfalls
|
|
75
|
+
- Things to watch out for
|
|
76
|
+
- Common mistakes in this codebase
|
|
77
|
+
TEMPLATE
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/railtie"
|
|
4
|
+
|
|
5
|
+
module RubyAiGemContext
|
|
6
|
+
class Railtie < Rails::Railtie
|
|
7
|
+
rake_tasks do
|
|
8
|
+
load File.expand_path("tasks/ruby_ai_gem_context.rake", __dir__)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
initializer "ruby_ai_gem_context.configure" do |app|
|
|
12
|
+
# Allow Rails config to override gem configuration
|
|
13
|
+
if app.config.respond_to?(:ruby_ai_gem_context)
|
|
14
|
+
RubyAiGemContext.configure do |config|
|
|
15
|
+
rails_config = app.config.ruby_ai_gem_context
|
|
16
|
+
|
|
17
|
+
config.model = rails_config.model if rails_config.respond_to?(:model) && rails_config.model
|
|
18
|
+
config.temperature = rails_config.temperature if rails_config.respond_to?(:temperature)
|
|
19
|
+
config.max_tokens = rails_config.max_tokens if rails_config.respond_to?(:max_tokens)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :ai_context do
|
|
4
|
+
desc "Setup: Generate boilerplate context files for selected AI platforms"
|
|
5
|
+
task :setup do
|
|
6
|
+
require "ruby_ai_gem_context"
|
|
7
|
+
|
|
8
|
+
ui = RubyAiGemContext::Interactive.new
|
|
9
|
+
config_file = RubyAiGemContext::ConfigFile.new
|
|
10
|
+
|
|
11
|
+
ui.header("AI Context Setup")
|
|
12
|
+
|
|
13
|
+
# Ask which platforms to generate for
|
|
14
|
+
selected = ui.select_platforms
|
|
15
|
+
|
|
16
|
+
if selected.empty?
|
|
17
|
+
ui.warning("No platforms selected. Exiting.")
|
|
18
|
+
exit 0
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
ui.info("Selected: #{selected.map { |k| RubyAiGemContext.platform(k).name }.join(', ')}")
|
|
22
|
+
|
|
23
|
+
# Process each platform
|
|
24
|
+
selected.each do |platform_key|
|
|
25
|
+
platform = RubyAiGemContext.platform(platform_key)
|
|
26
|
+
|
|
27
|
+
if platform.exists?
|
|
28
|
+
action = ui.handle_collision(platform)
|
|
29
|
+
|
|
30
|
+
case action
|
|
31
|
+
when :skip
|
|
32
|
+
ui.info("Skipping #{platform.filename}")
|
|
33
|
+
next
|
|
34
|
+
when :backup
|
|
35
|
+
backup_path = platform.backup
|
|
36
|
+
ui.info("Backed up to #{backup_path}")
|
|
37
|
+
when :diff
|
|
38
|
+
existing = platform.read
|
|
39
|
+
action = ui.show_diff(existing, platform.template)
|
|
40
|
+
case action
|
|
41
|
+
when :skip
|
|
42
|
+
ui.info("Keeping existing #{platform.filename}")
|
|
43
|
+
next
|
|
44
|
+
when :backup
|
|
45
|
+
backup_path = platform.backup
|
|
46
|
+
ui.info("Backed up to #{backup_path}")
|
|
47
|
+
end
|
|
48
|
+
when :overwrite
|
|
49
|
+
# Continue to write
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Write the template
|
|
54
|
+
path = platform.write(platform.template)
|
|
55
|
+
config_file.record_generated(platform_key, model: "template")
|
|
56
|
+
ui.success("Created #{path}")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
puts
|
|
60
|
+
ui.info("Boilerplate files created!")
|
|
61
|
+
ui.info("Next step: Run `rake ai_context:generate` to fill them with AI-generated content")
|
|
62
|
+
ui.info("Or edit the files manually with your project's specific information")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
desc "Generate: Fill context files with AI-generated content from your project"
|
|
66
|
+
task :generate do
|
|
67
|
+
require "ruby_ai_gem_context"
|
|
68
|
+
|
|
69
|
+
ui = RubyAiGemContext::Interactive.new
|
|
70
|
+
config_file = RubyAiGemContext::ConfigFile.new
|
|
71
|
+
|
|
72
|
+
ui.header("AI Context Generation")
|
|
73
|
+
|
|
74
|
+
# Check which platforms have been set up
|
|
75
|
+
existing_platforms = config_file.generated_platforms
|
|
76
|
+
|
|
77
|
+
if existing_platforms.empty?
|
|
78
|
+
ui.warning("No context files have been set up yet.")
|
|
79
|
+
ui.info("Run `rake ai_context:setup` first to create boilerplate files.")
|
|
80
|
+
exit 0
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Ask which to regenerate
|
|
84
|
+
selected = ui.select_platforms_to_regenerate(existing_platforms)
|
|
85
|
+
|
|
86
|
+
if selected.empty?
|
|
87
|
+
ui.warning("No platforms selected. Exiting.")
|
|
88
|
+
exit 0
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Ask about source folders
|
|
92
|
+
folders = ui.select_source_folders
|
|
93
|
+
|
|
94
|
+
# Show what will be scanned
|
|
95
|
+
collector = RubyAiGemContext::FileCollector.new(Dir.pwd, folders: folders)
|
|
96
|
+
summary = collector.summary
|
|
97
|
+
|
|
98
|
+
unless ui.confirm_source_folders(folders, summary)
|
|
99
|
+
ui.info("Generation cancelled.")
|
|
100
|
+
exit 0
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Record source folders
|
|
104
|
+
config_file.record_source_folders(folders)
|
|
105
|
+
|
|
106
|
+
# Show model info
|
|
107
|
+
model = RubyAiGemContext.configuration.model
|
|
108
|
+
ui.info("Using model: #{model}")
|
|
109
|
+
ui.info("(Change in config or set RUBY_LLM_MODEL env var)")
|
|
110
|
+
puts
|
|
111
|
+
|
|
112
|
+
# Generate for each platform
|
|
113
|
+
selected.each do |platform_key|
|
|
114
|
+
platform = RubyAiGemContext.platform(platform_key)
|
|
115
|
+
|
|
116
|
+
content = ui.with_spinner("Generating #{platform.name} context...") do
|
|
117
|
+
generator = RubyAiGemContext::Generator.new(
|
|
118
|
+
platform: platform,
|
|
119
|
+
file_collector: collector,
|
|
120
|
+
model: model
|
|
121
|
+
)
|
|
122
|
+
generator.generate
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Handle existing file
|
|
126
|
+
if platform.exists?
|
|
127
|
+
action = ui.handle_collision(platform)
|
|
128
|
+
|
|
129
|
+
case action
|
|
130
|
+
when :skip
|
|
131
|
+
ui.info("Skipping #{platform.filename}")
|
|
132
|
+
next
|
|
133
|
+
when :backup
|
|
134
|
+
platform.backup
|
|
135
|
+
when :diff
|
|
136
|
+
existing = platform.read
|
|
137
|
+
action = ui.show_diff(existing, content)
|
|
138
|
+
case action
|
|
139
|
+
when :skip
|
|
140
|
+
next
|
|
141
|
+
when :backup
|
|
142
|
+
platform.backup
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
path = platform.write(content)
|
|
148
|
+
config_file.record_generated(platform_key, model: model)
|
|
149
|
+
ui.success("Generated #{path}")
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
ui.review_reminder
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
desc "Generate context for a third-party gem: rake ai_context:generate_for_gem[gem_name]"
|
|
156
|
+
task :generate_for_gem, [:gem_name] do |_t, args|
|
|
157
|
+
require "ruby_ai_gem_context"
|
|
158
|
+
|
|
159
|
+
ui = RubyAiGemContext::Interactive.new
|
|
160
|
+
|
|
161
|
+
ui.header("Generate Context for Gem")
|
|
162
|
+
|
|
163
|
+
# Get gem name
|
|
164
|
+
gem_name = args[:gem_name] || ui.ask_gem_name
|
|
165
|
+
|
|
166
|
+
# Find the gem
|
|
167
|
+
begin
|
|
168
|
+
spec = Gem::Specification.find_by_name(gem_name)
|
|
169
|
+
rescue Gem::MissingSpecError
|
|
170
|
+
ui.error("Gem '#{gem_name}' not found. Is it installed?")
|
|
171
|
+
exit 1
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
ui.info("Found: #{spec.name} v#{spec.version}")
|
|
175
|
+
ui.info("Location: #{spec.gem_dir}")
|
|
176
|
+
puts
|
|
177
|
+
|
|
178
|
+
# Ask which platforms to generate for
|
|
179
|
+
selected = ui.select_platforms
|
|
180
|
+
|
|
181
|
+
if selected.empty?
|
|
182
|
+
ui.warning("No platforms selected. Exiting.")
|
|
183
|
+
exit 0
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Collect files from the gem
|
|
187
|
+
collector = RubyAiGemContext::FileCollector.new(spec.gem_dir)
|
|
188
|
+
summary = collector.summary
|
|
189
|
+
|
|
190
|
+
ui.info("Gem has #{summary[:total_files]} files (#{format_size(summary[:total_size])})")
|
|
191
|
+
|
|
192
|
+
unless ui.prompt.yes?("Generate context for this gem?")
|
|
193
|
+
ui.info("Generation cancelled.")
|
|
194
|
+
exit 0
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Create output directory
|
|
198
|
+
output_dir = File.join(Dir.pwd, ".ai_context", "gems", gem_name)
|
|
199
|
+
FileUtils.mkdir_p(output_dir)
|
|
200
|
+
|
|
201
|
+
model = RubyAiGemContext.configuration.model
|
|
202
|
+
ui.info("Using model: #{model}")
|
|
203
|
+
puts
|
|
204
|
+
|
|
205
|
+
# Generate for each platform
|
|
206
|
+
selected.each do |platform_key|
|
|
207
|
+
platform = RubyAiGemContext.platform(platform_key)
|
|
208
|
+
|
|
209
|
+
content = ui.with_spinner("Generating #{platform.name} context for #{gem_name}...") do
|
|
210
|
+
generator = RubyAiGemContext::Generator.new(
|
|
211
|
+
platform: platform,
|
|
212
|
+
file_collector: collector,
|
|
213
|
+
model: model
|
|
214
|
+
)
|
|
215
|
+
generator.generate
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
output_path = File.join(output_dir, platform.filename)
|
|
219
|
+
File.write(output_path, content)
|
|
220
|
+
ui.success("Generated #{output_path}")
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
puts
|
|
224
|
+
ui.info("Context files saved to: #{output_dir}/")
|
|
225
|
+
ui.info("You can copy these to your project or reference them as needed.")
|
|
226
|
+
ui.review_reminder
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
desc "List generated context files"
|
|
230
|
+
task :list do
|
|
231
|
+
require "ruby_ai_gem_context"
|
|
232
|
+
|
|
233
|
+
config_file = RubyAiGemContext::ConfigFile.new
|
|
234
|
+
config = config_file.load
|
|
235
|
+
|
|
236
|
+
puts "AI Context Files"
|
|
237
|
+
puts "=" * 40
|
|
238
|
+
|
|
239
|
+
generated = config["generated"] || {}
|
|
240
|
+
|
|
241
|
+
if generated.empty?
|
|
242
|
+
puts "No context files have been generated yet."
|
|
243
|
+
puts "Run `rake ai_context:setup` to get started."
|
|
244
|
+
else
|
|
245
|
+
generated.each do |platform_key, info|
|
|
246
|
+
platform = RubyAiGemContext.platform(platform_key)
|
|
247
|
+
exists = platform.exists? ? "✓" : "✗ (missing)"
|
|
248
|
+
puts
|
|
249
|
+
puts "#{platform.name}"
|
|
250
|
+
puts " File: #{info['path']} #{exists}"
|
|
251
|
+
puts " Model: #{info['model']}"
|
|
252
|
+
puts " Generated: #{info['created_at']}"
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
if config["source_folders"]
|
|
257
|
+
puts
|
|
258
|
+
puts "Source folders: #{config['source_folders'].join(', ')}"
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
desc "Clear all generated context files"
|
|
263
|
+
task :clear do
|
|
264
|
+
require "ruby_ai_gem_context"
|
|
265
|
+
|
|
266
|
+
ui = RubyAiGemContext::Interactive.new
|
|
267
|
+
config_file = RubyAiGemContext::ConfigFile.new
|
|
268
|
+
|
|
269
|
+
platforms = config_file.generated_platforms
|
|
270
|
+
|
|
271
|
+
if platforms.empty?
|
|
272
|
+
ui.info("No context files to clear.")
|
|
273
|
+
exit 0
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
ui.warning("This will delete the following files:")
|
|
277
|
+
platforms.each do |key|
|
|
278
|
+
platform = RubyAiGemContext.platform(key)
|
|
279
|
+
puts " - #{platform.path}" if platform.exists?
|
|
280
|
+
end
|
|
281
|
+
puts
|
|
282
|
+
|
|
283
|
+
unless ui.prompt.yes?("Are you sure you want to delete these files?")
|
|
284
|
+
ui.info("Cancelled.")
|
|
285
|
+
exit 0
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
platforms.each do |key|
|
|
289
|
+
platform = RubyAiGemContext.platform(key)
|
|
290
|
+
if platform.exists?
|
|
291
|
+
File.delete(platform.full_path)
|
|
292
|
+
ui.success("Deleted #{platform.path}")
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# Clear config
|
|
297
|
+
config_dir = File.join(Dir.pwd, RubyAiGemContext.configuration.config_dir)
|
|
298
|
+
FileUtils.rm_rf(config_dir)
|
|
299
|
+
ui.success("Cleared #{config_dir}/")
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def format_size(bytes)
|
|
304
|
+
if bytes < 1024
|
|
305
|
+
"#{bytes} B"
|
|
306
|
+
elsif bytes < 1024 * 1024
|
|
307
|
+
"#{(bytes / 1024.0).round(1)} KB"
|
|
308
|
+
else
|
|
309
|
+
"#{(bytes / (1024.0 * 1024)).round(1)} MB"
|
|
310
|
+
end
|
|
311
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "yaml"
|
|
5
|
+
require "time"
|
|
6
|
+
|
|
7
|
+
require_relative "ruby_ai_gem_context/version"
|
|
8
|
+
require_relative "ruby_ai_gem_context/configuration"
|
|
9
|
+
require_relative "ruby_ai_gem_context/platform"
|
|
10
|
+
require_relative "ruby_ai_gem_context/platforms/claude"
|
|
11
|
+
require_relative "ruby_ai_gem_context/platforms/cursor"
|
|
12
|
+
require_relative "ruby_ai_gem_context/platforms/windsurf"
|
|
13
|
+
require_relative "ruby_ai_gem_context/platforms/codex"
|
|
14
|
+
require_relative "ruby_ai_gem_context/platforms/llm_txt"
|
|
15
|
+
require_relative "ruby_ai_gem_context/config_file"
|
|
16
|
+
require_relative "ruby_ai_gem_context/file_collector"
|
|
17
|
+
require_relative "ruby_ai_gem_context/generator"
|
|
18
|
+
require_relative "ruby_ai_gem_context/interactive"
|
|
19
|
+
|
|
20
|
+
module RubyAiGemContext
|
|
21
|
+
class Error < StandardError; end
|
|
22
|
+
|
|
23
|
+
# All supported platforms
|
|
24
|
+
PLATFORMS = {
|
|
25
|
+
claude: Platforms::Claude,
|
|
26
|
+
cursor: Platforms::Cursor,
|
|
27
|
+
windsurf: Platforms::Windsurf,
|
|
28
|
+
codex: Platforms::Codex,
|
|
29
|
+
llm_txt: Platforms::LlmTxt
|
|
30
|
+
}.freeze
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
attr_writer :configuration
|
|
34
|
+
|
|
35
|
+
def configuration
|
|
36
|
+
@configuration ||= Configuration.new
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def configure
|
|
40
|
+
yield(configuration)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def reset_configuration!
|
|
44
|
+
@configuration = Configuration.new
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Get platform class by key
|
|
48
|
+
def platform(key)
|
|
49
|
+
PLATFORMS[key.to_sym] || raise(Error, "Unknown platform: #{key}")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# List all platform keys
|
|
53
|
+
def platform_keys
|
|
54
|
+
PLATFORMS.keys
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Load Rails integration if Rails is defined
|
|
60
|
+
require_relative "ruby_ai_gem_context/railtie" if defined?(Rails::Railtie)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/ruby_ai_gem_context/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "ruby-ai-gem-context"
|
|
7
|
+
spec.version = RubyAiGemContext::VERSION
|
|
8
|
+
spec.authors = ["Your Name"]
|
|
9
|
+
spec.email = ["your.email@example.com"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "Generate AI context files for Ruby projects"
|
|
12
|
+
spec.description = "Interactive rake tasks to generate context files for AI coding assistants " \
|
|
13
|
+
"(Claude, Cursor, Windsurf, Codex, llm.txt). Uses RubyLLM to analyze your " \
|
|
14
|
+
"codebase and create platform-specific context that helps AI understand your project."
|
|
15
|
+
spec.homepage = "https://github.com/AAlvAAro/ruby-ai-gem-context"
|
|
16
|
+
spec.license = "MIT"
|
|
17
|
+
spec.required_ruby_version = ">= 3.0.0"
|
|
18
|
+
|
|
19
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
20
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
|
21
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
22
|
+
|
|
23
|
+
spec.files = Dir.chdir(__dir__) do
|
|
24
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
25
|
+
(File.expand_path(f) == __FILE__) ||
|
|
26
|
+
f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
spec.bindir = "exe"
|
|
30
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
31
|
+
spec.require_paths = ["lib"]
|
|
32
|
+
|
|
33
|
+
# Core dependencies
|
|
34
|
+
spec.add_dependency "ruby_llm", ">= 1.0" # AI generation via multiple providers
|
|
35
|
+
spec.add_dependency "tty-prompt", "~> 0.23" # Interactive terminal prompts
|
|
36
|
+
spec.add_dependency "tty-spinner", "~> 0.9" # Progress spinners
|
|
37
|
+
|
|
38
|
+
spec.add_development_dependency "bundler", ">= 2.0"
|
|
39
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
40
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
|
41
|
+
end
|