directory-indexer 0.0.19 → 0.1.1
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 +5 -5
- package/dist/cli.js +92 -116
- package/dist/cli.js.map +1 -1
- package/dist/embedding.js +20 -4
- package/dist/embedding.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ docker exec ollama ollama pull nomic-embed-text
|
|
|
38
38
|
**3. Index your directories**
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
npx directory-indexer index ~/Documents ~/Projects
|
|
41
|
+
npx directory-indexer@latest index ~/Documents ~/Projects
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
**4. Configure AI assistant** _(Claude Desktop, Cursor, Cline, Roo Code, Zed etc.)_
|
|
@@ -50,7 +50,7 @@ Add to your MCP configuration:
|
|
|
50
50
|
"mcpServers": {
|
|
51
51
|
"directory-indexer": {
|
|
52
52
|
"command": "npx",
|
|
53
|
-
"args": ["directory-indexer", "serve"]
|
|
53
|
+
"args": ["directory-indexer@latest", "serve"]
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
}
|
|
@@ -134,7 +134,7 @@ Configure with AI assistants (Claude Desktop, Cline, etc.) using npx:
|
|
|
134
134
|
"mcpServers": {
|
|
135
135
|
"directory-indexer": {
|
|
136
136
|
"command": "npx",
|
|
137
|
-
"args": ["directory-indexer", "serve"]
|
|
137
|
+
"args": ["directory-indexer@latest", "serve"]
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
}
|
|
@@ -144,7 +144,7 @@ Index your directories:
|
|
|
144
144
|
|
|
145
145
|
```bash
|
|
146
146
|
# Index your directories first
|
|
147
|
-
npx directory-indexer index /home/user/projects/docs /home/user/work/reports
|
|
147
|
+
npx directory-indexer@latest index /home/user/projects/docs /home/user/work/reports
|
|
148
148
|
```
|
|
149
149
|
|
|
150
150
|
**How it works:**
|
|
@@ -186,7 +186,7 @@ Configure with custom endpoints and data directory:
|
|
|
186
186
|
"mcpServers": {
|
|
187
187
|
"directory-indexer": {
|
|
188
188
|
"command": "npx",
|
|
189
|
-
"args": ["directory-indexer", "serve"],
|
|
189
|
+
"args": ["directory-indexer@latest", "serve"],
|
|
190
190
|
"env": {
|
|
191
191
|
"DIRECTORY_INDEXER_DATA_DIR": "/opt/ai-knowledge-base",
|
|
192
192
|
"QDRANT_ENDPOINT": "http://localhost:6333",
|
package/dist/cli.js
CHANGED
|
@@ -17,31 +17,31 @@ const VERSION$1 = packageJson$1.version;
|
|
|
17
17
|
const MCP_TOOLS = [
|
|
18
18
|
{
|
|
19
19
|
name: "index",
|
|
20
|
-
description: `Index directories
|
|
20
|
+
description: `Index directories to make their files searchable. Processes files to create vector embeddings for semantic search.
|
|
21
21
|
|
|
22
22
|
When to use this tool:
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
- When setting up semantic search for a project or workspace
|
|
23
|
+
- User specifically requests indexing a directory as a knowledge base
|
|
24
|
+
- Adding new documentation, code repositories, or file collections to search
|
|
25
|
+
- Updating index when many files have changed
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
- Recursively scans directories for supported file types
|
|
30
|
-
-
|
|
31
|
-
- Generates vector embeddings
|
|
32
|
-
- Stores
|
|
33
|
-
- Skips unchanged files on re-indexing for efficiency
|
|
34
|
-
- Supports overlapping directory paths (files are deduplicated automatically)
|
|
27
|
+
How it works:
|
|
28
|
+
- Recursively scans directories for supported file types
|
|
29
|
+
- Extracts text content and splits into chunks
|
|
30
|
+
- Generates vector embeddings for semantic similarity
|
|
31
|
+
- Stores in database for fast retrieval
|
|
35
32
|
|
|
36
|
-
|
|
33
|
+
Examples:
|
|
34
|
+
- Index documentation: "/home/user/docs/project-wiki"
|
|
35
|
+
- Index codebase: "/home/user/projects/api-server"
|
|
36
|
+
- Index multiple directories: "/home/user/docs,/home/user/configs"
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
Indexing can take several minutes for large directories. Most users will already have directories indexed and can directly use search tool. Use server_info to check current indexing status first.`,
|
|
39
39
|
inputSchema: {
|
|
40
40
|
type: "object",
|
|
41
41
|
properties: {
|
|
42
42
|
directory_path: {
|
|
43
43
|
type: "string",
|
|
44
|
-
description: 'Comma-separated list of absolute
|
|
44
|
+
description: 'Comma-separated list of absolute directory paths to index. Must be absolute paths since MCP server runs independently. Examples: "/home/user/projects" (Unix) or "C:\\Users\\user\\projects" (Windows)'
|
|
45
45
|
}
|
|
46
46
|
},
|
|
47
47
|
required: ["directory_path"]
|
|
@@ -49,19 +49,28 @@ Performance note: Initial indexing may take time for large directories, but subs
|
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
name: "search",
|
|
52
|
-
description: `
|
|
52
|
+
description: `Search indexed files using natural language queries. Finds files containing content semantically similar to the query.
|
|
53
53
|
|
|
54
54
|
When to use this tool:
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
- Finding files related to specific features or topics
|
|
55
|
+
- Find documentation, guides, or explanations about specific topics
|
|
56
|
+
- Locate code files implementing certain functionality or patterns
|
|
57
|
+
- Discover configuration files, scripts, or settings related to a topic
|
|
58
|
+
- Search for files covering specific concepts or technologies
|
|
60
59
|
|
|
61
|
-
How
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
60
|
+
How it works:
|
|
61
|
+
- Converts query to vector embedding using semantic similarity
|
|
62
|
+
- Searches all indexed file chunks for relevant content
|
|
63
|
+
- Groups results by file and calculates average relevance scores
|
|
64
|
+
- Returns files ranked by relevance score
|
|
65
|
+
|
|
66
|
+
Examples:
|
|
67
|
+
- "database configuration" - finds config files, documentation about DB setup
|
|
68
|
+
- "error handling patterns" - finds code files with exception handling
|
|
69
|
+
- "authentication implementation" - finds auth-related code and docs
|
|
70
|
+
- "API documentation" - finds API guides, endpoint definitions
|
|
71
|
+
- "deployment scripts" - finds CI/CD configs, deployment automation
|
|
72
|
+
|
|
73
|
+
Returns files with similarity scores and chunk information. Use get_content to retrieve full file content or get_chunk to retrieve specific chunk content by chunk ID.
|
|
65
74
|
- Groups results by file to avoid duplicates from multiple matching sections
|
|
66
75
|
|
|
67
76
|
Response format:
|
|
@@ -92,30 +101,26 @@ Example queries:
|
|
|
92
101
|
},
|
|
93
102
|
{
|
|
94
103
|
name: "similar_files",
|
|
95
|
-
description: `Find files
|
|
104
|
+
description: `Find files with content similar to a reference file. Uses semantic similarity to find related documents, code files, or any text content.
|
|
96
105
|
|
|
97
106
|
When to use this tool:
|
|
98
|
-
-
|
|
99
|
-
-
|
|
100
|
-
-
|
|
101
|
-
-
|
|
102
|
-
- Exploring unfamiliar codebases by finding files similar to known examples
|
|
103
|
-
- Locating test files, configuration files, or documentation related to a source file
|
|
107
|
+
- Find documentation similar to a specific guide or README
|
|
108
|
+
- Locate related code files, configuration files, or scripts
|
|
109
|
+
- Discover alternative implementations or approaches
|
|
110
|
+
- Find files covering similar topics or concepts
|
|
104
111
|
|
|
105
|
-
How
|
|
112
|
+
How it works:
|
|
106
113
|
- Analyzes the semantic content of the reference file
|
|
107
114
|
- Compares against all indexed files using vector similarity
|
|
108
|
-
-
|
|
109
|
-
- Returns files ranked by content similarity, not just filename or location similarity
|
|
110
|
-
- Works across different file types and programming languages
|
|
115
|
+
- Returns files ranked by content similarity score
|
|
111
116
|
|
|
112
|
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
+
Examples:
|
|
118
|
+
- Given "deployment-guide.md" - finds other deployment docs, CI/CD guides, infrastructure setup
|
|
119
|
+
- Given "troubleshooting.md" - finds other troubleshooting guides, FAQ files, error documentation
|
|
120
|
+
- Given "config.yaml" - finds other configuration files, settings, environment setups
|
|
121
|
+
- Given "auth.py" - finds other authentication modules, security code, middleware
|
|
117
122
|
|
|
118
|
-
|
|
123
|
+
Returns file paths with similarity scores. Use get_content to read full files or get_chunk for specific sections.`,
|
|
119
124
|
inputSchema: {
|
|
120
125
|
type: "object",
|
|
121
126
|
properties: {
|
|
@@ -134,34 +139,26 @@ Note: The reference file must be indexed for this tool to work. If the file is n
|
|
|
134
139
|
},
|
|
135
140
|
{
|
|
136
141
|
name: "get_content",
|
|
137
|
-
description: `Retrieve the full content of a file or specific chunks
|
|
142
|
+
description: `Retrieve the full content of a file or specific chunks. Reads files directly from the filesystem.
|
|
138
143
|
|
|
139
144
|
When to use this tool:
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
-
-
|
|
144
|
-
- Following up on search results with detailed content examination
|
|
145
|
+
- Get complete file content after finding files through search
|
|
146
|
+
- Read documentation, code files, or configuration files for analysis
|
|
147
|
+
- Extract specific sections of large files using chunk ranges
|
|
148
|
+
- Access any text-based file content
|
|
145
149
|
|
|
146
|
-
How
|
|
147
|
-
-
|
|
148
|
-
-
|
|
149
|
-
-
|
|
150
|
-
-
|
|
151
|
-
- Useful for large files where you only need specific sections identified by search
|
|
150
|
+
How it works:
|
|
151
|
+
- Reads files directly from filesystem (not from search index)
|
|
152
|
+
- Returns entire file by default
|
|
153
|
+
- Can return specific chunk ranges for indexed files
|
|
154
|
+
- Preserves original formatting and content
|
|
152
155
|
|
|
153
|
-
|
|
154
|
-
-
|
|
155
|
-
-
|
|
156
|
-
-
|
|
157
|
-
- Preserves original formatting and content exactly as stored
|
|
156
|
+
Examples:
|
|
157
|
+
- Get full file: file_path="/home/user/docs/api.md"
|
|
158
|
+
- Get specific chunks: file_path="/home/user/code/main.py", chunks="2-5"
|
|
159
|
+
- Get single chunk: file_path="/home/user/config.json", chunks="1"
|
|
158
160
|
|
|
159
|
-
|
|
160
|
-
1. Use 'search' to find relevant files and identify interesting chunk IDs
|
|
161
|
-
2. Use 'get_content' to retrieve full file content or specific chunks
|
|
162
|
-
3. Analyze the content to understand context and implementation details
|
|
163
|
-
|
|
164
|
-
Performance note: For large files, using chunk ranges can be more efficient than reading entire files.`,
|
|
161
|
+
Returns file content as text. Use this after search or similar_files to read actual content.`,
|
|
165
162
|
inputSchema: {
|
|
166
163
|
type: "object",
|
|
167
164
|
properties: {
|
|
@@ -179,34 +176,26 @@ Performance note: For large files, using chunk ranges can be more efficient than
|
|
|
179
176
|
},
|
|
180
177
|
{
|
|
181
178
|
name: "get_chunk",
|
|
182
|
-
description: `Retrieve
|
|
179
|
+
description: `Retrieve content of a specific chunk from an indexed file. Gets exact text segments identified during search.
|
|
183
180
|
|
|
184
181
|
When to use this tool:
|
|
185
|
-
-
|
|
186
|
-
-
|
|
187
|
-
-
|
|
188
|
-
-
|
|
189
|
-
- When working with large files and you only need particular sections
|
|
190
|
-
|
|
191
|
-
How chunks work:
|
|
192
|
-
- Files are divided into overlapping text segments during indexing for better search granularity
|
|
193
|
-
- Each chunk represents a coherent section of text (typically 512 characters with overlap)
|
|
194
|
-
- Chunk IDs are sequential strings ("0", "1", "2", etc.) within each file
|
|
195
|
-
- Search results include chunk IDs for the most relevant sections
|
|
196
|
-
- This tool retrieves the exact content that was semantically matched
|
|
182
|
+
- Get specific relevant sections after performing a search
|
|
183
|
+
- Access only the most pertinent parts of large files
|
|
184
|
+
- Retrieve content from high-scoring chunks identified in search results
|
|
185
|
+
- Avoid reading entire files when only specific sections are needed
|
|
197
186
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
187
|
+
How it works:
|
|
188
|
+
- Files are split into overlapping text chunks during indexing
|
|
189
|
+
- Each chunk has a sequential ID ("0", "1", "2", etc.)
|
|
190
|
+
- Search results include chunk IDs for relevant sections
|
|
191
|
+
- Returns the exact content that was semantically matched
|
|
202
192
|
|
|
203
|
-
|
|
204
|
-
-
|
|
205
|
-
-
|
|
206
|
-
-
|
|
207
|
-
- Enables focused analysis on the most important content
|
|
193
|
+
Examples:
|
|
194
|
+
- After search returns chunk "3" from "api-docs.md" with high score
|
|
195
|
+
- Get chunk content: file_path="/docs/api-docs.md", chunk_id="3"
|
|
196
|
+
- Returns the specific text segment that matched your query
|
|
208
197
|
|
|
209
|
-
|
|
198
|
+
Returns chunk content as text. Use this with chunk IDs from search results to get precise content sections.`,
|
|
210
199
|
inputSchema: {
|
|
211
200
|
type: "object",
|
|
212
201
|
properties: {
|
|
@@ -224,39 +213,26 @@ Note: Both the file and the specific chunk must exist in the search index for th
|
|
|
224
213
|
},
|
|
225
214
|
{
|
|
226
215
|
name: "server_info",
|
|
227
|
-
description: `Get
|
|
216
|
+
description: `Get information about server status and indexed content. Shows what directories and files are available for search.
|
|
228
217
|
|
|
229
218
|
When to use this tool:
|
|
230
|
-
-
|
|
231
|
-
-
|
|
232
|
-
-
|
|
233
|
-
-
|
|
234
|
-
- To get an overview of available content for semantic search
|
|
235
|
-
- To check system health and identify any configuration problems
|
|
219
|
+
- Check what content is already indexed before performing searches
|
|
220
|
+
- Verify system is working properly
|
|
221
|
+
- See indexing statistics and status
|
|
222
|
+
- Understand scope of available searchable content
|
|
236
223
|
|
|
237
|
-
|
|
238
|
-
-
|
|
239
|
-
-
|
|
240
|
-
-
|
|
241
|
-
-
|
|
242
|
-
- List of all indexed directories with individual statistics
|
|
243
|
-
- File counts and chunk counts per directory
|
|
244
|
-
- Indexing status for each directory (completed, failed, in progress)
|
|
245
|
-
- Error reports and processing issues
|
|
246
|
-
- System consistency checks between database components
|
|
224
|
+
How it works:
|
|
225
|
+
- Reports total indexed directories, files, and chunks
|
|
226
|
+
- Shows database size and last indexing time
|
|
227
|
+
- Lists all indexed directories with file counts
|
|
228
|
+
- Reports any errors or issues
|
|
247
229
|
|
|
248
|
-
|
|
249
|
-
-
|
|
250
|
-
-
|
|
251
|
-
-
|
|
252
|
-
- Recent errors or warnings that may affect search quality
|
|
230
|
+
Examples:
|
|
231
|
+
- Check before searching: "What content is indexed?"
|
|
232
|
+
- Verify after indexing: "Did the indexing complete successfully?"
|
|
233
|
+
- Monitor system: "How many files are searchable?"
|
|
253
234
|
|
|
254
|
-
Use this
|
|
255
|
-
- Verify setup before performing search operations
|
|
256
|
-
- Understand the scope of available content
|
|
257
|
-
- Troubleshoot search or indexing issues
|
|
258
|
-
- Plan additional indexing operations
|
|
259
|
-
- Monitor system health and performance`,
|
|
235
|
+
Returns server version, indexing statistics, directory list, and any errors. Use this to understand what content is available for search and similar_files tools.`,
|
|
260
236
|
inputSchema: {
|
|
261
237
|
type: "object",
|
|
262
238
|
properties: {},
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../src/mcp.ts","../src/cli.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { \n CallToolRequestSchema, \n ListToolsRequestSchema,\n Tool\n} from '@modelcontextprotocol/sdk/types.js';\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { Config } from './config.js';\nimport { indexDirectories } from './indexing.js';\nimport { searchContent, findSimilarFiles, getFileContent, getChunkContent } from './search.js';\nimport { getIndexStatus } from './storage.js';\n\n// Read version from package.json\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst packageJsonPath = join(__dirname, '../package.json');\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\nconst VERSION = packageJson.version;\n\nconst MCP_TOOLS: Tool[] = [\n {\n name: 'index',\n description: `Index directories for AI-powered semantic search. This tool processes files in specified directories, extracts text content, generates vector embeddings, and stores them for semantic search capabilities.\n\nWhen to use this tool:\n- Before performing any search operations on new directories\n- When you want to add new code repositories, documentation, or text files to the searchable knowledge base\n- To update the index when files have been modified (the tool automatically detects and reprocesses changed files)\n- When setting up semantic search for a project or workspace\n\nWhat this tool does:\n- Recursively scans directories for supported file types (code, markdown, text, config files)\n- Chunks large files into smaller segments for better search precision\n- Generates vector embeddings using the configured embedding model\n- Stores file metadata and embeddings in a local database\n- Skips unchanged files on re-indexing for efficiency\n- Supports overlapping directory paths (files are deduplicated automatically)\n\nSupported file types: .md, .txt, .py, .js, .ts, .go, .rs, .java, .json, .yaml, .toml, .env, .conf, and many others\n\nPerformance note: Initial indexing may take time for large directories, but subsequent re-indexing is much faster as only changed files are reprocessed.`,\n inputSchema: {\n type: 'object',\n properties: {\n directory_path: {\n type: 'string',\n description: 'Comma-separated list of absolute or relative directory paths to index. Examples: \"/home/user/projects\" or \"./src,./docs,./tests\"'\n }\n },\n required: ['directory_path']\n }\n },\n {\n name: 'search',\n description: `Perform semantic search across indexed files using natural language queries. This tool uses vector similarity to find the most relevant content, going beyond simple keyword matching to understand intent and context.\n\nWhen to use this tool:\n- Finding code examples, functions, or patterns (\"error handling in Python\", \"JWT authentication implementation\")\n- Locating documentation or explanations (\"how to configure Redis\", \"API rate limiting guide\")\n- Discovering similar functionality across files (\"database connection patterns\", \"logging utilities\")\n- Research and exploration of codebases (\"machine learning models\", \"test utilities\")\n- Finding files related to specific features or topics\n\nHow semantic search works:\n- Searches by meaning and context, not just exact keywords\n- Finds conceptually related content even with different terminology\n- Returns files ranked by relevance with similarity scores\n- Groups results by file to avoid duplicates from multiple matching sections\n\nResponse format:\n- Returns lightweight metadata including file paths, relevance scores, and chunk IDs\n- Use 'get_chunk' or 'get_content' tools to fetch actual content from search results\n- Chunks are sorted by relevance score within each file\n- Average similarity score calculated across all matching chunks per file\n\nExample queries:\n- \"error handling patterns\" (finds try/catch, error classes, logging)\n- \"database migration scripts\" (finds SQL, schema changes, migration files)\n- \"authentication middleware\" (finds auth logic, JWT handling, middleware functions)`,\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Natural language search query describing what you are looking for. Can be concepts, functionality, or specific technical terms.'\n },\n limit: {\n type: 'number',\n description: 'Maximum number of files to return (default: 10). Each file may contain multiple matching chunks.',\n default: 10\n }\n },\n required: ['query']\n }\n },\n {\n name: 'similar_files',\n description: `Find files that are semantically similar to a given reference file. This tool analyzes the content and context of a file to discover other files with related functionality, similar patterns, or comparable content.\n\nWhen to use this tool:\n- Discovering related implementations across a codebase (\"find files similar to this authentication module\")\n- Locating alternative approaches or patterns (\"find other components like this React component\")\n- Finding documentation or examples related to a specific file\n- Identifying code duplication or similar functionality that could be refactored\n- Exploring unfamiliar codebases by finding files similar to known examples\n- Locating test files, configuration files, or documentation related to a source file\n\nHow similarity detection works:\n- Analyzes the semantic content of the reference file\n- Compares against all indexed files using vector similarity\n- Considers code patterns, function signatures, imports, and documentation\n- Returns files ranked by content similarity, not just filename or location similarity\n- Works across different file types and programming languages\n\nUse cases:\n- Code analysis: \"Find files similar to this database model to understand the schema patterns\"\n- Learning: \"Show me other API controllers similar to this one\"\n- Maintenance: \"Find files with similar error handling patterns\"\n- Architecture: \"Locate other services that follow this microservice pattern\"\n\nNote: The reference file must be indexed for this tool to work. If the file is not found in the index, an error will be returned.`,\n inputSchema: {\n type: 'object',\n properties: {\n file_path: {\n type: 'string',\n description: 'Absolute or relative path to the reference file. This file must have been previously indexed.'\n },\n limit: {\n type: 'number',\n description: 'Maximum number of similar files to return (default: 10). Results are sorted by similarity score.',\n default: 10\n }\n },\n required: ['file_path']\n }\n },\n {\n name: 'get_content',\n description: `Retrieve the full content of a file or specific chunks within a file. This tool reads files directly from the filesystem and can optionally return only specific portions of indexed files.\n\nWhen to use this tool:\n- After performing a search, to retrieve the actual content of relevant files\n- Reading complete files that were identified through semantic search\n- Extracting specific sections of large files using chunk ranges\n- Accessing source code, documentation, or configuration files for analysis\n- Following up on search results with detailed content examination\n\nHow chunk selection works:\n- If no chunks parameter is provided, returns the entire file content\n- Chunk ranges allow selective reading of large files (e.g., \"2-5\" returns chunks 2, 3, 4, and 5)\n- Single chunks can be specified (e.g., \"3\" returns only chunk 3)\n- Chunks are the same segments created during indexing for semantic search\n- Useful for large files where you only need specific sections identified by search\n\nFile access:\n- Reads files directly from the filesystem (not from the search index)\n- Works with any readable file, whether indexed or not\n- Supports all text-based file formats\n- Preserves original formatting and content exactly as stored\n\nWorkflow integration:\n1. Use 'search' to find relevant files and identify interesting chunk IDs\n2. Use 'get_content' to retrieve full file content or specific chunks\n3. Analyze the content to understand context and implementation details\n\nPerformance note: For large files, using chunk ranges can be more efficient than reading entire files.`,\n inputSchema: {\n type: 'object',\n properties: {\n file_path: {\n type: 'string',\n description: 'Absolute or relative path to the file to retrieve. File must be readable and text-based.'\n },\n chunks: {\n type: 'string',\n description: 'Optional chunk range specification. Examples: \"3\" (single chunk), \"2-5\" (chunks 2 through 5), \"1-3\" (first three chunks). Only works for indexed files.'\n }\n },\n required: ['file_path']\n }\n },\n {\n name: 'get_chunk',\n description: `Retrieve the content of a specific chunk from an indexed file. This tool provides precise access to individual text segments that were identified during semantic search, allowing efficient retrieval of only the most relevant content.\n\nWhen to use this tool:\n- After performing a 'search' operation, to fetch the actual content of specific chunks that matched your query\n- When you want to examine only the most relevant sections of a file rather than reading the entire file\n- For targeted content analysis where you need specific text segments identified by their chunk IDs\n- To build contextual responses using only the most semantically relevant portions of files\n- When working with large files and you only need particular sections\n\nHow chunks work:\n- Files are divided into overlapping text segments during indexing for better search granularity\n- Each chunk represents a coherent section of text (typically 512 characters with overlap)\n- Chunk IDs are sequential strings (\"0\", \"1\", \"2\", etc.) within each file\n- Search results include chunk IDs for the most relevant sections\n- This tool retrieves the exact content that was semantically matched\n\nTypical workflow:\n1. Use 'search' to find files and get chunk IDs with high relevance scores\n2. Use 'get_chunk' to retrieve the specific content of the most relevant chunks\n3. Analyze or process only the most pertinent text segments\n\nEfficiency benefits:\n- Avoids transferring unnecessary content from large files\n- Provides precise access to semantically relevant text\n- Reduces token usage by fetching only needed sections\n- Enables focused analysis on the most important content\n\nNote: Both the file and the specific chunk must exist in the search index for this tool to work.`,\n inputSchema: {\n type: 'object',\n properties: {\n file_path: {\n type: 'string',\n description: 'Absolute or relative path to the indexed file containing the desired chunk.'\n },\n chunk_id: {\n type: 'string',\n description: 'ID of the specific chunk to retrieve. This is typically obtained from search results and is a sequential string like \"0\", \"1\", \"2\", etc.'\n }\n },\n required: ['file_path', 'chunk_id']\n }\n },\n {\n name: 'server_info',\n description: `Get comprehensive information about the directory indexer server status, configuration, and indexed content. This tool provides a complete overview of the current state of the semantic search system.\n\nWhen to use this tool:\n- To check if the indexer is properly set up and operational\n- Before starting work to understand what content is already indexed\n- To verify indexing operations completed successfully\n- When debugging search issues or unexpected results\n- To get an overview of available content for semantic search\n- To check system health and identify any configuration problems\n\nInformation provided:\n- Server version and operational status\n- Total count of indexed directories, files, and searchable chunks\n- Database size and storage information\n- Most recent indexing timestamp\n- List of all indexed directories with individual statistics\n- File counts and chunk counts per directory\n- Indexing status for each directory (completed, failed, in progress)\n- Error reports and processing issues\n- System consistency checks between database components\n\nStatus indicators:\n- Operational status of vector database (Qdrant) connection\n- Embedding service availability\n- Data consistency between SQLite metadata and vector storage\n- Recent errors or warnings that may affect search quality\n\nUse this tool to:\n- Verify setup before performing search operations\n- Understand the scope of available content\n- Troubleshoot search or indexing issues\n- Plan additional indexing operations\n- Monitor system health and performance`,\n inputSchema: {\n type: 'object',\n properties: {},\n additionalProperties: false\n }\n }\n];\n\nexport async function startMcpServer(config: Config): Promise<void> {\n const server = new Server(\n {\n name: 'directory-indexer',\n version: VERSION\n },\n {\n capabilities: {\n tools: {}\n }\n }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: MCP_TOOLS\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n switch (name) {\n case 'index': {\n if (!args || typeof args.directory_path !== 'string') {\n throw new Error('directory_path is required');\n }\n const paths = args.directory_path.split(',').map((p: string) => p.trim());\n const result = await indexDirectories(paths, config);\n return {\n content: [\n {\n type: 'text',\n text: `Indexed ${result.indexed} files, skipped ${result.skipped} files, ${result.errors.length} errors`\n }\n ]\n };\n }\n\n case 'search': {\n if (!args || typeof args.query !== 'string') {\n throw new Error('query is required');\n }\n const results = await searchContent(args.query, { limit: (args.limit as number) || 10 });\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(results, null, 2)\n }\n ]\n };\n }\n\n case 'similar_files': {\n if (!args || typeof args.file_path !== 'string') {\n throw new Error('file_path is required');\n }\n const results = await findSimilarFiles(args.file_path, (args.limit as number) || 10);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(results, null, 2)\n }\n ]\n };\n }\n\n case 'get_content': {\n if (!args || typeof args.file_path !== 'string') {\n throw new Error('file_path is required');\n }\n const content = await getFileContent(args.file_path, args.chunks as string);\n return {\n content: [\n {\n type: 'text',\n text: content\n }\n ]\n };\n }\n\n case 'get_chunk': {\n if (!args || typeof args.file_path !== 'string' || typeof args.chunk_id !== 'string') {\n throw new Error('file_path and chunk_id are required');\n }\n const content = await getChunkContent(args.file_path, args.chunk_id);\n return {\n content: [\n {\n type: 'text',\n text: content\n }\n ]\n };\n }\n\n case 'server_info': {\n const status = await getIndexStatus();\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n name: 'directory-indexer',\n version: VERSION,\n status: status\n }, null, 2)\n }\n ]\n };\n }\n\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n return {\n content: [\n {\n type: 'text',\n text: `Error: ${errorMessage}`\n }\n ],\n isError: true\n };\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n \n if (config.verbose) {\n console.error('MCP server started successfully');\n }\n}","#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { fileURLToPath } from 'url';\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { indexDirectories } from './indexing.js';\nimport { searchContent, findSimilarFiles, getFileContent } from './search.js';\nimport { loadConfig } from './config.js';\nimport { getIndexStatus } from './storage.js';\nimport { startMcpServer } from './mcp.js';\n\n// Read version from package.json\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst packageJsonPath = join(__dirname, '../package.json');\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\nconst VERSION = packageJson.version;\n\nexport async function main() {\n const program = new Command();\n \n program\n .name('directory-indexer')\n .description('AI-powered directory indexing with semantic search')\n .version(VERSION);\n\n program\n .command('index')\n .description('Index directories for semantic search')\n .argument('<paths...>', 'Directory paths to index')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (paths: string[], options) => {\n try {\n const config = await loadConfig({ verbose: options.verbose });\n console.log(`Indexing ${paths.length} ${paths.length === 1 ? 'directory' : 'directories'}: ${paths.join(', ')}`);\n const result = await indexDirectories(paths, config);\n console.log(`Indexed ${result.indexed} files, skipped ${result.skipped} files, ${result.errors.length} errors`);\n if (result.errors.length > 0 && config.verbose) {\n console.log('Errors:', result.errors);\n }\n } catch (error) {\n console.error('Error indexing directories:', error);\n process.exit(1);\n }\n });\n\n program\n .command('search')\n .description('Search indexed content semantically')\n .argument('<query>', 'Search query')\n .option('-l, --limit <number>', 'Maximum number of results', '10')\n .option('-c, --show-chunks', 'Show individual chunk scores and IDs')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (query: string, options) => {\n try {\n await loadConfig({ verbose: options.verbose });\n const results = await searchContent(query, { limit: parseInt(options.limit) });\n \n if (results.length === 0) {\n console.log('No results found');\n return;\n }\n\n console.log(`Found ${results.length} results:\\n`);\n results.forEach((result, index) => {\n console.log(`${index + 1}. ${result.filePath}`);\n console.log(` Score: ${result.score.toFixed(3)} (${result.matchingChunks} chunks)`);\n \n if (options.showChunks && result.chunks.length > 0) {\n console.log(` Chunks:`);\n result.chunks.forEach(chunk => {\n console.log(` - Chunk ${chunk.chunkId}: ${chunk.score.toFixed(3)}`);\n });\n }\n \n console.log();\n });\n } catch (error) {\n console.error('Error searching content:', error);\n process.exit(1);\n }\n });\n\n program\n .command('similar')\n .description('Find files similar to a given file')\n .argument('<file>', 'File path to find similar files for')\n .option('-l, --limit <number>', 'Maximum number of results', '10')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (filePath: string, options) => {\n try {\n await loadConfig({ verbose: options.verbose });\n const results = await findSimilarFiles(filePath, parseInt(options.limit));\n \n if (results.length === 0) {\n console.log('No similar files found');\n return;\n }\n\n console.log(`Found ${results.length} similar files:\\n`);\n results.forEach((result, index) => {\n console.log(`${index + 1}. ${result.filePath}`);\n console.log(` Similarity: ${result.score.toFixed(3)}`);\n console.log();\n });\n } catch (error) {\n console.error('Error finding similar files:', error);\n process.exit(1);\n }\n });\n\n program\n .command('get')\n .description('Get file content')\n .argument('<file>', 'File path to retrieve')\n .option('-c, --chunks <range>', 'Chunk range (e.g., \"2-5\")')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (filePath: string, options) => {\n try {\n await loadConfig({ verbose: options.verbose });\n const content = await getFileContent(filePath, options.chunks);\n console.log(content);\n } catch (error) {\n console.error('Error getting file content:', error);\n process.exit(1);\n }\n });\n\n program\n .command('serve')\n .description('Start MCP server')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (options) => {\n try {\n const config = await loadConfig({ verbose: options.verbose });\n await startMcpServer(config);\n } catch (error) {\n console.error('Error starting MCP server:', error);\n process.exit(1);\n }\n });\n\n program\n .command('status')\n .description('Show indexing status')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (options) => {\n try {\n await loadConfig({ verbose: options.verbose });\n const status = await getIndexStatus();\n \n console.log('Directory Indexer Status Report');\n console.log('=====================================');\n console.log('');\n console.log('OVERVIEW:');\n console.log(` • ${status.directoriesIndexed} directories have been indexed`);\n console.log(` • ${status.filesIndexed} files processed for semantic search`);\n console.log(` • ${status.chunksIndexed} text chunks available for AI search`);\n console.log(` • Database storage: ${status.databaseSize}`);\n console.log(` • Most recent indexing: ${status.lastIndexed || 'No indexing performed yet'}`);\n \n if (status.errors.length > 0) {\n console.log(` • Processing errors encountered: ${status.errors.length}`);\n if (options.verbose) {\n console.log('');\n console.log('RECENT ERRORS:');\n status.errors.slice(0, 5).forEach(error => {\n console.log(` - ${error}`);\n });\n }\n }\n \n console.log('');\n console.log('INDEXED DIRECTORIES:');\n if (status.directories.length === 0) {\n console.log(' No directories have been indexed yet.');\n console.log(' Run \"directory-indexer index <path>\" to start indexing.');\n } else {\n status.directories.forEach(dir => {\n console.log('');\n console.log(` Directory: ${dir.path}`);\n console.log(` • Indexing status: ${dir.status}`);\n console.log(` • Files processed: ${dir.filesCount}`);\n console.log(` • Searchable chunks: ${dir.chunksCount}`);\n console.log(` • Last indexed: ${dir.lastIndexed || 'Never completed'}`);\n if (dir.errors.length > 0) {\n console.log(` • Files with errors: ${dir.errors.length}`);\n if (options.verbose) {\n console.log(' • Recent errors:');\n dir.errors.slice(0, 3).forEach(error => {\n console.log(` - ${error}`);\n });\n }\n }\n });\n }\n \n if (!status.qdrantConsistency.isConsistent) {\n console.log('');\n console.log('SYSTEM STATUS:');\n status.qdrantConsistency.issues.forEach(issue => {\n console.log(` • ${issue}`);\n });\n console.log('');\n console.log('ℹ️ Note: Status messages above may be normal during setup or active indexing.');\n } else {\n console.log('');\n console.log('SYSTEM STATUS:');\n console.log(' • All systems operational - ready for AI-powered search');\n }\n } catch (error) {\n console.error('Error getting status:', error);\n process.exit(1);\n }\n });\n\n await program.parseAsync();\n}\n\n// Main function is already exported above"],"names":["__dirname","packageJsonPath","packageJson","VERSION"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../src/mcp.ts","../src/cli.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { \n CallToolRequestSchema, \n ListToolsRequestSchema,\n Tool\n} from '@modelcontextprotocol/sdk/types.js';\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { Config } from './config.js';\nimport { indexDirectories } from './indexing.js';\nimport { searchContent, findSimilarFiles, getFileContent, getChunkContent } from './search.js';\nimport { getIndexStatus } from './storage.js';\n\n// Read version from package.json\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst packageJsonPath = join(__dirname, '../package.json');\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\nconst VERSION = packageJson.version;\n\nconst MCP_TOOLS: Tool[] = [\n {\n name: 'index',\n description: `Index directories to make their files searchable. Processes files to create vector embeddings for semantic search.\n\nWhen to use this tool:\n- User specifically requests indexing a directory as a knowledge base\n- Adding new documentation, code repositories, or file collections to search\n- Updating index when many files have changed\n\nHow it works:\n- Recursively scans directories for supported file types\n- Extracts text content and splits into chunks\n- Generates vector embeddings for semantic similarity\n- Stores in database for fast retrieval\n\nExamples:\n- Index documentation: \"/home/user/docs/project-wiki\"\n- Index codebase: \"/home/user/projects/api-server\"\n- Index multiple directories: \"/home/user/docs,/home/user/configs\"\n\nIndexing can take several minutes for large directories. Most users will already have directories indexed and can directly use search tool. Use server_info to check current indexing status first.`,\n inputSchema: {\n type: 'object',\n properties: {\n directory_path: {\n type: 'string',\n description: 'Comma-separated list of absolute directory paths to index. Must be absolute paths since MCP server runs independently. Examples: \"/home/user/projects\" (Unix) or \"C:\\\\Users\\\\user\\\\projects\" (Windows)'\n }\n },\n required: ['directory_path']\n }\n },\n {\n name: 'search',\n description: `Search indexed files using natural language queries. Finds files containing content semantically similar to the query.\n\nWhen to use this tool:\n- Find documentation, guides, or explanations about specific topics\n- Locate code files implementing certain functionality or patterns\n- Discover configuration files, scripts, or settings related to a topic\n- Search for files covering specific concepts or technologies\n\nHow it works:\n- Converts query to vector embedding using semantic similarity\n- Searches all indexed file chunks for relevant content\n- Groups results by file and calculates average relevance scores\n- Returns files ranked by relevance score\n\nExamples:\n- \"database configuration\" - finds config files, documentation about DB setup\n- \"error handling patterns\" - finds code files with exception handling\n- \"authentication implementation\" - finds auth-related code and docs\n- \"API documentation\" - finds API guides, endpoint definitions\n- \"deployment scripts\" - finds CI/CD configs, deployment automation\n\nReturns files with similarity scores and chunk information. Use get_content to retrieve full file content or get_chunk to retrieve specific chunk content by chunk ID.\n- Groups results by file to avoid duplicates from multiple matching sections\n\nResponse format:\n- Returns lightweight metadata including file paths, relevance scores, and chunk IDs\n- Use 'get_chunk' or 'get_content' tools to fetch actual content from search results\n- Chunks are sorted by relevance score within each file\n- Average similarity score calculated across all matching chunks per file\n\nExample queries:\n- \"error handling patterns\" (finds try/catch, error classes, logging)\n- \"database migration scripts\" (finds SQL, schema changes, migration files)\n- \"authentication middleware\" (finds auth logic, JWT handling, middleware functions)`,\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Natural language search query describing what you are looking for. Can be concepts, functionality, or specific technical terms.'\n },\n limit: {\n type: 'number',\n description: 'Maximum number of files to return (default: 10). Each file may contain multiple matching chunks.',\n default: 10\n }\n },\n required: ['query']\n }\n },\n {\n name: 'similar_files',\n description: `Find files with content similar to a reference file. Uses semantic similarity to find related documents, code files, or any text content.\n\nWhen to use this tool:\n- Find documentation similar to a specific guide or README\n- Locate related code files, configuration files, or scripts\n- Discover alternative implementations or approaches\n- Find files covering similar topics or concepts\n\nHow it works:\n- Analyzes the semantic content of the reference file\n- Compares against all indexed files using vector similarity\n- Returns files ranked by content similarity score\n\nExamples:\n- Given \"deployment-guide.md\" - finds other deployment docs, CI/CD guides, infrastructure setup\n- Given \"troubleshooting.md\" - finds other troubleshooting guides, FAQ files, error documentation\n- Given \"config.yaml\" - finds other configuration files, settings, environment setups\n- Given \"auth.py\" - finds other authentication modules, security code, middleware\n\nReturns file paths with similarity scores. Use get_content to read full files or get_chunk for specific sections.`,\n inputSchema: {\n type: 'object',\n properties: {\n file_path: {\n type: 'string',\n description: 'Absolute or relative path to the reference file. This file must have been previously indexed.'\n },\n limit: {\n type: 'number',\n description: 'Maximum number of similar files to return (default: 10). Results are sorted by similarity score.',\n default: 10\n }\n },\n required: ['file_path']\n }\n },\n {\n name: 'get_content',\n description: `Retrieve the full content of a file or specific chunks. Reads files directly from the filesystem.\n\nWhen to use this tool:\n- Get complete file content after finding files through search\n- Read documentation, code files, or configuration files for analysis\n- Extract specific sections of large files using chunk ranges\n- Access any text-based file content\n\nHow it works:\n- Reads files directly from filesystem (not from search index)\n- Returns entire file by default\n- Can return specific chunk ranges for indexed files\n- Preserves original formatting and content\n\nExamples:\n- Get full file: file_path=\"/home/user/docs/api.md\"\n- Get specific chunks: file_path=\"/home/user/code/main.py\", chunks=\"2-5\"\n- Get single chunk: file_path=\"/home/user/config.json\", chunks=\"1\"\n\nReturns file content as text. Use this after search or similar_files to read actual content.`,\n inputSchema: {\n type: 'object',\n properties: {\n file_path: {\n type: 'string',\n description: 'Absolute or relative path to the file to retrieve. File must be readable and text-based.'\n },\n chunks: {\n type: 'string',\n description: 'Optional chunk range specification. Examples: \"3\" (single chunk), \"2-5\" (chunks 2 through 5), \"1-3\" (first three chunks). Only works for indexed files.'\n }\n },\n required: ['file_path']\n }\n },\n {\n name: 'get_chunk',\n description: `Retrieve content of a specific chunk from an indexed file. Gets exact text segments identified during search.\n\nWhen to use this tool:\n- Get specific relevant sections after performing a search\n- Access only the most pertinent parts of large files\n- Retrieve content from high-scoring chunks identified in search results\n- Avoid reading entire files when only specific sections are needed\n\nHow it works:\n- Files are split into overlapping text chunks during indexing\n- Each chunk has a sequential ID (\"0\", \"1\", \"2\", etc.)\n- Search results include chunk IDs for relevant sections\n- Returns the exact content that was semantically matched\n\nExamples:\n- After search returns chunk \"3\" from \"api-docs.md\" with high score\n- Get chunk content: file_path=\"/docs/api-docs.md\", chunk_id=\"3\"\n- Returns the specific text segment that matched your query\n\nReturns chunk content as text. Use this with chunk IDs from search results to get precise content sections.`,\n inputSchema: {\n type: 'object',\n properties: {\n file_path: {\n type: 'string',\n description: 'Absolute or relative path to the indexed file containing the desired chunk.'\n },\n chunk_id: {\n type: 'string',\n description: 'ID of the specific chunk to retrieve. This is typically obtained from search results and is a sequential string like \"0\", \"1\", \"2\", etc.'\n }\n },\n required: ['file_path', 'chunk_id']\n }\n },\n {\n name: 'server_info',\n description: `Get information about server status and indexed content. Shows what directories and files are available for search.\n\nWhen to use this tool:\n- Check what content is already indexed before performing searches\n- Verify system is working properly\n- See indexing statistics and status\n- Understand scope of available searchable content\n\nHow it works:\n- Reports total indexed directories, files, and chunks\n- Shows database size and last indexing time\n- Lists all indexed directories with file counts\n- Reports any errors or issues\n\nExamples:\n- Check before searching: \"What content is indexed?\"\n- Verify after indexing: \"Did the indexing complete successfully?\"\n- Monitor system: \"How many files are searchable?\"\n\nReturns server version, indexing statistics, directory list, and any errors. Use this to understand what content is available for search and similar_files tools.`,\n inputSchema: {\n type: 'object',\n properties: {},\n additionalProperties: false\n }\n }\n];\n\nexport async function startMcpServer(config: Config): Promise<void> {\n const server = new Server(\n {\n name: 'directory-indexer',\n version: VERSION\n },\n {\n capabilities: {\n tools: {}\n }\n }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: MCP_TOOLS\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n switch (name) {\n case 'index': {\n if (!args || typeof args.directory_path !== 'string') {\n throw new Error('directory_path is required');\n }\n const paths = args.directory_path.split(',').map((p: string) => p.trim());\n const result = await indexDirectories(paths, config);\n return {\n content: [\n {\n type: 'text',\n text: `Indexed ${result.indexed} files, skipped ${result.skipped} files, ${result.errors.length} errors`\n }\n ]\n };\n }\n\n case 'search': {\n if (!args || typeof args.query !== 'string') {\n throw new Error('query is required');\n }\n const results = await searchContent(args.query, { limit: (args.limit as number) || 10 });\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(results, null, 2)\n }\n ]\n };\n }\n\n case 'similar_files': {\n if (!args || typeof args.file_path !== 'string') {\n throw new Error('file_path is required');\n }\n const results = await findSimilarFiles(args.file_path, (args.limit as number) || 10);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(results, null, 2)\n }\n ]\n };\n }\n\n case 'get_content': {\n if (!args || typeof args.file_path !== 'string') {\n throw new Error('file_path is required');\n }\n const content = await getFileContent(args.file_path, args.chunks as string);\n return {\n content: [\n {\n type: 'text',\n text: content\n }\n ]\n };\n }\n\n case 'get_chunk': {\n if (!args || typeof args.file_path !== 'string' || typeof args.chunk_id !== 'string') {\n throw new Error('file_path and chunk_id are required');\n }\n const content = await getChunkContent(args.file_path, args.chunk_id);\n return {\n content: [\n {\n type: 'text',\n text: content\n }\n ]\n };\n }\n\n case 'server_info': {\n const status = await getIndexStatus();\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n name: 'directory-indexer',\n version: VERSION,\n status: status\n }, null, 2)\n }\n ]\n };\n }\n\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n return {\n content: [\n {\n type: 'text',\n text: `Error: ${errorMessage}`\n }\n ],\n isError: true\n };\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n \n if (config.verbose) {\n console.error('MCP server started successfully');\n }\n}","#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { fileURLToPath } from 'url';\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { indexDirectories } from './indexing.js';\nimport { searchContent, findSimilarFiles, getFileContent } from './search.js';\nimport { loadConfig } from './config.js';\nimport { getIndexStatus } from './storage.js';\nimport { startMcpServer } from './mcp.js';\n\n// Read version from package.json\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst packageJsonPath = join(__dirname, '../package.json');\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\nconst VERSION = packageJson.version;\n\nexport async function main() {\n const program = new Command();\n \n program\n .name('directory-indexer')\n .description('AI-powered directory indexing with semantic search')\n .version(VERSION);\n\n program\n .command('index')\n .description('Index directories for semantic search')\n .argument('<paths...>', 'Directory paths to index')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (paths: string[], options) => {\n try {\n const config = await loadConfig({ verbose: options.verbose });\n console.log(`Indexing ${paths.length} ${paths.length === 1 ? 'directory' : 'directories'}: ${paths.join(', ')}`);\n const result = await indexDirectories(paths, config);\n console.log(`Indexed ${result.indexed} files, skipped ${result.skipped} files, ${result.errors.length} errors`);\n if (result.errors.length > 0 && config.verbose) {\n console.log('Errors:', result.errors);\n }\n } catch (error) {\n console.error('Error indexing directories:', error);\n process.exit(1);\n }\n });\n\n program\n .command('search')\n .description('Search indexed content semantically')\n .argument('<query>', 'Search query')\n .option('-l, --limit <number>', 'Maximum number of results', '10')\n .option('-c, --show-chunks', 'Show individual chunk scores and IDs')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (query: string, options) => {\n try {\n await loadConfig({ verbose: options.verbose });\n const results = await searchContent(query, { limit: parseInt(options.limit) });\n \n if (results.length === 0) {\n console.log('No results found');\n return;\n }\n\n console.log(`Found ${results.length} results:\\n`);\n results.forEach((result, index) => {\n console.log(`${index + 1}. ${result.filePath}`);\n console.log(` Score: ${result.score.toFixed(3)} (${result.matchingChunks} chunks)`);\n \n if (options.showChunks && result.chunks.length > 0) {\n console.log(` Chunks:`);\n result.chunks.forEach(chunk => {\n console.log(` - Chunk ${chunk.chunkId}: ${chunk.score.toFixed(3)}`);\n });\n }\n \n console.log();\n });\n } catch (error) {\n console.error('Error searching content:', error);\n process.exit(1);\n }\n });\n\n program\n .command('similar')\n .description('Find files similar to a given file')\n .argument('<file>', 'File path to find similar files for')\n .option('-l, --limit <number>', 'Maximum number of results', '10')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (filePath: string, options) => {\n try {\n await loadConfig({ verbose: options.verbose });\n const results = await findSimilarFiles(filePath, parseInt(options.limit));\n \n if (results.length === 0) {\n console.log('No similar files found');\n return;\n }\n\n console.log(`Found ${results.length} similar files:\\n`);\n results.forEach((result, index) => {\n console.log(`${index + 1}. ${result.filePath}`);\n console.log(` Similarity: ${result.score.toFixed(3)}`);\n console.log();\n });\n } catch (error) {\n console.error('Error finding similar files:', error);\n process.exit(1);\n }\n });\n\n program\n .command('get')\n .description('Get file content')\n .argument('<file>', 'File path to retrieve')\n .option('-c, --chunks <range>', 'Chunk range (e.g., \"2-5\")')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (filePath: string, options) => {\n try {\n await loadConfig({ verbose: options.verbose });\n const content = await getFileContent(filePath, options.chunks);\n console.log(content);\n } catch (error) {\n console.error('Error getting file content:', error);\n process.exit(1);\n }\n });\n\n program\n .command('serve')\n .description('Start MCP server')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (options) => {\n try {\n const config = await loadConfig({ verbose: options.verbose });\n await startMcpServer(config);\n } catch (error) {\n console.error('Error starting MCP server:', error);\n process.exit(1);\n }\n });\n\n program\n .command('status')\n .description('Show indexing status')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (options) => {\n try {\n await loadConfig({ verbose: options.verbose });\n const status = await getIndexStatus();\n \n console.log('Directory Indexer Status Report');\n console.log('=====================================');\n console.log('');\n console.log('OVERVIEW:');\n console.log(` • ${status.directoriesIndexed} directories have been indexed`);\n console.log(` • ${status.filesIndexed} files processed for semantic search`);\n console.log(` • ${status.chunksIndexed} text chunks available for AI search`);\n console.log(` • Database storage: ${status.databaseSize}`);\n console.log(` • Most recent indexing: ${status.lastIndexed || 'No indexing performed yet'}`);\n \n if (status.errors.length > 0) {\n console.log(` • Processing errors encountered: ${status.errors.length}`);\n if (options.verbose) {\n console.log('');\n console.log('RECENT ERRORS:');\n status.errors.slice(0, 5).forEach(error => {\n console.log(` - ${error}`);\n });\n }\n }\n \n console.log('');\n console.log('INDEXED DIRECTORIES:');\n if (status.directories.length === 0) {\n console.log(' No directories have been indexed yet.');\n console.log(' Run \"directory-indexer index <path>\" to start indexing.');\n } else {\n status.directories.forEach(dir => {\n console.log('');\n console.log(` Directory: ${dir.path}`);\n console.log(` • Indexing status: ${dir.status}`);\n console.log(` • Files processed: ${dir.filesCount}`);\n console.log(` • Searchable chunks: ${dir.chunksCount}`);\n console.log(` • Last indexed: ${dir.lastIndexed || 'Never completed'}`);\n if (dir.errors.length > 0) {\n console.log(` • Files with errors: ${dir.errors.length}`);\n if (options.verbose) {\n console.log(' • Recent errors:');\n dir.errors.slice(0, 3).forEach(error => {\n console.log(` - ${error}`);\n });\n }\n }\n });\n }\n \n if (!status.qdrantConsistency.isConsistent) {\n console.log('');\n console.log('SYSTEM STATUS:');\n status.qdrantConsistency.issues.forEach(issue => {\n console.log(` • ${issue}`);\n });\n console.log('');\n console.log('ℹ️ Note: Status messages above may be normal during setup or active indexing.');\n } else {\n console.log('');\n console.log('SYSTEM STATUS:');\n console.log(' • All systems operational - ready for AI-powered search');\n }\n } catch (error) {\n console.error('Error getting status:', error);\n process.exit(1);\n }\n });\n\n await program.parseAsync();\n}\n\n// Main function is already exported above"],"names":["__dirname","packageJsonPath","packageJson","VERSION"],"mappings":"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"}
|
package/dist/embedding.js
CHANGED
|
@@ -41,25 +41,41 @@ class OllamaEmbeddingProvider {
|
|
|
41
41
|
dimensions = 768;
|
|
42
42
|
async generateEmbedding(text) {
|
|
43
43
|
try {
|
|
44
|
-
const response = await fetch(`${this.config.endpoint}/api/
|
|
44
|
+
const response = await fetch(`${this.config.endpoint}/api/embed`, {
|
|
45
45
|
method: "POST",
|
|
46
46
|
headers: { "Content-Type": "application/json" },
|
|
47
47
|
body: JSON.stringify({
|
|
48
48
|
model: this.config.model,
|
|
49
|
-
|
|
49
|
+
input: text
|
|
50
50
|
})
|
|
51
51
|
});
|
|
52
52
|
if (!response.ok) {
|
|
53
53
|
throw new Error(`Ollama API error: ${response.statusText}`);
|
|
54
54
|
}
|
|
55
55
|
const data = await response.json();
|
|
56
|
-
return data.
|
|
56
|
+
return data.embeddings[0];
|
|
57
57
|
} catch (error) {
|
|
58
58
|
throw new EmbeddingError(`Failed to generate Ollama embedding`, error);
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
async generateEmbeddings(texts) {
|
|
62
|
-
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetch(`${this.config.endpoint}/api/embed`, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: { "Content-Type": "application/json" },
|
|
66
|
+
body: JSON.stringify({
|
|
67
|
+
model: this.config.model,
|
|
68
|
+
input: texts
|
|
69
|
+
})
|
|
70
|
+
});
|
|
71
|
+
if (!response.ok) {
|
|
72
|
+
throw new Error(`Ollama API error: ${response.statusText}`);
|
|
73
|
+
}
|
|
74
|
+
const data = await response.json();
|
|
75
|
+
return data.embeddings;
|
|
76
|
+
} catch (error) {
|
|
77
|
+
throw new EmbeddingError(`Failed to generate Ollama embeddings`, error);
|
|
78
|
+
}
|
|
63
79
|
}
|
|
64
80
|
}
|
|
65
81
|
class OpenAIEmbeddingProvider {
|
package/dist/embedding.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embedding.js","sources":["../src/embedding.ts"],"sourcesContent":["import { Config } from './config.js';\n\nexport interface EmbeddingProvider {\n name: string;\n dimensions: number;\n generateEmbedding(text: string): Promise<number[]>;\n generateEmbeddings(texts: string[]): Promise<number[][]>;\n}\n\nexport interface EmbeddingConfig {\n model: string;\n endpoint: string;\n dimensions: number;\n}\n\nexport class EmbeddingError extends Error {\n constructor(message: string, public override cause?: Error) {\n super(message);\n this.name = 'EmbeddingError';\n }\n}\n\nclass MockEmbeddingProvider implements EmbeddingProvider {\n name = 'mock';\n \n constructor(private config: EmbeddingConfig) {}\n \n get dimensions(): number {\n return this.config.dimensions;\n }\n \n async generateEmbedding(text: string): Promise<number[]> {\n const hash = this.hashString(text);\n return Array.from({ length: this.dimensions }, (_, i) => \n Math.sin(hash + i) * 0.1\n );\n }\n \n async generateEmbeddings(texts: string[]): Promise<number[][]> {\n return Promise.all(texts.map(text => this.generateEmbedding(text)));\n }\n \n private hashString(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash;\n }\n return Math.abs(hash);\n }\n}\n\nclass OllamaEmbeddingProvider implements EmbeddingProvider {\n name = 'ollama';\n dimensions = 768;\n \n constructor(private config: EmbeddingConfig) {}\n \n async generateEmbedding(text: string): Promise<number[]> {\n try {\n const response = await fetch(`${this.config.endpoint}/api/
|
|
1
|
+
{"version":3,"file":"embedding.js","sources":["../src/embedding.ts"],"sourcesContent":["import { Config } from './config.js';\n\nexport interface EmbeddingProvider {\n name: string;\n dimensions: number;\n generateEmbedding(text: string): Promise<number[]>;\n generateEmbeddings(texts: string[]): Promise<number[][]>;\n}\n\nexport interface EmbeddingConfig {\n model: string;\n endpoint: string;\n dimensions: number;\n}\n\nexport class EmbeddingError extends Error {\n constructor(message: string, public override cause?: Error) {\n super(message);\n this.name = 'EmbeddingError';\n }\n}\n\nclass MockEmbeddingProvider implements EmbeddingProvider {\n name = 'mock';\n \n constructor(private config: EmbeddingConfig) {}\n \n get dimensions(): number {\n return this.config.dimensions;\n }\n \n async generateEmbedding(text: string): Promise<number[]> {\n const hash = this.hashString(text);\n return Array.from({ length: this.dimensions }, (_, i) => \n Math.sin(hash + i) * 0.1\n );\n }\n \n async generateEmbeddings(texts: string[]): Promise<number[][]> {\n return Promise.all(texts.map(text => this.generateEmbedding(text)));\n }\n \n private hashString(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash;\n }\n return Math.abs(hash);\n }\n}\n\nclass OllamaEmbeddingProvider implements EmbeddingProvider {\n name = 'ollama';\n dimensions = 768;\n \n constructor(private config: EmbeddingConfig) {}\n \n async generateEmbedding(text: string): Promise<number[]> {\n try {\n const response = await fetch(`${this.config.endpoint}/api/embed`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: this.config.model,\n input: text\n })\n });\n \n if (!response.ok) {\n throw new Error(`Ollama API error: ${response.statusText}`);\n }\n \n const data = await response.json();\n return data.embeddings[0];\n } catch (error) {\n throw new EmbeddingError(`Failed to generate Ollama embedding`, error as Error);\n }\n }\n \n async generateEmbeddings(texts: string[]): Promise<number[][]> {\n try {\n const response = await fetch(`${this.config.endpoint}/api/embed`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n model: this.config.model,\n input: texts\n })\n });\n \n if (!response.ok) {\n throw new Error(`Ollama API error: ${response.statusText}`);\n }\n \n const data = await response.json();\n return data.embeddings;\n } catch (error) {\n throw new EmbeddingError(`Failed to generate Ollama embeddings`, error as Error);\n }\n }\n}\n\nclass OpenAIEmbeddingProvider implements EmbeddingProvider {\n name = 'openai';\n dimensions = 1536;\n \n constructor(private config: EmbeddingConfig) {}\n \n async generateEmbedding(text: string): Promise<number[]> {\n try {\n const response = await fetch('https://api.openai.com/v1/embeddings', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`\n },\n body: JSON.stringify({\n model: this.config.model,\n input: text\n })\n });\n \n if (!response.ok) {\n throw new Error(`OpenAI API error: ${response.statusText}`);\n }\n \n const data = await response.json();\n return data.data[0].embedding;\n } catch (error) {\n throw new EmbeddingError(`Failed to generate OpenAI embedding`, error as Error);\n }\n }\n \n async generateEmbeddings(texts: string[]): Promise<number[][]> {\n try {\n const response = await fetch('https://api.openai.com/v1/embeddings', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`\n },\n body: JSON.stringify({\n model: this.config.model,\n input: texts\n })\n });\n \n if (!response.ok) {\n throw new Error(`OpenAI API error: ${response.statusText}`);\n }\n \n const data = await response.json();\n return data.data.map((item: { embedding: number[] }) => item.embedding);\n } catch (error) {\n throw new EmbeddingError(`Failed to generate OpenAI embeddings`, error as Error);\n }\n }\n}\n\nexport function createEmbeddingProvider(provider: string, config: EmbeddingConfig): EmbeddingProvider {\n switch (provider) {\n case 'mock':\n return new MockEmbeddingProvider(config);\n case 'ollama':\n return new OllamaEmbeddingProvider(config);\n case 'openai':\n return new OpenAIEmbeddingProvider(config);\n default:\n throw new EmbeddingError(`Unknown embedding provider: ${provider}`);\n }\n}\n\nexport async function generateEmbedding(text: string, config: Config): Promise<number[]> {\n const provider = createEmbeddingProvider(config.embedding.provider, {\n model: config.embedding.model,\n endpoint: config.embedding.endpoint,\n dimensions: config.embedding.provider === 'mock' ? 384 : (config.embedding.provider === 'ollama' ? 768 : 1536)\n });\n \n return provider.generateEmbedding(text);\n}"],"names":[],"mappings":"AAeO,MAAM,uBAAuB,MAAM;AAAA,EACxC,YAAY,SAAiC,OAAe;AAC1D,UAAM,OAAO;AAD8B,SAAA,QAAA;AAE3C,SAAK,OAAO;AAAA,EACd;AACF;AAEA,MAAM,sBAAmD;AAAA,EAGvD,YAAoB,QAAyB;AAAzB,SAAA,SAAA;AAAA,EAA0B;AAAA,EAF9C,OAAO;AAAA,EAIP,IAAI,aAAqB;AACvB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,MAAM,kBAAkB,MAAiC;AACvD,UAAM,OAAO,KAAK,WAAW,IAAI;AACjC,WAAO,MAAM;AAAA,MAAK,EAAE,QAAQ,KAAK,WAAA;AAAA,MAAc,CAAC,GAAG,MACjD,KAAK,IAAI,OAAO,CAAC,IAAI;AAAA,IAAA;AAAA,EAEzB;AAAA,EAEA,MAAM,mBAAmB,OAAsC;AAC7D,WAAO,QAAQ,IAAI,MAAM,IAAI,UAAQ,KAAK,kBAAkB,IAAI,CAAC,CAAC;AAAA,EACpE;AAAA,EAEQ,WAAW,KAAqB;AACtC,QAAI,OAAO;AACX,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,YAAM,OAAO,IAAI,WAAW,CAAC;AAC7B,cAAS,QAAQ,KAAK,OAAQ;AAC9B,aAAO,OAAO;AAAA,IAChB;AACA,WAAO,KAAK,IAAI,IAAI;AAAA,EACtB;AACF;AAEA,MAAM,wBAAqD;AAAA,EAIzD,YAAoB,QAAyB;AAAzB,SAAA,SAAA;AAAA,EAA0B;AAAA,EAH9C,OAAO;AAAA,EACP,aAAa;AAAA,EAIb,MAAM,kBAAkB,MAAiC;AACvD,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,QAAQ,cAAc;AAAA,QAChE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,QAC3B,MAAM,KAAK,UAAU;AAAA,UACnB,OAAO,KAAK,OAAO;AAAA,UACnB,OAAO;AAAA,QAAA,CACR;AAAA,MAAA,CACF;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,qBAAqB,SAAS,UAAU,EAAE;AAAA,MAC5D;AAEA,YAAM,OAAO,MAAM,SAAS,KAAA;AAC5B,aAAO,KAAK,WAAW,CAAC;AAAA,IAC1B,SAAS,OAAO;AACd,YAAM,IAAI,eAAe,uCAAuC,KAAc;AAAA,IAChF;AAAA,EACF;AAAA,EAEA,MAAM,mBAAmB,OAAsC;AAC7D,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,QAAQ,cAAc;AAAA,QAChE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAA;AAAA,QAC3B,MAAM,KAAK,UAAU;AAAA,UACnB,OAAO,KAAK,OAAO;AAAA,UACnB,OAAO;AAAA,QAAA,CACR;AAAA,MAAA,CACF;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,qBAAqB,SAAS,UAAU,EAAE;AAAA,MAC5D;AAEA,YAAM,OAAO,MAAM,SAAS,KAAA;AAC5B,aAAO,KAAK;AAAA,IACd,SAAS,OAAO;AACd,YAAM,IAAI,eAAe,wCAAwC,KAAc;AAAA,IACjF;AAAA,EACF;AACF;AAEA,MAAM,wBAAqD;AAAA,EAIzD,YAAoB,QAAyB;AAAzB,SAAA,SAAA;AAAA,EAA0B;AAAA,EAH9C,OAAO;AAAA,EACP,aAAa;AAAA,EAIb,MAAM,kBAAkB,MAAiC;AACvD,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,wCAAwC;AAAA,QACnE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,iBAAiB,UAAU,QAAQ,IAAI,cAAc;AAAA,QAAA;AAAA,QAEvD,MAAM,KAAK,UAAU;AAAA,UACnB,OAAO,KAAK,OAAO;AAAA,UACnB,OAAO;AAAA,QAAA,CACR;AAAA,MAAA,CACF;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,qBAAqB,SAAS,UAAU,EAAE;AAAA,MAC5D;AAEA,YAAM,OAAO,MAAM,SAAS,KAAA;AAC5B,aAAO,KAAK,KAAK,CAAC,EAAE;AAAA,IACtB,SAAS,OAAO;AACd,YAAM,IAAI,eAAe,uCAAuC,KAAc;AAAA,IAChF;AAAA,EACF;AAAA,EAEA,MAAM,mBAAmB,OAAsC;AAC7D,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,wCAAwC;AAAA,QACnE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,iBAAiB,UAAU,QAAQ,IAAI,cAAc;AAAA,QAAA;AAAA,QAEvD,MAAM,KAAK,UAAU;AAAA,UACnB,OAAO,KAAK,OAAO;AAAA,UACnB,OAAO;AAAA,QAAA,CACR;AAAA,MAAA,CACF;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,qBAAqB,SAAS,UAAU,EAAE;AAAA,MAC5D;AAEA,YAAM,OAAO,MAAM,SAAS,KAAA;AAC5B,aAAO,KAAK,KAAK,IAAI,CAAC,SAAkC,KAAK,SAAS;AAAA,IACxE,SAAS,OAAO;AACd,YAAM,IAAI,eAAe,wCAAwC,KAAc;AAAA,IACjF;AAAA,EACF;AACF;AAEO,SAAS,wBAAwB,UAAkB,QAA4C;AACpG,UAAQ,UAAA;AAAA,IACN,KAAK;AACH,aAAO,IAAI,sBAAsB,MAAM;AAAA,IACzC,KAAK;AACH,aAAO,IAAI,wBAAwB,MAAM;AAAA,IAC3C,KAAK;AACH,aAAO,IAAI,wBAAwB,MAAM;AAAA,IAC3C;AACE,YAAM,IAAI,eAAe,+BAA+B,QAAQ,EAAE;AAAA,EAAA;AAExE;AAEA,eAAsB,kBAAkB,MAAc,QAAmC;AACvF,QAAM,WAAW,wBAAwB,OAAO,UAAU,UAAU;AAAA,IAClE,OAAO,OAAO,UAAU;AAAA,IACxB,UAAU,OAAO,UAAU;AAAA,IAC3B,YAAY,OAAO,UAAU,aAAa,SAAS,MAAO,OAAO,UAAU,aAAa,WAAW,MAAM;AAAA,EAAA,CAC1G;AAED,SAAO,SAAS,kBAAkB,IAAI;AACxC;"}
|