@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,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,2 @@
1
+ export declare function collectFiles(targetPath: string, baseDirs: readonly string[], excludePaths: string[]): Promise<string[]>;
2
+ //# sourceMappingURL=file-collection.d.ts.map
@@ -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":"AAAA,4EAA4E;AAE5E,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACvC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAGrD,OAAO,EACL,6BAA6B,EAE7B,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEnD,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAGhF,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,wBAAwB,GACzB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEnD,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,YAAY,GACb,MAAM,cAAc,CAAA;AAuCrB,+CAA+C;AAC/C,WAAW;AACX,+CAA+C;AAE/C,MAAM,eAAe,GAAG;IACtB,WAAW,EAAE,qBAAqB;CAC1B,CAAA;AAEV,+CAA+C;AAC/C,OAAO;AACP,+CAA+C;AAE/C,MAAM,SAAS,GAAG;;;;;;gEAM8C,eAAe,CAAC,WAAW;kGACO,oBAAoB;;;;;;;;;2CAS3E,CAAA;AAE3C,+CAA+C;AAC/C,cAAc;AACd,+CAA+C;AAE/C,iFAAiF;AACjF,mEAAmE;AACnE,SAAS,gBAAgB,CAAC,IAAc,EAAE,SAAiB,EAAE,IAAY;IACvE,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,CAAA;IACnD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,qBAAqB,IAAI,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAA;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;AACjC,CAAC;AAED,2DAA2D;AAC3D,SAAS,wBAAwB,CAAC,GAAW,EAAE,UAA8B;IAC3E,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAA;QACvC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAA;QAC5C,OAAO,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAA;QACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,OAAO,GAAqB,EAAE,CAAA;IACpC,IAAI,UAA8B,CAAA;IAClC,IAAI,IAAI,GAAG,KAAK,CAAA;IAEhB,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QACzB,QAAQ,GAAG,EAAE,CAAC;YACZ,KAAK,IAAI,CAAC;YACV,KAAK,QAAQ;gBACX,IAAI,GAAG,IAAI,CAAA;gBACX,CAAC,EAAE,CAAA;gBACH,MAAK;YACP,KAAK,YAAY,EAAE,CAAC;gBAClB,oEAAoE;gBACpE,kEAAkE;gBAClE,iEAAiE;gBACjE,sDAAsD;gBACtD,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;oBACnC,OAAO,CAAC,QAAQ,GAAG,EAAE,CAAA;gBACvB,CAAC;gBACD,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;gBAC/D,CAAC,GAAG,UAAU,GAAG,CAAC,CAAA;gBAClB,MAAK;YACP,CAAC;YACD,KAAK,iBAAiB;gBACpB,OAAO,CAAC,WAAW,GAAG,gBAAgB,CAAC,IAAI,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAA;gBAClE,CAAC,IAAI,CAAC,CAAA;gBACN,MAAK;YACP,KAAK,oBAAoB;gBACvB,OAAO,CAAC,cAAc,GAAG,gBAAgB,CAAC,IAAI,EAAE,CAAC,EAAE,oBAAoB,CAAC,CAAA;gBACxE,CAAC,IAAI,CAAC,CAAA;gBACN,MAAK;YACP,KAAK,UAAU;gBACb,oEAAoE;gBACpE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAA;gBACrB,CAAC,EAAE,CAAA;gBACH,MAAK;YACP,KAAK,UAAU;gBACb,OAAO,CAAC,MAAM,GAAG,IAAI,CAAA;gBACrB,CAAC,EAAE,CAAA;gBACH,MAAK;YACP,KAAK,kBAAkB;gBACrB,OAAO,CAAC,aAAa,GAAG,oBAAoB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;gBACrD,CAAC,IAAI,CAAC,CAAA;gBACN,MAAK;YACP;gBACE,wBAAwB,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;gBACzC,UAAU,GAAG,GAAG,CAAA;gBAChB,CAAC,EAAE,CAAA;gBACH,MAAK;QACT,CAAC;IACH,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AACtC,CAAC;AAED,+CAA+C;AAC/C,oBAAoB;AACpB,+CAA+C;AAE/C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,YAAkC,EAClC,aAAa,GAAqB,EAAE;IAEpC,MAAM,WAAW,GAAG,aAAa,CAAC,QAAQ,IAAI,EAAE,CAAA;IAEhD,uEAAuE;IACvE,oEAAoE;IACpE,0EAA0E;IAC1E,sEAAsE;IACtE,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;QACrD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;YAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GACpD,MAAM,wBAAwB,CAAC,WAAW,CAAC,CAAA;IAE7C,MAAM,WAAW,GACf,aAAa,CAAC,WAAW;QACzB,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;YAC3B,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC;YACnD,CAAC,CAAC,eAAe,CAAC,WAAW,CAAC,CAAA;IAClC,MAAM,cAAc,GAClB,aAAa,CAAC,cAAc;QAC5B,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;YAC9B,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,EAAE,CAAC;YACtD,CAAC,CAAC,SAAS,CAAC,CAAA;IAEhB,6BAA6B;IAC7B,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAA;IACzD,IAAI,gBAAgB,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAA;QAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,8CAA8C;IAC9C,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,mBAAmB,GAAG,sBAAsB,CAAC,cAAc,CAAC,CAAA;QAClE,IAAI,mBAAmB,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAA;YAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAiB;QAC7B,MAAM,EAAE,YAAY,CAAC,MAAM;QAC3B,QAAQ,EAAE,YAAY,CAAC,QAAQ;QAC/B,SAAS,EAAE,YAAY,CAAC,SAAS;QACjC,QAAQ;QACR,gBAAgB;QAChB,WAAW;KACZ,CAAA;IACD,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;QACjC,QAAQ,CAAC,cAAc,GAAG,cAAc,CAAA;IAC1C,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAcD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,QAAgB,EAChB,aAA4C,EAC5C,OAAO,GAAgC,EAAE,MAAM,EAAE,KAAK,EAAE;IAExD,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,aAAa,CAAA;IAChE,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACrD,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAA;IAC7F,IAAI,QAAQ,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC;QACnC,OAAO,CAAC,KAAK,CACX,sBAAsB,QAAQ,CAAC,iBAAiB,6BAA6B,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,WAAW,CAC/G,CAAA;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAA;QAC/E,OAAO,CAAC,CAAA;IACV,CAAC;IAED,MAAM,YAAY,GAAG,6BAA6B,CAAC,QAAQ,CAAC,CAAA;IAE5D,iEAAiE;IACjE,MAAM,WAAW,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;IACxC,MAAM,WAAW,CAAC,YAAY,CAAC,YAAY,CAAC,CAAA;IAE5C,OAAO,YAAY,CAAC,MAAM,CAAA;AAC5B,CAAC;AAED,+CAA+C;AAC/C,mBAAmB;AACnB,+CAA+C;AAE/C;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CACpC,OAAkE,EAClE,YAAkC;IAElC,IAAI,OAAO,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;QACnC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAA;IACnC,CAAC;IACD,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,SAAS,EAAE;YACT,OAAO,EAAE,OAAO,CAAC,aAAa;YAC9B,QAAQ,EAAE,YAAY,CAAC,QAAQ;YAC/B,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;SACjD;KACF,CAAA;AACH,CAAC;AAED,uEAAuE;AACvE,KAAK,UAAU,mBAAmB,CAAC,UAA8B;IAC/D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAA;QAC7D,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAA;QACjF,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAA;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,UAAU,CAAC,CAAA;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,+BAA+B,UAAU,EAAE,CAAC,CAAA;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAc,EAAE,aAAa,GAAkB,EAAE;IAC/E,oBAAoB;IACpB,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAErD,gBAAgB;IAChB,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,mBAAmB,CAAC,UAAU,CAAC,CAAA;IAExD,kDAAkD;IAClD,MAAM,YAAY,GAAG,mBAAmB,CAAC,aAAa,CAAC,CAAA;IACvD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;IACzD,MAAM,YAAY,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,EAAE,CAAC,CAAA;IAE7F,wEAAwE;IACxE,6BAA6B;IAC7B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC9C,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAChC,CAAC;IAED,2EAA2E;IAC3E,oEAAoE;IACpE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAA;IACpF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAA;QAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,SAAS,KAAK,CAAC,MAAM,qBAAqB,CAAC,CAAA;IAEzD,oEAAoE;IACpE,0EAA0E;IAC1E,+EAA+E;IAC/E,uBAAuB;IACvB,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC;QAChC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ;QAClC,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC,CAAA;IACF,MAAM,OAAO,GAAG,IAAI,eAAe,CACjC,MAAM,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CACrF,CAAA;IACD,MAAM,QAAQ,GAAG,cAAc,CAAC,YAAY,CAAC,CAAA;IAC7C,MAAM,WAAW,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAA;IACnD,MAAM,WAAW,CAAC,UAAU,EAAE,CAAA;IAE9B,oBAAoB;IACpB,MAAM,OAAO,GAAkB,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAA;IAE1E,IAAI,CAAC;QACH,KAAK,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAA;YAE1C,IAAI,CAAC;gBACH,MAAM,UAAU,GAAG,MAAM,gBAAgB,CACvC,QAAQ,EACR,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,EAC1C,sBAAsB,CACpB;oBACE,MAAM,EAAE,OAAO,CAAC,MAAM,KAAK,IAAI;oBAC/B,gEAAgE;oBAChE,kEAAkE;oBAClE,kCAAkC;oBAClC,aAAa,EAAE,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI;iBAClF,EACD,YAAY,CACb,CACF,CAAA;gBACD,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;oBACrB,4CAA4C;oBAC5C,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,QAAQ,yBAAyB,CAAC,CAAA;gBAC9D,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,QAAQ,YAAY,UAAU,UAAU,CAAC,CAAA;oBACnE,OAAO,CAAC,WAAW,IAAI,UAAU,CAAA;gBACnC,CAAC;gBACD,OAAO,CAAC,SAAS,EAAE,CAAA;YACrB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,CAAA;gBACpC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,QAAQ,gBAAgB,MAAM,EAAE,CAAC,CAAA;gBAC3D,OAAO,CAAC,MAAM,EAAE,CAAA;YAClB,CAAC;QACH,CAAC;QAED,sCAAsC;QACtC,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAA;IAC9B,CAAC;YAAS,CAAC;QACT,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAA;QACxB,MAAM,WAAW,CAAC,KAAK,EAAE,CAAA;IAC3B,CAAC;IAED,gBAAgB;IAChB,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IACjB,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;IACvC,OAAO,CAAC,KAAK,CAAC,cAAc,OAAO,CAAC,SAAS,EAAE,CAAC,CAAA;IAChD,OAAO,CAAC,KAAK,CAAC,cAAc,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAC7C,OAAO,CAAC,KAAK,CAAC,iBAAiB,OAAO,CAAC,WAAW,EAAE,CAAC,CAAA;IAErD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;IACtB,CAAC;AACH,CAAC"}