directory-indexer 0.2.1 → 0.2.2
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 +13 -165
- package/dist/cli.js.map +1 -1
- package/dist/indexing.js +6 -5
- package/dist/indexing.js.map +1 -1
- package/package.json +6 -7
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { indexDirectories } from "./indexing.js";
|
|
2
|
+
import { searchContent, findSimilarFiles, getFileContent } 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,13 +3,7 @@ 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
|
-
import { searchContent, findSimilarFiles, getFileContent } from "./search.js";
|
|
8
|
-
import { loadConfig } from "./config.js";
|
|
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";
|
|
6
|
+
import { handleIndex, handleSearch, handleSimilar, handleGet, handleServe, handleReset, handleStatus } from "./cli-handlers.js";
|
|
13
7
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
8
|
const packageJsonPath = join(__dirname, "../package.json");
|
|
15
9
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
@@ -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":[],"mappings":"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"}
|
package/dist/indexing.js
CHANGED
|
@@ -142,6 +142,7 @@ async function indexDirectories(paths, config) {
|
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
if (!config.verbose && totalFiles > 0) {
|
|
145
|
+
console.log("");
|
|
145
146
|
console.log(`Found ${totalFiles} files to process (checking for changes...)`);
|
|
146
147
|
}
|
|
147
148
|
for (const path of paths) {
|
|
@@ -151,7 +152,7 @@ async function indexDirectories(paths, config) {
|
|
|
151
152
|
const files = await scanDirectory(path, scanOptions);
|
|
152
153
|
const dirStartIndexed = indexed;
|
|
153
154
|
const dirStartSkipped = skipped;
|
|
154
|
-
const progressInterval =
|
|
155
|
+
const progressInterval = totalFiles > 1e3 ? 50 : 10;
|
|
155
156
|
for (const file of files) {
|
|
156
157
|
try {
|
|
157
158
|
const existingFile = await sqlite.getFile(file.path);
|
|
@@ -163,7 +164,7 @@ async function indexDirectories(paths, config) {
|
|
|
163
164
|
console.log(` Skipped: ${file.path} (unchanged)`);
|
|
164
165
|
}
|
|
165
166
|
if (!config.verbose && (indexed + skipped) % progressInterval === 0) {
|
|
166
|
-
console.log(`
|
|
167
|
+
console.log(`Progress: ${indexed + skipped}/${totalFiles} files (${skipped} skipped as unchanged)...`);
|
|
167
168
|
}
|
|
168
169
|
continue;
|
|
169
170
|
}
|
|
@@ -195,7 +196,7 @@ async function indexDirectories(paths, config) {
|
|
|
195
196
|
console.log(` Indexed: ${file.path} (${chunks.length} chunks)`);
|
|
196
197
|
}
|
|
197
198
|
if (!config.verbose && (indexed + skipped) % progressInterval === 0) {
|
|
198
|
-
console.log(`
|
|
199
|
+
console.log(`Progress: ${indexed + skipped}/${totalFiles} files (${skipped} skipped as unchanged)...`);
|
|
199
200
|
}
|
|
200
201
|
} catch (error) {
|
|
201
202
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -232,9 +233,9 @@ async function indexDirectories(paths, config) {
|
|
|
232
233
|
const dirIndexed = indexed - dirStartIndexed;
|
|
233
234
|
const dirSkipped = skipped - dirStartSkipped;
|
|
234
235
|
if (config.verbose) {
|
|
235
|
-
console.log(`
|
|
236
|
+
console.log(`Directory ${path} completed: ${dirIndexed} indexed, ${dirSkipped} skipped`);
|
|
236
237
|
} else {
|
|
237
|
-
console.log(`
|
|
238
|
+
console.log(`Directory ${path} completed: ${dirFiles} files processed`);
|
|
238
239
|
}
|
|
239
240
|
} catch (error) {
|
|
240
241
|
const normalizedPath = normalizePath(path);
|
package/dist/indexing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexing.js","sources":["../src/indexing.ts"],"sourcesContent":["import { promises as fs } from 'fs';\nimport { join } from 'path';\nimport { Config } from './config.js';\nimport {\n FileInfo,\n ChunkInfo,\n normalizePath,\n getFileInfo,\n shouldIgnoreFile,\n isSupportedFileType,\n isDirectory,\n isFile\n} from './utils.js';\nimport { loadGitignoreRules } from './gitignore.js';\nimport { generateEmbedding } from './embedding.js';\nimport { initializeStorage, FileRecord } from './storage.js';\n\nexport interface ScanOptions {\n ignorePatterns: string[];\n maxFileSize: number;\n respectGitignore: boolean;\n}\n\nexport interface IndexResult {\n indexed: number;\n skipped: number;\n failed: number;\n deleted: number;\n errors: string[];\n}\n\nexport class IndexingError extends Error {\n constructor(message: string, public override cause?: Error) {\n super(message);\n this.name = 'IndexingError';\n }\n}\n\nexport function chunkText(content: string, chunkSize: number, overlap: number): ChunkInfo[] {\n if (content.length <= chunkSize) {\n return [{\n id: '0',\n content,\n startIndex: 0,\n endIndex: content.length\n }];\n }\n\n const chunks: ChunkInfo[] = [];\n let startIndex = 0;\n let chunkId = 0;\n\n while (startIndex < content.length) {\n const endIndex = Math.min(startIndex + chunkSize, content.length);\n const chunkContent = content.slice(startIndex, endIndex);\n\n chunks.push({\n id: chunkId.toString(),\n content: chunkContent,\n startIndex,\n endIndex\n });\n\n chunkId++;\n const nextStart = endIndex - overlap;\n\n if (nextStart <= startIndex) {\n startIndex = startIndex + Math.max(1, chunkSize - overlap);\n } else {\n startIndex = nextStart;\n }\n\n if (startIndex >= content.length) break;\n }\n\n return chunks;\n}\n\nexport async function scanDirectory(dirPath: string, options: ScanOptions): Promise<FileInfo[]> {\n const files: FileInfo[] = [];\n const visited = new Set<string>();\n const basePath = normalizePath(dirPath);\n \n // Load gitignore rules for the root directory if enabled\n const gitignoreFilter = options.respectGitignore ? await loadGitignoreRules(dirPath) : null;\n\n async function walkDirectory(currentPath: string): Promise<void> {\n const normalizedPath = normalizePath(currentPath);\n\n if (visited.has(normalizedPath)) {\n return;\n }\n visited.add(normalizedPath);\n\n try {\n // Convert to relative path for gitignore matching\n const relativePath = normalizedPath.startsWith(basePath) \n ? normalizedPath.slice(basePath.length + 1)\n : normalizedPath;\n \n if (shouldIgnoreFile(normalizedPath, relativePath, options.ignorePatterns, gitignoreFilter)) {\n return;\n }\n\n if (await isDirectory(normalizedPath)) {\n const entries = await fs.readdir(normalizedPath);\n\n for (const entry of entries) {\n const fullPath = join(normalizedPath, entry);\n await walkDirectory(fullPath);\n }\n } else if (await isFile(normalizedPath)) {\n if (!isSupportedFileType(normalizedPath)) {\n return;\n }\n\n const stats = await fs.stat(normalizedPath);\n if (stats.size > options.maxFileSize) {\n return;\n }\n\n const fileInfo = await getFileInfo(normalizedPath);\n files.push(fileInfo);\n }\n } catch (error) {\n throw new IndexingError(`Failed to scan directory: ${normalizedPath}`, error as Error);\n }\n }\n\n await walkDirectory(dirPath);\n return files;\n}\n\nexport async function getFileMetadata(filePath: string): Promise<FileInfo> {\n try {\n return await getFileInfo(filePath);\n } catch (error) {\n throw new IndexingError(`Failed to get file metadata`, error as Error);\n }\n}\n\nasync function shouldReprocessFile(filePath: string, existingRecord: FileRecord, config: Config): Promise<boolean> {\n try {\n const fs = await import('fs/promises');\n\n // Try modtime check first (fast path)\n const currentStats = await fs.stat(filePath);\n const existingModTime = new Date(existingRecord.modifiedTime);\n\n // If modtime is clearly older, likely unchanged\n if (currentStats.mtime <= existingModTime) {\n return false; // Skip processing\n }\n\n // If modtime suggests change, verify with hash\n const currentFileInfo = await getFileInfo(filePath);\n return currentFileInfo.hash !== existingRecord.hash;\n\n } catch (modtimeError) {\n // Graceful fallback: skip modtime, use hash only\n if (config.verbose) {\n console.log(`Warning: Could not check modification time for ${filePath}:`, modtimeError);\n }\n try {\n const currentFileInfo = await getFileInfo(filePath);\n return currentFileInfo.hash !== existingRecord.hash;\n } catch (hashError) {\n // If we can't hash either, assume changed to be safe\n if (config.verbose) {\n console.log(`Warning: Could not compute hash for ${filePath}:`, hashError);\n }\n return true;\n }\n }\n}\n\nexport async function indexDirectories(paths: string[], config: Config): Promise<IndexResult> {\n let indexed = 0;\n let skipped = 0;\n let failed = 0;\n let deleted = 0;\n const errors: string[] = [];\n\n const scanOptions: ScanOptions = {\n ignorePatterns: config.indexing.ignorePatterns,\n maxFileSize: config.indexing.maxFileSize,\n respectGitignore: config.indexing.respectGitignore\n };\n\n // Initialize storage\n const { sqlite, qdrant } = await initializeStorage(config);\n\n // First pass: scan all directories to get total file count\n let totalFiles = 0;\n for (const path of paths) {\n try {\n if (config.verbose) {\n console.log(`Scanning directory: ${path}`);\n }\n const files = await scanDirectory(path, scanOptions);\n totalFiles += files.length;\n if (config.verbose) {\n console.log(`Found ${files.length} files to process in ${path}`);\n }\n } catch {\n // Continue with other directories even if one fails to scan\n }\n }\n\n if (!config.verbose && totalFiles > 0) {\n console.log(`Found ${totalFiles} files to process (checking for changes...)`);\n }\n\n for (const path of paths) {\n try {\n // Mark directory as indexing\n const normalizedPath = normalizePath(path);\n await sqlite.upsertDirectory(normalizedPath, 'indexing');\n\n const files = await scanDirectory(path, scanOptions);\n\n // Track directory-specific counters\n const dirStartIndexed = indexed;\n const dirStartSkipped = skipped;\n\n // Calculate progress interval for non-verbose updates\n const progressInterval = Math.max(10, Math.floor(totalFiles / 20));\n\n for (const file of files) {\n try {\n // Check if file already exists and needs reprocessing\n const existingFile = await sqlite.getFile(file.path);\n\n if (existingFile) {\n const needsReprocessing = await shouldReprocessFile(file.path, existingFile, config);\n if (!needsReprocessing) {\n skipped++;\n if (config.verbose) {\n console.log(` Skipped: ${file.path} (unchanged)`);\n }\n // Show periodic progress in non-verbose mode\n if (!config.verbose && (indexed + skipped) % progressInterval === 0) {\n console.log(` Progress: ${indexed + skipped}/${totalFiles} files (${skipped} skipped as unchanged)...`);\n }\n continue; // Skip unchanged file\n }\n\n // File changed - clean up old vectors first\n await qdrant.deletePointsByFilePath(file.path);\n }\n\n const content = await fs.readFile(file.path, 'utf-8');\n const chunks = chunkText(content, config.indexing.chunkSize, config.indexing.chunkOverlap);\n\n // Store file metadata in SQLite\n await sqlite.upsertFile(file, chunks);\n\n // Generate embeddings and store in Qdrant\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const embedding = await generateEmbedding(chunk.content, config);\n // Generate a unique integer ID by combining hash and chunk index\n const hashNum = parseInt(file.hash.slice(0, 8), 16);\n const pointId = (hashNum % 1000000) * 1000 + parseInt(chunk.id);\n const point = {\n id: pointId,\n vector: embedding,\n payload: {\n filePath: file.path,\n chunkId: chunk.id,\n fileHash: file.hash,\n content: chunk.content,\n parentDirectories: file.parentDirs\n }\n };\n await qdrant.upsertPoints([point]);\n }\n\n indexed++;\n if (config.verbose) {\n console.log(` Indexed: ${file.path} (${chunks.length} chunks)`);\n }\n // Show periodic progress in non-verbose mode\n if (!config.verbose && (indexed + skipped) % progressInterval === 0) {\n console.log(` Progress: ${indexed + skipped}/${totalFiles} files (${skipped} skipped as unchanged)...`);\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const causeMessage = error instanceof Error && error.cause ? `: ${(error.cause as Error).message}` : '';\n const fullError = `Failed to process ${file.path}: ${errorMessage}${causeMessage}`;\n errors.push(fullError);\n failed++;\n\n // Print error immediately during processing (not just in verbose mode)\n console.error(`❌ ${fullError}`);\n }\n }\n\n // Clean up deleted files from this directory\n const indexedFiles = await sqlite.getFilesByDirectory(normalizedPath);\n const existingFilePaths = new Set(files.map(f => f.path));\n const deletedFiles = indexedFiles.filter(f => !existingFilePaths.has(f.path));\n\n for (const deletedFile of deletedFiles) {\n try {\n // Remove from Qdrant\n await qdrant.deletePointsByFilePath(deletedFile.path);\n \n // Remove from SQLite\n await sqlite.deleteFile(deletedFile.path);\n \n deleted++;\n if (config.verbose) {\n console.log(` Cleaned up deleted file: ${deletedFile.path}`);\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const fullError = `Failed to clean up deleted file ${deletedFile.path}: ${errorMessage}`;\n errors.push(fullError);\n failed++;\n \n console.error(`❌ ${fullError}`);\n }\n }\n\n // Mark directory as completed if no errors for this directory\n const directoryErrors = errors.filter(err => err.includes(path));\n const directoryStatus = directoryErrors.length > 0 ? 'failed' : 'completed';\n await sqlite.upsertDirectory(normalizedPath, directoryStatus);\n\n // Show directory completion\n const dirFiles = files.length;\n const dirIndexed = indexed - dirStartIndexed;\n const dirSkipped = skipped - dirStartSkipped;\n if (config.verbose) {\n console.log(` Directory ${path} completed: ${dirIndexed} indexed, ${dirSkipped} skipped`);\n } else {\n console.log(` Directory ${path} completed: ${dirFiles} files processed`);\n }\n\n } catch (error) {\n const normalizedPath = normalizePath(path);\n await sqlite.upsertDirectory(normalizedPath, 'failed');\n errors.push(`Failed to scan directory ${path}: ${(error as Error).message}`);\n }\n }\n\n return { indexed, skipped, failed, deleted, errors };\n}"],"names":["fs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"indexing.js","sources":["../src/indexing.ts"],"sourcesContent":["import { promises as fs } from 'fs';\nimport { join } from 'path';\nimport { Config } from './config.js';\nimport {\n FileInfo,\n ChunkInfo,\n normalizePath,\n getFileInfo,\n shouldIgnoreFile,\n isSupportedFileType,\n isDirectory,\n isFile\n} from './utils.js';\nimport { loadGitignoreRules } from './gitignore.js';\nimport { generateEmbedding } from './embedding.js';\nimport { initializeStorage, FileRecord } from './storage.js';\n\nexport interface ScanOptions {\n ignorePatterns: string[];\n maxFileSize: number;\n respectGitignore: boolean;\n}\n\nexport interface IndexResult {\n indexed: number;\n skipped: number;\n failed: number;\n deleted: number;\n errors: string[];\n}\n\nexport class IndexingError extends Error {\n constructor(message: string, public override cause?: Error) {\n super(message);\n this.name = 'IndexingError';\n }\n}\n\nexport function chunkText(content: string, chunkSize: number, overlap: number): ChunkInfo[] {\n if (content.length <= chunkSize) {\n return [{\n id: '0',\n content,\n startIndex: 0,\n endIndex: content.length\n }];\n }\n\n const chunks: ChunkInfo[] = [];\n let startIndex = 0;\n let chunkId = 0;\n\n while (startIndex < content.length) {\n const endIndex = Math.min(startIndex + chunkSize, content.length);\n const chunkContent = content.slice(startIndex, endIndex);\n\n chunks.push({\n id: chunkId.toString(),\n content: chunkContent,\n startIndex,\n endIndex\n });\n\n chunkId++;\n const nextStart = endIndex - overlap;\n\n if (nextStart <= startIndex) {\n startIndex = startIndex + Math.max(1, chunkSize - overlap);\n } else {\n startIndex = nextStart;\n }\n\n if (startIndex >= content.length) break;\n }\n\n return chunks;\n}\n\nexport async function scanDirectory(dirPath: string, options: ScanOptions): Promise<FileInfo[]> {\n const files: FileInfo[] = [];\n const visited = new Set<string>();\n const basePath = normalizePath(dirPath);\n \n // Load gitignore rules for the root directory if enabled\n const gitignoreFilter = options.respectGitignore ? await loadGitignoreRules(dirPath) : null;\n\n async function walkDirectory(currentPath: string): Promise<void> {\n const normalizedPath = normalizePath(currentPath);\n\n if (visited.has(normalizedPath)) {\n return;\n }\n visited.add(normalizedPath);\n\n try {\n // Convert to relative path for gitignore matching\n const relativePath = normalizedPath.startsWith(basePath) \n ? normalizedPath.slice(basePath.length + 1)\n : normalizedPath;\n \n if (shouldIgnoreFile(normalizedPath, relativePath, options.ignorePatterns, gitignoreFilter)) {\n return;\n }\n\n if (await isDirectory(normalizedPath)) {\n const entries = await fs.readdir(normalizedPath);\n\n for (const entry of entries) {\n const fullPath = join(normalizedPath, entry);\n await walkDirectory(fullPath);\n }\n } else if (await isFile(normalizedPath)) {\n if (!isSupportedFileType(normalizedPath)) {\n return;\n }\n\n const stats = await fs.stat(normalizedPath);\n if (stats.size > options.maxFileSize) {\n return;\n }\n\n const fileInfo = await getFileInfo(normalizedPath);\n files.push(fileInfo);\n }\n } catch (error) {\n throw new IndexingError(`Failed to scan directory: ${normalizedPath}`, error as Error);\n }\n }\n\n await walkDirectory(dirPath);\n return files;\n}\n\nexport async function getFileMetadata(filePath: string): Promise<FileInfo> {\n try {\n return await getFileInfo(filePath);\n } catch (error) {\n throw new IndexingError(`Failed to get file metadata`, error as Error);\n }\n}\n\nasync function shouldReprocessFile(filePath: string, existingRecord: FileRecord, config: Config): Promise<boolean> {\n try {\n const fs = await import('fs/promises');\n\n // Try modtime check first (fast path)\n const currentStats = await fs.stat(filePath);\n const existingModTime = new Date(existingRecord.modifiedTime);\n\n // If modtime is clearly older, likely unchanged\n if (currentStats.mtime <= existingModTime) {\n return false; // Skip processing\n }\n\n // If modtime suggests change, verify with hash\n const currentFileInfo = await getFileInfo(filePath);\n return currentFileInfo.hash !== existingRecord.hash;\n\n } catch (modtimeError) {\n // Graceful fallback: skip modtime, use hash only\n if (config.verbose) {\n console.log(`Warning: Could not check modification time for ${filePath}:`, modtimeError);\n }\n try {\n const currentFileInfo = await getFileInfo(filePath);\n return currentFileInfo.hash !== existingRecord.hash;\n } catch (hashError) {\n // If we can't hash either, assume changed to be safe\n if (config.verbose) {\n console.log(`Warning: Could not compute hash for ${filePath}:`, hashError);\n }\n return true;\n }\n }\n}\n\nexport async function indexDirectories(paths: string[], config: Config): Promise<IndexResult> {\n let indexed = 0;\n let skipped = 0;\n let failed = 0;\n let deleted = 0;\n const errors: string[] = [];\n\n const scanOptions: ScanOptions = {\n ignorePatterns: config.indexing.ignorePatterns,\n maxFileSize: config.indexing.maxFileSize,\n respectGitignore: config.indexing.respectGitignore\n };\n\n // Initialize storage\n const { sqlite, qdrant } = await initializeStorage(config);\n\n // First pass: scan all directories to get total file count\n let totalFiles = 0;\n for (const path of paths) {\n try {\n if (config.verbose) {\n console.log(`Scanning directory: ${path}`);\n }\n const files = await scanDirectory(path, scanOptions);\n totalFiles += files.length;\n if (config.verbose) {\n console.log(`Found ${files.length} files to process in ${path}`);\n }\n } catch {\n // Continue with other directories even if one fails to scan\n }\n }\n\n if (!config.verbose && totalFiles > 0) {\n // Add a blank line for spacing in the console output\n console.log('');\n console.log(`Found ${totalFiles} files to process (checking for changes...)`);\n }\n\n for (const path of paths) {\n try {\n // Mark directory as indexing\n const normalizedPath = normalizePath(path);\n await sqlite.upsertDirectory(normalizedPath, 'indexing');\n\n const files = await scanDirectory(path, scanOptions);\n\n // Track directory-specific counters\n const dirStartIndexed = indexed;\n const dirStartSkipped = skipped;\n\n // Calculate progress interval for non-verbose updates\n const progressInterval = totalFiles > 1000 ? 50 : 10;\n\n for (const file of files) {\n try {\n // Check if file already exists and needs reprocessing\n const existingFile = await sqlite.getFile(file.path);\n\n if (existingFile) {\n const needsReprocessing = await shouldReprocessFile(file.path, existingFile, config);\n if (!needsReprocessing) {\n skipped++;\n if (config.verbose) {\n console.log(` Skipped: ${file.path} (unchanged)`);\n }\n // Show periodic progress in non-verbose mode\n if (!config.verbose && (indexed + skipped) % progressInterval === 0) {\n console.log(`Progress: ${indexed + skipped}/${totalFiles} files (${skipped} skipped as unchanged)...`);\n }\n continue; // Skip unchanged file\n }\n\n // File changed - clean up old vectors first\n await qdrant.deletePointsByFilePath(file.path);\n }\n\n const content = await fs.readFile(file.path, 'utf-8');\n const chunks = chunkText(content, config.indexing.chunkSize, config.indexing.chunkOverlap);\n\n // Store file metadata in SQLite\n await sqlite.upsertFile(file, chunks);\n\n // Generate embeddings and store in Qdrant\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const embedding = await generateEmbedding(chunk.content, config);\n // Generate a unique integer ID by combining hash and chunk index\n const hashNum = parseInt(file.hash.slice(0, 8), 16);\n const pointId = (hashNum % 1000000) * 1000 + parseInt(chunk.id);\n const point = {\n id: pointId,\n vector: embedding,\n payload: {\n filePath: file.path,\n chunkId: chunk.id,\n fileHash: file.hash,\n content: chunk.content,\n parentDirectories: file.parentDirs\n }\n };\n await qdrant.upsertPoints([point]);\n }\n\n indexed++;\n if (config.verbose) {\n console.log(` Indexed: ${file.path} (${chunks.length} chunks)`);\n }\n // Show periodic progress in non-verbose mode\n if (!config.verbose && (indexed + skipped) % progressInterval === 0) {\n console.log(`Progress: ${indexed + skipped}/${totalFiles} files (${skipped} skipped as unchanged)...`);\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const causeMessage = error instanceof Error && error.cause ? `: ${(error.cause as Error).message}` : '';\n const fullError = `Failed to process ${file.path}: ${errorMessage}${causeMessage}`;\n errors.push(fullError);\n failed++;\n\n // Print error immediately during processing (not just in verbose mode)\n console.error(`❌ ${fullError}`);\n }\n }\n\n // Clean up deleted files from this directory\n const indexedFiles = await sqlite.getFilesByDirectory(normalizedPath);\n const existingFilePaths = new Set(files.map(f => f.path));\n const deletedFiles = indexedFiles.filter(f => !existingFilePaths.has(f.path));\n\n for (const deletedFile of deletedFiles) {\n try {\n // Remove from Qdrant\n await qdrant.deletePointsByFilePath(deletedFile.path);\n \n // Remove from SQLite\n await sqlite.deleteFile(deletedFile.path);\n \n deleted++;\n if (config.verbose) {\n console.log(` Cleaned up deleted file: ${deletedFile.path}`);\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const fullError = `Failed to clean up deleted file ${deletedFile.path}: ${errorMessage}`;\n errors.push(fullError);\n failed++;\n \n console.error(`❌ ${fullError}`);\n }\n }\n\n // Mark directory as completed if no errors for this directory\n const directoryErrors = errors.filter(err => err.includes(path));\n const directoryStatus = directoryErrors.length > 0 ? 'failed' : 'completed';\n await sqlite.upsertDirectory(normalizedPath, directoryStatus);\n\n // Show directory completion\n const dirFiles = files.length;\n const dirIndexed = indexed - dirStartIndexed;\n const dirSkipped = skipped - dirStartSkipped;\n if (config.verbose) {\n console.log(`Directory ${path} completed: ${dirIndexed} indexed, ${dirSkipped} skipped`);\n } else {\n console.log(`Directory ${path} completed: ${dirFiles} files processed`);\n }\n\n } catch (error) {\n const normalizedPath = normalizePath(path);\n await sqlite.upsertDirectory(normalizedPath, 'failed');\n errors.push(`Failed to scan directory ${path}: ${(error as Error).message}`);\n }\n }\n\n return { indexed, skipped, failed, deleted, errors };\n}"],"names":["fs"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "directory-indexer",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "AI-powered directory indexing with semantic search for MCP servers",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "vite build",
|
|
12
12
|
"dev": "vite build --watch",
|
|
13
|
-
"test": "
|
|
14
|
-
"test:unit": "vitest run tests
|
|
15
|
-
"test:integration": "vitest run tests/integration
|
|
13
|
+
"test": "npm run test:unit",
|
|
14
|
+
"test:unit": "vitest run tests/*.unit.test.ts tests/mcp-handlers.test.ts tests/prerequisites.test.ts",
|
|
15
|
+
"test:integration": "vitest run tests/integration/",
|
|
16
|
+
"test:all": "vitest run",
|
|
16
17
|
"test:watch": "vitest",
|
|
17
18
|
"test:coverage": "vitest run --coverage",
|
|
18
|
-
"lint": "eslint src tests --ext .ts",
|
|
19
|
+
"lint": "eslint src tests --ext .ts && npm run typecheck",
|
|
19
20
|
"typecheck": "tsc --noEmit",
|
|
20
|
-
"clean": "rimraf dist",
|
|
21
21
|
"prepare": "npm run build",
|
|
22
22
|
"cli": "node bin/directory-indexer.js"
|
|
23
23
|
},
|
|
@@ -62,7 +62,6 @@
|
|
|
62
62
|
"@typescript-eslint/parser": "^8.15.0",
|
|
63
63
|
"@vitest/coverage-v8": "^3.2.4",
|
|
64
64
|
"eslint": "^9.15.0",
|
|
65
|
-
"rimraf": "^5.0.0",
|
|
66
65
|
"tmp": "^0.2.3",
|
|
67
66
|
"typescript": "^5.7.2",
|
|
68
67
|
"vite": "^6.0.3",
|