rails-ai-context 4.3.2 → 4.3.3
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/CHANGELOG.md +72 -53
- data/CLAUDE.md +1 -1
- data/README.md +268 -197
- data/demo-trace.gif +0 -0
- data/demo-trace.tape +21 -0
- data/demo.gif +0 -0
- data/demo.tape +33 -0
- data/docs/GUIDE.md +9 -9
- data/lib/generators/rails_ai_context/install/install_generator.rb +2 -1
- data/lib/rails_ai_context/configuration.rb +1 -1
- data/lib/rails_ai_context/doctor.rb +4 -2
- data/lib/rails_ai_context/fingerprinter.rb +2 -1
- data/lib/rails_ai_context/introspectors/accessibility_introspector.rb +2 -1
- data/lib/rails_ai_context/introspectors/action_mailbox_introspector.rb +2 -1
- data/lib/rails_ai_context/introspectors/action_text_introspector.rb +2 -1
- data/lib/rails_ai_context/introspectors/active_storage_introspector.rb +6 -3
- data/lib/rails_ai_context/introspectors/api_introspector.rb +8 -4
- data/lib/rails_ai_context/introspectors/asset_pipeline_introspector.rb +6 -3
- data/lib/rails_ai_context/introspectors/auth_introspector.rb +14 -7
- data/lib/rails_ai_context/introspectors/config_introspector.rb +12 -6
- data/lib/rails_ai_context/introspectors/controller_introspector.rb +20 -10
- data/lib/rails_ai_context/introspectors/convention_detector.rb +2 -1
- data/lib/rails_ai_context/introspectors/design_token_introspector.rb +8 -4
- data/lib/rails_ai_context/introspectors/devops_introspector.rb +6 -3
- data/lib/rails_ai_context/introspectors/engine_introspector.rb +4 -2
- data/lib/rails_ai_context/introspectors/frontend_framework_introspector.rb +2 -1
- data/lib/rails_ai_context/introspectors/i18n_introspector.rb +2 -1
- data/lib/rails_ai_context/introspectors/job_introspector.rb +8 -4
- data/lib/rails_ai_context/introspectors/middleware_introspector.rb +4 -2
- data/lib/rails_ai_context/introspectors/migration_introspector.rb +2 -1
- data/lib/rails_ai_context/introspectors/model_introspector.rb +20 -10
- data/lib/rails_ai_context/introspectors/multi_database_introspector.rb +12 -6
- data/lib/rails_ai_context/introspectors/performance_introspector.rb +6 -3
- data/lib/rails_ai_context/introspectors/route_introspector.rb +4 -2
- data/lib/rails_ai_context/introspectors/schema_introspector.rb +14 -7
- data/lib/rails_ai_context/introspectors/seeds_introspector.rb +2 -1
- data/lib/rails_ai_context/introspectors/stimulus_introspector.rb +8 -4
- data/lib/rails_ai_context/introspectors/test_introspector.rb +8 -4
- data/lib/rails_ai_context/introspectors/turbo_introspector.rb +22 -11
- data/lib/rails_ai_context/introspectors/view_introspector.rb +8 -4
- data/lib/rails_ai_context/introspectors/view_template_introspector.rb +10 -5
- data/lib/rails_ai_context/tasks/rails_ai_context.rake +8 -4
- data/lib/rails_ai_context/tools/analyze_feature.rb +66 -19
- data/lib/rails_ai_context/tools/diagnose.rb +4 -2
- data/lib/rails_ai_context/tools/get_callbacks.rb +4 -2
- data/lib/rails_ai_context/tools/get_concern.rb +12 -6
- data/lib/rails_ai_context/tools/get_controllers.rb +10 -5
- data/lib/rails_ai_context/tools/get_conventions.rb +4 -2
- data/lib/rails_ai_context/tools/get_design_system.rb +2 -1
- data/lib/rails_ai_context/tools/get_env.rb +8 -4
- data/lib/rails_ai_context/tools/get_helper_methods.rb +6 -3
- data/lib/rails_ai_context/tools/get_job_pattern.rb +2 -1
- data/lib/rails_ai_context/tools/get_model_details.rb +10 -5
- data/lib/rails_ai_context/tools/get_partial_interface.rb +14 -7
- data/lib/rails_ai_context/tools/get_schema.rb +2 -1
- data/lib/rails_ai_context/tools/get_service_pattern.rb +2 -1
- data/lib/rails_ai_context/tools/get_stimulus.rb +2 -1
- data/lib/rails_ai_context/tools/get_test_info.rb +4 -2
- data/lib/rails_ai_context/tools/get_turbo_map.rb +22 -11
- data/lib/rails_ai_context/tools/get_view.rb +6 -3
- data/lib/rails_ai_context/tools/migration_advisor.rb +2 -1
- data/lib/rails_ai_context/tools/onboard.rb +2 -1
- data/lib/rails_ai_context/tools/performance_check.rb +2 -1
- data/lib/rails_ai_context/tools/runtime_info.rb +10 -5
- data/lib/rails_ai_context/tools/search_code.rb +8 -4
- data/lib/rails_ai_context/tools/search_docs.rb +2 -1
- data/lib/rails_ai_context/tools/session_context.rb +2 -1
- data/lib/rails_ai_context/tools/validate.rb +16 -8
- data/lib/rails_ai_context/version.rb +1 -1
- metadata +5 -1
data/demo.tape
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# VHS demo tape for rails-ai-context install
|
|
2
|
+
Output demo.gif
|
|
3
|
+
|
|
4
|
+
Set Shell zsh
|
|
5
|
+
Set FontSize 14
|
|
6
|
+
Set Width 950
|
|
7
|
+
Set Height 520
|
|
8
|
+
Set Padding 12
|
|
9
|
+
Set Theme "Catppuccin Mocha"
|
|
10
|
+
Set TypingSpeed 35ms
|
|
11
|
+
|
|
12
|
+
Type "cd /Users/crisjosephnahine/Documents/Projects/daily-content-chef"
|
|
13
|
+
Enter
|
|
14
|
+
Sleep 1s
|
|
15
|
+
|
|
16
|
+
Type "rails generate rails_ai_context:install"
|
|
17
|
+
Sleep 400ms
|
|
18
|
+
Enter
|
|
19
|
+
Sleep 3s
|
|
20
|
+
|
|
21
|
+
# Select Claude Code + Cursor
|
|
22
|
+
Type "1,2"
|
|
23
|
+
Sleep 300ms
|
|
24
|
+
Enter
|
|
25
|
+
Sleep 2s
|
|
26
|
+
|
|
27
|
+
# Select MCP mode (yes)
|
|
28
|
+
Type "1"
|
|
29
|
+
Sleep 300ms
|
|
30
|
+
Enter
|
|
31
|
+
Sleep 4s
|
|
32
|
+
|
|
33
|
+
Sleep 2s
|
data/docs/GUIDE.md
CHANGED
|
@@ -1128,7 +1128,7 @@ Both transports are **read-only** — they expose the same 39 tools and never mo
|
|
|
1128
1128
|
RailsAiContext.configure do |config|
|
|
1129
1129
|
# --- Introspectors ---
|
|
1130
1130
|
|
|
1131
|
-
# Presets: :full (
|
|
1131
|
+
# Presets: :full (33 introspectors, default) or :standard (19)
|
|
1132
1132
|
config.preset = :full
|
|
1133
1133
|
|
|
1134
1134
|
# Cherry-pick on top of a preset
|
|
@@ -1300,7 +1300,7 @@ All split rules include an app overview file, so no context is lost when root fi
|
|
|
1300
1300
|
|
|
1301
1301
|
## Introspectors — Full List
|
|
1302
1302
|
|
|
1303
|
-
### Standard preset (
|
|
1303
|
+
### Standard preset (19 introspectors)
|
|
1304
1304
|
|
|
1305
1305
|
Core Rails structure only. Use `config.preset = :standard` for a lighter footprint.
|
|
1306
1306
|
|
|
@@ -1320,19 +1320,21 @@ Core Rails structure only. Use `config.preset = :standard` for a lighter footpri
|
|
|
1320
1320
|
| `view_templates` | View file contents, partial references, Stimulus data attributes, UI pattern extraction, model field usage in partials. |
|
|
1321
1321
|
| `design_tokens` | Auto-detects CSS framework (Tailwind v3/v4, Bootstrap, Sass, plain CSS) and extracts design tokens from config files and built CSS. |
|
|
1322
1322
|
| `components` | ViewComponent/Phlex components: props, slots, previews, sidecar assets, usage examples. |
|
|
1323
|
+
| `turbo` | Turbo Frames (IDs and files), Turbo Stream templates, model broadcasts (`broadcasts_to`, `broadcasts`). |
|
|
1324
|
+
| `auth` | Devise models with modules, Rails 8 built-in auth, has_secure_password, Pundit policies, CanCanCan, CORS config, CSP config. |
|
|
1325
|
+
| `accessibility` | ARIA attributes, semantic HTML elements, screen reader text, alt text coverage, landmark roles, accessibility score. |
|
|
1326
|
+
| `performance` | N+1 query risks, missing counter_cache, missing FK indexes, Model.all anti-patterns, eager load candidates. |
|
|
1327
|
+
| `i18n` | Default locale, available locales, locale files with key counts, backend class, parse errors. |
|
|
1323
1328
|
|
|
1324
|
-
### Full preset (
|
|
1329
|
+
### Full preset (33 introspectors) — default
|
|
1325
1330
|
|
|
1326
1331
|
Includes all standard introspectors plus:
|
|
1327
1332
|
|
|
1328
1333
|
| Introspector | What it discovers |
|
|
1329
1334
|
|-------------|-------------------|
|
|
1330
1335
|
| `views` | Layouts, templates grouped by controller, partials (per-controller and shared), helpers with methods, template engines (erb, haml, slim), view components. |
|
|
1331
|
-
| `turbo` | Turbo Frames (IDs and files), Turbo Stream templates, model broadcasts (`broadcasts_to`, `broadcasts`). |
|
|
1332
|
-
| `i18n` | Default locale, available locales, locale files with key counts, backend class, parse errors. |
|
|
1333
1336
|
| `active_storage` | Attachments (has_one_attached, has_many_attached per model), storage services, direct upload config. |
|
|
1334
1337
|
| `action_text` | Rich text fields (has_rich_text per model), Action Text installation status. |
|
|
1335
|
-
| `auth` | Devise models with modules, Rails 8 built-in auth, has_secure_password, Pundit policies, CanCanCan, CORS config, CSP config. |
|
|
1336
1338
|
| `api` | API-only mode, API versioning (from directory structure), serializers (Jbuilder, AMS, etc.), GraphQL (types, mutations), rate limiting (Rack::Attack). |
|
|
1337
1339
|
| `rake_tasks` | Custom rake tasks in `lib/tasks/` with names, descriptions, namespaces, file paths. |
|
|
1338
1340
|
| `assets` | Asset pipeline (Propshaft/Sprockets), JS bundler (importmap/esbuild/webpack/vite), CSS framework, importmap pins, manifest files. |
|
|
@@ -1342,10 +1344,8 @@ Includes all standard introspectors plus:
|
|
|
1342
1344
|
| `middleware` | Custom Rack middleware in app/middleware/ with detected patterns (auth, rate limiting, tenant isolation, logging). Full middleware stack. |
|
|
1343
1345
|
| `engines` | Mounted Rails engines from routes.rb with paths and descriptions for 23+ known engines (Sidekiq::Web, Flipper::UI, PgHero, ActiveAdmin, etc.). |
|
|
1344
1346
|
| `multi_database` | Multiple databases, replicas, sharding config, model-specific `connects_to` declarations. database.yml parsing fallback. |
|
|
1345
|
-
| `accessibility` | ARIA attributes, semantic HTML elements, screen reader text, alt text coverage, landmark roles, accessibility score. |
|
|
1346
|
-
| `performance` | N+1 query risks, missing counter_cache, missing FK indexes, Model.all anti-patterns, eager load candidates. |
|
|
1347
1347
|
| `frontend_frameworks` | Frontend JS framework detection (React/Vue/Svelte/Angular), mounting strategy (Inertia/react-rails), TypeScript config, state management, package manager. |
|
|
1348
|
-
| `database_stats` | PostgreSQL approximate row counts via `pg_stat_user_tables`.
|
|
1348
|
+
| `database_stats` | PostgreSQL approximate row counts via `pg_stat_user_tables`. Gracefully skips on non-PostgreSQL adapters. |
|
|
1349
1349
|
|
|
1350
1350
|
### Using the standard preset
|
|
1351
1351
|
|
|
@@ -6,7 +6,7 @@ module RailsAiContext
|
|
|
6
6
|
standard: %i[schema models routes jobs gems conventions controllers tests migrations stimulus
|
|
7
7
|
view_templates design_tokens config components
|
|
8
8
|
turbo auth accessibility performance i18n],
|
|
9
|
-
full: %i[schema models routes jobs gems conventions stimulus controllers views view_templates design_tokens turbo
|
|
9
|
+
full: %i[schema models routes jobs gems conventions stimulus database_stats controllers views view_templates design_tokens turbo
|
|
10
10
|
i18n config active_storage action_text auth api tests rake_tasks assets
|
|
11
11
|
devops action_mailbox migrations seeds middleware engines multi_database
|
|
12
12
|
components accessibility performance frontend_frameworks]
|
|
@@ -84,7 +84,8 @@ module RailsAiContext
|
|
|
84
84
|
message: "#{pending.size} pending migration(s) — schema data will be stale",
|
|
85
85
|
fix: "Run `rails db:migrate`")
|
|
86
86
|
end
|
|
87
|
-
rescue
|
|
87
|
+
rescue => e
|
|
88
|
+
$stderr.puts "[rails-ai-context] check_pending_migrations failed: #{e.message}" if ENV["DEBUG"]
|
|
88
89
|
# Can't check pending migrations in this environment
|
|
89
90
|
nil
|
|
90
91
|
end
|
|
@@ -234,7 +235,8 @@ module RailsAiContext
|
|
|
234
235
|
message: "#{errors.size} introspector(s) returned errors: #{errors.join(', ')}",
|
|
235
236
|
fix: "Check if the app has the required features (e.g., stimulus needs app/javascript/controllers/)")
|
|
236
237
|
end
|
|
237
|
-
rescue
|
|
238
|
+
rescue => e
|
|
239
|
+
$stderr.puts "[rails-ai-context] check_introspector_health failed: #{e.message}" if ENV["DEBUG"]
|
|
238
240
|
nil
|
|
239
241
|
end
|
|
240
242
|
|
|
@@ -71,7 +71,8 @@ module RailsAiContext
|
|
|
71
71
|
spec = Bundler.rubygems.find_name("rails-ai-context").first
|
|
72
72
|
return false unless spec
|
|
73
73
|
spec.source.is_a?(Bundler::Source::Path)
|
|
74
|
-
rescue
|
|
74
|
+
rescue => e
|
|
75
|
+
$stderr.puts "[rails-ai-context] local_gem_path? failed: #{e.message}" if ENV["DEBUG"]
|
|
75
76
|
false
|
|
76
77
|
end
|
|
77
78
|
|
|
@@ -50,7 +50,8 @@ module RailsAiContext
|
|
|
50
50
|
Dir.glob(File.join(dir, "**/*.{erb,haml,slim,html}")).each do |path|
|
|
51
51
|
content = File.read(path, encoding: "UTF-8", invalid: :replace, undef: :replace)
|
|
52
52
|
views << { file: path.sub("#{root}/", ""), content: content }
|
|
53
|
-
rescue
|
|
53
|
+
rescue => e
|
|
54
|
+
$stderr.puts "[rails-ai-context] collect_view_content failed: #{e.message}" if ENV["DEBUG"]
|
|
54
55
|
next
|
|
55
56
|
end
|
|
56
57
|
end
|
|
@@ -47,7 +47,8 @@ module RailsAiContext
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
attachments.sort_by { |a| [ a[:model], a[:name] ] }
|
|
50
|
-
rescue
|
|
50
|
+
rescue => e
|
|
51
|
+
$stderr.puts "[rails-ai-context] extract_attachments failed: #{e.message}" if ENV["DEBUG"]
|
|
51
52
|
[]
|
|
52
53
|
end
|
|
53
54
|
|
|
@@ -58,7 +59,8 @@ module RailsAiContext
|
|
|
58
59
|
require "yaml"
|
|
59
60
|
config = YAML.load_file(config_path, permitted_classes: [ Symbol ], aliases: true) || {}
|
|
60
61
|
config.keys.sort
|
|
61
|
-
rescue
|
|
62
|
+
rescue => e
|
|
63
|
+
$stderr.puts "[rails-ai-context] extract_storage_services failed: #{e.message}" if ENV["DEBUG"]
|
|
62
64
|
[]
|
|
63
65
|
end
|
|
64
66
|
|
|
@@ -71,7 +73,8 @@ module RailsAiContext
|
|
|
71
73
|
Dir.glob(File.join(dir, "**/*")).any? do |f|
|
|
72
74
|
next false if File.directory?(f)
|
|
73
75
|
File.read(f).match?(/direct.upload|DirectUpload|direct_upload/)
|
|
74
|
-
rescue
|
|
76
|
+
rescue => e
|
|
77
|
+
$stderr.puts "[rails-ai-context] detect_direct_upload failed: #{e.message}" if ENV["DEBUG"]
|
|
75
78
|
false
|
|
76
79
|
end
|
|
77
80
|
end
|
|
@@ -85,7 +85,8 @@ module RailsAiContext
|
|
|
85
85
|
.map { |path| path.sub("#{root}/", "") }
|
|
86
86
|
.sort
|
|
87
87
|
.uniq
|
|
88
|
-
rescue
|
|
88
|
+
rescue => e
|
|
89
|
+
$stderr.puts "[rails-ai-context] detect_openapi_specs failed: #{e.message}" if ENV["DEBUG"]
|
|
89
90
|
[]
|
|
90
91
|
end
|
|
91
92
|
|
|
@@ -99,7 +100,8 @@ module RailsAiContext
|
|
|
99
100
|
end
|
|
100
101
|
|
|
101
102
|
{ file: "config/initializers/cors.rb", origins: origins }
|
|
102
|
-
rescue
|
|
103
|
+
rescue => e
|
|
104
|
+
$stderr.puts "[rails-ai-context] detect_cors_config failed: #{e.message}" if ENV["DEBUG"]
|
|
103
105
|
nil
|
|
104
106
|
end
|
|
105
107
|
|
|
@@ -111,7 +113,8 @@ module RailsAiContext
|
|
|
111
113
|
codegen_tools = %w[openapi-typescript @graphql-codegen/cli orval]
|
|
112
114
|
|
|
113
115
|
codegen_tools.select { |tool| content.include?(%("#{tool}")) }
|
|
114
|
-
rescue
|
|
116
|
+
rescue => e
|
|
117
|
+
$stderr.puts "[rails-ai-context] detect_api_client_generation failed: #{e.message}" if ENV["DEBUG"]
|
|
115
118
|
[]
|
|
116
119
|
end
|
|
117
120
|
|
|
@@ -126,7 +129,8 @@ module RailsAiContext
|
|
|
126
129
|
Dir.glob(File.join(controllers_dir, "**/*.rb")).each do |path|
|
|
127
130
|
content = File.read(path)
|
|
128
131
|
return { rails_rate_limiting: true } if content.match?(/rate_limit\b/)
|
|
129
|
-
rescue
|
|
132
|
+
rescue => e
|
|
133
|
+
$stderr.puts "[rails-ai-context] detect_rate_limiting failed: #{e.message}" if ENV["DEBUG"]
|
|
130
134
|
next
|
|
131
135
|
end
|
|
132
136
|
end
|
|
@@ -42,7 +42,8 @@ module RailsAiContext
|
|
|
42
42
|
|
|
43
43
|
content = File.read(path)
|
|
44
44
|
content.scan(/pin\s+["']([^"']+)["']/).flatten.sort
|
|
45
|
-
rescue
|
|
45
|
+
rescue => e
|
|
46
|
+
$stderr.puts "[rails-ai-context] extract_importmap_pins failed: #{e.message}" if ENV["DEBUG"]
|
|
46
47
|
[]
|
|
47
48
|
end
|
|
48
49
|
|
|
@@ -76,7 +77,8 @@ module RailsAiContext
|
|
|
76
77
|
def read_gemfile_lock
|
|
77
78
|
path = File.join(root, "Gemfile.lock")
|
|
78
79
|
File.exist?(path) ? File.read(path) : nil
|
|
79
|
-
rescue
|
|
80
|
+
rescue => e
|
|
81
|
+
$stderr.puts "[rails-ai-context] read_gemfile_lock failed: #{e.message}" if ENV["DEBUG"]
|
|
80
82
|
nil
|
|
81
83
|
end
|
|
82
84
|
|
|
@@ -84,7 +86,8 @@ module RailsAiContext
|
|
|
84
86
|
path = File.join(root, "package.json")
|
|
85
87
|
return false unless File.exist?(path)
|
|
86
88
|
File.read(path).include?("\"#{package}\"")
|
|
87
|
-
rescue
|
|
89
|
+
rescue => e
|
|
90
|
+
$stderr.puts "[rails-ai-context] package_json_has? failed: #{e.message}" if ENV["DEBUG"]
|
|
88
91
|
false
|
|
89
92
|
end
|
|
90
93
|
end
|
|
@@ -103,7 +103,8 @@ module RailsAiContext
|
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
result
|
|
106
|
-
rescue
|
|
106
|
+
rescue => e
|
|
107
|
+
$stderr.puts "[rails-ai-context] detect_devise_modules_per_model failed: #{e.message}" if ENV["DEBUG"]
|
|
107
108
|
{}
|
|
108
109
|
end
|
|
109
110
|
|
|
@@ -115,7 +116,8 @@ module RailsAiContext
|
|
|
115
116
|
token_auth[:http_token_auth] = detect_http_token_auth
|
|
116
117
|
|
|
117
118
|
token_auth
|
|
118
|
-
rescue
|
|
119
|
+
rescue => e
|
|
120
|
+
$stderr.puts "[rails-ai-context] detect_token_auth failed: #{e.message}" if ENV["DEBUG"]
|
|
119
121
|
{}
|
|
120
122
|
end
|
|
121
123
|
|
|
@@ -129,7 +131,8 @@ module RailsAiContext
|
|
|
129
131
|
end
|
|
130
132
|
|
|
131
133
|
{ detected: true }
|
|
132
|
-
rescue
|
|
134
|
+
rescue => e
|
|
135
|
+
$stderr.puts "[rails-ai-context] detect_devise_jwt failed: #{e.message}" if ENV["DEBUG"]
|
|
133
136
|
{ detected: false }
|
|
134
137
|
end
|
|
135
138
|
|
|
@@ -150,7 +153,8 @@ module RailsAiContext
|
|
|
150
153
|
result[:grant_flows] = grant_flows if grant_flows
|
|
151
154
|
result[:access_token_expires_in] = expires_in if expires_in
|
|
152
155
|
result
|
|
153
|
-
rescue
|
|
156
|
+
rescue => e
|
|
157
|
+
$stderr.puts "[rails-ai-context] detect_doorkeeper failed: #{e.message}" if ENV["DEBUG"]
|
|
154
158
|
nil
|
|
155
159
|
end
|
|
156
160
|
|
|
@@ -164,7 +168,8 @@ module RailsAiContext
|
|
|
164
168
|
path.sub("#{root}/", "")
|
|
165
169
|
end
|
|
166
170
|
end.sort
|
|
167
|
-
rescue
|
|
171
|
+
rescue => e
|
|
172
|
+
$stderr.puts "[rails-ai-context] detect_http_token_auth failed: #{e.message}" if ENV["DEBUG"]
|
|
168
173
|
[]
|
|
169
174
|
end
|
|
170
175
|
|
|
@@ -182,7 +187,8 @@ module RailsAiContext
|
|
|
182
187
|
results << { model: model_name, matches: matches.flatten.map(&:strip) }
|
|
183
188
|
end
|
|
184
189
|
results.sort_by { |r| r[:model] }
|
|
185
|
-
rescue
|
|
190
|
+
rescue => e
|
|
191
|
+
$stderr.puts "[rails-ai-context] scan_models_for failed: #{e.message}" if ENV["DEBUG"]
|
|
186
192
|
[]
|
|
187
193
|
end
|
|
188
194
|
|
|
@@ -190,7 +196,8 @@ module RailsAiContext
|
|
|
190
196
|
lock_path = File.join(root, "Gemfile.lock")
|
|
191
197
|
return false unless File.exist?(lock_path)
|
|
192
198
|
File.read(lock_path).include?(" #{name} (")
|
|
193
|
-
rescue
|
|
199
|
+
rescue => e
|
|
200
|
+
$stderr.puts "[rails-ai-context] gem_present? failed: #{e.message}" if ENV["DEBUG"]
|
|
194
201
|
false
|
|
195
202
|
end
|
|
196
203
|
|
|
@@ -40,7 +40,8 @@ module RailsAiContext
|
|
|
40
40
|
when Array then store.first.to_s
|
|
41
41
|
else store.class.name
|
|
42
42
|
end
|
|
43
|
-
rescue
|
|
43
|
+
rescue => e
|
|
44
|
+
$stderr.puts "[rails-ai-context] detect_cache_store failed: #{e.message}" if ENV["DEBUG"]
|
|
44
45
|
"unknown"
|
|
45
46
|
end
|
|
46
47
|
|
|
@@ -55,7 +56,8 @@ module RailsAiContext
|
|
|
55
56
|
when Class then adapter.name
|
|
56
57
|
else adapter.to_s
|
|
57
58
|
end
|
|
58
|
-
rescue
|
|
59
|
+
rescue => e
|
|
60
|
+
$stderr.puts "[rails-ai-context] detect_queue_adapter failed: #{e.message}" if ENV["DEBUG"]
|
|
59
61
|
"unknown"
|
|
60
62
|
end
|
|
61
63
|
|
|
@@ -78,13 +80,15 @@ module RailsAiContext
|
|
|
78
80
|
end
|
|
79
81
|
|
|
80
82
|
settings.empty? ? nil : settings
|
|
81
|
-
rescue
|
|
83
|
+
rescue => e
|
|
84
|
+
$stderr.puts "[rails-ai-context] detect_mailer_settings failed: #{e.message}" if ENV["DEBUG"]
|
|
82
85
|
nil
|
|
83
86
|
end
|
|
84
87
|
|
|
85
88
|
def extract_middleware
|
|
86
89
|
app.middleware.map { |m| m.name || m.klass.to_s }.uniq
|
|
87
|
-
rescue
|
|
90
|
+
rescue => e
|
|
91
|
+
$stderr.puts "[rails-ai-context] extract_middleware failed: #{e.message}" if ENV["DEBUG"]
|
|
88
92
|
[]
|
|
89
93
|
end
|
|
90
94
|
|
|
@@ -100,7 +104,8 @@ module RailsAiContext
|
|
|
100
104
|
def credentials_configured?
|
|
101
105
|
creds = app.credentials
|
|
102
106
|
creds.respond_to?(:config) && creds.config.keys.any?
|
|
103
|
-
rescue
|
|
107
|
+
rescue => e
|
|
108
|
+
$stderr.puts "[rails-ai-context] credentials_configured? failed: #{e.message}" if ENV["DEBUG"]
|
|
104
109
|
false
|
|
105
110
|
end
|
|
106
111
|
|
|
@@ -113,7 +118,8 @@ module RailsAiContext
|
|
|
113
118
|
if content.match?(/< ActiveSupport::CurrentAttributes|< Rails::CurrentAttributes/)
|
|
114
119
|
File.basename(path, ".rb").camelize
|
|
115
120
|
end
|
|
116
|
-
rescue
|
|
121
|
+
rescue => e
|
|
122
|
+
$stderr.puts "[rails-ai-context] detect_current_attributes failed: #{e.message}" if ENV["DEBUG"]
|
|
117
123
|
nil
|
|
118
124
|
end
|
|
119
125
|
end
|
|
@@ -51,7 +51,8 @@ module RailsAiContext
|
|
|
51
51
|
else
|
|
52
52
|
Rails.application.eager_load!
|
|
53
53
|
end
|
|
54
|
-
rescue
|
|
54
|
+
rescue => e
|
|
55
|
+
$stderr.puts "[rails-ai-context] eager_load_controllers! failed: #{e.message}" if ENV["DEBUG"]
|
|
55
56
|
nil
|
|
56
57
|
end
|
|
57
58
|
|
|
@@ -131,7 +132,8 @@ module RailsAiContext
|
|
|
131
132
|
return actions if actions.any?
|
|
132
133
|
end
|
|
133
134
|
ctrl.action_methods.to_a.sort
|
|
134
|
-
rescue
|
|
135
|
+
rescue => e
|
|
136
|
+
$stderr.puts "[rails-ai-context] extract_actions failed: #{e.message}" if ENV["DEBUG"]
|
|
135
137
|
[]
|
|
136
138
|
end
|
|
137
139
|
|
|
@@ -192,7 +194,8 @@ module RailsAiContext
|
|
|
192
194
|
end
|
|
193
195
|
|
|
194
196
|
[]
|
|
195
|
-
rescue
|
|
197
|
+
rescue => e
|
|
198
|
+
$stderr.puts "[rails-ai-context] extract_filters failed: #{e.message}" if ENV["DEBUG"]
|
|
196
199
|
[]
|
|
197
200
|
end
|
|
198
201
|
|
|
@@ -215,7 +218,8 @@ module RailsAiContext
|
|
|
215
218
|
klass = klass.superclass
|
|
216
219
|
end
|
|
217
220
|
constraints
|
|
218
|
-
rescue
|
|
221
|
+
rescue => e
|
|
222
|
+
$stderr.puts "[rails-ai-context] collect_source_constraints failed: #{e.message}" if ENV["DEBUG"]
|
|
219
223
|
{}
|
|
220
224
|
end
|
|
221
225
|
|
|
@@ -287,7 +291,8 @@ module RailsAiContext
|
|
|
287
291
|
def devise_controller?(ctrl)
|
|
288
292
|
return false unless defined?(::DeviseController)
|
|
289
293
|
ctrl < ::DeviseController || ctrl.ancestors.any? { |a| a.name&.start_with?("Devise::") }
|
|
290
|
-
rescue
|
|
294
|
+
rescue => e
|
|
295
|
+
$stderr.puts "[rails-ai-context] devise_controller? failed: #{e.message}" if ENV["DEBUG"]
|
|
291
296
|
false
|
|
292
297
|
end
|
|
293
298
|
|
|
@@ -303,7 +308,8 @@ module RailsAiContext
|
|
|
303
308
|
.reject { |mod| mod.name&.start_with?("ActionController", "ActionDispatch", "ActiveSupport", "AbstractController") }
|
|
304
309
|
.map(&:name)
|
|
305
310
|
.compact
|
|
306
|
-
rescue
|
|
311
|
+
rescue => e
|
|
312
|
+
$stderr.puts "[rails-ai-context] extract_concerns failed: #{e.message}" if ENV["DEBUG"]
|
|
307
313
|
[]
|
|
308
314
|
end
|
|
309
315
|
|
|
@@ -338,7 +344,8 @@ module RailsAiContext
|
|
|
338
344
|
exceptions = exception_part&.scan(/([A-Z][\w:]+)/)&.flatten || []
|
|
339
345
|
exceptions.map { |ex| { exception: ex, handler: handler }.compact }
|
|
340
346
|
end.flatten
|
|
341
|
-
rescue
|
|
347
|
+
rescue => e
|
|
348
|
+
$stderr.puts "[rails-ai-context] extract_rescue_from failed: #{e.message}" if ENV["DEBUG"]
|
|
342
349
|
[]
|
|
343
350
|
end
|
|
344
351
|
|
|
@@ -349,7 +356,8 @@ module RailsAiContext
|
|
|
349
356
|
return nil unless match
|
|
350
357
|
|
|
351
358
|
match[1].strip
|
|
352
|
-
rescue
|
|
359
|
+
rescue => e
|
|
360
|
+
$stderr.puts "[rails-ai-context] extract_rate_limit failed: #{e.message}" if ENV["DEBUG"]
|
|
353
361
|
nil
|
|
354
362
|
end
|
|
355
363
|
|
|
@@ -369,7 +377,8 @@ module RailsAiContext
|
|
|
369
377
|
end
|
|
370
378
|
end
|
|
371
379
|
actions.uniq.sort
|
|
372
|
-
rescue
|
|
380
|
+
rescue => e
|
|
381
|
+
$stderr.puts "[rails-ai-context] extract_turbo_stream_actions failed: #{e.message}" if ENV["DEBUG"]
|
|
373
382
|
[]
|
|
374
383
|
end
|
|
375
384
|
|
|
@@ -377,7 +386,8 @@ module RailsAiContext
|
|
|
377
386
|
path = source_path(ctrl)
|
|
378
387
|
return nil unless path && File.exist?(path)
|
|
379
388
|
File.read(path)
|
|
380
|
-
rescue
|
|
389
|
+
rescue => e
|
|
390
|
+
$stderr.puts "[rails-ai-context] read_source failed: #{e.message}" if ENV["DEBUG"]
|
|
381
391
|
nil
|
|
382
392
|
end
|
|
383
393
|
|
|
@@ -146,7 +146,8 @@ module RailsAiContext
|
|
|
146
146
|
.select { |d| File.directory?(File.join(app_dir, d)) }
|
|
147
147
|
.reject { |d| STANDARD_APP_DIRS.include?(d) }
|
|
148
148
|
.sort
|
|
149
|
-
rescue
|
|
149
|
+
rescue => e
|
|
150
|
+
$stderr.puts "[rails-ai-context] detect_custom_directories failed: #{e.message}" if ENV["DEBUG"]
|
|
150
151
|
[]
|
|
151
152
|
end
|
|
152
153
|
|
|
@@ -75,7 +75,8 @@ module RailsAiContext
|
|
|
75
75
|
plugins << "headlessui" if pkg_content.include?("headlessui") || pkg_content.include?("@headlessui")
|
|
76
76
|
|
|
77
77
|
plugins.any? ? "#{framework}+#{plugins.join('+')}" : framework
|
|
78
|
-
rescue
|
|
78
|
+
rescue => e
|
|
79
|
+
$stderr.puts "[rails-ai-context] detect_framework failed: #{e.message}" if ENV["DEBUG"]
|
|
79
80
|
"unknown"
|
|
80
81
|
end
|
|
81
82
|
|
|
@@ -288,7 +289,8 @@ module RailsAiContext
|
|
|
288
289
|
end
|
|
289
290
|
|
|
290
291
|
result
|
|
291
|
-
rescue
|
|
292
|
+
rescue => e
|
|
293
|
+
$stderr.puts "[rails-ai-context] extract_font_loading failed: #{e.message}" if ENV["DEBUG"]
|
|
292
294
|
{ font_face: 0, google_fonts: false, system_fonts: false }
|
|
293
295
|
end
|
|
294
296
|
|
|
@@ -304,7 +306,8 @@ module RailsAiContext
|
|
|
304
306
|
end
|
|
305
307
|
end
|
|
306
308
|
layers.uniq
|
|
307
|
-
rescue
|
|
309
|
+
rescue => e
|
|
310
|
+
$stderr.puts "[rails-ai-context] extract_css_layers failed: #{e.message}" if ENV["DEBUG"]
|
|
308
311
|
[]
|
|
309
312
|
end
|
|
310
313
|
|
|
@@ -325,7 +328,8 @@ module RailsAiContext
|
|
|
325
328
|
end
|
|
326
329
|
end
|
|
327
330
|
plugins.uniq
|
|
328
|
-
rescue
|
|
331
|
+
rescue => e
|
|
332
|
+
$stderr.puts "[rails-ai-context] extract_postcss_plugins failed: #{e.message}" if ENV["DEBUG"]
|
|
329
333
|
[]
|
|
330
334
|
end
|
|
331
335
|
|
|
@@ -50,7 +50,8 @@ module RailsAiContext
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
config.empty? ? nil : config
|
|
53
|
-
rescue
|
|
53
|
+
rescue => e
|
|
54
|
+
$stderr.puts "[rails-ai-context] extract_puma_config failed: #{e.message}" if ENV["DEBUG"]
|
|
54
55
|
nil
|
|
55
56
|
end
|
|
56
57
|
|
|
@@ -77,7 +78,8 @@ module RailsAiContext
|
|
|
77
78
|
content = File.read(routes_path)
|
|
78
79
|
return true if content.match?(/\b(?:health|up|ping|status)\b/)
|
|
79
80
|
nil
|
|
80
|
-
rescue
|
|
81
|
+
rescue => e
|
|
82
|
+
$stderr.puts "[rails-ai-context] detect_health_check failed: #{e.message}" if ENV["DEBUG"]
|
|
81
83
|
nil
|
|
82
84
|
end
|
|
83
85
|
|
|
@@ -96,7 +98,8 @@ module RailsAiContext
|
|
|
96
98
|
info[:compose] = compose
|
|
97
99
|
|
|
98
100
|
info
|
|
99
|
-
rescue
|
|
101
|
+
rescue => e
|
|
102
|
+
$stderr.puts "[rails-ai-context] extract_docker_info failed: #{e.message}" if ENV["DEBUG"]
|
|
100
103
|
nil
|
|
101
104
|
end
|
|
102
105
|
|
|
@@ -100,10 +100,12 @@ module RailsAiContext
|
|
|
100
100
|
next if engine.name.start_with?("Rails::", "ActionPack::", "ActionView::", "ActiveModel::")
|
|
101
101
|
|
|
102
102
|
{ name: engine.name, root: engine.root.to_s.sub("#{Gem.dir}/gems/", "") }
|
|
103
|
-
rescue
|
|
103
|
+
rescue => e
|
|
104
|
+
$stderr.puts "[rails-ai-context] discover_rails_engines failed: #{e.message}" if ENV["DEBUG"]
|
|
104
105
|
nil
|
|
105
106
|
end.sort_by { |e| e[:name] }
|
|
106
|
-
rescue
|
|
107
|
+
rescue => e
|
|
108
|
+
$stderr.puts "[rails-ai-context] discover_rails_engines failed: #{e.message}" if ENV["DEBUG"]
|
|
107
109
|
[]
|
|
108
110
|
end
|
|
109
111
|
end
|
|
@@ -418,7 +418,8 @@ module RailsAiContext
|
|
|
418
418
|
return false unless File.exist?(path)
|
|
419
419
|
content = File.read(path, encoding: "bom|utf-8")
|
|
420
420
|
content.include?("\"#{name}\"")
|
|
421
|
-
rescue
|
|
421
|
+
rescue => e
|
|
422
|
+
$stderr.puts "[rails-ai-context] package_json_has_script? failed: #{e.message}" if ENV["DEBUG"]
|
|
422
423
|
false
|
|
423
424
|
end
|
|
424
425
|
end
|
|
@@ -42,7 +42,8 @@ module RailsAiContext
|
|
|
42
42
|
begin
|
|
43
43
|
data = YAML.load_file(path, permitted_classes: [ Symbol ], aliases: true) || {}
|
|
44
44
|
info[:key_count] = count_keys(data)
|
|
45
|
-
rescue
|
|
45
|
+
rescue => e
|
|
46
|
+
$stderr.puts "[rails-ai-context] extract_locale_files failed: #{e.message}" if ENV["DEBUG"]
|
|
46
47
|
info[:parse_error] = true
|
|
47
48
|
end
|
|
48
49
|
end
|
|
@@ -42,7 +42,8 @@ module RailsAiContext
|
|
|
42
42
|
priority: job.priority
|
|
43
43
|
}.compact
|
|
44
44
|
end.sort_by { |j| j[:name] }
|
|
45
|
-
rescue
|
|
45
|
+
rescue => e
|
|
46
|
+
$stderr.puts "[rails-ai-context] extract_jobs failed: #{e.message}" if ENV["DEBUG"]
|
|
46
47
|
[]
|
|
47
48
|
end
|
|
48
49
|
|
|
@@ -80,7 +81,8 @@ module RailsAiContext
|
|
|
80
81
|
job[:perform_signature] = perform_signature if perform_signature
|
|
81
82
|
job
|
|
82
83
|
end.sort_by { |j| j[:name] }
|
|
83
|
-
rescue
|
|
84
|
+
rescue => e
|
|
85
|
+
$stderr.puts "[rails-ai-context] extract_jobs_from_source failed: #{e.message}" if ENV["DEBUG"]
|
|
84
86
|
[]
|
|
85
87
|
end
|
|
86
88
|
|
|
@@ -99,7 +101,8 @@ module RailsAiContext
|
|
|
99
101
|
delivery_method: mailer.delivery_method.to_s
|
|
100
102
|
}
|
|
101
103
|
end.sort_by { |m| m[:name] }
|
|
102
|
-
rescue
|
|
104
|
+
rescue => e
|
|
105
|
+
$stderr.puts "[rails-ai-context] extract_mailers failed: #{e.message}" if ENV["DEBUG"]
|
|
103
106
|
[]
|
|
104
107
|
end
|
|
105
108
|
|
|
@@ -116,7 +119,8 @@ module RailsAiContext
|
|
|
116
119
|
.map(&:to_s)
|
|
117
120
|
}
|
|
118
121
|
end.sort_by { |c| c[:name] }
|
|
119
|
-
rescue
|
|
122
|
+
rescue => e
|
|
123
|
+
$stderr.puts "[rails-ai-context] extract_channels failed: #{e.message}" if ENV["DEBUG"]
|
|
120
124
|
[]
|
|
121
125
|
end
|
|
122
126
|
end
|