rails-ai-context 5.35.0 → 5.35.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/CHANGELOG.md +1024 -0
- data/CONTEXT.md +37 -7
- data/CONTRIBUTING.md +30 -1
- data/README.md +9 -9
- data/SECURITY.md +2 -2
- data/docs/ARCHITECTURE.md +12 -4
- data/docs/CLI.md +44 -15
- data/docs/COMPATIBILITY.md +34 -8
- data/docs/CONFIGURATION.md +28 -5
- data/docs/CUSTOM_TOOLS.md +8 -2
- data/docs/FAQ.md +5 -5
- data/docs/GUIDE.md +33 -65
- data/docs/INTROSPECTORS.md +4 -4
- data/docs/QUICKSTART.md +1 -1
- data/docs/RECIPES.md +5 -5
- data/docs/RELEASING.md +3 -1
- data/docs/SECURITY.md +255 -74
- data/docs/SETUP.md +1 -1
- data/docs/STANDALONE.md +2 -2
- data/docs/TOOLS.md +151 -90
- data/docs/TROUBLESHOOTING.md +123 -8
- data/docs/_config.yml +1 -1
- data/docs/adr/0008-query-runs-only-where-it-can-guard.md +38 -0
- data/docs/adr/0009-dbhub-shapes-in-ruby.md +26 -0
- data/docs/adr/0010-one-config-tool-with-sections.md +32 -0
- data/docs/index.md +2 -2
- data/exe/rails-ai-context +24 -9
- data/lib/generators/rails_ai_context/install/install_generator.rb +2 -0
- data/lib/rails_ai_context/app_databases.rb +377 -0
- data/lib/rails_ai_context/app_kind.rb +2 -0
- data/lib/rails_ai_context/cli/app_root.rb +1 -0
- data/lib/rails_ai_context/cli/tool_runner.rb +110 -99
- data/lib/rails_ai_context/configuration.rb +15 -8
- data/lib/rails_ai_context/database_family/mysql_runtime.rb +170 -0
- data/lib/rails_ai_context/database_family/postgresql_plan.rb +124 -0
- data/lib/rails_ai_context/database_family/postgresql_runtime.rb +211 -0
- data/lib/rails_ai_context/database_family/sqlite_runtime.rb +391 -0
- data/lib/rails_ai_context/database_family.rb +282 -0
- data/lib/rails_ai_context/database_file.rb +61 -7
- data/lib/rails_ai_context/database_yml.rb +7 -29
- data/lib/rails_ai_context/doctor.rb +15 -16
- data/lib/rails_ai_context/instrumentation.rb +1 -1
- data/lib/rails_ai_context/introspectors/connection_pool_introspector.rb +8 -23
- data/lib/rails_ai_context/introspectors/database_stats_introspector.rb +6 -70
- data/lib/rails_ai_context/introspectors/declared_constant.rb +19 -7
- data/lib/rails_ai_context/introspectors/env_introspector.rb +1 -1
- data/lib/rails_ai_context/introspectors/env_references.rb +1 -1
- data/lib/rails_ai_context/introspectors/job_introspector.rb +7 -7
- data/lib/rails_ai_context/introspectors/migration_introspector.rb +8 -11
- data/lib/rails_ai_context/introspectors/migration_replay/statements.rb +9 -9
- data/lib/rails_ai_context/introspectors/model_introspector.rb +33 -39
- data/lib/rails_ai_context/introspectors/multi_database_introspector.rb +33 -30
- data/lib/rails_ai_context/introspectors/node_source.rb +2 -0
- data/lib/rails_ai_context/introspectors/performance_introspector.rb +80 -24
- data/lib/rails_ai_context/introspectors/pg_partitions.rb +1 -4
- data/lib/rails_ai_context/introspectors/schema_conventions.rb +6 -8
- data/lib/rails_ai_context/introspectors/schema_dump_path.rb +12 -14
- data/lib/rails_ai_context/introspectors/schema_introspector.rb +47 -27
- data/lib/rails_ai_context/introspectors/schema_reader.rb +1 -1
- data/lib/rails_ai_context/introspectors/source_scan.rb +39 -4
- data/lib/rails_ai_context/migration_status.rb +18 -46
- data/lib/rails_ai_context/payload.rb +48 -1
- data/lib/rails_ai_context/pending_migrations.rb +3 -4
- data/lib/rails_ai_context/run_cache.rb +5 -0
- data/lib/rails_ai_context/schema_adapter.rb +13 -18
- data/lib/rails_ai_context/secret_columns.rb +506 -0
- data/lib/rails_ai_context/serializers/claude_rules_serializer.rb +2 -2
- data/lib/rails_ai_context/serializers/markdown_serializer.rb +14 -10
- data/lib/rails_ai_context/serializers/section_facts.rb +12 -2
- data/lib/rails_ai_context/serializers/stack_overview_helper.rb +5 -2
- data/lib/rails_ai_context/serializers/tool_guide_helper.rb +35 -7
- data/lib/rails_ai_context/server.rb +143 -29
- data/lib/rails_ai_context/sql_gate.rb +1007 -0
- data/lib/rails_ai_context/tasks/rails_ai_context.rake +1 -2
- data/lib/rails_ai_context/test_helper.rb +3 -1
- data/lib/rails_ai_context/tools/analyze_feature.rb +11 -7
- data/lib/rails_ai_context/tools/base_tool.rb +71 -48
- data/lib/rails_ai_context/tools/dependency_graph.rb +1 -1
- data/lib/rails_ai_context/tools/diagnose.rb +105 -42
- data/lib/rails_ai_context/tools/generate_test.rb +4 -6
- data/lib/rails_ai_context/tools/get_active_support.rb +1 -6
- data/lib/rails_ai_context/tools/get_api.rb +1 -6
- data/lib/rails_ai_context/tools/get_autoload.rb +1 -6
- data/lib/rails_ai_context/tools/get_callbacks.rb +5 -5
- data/lib/rails_ai_context/tools/get_component_catalog.rb +6 -7
- data/lib/rails_ai_context/tools/get_concern.rb +6 -6
- data/lib/rails_ai_context/tools/get_config.rb +189 -12
- data/lib/rails_ai_context/tools/get_context.rb +111 -105
- data/lib/rails_ai_context/tools/get_controllers.rb +8 -5
- data/lib/rails_ai_context/tools/get_conventions.rb +1 -6
- data/lib/rails_ai_context/tools/get_engines.rb +1 -6
- data/lib/rails_ai_context/tools/get_env.rb +1 -6
- data/lib/rails_ai_context/tools/get_env_config.rb +2 -8
- data/lib/rails_ai_context/tools/get_frontend_stack.rb +1 -6
- data/lib/rails_ai_context/tools/get_gems.rb +1 -6
- data/lib/rails_ai_context/tools/get_helper_methods.rb +4 -5
- data/lib/rails_ai_context/tools/get_i18n.rb +1 -7
- data/lib/rails_ai_context/tools/get_job_pattern.rb +1 -1
- data/lib/rails_ai_context/tools/get_mailers.rb +1 -1
- data/lib/rails_ai_context/tools/get_model_details.rb +5 -8
- data/lib/rails_ai_context/tools/get_partial_interface.rb +3 -4
- data/lib/rails_ai_context/tools/get_schema.rb +10 -8
- data/lib/rails_ai_context/tools/get_service_pattern.rb +60 -24
- data/lib/rails_ai_context/tools/get_turbo_map.rb +1 -1
- data/lib/rails_ai_context/tools/migration_advisor.rb +47 -32
- data/lib/rails_ai_context/tools/onboard.rb +24 -24
- data/lib/rails_ai_context/tools/performance_check.rb +15 -2
- data/lib/rails_ai_context/tools/query.rb +142 -1356
- data/lib/rails_ai_context/tools/read_logs.rb +1 -1
- data/lib/rails_ai_context/tools/review_changes.rb +6 -7
- data/lib/rails_ai_context/tools/runtime_info.rb +125 -88
- data/lib/rails_ai_context/tools/safe_call.rb +70 -28
- data/lib/rails_ai_context/tools/search_code.rb +0 -4
- data/lib/rails_ai_context/tools/search_docs.rb +3 -1
- data/lib/rails_ai_context/tools/security_scan.rb +9 -5
- data/lib/rails_ai_context/tools/session_context.rb +18 -12
- data/lib/rails_ai_context/tools/validate.rb +1 -0
- data/lib/rails_ai_context/tools/validate_semantics.rb +5 -5
- data/lib/rails_ai_context/version.rb +1 -1
- data/lib/rails_ai_context.rb +4 -7
- data/server.json +2 -2
- metadata +14 -3
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "time"
|
|
4
|
+
|
|
3
5
|
module RailsAiContext
|
|
4
6
|
module Tools
|
|
5
7
|
class SessionContext < BaseTool
|
|
@@ -24,7 +26,7 @@ module RailsAiContext
|
|
|
24
26
|
)
|
|
25
27
|
|
|
26
28
|
guide_row(
|
|
27
|
-
order:
|
|
29
|
+
order: 34,
|
|
28
30
|
mcp: "rails_session_context(action:\"status\")",
|
|
29
31
|
cli_args: "action=status",
|
|
30
32
|
summary: "Track what you've already queried, avoid redundant calls"
|
|
@@ -39,9 +41,11 @@ module RailsAiContext
|
|
|
39
41
|
|
|
40
42
|
if mark
|
|
41
43
|
tool, params = parse_mark(mark)
|
|
42
|
-
known =
|
|
44
|
+
known, section = known_tool(tool)
|
|
43
45
|
return error_response(unknown_mark_message(tool)) unless known
|
|
44
46
|
|
|
47
|
+
# A recorded call's parameters run in name order, and `section` follows every other a section reads.
|
|
48
|
+
params = [ params, "section:#{section.name}" ].reject(&:empty?).join(",") if section
|
|
45
49
|
session_record(known, params)
|
|
46
50
|
return text_response("Marked `#{known}` with params `#{echo_input(params)}` as queried.")
|
|
47
51
|
end
|
|
@@ -57,8 +61,6 @@ module RailsAiContext
|
|
|
57
61
|
else
|
|
58
62
|
text_response("Unknown action: #{echo_input(action)}. Use status, summary, or reset.")
|
|
59
63
|
end
|
|
60
|
-
rescue => e
|
|
61
|
-
text_response("Session context error: #{e.message}")
|
|
62
64
|
end
|
|
63
65
|
|
|
64
66
|
class << self
|
|
@@ -71,22 +73,26 @@ module RailsAiContext
|
|
|
71
73
|
[ tool, params ]
|
|
72
74
|
end
|
|
73
75
|
|
|
74
|
-
# The tool a mark names, spelled
|
|
75
|
-
#
|
|
76
|
-
|
|
77
|
-
# recorded a query nothing could ever have answered.
|
|
78
|
-
def known_tool_name(name)
|
|
76
|
+
# The tool a mark names, spelled as the server names it, so a mark and the call it stands for are one
|
|
77
|
+
# entry, with the config section a retired name stands for. Takes the short forms the CLI takes.
|
|
78
|
+
def known_tool(name)
|
|
79
79
|
return nil if name.to_s.empty?
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
candidates = RailsAiContext::CLI::ToolRunner.candidate_names(name)
|
|
82
|
+
tools = RailsAiContext::Server.exposed_tools.map(&:tool_name)
|
|
83
|
+
found = candidates.find { |candidate| tools.include?(candidate) }
|
|
84
|
+
return [ found, nil ] if found
|
|
85
|
+
|
|
86
|
+
section = candidates.filter_map { |candidate| GetConfig.retired_section(candidate) }.find(&:served?)
|
|
87
|
+
[ "rails_get_config", section ] if section
|
|
83
88
|
end
|
|
84
89
|
|
|
85
90
|
def unknown_mark_message(name)
|
|
86
91
|
usage = "Pass `tool:params`, e.g. `get_schema:users`."
|
|
87
92
|
return "`mark` names no tool. #{usage}" if name.to_s.empty?
|
|
88
93
|
|
|
89
|
-
|
|
94
|
+
names = RailsAiContext::Server.exposed_tools.map(&:tool_name) | RailsAiContext::Server.retired_names
|
|
95
|
+
short_names = names.map { |tool_name| RailsAiContext::CLI::ToolRunner.short_name(tool_name) }
|
|
90
96
|
suggestion = find_closest_match(name, short_names)
|
|
91
97
|
"Unknown tool '#{echo_input(name)}' in `mark`.#{" Did you mean '#{suggestion}'?" if suggestion} #{usage}"
|
|
92
98
|
end
|
|
@@ -514,7 +514,7 @@ module RailsAiContext
|
|
|
514
514
|
|
|
515
515
|
private_class_method def self.check_column_references_ast(file, visitor, context)
|
|
516
516
|
warnings = []
|
|
517
|
-
return warnings unless file.start_with?("app/models/")
|
|
517
|
+
return warnings unless file.start_with?("app/models/")
|
|
518
518
|
|
|
519
519
|
valid = model_valid_columns(file, context)
|
|
520
520
|
return warnings unless valid
|
|
@@ -534,7 +534,7 @@ module RailsAiContext
|
|
|
534
534
|
# Regex fallback
|
|
535
535
|
private_class_method def self.check_column_references_regex(file, content, context)
|
|
536
536
|
warnings = []
|
|
537
|
-
return warnings unless file.start_with?("app/models/")
|
|
537
|
+
return warnings unless file.start_with?("app/models/")
|
|
538
538
|
|
|
539
539
|
valid = model_valid_columns(file, context)
|
|
540
540
|
return warnings unless valid
|
|
@@ -647,7 +647,7 @@ module RailsAiContext
|
|
|
647
647
|
|
|
648
648
|
private_class_method def self.check_callback_existence_ast(file, visitor, context)
|
|
649
649
|
warnings = []
|
|
650
|
-
return warnings unless file.start_with?("app/models/")
|
|
650
|
+
return warnings unless file.start_with?("app/models/")
|
|
651
651
|
return warnings if visitor.callback_registrations.empty?
|
|
652
652
|
|
|
653
653
|
models = Payload.models(context)
|
|
@@ -740,7 +740,7 @@ module RailsAiContext
|
|
|
740
740
|
# `:versions`) has no line in the app to fix.
|
|
741
741
|
private_class_method def self.check_has_many_dependent(file, context, content)
|
|
742
742
|
warnings = []
|
|
743
|
-
return warnings unless file.start_with?("app/models/")
|
|
743
|
+
return warnings unless file.start_with?("app/models/")
|
|
744
744
|
|
|
745
745
|
models = Payload.models(context)
|
|
746
746
|
return warnings if models.empty?
|
|
@@ -767,7 +767,7 @@ module RailsAiContext
|
|
|
767
767
|
|
|
768
768
|
private_class_method def self.check_missing_fk_index(file, context)
|
|
769
769
|
warnings = []
|
|
770
|
-
return warnings unless file.start_with?("app/models/")
|
|
770
|
+
return warnings unless file.start_with?("app/models/")
|
|
771
771
|
|
|
772
772
|
schema = Payload.section(context, :schema)
|
|
773
773
|
models = Payload.models(context)
|
data/lib/rails_ai_context.rb
CHANGED
|
@@ -6,17 +6,14 @@ require "zeitwerk"
|
|
|
6
6
|
# boot that copy is the one on the load path.
|
|
7
7
|
require "logger"
|
|
8
8
|
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
# ActiveSupport as a side effect before any of this code runs. In static
|
|
13
|
-
# tier nothing boots Rails, so those methods are only defined by accident of
|
|
14
|
-
# which introspector happens to run first. Requiring them here up front
|
|
15
|
-
# makes both tiers behave the same regardless of load order.
|
|
9
|
+
# The static tier boots no Rails, so the core extensions the gem leans on load here.
|
|
10
|
+
# active_support first: on 7.1 array/conversions calls ActiveSupport.deprecator as it loads.
|
|
11
|
+
require "active_support"
|
|
16
12
|
require "active_support/core_ext/string/inflections"
|
|
17
13
|
require "active_support/core_ext/string/filters"
|
|
18
14
|
require "active_support/core_ext/object/deep_dup"
|
|
19
15
|
require "active_support/core_ext/object/blank"
|
|
16
|
+
require "active_support/core_ext/array/conversions"
|
|
20
17
|
|
|
21
18
|
# Same reason, for two stdlib constants. `Set` is autoloaded on newer Rubies
|
|
22
19
|
# and not on the oldest one supported here; `Date` is never autoloaded. Both
|
data/server.json
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.crisnahine/rails-ai-context",
|
|
4
4
|
"title": "Rails AI Context",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "35 MCP tools give AI agents live Rails schema, routes, models, and conventions.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "https://github.com/crisnahine/rails-ai-context",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "5.35.
|
|
10
|
+
"version": "5.35.2",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "mcpb",
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails-ai-context
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.35.
|
|
4
|
+
version: 5.35.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- crisnahine
|
|
@@ -210,7 +210,7 @@ dependencies:
|
|
|
210
210
|
description: |
|
|
211
211
|
rails-ai-context turns your running Rails app into the source of truth for AI
|
|
212
212
|
coding assistants. Instead of guessing from training data or stale file reads,
|
|
213
|
-
agents query
|
|
213
|
+
agents query 35 live tools (via MCP server or CLI) to get your actual schema,
|
|
214
214
|
associations, routes, inherited filters, conventions, and test patterns.
|
|
215
215
|
Semantic validation catches cross-file errors (wrong columns, missing partials,
|
|
216
216
|
broken routes) before code runs - so AI writes correct code on the first try.
|
|
@@ -264,6 +264,9 @@ files:
|
|
|
264
264
|
- docs/adr/0005-workspace-mcp-entries.md
|
|
265
265
|
- docs/adr/0006-strong-params-resolve-as-ruby-runs.md
|
|
266
266
|
- docs/adr/0007-every-install-question-has-a-flag.md
|
|
267
|
+
- docs/adr/0008-query-runs-only-where-it-can-guard.md
|
|
268
|
+
- docs/adr/0009-dbhub-shapes-in-ruby.md
|
|
269
|
+
- docs/adr/0010-one-config-tool-with-sections.md
|
|
267
270
|
- docs/agents/domain.md
|
|
268
271
|
- docs/agents/issue-tracker.md
|
|
269
272
|
- docs/agents/triage-labels.md
|
|
@@ -275,6 +278,7 @@ files:
|
|
|
275
278
|
- lib/rails_ai_context/action_filters.rb
|
|
276
279
|
- lib/rails_ai_context/action_outcome.rb
|
|
277
280
|
- lib/rails_ai_context/app_commands.rb
|
|
281
|
+
- lib/rails_ai_context/app_databases.rb
|
|
278
282
|
- lib/rails_ai_context/app_kind.rb
|
|
279
283
|
- lib/rails_ai_context/ast_cache.rb
|
|
280
284
|
- lib/rails_ai_context/base_mixins.rb
|
|
@@ -295,6 +299,11 @@ files:
|
|
|
295
299
|
- lib/rails_ai_context/context_file_report.rb
|
|
296
300
|
- lib/rails_ai_context/count_phrase.rb
|
|
297
301
|
- lib/rails_ai_context/data/docs/index.json
|
|
302
|
+
- lib/rails_ai_context/database_family.rb
|
|
303
|
+
- lib/rails_ai_context/database_family/mysql_runtime.rb
|
|
304
|
+
- lib/rails_ai_context/database_family/postgresql_plan.rb
|
|
305
|
+
- lib/rails_ai_context/database_family/postgresql_runtime.rb
|
|
306
|
+
- lib/rails_ai_context/database_family/sqlite_runtime.rb
|
|
298
307
|
- lib/rails_ai_context/database_file.rb
|
|
299
308
|
- lib/rails_ai_context/database_yml.rb
|
|
300
309
|
- lib/rails_ai_context/detail_level.rb
|
|
@@ -493,6 +502,7 @@ files:
|
|
|
493
502
|
- lib/rails_ai_context/schema_adapter.rb
|
|
494
503
|
- lib/rails_ai_context/schema_hint.rb
|
|
495
504
|
- lib/rails_ai_context/schema_version.rb
|
|
505
|
+
- lib/rails_ai_context/secret_columns.rb
|
|
496
506
|
- lib/rails_ai_context/serializers.rb
|
|
497
507
|
- lib/rails_ai_context/serializers/base.rb
|
|
498
508
|
- lib/rails_ai_context/serializers/claude_rules_serializer.rb
|
|
@@ -514,6 +524,7 @@ files:
|
|
|
514
524
|
- lib/rails_ai_context/serializers/test_command_detection.rb
|
|
515
525
|
- lib/rails_ai_context/serializers/tool_guide_helper.rb
|
|
516
526
|
- lib/rails_ai_context/server.rb
|
|
527
|
+
- lib/rails_ai_context/sql_gate.rb
|
|
517
528
|
- lib/rails_ai_context/static_app.rb
|
|
518
529
|
- lib/rails_ai_context/tasks/rails_ai_context.rake
|
|
519
530
|
- lib/rails_ai_context/test_framework.rb
|
|
@@ -614,6 +625,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
614
625
|
requirements: []
|
|
615
626
|
rubygems_version: 3.6.9
|
|
616
627
|
specification_version: 4
|
|
617
|
-
summary: Stop AI from guessing your Rails app.
|
|
628
|
+
summary: Stop AI from guessing your Rails app. 35 tools give coding agents ground
|
|
618
629
|
truth - schema, models, routes, conventions - on demand. MCP or CLI.
|
|
619
630
|
test_files: []
|