directory-indexer 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-handlers.js +191 -0
- package/dist/cli-handlers.js.map +1 -0
- package/dist/cli.js +15 -167
- package/dist/cli.js.map +1 -1
- package/dist/indexing.js +16 -7
- package/dist/indexing.js.map +1 -1
- package/dist/logger.js +43 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp-handlers.js +215 -42
- package/dist/mcp-handlers.js.map +1 -1
- package/dist/mcp.js +200 -106
- package/dist/mcp.js.map +1 -1
- package/dist/path-validation.js +47 -0
- package/dist/path-validation.js.map +1 -0
- package/dist/storage.js +46 -8
- package/dist/storage.js.map +1 -1
- package/dist/utils.js +2 -0
- package/dist/utils.js.map +1 -1
- package/package.json +19 -16
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { indexDirectories } from "./indexing.js";
|
|
2
|
+
import { getFileContent, searchContent, findSimilarFiles } from "./search.js";
|
|
3
|
+
import { loadConfig } from "./config.js";
|
|
4
|
+
import { getIndexStatus } from "./storage.js";
|
|
5
|
+
import { startMcpServer } from "./mcp.js";
|
|
6
|
+
import { validateIndexPrerequisites, validateSearchPrerequisites, getServiceStatus } from "./prerequisites.js";
|
|
7
|
+
import { resetEnvironment } from "./reset.js";
|
|
8
|
+
async function handleIndex(paths, options) {
|
|
9
|
+
const config = await loadConfig({ verbose: options.verbose });
|
|
10
|
+
await validateIndexPrerequisites(config);
|
|
11
|
+
console.log(`Indexing ${paths.length} ${paths.length === 1 ? "directory" : "directories"}: ${paths.join(", ")}`);
|
|
12
|
+
if (!options.verbose) {
|
|
13
|
+
console.log("Run with --verbose for detailed per-file indexing reports");
|
|
14
|
+
console.log("Indexing can be safely stopped and resumed - progress is automatically saved");
|
|
15
|
+
console.log("You can start using the MCP server while indexing continues");
|
|
16
|
+
console.log("Indexing may take time due to embedding generation - see project README for performance tips");
|
|
17
|
+
}
|
|
18
|
+
const result = await indexDirectories(paths, config);
|
|
19
|
+
console.log(`Indexed ${result.indexed} files, skipped ${result.skipped} files, cleaned up ${result.deleted} deleted files, ${result.failed} failed`);
|
|
20
|
+
if (result.errors.length > 0) {
|
|
21
|
+
console.log(`Errors: [`);
|
|
22
|
+
result.errors.forEach((error) => {
|
|
23
|
+
console.log(` '${error}'`);
|
|
24
|
+
});
|
|
25
|
+
console.log(`]`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function handleSearch(query, options) {
|
|
29
|
+
const config = await loadConfig({ verbose: options.verbose });
|
|
30
|
+
await validateSearchPrerequisites(config);
|
|
31
|
+
const results = await searchContent(query, { limit: options.limit || 10 });
|
|
32
|
+
if (results.length === 0) {
|
|
33
|
+
console.log("No results found");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
console.log(`Found ${results.length} results:
|
|
37
|
+
`);
|
|
38
|
+
results.forEach((result, index) => {
|
|
39
|
+
console.log(`${index + 1}. ${result.filePath}`);
|
|
40
|
+
console.log(` Score: ${result.score.toFixed(3)} (${result.matchingChunks} chunks)`);
|
|
41
|
+
if (options.showChunks && result.chunks.length > 0) {
|
|
42
|
+
console.log(` Chunks:`);
|
|
43
|
+
result.chunks.forEach((chunk) => {
|
|
44
|
+
console.log(` - Chunk ${chunk.chunkId}: ${chunk.score.toFixed(3)}`);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
console.log();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async function handleSimilar(filePath, options) {
|
|
51
|
+
const config = await loadConfig({ verbose: options.verbose });
|
|
52
|
+
await validateSearchPrerequisites(config);
|
|
53
|
+
const results = await findSimilarFiles(filePath, options.limit || 10);
|
|
54
|
+
if (results.length === 0) {
|
|
55
|
+
console.log("No similar files found");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
console.log(`Found ${results.length} similar files:
|
|
59
|
+
`);
|
|
60
|
+
results.forEach((result, index) => {
|
|
61
|
+
console.log(`${index + 1}. ${result.filePath}`);
|
|
62
|
+
console.log(` Similarity: ${result.score.toFixed(3)}`);
|
|
63
|
+
console.log();
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async function handleGet(filePath, options) {
|
|
67
|
+
await loadConfig({ verbose: options.verbose });
|
|
68
|
+
const content = await getFileContent(filePath, options.chunks);
|
|
69
|
+
console.log(content);
|
|
70
|
+
}
|
|
71
|
+
async function handleServe(options) {
|
|
72
|
+
const config = await loadConfig({ verbose: options.verbose });
|
|
73
|
+
await startMcpServer(config);
|
|
74
|
+
}
|
|
75
|
+
async function handleReset(options) {
|
|
76
|
+
const config = await loadConfig({ verbose: options.verbose });
|
|
77
|
+
await resetEnvironment(config, {
|
|
78
|
+
force: options.force,
|
|
79
|
+
verbose: options.verbose
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
async function handleStatus(options) {
|
|
83
|
+
const config = await loadConfig({ verbose: options.verbose });
|
|
84
|
+
const [status, serviceStatus] = await Promise.all([
|
|
85
|
+
getIndexStatus(),
|
|
86
|
+
getServiceStatus(config)
|
|
87
|
+
]);
|
|
88
|
+
console.log("Directory Indexer Status Report");
|
|
89
|
+
console.log("=====================================");
|
|
90
|
+
console.log("");
|
|
91
|
+
console.log("SERVICE STATUS:");
|
|
92
|
+
console.log(` • Qdrant database: ${serviceStatus.qdrant ? "Connected" : "Disconnected"}`);
|
|
93
|
+
console.log(` • Embedding service (${serviceStatus.embeddingProvider}): ${serviceStatus.embedding ? "Connected" : "Disconnected"}`);
|
|
94
|
+
console.log("");
|
|
95
|
+
console.log("OVERVIEW:");
|
|
96
|
+
console.log(` • ${status.directoriesIndexed} directories have been indexed`);
|
|
97
|
+
console.log(` • ${status.filesIndexed} files processed for semantic search`);
|
|
98
|
+
console.log(` • ${status.chunksIndexed} text chunks available for AI search`);
|
|
99
|
+
console.log(` • Database storage: ${status.databaseSize}`);
|
|
100
|
+
console.log(` • Most recent indexing: ${status.lastIndexed || "No indexing performed yet"}`);
|
|
101
|
+
if (status.errors.length > 0) {
|
|
102
|
+
console.log(` • Processing errors encountered: ${status.errors.length}`);
|
|
103
|
+
if (options.verbose) {
|
|
104
|
+
console.log("");
|
|
105
|
+
console.log("RECENT ERRORS:");
|
|
106
|
+
status.errors.slice(0, 5).forEach((error) => {
|
|
107
|
+
console.log(` - ${error}`);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
console.log("");
|
|
112
|
+
console.log("INDEXED DIRECTORIES:");
|
|
113
|
+
if (status.directories.length === 0) {
|
|
114
|
+
console.log(" No directories have been indexed yet.");
|
|
115
|
+
console.log(' Run "directory-indexer index <path>" to start indexing.');
|
|
116
|
+
} else {
|
|
117
|
+
status.directories.forEach((dir) => {
|
|
118
|
+
console.log("");
|
|
119
|
+
console.log(` Directory: ${dir.path}`);
|
|
120
|
+
console.log(` • Indexing status: ${dir.status}`);
|
|
121
|
+
console.log(` • Files processed: ${dir.filesCount}`);
|
|
122
|
+
console.log(` • Searchable chunks: ${dir.chunksCount}`);
|
|
123
|
+
console.log(` • Last indexed: ${dir.lastIndexed || "Never completed"}`);
|
|
124
|
+
if (dir.errors.length > 0) {
|
|
125
|
+
console.log(` • Files with errors: ${dir.errors.length}`);
|
|
126
|
+
if (options.verbose) {
|
|
127
|
+
console.log(" • Recent errors:");
|
|
128
|
+
dir.errors.slice(0, 3).forEach((error) => {
|
|
129
|
+
console.log(` - ${error}`);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if (status.workspaces.length > 0) {
|
|
136
|
+
console.log("");
|
|
137
|
+
console.log("WORKSPACES:");
|
|
138
|
+
console.log(` • ${status.workspaceHealth.healthy} healthy, ${status.workspaceHealth.warnings} warnings, ${status.workspaceHealth.errors} errors`);
|
|
139
|
+
if (status.workspaceHealth.errors > 0) {
|
|
140
|
+
console.log("");
|
|
141
|
+
console.log("WORKSPACE ERRORS:");
|
|
142
|
+
status.workspaceHealth.criticalIssues.forEach((issue) => {
|
|
143
|
+
console.log(` ❌ ${issue}`);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
if (status.workspaceHealth.recommendations.length > 0) {
|
|
147
|
+
console.log("");
|
|
148
|
+
console.log("WORKSPACE RECOMMENDATIONS:");
|
|
149
|
+
status.workspaceHealth.recommendations.forEach((rec) => {
|
|
150
|
+
console.log(` 💡 ${rec}`);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (options.verbose) {
|
|
154
|
+
console.log("");
|
|
155
|
+
console.log("WORKSPACE DETAILS:");
|
|
156
|
+
status.workspaces.forEach((workspace) => {
|
|
157
|
+
console.log("");
|
|
158
|
+
console.log(` Workspace: ${workspace.name}`);
|
|
159
|
+
console.log(` • Status: ${workspace.health.status}`);
|
|
160
|
+
console.log(` • Paths: ${workspace.paths.join(", ")}`);
|
|
161
|
+
console.log(` • Files: ${workspace.filesCount}, Chunks: ${workspace.chunksCount}`);
|
|
162
|
+
if (workspace.health.issues.length > 0) {
|
|
163
|
+
console.log(` • Issues: ${workspace.health.issues.join("; ")}`);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (!status.qdrantConsistency.isConsistent) {
|
|
169
|
+
console.log("");
|
|
170
|
+
console.log("SYSTEM STATUS:");
|
|
171
|
+
status.qdrantConsistency.issues.forEach((issue) => {
|
|
172
|
+
console.log(` • ${issue}`);
|
|
173
|
+
});
|
|
174
|
+
console.log("");
|
|
175
|
+
console.log("Note: Status messages above may be normal during setup or active indexing.");
|
|
176
|
+
} else {
|
|
177
|
+
console.log("");
|
|
178
|
+
console.log("SYSTEM STATUS:");
|
|
179
|
+
console.log(" • All systems operational - ready for AI-powered search");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
export {
|
|
183
|
+
handleGet,
|
|
184
|
+
handleIndex,
|
|
185
|
+
handleReset,
|
|
186
|
+
handleSearch,
|
|
187
|
+
handleServe,
|
|
188
|
+
handleSimilar,
|
|
189
|
+
handleStatus
|
|
190
|
+
};
|
|
191
|
+
//# sourceMappingURL=cli-handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-handlers.js","sources":["../src/cli-handlers.ts"],"sourcesContent":["import { 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';\nimport { validateIndexPrerequisites, validateSearchPrerequisites, getServiceStatus } from './prerequisites.js';\nimport { resetEnvironment } from './reset.js';\n\nexport interface IndexOptions {\n verbose?: boolean;\n}\n\nexport interface SearchOptions {\n limit?: number;\n showChunks?: boolean;\n verbose?: boolean;\n}\n\nexport interface SimilarOptions {\n limit?: number;\n verbose?: boolean;\n}\n\nexport interface GetOptions {\n chunks?: string;\n verbose?: boolean;\n}\n\nexport interface ServeOptions {\n verbose?: boolean;\n}\n\nexport interface ResetOptions {\n force?: boolean;\n verbose?: boolean;\n}\n\nexport interface StatusOptions {\n verbose?: boolean;\n}\n\nexport async function handleIndex(paths: string[], options: IndexOptions): Promise<void> {\n const config = await loadConfig({ verbose: options.verbose });\n await validateIndexPrerequisites(config);\n \n console.log(`Indexing ${paths.length} ${paths.length === 1 ? 'directory' : 'directories'}: ${paths.join(', ')}`);\n if (!options.verbose) {\n console.log('Run with --verbose for detailed per-file indexing reports');\n console.log('Indexing can be safely stopped and resumed - progress is automatically saved');\n console.log('You can start using the MCP server while indexing continues');\n console.log('Indexing may take time due to embedding generation - see project README for performance tips');\n }\n \n const result = await indexDirectories(paths, config);\n console.log(`Indexed ${result.indexed} files, skipped ${result.skipped} files, cleaned up ${result.deleted} deleted files, ${result.failed} failed`);\n \n if (result.errors.length > 0) {\n console.log(`Errors: [`);\n result.errors.forEach(error => {\n console.log(` '${error}'`);\n });\n console.log(`]`);\n }\n}\n\nexport async function handleSearch(query: string, options: SearchOptions): Promise<void> {\n const config = await loadConfig({ verbose: options.verbose });\n await validateSearchPrerequisites(config);\n \n const results = await searchContent(query, { limit: options.limit || 10 });\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}\n\nexport async function handleSimilar(filePath: string, options: SimilarOptions): Promise<void> {\n const config = await loadConfig({ verbose: options.verbose });\n await validateSearchPrerequisites(config);\n \n const results = await findSimilarFiles(filePath, options.limit || 10);\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}\n\nexport async function handleGet(filePath: string, options: GetOptions): Promise<void> {\n await loadConfig({ verbose: options.verbose });\n const content = await getFileContent(filePath, options.chunks);\n console.log(content);\n}\n\nexport async function handleServe(options: ServeOptions): Promise<void> {\n const config = await loadConfig({ verbose: options.verbose });\n await startMcpServer(config);\n}\n\nexport async function handleReset(options: ResetOptions): Promise<void> {\n const config = await loadConfig({ verbose: options.verbose });\n await resetEnvironment(config, { \n force: options.force, \n verbose: options.verbose \n });\n}\n\nexport async function handleStatus(options: StatusOptions): Promise<void> {\n const config = await loadConfig({ verbose: options.verbose });\n const [status, serviceStatus] = await Promise.all([\n getIndexStatus(),\n getServiceStatus(config)\n ]);\n \n console.log('Directory Indexer Status Report');\n console.log('=====================================');\n console.log('');\n console.log('SERVICE STATUS:');\n console.log(` • Qdrant database: ${serviceStatus.qdrant ? 'Connected' : 'Disconnected'}`);\n console.log(` • Embedding service (${serviceStatus.embeddingProvider}): ${serviceStatus.embedding ? 'Connected' : 'Disconnected'}`);\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.workspaces.length > 0) {\n console.log('');\n console.log('WORKSPACES:');\n console.log(` • ${status.workspaceHealth.healthy} healthy, ${status.workspaceHealth.warnings} warnings, ${status.workspaceHealth.errors} errors`);\n \n if (status.workspaceHealth.errors > 0) {\n console.log('');\n console.log('WORKSPACE ERRORS:');\n status.workspaceHealth.criticalIssues.forEach(issue => {\n console.log(` ❌ ${issue}`);\n });\n }\n \n if (status.workspaceHealth.recommendations.length > 0) {\n console.log('');\n console.log('WORKSPACE RECOMMENDATIONS:');\n status.workspaceHealth.recommendations.forEach(rec => {\n console.log(` 💡 ${rec}`);\n });\n }\n \n if (options.verbose) {\n console.log('');\n console.log('WORKSPACE DETAILS:');\n status.workspaces.forEach(workspace => {\n console.log('');\n console.log(` Workspace: ${workspace.name}`);\n console.log(` • Status: ${workspace.health.status}`);\n console.log(` • Paths: ${workspace.paths.join(', ')}`);\n console.log(` • Files: ${workspace.filesCount}, Chunks: ${workspace.chunksCount}`);\n if (workspace.health.issues.length > 0) {\n console.log(` • Issues: ${workspace.health.issues.join('; ')}`);\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}"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -3,15 +3,9 @@ import { Command } from "commander";
|
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
4
|
import { readFileSync } from "fs";
|
|
5
5
|
import { dirname, join } from "path";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import { getIndexStatus } from "./storage.js";
|
|
10
|
-
import { startMcpServer } from "./mcp.js";
|
|
11
|
-
import { validateIndexPrerequisites, validateSearchPrerequisites, getServiceStatus } from "./prerequisites.js";
|
|
12
|
-
import { resetEnvironment } from "./reset.js";
|
|
13
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
-
const packageJsonPath = join(__dirname, "../package.json");
|
|
6
|
+
import { handleIndex, handleSearch, handleSimilar, handleGet, handleServe, handleReset, handleStatus } from "./cli-handlers.js";
|
|
7
|
+
const __dirname$1 = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const packageJsonPath = join(__dirname$1, "../package.json");
|
|
15
9
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
16
10
|
const VERSION = packageJson.version;
|
|
17
11
|
async function main() {
|
|
@@ -19,24 +13,7 @@ async function main() {
|
|
|
19
13
|
program.name("directory-indexer").description("AI-powered directory indexing with semantic search").version(VERSION);
|
|
20
14
|
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) => {
|
|
21
15
|
try {
|
|
22
|
-
|
|
23
|
-
await validateIndexPrerequisites(config);
|
|
24
|
-
console.log(`Indexing ${paths.length} ${paths.length === 1 ? "directory" : "directories"}: ${paths.join(", ")}`);
|
|
25
|
-
if (!options.verbose) {
|
|
26
|
-
console.log("Run with --verbose for detailed per-file indexing reports");
|
|
27
|
-
console.log("Indexing can be safely stopped and resumed - progress is automatically saved");
|
|
28
|
-
console.log("You can start using the MCP server while indexing continues");
|
|
29
|
-
console.log("Indexing may take time due to embedding generation - see project README for performance tips");
|
|
30
|
-
}
|
|
31
|
-
const result = await indexDirectories(paths, config);
|
|
32
|
-
console.log(`Indexed ${result.indexed} files, skipped ${result.skipped} files, cleaned up ${result.deleted} deleted files, ${result.failed} failed`);
|
|
33
|
-
if (result.errors.length > 0) {
|
|
34
|
-
console.log(`Errors: [`);
|
|
35
|
-
result.errors.forEach((error) => {
|
|
36
|
-
console.log(` '${error}'`);
|
|
37
|
-
});
|
|
38
|
-
console.log(`]`);
|
|
39
|
-
}
|
|
16
|
+
await handleIndex(paths, options);
|
|
40
17
|
} catch (error) {
|
|
41
18
|
console.error("Error indexing directories:", error);
|
|
42
19
|
process.exit(1);
|
|
@@ -44,25 +21,10 @@ async function main() {
|
|
|
44
21
|
});
|
|
45
22
|
program.command("search").description("Search indexed content semantically").argument("<query>", "Search query").option("-l, --limit <number>", "Maximum number of results", "10").option("-c, --show-chunks", "Show individual chunk scores and IDs").option("-v, --verbose", "Enable verbose logging").action(async (query, options) => {
|
|
46
23
|
try {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
console.log("No results found");
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
console.log(`Found ${results.length} results:
|
|
55
|
-
`);
|
|
56
|
-
results.forEach((result, index) => {
|
|
57
|
-
console.log(`${index + 1}. ${result.filePath}`);
|
|
58
|
-
console.log(` Score: ${result.score.toFixed(3)} (${result.matchingChunks} chunks)`);
|
|
59
|
-
if (options.showChunks && result.chunks.length > 0) {
|
|
60
|
-
console.log(` Chunks:`);
|
|
61
|
-
result.chunks.forEach((chunk) => {
|
|
62
|
-
console.log(` - Chunk ${chunk.chunkId}: ${chunk.score.toFixed(3)}`);
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
console.log();
|
|
24
|
+
await handleSearch(query, {
|
|
25
|
+
limit: parseInt(options.limit),
|
|
26
|
+
showChunks: options.showChunks,
|
|
27
|
+
verbose: options.verbose
|
|
66
28
|
});
|
|
67
29
|
} catch (error) {
|
|
68
30
|
console.error("Error searching content:", error);
|
|
@@ -71,19 +33,9 @@ async function main() {
|
|
|
71
33
|
});
|
|
72
34
|
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) => {
|
|
73
35
|
try {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (results.length === 0) {
|
|
78
|
-
console.log("No similar files found");
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
console.log(`Found ${results.length} similar files:
|
|
82
|
-
`);
|
|
83
|
-
results.forEach((result, index) => {
|
|
84
|
-
console.log(`${index + 1}. ${result.filePath}`);
|
|
85
|
-
console.log(` Similarity: ${result.score.toFixed(3)}`);
|
|
86
|
-
console.log();
|
|
36
|
+
await handleSimilar(filePath, {
|
|
37
|
+
limit: parseInt(options.limit),
|
|
38
|
+
verbose: options.verbose
|
|
87
39
|
});
|
|
88
40
|
} catch (error) {
|
|
89
41
|
console.error("Error finding similar files:", error);
|
|
@@ -92,9 +44,7 @@ async function main() {
|
|
|
92
44
|
});
|
|
93
45
|
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) => {
|
|
94
46
|
try {
|
|
95
|
-
await
|
|
96
|
-
const content = await getFileContent(filePath, options.chunks);
|
|
97
|
-
console.log(content);
|
|
47
|
+
await handleGet(filePath, options);
|
|
98
48
|
} catch (error) {
|
|
99
49
|
console.error("Error getting file content:", error);
|
|
100
50
|
process.exit(1);
|
|
@@ -102,8 +52,7 @@ async function main() {
|
|
|
102
52
|
});
|
|
103
53
|
program.command("serve").description("Start MCP server").option("-v, --verbose", "Enable verbose logging").action(async (options) => {
|
|
104
54
|
try {
|
|
105
|
-
|
|
106
|
-
await startMcpServer(config);
|
|
55
|
+
await handleServe(options);
|
|
107
56
|
} catch (error) {
|
|
108
57
|
console.error("Error starting MCP server:", error);
|
|
109
58
|
process.exit(1);
|
|
@@ -111,11 +60,7 @@ async function main() {
|
|
|
111
60
|
});
|
|
112
61
|
program.command("reset").description("Reset directory-indexer data (database and vector collection)").option("--force", "Skip confirmation prompt").option("-v, --verbose", "Enable verbose logging").action(async (options) => {
|
|
113
62
|
try {
|
|
114
|
-
|
|
115
|
-
await resetEnvironment(config, {
|
|
116
|
-
force: options.force,
|
|
117
|
-
verbose: options.verbose
|
|
118
|
-
});
|
|
63
|
+
await handleReset(options);
|
|
119
64
|
} catch (error) {
|
|
120
65
|
if (error instanceof Error && error.message === "Reset cancelled by user") {
|
|
121
66
|
console.log("\nReset cancelled.");
|
|
@@ -127,104 +72,7 @@ async function main() {
|
|
|
127
72
|
});
|
|
128
73
|
program.command("status").description("Show indexing status").option("-v, --verbose", "Enable verbose logging").action(async (options) => {
|
|
129
74
|
try {
|
|
130
|
-
|
|
131
|
-
const [status, serviceStatus] = await Promise.all([
|
|
132
|
-
getIndexStatus(),
|
|
133
|
-
getServiceStatus(config)
|
|
134
|
-
]);
|
|
135
|
-
console.log("Directory Indexer Status Report");
|
|
136
|
-
console.log("=====================================");
|
|
137
|
-
console.log("");
|
|
138
|
-
console.log("SERVICE STATUS:");
|
|
139
|
-
console.log(` • Qdrant database: ${serviceStatus.qdrant ? "Connected" : "Disconnected"}`);
|
|
140
|
-
console.log(` • Embedding service (${serviceStatus.embeddingProvider}): ${serviceStatus.embedding ? "Connected" : "Disconnected"}`);
|
|
141
|
-
console.log("");
|
|
142
|
-
console.log("OVERVIEW:");
|
|
143
|
-
console.log(` • ${status.directoriesIndexed} directories have been indexed`);
|
|
144
|
-
console.log(` • ${status.filesIndexed} files processed for semantic search`);
|
|
145
|
-
console.log(` • ${status.chunksIndexed} text chunks available for AI search`);
|
|
146
|
-
console.log(` • Database storage: ${status.databaseSize}`);
|
|
147
|
-
console.log(` • Most recent indexing: ${status.lastIndexed || "No indexing performed yet"}`);
|
|
148
|
-
if (status.errors.length > 0) {
|
|
149
|
-
console.log(` • Processing errors encountered: ${status.errors.length}`);
|
|
150
|
-
if (options.verbose) {
|
|
151
|
-
console.log("");
|
|
152
|
-
console.log("RECENT ERRORS:");
|
|
153
|
-
status.errors.slice(0, 5).forEach((error) => {
|
|
154
|
-
console.log(` - ${error}`);
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
console.log("");
|
|
159
|
-
console.log("INDEXED DIRECTORIES:");
|
|
160
|
-
if (status.directories.length === 0) {
|
|
161
|
-
console.log(" No directories have been indexed yet.");
|
|
162
|
-
console.log(' Run "directory-indexer index <path>" to start indexing.');
|
|
163
|
-
} else {
|
|
164
|
-
status.directories.forEach((dir) => {
|
|
165
|
-
console.log("");
|
|
166
|
-
console.log(` Directory: ${dir.path}`);
|
|
167
|
-
console.log(` • Indexing status: ${dir.status}`);
|
|
168
|
-
console.log(` • Files processed: ${dir.filesCount}`);
|
|
169
|
-
console.log(` • Searchable chunks: ${dir.chunksCount}`);
|
|
170
|
-
console.log(` • Last indexed: ${dir.lastIndexed || "Never completed"}`);
|
|
171
|
-
if (dir.errors.length > 0) {
|
|
172
|
-
console.log(` • Files with errors: ${dir.errors.length}`);
|
|
173
|
-
if (options.verbose) {
|
|
174
|
-
console.log(" • Recent errors:");
|
|
175
|
-
dir.errors.slice(0, 3).forEach((error) => {
|
|
176
|
-
console.log(` - ${error}`);
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
if (status.workspaces.length > 0) {
|
|
183
|
-
console.log("");
|
|
184
|
-
console.log("WORKSPACES:");
|
|
185
|
-
console.log(` • ${status.workspaceHealth.healthy} healthy, ${status.workspaceHealth.warnings} warnings, ${status.workspaceHealth.errors} errors`);
|
|
186
|
-
if (status.workspaceHealth.errors > 0) {
|
|
187
|
-
console.log("");
|
|
188
|
-
console.log("WORKSPACE ERRORS:");
|
|
189
|
-
status.workspaceHealth.criticalIssues.forEach((issue) => {
|
|
190
|
-
console.log(` ❌ ${issue}`);
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
if (status.workspaceHealth.recommendations.length > 0) {
|
|
194
|
-
console.log("");
|
|
195
|
-
console.log("WORKSPACE RECOMMENDATIONS:");
|
|
196
|
-
status.workspaceHealth.recommendations.forEach((rec) => {
|
|
197
|
-
console.log(` 💡 ${rec}`);
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
if (options.verbose) {
|
|
201
|
-
console.log("");
|
|
202
|
-
console.log("WORKSPACE DETAILS:");
|
|
203
|
-
status.workspaces.forEach((workspace) => {
|
|
204
|
-
console.log("");
|
|
205
|
-
console.log(` Workspace: ${workspace.name}`);
|
|
206
|
-
console.log(` • Status: ${workspace.health.status}`);
|
|
207
|
-
console.log(` • Paths: ${workspace.paths.join(", ")}`);
|
|
208
|
-
console.log(` • Files: ${workspace.filesCount}, Chunks: ${workspace.chunksCount}`);
|
|
209
|
-
if (workspace.health.issues.length > 0) {
|
|
210
|
-
console.log(` • Issues: ${workspace.health.issues.join("; ")}`);
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (!status.qdrantConsistency.isConsistent) {
|
|
216
|
-
console.log("");
|
|
217
|
-
console.log("SYSTEM STATUS:");
|
|
218
|
-
status.qdrantConsistency.issues.forEach((issue) => {
|
|
219
|
-
console.log(` • ${issue}`);
|
|
220
|
-
});
|
|
221
|
-
console.log("");
|
|
222
|
-
console.log("Note: Status messages above may be normal during setup or active indexing.");
|
|
223
|
-
} else {
|
|
224
|
-
console.log("");
|
|
225
|
-
console.log("SYSTEM STATUS:");
|
|
226
|
-
console.log(" • All systems operational - ready for AI-powered search");
|
|
227
|
-
}
|
|
75
|
+
await handleStatus(options);
|
|
228
76
|
} catch (error) {
|
|
229
77
|
console.error("Error getting status:", error);
|
|
230
78
|
process.exit(1);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/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';\nimport { validateIndexPrerequisites, validateSearchPrerequisites, getServiceStatus } from './prerequisites.js';\nimport { resetEnvironment } from './reset.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 await validateIndexPrerequisites(config);\n console.log(`Indexing ${paths.length} ${paths.length === 1 ? 'directory' : 'directories'}: ${paths.join(', ')}`);\n if (!options.verbose) {\n console.log('Run with --verbose for detailed per-file indexing reports');\n console.log('Indexing can be safely stopped and resumed - progress is automatically saved');\n console.log('You can start using the MCP server while indexing continues');\n console.log('Indexing may take time due to embedding generation - see project README for performance tips');\n }\n const result = await indexDirectories(paths, config);\n console.log(`Indexed ${result.indexed} files, skipped ${result.skipped} files, cleaned up ${result.deleted} deleted files, ${result.failed} failed`);\n if (result.errors.length > 0) {\n console.log(`Errors: [`);\n result.errors.forEach(error => {\n console.log(` '${error}'`);\n });\n console.log(`]`);\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 const config = await loadConfig({ verbose: options.verbose });\n await validateSearchPrerequisites(config);\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 const config = await loadConfig({ verbose: options.verbose });\n await validateSearchPrerequisites(config);\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('reset')\n .description('Reset directory-indexer data (database and vector collection)')\n .option('--force', 'Skip confirmation prompt')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (options) => {\n try {\n const config = await loadConfig({ verbose: options.verbose });\n await resetEnvironment(config, { \n force: options.force, \n verbose: options.verbose \n });\n } catch (error) {\n if (error instanceof Error && error.message === 'Reset cancelled by user') {\n console.log('\\nReset cancelled.');\n process.exit(0);\n }\n console.error('Error during reset:', 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 const config = await loadConfig({ verbose: options.verbose });\n const [status, serviceStatus] = await Promise.all([\n getIndexStatus(),\n getServiceStatus(config)\n ]);\n \n console.log('Directory Indexer Status Report');\n console.log('=====================================');\n console.log('');\n console.log('SERVICE STATUS:');\n console.log(` • Qdrant database: ${serviceStatus.qdrant ? 'Connected' : 'Disconnected'}`);\n console.log(` • Embedding service (${serviceStatus.embeddingProvider}): ${serviceStatus.embedding ? 'Connected' : 'Disconnected'}`);\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 // Show workspace health information\n if (status.workspaces.length > 0) {\n console.log('');\n console.log('WORKSPACES:');\n console.log(` • ${status.workspaceHealth.healthy} healthy, ${status.workspaceHealth.warnings} warnings, ${status.workspaceHealth.errors} errors`);\n \n if (status.workspaceHealth.errors > 0) {\n console.log('');\n console.log('WORKSPACE ERRORS:');\n status.workspaceHealth.criticalIssues.forEach(issue => {\n console.log(` ❌ ${issue}`);\n });\n }\n \n if (status.workspaceHealth.recommendations.length > 0) {\n console.log('');\n console.log('WORKSPACE RECOMMENDATIONS:');\n status.workspaceHealth.recommendations.forEach(rec => {\n console.log(` 💡 ${rec}`);\n });\n }\n \n if (options.verbose) {\n console.log('');\n console.log('WORKSPACE DETAILS:');\n status.workspaces.forEach(workspace => {\n console.log('');\n console.log(` Workspace: ${workspace.name}`);\n console.log(` • Status: ${workspace.health.status}`);\n console.log(` • Paths: ${workspace.paths.join(', ')}`);\n console.log(` • Files: ${workspace.filesCount}, Chunks: ${workspace.chunksCount}`);\n if (workspace.health.issues.length > 0) {\n console.log(` • Issues: ${workspace.health.issues.join('; ')}`);\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":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { fileURLToPath } from 'url';\nimport { readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { \n handleIndex, \n handleSearch, \n handleSimilar, \n handleGet, \n handleServe, \n handleReset, \n handleStatus \n} from './cli-handlers.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 await handleIndex(paths, options);\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 handleSearch(query, {\n limit: parseInt(options.limit),\n showChunks: options.showChunks,\n verbose: options.verbose\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 handleSimilar(filePath, {\n limit: parseInt(options.limit),\n verbose: options.verbose\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 handleGet(filePath, options);\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 await handleServe(options);\n } catch (error) {\n console.error('Error starting MCP server:', error);\n process.exit(1);\n }\n });\n\n program\n .command('reset')\n .description('Reset directory-indexer data (database and vector collection)')\n .option('--force', 'Skip confirmation prompt')\n .option('-v, --verbose', 'Enable verbose logging')\n .action(async (options) => {\n try {\n await handleReset(options);\n } catch (error) {\n if (error instanceof Error && error.message === 'Reset cancelled by user') {\n console.log('\\nReset cancelled.');\n process.exit(0);\n }\n console.error('Error during reset:', 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 handleStatus(options);\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"],"mappings":"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"}
|
package/dist/indexing.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { promises } from "fs";
|
|
2
2
|
import { join } from "path";
|
|
3
|
-
import {
|
|
3
|
+
import { getFileInfo, normalizePath, shouldIgnoreFile, isDirectory, isFile, isSupportedFileType } from "./utils.js";
|
|
4
4
|
import { loadGitignoreRules } from "./gitignore.js";
|
|
5
5
|
import { generateEmbedding } from "./embedding.js";
|
|
6
6
|
import { initializeStorage } from "./storage.js";
|
|
7
|
+
import { log } from "./logger.js";
|
|
7
8
|
class IndexingError extends Error {
|
|
8
9
|
constructor(message, cause) {
|
|
9
10
|
super(message);
|
|
@@ -142,6 +143,7 @@ async function indexDirectories(paths, config) {
|
|
|
142
143
|
}
|
|
143
144
|
}
|
|
144
145
|
if (!config.verbose && totalFiles > 0) {
|
|
146
|
+
console.log("");
|
|
145
147
|
console.log(`Found ${totalFiles} files to process (checking for changes...)`);
|
|
146
148
|
}
|
|
147
149
|
for (const path of paths) {
|
|
@@ -151,7 +153,7 @@ async function indexDirectories(paths, config) {
|
|
|
151
153
|
const files = await scanDirectory(path, scanOptions);
|
|
152
154
|
const dirStartIndexed = indexed;
|
|
153
155
|
const dirStartSkipped = skipped;
|
|
154
|
-
const progressInterval =
|
|
156
|
+
const progressInterval = totalFiles > 1e3 ? 50 : 10;
|
|
155
157
|
for (const file of files) {
|
|
156
158
|
try {
|
|
157
159
|
const existingFile = await sqlite.getFile(file.path);
|
|
@@ -163,13 +165,20 @@ async function indexDirectories(paths, config) {
|
|
|
163
165
|
console.log(` Skipped: ${file.path} (unchanged)`);
|
|
164
166
|
}
|
|
165
167
|
if (!config.verbose && (indexed + skipped) % progressInterval === 0) {
|
|
166
|
-
console.log(`
|
|
168
|
+
console.log(`Progress: ${indexed + skipped}/${totalFiles} files (${skipped} skipped as unchanged)...`);
|
|
167
169
|
}
|
|
168
170
|
continue;
|
|
169
171
|
}
|
|
170
172
|
await qdrant.deletePointsByFilePath(file.path);
|
|
171
173
|
}
|
|
172
|
-
const
|
|
174
|
+
const rawContent = await promises.readFile(file.path, "utf-8");
|
|
175
|
+
if (rawContent.includes("�")) {
|
|
176
|
+
log("warning", "Skipping non-UTF-8 file", { path: file.path });
|
|
177
|
+
await sqlite.upsertFile(file, [], ["Skipped: file appears to be non-UTF-8 encoded"]);
|
|
178
|
+
skipped++;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
const content = rawContent.replace(/\r\n/g, "\n");
|
|
173
182
|
const chunks = chunkText(content, config.indexing.chunkSize, config.indexing.chunkOverlap);
|
|
174
183
|
await sqlite.upsertFile(file, chunks);
|
|
175
184
|
for (let i = 0; i < chunks.length; i++) {
|
|
@@ -195,7 +204,7 @@ async function indexDirectories(paths, config) {
|
|
|
195
204
|
console.log(` Indexed: ${file.path} (${chunks.length} chunks)`);
|
|
196
205
|
}
|
|
197
206
|
if (!config.verbose && (indexed + skipped) % progressInterval === 0) {
|
|
198
|
-
console.log(`
|
|
207
|
+
console.log(`Progress: ${indexed + skipped}/${totalFiles} files (${skipped} skipped as unchanged)...`);
|
|
199
208
|
}
|
|
200
209
|
} catch (error) {
|
|
201
210
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -232,9 +241,9 @@ async function indexDirectories(paths, config) {
|
|
|
232
241
|
const dirIndexed = indexed - dirStartIndexed;
|
|
233
242
|
const dirSkipped = skipped - dirStartSkipped;
|
|
234
243
|
if (config.verbose) {
|
|
235
|
-
console.log(`
|
|
244
|
+
console.log(`Directory ${path} completed: ${dirIndexed} indexed, ${dirSkipped} skipped`);
|
|
236
245
|
} else {
|
|
237
|
-
console.log(`
|
|
246
|
+
console.log(`Directory ${path} completed: ${dirFiles} files processed`);
|
|
238
247
|
}
|
|
239
248
|
} catch (error) {
|
|
240
249
|
const normalizedPath = normalizePath(path);
|