rails-ai-context 4.3.0 → 4.3.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +58 -8
  3. data/CLAUDE.md +4 -4
  4. data/CONTRIBUTING.md +1 -1
  5. data/README.md +7 -7
  6. data/SECURITY.md +2 -1
  7. data/docs/GUIDE.md +3 -3
  8. data/lib/generators/rails_ai_context/install/install_generator.rb +2 -2
  9. data/lib/rails_ai_context/configuration.rb +4 -2
  10. data/lib/rails_ai_context/doctor.rb +6 -1
  11. data/lib/rails_ai_context/fingerprinter.rb +24 -0
  12. data/lib/rails_ai_context/introspectors/component_introspector.rb +122 -7
  13. data/lib/rails_ai_context/introspectors/performance_introspector.rb +31 -26
  14. data/lib/rails_ai_context/introspectors/schema_introspector.rb +183 -6
  15. data/lib/rails_ai_context/introspectors/view_introspector.rb +2 -2
  16. data/lib/rails_ai_context/introspectors/view_template_introspector.rb +61 -8
  17. data/lib/rails_ai_context/serializers/claude_rules_serializer.rb +13 -22
  18. data/lib/rails_ai_context/serializers/claude_serializer.rb +15 -3
  19. data/lib/rails_ai_context/serializers/context_file_serializer.rb +15 -3
  20. data/lib/rails_ai_context/serializers/copilot_instructions_serializer.rb +3 -3
  21. data/lib/rails_ai_context/serializers/cursor_rules_serializer.rb +5 -5
  22. data/lib/rails_ai_context/serializers/design_system_helper.rb +8 -1
  23. data/lib/rails_ai_context/serializers/opencode_rules_serializer.rb +3 -3
  24. data/lib/rails_ai_context/serializers/opencode_serializer.rb +0 -1
  25. data/lib/rails_ai_context/serializers/tool_guide_helper.rb +15 -9
  26. data/lib/rails_ai_context/server.rb +8 -1
  27. data/lib/rails_ai_context/tools/analyze_feature.rb +24 -1
  28. data/lib/rails_ai_context/tools/base_tool.rb +78 -1
  29. data/lib/rails_ai_context/tools/dependency_graph.rb +4 -1
  30. data/lib/rails_ai_context/tools/diagnose.rb +135 -8
  31. data/lib/rails_ai_context/tools/generate_test.rb +87 -7
  32. data/lib/rails_ai_context/tools/get_callbacks.rb +27 -4
  33. data/lib/rails_ai_context/tools/get_component_catalog.rb +11 -2
  34. data/lib/rails_ai_context/tools/get_context.rb +71 -8
  35. data/lib/rails_ai_context/tools/get_conventions.rb +59 -0
  36. data/lib/rails_ai_context/tools/get_design_system.rb +45 -7
  37. data/lib/rails_ai_context/tools/get_edit_context.rb +3 -2
  38. data/lib/rails_ai_context/tools/get_env.rb +51 -24
  39. data/lib/rails_ai_context/tools/get_frontend_stack.rb +100 -9
  40. data/lib/rails_ai_context/tools/get_model_details.rb +20 -0
  41. data/lib/rails_ai_context/tools/get_partial_interface.rb +12 -5
  42. data/lib/rails_ai_context/tools/get_schema.rb +1 -0
  43. data/lib/rails_ai_context/tools/get_stimulus.rb +13 -7
  44. data/lib/rails_ai_context/tools/get_turbo_map.rb +35 -2
  45. data/lib/rails_ai_context/tools/get_view.rb +65 -9
  46. data/lib/rails_ai_context/tools/migration_advisor.rb +10 -3
  47. data/lib/rails_ai_context/tools/onboard.rb +413 -27
  48. data/lib/rails_ai_context/tools/performance_check.rb +45 -28
  49. data/lib/rails_ai_context/tools/query.rb +28 -2
  50. data/lib/rails_ai_context/tools/read_logs.rb +4 -1
  51. data/lib/rails_ai_context/tools/review_changes.rb +27 -17
  52. data/lib/rails_ai_context/tools/runtime_info.rb +289 -0
  53. data/lib/rails_ai_context/tools/search_code.rb +23 -4
  54. data/lib/rails_ai_context/tools/security_scan.rb +7 -1
  55. data/lib/rails_ai_context/tools/session_context.rb +137 -0
  56. data/lib/rails_ai_context/tools/validate.rb +5 -0
  57. data/lib/rails_ai_context/version.rb +1 -1
  58. metadata +6 -4
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAiContext
4
+ module Tools
5
+ class SessionContext < BaseTool
6
+ tool_name "rails_session_context"
7
+ description "Track what you've already queried to avoid redundant calls. " \
8
+ "Use action:\"status\" to see what tools you've called, action:\"summary\" for a compressed recap, " \
9
+ "action:\"reset\" to clear session, or mark:\"tool:param\" to record a query. " \
10
+ "Helps maintain focus during long development sessions."
11
+
12
+ input_schema(
13
+ properties: {
14
+ action: {
15
+ type: "string",
16
+ enum: %w[status summary reset],
17
+ description: "status: list queried tools with timestamps. summary: compressed recap. reset: clear session."
18
+ },
19
+ mark: {
20
+ type: "string",
21
+ description: "Mark a tool+params as already queried (e.g., 'get_schema:users', 'get_model_details:User')."
22
+ }
23
+ }
24
+ )
25
+
26
+ annotations(read_only_hint: true, destructive_hint: false, idempotent_hint: false, open_world_hint: false)
27
+
28
+ def self.call(action: nil, mark: nil, server_context: nil)
29
+ unless action || mark
30
+ return text_response("Provide `action` (status/summary/reset) or `mark` (tool:param to record).")
31
+ end
32
+
33
+ if mark
34
+ tool, params = parse_mark(mark)
35
+ session_record(tool, params)
36
+ return text_response("Marked `#{tool}` with params `#{params}` as queried.")
37
+ end
38
+
39
+ case action
40
+ when "status"
41
+ render_status
42
+ when "summary"
43
+ render_summary
44
+ when "reset"
45
+ session_reset!
46
+ text_response("Session cleared. All query records removed.")
47
+ else
48
+ text_response("Unknown action: #{action}. Use status, summary, or reset.")
49
+ end
50
+ rescue => e
51
+ text_response("Session context error: #{e.message}")
52
+ end
53
+
54
+ class << self
55
+ private
56
+
57
+ def parse_mark(mark_string)
58
+ parts = mark_string.split(":", 2)
59
+ tool = parts[0]&.strip
60
+ params = parts[1]&.strip || ""
61
+ [ tool, params ]
62
+ end
63
+
64
+ def render_status
65
+ queries = session_queries
66
+ if queries.empty?
67
+ return text_response("# Session Context\n\nNo queries recorded yet. Tools will be tracked as you use them.\n\n_Use `mark:\"tool:params\"` to manually record a query._\n_Note: CLI (`rails ai:tool`) runs each call in a separate process — session tracking only works via MCP._")
68
+ end
69
+
70
+ lines = [ "# Session Context (#{queries.size} queries)", "" ]
71
+ lines << "| Tool | Params | When |"
72
+ lines << "|------|--------|------|"
73
+
74
+ queries.sort_by { |q| q[:timestamp] }.each do |q|
75
+ ago = time_ago(q[:last_timestamp] || q[:timestamp])
76
+ params_str = q[:params].is_a?(Hash) ? q[:params].map { |k, v| "#{k}:#{v}" }.join(", ") : q[:params].to_s
77
+ params_display = params_str.empty? ? "-" : params_str.truncate(40)
78
+ count = q[:call_count] || 1
79
+ count_display = count > 1 ? " (#{count}x)" : ""
80
+ lines << "| `#{q[:tool]}`#{count_display} | #{params_display} | #{ago} |"
81
+ end
82
+
83
+ lines << ""
84
+ lines << "_Use `action:\"reset\"` to clear, or `action:\"summary\"` for a compressed recap._"
85
+ lines << "_Note: CLI (`rails ai:tool`) runs each call in a separate process — session tracking only works via MCP._"
86
+ text_response(lines.join("\n"))
87
+ end
88
+
89
+ def render_summary
90
+ queries = session_queries
91
+ if queries.empty?
92
+ return text_response("No queries recorded yet.")
93
+ end
94
+
95
+ total_calls = queries.sum { |q| q[:call_count] || 1 }
96
+ unique_tools = queries.map { |q| q[:tool] }.uniq.size
97
+ lines = [ "# Session Summary", "" ]
98
+ lines << "You have made #{total_calls} tool call(s) across #{unique_tools} unique tool(s) in this session:"
99
+ lines << ""
100
+
101
+ # Group by tool name, summing actual call counts
102
+ by_tool = queries.group_by { |q| q[:tool] }
103
+ by_tool.each do |tool, entries|
104
+ total_calls = entries.sum { |e| e[:call_count] || 1 }
105
+ params_list = entries.map { |c|
106
+ p = c[:params]
107
+ p.is_a?(Hash) ? p.map { |k, v| "#{k}:#{v}" }.join(", ") : p.to_s
108
+ }.reject(&:empty?)
109
+
110
+ if params_list.any?
111
+ lines << "- **#{tool}** (#{total_calls}x): #{params_list.uniq.join('; ')}"
112
+ else
113
+ lines << "- **#{tool}** (#{total_calls}x)"
114
+ end
115
+ end
116
+
117
+ lines << ""
118
+ lines << "_Avoid re-querying these. Use `action:\"status\"` for timestamps._"
119
+ text_response(lines.join("\n"))
120
+ end
121
+
122
+ def time_ago(iso_timestamp)
123
+ diff = Time.now - Time.parse(iso_timestamp)
124
+ if diff < 60
125
+ "#{diff.to_i}s ago"
126
+ elsif diff < 3600
127
+ "#{(diff / 60).to_i}m ago"
128
+ else
129
+ "#{(diff / 3600).to_i}h ago"
130
+ end
131
+ rescue
132
+ iso_timestamp
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -48,6 +48,11 @@ module RailsAiContext
48
48
  total = 0
49
49
 
50
50
  files.each do |file|
51
+ if file.nil? || file.strip.empty?
52
+ results << "- (empty) \u2014 skipped (empty filename)"
53
+ next
54
+ end
55
+
51
56
  full_path = Rails.root.join(file)
52
57
 
53
58
  unless File.exist?(full_path)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsAiContext
4
- VERSION = "4.3.0"
4
+ VERSION = "4.3.2"
5
5
  end
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: 4.3.0
4
+ version: 4.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - crisnahine
@@ -170,7 +170,7 @@ dependencies:
170
170
  description: |
171
171
  rails-ai-context gives AI coding agents a complete mental model of your Rails
172
172
  app — not just files, but how schema, models, routes, controllers, views, and
173
- conventions connect. 37 live tools (via MCP server or CLI) let agents query
173
+ conventions connect. 39 live tools (via MCP server or CLI) let agents query
174
174
  structure on demand with semantic validation that catches cross-file errors
175
175
  (wrong columns, missing partials, broken routes) before code runs.
176
176
  Auto-generates context files for Claude Code, Cursor, GitHub Copilot, and
@@ -293,9 +293,11 @@ files:
293
293
  - lib/rails_ai_context/tools/query.rb
294
294
  - lib/rails_ai_context/tools/read_logs.rb
295
295
  - lib/rails_ai_context/tools/review_changes.rb
296
+ - lib/rails_ai_context/tools/runtime_info.rb
296
297
  - lib/rails_ai_context/tools/search_code.rb
297
298
  - lib/rails_ai_context/tools/search_docs.rb
298
299
  - lib/rails_ai_context/tools/security_scan.rb
300
+ - lib/rails_ai_context/tools/session_context.rb
299
301
  - lib/rails_ai_context/tools/validate.rb
300
302
  - lib/rails_ai_context/version.rb
301
303
  - lib/rails_ai_context/watcher.rb
@@ -315,7 +317,7 @@ post_install_message: |
315
317
  rails-ai-context installed! Quick start:
316
318
  rails generate rails_ai_context:install
317
319
  rails ai:context # generate context files
318
- rails 'ai:tool[schema]' # run any of the 37 tools from CLI
320
+ rails 'ai:tool[schema]' # run any of the 39 tools from CLI
319
321
  rails ai:serve # start MCP server (optional)
320
322
  rdoc_options: []
321
323
  require_paths:
@@ -333,6 +335,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
333
335
  requirements: []
334
336
  rubygems_version: 3.6.9
335
337
  specification_version: 4
336
- summary: Give AI agents a complete mental model of your Rails app — 37 tools via MCP
338
+ summary: Give AI agents a complete mental model of your Rails app — 39 tools via MCP
337
339
  or CLI. Zero config.
338
340
  test_files: []