@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.
Files changed (247) hide show
  1. package/LICENSE +21 -0
  2. package/README.de.md +441 -0
  3. package/README.es.md +441 -0
  4. package/README.fr.md +441 -0
  5. package/README.md +530 -0
  6. package/README.pt-BR.md +441 -0
  7. package/README.zh-CN.md +441 -0
  8. package/dist/bin/install-skills.d.ts +19 -0
  9. package/dist/bin/install-skills.d.ts.map +1 -0
  10. package/dist/bin/install-skills.js +218 -0
  11. package/dist/bin/install-skills.js.map +1 -0
  12. package/dist/chunker/index.d.ts +24 -0
  13. package/dist/chunker/index.d.ts.map +1 -0
  14. package/dist/chunker/index.js +2 -0
  15. package/dist/chunker/index.js.map +1 -0
  16. package/dist/chunker/semantic-chunker.d.ts +96 -0
  17. package/dist/chunker/semantic-chunker.d.ts.map +1 -0
  18. package/dist/chunker/semantic-chunker.js +362 -0
  19. package/dist/chunker/semantic-chunker.js.map +1 -0
  20. package/dist/chunker/sentence-splitter.d.ts +32 -0
  21. package/dist/chunker/sentence-splitter.d.ts.map +1 -0
  22. package/dist/chunker/sentence-splitter.js +231 -0
  23. package/dist/chunker/sentence-splitter.js.map +1 -0
  24. package/dist/chunker/token-containment.d.ts +39 -0
  25. package/dist/chunker/token-containment.d.ts.map +1 -0
  26. package/dist/chunker/token-containment.js +83 -0
  27. package/dist/chunker/token-containment.js.map +1 -0
  28. package/dist/cli/common.d.ts +34 -0
  29. package/dist/cli/common.d.ts.map +1 -0
  30. package/dist/cli/common.js +121 -0
  31. package/dist/cli/common.js.map +1 -0
  32. package/dist/cli/delete.d.ts +3 -0
  33. package/dist/cli/delete.d.ts.map +1 -0
  34. package/dist/cli/delete.js +169 -0
  35. package/dist/cli/delete.js.map +1 -0
  36. package/dist/cli/file-collection.d.ts +2 -0
  37. package/dist/cli/file-collection.d.ts.map +1 -0
  38. package/dist/cli/file-collection.js +53 -0
  39. package/dist/cli/file-collection.js.map +1 -0
  40. package/dist/cli/ingest.d.ts +69 -0
  41. package/dist/cli/ingest.d.ts.map +1 -0
  42. package/dist/cli/ingest.js +323 -0
  43. package/dist/cli/ingest.js.map +1 -0
  44. package/dist/cli/list.d.ts +27 -0
  45. package/dist/cli/list.d.ts.map +1 -0
  46. package/dist/cli/list.js +207 -0
  47. package/dist/cli/list.js.map +1 -0
  48. package/dist/cli/options.d.ts +89 -0
  49. package/dist/cli/options.d.ts.map +1 -0
  50. package/dist/cli/options.js +244 -0
  51. package/dist/cli/options.js.map +1 -0
  52. package/dist/cli/query.d.ts +17 -0
  53. package/dist/cli/query.d.ts.map +1 -0
  54. package/dist/cli/query.js +194 -0
  55. package/dist/cli/query.js.map +1 -0
  56. package/dist/cli/read-neighbors.d.ts +3 -0
  57. package/dist/cli/read-neighbors.d.ts.map +1 -0
  58. package/dist/cli/read-neighbors.js +192 -0
  59. package/dist/cli/read-neighbors.js.map +1 -0
  60. package/dist/cli/status.d.ts +6 -0
  61. package/dist/cli/status.d.ts.map +1 -0
  62. package/dist/cli/status.js +78 -0
  63. package/dist/cli/status.js.map +1 -0
  64. package/dist/cli/sync.d.ts +6 -0
  65. package/dist/cli/sync.d.ts.map +1 -0
  66. package/dist/cli/sync.js +271 -0
  67. package/dist/cli/sync.js.map +1 -0
  68. package/dist/cli-main.d.ts +9 -0
  69. package/dist/cli-main.d.ts.map +1 -0
  70. package/dist/cli-main.js +60 -0
  71. package/dist/cli-main.js.map +1 -0
  72. package/dist/embedder/index.d.ts +143 -0
  73. package/dist/embedder/index.d.ts.map +1 -0
  74. package/dist/embedder/index.js +429 -0
  75. package/dist/embedder/index.js.map +1 -0
  76. package/dist/embedder/remote.d.ts +51 -0
  77. package/dist/embedder/remote.d.ts.map +1 -0
  78. package/dist/embedder/remote.js +182 -0
  79. package/dist/embedder/remote.js.map +1 -0
  80. package/dist/features/list.d.ts +37 -0
  81. package/dist/features/list.d.ts.map +1 -0
  82. package/dist/features/list.js +41 -0
  83. package/dist/features/list.js.map +1 -0
  84. package/dist/features/sync.d.ts +219 -0
  85. package/dist/features/sync.d.ts.map +1 -0
  86. package/dist/features/sync.js +461 -0
  87. package/dist/features/sync.js.map +1 -0
  88. package/dist/index.d.ts +3 -0
  89. package/dist/index.d.ts.map +1 -0
  90. package/dist/index.js +56 -0
  91. package/dist/index.js.map +1 -0
  92. package/dist/ingest/compute.d.ts +63 -0
  93. package/dist/ingest/compute.d.ts.map +1 -0
  94. package/dist/ingest/compute.js +161 -0
  95. package/dist/ingest/compute.js.map +1 -0
  96. package/dist/ingest/file.d.ts +40 -0
  97. package/dist/ingest/file.d.ts.map +1 -0
  98. package/dist/ingest/file.js +74 -0
  99. package/dist/ingest/file.js.map +1 -0
  100. package/dist/ingest/visual.d.ts +52 -0
  101. package/dist/ingest/visual.d.ts.map +1 -0
  102. package/dist/ingest/visual.js +294 -0
  103. package/dist/ingest/visual.js.map +1 -0
  104. package/dist/parser/docx-parser.d.ts +12 -0
  105. package/dist/parser/docx-parser.d.ts.map +1 -0
  106. package/dist/parser/docx-parser.js +375 -0
  107. package/dist/parser/docx-parser.js.map +1 -0
  108. package/dist/parser/html-parser.d.ts +16 -0
  109. package/dist/parser/html-parser.d.ts.map +1 -0
  110. package/dist/parser/html-parser.js +119 -0
  111. package/dist/parser/html-parser.js.map +1 -0
  112. package/dist/parser/index.d.ts +125 -0
  113. package/dist/parser/index.d.ts.map +1 -0
  114. package/dist/parser/index.js +364 -0
  115. package/dist/parser/index.js.map +1 -0
  116. package/dist/parser/pdf-extract.d.ts +49 -0
  117. package/dist/parser/pdf-extract.d.ts.map +1 -0
  118. package/dist/parser/pdf-extract.js +114 -0
  119. package/dist/parser/pdf-extract.js.map +1 -0
  120. package/dist/parser/pdf-filter.d.ts +91 -0
  121. package/dist/parser/pdf-filter.d.ts.map +1 -0
  122. package/dist/parser/pdf-filter.js +522 -0
  123. package/dist/parser/pdf-filter.js.map +1 -0
  124. package/dist/parser/title-extractor.d.ts +28 -0
  125. package/dist/parser/title-extractor.d.ts.map +1 -0
  126. package/dist/parser/title-extractor.js +105 -0
  127. package/dist/parser/title-extractor.js.map +1 -0
  128. package/dist/pdf-visual/captioner.d.ts +11 -0
  129. package/dist/pdf-visual/captioner.d.ts.map +1 -0
  130. package/dist/pdf-visual/captioner.js +48 -0
  131. package/dist/pdf-visual/captioner.js.map +1 -0
  132. package/dist/pdf-visual/captioners/fast.d.ts +7 -0
  133. package/dist/pdf-visual/captioners/fast.d.ts.map +1 -0
  134. package/dist/pdf-visual/captioners/fast.js +108 -0
  135. package/dist/pdf-visual/captioners/fast.js.map +1 -0
  136. package/dist/pdf-visual/captioners/quality.d.ts +7 -0
  137. package/dist/pdf-visual/captioners/quality.d.ts.map +1 -0
  138. package/dist/pdf-visual/captioners/quality.js +101 -0
  139. package/dist/pdf-visual/captioners/quality.js.map +1 -0
  140. package/dist/pdf-visual/captioners/shared.d.ts +81 -0
  141. package/dist/pdf-visual/captioners/shared.d.ts.map +1 -0
  142. package/dist/pdf-visual/captioners/shared.js +156 -0
  143. package/dist/pdf-visual/captioners/shared.js.map +1 -0
  144. package/dist/pdf-visual/detector.d.ts +9 -0
  145. package/dist/pdf-visual/detector.d.ts.map +1 -0
  146. package/dist/pdf-visual/detector.js +269 -0
  147. package/dist/pdf-visual/detector.js.map +1 -0
  148. package/dist/pdf-visual/index.d.ts +13 -0
  149. package/dist/pdf-visual/index.d.ts.map +1 -0
  150. package/dist/pdf-visual/index.js +53 -0
  151. package/dist/pdf-visual/index.js.map +1 -0
  152. package/dist/pdf-visual/renderer.d.ts +9 -0
  153. package/dist/pdf-visual/renderer.d.ts.map +1 -0
  154. package/dist/pdf-visual/renderer.js +186 -0
  155. package/dist/pdf-visual/renderer.js.map +1 -0
  156. package/dist/pdf-visual/types.d.ts +53 -0
  157. package/dist/pdf-visual/types.d.ts.map +1 -0
  158. package/dist/pdf-visual/types.js +17 -0
  159. package/dist/pdf-visual/types.js.map +1 -0
  160. package/dist/server/error-utils.d.ts +63 -0
  161. package/dist/server/error-utils.d.ts.map +1 -0
  162. package/dist/server/error-utils.js +124 -0
  163. package/dist/server/error-utils.js.map +1 -0
  164. package/dist/server/index.d.ts +216 -0
  165. package/dist/server/index.d.ts.map +1 -0
  166. package/dist/server/index.js +1068 -0
  167. package/dist/server/index.js.map +1 -0
  168. package/dist/server/list-scanner.d.ts +30 -0
  169. package/dist/server/list-scanner.d.ts.map +1 -0
  170. package/dist/server/list-scanner.js +50 -0
  171. package/dist/server/list-scanner.js.map +1 -0
  172. package/dist/server/tool-definitions.d.ts +8 -0
  173. package/dist/server/tool-definitions.d.ts.map +1 -0
  174. package/dist/server/tool-definitions.js +181 -0
  175. package/dist/server/tool-definitions.js.map +1 -0
  176. package/dist/server/tool-input.d.ts +37 -0
  177. package/dist/server/tool-input.d.ts.map +1 -0
  178. package/dist/server/tool-input.js +211 -0
  179. package/dist/server/tool-input.js.map +1 -0
  180. package/dist/server/types.d.ts +307 -0
  181. package/dist/server/types.d.ts.map +1 -0
  182. package/dist/server/types.js +3 -0
  183. package/dist/server/types.js.map +1 -0
  184. package/dist/server-main.d.ts +40 -0
  185. package/dist/server-main.d.ts.map +1 -0
  186. package/dist/server-main.js +254 -0
  187. package/dist/server-main.js.map +1 -0
  188. package/dist/utils/base-dirs.d.ts +145 -0
  189. package/dist/utils/base-dirs.d.ts.map +1 -0
  190. package/dist/utils/base-dirs.js +344 -0
  191. package/dist/utils/base-dirs.js.map +1 -0
  192. package/dist/utils/errors.d.ts +32 -0
  193. package/dist/utils/errors.d.ts.map +1 -0
  194. package/dist/utils/errors.js +61 -0
  195. package/dist/utils/errors.js.map +1 -0
  196. package/dist/utils/limits.d.ts +26 -0
  197. package/dist/utils/limits.d.ts.map +1 -0
  198. package/dist/utils/limits.js +28 -0
  199. package/dist/utils/limits.js.map +1 -0
  200. package/dist/utils/list-sources.d.ts +38 -0
  201. package/dist/utils/list-sources.d.ts.map +1 -0
  202. package/dist/utils/list-sources.js +40 -0
  203. package/dist/utils/list-sources.js.map +1 -0
  204. package/dist/utils/raw-data-utils.d.ts +76 -0
  205. package/dist/utils/raw-data-utils.d.ts.map +1 -0
  206. package/dist/utils/raw-data-utils.js +202 -0
  207. package/dist/utils/raw-data-utils.js.map +1 -0
  208. package/dist/utils/scan.d.ts +114 -0
  209. package/dist/utils/scan.d.ts.map +1 -0
  210. package/dist/utils/scan.js +209 -0
  211. package/dist/utils/scan.js.map +1 -0
  212. package/dist/utils/scope-match.d.ts +38 -0
  213. package/dist/utils/scope-match.d.ts.map +1 -0
  214. package/dist/utils/scope-match.js +86 -0
  215. package/dist/utils/scope-match.js.map +1 -0
  216. package/dist/utils/sensitive-path.d.ts +9 -0
  217. package/dist/utils/sensitive-path.d.ts.map +1 -0
  218. package/dist/utils/sensitive-path.js +78 -0
  219. package/dist/utils/sensitive-path.js.map +1 -0
  220. package/dist/utils/sync-path-key.d.ts +14 -0
  221. package/dist/utils/sync-path-key.d.ts.map +1 -0
  222. package/dist/utils/sync-path-key.js +27 -0
  223. package/dist/utils/sync-path-key.js.map +1 -0
  224. package/dist/utils/type-guards.d.ts +18 -0
  225. package/dist/utils/type-guards.d.ts.map +1 -0
  226. package/dist/utils/type-guards.js +34 -0
  227. package/dist/utils/type-guards.js.map +1 -0
  228. package/dist/utils/visual-profile.d.ts +10 -0
  229. package/dist/utils/visual-profile.d.ts.map +1 -0
  230. package/dist/utils/visual-profile.js +15 -0
  231. package/dist/utils/visual-profile.js.map +1 -0
  232. package/dist/vectordb/index.d.ts +132 -0
  233. package/dist/vectordb/index.d.ts.map +1 -0
  234. package/dist/vectordb/index.js +617 -0
  235. package/dist/vectordb/index.js.map +1 -0
  236. package/dist/vectordb/search-filters.d.ts +15 -0
  237. package/dist/vectordb/search-filters.d.ts.map +1 -0
  238. package/dist/vectordb/search-filters.js +129 -0
  239. package/dist/vectordb/search-filters.js.map +1 -0
  240. package/dist/vectordb/types.d.ts +194 -0
  241. package/dist/vectordb/types.d.ts.map +1 -0
  242. package/dist/vectordb/types.js +237 -0
  243. package/dist/vectordb/types.js.map +1 -0
  244. package/package.json +108 -0
  245. package/skills/mcp-local-rag/SKILL.md +234 -0
  246. package/skills/mcp-local-rag/references/cli-reference.md +190 -0
  247. package/skills/mcp-local-rag/references/html-ingestion.md +78 -0
@@ -0,0 +1,271 @@
1
+ // CLI sync subcommand — foreground incremental reconciliation.
2
+ //
3
+ // Composition root for `src/features/sync.ts`: supplies the real collaborators
4
+ // and renders the result. Planning, prune eligibility, execution order and the
5
+ // stop-on-first-error policy all live in the core, including the
6
+ // "inside a configured root" check.
7
+ //
8
+ // The run stays attached to the process: backgrounding and polling belong to
9
+ // the caller, so there is no daemon or watchdog here.
10
+ import { readFile, stat } from 'node:fs/promises';
11
+ import { resolve, sep } from 'node:path';
12
+ import { SemanticChunker } from '../chunker/index.js';
13
+ import { formatSyncError, runSync as runSyncCore, } from '../features/sync.js';
14
+ import { computeContentHash } from '../ingest/compute.js';
15
+ import { DocumentParser } from '../parser/index.js';
16
+ import { MAX_SCAN_DEPTH } from '../utils/limits.js';
17
+ import { bfsCollectSupportedFiles, canonicalizeRequestedPath, classifyRequestedPath, } from '../utils/scan.js';
18
+ import { createEmbedder, createVectorStore, formatCliError } from './common.js';
19
+ import { buildFileIngestOptions, ingestSingleFile, resolveConfig } from './ingest.js';
20
+ import { consumeBaseDirArg, requireVisualQuality, resolveGlobalConfig } from './options.js';
21
+ // ============================================
22
+ // Help
23
+ // ============================================
24
+ const HELP_TEXT = `Usage: mcp-local-rag [global-options] sync [options] [path]
25
+
26
+ Reconcile the index with the files on disk: ingest new and changed files, leave
27
+ unchanged files alone, and remove index entries for files that are gone.
28
+
29
+ Each changed PDF keeps the visual profile it was last indexed with; a new PDF,
30
+ or one indexed before profiles were recorded, stays text-only. Use --visual to
31
+ request VLM captioning for every PDF in scope instead, which also establishes a
32
+ profile for those PDFs. A PDF is re-ingested when its bytes or its profile
33
+ differ from what is indexed, and skipped otherwise. To turn visual mode off
34
+ for a path, run "ingest <path>": a successful normal ingest clears the recorded
35
+ profile. To retry a failed caption, run "ingest <path> --visual
36
+ --visual-quality <profile>" with the profile you want, because a plain ingest
37
+ clears it. Image storage is separate: --images is never recorded and never
38
+ makes a file changed.
39
+
40
+ Runs in the foreground until it finishes. Use your shell to run it in the
41
+ background.
42
+
43
+ Arguments:
44
+ <path> File or directory inside a configured base directory
45
+ (default: every configured base directory)
46
+
47
+ Options:
48
+ --base-dir <path> Document root (repeatable; overrides environment roots)
49
+ --images Store images for new/changed PDF and DOCX files
50
+ --visual Request VLM captioning for every PDF in scope, overriding
51
+ each PDF's recorded profile (PDFs only)
52
+ --visual-quality <profile>
53
+ VLM profile when --visual is set: fast (default,
54
+ lightweight) or quality (Qwen2.5-VL-3B, ~10x cache,
55
+ ~2x inference)
56
+ -h, --help Show this help
57
+
58
+ Without --base-dir, roots come from BASE_DIRS / BASE_DIR (default: current directory).
59
+
60
+ Global options (must appear before "sync"):
61
+ --db-path <path> LanceDB database path
62
+ --cache-dir <path> Model cache directory
63
+ --model-name <name> Embedding model`;
64
+ /**
65
+ * Parse sync-specific CLI arguments: repeatable roots, at most one positional
66
+ * path, and -h/--help. Unknown flags still print the usage and exit 1.
67
+ */
68
+ function parseArgs(args) {
69
+ let help = false;
70
+ const baseDirs = [];
71
+ let path;
72
+ let images = false;
73
+ let visual = false;
74
+ let visualQuality;
75
+ let index = 0;
76
+ while (index < args.length) {
77
+ const arg = args[index] ?? '';
78
+ switch (arg) {
79
+ case '-h':
80
+ case '--help':
81
+ help = true;
82
+ index++;
83
+ break;
84
+ case '--base-dir': {
85
+ const valueIndex = consumeBaseDirArg(args, index, baseDirs);
86
+ index = valueIndex + 1;
87
+ break;
88
+ }
89
+ case '--images':
90
+ images = true;
91
+ index++;
92
+ break;
93
+ case '--visual':
94
+ visual = true;
95
+ index++;
96
+ break;
97
+ case '--visual-quality':
98
+ visualQuality = requireVisualQuality(args, index);
99
+ index += 2;
100
+ break;
101
+ default:
102
+ if (arg.startsWith('-')) {
103
+ console.error(`Unknown option: ${arg}`);
104
+ console.error(HELP_TEXT);
105
+ process.exit(1);
106
+ }
107
+ if (path !== undefined) {
108
+ console.error(`Unexpected argument: ${arg}`);
109
+ console.error('Only one path is accepted. Omit it to sync every configured base directory.');
110
+ process.exit(1);
111
+ }
112
+ path = arg;
113
+ index++;
114
+ break;
115
+ }
116
+ }
117
+ const parsed = { help, baseDirs, images, visual };
118
+ if (path !== undefined) {
119
+ parsed.path = path;
120
+ }
121
+ if (visualQuality !== undefined) {
122
+ parsed.visualQuality = visualQuality;
123
+ }
124
+ return parsed;
125
+ }
126
+ // ============================================
127
+ // Reporting
128
+ // ============================================
129
+ /**
130
+ * Render the scanner's coverage facts as operator warnings. Each unobserved
131
+ * region is why prune was withheld there, so the path is named; the wording
132
+ * itself is not a contract.
133
+ */
134
+ function coverageWarnings(coverage, maxFileSize) {
135
+ return [
136
+ ...coverage.unreadableDirs.map(({ dirPath, code }) => `Warning: cannot read directory (${code}), so its indexed files were kept: ${dirPath}`),
137
+ ...coverage.depthLimitedDirs.map((dirPath) => `Warning: not scanned because it exceeds the maximum depth (${MAX_SCAN_DEPTH}), so its indexed files were kept: ${dirPath}`),
138
+ ...coverage.skippedSymlinks.map((linkPath) => `Warning: symbolic link not followed, so its indexed files were kept: ${linkPath}`),
139
+ ...coverage.oversizedFiles.map((filePath) => `Warning: not read because it exceeds the maximum file size (${maxFileSize} bytes), so its indexed chunks were kept: ${filePath}`),
140
+ ];
141
+ }
142
+ // ============================================
143
+ // Main Entry Point
144
+ // ============================================
145
+ /**
146
+ * Run the sync CLI subcommand.
147
+ */
148
+ export async function runSync(args, globalOptions = {}) {
149
+ const parsed = parseArgs(args);
150
+ if (parsed.help) {
151
+ console.error(HELP_TEXT);
152
+ process.exit(0);
153
+ }
154
+ const globalConfig = resolveGlobalConfig(globalOptions);
155
+ // Shared with `ingest`: CLI roots replace BASE_DIRS / BASE_DIR / cwd; an empty
156
+ // array preserves that environment fallback. Size/chunk settings share the
157
+ // same resolution and validation path.
158
+ const config = await resolveConfig(globalConfig, { baseDirs: parsed.baseDirs });
159
+ for (const warning of config.baseDirsWarnings) {
160
+ console.error(warning.message);
161
+ }
162
+ const excludePaths = [`${resolve(config.dbPath)}${sep}`, `${resolve(config.cacheDir)}${sep}`];
163
+ const vectorStore = createVectorStore(globalConfig);
164
+ // The parser's realpath check is the security boundary, so it takes the
165
+ // realpath'd roots; scanning uses the resolve()-only `rawBaseDirs` so scanned
166
+ // paths match the resolve()-stored DB keys (same split as `list`).
167
+ const parser = new DocumentParser({
168
+ baseDirs: config.baseDirs.baseDirs,
169
+ maxFileSize: config.maxFileSize,
170
+ });
171
+ const chunker = new SemanticChunker(config.chunkMinLength !== undefined ? { minChunkLength: config.chunkMinLength } : {});
172
+ // Built on the first upsert only: a run with nothing to ingest must not pay
173
+ // for the embedding model.
174
+ let embedder;
175
+ const ensureEmbedder = () => {
176
+ embedder ??= createEmbedder(globalConfig);
177
+ return embedder;
178
+ };
179
+ const collaborators = {
180
+ // The containment boundary for a requested path: the core compares this
181
+ // canonical form against the realpath'd roots, which is the only way to see
182
+ // that an intermediate component is a symbolic link out of the root.
183
+ canonicalizeRequestedPath,
184
+ // The walker's own predicates, so an explicitly requested path is subject to
185
+ // the same rules as a discovered one and is refused before it is read.
186
+ classifyPath: async (path) => await classifyRequestedPath(path, excludePaths),
187
+ // No `scope` argument, on purpose: a scope-pruned directory appears in none
188
+ // of the coverage arrays, which would hide an unobserved region and make
189
+ // prune unsafe.
190
+ scanDir: async (rootPath) => await bfsCollectSupportedFiles(rootPath, excludePaths, { maxDepth: MAX_SCAN_DEPTH }),
191
+ // Size first, bytes second: `MAX_FILE_SIZE` is otherwise enforced inside
192
+ // the parser, long after the whole file is already in memory here.
193
+ // Declining (`null`) keeps the rest of the run usable rather than aborting
194
+ // every future sync of the root over one oversized file.
195
+ //
196
+ // The bound holds only against a non-racing filesystem: a writer that grows
197
+ // the file between the `stat` and the `readFile` restores the unbounded
198
+ // read. That actor already has local write access as this user and can
199
+ // reach the database directly, so this is a recorded limitation.
200
+ hashFile: async (filePath) => {
201
+ if ((await stat(filePath)).size > config.maxFileSize) {
202
+ return null;
203
+ }
204
+ return computeContentHash(await readFile(filePath));
205
+ },
206
+ loadDbManifest: async () => await vectorStore.listSyncManifest(),
207
+ // Named as it happens, so a long run shows which file it is on and the
208
+ // counters alone are not the only record of what changed. A zero-chunk file
209
+ // already reports itself from inside `ingestSingleFile`.
210
+ ingestFile: async (filePath, options) => {
211
+ const chunkCount = await ingestSingleFile(filePath, { parser, chunker, embedder: ensureEmbedder(), vectorStore }, buildFileIngestOptions(options, globalConfig));
212
+ if (chunkCount > 0) {
213
+ console.error(`upserted ${filePath} (${chunkCount} chunks)`);
214
+ }
215
+ return chunkCount;
216
+ },
217
+ deleteExactPath: async (filePath) => await vectorStore.deleteChunks(filePath),
218
+ optimize: async () => {
219
+ await vectorStore.optimize();
220
+ },
221
+ };
222
+ try {
223
+ await vectorStore.initialize();
224
+ const result = await runSyncCore({
225
+ roots: config.baseDirs.rawBaseDirs,
226
+ // The realpath'd counterpart of the same roots, which is what the core
227
+ // decides requested-path containment in (the parser's boundary domain).
228
+ canonicalRoots: config.baseDirs.baseDirs,
229
+ dbPath: config.dbPath,
230
+ excludePaths,
231
+ platform: process.platform,
232
+ // resolve() (never realpath) so the requested path is spelled like the
233
+ // stored DB keys; the core validates it against the configured roots.
234
+ ...(parsed.path === undefined ? {} : { requestedPath: resolve(parsed.path) }),
235
+ ...(parsed.images ? { images: true } : {}),
236
+ // Only `--visual` makes the request explicit. Without it the core lets
237
+ // each PDF inherit its recorded profile, so a bare `--visual-quality` is
238
+ // parsed (and validated) but has no effect.
239
+ ...(parsed.visual ? { visualProfile: parsed.visualQuality ?? 'fast' } : {}),
240
+ collaborators,
241
+ });
242
+ for (const prunedPath of result.prunedPaths) {
243
+ console.error(`pruned ${prunedPath}`);
244
+ }
245
+ for (const warning of coverageWarnings(result.coverage, config.maxFileSize)) {
246
+ console.error(warning);
247
+ }
248
+ if (result.error !== null) {
249
+ console.error(`Error: ${formatSyncError(result.error)}`);
250
+ process.exitCode = 1;
251
+ return;
252
+ }
253
+ process.stdout.write(JSON.stringify({
254
+ upserted: result.upserted,
255
+ skipped: result.skipped,
256
+ empty: result.empty,
257
+ pruned: result.pruned,
258
+ }));
259
+ }
260
+ catch (error) {
261
+ console.error(`Error: ${formatCliError(error)}`);
262
+ process.exitCode = 1;
263
+ }
264
+ finally {
265
+ if (embedder !== undefined) {
266
+ await embedder.dispose();
267
+ }
268
+ await vectorStore.close();
269
+ }
270
+ }
271
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/cli/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { GlobalOptions } from './cli/options.js';
2
+ export declare const SUBCOMMANDS: readonly ['skills', 'ingest', 'list', 'query', 'status', 'delete', 'read-neighbors', 'sync'];
3
+ export type Subcommand = (typeof SUBCOMMANDS)[number];
4
+ /**
5
+ * Handle CLI subcommands. The caller is expected to have already validated
6
+ * `subcommand` against `SUBCOMMANDS`; the union type makes the switch exhaustive.
7
+ */
8
+ export declare function handleCli(subcommand: Subcommand, args: string[], globalOptions?: GlobalOptions): Promise<void>;
9
+ //# sourceMappingURL=cli-main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-main.d.ts","sourceRoot":"","sources":["../src/cli-main.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAMrD,eAAO,MAAM,WAAW,YACtB,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,MAAM,CACE,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAErD;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EAAE,EACd,aAAa,GAAE,aAAkB,GAChC,OAAO,CAAC,IAAI,CAAC,CA2Cf"}
@@ -0,0 +1,60 @@
1
+ // CLI entry point for subcommands (skills install, etc.)
2
+ import { run as runSkillsInstall } from './bin/install-skills.js';
3
+ import { runDelete } from './cli/delete.js';
4
+ import { runIngest } from './cli/ingest.js';
5
+ import { runList } from './cli/list.js';
6
+ import { runQuery } from './cli/query.js';
7
+ import { runReadNeighbors } from './cli/read-neighbors.js';
8
+ import { runStatus } from './cli/status.js';
9
+ import { runSync } from './cli/sync.js';
10
+ export const SUBCOMMANDS = [
11
+ 'skills',
12
+ 'ingest',
13
+ 'list',
14
+ 'query',
15
+ 'status',
16
+ 'delete',
17
+ 'read-neighbors',
18
+ 'sync',
19
+ ];
20
+ /**
21
+ * Handle CLI subcommands. The caller is expected to have already validated
22
+ * `subcommand` against `SUBCOMMANDS`; the union type makes the switch exhaustive.
23
+ */
24
+ export async function handleCli(subcommand, args, globalOptions = {}) {
25
+ switch (subcommand) {
26
+ case 'skills':
27
+ if (args[0] === 'install') {
28
+ runSkillsInstall(args.slice(1));
29
+ process.exit(0);
30
+ }
31
+ else {
32
+ console.error('Unknown skills subcommand. Usage: npx mcp-local-rag skills install [options]');
33
+ console.error('Run "npx mcp-local-rag skills install --help" for more information.');
34
+ process.exit(1);
35
+ }
36
+ break;
37
+ case 'ingest':
38
+ await runIngest(args, globalOptions);
39
+ break;
40
+ case 'list':
41
+ await runList(args, globalOptions);
42
+ break;
43
+ case 'query':
44
+ await runQuery(args, globalOptions);
45
+ break;
46
+ case 'status':
47
+ await runStatus(args, globalOptions);
48
+ break;
49
+ case 'delete':
50
+ await runDelete(args, globalOptions);
51
+ break;
52
+ case 'read-neighbors':
53
+ await runReadNeighbors(args, globalOptions);
54
+ break;
55
+ case 'sync':
56
+ await runSync(args, globalOptions);
57
+ break;
58
+ }
59
+ }
60
+ //# sourceMappingURL=cli-main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-main.js","sourceRoot":"","sources":["../src/cli-main.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,OAAO,EAAE,GAAG,IAAI,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,gBAAgB;IAChB,MAAM;CACE,CAAA;AAIV;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,UAAsB,EACtB,IAAc,EACd,aAAa,GAAkB,EAAE;IAEjC,QAAQ,UAAU,EAAE,CAAC;QACnB,KAAK,QAAQ;YACX,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC1B,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;gBAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CACX,8EAA8E,CAC/E,CAAA;gBACD,OAAO,CAAC,KAAK,CAAC,qEAAqE,CAAC,CAAA;gBACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;YACD,MAAK;QAEP,KAAK,QAAQ;YACX,MAAM,SAAS,CAAC,IAAI,EAAE,aAAa,CAAC,CAAA;YACpC,MAAK;QAEP,KAAK,MAAM;YACT,MAAM,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC,CAAA;YAClC,MAAK;QAEP,KAAK,OAAO;YACV,MAAM,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,CAAA;YACnC,MAAK;QAEP,KAAK,QAAQ;YACX,MAAM,SAAS,CAAC,IAAI,EAAE,aAAa,CAAC,CAAA;YACpC,MAAK;QAEP,KAAK,QAAQ;YACX,MAAM,SAAS,CAAC,IAAI,EAAE,aAAa,CAAC,CAAA;YACpC,MAAK;QAEP,KAAK,gBAAgB;YACnB,MAAM,gBAAgB,CAAC,IAAI,EAAE,aAAa,CAAC,CAAA;YAC3C,MAAK;QAEP,KAAK,MAAM;YACT,MAAM,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC,CAAA;YAClC,MAAK;IACT,CAAC;AACH,CAAC"}
@@ -0,0 +1,143 @@
1
+ import { AppError } from '../utils/errors.js';
2
+ /**
3
+ * Embedder configuration
4
+ */
5
+ export interface EmbedderConfig {
6
+ /** HuggingFace model path */
7
+ modelPath: string;
8
+ /** Batch size */
9
+ batchSize: number;
10
+ /** Model cache directory */
11
+ cacheDir: string;
12
+ /** Device type */
13
+ device?: string;
14
+ /**
15
+ * Quantization dtype, passed through to transformers.js with no allowlist.
16
+ * `undefined` means unset, which `initialize()` resolves to fp32 — the
17
+ * distinction gates failure-path error enrichment, so keep it.
18
+ */
19
+ dtype?: string;
20
+ }
21
+ interface TokenizerOptions {
22
+ padding?: boolean;
23
+ truncation?: boolean;
24
+ return_tensor?: boolean;
25
+ max_length?: number;
26
+ }
27
+ export interface PipelineTokenizer {
28
+ (input: string[], options: TokenizerOptions): {
29
+ input_ids?: unknown;
30
+ } | null | undefined;
31
+ /** `unknown` because a model may omit it or report a sentinel; see {@link usableTokenLimit}. */
32
+ model_max_length?: unknown;
33
+ }
34
+ export interface TokenLimitClamp {
35
+ /** The effective token cap, or `null` for degraded mode (no cap, no clamp). */
36
+ tokenLimit: number | null;
37
+ /** The pre-clamp tokenizer, for measuring true lengths. */
38
+ measurementTokenizer: PipelineTokenizer | null;
39
+ }
40
+ /**
41
+ * Bound the pipeline's tokenization length to the model's position window, by
42
+ * installing a proxy on `candidate`'s tokenizer.
43
+ *
44
+ * The pipeline tokenizes with no `max_length`, which resolves to
45
+ * `model_max_length ?? Infinity` and then to the batch's longest sequence, so a
46
+ * model whose `tokenizer_config.json` omits a real limit sends more positions
47
+ * than it has position embeddings and onnxruntime fails in the
48
+ * position-embedding `Add` node (#202).
49
+ *
50
+ * The measurement tokenizer is captured before the proxy, so measurement
51
+ * reports true lengths. A `Proxy` is used because `model_max_length` is a getter
52
+ * with no setter. An unrecognized shape, or no usable limit, leaves `candidate`
53
+ * untouched.
54
+ */
55
+ export declare function installTokenLimitClamp(candidate: unknown): TokenLimitClamp;
56
+ /**
57
+ * Embedding generation error
58
+ */
59
+ export declare class EmbeddingError extends AppError {
60
+ constructor(message: string, options?: {
61
+ cause?: Error;
62
+ });
63
+ }
64
+ /** Transformers.js wrapper: lazily loaded model, batched embedding. */
65
+ export declare class Embedder {
66
+ private model;
67
+ private initPromise;
68
+ /** The resolved cap, or `null` before initialization and in degraded mode. */
69
+ private tokenLimit;
70
+ /** The pre-clamp tokenizer, so measurement never reports clamped lengths. */
71
+ private measurementTokenizer;
72
+ /**
73
+ * One-shot flags, per instance: each state belongs to this embedder's model.
74
+ * They survive `dispose()`; re-initialization is not new information.
75
+ */
76
+ private truncationWarned;
77
+ private degradedModeWarned;
78
+ private readonly config;
79
+ constructor(config: EmbedderConfig);
80
+ /**
81
+ * Release resources held by the Embedder pipeline
82
+ */
83
+ dispose(): Promise<void>;
84
+ /**
85
+ * Initialize Transformers.js model
86
+ */
87
+ initialize(): Promise<void>;
88
+ /**
89
+ * Best-effort failure-path enrichment for an explicit `RAG_DTYPE`: name the
90
+ * dtypes the model does provide when the requested one is absent.
91
+ *
92
+ * The enumeration is a Hub network call in its own try/catch, so an
93
+ * air-gapped run degrades to a generic dtype-aware message instead of
94
+ * surfacing a confusing secondary error. Never throws, and never converts
95
+ * the load failure into a fallback — the caller always re-throws.
96
+ */
97
+ private enrichDtypeFailureMessage;
98
+ /**
99
+ * Ensure model is initialized (lazy initialization)
100
+ * This method is called automatically by embed() and embedBatch()
101
+ */
102
+ private ensureInitialized;
103
+ /**
104
+ * The effective token cap, or `null` when none could be resolved.
105
+ *
106
+ * Self-initializing: the value exists only after the model loads, and a
107
+ * caller may need it before the first embedding.
108
+ */
109
+ getTokenLimit(): Promise<number | null>;
110
+ /**
111
+ * Report once that no cap was resolved. Warning here rather than in
112
+ * `initialize()` covers every consumer, which all read the cap through
113
+ * {@link getTokenLimit}.
114
+ */
115
+ private warnDegradedMode;
116
+ /**
117
+ * The lengths batch planning runs on: `min(trueLength, cap)`, the length the
118
+ * clamped pipeline actually feeds the model. Warns once when a true length
119
+ * exceeds the cap.
120
+ */
121
+ private planTokenLengths;
122
+ /**
123
+ * The true token length of each text, in input order. Tokenization only, no
124
+ * inference.
125
+ *
126
+ * Measured with `truncation: false` through the pre-clamp tokenizer, so a
127
+ * length above {@link getTokenLimit} means inference will truncate. Throws
128
+ * when no such tokenizer was captured, rather than returning a length
129
+ * measured through an unknown surface.
130
+ */
131
+ countTokens(texts: string[]): Promise<number[]>;
132
+ /**
133
+ * Single-text embedding; the vector dimension depends on the model.
134
+ *
135
+ * Delegates to {@link embedBatch} so this path shares its clamp, measurement
136
+ * and warning rather than reaching the pipeline unguarded.
137
+ */
138
+ embed(text: string): Promise<number[]>;
139
+ /** Batched embedding; the vector dimension depends on the model. */
140
+ embedBatch(texts: string[]): Promise<number[][]>;
141
+ }
142
+ export {};
143
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/embedder/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,QAAQ,EAAW,MAAM,oBAAoB,CAAA;AAOtD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,kBAAkB;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAQD,UAAU,gBAAgB;IACxB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,gBAAgB,GAAG;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,GAAG,SAAS,CAAA;IACxF,gGAAgG;IAChG,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AA6CD,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,2DAA2D;IAC3D,oBAAoB,EAAE,iBAAiB,GAAG,IAAI,CAAA;CAC/C;AA4BD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,OAAO,GAAG,eAAe,CAyB1E;AAkED;;GAEG;AACH,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,EAGvD;CACF;AAMD,uEAAuE;AACvE,qBAAa,QAAQ;IAEnB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,WAAW,CAA6B;IAChD,8EAA8E;IAC9E,OAAO,CAAC,UAAU,CAAsB;IACxC,6EAA6E;IAC7E,OAAO,CAAC,oBAAoB,CAAiC;IAC7D;;;OAGG;IACH,OAAO,CAAC,gBAAgB,CAAiB;IACzC,OAAO,CAAC,kBAAkB,CAAiB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IAEvC,YAAY,MAAM,EAAE,cAAc,EAEjC;IAED;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAc7B;IAED;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAyChC;IAED;;;;;;;;OAQG;YACW,yBAAyB;IAqBvC;;;OAGG;YACW,iBAAiB;IAyB/B;;;;;OAKG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAM5C;IAED;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;;;OAIG;YACW,gBAAgB;IAoB9B;;;;;;;;OAQG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAkBpD;IAED;;;;;OAKG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAO3C;IAED,oEAAoE;IAC9D,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAyFrD;CACF"}