@afterxleep/doc-bot 1.16.0 → 1.18.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.
Files changed (82) hide show
  1. package/package.json +7 -4
  2. package/src/__tests__/temp-docs-1756129972061/test.md +5 -0
  3. package/src/__tests__/temp-docs-1756129972071/test.md +5 -0
  4. package/src/__tests__/temp-docs-1756129972075/test.md +5 -0
  5. package/src/__tests__/temp-docs-1756129972077/test.md +5 -0
  6. package/src/__tests__/temp-docs-1756129972079/test.md +5 -0
  7. package/src/__tests__/temp-docs-1756130189361/test.md +5 -0
  8. package/src/__tests__/temp-docs-1756130189372/test.md +5 -0
  9. package/src/__tests__/temp-docs-1756130189375/test.md +5 -0
  10. package/src/__tests__/temp-docs-1756130189378/test.md +5 -0
  11. package/src/__tests__/temp-docs-1756130189379/test.md +5 -0
  12. package/src/__tests__/temp-docs-1756130271128/test.md +5 -0
  13. package/src/__tests__/temp-docs-1756130271139/test.md +5 -0
  14. package/src/__tests__/temp-docs-1756130271142/test.md +5 -0
  15. package/src/__tests__/temp-docs-1756130271145/test.md +5 -0
  16. package/src/__tests__/temp-docs-1756130271146/test.md +5 -0
  17. package/src/__tests__/temp-docs-1756130687030/test.md +5 -0
  18. package/src/__tests__/temp-docs-1756130687044/test.md +5 -0
  19. package/src/__tests__/temp-docs-1756130687048/test.md +5 -0
  20. package/src/__tests__/temp-docs-1756130687051/test.md +5 -0
  21. package/src/__tests__/temp-docs-1756130687053/test.md +5 -0
  22. package/src/__tests__/temp-docs-1756131694925/test.md +5 -0
  23. package/src/__tests__/temp-docs-1756131694937/test.md +5 -0
  24. package/src/__tests__/temp-docs-1756131694941/test.md +5 -0
  25. package/src/__tests__/temp-docs-1756131694944/test.md +5 -0
  26. package/src/__tests__/temp-docs-1756131694946/test.md +5 -0
  27. package/src/__tests__/temp-docs-1756133998710/test.md +5 -0
  28. package/src/__tests__/temp-docs-1756133998721/test.md +5 -0
  29. package/src/__tests__/temp-docs-1756133998724/test.md +5 -0
  30. package/src/__tests__/temp-docs-1756133998727/test.md +5 -0
  31. package/src/__tests__/temp-docs-1756133998729/test.md +5 -0
  32. package/src/__tests__/temp-docs-1756134345935/test.md +5 -0
  33. package/src/__tests__/temp-docs-1756134345948/test.md +5 -0
  34. package/src/__tests__/temp-docs-1756134345952/test.md +5 -0
  35. package/src/__tests__/temp-docs-1756134345954/test.md +5 -0
  36. package/src/__tests__/temp-docs-1756134345957/test.md +5 -0
  37. package/src/__tests__/temp-docsets-1756129972079/2e443167/Mock.docset/Contents/Info.plist +10 -0
  38. package/src/__tests__/temp-docsets-1756129972079/2e443167/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  39. package/src/__tests__/temp-docsets-1756129972079/Mock.docset/Contents/Info.plist +10 -0
  40. package/src/__tests__/temp-docsets-1756129972079/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  41. package/src/__tests__/temp-docsets-1756129972079/docsets.json +10 -0
  42. package/src/__tests__/temp-docsets-1756130189379/Mock.docset/Contents/Info.plist +10 -0
  43. package/src/__tests__/temp-docsets-1756130189379/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  44. package/src/__tests__/temp-docsets-1756130189379/a4934c14/Mock.docset/Contents/Info.plist +10 -0
  45. package/src/__tests__/temp-docsets-1756130189379/a4934c14/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  46. package/src/__tests__/temp-docsets-1756130189379/docsets.json +10 -0
  47. package/src/__tests__/temp-docsets-1756130271146/3f8acbb2/Mock.docset/Contents/Info.plist +10 -0
  48. package/src/__tests__/temp-docsets-1756130271146/3f8acbb2/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  49. package/src/__tests__/temp-docsets-1756130271146/Mock.docset/Contents/Info.plist +10 -0
  50. package/src/__tests__/temp-docsets-1756130271146/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  51. package/src/__tests__/temp-docsets-1756130271146/docsets.json +10 -0
  52. package/src/__tests__/temp-docsets-1756130687053/6810e6bd/Mock.docset/Contents/Info.plist +10 -0
  53. package/src/__tests__/temp-docsets-1756130687053/6810e6bd/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  54. package/src/__tests__/temp-docsets-1756130687053/Mock.docset/Contents/Info.plist +10 -0
  55. package/src/__tests__/temp-docsets-1756130687053/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  56. package/src/__tests__/temp-docsets-1756130687053/docsets.json +10 -0
  57. package/src/__tests__/temp-docsets-1756131694946/Mock.docset/Contents/Info.plist +10 -0
  58. package/src/__tests__/temp-docsets-1756131694946/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  59. package/src/__tests__/temp-docsets-1756131694946/dd703046/Mock.docset/Contents/Info.plist +10 -0
  60. package/src/__tests__/temp-docsets-1756131694946/dd703046/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  61. package/src/__tests__/temp-docsets-1756131694946/docsets.json +10 -0
  62. package/src/__tests__/temp-docsets-1756133998729/9e061136/Mock.docset/Contents/Info.plist +10 -0
  63. package/src/__tests__/temp-docsets-1756133998729/9e061136/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  64. package/src/__tests__/temp-docsets-1756133998729/Mock.docset/Contents/Info.plist +10 -0
  65. package/src/__tests__/temp-docsets-1756133998729/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  66. package/src/__tests__/temp-docsets-1756133998729/docsets.json +10 -0
  67. package/src/__tests__/temp-docsets-1756134345957/03e730af/Mock.docset/Contents/Info.plist +10 -0
  68. package/src/__tests__/temp-docsets-1756134345957/03e730af/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  69. package/src/__tests__/temp-docsets-1756134345957/Mock.docset/Contents/Info.plist +10 -0
  70. package/src/__tests__/temp-docsets-1756134345957/Mock.docset/Contents/Resources/docSet.dsidx +0 -0
  71. package/src/__tests__/temp-docsets-1756134345957/docsets.json +10 -0
  72. package/src/index.js +18 -11
  73. package/src/services/DocumentationService.js +26 -1
  74. package/prompts/file-docs.txt +0 -52
  75. package/prompts/global-rules.txt +0 -83
  76. package/prompts/mandatory-rules.txt +0 -117
  77. package/prompts/search-results.txt +0 -48
  78. package/prompts/system-prompt.txt +0 -210
  79. package/src/__tests__/docset-integration.test.js +0 -146
  80. package/src/services/__tests__/DocumentationService.test.js +0 -318
  81. package/src/services/__tests__/UnifiedSearchService.test.js +0 -302
  82. package/src/services/docset/__tests__/EnhancedDocsetDatabase.test.js +0 -324
@@ -1,146 +0,0 @@
1
- import { DocsServer } from '../index.js';
2
- import fs from 'fs-extra';
3
- import path from 'path';
4
- import { fileURLToPath } from 'url';
5
- import { dirname } from 'path';
6
- import os from 'os';
7
-
8
- const __filename = fileURLToPath(import.meta.url);
9
- const __dirname = dirname(__filename);
10
-
11
- describe('DocsServer Docset Integration', () => {
12
- let server;
13
- let tempDocsPath;
14
- let tempDocsetsPath;
15
-
16
- beforeEach(async () => {
17
- // Create temporary directories
18
- tempDocsPath = path.join(__dirname, 'temp-docs-' + Date.now());
19
- tempDocsetsPath = path.join(__dirname, 'temp-docsets-' + Date.now());
20
-
21
- await fs.ensureDir(tempDocsPath);
22
- await fs.ensureDir(tempDocsetsPath);
23
-
24
- // Create a simple test doc
25
- await fs.writeFile(
26
- path.join(tempDocsPath, 'test.md'),
27
- '---\nalwaysApply: true\ntitle: Test Doc\n---\n# Test'
28
- );
29
- });
30
-
31
- afterEach(async () => {
32
- if (server) {
33
- await server.close();
34
- }
35
- await fs.remove(tempDocsPath);
36
- await fs.remove(tempDocsetsPath);
37
- });
38
-
39
- describe('Server initialization with docsets', () => {
40
- it('should initialize with custom docsets path', async () => {
41
- server = new DocsServer({
42
- docsPath: tempDocsPath,
43
- docsetsPath: tempDocsetsPath,
44
- verbose: false
45
- });
46
-
47
- await server.start();
48
-
49
- expect(server.docsetService).toBeDefined();
50
- expect(server.docsetService.storagePath).toBe(tempDocsetsPath);
51
- });
52
-
53
- it('should use default docsets path when not provided', async () => {
54
- server = new DocsServer({
55
- docsPath: tempDocsPath,
56
- verbose: false
57
- });
58
-
59
- await server.start();
60
-
61
- const expectedPath = path.join(os.homedir(), 'Developer', 'DocSets');
62
- expect(server.docsetService.storagePath).toBe(expectedPath);
63
- });
64
- });
65
-
66
- describe('Docset service functionality', () => {
67
- beforeEach(async () => {
68
- server = new DocsServer({
69
- docsPath: tempDocsPath,
70
- docsetsPath: tempDocsetsPath,
71
- verbose: false
72
- });
73
- await server.start();
74
- });
75
-
76
- it('should have docset service initialized', () => {
77
- expect(server.docsetService).toBeDefined();
78
- expect(server.multiDocsetDatabase).toBeDefined();
79
- });
80
-
81
- it('should have empty docsets initially', async () => {
82
- const docsets = await server.docsetService.listDocsets();
83
- expect(docsets).toEqual([]);
84
- });
85
-
86
- it('should handle docset operations', async () => {
87
- // Create a mock docset
88
- const mockDocsetPath = path.join(tempDocsetsPath, 'Mock.docset');
89
- const contentsPath = path.join(mockDocsetPath, 'Contents');
90
- const resourcesPath = path.join(contentsPath, 'Resources');
91
-
92
- await fs.ensureDir(resourcesPath);
93
-
94
- // Create Info.plist
95
- const infoPlist = `<?xml version="1.0" encoding="UTF-8"?>
96
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
97
- <plist version="1.0">
98
- <dict>
99
- <key>CFBundleName</key>
100
- <string>Mock Documentation</string>
101
- <key>CFBundleIdentifier</key>
102
- <string>mock.documentation</string>
103
- </dict>
104
- </plist>`;
105
- await fs.writeFile(path.join(contentsPath, 'Info.plist'), infoPlist);
106
-
107
- // Create SQLite database
108
- const Database = (await import('better-sqlite3')).default;
109
- const dbPath = path.join(resourcesPath, 'docSet.dsidx');
110
- const db = new Database(dbPath);
111
- db.exec(`
112
- CREATE TABLE searchIndex(
113
- id INTEGER PRIMARY KEY,
114
- name TEXT,
115
- type TEXT,
116
- path TEXT
117
- );
118
- `);
119
- db.prepare('INSERT INTO searchIndex (name, type, path) VALUES (?, ?, ?)')
120
- .run('TestClass', 'Class', 'test.html');
121
- db.close();
122
-
123
- // Test adding docset
124
- const docsetInfo = await server.docsetService.addDocset(mockDocsetPath);
125
- expect(docsetInfo.name).toBe('Mock Documentation');
126
-
127
- // Test listing docsets
128
- const docsets = await server.docsetService.listDocsets();
129
- expect(docsets).toHaveLength(1);
130
- expect(docsets[0].name).toBe('Mock Documentation');
131
-
132
- // Add to database for searching
133
- server.multiDocsetDatabase.addDocset(docsetInfo);
134
-
135
- // Test searching
136
- const searchResults = server.multiDocsetDatabase.search('Test');
137
- expect(searchResults).toHaveLength(1);
138
- expect(searchResults[0].name).toBe('TestClass');
139
-
140
- // Test removing docset
141
- await server.docsetService.removeDocset(docsetInfo.id);
142
- const finalDocsets = await server.docsetService.listDocsets();
143
- expect(finalDocsets).toHaveLength(0);
144
- });
145
- });
146
- });
@@ -1,318 +0,0 @@
1
- import { DocumentationService } from '../DocumentationService.js';
2
- import fs from 'fs-extra';
3
- import path from 'path';
4
- import { fileURLToPath } from 'url';
5
- import { dirname } from 'path';
6
-
7
- const __filename = fileURLToPath(import.meta.url);
8
- const __dirname = dirname(__filename);
9
-
10
- describe('DocumentationService', () => {
11
- let docService;
12
- let tempDocsPath;
13
-
14
- beforeEach(async () => {
15
- tempDocsPath = path.join(__dirname, 'temp-docs-' + Date.now());
16
- await fs.ensureDir(tempDocsPath);
17
- docService = new DocumentationService(tempDocsPath);
18
- });
19
-
20
- afterEach(async () => {
21
- await fs.remove(tempDocsPath);
22
- });
23
-
24
- describe('extractRelevantSnippet', () => {
25
- it('should extract snippet around exact phrase match', () => {
26
- const content = `This is some content before the match.
27
- Here we discuss how to use AlarmKit Framework effectively.
28
- And this is content after the match.`;
29
-
30
- const snippet = docService.extractRelevantSnippet(
31
- content,
32
- ['use', 'alarmkit', 'framework'],
33
- 'use AlarmKit Framework'
34
- );
35
-
36
- expect(snippet).toContain('use AlarmKit Framework');
37
- expect(snippet.length).toBeLessThanOrEqual(250);
38
- });
39
-
40
- it('should find best snippet with most matching terms', () => {
41
- const content = `# Introduction
42
- This document covers various topics.
43
-
44
- # URLSession Configuration
45
- Learn how to configure URLSession properly.
46
-
47
- # Advanced Usage
48
- Here we discuss URLSession and configuration together.
49
- URLSession provides many configuration options.`;
50
-
51
- const snippet = docService.extractRelevantSnippet(
52
- content,
53
- ['urlsession', 'configuration'],
54
- 'URLSession configuration'
55
- );
56
-
57
- expect(snippet).toContain('URLSession');
58
- expect(snippet).toContain('configuration');
59
- });
60
-
61
- it('should prioritize headers containing search terms', () => {
62
- const content = `# Random Header
63
- Some content here.
64
-
65
- # AlarmKit Integration
66
- This is the section about integration.
67
-
68
- Some other content mentioning AlarmKit.`;
69
-
70
- const snippet = docService.extractRelevantSnippet(
71
- content,
72
- ['alarmkit', 'integration'],
73
- 'AlarmKit integration'
74
- );
75
-
76
- expect(snippet).toContain('# AlarmKit Integration');
77
- });
78
-
79
- it('should return description from metadata if no good snippet found', () => {
80
- const content = `---
81
- title: Test Document
82
- description: This is a comprehensive guide to using the API
83
- ---
84
-
85
- Some unrelated content here.`;
86
-
87
- const snippet = docService.extractRelevantSnippet(
88
- content,
89
- ['nonexistent', 'terms'],
90
- 'nonexistent terms'
91
- );
92
-
93
- expect(snippet).toBe('This is a comprehensive guide to using the API');
94
- });
95
-
96
- it('should clean and format snippets properly', () => {
97
- const content = `This is **bold** text with \`code\` and multiple spaces.`;
98
-
99
- const snippet = docService.extractRelevantSnippet(
100
- content,
101
- ['bold', 'text'],
102
- 'bold text'
103
- );
104
-
105
- expect(snippet).not.toContain('**');
106
- expect(snippet).not.toContain('`');
107
- expect(snippet).not.toMatch(/\s{2,}/);
108
- });
109
- });
110
-
111
- describe('getMatchedTerms', () => {
112
- it('should return terms that match in document', () => {
113
- const doc = {
114
- content: 'Learn about URLSession and networking in Swift',
115
- metadata: {
116
- title: 'Swift Networking Guide',
117
- description: 'A guide to URLSession'
118
- },
119
- fileName: 'networking.md'
120
- };
121
-
122
- const matched = docService.getMatchedTerms(doc, ['urlsession', 'swift', 'api']);
123
-
124
- expect(matched).toContain('urlsession');
125
- expect(matched).toContain('swift');
126
- expect(matched).not.toContain('api');
127
- });
128
-
129
- it('should match terms in title and description', () => {
130
- const doc = {
131
- content: 'Some content',
132
- metadata: {
133
- title: 'AlarmKit Framework',
134
- description: 'Learn to use AlarmKit'
135
- },
136
- fileName: 'guide.md'
137
- };
138
-
139
- const matched = docService.getMatchedTerms(doc, ['alarmkit', 'framework', 'use']);
140
-
141
- expect(matched).toEqual(['alarmkit', 'framework', 'use']);
142
- });
143
- });
144
-
145
- describe('searchDocuments with enhanced features', () => {
146
- beforeEach(async () => {
147
- // Create test documents
148
- await fs.writeFile(
149
- path.join(tempDocsPath, 'high-relevance.md'),
150
- `---
151
- title: AlarmKit Framework Guide
152
- description: Complete guide to using AlarmKit Framework
153
- keywords: [alarmkit, framework, ios]
154
- ---
155
-
156
- # AlarmKit Framework
157
-
158
- Learn how to use AlarmKit Framework effectively.
159
- AlarmKit provides powerful alarm functionality.`
160
- );
161
-
162
- await fs.writeFile(
163
- path.join(tempDocsPath, 'medium-relevance.md'),
164
- `---
165
- title: iOS Development
166
- description: General iOS development guide
167
- ---
168
-
169
- # iOS Development
170
-
171
- This guide covers various frameworks including AlarmKit.`
172
- );
173
-
174
- await fs.writeFile(
175
- path.join(tempDocsPath, 'low-relevance.md'),
176
- `---
177
- title: Random Document
178
- ---
179
-
180
- # Random Content
181
-
182
- This has nothing to do with alarms or kits.`
183
- );
184
-
185
- await docService.initialize();
186
- });
187
-
188
- it('should return results with snippets and matched terms', async () => {
189
- const results = await docService.searchDocuments('AlarmKit Framework');
190
-
191
- expect(results.length).toBeGreaterThan(0);
192
- expect(results[0].snippet).toBeDefined();
193
- expect(results[0].matchedTerms).toBeDefined();
194
- expect(results[0].matchedTerms).toContain('alarmkit');
195
- expect(results[0].matchedTerms).toContain('framework');
196
- });
197
-
198
- it('should filter out low relevance results', async () => {
199
- const results = await docService.searchDocuments('AlarmKit Framework');
200
-
201
- // Should not include the "Random Document" with no relevant content
202
- const hasLowRelevance = results.some(r => r.metadata?.title === 'Random Document');
203
- expect(hasLowRelevance).toBe(false);
204
- });
205
-
206
- it('should prioritize exact phrase matches', async () => {
207
- const results = await docService.searchDocuments('AlarmKit Framework');
208
-
209
- expect(results[0].metadata?.title).toBe('AlarmKit Framework Guide');
210
- expect(results[0].relevanceScore).toBeGreaterThan(50);
211
- });
212
-
213
- it('should boost keyword matches', async () => {
214
- const results = await docService.searchDocuments('alarmkit');
215
-
216
- // Document with alarmkit in keywords should score higher
217
- expect(results[0].metadata?.keywords).toContain('alarmkit');
218
- });
219
- });
220
-
221
- describe('calculateAdvancedRelevanceScore', () => {
222
- it('should give high score for exact phrase match', () => {
223
- const doc = {
224
- content: 'Learn how to use AlarmKit Framework in your iOS app',
225
- metadata: { title: 'iOS Guide' },
226
- fileName: 'guide.md'
227
- };
228
-
229
- const score = docService.calculateAdvancedRelevanceScore(
230
- doc,
231
- ['alarmkit', 'framework'],
232
- 'AlarmKit Framework'
233
- );
234
-
235
- expect(score).toBeGreaterThan(20); // Exact phrase bonus
236
- });
237
-
238
- it('should boost matches in title', () => {
239
- const doc1 = {
240
- content: 'Some content about URLSession',
241
- metadata: { title: 'URLSession Guide' },
242
- fileName: 'guide1.md'
243
- };
244
-
245
- const doc2 = {
246
- content: 'URLSession is mentioned here',
247
- metadata: { title: 'Random Guide' },
248
- fileName: 'guide2.md'
249
- };
250
-
251
- const score1 = docService.calculateAdvancedRelevanceScore(
252
- doc1,
253
- ['urlsession'],
254
- 'URLSession'
255
- );
256
-
257
- const score2 = docService.calculateAdvancedRelevanceScore(
258
- doc2,
259
- ['urlsession'],
260
- 'URLSession'
261
- );
262
-
263
- expect(score1).toBeGreaterThan(score2);
264
- });
265
-
266
- it('should apply term coverage bonus', () => {
267
- const doc = {
268
- content: 'URLSession configuration and usage',
269
- metadata: { title: 'Networking' },
270
- fileName: 'net.md'
271
- };
272
-
273
- const score1 = docService.calculateAdvancedRelevanceScore(
274
- doc,
275
- ['urlsession'],
276
- 'URLSession'
277
- );
278
-
279
- const score2 = docService.calculateAdvancedRelevanceScore(
280
- doc,
281
- ['urlsession', 'configuration'],
282
- 'URLSession configuration'
283
- );
284
-
285
- // Matching both terms should score higher
286
- expect(score2).toBeGreaterThan(score1);
287
- });
288
-
289
- it('should cap content match frequency to prevent spam', () => {
290
- const spamDoc = {
291
- content: 'test '.repeat(100),
292
- metadata: { title: 'Spam' },
293
- fileName: 'spam.md'
294
- };
295
-
296
- const normalDoc = {
297
- content: 'This is a test document with normal content',
298
- metadata: { title: 'Normal' },
299
- fileName: 'normal.md'
300
- };
301
-
302
- const spamScore = docService.calculateAdvancedRelevanceScore(
303
- spamDoc,
304
- ['test'],
305
- 'test'
306
- );
307
-
308
- const normalScore = docService.calculateAdvancedRelevanceScore(
309
- normalDoc,
310
- ['test'],
311
- 'test'
312
- );
313
-
314
- // Spam score should be capped, not drastically higher
315
- expect(spamScore / normalScore).toBeLessThan(5);
316
- });
317
- });
318
- });