gitlab-docs-mcp 1.0.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/LICENSE +21 -0
- package/README.md +130 -0
- package/data/gitlab-docs/documents.json +38252 -0
- package/data/gitlab-docs/index_meta.json +6 -0
- package/dist/bin.js +2 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +54 -0
- package/dist/config.js.map +1 -0
- package/dist/content/cache.d.ts +51 -0
- package/dist/content/cache.d.ts.map +1 -0
- package/dist/content/cache.js +60 -0
- package/dist/content/cache.js.map +1 -0
- package/dist/content/cache.test.d.ts +2 -0
- package/dist/content/cache.test.d.ts.map +1 -0
- package/dist/content/cache.test.js +58 -0
- package/dist/content/cache.test.js.map +1 -0
- package/dist/content/index.d.ts +3 -0
- package/dist/content/index.d.ts.map +1 -0
- package/dist/content/index.js +3 -0
- package/dist/content/index.js.map +1 -0
- package/dist/content/parser.d.ts +32 -0
- package/dist/content/parser.d.ts.map +1 -0
- package/dist/content/parser.js +72 -0
- package/dist/content/parser.js.map +1 -0
- package/dist/content/parser.test.d.ts +2 -0
- package/dist/content/parser.test.d.ts.map +1 -0
- package/dist/content/parser.test.js +71 -0
- package/dist/content/parser.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +92 -0
- package/dist/index.js.map +1 -0
- package/dist/search/document.d.ts +11 -0
- package/dist/search/document.d.ts.map +1 -0
- package/dist/search/document.js +47 -0
- package/dist/search/document.js.map +1 -0
- package/dist/search/engine.d.ts +41 -0
- package/dist/search/engine.d.ts.map +1 -0
- package/dist/search/engine.js +200 -0
- package/dist/search/engine.js.map +1 -0
- package/dist/search/flexsearch-wrapper.d.ts +51 -0
- package/dist/search/flexsearch-wrapper.d.ts.map +1 -0
- package/dist/search/flexsearch-wrapper.js +55 -0
- package/dist/search/flexsearch-wrapper.js.map +1 -0
- package/dist/search/index.d.ts +4 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +4 -0
- package/dist/search/index.js.map +1 -0
- package/dist/tools/getDocPage.d.ts +8 -0
- package/dist/tools/getDocPage.d.ts.map +1 -0
- package/dist/tools/getDocPage.js +48 -0
- package/dist/tools/getDocPage.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +5 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/listDocSections.d.ts +8 -0
- package/dist/tools/listDocSections.d.ts.map +1 -0
- package/dist/tools/listDocSections.js +17 -0
- package/dist/tools/listDocSections.js.map +1 -0
- package/dist/tools/registry.d.ts +14 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +64 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/registry.test.d.ts +2 -0
- package/dist/tools/registry.test.d.ts.map +1 -0
- package/dist/tools/registry.test.js +45 -0
- package/dist/tools/registry.test.js.map +1 -0
- package/dist/tools/searchGitLabDocs.d.ts +19 -0
- package/dist/tools/searchGitLabDocs.d.ts.map +1 -0
- package/dist/tools/searchGitLabDocs.js +25 -0
- package/dist/tools/searchGitLabDocs.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/models.d.ts +57 -0
- package/dist/types/models.d.ts.map +1 -0
- package/dist/types/models.js +41 -0
- package/dist/types/models.js.map +1 -0
- package/dist/utils/constants.d.ts +31 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +38 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/constants.test.d.ts +2 -0
- package/dist/utils/constants.test.d.ts.map +1 -0
- package/dist/utils/constants.test.js +16 -0
- package/dist/utils/constants.test.js.map +1 -0
- package/dist/utils/errors.d.ts +22 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +43 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/errors.test.d.ts +2 -0
- package/dist/utils/errors.test.d.ts.map +1 -0
- package/dist/utils/errors.test.js +55 -0
- package/dist/utils/errors.test.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +23 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +44 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/logger.test.d.ts +2 -0
- package/dist/utils/logger.test.d.ts.map +1 -0
- package/dist/utils/logger.test.js +71 -0
- package/dist/utils/logger.test.js.map +1 -0
- package/dist/utils/performance.d.ts +53 -0
- package/dist/utils/performance.d.ts.map +1 -0
- package/dist/utils/performance.js +130 -0
- package/dist/utils/performance.js.map +1 -0
- package/dist/utils/performance.test.d.ts +2 -0
- package/dist/utils/performance.test.d.ts.map +1 -0
- package/dist/utils/performance.test.js +75 -0
- package/dist/utils/performance.test.js.map +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { logger } from '../utils/logger.js';
|
|
2
|
+
export class DocumentTree {
|
|
3
|
+
sections;
|
|
4
|
+
constructor() {
|
|
5
|
+
this.sections = new Map();
|
|
6
|
+
}
|
|
7
|
+
buildFromEngine(engine) {
|
|
8
|
+
const documents = engine.getAllDocuments();
|
|
9
|
+
const sectionMap = new Map();
|
|
10
|
+
// Group documents by section
|
|
11
|
+
for (const doc of documents) {
|
|
12
|
+
if (!sectionMap.has(doc.section)) {
|
|
13
|
+
sectionMap.set(doc.section, new Set());
|
|
14
|
+
}
|
|
15
|
+
sectionMap.get(doc.section).add(doc.path);
|
|
16
|
+
}
|
|
17
|
+
// Build section tree
|
|
18
|
+
for (const [section, paths] of sectionMap) {
|
|
19
|
+
// Determine subsections (folders under section)
|
|
20
|
+
const subsections = new Set();
|
|
21
|
+
for (const path of paths) {
|
|
22
|
+
const parts = path.split('/');
|
|
23
|
+
if (parts.length > 2) {
|
|
24
|
+
// Has subsection (e.g., ci/pipelines/...)
|
|
25
|
+
subsections.add(parts[1]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
this.sections.set(section, {
|
|
29
|
+
name: section,
|
|
30
|
+
path: section,
|
|
31
|
+
pageCount: paths.size,
|
|
32
|
+
subsections: subsections.size > 0 ? Array.from(subsections).sort() : undefined,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
logger.info(`Built document tree: ${this.sections.size} sections`);
|
|
36
|
+
}
|
|
37
|
+
getAllSections() {
|
|
38
|
+
return Array.from(this.sections.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
39
|
+
}
|
|
40
|
+
getSectionCount() {
|
|
41
|
+
return this.sections.size;
|
|
42
|
+
}
|
|
43
|
+
getSection(name) {
|
|
44
|
+
return this.sections.get(name);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document.js","sourceRoot":"","sources":["../../src/search/document.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,OAAO,YAAY;IACf,QAAQ,CAA0B;IAE1C;QACE,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;IAC5B,CAAC;IAED,eAAe,CAAC,MAAoB;QAClC,MAAM,SAAS,GAAG,MAAM,CAAC,eAAe,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAC;QAElD,6BAA6B;QAC7B,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBACjC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;YACzC,CAAC;YACD,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC;QAED,qBAAqB;QACrB,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,UAAU,EAAE,CAAC;YAC1C,gDAAgD;YAChD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;YACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC9B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACrB,0CAA0C;oBAC1C,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE;gBACzB,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,OAAO;gBACb,SAAS,EAAE,KAAK,CAAC,IAAI;gBACrB,WAAW,EAAE,WAAW,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;aAC/E,CAAC,CAAC;QACL,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,wBAAwB,IAAI,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,CAAC;IACrE,CAAC;IAED,cAAc;QACZ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACzF,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;CACF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { SearchResult, Document as DocType } from '../types/models.js';
|
|
2
|
+
/**
|
|
3
|
+
* Full-text search engine using Flexsearch
|
|
4
|
+
* Provides fast in-memory search across GitLab documentation
|
|
5
|
+
*/
|
|
6
|
+
export declare class SearchEngine {
|
|
7
|
+
private index;
|
|
8
|
+
private documents;
|
|
9
|
+
private indexPath;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new search engine instance
|
|
12
|
+
* @param indexPath - Path to the search index directory
|
|
13
|
+
*/
|
|
14
|
+
constructor(indexPath: string);
|
|
15
|
+
/**
|
|
16
|
+
* Loads the search index from disk
|
|
17
|
+
* Reads documents and adds them to the Flexsearch index
|
|
18
|
+
* @throws {IndexNotFoundError} If index files are missing
|
|
19
|
+
* @throws {IndexLoadError} If index data cannot be parsed
|
|
20
|
+
*/
|
|
21
|
+
loadIndex(): void;
|
|
22
|
+
/**
|
|
23
|
+
* Performs full-text search across documents
|
|
24
|
+
* @param query - Search query string
|
|
25
|
+
* @param maxResults - Maximum number of results to return (default: 10)
|
|
26
|
+
* @param section - Optional section filter
|
|
27
|
+
* @param minScore - Minimum score threshold for results (default: 0.0)
|
|
28
|
+
* @returns Search results with total count
|
|
29
|
+
*/
|
|
30
|
+
search(query: string, maxResults?: number, section?: string, minScore?: number): {
|
|
31
|
+
results: SearchResult[];
|
|
32
|
+
total: number;
|
|
33
|
+
};
|
|
34
|
+
private calculateScore;
|
|
35
|
+
private generateExcerpt;
|
|
36
|
+
isReady(): boolean;
|
|
37
|
+
getDocumentCount(): number;
|
|
38
|
+
getDocument(id: string): DocType | undefined;
|
|
39
|
+
getAllDocuments(): DocType[];
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/search/engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAsB5E;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,SAAS,CAAS;IAE1B;;;OAGG;gBACS,SAAS,EAAE,MAAM;IAa7B;;;;;OAKG;IACH,SAAS,IAAI,IAAI;IAsCjB;;;;;;;OAOG;IACH,MAAM,CACJ,KAAK,EAAE,MAAM,EACb,UAAU,GAAE,MAAW,EACvB,OAAO,CAAC,EAAE,MAAM,EAChB,QAAQ,GAAE,MAAY,GACrB;QAAE,OAAO,EAAE,YAAY,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IA2D7C,OAAO,CAAC,cAAc;IAgDtB,OAAO,CAAC,eAAe;IA4BvB,OAAO,IAAI,OAAO;IAIlB,gBAAgB,IAAI,MAAM;IAI1B,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI5C,eAAe,IAAI,OAAO,EAAE;CAG7B"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
import { IndexNotFoundError, IndexLoadError } from '../utils/errors.js';
|
|
5
|
+
import { FlexSearchIndex } from './flexsearch-wrapper.js';
|
|
6
|
+
import { performanceMonitor } from '../utils/performance.js';
|
|
7
|
+
import { FLEXSEARCH_TOKENIZE, FLEXSEARCH_RESOLUTION, FLEXSEARCH_MIN_LENGTH, FLEXSEARCH_CACHE_SIZE, SCORE_TITLE_MATCH, SCORE_SECTION_MATCH, SCORE_CONTENT_MATCH, SCORE_MAX_CONTENT, SCORE_MAX, DEFAULT_EXCERPT_LENGTH, EXCERPT_CONTEXT_BEFORE, EXCERPT_CONTEXT_AFTER, INDEX_META_FILE, INDEX_DOCS_FILE, } from '../utils/constants.js';
|
|
8
|
+
/**
|
|
9
|
+
* Full-text search engine using Flexsearch
|
|
10
|
+
* Provides fast in-memory search across GitLab documentation
|
|
11
|
+
*/
|
|
12
|
+
export class SearchEngine {
|
|
13
|
+
index;
|
|
14
|
+
documents;
|
|
15
|
+
indexPath;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new search engine instance
|
|
18
|
+
* @param indexPath - Path to the search index directory
|
|
19
|
+
*/
|
|
20
|
+
constructor(indexPath) {
|
|
21
|
+
this.indexPath = indexPath;
|
|
22
|
+
this.documents = new Map();
|
|
23
|
+
// Initialize Flexsearch index with type-safe wrapper
|
|
24
|
+
this.index = new FlexSearchIndex({
|
|
25
|
+
tokenize: FLEXSEARCH_TOKENIZE,
|
|
26
|
+
resolution: FLEXSEARCH_RESOLUTION,
|
|
27
|
+
minlength: FLEXSEARCH_MIN_LENGTH,
|
|
28
|
+
cache: FLEXSEARCH_CACHE_SIZE,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Loads the search index from disk
|
|
33
|
+
* Reads documents and adds them to the Flexsearch index
|
|
34
|
+
* @throws {IndexNotFoundError} If index files are missing
|
|
35
|
+
* @throws {IndexLoadError} If index data cannot be parsed
|
|
36
|
+
*/
|
|
37
|
+
loadIndex() {
|
|
38
|
+
return performanceMonitor.measureSync('index-load', () => {
|
|
39
|
+
const metaPath = join(this.indexPath, INDEX_META_FILE);
|
|
40
|
+
const docsPath = join(this.indexPath, INDEX_DOCS_FILE);
|
|
41
|
+
if (!existsSync(metaPath) || !existsSync(docsPath)) {
|
|
42
|
+
throw new IndexNotFoundError(this.indexPath);
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
// Load documents
|
|
46
|
+
const docsData = JSON.parse(readFileSync(docsPath, 'utf-8'));
|
|
47
|
+
for (const doc of docsData) {
|
|
48
|
+
const typedDoc = doc;
|
|
49
|
+
// Convert lastUpdated string to Date
|
|
50
|
+
if (typeof typedDoc.lastUpdated === 'string') {
|
|
51
|
+
typedDoc.lastUpdated = new Date(typedDoc.lastUpdated);
|
|
52
|
+
}
|
|
53
|
+
this.documents.set(typedDoc.id, typedDoc);
|
|
54
|
+
this.index.add({
|
|
55
|
+
id: typedDoc.id,
|
|
56
|
+
title: typedDoc.title,
|
|
57
|
+
section: typedDoc.section,
|
|
58
|
+
content: typedDoc.content,
|
|
59
|
+
path: typedDoc.path,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
logger.info(`Loaded ${this.documents.size} documents`);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
throw new IndexLoadError('Failed to parse index data', error instanceof Error ? error : undefined);
|
|
66
|
+
}
|
|
67
|
+
}, { documentCount: this.documents.size });
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Performs full-text search across documents
|
|
71
|
+
* @param query - Search query string
|
|
72
|
+
* @param maxResults - Maximum number of results to return (default: 10)
|
|
73
|
+
* @param section - Optional section filter
|
|
74
|
+
* @param minScore - Minimum score threshold for results (default: 0.0)
|
|
75
|
+
* @returns Search results with total count
|
|
76
|
+
*/
|
|
77
|
+
search(query, maxResults = 10, section, minScore = 0.0) {
|
|
78
|
+
return performanceMonitor.measureSync('search', () => {
|
|
79
|
+
// Perform search using type-safe wrapper
|
|
80
|
+
const searchResults = this.index.search(query);
|
|
81
|
+
// Flatten results (Flexsearch returns results per field)
|
|
82
|
+
const docIds = new Set();
|
|
83
|
+
for (const fieldResults of searchResults) {
|
|
84
|
+
if (Array.isArray(fieldResults.result)) {
|
|
85
|
+
for (const item of fieldResults.result) {
|
|
86
|
+
// FlexSearch returns string IDs directly, not objects
|
|
87
|
+
const id = typeof item === 'string' ? item : item.id;
|
|
88
|
+
docIds.add(id);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Convert to SearchResult format
|
|
93
|
+
const results = [];
|
|
94
|
+
for (const id of docIds) {
|
|
95
|
+
const doc = this.documents.get(id);
|
|
96
|
+
if (!doc) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
// Filter by section if specified
|
|
100
|
+
if (section && doc.section !== section) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
// Calculate score (simplified - based on query matches)
|
|
104
|
+
const score = this.calculateScore(query, doc);
|
|
105
|
+
if (score < minScore) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
results.push({
|
|
109
|
+
title: doc.title,
|
|
110
|
+
path: doc.path,
|
|
111
|
+
url: `https://docs.gitlab.com/${doc.path}`,
|
|
112
|
+
excerpt: this.generateExcerpt(query, doc.content),
|
|
113
|
+
score,
|
|
114
|
+
});
|
|
115
|
+
if (results.length >= maxResults) {
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Sort by score
|
|
120
|
+
results.sort((a, b) => b.score - a.score);
|
|
121
|
+
return {
|
|
122
|
+
results: results.slice(0, maxResults),
|
|
123
|
+
total: docIds.size,
|
|
124
|
+
};
|
|
125
|
+
}, { query, maxResults, section, minScore });
|
|
126
|
+
}
|
|
127
|
+
calculateScore(query, doc) {
|
|
128
|
+
const queryLower = query.toLowerCase();
|
|
129
|
+
const titleLower = doc.title.toLowerCase();
|
|
130
|
+
const sectionLower = doc.section.toLowerCase();
|
|
131
|
+
const contentLower = doc.content.toLowerCase();
|
|
132
|
+
let score = 0;
|
|
133
|
+
// Split query into words for better matching
|
|
134
|
+
const queryWords = queryLower.split(/\s+/).filter(w => w.length > 0);
|
|
135
|
+
// Title matches (highest weight)
|
|
136
|
+
for (const word of queryWords) {
|
|
137
|
+
if (titleLower.includes(word)) {
|
|
138
|
+
score += SCORE_TITLE_MATCH;
|
|
139
|
+
// Bonus for exact title match
|
|
140
|
+
if (titleLower === queryLower) {
|
|
141
|
+
score += SCORE_TITLE_MATCH;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Section matches
|
|
146
|
+
for (const word of queryWords) {
|
|
147
|
+
if (sectionLower.includes(word)) {
|
|
148
|
+
score += SCORE_SECTION_MATCH;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// Content match (word frequency)
|
|
152
|
+
for (const word of queryWords) {
|
|
153
|
+
if (word.length >= 3) { // Skip very short words
|
|
154
|
+
const regex = new RegExp(word, 'gi');
|
|
155
|
+
const matches = (contentLower.match(regex) || []).length;
|
|
156
|
+
score += Math.min(matches * SCORE_CONTENT_MATCH, SCORE_MAX_CONTENT / queryWords.length);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Path match bonus (e.g., ci/pipelines for "pipeline" query)
|
|
160
|
+
const pathLower = doc.path.toLowerCase();
|
|
161
|
+
for (const word of queryWords) {
|
|
162
|
+
if (pathLower.includes(word)) {
|
|
163
|
+
score += 0.5;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return Math.min(score, SCORE_MAX);
|
|
167
|
+
}
|
|
168
|
+
generateExcerpt(query, content, maxLength = DEFAULT_EXCERPT_LENGTH) {
|
|
169
|
+
const queryLower = query.toLowerCase();
|
|
170
|
+
const contentLower = content.toLowerCase();
|
|
171
|
+
const index = contentLower.indexOf(queryLower);
|
|
172
|
+
if (index === -1) {
|
|
173
|
+
return content.substring(0, maxLength) + '...';
|
|
174
|
+
}
|
|
175
|
+
// Extract context around match
|
|
176
|
+
const start = Math.max(0, index - EXCERPT_CONTEXT_BEFORE);
|
|
177
|
+
const end = Math.min(content.length, index + query.length + EXCERPT_CONTEXT_AFTER);
|
|
178
|
+
let excerpt = content.substring(start, end);
|
|
179
|
+
if (start > 0) {
|
|
180
|
+
excerpt = '...' + excerpt;
|
|
181
|
+
}
|
|
182
|
+
if (end < content.length) {
|
|
183
|
+
excerpt += '...';
|
|
184
|
+
}
|
|
185
|
+
return excerpt;
|
|
186
|
+
}
|
|
187
|
+
isReady() {
|
|
188
|
+
return this.documents.size > 0;
|
|
189
|
+
}
|
|
190
|
+
getDocumentCount() {
|
|
191
|
+
return this.documents.size;
|
|
192
|
+
}
|
|
193
|
+
getDocument(id) {
|
|
194
|
+
return this.documents.get(id);
|
|
195
|
+
}
|
|
196
|
+
getAllDocuments() {
|
|
197
|
+
return Array.from(this.documents.values());
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/search/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe wrapper for FlexSearch Document index
|
|
3
|
+
* Eliminates the need for @ts-ignore and any type assertions
|
|
4
|
+
*/
|
|
5
|
+
export interface FlexSearchConfig {
|
|
6
|
+
tokenize: string;
|
|
7
|
+
resolution: number;
|
|
8
|
+
minlength: number;
|
|
9
|
+
cache: number | boolean;
|
|
10
|
+
}
|
|
11
|
+
interface IndexDocument {
|
|
12
|
+
id: string;
|
|
13
|
+
title: string;
|
|
14
|
+
section: string;
|
|
15
|
+
content: string;
|
|
16
|
+
path: string;
|
|
17
|
+
}
|
|
18
|
+
interface SearchField {
|
|
19
|
+
field: string;
|
|
20
|
+
result: Array<{
|
|
21
|
+
id: string;
|
|
22
|
+
title?: string;
|
|
23
|
+
section?: string;
|
|
24
|
+
path?: string;
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Type-safe FlexSearch document index wrapper
|
|
29
|
+
*/
|
|
30
|
+
export declare class FlexSearchIndex {
|
|
31
|
+
private index;
|
|
32
|
+
constructor(config: FlexSearchConfig);
|
|
33
|
+
/**
|
|
34
|
+
* Add a document to the index
|
|
35
|
+
*/
|
|
36
|
+
add(doc: IndexDocument): void;
|
|
37
|
+
/**
|
|
38
|
+
* Search the index with type-safe results
|
|
39
|
+
*/
|
|
40
|
+
search(query: string): SearchField[];
|
|
41
|
+
/**
|
|
42
|
+
* Remove a document from the index
|
|
43
|
+
*/
|
|
44
|
+
remove(id: string): void;
|
|
45
|
+
/**
|
|
46
|
+
* Update a document in the index
|
|
47
|
+
*/
|
|
48
|
+
update(doc: IndexDocument): void;
|
|
49
|
+
}
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=flexsearch-wrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flexsearch-wrapper.d.ts","sourceRoot":"","sources":["../../src/search/flexsearch-wrapper.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB;AAED,UAAU,aAAa;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,KAAK,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,qBAAa,eAAe;IAG1B,OAAO,CAAC,KAAK,CAAM;gBAEP,MAAM,EAAE,gBAAgB;IAiBpC;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;IAK7B;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE;IAMpC;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAKxB;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;CAIjC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import FlexSearch from 'flexsearch';
|
|
2
|
+
/**
|
|
3
|
+
* Type-safe FlexSearch document index wrapper
|
|
4
|
+
*/
|
|
5
|
+
export class FlexSearchIndex {
|
|
6
|
+
// Keep internal index as private with controlled type
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
8
|
+
index;
|
|
9
|
+
constructor(config) {
|
|
10
|
+
// Single controlled type assertion point
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
|
|
12
|
+
this.index = new FlexSearch.Document({
|
|
13
|
+
document: {
|
|
14
|
+
id: 'id',
|
|
15
|
+
index: ['title:3', 'section:2', 'content'],
|
|
16
|
+
store: ['title', 'section', 'path'],
|
|
17
|
+
},
|
|
18
|
+
tokenize: config.tokenize,
|
|
19
|
+
resolution: config.resolution,
|
|
20
|
+
minlength: config.minlength,
|
|
21
|
+
optimize: true,
|
|
22
|
+
cache: config.cache,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Add a document to the index
|
|
27
|
+
*/
|
|
28
|
+
add(doc) {
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
30
|
+
this.index.add(doc);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Search the index with type-safe results
|
|
34
|
+
*/
|
|
35
|
+
search(query) {
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
37
|
+
const results = this.index.search(query);
|
|
38
|
+
return results;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Remove a document from the index
|
|
42
|
+
*/
|
|
43
|
+
remove(id) {
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
45
|
+
this.index.remove(id);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Update a document in the index
|
|
49
|
+
*/
|
|
50
|
+
update(doc) {
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
52
|
+
this.index.update(doc);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=flexsearch-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flexsearch-wrapper.js","sourceRoot":"","sources":["../../src/search/flexsearch-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAC;AA+BpC;;GAEG;AACH,MAAM,OAAO,eAAe;IAC1B,sDAAsD;IACtD,8DAA8D;IACtD,KAAK,CAAM;IAEnB,YAAY,MAAwB;QAClC,yCAAyC;QACzC,sLAAsL;QACtL,IAAI,CAAC,KAAK,GAAG,IAAK,UAAkB,CAAC,QAAQ,CAAC;YAC5C,QAAQ,EAAE;gBACR,EAAE,EAAE,IAAI;gBACR,KAAK,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,CAAC;gBAC1C,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC;aACpC;YACD,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,GAAkB;QACpB,yGAAyG;QACzG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAa;QAClB,yGAAyG;QACzG,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAkB,CAAC;QAC1D,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,EAAU;QACf,yGAAyG;QACzG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,GAAkB;QACvB,yGAAyG;QACzG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/search/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,yBAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/search/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,yBAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getDocPage.d.ts","sourceRoot":"","sources":["../../src/tools/getDocPage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAQzD,wBAAsB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW;;;;;GA+CvE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { DocPageResponseSchema } from '../types/models.js';
|
|
3
|
+
import { DocumentNotFoundError } from '../utils/errors.js';
|
|
4
|
+
const GetDocPageArgsSchema = z.object({
|
|
5
|
+
path: z.string(),
|
|
6
|
+
});
|
|
7
|
+
export async function getDocPageTool(args, context) {
|
|
8
|
+
const { path } = GetDocPageArgsSchema.parse(args);
|
|
9
|
+
// Check cache
|
|
10
|
+
const cacheKey = `doc:${path}`;
|
|
11
|
+
const cached = context.cache.get(cacheKey);
|
|
12
|
+
if (cached) {
|
|
13
|
+
return {
|
|
14
|
+
content: [
|
|
15
|
+
{
|
|
16
|
+
type: 'text',
|
|
17
|
+
text: cached,
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
// Find document
|
|
23
|
+
const doc = context.searchEngine.getAllDocuments().find((d) => d.path === path);
|
|
24
|
+
if (!doc) {
|
|
25
|
+
throw new DocumentNotFoundError(path);
|
|
26
|
+
}
|
|
27
|
+
// Parse markdown
|
|
28
|
+
const parsedContent = await context.parser.parse(doc.content);
|
|
29
|
+
const response = DocPageResponseSchema.parse({
|
|
30
|
+
title: doc.title,
|
|
31
|
+
path: doc.path,
|
|
32
|
+
url: `https://docs.gitlab.com/${doc.path}`,
|
|
33
|
+
content: parsedContent,
|
|
34
|
+
metadata: doc.metadata || {},
|
|
35
|
+
});
|
|
36
|
+
// Cache result
|
|
37
|
+
const responseText = JSON.stringify(response, null, 2);
|
|
38
|
+
context.cache.set(cacheKey, responseText);
|
|
39
|
+
return {
|
|
40
|
+
content: [
|
|
41
|
+
{
|
|
42
|
+
type: 'text',
|
|
43
|
+
text: responseText,
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=getDocPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getDocPage.js","sourceRoot":"","sources":["../../src/tools/getDocPage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACjB,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAa,EAAE,OAAoB;IACtE,MAAM,EAAE,IAAI,EAAE,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElD,cAAc;IACd,MAAM,QAAQ,GAAG,OAAO,IAAI,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,MAAM,EAAE,CAAC;QACX,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,MAAM;iBACb;aACF;SACF,CAAC;IACJ,CAAC;IAED,gBAAgB;IAChB,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAEhF,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,iBAAiB;IACjB,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAE9D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,CAAC;QAC3C,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,GAAG,EAAE,2BAA2B,GAAG,CAAC,IAAI,EAAE;QAC1C,OAAO,EAAE,aAAa;QACtB,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE;KAC7B,CAAC,CAAC;IAEH,eAAe;IACf,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAE1C,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,YAAY;aACnB;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listDocSections.d.ts","sourceRoot":"","sources":["../../src/tools/listDocSections.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW;;;;;EAgBtE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ListSectionsResponseSchema } from '../types/models.js';
|
|
2
|
+
export function listDocSectionsTool(args, context) {
|
|
3
|
+
const sections = context.docTree.getAllSections();
|
|
4
|
+
const response = ListSectionsResponseSchema.parse({
|
|
5
|
+
sections,
|
|
6
|
+
total: sections.length,
|
|
7
|
+
});
|
|
8
|
+
return {
|
|
9
|
+
content: [
|
|
10
|
+
{
|
|
11
|
+
type: 'text',
|
|
12
|
+
text: JSON.stringify(response, null, 2),
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=listDocSections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listDocSections.js","sourceRoot":"","sources":["../../src/tools/listDocSections.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAEhE,MAAM,UAAU,mBAAmB,CAAC,IAAa,EAAE,OAAoB;IACrE,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;IAElD,MAAM,QAAQ,GAAG,0BAA0B,CAAC,KAAK,CAAC;QAChD,QAAQ;QACR,KAAK,EAAE,QAAQ,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;aACxC;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* MCP Tool registry - single source of truth for tool definitions
|
|
4
|
+
*/
|
|
5
|
+
export declare const TOOL_DEFINITIONS: Tool[];
|
|
6
|
+
/**
|
|
7
|
+
* Get tool definition by name
|
|
8
|
+
*/
|
|
9
|
+
export declare function getToolDefinition(name: string): Tool | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Validate tool name exists
|
|
12
|
+
*/
|
|
13
|
+
export declare function isValidToolName(name: string): boolean;
|
|
14
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAG1D;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,IAAI,EA8ClC,CAAC;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAEhE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD"}
|