rails-ai-context 0.15.4 → 0.15.5
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 +13 -0
- data/README.md +1 -1
- data/SECURITY.md +1 -1
- data/docs/GUIDE.md +30 -11
- data/lib/rails_ai_context/tools/get_controllers.rb +9 -3
- data/lib/rails_ai_context/tools/get_edit_context.rb +5 -0
- data/lib/rails_ai_context/tools/get_routes.rb +4 -3
- data/lib/rails_ai_context/tools/get_test_info.rb +5 -2
- data/lib/rails_ai_context/tools/get_view.rb +26 -0
- data/lib/rails_ai_context/tools/search_code.rb +12 -0
- data/lib/rails_ai_context/tools/validate.rb +30 -9
- data/lib/rails_ai_context/version.rb +1 -1
- data/server.json +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a9e71509ab3fcf2437fdd2616f8cb88140b478677abdd4ebd7cf6818eb8cead3
|
|
4
|
+
data.tar.gz: c6847c4a500d762665ea2493c0ee56943bfe2e601b645bf5e9ec97df81f7e495
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fb13a050a3e8200d1bac5f8d0d59bc1a67469a3fbe904682824541430f9f10755197fa3bd17858c08a2eedcc89f71c9da2dfffea8a8bcd0c177784f85ef511c6
|
|
7
|
+
data.tar.gz: 4e05a8e22c395b4091d336268aa3e3994f416b11d174e63d922b5979b46695a222176a0871253ddd940638ead977e2917d14998618a91c25ad4a6f891eca9694
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.15.5] - 2026-03-22
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **ERB validation** — now catches missing `<% end %>` by compiling ERB to Ruby then syntax-checking the result (was only checking ERB tag syntax).
|
|
13
|
+
- **Controller namespace format** — accepts both `Bonus::CrisesController` and `bonus/crises` (cross-tool consistency).
|
|
14
|
+
- **Layouts discoverable** — `controller:"layouts"` now works in view tool.
|
|
15
|
+
- **Validate error detail** — Ruby shows up to 5 error lines, JS shows 3 (was truncated to 1).
|
|
16
|
+
- **Invalid/empty regex** — early validation with clear error messages instead of silent fail.
|
|
17
|
+
- **Route count accuracy** — shows filtered count when `app_only:true`, not unfiltered total.
|
|
18
|
+
- **Namespace test lookup** — supports `bonus/crises` format and flat test directories.
|
|
19
|
+
- **Empty inputs** — `near:""` in edit_context and `pattern:""` in search return helpful errors.
|
|
20
|
+
|
|
8
21
|
## [0.15.4] - 2026-03-22
|
|
9
22
|
|
|
10
23
|
### Fixed
|
data/README.md
CHANGED
|
@@ -302,7 +302,7 @@ end
|
|
|
302
302
|
| `max_tool_response_chars` | `120_000` | Safety cap for MCP tool responses |
|
|
303
303
|
| `excluded_models` | internal Rails models | Models to skip during introspection |
|
|
304
304
|
| `excluded_paths` | `node_modules tmp log vendor .git` | Paths excluded from code search |
|
|
305
|
-
| `sensitive_patterns` | `.env .env.*
|
|
305
|
+
| `sensitive_patterns` | `.env .env.* config/master.key config/credentials.yml.enc config/credentials/*.yml.enc *.pem *.key` | File patterns blocked from search and read tools |
|
|
306
306
|
| `auto_mount` | `false` | Auto-mount HTTP MCP endpoint |
|
|
307
307
|
| `http_path` | `"/mcp"` | HTTP endpoint path |
|
|
308
308
|
| `http_port` | `6029` | HTTP server port |
|
data/SECURITY.md
CHANGED
data/docs/GUIDE.md
CHANGED
|
@@ -146,22 +146,23 @@ end
|
|
|
146
146
|
| `app/models/AGENTS.md` | Model reference | Auto-loaded by OpenCode when reading files in `app/models/`. |
|
|
147
147
|
| `app/controllers/AGENTS.md` | Controller reference | Auto-loaded by OpenCode when reading files in `app/controllers/`. |
|
|
148
148
|
|
|
149
|
-
### Cursor (
|
|
149
|
+
### Cursor (5 files)
|
|
150
150
|
|
|
151
151
|
| File | Purpose | Notes |
|
|
152
152
|
|------|---------|-------|
|
|
153
153
|
| `.cursor/rules/rails-project.mdc` | Project overview | `alwaysApply: true` — loaded in every conversation. |
|
|
154
154
|
| `.cursor/rules/rails-models.mdc` | Model reference | `globs: app/models/**/*.rb` — auto-attaches when editing models. |
|
|
155
155
|
| `.cursor/rules/rails-controllers.mdc` | Controller reference | `globs: app/controllers/**/*.rb` — auto-attaches when editing controllers. |
|
|
156
|
-
| `.cursor/rules/rails-ui-patterns.mdc` | UI patterns and design tokens | `
|
|
156
|
+
| `.cursor/rules/rails-ui-patterns.mdc` | UI patterns and design tokens | `globs: app/views/**/*.erb` — loaded when editing views. |
|
|
157
157
|
| `.cursor/rules/rails-mcp-tools.mdc` | MCP tool reference | `alwaysApply: true` — always available. |
|
|
158
158
|
|
|
159
|
-
### Windsurf (
|
|
159
|
+
### Windsurf (4 files)
|
|
160
160
|
|
|
161
161
|
| File | Purpose | Notes |
|
|
162
162
|
|------|---------|-------|
|
|
163
163
|
| `.windsurfrules` | Main context file | Hard-capped at 5,800 chars (Windsurf's 6K limit). Truncated silently if exceeded. |
|
|
164
164
|
| `.windsurf/rules/rails-context.md` | Project overview | New Windsurf rules format. |
|
|
165
|
+
| `.windsurf/rules/rails-ui-patterns.md` | UI patterns and design tokens | Loaded when editing views. |
|
|
165
166
|
| `.windsurf/rules/rails-mcp-tools.md` | MCP tool reference | Compact — respects 6K per-file limit. |
|
|
166
167
|
|
|
167
168
|
### GitHub Copilot (6 files)
|
|
@@ -172,7 +173,7 @@ end
|
|
|
172
173
|
| `.github/instructions/rails-models.instructions.md` | Model context | `applyTo: app/models/**/*.rb` — loaded when editing models. |
|
|
173
174
|
| `.github/instructions/rails-controllers.instructions.md` | Controller context | `applyTo: app/controllers/**/*.rb` — loaded when editing controllers. |
|
|
174
175
|
| `.github/instructions/rails-context.instructions.md` | Project context and conventions | `applyTo: **/*` — loaded everywhere. |
|
|
175
|
-
| `.github/instructions/rails-ui-patterns.instructions.md` | UI patterns and design tokens | `applyTo:
|
|
176
|
+
| `.github/instructions/rails-ui-patterns.instructions.md` | UI patterns and design tokens | `applyTo: app/views/**/*.erb` — loaded when editing views. |
|
|
176
177
|
| `.github/instructions/rails-mcp-tools.instructions.md` | MCP tool reference | `applyTo: **/*` — loaded everywhere. |
|
|
177
178
|
|
|
178
179
|
### Generic (1 file)
|
|
@@ -359,8 +360,11 @@ Returns controller details: actions, filters, strong params, concerns.
|
|
|
359
360
|
|
|
360
361
|
| Param | Type | Description |
|
|
361
362
|
|-------|------|-------------|
|
|
362
|
-
| `controller` | string | Specific controller name (e.g. `UsersController`). Case-insensitive. |
|
|
363
|
+
| `controller` | string | Specific controller name (e.g. `UsersController`, `cooks`, `bonus/crises`). Case-insensitive, flexible format. |
|
|
364
|
+
| `action` | string | Specific action (e.g. `index`). Requires controller. Returns source code with applicable filters. |
|
|
363
365
|
| `detail` | string | `summary` / `standard` (default) / `full`. Ignored when controller is specified. |
|
|
366
|
+
| `limit` | integer | Max controllers to return when listing. Default: 50. |
|
|
367
|
+
| `offset` | integer | Skip this many controllers for pagination. Default: 0. |
|
|
364
368
|
|
|
365
369
|
**Examples:**
|
|
366
370
|
|
|
@@ -382,7 +386,7 @@ rails_get_controllers(detail: "full")
|
|
|
382
386
|
|
|
383
387
|
Returns application configuration. No parameters.
|
|
384
388
|
|
|
385
|
-
**Returns:** cache store, session store, timezone,
|
|
389
|
+
**Returns:** cache store, session store, timezone, queue adapter, mailer settings, custom middleware, initializers, current attributes.
|
|
386
390
|
|
|
387
391
|
```
|
|
388
392
|
rails_get_config()
|
|
@@ -391,20 +395,35 @@ rails_get_config()
|
|
|
391
395
|
|
|
392
396
|
### rails_get_test_info
|
|
393
397
|
|
|
394
|
-
Returns test infrastructure details.
|
|
398
|
+
Returns test infrastructure details. Optionally filter by model or controller to find existing tests.
|
|
395
399
|
|
|
396
|
-
**
|
|
400
|
+
**Parameters:**
|
|
401
|
+
|
|
402
|
+
| Param | Type | Description |
|
|
403
|
+
|-------|------|-------------|
|
|
404
|
+
| `model` | string | Show tests for a specific model (e.g. `User`). |
|
|
405
|
+
| `controller` | string | Show tests for a specific controller (e.g. `Cooks`). |
|
|
406
|
+
| `detail` | string | `summary` / `standard` (default) / `full`. |
|
|
397
407
|
|
|
398
408
|
```
|
|
399
409
|
rails_get_test_info()
|
|
400
|
-
→ Framework: rspec, Factories: spec/factories (12 files), CI: .github/workflows/ci.yml
|
|
410
|
+
→ Framework: rspec, Factories: spec/factories (12 files), CI: .github/workflows/ci.yml
|
|
411
|
+
|
|
412
|
+
rails_get_test_info(model: "User")
|
|
413
|
+
→ Shows spec/models/user_spec.rb test names (summary/standard) or full source (full)
|
|
401
414
|
```
|
|
402
415
|
|
|
403
416
|
### rails_get_gems
|
|
404
417
|
|
|
405
|
-
Returns notable gems categorized by function.
|
|
418
|
+
Returns notable gems categorized by function.
|
|
419
|
+
|
|
420
|
+
**Parameters:**
|
|
421
|
+
|
|
422
|
+
| Param | Type | Description |
|
|
423
|
+
|-------|------|-------------|
|
|
424
|
+
| `category` | string | Filter by category: `auth`, `jobs`, `frontend`, `api`, `database`, `files`, `testing`, `deploy`, `all` (default). |
|
|
406
425
|
|
|
407
|
-
**Returns:**
|
|
426
|
+
**Returns:** Notable gems grouped by category with descriptions.
|
|
408
427
|
|
|
409
428
|
```
|
|
410
429
|
rails_get_gems()
|
|
@@ -48,13 +48,19 @@ module RailsAiContext
|
|
|
48
48
|
# Specific controller — always full detail (searches ALL controllers including framework)
|
|
49
49
|
# Flexible matching: "cooks", "CooksController", "cookscontroller" all work
|
|
50
50
|
if controller
|
|
51
|
-
|
|
51
|
+
# Accept multiple formats: "CooksController", "cooks", "bonus/crises", "Bonus::CrisesController"
|
|
52
|
+
normalized = controller.downcase.delete_suffix("controller").tr("/", "::")
|
|
52
53
|
key = controllers.keys.find { |k|
|
|
53
54
|
kd = k.downcase
|
|
54
|
-
kd == controller.downcase ||
|
|
55
|
+
kd == controller.downcase ||
|
|
56
|
+
kd.delete_suffix("controller") == normalized ||
|
|
57
|
+
kd.delete_suffix("controller").tr("::", "/") == controller.downcase.delete_suffix("controller")
|
|
55
58
|
} || controller
|
|
56
59
|
info = controllers[key]
|
|
57
|
-
|
|
60
|
+
unless info
|
|
61
|
+
available = app_controller_names.any? ? "Available: #{app_controller_names.join(', ')}" : "No controllers discovered."
|
|
62
|
+
return text_response("Controller '#{controller}' not found. #{available}")
|
|
63
|
+
end
|
|
58
64
|
return text_response("Error inspecting #{key}: #{info[:error]}") if info[:error]
|
|
59
65
|
|
|
60
66
|
# Specific action — return source code
|
|
@@ -32,6 +32,11 @@ module RailsAiContext
|
|
|
32
32
|
SENSITIVE_PATTERNS = nil # uses configuration.sensitive_patterns
|
|
33
33
|
|
|
34
34
|
def self.call(file:, near:, context_lines: 5, server_context: nil)
|
|
35
|
+
# Reject empty search term
|
|
36
|
+
if near.nil? || near.strip.empty?
|
|
37
|
+
return text_response("The `near` parameter is required. Provide a method name, keyword, or string to find.")
|
|
38
|
+
end
|
|
39
|
+
|
|
35
40
|
full_path = Rails.root.join(file)
|
|
36
41
|
|
|
37
42
|
# Block access to sensitive files (secrets, keys, credentials)
|
|
@@ -65,6 +65,7 @@ module RailsAiContext
|
|
|
65
65
|
|
|
66
66
|
# Combine PUT/PATCH duplicates (Rails generates both for update routes)
|
|
67
67
|
by_controller = by_controller.transform_values { |actions| dedupe_put_patch(actions) }
|
|
68
|
+
filtered_total = by_controller.values.sum(&:size)
|
|
68
69
|
|
|
69
70
|
case detail
|
|
70
71
|
when "summary"
|
|
@@ -72,7 +73,7 @@ module RailsAiContext
|
|
|
72
73
|
app_routes = controller ? by_controller : by_controller.reject { |k, _| FRAMEWORK_PREFIXES.any? { |p| k.downcase.start_with?(p) } }
|
|
73
74
|
framework_routes = controller ? {} : by_controller.select { |k, _| FRAMEWORK_PREFIXES.any? { |p| k.downcase.start_with?(p) } }
|
|
74
75
|
|
|
75
|
-
lines = [ "# Routes Summary (#{
|
|
76
|
+
lines = [ "# Routes Summary (#{filtered_total} routes)", "" ]
|
|
76
77
|
|
|
77
78
|
# Group sibling routes with identical verb patterns (e.g., bonus/*)
|
|
78
79
|
grouped = app_routes.keys.sort.group_by do |ctrl|
|
|
@@ -118,7 +119,7 @@ module RailsAiContext
|
|
|
118
119
|
app_routes = controller ? by_controller : by_controller.reject { |k, _| FRAMEWORK_PREFIXES.any? { |p| k.downcase.start_with?(p) } }
|
|
119
120
|
framework_routes = controller ? {} : by_controller.select { |k, _| FRAMEWORK_PREFIXES.any? { |p| k.downcase.start_with?(p) } }
|
|
120
121
|
|
|
121
|
-
lines = [ "# Routes (#{
|
|
122
|
+
lines = [ "# Routes (#{filtered_total} routes)", "" ]
|
|
122
123
|
count = 0
|
|
123
124
|
|
|
124
125
|
# Group identical sibling route sets (e.g. bonus/*)
|
|
@@ -181,7 +182,7 @@ module RailsAiContext
|
|
|
181
182
|
when "full"
|
|
182
183
|
# Existing full table behavior
|
|
183
184
|
limit ||= 200
|
|
184
|
-
lines = [ "# Routes Full Detail (#{
|
|
185
|
+
lines = [ "# Routes Full Detail (#{filtered_total} routes)", "" ]
|
|
185
186
|
lines << "| Verb | Path | Controller#Action | Name |"
|
|
186
187
|
lines << "|------|------|-------------------|------|"
|
|
187
188
|
count = 0
|
|
@@ -122,7 +122,8 @@ module RailsAiContext
|
|
|
122
122
|
MAX_TEST_FILE_SIZE = 500_000 # 500KB safety limit
|
|
123
123
|
|
|
124
124
|
private_class_method def self.find_test_file(name, type, detail = "full")
|
|
125
|
-
|
|
125
|
+
# Normalize: accept "Bonus::CrisesController", "bonus/crises", "Crises"
|
|
126
|
+
snake = name.to_s.tr("/", "::").underscore.sub(/_controller$/, "")
|
|
126
127
|
candidates = case type
|
|
127
128
|
when :model
|
|
128
129
|
[
|
|
@@ -133,7 +134,9 @@ module RailsAiContext
|
|
|
133
134
|
[
|
|
134
135
|
"spec/controllers/#{snake}_controller_spec.rb",
|
|
135
136
|
"spec/requests/#{snake}_spec.rb",
|
|
136
|
-
"test/controllers/#{snake}_controller_test.rb"
|
|
137
|
+
"test/controllers/#{snake}_controller_test.rb",
|
|
138
|
+
# Also try without namespace prefix for flat test dirs
|
|
139
|
+
"spec/requests/#{snake.split('/').last}_spec.rb"
|
|
137
140
|
]
|
|
138
141
|
end
|
|
139
142
|
|
|
@@ -43,6 +43,11 @@ module RailsAiContext
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
# Filter by controller (also checks partials for directories like "shared/")
|
|
46
|
+
# Special case: "layouts" reads from app/views/layouts/ (excluded from normal listing)
|
|
47
|
+
if controller&.downcase == "layouts"
|
|
48
|
+
return list_layouts(detail)
|
|
49
|
+
end
|
|
50
|
+
|
|
46
51
|
if controller
|
|
47
52
|
ctrl_lower = controller.downcase
|
|
48
53
|
filtered_templates = templates.select { |k, _| k.downcase.start_with?(ctrl_lower + "/") }
|
|
@@ -135,6 +140,27 @@ module RailsAiContext
|
|
|
135
140
|
end
|
|
136
141
|
end
|
|
137
142
|
|
|
143
|
+
private_class_method def self.list_layouts(detail)
|
|
144
|
+
layouts_dir = Rails.root.join("app", "views", "layouts")
|
|
145
|
+
return text_response("No app/views/layouts/ directory found.") unless Dir.exist?(layouts_dir)
|
|
146
|
+
|
|
147
|
+
files = Dir.glob(File.join(layouts_dir, "*")).reject { |f| File.directory?(f) }.sort
|
|
148
|
+
return text_response("No layout files found.") if files.empty?
|
|
149
|
+
|
|
150
|
+
lines = [ "# Layouts (#{files.size} files)", "" ]
|
|
151
|
+
files.each do |path|
|
|
152
|
+
relative = "layouts/#{File.basename(path)}"
|
|
153
|
+
if detail == "full"
|
|
154
|
+
content = File.read(path, encoding: "UTF-8", invalid: :replace, undef: :replace) rescue "(error reading)"
|
|
155
|
+
lines << "## #{relative}" << "```erb" << strip_svg(content) << "```" << ""
|
|
156
|
+
else
|
|
157
|
+
line_count = (File.readlines(path).size rescue 0)
|
|
158
|
+
lines << "- #{relative} (#{line_count} lines)"
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
text_response(lines.join("\n"))
|
|
162
|
+
end
|
|
163
|
+
|
|
138
164
|
MAX_FILE_SIZE = 2_000_000 # 2MB safety limit
|
|
139
165
|
|
|
140
166
|
private_class_method def self.read_view_file(path)
|
|
@@ -41,6 +41,18 @@ module RailsAiContext
|
|
|
41
41
|
def self.call(pattern:, path: nil, file_type: nil, max_results: 30, context_lines: 0, server_context: nil)
|
|
42
42
|
root = Rails.root.to_s
|
|
43
43
|
|
|
44
|
+
# Reject empty or whitespace-only patterns
|
|
45
|
+
if pattern.nil? || pattern.strip.empty?
|
|
46
|
+
return text_response("Pattern is required. Provide a search term or regex.")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Validate regex syntax early
|
|
50
|
+
begin
|
|
51
|
+
Regexp.new(pattern, timeout: 1)
|
|
52
|
+
rescue RegexpError => e
|
|
53
|
+
return text_response("Invalid regex pattern: #{e.message}")
|
|
54
|
+
end
|
|
55
|
+
|
|
44
56
|
# Validate file_type to prevent injection
|
|
45
57
|
if file_type && !file_type.match?(/\A[a-zA-Z0-9]+\z/)
|
|
46
58
|
return text_response("Invalid file_type: must contain only alphanumeric characters.")
|
|
@@ -93,20 +93,37 @@ module RailsAiContext
|
|
|
93
93
|
if status.success?
|
|
94
94
|
[ true, nil ]
|
|
95
95
|
else
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
# Show up to 5 non-empty error lines for full context (ruby -c gives multi-line errors)
|
|
97
|
+
error_lines = result.lines
|
|
98
|
+
.reject { |l| l.strip.empty? || l.include?("Syntax OK") }
|
|
99
|
+
.first(5)
|
|
100
|
+
.map { |l| l.strip.sub(full_path.to_s, File.basename(full_path.to_s)) }
|
|
101
|
+
error = error_lines.any? ? error_lines.join("\n") : "syntax error"
|
|
98
102
|
[ false, error ]
|
|
99
103
|
end
|
|
100
104
|
end
|
|
101
105
|
|
|
102
|
-
# Validate ERB
|
|
106
|
+
# Validate ERB by compiling to Ruby source then syntax-checking the result.
|
|
107
|
+
# ERB.new(...).src only validates ERB tag syntax — it does NOT catch missing <% end %>.
|
|
108
|
+
# So we compile to Ruby, then run ruby -c on the compiled output to catch block mismatches.
|
|
103
109
|
private_class_method def self.validate_erb(full_path)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
110
|
+
# Step 1: Compile ERB to Ruby source
|
|
111
|
+
compile_script = "require 'erb'; print ERB.new(File.read(ARGV[0])).src"
|
|
112
|
+
compiled, compile_status = Open3.capture2e("ruby", "-e", compile_script, full_path.to_s)
|
|
113
|
+
|
|
114
|
+
unless compile_status.success?
|
|
115
|
+
error = compiled.lines.reject { |l| l.strip.empty? }.first&.strip || "ERB syntax error"
|
|
116
|
+
return [ false, error ]
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Step 2: Syntax-check the compiled Ruby to catch missing end, unclosed blocks, etc.
|
|
120
|
+
check_result, check_status = Open3.capture2e("ruby", "-c", "-", stdin_data: compiled)
|
|
121
|
+
if check_status.success?
|
|
107
122
|
[ true, nil ]
|
|
108
123
|
else
|
|
109
|
-
error =
|
|
124
|
+
error = check_result.lines.reject { |l| l.strip.empty? || l.include?("Syntax OK") }.first&.strip || "ERB error"
|
|
125
|
+
# Make the error more helpful — it's from compiled source, translate back
|
|
126
|
+
error = error.sub(/^-:/, "compiled ERB line ")
|
|
110
127
|
[ false, error ]
|
|
111
128
|
end
|
|
112
129
|
end
|
|
@@ -120,8 +137,12 @@ module RailsAiContext
|
|
|
120
137
|
if status.success?
|
|
121
138
|
[ true, nil ]
|
|
122
139
|
else
|
|
123
|
-
|
|
124
|
-
|
|
140
|
+
# Show up to 3 non-empty error lines for context
|
|
141
|
+
error_lines = result.lines
|
|
142
|
+
.reject { |l| l.strip.empty? }
|
|
143
|
+
.first(3)
|
|
144
|
+
.map { |l| l.strip.sub(full_path.to_s, File.basename(full_path.to_s)) }
|
|
145
|
+
error = error_lines.any? ? error_lines.join("\n") : "syntax error"
|
|
125
146
|
[ false, error ]
|
|
126
147
|
end
|
|
127
148
|
else
|
data/server.json
CHANGED
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
"url": "https://github.com/crisnahine/rails-ai-context",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "0.15.
|
|
10
|
+
"version": "0.15.4",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "mcpb",
|
|
14
|
-
"identifier": "https://github.com/crisnahine/rails-ai-context/releases/download/v0.15.
|
|
14
|
+
"identifier": "https://github.com/crisnahine/rails-ai-context/releases/download/v0.15.4/rails-ai-context-mcp.mcpb",
|
|
15
15
|
"fileSha256": "dd711a0ad6c4de943ae4da94eaf59a6dc9494b9d57f726e24649ed4e2f156990",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|