@ssmeo/mcp-local-rag 0.18.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.de.md +441 -0
- package/README.es.md +441 -0
- package/README.fr.md +441 -0
- package/README.md +530 -0
- package/README.pt-BR.md +441 -0
- package/README.zh-CN.md +441 -0
- package/dist/bin/install-skills.d.ts +19 -0
- package/dist/bin/install-skills.d.ts.map +1 -0
- package/dist/bin/install-skills.js +218 -0
- package/dist/bin/install-skills.js.map +1 -0
- package/dist/chunker/index.d.ts +24 -0
- package/dist/chunker/index.d.ts.map +1 -0
- package/dist/chunker/index.js +2 -0
- package/dist/chunker/index.js.map +1 -0
- package/dist/chunker/semantic-chunker.d.ts +96 -0
- package/dist/chunker/semantic-chunker.d.ts.map +1 -0
- package/dist/chunker/semantic-chunker.js +362 -0
- package/dist/chunker/semantic-chunker.js.map +1 -0
- package/dist/chunker/sentence-splitter.d.ts +32 -0
- package/dist/chunker/sentence-splitter.d.ts.map +1 -0
- package/dist/chunker/sentence-splitter.js +231 -0
- package/dist/chunker/sentence-splitter.js.map +1 -0
- package/dist/chunker/token-containment.d.ts +39 -0
- package/dist/chunker/token-containment.d.ts.map +1 -0
- package/dist/chunker/token-containment.js +83 -0
- package/dist/chunker/token-containment.js.map +1 -0
- package/dist/cli/common.d.ts +34 -0
- package/dist/cli/common.d.ts.map +1 -0
- package/dist/cli/common.js +121 -0
- package/dist/cli/common.js.map +1 -0
- package/dist/cli/delete.d.ts +3 -0
- package/dist/cli/delete.d.ts.map +1 -0
- package/dist/cli/delete.js +169 -0
- package/dist/cli/delete.js.map +1 -0
- package/dist/cli/file-collection.d.ts +2 -0
- package/dist/cli/file-collection.d.ts.map +1 -0
- package/dist/cli/file-collection.js +53 -0
- package/dist/cli/file-collection.js.map +1 -0
- package/dist/cli/ingest.d.ts +69 -0
- package/dist/cli/ingest.d.ts.map +1 -0
- package/dist/cli/ingest.js +323 -0
- package/dist/cli/ingest.js.map +1 -0
- package/dist/cli/list.d.ts +27 -0
- package/dist/cli/list.d.ts.map +1 -0
- package/dist/cli/list.js +207 -0
- package/dist/cli/list.js.map +1 -0
- package/dist/cli/options.d.ts +89 -0
- package/dist/cli/options.d.ts.map +1 -0
- package/dist/cli/options.js +244 -0
- package/dist/cli/options.js.map +1 -0
- package/dist/cli/query.d.ts +17 -0
- package/dist/cli/query.d.ts.map +1 -0
- package/dist/cli/query.js +194 -0
- package/dist/cli/query.js.map +1 -0
- package/dist/cli/read-neighbors.d.ts +3 -0
- package/dist/cli/read-neighbors.d.ts.map +1 -0
- package/dist/cli/read-neighbors.js +192 -0
- package/dist/cli/read-neighbors.js.map +1 -0
- package/dist/cli/status.d.ts +6 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +78 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/sync.d.ts +6 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +271 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli-main.d.ts +9 -0
- package/dist/cli-main.d.ts.map +1 -0
- package/dist/cli-main.js +60 -0
- package/dist/cli-main.js.map +1 -0
- package/dist/embedder/index.d.ts +143 -0
- package/dist/embedder/index.d.ts.map +1 -0
- package/dist/embedder/index.js +429 -0
- package/dist/embedder/index.js.map +1 -0
- package/dist/embedder/remote.d.ts +51 -0
- package/dist/embedder/remote.d.ts.map +1 -0
- package/dist/embedder/remote.js +182 -0
- package/dist/embedder/remote.js.map +1 -0
- package/dist/features/list.d.ts +37 -0
- package/dist/features/list.d.ts.map +1 -0
- package/dist/features/list.js +41 -0
- package/dist/features/list.js.map +1 -0
- package/dist/features/sync.d.ts +219 -0
- package/dist/features/sync.d.ts.map +1 -0
- package/dist/features/sync.js +461 -0
- package/dist/features/sync.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest/compute.d.ts +63 -0
- package/dist/ingest/compute.d.ts.map +1 -0
- package/dist/ingest/compute.js +161 -0
- package/dist/ingest/compute.js.map +1 -0
- package/dist/ingest/file.d.ts +40 -0
- package/dist/ingest/file.d.ts.map +1 -0
- package/dist/ingest/file.js +74 -0
- package/dist/ingest/file.js.map +1 -0
- package/dist/ingest/visual.d.ts +52 -0
- package/dist/ingest/visual.d.ts.map +1 -0
- package/dist/ingest/visual.js +294 -0
- package/dist/ingest/visual.js.map +1 -0
- package/dist/parser/docx-parser.d.ts +12 -0
- package/dist/parser/docx-parser.d.ts.map +1 -0
- package/dist/parser/docx-parser.js +375 -0
- package/dist/parser/docx-parser.js.map +1 -0
- package/dist/parser/html-parser.d.ts +16 -0
- package/dist/parser/html-parser.d.ts.map +1 -0
- package/dist/parser/html-parser.js +119 -0
- package/dist/parser/html-parser.js.map +1 -0
- package/dist/parser/index.d.ts +125 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +364 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/pdf-extract.d.ts +49 -0
- package/dist/parser/pdf-extract.d.ts.map +1 -0
- package/dist/parser/pdf-extract.js +114 -0
- package/dist/parser/pdf-extract.js.map +1 -0
- package/dist/parser/pdf-filter.d.ts +91 -0
- package/dist/parser/pdf-filter.d.ts.map +1 -0
- package/dist/parser/pdf-filter.js +522 -0
- package/dist/parser/pdf-filter.js.map +1 -0
- package/dist/parser/title-extractor.d.ts +28 -0
- package/dist/parser/title-extractor.d.ts.map +1 -0
- package/dist/parser/title-extractor.js +105 -0
- package/dist/parser/title-extractor.js.map +1 -0
- package/dist/pdf-visual/captioner.d.ts +11 -0
- package/dist/pdf-visual/captioner.d.ts.map +1 -0
- package/dist/pdf-visual/captioner.js +48 -0
- package/dist/pdf-visual/captioner.js.map +1 -0
- package/dist/pdf-visual/captioners/fast.d.ts +7 -0
- package/dist/pdf-visual/captioners/fast.d.ts.map +1 -0
- package/dist/pdf-visual/captioners/fast.js +108 -0
- package/dist/pdf-visual/captioners/fast.js.map +1 -0
- package/dist/pdf-visual/captioners/quality.d.ts +7 -0
- package/dist/pdf-visual/captioners/quality.d.ts.map +1 -0
- package/dist/pdf-visual/captioners/quality.js +101 -0
- package/dist/pdf-visual/captioners/quality.js.map +1 -0
- package/dist/pdf-visual/captioners/shared.d.ts +81 -0
- package/dist/pdf-visual/captioners/shared.d.ts.map +1 -0
- package/dist/pdf-visual/captioners/shared.js +156 -0
- package/dist/pdf-visual/captioners/shared.js.map +1 -0
- package/dist/pdf-visual/detector.d.ts +9 -0
- package/dist/pdf-visual/detector.d.ts.map +1 -0
- package/dist/pdf-visual/detector.js +269 -0
- package/dist/pdf-visual/detector.js.map +1 -0
- package/dist/pdf-visual/index.d.ts +13 -0
- package/dist/pdf-visual/index.d.ts.map +1 -0
- package/dist/pdf-visual/index.js +53 -0
- package/dist/pdf-visual/index.js.map +1 -0
- package/dist/pdf-visual/renderer.d.ts +9 -0
- package/dist/pdf-visual/renderer.d.ts.map +1 -0
- package/dist/pdf-visual/renderer.js +186 -0
- package/dist/pdf-visual/renderer.js.map +1 -0
- package/dist/pdf-visual/types.d.ts +53 -0
- package/dist/pdf-visual/types.d.ts.map +1 -0
- package/dist/pdf-visual/types.js +17 -0
- package/dist/pdf-visual/types.js.map +1 -0
- package/dist/server/error-utils.d.ts +63 -0
- package/dist/server/error-utils.d.ts.map +1 -0
- package/dist/server/error-utils.js +124 -0
- package/dist/server/error-utils.js.map +1 -0
- package/dist/server/index.d.ts +216 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +1068 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/list-scanner.d.ts +30 -0
- package/dist/server/list-scanner.d.ts.map +1 -0
- package/dist/server/list-scanner.js +50 -0
- package/dist/server/list-scanner.js.map +1 -0
- package/dist/server/tool-definitions.d.ts +8 -0
- package/dist/server/tool-definitions.d.ts.map +1 -0
- package/dist/server/tool-definitions.js +181 -0
- package/dist/server/tool-definitions.js.map +1 -0
- package/dist/server/tool-input.d.ts +37 -0
- package/dist/server/tool-input.d.ts.map +1 -0
- package/dist/server/tool-input.js +211 -0
- package/dist/server/tool-input.js.map +1 -0
- package/dist/server/types.d.ts +307 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +3 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server-main.d.ts +40 -0
- package/dist/server-main.d.ts.map +1 -0
- package/dist/server-main.js +254 -0
- package/dist/server-main.js.map +1 -0
- package/dist/utils/base-dirs.d.ts +145 -0
- package/dist/utils/base-dirs.d.ts.map +1 -0
- package/dist/utils/base-dirs.js +344 -0
- package/dist/utils/base-dirs.js.map +1 -0
- package/dist/utils/errors.d.ts +32 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +61 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/limits.d.ts +26 -0
- package/dist/utils/limits.d.ts.map +1 -0
- package/dist/utils/limits.js +28 -0
- package/dist/utils/limits.js.map +1 -0
- package/dist/utils/list-sources.d.ts +38 -0
- package/dist/utils/list-sources.d.ts.map +1 -0
- package/dist/utils/list-sources.js +40 -0
- package/dist/utils/list-sources.js.map +1 -0
- package/dist/utils/raw-data-utils.d.ts +76 -0
- package/dist/utils/raw-data-utils.d.ts.map +1 -0
- package/dist/utils/raw-data-utils.js +202 -0
- package/dist/utils/raw-data-utils.js.map +1 -0
- package/dist/utils/scan.d.ts +114 -0
- package/dist/utils/scan.d.ts.map +1 -0
- package/dist/utils/scan.js +209 -0
- package/dist/utils/scan.js.map +1 -0
- package/dist/utils/scope-match.d.ts +38 -0
- package/dist/utils/scope-match.d.ts.map +1 -0
- package/dist/utils/scope-match.js +86 -0
- package/dist/utils/scope-match.js.map +1 -0
- package/dist/utils/sensitive-path.d.ts +9 -0
- package/dist/utils/sensitive-path.d.ts.map +1 -0
- package/dist/utils/sensitive-path.js +78 -0
- package/dist/utils/sensitive-path.js.map +1 -0
- package/dist/utils/sync-path-key.d.ts +14 -0
- package/dist/utils/sync-path-key.d.ts.map +1 -0
- package/dist/utils/sync-path-key.js +27 -0
- package/dist/utils/sync-path-key.js.map +1 -0
- package/dist/utils/type-guards.d.ts +18 -0
- package/dist/utils/type-guards.d.ts.map +1 -0
- package/dist/utils/type-guards.js +34 -0
- package/dist/utils/type-guards.js.map +1 -0
- package/dist/utils/visual-profile.d.ts +10 -0
- package/dist/utils/visual-profile.d.ts.map +1 -0
- package/dist/utils/visual-profile.js +15 -0
- package/dist/utils/visual-profile.js.map +1 -0
- package/dist/vectordb/index.d.ts +132 -0
- package/dist/vectordb/index.d.ts.map +1 -0
- package/dist/vectordb/index.js +617 -0
- package/dist/vectordb/index.js.map +1 -0
- package/dist/vectordb/search-filters.d.ts +15 -0
- package/dist/vectordb/search-filters.d.ts.map +1 -0
- package/dist/vectordb/search-filters.js +129 -0
- package/dist/vectordb/search-filters.js.map +1 -0
- package/dist/vectordb/types.d.ts +194 -0
- package/dist/vectordb/types.d.ts.map +1 -0
- package/dist/vectordb/types.js +237 -0
- package/dist/vectordb/types.js.map +1 -0
- package/package.json +108 -0
- package/skills/mcp-local-rag/SKILL.md +234 -0
- package/skills/mcp-local-rag/references/cli-reference.md +190 -0
- package/skills/mcp-local-rag/references/html-ingestion.md +78 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// CLI delete subcommand — delete ingested content by file path or source URL
|
|
2
|
+
import { unlink } from 'node:fs/promises';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { checkRawDataArtifacts, generateMetaJsonPath, generateRawDataPath, isEnoent, isPathInRawDataDirLexical, } from '../utils/raw-data-utils.js';
|
|
5
|
+
import { createVectorStore, formatCliError } from './common.js';
|
|
6
|
+
import { resolveGlobalConfig, validatePath } from './options.js';
|
|
7
|
+
// ============================================
|
|
8
|
+
// Help
|
|
9
|
+
// ============================================
|
|
10
|
+
const HELP_TEXT = `Usage: mcp-local-rag [global-options] delete [--source <url>] [<file-path>]
|
|
11
|
+
|
|
12
|
+
Delete ingested content by file path or source URL.
|
|
13
|
+
|
|
14
|
+
Either <file-path> or --source is required (not both).
|
|
15
|
+
|
|
16
|
+
Arguments:
|
|
17
|
+
<file-path> File path of ingested content to delete
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
--source <url> Delete by source URL (for content ingested via ingest_data)
|
|
21
|
+
-h, --help Show this help
|
|
22
|
+
|
|
23
|
+
Global options (must appear before "delete"):
|
|
24
|
+
--db-path <path> LanceDB database path
|
|
25
|
+
--cache-dir <path> Model cache directory
|
|
26
|
+
--model-name <name> Embedding model`;
|
|
27
|
+
/**
|
|
28
|
+
* Parse delete-specific CLI arguments.
|
|
29
|
+
* Accepts a positional <file-path>, --source <url>, and -h/--help.
|
|
30
|
+
* Unknown flags or conflicting args cause exit(1).
|
|
31
|
+
*/
|
|
32
|
+
/** Report a usage error with the help text and stop. */
|
|
33
|
+
function usageError(message) {
|
|
34
|
+
console.error(message);
|
|
35
|
+
console.error(HELP_TEXT);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
function parseArgs(args) {
|
|
39
|
+
const result = { help: false };
|
|
40
|
+
let i = 0;
|
|
41
|
+
while (i < args.length) {
|
|
42
|
+
const arg = args[i] ?? '';
|
|
43
|
+
if (arg === '-h' || arg === '--help') {
|
|
44
|
+
result.help = true;
|
|
45
|
+
i += 1;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (arg === '--source') {
|
|
49
|
+
const value = args[i + 1];
|
|
50
|
+
if (value === undefined || value.startsWith('-')) {
|
|
51
|
+
usageError('Missing value for --source');
|
|
52
|
+
}
|
|
53
|
+
result.source = value;
|
|
54
|
+
i += 2;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (arg.startsWith('-')) {
|
|
58
|
+
usageError(`Unknown option: ${arg}`);
|
|
59
|
+
}
|
|
60
|
+
if (result.filePath !== undefined) {
|
|
61
|
+
usageError(`Unexpected argument: ${arg}`);
|
|
62
|
+
}
|
|
63
|
+
// Positional argument: file-path
|
|
64
|
+
result.filePath = arg;
|
|
65
|
+
i += 1;
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
// ============================================
|
|
70
|
+
// Main Entry Point
|
|
71
|
+
// ============================================
|
|
72
|
+
/**
|
|
73
|
+
* Run the delete CLI subcommand.
|
|
74
|
+
*/
|
|
75
|
+
/**
|
|
76
|
+
* Resolve the document to delete from either input form, or `null` when the
|
|
77
|
+
* path was rejected (the reason is already reported).
|
|
78
|
+
*/
|
|
79
|
+
function resolveTargetPath(parsed, dbPath) {
|
|
80
|
+
if (parsed.source) {
|
|
81
|
+
return generateRawDataPath(dbPath, parsed.source);
|
|
82
|
+
}
|
|
83
|
+
// DB key is the resolve()'d ingest path, so look up by resolve() (never
|
|
84
|
+
// realpath) — realpath stays in validatePath/validateFilePath.
|
|
85
|
+
const targetPath = resolve(parsed.filePath ?? '');
|
|
86
|
+
const pathError = validatePath(targetPath, '<file-path>');
|
|
87
|
+
if (pathError) {
|
|
88
|
+
console.error(pathError);
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
return targetPath;
|
|
92
|
+
}
|
|
93
|
+
/** Unlink one raw-data file, treating an already-absent file as success. */
|
|
94
|
+
async function unlinkIfPresent(path) {
|
|
95
|
+
try {
|
|
96
|
+
await unlink(path);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (!isEnoent(error)) {
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Remove a managed raw-data document and its sidecar, reporting what existed. */
|
|
105
|
+
async function removeRawDataArtifacts(targetPath) {
|
|
106
|
+
// Pre-unlink existence (shared with the MCP server delete path).
|
|
107
|
+
const artifacts = await checkRawDataArtifacts(targetPath);
|
|
108
|
+
await unlinkIfPresent(targetPath);
|
|
109
|
+
await unlinkIfPresent(generateMetaJsonPath(targetPath));
|
|
110
|
+
return artifacts;
|
|
111
|
+
}
|
|
112
|
+
export async function runDelete(args, globalOptions = {}) {
|
|
113
|
+
// Parse CLI options
|
|
114
|
+
const parsed = parseArgs(args);
|
|
115
|
+
// Handle --help
|
|
116
|
+
if (parsed.help) {
|
|
117
|
+
console.error(HELP_TEXT);
|
|
118
|
+
process.exit(0);
|
|
119
|
+
}
|
|
120
|
+
// Validate: either file-path or --source required, not both
|
|
121
|
+
if (!parsed.filePath && !parsed.source) {
|
|
122
|
+
console.error('Either <file-path> or --source is required');
|
|
123
|
+
console.error(HELP_TEXT);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
if (parsed.filePath && parsed.source) {
|
|
127
|
+
console.error('Cannot specify both <file-path> and --source');
|
|
128
|
+
console.error(HELP_TEXT);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
// Resolve global config
|
|
132
|
+
const globalConfig = resolveGlobalConfig(globalOptions);
|
|
133
|
+
const vectorStore = createVectorStore(globalConfig);
|
|
134
|
+
try {
|
|
135
|
+
await vectorStore.initialize();
|
|
136
|
+
const targetPath = resolveTargetPath(parsed, globalConfig.dbPath);
|
|
137
|
+
if (targetPath === null) {
|
|
138
|
+
process.exitCode = 1;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// Delete chunks from VectorStore
|
|
142
|
+
const removedChunks = await vectorStore.deleteChunks(targetPath);
|
|
143
|
+
// Optimize immediately after the DB delete: a later raw-data unlink failure
|
|
144
|
+
// (re-thrown below for non-ENOENT) must not skip compaction once the rows
|
|
145
|
+
// are already gone.
|
|
146
|
+
await vectorStore.optimize();
|
|
147
|
+
const removedFiles = isPathInRawDataDirLexical(targetPath, globalConfig.dbPath)
|
|
148
|
+
? await removeRawDataArtifacts(targetPath)
|
|
149
|
+
: { rawDataExisted: false, metaExisted: false };
|
|
150
|
+
// Output result JSON to stdout
|
|
151
|
+
const result = {
|
|
152
|
+
filePath: targetPath,
|
|
153
|
+
deleted: true,
|
|
154
|
+
removedChunks,
|
|
155
|
+
existed: removedChunks > 0 || removedFiles.rawDataExisted || removedFiles.metaExisted,
|
|
156
|
+
timestamp: new Date().toISOString(),
|
|
157
|
+
};
|
|
158
|
+
process.stdout.write(JSON.stringify(result));
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
const reason = formatCliError(error);
|
|
162
|
+
console.error(`Error: ${reason}`);
|
|
163
|
+
process.exitCode = 1;
|
|
164
|
+
}
|
|
165
|
+
finally {
|
|
166
|
+
await vectorStore.close();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=delete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.js","sourceRoot":"","sources":["../../src/cli/delete.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-collection.d.ts","sourceRoot":"","sources":["../../src/cli/file-collection.ts"],"names":[],"mappings":"AAeA,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,YAAY,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,MAAM,EAAE,CAAC,CA0DnB"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// CLI ingest file collection.
|
|
2
|
+
//
|
|
3
|
+
// Resolves the positional ingest path into the concrete list of supported
|
|
4
|
+
// files to ingest. Single-file mode validates the extension; directory mode
|
|
5
|
+
// confirms the path is inside a configured root and delegates the bounded
|
|
6
|
+
// BFS walk to `bfsCollectSupportedFiles`. Out-of-root directory targets exit
|
|
7
|
+
// the process (preserved from the original inline implementation).
|
|
8
|
+
import { realpath, stat } from 'node:fs/promises';
|
|
9
|
+
import { extname, resolve, sep } from 'node:path';
|
|
10
|
+
import { SUPPORTED_EXTENSIONS } from '../parser/index.js';
|
|
11
|
+
import { MAX_SCAN_DEPTH } from '../utils/limits.js';
|
|
12
|
+
import { bfsCollectSupportedFiles } from '../utils/scan.js';
|
|
13
|
+
export async function collectFiles(targetPath, baseDirs, excludePaths) {
|
|
14
|
+
const resolved = resolve(targetPath);
|
|
15
|
+
const info = await stat(resolved);
|
|
16
|
+
if (info.isFile()) {
|
|
17
|
+
const ext = extname(resolved).toLowerCase();
|
|
18
|
+
if (!SUPPORTED_EXTENSIONS.has(ext)) {
|
|
19
|
+
console.error(`Unsupported file extension: ${ext} (supported: ${[...SUPPORTED_EXTENSIONS].join(', ')})`);
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
// Store the resolve()'d path (the DB key), not realpath — path policy:
|
|
23
|
+
// realpath only at the security boundary, resolve() everywhere user-facing.
|
|
24
|
+
return [resolved];
|
|
25
|
+
}
|
|
26
|
+
if (info.isDirectory()) {
|
|
27
|
+
// realpath both sides so a symlinked positional path still matches a
|
|
28
|
+
// root whose realpath agrees. baseDirs from resolveCliBaseDirsOrExit
|
|
29
|
+
// are already realpath-normalized with a trailing sep.
|
|
30
|
+
const realResolved = await realpath(resolved);
|
|
31
|
+
const realResolvedWithSep = realResolved.endsWith(sep) ? realResolved : realResolved + sep;
|
|
32
|
+
const insideAnyRoot = baseDirs.some((root) => realResolvedWithSep === root || realResolvedWithSep.startsWith(root));
|
|
33
|
+
if (!insideAnyRoot) {
|
|
34
|
+
console.error(`Error: ${targetPath} is not under any configured base directory. ` +
|
|
35
|
+
`Allowed roots: ${baseDirs.join(', ')}. ` +
|
|
36
|
+
`Provide a path inside one of the configured roots, or set BASE_DIRS / --base-dir to include the desired tree.`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
// `realResolved` is used ONLY for the in-root containment check (security).
|
|
40
|
+
// The walk uses the resolve()'d `resolved` so the stored DB keys match what
|
|
41
|
+
// `list`/`delete`/`read_chunk_neighbors` use (resolve(), not realpath).
|
|
42
|
+
const { files: collected, unreadableDirs, depthLimited, } = await bfsCollectSupportedFiles(resolved, excludePaths);
|
|
43
|
+
for (const { dirPath } of unreadableDirs) {
|
|
44
|
+
console.error(`Warning: cannot read directory: ${dirPath}`);
|
|
45
|
+
}
|
|
46
|
+
if (depthLimited) {
|
|
47
|
+
console.error(`Warning: some directories were skipped because they exceed the maximum depth (${MAX_SCAN_DEPTH})`);
|
|
48
|
+
}
|
|
49
|
+
return [...new Set(collected)].sort();
|
|
50
|
+
}
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=file-collection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-collection.js","sourceRoot":"","sources":["../../src/cli/file-collection.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,0EAA0E;AAC1E,4EAA4E;AAC5E,0EAA0E;AAC1E,6EAA6E;AAC7E,mEAAmE;AAEnE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAEjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAA;AAE3D,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAAkB,EAClB,QAA2B,EAC3B,YAAsB;IAEtB,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IACpC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAA;IAEjC,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAA;QAC3C,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CACX,+BAA+B,GAAG,gBAAgB,CAAC,GAAG,oBAAoB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC1F,CAAA;YACD,OAAO,EAAE,CAAA;QACX,CAAC;QACD,uEAAuE;QACvE,4EAA4E;QAC5E,OAAO,CAAC,QAAQ,CAAC,CAAA;IACnB,CAAC;IAED,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACvB,qEAAqE;QACrE,qEAAqE;QACrE,uDAAuD;QACvD,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAC7C,MAAM,mBAAmB,GAAG,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,GAAG,GAAG,CAAA;QAC1F,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CACjC,CAAC,IAAI,EAAE,EAAE,CAAC,mBAAmB,KAAK,IAAI,IAAI,mBAAmB,CAAC,UAAU,CAAC,IAAI,CAAC,CAC/E,CAAA;QACD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CACX,UAAU,UAAU,+CAA+C;gBACjE,kBAAkB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBACzC,+GAA+G,CAClH,CAAA;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QAED,4EAA4E;QAC5E,4EAA4E;QAC5E,wEAAwE;QACxE,MAAM,EACJ,KAAK,EAAE,SAAS,EAChB,cAAc,EACd,YAAY,GACb,GAAG,MAAM,wBAAwB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAA;QAE1D,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,cAAc,EAAE,CAAC;YACzC,OAAO,CAAC,KAAK,CAAC,mCAAmC,OAAO,EAAE,CAAC,CAAA;QAC7D,CAAC;QAED,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CACX,iFAAiF,cAAc,GAAG,CACnG,CAAA;QACH,CAAC;QAED,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IACvC,CAAC;IAED,OAAO,EAAE,CAAA;AACX,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { SemanticChunker } from '../chunker/index.js';
|
|
2
|
+
import type { Embedder } from '../embedder/index.js';
|
|
3
|
+
import type { RemoteEmbedder } from '../embedder/remote.js';
|
|
4
|
+
import { type PrepareFileForIngestOptions } from '../ingest/file.js';
|
|
5
|
+
import { DocumentParser } from '../parser/index.js';
|
|
6
|
+
import type { BaseDirsConfig, BaseDirsConfigWarning } from '../utils/base-dirs.js';
|
|
7
|
+
import type { QualityProfile } from '../utils/visual-profile.js';
|
|
8
|
+
import type { VectorStore } from '../vectordb/index.js';
|
|
9
|
+
import type { GlobalOptions, ResolvedGlobalConfig } from './options.js';
|
|
10
|
+
interface IngestConfig {
|
|
11
|
+
baseDirs: BaseDirsConfig;
|
|
12
|
+
baseDirsWarnings: BaseDirsConfigWarning[];
|
|
13
|
+
dbPath: string;
|
|
14
|
+
cacheDir: string;
|
|
15
|
+
modelName: string;
|
|
16
|
+
maxFileSize: number;
|
|
17
|
+
chunkMinLength?: number;
|
|
18
|
+
}
|
|
19
|
+
interface IngestCliOptions {
|
|
20
|
+
/** Repeatable, in CLI order. Empty means unset — the resolver uses env / cwd. */
|
|
21
|
+
baseDirs?: string[] | undefined;
|
|
22
|
+
maxFileSize?: number | undefined;
|
|
23
|
+
chunkMinLength?: number | undefined;
|
|
24
|
+
visual?: boolean | undefined;
|
|
25
|
+
images?: boolean | undefined;
|
|
26
|
+
/** Silently ignored unless `visual` is true. Defaults to `'fast'`. */
|
|
27
|
+
visualQuality?: QualityProfile | undefined;
|
|
28
|
+
}
|
|
29
|
+
interface ParsedArgs {
|
|
30
|
+
positional: string | undefined;
|
|
31
|
+
options: IngestCliOptions;
|
|
32
|
+
help: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare function parseArgs(args: string[]): ParsedArgs;
|
|
35
|
+
/**
|
|
36
|
+
* Merge global config with ingest-specific options (CLI > env > defaults).
|
|
37
|
+
*
|
|
38
|
+
* CLI roots are pre-validated against the sensitive-path policy here, so the
|
|
39
|
+
* user gets `--base-dir`-attributed errors before the resolver touches disk.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolveConfig(globalConfig: ResolvedGlobalConfig, ingestOptions?: IngestCliOptions): Promise<IngestConfig>;
|
|
42
|
+
/** Collaborators one CLI ingest run needs, injected as a unit. */
|
|
43
|
+
export interface SingleFileIngestCollaborators {
|
|
44
|
+
parser: DocumentParser;
|
|
45
|
+
chunker: SemanticChunker;
|
|
46
|
+
embedder: Embedder | RemoteEmbedder;
|
|
47
|
+
vectorStore: VectorStore;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Ingest one file, returning the number of chunks inserted.
|
|
51
|
+
*
|
|
52
|
+
* `options` is the shared preparation contract, passed straight through: a
|
|
53
|
+
* `captioner` on a `.pdf` routes through VLM captioning, and `pdf-visual` is
|
|
54
|
+
* loaded by dynamic import, so no other path pulls the VLM module in.
|
|
55
|
+
*/
|
|
56
|
+
export declare function ingestSingleFile(filePath: string, collaborators: SingleFileIngestCollaborators, options?: PrepareFileForIngestOptions): Promise<number>;
|
|
57
|
+
/**
|
|
58
|
+
* Turn a resolved per-file request into shared preparation options. The
|
|
59
|
+
* captioner block travels only with a non-null profile, carrying the cacheDir
|
|
60
|
+
* `resolveGlobalConfig` validated. Shared by `ingest` and CLI `sync`, so both
|
|
61
|
+
* reach the VLM through one mapping.
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildFileIngestOptions(request: {
|
|
64
|
+
images: boolean;
|
|
65
|
+
visualProfile: QualityProfile | null;
|
|
66
|
+
}, globalConfig: ResolvedGlobalConfig): PrepareFileForIngestOptions;
|
|
67
|
+
export declare function runIngest(args: string[], globalOptions?: GlobalOptions): Promise<void>;
|
|
68
|
+
export {};
|
|
69
|
+
//# sourceMappingURL=ingest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest.d.ts","sourceRoot":"","sources":["../../src/cli/ingest.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EAEL,KAAK,2BAA2B,EAEjC,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAElF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAQvD,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAgBvE,UAAU,YAAY;IACpB,QAAQ,EAAE,cAAc,CAAA;IACxB,gBAAgB,EAAE,qBAAqB,EAAE,CAAA;IACzC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAQD,UAAU,gBAAgB;IACxB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5B,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5B,sEAAsE;IACtE,aAAa,CAAC,EAAE,cAAc,GAAG,SAAS,CAAA;CAC3C;AAED,UAAU,UAAU;IAClB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,OAAO,EAAE,gBAAgB,CAAA;IACzB,IAAI,EAAE,OAAO,CAAA;CACd;AA6DD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAwDpD;AAMD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,YAAY,EAAE,oBAAoB,EAClC,aAAa,GAAE,gBAAqB,GACnC,OAAO,CAAC,YAAY,CAAC,CAyDvB;AAMD,kEAAkE;AAClE,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,cAAc,CAAA;IACtB,OAAO,EAAE,eAAe,CAAA;IACxB,QAAQ,EAAE,QAAQ,GAAG,cAAc,CAAA;IACnC,WAAW,EAAE,WAAW,CAAA;CACzB;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,6BAA6B,EAC5C,OAAO,GAAE,2BAA+C,GACvD,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAMD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,cAAc,GAAG,IAAI,CAAA;CAAE,EAClE,YAAY,EAAE,oBAAoB,GACjC,2BAA2B,CAY7B;AAmBD,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,aAAa,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsGhG"}
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
// CLI ingest subcommand — bulk file ingestion with single optimize() at end
|
|
2
|
+
import { stat } from 'node:fs/promises';
|
|
3
|
+
import { resolve, sep } from 'node:path';
|
|
4
|
+
import { SemanticChunker } from '../chunker/index.js';
|
|
5
|
+
import { buildPreparedFileVectorChunks, prepareFileForIngest, } from '../ingest/file.js';
|
|
6
|
+
import { DocumentParser } from '../parser/index.js';
|
|
7
|
+
import { DEFAULT_MAX_FILE_SIZE, MAX_CHUNK_MIN_LENGTH } from '../utils/limits.js';
|
|
8
|
+
import { createEmbedder, createVectorStore, formatCliError, resolveCliBaseDirsOrExit, } from './common.js';
|
|
9
|
+
import { collectFiles } from './file-collection.js';
|
|
10
|
+
import { consumeBaseDirArg, requireFlagValue, requireVisualQuality, resolveDevice, resolveGlobalConfig, validateChunkMinLength, validateMaxFileSize, validatePath, } from './options.js';
|
|
11
|
+
// ============================================
|
|
12
|
+
// Defaults
|
|
13
|
+
// ============================================
|
|
14
|
+
const INGEST_DEFAULTS = {
|
|
15
|
+
maxFileSize: DEFAULT_MAX_FILE_SIZE,
|
|
16
|
+
};
|
|
17
|
+
// ============================================
|
|
18
|
+
// Help
|
|
19
|
+
// ============================================
|
|
20
|
+
const HELP_TEXT = `Usage: mcp-local-rag [global-options] ingest [options] <path>
|
|
21
|
+
|
|
22
|
+
Ingest a single file or all supported files under a directory.
|
|
23
|
+
|
|
24
|
+
Options:
|
|
25
|
+
--base-dir <path> Base directory for documents (repeatable: pass once per root; default: BASE_DIRS/BASE_DIR env or cwd)
|
|
26
|
+
--max-file-size <n> Max file size in bytes (default: ${INGEST_DEFAULTS.maxFileSize})
|
|
27
|
+
--chunk-min-length <n> Minimum ordinary chunk length in characters (default: 50, range: 1-${MAX_CHUNK_MIN_LENGTH}); a fragment of content split to fit the model's token limit can be shorter
|
|
28
|
+
--visual Enable VLM captioning for PDF figure pages (PDFs only; no effect on other types)
|
|
29
|
+
--images Store bounded PDF figures/tables and Mammoth DOCX images
|
|
30
|
+
--visual-quality <profile> VLM profile when --visual is set: fast (default, lightweight) or quality (Qwen2.5-VL-3B, ~10x cache, ~2x inference)
|
|
31
|
+
-h, --help Show this help
|
|
32
|
+
|
|
33
|
+
Global options (must appear before "ingest"):
|
|
34
|
+
--db-path <path> LanceDB database path
|
|
35
|
+
--cache-dir <path> Model cache directory
|
|
36
|
+
--model-name <name> Embedding model`;
|
|
37
|
+
// ============================================
|
|
38
|
+
// Arg Parsing
|
|
39
|
+
// ============================================
|
|
40
|
+
/** A global flag passed after the subcommand is an error, not a pass-through. */
|
|
41
|
+
/** Read a flag whose value must be a bare non-negative integer. */
|
|
42
|
+
function requireCountFlag(args, flagIndex, flag) {
|
|
43
|
+
const raw = requireFlagValue(args, flagIndex, flag);
|
|
44
|
+
if (!/^\d+$/.test(raw)) {
|
|
45
|
+
console.error(`Invalid value for ${flag}: "${raw.slice(0, 100)}"`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
return Number.parseInt(raw, 10);
|
|
49
|
+
}
|
|
50
|
+
/** Reject an unknown flag, or a second positional path. */
|
|
51
|
+
function rejectUnexpectedArgument(arg, positional) {
|
|
52
|
+
if (arg.startsWith('-')) {
|
|
53
|
+
console.error(`Unknown option: ${arg}`);
|
|
54
|
+
console.error(HELP_TEXT);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
if (positional !== undefined) {
|
|
58
|
+
console.error(`Unexpected argument: ${arg}`);
|
|
59
|
+
console.error('Only one path is accepted. Use a directory to ingest multiple files.');
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function parseArgs(args) {
|
|
64
|
+
const options = {};
|
|
65
|
+
let positional;
|
|
66
|
+
let help = false;
|
|
67
|
+
let i = 0;
|
|
68
|
+
while (i < args.length) {
|
|
69
|
+
const arg = args[i] ?? '';
|
|
70
|
+
switch (arg) {
|
|
71
|
+
case '-h':
|
|
72
|
+
case '--help':
|
|
73
|
+
help = true;
|
|
74
|
+
i++;
|
|
75
|
+
break;
|
|
76
|
+
case '--base-dir': {
|
|
77
|
+
// Repeatable: each `--base-dir <path>` occurrence appends one entry
|
|
78
|
+
// to `options.baseDirs`. The accumulator is lazily initialized so
|
|
79
|
+
// an absent flag leaves `options.baseDirs` as `undefined`, which
|
|
80
|
+
// the resolver treats as "fall through to env / cwd".
|
|
81
|
+
if (options.baseDirs === undefined) {
|
|
82
|
+
options.baseDirs = [];
|
|
83
|
+
}
|
|
84
|
+
const valueIndex = consumeBaseDirArg(args, i, options.baseDirs);
|
|
85
|
+
i = valueIndex + 1;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
case '--max-file-size':
|
|
89
|
+
options.maxFileSize = requireCountFlag(args, i, '--max-file-size');
|
|
90
|
+
i += 2;
|
|
91
|
+
break;
|
|
92
|
+
case '--chunk-min-length':
|
|
93
|
+
options.chunkMinLength = requireCountFlag(args, i, '--chunk-min-length');
|
|
94
|
+
i += 2;
|
|
95
|
+
break;
|
|
96
|
+
case '--visual':
|
|
97
|
+
// Boolean toggle: no value consumed. Mirrors the -h/--help pattern.
|
|
98
|
+
options.visual = true;
|
|
99
|
+
i++;
|
|
100
|
+
break;
|
|
101
|
+
case '--images':
|
|
102
|
+
options.images = true;
|
|
103
|
+
i++;
|
|
104
|
+
break;
|
|
105
|
+
case '--visual-quality':
|
|
106
|
+
options.visualQuality = requireVisualQuality(args, i);
|
|
107
|
+
i += 2;
|
|
108
|
+
break;
|
|
109
|
+
default:
|
|
110
|
+
rejectUnexpectedArgument(arg, positional);
|
|
111
|
+
positional = arg;
|
|
112
|
+
i++;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return { positional, options, help };
|
|
117
|
+
}
|
|
118
|
+
// ============================================
|
|
119
|
+
// Config Resolution
|
|
120
|
+
// ============================================
|
|
121
|
+
/**
|
|
122
|
+
* Merge global config with ingest-specific options (CLI > env > defaults).
|
|
123
|
+
*
|
|
124
|
+
* CLI roots are pre-validated against the sensitive-path policy here, so the
|
|
125
|
+
* user gets `--base-dir`-attributed errors before the resolver touches disk.
|
|
126
|
+
*/
|
|
127
|
+
export async function resolveConfig(globalConfig, ingestOptions = {}) {
|
|
128
|
+
const cliBaseDirs = ingestOptions.baseDirs ?? [];
|
|
129
|
+
// Validate CLI-supplied paths against the sensitive-path policy before
|
|
130
|
+
// calling the resolver. Doing this here (rather than relying on the
|
|
131
|
+
// resolver) keeps the error message attributed to `--base-dir` and avoids
|
|
132
|
+
// an unnecessary realpath round-trip on a path we will reject anyway.
|
|
133
|
+
for (const root of cliBaseDirs) {
|
|
134
|
+
const baseDirError = validatePath(root, '--base-dir');
|
|
135
|
+
if (baseDirError) {
|
|
136
|
+
console.error(baseDirError);
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const { config: baseDirs, warnings: baseDirsWarnings } = await resolveCliBaseDirsOrExit(cliBaseDirs);
|
|
141
|
+
const maxFileSize = ingestOptions.maxFileSize ??
|
|
142
|
+
(process.env['MAX_FILE_SIZE']
|
|
143
|
+
? Number.parseInt(process.env['MAX_FILE_SIZE'], 10)
|
|
144
|
+
: INGEST_DEFAULTS.maxFileSize);
|
|
145
|
+
const chunkMinLength = ingestOptions.chunkMinLength ??
|
|
146
|
+
(process.env['CHUNK_MIN_LENGTH']
|
|
147
|
+
? Number.parseInt(process.env['CHUNK_MIN_LENGTH'], 10)
|
|
148
|
+
: undefined);
|
|
149
|
+
// Validate maxFileSize range
|
|
150
|
+
const maxFileSizeError = validateMaxFileSize(maxFileSize);
|
|
151
|
+
if (maxFileSizeError) {
|
|
152
|
+
console.error(maxFileSizeError);
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
// Validate chunkMinLength range (if provided)
|
|
156
|
+
if (chunkMinLength !== undefined) {
|
|
157
|
+
const chunkMinLengthError = validateChunkMinLength(chunkMinLength);
|
|
158
|
+
if (chunkMinLengthError) {
|
|
159
|
+
console.error(chunkMinLengthError);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const resolved = {
|
|
164
|
+
dbPath: globalConfig.dbPath,
|
|
165
|
+
cacheDir: globalConfig.cacheDir,
|
|
166
|
+
modelName: globalConfig.modelName,
|
|
167
|
+
baseDirs,
|
|
168
|
+
baseDirsWarnings,
|
|
169
|
+
maxFileSize,
|
|
170
|
+
};
|
|
171
|
+
if (chunkMinLength !== undefined) {
|
|
172
|
+
resolved.chunkMinLength = chunkMinLength;
|
|
173
|
+
}
|
|
174
|
+
return resolved;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Ingest one file, returning the number of chunks inserted.
|
|
178
|
+
*
|
|
179
|
+
* `options` is the shared preparation contract, passed straight through: a
|
|
180
|
+
* `captioner` on a `.pdf` routes through VLM captioning, and `pdf-visual` is
|
|
181
|
+
* loaded by dynamic import, so no other path pulls the VLM module in.
|
|
182
|
+
*/
|
|
183
|
+
export async function ingestSingleFile(filePath, collaborators, options = { images: false }) {
|
|
184
|
+
const { parser, chunker, embedder, vectorStore } = collaborators;
|
|
185
|
+
const isPdf = filePath.toLowerCase().endsWith('.pdf');
|
|
186
|
+
const prepared = await prepareFileForIngest(filePath, { parser, chunker, embedder }, options);
|
|
187
|
+
if (prepared.omittedImageCount > 0) {
|
|
188
|
+
console.error(` Warning: skipped ${prepared.omittedImageCount} undecodable or oversized ${isPdf ? 'PDF' : 'DOCX'} image(s)`);
|
|
189
|
+
}
|
|
190
|
+
if (prepared.chunks.length === 0) {
|
|
191
|
+
console.error(` Warning: 0 chunks generated (file may be empty or too short)`);
|
|
192
|
+
return 0;
|
|
193
|
+
}
|
|
194
|
+
const vectorChunks = buildPreparedFileVectorChunks(prepared);
|
|
195
|
+
// Delete existing chunks for this file, then insert the new ones
|
|
196
|
+
await vectorStore.deleteChunks(filePath);
|
|
197
|
+
await vectorStore.insertChunks(vectorChunks);
|
|
198
|
+
return vectorChunks.length;
|
|
199
|
+
}
|
|
200
|
+
// ============================================
|
|
201
|
+
// Main Entry Point
|
|
202
|
+
// ============================================
|
|
203
|
+
/**
|
|
204
|
+
* Turn a resolved per-file request into shared preparation options. The
|
|
205
|
+
* captioner block travels only with a non-null profile, carrying the cacheDir
|
|
206
|
+
* `resolveGlobalConfig` validated. Shared by `ingest` and CLI `sync`, so both
|
|
207
|
+
* reach the VLM through one mapping.
|
|
208
|
+
*/
|
|
209
|
+
export function buildFileIngestOptions(request, globalConfig) {
|
|
210
|
+
if (request.visualProfile === null) {
|
|
211
|
+
return { images: request.images };
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
images: request.images,
|
|
215
|
+
captioner: {
|
|
216
|
+
profile: request.visualProfile,
|
|
217
|
+
cacheDir: globalConfig.cacheDir,
|
|
218
|
+
device: resolveDevice(process.env['RAG_DEVICE']),
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
/** Require a positional path argument that names something on disk. */
|
|
223
|
+
async function requireExistingPath(positional) {
|
|
224
|
+
if (!positional) {
|
|
225
|
+
console.error('Usage: mcp-local-rag ingest [options] <path>');
|
|
226
|
+
console.error(' Ingest a single file or all supported files under a directory.');
|
|
227
|
+
console.error(' Run with --help for all options.');
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
await stat(positional);
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
console.error(`Error: path does not exist: ${positional}`);
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
return positional;
|
|
238
|
+
}
|
|
239
|
+
export async function runIngest(args, globalOptions = {}) {
|
|
240
|
+
// Parse CLI options
|
|
241
|
+
const { positional, options, help } = parseArgs(args);
|
|
242
|
+
// Handle --help
|
|
243
|
+
if (help) {
|
|
244
|
+
console.error(HELP_TEXT);
|
|
245
|
+
process.exit(0);
|
|
246
|
+
}
|
|
247
|
+
const targetPath = await requireExistingPath(positional);
|
|
248
|
+
// Resolve config: CLI flags > env vars > defaults
|
|
249
|
+
const globalConfig = resolveGlobalConfig(globalOptions);
|
|
250
|
+
const config = await resolveConfig(globalConfig, options);
|
|
251
|
+
const excludePaths = [`${resolve(config.dbPath)}${sep}`, `${resolve(config.cacheDir)}${sep}`];
|
|
252
|
+
// Surface resolver warnings (precedence, nested-root pruning) on stderr
|
|
253
|
+
// before scan output starts.
|
|
254
|
+
for (const warning of config.baseDirsWarnings) {
|
|
255
|
+
console.error(warning.message);
|
|
256
|
+
}
|
|
257
|
+
// Directory mode scans only the positional directory; configured roots are
|
|
258
|
+
// the containment boundary used by collectFiles and DocumentParser.
|
|
259
|
+
const files = await collectFiles(targetPath, config.baseDirs.baseDirs, excludePaths);
|
|
260
|
+
if (files.length === 0) {
|
|
261
|
+
console.error('No supported files found.');
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
console.error(`Found ${files.length} file(s) to ingest.`);
|
|
265
|
+
// Initialize components (single instances reused across all files).
|
|
266
|
+
// The parser receives the full multi-root config. The directory-scan loop
|
|
267
|
+
// (`collectFiles`) iterates every effective root in `config.baseDirs.baseDirs`
|
|
268
|
+
// and dedupes overlap.
|
|
269
|
+
const parser = new DocumentParser({
|
|
270
|
+
baseDirs: config.baseDirs.baseDirs,
|
|
271
|
+
maxFileSize: config.maxFileSize,
|
|
272
|
+
});
|
|
273
|
+
const chunker = new SemanticChunker(config.chunkMinLength !== undefined ? { minChunkLength: config.chunkMinLength } : {});
|
|
274
|
+
const embedder = createEmbedder(globalConfig);
|
|
275
|
+
const vectorStore = createVectorStore(globalConfig);
|
|
276
|
+
await vectorStore.initialize();
|
|
277
|
+
// Process each file
|
|
278
|
+
const summary = { succeeded: 0, failed: 0, totalChunks: 0 };
|
|
279
|
+
try {
|
|
280
|
+
for (const [i, filePath] of files.entries()) {
|
|
281
|
+
const label = `[${i + 1}/${files.length}]`;
|
|
282
|
+
try {
|
|
283
|
+
const chunkCount = await ingestSingleFile(filePath, { parser, chunker, embedder, vectorStore }, buildFileIngestOptions({
|
|
284
|
+
images: options.images === true,
|
|
285
|
+
// `--visual-quality` defaults to `fast` and is silently ignored
|
|
286
|
+
// without `--visual`, mirroring how `--visual` itself is silently
|
|
287
|
+
// coerced away for non-PDF files.
|
|
288
|
+
visualProfile: options.visual === true ? (options.visualQuality ?? 'fast') : null,
|
|
289
|
+
}, globalConfig));
|
|
290
|
+
if (chunkCount === 0) {
|
|
291
|
+
// 0 chunks is a skip/warning, not a failure
|
|
292
|
+
console.error(`${label} ${filePath} ... SKIPPED (0 chunks)`);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
console.error(`${label} ${filePath} ... OK (${chunkCount} chunks)`);
|
|
296
|
+
summary.totalChunks += chunkCount;
|
|
297
|
+
}
|
|
298
|
+
summary.succeeded++;
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
const reason = formatCliError(error);
|
|
302
|
+
console.error(`${label} ${filePath} ... FAILED: ${reason}`);
|
|
303
|
+
summary.failed++;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// Optimize once at end (not per-file)
|
|
307
|
+
await vectorStore.optimize();
|
|
308
|
+
}
|
|
309
|
+
finally {
|
|
310
|
+
await embedder.dispose();
|
|
311
|
+
await vectorStore.close();
|
|
312
|
+
}
|
|
313
|
+
// Print summary
|
|
314
|
+
console.error('');
|
|
315
|
+
console.error('--- Ingest Summary ---');
|
|
316
|
+
console.error(`Succeeded: ${summary.succeeded}`);
|
|
317
|
+
console.error(`Failed: ${summary.failed}`);
|
|
318
|
+
console.error(`Total chunks: ${summary.totalChunks}`);
|
|
319
|
+
if (summary.failed > 0) {
|
|
320
|
+
process.exitCode = 1;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
//# sourceMappingURL=ingest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest.js","sourceRoot":"","sources":["../../src/cli/ingest.ts"],"names":[],"mappings":"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"}
|