directory-indexer 0.0.9 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -67
- package/dist/cli.js +316 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js +67 -0
- package/dist/config.js.map +1 -0
- package/dist/embedding.js +141 -0
- package/dist/embedding.js.map +1 -0
- package/dist/indexing.js +145 -0
- package/dist/indexing.js.map +1 -0
- package/dist/search.js +97 -0
- package/dist/search.js.map +1 -0
- package/dist/storage.js +303 -0
- package/dist/storage.js.map +1 -0
- package/dist/utils.js +126 -0
- package/dist/utils.js.map +1 -0
- package/package.json +37 -26
- package/bin/directory-indexer.js +0 -70
- package/binaries/directory-indexer-darwin-arm64 +0 -0
- package/binaries/directory-indexer-darwin-x64 +0 -0
- package/binaries/directory-indexer-linux-x64 +0 -0
- package/binaries/directory-indexer.exe-win32-x64 +0 -0
- package/scripts/build-all.js +0 -87
- package/scripts/cleanup-act.sh +0 -44
- package/scripts/postinstall.js +0 -47
- package/scripts/pre-push +0 -56
- package/scripts/start-dev-services.sh +0 -108
- package/scripts/stop-dev-services.sh +0 -42
package/README.md
CHANGED
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
**Turn your directories into an AI-powered knowledge base.**
|
|
4
4
|
|
|
5
5
|
[](https://npmjs.com/package/directory-indexer)
|
|
6
|
-
[](https://crates.io/crates/directory-indexer)
|
|
7
6
|
[](https://codecov.io/gh/peteretelej/directory-indexer)
|
|
8
|
-
[](https://www.rust-lang.org)
|
|
9
7
|
[](https://opensource.org/licenses/MIT)
|
|
10
8
|
[](https://github.com/peteretelej/directory-indexer/actions)
|
|
11
9
|
|
|
@@ -73,104 +71,81 @@ curl http://localhost:11434/api/tags
|
|
|
73
71
|
|
|
74
72
|
If either fails, directory-indexer will show a helpful error with setup guidance.
|
|
75
73
|
|
|
76
|
-
## Installation
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
npm install -g directory-indexer
|
|
80
|
-
```
|
|
81
|
-
|
|
82
74
|
## Usage
|
|
83
75
|
|
|
84
76
|
### MCP Integration
|
|
85
77
|
|
|
86
|
-
Configure with Claude Desktop:
|
|
78
|
+
Configure with AI assistants (Claude Desktop, Cline, etc.) using npx:
|
|
87
79
|
|
|
88
80
|
```json
|
|
89
81
|
{
|
|
90
82
|
"mcpServers": {
|
|
91
83
|
"directory-indexer": {
|
|
92
|
-
"command": "
|
|
93
|
-
"args": ["serve"]
|
|
84
|
+
"command": "npx",
|
|
85
|
+
"args": ["directory-indexer", "serve"]
|
|
94
86
|
}
|
|
95
87
|
}
|
|
96
88
|
}
|
|
97
89
|
```
|
|
98
90
|
|
|
99
|
-
|
|
91
|
+
Index your directories and start using with your AI assistant:
|
|
100
92
|
|
|
101
93
|
```bash
|
|
102
|
-
|
|
103
|
-
|
|
94
|
+
# Index your directories first
|
|
95
|
+
npx directory-indexer index /home/user/projects/docs /home/user/work/reports
|
|
104
96
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
### CLI Commands
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
# Index your directories
|
|
111
|
-
# Linux/macOS
|
|
112
|
-
directory-indexer index /home/user/projects/api-docs /mnt/work/incident-reports
|
|
113
|
-
# Windows
|
|
114
|
-
directory-indexer index "C:\work\documentation" "D:\projects\my-app\docs"
|
|
115
|
-
|
|
116
|
-
# Search semantically
|
|
117
|
-
directory-indexer search "database timeout errors"
|
|
118
|
-
|
|
119
|
-
# Find similar files
|
|
120
|
-
# Linux/macOS
|
|
121
|
-
directory-indexer similar /mnt/work/incident-reports/redis-outage.md
|
|
122
|
-
# Windows
|
|
123
|
-
directory-indexer similar "C:\work\incidents\redis-outage.md"
|
|
124
|
-
|
|
125
|
-
# Get file content
|
|
126
|
-
directory-indexer get /home/user/projects/api-docs/auth-guide.md
|
|
127
|
-
|
|
128
|
-
# Show status
|
|
129
|
-
directory-indexer status
|
|
97
|
+
# Start MCP server (usually done automatically by your AI assistant)
|
|
98
|
+
npx directory-indexer serve
|
|
130
99
|
```
|
|
131
100
|
|
|
132
|
-
|
|
101
|
+
### Using with AI Assistant
|
|
133
102
|
|
|
134
|
-
|
|
103
|
+
Once configured, your AI assistant can search your indexed documents semantically:
|
|
135
104
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
# Optional data directory (default: ~/.directory-indexer)
|
|
142
|
-
# Linux/macOS
|
|
143
|
-
export DIRECTORY_INDEXER_DATA_DIR="/opt/directory-indexer-data"
|
|
144
|
-
# Windows
|
|
145
|
-
set DIRECTORY_INDEXER_DATA_DIR=D:\data\directory-indexer
|
|
146
|
-
|
|
147
|
-
# Optional Qdrant collection name (default: directory-indexer)
|
|
148
|
-
# Note: Setting to "test" enables auto-cleanup for testing
|
|
149
|
-
export DIRECTORY_INDEXER_QDRANT_COLLECTION="my-custom-collection"
|
|
105
|
+
- _"Find API authentication examples"_
|
|
106
|
+
- _"Show me incidents similar to this outage report"_
|
|
107
|
+
- _"Find troubleshooting guides on SQL deadlocks"_
|
|
108
|
+
- _"What files contain database configuration?"_
|
|
150
109
|
|
|
151
|
-
|
|
152
|
-
export QDRANT_API_KEY="your-qdrant-key"
|
|
153
|
-
export OLLAMA_API_KEY="your-ollama-key" # if using hosted Ollama
|
|
154
|
-
```
|
|
110
|
+
### Custom Configuration
|
|
155
111
|
|
|
156
|
-
|
|
112
|
+
Configure with custom endpoints and data directory:
|
|
157
113
|
|
|
158
114
|
```json
|
|
159
115
|
{
|
|
160
116
|
"mcpServers": {
|
|
161
117
|
"directory-indexer": {
|
|
162
|
-
"command": "
|
|
163
|
-
"args": ["serve"],
|
|
118
|
+
"command": "npx",
|
|
119
|
+
"args": ["directory-indexer", "serve"],
|
|
164
120
|
"env": {
|
|
121
|
+
"DIRECTORY_INDEXER_DATA_DIR": "/opt/ai-knowledge-base",
|
|
165
122
|
"QDRANT_ENDPOINT": "http://localhost:6333",
|
|
166
|
-
"OLLAMA_ENDPOINT": "http://localhost:11434"
|
|
167
|
-
"DIRECTORY_INDEXER_DATA_DIR": "/opt/directory-indexer-data"
|
|
123
|
+
"OLLAMA_ENDPOINT": "http://localhost:11434"
|
|
168
124
|
}
|
|
169
125
|
}
|
|
170
126
|
}
|
|
171
127
|
}
|
|
172
128
|
```
|
|
173
129
|
|
|
130
|
+
### CLI Usage
|
|
131
|
+
|
|
132
|
+
For advanced users who prefer command-line usage, see [CLI Documentation](./docs/design.md#cli-usage).
|
|
133
|
+
|
|
134
|
+
## Configuration
|
|
135
|
+
|
|
136
|
+
Environment variables for MCP configuration:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Data directory (default: ~/.directory-indexer)
|
|
140
|
+
export DIRECTORY_INDEXER_DATA_DIR="/opt/ai-knowledge-base"
|
|
141
|
+
|
|
142
|
+
# Service endpoints (defaults shown)
|
|
143
|
+
export QDRANT_ENDPOINT="http://localhost:6333"
|
|
144
|
+
export OLLAMA_ENDPOINT="http://localhost:11434"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
For all configuration options, see [Environment Variables](./docs/design.md#environment-variables).
|
|
148
|
+
|
|
174
149
|
## Supported Files
|
|
175
150
|
|
|
176
151
|
- **Text**: `.md`, `.txt`
|
|
@@ -180,7 +155,8 @@ export OLLAMA_API_KEY="your-ollama-key" # if using hosted Ollama
|
|
|
180
155
|
|
|
181
156
|
## Documentation
|
|
182
157
|
|
|
183
|
-
- **[API Reference](docs/
|
|
158
|
+
- **[API Reference](docs/API.md)**: CLI commands and MCP tools
|
|
159
|
+
- **[Flow Diagrams](docs/flows.md)**: System architecture and process flows
|
|
184
160
|
- **[Contributing](docs/CONTRIBUTING.md)**: Development setup and guidelines
|
|
185
161
|
- **[Design](docs/design.md)**: Architecture and technical decisions
|
|
186
162
|
|
|
@@ -189,16 +165,19 @@ export OLLAMA_API_KEY="your-ollama-key" # if using hosted Ollama
|
|
|
189
165
|
Once indexed, try these queries with your AI assistant:
|
|
190
166
|
|
|
191
167
|
**Search by concept:**
|
|
168
|
+
|
|
192
169
|
- _"Find API authentication examples"_
|
|
193
170
|
- _"Show me error handling patterns"_
|
|
194
171
|
- _"Find configuration for Redis"_
|
|
195
172
|
|
|
196
173
|
**Find similar content:**
|
|
197
|
-
|
|
198
|
-
- _"
|
|
174
|
+
|
|
175
|
+
- _"Show me incidents similar to this outage report"_ _(when you have an incident file open)_
|
|
176
|
+
- _"Find documentation like this API guide"_ _(when viewing an API doc)_
|
|
199
177
|
- _"What files are similar to my deployment script?"_
|
|
200
178
|
|
|
201
179
|
**Troubleshoot issues:**
|
|
180
|
+
|
|
202
181
|
- _"Find troubleshooting guides on SQL deadlocks"_
|
|
203
182
|
- _"Show me solutions for timeout errors"_
|
|
204
183
|
- _"Find debugging tips for performance issues"_
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { indexDirectories } from "./indexing.js";
|
|
4
|
+
import { getFileContent, findSimilarFiles, searchContent } from "./search.js";
|
|
5
|
+
import { loadConfig } from "./config.js";
|
|
6
|
+
import { getIndexStatus } from "./storage.js";
|
|
7
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
8
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9
|
+
import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
10
|
+
const MCP_TOOLS = [
|
|
11
|
+
{
|
|
12
|
+
name: "index",
|
|
13
|
+
description: "Index directories for semantic search",
|
|
14
|
+
inputSchema: {
|
|
15
|
+
type: "object",
|
|
16
|
+
properties: {
|
|
17
|
+
directory_path: {
|
|
18
|
+
type: "string",
|
|
19
|
+
description: "Comma-separated list of directory paths to index"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
required: ["directory_path"]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "search",
|
|
27
|
+
description: "Search indexed content semantically",
|
|
28
|
+
inputSchema: {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
query: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: "Search query"
|
|
34
|
+
},
|
|
35
|
+
limit: {
|
|
36
|
+
type: "number",
|
|
37
|
+
description: "Maximum number of results (default: 10)",
|
|
38
|
+
default: 10
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
required: ["query"]
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "similar_files",
|
|
46
|
+
description: "Find files similar to a given file",
|
|
47
|
+
inputSchema: {
|
|
48
|
+
type: "object",
|
|
49
|
+
properties: {
|
|
50
|
+
file_path: {
|
|
51
|
+
type: "string",
|
|
52
|
+
description: "Path to the file to find similar files for"
|
|
53
|
+
},
|
|
54
|
+
limit: {
|
|
55
|
+
type: "number",
|
|
56
|
+
description: "Maximum number of results (default: 10)",
|
|
57
|
+
default: 10
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
required: ["file_path"]
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: "get_content",
|
|
65
|
+
description: "Get file content",
|
|
66
|
+
inputSchema: {
|
|
67
|
+
type: "object",
|
|
68
|
+
properties: {
|
|
69
|
+
file_path: {
|
|
70
|
+
type: "string",
|
|
71
|
+
description: "Path to the file to retrieve"
|
|
72
|
+
},
|
|
73
|
+
chunks: {
|
|
74
|
+
type: "string",
|
|
75
|
+
description: 'Optional chunk range (e.g., "2-5")'
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
required: ["file_path"]
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: "server_info",
|
|
83
|
+
description: "Get server information and status",
|
|
84
|
+
inputSchema: {
|
|
85
|
+
type: "object",
|
|
86
|
+
properties: {}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
];
|
|
90
|
+
async function startMcpServer(config) {
|
|
91
|
+
const server = new Server(
|
|
92
|
+
{
|
|
93
|
+
name: "directory-indexer",
|
|
94
|
+
version: "0.0.10"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
capabilities: {
|
|
98
|
+
tools: {}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
103
|
+
return {
|
|
104
|
+
tools: MCP_TOOLS
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
108
|
+
const { name, arguments: args } = request.params;
|
|
109
|
+
try {
|
|
110
|
+
switch (name) {
|
|
111
|
+
case "index": {
|
|
112
|
+
if (!args || typeof args.directory_path !== "string") {
|
|
113
|
+
throw new Error("directory_path is required");
|
|
114
|
+
}
|
|
115
|
+
const paths = args.directory_path.split(",").map((p) => p.trim());
|
|
116
|
+
const result = await indexDirectories(paths, config);
|
|
117
|
+
return {
|
|
118
|
+
content: [
|
|
119
|
+
{
|
|
120
|
+
type: "text",
|
|
121
|
+
text: `Indexed ${result.indexed} files, skipped ${result.skipped} files, ${result.errors.length} errors`
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
case "search": {
|
|
127
|
+
if (!args || typeof args.query !== "string") {
|
|
128
|
+
throw new Error("query is required");
|
|
129
|
+
}
|
|
130
|
+
const results = await searchContent(args.query, { limit: args.limit || 10 });
|
|
131
|
+
return {
|
|
132
|
+
content: [
|
|
133
|
+
{
|
|
134
|
+
type: "text",
|
|
135
|
+
text: JSON.stringify(results, null, 2)
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
case "similar_files": {
|
|
141
|
+
if (!args || typeof args.file_path !== "string") {
|
|
142
|
+
throw new Error("file_path is required");
|
|
143
|
+
}
|
|
144
|
+
const results = await findSimilarFiles(args.file_path, args.limit || 10);
|
|
145
|
+
return {
|
|
146
|
+
content: [
|
|
147
|
+
{
|
|
148
|
+
type: "text",
|
|
149
|
+
text: JSON.stringify(results, null, 2)
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
case "get_content": {
|
|
155
|
+
if (!args || typeof args.file_path !== "string") {
|
|
156
|
+
throw new Error("file_path is required");
|
|
157
|
+
}
|
|
158
|
+
const content = await getFileContent(args.file_path, args.chunks);
|
|
159
|
+
return {
|
|
160
|
+
content: [
|
|
161
|
+
{
|
|
162
|
+
type: "text",
|
|
163
|
+
text: content
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
case "server_info": {
|
|
169
|
+
const status = await getIndexStatus();
|
|
170
|
+
return {
|
|
171
|
+
content: [
|
|
172
|
+
{
|
|
173
|
+
type: "text",
|
|
174
|
+
text: JSON.stringify({
|
|
175
|
+
name: "directory-indexer",
|
|
176
|
+
version: "0.0.10",
|
|
177
|
+
status
|
|
178
|
+
}, null, 2)
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
default:
|
|
184
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
185
|
+
}
|
|
186
|
+
} catch (error) {
|
|
187
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
188
|
+
return {
|
|
189
|
+
content: [
|
|
190
|
+
{
|
|
191
|
+
type: "text",
|
|
192
|
+
text: `Error: ${errorMessage}`
|
|
193
|
+
}
|
|
194
|
+
],
|
|
195
|
+
isError: true
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
const transport = new StdioServerTransport();
|
|
200
|
+
await server.connect(transport);
|
|
201
|
+
if (config.verbose) {
|
|
202
|
+
console.error("MCP server started successfully");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async function main() {
|
|
206
|
+
const program = new Command();
|
|
207
|
+
program.name("directory-indexer").description("AI-powered directory indexing with semantic search").version("0.0.10");
|
|
208
|
+
program.command("index").description("Index directories for semantic search").argument("<paths...>", "Directory paths to index").option("-v, --verbose", "Enable verbose logging").action(async (paths, options) => {
|
|
209
|
+
try {
|
|
210
|
+
const config = await loadConfig({ verbose: options.verbose });
|
|
211
|
+
console.log(`Indexing ${paths.length} directories...`);
|
|
212
|
+
const result = await indexDirectories(paths, config);
|
|
213
|
+
console.log(`Indexed ${result.indexed} files, skipped ${result.skipped} files, ${result.errors.length} errors`);
|
|
214
|
+
if (result.errors.length > 0 && config.verbose) {
|
|
215
|
+
console.log("Errors:", result.errors);
|
|
216
|
+
}
|
|
217
|
+
} catch (error) {
|
|
218
|
+
console.error("Error indexing directories:", error);
|
|
219
|
+
process.exit(1);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
program.command("search").description("Search indexed content semantically").argument("<query>", "Search query").option("-l, --limit <number>", "Maximum number of results", "10").option("-v, --verbose", "Enable verbose logging").action(async (query, options) => {
|
|
223
|
+
try {
|
|
224
|
+
await loadConfig({ verbose: options.verbose });
|
|
225
|
+
const results = await searchContent(query, { limit: parseInt(options.limit) });
|
|
226
|
+
if (results.length === 0) {
|
|
227
|
+
console.log("No results found");
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
console.log(`Found ${results.length} results:
|
|
231
|
+
`);
|
|
232
|
+
results.forEach((result, index) => {
|
|
233
|
+
console.log(`${index + 1}. ${result.filePath}`);
|
|
234
|
+
console.log(` Score: ${result.score.toFixed(3)}`);
|
|
235
|
+
if (result.content) {
|
|
236
|
+
console.log(` Content: ${result.content.substring(0, 150)}...`);
|
|
237
|
+
}
|
|
238
|
+
console.log();
|
|
239
|
+
});
|
|
240
|
+
} catch (error) {
|
|
241
|
+
console.error("Error searching content:", error);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
program.command("similar").description("Find files similar to a given file").argument("<file>", "File path to find similar files for").option("-l, --limit <number>", "Maximum number of results", "10").option("-v, --verbose", "Enable verbose logging").action(async (filePath, options) => {
|
|
246
|
+
try {
|
|
247
|
+
await loadConfig({ verbose: options.verbose });
|
|
248
|
+
const results = await findSimilarFiles(filePath, parseInt(options.limit));
|
|
249
|
+
if (results.length === 0) {
|
|
250
|
+
console.log("No similar files found");
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
console.log(`Found ${results.length} similar files:
|
|
254
|
+
`);
|
|
255
|
+
results.forEach((result, index) => {
|
|
256
|
+
console.log(`${index + 1}. ${result.filePath}`);
|
|
257
|
+
console.log(` Similarity: ${result.score.toFixed(3)}`);
|
|
258
|
+
console.log();
|
|
259
|
+
});
|
|
260
|
+
} catch (error) {
|
|
261
|
+
console.error("Error finding similar files:", error);
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
program.command("get").description("Get file content").argument("<file>", "File path to retrieve").option("-c, --chunks <range>", 'Chunk range (e.g., "2-5")').option("-v, --verbose", "Enable verbose logging").action(async (filePath, options) => {
|
|
266
|
+
try {
|
|
267
|
+
await loadConfig({ verbose: options.verbose });
|
|
268
|
+
const content = await getFileContent(filePath, options.chunks);
|
|
269
|
+
console.log(content);
|
|
270
|
+
} catch (error) {
|
|
271
|
+
console.error("Error getting file content:", error);
|
|
272
|
+
process.exit(1);
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
program.command("serve").description("Start MCP server").option("-v, --verbose", "Enable verbose logging").action(async (options) => {
|
|
276
|
+
try {
|
|
277
|
+
const config = await loadConfig({ verbose: options.verbose });
|
|
278
|
+
await startMcpServer(config);
|
|
279
|
+
} catch (error) {
|
|
280
|
+
console.error("Error starting MCP server:", error);
|
|
281
|
+
process.exit(1);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
program.command("status").description("Show indexing status").option("-v, --verbose", "Enable verbose logging").action(async (options) => {
|
|
285
|
+
try {
|
|
286
|
+
await loadConfig({ verbose: options.verbose });
|
|
287
|
+
const status = await getIndexStatus();
|
|
288
|
+
console.log("Indexing Status:");
|
|
289
|
+
console.log(` Directories indexed: ${status.directoriesIndexed}`);
|
|
290
|
+
console.log(` Files indexed: ${status.filesIndexed}`);
|
|
291
|
+
console.log(` Total chunks: ${status.chunksIndexed}`);
|
|
292
|
+
console.log(` Database size: ${status.databaseSize}`);
|
|
293
|
+
console.log(` Last indexed: ${status.lastIndexed || "Never"}`);
|
|
294
|
+
if (status.errors.length > 0) {
|
|
295
|
+
console.log(` Errors: ${status.errors.length}`);
|
|
296
|
+
if (options.verbose) {
|
|
297
|
+
console.log(" Recent errors:");
|
|
298
|
+
status.errors.slice(0, 5).forEach((error) => {
|
|
299
|
+
console.log(` - ${error}`);
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
} catch (error) {
|
|
304
|
+
console.error("Error getting status:", error);
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
await program.parseAsync();
|
|
309
|
+
}
|
|
310
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
311
|
+
main().catch(console.error);
|
|
312
|
+
}
|
|
313
|
+
export {
|
|
314
|
+
main
|
|
315
|
+
};
|
|
316
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +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 { Config } from './config.js';\nimport { indexDirectories } from './indexing.js';\nimport { searchContent, findSimilarFiles, getFileContent } from './search.js';\nimport { getIndexStatus } from './storage.js';\n\nconst MCP_TOOLS: Tool[] = [\n {\n name: 'index',\n description: 'Index directories for semantic search',\n inputSchema: {\n type: 'object',\n properties: {\n directory_path: {\n type: 'string',\n description: 'Comma-separated list of directory paths to index'\n }\n },\n required: ['directory_path']\n }\n },\n {\n name: 'search',\n description: 'Search indexed content semantically',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query'\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results (default: 10)',\n default: 10\n }\n },\n required: ['query']\n }\n },\n {\n name: 'similar_files',\n description: 'Find files similar to a given file',\n inputSchema: {\n type: 'object',\n properties: {\n file_path: {\n type: 'string',\n description: 'Path to the file to find similar files for'\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results (default: 10)',\n default: 10\n }\n },\n required: ['file_path']\n }\n },\n {\n name: 'get_content',\n description: 'Get file content',\n inputSchema: {\n type: 'object',\n properties: {\n file_path: {\n type: 'string',\n description: 'Path to the file to retrieve'\n },\n chunks: {\n type: 'string',\n description: 'Optional chunk range (e.g., \"2-5\")'\n }\n },\n required: ['file_path']\n }\n },\n {\n name: 'server_info',\n description: 'Get server information and status',\n inputSchema: {\n type: 'object',\n properties: {}\n }\n }\n];\n\nexport async function startMcpServer(config: Config): Promise<void> {\n const server = new Server(\n {\n name: 'directory-indexer',\n version: '0.0.10'\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 '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: '0.0.10',\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 { 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\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('0.0.10');\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} directories...`);\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('-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)}`);\n if (result.content) {\n console.log(` Content: ${result.content.substring(0, 150)}...`);\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('Indexing Status:');\n console.log(` Directories indexed: ${status.directoriesIndexed}`);\n console.log(` Files indexed: ${status.filesIndexed}`);\n console.log(` Total chunks: ${status.chunksIndexed}`);\n console.log(` Database size: ${status.databaseSize}`);\n console.log(` Last indexed: ${status.lastIndexed || 'Never'}`);\n \n if (status.errors.length > 0) {\n console.log(` Errors: ${status.errors.length}`);\n if (options.verbose) {\n console.log(' Recent errors:');\n status.errors.slice(0, 5).forEach(error => {\n console.log(` - ${error}`);\n });\n }\n }\n } catch (error) {\n console.error('Error getting status:', error);\n process.exit(1);\n }\n });\n\n await program.parseAsync();\n}\n\nif (import.meta.url === `file://${process.argv[1]}`) {\n main().catch(console.error);\n}"],"names":[],"mappings":"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"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { homedir } from "os";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
const ConfigSchema = z.object({
|
|
5
|
+
storage: z.object({
|
|
6
|
+
sqlitePath: z.string(),
|
|
7
|
+
qdrantEndpoint: z.string().url(),
|
|
8
|
+
qdrantCollection: z.string()
|
|
9
|
+
}),
|
|
10
|
+
embedding: z.object({
|
|
11
|
+
provider: z.enum(["ollama", "openai", "mock"]),
|
|
12
|
+
model: z.string(),
|
|
13
|
+
endpoint: z.string().url()
|
|
14
|
+
}),
|
|
15
|
+
indexing: z.object({
|
|
16
|
+
chunkSize: z.number().positive(),
|
|
17
|
+
chunkOverlap: z.number().nonnegative(),
|
|
18
|
+
maxFileSize: z.number().positive(),
|
|
19
|
+
ignorePatterns: z.array(z.string())
|
|
20
|
+
}),
|
|
21
|
+
dataDir: z.string(),
|
|
22
|
+
verbose: z.boolean()
|
|
23
|
+
});
|
|
24
|
+
class ConfigError extends Error {
|
|
25
|
+
constructor(message, cause) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.cause = cause;
|
|
28
|
+
this.name = "ConfigError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function loadConfig(options = {}) {
|
|
32
|
+
const dataDir = process.env.DIRECTORY_INDEXER_DATA_DIR || join(homedir(), ".directory-indexer");
|
|
33
|
+
const config = {
|
|
34
|
+
storage: {
|
|
35
|
+
sqlitePath: join(dataDir, "data.db"),
|
|
36
|
+
qdrantEndpoint: process.env.QDRANT_ENDPOINT || "http://localhost:6333",
|
|
37
|
+
qdrantCollection: process.env.DIRECTORY_INDEXER_QDRANT_COLLECTION || "directory-indexer"
|
|
38
|
+
},
|
|
39
|
+
embedding: {
|
|
40
|
+
provider: process.env.EMBEDDING_PROVIDER || "ollama",
|
|
41
|
+
model: process.env.EMBEDDING_MODEL || "nomic-embed-text",
|
|
42
|
+
endpoint: process.env.OLLAMA_ENDPOINT || "http://localhost:11434"
|
|
43
|
+
},
|
|
44
|
+
indexing: {
|
|
45
|
+
chunkSize: parseInt(process.env.CHUNK_SIZE || "512"),
|
|
46
|
+
chunkOverlap: parseInt(process.env.CHUNK_OVERLAP || "50"),
|
|
47
|
+
maxFileSize: parseInt(process.env.MAX_FILE_SIZE || "10485760"),
|
|
48
|
+
ignorePatterns: [".git", "node_modules", "target", ".DS_Store"]
|
|
49
|
+
},
|
|
50
|
+
dataDir,
|
|
51
|
+
verbose: options.verbose ?? process.env.VERBOSE === "true"
|
|
52
|
+
};
|
|
53
|
+
try {
|
|
54
|
+
return ConfigSchema.parse(config);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (error instanceof z.ZodError) {
|
|
57
|
+
const messages = error.errors.map((e) => `${e.path.join(".")}: ${e.message}`);
|
|
58
|
+
throw new ConfigError(`Configuration validation failed: ${messages.join(", ")}`, error);
|
|
59
|
+
}
|
|
60
|
+
throw new ConfigError("Failed to load configuration", error);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export {
|
|
64
|
+
ConfigError,
|
|
65
|
+
loadConfig
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sources":["../src/config.ts"],"sourcesContent":["import { homedir } from 'os';\nimport { join } from 'path';\nimport { z } from 'zod';\n\nconst ConfigSchema = z.object({\n storage: z.object({\n sqlitePath: z.string(),\n qdrantEndpoint: z.string().url(),\n qdrantCollection: z.string(),\n }),\n embedding: z.object({\n provider: z.enum(['ollama', 'openai', 'mock']),\n model: z.string(),\n endpoint: z.string().url(),\n }),\n indexing: z.object({\n chunkSize: z.number().positive(),\n chunkOverlap: z.number().nonnegative(),\n maxFileSize: z.number().positive(),\n ignorePatterns: z.array(z.string()),\n }),\n dataDir: z.string(),\n verbose: z.boolean(),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\nexport class ConfigError extends Error {\n constructor(message: string, public override cause?: Error) {\n super(message);\n this.name = 'ConfigError';\n }\n}\n\nexport function loadConfig(options: { verbose?: boolean } = {}): Config {\n const dataDir = process.env.DIRECTORY_INDEXER_DATA_DIR || join(homedir(), '.directory-indexer');\n \n const config = {\n storage: {\n sqlitePath: join(dataDir, 'data.db'),\n qdrantEndpoint: process.env.QDRANT_ENDPOINT || 'http://localhost:6333',\n qdrantCollection: process.env.DIRECTORY_INDEXER_QDRANT_COLLECTION || 'directory-indexer',\n },\n embedding: {\n provider: (process.env.EMBEDDING_PROVIDER as Config['embedding']['provider']) || 'ollama',\n model: process.env.EMBEDDING_MODEL || 'nomic-embed-text',\n endpoint: process.env.OLLAMA_ENDPOINT || 'http://localhost:11434',\n },\n indexing: {\n chunkSize: parseInt(process.env.CHUNK_SIZE || '512'),\n chunkOverlap: parseInt(process.env.CHUNK_OVERLAP || '50'),\n maxFileSize: parseInt(process.env.MAX_FILE_SIZE || '10485760'),\n ignorePatterns: ['.git', 'node_modules', 'target', '.DS_Store'],\n },\n dataDir,\n verbose: options.verbose ?? (process.env.VERBOSE === 'true'),\n };\n\n try {\n return ConfigSchema.parse(config);\n } catch (error) {\n if (error instanceof z.ZodError) {\n const messages = error.errors.map(e => `${e.path.join('.')}: ${e.message}`);\n throw new ConfigError(`Configuration validation failed: ${messages.join(', ')}`, error);\n }\n throw new ConfigError('Failed to load configuration', error as Error);\n }\n}"],"names":[],"mappings":";;;AAIA,MAAM,eAAe,EAAE,OAAO;AAAA,EAC5B,SAAS,EAAE,OAAO;AAAA,IAChB,YAAY,EAAE,OAAA;AAAA,IACd,gBAAgB,EAAE,OAAA,EAAS,IAAA;AAAA,IAC3B,kBAAkB,EAAE,OAAA;AAAA,EAAO,CAC5B;AAAA,EACD,WAAW,EAAE,OAAO;AAAA,IAClB,UAAU,EAAE,KAAK,CAAC,UAAU,UAAU,MAAM,CAAC;AAAA,IAC7C,OAAO,EAAE,OAAA;AAAA,IACT,UAAU,EAAE,OAAA,EAAS,IAAA;AAAA,EAAI,CAC1B;AAAA,EACD,UAAU,EAAE,OAAO;AAAA,IACjB,WAAW,EAAE,OAAA,EAAS,SAAA;AAAA,IACtB,cAAc,EAAE,OAAA,EAAS,YAAA;AAAA,IACzB,aAAa,EAAE,OAAA,EAAS,SAAA;AAAA,IACxB,gBAAgB,EAAE,MAAM,EAAE,QAAQ;AAAA,EAAA,CACnC;AAAA,EACD,SAAS,EAAE,OAAA;AAAA,EACX,SAAS,EAAE,QAAA;AACb,CAAC;AAIM,MAAM,oBAAoB,MAAM;AAAA,EACrC,YAAY,SAAiC,OAAe;AAC1D,UAAM,OAAO;AAD8B,SAAA,QAAA;AAE3C,SAAK,OAAO;AAAA,EACd;AACF;AAEO,SAAS,WAAW,UAAiC,IAAY;AACtE,QAAM,UAAU,QAAQ,IAAI,8BAA8B,KAAK,QAAA,GAAW,oBAAoB;AAE9F,QAAM,SAAS;AAAA,IACb,SAAS;AAAA,MACP,YAAY,KAAK,SAAS,SAAS;AAAA,MACnC,gBAAgB,QAAQ,IAAI,mBAAmB;AAAA,MAC/C,kBAAkB,QAAQ,IAAI,uCAAuC;AAAA,IAAA;AAAA,IAEvE,WAAW;AAAA,MACT,UAAW,QAAQ,IAAI,sBAA0D;AAAA,MACjF,OAAO,QAAQ,IAAI,mBAAmB;AAAA,MACtC,UAAU,QAAQ,IAAI,mBAAmB;AAAA,IAAA;AAAA,IAE3C,UAAU;AAAA,MACR,WAAW,SAAS,QAAQ,IAAI,cAAc,KAAK;AAAA,MACnD,cAAc,SAAS,QAAQ,IAAI,iBAAiB,IAAI;AAAA,MACxD,aAAa,SAAS,QAAQ,IAAI,iBAAiB,UAAU;AAAA,MAC7D,gBAAgB,CAAC,QAAQ,gBAAgB,UAAU,WAAW;AAAA,IAAA;AAAA,IAEhE;AAAA,IACA,SAAS,QAAQ,WAAY,QAAQ,IAAI,YAAY;AAAA,EAAA;AAGvD,MAAI;AACF,WAAO,aAAa,MAAM,MAAM;AAAA,EAClC,SAAS,OAAO;AACd,QAAI,iBAAiB,EAAE,UAAU;AAC/B,YAAM,WAAW,MAAM,OAAO,IAAI,OAAK,GAAG,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE;AAC1E,YAAM,IAAI,YAAY,oCAAoC,SAAS,KAAK,IAAI,CAAC,IAAI,KAAK;AAAA,IACxF;AACA,UAAM,IAAI,YAAY,gCAAgC,KAAc;AAAA,EACtE;AACF;"}
|