@afterxleep/doc-bot 1.7.9 → 1.7.11
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/AGENT_INTEGRATION_RULE.txt +142 -0
- package/README.md +13 -0
- package/package.json +3 -2
- package/prompts/system-prompt.txt +28 -7
- package/src/index.js +127 -109
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# AGENT INTEGRATION PROTOCOL: DOC-BOT MCP ENFORCEMENT
|
|
2
|
+
# ============================================================
|
|
3
|
+
# Add this to your agent configuration (CLAUDE.md, .cursorrules, copilot-instructions.md, etc.)
|
|
4
|
+
|
|
5
|
+
## PHASE 1: ENVIRONMENT DETECTION
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
IF (
|
|
9
|
+
(filesystem_contains("doc-bot/") AND
|
|
10
|
+
(mcp_server_available("doc-bot") OR mcp_server_available("@afterxleep/doc-bot"))
|
|
11
|
+
) THEN {
|
|
12
|
+
ACTIVATE: doc_bot_enforcement_protocol()
|
|
13
|
+
SET: project_documentation_authority = TRUE
|
|
14
|
+
SET: general_knowledge_override = DISABLED
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## PHASE 2: REQUEST CLASSIFICATION ENGINE
|
|
19
|
+
|
|
20
|
+
### CLASSIFICATION MATRIX:
|
|
21
|
+
|
|
22
|
+
**CLASS A: CODE_GENERATION**
|
|
23
|
+
```
|
|
24
|
+
Trigger Pattern: /\b(write|create|implement|build|add|code|function|class|component|method|develop|generate|make|refactor|modify|update|fix|debug)\b/i
|
|
25
|
+
Required Action: MANDATORY_CALL(check_project_rules, extract_task_description())
|
|
26
|
+
Blocking: TRUE (cannot proceed without tool response)
|
|
27
|
+
Timeout: 30s
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**CLASS B: PROJECT_INQUIRY**
|
|
31
|
+
```
|
|
32
|
+
Trigger Pattern: /\b(how|what|why|architecture|approach|pattern|feature|authentication|database|api|testing)\b/i
|
|
33
|
+
Context Pattern: /\b(this project|this codebase|here|our|current project)\b/i
|
|
34
|
+
Required Action: MANDATORY_CALL(search_documentation, extract_keywords())
|
|
35
|
+
Blocking: TRUE
|
|
36
|
+
Timeout: 30s
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**CLASS C: DOCUMENTATION_DISCOVERY**
|
|
40
|
+
```
|
|
41
|
+
Trigger Pattern: /\b(documentation|available|capabilities|help|rules|standards|what exists|docs|guide)\b/i
|
|
42
|
+
Required Action: MANDATORY_CALL(get_global_rules)
|
|
43
|
+
Blocking: TRUE
|
|
44
|
+
Timeout: 30s
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**CLASS D: DOCUMENT_ACCESS**
|
|
48
|
+
```
|
|
49
|
+
Trigger Pattern: /\b(read|show|get content|full document|complete|entire)\b/i
|
|
50
|
+
Previous Context: search_results_present()
|
|
51
|
+
Required Action: MANDATORY_CALL(read_specific_document, extract_filename())
|
|
52
|
+
Blocking: FALSE
|
|
53
|
+
Timeout: 15s
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**CLASS E: DOCUMENTATION_CREATION**
|
|
57
|
+
```
|
|
58
|
+
Trigger Pattern: /\b(document|create rule|add rule|save knowledge|capture pattern|remember|note this|new rule)\b/i
|
|
59
|
+
Context Pattern: /\b(we should document|this should be a rule|add to documentation|create guideline)\b/i
|
|
60
|
+
Required Action: MANDATORY_CALL(create_or_update_rule, extract_rule_params())
|
|
61
|
+
Blocking: FALSE
|
|
62
|
+
Timeout: 30s
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Note**: For file-specific queries like "working on src/utils.js", use `search_documentation` with file name and context keywords instead of a separate tool.
|
|
66
|
+
|
|
67
|
+
## PHASE 3: EXECUTION ENFORCEMENT
|
|
68
|
+
|
|
69
|
+
### PRE-RESPONSE VALIDATION:
|
|
70
|
+
```
|
|
71
|
+
BEFORE generating_response():
|
|
72
|
+
classification = classify_request(user_input)
|
|
73
|
+
IF classification != "UNRELATED":
|
|
74
|
+
tool_result = execute_mandatory_tool(classification)
|
|
75
|
+
IF tool_result.status == "ERROR":
|
|
76
|
+
RETURN error_recovery_response()
|
|
77
|
+
ELSE:
|
|
78
|
+
INJECT tool_result INTO response_context
|
|
79
|
+
SET authoritative_source = tool_result
|
|
80
|
+
DISABLE general_knowledge_fallback
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### RESPONSE CONSTRAINT ENGINE:
|
|
84
|
+
```
|
|
85
|
+
WHILE generating_response():
|
|
86
|
+
IF attempting_to_use(general_knowledge) AND authoritative_source.exists():
|
|
87
|
+
INTERRUPT_GENERATION()
|
|
88
|
+
FORCE_USE(authoritative_source)
|
|
89
|
+
|
|
90
|
+
IF code_generation_detected() AND NOT project_rules_checked:
|
|
91
|
+
HALT_EXECUTION()
|
|
92
|
+
EMIT_ERROR("Project rules validation required before code generation")
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## PHASE 4: QUALITY ASSURANCE
|
|
96
|
+
|
|
97
|
+
### RESPONSE VALIDATION:
|
|
98
|
+
```
|
|
99
|
+
AFTER generating_response():
|
|
100
|
+
IF response_contradicts(tool_result):
|
|
101
|
+
REGENERATE_RESPONSE(tool_result_only=TRUE)
|
|
102
|
+
|
|
103
|
+
IF response_lacks(tool_attribution):
|
|
104
|
+
APPEND_ATTRIBUTION(tool_result.source)
|
|
105
|
+
|
|
106
|
+
VALIDATE response_compliance(project_rules)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### FAILURE DETECTION & RECOVERY:
|
|
110
|
+
```
|
|
111
|
+
IF response_generated() WITHOUT tool_execution():
|
|
112
|
+
LOG_VIOLATION("Tool bypass detected")
|
|
113
|
+
REGENERATE_WITH_TOOLS()
|
|
114
|
+
PREPEND_WARNING("Corrected response using project documentation:")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## PHASE 5: BEHAVIORAL CONSTRAINTS
|
|
118
|
+
|
|
119
|
+
### ABSOLUTE PROHIBITIONS:
|
|
120
|
+
- **Code generation without project rules validation**
|
|
121
|
+
- **Project-specific answers from general knowledge**
|
|
122
|
+
- **Overriding tool responses with training data**
|
|
123
|
+
- **Bypassing tool calls for "simple" questions**
|
|
124
|
+
|
|
125
|
+
### MANDATORY BEHAVIORS:
|
|
126
|
+
- **Tool-first response generation**
|
|
127
|
+
- **Explicit tool result attribution**
|
|
128
|
+
- **Project documentation precedence**
|
|
129
|
+
- **Error acknowledgment and correction**
|
|
130
|
+
|
|
131
|
+
## VERIFICATION PROTOCOL:
|
|
132
|
+
|
|
133
|
+
**Test Inputs** (Agent must call tools immediately):
|
|
134
|
+
- "What documentation is available?" → get_global_rules()
|
|
135
|
+
- "How do I implement auth?" → search_documentation("authentication")
|
|
136
|
+
- "Create a new component" → check_project_rules("create component")
|
|
137
|
+
- "Working on src/utils.js" → search_documentation("src/utils.js utils")
|
|
138
|
+
- "We should document this pattern" → create_or_update_rule({fileName: "pattern-name.md", title: "Pattern Name", content: "...", alwaysApply: false})
|
|
139
|
+
|
|
140
|
+
**Expected Behavior**: Tool execution within 2 seconds, no general knowledge responses.
|
|
141
|
+
|
|
142
|
+
**Failure Indicators**: Any response without tool execution, generic programming advice, standard framework suggestions.
|
package/README.md
CHANGED
|
@@ -131,6 +131,19 @@ Traditional AI assistants use static rule files (like Cursor Rules or Copilot's
|
|
|
131
131
|
|
|
132
132
|
3. **Restart your AI tool**
|
|
133
133
|
|
|
134
|
+
4. **Ensure Agent Compliance** (Essential): Add the expert-engineered integration protocol to guarantee your agent uses doc-bot:
|
|
135
|
+
|
|
136
|
+
**⚡ Setup**: Copy the rule from [`AGENT_INTEGRATION_RULE.txt`](./AGENT_INTEGRATION_RULE.txt) into your agent configuration.
|
|
137
|
+
**🎯 Why This Matters**: Without this rule, agents may default to general knowledge instead of your doc-bot documentation.
|
|
138
|
+
|
|
139
|
+
**Platform-Specific Instructions**:
|
|
140
|
+
- **Claude Code**: Add rule to your global `CLAUDE.md`
|
|
141
|
+
- **Cursor**: Create a `.mdc` file in `.cursor/rules/` directory with `alwaysApply: true`
|
|
142
|
+
- **GitHub Copilot**: Add rule to `.github/copilot-instructions.md`
|
|
143
|
+
- **Continue.dev**: Add rule to system prompt configuration
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
134
147
|
## How to organize your documentation
|
|
135
148
|
|
|
136
149
|
Create a `doc-bot/` folder in your project root with markdown files using frontmatter:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@afterxleep/doc-bot",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.11",
|
|
4
4
|
"description": "Generic MCP server for intelligent documentation access in any project",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"bin/",
|
|
60
60
|
"prompts/",
|
|
61
61
|
"README.md",
|
|
62
|
-
"LICENSE"
|
|
62
|
+
"LICENSE",
|
|
63
|
+
"AGENT_INTEGRATION_RULE.txt"
|
|
63
64
|
]
|
|
64
65
|
}
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
| `check_project_rules` | Code generation keywords | ANY code output | Execute before code generation |
|
|
14
14
|
| `search_documentation` | Project-specific questions | Feature/architecture queries | Execute for project context |
|
|
15
15
|
| `get_global_rules` | Documentation discovery | Rule/capability queries | Execute for overview |
|
|
16
|
-
| `get_relevant_docs` | File-specific context | Targeted work | Execute for context |
|
|
17
16
|
| `read_specific_document` | Document access | Full content needs | Execute after search results |
|
|
17
|
+
| `create_or_update_rule` | Rule creation/learning | New knowledge capture | Execute to document patterns/rules |
|
|
18
|
+
| `refresh_documentation` | Manual refresh | File detection issues | Execute after manual file additions |
|
|
18
19
|
|
|
19
20
|
## KEYWORD MAPPING:
|
|
20
21
|
|
|
@@ -32,9 +33,19 @@
|
|
|
32
33
|
**Keywords**: documentation, available, capabilities, help with, what exists, rules, standards
|
|
33
34
|
**Action**: Execute `get_global_rules` for comprehensive overview
|
|
34
35
|
|
|
35
|
-
### Context
|
|
36
|
-
**Keywords**: working on, this file, specific file, directory, component path
|
|
37
|
-
**Action**: Execute `
|
|
36
|
+
### File Context Triggers:
|
|
37
|
+
**Keywords**: working on, this file, specific file, directory, component path
|
|
38
|
+
**Action**: Execute `search_documentation` with file name and context keywords
|
|
39
|
+
|
|
40
|
+
### Documentation Creation Triggers:
|
|
41
|
+
**Keywords**: document, create rule, add rule, save knowledge, capture pattern, remember, note this, new rule
|
|
42
|
+
**Context Indicators**: "we should document", "this should be a rule", "add to documentation", "create guideline"
|
|
43
|
+
**Action**: Execute `create_or_update_rule` to capture new knowledge
|
|
44
|
+
|
|
45
|
+
### Documentation Refresh Triggers:
|
|
46
|
+
**Keywords**: refresh, reload, update index, detect files, manual files, can't find, document not found
|
|
47
|
+
**Context Indicators**: "added files manually", "files not showing up", "refresh documentation", "reload docs"
|
|
48
|
+
**Action**: Execute `refresh_documentation` to reindex files
|
|
38
49
|
|
|
39
50
|
## EXECUTION ALGORITHM:
|
|
40
51
|
|
|
@@ -71,9 +82,19 @@ Action: get_global_rules()
|
|
|
71
82
|
Reason: Documentation discovery request
|
|
72
83
|
|
|
73
84
|
Input: "I'm working on src/components/Header.js"
|
|
74
|
-
Analysis: Contains "working on" + file path (context trigger)
|
|
75
|
-
Action:
|
|
76
|
-
Reason: File-specific context requirement
|
|
85
|
+
Analysis: Contains "working on" + file path (file context trigger)
|
|
86
|
+
Action: search_documentation("src/components/Header.js component")
|
|
87
|
+
Reason: File-specific context search requirement
|
|
88
|
+
|
|
89
|
+
Input: "We should document this pattern - always use TypeScript interfaces for API responses"
|
|
90
|
+
Analysis: Contains "should document" + "pattern" (documentation creation trigger)
|
|
91
|
+
Action: create_or_update_rule({fileName: "api-patterns.md", title: "API Response Patterns", content: "Always use TypeScript interfaces for API responses", alwaysApply: true})
|
|
92
|
+
Reason: New knowledge capture requirement
|
|
93
|
+
|
|
94
|
+
Input: "I added files manually but they're not showing up in search"
|
|
95
|
+
Analysis: Contains "added files manually" + "not showing up" (refresh trigger)
|
|
96
|
+
Action: refresh_documentation()
|
|
97
|
+
Reason: Manual file detection issue
|
|
77
98
|
```
|
|
78
99
|
|
|
79
100
|
## COMPLIANCE PROTOCOL:
|
package/src/index.js
CHANGED
|
@@ -187,25 +187,6 @@ class DocsServer {
|
|
|
187
187
|
required: ['query']
|
|
188
188
|
}
|
|
189
189
|
},
|
|
190
|
-
{
|
|
191
|
-
name: 'get_relevant_docs',
|
|
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
|
-
inputSchema: {
|
|
194
|
-
type: 'object',
|
|
195
|
-
properties: {
|
|
196
|
-
context: {
|
|
197
|
-
type: 'object',
|
|
198
|
-
description: 'Context for getting relevant documentation',
|
|
199
|
-
properties: {
|
|
200
|
-
query: { type: 'string', description: 'What you\'re trying to accomplish' },
|
|
201
|
-
filePath: { type: 'string', description: 'File path you\'re working on' },
|
|
202
|
-
codeSnippet: { type: 'string', description: 'Code snippet for context' }
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
},
|
|
206
|
-
required: ['context']
|
|
207
|
-
}
|
|
208
|
-
},
|
|
209
190
|
{
|
|
210
191
|
name: 'get_global_rules',
|
|
211
192
|
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.',
|
|
@@ -242,6 +223,50 @@ class DocsServer {
|
|
|
242
223
|
},
|
|
243
224
|
required: ['fileName']
|
|
244
225
|
}
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: 'create_or_update_rule',
|
|
229
|
+
description: 'Create a new documentation rule or update an existing one. Use this to add new project knowledge or update existing documentation based on learnings.',
|
|
230
|
+
inputSchema: {
|
|
231
|
+
type: 'object',
|
|
232
|
+
properties: {
|
|
233
|
+
fileName: {
|
|
234
|
+
type: 'string',
|
|
235
|
+
description: 'File name for the rule (e.g., "react-patterns.md"). If file exists, it will be updated.'
|
|
236
|
+
},
|
|
237
|
+
title: {
|
|
238
|
+
type: 'string',
|
|
239
|
+
description: 'Title of the documentation rule'
|
|
240
|
+
},
|
|
241
|
+
description: {
|
|
242
|
+
type: 'string',
|
|
243
|
+
description: 'Brief description of what this rule covers'
|
|
244
|
+
},
|
|
245
|
+
keywords: {
|
|
246
|
+
type: 'array',
|
|
247
|
+
items: { type: 'string' },
|
|
248
|
+
description: 'Keywords for search indexing (e.g., ["react", "patterns", "components"])'
|
|
249
|
+
},
|
|
250
|
+
alwaysApply: {
|
|
251
|
+
type: 'boolean',
|
|
252
|
+
description: 'Whether this rule should always apply (true for global rules, false for contextual)'
|
|
253
|
+
},
|
|
254
|
+
content: {
|
|
255
|
+
type: 'string',
|
|
256
|
+
description: 'The markdown content of the rule'
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
required: ['fileName', 'title', 'content', 'alwaysApply']
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: 'refresh_documentation',
|
|
264
|
+
description: 'Manually refresh the documentation index to detect new or changed files. Use this after manually adding files to the docs folder.',
|
|
265
|
+
inputSchema: {
|
|
266
|
+
type: 'object',
|
|
267
|
+
properties: {},
|
|
268
|
+
additionalProperties: false
|
|
269
|
+
}
|
|
245
270
|
}
|
|
246
271
|
]
|
|
247
272
|
};
|
|
@@ -276,19 +301,6 @@ class DocsServer {
|
|
|
276
301
|
}]
|
|
277
302
|
};
|
|
278
303
|
|
|
279
|
-
case 'get_relevant_docs':
|
|
280
|
-
const context = args?.context;
|
|
281
|
-
if (!context) {
|
|
282
|
-
throw new Error('Context parameter is required');
|
|
283
|
-
}
|
|
284
|
-
const relevant = await this.inferenceEngine.getRelevantDocumentation(context);
|
|
285
|
-
return {
|
|
286
|
-
content: [{
|
|
287
|
-
type: 'text',
|
|
288
|
-
text: await this.formatRelevantDocs(relevant)
|
|
289
|
-
}]
|
|
290
|
-
};
|
|
291
|
-
|
|
292
304
|
case 'get_global_rules':
|
|
293
305
|
const globalRules = await this.docService.getGlobalRules();
|
|
294
306
|
return {
|
|
@@ -326,6 +338,40 @@ class DocsServer {
|
|
|
326
338
|
text: await this.formatSingleDocument(doc)
|
|
327
339
|
}]
|
|
328
340
|
};
|
|
341
|
+
|
|
342
|
+
case 'create_or_update_rule':
|
|
343
|
+
const { fileName: ruleFileName, title, description, keywords, alwaysApply, content } = args || {};
|
|
344
|
+
|
|
345
|
+
if (!ruleFileName || !title || !content || alwaysApply === undefined) {
|
|
346
|
+
throw new Error('fileName, title, content, and alwaysApply parameters are required');
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const result = await this.createOrUpdateRule({
|
|
350
|
+
fileName: ruleFileName,
|
|
351
|
+
title,
|
|
352
|
+
description,
|
|
353
|
+
keywords,
|
|
354
|
+
alwaysApply,
|
|
355
|
+
content
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
return {
|
|
359
|
+
content: [{
|
|
360
|
+
type: 'text',
|
|
361
|
+
text: result
|
|
362
|
+
}]
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
case 'refresh_documentation':
|
|
366
|
+
await this.docService.reload();
|
|
367
|
+
const docCount = this.docService.documents.size;
|
|
368
|
+
|
|
369
|
+
return {
|
|
370
|
+
content: [{
|
|
371
|
+
type: 'text',
|
|
372
|
+
text: `✅ Documentation refreshed successfully!\n\n**Files indexed:** ${docCount}\n**Last updated:** ${new Date().toLocaleString()}\n\n💡 All manually added files should now be available for search and reading.`
|
|
373
|
+
}]
|
|
374
|
+
};
|
|
329
375
|
|
|
330
376
|
default:
|
|
331
377
|
throw new Error(`Unknown tool: ${name}`);
|
|
@@ -415,83 +461,6 @@ class DocsServer {
|
|
|
415
461
|
.replace('${results}', formattedResults);
|
|
416
462
|
}
|
|
417
463
|
|
|
418
|
-
async formatRelevantDocs(relevant) {
|
|
419
|
-
const template = await this.loadPromptTemplate('relevant-docs');
|
|
420
|
-
if (!template) {
|
|
421
|
-
// Fallback to original format
|
|
422
|
-
let output = '# Relevant Documentation\n\n';
|
|
423
|
-
|
|
424
|
-
if (relevant.globalRules?.length > 0) {
|
|
425
|
-
output += '## 🌟 Global Rules (Always Apply)\n\n';
|
|
426
|
-
relevant.globalRules.forEach(rule => {
|
|
427
|
-
output += `### ${rule.metadata?.title || rule.fileName}\n`;
|
|
428
|
-
output += `${rule.content}\n\n`;
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
if (relevant.contextualDocs?.length > 0) {
|
|
433
|
-
output += '## 📂 Contextual Documentation\n\n';
|
|
434
|
-
relevant.contextualDocs.forEach(doc => {
|
|
435
|
-
output += `### ${doc.metadata?.title || doc.fileName}\n`;
|
|
436
|
-
output += `${doc.content}\n\n`;
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
if (relevant.inferredDocs?.length > 0) {
|
|
441
|
-
output += '## 🧠 Inferred Documentation\n\n';
|
|
442
|
-
relevant.inferredDocs.forEach(doc => {
|
|
443
|
-
output += `### ${doc.metadata?.title || doc.fileName}\n`;
|
|
444
|
-
output += `${doc.content}\n\n`;
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
if (relevant.confidence !== undefined) {
|
|
449
|
-
output += `**Confidence:** ${relevant.confidence.toFixed(2)}\n\n`;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
output += '\n⚠️ CRITICAL: These rules are MANDATORY and must be followed before generating code.\n';
|
|
453
|
-
return output;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// Build sections for template
|
|
457
|
-
let globalRulesSection = '';
|
|
458
|
-
if (relevant.globalRules?.length > 0) {
|
|
459
|
-
globalRulesSection = '## 🌟 Global Rules (Always Apply)\n\n';
|
|
460
|
-
relevant.globalRules.forEach(rule => {
|
|
461
|
-
globalRulesSection += `### ${rule.metadata?.title || rule.fileName}\n`;
|
|
462
|
-
globalRulesSection += `${rule.content}\n\n`;
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
let contextualDocsSection = '';
|
|
467
|
-
if (relevant.contextualDocs?.length > 0) {
|
|
468
|
-
contextualDocsSection = '## 📂 Contextual Documentation\n\n';
|
|
469
|
-
relevant.contextualDocs.forEach(doc => {
|
|
470
|
-
contextualDocsSection += `### ${doc.metadata?.title || doc.fileName}\n`;
|
|
471
|
-
contextualDocsSection += `${doc.content}\n\n`;
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
let inferredDocsSection = '';
|
|
476
|
-
if (relevant.inferredDocs?.length > 0) {
|
|
477
|
-
inferredDocsSection = '## 🧠 Inferred Documentation\n\n';
|
|
478
|
-
relevant.inferredDocs.forEach(doc => {
|
|
479
|
-
inferredDocsSection += `### ${doc.metadata?.title || doc.fileName}\n`;
|
|
480
|
-
inferredDocsSection += `${doc.content}\n\n`;
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
let confidenceSection = '';
|
|
485
|
-
if (relevant.confidence !== undefined) {
|
|
486
|
-
confidenceSection = `**Confidence:** ${relevant.confidence.toFixed(2)}\n\n`;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
return template
|
|
490
|
-
.replace('${globalRulesSection}', globalRulesSection)
|
|
491
|
-
.replace('${contextualDocsSection}', contextualDocsSection)
|
|
492
|
-
.replace('${inferredDocsSection}', inferredDocsSection)
|
|
493
|
-
.replace('${confidenceSection}', confidenceSection);
|
|
494
|
-
}
|
|
495
464
|
|
|
496
465
|
async formatGlobalRules(globalRules) {
|
|
497
466
|
if (!globalRules || globalRules.length === 0) {
|
|
@@ -585,6 +554,55 @@ class DocsServer {
|
|
|
585
554
|
return output;
|
|
586
555
|
}
|
|
587
556
|
|
|
557
|
+
async createOrUpdateRule({ fileName, title, description, keywords, alwaysApply, content }) {
|
|
558
|
+
const fs = require('fs-extra');
|
|
559
|
+
const path = require('path');
|
|
560
|
+
|
|
561
|
+
try {
|
|
562
|
+
// Ensure the docs directory exists
|
|
563
|
+
await fs.ensureDir(this.options.docsPath);
|
|
564
|
+
|
|
565
|
+
// Create the full file path
|
|
566
|
+
const filePath = path.join(this.options.docsPath, fileName);
|
|
567
|
+
|
|
568
|
+
// Build frontmatter
|
|
569
|
+
let frontmatter = '---\n';
|
|
570
|
+
frontmatter += `alwaysApply: ${alwaysApply}\n`;
|
|
571
|
+
frontmatter += `title: "${title}"\n`;
|
|
572
|
+
if (description) {
|
|
573
|
+
frontmatter += `description: "${description}"\n`;
|
|
574
|
+
}
|
|
575
|
+
if (keywords && keywords.length > 0) {
|
|
576
|
+
frontmatter += `keywords: [${keywords.map(k => `"${k}"`).join(', ')}]\n`;
|
|
577
|
+
}
|
|
578
|
+
frontmatter += '---\n\n';
|
|
579
|
+
|
|
580
|
+
// Combine frontmatter and content
|
|
581
|
+
const fullContent = frontmatter + content;
|
|
582
|
+
|
|
583
|
+
// Check if file exists to determine if this is create or update
|
|
584
|
+
const fileExists = await fs.pathExists(filePath);
|
|
585
|
+
const action = fileExists ? 'updated' : 'created';
|
|
586
|
+
|
|
587
|
+
// Write the file
|
|
588
|
+
await fs.writeFile(filePath, fullContent, 'utf8');
|
|
589
|
+
|
|
590
|
+
// Reload the documentation service to pick up the new/updated file
|
|
591
|
+
await this.docService.reload();
|
|
592
|
+
|
|
593
|
+
return `✅ Documentation rule ${action} successfully: ${fileName}\n\n` +
|
|
594
|
+
`**Title**: ${title}\n` +
|
|
595
|
+
`**Type**: ${alwaysApply ? 'Global Rule (always applies)' : 'Contextual Rule (applies when relevant)'}\n` +
|
|
596
|
+
`**File**: ${fileName}\n` +
|
|
597
|
+
(description ? `**Description**: ${description}\n` : '') +
|
|
598
|
+
(keywords && keywords.length > 0 ? `**Keywords**: ${keywords.join(', ')}\n` : '') +
|
|
599
|
+
`\n**Content**:\n${content}`;
|
|
600
|
+
|
|
601
|
+
} catch (error) {
|
|
602
|
+
throw new Error(`Failed to ${fileName.includes('/') ? 'create' : 'update'} rule: ${error.message}`);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
588
606
|
async generateSystemPrompt() {
|
|
589
607
|
const globalRules = await this.docService.getGlobalRules();
|
|
590
608
|
const allDocs = await this.docService.getAllDocuments();
|