rails-ai-bridge 1.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/.rubocop.yml +23 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +259 -0
- data/CLAUDE.md +55 -0
- data/CODE_OF_CONDUCT.md +44 -0
- data/CONTRIBUTING.md +89 -0
- data/LICENSE +21 -0
- data/README.md +476 -0
- data/Rakefile +8 -0
- data/SECURITY.md +50 -0
- data/docs/COVERAGE.md +52 -0
- data/docs/GUIDE.md +920 -0
- data/exe/rails-ai-bridge +95 -0
- data/lib/generators/rails_ai_bridge/README.md +29 -0
- data/lib/generators/rails_ai_bridge/install/install_generator.rb +169 -0
- data/lib/generators/rails_ai_bridge/install/templates/overrides.md.example +31 -0
- data/lib/rails-ai-bridge.rb +5 -0
- data/lib/rails_ai_bridge/README.md +37 -0
- data/lib/rails_ai_bridge/configuration.rb +120 -0
- data/lib/rails_ai_bridge/context_provider.rb +123 -0
- data/lib/rails_ai_bridge/doctor.rb +228 -0
- data/lib/rails_ai_bridge/engine.rb +31 -0
- data/lib/rails_ai_bridge/fingerprinter.rb +61 -0
- data/lib/rails_ai_bridge/http_transport_app.rb +27 -0
- data/lib/rails_ai_bridge/introspector.rb +93 -0
- data/lib/rails_ai_bridge/introspectors/README.md +43 -0
- data/lib/rails_ai_bridge/introspectors/action_mailbox_introspector.rb +50 -0
- data/lib/rails_ai_bridge/introspectors/action_text_introspector.rb +48 -0
- data/lib/rails_ai_bridge/introspectors/active_storage_introspector.rb +81 -0
- data/lib/rails_ai_bridge/introspectors/api_introspector.rb +92 -0
- data/lib/rails_ai_bridge/introspectors/asset_pipeline_introspector.rb +92 -0
- data/lib/rails_ai_bridge/introspectors/auth_introspector.rb +115 -0
- data/lib/rails_ai_bridge/introspectors/config_introspector.rb +88 -0
- data/lib/rails_ai_bridge/introspectors/controller_introspector.rb +135 -0
- data/lib/rails_ai_bridge/introspectors/convention_detector.rb +144 -0
- data/lib/rails_ai_bridge/introspectors/database_stats_introspector.rb +39 -0
- data/lib/rails_ai_bridge/introspectors/devops_introspector.rb +111 -0
- data/lib/rails_ai_bridge/introspectors/engine_introspector.rb +111 -0
- data/lib/rails_ai_bridge/introspectors/gem_introspector.rb +178 -0
- data/lib/rails_ai_bridge/introspectors/i18n_introspector.rb +66 -0
- data/lib/rails_ai_bridge/introspectors/job_introspector.rb +82 -0
- data/lib/rails_ai_bridge/introspectors/middleware_introspector.rb +98 -0
- data/lib/rails_ai_bridge/introspectors/migration_introspector.rb +127 -0
- data/lib/rails_ai_bridge/introspectors/model_introspector.rb +205 -0
- data/lib/rails_ai_bridge/introspectors/multi_database_introspector.rb +144 -0
- data/lib/rails_ai_bridge/introspectors/rake_task_introspector.rb +68 -0
- data/lib/rails_ai_bridge/introspectors/route_introspector.rb +83 -0
- data/lib/rails_ai_bridge/introspectors/schema_introspector.rb +143 -0
- data/lib/rails_ai_bridge/introspectors/seeds_introspector.rb +89 -0
- data/lib/rails_ai_bridge/introspectors/stimulus_introspector.rb +81 -0
- data/lib/rails_ai_bridge/introspectors/test_introspector.rb +137 -0
- data/lib/rails_ai_bridge/introspectors/turbo_introspector.rb +80 -0
- data/lib/rails_ai_bridge/introspectors/view_introspector.rb +130 -0
- data/lib/rails_ai_bridge/mcp_http_auth.rb +69 -0
- data/lib/rails_ai_bridge/middleware.rb +42 -0
- data/lib/rails_ai_bridge/resources.rb +240 -0
- data/lib/rails_ai_bridge/serializers/README.md +36 -0
- data/lib/rails_ai_bridge/serializers/claude_rules_serializer.rb +147 -0
- data/lib/rails_ai_bridge/serializers/claude_serializer.rb +285 -0
- data/lib/rails_ai_bridge/serializers/codex_serializer.rb +150 -0
- data/lib/rails_ai_bridge/serializers/codex_support_serializer.rb +64 -0
- data/lib/rails_ai_bridge/serializers/context_file_serializer.rb +108 -0
- data/lib/rails_ai_bridge/serializers/context_summary.rb +71 -0
- data/lib/rails_ai_bridge/serializers/copilot_instructions_serializer.rb +143 -0
- data/lib/rails_ai_bridge/serializers/copilot_serializer.rb +171 -0
- data/lib/rails_ai_bridge/serializers/cursor_rules_serializer.rb +218 -0
- data/lib/rails_ai_bridge/serializers/json_serializer.rb +19 -0
- data/lib/rails_ai_bridge/serializers/markdown_serializer.rb +505 -0
- data/lib/rails_ai_bridge/serializers/rules_serializer.rb +157 -0
- data/lib/rails_ai_bridge/serializers/shared_assistant_guidance.rb +158 -0
- data/lib/rails_ai_bridge/serializers/windsurf_rules_serializer.rb +84 -0
- data/lib/rails_ai_bridge/serializers/windsurf_serializer.rb +96 -0
- data/lib/rails_ai_bridge/server.rb +97 -0
- data/lib/rails_ai_bridge/tasks/rails_ai_bridge.rake +183 -0
- data/lib/rails_ai_bridge/tools/README.md +46 -0
- data/lib/rails_ai_bridge/tools/base_tool.rb +60 -0
- data/lib/rails_ai_bridge/tools/get_config.rb +42 -0
- data/lib/rails_ai_bridge/tools/get_controllers.rb +111 -0
- data/lib/rails_ai_bridge/tools/get_conventions.rb +88 -0
- data/lib/rails_ai_bridge/tools/get_gems.rb +50 -0
- data/lib/rails_ai_bridge/tools/get_model_details.rb +144 -0
- data/lib/rails_ai_bridge/tools/get_routes.rb +109 -0
- data/lib/rails_ai_bridge/tools/get_schema.rb +156 -0
- data/lib/rails_ai_bridge/tools/get_stimulus.rb +129 -0
- data/lib/rails_ai_bridge/tools/get_test_info.rb +35 -0
- data/lib/rails_ai_bridge/tools/get_view.rb +227 -0
- data/lib/rails_ai_bridge/tools/search_code.rb +204 -0
- data/lib/rails_ai_bridge/version.rb +5 -0
- data/lib/rails_ai_bridge/view_file_analyzer.rb +61 -0
- data/lib/rails_ai_bridge/watcher.rb +75 -0
- data/lib/rails_ai_bridge.rb +103 -0
- data/rails-ai-bridge.gemspec +65 -0
- data/resume.md +181 -0
- data/server.json +12 -0
- metadata +319 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 94459120e6365ac608ed9a403e16a622e7ef664b377f8585980827c28dd911f0
|
|
4
|
+
data.tar.gz: e3561760ceb930242a6d344ae3938dfdca49879639e7776a19cc2fa08adff4eb
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c595b9b20dc56cef6adf370d931f06083137691cd5323dd8fe43615eba819eb7d725d5ee62160c0305fb311f3d2592ad767cd2eb8b69bfc3f075aae380b9209e
|
|
7
|
+
data.tar.gz: d6ee1293103eccc654bbed37f67b9deb022ecede51ee8bc4f4714db86f7f18d73a3ebe0054d86c6c8350107dd1bf6239520ff137c5b828faeb75152095c158bd
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
inherit_gem:
|
|
2
|
+
rubocop-rails-omakase: rubocop.yml
|
|
3
|
+
|
|
4
|
+
AllCops:
|
|
5
|
+
TargetRubyVersion: 3.2
|
|
6
|
+
NewCops: enable
|
|
7
|
+
Exclude:
|
|
8
|
+
- "spec/fixtures/**/*"
|
|
9
|
+
- "vendor/**/*"
|
|
10
|
+
|
|
11
|
+
Style/Documentation:
|
|
12
|
+
Enabled: false
|
|
13
|
+
|
|
14
|
+
Metrics/MethodLength:
|
|
15
|
+
Max: 25
|
|
16
|
+
|
|
17
|
+
Metrics/ClassLength:
|
|
18
|
+
Max: 200
|
|
19
|
+
|
|
20
|
+
Metrics/BlockLength:
|
|
21
|
+
Exclude:
|
|
22
|
+
- "spec/**/*"
|
|
23
|
+
- "*.gemspec"
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.4.9
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Shared runtime context provider** — MCP tools and `rails://...` resources now read through `RailsAiBridge::ContextProvider`, keeping cache invalidation and snapshot semantics aligned across both entry points.
|
|
13
|
+
- **Explicit extension registries** — `config.additional_introspectors`, `config.additional_tools`, and `config.additional_resources` allow host apps or companion gems to extend the built-ins without patching core constants.
|
|
14
|
+
- **HTTP transport Rack builder** — `RailsAiBridge::HttpTransportApp` centralizes HTTP MCP request handling for both standalone server mode and middleware auto-mount.
|
|
15
|
+
- **Section-level context reads** — `ContextProvider.fetch_section` and `BaseTool.cached_section` let single-section tools avoid rebuilding or materializing the full snapshot path when unnecessary.
|
|
16
|
+
- **Folder-level contributor docs** — key runtime folders now include local `README.md` guides for structure, boundaries, and extension points.
|
|
17
|
+
- **Extensibility integration coverage** — specs now prove that a custom introspector, tool, and resource can be registered and used together from the host app configuration surface.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **Install generator messages** — the install flow now reports created vs unchanged files correctly and the generated initializer comments reflect the current preset sizes.
|
|
22
|
+
- **Fingerprint reuse on invalidation** — context refresh reuses a single fingerprint snapshot per fetch cycle instead of scanning twice when cached context becomes stale.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **Install generator output bug** — `generate_context` results are no longer iterated as raw hash pairs during install-time file generation.
|
|
27
|
+
|
|
28
|
+
## [1.1.0] - 2026-03-20
|
|
29
|
+
|
|
30
|
+
### Security
|
|
31
|
+
|
|
32
|
+
- **HTTP MCP authentication** — Optional Bearer token via `config.http_mcp_token` or `ENV["RAILS_AI_BRIDGE_MCP_TOKEN"]` (ENV wins when set). When a token is configured, `auto_mount` and `rails ai:serve_http` require `Authorization: Bearer <token>`.
|
|
33
|
+
- **Production guards** — `config.auto_mount = true` in production raises at boot unless `config.allow_auto_mount_in_production = true` and a non-empty MCP token is set. `rails ai:serve_http` in production requires a token.
|
|
34
|
+
- **`rails_search_code` allowlist** — `file_type` must be an allowed extension (default: `rb`, `erb`, `js`, `ts`, `jsx`, `tsx`, `yml`, `yaml`, `json`). Extra extensions: `config.search_code_allowed_file_types`. Unrestricted search uses only those extensions; ripgrep/Ruby paths also exclude common secret filenames (e.g. `.env*`, `*.key`, `*.pem`).
|
|
35
|
+
- **Credentials metadata** — `credentials_keys` is omitted from config introspection and the `rails://config` MCP resource unless `config.expose_credentials_key_names = true`.
|
|
36
|
+
|
|
37
|
+
## [1.0.0] - 2026-03-18
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- **First release as `rails-ai-bridge`** — Ruby gem and GitHub project renamed from `rails-ai-context`; public constant namespace is **`RailsAiBridge`**. Install with `rails generate rails_ai_bridge:install`. Host paths: `config/initializers/rails_ai_bridge.rb`, `config/rails_ai_bridge/overrides.md`, `.mcp.json` server key `rails-ai-bridge`, CLI `exe/rails-ai-bridge`. **Breaking:** no compatibility shim for the old gem name or paths.
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
|
|
45
|
+
- **`RailsAiBridge::Serializers::SharedAssistantGuidance`** — shared engineering rules, Rails performance pattern examples, optional **`config/rails_ai_bridge/overrides.md`** merge into compact Copilot + Codex, and Cursor `rails-engineering.mdc` body.
|
|
46
|
+
- **Cursor `rails-engineering.mdc`** — `alwaysApply: true` engineering essentials + pointers to full `copilot-instructions.md` / `AGENTS.md` and MCP rules.
|
|
47
|
+
- **Configuration** — `assistant_overrides_path`, `copilot_compact_model_list_limit` (default 5), `codex_compact_model_list_limit` (default 3); `0` lists no model names (MCP-only pointer).
|
|
48
|
+
- **Install generator** — creates `config/rails_ai_bridge/overrides.md` stub and `overrides.md.example` when missing.
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
|
|
52
|
+
- **Overrides stub** — install stub uses `<!-- rails-ai-bridge:omit-merge -->`; overrides are **not** merged into Copilot/Codex until that line is removed.
|
|
53
|
+
- **Consistent controller counts in compact output** — stack summaries use the controller introspector for the primary count (aligned with split rules); when routing lists more controller names than `app/controllers` classes, both counts are shown.
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
|
|
57
|
+
- **Compact guidance** — `CLAUDE.md`, Copilot compact instructions, and `AGENTS.md` include a performance/security baseline and note that generated files are snapshots; `.codex/README.md` documents re-merging team rules.
|
|
58
|
+
- **Copilot compact** — `.github/copilot-instructions.md` leads with **Engineering rules** before stack inventory; MCP section notes path-scoped files under `.github/instructions/` and `.cursor/rules/`.
|
|
59
|
+
- **Copilot / Codex / `.cursorrules` order** — engineering rules → stack → optional repo-specific → performance + **Rails patterns** → trimmed models → MCP.
|
|
60
|
+
- **Legacy `.cursorrules`** — same ordering; model list uses `copilot_compact_model_list_limit`.
|
|
61
|
+
- **`rails-project.mdc`** — uses `ContextSummary.routes_stack_line`; caps gem categories; references `rails-engineering.mdc`.
|
|
62
|
+
|
|
63
|
+
## [0.8.0] - 2026-03-19
|
|
64
|
+
|
|
65
|
+
### Added
|
|
66
|
+
|
|
67
|
+
- **OpenAI Codex support** via `AGENTS.md`, `.codex/README.md`, and `rails ai:context:codex`.
|
|
68
|
+
- **Codex serializer integration** in the context file pipeline so `format: :all` now includes Codex output.
|
|
69
|
+
|
|
70
|
+
### Fixed
|
|
71
|
+
|
|
72
|
+
- **`rails_search_code` invalid regex handling** — the Ruby fallback path now returns a controlled error response instead of raising `RegexpError`.
|
|
73
|
+
|
|
74
|
+
### Changed
|
|
75
|
+
|
|
76
|
+
- **Fork metadata** — gemspec, `server.json`, README, CONTRIBUTING, SECURITY, and CODE_OF_CONDUCT now point to the maintained fork instead of upstream operational contacts.
|
|
77
|
+
- **Security documentation** — clarified that MCP tools are read-only but may still expose sensitive application structure, especially over HTTP transport.
|
|
78
|
+
- **Internal review summary** — translated `resume.md` to English and updated it to reflect the current fork, Codex support, compatibility notes, and security posture.
|
|
79
|
+
|
|
80
|
+
## [0.7.1] - 2026-03-19
|
|
81
|
+
|
|
82
|
+
### Added
|
|
83
|
+
|
|
84
|
+
- **Full MCP tool reference in all context files** — every generated file (CLAUDE.md, .cursorrules, .windsurfrules, copilot-instructions.md) now includes complete tool documentation with parameters, detail levels, pagination examples, and usage workflow. Dedicated `rails-mcp-tools` split rule files added for Claude, Cursor, Windsurf, and Copilot.
|
|
85
|
+
- **MCP Registry listing** — published to the [official MCP Registry](https://registry.modelcontextprotocol.io) as `io.github.crisnahine/rails-ai-context` via mcpb package type.
|
|
86
|
+
|
|
87
|
+
### Fixed
|
|
88
|
+
|
|
89
|
+
- **Schema version parsing** — versions with underscores (e.g. `2024_01_15_123456`) were truncated to the first digit group. Now captures the full version string.
|
|
90
|
+
- **Documentation** — updated README (detail levels, pagination, generated file tree, config options), SECURITY.md (supported versions), CONTRIBUTING.md (project structure), gemspec (post-install message), demo_script.sh (all 17 generated files).
|
|
91
|
+
|
|
92
|
+
## [0.7.0] - 2026-03-19
|
|
93
|
+
|
|
94
|
+
### Added
|
|
95
|
+
|
|
96
|
+
- **Detail levels on MCP tools** — `detail:"summary"`, `detail:"standard"` (default), `detail:"full"` on `rails_get_schema`, `rails_get_routes`, `rails_get_model_details`, `rails_get_controllers`. AI calls summary first, then drills down. Based on Anthropic's recommended MCP pattern.
|
|
97
|
+
- **Pagination** — `limit` and `offset` parameters on schema and routes tools for apps with hundreds of tables/routes.
|
|
98
|
+
- **Response size safety net** — Configurable hard cap (`max_tool_response_chars`, default 120K) on tool responses. Truncated responses include hints to use filters.
|
|
99
|
+
- **Compact CLAUDE.md** — New `:compact` context mode (default) generates ≤150 lines per Claude Code's official recommendation. Contains stack overview, key models, and MCP tool usage guide.
|
|
100
|
+
- **Full mode preserved** — `config.context_mode = :full` retains the existing full-dump behavior. Also available via `rails ai:context:full` or `CONTEXT_MODE=full`.
|
|
101
|
+
- **`.claude/rules/` generation** — Generates quick-reference files in `.claude/rules/` for schema and models. Auto-loaded by Claude Code alongside CLAUDE.md.
|
|
102
|
+
- **Cursor MDC rules** — Generates `.cursor/rules/*.mdc` files with YAML frontmatter (globs, alwaysApply). Project overview is always-on; model/controller rules auto-attach when working in matching directories. Legacy `.cursorrules` kept for backward compatibility.
|
|
103
|
+
- **Windsurf 6K compliance** — `.windsurfrules` is now hard-capped at 5,800 characters (within Windsurf's 6,000 char limit). Generates `.windsurf/rules/*.md` for the new rules format.
|
|
104
|
+
- **Copilot path-specific instructions** — Generates `.github/instructions/*.instructions.md` with `applyTo` frontmatter for model and controller contexts. Main `copilot-instructions.md` respects compact mode (≤500 lines).
|
|
105
|
+
- **`rails ai:context:full` task** — Dedicated rake task for full context dump.
|
|
106
|
+
- **Configurable limits** — `claude_max_lines` (default: 150), `max_tool_response_chars` (default: 120K).
|
|
107
|
+
|
|
108
|
+
### Changed
|
|
109
|
+
|
|
110
|
+
- Default `context_mode` is now `:compact` (was implicitly `:full`). Existing behavior available via `config.context_mode = :full`.
|
|
111
|
+
- Tools default to `detail:"standard"` which returns bounded results, not unlimited.
|
|
112
|
+
- All tools return pagination hints when results are truncated.
|
|
113
|
+
- `.windsurfrules` now uses dedicated `WindsurfSerializer` instead of sharing `RulesSerializer` with Cursor.
|
|
114
|
+
|
|
115
|
+
## [0.6.0] - 2026-03-18
|
|
116
|
+
|
|
117
|
+
### Added
|
|
118
|
+
|
|
119
|
+
- **Migrations introspector** — Discovers migration files, pending migrations, recent history, schema version, and migration statistics. Works without DB connection.
|
|
120
|
+
- **Seeds introspector** — Analyzes db/seeds.rb structure, discovers seed files in db/seeds/, detects which models are seeded, and identifies patterns (Faker, environment conditionals, find_or_create_by).
|
|
121
|
+
- **Middleware introspector** — Discovers custom Rack middleware in app/middleware/, detects patterns (auth, rate limiting, tenant isolation, logging), and categorizes the full middleware stack.
|
|
122
|
+
- **Engine introspector** — Discovers mounted Rails engines from routes.rb with paths and descriptions for 23+ known engines (Sidekiq::Web, Flipper::UI, PgHero, ActiveAdmin, etc.).
|
|
123
|
+
- **Multi-database introspector** — Discovers multiple databases, replicas, sharding config, and model-specific `connects_to` declarations. Works with database.yml parsing fallback.
|
|
124
|
+
- **2 new MCP resources** — `rails://migrations`, `rails://engines`
|
|
125
|
+
- **Migrations added to :standard preset** — AI tools now see migration context by default
|
|
126
|
+
- **Doctor check** — New `check_migrations` diagnostic
|
|
127
|
+
- **Fingerprinter** — Now watches `db/migrate/`, `app/middleware/`, and `config/database.yml`
|
|
128
|
+
|
|
129
|
+
### Changed
|
|
130
|
+
|
|
131
|
+
- Default `:standard` preset expanded from 8 to 9 introspectors (added `:migrations`)
|
|
132
|
+
- Default `:full` preset expanded from 21 to 26 introspectors
|
|
133
|
+
- Doctor checks expanded from 11 to 12
|
|
134
|
+
- Static MCP resources expanded from 7 to 9
|
|
135
|
+
|
|
136
|
+
## [0.5.2] - 2026-03-18
|
|
137
|
+
|
|
138
|
+
### Fixed
|
|
139
|
+
|
|
140
|
+
- **MCP tool nil crash** — All 9 MCP tools now handle missing introspector data gracefully instead of crashing with `NoMethodError` when the introspector is not in the active preset (e.g. `rails_get_config` with `:standard` preset)
|
|
141
|
+
- **Zeitwerk dependency** — Changed from open-ended `>= 2.6` to pessimistic `~> 2.6` per RubyGems best practices
|
|
142
|
+
- **Documentation** — Updated CONTRIBUTING.md, CHANGELOG.md, and CLAUDE.md to reflect Zeitwerk autoloading, introspector presets, and `.mcp.json` auto-discovery changes
|
|
143
|
+
|
|
144
|
+
## [0.5.0] - 2026-03-18
|
|
145
|
+
|
|
146
|
+
### Added
|
|
147
|
+
|
|
148
|
+
- **Introspector presets** — `:standard` (8 core introspectors, fast) and `:full` (all 21, thorough) via `config.preset = :standard`
|
|
149
|
+
- **`.mcp.json` auto-discovery** — Install generator creates `.mcp.json` so Claude Code and Cursor auto-detect the MCP server with zero manual config
|
|
150
|
+
- **Zeitwerk autoloading** — Replaced 47 `require_relative` calls with Zeitwerk for faster boot and conventional file loading
|
|
151
|
+
- **Automated release workflow** — GitHub Actions publishes to RubyGems via trusted publishing when a version tag is pushed
|
|
152
|
+
- **Version consistency check** — Release workflow verifies git tag matches `version.rb` before publishing
|
|
153
|
+
- **Auto GitHub Release** — Release notes extracted from CHANGELOG.md automatically
|
|
154
|
+
- **Dependabot** — Weekly automated dependency and GitHub Actions updates
|
|
155
|
+
- **README demo GIF** — Animated terminal recording showing install, doctor, and context generation
|
|
156
|
+
- **SECURITY.md** — Security policy with supported versions and reporting process
|
|
157
|
+
- **CODE_OF_CONDUCT.md** — Contributor Covenant v2.1
|
|
158
|
+
- **GitHub repo topics** — Added discoverability keywords (rails, mcp, ai, etc.)
|
|
159
|
+
|
|
160
|
+
### Changed
|
|
161
|
+
|
|
162
|
+
- Default introspectors reduced from 21 to 8 (`:standard` preset) for faster boot; use `config.preset = :full` for all 21
|
|
163
|
+
- New files auto-loaded by Zeitwerk — no manual `require_relative` needed when adding introspectors or tools
|
|
164
|
+
|
|
165
|
+
## [0.4.0] - 2026-03-18
|
|
166
|
+
|
|
167
|
+
### Added
|
|
168
|
+
|
|
169
|
+
- **14 new introspectors** — Controllers, Views, Turbo/Hotwire, I18n, Config, Active Storage, Action Text, Auth, API, Tests, Rake Tasks, Asset Pipeline, DevOps, Action Mailbox
|
|
170
|
+
- **3 new MCP tools** — `rails_get_controllers`, `rails_get_config`, `rails_get_test_info`
|
|
171
|
+
- **3 new MCP resources** — `rails://controllers`, `rails://config`, `rails://tests`
|
|
172
|
+
- **Model introspector enhancements** — Extracts `has_secure_password`, `encrypts`, `normalizes`, `delegate`, `serialize`, `store`, `generates_token_for`, `has_one_attached`, `has_many_attached`, `has_rich_text`, `broadcasts_to` via source parsing
|
|
173
|
+
- **Stimulus introspector enhancements** — Extracts `outlets` and `classes` from controllers
|
|
174
|
+
- **Gem introspector enhancements** — 30+ new notable gems: monitoring (Sentry, Datadog, New Relic, Skylight), admin (ActiveAdmin, Administrate, Avo), pagination (Pagy, Kaminari), search (Ransack, pg_search, Searchkick), forms (SimpleForm), utilities (Faraday, Flipper, Bullet, Rack::Attack), and more
|
|
175
|
+
- **Convention detector enhancements** — Detects concerns, validators, policies, serializers, notifiers, Phlex, PWA, encrypted attributes, normalizations
|
|
176
|
+
- **Markdown serializer sections** — All 14 new introspector sections rendered in generated context files
|
|
177
|
+
- **Doctor enhancements** — 4 new checks: controllers, views, i18n, tests (11 total)
|
|
178
|
+
- **Fingerprinter expansion** — Watches `app/controllers`, `app/views`, `app/jobs`, `app/mailers`, `app/channels`, `app/javascript/controllers`, `config/initializers`, `lib/tasks`; glob now covers `.rb`, `.rake`, `.js`, `.ts`, `.erb`, `.haml`, `.slim`, `.yml`
|
|
179
|
+
|
|
180
|
+
### Fixed
|
|
181
|
+
|
|
182
|
+
- **YAML parsing** — `YAML.load_file` calls now pass `permitted_classes: [Symbol], aliases: true` for Psych 4 (Ruby 3.1+) compatibility
|
|
183
|
+
- **Rake task parser** — Fixed `@last_desc` instance variable leaking between files; fixed namespace tracking with indent-based stack
|
|
184
|
+
- **Vite detection** — Changed `File.exist?("vite.config")` to `Dir.glob("vite.config.*")` to match `.js`/`.ts`/`.mjs` extensions
|
|
185
|
+
- **Health check regex** — Added word boundaries to avoid false positives on substrings (e.g. "groups" matching "up")
|
|
186
|
+
- **Multi-attribute macros** — `normalizes :email, :name` now captures all attributes, not just the first
|
|
187
|
+
- **Stimulus action regex** — Requires `method(args) {` pattern to avoid matching control flow keywords
|
|
188
|
+
- **Controller respond_to** — Simplified format extraction to avoid nested `end` keyword issues
|
|
189
|
+
- **GetRoutes nil guard** — Added `|| {}` fallback for `by_controller` to prevent crash on partial introspection data
|
|
190
|
+
- **GetSchema nil guard** — Added `|| {}` fallback for `schema[:tables]` to prevent crash on partial schema data
|
|
191
|
+
- **View layout discovery** — Added `File.file?` filter to exclude directories from layout listing
|
|
192
|
+
- **Fingerprinter glob** — Changed from `**/*.rb` to multi-extension glob to detect changes in `.rake`, `.js`, `.ts`, `.erb` files
|
|
193
|
+
|
|
194
|
+
### Changed
|
|
195
|
+
|
|
196
|
+
- Default introspectors expanded from 7 to 21
|
|
197
|
+
- MCP tools expanded from 6 to 9
|
|
198
|
+
- Static MCP resources expanded from 4 to 7
|
|
199
|
+
- Doctor checks expanded from 7 to 11
|
|
200
|
+
- Test suite expanded from 149 to 247 examples with exact value assertions
|
|
201
|
+
|
|
202
|
+
## [0.3.0] - 2026-03-18
|
|
203
|
+
|
|
204
|
+
### Added
|
|
205
|
+
|
|
206
|
+
- **Cache invalidation** — TTL + file fingerprinting for MCP tool cache (replaces permanent `||=` cache)
|
|
207
|
+
- **MCP Resources** — Static resources (`rails://schema`, `rails://routes`, `rails://conventions`, `rails://gems`) and resource template (`rails://models/{name}`)
|
|
208
|
+
- **Per-assistant serializers** — Claude gets behavioral rules, Cursor/Windsurf get compact rules, Copilot gets task-oriented GFM
|
|
209
|
+
- **Stimulus introspector** — Extracts Stimulus controller targets, values, and actions from JS/TS files
|
|
210
|
+
- **Database stats introspector** — Opt-in PostgreSQL approximate row counts via `pg_stat_user_tables`
|
|
211
|
+
- **Auto-mount HTTP middleware** — Rack middleware for MCP endpoint when `config.auto_mount = true`
|
|
212
|
+
- **Diff-aware regeneration** — Context file generation skips unchanged files
|
|
213
|
+
- **`rails ai:doctor`** — Diagnostic command with AI readiness score (0-100)
|
|
214
|
+
- **`rails ai:watch`** — File watcher that auto-regenerates context files on change (requires `listen` gem)
|
|
215
|
+
|
|
216
|
+
### Fixed
|
|
217
|
+
|
|
218
|
+
- **Shell injection in SearchCode** — Replaced backtick execution with `Open3.capture2` array form; added file_type validation, max_results cap, and path traversal protection
|
|
219
|
+
- **Scope extraction** — Fixed broken `model.methods.grep(/^_scope_/)` by parsing source files for `scope :name` declarations
|
|
220
|
+
- **Route introspector** — Fixed `route.internal?` compatibility with Rails 8.1
|
|
221
|
+
|
|
222
|
+
### Changed
|
|
223
|
+
|
|
224
|
+
- `generate_context` now returns `{ written: [], skipped: [] }` instead of flat array
|
|
225
|
+
- Default introspectors now include `:stimulus`
|
|
226
|
+
|
|
227
|
+
## [0.2.0] - 2026-03-18
|
|
228
|
+
|
|
229
|
+
### Added
|
|
230
|
+
|
|
231
|
+
- Named rake tasks (`ai:context:claude`, `ai:context:cursor`, etc.) that work without quoting in zsh
|
|
232
|
+
- AI assistant summary table printed after `ai:context` and `ai:inspect`
|
|
233
|
+
- `ENV["FORMAT"]` fallback for `ai:context_for` task
|
|
234
|
+
- Format validation in `ContextFileSerializer` — unknown formats now raise `ArgumentError` with valid options
|
|
235
|
+
|
|
236
|
+
### Fixed
|
|
237
|
+
|
|
238
|
+
- `rails ai:context_for[claude]` failing in zsh due to bracket glob interpretation
|
|
239
|
+
- Double introspection in `ai:context` and `ai:context_for` tasks (removed unused `RailsAiBridge.introspect` calls)
|
|
240
|
+
|
|
241
|
+
## [0.1.0] - 2026-03-18
|
|
242
|
+
|
|
243
|
+
### Added
|
|
244
|
+
|
|
245
|
+
- Initial release
|
|
246
|
+
- Schema introspection (live DB + static schema.rb fallback)
|
|
247
|
+
- Model introspection (associations, validations, scopes, enums, callbacks, concerns)
|
|
248
|
+
- Route introspection (HTTP verbs, paths, controller actions, API namespaces)
|
|
249
|
+
- Job introspection (ActiveJob, mailers, Action Cable channels)
|
|
250
|
+
- Gem analysis (40+ notable gems mapped to categories with explanations)
|
|
251
|
+
- Convention detection (architecture style, design patterns, directory structure)
|
|
252
|
+
- 6 MCP tools: `rails_get_schema`, `rails_get_routes`, `rails_get_model_details`, `rails_get_gems`, `rails_search_code`, `rails_get_conventions`
|
|
253
|
+
- Context file generation: CLAUDE.md, .cursorrules, .windsurfrules, .github/copilot-instructions.md, JSON
|
|
254
|
+
- Rails Engine with Railtie auto-setup
|
|
255
|
+
- Install generator (`rails generate rails_ai_bridge:install`)
|
|
256
|
+
- Rake tasks: `ai:context`, `ai:serve`, `ai:serve_http`, `ai:inspect`
|
|
257
|
+
- CLI executable: `rails-ai-bridge serve|context|inspect`
|
|
258
|
+
- Stdio + Streamable HTTP transport support via official mcp SDK
|
|
259
|
+
- CI matrix: Ruby 3.2/3.3/3.4 × Rails 7.1/7.2/8.0
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# CLAUDE.md — rails-ai-bridge development guide
|
|
2
|
+
|
|
3
|
+
This is a Ruby gem that auto-introspects Rails applications and exposes their
|
|
4
|
+
structure to AI assistants via the Model Context Protocol (MCP).
|
|
5
|
+
|
|
6
|
+
## Architecture
|
|
7
|
+
|
|
8
|
+
- `lib/rails_ai_bridge.rb` — Main entry point, public API (Zeitwerk autoloaded)
|
|
9
|
+
- `lib/rails_ai_bridge/configuration.rb` — User-facing config with presets (:standard, :full)
|
|
10
|
+
- `lib/rails_ai_bridge/introspector.rb` — Orchestrates sub-introspectors
|
|
11
|
+
- `lib/rails_ai_bridge/introspectors/` — 27 introspectors (schema, models, routes, jobs, gems, conventions, stimulus, database_stats, controllers, views, turbo, i18n, config, active_storage, action_text, auth, api, tests, rake_tasks, assets, devops, action_mailbox, migrations, seeds, middleware, engines, multi_database)
|
|
12
|
+
- `lib/rails_ai_bridge/tools/` — 9 MCP tools using the official mcp SDK
|
|
13
|
+
- `lib/rails_ai_bridge/serializers/` — Output formatters (claude, claude_rules, cursor_rules, windsurf, windsurf_rules, copilot, copilot_instructions, rules, markdown, JSON)
|
|
14
|
+
- `lib/rails_ai_bridge/resources.rb` — MCP resources (static data AI clients read directly)
|
|
15
|
+
- `lib/rails_ai_bridge/server.rb` — MCP server configuration (stdio + HTTP transports)
|
|
16
|
+
- `lib/rails_ai_bridge/middleware.rb` — Rack middleware for auto-mounting MCP HTTP endpoint
|
|
17
|
+
- `lib/rails_ai_bridge/fingerprinter.rb` — SHA256 file fingerprinting for cache invalidation
|
|
18
|
+
- `lib/rails_ai_bridge/doctor.rb` — Diagnostic checks and AI readiness scoring
|
|
19
|
+
- `lib/rails_ai_bridge/watcher.rb` — File watcher for auto-regenerating context files
|
|
20
|
+
- `lib/rails_ai_bridge/engine.rb` — Rails Engine for auto-integration
|
|
21
|
+
- `lib/generators/rails_ai_bridge/install/` — Install generator (creates .mcp.json, initializer, context files)
|
|
22
|
+
|
|
23
|
+
## Key Design Decisions
|
|
24
|
+
|
|
25
|
+
1. **Built on official mcp SDK** — not a custom protocol implementation
|
|
26
|
+
2. **Zero-config** — Railtie auto-registers at boot, introspects without setup
|
|
27
|
+
3. **Graceful degradation** — works without DB by parsing schema.rb as text
|
|
28
|
+
4. **Read-only tools only** — all MCP tools are annotated as non-destructive
|
|
29
|
+
5. **Dual output** — static files (CLAUDE.md) + live MCP server (stdio/HTTP)
|
|
30
|
+
6. **Diff-aware** — context regeneration skips unchanged files
|
|
31
|
+
7. **Per-assistant serializers** — each AI tool gets tailored output format
|
|
32
|
+
8. **Zeitwerk autoloading** — files loaded on-demand, not all upfront
|
|
33
|
+
9. **Introspector presets** — `:standard` (9 core) default, `:full` (26) for power users
|
|
34
|
+
10. **MCP auto-discovery** — `.mcp.json` generated by install generator
|
|
35
|
+
11. **Compact by default** — context files ≤150 lines, MCP tools use `detail` parameter (summary/standard/full)
|
|
36
|
+
12. **Per-tool split rules** — `.claude/rules/`, `.cursor/rules/`, `.windsurf/rules/`, `.github/instructions/`
|
|
37
|
+
|
|
38
|
+
## Testing
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
bundle exec rspec # Run specs (364 examples)
|
|
42
|
+
bundle exec rubocop # Lint
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Uses combustion gem for testing Rails engine behavior in isolation.
|
|
46
|
+
|
|
47
|
+
## Conventions
|
|
48
|
+
|
|
49
|
+
- Ruby 3.2+ features OK (pattern matching, etc.)
|
|
50
|
+
- Follow rubocop-rails-omakase style
|
|
51
|
+
- Every introspector returns a Hash, never raises (wraps errors in `{ error: msg }`)
|
|
52
|
+
- MCP tools return `MCP::Tool::Response` objects per SDK convention
|
|
53
|
+
- All tools prefixed with `rails_` per MCP naming best practices
|
|
54
|
+
- `generate_context` returns `{ written: [], skipped: [] }` hash
|
|
55
|
+
- Zeitwerk autoloads all files — no `require_relative` needed for new classes
|
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, caste, color, religion, or sexual
|
|
10
|
+
identity and orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment:
|
|
18
|
+
|
|
19
|
+
* Using welcoming and inclusive language
|
|
20
|
+
* Being respectful of differing viewpoints and experiences
|
|
21
|
+
* Gracefully accepting constructive criticism
|
|
22
|
+
* Focusing on what is best for the community
|
|
23
|
+
* Showing empathy towards other community members
|
|
24
|
+
|
|
25
|
+
Examples of unacceptable behavior:
|
|
26
|
+
|
|
27
|
+
* The use of sexualized language or imagery, and sexual attention or advances of any kind
|
|
28
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
29
|
+
* Public or private harassment
|
|
30
|
+
* Publishing others' private information without explicit permission
|
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
32
|
+
|
|
33
|
+
## Enforcement
|
|
34
|
+
|
|
35
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
36
|
+
reported to the maintainer of this fork at **ismael.marin@gmail.com**.
|
|
37
|
+
|
|
38
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
|
39
|
+
|
|
40
|
+
## Attribution
|
|
41
|
+
|
|
42
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
|
|
43
|
+
version 2.1, available at
|
|
44
|
+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html).
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Contributing to rails-ai-bridge
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing! This guide covers everything you need to get started.
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/igmarin/rails-ai-bridge.git
|
|
9
|
+
cd rails-ai-bridge
|
|
10
|
+
bundle install
|
|
11
|
+
bundle exec rspec
|
|
12
|
+
bundle exec rubocop --parallel
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The test suite uses [Combustion](https://github.com/pat/combustion) to boot a minimal Rails app in `spec/internal/`. No external database required — tests run against an in-memory SQLite database.
|
|
16
|
+
|
|
17
|
+
## Project Structure
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
lib/rails_ai_bridge/
|
|
21
|
+
├── introspectors/ # 27 introspectors (schema, models, routes, etc.)
|
|
22
|
+
├── tools/ # 9 MCP tools with detail levels and pagination
|
|
23
|
+
├── serializers/ # Per-assistant formatters (claude, cursor, windsurf, copilot, JSON)
|
|
24
|
+
├── server.rb # MCP server setup (stdio + HTTP)
|
|
25
|
+
├── engine.rb # Rails Engine for auto-integration
|
|
26
|
+
└── configuration.rb # User-facing config (presets, context_mode, limits)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Adding a New Introspector
|
|
30
|
+
|
|
31
|
+
1. Create `lib/rails_ai_bridge/introspectors/your_introspector.rb` (auto-loaded by Zeitwerk)
|
|
32
|
+
2. Implement `#initialize(app)` and `#call` → returns a Hash (never raises)
|
|
33
|
+
3. Register it in `lib/rails_ai_bridge/introspector.rb` (the `INTROSPECTOR_MAP`)
|
|
34
|
+
4. Add the key to the appropriate preset(s) in `Configuration::PRESETS` (`:standard` for core, `:full` for all)
|
|
35
|
+
5. Write specs in `spec/lib/rails_ai_bridge/your_introspector_spec.rb`
|
|
36
|
+
|
|
37
|
+
## Adding a New MCP Tool
|
|
38
|
+
|
|
39
|
+
1. Create `lib/rails_ai_bridge/tools/your_tool.rb` inheriting from `BaseTool` (auto-loaded by Zeitwerk)
|
|
40
|
+
2. Define `tool_name`, `description`, `input_schema`, and `annotations`
|
|
41
|
+
3. Implement `def self.call(...)` returning `text_response(string)`
|
|
42
|
+
4. Register in `Server::TOOLS`
|
|
43
|
+
5. Write specs in `spec/lib/rails_ai_bridge/tools/your_tool_spec.rb`
|
|
44
|
+
|
|
45
|
+
## Code Style
|
|
46
|
+
|
|
47
|
+
- Follow `rubocop-rails-omakase` style (run `bundle exec rubocop`)
|
|
48
|
+
- Ruby 3.2+ features welcome (pattern matching, etc.)
|
|
49
|
+
- Every introspector must return a Hash and never raise — wrap errors in `{ error: msg }`
|
|
50
|
+
- MCP tools return `MCP::Tool::Response` objects
|
|
51
|
+
- All tools must be prefixed with `rails_` and annotated as read-only
|
|
52
|
+
|
|
53
|
+
## Running Tests
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
bundle exec rspec # Full test suite
|
|
57
|
+
bundle exec rspec spec/lib/ # Just lib specs
|
|
58
|
+
bundle exec rubocop --parallel # Lint check
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Pull Request Process
|
|
62
|
+
|
|
63
|
+
1. Fork the repo and create your branch from `main`
|
|
64
|
+
2. Add tests for any new functionality
|
|
65
|
+
3. Ensure `bundle exec rspec` and `bundle exec rubocop` pass
|
|
66
|
+
4. Update CHANGELOG.md under an `## [Unreleased]` section
|
|
67
|
+
5. Open a PR with a clear title and description
|
|
68
|
+
|
|
69
|
+
## Reporting Bugs
|
|
70
|
+
|
|
71
|
+
Open an issue at https://github.com/igmarin/rails-ai-bridge/issues with:
|
|
72
|
+
- Ruby and Rails versions
|
|
73
|
+
- Gem version
|
|
74
|
+
- Steps to reproduce
|
|
75
|
+
- Expected vs actual behavior
|
|
76
|
+
|
|
77
|
+
## Releasing to RubyGems (maintainers)
|
|
78
|
+
|
|
79
|
+
Pre-flight checklist:
|
|
80
|
+
|
|
81
|
+
1. **Name availability** — Confirm `rails-ai-bridge` is available (or owned by you) on [RubyGems](https://rubygems.org/gems/rails-ai-bridge).
|
|
82
|
+
2. **Version** — `lib/rails_ai_bridge/version.rb` must match the Git tag (release workflow expects `v#{VERSION}`).
|
|
83
|
+
3. **Changelog** — Add a `## [x.y.z]` section in `CHANGELOG.md` (release notes are extracted from it in CI).
|
|
84
|
+
4. **Build locally** — `gem build rails-ai-bridge.gemspec` and smoke-test in a dummy Rails app (`rails generate rails_ai_bridge:install`, `rails ai:bridge`, `rails ai:serve`).
|
|
85
|
+
5. **MFA** — RubyGems account must have MFA; `spec.metadata["rubygems_mfa_required"]` is already `"true"`.
|
|
86
|
+
6. **Trusted publishing** — Prefer [OIDC trusted publishing](https://guides.rubygems.org/trusted-publishing/) with the existing `rubygems/release-gem@v1` workflow; configure the gem owner on RubyGems to trust this repository/workflow.
|
|
87
|
+
7. **Secrets** — Avoid API keys in the repo; rely on trusted publishing or short-lived CI secrets.
|
|
88
|
+
8. **MCP registry** — If you publish `server.json` to the MCP registry, coordinate the `name` field (`io.github.igmarin/rails-ai-bridge`) with registry requirements.
|
|
89
|
+
9. **Post-release** — Verify `bundle add rails-ai-bridge` from RubyGems and that badges in the README resolve.
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ismael G Marin Cabrera
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|