@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,461 @@
1
+ // Dispatch-agnostic incremental-sync planning and execution: the single core
2
+ // shared by the `sync` CLI subcommand and the MCP `sync_start` tool. Every
3
+ // collaborator is a local structural interface, so this module imports nothing
4
+ // from the domain layers, not even for types.
5
+ //
6
+ // Path identity: reconciliation compares generated keys
7
+ // (`toSyncPathKey(path, platform)`) and answers containment with the unchanged
8
+ // `isUnderOrEqual`. Deletion instead uses the verbatim stored `filePath`,
9
+ // because that is what the storage predicate matches.
10
+ //
11
+ // Two spellings, one matcher: `toSyncPathKey` stays purely lexical (a key must
12
+ // be derivable for a file no longer on disk), while the requested path's
13
+ // CONTAINMENT is decided against canonicalized values — see
14
+ // `isRequestedPathContained`. Do not collapse the two by making key generation
15
+ // follow symbolic links.
16
+ //
17
+ // `platform` is an explicit input, so Windows key semantics are provable from a
18
+ // POSIX host.
19
+ import { isManagedRawDataPath } from '../utils/raw-data-utils.js';
20
+ import { isUnderOrEqual } from '../utils/scope-match.js';
21
+ import { toSyncPathKey } from '../utils/sync-path-key.js';
22
+ import { isQualityProfile } from '../utils/visual-profile.js';
23
+ /** Append an attributable path only when the underlying message does not already contain it. */
24
+ export function formatSyncError({ message, filePath }) {
25
+ return filePath === null || message.includes(filePath) ? message : `${message} (${filePath})`;
26
+ }
27
+ /** Only a PDF carries visual intent; every other type ignores stored profiles. */
28
+ function isEligiblePdf(filePath) {
29
+ return filePath.toLowerCase().endsWith('.pdf');
30
+ }
31
+ /**
32
+ * The desired profile for one eligible PDF, and the only place a stored profile
33
+ * is interpreted.
34
+ *
35
+ * An override is not read against the rows at all, which is what lets one CLI
36
+ * run repair stored state this function would otherwise refuse to interpret.
37
+ * Without one, rows that admit no single answer throw rather than converge the
38
+ * file onto a guess.
39
+ */
40
+ function resolveDesiredProfile(filePath, stored, override) {
41
+ if (override !== undefined) {
42
+ return override;
43
+ }
44
+ const known = new Set();
45
+ for (const profile of stored?.profiles ?? []) {
46
+ if (profile === null) {
47
+ continue;
48
+ }
49
+ if (!isQualityProfile(profile)) {
50
+ throw new Error(`Sync cannot infer the visual mode of ${filePath}: it stores an unsupported visual profile "${profile}". Re-run sync with --visual (optionally --visual-quality quality) to set one explicitly, or re-ingest the file.`);
51
+ }
52
+ known.add(profile);
53
+ }
54
+ if (known.size > 1) {
55
+ throw new Error(`Sync cannot infer the visual mode of ${filePath}: its indexed rows disagree (${[...known].sort().join(', ')}). Re-run sync with --visual (optionally --visual-quality quality) to set one explicitly, or re-ingest the file.`);
56
+ }
57
+ return known.values().next().value ?? null;
58
+ }
59
+ /**
60
+ * A comparison key is converged only when it is stored under exactly one
61
+ * spelling, every one of that spelling's rows carries the current disk hash,
62
+ * and — for a PDF — every row already records the desired profile. No rows, a
63
+ * hashless row, disagreeing rows, a stale hash, or a profile mismatch all make
64
+ * it dirty.
65
+ *
66
+ * The single-spelling condition matters because deletion is by exact path: on
67
+ * Windows, ingesting `C:\Docs\A.md` and later `c:\docs\a.md` leaves two row sets
68
+ * for one file, both with the correct hash. Without this condition sync would
69
+ * skip the key forever and searches would keep returning duplicate hits; with
70
+ * it, the key is re-ingested and the other spellings become stale deletions, so
71
+ * one run converges it back to a single spelling.
72
+ */
73
+ function isConverged(stored, diskHash, desiredProfile, comparesProfile) {
74
+ if (stored.paths.length !== 1 || !stored.hashes.every((hash) => hash === diskHash)) {
75
+ return false;
76
+ }
77
+ return !comparesProfile || stored.profiles.every((profile) => profile === desiredProfile);
78
+ }
79
+ /**
80
+ * Decide the skip, upsert, and prune actions for one sync run.
81
+ *
82
+ * A key is pruned only when every one of four conditions holds: inside the
83
+ * requested scope, absent from disk, outside the excluded and managed paths,
84
+ * and outside every unobserved prefix. Dropping any one protects the rows.
85
+ *
86
+ * Throws when an eligible PDF's stored profiles admit no single answer; the
87
+ * caller must surface that before any mutation runs.
88
+ */
89
+ export function planSync(input) {
90
+ const keyOf = (path) => toSyncPathKey(path, input.platform);
91
+ const isKeyUnder = (key, prefixes) => prefixes.some((prefix) => isUnderOrEqual(key, keyOf(prefix)));
92
+ const request = input.request;
93
+ const scopePrefixes = request.kind === 'roots' ? input.roots : [request.path];
94
+ // A file request addresses exactly one comparison key, so its prune scope is
95
+ // equality rather than `isKeyUnder`'s exact-or-descendant membership: a stored
96
+ // row at `<requested file>/child.md` — left behind by a directory that was later
97
+ // replaced by a file of the same name — is a different key and must survive.
98
+ // Directory and roots requests keep the descendant semantics.
99
+ const requestedFileKey = request.kind === 'file' ? keyOf(request.path) : null;
100
+ const isInRequestedScope = (rowKey) => requestedFileKey === null ? isKeyUnder(rowKey, scopePrefixes) : rowKey === requestedFileKey;
101
+ const diskByKey = groupDiskFilesByKey(input.diskFiles, keyOf);
102
+ const storedByKey = groupStoredRowsByKey(input.dbRows, keyOf);
103
+ const { upserts, skipped } = planUpserts(diskByKey, storedByKey, input.visualProfile);
104
+ const unobservedPrefixes = [
105
+ ...input.coverage.unreadableDirs.map((dir) => dir.dirPath),
106
+ ...input.coverage.depthLimitedDirs,
107
+ ...input.coverage.skippedSymlinks,
108
+ ...input.coverage.oversizedFiles,
109
+ ];
110
+ const prunes = [];
111
+ for (const [rowKey, group] of storedByKey) {
112
+ const survives = diskByKey.has(rowKey) ||
113
+ !isInRequestedScope(rowKey) ||
114
+ isKeyUnder(rowKey, unobservedPrefixes) ||
115
+ isKeyUnder(rowKey, input.excludePaths) ||
116
+ group.paths.some((path) => isManagedRawDataPath(path, input.dbPath));
117
+ if (!survives) {
118
+ prunes.push({ storedPaths: group.paths });
119
+ }
120
+ }
121
+ return { upserts, skipped, prunes };
122
+ }
123
+ /** First disk spelling wins for each comparison key. */
124
+ function groupDiskFilesByKey(diskFiles, keyOf) {
125
+ const diskByKey = new Map();
126
+ for (const file of diskFiles) {
127
+ const fileKey = keyOf(file.filePath);
128
+ if (!diskByKey.has(fileKey)) {
129
+ diskByKey.set(fileKey, file);
130
+ }
131
+ }
132
+ return diskByKey;
133
+ }
134
+ /** Collect every stored spelling and hash that shares a comparison key. */
135
+ function groupStoredRowsByKey(dbRows, keyOf) {
136
+ const storedByKey = new Map();
137
+ for (const row of dbRows) {
138
+ const rowKey = keyOf(row.filePath);
139
+ const group = storedByKey.get(rowKey) ?? { paths: [], hashes: [], profiles: [] };
140
+ if (!group.paths.includes(row.filePath)) {
141
+ group.paths.push(row.filePath);
142
+ }
143
+ group.hashes.push(row.contentHash ?? null);
144
+ // An empty string is what the fresh-table create path seeds for Arrow
145
+ // inference, so it means absence exactly like `null` and `undefined`.
146
+ const profile = row.visualProfile ?? null;
147
+ group.profiles.push(profile === '' ? null : profile);
148
+ storedByKey.set(rowKey, group);
149
+ }
150
+ return storedByKey;
151
+ }
152
+ /**
153
+ * A disk file is skipped when the index already agrees with it.
154
+ *
155
+ * Profile resolution happens here, per scanned file, which is what confines a
156
+ * corrupt stored value to the file that owns it: a row outside the requested
157
+ * scope, under a missing or oversized file, or attached to a non-PDF is never
158
+ * interpreted and therefore cannot fail an unrelated run.
159
+ */
160
+ function planUpserts(diskByKey, storedByKey, override) {
161
+ const upserts = [];
162
+ let skipped = 0;
163
+ for (const [fileKey, file] of diskByKey) {
164
+ const group = storedByKey.get(fileKey);
165
+ const isPdf = isEligiblePdf(file.filePath);
166
+ const visualProfile = isPdf ? resolveDesiredProfile(file.filePath, group, override) : null;
167
+ if (group && isConverged(group, file.contentHash, visualProfile, isPdf)) {
168
+ skipped += 1;
169
+ continue;
170
+ }
171
+ upserts.push({
172
+ filePath: file.filePath,
173
+ // `ingestFile` replaces its own spelling; any other spelling of the same
174
+ // key would otherwise survive as a duplicate of the same file.
175
+ staleStoredPaths: (group?.paths ?? []).filter((path) => path !== file.filePath),
176
+ visualProfile,
177
+ });
178
+ }
179
+ return { upserts, skipped };
180
+ }
181
+ // ============================================
182
+ // Execution (steps 5-10)
183
+ // ============================================
184
+ function toMessage(caught) {
185
+ return caught instanceof Error ? caught.message : String(caught);
186
+ }
187
+ /**
188
+ * The controlled error for a requested path the collect predicates refuse. One
189
+ * message per rejection, owned here rather than in the adapters, so the CLI and
190
+ * MCP surfaces refuse the same paths with the same words.
191
+ *
192
+ * The `irregular` case is also what keeps a caller from handing sync something
193
+ * whose read never returns (a FIFO). It fixes that trigger only: nothing here
194
+ * bounds a collaborator that hangs for some other reason, and the MCP mutation
195
+ * guard is still released solely by the job promise settling.
196
+ */
197
+ function requestedPathRejection(kind, path) {
198
+ switch (kind) {
199
+ case 'missing':
200
+ return `Sync path does not exist: ${path}`;
201
+ case 'irregular':
202
+ return `Sync path is not a regular file or directory: ${path}`;
203
+ case 'symlink':
204
+ return `Sync path is a symbolic link, which sync never follows: ${path}`;
205
+ case 'excluded':
206
+ return `Sync path is inside the database or cache directory: ${path}`;
207
+ case 'unsupported':
208
+ return `Sync path is not a supported document type: ${path}`;
209
+ }
210
+ }
211
+ /**
212
+ * The one message every out-of-root request receives. A readable target, an
213
+ * unreadable one, and an absent one are deliberately indistinguishable here, so
214
+ * the error text cannot be used to probe for the existence or readability of
215
+ * paths outside the configured roots. Requests that ARE inside a root keep their
216
+ * specific messages ({@link requestedPathRejection}): those name nothing the
217
+ * caller did not already supply.
218
+ */
219
+ function outsideConfiguredRootsMessage(path) {
220
+ return `Sync path is outside every configured root: ${path}`;
221
+ }
222
+ /**
223
+ * Containment of an explicitly requested path, decided before anything reads it.
224
+ * Two questions, both answered by composing generated keys with the unchanged
225
+ * `isUnderOrEqual`:
226
+ *
227
+ * 1. Is the requested spelling under a configured root spelling? This keeps the
228
+ * request in the same lexical space as the stored DB keys.
229
+ * 2. Is its canonical form under a canonicalized root? This is the security
230
+ * boundary. `resolve()` cannot see that an intermediate component is a
231
+ * symbolic link, so question 1 alone accepts `<root>/link/secret.md` whose
232
+ * real location is outside every root, and the walker's own symlink skipping
233
+ * does not help: nothing walks an explicitly named path.
234
+ *
235
+ * A path that cannot be canonicalized fails, which is also what makes the
236
+ * rejection uniform.
237
+ */
238
+ async function isRequestedPathContained(requestedPath, input) {
239
+ const { platform } = input;
240
+ const isUnderAny = (path, prefixes) => prefixes.some((prefix) => isUnderOrEqual(toSyncPathKey(path, platform), toSyncPathKey(prefix, platform)));
241
+ if (!isUnderAny(requestedPath, input.roots)) {
242
+ return false;
243
+ }
244
+ const canonicalPath = await input.collaborators.canonicalizeRequestedPath(requestedPath);
245
+ return canonicalPath !== null && isUnderAny(canonicalPath, input.canonicalRoots);
246
+ }
247
+ /** Ingest every planned file, stopping at the first failure. */
248
+ async function runUpserts(plan, executor, images, state) {
249
+ for (const action of plan.upserts) {
250
+ try {
251
+ const chunkCount = await executor.ingestFile(action.filePath, {
252
+ images,
253
+ visualProfile: action.visualProfile,
254
+ });
255
+ if (chunkCount === 0) {
256
+ state.empty += 1;
257
+ continue;
258
+ }
259
+ state.upserted += 1;
260
+ state.mutated = true;
261
+ // After the insert, not before: a zero-chunk result must leave every
262
+ // stored spelling of this key untouched.
263
+ for (const stalePath of action.staleStoredPaths) {
264
+ await executor.deleteExactPath(stalePath);
265
+ }
266
+ }
267
+ catch (caught) {
268
+ state.error = { message: toMessage(caught), filePath: action.filePath };
269
+ return;
270
+ }
271
+ }
272
+ }
273
+ /** Delete every planned stale group, stopping at the first failure. */
274
+ async function runPrunes(plan, executor, state) {
275
+ for (const action of plan.prunes) {
276
+ const [reported] = action.storedPaths;
277
+ try {
278
+ for (const storedPath of action.storedPaths) {
279
+ await executor.deleteExactPath(storedPath);
280
+ state.mutated = true;
281
+ }
282
+ state.pruned += 1;
283
+ if (reported !== undefined) {
284
+ state.prunedPaths.push(reported);
285
+ }
286
+ }
287
+ catch (caught) {
288
+ state.error = { message: toMessage(caught), filePath: reported ?? null };
289
+ return;
290
+ }
291
+ }
292
+ }
293
+ export async function executeSyncPlan(plan, executor, images = false) {
294
+ const state = {
295
+ upserted: 0,
296
+ empty: 0,
297
+ pruned: 0,
298
+ mutated: false,
299
+ error: null,
300
+ prunedPaths: [],
301
+ };
302
+ await runUpserts(plan, executor, images, state);
303
+ if (state.error === null) {
304
+ await runPrunes(plan, executor, state);
305
+ }
306
+ if (state.error === null && state.mutated) {
307
+ try {
308
+ await executor.optimize();
309
+ }
310
+ catch (caught) {
311
+ state.error = { message: toMessage(caught), filePath: null };
312
+ }
313
+ }
314
+ return {
315
+ upserted: state.upserted,
316
+ skipped: plan.skipped,
317
+ empty: state.empty,
318
+ pruned: state.pruned,
319
+ prunedPaths: state.prunedPaths,
320
+ error: state.error,
321
+ };
322
+ }
323
+ /**
324
+ * `attributedPath` tracks what a thrown error should be blamed on, so an
325
+ * orchestration failure still names the file, root, or requested path involved.
326
+ */
327
+ /**
328
+ * Resolve what a sync run addresses and which directories it must walk.
329
+ * Containment is checked against canonical values, and classification happens
330
+ * before any read, so nothing unsupported is hashed or ingested.
331
+ */
332
+ async function resolveSyncRequest(input) {
333
+ const requestedPath = input.requestedPath;
334
+ if (requestedPath === undefined) {
335
+ return { request: { kind: 'roots' }, scanRoots: input.roots };
336
+ }
337
+ if (!(await isRequestedPathContained(requestedPath, input))) {
338
+ throw new Error(outsideConfiguredRootsMessage(requestedPath));
339
+ }
340
+ const kind = await input.collaborators.classifyPath(requestedPath);
341
+ if (kind !== 'directory' && kind !== 'file') {
342
+ throw new Error(requestedPathRejection(kind, requestedPath));
343
+ }
344
+ // An explicit directory becomes its own depth-zero BFS root; an explicit
345
+ // file needs no directory walk and no depth evaluation at all.
346
+ return {
347
+ request: { kind, path: requestedPath },
348
+ scanRoots: kind === 'directory' ? [requestedPath] : [],
349
+ };
350
+ }
351
+ async function gatherSyncInputs(input) {
352
+ const { collaborators, platform } = input;
353
+ const coverage = {
354
+ unreadableDirs: [],
355
+ depthLimitedDirs: [],
356
+ skippedSymlinks: [],
357
+ oversizedFiles: [],
358
+ };
359
+ let attributedPath = null;
360
+ try {
361
+ const requestedPath = input.requestedPath;
362
+ if (requestedPath !== undefined) {
363
+ attributedPath = requestedPath;
364
+ }
365
+ const { request, scanRoots } = await resolveSyncRequest(input);
366
+ const scannedFiles = [];
367
+ for (const root of scanRoots) {
368
+ attributedPath = root;
369
+ const scan = await collaborators.scanDir(root);
370
+ scannedFiles.push(...scan.files);
371
+ coverage.unreadableDirs.push(...scan.unreadableDirs);
372
+ coverage.depthLimitedDirs.push(...scan.depthLimitedDirs);
373
+ coverage.skippedSymlinks.push(...scan.skippedSymlinks);
374
+ }
375
+ if (request.kind === 'file') {
376
+ scannedFiles.push(request.path);
377
+ }
378
+ // Overlapping roots can surface the same file twice; hash each comparison
379
+ // key once, keeping the first spelling encountered.
380
+ const diskByKey = new Map();
381
+ for (const filePath of scannedFiles) {
382
+ const fileKey = toSyncPathKey(filePath, platform);
383
+ if (!diskByKey.has(fileKey)) {
384
+ diskByKey.set(fileKey, filePath);
385
+ }
386
+ }
387
+ const diskFiles = [];
388
+ for (const filePath of diskByKey.values()) {
389
+ attributedPath = filePath;
390
+ const contentHash = await collaborators.hashFile(filePath);
391
+ if (contentHash === null) {
392
+ // Its bytes were never read, so its content identity is unknown for this
393
+ // run. Recording it as an unobserved region is what keeps its stored rows
394
+ // alive: leaving it out of the manifest alone would look like a deletion.
395
+ coverage.oversizedFiles.push(filePath);
396
+ continue;
397
+ }
398
+ diskFiles.push({ filePath, contentHash });
399
+ }
400
+ attributedPath = null;
401
+ const dbRows = await collaborators.loadDbManifest();
402
+ return { ok: true, coverage, request, diskFiles, dbRows };
403
+ }
404
+ catch (caught) {
405
+ return {
406
+ ok: false,
407
+ coverage,
408
+ error: { message: toMessage(caught), filePath: attributedPath },
409
+ };
410
+ }
411
+ }
412
+ /**
413
+ * Run one full sync. Counters and coverage facts are plain data — the caller
414
+ * owns printing and exit status. A run with nothing to do calls neither
415
+ * `ingestFile` nor `optimize`, so a true no-op never loads the model.
416
+ */
417
+ export async function runSync(input) {
418
+ const gathered = await gatherSyncInputs(input);
419
+ if (!gathered.ok) {
420
+ return {
421
+ upserted: 0,
422
+ skipped: 0,
423
+ empty: 0,
424
+ pruned: 0,
425
+ prunedPaths: [],
426
+ coverage: gathered.coverage,
427
+ error: gathered.error,
428
+ };
429
+ }
430
+ let plan;
431
+ try {
432
+ plan = planSync({
433
+ roots: input.roots,
434
+ dbPath: input.dbPath,
435
+ excludePaths: input.excludePaths,
436
+ platform: input.platform,
437
+ request: gathered.request,
438
+ diskFiles: gathered.diskFiles,
439
+ dbRows: gathered.dbRows,
440
+ coverage: gathered.coverage,
441
+ ...(input.visualProfile === undefined ? {} : { visualProfile: input.visualProfile }),
442
+ });
443
+ }
444
+ catch (caught) {
445
+ // Planning is pure, so nothing has been written yet: the run reports the
446
+ // same envelope a gathering failure does, with no executor call at all. The
447
+ // message already names the file it is attributable to.
448
+ return {
449
+ upserted: 0,
450
+ skipped: 0,
451
+ empty: 0,
452
+ pruned: 0,
453
+ prunedPaths: [],
454
+ coverage: gathered.coverage,
455
+ error: { message: toMessage(caught), filePath: null },
456
+ };
457
+ }
458
+ const execution = await executeSyncPlan(plan, input.collaborators, input.images === true);
459
+ return { ...execution, coverage: gathered.coverage };
460
+ }
461
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/features/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env node
2
+ // Entry point for mcp-local-rag
3
+ // Routes to CLI subcommands or starts the MCP server
4
+ import { parseGlobalOptions } from './cli/options.js';
5
+ import { handleCli, SUBCOMMANDS } from './cli-main.js';
6
+ import { startServer } from './server-main.js';
7
+ // ============================================
8
+ // Routing helpers
9
+ // ============================================
10
+ const SUBCOMMAND_SET = new Set(SUBCOMMANDS);
11
+ function isSubcommand(value) {
12
+ return SUBCOMMAND_SET.has(value);
13
+ }
14
+ /** Replace control chars and truncate, so an unexpected argv value
15
+ * echoed to stderr cannot smuggle ANSI escapes or CR/LF into log lines. */
16
+ function sanitizeForEcho(s) {
17
+ return s.replace(/\p{Cc}/gu, '?').slice(0, 100);
18
+ }
19
+ // ============================================
20
+ // Routing
21
+ // ============================================
22
+ const { globalOptions, remainingArgs } = parseGlobalOptions(process.argv.slice(2));
23
+ const firstArg = remainingArgs[0];
24
+ if (firstArg !== undefined && isSubcommand(firstArg)) {
25
+ // CLI subcommand
26
+ handleCli(firstArg, remainingArgs.slice(1), globalOptions).catch((error) => {
27
+ console.error(error);
28
+ process.exit(1);
29
+ });
30
+ }
31
+ else if (remainingArgs.length === 0) {
32
+ if (Object.keys(globalOptions).length > 0) {
33
+ console.error('Global CLI options are not supported when launching the MCP server directly.');
34
+ console.error('Use environment variables like DB_PATH, CACHE_DIR, MODEL_NAME, BASE_DIR, BASE_DIRS, and MAX_FILE_SIZE instead.');
35
+ process.exit(1);
36
+ }
37
+ // Default: start MCP server (env-only, no CLI flags)
38
+ process.on('unhandledRejection', (reason, promise) => {
39
+ console.error('Unhandled Rejection at:', promise, 'reason:', reason);
40
+ process.exit(1);
41
+ });
42
+ process.on('uncaughtException', (error) => {
43
+ console.error('Uncaught Exception:', error);
44
+ process.exit(1);
45
+ });
46
+ startServer().catch((error) => {
47
+ console.error('Failed to start server:', error);
48
+ process.exit(1);
49
+ });
50
+ }
51
+ else {
52
+ console.error(`Unknown command: ${sanitizeForEcho(firstArg ?? '')}`);
53
+ console.error(`Available commands: ${SUBCOMMANDS.join(', ')}`);
54
+ process.exit(1);
55
+ }
56
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,gCAAgC;AAChC,qDAAqD;AAErD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAmB,MAAM,eAAe,CAAA;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C,+CAA+C;AAC/C,kBAAkB;AAClB,+CAA+C;AAE/C,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC,WAAW,CAAC,CAAA;AAEhE,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;AAClC,CAAC;AAED;4EAC4E;AAC5E,SAAS,eAAe,CAAC,CAAS;IAChC,OAAO,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AACjD,CAAC;AAED,+CAA+C;AAC/C,UAAU;AACV,+CAA+C;AAE/C,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AAClF,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC,CAAC,CAAA;AAEjC,IAAI,QAAQ,KAAK,SAAS,IAAI,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;IACrD,iBAAiB;IACjB,SAAS,CAAC,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACzE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC,CAAC,CAAA;AACJ,CAAC;KAAM,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;IACtC,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,OAAO,CAAC,KAAK,CAAC,8EAA8E,CAAC,CAAA;QAC7F,OAAO,CAAC,KAAK,CACX,gHAAgH,CACjH,CAAA;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,qDAAqD;IACrD,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QACnD,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAA;QACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC,CAAC,CAAA;IAEF,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,KAAK,EAAE,EAAE;QACxC,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAA;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC,CAAC,CAAA;IAEF,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QACrC,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAA;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC,CAAC,CAAA;AACJ,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,KAAK,CAAC,oBAAoB,eAAe,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;IACpE,OAAO,CAAC,KAAK,CAAC,uBAAuB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC"}
@@ -0,0 +1,63 @@
1
+ import type { AtomicTextRange, SemanticChunker, TextChunk } from '../chunker/index.js';
2
+ import type { EmbedderInterface } from '../chunker/semantic-chunker.js';
3
+ import type { ParseResult } from '../parser/index.js';
4
+ import type { ImageRendition } from '../pdf-visual/types.js';
5
+ import type { VectorChunk, VisualAttachment } from '../vectordb/index.js';
6
+ /** `embeddings` has the same length as `chunks`, index for index. */
7
+ export interface BuildChunksAndEmbeddingsResult {
8
+ chunks: TextChunk[];
9
+ embeddings: number[][];
10
+ }
11
+ export interface BuildChunksFromParseResultResult extends BuildChunksAndEmbeddingsResult {
12
+ visualAttachments: Map<number, VisualAttachment[]>;
13
+ omittedImageCount: number;
14
+ }
15
+ export declare function findNearestChunk(chunks: readonly TextChunk[], sourceOffset: number): TextChunk | undefined;
16
+ export declare function createVisualAttachment(imageIndex: number, rendition: ImageRendition): VisualAttachment;
17
+ /**
18
+ * Compute semantic chunks and their embeddings for already-extracted text.
19
+ *
20
+ * Does not fail fast on zero chunks — the MCP handler throws, the CLI warns
21
+ * and returns 0. Chunker and embedder errors propagate verbatim.
22
+ */
23
+ export declare function buildChunksAndEmbeddings(text: string, chunker: SemanticChunker, embedder: EmbedderInterface, atomicRanges?: readonly AtomicTextRange[]): Promise<BuildChunksAndEmbeddingsResult>;
24
+ /**
25
+ * Preserve the parser content/range mapping at one shared boundary. Display
26
+ * title handling stays in each dispatch root because it does not affect chunks.
27
+ */
28
+ export declare function buildChunksFromParseResult(result: ParseResult, chunker: SemanticChunker, embedder: EmbedderInterface): Promise<BuildChunksFromParseResultResult>;
29
+ /**
30
+ * Content identity of a source file: SHA-256 of its raw BYTES, not of the
31
+ * parsed text, so any caller that can read the file reproduces it — which is
32
+ * what lets a later sync decide "unchanged" without re-parsing.
33
+ */
34
+ export declare function computeContentHash(bytes: Uint8Array): string;
35
+ /**
36
+ * Build persistable `VectorChunk`s from computed chunks + embeddings — the
37
+ * single chunk→row mapping for both the MCP handler and both CLI paths. One
38
+ * shared `timestamp` per call, a fresh `id`, and `fileName`/`fileType` derived
39
+ * with `node:path` so they hold on Windows.
40
+ *
41
+ * Throws when a chunk has no embedding; the two arrays must align 1:1.
42
+ *
43
+ * `contentHash` is `null` for a chunk set with no source file, and the key is
44
+ * then omitted rather than stored empty, so a hashless row is never mistaken
45
+ * for a real hash. Required, not optional, so a new call site cannot silently
46
+ * write hashless rows.
47
+ *
48
+ * `visualProfile` is the requested visual intent of this ingestion, copied to
49
+ * every row. It accepts `null`/`undefined` and then omits the optional property,
50
+ * so a caller holding a nullable value can pass it directly under
51
+ * `exactOptionalPropertyTypes` and a caller with no visual concept can omit it.
52
+ */
53
+ export declare function buildVectorChunks(params: {
54
+ filePath: string;
55
+ chunks: TextChunk[];
56
+ embeddings: number[][];
57
+ fileSize: number;
58
+ fileTitle: string | null;
59
+ contentHash: string | null;
60
+ visualAttachments?: ReadonlyMap<number, readonly VisualAttachment[]>;
61
+ visualProfile?: string | null;
62
+ }): VectorChunk[];
63
+ //# sourceMappingURL=compute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute.d.ts","sourceRoot":"","sources":["../../src/ingest/compute.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACtF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAazE,qEAAqE;AACrE,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,SAAS,EAAE,CAAA;IACnB,UAAU,EAAE,MAAM,EAAE,EAAE,CAAA;CACvB;AAED,MAAM,WAAW,gCAAiC,SAAQ,8BAA8B;IACtF,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAA;IAClD,iBAAiB,EAAE,MAAM,CAAA;CAC1B;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,SAAS,EAAE,EAC5B,YAAY,EAAE,MAAM,GACnB,SAAS,GAAG,SAAS,CAsBvB;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,cAAc,GACxB,gBAAgB,CAclB;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,iBAAiB,EAC3B,YAAY,CAAC,EAAE,SAAS,eAAe,EAAE,GACxC,OAAO,CAAC,8BAA8B,CAAC,CAWzC;AAED;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,gCAAgC,CAAC,CAiC3C;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAE5D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,SAAS,EAAE,CAAA;IACnB,UAAU,EAAE,MAAM,EAAE,EAAE,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,iBAAiB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC,CAAA;IACpE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B,GAAG,WAAW,EAAE,CA0ChB"}