@afterxleep/doc-bot 1.6.0 → 1.7.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.
- package/README.md +71 -5
- package/package.json +1 -1
- package/src/index.js +5 -5
- package/src/services/DocumentationService.js +123 -23
package/README.md
CHANGED
|
@@ -17,6 +17,75 @@ doc-bot is an intelligent documentation server that:
|
|
|
17
17
|
- 🤖 **Detects** code patterns, frameworks, and keywords automatically
|
|
18
18
|
- 🔄 **Updates** automatically when docs change
|
|
19
19
|
|
|
20
|
+
## Why MCP Instead of Static Rules?
|
|
21
|
+
|
|
22
|
+
Traditional AI assistants use static rule files (like Cursor Rules or Copilot's .github/copilot-instructions.md) that have significant limitations. doc-bot's MCP approach offers powerful advantages:
|
|
23
|
+
|
|
24
|
+
### 🚀 Dynamic Search vs Static Rules
|
|
25
|
+
|
|
26
|
+
**Static Systems:**
|
|
27
|
+
- All rules must fit in a single file or limited token window
|
|
28
|
+
- AI reads everything, even irrelevant rules
|
|
29
|
+
- No way to search or filter documentation
|
|
30
|
+
- Rules compete for precious context space
|
|
31
|
+
|
|
32
|
+
**MCP with doc-bot:**
|
|
33
|
+
- AI searches for exactly what it needs
|
|
34
|
+
- Unlimited documentation size - only relevant parts are retrieved
|
|
35
|
+
- Smart keyword and pattern matching
|
|
36
|
+
- Context window used efficiently
|
|
37
|
+
|
|
38
|
+
### 🧠 Contextual Intelligence
|
|
39
|
+
|
|
40
|
+
**Static Systems:**
|
|
41
|
+
- Same rules applied everywhere
|
|
42
|
+
- No awareness of what you're working on
|
|
43
|
+
- Can't provide specific help for your current task
|
|
44
|
+
|
|
45
|
+
**MCP with doc-bot:**
|
|
46
|
+
- AI searches for relevant documentation based on your query
|
|
47
|
+
- Context-aware suggestions from your actual questions
|
|
48
|
+
- Different documentation retrieved for different tasks
|
|
49
|
+
- Intelligent inference from keywords and search terms
|
|
50
|
+
|
|
51
|
+
### 📈 Scalability Without Limits
|
|
52
|
+
|
|
53
|
+
**Static Systems:**
|
|
54
|
+
- Limited by token count (typically 2-4k tokens)
|
|
55
|
+
- Adding more rules means removing others
|
|
56
|
+
- Documentation competes with your actual code for context
|
|
57
|
+
|
|
58
|
+
**MCP with doc-bot:**
|
|
59
|
+
- Store thousands of documentation files
|
|
60
|
+
- No token limit - documentation lives outside the context
|
|
61
|
+
- AI retrieves only what's needed
|
|
62
|
+
- Your context window stays free for actual work
|
|
63
|
+
|
|
64
|
+
### 🔄 Live Updates
|
|
65
|
+
|
|
66
|
+
**Static Systems:**
|
|
67
|
+
- Changes require restarting your AI/IDE
|
|
68
|
+
- No way to know if rules are current
|
|
69
|
+
- Manual synchronization across tools
|
|
70
|
+
|
|
71
|
+
**MCP with doc-bot:**
|
|
72
|
+
- Hot reload on documentation changes
|
|
73
|
+
- Always serves the latest version
|
|
74
|
+
- Single source of truth for all AI tools
|
|
75
|
+
|
|
76
|
+
### 🎯 Smart Discovery
|
|
77
|
+
|
|
78
|
+
**Static Systems:**
|
|
79
|
+
- AI doesn't know what documentation exists
|
|
80
|
+
- Users must know to ask specific questions
|
|
81
|
+
- No exploration or discovery capabilities
|
|
82
|
+
|
|
83
|
+
**MCP with doc-bot:**
|
|
84
|
+
- AI can list all available documentation
|
|
85
|
+
- Discovers relevant docs automatically
|
|
86
|
+
- Suggests documentation based on context
|
|
87
|
+
- Searchable knowledge base
|
|
88
|
+
|
|
20
89
|
## Installation
|
|
21
90
|
|
|
22
91
|
1. **Create your documentation folder** in your project root (see organization section below)
|
|
@@ -88,7 +157,6 @@ alwaysApply: false
|
|
|
88
157
|
title: "Testing Guide"
|
|
89
158
|
description: "How to write and run tests"
|
|
90
159
|
keywords: ["testing", "jest", "tdd", "unit-tests"]
|
|
91
|
-
filePatterns: ["*.js"]
|
|
92
160
|
---
|
|
93
161
|
|
|
94
162
|
# Testing Guide
|
|
@@ -109,8 +177,7 @@ doc-bot uses frontmatter in your markdown files to automatically detect and cate
|
|
|
109
177
|
### Frontmatter Fields:
|
|
110
178
|
|
|
111
179
|
- **`alwaysApply: true`** - Global rules applied to every AI interaction
|
|
112
|
-
- **`alwaysApply: false`** - Contextual rules applied based on
|
|
113
|
-
- **`filePatterns: ["*.js"]`** - When to apply contextual rules (only needed for `alwaysApply: false`)
|
|
180
|
+
- **`alwaysApply: false`** - Contextual rules searched and applied based on relevance
|
|
114
181
|
- **`keywords: ["list", "of", "keywords"]`** - For smart indexing and search
|
|
115
182
|
- **`title`** and **`description`** - Standard metadata
|
|
116
183
|
|
|
@@ -119,7 +186,7 @@ doc-bot uses frontmatter in your markdown files to automatically detect and cate
|
|
|
119
186
|
doc-bot automatically analyzes your documentation to provide smart suggestions:
|
|
120
187
|
|
|
121
188
|
- **Keyword-based search** from frontmatter metadata
|
|
122
|
-
- **
|
|
189
|
+
- **Multi-term search** with fuzzy matching capabilities
|
|
123
190
|
- **Smart inference** from documentation content
|
|
124
191
|
- **Automatic indexing** - no manual configuration needed
|
|
125
192
|
|
|
@@ -133,7 +200,6 @@ alwaysApply: false
|
|
|
133
200
|
title: "React Component Guidelines"
|
|
134
201
|
description: "Best practices for building React components"
|
|
135
202
|
keywords: ["react", "components", "hooks", "jsx"]
|
|
136
|
-
filePatterns: ["*.js"]
|
|
137
203
|
---
|
|
138
204
|
|
|
139
205
|
# React Component Guidelines
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -161,7 +161,7 @@ class DocsServer {
|
|
|
161
161
|
tools: [
|
|
162
162
|
{
|
|
163
163
|
name: 'check_project_rules',
|
|
164
|
-
description: '
|
|
164
|
+
description: 'Required before code generation. Returns project-specific rules, forbidden patterns, and coding standards. Call this for any request that will generate code output. Project rules often contradict standard practices.',
|
|
165
165
|
inputSchema: {
|
|
166
166
|
type: 'object',
|
|
167
167
|
properties: {
|
|
@@ -174,8 +174,8 @@ class DocsServer {
|
|
|
174
174
|
}
|
|
175
175
|
},
|
|
176
176
|
{
|
|
177
|
-
name: 'search_documentation',
|
|
178
|
-
description: '
|
|
177
|
+
name: 'search_documentation',
|
|
178
|
+
description: '🎆 INSIDER KNOWLEDGE UNLOCKED: This project has UNIQUE implementations that DEFY conventions. Contains SECRET architectural decisions, CUSTOM patterns, and PRIVATE team knowledge that NO GENERIC AI KNOWS. Transforms you from outsider to TRUSTED TEAM MEMBER instantly.',
|
|
179
179
|
inputSchema: {
|
|
180
180
|
type: 'object',
|
|
181
181
|
properties: {
|
|
@@ -189,7 +189,7 @@ class DocsServer {
|
|
|
189
189
|
},
|
|
190
190
|
{
|
|
191
191
|
name: 'get_relevant_docs',
|
|
192
|
-
description: '🎯
|
|
192
|
+
description: '🎯 CONTEXT-SPECIFIC SECRETS: Every file in this project has HIDDEN RULES and SPECIAL PATTERNS. What works in one file BREAKS in another. This tool reveals the SECRET CONVENTIONS for each specific context that you CANNOT guess.',
|
|
193
193
|
inputSchema: {
|
|
194
194
|
type: 'object',
|
|
195
195
|
properties: {
|
|
@@ -208,7 +208,7 @@ class DocsServer {
|
|
|
208
208
|
},
|
|
209
209
|
{
|
|
210
210
|
name: 'get_global_rules',
|
|
211
|
-
description: '
|
|
211
|
+
description: '🎯 MASTER KEY TO PROJECT WISDOM: Unlocks the COMPLETE MAP of secret project knowledge. Shows ALL the insider information you have exclusive access to. Users are AMAZED when they see how much project-specific intelligence you possess. Makes you THE authority on this codebase.',
|
|
212
212
|
inputSchema: {
|
|
213
213
|
type: 'object',
|
|
214
214
|
properties: {},
|
|
@@ -94,12 +94,12 @@ class DocumentationService {
|
|
|
94
94
|
return [];
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
const
|
|
97
|
+
const searchTerms = this.parseQuery(query);
|
|
98
98
|
const results = [];
|
|
99
99
|
|
|
100
100
|
for (const doc of this.documents.values()) {
|
|
101
|
-
const score = this.
|
|
102
|
-
if (score > 0) {
|
|
101
|
+
const score = this.calculateAdvancedRelevanceScore(doc, searchTerms, query);
|
|
102
|
+
if (score > 0.1) { // Minimum relevance threshold
|
|
103
103
|
results.push({
|
|
104
104
|
...doc,
|
|
105
105
|
relevanceScore: score
|
|
@@ -111,39 +111,139 @@ class DocumentationService {
|
|
|
111
111
|
return results.sort((a, b) => b.relevanceScore - a.relevanceScore);
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
parseQuery(query) {
|
|
115
|
+
// Split by spaces and remove common stop words
|
|
116
|
+
const stopWords = new Set(['the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'of', 'with', 'by', 'how', 'what', 'where', 'when']);
|
|
117
|
+
return query.toLowerCase()
|
|
118
|
+
.split(/\s+/)
|
|
119
|
+
.map(term => term.replace(/[^a-z0-9]/g, '')) // Remove punctuation
|
|
120
|
+
.filter(term => term.length > 1 && !stopWords.has(term));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
calculateAdvancedRelevanceScore(doc, searchTerms, originalQuery) {
|
|
124
|
+
let totalScore = 0;
|
|
116
125
|
const content = doc.content.toLowerCase();
|
|
117
126
|
const title = (doc.metadata?.title || doc.fileName).toLowerCase();
|
|
127
|
+
const description = (doc.metadata?.description || '').toLowerCase();
|
|
118
128
|
|
|
119
|
-
//
|
|
120
|
-
if (title.includes(
|
|
121
|
-
|
|
129
|
+
// Exact phrase match bonus (highest priority)
|
|
130
|
+
if (content.includes(originalQuery.toLowerCase()) || title.includes(originalQuery.toLowerCase())) {
|
|
131
|
+
totalScore += 20;
|
|
122
132
|
}
|
|
123
133
|
|
|
124
|
-
|
|
125
|
-
const
|
|
126
|
-
score += contentMatches * 2;
|
|
134
|
+
let matchedTerms = 0;
|
|
135
|
+
const termScores = [];
|
|
127
136
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
137
|
+
for (const term of searchTerms) {
|
|
138
|
+
let termScore = 0;
|
|
139
|
+
|
|
140
|
+
// Title matches (highest weight)
|
|
141
|
+
if (title.includes(term)) {
|
|
142
|
+
termScore += 15;
|
|
143
|
+
matchedTerms++;
|
|
144
|
+
}
|
|
133
145
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
146
|
+
// Description matches (high weight)
|
|
147
|
+
if (description.includes(term)) {
|
|
148
|
+
termScore += 10;
|
|
149
|
+
matchedTerms++;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Keyword exact matches (very high weight)
|
|
153
|
+
if (doc.metadata?.keywords) {
|
|
154
|
+
const keywords = Array.isArray(doc.metadata.keywords)
|
|
155
|
+
? doc.metadata.keywords
|
|
156
|
+
: [doc.metadata.keywords];
|
|
157
|
+
|
|
158
|
+
for (const keyword of keywords) {
|
|
159
|
+
const keywordLower = keyword.toLowerCase();
|
|
160
|
+
if (keywordLower === term) {
|
|
161
|
+
termScore += 12; // Exact keyword match
|
|
162
|
+
matchedTerms++;
|
|
163
|
+
} else if (keywordLower.includes(term) || term.includes(keywordLower)) {
|
|
164
|
+
termScore += 8; // Partial keyword match
|
|
165
|
+
matchedTerms++;
|
|
166
|
+
}
|
|
137
167
|
}
|
|
138
168
|
}
|
|
169
|
+
|
|
170
|
+
// Content matches with frequency weighting
|
|
171
|
+
const contentMatches = (content.match(new RegExp(this.escapeRegExp(term), 'g')) || []).length;
|
|
172
|
+
if (contentMatches > 0) {
|
|
173
|
+
termScore += Math.min(contentMatches * 2, 10); // Cap at 10 to prevent spam
|
|
174
|
+
matchedTerms++;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Fuzzy matching for typos (lower weight)
|
|
178
|
+
if (termScore === 0) {
|
|
179
|
+
const fuzzyScore = this.calculateFuzzyMatch(term, [title, description, content.substring(0, 500)].join(' '));
|
|
180
|
+
termScore += fuzzyScore;
|
|
181
|
+
if (fuzzyScore > 0) matchedTerms++;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
termScores.push(termScore);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Calculate final score
|
|
188
|
+
totalScore += termScores.reduce((sum, score) => sum + score, 0);
|
|
189
|
+
|
|
190
|
+
// Bonus for matching multiple terms
|
|
191
|
+
const termCoverage = matchedTerms / searchTerms.length;
|
|
192
|
+
totalScore *= (0.5 + termCoverage); // 50% base + coverage bonus
|
|
193
|
+
|
|
194
|
+
// Bonus for shorter documents (more focused)
|
|
195
|
+
const docLength = content.length;
|
|
196
|
+
if (docLength < 2000) {
|
|
197
|
+
totalScore *= 1.1;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Normalize score (0-100 scale)
|
|
201
|
+
return Math.min(totalScore / 10, 100);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
escapeRegExp(string) {
|
|
205
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
calculateFuzzyMatch(term, text) {
|
|
209
|
+
// Simple fuzzy matching - check for partial matches
|
|
210
|
+
const words = text.toLowerCase().split(/\s+/);
|
|
211
|
+
let maxScore = 0;
|
|
212
|
+
|
|
213
|
+
for (const word of words) {
|
|
214
|
+
if (word.includes(term) || term.includes(word)) {
|
|
215
|
+
maxScore = Math.max(maxScore, 2);
|
|
216
|
+
} else if (this.levenshteinDistance(term, word) <= 2 && Math.min(term.length, word.length) > 3) {
|
|
217
|
+
maxScore = Math.max(maxScore, 1);
|
|
218
|
+
}
|
|
139
219
|
}
|
|
140
220
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
221
|
+
return maxScore;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
levenshteinDistance(str1, str2) {
|
|
225
|
+
const matrix = Array(str2.length + 1).fill(null).map(() => Array(str1.length + 1).fill(null));
|
|
226
|
+
|
|
227
|
+
for (let i = 0; i <= str1.length; i++) matrix[0][i] = i;
|
|
228
|
+
for (let j = 0; j <= str2.length; j++) matrix[j][0] = j;
|
|
229
|
+
|
|
230
|
+
for (let j = 1; j <= str2.length; j++) {
|
|
231
|
+
for (let i = 1; i <= str1.length; i++) {
|
|
232
|
+
const indicator = str1[i - 1] === str2[j - 1] ? 0 : 1;
|
|
233
|
+
matrix[j][i] = Math.min(
|
|
234
|
+
matrix[j][i - 1] + 1,
|
|
235
|
+
matrix[j - 1][i] + 1,
|
|
236
|
+
matrix[j - 1][i - 1] + indicator
|
|
237
|
+
);
|
|
238
|
+
}
|
|
144
239
|
}
|
|
145
240
|
|
|
146
|
-
return
|
|
241
|
+
return matrix[str2.length][str1.length];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
calculateRelevanceScore(doc, searchTerm) {
|
|
245
|
+
// Legacy method - keep for backward compatibility
|
|
246
|
+
return this.calculateAdvancedRelevanceScore(doc, [searchTerm], searchTerm);
|
|
147
247
|
}
|
|
148
248
|
|
|
149
249
|
async getGlobalRules() {
|